From 9b60b973b11307d6c812db001334352fbda4cdb9 Mon Sep 17 00:00:00 2001 From: oetiker Date: Mon, 22 Sep 2008 06:35:26 +0000 Subject: [PATCH] I finally finished the first version of the patch (attached) -- Fidelis Assis fidelis pobox.com (this does not seem to quite work yet at least not in my hardy setup) git-svn-id: svn://svn.oetiker.ch/rrdtool/trunk/program@1517 a5681a0c-68f1-0310-ab6d-d61299d08faa --- MakeMakefile | 4 +- bindings/Makefile.am | 16 +- bindings/lua/Makefile.lua | 120 +++++++++++++ bindings/lua/README | 21 +++ bindings/lua/rrdlua.c | 360 ++++++++++++++++++++++++++++++++++++++ bindings/lua/test.lua | 98 +++++++++++ configure.ac | 60 ++++++- doc/Makefile.am | 2 +- doc/rrdlua.pod | 137 +++++++++++++++ 9 files changed, 802 insertions(+), 16 deletions(-) create mode 100644 bindings/lua/Makefile.lua create mode 100644 bindings/lua/README create mode 100644 bindings/lua/rrdlua.c create mode 100644 bindings/lua/test.lua create mode 100644 doc/rrdlua.pod diff --git a/MakeMakefile b/MakeMakefile index aca14cc..f945d3b 100755 --- a/MakeMakefile +++ b/MakeMakefile @@ -3,8 +3,8 @@ # Run this script after the first cvs checkout to build # makefiles and friends -PATH="/usr/sepp/bin:$PATH" -export PATH +#PATH="/usr/sepp/bin:$PATH" +#export PATH vcheck (){ perl < Makefile && $(MAKE) + # rules for building the perl module perl_piped: perl-piped/Makefile cd perl-piped && $(MAKE) @@ -52,5 +57,6 @@ clean-local: test -f perl-shared/Makefile && cd perl-shared && $(MAKE) clean || true test -f perl-shared/Makefile && rm -f perl-shared/Makefile || true test -f ruby/Makefile && cd ruby && $(MAKE) clean && rm Makefile || true + test -f lua/Makefile && cd lua && $(MAKE) clean && rm Makefile || true test -d python/build && cd python && rm -rf build || true ##END## diff --git a/bindings/lua/Makefile.lua b/bindings/lua/Makefile.lua new file mode 100644 index 0000000..08be1cc --- /dev/null +++ b/bindings/lua/Makefile.lua @@ -0,0 +1,120 @@ +-- min version +local min_major, min_minor = 5, 1 +local major, minor = string.match(_VERSION, 'Lua (%d+)\.(%d*)') + +if (tonumber(major) < min_major or + tonumber(major) == min_major and tonumber(minor) < min_minor) then + error(string.format( + '\n\n*** Lua rrdtool module requires Lua %d.%d or greater. ***\n', + min_major, min_minor)) + os.exit(1) +end +local lua_version = major .. '.' .. minor + +local options = arg[1] +if options then + io.write(string.gsub(options, ' (%S-=)', '\n%1'), '\n\n') +end + +io.stdout:write([[ +T= rrd +# Version +LIB_VERSION=0.0.8 +LUA_VERSION=]],major, '.',minor,[[ + + +# set lua include, lib and C installation dirs +PKG_CONFIG=$(firstword $(shell which pkg-config)) +ifeq (pkg-config,$(findstring pkg-config,$(PKG_CONFIG))) + LUA_LIBDIR=$(shell pkg-config --variable=INSTALL_CMOD lua$(LUA_VERSION)) + ifeq (,$(LUA_LIBDIR)) + $(warning *** couldn't find lua$(LUA_VERSION).pc) + else + LUA_CFLAGS=$(shell pkg-config --cflags lua$(LUA_VERSION) 2>/dev/null) + LUA_LFLAGS=$(shell pkg-config --libs lua$(LUA_VERSION) 2>/dev/null) + endif +else + $(warning couldn't find pkg-config) +endif + +ifeq (,$(LUA_LIBDIR)) + $(warning *** setting Lua dirs to defaults in src package) + LUA_CFLAGS=-I/usr/local/include -I/usr/local/include/lua + LUA_LFLAGS=-L/usr/local/lib/lua/$(LUA_VERSION) -llua + LUA_LIBDIR=/usr/local/lib/lua/$(LUA_VERSION) +endif + +]]) + +-- overwrite global LUA_LIBDIR if default lib is set +if lib then + io.stdout:write([[ +# override LUA_LIBDIR for site install +LUA_LIBDIR=]],lib,[[/$(LUA_VERSION) +]]) +end + +io.stdout:write([[ + +# OS dependent +LIB_EXT= .so + +# if this "autoconf" doesn't work for you, set LIB_OPTION for shared +# object manually. +LD=$(shell ld -V -o /dev/null 2>&1) +ifneq (,$(findstring Solaris,$(LD))) + # Solaris - tested with 2.6, gcc 2.95.3 20010315 and Solaris ld + LIB_OPTION= -G -dy +else + ifneq (,$(findstring GNU,$(LD))) + # GNU ld + LIB_OPTION= -shared -dy + else + $(error couldn't identify your ld. Please set the shared option manually) + endif +endif + +RRD_CFLAGS=-I../../src/ +RRD_LIB_DIR=-L../../src/.libs -lrrd + +# Choose the PIC option +# safest, works on most systems +PIC=-fPIC +# probably faster, but may not work on your system +#PIC=-fpic + +# Compilation directives +OPTIONS= -O3 -Wall ${PIC} -fomit-frame-pointer -pedantic-errors -W -Waggregate-return -Wcast-align -Wmissing-prototypes -Wnested-externs -Wshadow -Wwrite-strings +LIBS= $(RRD_LIB_DIR) $(LUA_LFLAGS) -lm +CFLAGS= $(OPTIONS) $(LUA_CFLAGS) $(RRD_CFLAGS) -DLIB_VERSION=\"$(LIB_VERSION)\" +#CC= gcc + +LIBNAME= $T-$(LIB_VERSION)$(LIB_EXT) + +SRCS= rrdlua.c +OBJS= rrdlua.o + +all: $(LIBNAME) + +lib: $(LIBNAME) + +*.o: *.c + +$(LIBNAME): $(OBJS) + $(CC) $(CFLAGS) $(LIB_OPTION) $(OBJS) $(LIBS) -o $(LIBNAME) + +install: $(LIBNAME) + mkdir -p $(LUA_LIBDIR) + cp $(LIBNAME) $(LUA_LIBDIR) + strip $(LUA_LIBDIR)/$(LIBNAME) + (cd $(LUA_LIBDIR) ; rm -f $T$(LIB_EXT) ; ln -fs $(LIBNAME) $T$(LIB_EXT)) + $(POD2MAN) --release=$(VERSION) --center=RRDLua --section=3 rrdlua.pod > $(PREFIX)/man/man3/rrdlua.3 + +test: $(LIBNAME) + ln -sf $(LIBNAME) rrd.so + lua test.lua + +clean: + rm -f $L $(LIBNAME) $(OBJS) *.so *.rrd *.xml *.png *~ +]]) + diff --git a/bindings/lua/README b/bindings/lua/README new file mode 100644 index 0000000..f1fe186 --- /dev/null +++ b/bindings/lua/README @@ -0,0 +1,21 @@ +RRDLua is a Lua module for RRD functions. + +Compiling: + +Just run "configure" from the top RRDTool package dir and then 'make'. +You should have lua and lua-dev packages installed before executing +configure. + +Testing: + +Enter the bindings/lua dir, run 'make test' and use your preferred +viewer to display the just created graph 'test.png'. If you can read +"Enjoy Lua RRDtool module!" on the picture, everything went fine. + +Installation: + +Run 'make install' from the top dir of the RRDtool package. The Lua +module will be installed in the same RRDtool installation dir, +under the subdir lib/lua/. + + diff --git a/bindings/lua/rrdlua.c b/bindings/lua/rrdlua.c new file mode 100644 index 0000000..a786077 --- /dev/null +++ b/bindings/lua/rrdlua.c @@ -0,0 +1,360 @@ +/* + * Lua bindings for RRDTool + * + * This software is licensed to the public under the Free Software + * Foundation's GNU GPL, version 2 or later. You may obtain a copy + * of the GPL by visiting the Free Software Foundations web site at + * www.fsf.org, and a copy is included in this distribution. + * + * Copyright 2008 Fidelis Assis, all rights reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" +#include "../../src/rrd_tool.h" + +extern void rrd_freemem(void *mem); + +extern int luaopen_rrd (lua_State * L); +typedef int (*RRD_FUNCTION)(int, char **); +typedef rrd_info_t *(RRD_FUNCTION_V)(int, char **); + +/**********************************************************/ + +static void reset_rrd_state(void) +{ + optind = 0; + opterr = 0; + rrd_clear_error(); +} + +static char **make_argv(const char *cmd, lua_State * L) +{ + char **argv; + int i; + int argc = lua_gettop(L) + 1; + + if (!(argv = calloc(argc, sizeof (char *)))) + /* raise an error and never return */ + luaL_error(L, "Can't allocate memory for arguments array", cmd); + + /* fprintf(stderr, "Args:\n"); */ + argv[0] = (char *) cmd; /* Dummy arg. Cast to (char *) because rrd */ + /* functions don't expect (const * char) */ + /* fprintf(stderr, "%s\n", argv[0]); */ + for (i=1; ikey); + switch (data->type) { + case RD_I_CNT: + if (isnan(data->value.u_val)) { + lua_pushnil(L); + } else { + lua_pushnumber(L, (lua_Number) data->value.u_val); + } + lua_rawset(L, -3); + break; + case RD_I_VAL: + lua_pushnumber(L, (lua_Number) data->value.u_val); + lua_rawset(L, -3); + break; + case RD_I_STR: + lua_pushstring(L, data->value.u_str); + lua_rawset(L, -3); + break; + case RD_I_BLO: + lua_pushlstring(L, (const char *) data->value.u_blo.ptr, + data->value.u_blo.size); + lua_rawset(L, -3); + break; + default: + rrd_info_free(p); + return luaL_error(L, "Wrong data type to info call"); + break; + } + data = data->next; + } + rrd_info_free(p); + return 1; +} +#endif + +/**********************************************************/ + +static int +lua_rrd_create (lua_State * L) +{ + rrd_common_call(L, "create", rrd_create); + return 0; +} + +static int +lua_rrd_dump (lua_State * L) +{ + rrd_common_call(L, "dump", rrd_dump); + return 0; +} + +static int +lua_rrd_resize (lua_State * L) +{ + rrd_common_call(L, "resize", rrd_resize); + return 0; +} + +static int +lua_rrd_restore (lua_State * L) +{ + rrd_common_call(L, "restore", rrd_restore); + return 0; +} + +static int +lua_rrd_tune (lua_State * L) +{ + rrd_common_call(L, "tune", rrd_tune); + return 0; +} + +static int +lua_rrd_update (lua_State * L) +{ + rrd_common_call(L, "update", rrd_update); + return 0; +} + +static int +lua_rrd_fetch (lua_State * L) +{ + int argc = lua_gettop(L) + 1; + char **argv = make_argv("fetch", L); + unsigned long i, j, step, ds_cnt; + rrd_value_t *data, *p; + char **names; + time_t t, start, end; + + reset_rrd_state(); + rrd_fetch(argc, argv, &start, &end, &step, &ds_cnt, &names, &data); + free(argv); + if (rrd_test_error()) luaL_error(L, rrd_get_error()); + + lua_pushnumber(L, (lua_Number) start); + lua_pushnumber(L, (lua_Number) step); + /* fprintf(stderr, "%lu, %lu, %lu, %lu\n", start, end, step, num_points); */ + + /* create the ds names array */ + lua_newtable(L); + for (i=0; i returns a single INTEGER representing the timestamp of the +first data sample in an RRA within an RRD file. Example returning the +first timestamp of the third RRA (index 2): + + local firstdate = rrd.first('example.rrd', '--rraindex', 2) + +B returns a single INTEGER representing the last update time. + + local lastupdate = rrd.last('example.rrd') + +B returns the x-size and y-size of the created image and a table +with the results of the PRINT arguments. + + local xsize, ysize, averages = rrd.graph ... + print(string.format("Image size: %dx%d", xsize, ysize) + print("Averages: ", table.concat(averages, ', ')) + +B returns a table where the keys and the values represent property +names and property values of the RRD. + + local info = rrd.info("test.rrd") + for key, value in pairs(info) do + print(key, ' = ', value) + end + +B takes the same parameters as rrd.graph but it returns a table +only. The table returned contains meta information about the graph, like +its size as well as the position of the graph area on the image. When +called with and empty filename, the contents of the graph will be returned +in the table as well (key 'image'). + +B also returns a table. The keys of the table are strings +formed by the concatenation of timestamp, RRA index and data source name +for each consolidated data point (CDP) written to disk as a result of the +current update call. The key values are CDP values. + +B is the most complex of the pack regarding return values. It +returns 5 values: the initial timestamp, the step, two parallel arrays +containing the data source names and their data points respectively, and +the final timestamp. + + package.cpath = '/usr/local/rrdtool-1.3.3/lib/lua/5.1/?.so;' .. + package.cpath + local rrd = require "rrd" + local first, last = rrd.first("test.rrd"), rrd.last("test.rrd") + local start, step, names, data = + rrd.fetch("test.rrd", "--start", first, "--end", last, "AVERAGE") + io.write(string.format("Start: %s (%d)\n", + os.date("%c", start),start)) + io.write("Step size: ", step, " seconds\n") + io.write("DS names: ", table.concat(names, ', '), "\n") + io.write("Data points: ", #data[1], "\n") + io.write("Data:\n") + for i,dp in ipairs(data) do + io.write(os.date("%t", start), " (", start, "): ") + start = start + step + for j,v in ipairs(dp) do + io.write(v, " ") + end + io.write("\n") + end + +=head1 AUTHOR + +Fidelis Assis Efidelis@pobox.comE -- 2.30.2