~ubuntu-branches/ubuntu/maverick/rrdtool/maverick

« back to all changes in this revision

Viewing changes to bindings/lua/rrdlua.c

  • Committer: Bazaar Package Importer
  • Author(s): Clint Byrum
  • Date: 2010-07-22 08:07:01 UTC
  • mfrom: (1.2.8 upstream) (3.1.6 sid)
  • Revision ID: james.westby@ubuntu.com-20100722080701-k46mgdfz6euxwqsm
Tags: 1.4.3-1ubuntu1
* Merge from debian unstable, Remaining changes:
  - debian/control: Don't build against ruby1.9 as we don't want
    it in main.
* require libdbi >= 0.8.3 to prevent aborts when using dbi datasources

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Lua bindings for RRDTool
 
3
 *
 
4
 * This software is licensed to the public under the Free Software
 
5
 * Foundation's GNU GPL, version 2 or later. You may obtain a copy
 
6
 * of the GPL by visiting the Free Software Foundations web site at
 
7
 * www.fsf.org, and a copy is included in this distribution.
 
8
 *
 
9
 * Copyright 2008 Fidelis Assis, all rights reserved.
 
10
 *
 
11
 */
 
12
 
 
13
#include <ctype.h>
 
14
#include <stddef.h>
 
15
#include <stdio.h>
 
16
#include <stdlib.h>
 
17
#include <unistd.h>
 
18
#include <string.h>
 
19
#include <math.h>
 
20
#include <errno.h>
 
21
#include <dirent.h>
 
22
#include <inttypes.h>
 
23
 
 
24
#include "lua.h"
 
25
#include "lauxlib.h"
 
26
#include "lualib.h"
 
27
#include "../../src/rrd_tool.h"
 
28
 
 
29
#ifdef LUA50
 
30
#ifdef HAVE_COMPAT51
 
31
#include "compat-5.1.h"
 
32
#else
 
33
#include "compat-5.1r5/compat-5.1.h"
 
34
#endif
 
35
#endif
 
36
 
 
37
extern void rrd_freemem(void *mem);
 
38
 
 
39
extern int luaopen_rrd (lua_State * L);
 
40
typedef int (*RRD_FUNCTION)(int, char **);
 
41
typedef rrd_info_t *(RRD_FUNCTION_V)(int, char **);
 
42
 
 
43
/**********************************************************/
 
44
 
 
45
static void reset_rrd_state(void)
 
46
{
 
47
    optind = 0;
 
48
    opterr = 0;
 
49
    rrd_clear_error();
 
50
}
 
51
 
 
52
static char **make_argv(const char *cmd, lua_State * L)
 
53
{
 
54
  char **argv;
 
55
  int i;
 
56
  int argc = lua_gettop(L) + 1;
 
57
 
 
58
  if (!(argv = calloc(argc, sizeof (char *)))) 
 
59
    /* raise an error and never return */
 
60
    luaL_error(L, "Can't allocate memory for arguments array", cmd);
 
61
 
 
62
  /* fprintf(stderr, "Args:\n"); */
 
63
  argv[0] = (char *) cmd; /* Dummy arg. Cast to (char *) because rrd */
 
64
                          /* functions don't expect (const * char)   */
 
65
  /* fprintf(stderr, "%s\n", argv[0]); */
 
66
  for (i=1; i<argc; i++) {
 
67
    /* accepts string or number */
 
68
    if (lua_isstring(L, i) || lua_isnumber(L, i)) {
 
69
      if (!(argv[i] = strdup(lua_tostring (L, i)))) {
 
70
        /* raise an error and never return */
 
71
        luaL_error(L, "%s - error duplicating string area for arg #%d",
 
72
                   cmd, i);
 
73
      }
 
74
    } else {
 
75
      /* raise an error and never return */
 
76
      luaL_error(L, "Invalid arg #%d to %s: args must be strings or numbers",
 
77
                 i, cmd);
 
78
    }
 
79
    /* fprintf(stderr, "%s\n", argv[i]); */
 
80
  }
 
81
  return argv;
 
82
}
 
