📄 sqlora.c
字号:
#ifdef HAVE_STRDUP
/* Sometimes strdup is not defined in strict ansi mode,
* even if it is in libc
*/
extern char * strdup __P((const char *s));
#else
/**
* strdup if not available on the target system
* @param s I - The string to duplicate
* @return The newly allocated string.
*/
char * DEFUN(strdup, (s), const char * s)
{
char *n;
n = (char *) MALLOC(sizeof(char) * (strlen(s) + 1) );
TRACE(4, fprintf(_trace_fp,"strdup: Allocated %d bytes\n", (strlen(s) + 1)););
if (n)
strcpy(n, s);
return(n);
}
#endif
/*---------------------------------------------------------------------------
Parameters (Can be changed by environment variables or sqlo_set)
Naming conventions of environment variables:
SQLORA_ || upper(<param_name>)
---------------------------------------------------------------------------*/
/* Parameters, sort them by name */
static sqlora_param_t g_params[] = {
{"PREFETCH_ROWS", INTEGER, (VOID *)&_num_prefetch_rows, NULL},
{"LONGSIZE", INTEGER, (VOID *)&_max_long_size, NULL},
{"TRACE_FILE", STRING, _trace_file, NULL},
{"TRACE_LEVEL", INTEGER, &_trace_level, NULL},
{NULL, INTEGER, NULL, NULL}
};
/*-------------------------------------------------------------------------
* STATIC FUNCTIONS
*-----------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*/
/**
* Inits all mutexes.
* @returns OCI status.
*/
#if CC_PRAGMA_INLINE
#pragma INLINE _init_mutexes
#endif
static inline int
DEFUN_VOID(_init_mutexes)
{
int status = SQLO_SUCCESS;
#ifdef ENABLE_PTHREADS
pthread_mutex_init(&_dbv_mux, NULL);
pthread_mutex_init(&_stmtv_mux, NULL);
pthread_mutex_init(&_env_mux, NULL);
#elif ENABLE_ORATHREADS
status = (OCIThreadMutexInit(_oci_envhp, _oci_errhp, &_dbv_mux) ||
OCIThreadMutexInit(_oci_envhp, _oci_errhp, &_stmtv_mux) ||
OCIThreadMutexInit(_oci_envhp, _oci_errhp, &_env_mux) );
#endif
return status;
}
/*-------------------------------------------------------------------------*/
/**
* Lock @ref _env_mux
* @return OCI status
*/
#if CC_PRAGMA_INLINE
#pragma INLINE _env_lock
#endif
static inline int
DEFUN_VOID(_env_lock)
{
#ifdef ENABLE_PTHREADS
pthread_mutex_lock(&_env_mux);
#elif ENABLE_ORATHREADS
return(OCIThreadMutexAcquire(_oci_envhp, _oci_errhp, _env_mux));
#endif
return OCI_SUCCESS;
}
/*-------------------------------------------------------------------------*/
/**
* Unlock @ref _env_mux.
* @return OCI status
*/
#if CC_PRAGMA_INLINE
#pragma INLINE _env_unlock
#endif
static inline int
DEFUN_VOID(_env_unlock)
{
#ifdef ENABLE_PTHREADS
pthread_mutex_unlock(&_env_mux);
#elif ENABLE_ORATHREADS
return (OCIThreadMutexRelease(_oci_envhp, _oci_errhp, _env_mux));
#endif
return(OCI_SUCCESS);
}
/*-------------------------------------------------------------------------*/
/**
* Lock @ref _dbv
* @return OCI status
*/
#if CC_PRAGMA_INLINE
#pragma INLINE _dbv_lock
#endif
static inline int
DEFUN_VOID(_dbv_lock)
{
#ifdef ENABLE_PTHREADS
pthread_mutex_lock(&_dbv_mux);
#elif ENABLE_ORATHREADS
return(OCIThreadMutexAcquire(_oci_envhp, _oci_errhp, _dbv_mux));
#endif
return OCI_SUCCESS;
}
/*-------------------------------------------------------------------------*/
/**
* Unlock @ref _dbv.
* @return OCI status
*/
#if CC_PRAGMA_INLINE
#pragma INLINE _dbv_unlock
#endif
static inline int
DEFUN_VOID(_dbv_unlock)
{
#ifdef ENABLE_PTHREADS
pthread_mutex_unlock(&_dbv_mux);
#elif ENABLE_ORATHREADS
return (OCIThreadMutexRelease(_oci_envhp, _oci_errhp, _dbv_mux));
#endif
return(OCI_SUCCESS);
}
/*-------------------------------------------------------------------------*/
/**
* Lock @ref _stmtv
* @return OCI status
*/
#if CC_PRAGMA_INLINE
#pragma INLINE _stmtv_lock
#endif
static inline int
DEFUN_VOID(_stmtv_lock)
{
#ifdef ENABLE_PTHREADS
pthread_mutex_lock(&_stmtv_mux);
#elif ENABLE_ORATHREADS
return (OCIThreadMutexAcquire(_oci_envhp, _oci_errhp, _stmtv_mux));
#endif
return(OCI_SUCCESS);
}
/*-------------------------------------------------------------------------*/
/**
* Unlock @ref _stmtv.
* @return OCI status
*/
#if CC_PRAGMA_INLINE
#pragma INLINE _stmtv_unlock
#endif
static inline int
DEFUN_VOID(_stmtv_unlock)
{
#ifdef ENABLE_PTHREADS
pthread_mutex_unlock(&_stmtv_mux);
#elif ENABLE_ORATHREADS
return (OCIThreadMutexRelease(_oci_envhp, _oci_errhp, _stmtv_mux));
#endif
return(OCI_SUCCESS);
}
/*-------------------------------------------------------------------------*/
/**
* Sets the attribute PREFETCH_ROWS.
* @param stp I - statement pointer
* @param nrows I - Number of rows to prefetch
* @return OCI status code
*/
#if CC_PRAGMA_INLINE
#pragma INLINE _set_prefetch_rows
#endif
static inline int
DEFUN(_set_prefetch_rows, (stp, nrows),
sqlo_stmt_ptr_t stp AND
unsigned int nrows)
{
unsigned int prefetch_rows = nrows;
int status;
status = OCIAttrSet((dvoid*)stp->stmthp,
(ub4)OCI_HTYPE_STMT,
&prefetch_rows,
(ub4) sizeof(prefetch_rows),
(ub4)OCI_ATTR_PREFETCH_ROWS,
stp->dbp->errhp);
return(status);
}
/*-------------------------------------------------------------------------*/
/**
* Gets the statement text and puts it into stp->stmt.
*
* @param stp I - statement pointer
* @return OCI status code
*/
#if CC_PRAGMA_INLINE
#pragma INLINE _get_stmt_string
#endif
static inline const char *
DEFUN(_get_stmt_string, (stp),
sqlo_stmt_ptr_t stp
)
{
static const char *nostmt = "_get_stmt_string: No statement avalailable";
if (!stp->stmt)
return(nostmt);
return stp->stmt;
}
/*-------------------------------------------------------------------------*/
/**
* Gets the statement state
*
* @param stp I - statement pointer
* @return The statement state or -1 on error.
*/
#if CC_PRAGMA_INLINE
#pragma INLINE _get_stmt_state
#endif
static inline int
DEFUN(_get_stmt_state, (stp),
sqlo_stmt_ptr_t stp
)
{
int status;
ub4 st = 0;
/* OCI_ATTR_STMT_STATE is not defined in Oracle < 9i
* I define this here, to make it compile with Oracle 8,8i,
* but nobody should call this
* function
*/
#ifndef OCI_ATTR_STMT_STATE
#define OCI_ATTR_STMT_STATE 182
#endif
if( (status = OCIAttrGet((dvoid*)stp->stmthp,
(ub4)OCI_HTYPE_STMT,
(dvoid *)&st,
(ub4 *) 0,
(ub4)OCI_ATTR_STMT_STATE,
stp->dbp->errhp)))
return (status);
return ((int)st);
}
/*-------------------------------------------------------------------------*/
/**
* Adds a new database entry to @ref _dbv[].
* Alllocates a new entry entry if necessary, or reuses an old one.
* @return The pointer to the entry. The entry is marked used.
*/
static sqlo_db_ptr_t
DEFUN_VOID(_db_add)
{
register unsigned int dbv_idx;
unsigned int first_null_idx; /* first null slot */
bool_t first_null_idx_set; /* Flag indicates that first_null_idx is valid */
bool_t found_free;
unsigned int free_idx;
TRACE(4, fprintf(_trace_fp, "_db_add starts _dbv_size=%u\n", _dbv_size););
/* check for initialization */
if ((! _sqlo_init) || (_dbv_size <= 0))
return (NULL) ;
EXEC_WHEN_THREADING(_dbv_lock();); /* start of critical section */
/* we need to check first if there is an unused allocated slot */
found_free = FALSE;
first_null_idx_set = FALSE;
free_idx = 0;
first_null_idx = 0;
for (dbv_idx = 0; dbv_idx < _dbv_size; ++dbv_idx) {
if ((_dbv[ dbv_idx ]) && (! _dbv[ dbv_idx ]->used)) { /* free slot found */
free_idx = dbv_idx;
found_free = TRUE;
break ;
} else if ( !first_null_idx_set && !_dbv[ dbv_idx ]) {
first_null_idx = dbv_idx;
first_null_idx_set = TRUE;
}
}
TRACE(4, fprintf(_trace_fp, "_db_add: found_free=%d, free_idx=%u "
"first_null_idx_set=%d, first_null_idx=%u\n",
found_free, free_idx,
first_null_idx_set, first_null_idx););
/* if an unused allocated slot was found */
if (found_free) {
TRACE(3, fprintf(_trace_fp, "_db_add: Reusing db handle %u\n", free_idx););
_dbv[ free_idx ]->dbh = free_idx;
_dbv[ free_idx ]->used = TRUE ; /* set the in use flag *before* releasing the mutex */
} else {
/* alloc a new if possible */
if (first_null_idx_set) {
TRACE(3, fprintf(_trace_fp,"_db_add: Added new handle %u\n", first_null_idx););
_dbv[ first_null_idx ] = MALLOC(sizeof(sqlo_db_t)) ;
if (_dbv[ first_null_idx ]) {
TRACE(4, fprintf(_trace_fp,"_db_add: Allocated %u bytes\n",
(unsigned int) sizeof(sqlo_db_t)););
memset(_dbv[ first_null_idx ], 0, sizeof(sqlo_db_t)) ;
_dbv[ first_null_idx ]->dbh = first_null_idx;
_dbv[ first_null_idx ]->used = TRUE ; /* set this flag *before* releasing the mutex */
free_idx = first_null_idx;
} else {
/* alloc failed */
EXEC_WHEN_THREADING(_dbv_unlock();); /* end of critical section */
return (NULL);
}
} else {
/* no free slots */
EXEC_WHEN_THREADING(_dbv_unlock();); /* end of critical section */
return (NULL);
}
}
EXEC_WHEN_THREADING(_dbv_unlock();); /* end of critical section */
return (_dbv[ free_idx ]) ;
}
/*-------------------------------------------------------------------------*/
/**
* Release a database in _dbv[].
* Marks it as unused and frees all allocated handles.
*
* @param dbp - I The pointer to the database structure
*/
static void
DEFUN(_db_release, (dbp), sqlo_db_ptr_t dbp)
{
if (!dbp)
return;
TRACE(2, fprintf(_get_trace_fp(dbp), "_db_release[%u] starts\n", dbp->dbh); );
if (dbp->srvhp)
(void)OCIHandleFree((dvoid *) dbp->srvhp, OCI_HTYPE_SERVER);
if (dbp->svchp)
(void)OCIHandleFree((dvoid *) dbp->svchp, OCI_HTYPE_SVCCTX);
if (dbp->errhp)
(void)OCIHandleFree((dvoid *) dbp->errhp, OCI_HTYPE_ERROR);
if (dbp->authp)
(void)OCIHandleFree((dvoid *) dbp->authp, OCI_HTYPE_SESSION);
if (dbp->envhp)
(void)OCIHandleFree((dvoid *) dbp->envhp, OCI_HTYPE_ENV);
dbp->srvhp = NULL;
dbp->svchp = NULL;
dbp->errhp = NULL;
dbp->authp = NULL;
dbp->envhp = NULL;
if (dbp->tnsname) {
FREE(dbp->tnsname);
dbp->tnsname = NULL;
}
/* close the trace file */
if (dbp->trace_fp) {
fclose(dbp->trace_fp);
dbp->trace_fp = NULL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -