• Main Page
  • Modules
  • Data Structures
  • Files
  • File List

D:/Perso/dev/ocilib/ocilib/src/subscription.c

00001 /*
00002     +-----------------------------------------------------------------------------------------+
00003     |                                                                                         |
00004     |                               OCILIB - C Driver for Oracle                              |
00005     |                                                                                         |
00006     |                                (C Wrapper for Oracle OCI)                               |
00007     |                                                                                         |
00008     |                              Website : http://www.ocilib.net                            |
00009     |                                                                                         |
00010     |             Copyright (c) 2007-2010 Vincent ROGIER <vince.rogier@ocilib.net>            |
00011     |                                                                                         |
00012     +-----------------------------------------------------------------------------------------+
00013     |                                                                                         |
00014     |             This library is free software; you can redistribute it and/or               |
00015     |             modify it under the terms of the GNU Lesser General Public                  |
00016     |             License as published by the Free Software Foundation; either                |
00017     |             version 2 of the License, or (at your option) any later version.            |
00018     |                                                                                         |
00019     |             This library is distributed in the hope that it will be useful,             |
00020     |             but WITHOUT ANY WARRANTY; without even the implied warranty of              |
00021     |             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU           |
00022     |             Lesser General Public License for more details.                             |
00023     |                                                                                         |
00024     |             You should have received a copy of the GNU Lesser General Public            |
00025     |             License along with this library; if not, write to the Free                  |
00026     |             Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.          |
00027     |                                                                                         |
00028     +-----------------------------------------------------------------------------------------+
00029 */
00030 
00031 /* --------------------------------------------------------------------------------------------- *
00032  * $Id: subscriptions.c, v 3.8.1 2010-12-13 00:00 Vincent Rogier $
00033  * --------------------------------------------------------------------------------------------- */
00034 
00035 #include "ocilib_internal.h"
00036 
00037 /* ********************************************************************************************* *
00038  *                             PRIVATE FUNCTIONS
00039  * ********************************************************************************************* */
00040 
00041 /* --------------------------------------------------------------------------------------------- *
00042  * OCI_SubscriptionClose
00043  * --------------------------------------------------------------------------------------------- */
00044 
00045 boolean OCI_SubscriptionClose
00046 (
00047     OCI_Subscription *sub
00048 )
00049 {
00050     boolean res = TRUE;
00051 
00052     OCI_CHECK_PTR(OCI_IPC_NOTIFY, sub, FALSE);
00053 
00054     #if OCI_VERSION_COMPILE >= OCI_10_2
00055 
00056     /* deregister the subscription if connection still alive */
00057 
00058     if (sub->subhp != NULL)
00059     {
00060         OCI_Connection * con = NULL;
00061 
00062         if (sub->con == NULL)
00063         {
00064             con = OCI_ConnectionCreate(sub->saved_db, sub->saved_user,
00065                                        sub->saved_pwd, OCI_SESSION_DEFAULT);
00066 
00067             sub->con = con;
00068         }
00069 
00070         if (sub->con != NULL)
00071         {
00072             OCI_CALL3
00073             (
00074                 res, sub->err,
00075 
00076                 OCISubscriptionUnRegister(sub->con->cxt, sub->subhp,
00077                                           sub->err,(ub4) OCI_DEFAULT)
00078             )
00079         }
00080 
00081         if (con != NULL)
00082         {
00083             OCI_ConnectionFree(con);
00084         }
00085     }
00086 
00087     /* free OCI handle */
00088 
00089     OCI_HandleFree((dvoid *) sub->subhp, OCI_HTYPE_SUBSCRIPTION);
00090 
00091     /* close error handle */
00092 
00093     if (sub->err != NULL)
00094     {
00095         OCI_HandleFree(sub->err, OCI_HTYPE_ERROR);
00096     }
00097 
00098     #endif
00099 
00100     /* free event data */
00101 
00102     OCI_FREE(sub->event.dbname);
00103     OCI_FREE(sub->event.objname);
00104     OCI_FREE(sub->event.rowid);
00105 
00106     /* free strings */
00107 
00108     OCI_FREE(sub->saved_db);
00109     OCI_FREE(sub->saved_user);
00110     OCI_FREE(sub->saved_pwd);
00111     OCI_FREE(sub->name);
00112 
00113     return res;
00114 }
00115 
00116 /* --------------------------------------------------------------------------------------------- *
00117  * OCI_SubscriptionDetachConnection
00118  * --------------------------------------------------------------------------------------------- */
00119 
00120 boolean OCI_SubscriptionDetachConnection
00121 (
00122     OCI_Connection *con
00123 )
00124 {
00125     OCI_List *list = OCILib.subs;
00126     OCI_Item *item = NULL;
00127 
00128     OCI_CHECK(list == NULL, FALSE);
00129 
00130     if (list->mutex != NULL)
00131         OCI_MutexAcquire(list->mutex);
00132 
00133     item = list->head;
00134 
00135     /* for each item in the list, check the connection */
00136 
00137     while (item != NULL)
00138     {
00139         OCI_Subscription * sub = (OCI_Subscription *) item->data;
00140 
00141         if ((sub != NULL) && (sub->con == con))
00142         {
00143             sub->con = NULL;
00144 
00145             sub->saved_db   = mtsdup(con->db);
00146             sub->saved_user = mtsdup(con->user);
00147             sub->saved_pwd  = mtsdup(con->pwd);
00148         }
00149 
00150         item = item->next;
00151     }
00152 
00153     if (list->mutex != NULL)
00154         OCI_MutexRelease(list->mutex);
00155 
00156     return TRUE;
00157 }
00158 
00159 /* ********************************************************************************************* *
00160  *                            PUBLIC FUNCTIONS
00161  * ********************************************************************************************* */
00162 
00163 /* --------------------------------------------------------------------------------------------- *
00164  * OCI_SubscriptionCreate
00165  * --------------------------------------------------------------------------------------------- */
00166 
00167 OCI_Subscription * OCI_API OCI_SubscriptionRegister
00168 (
00169     OCI_Connection *con,
00170     const mtext    *name,
00171     unsigned int    type,
00172     POCI_NOTIFY     handler,
00173     unsigned int    port,
00174     unsigned int    timeout
00175 )
00176 {
00177     OCI_Subscription *sub = NULL;
00178     OCI_Item *item        = NULL;
00179     boolean res           = TRUE;
00180 
00181     OCI_CHECK_INITIALIZED(NULL);
00182     OCI_CHECK_DATABASE_NOTIFY_ENABLED(NULL);
00183 
00184     OCI_CHECK_PTR(OCI_IPC_CONNECTION, con, NULL);
00185     OCI_CHECK_PTR(OCI_IPC_PROC, handler, NULL);
00186     OCI_CHECK_PTR(OCI_IPC_STRING, name, NULL);
00187 
00188     #if OCI_VERSION_COMPILE >= OCI_10_2
00189 
00190     /* create subscription object */
00191 
00192     item = OCI_ListAppend(OCILib.subs, sizeof(*sub));
00193 
00194     if (item != NULL)
00195     {
00196         sub = (OCI_Subscription *) item->data;
00197 
00198         /* allocate error handle */
00199 
00200         res = (OCI_SUCCESS == OCI_HandleAlloc(OCILib.env,
00201                                               (dvoid **) (void *) &sub->err,
00202                                               OCI_HTYPE_ERROR, (size_t) 0,
00203                                               (dvoid **) NULL));
00204 
00205         /* allocate subcription handle */
00206 
00207         res = (OCI_SUCCESS == OCI_HandleAlloc(OCILib.env,
00208                                               (dvoid **) (void *) &sub->subhp,
00209                                               OCI_HTYPE_SUBSCRIPTION, (size_t) 0,
00210                                               (dvoid **) NULL));
00211 
00212         if (res == TRUE)
00213         {
00214             ub4 attr   = 0;
00215             int osize  = -1;
00216             void *ostr = NULL;
00217 
00218             sub->con       = con;
00219             sub->port      = (ub4) port;
00220             sub->timeout   = (ub4) timeout;
00221             sub->handler   = handler;
00222             sub->type      = type;
00223             sub->name      = mtsdup(name);
00224             sub->event.sub = sub;
00225 
00226             /* set/get port number */
00227 
00228             if (sub->port > 0)
00229             {
00230                 OCI_CALL3
00231                 (
00232                     res, sub->err,
00233 
00234                     OCIAttrSet((dvoid *) OCILib.env, (ub4) OCI_HTYPE_ENV,
00235                                (dvoid *) &sub->port, (ub4) sizeof (sub->port),
00236                                (ub4) OCI_ATTR_SUBSCR_PORTNO, sub->err)
00237                 )
00238             }
00239             else
00240             {
00241                 OCI_CALL3
00242                 (
00243                     res, sub->err,
00244 
00245                     OCIAttrGet((dvoid *) OCILib.env, (ub4) OCI_HTYPE_ENV,
00246                                (dvoid *) &sub->port, (ub4) 0,
00247                                (ub4) OCI_ATTR_SUBSCR_PORTNO, sub->err)
00248                 )
00249             }
00250 
00251             /* set/get timeout */
00252 
00253             if(sub->timeout > 0)
00254             {
00255                 OCI_CALL3
00256                 (
00257                     res, sub->err,
00258 
00259                     OCIAttrSet((dvoid *) sub->subhp, (ub4) OCI_HTYPE_SUBSCRIPTION,
00260                                (dvoid *) &sub->timeout, (ub4) sizeof (sub->timeout),
00261                                (ub4) OCI_ATTR_SUBSCR_TIMEOUT, sub->err)
00262                 )
00263             }
00264 
00265             /* name  */
00266 
00267             ostr = OCI_GetInputMetaString(sub->name, &osize);
00268 
00269             OCI_CALL3
00270             (
00271                 res, sub->err,
00272 
00273                 OCIAttrSet((dvoid *) sub->subhp, (ub4) OCI_HTYPE_SUBSCRIPTION,
00274                            (dvoid *) ostr, (ub4) osize,
00275                            (ub4) OCI_ATTR_SUBSCR_NAME, sub->err)
00276             )
00277 
00278             OCI_ReleaseMetaString(ostr);
00279 
00280             /* namespace for CDN */
00281 
00282             attr =  OCI_SUBSCR_NAMESPACE_DBCHANGE;
00283 
00284             OCI_CALL3
00285             (
00286                 res, sub->err,
00287 
00288                 OCIAttrSet((dvoid *) sub->subhp, (ub4) OCI_HTYPE_SUBSCRIPTION,
00289                            (dvoid *) &attr, (ub4) sizeof(attr),
00290                            (ub4) OCI_ATTR_SUBSCR_NAMESPACE, sub->err)
00291             )
00292 
00293 /* On MSVC, casting a function pointer to a data pointer generates a warning.
00294    As there is no other to way to do regarding the OCI API, let's disable this
00295    warning just the time to set the callback attribute to the subscription handle */
00296 
00297             #ifdef _MSC_VER
00298             #pragma warning(disable: 4054)
00299             #endif
00300 
00301             /* internal callback handler */
00302 
00303             OCI_CALL3
00304             (
00305                 res, sub->err,
00306 
00307                 OCIAttrSet((dvoid *) sub->subhp, (ub4) OCI_HTYPE_SUBSCRIPTION,
00308                            (dvoid *) OCI_ProcNotify, (ub4) 0,
00309                            (ub4) OCI_ATTR_SUBSCR_CALLBACK, sub->err)
00310             )
00311 
00312             #ifdef _MSC_VER
00313             #pragma warning(default: 4054)
00314             #endif
00315 
00316             /* RowIds handling */
00317 
00318             if (sub->type & OCI_CNT_ROWS)
00319             {
00320                 attr = TRUE;
00321 
00322                 OCI_CALL3
00323                 (
00324                     res, sub->err,
00325 
00326                     OCIAttrSet((dvoid *) sub->subhp, (ub4) OCI_HTYPE_SUBSCRIPTION,
00327                                (dvoid *) &attr, (ub4) sizeof(attr),
00328                                (ub4) OCI_ATTR_CHNF_ROWIDS, sub->err)
00329                 )
00330             }
00331 
00332             /* set subsription context pointer to our subscription structure */
00333 
00334             OCI_CALL3
00335             (
00336                 res, sub->err,
00337 
00338                 OCIAttrSet((dvoid *) sub->subhp, (ub4) OCI_HTYPE_SUBSCRIPTION,
00339                            (dvoid *) sub, (ub4) 0,
00340                            (ub4) OCI_ATTR_SUBSCR_CTX, sub->err)
00341             )
00342 
00343             /* all attributes set, let's register the subscription ! */
00344 
00345             OCI_CALL3
00346             (
00347                 res, sub->err,
00348 
00349                 OCISubscriptionRegister(sub->con->cxt, &sub->subhp, (ub2) 1,
00350                                         sub->err,(ub4) OCI_DEFAULT)
00351 
00352             )
00353         }
00354     }
00355     else
00356         res = FALSE;
00357 
00358     if (res == FALSE)
00359     {
00360         OCI_SubscriptionClose(sub);
00361         OCI_ListRemove(OCILib.subs, sub);
00362         OCI_FREE(sub);
00363     }
00364 
00365     #else
00366 
00367     res = FALSE;
00368 
00369     OCI_NOT_USED(name);
00370     OCI_NOT_USED(type);
00371     OCI_NOT_USED(handler);
00372     OCI_NOT_USED(port);
00373     OCI_NOT_USED(timeout);
00374     OCI_NOT_USED(con);
00375     OCI_NOT_USED(item);
00376 
00377     #endif
00378 
00379     OCI_RESULT(res);
00380 
00381     return sub;
00382 }
00383 
00384 /* --------------------------------------------------------------------------------------------- *
00385  * OCI_SubscriptionUnregister
00386  * --------------------------------------------------------------------------------------------- */
00387 
00388 boolean OCI_API OCI_SubscriptionUnregister
00389 (
00390     OCI_Subscription *sub
00391 )
00392 {
00393     boolean res = TRUE;
00394 
00395     OCI_CHECK_PTR(OCI_IPC_NOTIFY, sub, FALSE);
00396 
00397     res = OCI_SubscriptionClose(sub);
00398 
00399     OCI_ListRemove(OCILib.subs, sub);
00400 
00401     OCI_FREE(sub);
00402 
00403     OCI_RESULT(res);
00404 
00405     return res;
00406 }
00407 
00408 /* --------------------------------------------------------------------------------------------- *
00409  * OCI_SubscriptionAddStatement
00410  * --------------------------------------------------------------------------------------------- */
00411 
00412 boolean OCI_API OCI_SubscriptionAddStatement
00413 (
00414     OCI_Subscription *sub,
00415     OCI_Statement    *stmt
00416 )
00417 {
00418     boolean res = TRUE;
00419 
00420     OCI_CHECK_PTR(OCI_IPC_NOTIFY, sub, FALSE);
00421     OCI_CHECK_PTR(OCI_IPC_STATEMENT, stmt, FALSE);
00422 
00423     OCI_CHECK_STMT_STATUS(stmt, OCI_STMT_CLOSED, FALSE);
00424     OCI_CHECK_STMT_STATUS(stmt, OCI_STMT_EXECUTED, FALSE);
00425 
00426     #if OCI_VERSION_COMPILE >= OCI_10_2
00427 
00428     /* register the statement query if provided */
00429 
00430     if (sub->type & OCI_CNT_OBJECTS)
00431     {
00432         OCI_CALL3
00433         (
00434             res, sub->err,
00435 
00436             OCIAttrSet((dvoid *) stmt->stmt, (ub4) OCI_HTYPE_STMT,
00437                        (dvoid *) sub->subhp, (ub4) 0,
00438                        (ub4) OCI_ATTR_CHNF_REGHANDLE, sub->err)
00439         )
00440 
00441         res = res && OCI_Execute(stmt) && (OCI_GetResultset(stmt) != NULL);
00442     }
00443 
00444     #endif
00445 
00446     OCI_RESULT(res);
00447 
00448     return res;
00449 }
00450 
00451 /* --------------------------------------------------------------------------------------------- *
00452  * OCI_SubscriptionGetName
00453  * --------------------------------------------------------------------------------------------- */
00454 
00455 const mtext * OCI_API OCI_SubscriptionGetName
00456 (
00457     OCI_Subscription *sub
00458 )
00459 {
00460     OCI_CHECK_PTR(OCI_IPC_NOTIFY, sub, NULL);
00461 
00462     OCI_RESULT(TRUE);
00463 
00464     return sub->name;
00465 }
00466 
00467 /* --------------------------------------------------------------------------------------------- *
00468  * OCI_SubscriptionGetPort
00469  * --------------------------------------------------------------------------------------------- */
00470 
00471 unsigned int OCI_API OCI_SubscriptionGetPort
00472 (
00473     OCI_Subscription *sub
00474 )
00475 {
00476     OCI_CHECK_PTR(OCI_IPC_NOTIFY, sub, 0);
00477 
00478     OCI_RESULT(TRUE);
00479 
00480     return sub->port;
00481 }
00482 
00483 /* --------------------------------------------------------------------------------------------- *
00484  * OCI_SubscriptionGetTimeout
00485  * --------------------------------------------------------------------------------------------- */
00486 
00487 unsigned int OCI_API OCI_SubscriptionGetTimeout
00488 (
00489     OCI_Subscription *sub
00490 )
00491 {
00492     OCI_CHECK_PTR(OCI_IPC_NOTIFY, sub, 0);
00493 
00494     OCI_RESULT(TRUE);
00495 
00496     return sub->timeout;
00497 }
00498 

Generated on Mon Dec 13 2010 22:32:02 for OCILIB (C Driver for Oracle) by  doxygen 1.7.2