83
 
 
84
static int
 
85
rrd_common_call (lua_State *L, const char *cmd, RRD_FUNCTION rrd_function)
 
86
{
 
87
  char **argv;
 
88
  int argc = lua_gettop(L) + 1;
 
89
 
 
90
  argv = make_argv(cmd, L);
 
91
  reset_rrd_state();
 
92
  rrd_function(argc, argv);
 
93
  free(argv);
 
94
  if (rrd_test_error()) luaL_error(L, rrd_get_error());
 
95
  return 0;
 
96
}
 
97
 
 
98
#if defined(DINF)
 
99
static int
 
100
lua_rrd_infocall(lua_State *L, const char *cmd, RRD_FUNCTION_V rrd_function)
 
101
{
 
102
  char **argv;
 
103
  rrd_info_t *p, *data;
 
104
  int argc = lua_gettop(L) + 1;
 
105
 
 
106
  argv = make_argv(cmd, L);
 
107
  reset_rrd_state();
 
108
  data = rrd_function(argc, argv);
 
109
  free(argv);
 
110
  if (rrd_test_error()) luaL_error(L, rrd_get_error());
 
111
 
 
112
  lua_newtable(L);
 
113
  p = data;
 
114
  while (data) {
 
115
    lua_pushstring(L, data->key);
 
116
    switch (data->type) {
 
117
      case RD_I_CNT:
 
118
        if (isnan(data->value.u_val)) {
 
119
          lua_pushnil(L); 
 
120
        } else {
 
121
          lua_pushnumber(L, (lua_Number) data->value.u_val);
 
122
        }
 
123
        lua_rawset(L, -3);
 
124
        break;
 
125
      case RD_I_VAL:
 
126
        lua_pushnumber(L, (lua_Number) data->value.u_val);
 
127
        lua_rawset(L, -3);
 
128
        break;
 
129
      case RD_I_STR:
 
130
        lua_pushstring(L, data->value.u_str);
 
131
        lua_rawset(L, -3);
 
132
        break;
 
133
      case RD_I_BLO:
 
134
        lua_pushlstring(L, (const char *) data->value.u_blo.ptr,
 
135
                        data->value.u_blo.size);
 
136
        lua_rawset(L, -3);
 
137
        break;
 
138
      default:
 
139
        rrd_info_free(p); 
 
140
        return luaL_error(L, "Wrong data type to info call");
 
141
        break;
 
142
    }
 
143
    data = data->next;
 
144
  }
 
145
  rrd_info_free(p); 
 
146
  return 1;
 
147
}
 
148
#endif
 
149
 
 
150
/**********************************************************/
 
151
 
 
152
static int
 
153
lua_rrd_create (lua_State * L)
 
154
{
 
155
  rrd_common_call(L, "create", rrd_create);
 
156
  return 0;
 
157
}
 
158
 
 
159
static int
 
160
lua_rrd_dump (lua_State * L)
 
161
{
 
162
  rrd_common_call(L, "dump", rrd_dump);
 
163
  return 0;
 
164
}
 
165
 
 
166
static int
 
167
lua_rrd_resize (lua_State * L)
 
168
{
 
169
  rrd_common_call(L, "resize", rrd_resize);
 
170
  return 0;
 
171
}
 
172
 
 
173
static int
 
174
lua_rrd_restore (lua_State * L)
 
175
{
 
176
  rrd_common_call(L, "restore", rrd_restore);
 
177
  return 0;
 
178
}
 
179
 
 
180
static int
 
181
lua_rrd_tune (lua_State * L)
 
182
{
 
183
  rrd_common_call(L, "tune", rrd_tune);
 
184
  return 0;
 
185
}
 
186
 
 
187
static int
 
188
lua_rrd_update (lua_State * L)
 
