GxSNMP Database documentation
hello
GxSNMP Database introduction
This is a introduction to use the virtual database system.
An application utilizes the database engine client API.
It sets up a connection to a database daemon server, that handles connection between
applications and databases. An application can have database
tables located at several databases, by having several connections to database
daemon servers. All this is determined at connection time and
stored in a table_data_storage structures.
So we have:
Application connection setup
GxSNMP Native API
GxSNMP CORBA API
Database daemon server
Table_data_storage
Application connection setup
The application must first setup a connection to a running
database daemon server. See the examples of how to setup this connection.
API
Various interfaces to access the database.
Read more about this in .
Read more about this in .
Database daemon server
A database daemon handles data between a database and
several clients. The daemon can only handle one database
vendor at a time. Although the client can connect to
several database daemons.
Table_data_storage
This is a structure that is used by the API and stores
information about, table records loaded filter information,
connection descriptor and more.
Read more about this structure in Database data types.
GxSNMP Database data types Description
These database types is used by the database engine, and here
we describe what the user must setup, before utilizing the engine,
and how data is presented.
Globals
To the user there is no known globals :-)
The database client API itself uses a few globals internally.
Therefor the library isn't thread safe.
typedef G_sqldb_table
This is mainly a data storage for a database table, along with
connection related information.
typedef struct _G_sqldb_table
{
G_sql * engine; /* SQL engine structure */
gchar ** database; /* Name of the SQL database */
gchar * name; /* Name of the SQL table */
gint type; /* unused */
gint sock; /* Database daemon server socket */
gpointer filter; /* load/find filter to use */
gint row_length; /* Size of each row in bytes */
gint row_private; /* Offset in row to gpointer
for use by library only */
G_sqldb_column * columns; /* Pointer to column array */
struct _G_sqldb_table_private * private; /* For use by library only */
}
G_sqldb_table;
Example:
static
G_sqldb_table snmp_db_struct =
{
0, /* Pointer to G_sql structure */
0, /* Pointer to database name */
"snmp", /* Pointer to table name */
0,
my_socket_to_ddserver, /* connection descriptor to gxdd */
0,
sizeof (DB_snmp), /* Length of a row in bytes */
G_STRUCT_OFFSET (DB_snmp, g_sqldb_private), /* Offset of private hndl */
0 /* List of column definitions */
};
G_sqldb_table * snmp_sqldb = & snmp_db_struct;
In this example We set up a G_sqldb_table that holds loaded table data.
Use the Client API call g_sqldb_table_load () to load this structure with
table data.
Notification callback function
This function is passed all information in a notification.
void (* func)(GIOChannel *channel,
gint type, /* Type of notification */
guint rowid, /* database row number */
gchar *table, /* database table name */
gpointer data); /* Notification data */
Notification Types:
typedef enum {
DB_NOTIF_TABLE_CHANGED = 1, /* db-table has changed */
DB_NOTIF_TABLE_FIELD_CHANGED, /* db-field has changed */
DB_NOTIF_TABLE_RECORD_CHANGED /* db-record has changed */
} DB_Notification_Types;
GxSNMP Database Native API reference #include "dbapi.h" gint db_server_connect_config (gchar *host, gint port) gint db_server_connect (gchar *host, gint port) gint db_server_disconnect (gchar *host, gint port) gint g_sqldb_dbctl (G_sqldb_table *sqldb, gint value) gboolean g_sqldb_table_load (G_sqldb_table *sqldb) gboolean g_sqldb_table_list (G_sqldb_table *sqldb) gboolean g_sqldb_row_add (G_sqldb_table *sqldb, gpointer row) gboolean g_sqldb_row_delete (G_sqldb_table *sqldb, gpointer row) gpointer g_sqldb_row_find (G_sqldb_table *sqldb, gpointer row,
gchar *field, gpointer keyp) gboolean g_sqldb_reload_row (G_sqldb_table *sqldb, gpointer row) gint g_sqldb_highest_rowid (G_sqldb_table *sqldb, gchar *field) gint g_sqldb_table_cb (G_sqldb_table *sqldb,
gpointer row,
G_sqldb_cb_type type,
G_sqldb_cb func,
gpointer data)
gpointer db_create_row (gchar *tablename) gint db_destroy_row (gchar *tablename, gpointer row) GList db_load_table (G_sqldb_table *sqldb) GList db_find_rows (G_sqldb_table *sqldb) gint db_filter_setup (db_filter *filter,
gchar *name,
guint method) gint db_filter_add (db_filter *filter,
gchar *name,
gpointer value) gint db_filter_modify (db_filter *filter,
gchar *field,
gpointer value) gint db_filter_del (db_filter *filter,
gchar *field) void db_notification_add (gpointer func) void db_notification_del (gpointer func) Description
Client API is used by the application to store and utilize
data in a database. The functions operate on database tables
and records. A database table
is loaded into memory where application can use it. Then
updates is sent to memory and database.
Details hello db_server_connect_config () gint db_server_connect_config (gchar *host, gint port)
Before the database API is ready for use, one must learn the
API about database table it will use, this is done by calling
for a Master table, that has information about all database
tables used in the Virtual Database System. The Master table is
located at host at TCP port .
host: machine running a DB daemon serving the Master table.port: TCP port DB daemon is listening to.returns: Socket of connection to DB daemon. db_server_connect () gint db_server_connect (gchar *host, gint port)
After the Master table has been loaded, one can start connecting to other DB daemons serving other tables, that has been described in the Master
table. If the DB daemon serving the Master table, also serves those table, there is no need to call this function.
host: machine running a DB daemon serving the Master table.port: TCP port DB daemon is listening to.returns: Socket of connection to DB daemon. db_server_disconnect () gint db_server_disconnect (gint port)
Disconnecting to a DB daemon.
sock: Connection descriptor to a DB daemon.returns: NULL if successful. g_sqldb_dbctl () gint g_sqldb_dbctl (G_sqldb_table * sqldb,
gint value)
Change connection parameters of a database server daemon connection.
/* This will set the connection with full notification,
autorized, and read/write access */
gint value = DBCTL_NOTIFY_FULL | DBCTL_AUTH | DBCTL_RW;
g_sqldb_dbctl (sqldb, value);
sqldb: Table information with connection descriptor.value: the value to apply to this connection.returns: TRUE if successful. g_sqldb_table_load () gboolean g_sqldb_table_load (G_sqldb_table * sqldb)
Load a database table into memory
GList *gl;
DB_host row; /* structure of a record */
g_sqldb_table_load (host_sqldb);
gl = g_sqldb_table_list (host_sqldb);
while(gl){ /* traverse whole table */
row = gl->data;
/* use row data */
gl = gl->next;
}
table: data storage.returns: TRUE if successful. g_sqldb_table_list () GList * g_sqldb_table_list (G_sqldb_table * sqldb)
Get table records from a database table previously loaded.
table: data storage.returns: GList of database rows. g_sqldb_row_add () gboolean g_sqldb_row_add (G_sqldb_table * sqldb, gpointer row)
Add a database record into database and memory.
table: data storage.row: database table record.returns: TRUE if successful. g_sqldb_row_update () gboolean g_sqldb_row_update (G_sqldb_table * sqldb, gpointer row)
Update a database record in both memory and database.
table: data storage.row: database table record.returns: TRUE if successful. g_sqldb_row_delete () gboolean g_sqldb_row_delete (G_sqldb_table * sqldb, gpointer row)
Delete a record from database and memory.
table: data storage.row: database table record.returns: TRUE if successful. g_sqldb_row_find () gpointer g_sqldb_row_find (G_sqldb_table * sqldb, gchar *field,
gpointer keyp)
Find a record in memory loaded database table.
EXAMPLE NEEDED !
table: data storage.field: database field name.keyp: pointer to a rowid of a record.returns: TRUE if successful. g_sqldb_row_reload () gboolean g_sqldb_row_reload (G_sqldb_table * sqldb, gpointer row)
Reload a single record in memory from a database table.
table: data storage.row: database record.returns: TRUE if successful. g_sqldb_highest_rowid () gint g_sqldb_highest_rowid (G_sqldb_table * sqldb, gchar *field)
Find highest ROWID in memory loaded database table.
table: data storage.field: database field name.returns: TRUE if successful. g_sqldb_table_cb_add() gint g_sqldb_table_cb_add (G_sqldb_table *sqldb,
gpointer row,
G_sqldb_cb_type type,
G_sqldb_cb func,
gpointer data)
Find highest ROWID in memory loaded database table.
table: data storage.row: database record.type: callback type.func: callback function.data: callback data.returns: TRUE if successful. db_create_row () gpointer db_create_row (gchar *tablename)
Allocate memory to hold a structure that corresponds to the size
of the record identified by tablename. It will also setup initial
parameters if possible.
DB_host *dbh;
dbh = db_create_row("host"); /* table name is used
to identify record type*/
printf("%s", dbh->created);
printf("%s", dbh->modified);
tablename: type of record to create.returns: Object created. db_destroy_row() gint db_destroy_row (gpointer row)
Destroys as much as possible of an record, prior to user
application freeing it. Using record descriptors we know
what fields is possible to free and what is not.
row: record to destroy.returns: TRUE if destroyed. db_load_table () GList db_load_table (G_sqldb_table *table)
Is used to load a table from the database to memory.
A filter can be used to select specific records.
The function returns a GList of records.
table: data storage.returns: TRUE if destroyed. db_find_rows () GList db_find_rows (G_sqldb_table *table)
Sqldb contains a loaded database table, and using db_find_rows()
we can use a filter to sort out specific rows in this table. The
function returns a GList of records.
DB_host *dbhp;
host_sqldb->sock = socket_to_gxddserver; /* Set socket in our G_sqldb_table */
g_sqldb_table_load(host_sqldb); /* load in table in our G_sqldb_table */
/* setup filter */
host_sqldb->filter = & filter;
db_filter_setup(& filter, "host", OBJ_FIND_SINGLE); /* "host" is tablename */
db_filter_add(& filter, "name", "my-unix-machine"); /* "name" is fieldname,
"my-unix-machine" is the fieldvalue to search for in fieldname */
gl = db_find_rows(host_sqldb); /* make the search */
if(!gl){
fprintf(stderr,"Nothing passed through the filter.\n");
}
else while(gl){
fprintf(stderr, "going though GList pointer\n");
dbhp = gl->data;
printf("created: %s\n", dbhp->created);
printf("modified: %s\n", dbhp->modified);
printf("dns_name: %s\n", dbhp->dns_name);
printf("name: %s\n", dbhp->name);
printf("description: %s\n", dbhp->description);
gl = gl->next;
}
table: data storage ( previously loaded).returns: GList of records matching filter. db_filter_setup () gint db_filter_setup (db_filter *filter, gchar *name, guint method)
Initialize a filter.
filter: filter to initialize.name: tablename this filter is used for.method: search method.returns: TRUE if successful. db_filter_add () gint db_filter_add (db_filter *filter, gchar *field, gpointer value)
Add a search entry in the filter.
/* setup filter */
host_sqldb->filter = & filter;
db_filter_setup(& filter, "host", OBJ_FIND_SINGLE); /* "host" is tablename */
db_filter_add(& filter, "name", "my-unix-machine"); /* "name" is fieldname,
"my-unix-machine" is the fieldvalue to search for in fieldname */
filter: filter to add entry in.field: database fieldname.value: value to search for in fieldname.returns: TRUE if successful. db_filter_modify () gint db_filter_modify (db_filter *filter, gchar *field, gpointer value)
modify a search entry in the filter.
host_sqldb->filter = & filter;
db_filter_setup(& filter, "host", OBJ_FIND_SINGLE); /* "host" is tablename */
db_filter_add(& filter, "name", "my-unix-machine"); /* "name" is fieldname,
"my-unix-machine" is the fieldvalue to search for in fieldname */
db_filter_modify(& filter, "name", "my-unix-host");
filter: filter to modify entry in.field: database fieldname filter entry to modify.value: value to modify in fieldname.returns: TRUE if successful. db_filter_del () gint db_filter_del (db_filter *filter, gchar *field)
delete a search entry in the filter.
/* setup filter */
host_sqldb->filter = & filter;
db_filter_setup(& filter, "host", OBJ_FIND_SINGLE); /* "host" is tablename */
db_filter_add(& filter, "name", "my-unix-machine"); /* "name" is fieldname,
"my-unix-machine" is the fieldvalue to search for in fieldname */
db_filter_modify(& filter, "name", "my-unix-host");
db_filter_delete(& filter, "name");
filter: filter to delete entry in.field: fieldname entry to delete.returns: TRUE if successful. db_notification_add () void db_notification_add (gpointer func)
Registers a function that will be called each time we receive
a notification.
static void notification_cb(GIOChannel *channel,gint type,guint rowid,
gchar *table,gpointer data);
/*** Database notification callback ***/
static void
notification_cb (GIOChannel *channel, gint type, guint rowid,
gchar *table, gpointer data)
{
DB_interface * dbi;
DB_host * dbh;
gchar * oldtag;
dbi = g_sqldb_row_find(interface_sqldb, "_rowid", &rowid);
if(dbi){
oldtag = g_strdup(dbi->tags);
g_sqldb_reload_row(interface_sqldb, dbi);
dbi = g_sqldb_row_find(interface_sqldb, "_rowid", &rowid);
dbh = g_sqldb_row_find(host_sqldb, "_rowid", &dbi->host);
if(dbi && dbh)
fprintf(stderr,"Host %s, Interface %s(%s) is %s\n",
dbh->name, dbi->name, dbi->address, dbi->tags);
}
}
gint
main (int argc, char *argv[])
{
/* start the Virtual Database System */
ddchannel = db_server_connect_config ("127.0.0.1", 4000);
/* Register a notificatoin callback */
db_notification_add (notification_cb);
gtk_main();
}
func: Callback function to register.
listitem>returns: db_notification_del () void db_notification_del (gpointer func)
Removes a previous registered notification callback function.
func: Callback function to unregister.returns: GxSNMP Database CORBA interface reference void TableOpen (in GSQLDBTable table) void TableClose (in GSQLDBTable table) RowHost GetRowHost () RowInterface GetRowInterface () Description
The CORBA interface is not yet defined.
Details
module GxSNMP {
interface GSQLDB {
struct GSQLDBTable {
string table;
};
struct RowHost {
long objid;
string created;
string modified;
string dnsname;
string name;
string description;
string contact;
string tags;
};
struct RowInterface {
long objid;
string created;
string modified;
long host;
long snmp;
long transport;
string address;
string netmask;
string name;
string tags;
};
struct RowMap {
long objid;
string created;
string modified;
string name;
string tab;
string description;
string tags;
};
struct RowGraph {
long objid;
string created;
string modified;
long map;
long type;
long host;
long network;
string details;
long x;
long y;
string pixmap;
string tags;
};
void TableOpen (in GSQLDBTable table);
void TableClose (in GSQLDBTable table);
RowHost GetRowHost ();
RowInterface GetRowInterface ();
RowMap GetRowMap ();
RowGraph GetRowGraph ();
};
};
GxSNMP Database tutorial
This example will show how to use the API in the
simplest of ways.
Please read the for reference.
Step by step
A walkthrough of what happens in this example.
First call TableOpen on our database table.
This is also a client init for
the database server.
Now we call a GetRow function, that returns a pointer to a
row in our database table. The layout of the memory is
specified in the IDL file.
Done, call TableClose to tell database server we are done.
Lets look at our first example.
The point in this example is to show that we are only
dependent on the IDL interface, to be able to
communicate to the database server.
#include "gnome.h"
#include "orb/orbit.h"
#include "liboaf/liboaf.h"
#include "orbit-gxsnmp-db.h"
int main (int argc, char **argv)
{
CORBA_Environment ev;
CORBA_ORB orb;
GxSNMP_GSQLDB gsqldbclient;
GxSNMP_GSQLDB_GSQLDBTable *table;
GxSNMP_GSQLDB_RowHost *host;
gchar *query;
CORBA_exception_init (& ev);
orb = oaf_init(argc,argv);
query = g_strdup("repo_ids.has ('IDL:GxSNMP/DB:1.0')");
gsqldbclient = oaf_activate (query, NULL, 0, NULL, & ev);
g_free(query);
if(gsqldbclient == CORBA_OBJECT_NIL) {
g_print("cannot bind to object\n");
exit(-1);
}
table = GxSNMP_GSQLDB_GSQLDBTable__alloc();
table->table = CORBA_string_dup("host");
GxSNMP_GSQLDB_TableOpen (gsqldbclient, table, & ev);
while((host = GxSNMP_GSQLDB_GetRowHost (gsqldbclient, & ev))){
if(ev._major != CORBA_NO_EXCEPTION) break;
printf("objid: %d\n", host->objid);
printf("created: %s\n", host->created);
printf("modified: %s\n", host->modified);
printf("dnsname: %s\n", host->dnsname);
printf("name: %s\n", host->name);
printf("description: %s\n", host->description);
printf("contact: %s\n", host->contact);
printf("tags: %s\n\n", host->tags);
CORBA_free(host);
}
GxSNMP_GSQLDB_TableClose (gsqldbclient, table, & ev);
CORBA_free(table);
CORBA_exception_free (& ev);
exit(0);
}
The example first locates our object ( which is the database CORBA interface ).
It is located using a local OAF daemon. We ask for a interface that supports
the 'IDL:GxSNMP/DB:1.0' interface.
Native API simplest example
This example will show how to use the Native API in the
simplest of ways.
Please read the for reference.
#include "dbapi.h"
#include "gxsnmp/gxsnmp_dbapi.h"
int
main (int argc, char **argv)
{
DB_host *row;
GList *gl;
/* start the Virtual Database System */
dcsock = db_server_connect_config ("127.0.0.1", 4000);
host_sqldb->sock = dcsock;
g_sqldb_table_load (host_sqldb);
gl = g_sqldb_table_list(host_sqldb);
while(gl){
row = gl->data;
printf("name: %s\n", row->dns_name);
}
/* please notice we doesn't do any memory cleanup */
}
Database daemon internals
Here is a overview of the internals of the database daemon.
It is the "design".
gxdd
What follows is a discussion of the internal components of the
database daemon.
The picture is a conceptual view of the actual process running.
Each square represents a code block, that consist of a few
source files.
SQL-plugin. A vendor native interface between the database and
the g_sql-api.
EXAMPLE plugins/mysql/mysql_backend.c.
g_sql-api. This is a generic api over the SQL-plugin.
lib/g_sql.c.
Request processor. Executes client requests from the reqlist.
server/queue.c.
Reqlist. A list of pending requests.
server/main.c:GList *tranq.
Connection handler. Handles connection to clients.
server/tcp_services.c.
Corba skel. This is a corba implementation to enable corba users.
server/impl-host.c,
server/impl-host.c.
Encode/Decode, Table Descriptor. These to is a group of functions
on both the server and the client side.
The Encode/Decode is used to translate between C structures,
encapsulated pdus and with help of the g_sql-api; native SQL structures.
The Table Descriptor is a group of functions that has to be
initialized with data that describes each table that the
database engine is going to use.
lib/table-common.c.
lib/pdu.c.
Client side internals
Here is a overview of the internals of the APIs that the
client uses.
client
What follows is a discussion of the internal components of the
Client APIs.
The picture is a conceptual view of the actual process running.
Each square represents a code block, that consist of a few
source files.
I/O. The I/O transmit and receives data to/from the database
engine. It is also the API how the clients connect.
lib/ddclient.c.
g_sqldb-api. This is a API that load data into memory, sends data
to the daemon. It also handles notification.
lib/g_sqldb.c.
db-api. The db-api uses the g_sqldb-api and adds some own APIs.
It can be used to load into memory using a table filter, or copy from
memory to memory using a table filter.
lib/object.c.
GxSNMP Addon API. Convenient functions that uses the
g_sqldb-api and the db-api to load a bulk of tables, setup
internal pointers, ie, private pointers that the VDS doesn't
know how to use. It also setups predefined filter.
The GxSNMP Addon API, can be modified to fit another type
of application, if the VDS ever would be used outside GxSNMP.
lib/gxsnmp_*.
include/gxsnmp/*.
Encode/Decode, Table Descriptor. Please see the Database daemon
internals for info. The client side initializes the Table descriptors
by calling db_server_connect_config ().