2 * 2008+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
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.
18 #include <sys/types.h>
20 #include <sys/socket.h>
22 #include <sys/syscall.h>
34 #include <netinet/in.h>
36 #include "elliptics/packet.h"
37 #include "elliptics/interface.h"
43 #define __unused __attribute__ ((unused))
46 static struct dnet_log ioclient_logger
;
48 static void dnet_usage(char *p
)
50 fprintf(stderr
, "Usage: %s\n"
51 " -r addr:port:family - adds a route to the given node\n"
52 " -W file - write given file to the network storage\n"
53 " -s - request IO counter stats from node\n"
54 " -z - request VFS IO stats from node\n"
55 " -a - request stats from all connected nodes\n"
56 " -U status - update server status: 1 - elliptics exits, 2 - goes RO\n"
57 " -R file - read given file from the network into the local storage\n"
58 " -I id - transaction id (used to read data)\n"
59 " -g groups - group IDs to connect\n"
60 " -c cmd-event - execute command with given event on the remote node\n"
61 " -L file - lookup a storage which hosts given file\n"
62 " -l log - log file. Default: disabled\n"
63 " -w timeout - wait timeout in seconds used to wait for content sync.\n"
64 " ... - parameters can be repeated multiple times\n"
65 " each time they correspond to the last added node\n"
66 " -m mask - log events mask\n"
67 " -M mask - set new log mask\n"
68 " -F flags - change node flags (see @cfg->flags comments in include/elliptics/interface.h)\n"
69 " -O offset - read/write offset in the file\n"
70 " -S size - read/write transaction size\n"
71 " -u file - unlink file\n"
72 " -N namespace - use this namespace for operations\n"
73 " -D object - read latest data for given object, if -I id is specified, this field is unused\n"
74 " -C flags - command flags\n"
75 " -t column - column ID to read or write\n"
76 " -d - start defragmentation\n"
80 int main(int argc
, char *argv
[])
82 int ch
, err
, i
, have_remote
= 0;
83 int io_counter_stat
= 0, vfs_stat
= 0, single_node_stat
= 1;
84 struct dnet_node_status node_status
;
85 int update_status
= 0;
86 struct dnet_node
*n
= NULL
;
87 struct dnet_config cfg
, rem
, *remotes
= NULL
;
88 char *logfile
= "/dev/stderr", *readf
= NULL
, *writef
= NULL
, *cmd
= NULL
, *lookup
= NULL
;
89 char *read_data
= NULL
;
91 unsigned char trans_id
[DNET_ID_SIZE
], *id
= NULL
;
93 uint64_t offset
, size
;
94 int *groups
= NULL
, group_num
= 0;
95 int type
= EBLOB_TYPE_DATA
;
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_mask
= ~0U;
109 cfg
.sock_type
= SOCK_STREAM
;
110 cfg
.proto
= IPPROTO_TCP
;
111 cfg
.wait_timeout
= 60;
112 ioclient_logger
.log_mask
= DNET_LOG_ERROR
| DNET_LOG_DATA
;
114 memcpy(&rem
, &cfg
, sizeof(struct dnet_config
));
116 while ((ch
= getopt(argc
, argv
, "dC:t:A:F:M:N:g:u:O:S:m:zsU:aL:w:l:c:I:r:W:R:D:h")) != -1) {
122 cflags
= strtoull(optarg
, NULL
, 0);
128 node_status
.nflags
= strtol(optarg
, NULL
, 0);
132 node_status
.log_mask
= strtol(optarg
, NULL
, 0);
137 cfg
.nsize
= strlen(optarg
);
143 offset
= strtoull(optarg
, NULL
, 0);
146 size
= strtoull(optarg
, NULL
, 0);
149 ioclient_logger
.log_mask
= strtoul(optarg
, NULL
, 0);
155 node_status
.status_flags
= strtol(optarg
, NULL
, 0);
162 single_node_stat
= 0;
168 cfg
.check_timeout
= cfg
.wait_timeout
= atoi(optarg
);
177 err
= dnet_parse_numeric_id(optarg
, trans_id
);
183 group_num
= dnet_parse_groups(optarg
, &groups
);
188 err
= dnet_parse_addr(optarg
, &rem
);
192 remotes
= realloc(remotes
, sizeof(rem
) * have_remote
);
195 memcpy(&remotes
[have_remote
- 1], &rem
, sizeof(rem
));
213 log
= fopen(logfile
, "a");
216 fprintf(stderr
, "Failed to open log file %s: %s.\n", logfile
, strerror(errno
));
220 ioclient_logger
.log_private
= log
;
221 ioclient_logger
.log
= dnet_common_log
;
222 cfg
.log
= &ioclient_logger
;
224 n
= dnet_node_create(&cfg
);
229 sigaddset(&mask
, SIGTERM
);
230 sigaddset(&mask
, SIGINT
);
231 sigaddset(&mask
, SIGHUP
);
232 sigaddset(&mask
, SIGCHLD
);
233 pthread_sigmask(SIG_UNBLOCK
, &mask
, NULL
);
234 sigprocmask(SIG_UNBLOCK
, &mask
, NULL
);
236 dnet_node_set_groups(n
, groups
, group_num
);
239 int error
= -ECONNRESET
;
240 for (i
=0; i
<have_remote
; ++i
) {
241 if (single_node_stat
&& (vfs_stat
|| io_counter_stat
))
242 remotes
[i
].flags
= DNET_CFG_NO_ROUTE_LIST
;
243 err
= dnet_add_state(n
, &remotes
[i
]);
253 return dnet_start_defrag(n
, cflags
);
259 dnet_setup_id(&raw
, 0, id
);
262 err
= dnet_write_file_id(n
, writef
, &raw
, offset
, offset
, size
, cflags
, 0);
264 err
= dnet_write_file(n
, writef
, writef
, strlen(writef
), offset
, offset
, size
, cflags
, 0, type
);
275 dnet_setup_id(&raw
, 0, id
);
278 err
= dnet_read_file_id(n
, readf
, &raw
, offset
, size
);
280 err
= dnet_read_file(n
, readf
, readf
, strlen(readf
), offset
, size
, type
);
289 struct dnet_io_attr io
;
292 dnet_transform(n
, read_data
, strlen(read_data
), &raw
);
294 memcpy(&raw
.id
, id
, DNET_ID_SIZE
);
297 raw
.group_id
= 0; /* unused */
299 memset(&io
, 0, sizeof(io
));
301 memcpy(io
.id
, raw
.id
, DNET_ID_SIZE
);
302 memcpy(io
.parent
, raw
.id
, DNET_ID_SIZE
);
304 /* number of copies to check to find the latest data */
307 err
= dnet_read_latest(n
, &raw
, &io
, cflags
, &data
);
311 data
+= sizeof(struct dnet_io_attr
);
312 io
.size
-= sizeof(struct dnet_io_attr
);
315 err
= write(1, data
, io
.size
);
318 dnet_log_raw(n
, DNET_LOG_ERROR
, "%s: can not write data to stdout: %d %s",
319 read_data
, err
, strerror(-err
));
331 for (i
=0; i
<group_num
; ++i
) {
332 dnet_setup_id(&raw
, groups
[i
], id
);
334 dnet_remove_object_now(n
, &raw
, cflags
);
340 err
= dnet_remove_file(n
, removef
, strlen(removef
), NULL
, cflags
);
346 struct dnet_id __did
, *did
= NULL
;
348 int len
= strlen(cmd
);
349 int event_size
= len
;
353 tmp
= strchr(cmd
, ' ');
355 event_size
= tmp
- cmd
;
361 dnet_setup_id(did
, 0, id
);
365 sph
= malloc(sizeof(struct sph
) + len
+ 1);
369 memset(sph
, 0, sizeof(struct sph
));
371 sph
->flags
= DNET_SPH_FLAGS_SRC_BLOCK
;
373 sph
->binary_size
= 0;
374 sph
->data_size
= len
- event_size
;
375 sph
->event_size
= event_size
;
377 sprintf(sph
->data
, "%s", cmd
);
379 err
= dnet_send_cmd(n
, did
, sph
, (void **)&ret
);
388 ret
= realloc(ret
, err
+ 1);
394 printf("%s: '%s'", cmd
, ret
);
400 err
= dnet_lookup(n
, lookup
);
406 err
= dnet_request_stat(n
, NULL
, DNET_CMD_STAT
, 0, NULL
, NULL
);
411 if (io_counter_stat
) {
412 err
= dnet_request_stat(n
, NULL
, DNET_CMD_STAT_COUNT
, DNET_ATTR_CNTR_GLOBAL
, NULL
, NULL
);
418 struct dnet_addr addr
;
420 for (i
=0; i
<have_remote
; ++i
) {
421 memset(&addr
, 0, sizeof(addr
));
422 addr
.addr_len
= sizeof(addr
.addr
);
424 err
= dnet_fill_addr(&addr
, remotes
[i
].addr
, remotes
[i
].port
,
425 remotes
[i
].family
, remotes
[i
].sock_type
, remotes
[i
].proto
);
427 dnet_log_raw(n
, DNET_LOG_ERROR
, "ioclient: dnet_fill_addr: %s:%s:%d, sock_type: %d, proto: %d: %s %d\n",
428 remotes
[i
].addr
, remotes
[i
].port
,
429 remotes
[i
].family
, remotes
[i
].sock_type
, remotes
[i
].proto
,
430 strerror(-err
), err
);
433 err
= dnet_update_status(n
, &addr
, NULL
, &node_status
);
435 dnet_log_raw(n
, DNET_LOG_ERROR
, "ioclient: dnet_update_status: %s:%s:%d, sock_type: %d, proto: %d: update: %d: "
437 remotes
[i
].addr
, remotes
[i
].port
,
438 remotes
[i
].family
, remotes
[i
].sock_type
, remotes
[i
].proto
, update_status
,
439 strerror(-err
), err
);
445 dnet_node_destroy(n
);