189
{
 
190
  rrd_common_call(L, "update", rrd_update);
 
191
  return 0;
 
192
}
 
193
 
 
194
static int
 
195
lua_rrd_fetch (lua_State * L)
 
196
{
 
197
  int argc = lua_gettop(L) + 1;
 
198
  char **argv = make_argv("fetch", L);
 
199
  unsigned long i, j, step, ds_cnt;
 
200
  rrd_value_t *data, *p;
 
201
  char    **names;
 
202
  time_t  t, start, end;
 
203
 
 
204
  reset_rrd_state();
 
205
  rrd_fetch(argc, argv, &start, &end, &step, &ds_cnt, &names, &data);
 
206
  free(argv);
 
207
  if (rrd_test_error()) luaL_error(L, rrd_get_error());
 
208
 
 
209
  lua_pushnumber(L, (lua_Number) start);
 
210
  lua_pushnumber(L, (lua_Number) step);
 
211
  /* fprintf(stderr, "%lu, %lu, %lu, %lu\n", start, end, step, num_points); */
 
212
 
 
213
  /* create the ds names array */
 
214
  lua_newtable(L);
 
215
  for (i=0; i<ds_cnt; i++) {
 
216
    lua_pushstring(L, names[i]);
 
217
    lua_rawseti(L, -2, i+1);
 
218
    rrd_freemem(names[i]);
 
219
  }
 
220
  rrd_freemem(names);
 
221
 
 
222
  /* create the data points array */
 
223
  lua_newtable(L);
 
224
  p = data;
 
225
  for (t=start, i=0; t<end; t+=step, i++) {
 
226
    lua_newtable(L);
 
227
    for (j=0; j<ds_cnt; j++) {
 
228
      /*fprintf(stderr, "Point #%lu\n", j+1); */
 
229
      lua_pushnumber(L, (lua_Number) *p++);
 
230
      lua_rawseti(L, -2, j+1);
 
231
    }
 
232
    lua_rawseti(L, -2, i+1);
 
233
  }
 
234
  rrd_freemem(data);
 
235
 
 
236
  /* return the end as the last value */
 
237
  lua_pushnumber(L, (lua_Number) end);
 
238
 
 
239
  return 5;
 
240
}
 
241
 
 
242
static int
 
243
lua_rrd_first (lua_State * L)
 
244
{
 
245
  time_t first;
 
246
  int argc = lua_gettop(L) + 1;
 
247
  char **argv = make_argv("first", L);
 
248
  reset_rrd_state();
 
249
  first = rrd_first(argc, argv);
 
250
  free(argv);
 
251
  if (rrd_test_error()) luaL_error(L, rrd_get_error());
 
252
  lua_pushnumber(L, (lua_Number) first);
 
253
  return 1;
 
254
}
 
255
 
 
256
static int
 
257
lua_rrd_last (lua_State * L)
 
258
{
 
259
  time_t last;
 
260
  int argc = lua_gettop(L) + 1;
 
261
  char **argv = make_argv("last", L);
 
262
  reset_rrd_state();
 
263
  last = rrd_last(argc, argv);
 
264
  free(argv);
 
265
  if (rrd_test_error()) luaL_error(L, rrd_get_error());
 
266
  lua_pushnumber(L, (lua_Number) last);
 
267
  return 1;
 
268
}
 
269
 
 
270
static int
 
271
lua_rrd_graph (lua_State * L)
 
