2 * 2011+ 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 #define _XOPEN_SOURCE 600
18 #include <sys/types.h>
20 #include <sys/socket.h>
37 #include "elliptics/interface.h"
38 #include "elliptics/packet.h"
39 #include "elliptics/cppdef.h"
43 using namespace ioremap::elliptics
;
45 class finder
: public session
{
47 finder(node
&n
) : session(n
) {};
50 void add_remote(const char *addr
);
52 void parse_lookup(const std::string
&ret
);
53 void parse_meta(const std::string
&ret
);
56 void finder::add_remote(const char *addr
)
58 struct dnet_config rem
;
61 memset(&rem
, 0, sizeof(rem
));
63 err
= dnet_parse_addr((char *)addr
, &rem
);
65 std::ostringstream str
;
66 str
<< "Failed to parse addr: " << addr
;
67 throw std::runtime_error(str
.str());
70 m_node
->add_remote(rem
.addr
, atoi(rem
.port
), rem
.family
);
73 void finder::parse_lookup(const std::string
&ret
)
75 long size
= ret
.size();
76 void *data
= (void *)ret
.data();
79 struct dnet_addr
*addr
= (struct dnet_addr
*)data
;
80 struct dnet_cmd
*cmd
= (struct dnet_cmd
*)(addr
+ 1);
83 struct dnet_file_info
*info
= NULL
;
84 char addr_str
[128] = "no-address";
86 if (cmd
->size
>= sizeof(struct dnet_addr_attr
)) {
87 struct dnet_addr_attr
*a
= (struct dnet_addr_attr
*)(cmd
+ 1);
89 if (cmd
->size
> sizeof(struct dnet_addr_attr
) + sizeof(struct dnet_file_info
)) {
90 info
= (struct dnet_file_info
*)(a
+ 1);
91 dnet_convert_file_info(info
);
94 dnet_convert_addr_attr(a
);
95 dnet_server_convert_dnet_addr_raw(&a
->addr
, addr_str
, sizeof(addr_str
));
98 std::string route_addr
= "failed to get route table";
101 route_addr
= lookup_addr(cmd
->id
);
102 } catch (const std::exception
&e
) {
106 dnet_log_raw(get_node(), DNET_LOG_DATA
, "%s: FIND object: %s: should live at: %s\n",
107 dnet_dump_id(&cmd
->id
), addr_str
, route_addr
.c_str());
109 dnet_log_raw(get_node(), DNET_LOG_DATA
, "%s: FIND-OK object: %s: should live at: %s, "
110 "offset: %llu, size: %llu, mode: %llo, path: %s\n",
111 dnet_dump_id(&cmd
->id
), addr_str
, route_addr
.c_str(),
112 (unsigned long long)info
->offset
, (unsigned long long)info
->size
,
113 (unsigned long long)info
->mode
, (char *)(info
+ 1));
115 if (cmd
->status
!= 0)
116 dnet_log_raw(get_node(), DNET_LOG_DATA
, "%s: FIND object: status: %d\n", dnet_dump_id(&cmd
->id
), cmd
->status
);
119 data
= (char *)data
+ sizeof(struct dnet_addr
) + sizeof(struct dnet_cmd
) + cmd
->size
;
120 size
-= sizeof(struct dnet_addr
) + sizeof(struct dnet_cmd
) + cmd
->size
;
124 void finder::parse_meta(const std::string
&ret
)
126 long size
= ret
.size();
127 void *data
= (void *)ret
.data();
130 struct dnet_addr
*addr
= (struct dnet_addr
*)data
;
131 struct dnet_cmd
*cmd
= (struct dnet_cmd
*)(addr
+ 1);
134 dnet_server_convert_dnet_addr_raw(addr
, addr_str
, sizeof(addr_str
));
136 if (cmd
->size
> sizeof(struct dnet_io_attr
)) {
137 struct dnet_io_attr
*io
= (struct dnet_io_attr
*)(cmd
+ 1);
139 dnet_convert_io_attr(io
);
141 dnet_log_raw(get_node(), DNET_LOG_DATA
, "%s: FIND-OK meta: %s: cmd: %s, io size: %llu\n",
142 dnet_dump_id(&cmd
->id
), addr_str
, dnet_cmd_string(cmd
->cmd
),
143 (unsigned long long)io
->size
);
145 struct dnet_meta_container mc
;
146 memset(&mc
, 0, sizeof(mc
));
150 memcpy(&mc
.id
, &cmd
->id
, sizeof(struct dnet_id
));
151 dnet_meta_print(m_session
, &mc
);
153 if (cmd
->status
!= 0)
154 dnet_log_raw(get_node(), DNET_LOG_DATA
, "%s: FIND meta: %s: status: %d\n",
155 dnet_dump_id(&cmd
->id
), addr_str
, cmd
->status
);
158 data
= (char *)data
+ sizeof(struct dnet_addr
) + sizeof(struct dnet_cmd
) + cmd
->size
;
159 size
-= sizeof(struct dnet_addr
) + sizeof(struct dnet_cmd
) + cmd
->size
;
163 static __attribute__ ((noreturn
)) void efinder_usage(const char *p
)
165 fprintf(stderr
, "Usage: %s <options>\n"
166 " -r addr:port:family - remote node to connect\n"
167 " -l log - log file\n"
168 " -m level - log level\n"
169 " -I id - object ID\n"
175 int main(int argc
, char *argv
[])
178 char *logfile
= (char *)"/dev/stderr";
179 int log_level
= DNET_LOG_ERROR
;
182 struct dnet_trans_control ctl
;
184 while ((ch
= getopt(argc
, argv
, "r:l:m:I:h")) != -1) {
193 log_level
= strtoul(optarg
, NULL
, 0);
196 err
= dnet_parse_numeric_id(optarg
, raw
.id
);
202 efinder_usage(argv
[0]);
208 fprintf(stderr
, "You must specify remote addr and object ID\n");
209 efinder_usage(argv
[0]);
213 log_file
log(logfile
, log_level
);
217 find
.add_remote(remote
);
222 memset(&ctl
, 0, sizeof(struct dnet_trans_control
));
224 ctl
.priv
= (void *)&c
;
225 ctl
.complete
= callback::complete_callback
;
227 dnet_setup_id(&ctl
.id
, 0, raw
.id
);
228 ctl
.cflags
= DNET_FLAGS_DIRECT
| DNET_FLAGS_NEED_ACK
| DNET_ATTR_META_TIMES
;
229 ctl
.cmd
= DNET_CMD_LOOKUP
;
231 int num
= find
.request_cmd(ctl
);
232 std::string lookup_ret
= c
.wait(num
);
233 find
.parse_lookup(lookup_ret
);
241 memset(&ctl
, 0, sizeof(ctl
));
243 ctl
.priv
= (void *)&c
;
244 ctl
.complete
= callback::complete_callback
;
246 dnet_setup_id(&ctl
.id
, 0, raw
.id
);
247 ctl
.cmd
= DNET_CMD_READ
;
248 ctl
.cflags
= DNET_FLAGS_DIRECT
| DNET_FLAGS_NEED_ACK
;
250 struct dnet_io_attr io
;
251 memset(&io
, 0, sizeof(io
));
252 io
.flags
= DNET_IO_FLAGS_META
;
253 memcpy(io
.id
, ctl
.id
.id
, DNET_ID_SIZE
);
254 memcpy(io
.parent
, ctl
.id
.id
, DNET_ID_SIZE
);
256 ctl
.size
= sizeof(io
);
258 int num
= find
.request_cmd(ctl
);
259 std::string meta_ret
= c
.wait(num
);
260 find
.parse_meta(meta_ret
);
262 } catch (const std::exception
&e
) {
263 std::cerr
<< e
.what() << std::endl
;