C:/Users/vincent/Data/Perso/dev/ocilib/ocilib/src/connpool.c

00001 /*
00002    +----------------------------------------------------------------------+
00003    |                                                                      |
00004    |                     OCILIB - C Driver for Oracle                     |
00005    |                                                                      |
00006    |                      (C Wrapper for Oracle OCI)                      |
00007    |                                                                      |
00008    +----------------------------------------------------------------------+
00009    |                      Website : http://www.ocilib.net                 |
00010    +----------------------------------------------------------------------+
00011    |               Copyright (c) 2007-2009 Vincent ROGIER                 |
00012    +----------------------------------------------------------------------+
00013    | This library is free software; you can redistribute it and/or        |
00014    | modify it under the terms of the GNU Lesser General Public           |
00015    | License as published by the Free Software Foundation; either         |
00016    | version 2 of the License, or (at your option) any later version.     |
00017    |                                                                      |
00018    | This library is distributed in the hope that it will be useful,      |
00019    | but WITHOUT ANY WARRANTY; without even the implied warranty of       |
00020    | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    |
00021    | Lesser General Public License for more details.                      |
00022    |                                                                      |
00023    | You should have received a copy of the GNU Lesser General Public     |
00024    | License along with this library; if not, write to the Free           |
00025    | Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.   |
00026    +----------------------------------------------------------------------+
00027    |          Author: Vincent ROGIER <vince.rogier@gmail.com>             |
00028    +----------------------------------------------------------------------+
00029 */
00030 
00031 /* ------------------------------------------------------------------------ *
00032  * $Id: connpool.c, v 3.4.0 2009-07-30 17:40 Vince $
00033  * ------------------------------------------------------------------------ */
00034 
00035 #include "ocilib_internal.h"
00036 
00037 /* ************************************************************************ *
00038  *                             PRIVATE FUNCTIONS
00039  * ************************************************************************ */
00040 
00041 /* ------------------------------------------------------------------------ *
00042  * OCI_ConnPoolClose
00043  * ------------------------------------------------------------------------ */
00044 
00045 boolean OCI_ConnPoolClose(OCI_ConnPool *pool)
00046 {
00047     boolean res = TRUE;
00048 
00049     OCI_CHECK_PTR(OCI_IPC_CONNPOOL, pool, FALSE);
00050 
00051     /* free all connections */
00052 
00053     OCI_ListForEach(pool->cons, (boolean (*)(void *)) OCI_ConnectionClose);
00054     OCI_ListClear(pool->cons);
00055     OCI_ListFree(pool->cons);
00056 
00057     pool->cons = NULL;
00058 
00059     if (OCI_LIB_THREADED)
00060         OCI_MutexFree(pool->mutex);
00061 
00062 #if OCI_VERSION_COMPILE >= OCI_9_0
00063 
00064     if (OCILib.version_runtime >= OCI_9_0)
00065     {
00066         /* close connection pool handle */
00067 
00068         if (pool->handle != NULL)
00069         {
00070             OCI_CALL0
00071             (
00072                 res, pool->err,
00073 
00074                 OCIConnectionPoolDestroy(pool->handle, pool->err,
00075                                           (ub4) OCI_DEFAULT)
00076             )
00077 
00078             OCI_HandleFree((void *) pool->handle, (ub4) OCI_HTYPE_CPOOL);
00079         }
00080 
00081         /* close error handle */
00082 
00083         if (pool->err != NULL)
00084             OCI_HandleFree((void *) pool->err, (ub4) OCI_HTYPE_ERROR);
00085     }
00086 
00087 #endif
00088 
00089     pool->err    = NULL;
00090     pool->handle = NULL;
00091 
00092     /* free strings */
00093 
00094     OCI_FREE(pool->name);
00095     OCI_FREE(pool->db);
00096     OCI_FREE(pool->user);
00097     OCI_FREE(pool->pwd);
00098 
00099     return res;
00100 }
00101 
00102 /* ************************************************************************ *
00103  *                             PUBLIC FUNCTIONS
00104  * ************************************************************************ */
00105 
00106 /* ------------------------------------------------------------------------ *
00107  * OCI_ConnPoolCreate
00108  * ------------------------------------------------------------------------ */
00109 
00110 OCI_ConnPool * OCI_API OCI_ConnPoolCreate(const mtext *db, const mtext *user,
00111                                           const mtext *pwd,
00112                                           unsigned int mode,
00113                                           unsigned int min_con,
00114                                           unsigned int max_con,
00115                                           unsigned int incr_con)
00116 {
00117     OCI_ConnPool *pool = NULL;
00118     OCI_Item     *item = NULL;
00119     boolean res        = TRUE;
00120 
00121     OCI_CHECK_MIN(NULL, NULL, max_con, 1, FALSE);
00122 
00123     /* let's be sure OCI_Initialize() has been called */
00124 
00125     OCI_CHECK_INITIALIZED(NULL);
00126 
00127     /* create connection pool object */
00128 
00129     item = OCI_ListAppend(OCILib.pools, sizeof(*pool));
00130 
00131     if (item != NULL)
00132     {
00133         pool = (OCI_ConnPool *) item->data;
00134 
00135         /* create internal lists */
00136 
00137         pool->cons = OCI_ListCreate(OCI_IPC_CONNECTION);
00138 
00139         if (OCI_LIB_THREADED)
00140         {
00141             /* create mutex for OCI_ConnPoolGetConnection() */
00142 
00143             pool->mutex = OCI_MutexCreateInternal();
00144 
00145             res = (pool->mutex != NULL);
00146         }
00147     }
00148     else
00149         res = FALSE;
00150 
00151     /* set attributes */
00152 
00153     if (res == TRUE)
00154     {
00155 
00156         pool->mode = mode;
00157         pool->min  = min_con;
00158         pool->max  = max_con;
00159         pool->incr = incr_con;
00160 
00161         pool->db   = mtsdup(db   != NULL ? db   : MT(""));
00162         pool->user = mtsdup(user != NULL ? user : MT(""));
00163         pool->pwd  = mtsdup(pwd  != NULL ? pwd  : MT(""));
00164     }
00165 
00166 
00167 #if OCI_VERSION_COMPILE >= OCI_9_0
00168 
00169     if (OCILib.version_runtime >= OCI_9_0)
00170     {
00171         int osize_name  = -1;
00172         int osize_db    = -1;
00173         int osize_user  = -1;
00174         int osize_pwd   = -1;
00175 
00176         void *ostr_name = NULL;
00177         void *ostr_db   = NULL;
00178         void *ostr_user = NULL;
00179         void *ostr_pwd  = NULL;
00180 
00181         /* allocate error handle */
00182 
00183         if (res == TRUE)
00184             res = (OCI_SUCCESS == OCI_HandleAlloc((dvoid *) OCILib.env,
00185                                                   (dvoid **) (void *) &pool->err,
00186                                                   (ub4) OCI_HTYPE_ERROR,
00187                                                   (size_t) 0,
00188                                                   (dvoid **) NULL));
00189 
00190         /* allocate connection pool handle */
00191 
00192         if (res == TRUE)
00193             res = (OCI_SUCCESS == OCI_HandleAlloc((dvoid *) OCILib.env,
00194                                                   (dvoid **) (void *) &pool->handle,
00195                                                   (ub4) OCI_HTYPE_CPOOL,
00196                                                   (size_t) 0,
00197                                                   (dvoid **) NULL));
00198 
00199         /* create the pool */
00200 
00201         if (res == TRUE)
00202         {
00203             ostr_db    = OCI_GetInputMetaString(pool->db,   &osize_db);
00204             ostr_user  = OCI_GetInputMetaString(pool->user, &osize_user);
00205             ostr_pwd   = OCI_GetInputMetaString(pool->pwd,  &osize_pwd);
00206 
00207             OCI_CALL3
00208             (
00209                 res, pool->err,
00210 
00211                 OCIConnectionPoolCreate(OCILib.env, pool->err, pool->handle,
00212                                         (OraText **) (dvoid *) &ostr_name,
00213                                         (sb4*) &osize_name,
00214                                         (OraText *) ostr_db, (sb4) osize_db,
00215                                         (ub4) pool->min, (ub4) pool->max,
00216                                         (ub4) pool->incr, (OraText *) ostr_user,
00217                                         (sb4) osize_user, (OraText *) ostr_pwd,
00218                                         (sb4) osize_pwd,  (ub4) OCI_DEFAULT)
00219             )
00220 
00221             OCI_ReleaseMetaString(ostr_db);
00222             OCI_ReleaseMetaString(ostr_user);
00223             OCI_ReleaseMetaString(ostr_pwd);
00224         }
00225 
00226         if ((res == TRUE) && (ostr_name != NULL))
00227         {
00228             pool->name = (mtext *) OCI_MemAlloc(OCI_IPC_STRING, sizeof(mtext),
00229                                                 (osize_name/sizeof(omtext)) + 1,
00230                                                 FALSE);
00231 
00232             if (pool->name != NULL)
00233             {
00234                 OCI_CopyString(ostr_name, pool->name, &osize_name,
00235                                sizeof(omtext), sizeof(mtext));
00236             }
00237             else
00238                 res = FALSE;
00239         }
00240     }
00241 
00242 #endif
00243 
00244    /* on success, we allocate internal OCI connection objects for pool
00245       minimum size */
00246 
00247     if (res == TRUE)
00248     {
00249         OCI_Connection *cn;
00250 
00251         while ((min_con--) > 0)
00252         {
00253             cn = OCI_ConnectionAllocate(pool, pool->db, pool->user,
00254                                         pool->pwd, pool->mode);
00255         }
00256     }
00257     else
00258     {
00259         OCI_ConnPoolFree(pool);
00260         pool = NULL;
00261     }
00262 
00263     OCI_RESULT(res);
00264 
00265     return pool;
00266 }
00267 
00268 /* ------------------------------------------------------------------------ *
00269  * OCI_ConnPoolFree
00270  * ------------------------------------------------------------------------ */
00271 
00272 boolean OCI_API OCI_ConnPoolFree(OCI_ConnPool *pool)
00273 {
00274     boolean res = TRUE;
00275 
00276     OCI_CHECK_PTR(OCI_IPC_CONNPOOL, pool, FALSE);
00277 
00278     res = OCI_ConnPoolClose(pool);
00279 
00280     OCI_ListRemove(OCILib.pools, pool);
00281 
00282     OCI_FREE(pool);
00283 
00284     OCI_RESULT(res);
00285 
00286     return res;
00287 }
00288 
00289 /* ------------------------------------------------------------------------ *
00290  * OCI_ConnPoolGetConnection
00291  * ------------------------------------------------------------------------ */
00292 
00293 OCI_Connection * OCI_API OCI_ConnPoolGetConnection(OCI_ConnPool *pool)
00294 {
00295     OCI_Connection *con  = NULL;
00296     OCI_Item       *item = NULL;
00297     boolean res          = FALSE;
00298     boolean found        = FALSE;
00299 
00300     OCI_CHECK_PTR(OCI_IPC_CONNPOOL, pool, NULL);
00301 
00302     if (OCI_LIB_THREADED)
00303         OCI_MutexAcquire(pool->mutex);
00304 
00305     /* fist, try to find an unused OCI_Connection in list */
00306 
00307     item = pool->cons->head;
00308 
00309     while (item != NULL)
00310     {
00311         con = (OCI_Connection *) item->data;
00312 
00313         if (con->cstate == OCI_CONN_ALLOCATED)
00314         {
00315             found = TRUE;
00316             break;
00317         }
00318 
00319         item = item->next;
00320     }
00321 
00322     if (found == FALSE)
00323     {
00324         /* no available connection found ! Try to allocate a new one... */
00325 
00326         if (OCILib.version_runtime >= OCI_9_0 || pool->cons->count < pool->max)
00327         {
00328             ub4 i, nb;
00329             OCI_Connection *c = NULL;
00330 
00331             nb = pool->nb_opened + pool->incr;
00332 
00333             if (nb > pool->max)
00334                 nb = pool->max;
00335 
00336             for (i = 0; i < nb; i++)
00337             {
00338                 c = OCI_ConnectionAllocate(pool, pool->db, pool->user,
00339                                            pool->pwd, pool->mode);
00340 
00341                 if (i == 0 && c != NULL)
00342                    con = c;
00343             }
00344         }
00345     }
00346 
00347     if (con != NULL)
00348     {
00349         res = TRUE;
00350 
00351         if (con->cstate == OCI_CONN_ALLOCATED)
00352             res = res && OCI_ConnectionAttach(con);
00353 
00354         res  = res &&  OCI_ConnectionLogon(con);
00355 
00356         if (res == FALSE)
00357         {
00358             OCI_ConnectionFree(con);
00359             con = NULL;
00360         }
00361     }
00362 
00363     if (OCI_LIB_THREADED)
00364         OCI_MutexRelease(pool->mutex);
00365 
00366     OCI_RESULT(res);
00367 
00368     return con;
00369 }
00370 
00371 /* ------------------------------------------------------------------------ *
00372  * OCI_ConnPoolGetTimeout
00373  * ------------------------------------------------------------------------ */
00374 
00375 unsigned int OCI_API OCI_ConnPoolGetTimeout(OCI_ConnPool *pool)
00376 {
00377     OCI_CHECK_PTR(OCI_IPC_CONNPOOL, pool, 0);
00378 
00379     OCI_RESULT(TRUE);
00380 
00381     return pool->timeout;
00382 }
00383 
00384 /* ------------------------------------------------------------------------ *
00385  * OCI_ConnPoolSetTimeout
00386  * ------------------------------------------------------------------------ */
00387 
00388 boolean OCI_API OCI_ConnPoolSetTimeout(OCI_ConnPool *pool, unsigned int value)
00389 {
00390     boolean res = TRUE;
00391 
00392     OCI_CHECK_PTR(OCI_IPC_CONNPOOL, pool, FALSE);
00393 
00394 #if OCI_VERSION_COMPILE >= OCI_9_0
00395 
00396     if (OCILib.version_runtime >= OCI_9_0)
00397     {
00398         ub4 timeout = value;
00399 
00400         OCI_CALL3
00401         (
00402             res, pool->err,
00403 
00404             OCIAttrSet((dvoid *) pool->handle, (ub4) OCI_HTYPE_CPOOL,
00405                        (dvoid *) &timeout,(ub4) sizeof(timeout),
00406                        (ub4) OCI_ATTR_CONN_TIMEOUT, pool->err)
00407         )
00408     }
00409 
00410 #endif
00411 
00412     if (res == TRUE)
00413         pool->timeout = value;
00414 
00415     OCI_RESULT(res);
00416 
00417     return res;
00418 }
00419 
00420 /* ------------------------------------------------------------------------ *
00421  * OCI_ConnPoolGetlGetNoWait
00422  * ------------------------------------------------------------------------ */
00423 
00424 boolean OCI_API OCI_ConnPoolGetlGetNoWait(OCI_ConnPool *pool)
00425 {
00426     OCI_CHECK_PTR(OCI_IPC_CONNPOOL, pool, FALSE);
00427 
00428     OCI_RESULT(TRUE);
00429 
00430     return pool->nowait;
00431 }
00432 
00433 /* ------------------------------------------------------------------------ *
00434  * OCI_ConnPoolSetNoWait
00435  * ------------------------------------------------------------------------ */
00436 
00437 boolean OCI_API OCI_ConnPoolSetNoWait(OCI_ConnPool *pool, boolean value)
00438 {
00439     boolean res = TRUE;
00440 
00441     OCI_CHECK_PTR(OCI_IPC_CONNPOOL, pool, 0);
00442 
00443 #if OCI_VERSION_COMPILE >= OCI_9_0
00444 
00445     if (OCILib.version_runtime >= OCI_9_0)
00446     {
00447         ub1 nowait = (ub1) value;
00448 
00449         OCI_CALL3
00450         (
00451             res, pool->err,
00452 
00453             OCIAttrSet((dvoid *) pool->handle, (ub4) OCI_HTYPE_CPOOL,
00454                        (dvoid *) &nowait, (ub4) sizeof(nowait),
00455                        (ub4) OCI_ATTR_CONN_NOWAIT, pool->err)
00456         )
00457     }
00458 
00459 #endif
00460 
00461     if (res == TRUE)
00462         pool->nowait = value;
00463 
00464     OCI_RESULT(res);
00465 
00466     return TRUE;
00467 }
00468 
00469 /* ------------------------------------------------------------------------ *
00470  * OCI_ConnPoolGetBusyCount
00471  * ------------------------------------------------------------------------ */
00472 
00473 unsigned int OCI_API OCI_ConnPoolGetBusyCount(OCI_ConnPool *pool)
00474 {
00475     boolean res = TRUE;
00476 
00477     OCI_CHECK_PTR(OCI_IPC_CONNPOOL, pool, 0);
00478 
00479 #if OCI_VERSION_COMPILE >= OCI_9_0
00480 
00481     if (OCILib.version_runtime >= OCI_9_0)
00482     {
00483         ub4 value = 0;
00484 
00485         OCI_CALL3
00486         (
00487             res, pool->err,
00488 
00489             OCIAttrGet((dvoid *) pool->handle,(ub4) OCI_HTYPE_CPOOL,
00490                        (dvoid *) &value, (ub4 *) NULL,
00491                        (ub4) OCI_ATTR_CONN_BUSY_COUNT, pool->err)
00492         )
00493 
00494         if (res == TRUE)
00495             pool->nb_busy = value;
00496     }
00497 
00498 #endif
00499 
00500     OCI_RESULT(res);
00501 
00502     return pool->nb_busy;
00503 }
00504 
00505 /* ------------------------------------------------------------------------ *
00506  * OCI_ConnPoolGetOpenedCount
00507  * ------------------------------------------------------------------------ */
00508 
00509 unsigned int OCI_API OCI_ConnPoolGetOpenedCount(OCI_ConnPool *pool)
00510 {
00511     boolean res = TRUE;
00512 
00513     OCI_CHECK_PTR(OCI_IPC_CONNPOOL, pool, 0);
00514 
00515 #if OCI_VERSION_COMPILE >= OCI_9_0
00516 
00517     if (OCILib.version_runtime >= OCI_9_0)
00518     {
00519         ub4 value = 0;
00520 
00521         OCI_CALL3
00522         (
00523             res, pool->err,
00524 
00525             OCIAttrGet((dvoid *) pool->handle, (ub4) OCI_HTYPE_CPOOL,
00526                        (dvoid *) &value, (ub4 *) NULL,
00527                        (ub4) OCI_ATTR_CONN_OPEN_COUNT, pool->err)
00528         )
00529 
00530         if (res == TRUE)
00531             pool->nb_opened = value;
00532     }
00533 
00534 #endif
00535 
00536      OCI_RESULT(res);
00537 
00538      return pool->nb_opened;
00539 }
00540 
00541 /* ------------------------------------------------------------------------ *
00542  * OCI_ConnPoolGetMin
00543  * ------------------------------------------------------------------------ */
00544 
00545 unsigned int OCI_API OCI_ConnPoolGetMin(OCI_ConnPool *pool)
00546 {
00547     OCI_CHECK_PTR(OCI_IPC_CONNPOOL, pool, 0);
00548 
00549     OCI_RESULT(TRUE);
00550 
00551     return pool->min;
00552 }
00553 
00554 /* ------------------------------------------------------------------------ *
00555  * OCI_ConnPoolGetMax
00556  * ------------------------------------------------------------------------ */
00557 
00558 unsigned int OCI_API OCI_ConnPoolGetMax(OCI_ConnPool *pool)
00559 {
00560     OCI_CHECK_PTR(OCI_IPC_CONNPOOL, pool, 0);
00561 
00562     OCI_RESULT(TRUE);
00563 
00564     return pool->max;
00565 }
00566 
00567 /* ------------------------------------------------------------------------ *
00568  * OCI_ConnPoolGetIncrement
00569  * ------------------------------------------------------------------------ */
00570 
00571 unsigned int OCI_API OCI_ConnPoolGetIncrement(OCI_ConnPool *pool)
00572 {
00573     OCI_CHECK_PTR(OCI_IPC_CONNPOOL, pool, 0);
00574 
00575     OCI_RESULT(TRUE);
00576 
00577     return pool->incr;
00578 }

Generated on Thu Jul 30 17:41:52 2009 for OCILIB (C Driver for Oracle) by  doxygen 1.5.4