#include "sm.h"
#ifdef STORAGE_ORACLE
#include <string.h>
#include <oci.h>
typedef struct OracleDriver
{
OCIEnv *ociEnvironment;
OCIError *ociError;
OCISvcCtx *ociService;
OCIStmt *ociStatement;
OCIDefine *ociDefine;
OCIBind *ociBind;
xht filters;
char *prefix;
char *svUser;
char *svPass;
} *OracleDriverPointer;
#define BLOCKSIZE (1024)
static int _st_oracle_realloc(void **oblocks, int len)
{
void *nblocks;
int nlen;
nlen = (((len-1)/BLOCKSIZE)+1)*BLOCKSIZE;
while((nblocks = realloc(*oblocks, nlen)) == NULL) sleep(1);
*oblocks = nblocks;
return nlen;
}
#define ORACLE_SAFE(blocks, size, len) if((size) > len) len = _st_oracle_realloc((void**)&(blocks),(size));
int checkOCIError(st_driver_t drv, char *szDoing, OCIError *m_ociError, sword nStatus)
{
text txtErrorBuffer[512];
ub4 nErrorCode;
switch (nStatus)
{
case OCI_SUCCESS:
break;
case OCI_SUCCESS_WITH_INFO:
log_write(drv->st->sm->log, LOG_ERR, "(%s) Error - OCI_SUCCESS_WITH_INFO\n", szDoing);
break;
case OCI_NEED_DATA:
log_write(drv->st->sm->log, LOG_ERR, "(%s) Error - OCI_NEED_DATA\n", szDoing);
break;
case OCI_NO_DATA:
log_write(drv->st->sm->log, LOG_ERR, "(%s) Error - OCI_NODATA\n", szDoing);
break;
case OCI_ERROR:
OCIErrorGet(m_ociError, (ub4) 1, (text *) NULL, &nErrorCode, txtErrorBuffer, (ub4) sizeof(txtErrorBuffer), OCI_HTYPE_ERROR);
log_write(drv->st->sm->log, LOG_ERR, "(%s) Error - %s\n", szDoing, txtErrorBuffer);
break;
case OCI_INVALID_HANDLE:
log_write(drv->st->sm->log, LOG_ERR, "(%s) Error - OCI_INVALID_HANDLE\n", szDoing);
break;
case OCI_STILL_EXECUTING:
log_write(drv->st->sm->log, LOG_ERR, "(%s) Error - OCI_STILL_EXECUTE\n", szDoing);
break;
default:
break;
}
return nStatus;
}
int oracle_escape_string(char *dest, int dest_length, char *src, int src_length)
{
int result = 0;
char *src_end = src + src_length;
char *dest_end = dest + dest_length - 1;
while (src < src_end)
{
if (dest < dest_end)
{
static const char ESCAPED_STR[] = "'&";
if (strchr(ESCAPED_STR, *src) != NULL)
{
if (dest + 2 < dest_end)
{
*dest++ = '\'';
*dest++ = *src;
src++;
}
else
{
result = -1;
break;
}
}
else
{
*dest++ = *src++;
}
}
else
{
result = -1;
break;
}
}
*dest = '\0';
return result;
}
static int oracle_ping(st_driver_t drv)
{
OracleDriverPointer odpOracleDriver = (OracleDriverPointer)drv->private;
int nResultCode = OCIStmtPrepare(odpOracleDriver->ociStatement, odpOracleDriver->ociError,
"select sysdate from dual", (ub4) 24, OCI_NTV_SYNTAX,
OCI_DEFAULT);
nResultCode = OCIStmtExecute(odpOracleDriver->ociService, odpOracleDriver->ociStatement, odpOracleDriver->ociError,
(ub4) 0, (ub4) 0,
(CONST OCISnapshot *) NULL, (OCISnapshot *) NULL,
OCI_DESCRIBE_ONLY );
if (nResultCode != 0)
{
char szErrorBuffer[250];
char *svHost, *svUser, *svPass;
OCIErrorGet((dvoid *)odpOracleDriver->ociError, (ub4) 1, (text *) NULL, &nResultCode, szErrorBuffer, (ub4) sizeof(szErrorBuffer), OCI_HTYPE_ERROR);
log_write(drv->st->sm->log, LOG_ERR, "storage_oracle.c (oracle_ping): %s", szErrorBuffer);
svHost = config_get_one(drv->st->sm->config, "storage.oracle.host", 0);
svUser = config_get_one(drv->st->sm->config, "storage.oracle.user", 0);
svPass = config_get_one(drv->st->sm->config, "storage.oracle.pass", 0);
nResultCode = OCILogon((dvoid *)odpOracleDriver->ociEnvironment, (dvoid *)odpOracleDriver->ociError, &(odpOracleDriver->ociService), svUser, strlen(svUser), svPass, strlen(svPass), svHost, strlen(svHost));
if (nResultCode != 0)
{
OCIErrorGet((dvoid *)odpOracleDriver->ociError, (ub4) 1, (text *) NULL, &nResultCode, szErrorBuffer, (ub4) sizeof(szErrorBuffer), OCI_HTYPE_ERROR);
log_write(drv->st->sm->log, LOG_ERR, "storage_oracle.c (oracle_ping): %s", szErrorBuffer);
}
}
return nResultCode;
}
static void _st_oracle_convert_filter_recursive(st_filter_t f, char **buf, int *buflen, int *nbuf)
{
st_filter_t scan;
switch(f->type)
{
case st_filter_type_PAIR:
ORACLE_SAFE((*buf), *buflen + 12, *buflen);
*nbuf += sprintf(&((*buf)[*nbuf]), "( \"%s\" = \'%s\' ) ", f->key, f->val);
break;
case st_filter_type_AND:
ORACLE_SAFE((*buf), *buflen + 2, *buflen);
*nbuf += sprintf(&((*buf)[*nbuf]), "( ");
for(scan = f->sub; scan != NULL; scan = scan->next)
{
_st_oracle_convert_filter_recursive(scan, buf, buflen, nbuf);
if(scan->next != NULL)
{
ORACLE_SAFE((*buf), *buflen + 4, *buflen);
*nbuf += sprintf(&((*buf)[*nbuf]), "AND ");
}
}
ORACLE_SAFE((*buf), *buflen + 2, *buflen);
*nbuf += sprintf(&((*buf)[*nbuf]), ") ");
return;
case st_filter_type_OR:
ORACLE_SAFE((*buf), *buflen + 2, *buflen);
*nbuf += sprintf(&((*buf)[*nbuf]), "( ");
for(scan = f->sub; scan != NULL; scan = scan->next)
{
_st_oracle_convert_filter_recursive(scan, buf, buflen, nbuf);
if(scan->next != NULL)
{
ORACLE_SAFE((*buf), *buflen + 3, *buflen);
*nbuf += sprintf(&((*buf)[*nbuf]), "OR ");
}
}
ORACLE_SAFE((*buf), *buflen + 2, *buflen);
*nbuf += sprintf(&((*buf)[*nbuf]), ") ");
return;
case st_filter_type_NOT:
ORACLE_SAFE((*buf), *buflen + 6, *buflen);
*nbuf += sprintf(&((*buf)[*nbuf]), "( NOT ");
_st_oracle_convert_filter_recursive(f->sub, buf, buflen, nbuf);
ORACLE_SAFE((*buf), *buflen + 2, *buflen);
*nbuf += sprintf(&((*buf)[*nbuf]), ") ");
return;
}
}
static char *_st_oracle_convert_filter(st_driver_t drv, char *owner, char *filter)
{
OracleDriverPointer data = (OracleDriverPointer) drv->private;
char *buf = NULL, *sbuf = NULL, *cfilter;
int buflen = 0, nbuf = 0, fbuf;
st_filter_t f;
ORACLE_SAFE(buf, 24 + strlen(owner), buflen);
nbuf = sprintf(buf, "\"collection-owner\" = '%s'", owner);
sbuf = xhash_get(data->filters, filter);
if(sbuf != NULL)
{
ORACLE_SAFE(buf, buflen + strlen(sbuf) + 7, buflen);
nbuf += sprintf(&buf[nbuf], " AND %s", sbuf);
return buf;
}
cfilter = pstrdup(xhash_pool(data->filters), filter);
f = storage_filter(filter);
if(f == NULL)
{
return buf;
}
ORACLE_SAFE(buf, buflen + 5, buflen);
nbuf += sprintf(&buf[nbuf], " AND ");
fbuf = nbuf;
_st_oracle_convert_filter_recursive(f, &buf, &buflen, &nbuf);
xhash_put(data->filters, cfilter, pstrdup(xhash_pool(data->filters), &buf[fbuf]));
pool_free(f->p);
return buf;
}
static st_ret_t _st_oracle_add_type(st_driver_t drv, char *type)
{
return st_SUCCESS;
}
static st_ret_t _st_oracle_put_guts(st_driver_t drv, char *type, char *owner, os_t os)
{
static const char STR_PREFIX[] = "STR";
static const char NAD_PREFIX[] = "NAD";
OracleDriverPointer data = (OracleDriverPointer) drv->private;
char *left = NULL, *right = NULL;
int lleft = 0, lright = 0, nleft, nright;
os_object_t o;
char *key = NULL, *cval = NULL;
int cval_len;
dvoid *val = NULL;
os_type_t ot;
char *xml = NULL;
int xlen;
char tbuf[128];
int nResultCode = 0;
if(os_count(os) == 0)
{
return st_SUCCESS;
}
if(data->prefix != NULL)
{
snprintf(tbuf, sizeof(tbuf), "%s%s", data->prefix, type);
type = tbuf;
}
if(os_iter_first(os))
{
do
{
ORACLE_SAFE(left, strlen(type) + 36, lleft);
nleft = sprintf(left, "INSERT INTO \"%s\" ( \"collection-owner\"", type);
ORACLE_SAFE(right, strlen(owner) + 15, lright);
nright = sprintf(right, " ) VALUES ( '%s'", owner);
o = os_iter_object(os);
if(os_object_iter_first(o))
{
do
{
os_object_iter_get(o, &key, &val, &ot);
switch(ot)
{
case os_type_BOOLEAN:
cval = val ? strdup("1") : strdup("0");
break;
case os_type_INTEGER:
cval = (char *) malloc(sizeof(char) * 20);
sprintf(cval, "%d", (int) val);
strlen(cval);
break;
case os_type_STRING:
cval_len = (strlen((char *) val) * 2) + 1;
cval = (char *) malloc(cval_len);
oracle_escape_string(cval , cval_len, (char *) val, strlen(val));
break;
case os_type_NAD:
nad_print((nad_t) val, 0, &xml, &xlen);
cval_len = (xlen * 2) + sizeof (NAD_PREFIX);
cval = (char *) malloc(cval_len);
memcpy(cval, NAD_PREFIX, sizeof (NAD_PREFIX) - 1);
oracle_escape_string(cval + sizeof (NAD_PREFIX) - 1,
cval_len - sizeof (NAD_PREFIX) + 1, (char *) xml, xlen);
break;
}
log_debug(ZONE, "key %s val %s", key, cval);
ORACLE_SAFE(left, lleft + strlen(key) + 4, lleft);
nleft += sprintf(&left[nleft], ", \"%s\"", key);
ORACLE_SAFE(right, lright + strlen(cval) + 4, lright);
nright += sprintf(&right[nright], ", '%s'", cval);
free(cval);
} while(os_object_iter_next(o));
ORACLE_SAFE(left, lleft + strlen(right) + 2, lleft);
sprintf(&left[nleft], "%s )", right);
log_debug(ZONE, "_st_oracle_put_guts: Generated SQL: %s", left);
nResultCode = checkOCIError(drv, "oracle_put_guts: Prepare", data->ociError, OCIStmtPrepare(data->ociStatement, data->ociError, left,
(ub4) strlen(left), OCI_NTV_SYNTAX, OCI_DEFAULT));
if (nResultCode != 0)
{
free(left);
free(right);
return st_FAILED;
}
nResultCode = checkOCIError(drv, "oracle_put_guts: Execute", data->ociError, OCIStmtExecute(data->ociService, data->ociStatement,
data->ociError, (ub4) 1, (ub4) 0,
(CONST OCISnapshot *) NULL, (OCISnapshot *) NULL,
OCI_DEFAULT | OCI_COMMIT_ON_SUCCESS));
if (nResultCode != 0)
{
free(left);
free(right);
return st_FAILED;
}
}
} while(os_iter_next(os));
}
free(left);
free(right);
return st_SUCCESS;
}
static st_ret_t _st_oracle_put(st_driver_t drv, char *type, char *owner, os_t os)
{
if( !owner ) {
log_debug(ZONE,"_st_oracle_put: owner is null");
return st_FAILED;
}
if(os_count(os) == 0)
{
return st_SUCCESS;
}
if(oracle_ping(drv) != 0)
{
log_write(drv->st->sm->log, LOG_ERR, "oracle: connection to database lost");
return st_FAILED;
}
if(_st_oracle_put_guts(drv, type, owner, os) != st_SUCCESS)
{
return st_FAILED;
}
return st_SUCCESS;
}
static st_ret_t _st_oracle_get(st_driver_t drv, char *a_szType, char *owner, char *filter, os_t *os)
{
OracleDriverPointer data = (OracleDriverPointer) drv->private;
os_object_t o;
os_type_t ot;
char szBuffer[128];
char *szWhereClause = NULL;
char *szQuery = NULL;
int nQueryLength = 0;
int nResultCode = 0;
int nNumberOfFields = 0;
int nIndex = 0;
if( !owner ) {
log_debug(ZONE,"_st_oracle_get: owner is null");
return st_FAILED;
}
if(oracle_ping(drv) != 0)
{
log_write(drv->st->sm->log, LOG_ERR, "_st_oracle_get: Connection to database lost!");
return st_FAILED;
}
if(data->prefix != NULL)
{
snprintf(szBuffer, sizeof(szBuffer), "%s%s", data->prefix, a_szType);
a_szType = szBuffer;
}
szWhereClause = _st_oracle_convert_filter(drv, owner, filter);
log_debug(ZONE, "_st_oracle_get: Generated Filter: %s", szWhereClause);
ORACLE_SAFE(szQuery, strlen(a_szType) + strlen(szWhereClause) + 50, nQueryLength);
sprintf(szQuery, "SELECT * FROM \"%s\" WHERE %s ORDER BY \"object-sequence\"", a_szType, szWhereClause);
free(szWhereClause);
log_debug(ZONE, "_st_oracle_get: Prepared SQL: %s", szQuery);
nResultCode = checkOCIError(drv, "_st_oracle_get: Prepare Statement", data->ociError, OCIStmtPrepare(data->ociStatement, data->ociError,
szQuery, (ub4)strlen(szQuery), OCI_NTV_SYNTAX,
OCI_DEFAULT));
if (nResultCode != 0)
{
free(szQuery);
return st_FAILED;
}
nResultCode = checkOCIError(drv, "_st_oracle_get: Statement Describe", data->ociError, OCIStmtExecute(data->ociService,
data->ociStatement, data->ociError, (ub4)0,
(ub4)0, (CONST OCISnapshot *)NULL,
(OCISnapshot *)NULL, OCI_DESCRIBE_ONLY));
if (nResultCode != 0)
{
free(szQuery);
return st_FAILED;
}
free(szQuery);
nResultCode = OCI_SUCCESS;
checkOCIError(drv, "_st_oracle_get: Get Field Count", data->ociError, OCIAttrGet(data->ociStatement, OCI_HTYPE_STMT,
(dvoid *)&nNumberOfFields, (ub4 *)NULL, OCI_ATTR_PARAM_COUNT,
data->ociError));
if (nNumberOfFields == 0)
{
return st_NOTFOUND;
}
else
{
OCIDefine *arrFields[nNumberOfFields];
char arrszFieldData[nNumberOfFields][4001];
char arrszFieldName[nNumberOfFields][255];
ub2 arrnFieldType[nNumberOfFields];
sb2 arrnFieldIndicator[nNumberOfFields];
int arrnFieldSize[nNumberOfFields];
char *svFieldName;
int nNameSize;
int nIntValue;
nad_t nad;
for (nIndex = 0; nIndex < nNumberOfFields; nIndex++)
{
arrFields[nIndex] = NULL;
checkOCIError(drv, "_st_oracle_get: Get Parameter", data->ociError, OCIParamGet(data->ociStatement, OCI_HTYPE_STMT, data->ociError,
(dvoid **) &arrFields[nIndex], (ub4) (nIndex + 1)));
checkOCIError(drv, "_st_oracle_get: Get Field Name", data->ociError, OCIAttrGet(arrFields[nIndex], OCI_DTYPE_PARAM,
(dvoid *) &svFieldName, &nNameSize,
OCI_ATTR_NAME, data->ociError));
strncpy(arrszFieldName[nIndex], svFieldName, nNameSize);
arrszFieldName[nIndex][nNameSize] = '\0';
arrnFieldType[nIndex] = 0;
checkOCIError(drv, "_st_oracle_get: Get Field Type", data->ociError, OCIAttrGet(arrFields[nIndex], OCI_DTYPE_PARAM,
(dvoid *) &arrnFieldType[nIndex], (ub4 *) NULL,
(ub4) OCI_ATTR_DATA_TYPE, data->ociError));
checkOCIError(drv, "_st_oracle_get: Get Field Size", data->ociError, OCIAttrGet(arrFields[nIndex], OCI_DTYPE_PARAM,
(dvoid *) &arrnFieldSize[nIndex], (ub4 *) NULL,
(ub4) OCI_ATTR_DATA_SIZE, data->ociError));
if (arrnFieldSize[nIndex] > 4000 || arrnFieldSize[nIndex] < 1)
{
arrnFieldSize[nIndex] = 4000;
}
checkOCIError(drv, "_st_oracle_get: Define String", data->ociError, OCIDefineByPos(data->ociStatement, &arrFields[nIndex],
data->ociError, (nIndex + 1), (dvoid *)&arrszFieldData[nIndex],
4000, SQLT_STR, &arrnFieldIndicator[nIndex],
(ub2 *) 0, (ub2 *) 0, OCI_DEFAULT));
}
nResultCode = OCIStmtExecute(data->ociService, data->ociStatement, data->ociError, (ub4) 1, (ub4) 0, (CONST OCISnapshot *) NULL,
(OCISnapshot *) NULL, OCI_DEFAULT);
if (nResultCode == OCI_SUCCESS || nResultCode == OCI_SUCCESS_WITH_INFO)
{
for (nIndex = 0; nIndex < nNumberOfFields; nIndex++)
{
if (arrnFieldIndicator[nIndex] == -1)
{
arrszFieldData[nIndex][0] = '\0';
}
}
}
else if (nResultCode != OCI_NO_DATA)
{
checkOCIError(drv, "_st_oracle_get: Execute Statement", data->ociError, nResultCode);
return st_FAILED;
}
if (nResultCode == OCI_NO_DATA)
{
return st_NOTFOUND;
}
*os = os_new();
while (nResultCode != OCI_NO_DATA)
{
o = os_object_new(*os);
for (nIndex = 0; nIndex < nNumberOfFields; nIndex++)
{
if(strcmp(arrszFieldName[nIndex], "collection-owner") == 0 || strcmp(arrszFieldName[nIndex], "object-sequence") == 0)
{
continue;
}
if (arrszFieldData[nIndex][0] == '\0')
{
continue;
}
switch(arrnFieldType[nIndex])
{
case SQLT_CHR:
if (arrnFieldSize[nIndex] > 2)
{
log_debug(ZONE, "Field %s is Field Type SQLT_CHR of Size %d, setting os_type_STRING", arrszFieldName[nIndex], arrnFieldSize[nIndex]);
ot = os_type_STRING;
}
else
{
log_debug(ZONE, "Field %s is Field Type SQLT_CHR of Size %d, setting os_type_BOOLEAN", arrszFieldName[nIndex], arrnFieldSize[nIndex]);
ot = os_type_BOOLEAN;
}
break;
case SQLT_AFC:
if (arrnFieldSize[nIndex] > 2)
{
log_debug(ZONE, "Field %s is Field Type SQLT_AFC of Size %d, setting os_type_STRING", arrszFieldName[nIndex], arrnFieldSize[nIndex]);
ot = os_type_STRING;
}
else
{
log_debug(ZONE, "Field %s is Field Type SQLT_AFC of Size %d, setting os_type_BOOLEAN", arrszFieldName[nIndex], arrnFieldSize[nIndex]);
ot = os_type_BOOLEAN;
}
break;
case SQLT_NUM:
log_debug(ZONE, "Field %s is Field Type SQLT_NUM of Size %d", arrszFieldName[nIndex], arrnFieldSize[nIndex]);
ot = os_type_INTEGER;
break;
default:
log_debug(ZONE, "Unknown field type %d, for column %s ignoring it", arrnFieldType[nIndex], arrszFieldName[nIndex]);
continue;
}
switch(ot)
{
case os_type_BOOLEAN:
nIntValue = (arrszFieldData[nIndex][0] == '0') ? 0 : 1;
os_object_put(o, arrszFieldName[nIndex], &nIntValue, ot);
break;
case os_type_INTEGER:
nIntValue = atoi(arrszFieldData[nIndex]);
os_object_put(o, arrszFieldName[nIndex], &nIntValue, ot);
break;
case os_type_STRING:
if(strlen(arrszFieldData[nIndex]) >= 3 && strncmp(arrszFieldData[nIndex], "NAD", 3) == 0)
{
if(strlen(arrszFieldData[nIndex]) == 3)
{
log_write(drv->st->sm->log, LOG_ERR, "Found XML cell with no XML content; table=%s, owner=%s", a_szType, owner);
os_free(*os);
return st_FAILED;
}
nad = nad_parse(drv->st->sm->router->nad_cache, &arrszFieldData[nIndex][3], strlen(arrszFieldData[nIndex]) - 3);
if(nad == NULL)
{
log_write(drv->st->sm->log, LOG_ERR, "Found XML cell with unparseable XML content; table=%s, owner=%s", a_szType, owner);
log_write(drv->st->sm->log, LOG_ERR, "Unparseable Content: %s", &arrszFieldData[nIndex][3]);
os_free(*os);
return st_FAILED;
}
os_object_put(o, arrszFieldName[nIndex], nad, os_type_NAD);
}
else
{
int offset;
if(strlen(arrszFieldData[nIndex]) >= 3 && strncmp(arrszFieldData[nIndex], "STR", 3) == 0)
{
offset = 3;
}
else
{
offset = 0;
}
os_object_put(o, arrszFieldName[nIndex], arrszFieldData[nIndex + offset], os_type_STRING);
}
break;
case os_type_NAD:
break;
}
}
log_debug(ZONE, "Get Next Row.");
nResultCode = OCIStmtFetch2(data->ociStatement, data->ociError, 1, OCI_DEFAULT, 0, OCI_DEFAULT);
if (nResultCode == OCI_SUCCESS || nResultCode == OCI_SUCCESS_WITH_INFO)
{
for (nIndex = 0; nIndex < nNumberOfFields; nIndex++)
{
if (arrnFieldIndicator[nIndex] == -1)
{
arrszFieldData[nIndex][0] = '\0';
}
}
}
else if (nResultCode != OCI_NO_DATA)
{
checkOCIError(drv, "_st_oracle_get: Fetch Next Row", data->ociError, nResultCode);
break;
}
}
}
return st_SUCCESS;
}
static st_ret_t _st_oracle_delete(st_driver_t drv, char *type, char *owner, char *filter)
{
OracleDriverPointer data = (OracleDriverPointer) drv->private;
char *cond, *buf = NULL;
int buflen = 0;
int nResultCode = 0;
char tbuf[128];
if(oracle_ping(drv) != 0)
{
log_write(drv->st->sm->log, LOG_ERR, "oracle: Connection to database lost");
return st_FAILED;
}
if(data->prefix != NULL)
{
snprintf(tbuf, sizeof(tbuf), "%s%s", data->prefix, type);
type = tbuf;
}
cond = _st_oracle_convert_filter(drv, owner, filter);
log_debug(ZONE, "oracle: Generated filter: %s", cond);
ORACLE_SAFE(buf, strlen(type) + strlen(cond) + 19, buflen);
sprintf(buf, "DELETE FROM \"%s\" WHERE %s", type, cond);
free(cond);
log_debug(ZONE, "_st_oracle_delete: Prepared SQL: %s", buf);
nResultCode = checkOCIError(drv, "_st_oracle_delete: Prepare", data->ociError, OCIStmtPrepare(data->ociStatement, data->ociError, buf,
(ub4) strlen(buf), OCI_NTV_SYNTAX, OCI_DEFAULT));
if (nResultCode != 0)
{
free(buf);
return st_FAILED;
}
log_debug(ZONE, "_st_oracle_delete: Executing Delete.");
nResultCode = checkOCIError(drv, "_st_oracle_delete: Execute", data->ociError, OCIStmtExecute(data->ociService, data->ociStatement,
data->ociError, (ub4) 1, (ub4) 0, (CONST OCISnapshot *) NULL,
(OCISnapshot *) NULL, OCI_DEFAULT | OCI_COMMIT_ON_SUCCESS));
free(buf);
log_debug(ZONE, "Result query: %d",nResultCode);
if(nResultCode != 0)
{
return st_FAILED;
}
return st_SUCCESS;
}
static st_ret_t _st_oracle_replace(st_driver_t drv, char *type, char *owner, char *filter, os_t os)
{
if(oracle_ping(drv) != 0)
{
log_write(drv->st->sm->log, LOG_ERR, "oracle: connection to database lost");
return st_FAILED;
}
if(_st_oracle_delete(drv, type, owner, filter) == st_FAILED)
{
return st_FAILED;
}
if(_st_oracle_put_guts(drv, type, owner, os) == st_FAILED)
{
return st_FAILED;
}
return st_SUCCESS;
}
static void _st_oracle_free(st_driver_t drv) {
OracleDriverPointer data = (OracleDriverPointer) drv->private;
OCILogoff(data->ociService, data->ociError);
OCIHandleFree((dvoid *) data->ociStatement, OCI_HTYPE_STMT);
OCIHandleFree((dvoid *) data->ociService, OCI_HTYPE_SVCCTX);
OCIHandleFree((dvoid *) data->ociError, OCI_HTYPE_ERROR);
OCIHandleFree((dvoid *) data->ociEnvironment, OCI_HTYPE_ENV);
xhash_free(data->filters);
free(data->prefix);
free(data);
}
st_ret_t st_oracle_init(st_driver_t drv)
{
int nResultCode;
char *svHost, *svUser, *svPass;
OCIEnv *ociEnvironment;
OCIError *ociError;
OCISvcCtx *ociService;
OCIStmt *ociStatement;
OracleDriverPointer data;
svHost = config_get_one(drv->st->sm->config, "storage.oracle.host", 0);
svUser = config_get_one(drv->st->sm->config, "storage.oracle.user", 0);
svPass = config_get_one(drv->st->sm->config, "storage.oracle.pass", 0);
if(svHost == NULL || svUser == NULL || svPass == NULL)
{
log_write(drv->st->sm->log, LOG_ERR, "(st_oracle_init: ) Invalid driver config from XML file.");
return st_FAILED;
}
nResultCode = OCIInitialize((ub4) OCI_DEFAULT, (dvoid *)0, (dvoid * (*)(dvoid *, size_t))0, (dvoid * (*)(dvoid *, dvoid *, size_t))0, (void (*)(dvoid *, dvoid *)) 0);
if (nResultCode != 0)
{
log_write(drv->st->sm->log, LOG_ERR, "(st_oracle_init: ) Could not Initialize OCI (%d)", nResultCode);
return st_FAILED;
}
nResultCode = OCIEnvInit((OCIEnv **) &ociEnvironment, OCI_DEFAULT, (size_t) 0, (dvoid **) 0);
if (nResultCode != 0)
{
log_write(drv->st->sm->log, LOG_ERR, "(st_oracle_init: ) Could not Initialize OCI Environment (%d)", nResultCode);
return st_FAILED;
}
nResultCode = OCIHandleAlloc((dvoid *) ociEnvironment, (dvoid **) &ociError, OCI_HTYPE_ERROR, (size_t) 0, (dvoid **) 0);
if (nResultCode != 0)
{
log_write(drv->st->sm->log, LOG_ERR, "(st_oracle_init: ) Could not create OCI Error object (%d)" , nResultCode);
nResultCode = OCIHandleFree((dvoid *) ociEnvironment, OCI_HTYPE_ENV);
return st_FAILED;
}
nResultCode = checkOCIError(drv, "st_oracle_init: Allocate Service", ociError, OCIHandleAlloc((dvoid *) ociEnvironment,
(dvoid **)&ociService, OCI_HTYPE_SVCCTX,
(size_t)NULL, (dvoid **)NULL));
if (nResultCode != 0)
{
nResultCode = OCIHandleFree((dvoid *) ociError, OCI_HTYPE_ERROR);
nResultCode = OCIHandleFree((dvoid *) ociEnvironment, OCI_HTYPE_ENV);
return st_FAILED;
}
nResultCode = checkOCIError(drv, "st_oracle_init: Connect to Server", ociError, OCILogon(ociEnvironment, ociError, &ociService,
svUser, strlen(svUser), svPass, strlen(svPass),
svHost, strlen(svHost)));
if (nResultCode != 0)
{
nResultCode = OCIHandleFree((dvoid *) ociService, OCI_HTYPE_SVCCTX);
nResultCode = OCIHandleFree((dvoid *) ociError, OCI_HTYPE_ERROR);
nResultCode = OCIHandleFree((dvoid *) ociEnvironment, OCI_HTYPE_ENV);
return st_FAILED;
}
nResultCode = checkOCIError(drv, "st_oracle_init: Allocate Statement", ociError, OCIHandleAlloc((dvoid *)ociEnvironment,
(dvoid **)&ociStatement, OCI_HTYPE_STMT,
(size_t)NULL, (dvoid **)NULL));
if (nResultCode != 0)
{
nResultCode = OCILogoff(ociService, ociError);
nResultCode = OCIHandleFree((dvoid *) ociService, OCI_HTYPE_SVCCTX);
nResultCode = OCIHandleFree((dvoid *) ociError, OCI_HTYPE_ERROR);
nResultCode = OCIHandleFree((dvoid *) ociEnvironment, OCI_HTYPE_ENV);
return st_FAILED;
}
data = (OracleDriverPointer) malloc(sizeof(struct OracleDriver));
memset(data, 0, sizeof(struct OracleDriver));
data->ociEnvironment = ociEnvironment;
data->ociError = ociError;
data->ociService = ociService;
data->ociStatement = ociStatement;
data->ociDefine = NULL;
data->ociBind = NULL;
data->svUser = svUser;
data->svPass = svPass;
data->filters = xhash_new(17);
data->prefix = config_get_one(drv->st->sm->config, "storage.oracle.prefix", 0);
drv->private = (void *) data;
drv->add_type = _st_oracle_add_type;
drv->put = _st_oracle_put;
drv->get = _st_oracle_get;
drv->delete = _st_oracle_delete;
drv->replace = _st_oracle_replace;
drv->free = _st_oracle_free;
return st_SUCCESS;
}
#endif