$Id: dag.txt,v 1.7 2000/02/19 19:11:39 remlali Exp $

Think this guide should explain how to use
the Client API and how to make a table-plugin.

Database API guide

INDEX

1          Introduction
2          Client API
2.1          Client API layers
2.1.1          Object API
2.1.2          gsqldb API
2.1.3          Primitive API
3.1        API example with a simple client
3.1.1        Include files and definitions
A          Packet layout
B          MemberRecord
C          Code documentation
C.1          Loading a table filtered


2.1 Client API layers

  Here is a brief overview description of how the Client API is
  structured.

  Here are the layers currently in used and planned.

  1 Object
  2 g_sqldb
  3 primitive

2.1.1 Object API

   This section ( 2.1.1 ) talks about the Object API usage.


2.1.1.1 Object API introduction

   This is the API one should use to "talk object oriented" with the database.
   The object API layer is based on the code found in the DB_* files.
   API functions has a prefix of 'gxobject_', here is those functions that are
   defined today:

   gxobject_db_create    ( Type_of_object )
   gxobject_db_destroy   ( gxobject * )
   gxobject_db_add       ( gxobject * )
   gxobject_db_update    ( gxobject * )
   gxobject_db_delete    ( gxobject * )
   gxobject_db_find      ( gxobject * )
   gxobject_db_load      ( gxobject * )

   These functions operate on object structures.

   Mainly what is done here is that when you call gxobject_db_add() for example
   it will dispatch to the table-plugin and call a function that is equal to the
   old DB_ files. For example, if the code used to call host_add. Then if we
   setup a object, and call gxobject_db_add(), we should be executing same lines
   of code in the plugin that host_add() had.


   Here is how the object structures look like:

      First we have a context structure that is to be used with database objects.

      typedef struct _gxobject_ctx {
        gint  type;                   /* type of table to use (same as name of table)  */
        gint  sock;                   /* socket to use if we contact database daemon */
        gxdb_tables tables;           /* pointer to all tables loaded in memory */
        gpointer user;                /* various information held here, filter etc.. */
      } gxobject_ctx;


      This is the gxobject structure 

      typedef struct _gxobject {
        gint objnum;                  /* unique object number */
        gint type;                    /* type of object */
        gpointer ctx;                 /* additional context information */
        gpointer obj;                 /* object */
      } gxobject;

   The purpose of the gxobject_ctx structure is to provide additional information
   along with the object. For example the database must have socket, and table
   information to act on a object.


2.1.1.2 Object API Filter capability

   The Object API uses a general filter struct to do filtering, that was previous
   made by alot of functions. Therefor setting up a filter takes more code now, and
   the code should have predefined filters. These are found in 
   database/lib/db_filters.c

   The function gxobject_db_find() and gxobject_db_load functions currently supports
   the filter capability. Goal is to make the filter a general capability.

   Here is the structures used by the filter function.

   typedef enum {
     OBJ_FIND_MULTI = 1,
     OBJ_FIND_SINGLE
   } GxSNMP_OBJECT_FILTER;


   typedef struct _gxobject_db_filter  {
     gint method;                  /* match method */
     gchar **args;                 /* a setup of filters */
   } gxobject_db_filter;

   Here is a example of how to setup and perform filtering:

    The original code did:

      dialog->selected_interface = interface_find_by_rowid (rowid);

    Here is the equal code, setting up the filter manually:

       gxobject           gxobj;
       gxobject_ctx       gxctx;
       gxobject_db_filter gxfilter;
       gint               xa,xb;
       void               *arg[4];

       gxobj.ctx = &gxctx;				// address to context information 
       gxctx.type = OBJ_DB_INTERFACE;		// its a INTERFACE object
       gxctx.user = &gxfilter;			// address to filter
       gxfilter.method = OBJ_FIND_SINGLE;		// find ONE match
       gxfilter.args = &arg;			// address to filter array
       xa = OBJ_DB_TABLE_INTERFACE_ROWID;		// ROWID field in interface table
       xb = rowid;					//  should match with 'rowid' var.
       arg[0] = &xa;
       arg[1] = &xb;
       arg[2] = 0;					// null terminate array

       dialog->selected_interface = gxobject_db_find(&gxobj);

    Here is a example using a predefined filter:

       gxobj.ctx = &gxctx;
       gxctx.type = OBJ_DB_INTERFACE;
       gxctx.user = &db_find_by_rowid;		/* pointer filter to the predefined filter */

    Here we put new data, that will be searched for.

       *((gint *) db_find_by_rowid.args[0]) = OBJ_DB_TABLE_INTERFACE_ROWID;        /*set table to use */
       *((gint *) db_find_by_rowid.args[1]) = rowid;                               /* rowid in table to search for */

       dialog->selected_interface = gxobject_db_find(&gxobj);



2.1.2 gsqldb API

   This is the API that should be nearly compatible with the g_sqldb functions.
   API functions has a prefix of 'g_sqldb_'. 

2.1.3 Primitive API

   This has not been implemented. It should be a simple interface
   to provide database access.


3.1        API example with a simple client

   This section gives an example of how to use
   the Client API.

3.1.1 Include files and definitions

   The client application needs to include following files:

     #include <stdio.h>
     #include <glib.h>
     #include "debug.h"
     #include "gxsnmpdbc.h"
     #include "gxsnmpdb.h"
     #include "db_filters.h"

   Following needs to be defined:

     extern gxdb_tables db_tables;
     int debug_level;
     int dcsock;
     gchar packet[4000];
     gchar bufx[4000];

   Order of execution. The application must execute following
   block in order. Each step is explained with example code.

     Load configuration
     Load table-plugins
     Start table-plugins
     Connect to database daemon.
     User code with Client API
     Disconnect to database daemon.
     
   

   


Appendix A

  Packet layout

  Packet layout defines how the client API and the database daemon
  should exchange information. All information exchanged has a
  common packet layout.

    +-------+------+-------+---+------------+-----+
    |Action |Objlen|Objects|TPL|MemberRecord| ... |
    +-------+------+-------+---+------------+-----+
    <--- Header ---->

    Fig. An example of a packet to add a row in the 'host' table.

  First is the Header, that has a maximum size of 40 bytes.

  TAR is the command to add a row into a table. Objects is
  data. TPL is total packet length.
  MemberRecord is each field in the table.

Appendix B

  MemberRecord

  The MemberRecord is how the client API and the database daemon
  exchange data. This data is actually SQL field data that is
  inserted or processed into structures etc..
  This is how a MemberRecord looks like:

    +----------+------------+------------+
    |MemberLen | MemberType | MemberData |
    +----------+------------+------------+

  MemberLen is how long the whole MemberRecord is. MemberType
  identifies what type of data is containd in MemberData.
  Currently we have defined 32bit integer and ASCIIZ.

Appendix C

  Code documentation

  This section will describe how the code under gxsnmp/database works

C.1 Loading a table filtered

  The gxobject_load() function ( under dev ) will load a whole
  table into memory. If the contexts user pointer ( ctx->user ) is
  set to a filter, this filter will be used when loading.
  Here is a short description of how it works:
  gxobject_load() will lookup the right table plugin to use and
  calls the obj_load() function in the plugin.

  obj_load() checks if a filter is set. If that is true, it will
  convert the filter into memberrecords, with a packet header
  of TABLE_LOAD_FILTERED. Now it can send the packet to the
  database daemon. The DD will in turn call the same plugin
  to encode a proper SQL string, to send to the database.
  This is done with encode_sql function in plugin, with
  SQL_SELECT switch.
