[rtg] Oracle driver
Brian T. O'Neill
btoneill at misplaced.net
Wed Jun 7 00:13:12 EDT 2006
Any idea on performance difference between Oracle and MySQL for this
type of data? We've been debating trying Oracle but haven't had time to
write the driver. Having a corporate license to run as many instances of
Oracle at no additional cost is a nice plus to giving it a shot for on
our side.
Brian
Quoting Leech, Jonathan (jleech at virtela.net) from :
> Here is the working code for an Oracle database, using OCI. It creates a connection pool with the same number of connections as RTG threads, but can be easily modified to use fewer connections.
>
> librtgoci.c
> ----------------------
> /*
> * RTG Oracle OCI database driver
> */
>
> #include "rtg.h"
> #include <oci.h>
> #include <sys/param.h>
>
> // thread-specific global variable
> pthread_key_t key;
>
> // only call the thread-specific variable setup once
> pthread_once_t once = PTHREAD_ONCE_INIT;
>
> // holds the config info for all the threads
> config_t *set;
>
> // Oracle handles
> static OCIError *errhp;
> static OCIEnv *envhp;
> static OCICPool *poolhp;
>
> // stores the Oracle connection pool name and length
> static OraText *poolName;
> static sb4 poolNameLen;
>
> /* Max,Min, and increment connections */
> static ub4 conMin = 1;
> static ub4 conIncr = 1;
>
> // log any Oracle errors
> void checkerr(errhp, status)
> OCIError *errhp;
> sword status;
> {
> text errbuf[512];
> sb4 errcode = 0;
>
> switch (status)
> {
> case OCI_SUCCESS:
> break;
> case OCI_SUCCESS_WITH_INFO:
> debug(LOW, "Error - OCI_SUCCESS_WITH_INFO\n");
> break;
> case OCI_NEED_DATA:
> debug(LOW, "Error - OCI_NEED_DATA\n");
> break;
> case OCI_NO_DATA:
> debug(LOW, "Error - OCI_NODATA\n");
> break;
> case OCI_ERROR:
> (void) OCIErrorGet((dvoid *)errhp, (ub4) 1, (text *) NULL, &errcode,
> errbuf, (ub4) sizeof(errbuf), OCI_HTYPE_ERROR);
> debug(LOW, "Error - %.*s\n", 512, errbuf);
> break;
> case OCI_INVALID_HANDLE:
> debug(LOW, "Error - OCI_INVALID_HANDLE\n");
> break;
> case OCI_STILL_EXECUTING:
> debug(LOW, "Error - OCI_STILL_EXECUTE\n");
> break;
> case OCI_CONTINUE:
> debug(LOW, "Error - OCI_CONTINUE\n");
> break;
> default:
> break;
> }
> }
>
> /* variable cleanup function */
> void killkey(void *target) {
> free(target);
>
> // destroy the connection pool
> checkerr(errhp, (sword)OCIConnectionPoolDestroy(poolhp, errhp, OCI_DEFAULT));
> checkerr(errhp, OCIHandleFree((dvoid *)poolhp, OCI_HTYPE_CPOOL));
> checkerr(errhp, OCIHandleFree((dvoid *)errhp, OCI_HTYPE_ERROR));
> }
>
> /* called when library loads */
> void __attribute__ ((constructor)) dl_init(void) {
> }
>
> /* this gets called once */
> void my_makekey() {
> /* this shouldn't fail, and we're too early on to report errors */
> pthread_key_create(&key, killkey);
>
> // create the connection pool
> OCIEnvCreate (&envhp, OCI_THREADED, (dvoid *)0, NULL, NULL, NULL, 0, (dvoid *)0);
>
> (void)OCIHandleAlloc((dvoid *)envhp, (dvoid**)&errhp, OCI_HTYPE_ERROR, (size_t)0, (dvoid **) 0);
>
> (void)OCIHandleAlloc((dvoid *) envhp, (dvoid **) &poolhp, OCI_HTYPE_CPOOL, (size_t) 0, (dvoid **) 0);
>
> checkerr(errhp, OCIConnectionPoolCreate(envhp,
> errhp, poolhp, &poolName, &poolNameLen,
> set->dbdb, (sb4)strlen((const signed char *)set->dbdb),
> conMin, set->threads, conIncr,
> set->dbuser, (sb4)strlen((const signed char *)set->dbuser),
> set->dbpass, (sb4)strlen((const signed char *)set->dbpass),
> OCI_DEFAULT)
> );
> OCIThreadProcessInit();
> checkerr(errhp, OCIThreadInit(envhp, errhp));
> }
>
> int __db_test() {
> return TRUE;
> }
>
> /*
> * check the status of the connection
> * we don't try and reconnect because this is sometimes used to confirm a disconnect
> */
> int __db_status() {
> sword lstat = OCI_SUCCESS;
> char buf[100];
>
> OCISvcCtx *svchp = pthread_getspecific(key);
> checkerr(errhp, lstat = OCIServerVersion(svchp, errhp, buf, 100, OCI_HTYPE_SVCCTX));
> if (lstat == OCI_SUCCESS) {
> return TRUE;
> } else {
> return FALSE;
> }
> }
>
> int __db_connect(config_t *config) {
> // initialize the key and connection pool once
> set = config;
> pthread_once(&once, my_makekey);
>
> // connect to Oracle
> OCISvcCtx *svchp = (OCISvcCtx *)0;
> checkerr(errhp, OCILogon2(envhp, errhp, &svchp,
> (CONST OraText *)config->dbuser, (ub4)strlen((const signed char *)config->dbuser),
> (CONST OraText *)config->dbpass, (ub4)strlen((const signed char *)config->dbpass),
> (CONST OraText *)poolName, (ub4)poolNameLen, OCI_CPOOL)
> );
>
> // store the Oracle session in thread-specific storage
> pthread_setspecific(key, svchp);
>
> return __db_status();
> }
>
> int __db_disconnect() {
> OCISvcCtx *svchp = pthread_getspecific(key);
> checkerr(errhp, OCILogoff((dvoid *) svchp, errhp));
> return TRUE;
> }
>
> int __db_insert(char *table, int iid, unsigned long long insert_val, double insert_rate) {
> char *query;
> OCISvcCtx *svchp = pthread_getspecific(key);
> OCIStmt *stmthp = (OCIStmt *)0;
> sword lstat;
>
> asprintf(&query, "INSERT INTO %s (id,dtime,counter) VALUES (%i,sysdate,%llu)", table, iid, insert_val);
>
> debug(HIGH, "Query = \"%s\"\n", query);
>
> OCIHandleAlloc(envhp, (dvoid **)&stmthp, OCI_HTYPE_STMT, (size_t)0, (dvoid **)0);
>
> checkerr(errhp, lstat = OCIStmtPrepare (stmthp, errhp, (CONST OraText *)query, (ub4)strlen((const signed char *)query), OCI_NTV_SYNTAX, OCI_DEFAULT));
>
> checkerr(errhp, lstat = OCIStmtExecute (svchp, stmthp, errhp, (ub4)1, (ub4)0, (OCISnapshot *)0, (OCISnapshot *)0, OCI_DEFAULT));
>
> checkerr(errhp, lstat = OCITransCommit(svchp, errhp, (ub4)0));
>
> checkerr(errhp, lstat = OCIHandleFree((dvoid *)stmthp, OCI_HTYPE_STMT));
>
> free(query);
>
> if (lstat == OCI_SUCCESS) {
> return TRUE;
> } else {
> return FALSE;
> }
> }
> _______________________________________________
> RTG mailing list
> RTG at fireflynetworks.net
> http://fireflynetworks.net/mailman/listinfo/rtg
--
btoneill at misplaced.net
****************************************************************************
UNIX is simple and coherent, but it takes a genius (or at any rate a
programmer) to understand and appreciate the simplicity." - Dennis Ritchie
****************************************************************************
More information about the RTG
mailing list