Fixed dnet_mix_states() when ID is null
[elliptics.git] / example / notify.c
blob0f271038db3b7db99bbf1e55b1727c682a4a3395
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 <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <time.h>
31 #include <netinet/in.h>
33 #include "elliptics/packet.h"
34 #include "elliptics/interface.h"
36 #include "common.h"
38 #ifndef __unused
39 #define __unused __attribute__ ((unused))
40 #endif
42 static struct dnet_log notify_logger;
44 static int notify_complete(struct dnet_net_state *state,
45 struct dnet_cmd *cmd,
46 void *priv)
48 struct dnet_io_notification *io;
49 char str[64];
50 struct tm tm;
51 struct timeval tv;
52 FILE *stream = priv;
54 if (is_trans_destroyed(state, cmd))
55 return 0;
57 if (cmd->size != sizeof(struct dnet_io_notification))
58 return 0;
60 gettimeofday(&tv, NULL);
61 localtime_r((time_t *)&tv.tv_sec, &tm);
62 strftime(str, sizeof(str), "%F %R:%S", &tm);
64 fprintf(stream, "%s.%06lu : ", str, (unsigned long)tv.tv_usec);
66 io = (struct dnet_io_notification *)(cmd + 1);
68 dnet_convert_io_notification(io);
70 fprintf(stream, "%s: client: %s, size: %llu, offset: %llu, flags: %x\n",
71 dnet_dump_id_str(io->io.id), dnet_server_convert_dnet_addr(&io->addr.addr),
72 (unsigned long long)io->io.size,
73 (unsigned long long)io->io.offset, io->io.flags);
74 fflush(stream);
76 return 0;
79 static void notify_usage(char *p)
81 fprintf(stderr, "Usage: %s\n"
82 " -a addr:port:family - creates a node with given network address\n"
83 " -r addr:port:family - adds a route to the given node\n"
84 " -l log - log file. Default: disabled\n"
85 " -L log - notifications log. Default: stdout\n"
86 " -w timeout - wait timeout in seconds used to wait for content sync.\n"
87 " -m level - log level\n"
88 " -g group_id - group ID to connect\n"
89 " -I id - request notifications for given ID\n"
90 , p);
93 int main(int argc, char *argv[])
95 int ch, err, have_remote = 0, i;
96 struct dnet_node *n = NULL;
97 struct dnet_session *s = NULL;
98 struct dnet_config cfg, rem;
99 int max_id_idx = 1000, id_idx = 0, group_id = 0;
100 unsigned char id[max_id_idx][DNET_ID_SIZE];
101 char *logfile = "/dev/stderr", *notify_file = "/dev/stdout";
102 FILE *log = NULL, *notify;
104 memset(&cfg, 0, sizeof(struct dnet_config));
106 cfg.sock_type = SOCK_STREAM;
107 cfg.proto = IPPROTO_TCP;
108 cfg.wait_timeout = 60*60;
109 notify_logger.log_level = DNET_LOG_INFO;
111 memcpy(&rem, &cfg, sizeof(struct dnet_config));
113 while ((ch = getopt(argc, argv, "g:m:w:l:I:a:r:h")) != -1) {
114 switch (ch) {
115 case 'm':
116 notify_logger.log_level = strtoul(optarg, NULL, 0);
117 break;
118 case 'w':
119 cfg.wait_timeout = atoi(optarg);
120 break;
121 case 'L':
122 notify_file = optarg;
123 break;
124 case 'l':
125 logfile = optarg;
126 break;
127 case 'I':
128 if (id_idx < max_id_idx) {
129 err = dnet_parse_numeric_id(optarg, id[id_idx]);
130 if (err)
131 return err;
132 id_idx++;
134 break;
135 case 'g':
136 group_id = atoi(optarg);
137 break;
138 case 'a':
139 err = dnet_parse_addr(optarg, &cfg);
140 if (err)
141 return err;
142 break;
143 case 'r':
144 err = dnet_parse_addr(optarg, &rem);
145 if (err)
146 return err;
147 have_remote = 1;
148 break;
149 case 'h':
150 default:
151 notify_usage(argv[0]);
152 return -1;
156 if (!id_idx) {
157 fprintf(stderr, "No ID specified to watch.\n");
158 return -EINVAL;
161 if (!have_remote) {
162 fprintf(stderr, "No remote node specified to route requests.\n");
163 return -ENOENT;
166 log = fopen(logfile, "a");
167 if (!log) {
168 err = -errno;
169 fprintf(stderr, "Failed to open log file %s: %s.\n", logfile, strerror(errno));
170 return err;
173 notify_logger.log_private = log;
174 notify_logger.log = dnet_common_log;
175 cfg.log = &notify_logger;
177 notify = fopen(notify_file, "a");
178 if (!notify) {
179 err = -errno;
180 fprintf(stderr, "Failed to open notify file %s: %s.\n", notify_file, strerror(errno));
181 return err;
184 n = dnet_node_create(&cfg);
185 if (!n)
186 return -1;
188 s = dnet_session_create(n);
189 if (!s)
190 return -1;
192 err = dnet_add_state(n, &rem);
193 if (err)
194 return err;
196 for (i=0; i<id_idx; ++i) {
197 struct dnet_id raw;
198 dnet_setup_id(&raw, group_id, id[i]);
199 err = dnet_request_notification(s, &raw, notify_complete, notify);
202 while (1) {
203 sleep(1);
206 return 0;