272
{
 
273
  int argc = lua_gettop(L) + 1;
 
274
  char **argv = make_argv("last", L);
 
275
  char **calcpr;
 
276
  int i, xsize, ysize;
 
277
  double ymin, ymax;
 
278
 
 
279
  reset_rrd_state();
 
280
  rrd_graph(argc, argv, &calcpr, &xsize, &ysize, NULL, &ymin, &ymax);
 
281
  free(argv);
 
282
  if (rrd_test_error()) luaL_error(L, rrd_get_error());
 
283
  lua_pushnumber(L, (lua_Number) xsize);
 
284
  lua_pushnumber(L, (lua_Number) ysize);
 
285
  lua_newtable(L);
 
286
  for (i = 0; calcpr && calcpr[i]; i++) {
 
287
      lua_pushstring(L, calcpr[i]);
 
288
      lua_rawseti(L, -2, i+1);
 
289
      rrd_freemem(calcpr[i]);
 
290
  }
 
291
  rrd_freemem(calcpr);
 
292
  return 3;
 
293
}
 
294
 
 
295
static int
 
296
lua_rrd_flushcached(lua_State *L)
 
297
{
 
298
  return rrd_common_call(L, "flushcached", rrd_flushcached);
 
299
}
 
300
 
 
301
#if defined(DINF)
 
302
static int
 
303
lua_rrd_info (lua_State * L)
 
304
{
 
305
  return lua_rrd_infocall(L, "info", rrd_info);
 
306
}
 
307
 
 
308
static int
 
309
lua_rrd_graphv (lua_State * L)
 
310
{
 
311
  return lua_rrd_infocall(L, "graphv", rrd_graph_v);
 
312
}
 
313
 
 
314
static int
 
315
lua_rrd_updatev (lua_State * L)
 
316
{
 
317
  return lua_rrd_infocall(L, "updatev", rrd_update_v);
 
318
}
 
319
#endif
 
320
 
 
321
/**********************************************************/
 
322
 
 
323
/*
 
324
** Assumes the table is on top of the stack.
 
325
*/
 
326
static void
 
327
set_info (lua_State * L)
 
328
{
 
329
  lua_pushliteral (L, "_COPYRIGHT");
 
330
  lua_pushliteral (L, "Copyright (C) 2008 Fidelis Assis");
 
331
  lua_settable (L, -3);
 
332
  lua_pushliteral (L, "_DESCRIPTION");
 
333
  lua_pushliteral (L, "RRD-lua is a Lua binding for RRDTool.");
 
334
  lua_settable (L, -3);
 
335
  lua_pushliteral (L, "_NAME");
 
336
  lua_pushliteral (L, "RRD-Lua");
 
337
  lua_settable (L, -3);
 
338
  lua_pushliteral (L, "_VERSION");
 
339
  lua_pushliteral (L, LIB_VERSION);
 
340
  lua_settable (L, -3);
 
341
}
 
342
 
 
343
/**********************************************************/
 
344
 
 
345
static const struct luaL_reg rrd[] = {
 
346
  {"create", lua_rrd_create},
 
347
  {"dump", lua_rrd_dump},
 
348
  {"fetch", lua_rrd_fetch},
 
349
  {"first", lua_rrd_first},
 
350
  {"graph", lua_rrd_graph},
 
351
  {"last", lua_rrd_last},
 
352
  {"resize", lua_rrd_resize},
 
353
  {"restore", lua_rrd_restore},
 
354
  {"tune", lua_rrd_tune},
 
355
  {"update", lua_rrd_update},
 
356
  {"flushcached", lua_rrd_flushcached},
 
357
#if defined(DINF)
 
358
  {"info", lua_rrd_info},
 
359
  {"updatev", lua_rrd_updatev},
 
360
  {"graphv", lua_rrd_graphv},
 
361
#endif
 
362
  {NULL, NULL}
 
363
};
 
364
 
 
365
 
 
366
/*
 
367
** Open RRD library
 
368
*/
 
369
int
 
370
luaopen_rrd (lua_State * L)
 
371
{
 
372
#if defined LUA50
 
373
  /* luaL_module is defined in compat-5.1.c */
 
374
  luaL_module (L, "rrd", rrd, 0);
 
375
#else
 
376
  luaL_register (L, "rrd", rrd);
 
377
#endif
 
378
  set_info (L);
 
379
  return 1;
 
380
}