OCILIB (C Driver for Oracle) 3.9.1
|
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-2011 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.9.1 2011-07-08 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 { 00132 OCI_MutexAcquire(list->mutex); 00133 } 00134 00135 item = list->head; 00136 00137 /* for each item in the list, check the connection */ 00138 00139 while (item != NULL) 00140 { 00141 OCI_Subscription * sub = (OCI_Subscription *) item->data; 00142 00143 if ((sub != NULL) && (sub->con == con)) 00144 { 00145 sub->con = NULL; 00146 00147 sub->saved_db = mtsdup(con->db); 00148 sub->saved_user = mtsdup(con->user); 00149 sub->saved_pwd = mtsdup(con->pwd); 00150 } 00151 00152 item = item->next; 00153 } 00154 00155 if (list->mutex != NULL) 00156 { 00157 OCI_MutexRelease(list->mutex); 00158 } 00159 00160 return TRUE; 00161 } 00162 00163 /* ********************************************************************************************* * 00164 * PUBLIC FUNCTIONS 00165 * ********************************************************************************************* */ 00166 00167 /* --------------------------------------------------------------------------------------------- * 00168 * OCI_SubscriptionCreate 00169 * --------------------------------------------------------------------------------------------- */ 00170 00171 OCI_Subscription * OCI_API OCI_SubscriptionRegister 00172 ( 00173 OCI_Connection *con, 00174 const mtext *name, 00175 unsigned int type, 00176 POCI_NOTIFY handler, 00177 unsigned int port, 00178 unsigned int timeout 00179 ) 00180 { 00181 OCI_Subscription *sub = NULL; 00182 OCI_Item *item = NULL; 00183 boolean res = TRUE; 00184 00185 OCI_CHECK_INITIALIZED(NULL); 00186 OCI_CHECK_DATABASE_NOTIFY_ENABLED(NULL); 00187 00188 OCI_CHECK_PTR(OCI_IPC_CONNECTION, con, NULL); 00189 OCI_CHECK_PTR(OCI_IPC_PROC, handler, NULL); 00190 OCI_CHECK_PTR(OCI_IPC_STRING, name, NULL); 00191 00192 #if OCI_VERSION_COMPILE >= OCI_10_2 00193 00194 /* create subscription object */ 00195 00196 item = OCI_ListAppend(OCILib.subs, sizeof(*sub)); 00197 00198 if (item != NULL) 00199 { 00200 sub = (OCI_Subscription *) item->data; 00201 00202 /* allocate error handle */ 00203 00204 res = (OCI_SUCCESS == OCI_HandleAlloc(con->env, 00205 (dvoid **) (void *) &sub->err, 00206 OCI_HTYPE_ERROR, (size_t) 0, 00207 (dvoid **) NULL)); 00208 00209 /* allocate subcription handle */ 00210 00211 res = (OCI_SUCCESS == OCI_HandleAlloc(con->env, 00212 (dvoid **) (void *) &sub->subhp, 00213 OCI_HTYPE_SUBSCRIPTION, (size_t) 0, 00214 (dvoid **) NULL)); 00215 00216 if (res == TRUE) 00217 { 00218 ub4 attr = 0; 00219 int osize = -1; 00220 void *ostr = NULL; 00221 00222 sub->con = con; 00223 sub->env = con->env; 00224 sub->port = (ub4) port; 00225 sub->timeout = (ub4) timeout; 00226 sub->handler = handler; 00227 sub->type = type; 00228 sub->name = mtsdup(name); 00229 sub->event.sub = sub; 00230 00231 /* set/get port number */ 00232 00233 if (sub->port > 0) 00234 { 00235 OCI_CALL3 00236 ( 00237 res, sub->err, 00238 00239 OCIAttrSet((dvoid *) con->env, (ub4) OCI_HTYPE_ENV, 00240 (dvoid *) &sub->port, (ub4) sizeof (sub->port), 00241 (ub4) OCI_ATTR_SUBSCR_PORTNO, sub->err) 00242 ) 00243 } 00244 else 00245 { 00246 OCI_CALL3 00247 ( 00248 res, sub->err, 00249 00250 OCIAttrGet((dvoid *) con->env, (ub4) OCI_HTYPE_ENV, 00251 (dvoid *) &sub->port, (ub4) 0, 00252 (ub4) OCI_ATTR_SUBSCR_PORTNO, sub->err) 00253 ) 00254 } 00255 00256 /* set/get timeout */ 00257 00258 if(sub->timeout > 0) 00259 { 00260 OCI_CALL3 00261 ( 00262 res, sub->err, 00263 00264 OCIAttrSet((dvoid *) sub->subhp, (ub4) OCI_HTYPE_SUBSCRIPTION, 00265 (dvoid *) &sub->timeout, (ub4) sizeof (sub->timeout), 00266 (ub4) OCI_ATTR_SUBSCR_TIMEOUT, sub->err) 00267 ) 00268 } 00269 00270 /* name */ 00271 00272 ostr = OCI_GetInputMetaString(sub->name, &osize); 00273 00274 OCI_CALL3 00275 ( 00276 res, sub->err, 00277 00278 OCIAttrSet((dvoid *) sub->subhp, (ub4) OCI_HTYPE_SUBSCRIPTION, 00279 (dvoid *) ostr, (ub4) osize, 00280 (ub4) OCI_ATTR_SUBSCR_NAME, sub->err) 00281 ) 00282 00283 OCI_ReleaseMetaString(ostr); 00284 00285 /* namespace for CDN */ 00286 00287 attr = OCI_SUBSCR_NAMESPACE_DBCHANGE; 00288 00289 OCI_CALL3 00290 ( 00291 res, sub->err, 00292 00293 OCIAttrSet((dvoid *) sub->subhp, (ub4) OCI_HTYPE_SUBSCRIPTION, 00294 (dvoid *) &attr, (ub4) sizeof(attr), 00295 (ub4) OCI_ATTR_SUBSCR_NAMESPACE, sub->err) 00296 ) 00297 00298 /* On MSVC, casting a function pointer to a data pointer generates a warning. 00299 As there is no other to way to do regarding the OCI API, let's disable this 00300 warning just the time to set the callback attribute to the subscription handle */ 00301 00302 #ifdef _MSC_VER 00303 00304 #pragma warning(disable: 4054) 00305 00306 #endif 00307 00308 /* internal callback handler */ 00309 00310 OCI_CALL3 00311 ( 00312 res, sub->err, 00313 00314 OCIAttrSet((dvoid *) sub->subhp, (ub4) OCI_HTYPE_SUBSCRIPTION, 00315 (dvoid *) OCI_ProcNotify, (ub4) 0, 00316 (ub4) OCI_ATTR_SUBSCR_CALLBACK, sub->err) 00317 ) 00318 00319 #ifdef _MSC_VER 00320 00321 #pragma warning(default: 4054) 00322 00323 #endif 00324 00325 /* RowIds handling */ 00326 00327 if (sub->type & OCI_CNT_ROWS) 00328 { 00329 attr = TRUE; 00330 00331 OCI_CALL3 00332 ( 00333 res, sub->err, 00334 00335 OCIAttrSet((dvoid *) sub->subhp, (ub4) OCI_HTYPE_SUBSCRIPTION, 00336 (dvoid *) &attr, (ub4) sizeof(attr), 00337 (ub4) OCI_ATTR_CHNF_ROWIDS, sub->err) 00338 ) 00339 } 00340 00341 /* set subsription context pointer to our subscription structure */ 00342 00343 OCI_CALL3 00344 ( 00345 res, sub->err, 00346 00347 OCIAttrSet((dvoid *) sub->subhp, (ub4) OCI_HTYPE_SUBSCRIPTION, 00348 (dvoid *) sub, (ub4) 0, 00349 (ub4) OCI_ATTR_SUBSCR_CTX, sub->err) 00350 ) 00351 00352 /* all attributes set, let's register the subscription ! */ 00353 00354 OCI_CALL3 00355 ( 00356 res, sub->err, 00357 00358 OCISubscriptionRegister(sub->con->cxt, &sub->subhp, (ub2) 1, 00359 sub->err,(ub4) OCI_DEFAULT) 00360 00361 ) 00362 } 00363 } 00364 else 00365 { 00366 res = FALSE; 00367 } 00368 00369 if (res == FALSE) 00370 { 00371 OCI_SubscriptionClose(sub); 00372 OCI_ListRemove(OCILib.subs, sub); 00373 OCI_FREE(sub); 00374 } 00375 00376 #else 00377 00378 res = FALSE; 00379 00380 OCI_NOT_USED(name); 00381 OCI_NOT_USED(type); 00382 OCI_NOT_USED(handler); 00383 OCI_NOT_USED(port); 00384 OCI_NOT_USED(timeout); 00385 OCI_NOT_USED(con); 00386 OCI_NOT_USED(item); 00387 00388 #endif 00389 00390 OCI_RESULT(res); 00391 00392 return sub; 00393 } 00394 00395 /* --------------------------------------------------------------------------------------------- * 00396 * OCI_SubscriptionUnregister 00397 * --------------------------------------------------------------------------------------------- */ 00398 00399 boolean OCI_API OCI_SubscriptionUnregister 00400 ( 00401 OCI_Subscription *sub 00402 ) 00403 { 00404 boolean res = TRUE; 00405 00406 OCI_CHECK_PTR(OCI_IPC_NOTIFY, sub, FALSE); 00407 00408 res = OCI_SubscriptionClose(sub); 00409 00410 OCI_ListRemove(OCILib.subs, sub); 00411 00412 OCI_FREE(sub); 00413 00414 OCI_RESULT(res); 00415 00416 return res; 00417 } 00418 00419 /* --------------------------------------------------------------------------------------------- * 00420 * OCI_SubscriptionAddStatement 00421 * --------------------------------------------------------------------------------------------- */ 00422 00423 boolean OCI_API OCI_SubscriptionAddStatement 00424 ( 00425 OCI_Subscription *sub, 00426 OCI_Statement *stmt 00427 ) 00428 { 00429 boolean res = TRUE; 00430 00431 OCI_CHECK_PTR(OCI_IPC_NOTIFY, sub, FALSE); 00432 OCI_CHECK_PTR(OCI_IPC_STATEMENT, stmt, FALSE); 00433 00434 OCI_CHECK_STMT_STATUS(stmt, OCI_STMT_PREPARED, FALSE); 00435 00436 #if OCI_VERSION_COMPILE >= OCI_10_2 00437 00438 /* register the statement query if provided */ 00439 00440 if (sub->type & OCI_CNT_OBJECTS) 00441 { 00442 OCI_CALL3 00443 ( 00444 res, sub->err, 00445 00446 OCIAttrSet((dvoid *) stmt->stmt, (ub4) OCI_HTYPE_STMT, 00447 (dvoid *) sub->subhp, (ub4) 0, 00448 (ub4) OCI_ATTR_CHNF_REGHANDLE, sub->err) 00449 ) 00450 00451 res = res && OCI_Execute(stmt) && (OCI_GetResultset(stmt) != NULL); 00452 } 00453 00454 #endif 00455 00456 OCI_RESULT(res); 00457 00458 return res; 00459 } 00460 00461 /* --------------------------------------------------------------------------------------------- * 00462 * OCI_SubscriptionGetName 00463 * --------------------------------------------------------------------------------------------- */ 00464 00465 const mtext * OCI_API OCI_SubscriptionGetName 00466 ( 00467 OCI_Subscription *sub 00468 ) 00469 { 00470 OCI_CHECK_PTR(OCI_IPC_NOTIFY, sub, NULL); 00471 00472 OCI_RESULT(TRUE); 00473 00474 return sub->name; 00475 } 00476 00477 /* --------------------------------------------------------------------------------------------- * 00478 * OCI_SubscriptionGetPort 00479 * --------------------------------------------------------------------------------------------- */ 00480 00481 unsigned int OCI_API OCI_SubscriptionGetPort 00482 ( 00483 OCI_Subscription *sub 00484 ) 00485 { 00486 OCI_CHECK_PTR(OCI_IPC_NOTIFY, sub, 0); 00487 00488 OCI_RESULT(TRUE); 00489 00490 return sub->port; 00491 } 00492 00493 /* --------------------------------------------------------------------------------------------- * 00494 * OCI_SubscriptionGetTimeout 00495 * --------------------------------------------------------------------------------------------- */ 00496 00497 unsigned int OCI_API OCI_SubscriptionGetTimeout 00498 ( 00499 OCI_Subscription *sub 00500 ) 00501 { 00502 OCI_CHECK_PTR(OCI_IPC_NOTIFY, sub, 0); 00503 00504 OCI_RESULT(TRUE); 00505 00506 return sub->timeout; 00507 } 00508