[rrd-developers] Tcl interface for RRDtool 1.0.13

Frank Strauss strauss at ibr.cs.tu-bs.de
Thu Mar 9 17:39:04 MET 2000


Hi!

Applied you'll find a patch that adds a Tcl interface to RRDtool.
This might be useful when you want to combine features of Scotty
with RRDtool, e.g. retrieving data of an interface by its name,
whatever it's ifIndex in the ifTable might be. See the applied
example.

Note that this is just a quick hack I did one year ago after I've
learned about RRDtool at the GUUG meeting. I finished it to the
present status just last night, due to some kind of a deal with
Tobi. ;-)

Tobi, feel free to integrate it with your RRDtool distribution, if
you like.

 Frank

diff -u -r -N --exclude Makefile --exclude html --exclude doc --exclude Makefile.in --exclude Makefile.old --exclude perl --exclude aclocal.m4 --exclude configure rrdtool-1.0.13/Makefile.am rrdtool-1.0.13-ibr/Makefile.am
--- rrdtool-1.0.13/Makefile.am	Sat Feb 12 19:19:34 2000
+++ rrdtool-1.0.13-ibr/Makefile.am	Thu Mar  9 16:59:23 2000
@@ -1,7 +1,7 @@
 ## Process this file with automake to produce Makefile.in
 RSYNC = rsync --rsh=ssh
 # build the following subdirectories
-SUBDIRS = cgilib-0.4 config gd1.3 zlib-1.1.3 libpng-1.0.3 src doc examples contrib
+SUBDIRS = cgilib-0.4 config gd1.3 zlib-1.1.3 libpng-1.0.3 src doc examples contrib tcl
 
 # the following files are not mentioned in any other Makefile
 EXTRA_DIST = COPYRIGHT CHANGES NT-BUILD-TIPS.txt TODO CONTRIBUTORS  \
diff -u -r -N --exclude Makefile --exclude html --exclude doc --exclude Makefile.in --exclude Makefile.old --exclude perl --exclude aclocal.m4 --exclude configure rrdtool-1.0.13/configure.in rrdtool-1.0.13-ibr/configure.in
--- rrdtool-1.0.13/configure.in	Sun Feb 13 20:39:12 2000
+++ rrdtool-1.0.13-ibr/configure.in	Thu Mar  9 12:11:46 2000
@@ -17,6 +17,7 @@
 
 dnl tell automake the this script is for rrdtool
 AM_INIT_AUTOMAKE(rrdtool, 1.0.13)
+AC_SUBST(VERSION)
 
 dnl where we install our stuff ...
 AC_PREFIX_DEFAULT( /usr/local/rrdtool-1.0.13 )
@@ -49,6 +50,33 @@
 fi
 AC_SUBST(COMP_PERL)
 
