Chapter 6. RSP Lib API

Table of Contents
Getting Started
Linking with the Library (C versions)
Linking with the Java Version
Linking with the Perl Version
RSP Lib
C Function Reference
Java Function Reference
Perl Function Reference
Example RSP Lib Code - C
Example RSP Lib Code - Java
Example RSP Lib Code - Perl

The RSP Monitoring Tools were designed from the ground up to be an extendable, scalable solution for large and small networks. One of the biggest features of the RSP design is its architecture with these very goals in mind. This architecture is implemented through the RSP Lib API (Application Programming Interface), with hooks for Java, C and Perl. This manual will discuss how to get started using this API in your own applications.

It should be noted that the RSP Lib API is designed to extend the functionality of the monitor and analysis features of the RSP suite. A separate architecture was developed for the module interface, allowing new modules to be developed for the RSPD program, known as the RSPD Module API. This documentation is available in the RSPD application section.

The RSP Lib API was provided for programmers to implement their own custom monitoring and analysis solutions. Because it is impossible to anticipate every conceivable monitoring or analysis situation, design for these tools had to be generalized, potentially at the cost of highly specialized fields. For instance, it may be useful to write a new monitoring interface for networks that specialize in hospital patient monitoring (where a multitude of sensors monitor a single patient's status). Using the RSP Lib, implementing a custom monitoring or analysis package for your applications becomes simplicity itself.

Before you begin, you should have some kind of RSP topology setup (say one or more RSPD nodes and a JRSP/RSP Web monitor running) for testing. Also, you should have the necessary build tools and or interpreters installed (such as GCC, Perl or a Java VM). Finally, you should be proficient in your chosen language (C/C++, Perl or Java) and your operating environment, including the necessary experience to develop, build and debug software using a third party API. This manual will not go into detail on how to develop software - there are plenty of good resources available either at a local bookstore or on the World Wide Web.

Getting Started

The RSP Lib API is available in several versions: a Perl, Java or C version, and, in the case of the C version, is also available as either a static or shared object library. No matter which version you decide to use, all are very similar to one another (function names are similar, though may be accessed in different ways, etc). Therefore, this documentation will detail each function, as well as give the alternative names (and examples) for each of the different library.

Linking with the Library (C versions)

There are two ways to link the RSP Lib API into your C programs: either as a static object, or as a shared library. Either method is acceptable, though your project requirements may dictate which method is preferable. Keep in mind that linking with the static library means a new version of your software must be built whenever your users wish to use the latest version of the RSP Lib API. Shared object libraries solve this problem, but create more of a hassle in maintaining version dependencies (say your program requires a certain version of the RSP Lib API and is incompatible with different versions). Be sure to keep these considerations in mind when deciding which linking method to use.

The shared object version of the RSP Lib API is available in the librsplib.so file. If you are using GCC (a free compiler and linker popular on the Linux and UNIX platforms, though also available for Windows and Macintosh), simply add the command -lrsplib to the end of your link command:

gcc -o PROGRAM_NAME SOURCE_CODE.c -lrsplib
			

In order for the above command to work, it is imperative that GCC be able to find the librsplib.so file. Therefore, you can either install the file into a common library location on your system (usually /usr/local/lib on Linux and UNIX platforms), or give GCC an explicit command to find the shared library (using the -L parameter). Check with your linker's documentation for complete details on linking C code with shared object libraries.

To link with the static version of the C library, you need to use the librsplib.a file, which contains the object code needed to build your application. When your program is linked, the contents of this library are copied into your application's executable, making its file size grow (though not by very much, as the RSP Lib API is a fairly small library).

Using the GCC compiler/linker, simply include the librsplib.a file along with all of your code object files (usually named with a .o suffix), such as in the following example:

gcc -o PROGRAM NAME SOURCE_CODE.o /PATH/TO/librsplib.a
			

Again, be sure to check with your linker's documentation for detailed instructions on including static libraries into your applications.

Once you are building your applications using either version of the RSP Lib API, you need to include the RSP Lib API header file into all appropriate C coded files (which is done using the #include <rsplib.h> directive). Note that your compiler needs to be able to find this file, so it either needs to be placed in a standard location (such as /usr/include on Linux and UNIX platforms), or in a directory that can be otherwise found by your compiler. Using GCC, the -I option can be used to specify a directory that contains header files. Check with your compiler's documentation for specific instructions on including files (and how to locate them on your system).

Once you have successfully built an application, including linking against either the shared object or static versions of the library, as well as placing a #include <rsplib.h> line into your source coded file(s), you are ready to begin programming with the library.

Linking with the Java Version

To build a Java application using the Java version of the RSP Lib API, you compile your code with the rsplib.jar archive file. This file contains a number of Java class files, assembled together into a single Java Archive file (JAR). If you are using Sun Microsystems' compiler on a Linux or UNIX system, you can use a command similar to the following:

javac -classpath /PATH/TO/rsplib.jar SOURCE_CODE.java
			

Be sure to check with your specific compiler for details on compiling against a JAR file.

To reference the Java code located within this JAR file, you must place appropriate import lines into your Java files, such as:

import com.dracoware.*;
			

Alternatively, you can reference each class specifically (there are 8):

  • RspGraphReturnData

  • RspModule

  • RspParseException

  • RspParseLine

  • RspParser

  • RspServer

  • RspStream

  • RspThreshold

Once you have completed both of these steps, you are now ready to begin developing your RSP Lib API-aware Java application.

Linking with the Perl Version

The Perl version of the RSP Lib API is used in a slightly different way than the Java or C versions of the library. The Perl version is made up of two parts: the C shared object library and the Perl wrapper interface. When developing with the library, you call the wrapper routines, which in turn call the C version of the routine.

To begin developing in Perl, install the appropriate version of the C library and the Perl wrapper using the included installation script (install_perl_files.sh on Linux and UNIX systems). Once this has been done, place the following line at the top of your Perl code file(s):

use rsplib;
			

This will reference the rsplib.pm module. Once this line has been added to your Perl file(s), build the application like you would normally build it. You can now begin using the RSP Lib API software in your Perl program.

RSP Lib

All the functions (or classes for Java) in RSP Lib fall into two main groups. The first group of functions are for retrieving current data from an RSPD server. RSP Lib handles SSL connections as well as persistent connections including keep alives. The second group of functions serve to gather history data archived on a History Listener server or a MySQL database. Once a connection is established, you may ask for a list of all hosts and modules on the server, ask for a list of all keys given a specific host or module, or finally retrieve actual data over a given time period.

C Function Reference

Table of Contents
RSP_newServer -- Creates a data structure for an RSPD connection..
RSP_serverUseSSL -- Specifies that this connection should use secure SSL communication.
RSP_serverConnect -- Gets current data from an RSPD.
RSP_nextServerModule -- Returns next module data structure in chain.
RSP_serverSendKeepAlive -- Sends a keep-alive packet to a persistently connected RSPD.
RSP_serverFree -- Clears internal data downloaded from an RSPD.
RSP_newParseRemote -- Sets up internal structures for parsing history data from a History Listener.
RSP_remoteUseSSL -- Specifies that this connection should use secure SSL communication.
RSP_newParseMySQL -- Sets up internal structures for parsing MySQL data.
RSP_getHostsAndModules -- Retrieves all host and module names.
RSP_getKeys -- Retrieves all keys from a given host and module.
RSP_parseBegin -- Prepares to parse history data.
RSP_parseNext -- Returns the next set of parsed history data.
RSP_parseDelete -- Frees internal data associated with parsed history data.

This section details each of the functions available to the C version of the library. It should be noted all of the functions listed have corresponding error codes and messages in such cases where they occur. When an error happens, the function will generally return a value with signals this (such as NULL or -1). In addition, the integer rsp_error will be set to the error value, and the string rsp_errorstr will contain to the error message. To access these variables, simply add the following two lines to your code:

extern int rsp_error;
extern char rsp_errorstr[RSP_ERROR_SIZE];
		

Java Function Reference

Note that the Java functions are broken down by Class and are included in a separate reference guide: the RSP API Javadoc HTML Documentation, available online.

Perl Function Reference

Table of Contents
RSP_server -- Creates an object for an RSPD connection.
useSSL -- Specifies that this connection should use secure SSL communication.
connect -- Gets current data from an RSPD.
nextServerModule -- Returns next module data structure in chain.
sendKeepAlive -- Sends a keep-alive packet to a persistently connected RSPD.
RSP_parseData -- Creates an object for history parsing.
remoteUseSSL -- Specifies that this connection should use secure SSL communication.
getHostsAndModules -- Retrieves all host and module names.
getKeys -- Retrieves all keys from a given host and module.
begin -- Prepares to parse history data.
next -- Returns the next set of parsed history data.

The perl functions for RSP Lib are very similar to those in C, as the perl module in fact uses the compiled C library. The main difference is that the functions are called directly from the object in object-oriented style.

The two main objects are RSP_server (for gathering RSPD server data) and RSP_parseData (for retrieving history data). From then on, functions are called from the object itself. For example:

use rsplib;

# Server functions
my $node = new rsplib::RSP_server("127.0.0.1", 3497, 5, 0);

$node->useSSL("./keyfile.rsa");
$node->connect();

# ...

# Parse functions
my $pd = new rsplib::RSP_parseData("127.0.0.1", 3496, 5);
$pd->begin();
		

Example RSP Lib Code - C

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include "rsplib.h"

extern int rsp_error;
extern char rsp_errorstr[];

void serverTest(void);
void parseTest(void);

void serverTest(void)
{
	RSP_server* data;
	RSP_module* node;

	// Connect to localhost, persistent
	if((data = RSP_newServer("127.0.0.1", 3497, 5, 1)) == NULL)
	{
		fprintf(stderr, "Got error: %s\n", rsp_errorstr);
		exit(EXIT_FAILURE);
	}

	// We want to use SSL for this connection
	if(RSP_serverUseSSL(data, "./keyfile.rsa") == -1)
	{
		fprintf(stderr, "Got error: %s\n", rsp_errorstr);
		exit(EXIT_FAILURE);
	}

	// Make the connection
	if(RSP_serverConnect(data) == -1)
	{
		fprintf(stderr, "Got error: %s\n", rsp_errorstr);
		exit(EXIT_FAILURE);
	}

	// This is how keep alives are sent
	if(RSP_serverSendKeepAlive(data) == -1)
	{
		fprintf(stderr, "Got error: %s\n", rsp_errorstr);
		exit(EXIT_FAILURE);
	}

	// Iterate through each module
	while((node = RSP_nextServerModule(data)) != NULL)
	{
		// print out data
		printf("Name = %s, Data = %s, Thresh = %d\n", node->name, node->data, node->threshCrossed);
	}

	// Always free data when you are done
	RSP_serverFree(data);
}

void parseTest(void)
{
	RSP_parseData* pd;
	RSP_parseLine* line;
	char **hosts, **modules, **keys;
	int i;

	pd = RSP_newParseRemote("127.0.0.1", 3496, 5);

	RSP_remoteUseSSL(pd, "./keyfile.rsa");

	// Get list of hosts and modules
	RSP_getHostsAndModules(pd, &hosts, &modules);
	printf("Hosts on server:\n");

	// Always be sure to free the data in this way
	i = 0;
	while(hosts[i] != NULL)
	{
		printf("%s\n", hosts[i]);
		free(hosts[i++]);
	}
	free(hosts);

	printf("\nModules on server:\n");
	i = 0;
	while(modules[i] != NULL)
	{
		printf("%s\n", modules[i]);
		free(modules[i++]);
	}
	free(modules);

	// Get all keys for this host and module	
	RSP_getKeys(pd, "euclid", "CPUInfo", &keys);
	printf("\nKeys on server for euclid CPUInfo:\n");

	i = 0;
	while(keys[i] != NULL)
	{
		printf("%s\n", keys[i]);
		free(keys[i++]);
	}
	free(keys);

	if(RSP_parseBegin(pd, "euclid", "CPUInfo", "idle", -1, -1, 0) == -1)
	{
		fprintf(stderr, "Got error: %s\n", rsp_errorstr);
		exit(EXIT_FAILURE);
	}

	printf("\n");
	while((line = RSP_parseNext(pd)) != NULL)
	{
		printf("%d %s\n", (int)line->time, line->szData);
	}

	RSP_parseDelete(pd);
}

int main(int argc, char** argv)
{
	serverTest();
	parseTest();
}
			

Example RSP Lib Code - Java

import com.dracoware.rsplib.*;
import java.io.IOException;
import java.io.File;
import java.util.*;

public class javatest
{
	public static void main(String[] args)
	{
		serverTest();
		parseTest();
	}

	public static void serverTest()
	{
		RspServer testNode = new RspServer("local", "127.0.0.1", 3487);
		testNode.setPersistent(true);

		try {
			testNode.useSSL(new File("./javatest.rsa"));
			testNode.connect();
		} catch (IOException e) {
			System.err.println(e.toString());
			return;
		}

		Enumeration e = testNode.getData().elements();
		while(e.hasMoreElements())
		{
			RspModule m = (RspModule)e.nextElement();

			System.out.println("name = " + m.getName() + ", data = " + m.getData() + ", thresh = " + m.threshCrossed());
		}

		testNode.disconnect();
	}

	public static void parseTest()
	{
		try {
			RspParser parser = new RspParser();
			parser.parseInfoRemote("localhost", 3496, 5);
			parser.remoteUseSSL(new File("./javatest.rsa"));

			Vector hosts = new Vector();
		  	Vector modules = new Vector();
			Vector keys = new Vector();

			parser.getHostsAndModules(hosts, modules);

			Enumeration e = hosts.elements();
			System.out.println("Hosts: ");
			while(e.hasMoreElements())
				System.out.println((String)e.nextElement());
			
			e = modules.elements();
			System.out.println();
			System.out.println("Modules: ");
			while(e.hasMoreElements())
				System.out.println((String)e.nextElement());

			parser.getKeys("euclid", "CPUInfo", keys);

			e = keys.elements();
			System.out.println();
			System.out.println("Keys: ");
			while(e.hasMoreElements())
				System.out.println((String)e.nextElement());

			parser.beginParse("euclid", "CPUInfo", "idle", -1, -1, false);

			RspParseLine line;
			while((line = parser.nextLine()) != null)
				System.out.println(line.getTime().toString() + " " + line.getGraphData());
		}
		catch (RspParseException rpE) {
			System.err.println("Parse error: " + rpE.getMessage());
		}
	}
}
			

Example RSP Lib Code - Perl

#!/usr/bin/perl

use strict;
use rsplib;

sub serverTest() {
	my $node = new rsplib::RSP_server("127.0.0.1", 3497, 5, 0);

	$node->useSSL("./perltest.rsa");
	$node->connect();
	
	my $module;
	while(defined($module = $node->nextServerModule())) {
		print "Name = \"" . $module->getName() . "\", Data = \"" .
			$module->getData() . "\", Thresh = \"" . $module->threshold() . "\"\n";
	}
}

sub parseTest() {
	my $pd = new rsplib::RSP_parseData("127.0.0.1", 3496, 30);

	my @hosts;
	my @modules;

	$pd->getHostsAndModules(\@hosts, \@modules);

	print "Hosts:\n";
	foreach my $host (@hosts) {
		print $host . "\n";
	}

	print "\nModules:\n";
	foreach my $module (@modules) {
		print $module . "\n";
	}

	my @keys;

	$pd->getKeys("euclid", "CPUInfo", \@keys);

	print "\nKeys:\n";
	foreach my $key (@keys) {
		print $key . "\n";
	}

	$pd->begin("euclid", "CPUInfo", "idle", -1, -1, 0);

	my $line;
	while(defined($line = $pd->next())) {
		print $line->getTime() . " " . $line->getData() . " " . $line->getGraphType() . "\n";
	}
}

serverTest();
parseTest();