Merge branch 'master' of github.com:reverbrain/elliptics
[elliptics.git] / example / stat.c
blobf5b153674436178bfd9236c324c167bb5a7edd1f
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 stat_logger;
43 static int stat_mem, stat_la, stat_fs;
45 static int stat_complete(struct dnet_net_state *state,
46 struct dnet_cmd *cmd,
47 void *priv)
49 float la[3];
50 struct dnet_stat *st;
51 char str[64];
52 struct tm tm;
53 struct timeval tv;
54 FILE *stream = priv;
56 if (is_trans_destroyed(state, cmd))
57 return 0;
59 if (cmd->size != sizeof(struct dnet_stat))
60 return cmd->status;
62 if (!stat_mem && !stat_la && !stat_fs)
63 return 0;
65 gettimeofday(&tv, NULL);
66 localtime_r((time_t *)&tv.tv_sec, &tm);
67 strftime(str, sizeof(str), "%F %R:%S", &tm);
69 fprintf(stream, "%s.%06lu :", str, (unsigned long)tv.tv_usec);
71 st = (struct dnet_stat *)(cmd + 1);
73 dnet_convert_stat(st);
75 la[0] = (float)st->la[0] / 100.0;
76 la[1] = (float)st->la[1] / 100.0;
77 la[2] = (float)st->la[2] / 100.0;
80 fprintf(stream, "%s: %s: ", dnet_dump_id(&cmd->id), dnet_state_dump_addr(state));
82 if (stat_la)
83 fprintf(stream, "la: %3.2f %3.2f %3.2f ", la[0], la[1], la[2]);
85 if (stat_mem)
86 fprintf(stream, "mem: total: %8llu kB, free: %8llu kB, cache: %8llu kB, buffers: %8llu, active: %8llu, inactive: %8llu ",
87 (unsigned long long)st->vm_total, (unsigned long long)st->vm_free,
88 (unsigned long long)st->vm_cached, (unsigned long long)st->vm_buffers,
89 (unsigned long long)st->vm_active, (unsigned long long)st->vm_inactive);
91 if (stat_fs)
92 fprintf(stream, "fs: total: %8llu mB, avail: %8llu/%8llu mB ",
93 (unsigned long long)(st->frsize * st->blocks / 1024 / 1024),
94 (unsigned long long)(st->bavail * st->bsize / 1024 / 1024),
95 (unsigned long long)(st->bfree * st->bsize / 1024 / 1024));
97 fprintf(stream, "\n");
98 fflush(stream);
100 return 0;
103 static void stat_usage(char *p)
105 fprintf(stderr, "Usage: %s\n"
106 " -r addr:port:family - adds a route to the given node\n"
107 " -l log - log file. Default: disabled\n"
108 " -L log - statistics log. Default: stdout\n"
109 " -w timeout - wait timeout in seconds used to wait for content sync.\n"
110 " -m level - log level\n"
111 " -I id - request statistics from node which handles given id\n"
112 " -t timeout - timeout in seconds to repeatedly request statistics\n"
113 " -M - show memory usage statistics\n"
114 " -F - show filesystem usage statistics\n"
115 " -A - show load average statistics\n"
116 , p);
119 int main(int argc, char *argv[])
121 int ch, err, i, have_remote = 0;
122 struct dnet_node *n = NULL;
123 struct dnet_config cfg, rem;
124 int max_id_idx = 1000, id_idx = 0;
125 int timeout;
126 unsigned char id[max_id_idx][DNET_ID_SIZE];
127 char *logfile = "/dev/stderr", *statfile = "/dev/stdout";
128 FILE *log = NULL, *stat;
130 memset(&cfg, 0, sizeof(struct dnet_config));
132 cfg.sock_type = SOCK_STREAM;
133 cfg.proto = IPPROTO_TCP;
134 cfg.wait_timeout = 60*60;
135 stat_logger.log_level = DNET_LOG_ERROR;
137 timeout = 1;
139 memcpy(&rem, &cfg, sizeof(struct dnet_config));
141 while ((ch = getopt(argc, argv, "MFAt:m:w:l:I:r:h")) != -1) {
142 switch (ch) {
143 case 'M':
144 stat_mem = 1;
145 break;
146 case 'F':
147 stat_fs = 1;
148 break;
149 case 'A':
150 stat_la = 1;
151 break;
152 case 't':
153 timeout = atoi(optarg);
154 break;
155 case 'm':
156 stat_logger.log_level = strtoul(optarg, NULL, 0);
157 break;
158 case 'w':
159 cfg.wait_timeout = atoi(optarg);
160 break;
161 case 'L':
162 statfile = optarg;
163 break;
164 case 'l':
165 logfile = optarg;
166 break;
167 case 'I':
168 if (id_idx < max_id_idx) {
169 err = dnet_parse_numeric_id(optarg, id[id_idx]);
170 if (err)
171 return err;
172 id_idx++;
174 break;
175 case 'r':
176 err = dnet_parse_addr(optarg, &rem);
177 if (err)
178 return err;
179 have_remote = 1;
180 break;
181 case 'h':
182 default:
183 stat_usage(argv[0]);
184 return -1;
188 if (!have_remote) {
189 fprintf(stderr, "No remote node specified to route requests.\n");
190 return -ENOENT;
193 log = fopen(logfile, "a");
194 if (!log) {
195 err = -errno;
196 fprintf(stderr, "Failed to open log file %s: %s.\n", logfile, strerror(errno));
197 return err;
200 stat_logger.log_private = log;
201 stat_logger.log = dnet_common_log;
202 cfg.log = &stat_logger;
204 stat = fopen(statfile, "a");
205 if (!stat) {
206 err = -errno;
207 fprintf(stderr, "Failed to open stat file %s: %s.\n", statfile, strerror(errno));
208 return err;
211 n = dnet_node_create(&cfg);
212 if (!n)
213 return -1;
215 err = dnet_add_state(n, &rem);
216 if (err)
217 return err;
219 while (1) {
220 struct dnet_id raw;
222 if (!id_idx) {
223 err = dnet_request_stat(n, NULL, DNET_CMD_STAT, 0, stat_complete, stat);
224 if (err < 0)
225 return err;
228 for (i=0; i<id_idx; ++i) {
229 dnet_setup_id(&raw, 0, id[i]);
230 err = dnet_request_stat(n, &raw, DNET_CMD_STAT, 0, stat_complete, stat);
231 if (err < 0)
232 return err;
235 sleep(timeout);
238 return 0;