poll() uses msecs as timeout
[elliptics.git] / example / backends.c
blob1894dca60432b4080b70974f776ffd6179aa96f6
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/statvfs.h>
20 #include <errno.h>
21 #include <ctype.h>
22 #include <dirent.h>
23 #include <fcntl.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
29 #include "elliptics/packet.h"
30 #include "elliptics/interface.h"
32 #include "backends.h"
34 #ifndef __unused
35 #define __unused __attribute__ ((unused))
36 #endif
38 #if defined HAVE_PROC_STAT
39 static int backend_vm_stat(struct dnet_stat *st)
41 int err;
42 FILE *f;
43 float la[3];
44 unsigned long long stub;
46 f = fopen("/proc/loadavg", "r");
47 if (!f) {
48 err = -errno;
49 dnet_backend_log(DNET_LOG_ERROR, "Failed to open '/proc/loadavg': %s [%d].\n",
50 strerror(errno), errno);
51 goto err_out_exit;
54 err = fscanf(f, "%f %f %f", &la[0], &la[1], &la[2]);
55 if (err != 3) {
56 err = -errno;
57 if (!err)
58 err = -EINVAL;
60 dnet_backend_log(DNET_LOG_ERROR, "Failed to read load average data: %s [%d].\n",
61 strerror(errno), errno);
62 goto err_out_close;
65 st->la[0] = la[0] * 100;
66 st->la[1] = la[1] * 100;
67 st->la[2] = la[2] * 100;
69 fclose(f);
71 f = fopen("/proc/meminfo", "r");
72 if (!f) {
73 err = -errno;
74 dnet_backend_log(DNET_LOG_ERROR, "Failed to open '/proc/meminfo': %s [%d].\n",
75 strerror(errno), errno);
76 goto err_out_exit;
79 err = fscanf(f, "MemTotal:%llu kB\n", (unsigned long long *)&st->vm_total);
80 err = fscanf(f, "MemFree:%llu kB\n", (unsigned long long *)&st->vm_free);
81 err = fscanf(f, "Buffers:%llu kB\n", (unsigned long long *)&st->vm_buffers);
82 err = fscanf(f, "Cached:%llu kB\n", (unsigned long long *)&st->vm_cached);
83 err = fscanf(f, "SwapCached:%llu kB\n", (unsigned long long *)&stub);
84 err = fscanf(f, "Active:%llu kB\n", (unsigned long long *)&st->vm_active);
85 err = fscanf(f, "Inactive:%llu kB\n", (unsigned long long *)&st->vm_inactive);
87 fclose(f);
88 return 0;
90 err_out_close:
91 fclose(f);
92 err_out_exit:
93 return err;
95 #elif defined HAVE_SYSCTL_STAT
96 #include <sys/sysctl.h>
97 #include <sys/resource.h>
99 static int backend_vm_stat(struct dnet_stat *st)
101 int err;
102 struct loadavg la;
103 long page_size = 0;
104 size_t sz = sizeof(la);
106 err = sysctlbyname("vm.loadavg", &la, &sz, NULL, 0);
107 if (err) {
108 err = -errno;
109 dnet_backend_log(DNET_LOG_ERROR, "Failed to get load average data: %s [%d].\n",
110 strerror(errno), errno);
111 return err;
114 st->la[0] = (double)la.ldavg[0] / la.fscale * 100;
115 st->la[1] = (double)la.ldavg[1] / la.fscale * 100;
116 st->la[2] = (double)la.ldavg[2] / la.fscale * 100;
118 sz = sizeof(uint64_t);
119 sysctlbyname("vm.stats.vm.v_active_count", &st->vm_active, &sz, NULL, 0);
120 sz = sizeof(uint64_t);
121 sysctlbyname("vm.stats.vm.v_inactive_count", &st->vm_inactive, &sz, NULL, 0);
122 sz = sizeof(uint64_t);
123 sysctlbyname("vm.stats.vm.v_cache_count", &st->vm_cached, &sz, NULL, 0);
124 sz = sizeof(uint64_t);
125 sysctlbyname("vm.stats.vm.v_free_count", &st->vm_free, &sz, NULL, 0);
126 sz = sizeof(uint64_t);
127 sysctlbyname("vm.stats.vm.v_wire_count", &st->vm_buffers, &sz, NULL, 0);
128 sz = sizeof(uint64_t);
129 sysctlbyname("vm.stats.vm.v_page_count", &st->vm_total, &sz, NULL, 0);
130 sz = sizeof(page_size);
131 sysctlbyname("vm.stats.vm.v_page_size", &page_size, &sz, NULL, 0);
133 page_size /= 1024;
135 st->vm_total *= page_size;
136 st->vm_active *= page_size;
137 st->vm_inactive *= page_size;
138 st->vm_free *= page_size;
139 st->vm_cached *= page_size;
140 st->vm_buffers *= page_size;
142 return 0;
144 #else
145 static int backend_vm_stat(struct dnet_stat *st __unused)
147 return 0;
149 #endif
151 int backend_stat_low_level(const char *path, struct dnet_stat *st)
153 struct statvfs s;
154 int err;
155 float la[3];
157 err = statvfs(path, &s);
158 if (err) {
159 err = -errno;
160 dnet_backend_log(DNET_LOG_ERROR, "Failed to get VFS statistics of '%s': %s [%d].\n",
161 path, strerror(errno), errno);
162 return err;
165 st->bsize = s.f_bsize;
166 st->frsize = s.f_frsize;
167 st->blocks = s.f_blocks;
168 st->bfree = s.f_bfree;
169 st->bavail = s.f_bavail;
170 st->files = s.f_files;
171 st->ffree = s.f_ffree;
172 st->favail = s.f_favail;
173 st->fsid = s.f_fsid;
174 st->flag = s.f_flag;
175 st->namemax = s.f_namemax;
177 err = backend_vm_stat(st);
178 if (err)
179 return err;
181 la[0] = (float)st->la[0] / 100.0;
182 la[1] = (float)st->la[1] / 100.0;
183 la[2] = (float)st->la[2] / 100.0;
185 dnet_backend_log(DNET_LOG_DEBUG, "Stat: la: %f %f %f, mem: total: %llu, free: %llu, cache: %llu.\n",
186 la[0], la[1], la[2],
187 (unsigned long long)st->vm_total, (unsigned long long)st->vm_free, (unsigned long long)st->vm_cached);
189 dnet_convert_stat(st);
191 return 0;
194 int backend_stat(void *state, char *path, struct dnet_cmd *cmd)
196 struct dnet_stat st;
197 int err;
199 if (!path)
200 path = ".";
202 memset(&st, 0, sizeof(struct dnet_stat));
204 err = backend_stat_low_level(path, &st);
205 if (err)
206 return err;
208 return dnet_send_reply(state, cmd, &st, sizeof(struct dnet_stat), 0);
211 int backend_storage_size(struct dnet_config_backend *b, const char *root)
213 struct statvfs s;
214 int err;
216 err = statvfs(root, &s);
217 if (err) {
218 err = -errno;
219 dnet_backend_log(DNET_LOG_ERROR, "Failed to get VFS statistics of '%s': %s [%d].\n",
220 root, strerror(errno), errno);
221 return err;
224 b->storage_size = s.f_frsize * s.f_blocks;
225 b->storage_free = s.f_bsize * s.f_bavail;
227 return 0;