Added startup stack size check
[elliptics.git] / example / ioclient.c
blobe8c368b20659cd376a85210768e1a56be8a82430
1 /*
2 * 2008+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
3 * All rights reserved.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <sys/socket.h>
19 #include <sys/time.h>
20 #include <sys/syscall.h>
22 #include <ctype.h>
23 #include <fcntl.h>
24 #include <errno.h>
25 #include <unistd.h>
26 #include <signal.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <time.h>
32 #include <netinet/in.h>
34 #include "elliptics/packet.h"
35 #include "elliptics/interface.h"
37 #include "backends.h"
38 #include "common.h"
40 #ifndef __unused
41 #define __unused __attribute__ ((unused))
42 #endif
44 static struct dnet_log ioclient_logger;
46 static void dnet_usage(char *p)
48 fprintf(stderr, "Usage: %s\n"
49 " -r addr:port:family - adds a route to the given node\n"
50 " -W file - write given file to the network storage\n"
51 " -s - request IO counter stats from node\n"
52 " -z - request VFS IO stats from node\n"
53 " -a - request stats from all connected nodes\n"
54 " -U status - update server status: 1 - elliptics exits, 2 - goes RO\n"
55 " -R file - read given file from the network into the local storage\n"
56 " -I id - transaction id (used to read data)\n"
57 " -g groups - group IDs to connect\n"
58 " -c cmd-event - execute command with given event on the remote node\n"
59 " -L file - lookup a storage which hosts given file\n"
60 " -l log - log file. Default: disabled\n"
61 " -w timeout - wait timeout in seconds used to wait for content sync.\n"
62 " ... - parameters can be repeated multiple times\n"
63 " each time they correspond to the last added node\n"
64 " -m level - log level\n"
65 " -M level - set new log level\n"
66 " -F flags - change node flags (see @cfg->flags comments in include/elliptics/interface.h)\n"
67 " -O offset - read/write offset in the file\n"
68 " -S size - read/write transaction size\n"
69 " -u file - unlink file\n"
70 " -N namespace - use this namespace for operations\n"
71 " -D object - read latest data for given object, if -I id is specified, this field is unused\n"
72 " -C flags - command flags\n"
73 " -t column - column ID to read or write\n"
74 " -d - start defragmentation\n"
75 " -i flags - IO flags (see DNET_IO_FLAGS_* in include/elliptics/packet.h\n"
76 , p);
79 int main(int argc, char *argv[])
81 int ch, err, i, have_remote = 0;
82 int io_counter_stat = 0, vfs_stat = 0, single_node_stat = 1;
83 struct dnet_node_status node_status;
84 int update_status = 0;
85 struct dnet_node *n = NULL;
86 struct dnet_config cfg, rem, *remotes = NULL;
87 char *logfile = "/dev/stderr", *readf = NULL, *writef = NULL, *cmd = NULL, *lookup = NULL;
88 char *read_data = NULL;
89 char *removef = NULL;
90 unsigned char trans_id[DNET_ID_SIZE], *id = NULL;
91 FILE *log = NULL;
92 uint64_t offset, size;
93 int *groups = NULL, group_num = 0;
94 int type = EBLOB_TYPE_DATA;
95 uint64_t cflags = 0;
96 uint64_t ioflags = 0;
97 int defrag = 0;
98 sigset_t mask;
100 memset(&node_status, 0, sizeof(struct dnet_node_status));
101 memset(&cfg, 0, sizeof(struct dnet_config));
103 node_status.nflags = -1;
104 node_status.status_flags = -1;
105 node_status.log_level = ~0U;
107 size = offset = 0;
109 cfg.sock_type = SOCK_STREAM;
110 cfg.proto = IPPROTO_TCP;
111 cfg.wait_timeout = 60;
112 ioclient_logger.log_level = DNET_LOG_ERROR;
114 memcpy(&rem, &cfg, sizeof(struct dnet_config));
116 while ((ch = getopt(argc, argv, "i:dC:t:A:F:M:N:g:u:O:S:m:zsU:aL:w:l:c:I:r:W:R:D:h")) != -1) {
117 switch (ch) {
118 case 'i':
119 ioflags = strtoull(optarg, NULL, 0);
120 break;
121 case 'd':
122 defrag = 1;
123 break;
124 case 'C':
125 cflags = strtoull(optarg, NULL, 0);
126 break;
127 case 't':
128 type = atoi(optarg);
129 break;
130 case 'F':
131 node_status.nflags = strtol(optarg, NULL, 0);
132 update_status = 1;
133 break;
134 case 'M':
135 node_status.log_level = atoi(optarg);
136 update_status = 1;
137 break;
138 case 'N':
139 cfg.ns = optarg;
140 cfg.nsize = strlen(optarg);
141 break;
142 case 'u':
143 removef = optarg;
144 break;
145 case 'O':
146 offset = strtoull(optarg, NULL, 0);
147 break;
148 case 'S':
149 size = strtoull(optarg, NULL, 0);
150 break;
151 case 'm':
152 ioclient_logger.log_level = atoi(optarg);
153 break;
154 case 's':
155 io_counter_stat = 1;
156 break;
157 case 'U':
158 node_status.status_flags = strtol(optarg, NULL, 0);
159 update_status = 1;
160 break;
161 case 'z':
162 vfs_stat = 1;
163 break;
164 case 'a':
165 single_node_stat = 0;
166 break;
167 case 'L':
168 lookup = optarg;
169 break;
170 case 'w':
171 cfg.check_timeout = cfg.wait_timeout = atoi(optarg);
172 break;
173 case 'l':
174 logfile = optarg;
175 break;
176 case 'c':
177 cmd = optarg;
178 break;
179 case 'I':
180 err = dnet_parse_numeric_id(optarg, trans_id);
181 if (err)
182 return err;
183 id = trans_id;
184 break;
185 case 'g':
186 group_num = dnet_parse_groups(optarg, &groups);
187 if (group_num <= 0)
188 return -1;
189 break;
190 case 'r':
191 err = dnet_parse_addr(optarg, &rem);
192 if (err)
193 return err;
194 have_remote++;
195 remotes = realloc(remotes, sizeof(rem) * have_remote);
196 if (!remotes)
197 return -ENOMEM;
198 memcpy(&remotes[have_remote - 1], &rem, sizeof(rem));
199 break;
200 case 'W':
201 writef = optarg;
202 break;
203 case 'R':
204 readf = optarg;
205 break;
206 case 'D':
207 read_data = optarg;
208 break;
209 case 'h':
210 default:
211 dnet_usage(argv[0]);
212 return -1;
216 log = fopen(logfile, "a");
217 if (!log) {
218 err = -errno;
219 fprintf(stderr, "Failed to open log file %s: %s.\n", logfile, strerror(errno));
220 return err;
223 ioclient_logger.log_private = log;
224 ioclient_logger.log = dnet_common_log;
225 cfg.log = &ioclient_logger;
227 n = dnet_node_create(&cfg);
228 if (!n)
229 return -1;
231 sigemptyset(&mask);
232 sigaddset(&mask, SIGTERM);
233 sigaddset(&mask, SIGINT);
234 sigaddset(&mask, SIGHUP);
235 sigaddset(&mask, SIGCHLD);
236 pthread_sigmask(SIG_UNBLOCK, &mask, NULL);
237 sigprocmask(SIG_UNBLOCK, &mask, NULL);
239 dnet_node_set_groups(n, groups, group_num);
241 if (have_remote) {
242 int error = -ECONNRESET;
243 for (i=0; i<have_remote; ++i) {
244 if (single_node_stat && (vfs_stat || io_counter_stat))
245 remotes[i].flags = DNET_CFG_NO_ROUTE_LIST;
246 err = dnet_add_state(n, &remotes[i]);
247 if (!err)
248 error = 0;
251 if (error)
252 return error;
255 if (defrag)
256 return dnet_start_defrag(n, cflags);
258 if (writef) {
259 if (id) {
260 struct dnet_id raw;
262 dnet_setup_id(&raw, 0, id);
263 raw.type = type;
265 err = dnet_write_file_id(n, writef, &raw, offset, offset, size, cflags, ioflags);
266 } else {
267 err = dnet_write_file(n, writef, writef, strlen(writef), offset, offset, size, cflags, ioflags, type);
270 if (err)
271 return err;
274 if (readf) {
275 if (id) {
276 struct dnet_id raw;
278 dnet_setup_id(&raw, 0, id);
279 raw.type = type;
281 err = dnet_read_file_id(n, readf, &raw, offset, size);
282 } else {
283 err = dnet_read_file(n, readf, readf, strlen(readf), offset, size, type);
285 if (err)
286 return err;
289 if (read_data) {
290 void *data;
291 struct dnet_id raw;
292 struct dnet_io_attr io;
294 if (!id) {
295 dnet_transform(n, read_data, strlen(read_data), &raw);
296 } else {
297 memcpy(&raw.id, id, DNET_ID_SIZE);
299 raw.type = type;
300 raw.group_id = 0; /* unused */
302 memset(&io, 0, sizeof(io));
303 io.type = type;
304 io.flags = ioflags;
305 memcpy(io.id, raw.id, DNET_ID_SIZE);
306 memcpy(io.parent, raw.id, DNET_ID_SIZE);
308 /* number of copies to check to find the latest data */
309 io.num = group_num;
311 err = dnet_read_latest(n, &raw, &io, cflags, &data);
312 if (err)
313 return err;
315 data += sizeof(struct dnet_io_attr);
316 io.size -= sizeof(struct dnet_io_attr);
318 while (io.size) {
319 err = write(1, data, io.size);
320 if (err <= 0) {
321 err = -errno;
322 dnet_log_raw(n, DNET_LOG_ERROR, "%s: can not write data to stdout: %d %s",
323 read_data, err, strerror(-err));
324 return err;
327 io.size -= err;
331 if (removef) {
332 if (id) {
333 struct dnet_id raw;
335 dnet_setup_id(&raw, 0, id);
336 raw.type = type;
337 dnet_remove_object_now(n, &raw, cflags, ioflags);
339 return 0;
342 err = dnet_remove_file(n, removef, strlen(removef), NULL, cflags, ioflags);
343 if (err)
344 return err;
347 if (cmd) {
348 struct dnet_id __did, *did = NULL;
349 struct sph *sph;
350 int len = strlen(cmd);
351 int event_size = len;
352 char *ret = NULL;
353 char *tmp;
355 tmp = strchr(cmd, ' ');
356 if (tmp) {
357 event_size = tmp - cmd;
360 if (id) {
361 did = &__did;
363 dnet_setup_id(did, 0, id);
364 did->type = type;
367 sph = malloc(sizeof(struct sph) + len + 1);
368 if (!sph)
369 return -ENOMEM;
371 memset(sph, 0, sizeof(struct sph));
373 sph->flags = DNET_SPH_FLAGS_SRC_BLOCK;
374 sph->key = -1;
375 sph->binary_size = 0;
376 sph->data_size = len - event_size;
377 sph->event_size = event_size;
379 sprintf(sph->data, "%s", cmd);
381 err = dnet_send_cmd(n, did, sph, (void **)&ret);
382 if (err < 0)
383 return err;
385 free(sph);
387 if (err > 0) {
388 printf("%.*s\n", err, ret);
389 free(ret);
393 if (lookup) {
394 err = dnet_lookup(n, lookup);
395 if (err)
396 return err;
399 if (vfs_stat) {
400 err = dnet_request_stat(n, NULL, DNET_CMD_STAT, 0, NULL, NULL);
401 if (err < 0)
402 return err;
405 if (io_counter_stat) {
406 err = dnet_request_stat(n, NULL, DNET_CMD_STAT_COUNT, DNET_ATTR_CNTR_GLOBAL, NULL, NULL);
407 if (err < 0)
408 return err;
411 if (update_status) {
412 struct dnet_addr addr;
414 for (i=0; i<have_remote; ++i) {
415 memset(&addr, 0, sizeof(addr));
416 addr.addr_len = sizeof(addr.addr);
418 err = dnet_fill_addr(&addr, remotes[i].addr, remotes[i].port,
419 remotes[i].family, remotes[i].sock_type, remotes[i].proto);
420 if (err) {
421 dnet_log_raw(n, DNET_LOG_ERROR, "ioclient: dnet_fill_addr: %s:%s:%d, sock_type: %d, proto: %d: %s %d\n",
422 remotes[i].addr, remotes[i].port,
423 remotes[i].family, remotes[i].sock_type, remotes[i].proto,
424 strerror(-err), err);
427 err = dnet_update_status(n, &addr, NULL, &node_status);
428 if (err) {
429 dnet_log_raw(n, DNET_LOG_ERROR, "ioclient: dnet_update_status: %s:%s:%d, sock_type: %d, proto: %d: update: %d: "
430 "%s %d\n",
431 remotes[i].addr, remotes[i].port,
432 remotes[i].family, remotes[i].sock_type, remotes[i].proto, update_status,
433 strerror(-err), err);
439 dnet_node_destroy(n);
441 return 0;