OCILIB (C Driver for Oracle) 3.12.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-2013 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, 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 if (res == TRUE) 00210 { 00211 /* allocate subcription handle */ 00212 00213 res = (OCI_SUCCESS == OCI_HandleAlloc(con->env, 00214 (dvoid **) (void *) &sub->subhp, 00215 OCI_HTYPE_SUBSCRIPTION, (size_t) 0, 00216 (dvoid **) NULL)); 00217 } 00218 00219 if (res == TRUE) 00220 { 00221 ub4 attr = 0; 00222 int osize = -1; 00223 void *ostr = NULL; 00224 00225 sub->con = con; 00226 sub->env = con->env; 00227 sub->port = (ub4) port; 00228 sub->timeout = (ub4) timeout; 00229 sub->handler = handler; 00230 sub->type = type; 00231 sub->name = mtsdup(name); 00232 sub->event.sub = sub; 00233 00234 /* set/get port number */ 00235 00236 if (sub->port > 0) 00237 { 00238 OCI_CALL3 00239 ( 00240 res, sub->err, 00241 00242 OCIAttrSet((dvoid *) sub->subhp, (ub4) OCI_HTYPE_SUBSCRIPTION, 00243 (dvoid *) &sub->port, (ub4) sizeof (sub->port), 00244 (ub4) OCI_ATTR_SUBSCR_PORTNO, sub->err) 00245 ) 00246 } 00247 else 00248 { 00249 OCI_CALL3 00250 ( 00251 res, sub->err, 00252 00253 OCIAttrGet((dvoid *) sub->subhp, (ub4) OCI_HTYPE_SUBSCRIPTION, 00254 (dvoid *) &sub->port, (ub4) 0, 00255 (ub4) OCI_ATTR_SUBSCR_PORTNO, sub->err) 00256 ) 00257 } 00258 00259 /* set timeout */ 00260 00261 if(sub->timeout > 0) 00262 { 00263 OCI_CALL3 00264 ( 00265 res, sub->err, 00266 00267 OCIAttrSet((dvoid *) sub->subhp, (ub4) OCI_HTYPE_SUBSCRIPTION, 00268 (dvoid *) &sub->timeout, (ub4) sizeof (sub->timeout), 00269 (ub4) OCI_ATTR_SUBSCR_TIMEOUT, sub->err) 00270 ) 00271 } 00272 00273 /* name */ 00274 00275 ostr = OCI_GetInputMetaString(sub->name, &osize); 00276 00277 OCI_CALL3 00278 ( 00279 res, sub->err, 00280 00281 OCIAttrSet((dvoid *) sub->subhp, (ub4) OCI_HTYPE_SUBSCRIPTION, 00282 (dvoid *) ostr, (ub4) osize, 00283 (ub4) OCI_ATTR_SUBSCR_NAME, sub->err) 00284 ) 00285 00286 OCI_ReleaseMetaString(ostr); 00287 00288 /* namespace for CDN */ 00289 00290 attr = OCI_SUBSCR_NAMESPACE_DBCHANGE; 00291 00292 OCI_CALL3 00293 ( 00294 res, sub->err, 00295 00296 OCIAttrSet((dvoid *) sub->subhp, (ub4) OCI_HTYPE_SUBSCRIPTION, 00297 (dvoid *) &attr, (ub4) sizeof(attr), 00298 (ub4) OCI_ATTR_SUBSCR_NAMESPACE, sub->err) 00299 ) 00300 00301 /* protocol for CDN */ 00302 00303 attr = OCI_SUBSCR_PROTO_OCI; 00304 00305 OCI_CALL3 00306 ( 00307 res, sub->err, 00308 00309 OCIAttrSet((dvoid *) sub->subhp, (ub4) OCI_HTYPE_SUBSCRIPTION, 00310 (dvoid *) &attr, (ub4) sizeof(attr), 00311 (ub4) OCI_ATTR_SUBSCR_RECPTPROTO, sub->err) 00312 ) 00313 00314 /* internal callback handler */ 00315 00316 OCI_CALL3 00317 ( 00318 res, sub->err, 00319 00320 OCIAttrSet((dvoid *) sub->subhp, (ub4) OCI_HTYPE_SUBSCRIPTION, 00321 (dvoid *) OCI_ProcNotifyChanges, (ub4) 0, 00322 (ub4) OCI_ATTR_SUBSCR_CALLBACK, sub->err) 00323 ) 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