+dnl Check for Tcl.
+dirs="$prefix/lib /usr/local/lib /usr/lib"
+found=0
+for f in $dirs ; do
+	AC_MSG_CHECKING(for tclConfig.sh in $f)
+        if test -f "$f/tclConfig.sh" ; then
+        	tcl_config=$f/tclConfig.sh
+	        found=1
+	        AC_MSG_RESULT(yes)
+	        break
+        else
+	        AC_MSG_RESULT(no)
+        fi
+done
+if test $found -eq 0 ; then
+        AC_MSG_ERROR([tclConfig.sh not found - Tcl interface won't be built])
+	COMP_TCL=
+else
+	COMP_TCL="tcl"
+	. $tcl_config
+fi
+AC_SUBST(COMP_TCL)
+AC_SUBST(TCL_SHLIB_CFLAGS)
+AC_SUBST(TCL_SHLIB_LD)
+AC_SUBST(TCL_SHLIB_SUFFIX)
+AC_SUBST(TCL_PACKAGE_PATH)
+AC_SUBST(TCL_LD_SEARCH_FLAGS)
 
 dnl Check for the compiler and static/shared library creation.
 AC_PROG_CC
@@ -57,7 +85,7 @@
 
 dnl don't build a shared library ... perl will do it's own magic. 
 dnl this can be changed when running configure
-AC_DISABLE_SHARED
+dnl AC_DISABLE_SHARED
 
 AM_PROG_LIBTOOL
 
@@ -301,6 +329,7 @@
           libpng-1.0.3/Makefile				\
           zlib-1.1.3/Makefile				\
           src/Makefile					\
+          tcl/Makefile					\
           Makefile,					\
           [chmod +x examples/*.cgi examples/*.pl contrib/*/*.pl])
 
diff -u -r -N --exclude Makefile --exclude html --exclude doc --exclude Makefile.in --exclude Makefile.old --exclude perl --exclude aclocal.m4 --exclude configure rrdtool-1.0.13/tcl/Makefile.am rrdtool-1.0.13-ibr/tcl/Makefile.am
--- rrdtool-1.0.13/tcl/Makefile.am	Thu Jan  1 01:00:00 1970
+++ rrdtool-1.0.13-ibr/tcl/Makefile.am	Thu Mar  9 17:11:40 2000
@@ -0,0 +1,39 @@
+
+EXTRA_DIST = README ifOctets.tcl tclrrd.c
+CLEANFILES = tclrrd.o tclrrd.so
+
+VERSION = @VERSION@
+
+TCL_SHLIB_LD = @TCL_SHLIB_LD@
+TCL_SHLIB_CFLAGS = @TCL_SHLIB_CFLAGS@
+TCL_SHLIB_SUFFIX = @TCL_SHLIB_SUFFIX@
+TCL_PACKAGE_PATH = @TCL_PACKAGE_PATH@
+TCL_LD_SEARCH_FLAGS = @TCL_LD_SEARCH_FLAGS@
+
+CGI_LIB_DIR        = $(top_srcdir)/@CGI_LIB_DIR@
+GD_LIB_DIR         = $(top_srcdir)/@GD_LIB_DIR@
+PNG_LIB_DIR        = $(top_srcdir)/@PNG_LIB_DIR@
+ZLIB_LIB_DIR       = $(top_srcdir)/@ZLIB_LIB_DIR@
+SRC_DIR            = $(top_srcdir)/src
+INCLUDES           = -I$(SRC_DIR) -I$(GD_LIB_DIR) -I$(PNG_LIB_DIR) -I$(ZLIB_LIB_DIR)
+LIBDIRS            = -L$(libdir) -L$(SRC_DIR) -L$(GD_LIB_DIR) -L$(PNG_LIB_DIR)
+LIB_RUNTIME_DIR    = $(libdir)
+
+tclrrd$(TCL_SHLIB_SUFFIX): tclrrd.o
+	$(TCL_SHLIB_LD) $(LIBDIRS) $< -o $@ -lrrd -lgd -lm
+
+tclrrd.o: tclrrd.c
+	$(CC) $(CFLAGS) $(TCL_SHLIB_CFLAGS) $(INCLUDES) -c $< -DVERSION=\"$(VERSION)\"
+
+all-local: tclrrd$(TCL_SHLIB_SUFFIX)
+
+install-data-local: tclrrd$(TCL_SHLIB_SUFFIX)
+	cp tclrrd$(TCL_SHLIB_SUFFIX) $(TCL_PACKAGE_PATH)/tclrrd$(VERSION)$(TCL_SHLIB_SUFFIX)
+	if [ ! -d $(TCL_PACKAGE_PATH)/tclrrd$(VERSION) ] ; then \
+		mkdir $(TCL_PACKAGE_PATH)/tclrrd$(VERSION) ; \
+	fi
+	echo "package ifneeded Rrd $(VERSION) [list load [file join \$$dir .. tclrrd$(VERSION)$(TCL_SHLIB_SUFFIX)]]" > $(TCL_PACKAGE_PATH)/tclrrd$(VERSION)/pkgIndex.tcl
+
+diff:
+	cd .. ; diff -c -u -r -N --exclude Makefile --exclude html --exclude doc --exclude Makefile.in --exclude Makefile.old --exclude perl --exclude aclocal.m4 --exclude configure rrdtool-1.0.13 rrdtool-1.0.13-ibr > rrdtool-1.0.13-ibr.patch
+	
diff -u -r -N --exclude Makefile --exclude html --exclude doc --exclude Makefile.in --exclude Makefile.old --exclude perl --exclude aclocal.m4 --exclude configure rrdtool-1.0.13/tcl/README rrdtool-1.0.13-ibr/tcl/README
--- rrdtool-1.0.13/tcl/README	Thu Jan  1 01:00:00 1970
+++ rrdtool-1.0.13-ibr/tcl/README	Thu Mar  9 17:14:08 2000
@@ -0,0 +1,31 @@
+TCLRRD -- A TCL interpreter extension to access the RRD library,
+	  contributed to Tobias Oetiker's RRD tools.
+
+Copyright (c) 1999,2000 Frank Strauss, Technical University of Braunschweig.
+
+See the file "COPYING" for information on usage and redistribution
+of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+TCLRRD adds a dynamically loadable package to the Tcl 8.x interpreter
+to access all RRD functions as of RRDtool 1.0.13. All command names
+and arguments are equal to those of RRDtool. They are assigned to the
+namespace `Rrd', e.g.  `Rrd::create'. Return values are a bit
+different from plain rrdtool behavior to enable more native Tcl
+usage. Errors are mapped to the TCL_ERROR return code together with
+the RRD error strings.
+
+TCLRRD makes it easy to combine RRD use with advanced SNMP functionality
+of scotty (http://wwwsnmp.cs.utwente.nl/~schoenw/scotty/). E.g., it's easy
+to use some scotty code to get the counters of some interfaces by their
+interface name and then use Rrd::update to store the values. Furthermore,
+data source types (see RRD::create documentation) and integer value ranges
+could be easily retrieved from MIB information.
+
+TCLRRD has been written on a Linux system for use with Tcl 8.x. It should
+work on many other platforms, although it has not been tested. There are
+no fool proof installation procedures. Take a look at Makefile.am and
+adapt it, if required.
+
+TCLRRD has been written for RRD 1.0.13.
+
+	Frank Strauss <strauss at ibr.cs.tu-bs.de>, 09-Mar-2000
Binary files rrdtool-1.0.13/tcl/gaga.png and rrdtool-1.0.13-ibr/tcl/gaga.png differ
diff -u -r -N --exclude Makefile --exclude html --exclude doc --exclude Makefile.in --exclude Makefile.old --exclude perl --exclude aclocal.m4 --exclude configure rrdtool-1.0.13/tcl/ifOctets.tcl rrdtool-1.0.13-ibr/tcl/ifOctets.tcl
--- rrdtool-1.0.13/tcl/ifOctets.tcl	Thu Jan  1 01:00:00 1970
+++ rrdtool-1.0.13-ibr/tcl/ifOctets.tcl	Thu Mar  9 16:53:33 2000
@@ -0,0 +1,45 @@
+#!/bin/sh
+# the next line restarts using tclsh -*- tcl -*- \
+exec tclsh8.2 "$0" "$@"
+
+package require Tnm 3.0
+package require Rrd 1.0.13
+
+set rrdfile "[lindex $argv 0]-[lindex $argv 1].rrd"
+
+# create rrdfile if not yet existent
+if {[file exists $rrdfile] == 0} {
+    Rrd::create $rrdfile --step 5 \
+	    DS:inOctets:COUNTER:10:U:U DS:outOctets:COUNTER:10:U:U \
+	    RRA:AVERAGE:0.5:1:12
+}
+
+# get an snmp session context
+set session [Tnm::snmp generator -address [lindex $argv 0]]
+
+# walk through the ifDescr column to find the right interface
+$session walk descr IF-MIB!ifDescr {
+
+    # is this the right interface?
+    if {"[Tnm::snmp value $descr 0]" == "[lindex $argv 1]"} {
+
+	# get the instance part of this table row
+	set inst [lindex [Tnm::mib split [Tnm::snmp oid $descr 0]] 1]
+
+	# get the two interface's octet counter values
+	set in [lindex [lindex [$session get IF-MIB!ifInOctets.$inst] 0] 2]
+	set out [lindex [lindex [$session get IF-MIB!ifOutOctets.$inst] 0] 2]
+
+	# write the values to the rrd
+	puts "$in $out"
+	Rrd::update $rrdfile --template inOctets:outOctets N:$in:$out
+
+	Rrd::graph gaga.png --title "gaga" \
+		DEF:in=$rrdfile:inOctets:AVERAGE \
+		DEF:out=$rrdfile:outOctets:AVERAGE \
+		AREA:in#0000FF:inOctets \
+		LINE2:out#00C000:outOctets
+
+	#puts [Rrd::fetch $rrdfile AVERAGE]
+    }
+}
Binary files rrdtool-1.0.13/tcl/molinari-hme0.rrd and rrdtool-1.0.13-ibr/tcl/molinari-hme0.rrd differ
diff -u -r -N --exclude Makefile --exclude html --exclude doc --exclude Makefile.in --exclude Makefile.old --exclude perl --exclude aclocal.m4 --exclude configure rrdtool-1.0.13/tcl/tclrrd.c rrdtool-1.0.13-ibr/tcl/tclrrd.c
--- rrdtool-1.0.13/tcl/tclrrd.c	Thu Jan  1 01:00:00 1970
+++ rrdtool-1.0.13-ibr/tcl/tclrrd.c	Thu Mar  9 01:00:22 2000
@@ -0,0 +1,335 @@
+/*
+ * tclrrd.c -- A TCL interpreter extension to access the RRD library.
+ *
+ * Copyright (c) 1999,2000 Frank Strauss, Technical University of Braunschweig.
+ *
+ * See the file "COPYING" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+
+
+#include <time.h>
+#include <tcl.h>
+#include <rrd_tool.h>
+#include <rrd_format.h>
+
+
+
+extern int __getopt_initialized;
+
+
+
+int
+Rrd_Create(clientData, interp, argc, argv)
+    ClientData clientData;
+    Tcl_Interp *interp;
+    int argc;
+    char *argv[];
+{
+    optind = 0;
+    
+    rrd_create(argc, argv);
+
+    if (rrd_test_error()) {
+	Tcl_AppendResult(interp, "RRD Error: ",
+			 rrd_get_error(), (char *) NULL);
+        rrd_clear_error();
+	return TCL_ERROR;
+    }
+
+    return TCL_OK;
+}
+
+
+
+int
+Rrd_Dump(clientData, interp, argc, argv)
+    ClientData clientData;
+    Tcl_Interp *interp;
+    int argc;
+    char *argv[];
+{
+    /* NOTE: rrd_dump() writes to stdout. No interaction with TCL. */
+
+    optind = 0;
+    
+    rrd_dump(argc, argv);
+
+    if (rrd_test_error()) {
+	Tcl_AppendResult(interp, "RRD Error: ",
+			 rrd_get_error(), (char *) NULL);
+        rrd_clear_error();
+	return TCL_ERROR;
+    }
+
+    return TCL_OK;
+}
+
+
+
+int
+Rrd_Last(clientData, interp, argc, argv)
+    ClientData clientData;
+    Tcl_Interp *interp;
+    int argc;
+    char *argv[];
+{
+    time_t t;
+
+    optind = 0;
+    
+    t = rrd_last(argc, argv);
+
+    if (rrd_test_error()) {
+	Tcl_AppendResult(interp, "RRD Error: ",
+			 rrd_get_error(), (char *) NULL);
+        rrd_clear_error();
+	return TCL_ERROR;
+    }
+
+    Tcl_SetIntObj(Tcl_GetObjResult(interp), t);
+
+    return TCL_OK;
+}
+
+
+
+int
+Rrd_Update(clientData, interp, argc, argv)
+    ClientData clientData;
+    Tcl_Interp *interp;
+    int argc;
+    char *argv[];
+{
+    optind = 0;
+    
+    rrd_update(argc, argv);
+
+    if (rrd_test_error()) {
+	Tcl_AppendResult(interp, "RRD Error: ",
+			 rrd_get_error(), (char *) NULL);
+        rrd_clear_error();
+	return TCL_ERROR;
+    }
+
+    return TCL_OK;
+}
+
+
+
+int
+Rrd_Fetch(clientData, interp, argc, argv)
+    ClientData clientData;
+    Tcl_Interp *interp;
+    int argc;
+    char *argv[];
+{
+    time_t start, end;
+    unsigned long step, ds_cnt, i, ii;
+    rrd_value_t *data, *datai;
+    char **ds_namv;
+    Tcl_Obj *listPtr;
+    char s[30];
+
+    optind = 0;
+    
+    if (rrd_fetch(argc, argv, &start, &end, &step,
+		  &ds_cnt, &ds_namv, &data) != -1) {
+        datai = data;
+        listPtr = Tcl_GetObjResult(interp);
+        for (i = start; i <= end; i += step) {
+            for (ii = 0; ii < ds_cnt; ii++) {
+		sprintf(s, "%.2f", *(datai++));
+                Tcl_ListObjAppendElement(interp, listPtr,
+					 Tcl_NewStringObj(s, -1));
+            }
+        }
+        for (i=0; i<ds_cnt; i++) free(ds_namv[i]);
+        free(ds_namv);
+        free(data);
+    }
+
+    if (rrd_test_error()) {
+	Tcl_AppendResult(interp, "RRD Error: ",
+			 rrd_get_error(), (char *) NULL);
+        rrd_clear_error();
+	return TCL_ERROR;
+    }
+
+    return TCL_OK;
+}
+
+
+
+int
+Rrd_Graph(clientData, interp, argc, argv)
+    ClientData clientData;
+    Tcl_Interp *interp;
+    int argc;
+    char *argv[];
+{
+    char **calcpr;
+    int xsize, ysize;
+    Tcl_Obj *listPtr;
+
+    optind = 0;
+    
+    calcpr = NULL;
+    if (rrd_graph(argc, argv, &calcpr, &xsize, &ysize) != -1 ) {
+        listPtr = Tcl_GetObjResult(interp);
+        Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewIntObj(xsize));
+        Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewIntObj(ysize));
+        if (calcpr) {
+#if 0
+	    int i;
+	    
+            for(i = 0; calcpr[i]; i++){
+                printf("%s\n", calcpr[i]);
+                free(calcpr[i]);
+            } 
+#endif
+            free(calcpr);
+        }
+    }
+
+    if (rrd_test_error()) {
+	Tcl_AppendResult(interp, "RRD Error: ",
+			 rrd_get_error(), (char *) NULL);
+        rrd_clear_error();
+	return TCL_ERROR;
+    }
+
+    return TCL_OK;
+}
+
+
+
+int
+Rrd_Tune(clientData, interp, argc, argv)
+    ClientData clientData;
+    Tcl_Interp *interp;
+    int argc;
+    char *argv[];
+{
+    optind = 0;
+    
+    rrd_tune(argc, argv);
+
+    if (rrd_test_error()) {
+	Tcl_AppendResult(interp, "RRD Error: ",
+			 rrd_get_error(), (char *) NULL);
+        rrd_clear_error();
+	return TCL_ERROR;
+    }
+
+    return TCL_OK;
+}
+
+
+
+int
+Rrd_Resize(clientData, interp, argc, argv)
+    ClientData clientData;
+    Tcl_Interp *interp;
+    int argc;
+    char *argv[];
+{
+    optind = 0;
+    
+    rrd_resize(argc, argv);
+
+    if (rrd_test_error()) {
+	Tcl_AppendResult(interp, "RRD Error: ",
+			 rrd_get_error(), (char *) NULL);
+        rrd_clear_error();
+	return TCL_ERROR;
+    }
+
+    return TCL_OK;
+}
+
+
+
+int
+Rrd_Restore(clientData, interp, argc, argv)
+    ClientData clientData;
+    Tcl_Interp *interp;
+    int argc;
+    char *argv[];
+{
+    optind = 0;
+    
+    rrd_restore(argc, argv);
+
+    if (rrd_test_error()) {
+	Tcl_AppendResult(interp, "RRD Error: ",
+			 rrd_get_error(), (char *) NULL);
+        rrd_clear_error();
+	return TCL_ERROR;
+    }
+
+    return TCL_OK;
+}
+
+
+
+/*
+ * The following structure defines the commands in the Rrd extension.
+ */
+
+typedef struct {
+    char *name;			/* Name of the command. */
+    Tcl_CmdProc *proc;		/* Procedure for command. */
+} CmdInfo;
+
+static CmdInfo rrdCmds[] = {
+    { "Rrd::create",	Rrd_Create		},
+    { "Rrd::dump",	Rrd_Dump		},
+    { "Rrd::last",	Rrd_Last		},
+    { "Rrd::update",	Rrd_Update		},
+    { "Rrd::fetch",	Rrd_Fetch		},
+    { "Rrd::graph",	Rrd_Graph		},
+    { "Rrd::tune",	Rrd_Tune		},
+    { "Rrd::resize",	Rrd_Resize		},
+    { "Rrd::restore",	Rrd_Restore		},
+    { (char *) NULL,	(Tcl_CmdProc *) NULL	}
+};
+
+
+
+int
+Tclrrd_Init(interp, safe)
+    Tcl_Interp *interp;
+    int safe;
+{ 
+    CmdInfo *cmdInfoPtr;
+    Tcl_CmdInfo info;
+
+    if (Tcl_PkgRequire(interp, "Tcl", TCL_VERSION, 1) == NULL) {
+        return TCL_ERROR;
+    }
+
+    Tcl_SetVar2(interp, "rrd", "version", VERSION, TCL_GLOBAL_ONLY);
+
+    for (cmdInfoPtr = rrdCmds; cmdInfoPtr->name != NULL; cmdInfoPtr++) {
+	/*
+	 * Check if the command already exists and return an error
+	 * to ensure we detect name clashes while loading the Rrd
+	 * extension.
+	 */
+	if (Tcl_GetCommandInfo(interp, cmdInfoPtr->name, &info)) {
+	    Tcl_AppendResult(interp, "command \"", cmdInfoPtr->name,
+			     "\" already exists", (char *) NULL);
+	    return TCL_ERROR;
+	}
+	Tcl_CreateCommand(interp, cmdInfoPtr->name, cmdInfoPtr->proc,
+		          (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
+    }
+
+    if (Tcl_PkgProvide(interp, "Rrd", VERSION) != TCL_OK) {
+	return TCL_ERROR;
+    }
+
+    return TCL_OK;
+}

--
Unsubscribe mailto:rrd-developers-request at list.ee.ethz.ch?subject=unsubscribe
Help        mailto:rrd-developers-request at list.ee.ethz.ch?subject=help
Archive     http://www.ee.ethz.ch/~slist/rrd-developers



More information about the rrd-developers mailing list