d2a7ace09b1b05ad9b3aad2bb401e2ae614afcbf
1 /* $Id$
2 * Substantial penalty for early withdrawal.
3 */
5 #include <unistd.h>
6 #include <ruby.h>
7 #include "../../src/rrd_tool.h"
9 typedef struct string_arr_t {
10 int len;
11 char **strings;
12 } string_arr;
14 VALUE mRRD;
15 VALUE rb_eRRDError;
17 typedef int (
18 *RRDFUNC) (
19 int argc,
20 char **argv);
22 #define RRD_CHECK_ERROR \
23 if (rrd_test_error()) \
24 rb_raise(rb_eRRDError, rrd_get_error()); \
25 rrd_clear_error();
27 string_arr string_arr_new(
28 VALUE rb_strings)
29 {
30 string_arr a;
31 char buf[64];
32 int i;
34 Check_Type(rb_strings, T_ARRAY);
35 a.len = RARRAY(rb_strings)->len + 1;
37 a.strings = malloc(a.len * sizeof(char *));
38 a.strings[0] = "dummy"; /* first element is a dummy element */
40 for (i = 0; i < a.len - 1; i++) {
41 VALUE v = rb_ary_entry(rb_strings, i);
43 switch (TYPE(v)) {
44 case T_STRING:
45 a.strings[i + 1] = strdup(STR2CSTR(v));
46 break;
47 case T_FIXNUM:
48 snprintf(buf, 63, "%d", FIX2INT(v));
49 a.strings[i + 1] = strdup(buf);
50 break;
51 default:
52 rb_raise(rb_eTypeError,
53 "invalid argument - %s, expected T_STRING or T_FIXNUM on index %d",
54 rb_class2name(CLASS_OF(v)), i);
55 break;
56 }
57 }
59 return a;
60 }
62 void string_arr_delete(
63 string_arr a)
64 {
65 int i;
67 /* skip dummy first entry */
68 for (i = 1; i < a.len; i++) {
69 free(a.strings[i]);
70 }
72 free(a.strings);
73 }
75 void reset_rrd_state(
76 )
77 {
78 optind = 0;
79 opterr = 0;
80 rrd_clear_error();
81 }
83 /* Simple Calls */
85 VALUE rrd_call(
86 RRDFUNC func,
87 VALUE args)
88 {
89 string_arr a;
91 a = string_arr_new(args);
92 reset_rrd_state();
93 func(a.len, a.strings);
94 string_arr_delete(a);
96 RRD_CHECK_ERROR return Qnil;
97 }
99 VALUE rb_rrd_create(
100 VALUE self,
101 VALUE args)
102 {
103 return rrd_call(rrd_create, args);
104 }
106 VALUE rb_rrd_dump(
107 VALUE self,
108 VALUE args)
109 {
110 return rrd_call(rrd_dump, args);
111 }
113 VALUE rb_rrd_resize(
114 VALUE self,
115 VALUE args)
116 {
117 return rrd_call(rrd_resize, args);
118 }
120 VALUE rb_rrd_restore(
121 VALUE self,
122 VALUE args)
123 {
124 return rrd_call(rrd_restore, args);
125 }
127 VALUE rb_rrd_tune(
128 VALUE self,
129 VALUE args)
130 {
131 return rrd_call(rrd_tune, args);
132 }
134 VALUE rb_rrd_update(
135 VALUE self,
136 VALUE args)
137 {
138 return rrd_call(rrd_update, args);
139 }
142 /* Calls Returning Data via the Info Interface */
144 VALUE rb_rrd_infocall(
145 RRDFUNC func,
146 VALUE args)
147 {
148 string_arr a;
149 rrd_info_t *p, *data;
150 VALUE result;
152 a = string_arr_new(args);
153 data = func(a.len, a.strings);
154 string_arr_delete(a);
156 RRD_CHECK_ERROR result = rb_hash_new();
158 p = data;
159 while (data) {
160 VALUE key = rb_str_new2(data->key);
162 switch (data->type) {
163 case RD_I_VAL:
164 if (isnan(data->value.u_val)) {
165 rb_hash_aset(result, key, Qnil);
166 } else {
167 rb_hash_aset(result, key, rb_float_new(data->value.u_val));
168 }
169 break;
170 case RD_I_CNT:
171 rb_hash_aset(result, key, INT2FIX(data->value.u_cnt));
172 break;
173 case RD_I_STR:
174 rb_hash_aset(result, key, rb_str_new2(data->value.u_str));
175 break;
176 case RD_I_BLO:
177 rb_hash_aset(result, key,
178 rb_str_new(data->value.u_blo.ptr,
179 data->value.u_blo.size));
180 break;
181 }
182 data = data->next;
183 }
184 rrd_info_free(p);
185 return result;
186 }
188 VALUE rb_rrd_info(
189 VALUE self,
190 VALUE args)
191 {
192 return rb_rrd_infocall(rrd_info, args);
193 }
195 VALUE rb_rrd_updatev(
196 VALUE self,
197 VALUE args)
198 {
199 return rb_rrd_infocall(rrd_update_v, args);
200 }
202 VALUE rb_rrd_graphv(
203 VALUE self,
204 VALUE args)
205 {
206 return rb_rrd_infocall(rrd_graph_v, args);
207 }
210 /* Other Calls */
212 VALUE rb_rrd_fetch(
213 VALUE self,
214 VALUE args)
215 {
216 string_arr a;
217 unsigned long i, j, k, step, ds_cnt;
218 rrd_value_t *raw_data;
219 char **raw_names;
220 VALUE data, names, result;
221 time_t start, end;
223 a = string_arr_new(args);
224 reset_rrd_state();
225 rrd_fetch(a.len, a.strings, &start, &end, &step, &ds_cnt, &raw_names,
226 &raw_data);
227 string_arr_delete(a);
229 RRD_CHECK_ERROR names = rb_ary_new();
231 for (i = 0; i < ds_cnt; i++) {
232 rb_ary_push(names, rb_str_new2(raw_names[i]));
233 rrd_freemem(raw_names[i]);
234 }
235 rrd_freemem(raw_names);
237 k = 0;
238 data = rb_ary_new();
239 for (i = start; i <= end; i += step) {
240 VALUE line = rb_ary_new2(ds_cnt);
242 for (j = 0; j < ds_cnt; j++) {
243 rb_ary_store(line, j, rb_float_new(raw_data[k]));
244 k++;
245 }
246 rb_ary_push(data, line);
247 }
248 rrd_freemem(raw_data);
250 result = rb_ary_new2(5);
251 rb_ary_store(result, 0, INT2NUM(start));
252 rb_ary_store(result, 1, INT2NUM(end));
253 rb_ary_store(result, 2, names);
254 rb_ary_store(result, 3, data);
255 rb_ary_store(result, 4, INT2FIX(step));
256 return result;
257 }
259 VALUE rb_rrd_graph(
260 VALUE self,
261 VALUE args)
262 {
263 string_arr a;
264 char **calcpr, **p;
265 VALUE result, print_results;
266 int xsize, ysize;
267 double ymin, ymax;
269 a = string_arr_new(args);
270 reset_rrd_state();
271 rrd_graph(a.len, a.strings, &calcpr, &xsize, &ysize, NULL, &ymin, &ymax);
272 string_arr_delete(a);
274 RRD_CHECK_ERROR result = rb_ary_new2(3);
276 print_results = rb_ary_new();
277 p = calcpr;
278 for (p = calcpr; p && *p; p++) {
279 rb_ary_push(print_results, rb_str_new2(*p));
280 rrd_freemem(*p);
281 }
282 rrd_freemem(calcpr);
283 rb_ary_store(result, 0, print_results);
284 rb_ary_store(result, 1, INT2FIX(xsize));
285 rb_ary_store(result, 2, INT2FIX(ysize));
286 return result;
287 }
290 VALUE rb_rrd_last(
291 VALUE self,
292 VALUE args)
293 {
294 string_arr a;
295 time_t last;
297 a = string_arr_new(args);
298 reset_rrd_state();
299 last = rrd_last(a.len, a.strings);
300 string_arr_delete(a);
302 RRD_CHECK_ERROR
303 return rb_funcall(rb_cTime, rb_intern("at"), 1, INT2FIX(last));
304 }
306 void Init_RRD(
307 )
308 {
309 mRRD = rb_define_module("RRD");
310 rb_eRRDError = rb_define_class("RRDError", rb_eStandardError);
312 rb_define_module_function(mRRD, "create", rb_rrd_create, -2);
313 rb_define_module_function(mRRD, "dump", rb_rrd_dump, -2);
314 rb_define_module_function(mRRD, "fetch", rb_rrd_fetch, -2);
315 rb_define_module_function(mRRD, "graph", rb_rrd_graph, -2);
316 rb_define_module_function(mRRD, "last", rb_rrd_last, -2);
317 rb_define_module_function(mRRD, "resize", rb_rrd_resize, -2);
318 rb_define_module_function(mRRD, "restore", rb_rrd_restore, -2);
319 rb_define_module_function(mRRD, "tune", rb_rrd_tune, -2);
320 rb_define_module_function(mRRD, "update", rb_rrd_update, -2);
321 rb_define_module_function(mRRD, "info", rb_rrd_info, -2);
322 rb_define_module_function(mRRD, "updatev", rb_rrd_updatev, -2);
323 rb_define_module_function(mRRD, "graphv", rb_rrd_graphv, -2);
324 }