orapig.png

OraPIG Configomat -- Configuration Generator

OraPIG Configomat takes configuration data stored in a database file and converts it into Python or C/C++ data structures. This data can be included in application programs to allow access to the global configuration without having to connect to the database. This provides the best of both worlds:

diagram:

.       database table --> python module --> python applications
.                      --> C/C++  module --> C/C++  applications

Specifying the Configuration Table

Just about any table can be converted by the configomat.

Let's look at an example table called "netservices". It's a configuration table for some hypothetical network service and has these columns:

       name : service name.  this is the primary key.
       host : hostname.
       port : ip port.
      admin : email of administrative contact.
description : description of the service.

and four rows of data:

 table:  netservices

 name     | host   | port | admin | description
----------+--------+------+-------+-----------------------------
 xmap     | ajax   | 2305 | steve | shared xmap validator
 qman     | ajax   | 1999 | bob   | queue manager
 thumbs01 | xerxes | 1022 | bob   | primary thumbnail server
 thumbs02 | ajax   | 1022 | bob   | secondary thumbnail server

Generating the Interfaces

The simplest commands to generate the Python and C/C++ interfaces are:

configomat --conn=orapig/orapig --table=netservices --lang=python
configomat --conn=orapig/orapig --table=netservices --lang=gperf

The only required parameters are the database connection string and the table name. Full command line detail appear below.

Contents of the Python Module

There are three things in the generated python module:

All data from the table is represented as strings, regardless of the column type in the table.

Using the Python Interface

To use the file, just import it in the usual manner:

>>> import netservices

keys is a list of all the keys. This is the data in the table's primary key:

>>> netservices.keys
['qman', 'thumbs01', 'thumbs02', 'xmap']

data is a dictonary indexed by the elements in keys:

>>> from pprint import pprint
>>> pprint(netservices.data)
{'qman': {'admin': 'bob',
          'description': 'queue manager',
          'host': 'ajax',
          'port': '1999'},
 'thumbs01': {'admin': 'bob',
              'description': 'primary thumbnail server',
              'host': 'xerxes',
              'port': '1022'},
 'thumbs02': {'admin': 'bob',
              'description': 'secondary thumbnail server',
              'host': 'ajax',
              'port': '1022'},
 'xmap': {'admin': 'steve',
          'description': 'shared xmap validator',
          'host': 'ajax',
          'port': '2305'}}

You can access a particular configuration record by subscripting with one the key names:

>>> pprint(netservices.data['xmap'])
{'admin': 'steve',
 'description': 'shared xmap validator',
 'host': 'ajax',
 'port': '2305'}

and access a particular field by subscripting again with the column name:

>>> netservices.data['xmap']['port']
'2305'

Contents of the C/C++ Module

(note, I'm still experimenting with this, so there might be minor changes. I'm also experimenting with gperf's C++ capabilities, so the C++ interface might expand to be a class.)

All data from the table is represented as strings, regardless of the column type in the table.

The configomat uses gnu gperf program, details below.

Using the C/C++ Interface

Include the generated header file:

#include "netservices.h"

netservices_keys is an array of all the keys:

int i;
int nkeys = sizeof(netservices_keys[0]) / sizeof(netservices_keys);
for (i = 0; i < nkeys; ++i)
    printf("%d. %s\n", i, netservices_keys[i]);

output:

1. qman
2. thumbs01
3. thumbs02
4. xmap

The functions netservices_gethost() and netservices_getport() will return the host and port parameters for the given key. Similar functions exist for each of the columns. They take one parameter which is the key, and return either a string or NULL if the key does not exist:

char *host = netservices_gethost("qman");
char *port = netservices_getport("arglebarg"); /*does not exist*/
if (host != NULL)
    printf("host: %s\n", host);
printf("port: %p\n", port);

output:

host: ajax
port: (nil)

To compile the test program, pass -DTEST to the compiler.

Running Configomat

The usage of OraPIG Configomat is:

configomat [options]

The command line options are:

--help, -h                   show this help message and exit
--conn=CONN, -C CONN         database connection string (required)
--table=TABLENAME            generate bindings for this table (required)
--lang=LANG                  language binding (currently gperf or python)
--output=OUTPUT, -O OUTPUT   output file, defaults to stdout
--pass=PASS, -P PASS         database password (not implemented)
--header=file, -H file       generate C/C++ header file
--dump dump parsed data and exit (for debugging)

Example Makefile

Here are some example Makefile entries:

config: netservices.py netservices.o

netservices.py:
  configomat.py --conn=orapig/orapig --table=netservices -O netservices.py

netservices.o:
  configomat.py --conn=orapig/orapig --table=netservices --lang=gperf -O netservices.gperf -H netservices.h
  gperf -t --ignore-case --output=netservices.c netservices.gperf
  $(CC) $(CFLAGS) -c netservices.c

test:
  configomat.py --conn=orapig/orapig --table=netservices --lang=gperf -O netservices.gperf -H netservices.h
  gperf -t --ignore-case --output=netservices.c netservices.gperf
  $(CC) $(CFLAGS) -DTEST netservices.c -o netservices-test
  ./netservices-test

clean:
  rm -f netservices.py netservices.pyc
  rm -f netservices.gperf netservices.h netservices.c netservices.o netservices-test

Gperf Note

The C/C++ bindingings use the Gnu perfect hash function generator gperf. Details, docs and downloads available here:

Administrivia

Configomat is part of OraPIG, the Oracle Python Interface Generator.

Version:

1.0

Download:

http://code.google.com/p/orapig

Documentation:

http://markharrison.net/orapig

Author:

Mark Harrison (mh@pixar.com)

License:

Copyright 2008 Pixar, available under a BSD license.

Support:

Send questions to the cx_Oracle mailing list. There's a link at: http://python.net/crew/atuining/cx_Oracle

Dependencies:

cx_Oracle, the Python interface for Oracle:

http://python.net/crew/atuining/cx_Oracle

The C/C++ language binding uses gperf, the gnu perfect hash generator:

http://www.gnu.org/software/gperf

Installation:

Configomat is a standalone script. Edit the #! line and put in an appropriate path.

OraPIG Motto:

"There's a Snake in my Oracle!"

This has been tested with Python 2.3 and 2.4, and Oracle 10.2.1.

Thanks

FAQs

  1. question

    answer

TODO