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_config cfg
, rem
, *remotes
= NULL
;
87 char *logfile
= "/dev/stderr", *readf
= NULL
, *writef
= NULL
, *cmd
= NULL
, *lookup
= NULL
;
88 char *read_data
= NULL
;
90 unsigned char trans_id
[DNET_ID_SIZE
], *id
= NULL
;
92 uint64_t offset
, size
;
93 int *groups
= NULL
, group_num
= 0;
94 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_level
= ~0U;
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) {
119 ioflags
= strtoull(optarg
, NULL
, 0);
125 cflags
= strtoull(optarg
, NULL
, 0);
131 node_status
.nflags
= strtol(optarg
, NULL
, 0);
135 node_status
.log_level
= atoi(optarg
);
140 cfg
.nsize
= strlen(optarg
);
146 offset
= strtoull(optarg
, NULL
, 0);
149 size
= strtoull(optarg
, NULL
, 0);
152 ioclient_logger
.log_level
= atoi(optarg
);
158 node_status
.status_flags
= strtol(optarg
, NULL
, 0);
165 single_node_stat
= 0;
171 cfg
.check_timeout
= cfg
.wait_timeout
= atoi(optarg
);
180 err
= dnet_parse_numeric_id(optarg
, trans_id
);
186 group_num
= dnet_parse_groups(optarg
, &groups
);
191 err
= dnet_parse_addr(optarg
, &rem
);
195 remotes
= realloc(remotes
, sizeof(rem
) * have_remote
);
198 memcpy(&remotes
[have_remote
- 1], &rem
, sizeof(rem
));
216 log
= fopen(logfile
, "a");
219 fprintf(stderr
, "Failed to open log file %s: %s.\n", logfile
, strerror(errno
));
223 ioclient_logger
.log_private
= log
;
224 ioclient_logger
.log
= dnet_common_log
;
225 cfg
.log
= &ioclient_logger
;
227 n
= dnet_node_create(&cfg
);
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
);
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
]);
256 return dnet_start_defrag(n
, cflags
);
262 dnet_setup_id(&raw
, 0, id
);
265 err
= dnet_write_file_id(n
, writef
, &raw
, offset
, offset
, size
, cflags
, ioflags
);
267 err
= dnet_write_file(n
, writef
, writef
, strlen(writef
), offset
, offset
, size
, cflags
, ioflags
, type
);
278 dnet_setup_id(&raw
, 0, id
);
281 err
= dnet_read_file_id(n
, readf
, &raw
, offset
, size
);
283 err
= dnet_read_file(n
, readf
, readf
, strlen(readf
), offset
, size
, type
);
292 struct dnet_io_attr io
;
295 dnet_transform(n
, read_data
, strlen(read_data
), &raw
);
297 memcpy(&raw
.id
, id
, DNET_ID_SIZE
);
300 raw
.group_id
= 0; /* unused */
302 memset(&io
, 0, sizeof(io
));
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 */
311 err
= dnet_read_latest(n
, &raw
, &io
, cflags
, &data
);
315 data
+= sizeof(struct dnet_io_attr
);
316 io
.size
-= sizeof(struct dnet_io_attr
);
319 err
= write(1, data
, io
.size
);
322 dnet_log_raw(n
, DNET_LOG_ERROR
, "%s: can not write data to stdout: %d %s",
323 read_data
, err
, strerror(-err
));
335 dnet_setup_id(&raw
, 0, id
);
337 dnet_remove_object_now(n
, &raw
, cflags
, ioflags
);
342 err
= dnet_remove_file(n
, removef
, strlen(removef
), NULL
, cflags
, ioflags
);
348 struct dnet_id __did
, *did
= NULL
;
350 int len
= strlen(cmd
);
351 int event_size
= len
;
355 tmp
= strchr(cmd
, ' ');
357 event_size
= tmp
- cmd
;
363 dnet_setup_id(did
, 0, id
);
367 sph
= malloc(sizeof(struct sph
) + len
+ 1);
371 memset(sph
, 0, sizeof(struct sph
));
373 sph
->flags
= DNET_SPH_FLAGS_SRC_BLOCK
;
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
);
388 printf("%.*s\n", err
, ret
);
394 err
= dnet_lookup(n
, lookup
);
400 err
= dnet_request_stat(n
, NULL
, DNET_CMD_STAT
, 0, NULL
, NULL
);
405 if (io_counter_stat
) {
406 err
= dnet_request_stat(n
, NULL
, DNET_CMD_STAT_COUNT
, DNET_ATTR_CNTR_GLOBAL
, NULL
, NULL
);
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
);
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
);
429 dnet_log_raw(n
, DNET_LOG_ERROR
, "ioclient: dnet_update_status: %s:%s:%d, sock_type: %d, proto: %d: update: %d: "
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
);