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.
16 #include <sys/types.h>
18 #include <sys/socket.h>
20 #include <sys/syscall.h>
32 #include <netinet/in.h>
34 #include "elliptics/packet.h"
35 #include "elliptics/interface.h"
41 #define __unused __attribute__ ((unused))
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"
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_session
*s
= 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
;
101 memset(&node_status
, 0, sizeof(struct dnet_node_status
));
102 memset(&cfg
, 0, sizeof(struct dnet_config
));
104 node_status
.nflags
= -1;
105 node_status
.status_flags
= -1;
106 node_status
.log_level
= ~0U;
110 cfg
.sock_type
= SOCK_STREAM
;
111 cfg
.proto
= IPPROTO_TCP
;
112 cfg
.wait_timeout
= 60;
113 ioclient_logger
.log_level
= DNET_LOG_ERROR
;
115 memcpy(&rem
, &cfg
, sizeof(struct dnet_config
));
117 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) {
120 ioflags
= strtoull(optarg
, NULL
, 0);
126 cflags
= strtoull(optarg
, NULL
, 0);
132 node_status
.nflags
= strtol(optarg
, NULL
, 0);
136 node_status
.log_level
= atoi(optarg
);
141 cfg
.nsize
= strlen(optarg
);
147 offset
= strtoull(optarg
, NULL
, 0);
150 size
= strtoull(optarg
, NULL
, 0);
153 ioclient_logger
.log_level
= atoi(optarg
);
159 node_status
.status_flags
= strtol(optarg
, NULL
, 0);
166 single_node_stat
= 0;
172 cfg
.check_timeout
= cfg
.wait_timeout
= atoi(optarg
);
181 err
= dnet_parse_numeric_id(optarg
, trans_id
);
187 group_num
= dnet_parse_groups(optarg
, &groups
);
192 err
= dnet_parse_addr(optarg
, &rem
);
196 remotes
= realloc(remotes
, sizeof(rem
) * have_remote
);
199 memcpy(&remotes
[have_remote
- 1], &rem
, sizeof(rem
));
217 log
= fopen(logfile
, "a");
220 fprintf(stderr
, "Failed to open log file %s: %s.\n", logfile
, strerror(errno
));
224 ioclient_logger
.log_private
= log
;
225 ioclient_logger
.log
= dnet_common_log
;
226 cfg
.log
= &ioclient_logger
;
228 n
= dnet_node_create(&cfg
);
233 sigaddset(&mask
, SIGTERM
);
234 sigaddset(&mask
, SIGINT
);
235 sigaddset(&mask
, SIGHUP
);
236 sigaddset(&mask
, SIGCHLD
);
237 pthread_sigmask(SIG_UNBLOCK
, &mask
, NULL
);
238 sigprocmask(SIG_UNBLOCK
, &mask
, NULL
);
241 int error
= -ECONNRESET
;
242 for (i
=0; i
<have_remote
; ++i
) {
243 if (single_node_stat
&& (vfs_stat
|| io_counter_stat
))
244 remotes
[i
].flags
= DNET_CFG_NO_ROUTE_LIST
;
245 err
= dnet_add_state(n
, &remotes
[i
]);
254 s
= dnet_session_create(n
);
258 dnet_session_set_groups(s
, groups
, group_num
);
261 return dnet_start_defrag(s
, cflags
);
267 dnet_setup_id(&raw
, 0, id
);
270 err
= dnet_write_file_id(s
, writef
, &raw
, offset
, offset
, size
, cflags
, ioflags
);
272 err
= dnet_write_file(s
, writef
, writef
, strlen(writef
), offset
, offset
, size
, cflags
, ioflags
, type
);
283 dnet_setup_id(&raw
, 0, id
);
286 err
= dnet_read_file_id(s
, readf
, &raw
, offset
, size
);
288 err
= dnet_read_file(s
, readf
, readf
, strlen(readf
), offset
, size
, type
);
297 struct dnet_io_attr io
;
300 dnet_transform(n
, read_data
, strlen(read_data
), &raw
);
302 memcpy(&raw
.id
, id
, DNET_ID_SIZE
);
305 raw
.group_id
= 0; /* unused */
307 memset(&io
, 0, sizeof(io
));
310 memcpy(io
.id
, raw
.id
, DNET_ID_SIZE
);
311 memcpy(io
.parent
, raw
.id
, DNET_ID_SIZE
);
313 /* number of copies to check to find the latest data */
316 err
= dnet_read_latest(s
, &raw
, &io
, cflags
, &data
);
320 data
+= sizeof(struct dnet_io_attr
);
321 io
.size
-= sizeof(struct dnet_io_attr
);
324 err
= write(1, data
, io
.size
);
327 dnet_log_raw(n
, DNET_LOG_ERROR
, "%s: can not write data to stdout: %d %s",
328 read_data
, err
, strerror(-err
));
340 dnet_setup_id(&raw
, 0, id
);
342 dnet_remove_object_now(s
, &raw
, cflags
, ioflags
);
347 err
= dnet_remove_file(s
, removef
, strlen(removef
), NULL
, cflags
, ioflags
);
353 struct dnet_id __did
, *did
= NULL
;
355 int len
= strlen(cmd
);
356 int event_size
= len
;
360 tmp
= strchr(cmd
, ' ');
362 event_size
= tmp
- cmd
;
368 dnet_setup_id(did
, 0, id
);
372 sph
= malloc(sizeof(struct sph
) + len
+ 1);
376 memset(sph
, 0, sizeof(struct sph
));
378 sph
->flags
= DNET_SPH_FLAGS_SRC_BLOCK
;
380 sph
->binary_size
= 0;
381 sph
->data_size
= len
- event_size
;
382 sph
->event_size
= event_size
;
384 sprintf(sph
->data
, "%s", cmd
);
386 err
= dnet_send_cmd(s
, did
, sph
, (void **)&ret
);
393 printf("%.*s\n", err
, ret
);
399 err
= dnet_lookup(s
, lookup
);
405 err
= dnet_request_stat(s
, NULL
, DNET_CMD_STAT
, 0, NULL
, NULL
);
410 if (io_counter_stat
) {
411 err
= dnet_request_stat(s
, NULL
, DNET_CMD_STAT_COUNT
, DNET_ATTR_CNTR_GLOBAL
, NULL
, NULL
);
417 struct dnet_addr addr
;
419 for (i
=0; i
<have_remote
; ++i
) {
420 memset(&addr
, 0, sizeof(addr
));
421 addr
.addr_len
= sizeof(addr
.addr
);
423 err
= dnet_fill_addr(&addr
, remotes
[i
].addr
, remotes
[i
].port
,
424 remotes
[i
].family
, remotes
[i
].sock_type
, remotes
[i
].proto
);
426 dnet_log_raw(n
, DNET_LOG_ERROR
, "ioclient: dnet_fill_addr: %s:%s:%d, sock_type: %d, proto: %d: %s %d\n",
427 remotes
[i
].addr
, remotes
[i
].port
,
428 remotes
[i
].family
, remotes
[i
].sock_type
, remotes
[i
].proto
,
429 strerror(-err
), err
);
432 err
= dnet_update_status(s
, &addr
, NULL
, &node_status
);
434 dnet_log_raw(n
, DNET_LOG_ERROR
, "ioclient: dnet_update_status: %s:%s:%d, sock_type: %d, proto: %d: update: %d: "
436 remotes
[i
].addr
, remotes
[i
].port
,
437 remotes
[i
].family
, remotes
[i
].sock_type
, remotes
[i
].proto
, update_status
,
438 strerror(-err
), err
);
444 dnet_session_destroy(s
);
445 dnet_node_destroy(n
);