OCILIB (C Driver for Oracle) 3.12.1
callback.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-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: callback.c, Vincent Rogier $
00033  * --------------------------------------------------------------------------------------------- */
00034 
00035 #include "ocilib_internal.h"
00036 
00037 /* ********************************************************************************************* *
00038  *                             PRIVATE FUNCTIONS
00039  * ********************************************************************************************* */
00040 
00041 /* --------------------------------------------------------------------------------------------- *
00042  * OCI_ProcInBind
00043  * --------------------------------------------------------------------------------------------- */
00044 
00045 sb4 OCI_ProcInBind
00046 (
00047     dvoid   *ictxp,
00048     OCIBind *bindp,
00049     ub4      iter,
00050     ub4      index,
00051     dvoid  **bufpp,
00052     ub4     *alenp,
00053     ub1     *piecep,
00054     dvoid  **indp
00055 )
00056 {
00057     OCI_Bind * bnd = (OCI_Bind *) ictxp;
00058     sb2 *ind       = (sb2 *) bnd->buf.inds;
00059     ub4 i          = 0;
00060 
00061     /* those checks may be not necessary but they keep away compilers warning
00062        away if the warning level is set to maximum !
00063     */
00064 
00065     OCI_NOT_USED(index);
00066     OCI_NOT_USED(bindp);
00067 
00068     /* check objects and bounds */
00069 
00070     OCI_CHECK(bnd  == NULL, OCI_ERROR);
00071     OCI_CHECK(iter >= bnd->buf.count, OCI_ERROR);
00072 
00073     /* indicators must be set to -1 depending on datatype,
00074        so let's do it for all */
00075 
00076     for (i = 0; i < bnd->buf.count; i++, ind++)
00077     {
00078         *ind = -1;
00079     }
00080 
00081     /* setup bind index because OCI_RegisterXXX() might not have been called
00082        in the same order than the variables in the returning clause */
00083 
00084     if (iter == 0)
00085     {
00086         bnd->dynpos = bnd->stmt->dynidx++;
00087     }
00088 
00089     /* we do not need to do anything here except setting indicators */
00090 
00091     *bufpp  = (dvoid *) 0;
00092     *alenp  = (ub4    ) 0;
00093     *indp   = (dvoid *) bnd->buf.inds;
00094     *piecep = (ub1    ) OCI_ONE_PIECE;
00095 
00096     return OCI_CONTINUE;
00097 }
00098 
00099 /* --------------------------------------------------------------------------------------------- *
00100  * OCI_ProcOutBind
00101  * --------------------------------------------------------------------------------------------- */
00102 
00103 sb4 OCI_ProcOutBind
00104 (
00105     dvoid   *octxp,
00106     OCIBind *bindp,
00107     ub4      iter,
00108     ub4      index,
00109     dvoid  **bufpp,
00110     ub4    **alenp,
00111     ub1     *piecep,
00112     dvoid  **indp,
00113     ub2    **rcodep
00114 )
00115 {
00116     OCI_Bind * bnd    = (OCI_Bind *) octxp;
00117     OCI_Define *def   = NULL;
00118     OCI_Resultset *rs = NULL;
00119     boolean res       = TRUE;
00120     ub4 rows          = 0;
00121 
00122     /* those checks may be not necessary but they keep away compilers warning
00123        away if the warning level is set to maximum !
00124     */
00125 
00126     OCI_NOT_USED(bindp);
00127 
00128     /* check objects and bounds */
00129 
00130     OCI_CHECK(bnd  == NULL, OCI_ERROR);
00131     OCI_CHECK(iter >= bnd->buf.count, OCI_ERROR);
00132 
00133     /* update statmement status */
00134 
00135     bnd->stmt->status |= OCI_STMT_EXECUTED;
00136 
00137     /* create resultset on the first row processed for each iteration */
00138 
00139     if (index == 0)
00140     {
00141         bnd->stmt->nb_rs  = bnd->stmt->nb_iters;
00142         bnd->stmt->cur_rs = 0;
00143 
00144         /* allocate resultset handles array */
00145 
00146         if (bnd->stmt->rsts == NULL)
00147         {
00148             bnd->stmt->rsts = (OCI_Resultset **) OCI_MemAlloc(OCI_IPC_RESULTSET_ARRAY,
00149                                                               sizeof(*bnd->stmt->rsts),
00150                                                               (size_t) bnd->stmt->nb_rs, TRUE);
00151 
00152             if (bnd->stmt->rsts == NULL)
00153             {
00154                 res = FALSE;
00155             }
00156         }
00157 
00158         /* create resultset as needed */
00159 
00160         if (res == TRUE && bnd->stmt->rsts[iter] == NULL)
00161         {
00162             OCI_CALL1
00163             (
00164                 res, bnd->stmt->con, bnd->stmt,
00165 
00166                 OCIAttrGet(bnd->buf.handle, (ub4) OCI_HTYPE_BIND, (void *) &rows, (ub4 *) NULL,
00167                            (ub4) OCI_ATTR_ROWS_RETURNED, bnd->stmt->con->err)
00168             )
00169 
00170             if (res == TRUE)
00171             {
00172                 bnd->stmt->rsts[iter] = OCI_ResultsetCreate(bnd->stmt, rows);
00173 
00174                 if (bnd->stmt->rsts[iter] != NULL)
00175                 {
00176                     bnd->stmt->rsts[iter]->row_count = rows;
00177                 }
00178             }
00179         }
00180     }
00181 
00182     OCI_CHECK(bnd->stmt->rsts == NULL, OCI_ERROR);
00183 
00184     rs = bnd->stmt->rsts[iter];
00185 
00186     OCI_CHECK(rs == NULL, OCI_ERROR);
00187 
00188     /* ok.. let's Oracle update its buffers */
00189 
00190     if (res == TRUE)
00191     {
00192         /* update pointers contents */
00193 
00194         def = &rs->defs[bnd->dynpos];
00195 
00196         switch (def->col.type)
00197         {
00198             case OCI_CDT_CURSOR:
00199             case OCI_CDT_TIMESTAMP:
00200             case OCI_CDT_INTERVAL:
00201             case OCI_CDT_LOB:
00202             case OCI_CDT_FILE:
00203             {
00204                 *bufpp = def->buf.data[index];
00205                 break;
00206             }
00207             default:
00208             {
00209                 *bufpp = (((ub1*)def->buf.data) + (size_t) (def->col.bufsize * index));
00210                 break;
00211             }
00212         }
00213 
00214         *alenp  = (ub4   *) (((ub1 *) def->buf.lens) + (size_t) ((ub4) def->buf.sizelen * index));
00215         *indp   = (dvoid *) (((ub1 *) def->buf.inds) + (size_t) ((ub4) sizeof(sb2)      * index));
00216         *piecep = (ub1    ) OCI_ONE_PIECE;
00217         *rcodep = (ub2   *) NULL;
00218     }
00219 
00220     return ((res == TRUE) ? OCI_CONTINUE : OCI_ERROR);
00221 }
00222 
00223 /* --------------------------------------------------------------------------------------------- *
00224  * OCI_ProcNotifyMessages
00225  * --------------------------------------------------------------------------------------------- */
00226 
00227 ub4 OCI_ProcNotifyMessages
00228 (
00229     void            *ctx,
00230     OCISubscription *subscrhp,
00231     void            *payload,
00232     ub4              paylen,
00233     void            *desc,
00234     ub4              mode
00235 )
00236 {
00237     OCI_Dequeue *dequeue = (OCI_Dequeue *) ctx;
00238 
00239     OCI_NOT_USED(paylen);
00240     OCI_NOT_USED(payload);
00241     OCI_NOT_USED(mode);
00242     OCI_NOT_USED(subscrhp);
00243     OCI_NOT_USED(desc);
00244 
00245     OCI_CHECK(dequeue == NULL, OCI_SUCCESS);
00246   
00247     dequeue->callback(dequeue);
00248     
00249     return OCI_SUCCESS;
00250 }
00251 
00252 /* --------------------------------------------------------------------------------------------- *
00253  * OCI_ProcNotifyChanges
00254  * --------------------------------------------------------------------------------------------- */
00255 
00256 ub4 OCI_ProcNotifyChanges
00257 (
00258     void            *ctx,
00259     OCISubscription *subscrhp,
00260     void            *payload,
00261     ub4              paylen,
00262     void            *desc,
00263     ub4              mode
00264 )
00265 {
00266     OCI_Subscription *sub = (OCI_Subscription *) ctx;
00267     boolean res           = TRUE;
00268     void *ostr            = NULL;
00269     int osize             = 0;
00270     ub4 type              = 0;
00271 
00272     OCI_NOT_USED(paylen);
00273     OCI_NOT_USED(payload);
00274     OCI_NOT_USED(mode);
00275     OCI_NOT_USED(subscrhp);
00276 
00277     OCI_CHECK(sub == NULL, OCI_SUCCESS);
00278 
00279     OCI_EventReset(&sub->event);
00280 
00281 #if OCI_VERSION_COMPILE >= OCI_10_2
00282 
00283     /* get database that generated the notification */
00284 
00285     OCI_CALL3
00286     (
00287         res, sub->err,
00288 
00289         OCIAttrGet((dvoid *) desc, (ub4) OCI_DTYPE_CHDES, (dvoid *) &ostr, (ub4 *) &osize,
00290                    (ub4) OCI_ATTR_CHDES_DBNAME, sub->err)
00291     )
00292 
00293     if ((res == TRUE) && (osize > (int) sub->event.dbname_size))
00294     {
00295         /* buffer is ANSI  */
00296 
00297         sub->event.dbname = (dtext *) OCI_MemRealloc(sub->event.dbname,  OCI_IPC_STRING,
00298                                                      sizeof(dtext), (size_t) (osize + 1));
00299 
00300         sub->event.dbname_size = osize;
00301     }
00302 
00303     OCI_CopyString(ostr, sub->event.dbname, &osize, sizeof(char), sizeof(dtext));
00304 
00305     /* get notification type */
00306 
00307     OCI_CALL3
00308     (
00309         res, sub->err,
00310 
00311         OCIAttrGet((dvoid *) desc, (ub4) OCI_DTYPE_CHDES,
00312                    (dvoid *) &type, (ub4 *) NULL,
00313                    (ub4) OCI_ATTR_CHDES_NFYTYPE, sub->err)
00314     )
00315 
00316     switch(type)
00317     {
00318         case OCI_EVENT_STARTUP:
00319         case OCI_EVENT_SHUTDOWN:
00320         case OCI_EVENT_SHUTDOWN_ANY:
00321         {
00322             if (sub->type & OCI_CNT_DATABASES)
00323             {
00324                 sub->event.type = type;
00325             }
00326 
00327             break;
00328         }
00329         case OCI_EVENT_DEREG:
00330         {
00331             sub->event.type = type;
00332             break;
00333         }
00334         case OCI_EVENT_OBJCHANGE:
00335         {
00336             if (sub->type & OCI_CNT_OBJECTS)
00337             {
00338                 sub->event.type = type;
00339             }
00340 
00341             break;
00342         }
00343         default:
00344         {
00345             break;
00346         }
00347     }
00348 
00349     /* for object, much work to do for retrieving data */
00350 
00351     if (sub->event.type == OCI_EVENT_OBJCHANGE)
00352     {
00353         OCIColl *tables = 0;
00354 
00355         /* get collection of modified tables */
00356 
00357         OCI_CALL3
00358         (
00359             res, sub->err,
00360 
00361             OCIAttrGet((dvoid *) desc, (ub4) OCI_DTYPE_CHDES, (dvoid *) &tables,
00362                        (ub4   *) NULL, (ub4) OCI_ATTR_CHDES_TABLE_CHANGES,  sub->err)
00363         )
00364 
00365         if (tables != NULL)
00366         {
00367             dvoid **tbl_elem  = NULL;
00368             dvoid  *tbl_ind   = NULL;
00369             boolean tbl_exist = FALSE;
00370             sb4     nb_tables = 0;
00371             sb4     nb_rows   = 0;
00372             sb4     i;
00373             
00374             /* get number of tables in the collection */
00375 
00376             OCI_CALL3
00377             (
00378                 res, sub->err,
00379 
00380                 OCICollSize(sub->env, sub->err, tables, &nb_tables)
00381             )
00382 
00383             for (i = 0; i < nb_tables; i++)
00384             {
00385                 nb_rows = 0;
00386 
00387                 /* partial reset of the event object  */
00388 
00389                 if (sub->event.objname != NULL)
00390                 {
00391                     sub->event.objname[0] = 0;
00392                 }
00393 
00394                 if (sub->event.rowid != NULL)
00395                 {
00396                     sub->event.rowid[0] = 0;
00397                 }
00398 
00399                 /* get table element */
00400 
00401                 OCI_CALL3
00402                 (
00403                     res, sub->err,
00404 
00405                     OCICollGetElem(sub->env, sub->err,  tables, i, &tbl_exist,
00406                                    (dvoid**) (dvoid*) &tbl_elem, (dvoid**) &tbl_ind)
00407                 )
00408 
00409                 /* get table name */
00410 
00411                 OCI_CALL3
00412                 (
00413                     res, sub->err,
00414 
00415                     OCIAttrGet((dvoid *) *tbl_elem,
00416                                (ub4) OCI_DTYPE_TABLE_CHDES,
00417                                (dvoid *) &ostr, (ub4 *) &osize,
00418                                (ub4) OCI_ATTR_CHDES_TABLE_NAME,
00419                                sub->err)
00420                 )
00421 
00422                 if(osize > (int) sub->event.objname_size)
00423                 {
00424                     /* buffer is ANSI  */
00425 
00426                     sub->event.objname = (dtext *) OCI_MemRealloc(sub->event.objname,
00427                                                                   OCI_IPC_STRING, sizeof(dtext),
00428                                                                   (size_t) (osize + 1));
00429 
00430                     sub->event.objname_size = osize;
00431                 }
00432 
00433                 OCI_CopyString(ostr, sub->event.objname, &osize, sizeof(char), sizeof(dtext));
00434 
00435                 /* get table modification type */
00436 
00437                 OCI_CALL3
00438                 (
00439                     res, sub->err,
00440 
00441                     OCIAttrGet((dvoid *) *tbl_elem, (ub4) OCI_DTYPE_TABLE_CHDES,
00442                                (dvoid *) &sub->event.op, (ub4*) NULL,
00443                                (ub4) OCI_ATTR_CHDES_TABLE_OPFLAGS, sub->err)
00444                 )
00445 
00446                 sub->event.op = sub->event.op & (~OCI_OPCODE_ALLROWS);
00447                 sub->event.op = sub->event.op & (~OCI_OPCODE_ALLOPS);
00448 
00449                 /* if requested, get row details */
00450 
00451                 if (sub->type & OCI_CNT_ROWS)
00452                 {
00453                     OCIColl *rows = 0;
00454 
00455                     /* get collection of modified rows */
00456 
00457                     OCI_CALL3
00458                     (
00459                         res, sub->err,
00460 
00461                         OCIAttrGet((dvoid *) *tbl_elem, (ub4) OCI_DTYPE_TABLE_CHDES,
00462                                    (dvoid *) &rows, (ub4 *) NULL,
00463                                    (ub4    ) OCI_ATTR_CHDES_TABLE_ROW_CHANGES, sub->err)
00464                     )
00465 
00466                     if (rows != NULL)
00467                     {
00468                         dvoid **row_elem  = NULL;
00469                         dvoid  *row_ind   = NULL;
00470                         boolean row_exist = FALSE;
00471                         sb4 j;
00472 
00473                         /* get number of rows */
00474 
00475                         OCI_CALL3
00476                         (
00477                             res, sub->err,
00478 
00479                             OCICollSize(sub->env, sub->err, rows, &nb_rows)
00480                         )
00481 
00482                         for (j = 0; j < nb_rows; j++)
00483                         {
00484                             /* partial reset of the event  */
00485 
00486                             if (sub->event.rowid != NULL)
00487                             {
00488                                 sub->event.rowid[0] = 0;
00489                             }
00490 
00491                             /* get row element */
00492 
00493                             OCI_CALL3
00494                             (
00495                                 res, sub->err,
00496 
00497                                 OCICollGetElem(sub->env, sub->err, rows, j, &row_exist,
00498                                                (dvoid**) (dvoid*) &row_elem, (dvoid**) &row_ind)
00499                             )
00500 
00501                             /* get rowid  */
00502 
00503                             OCI_CALL3
00504                             (
00505                                 res, sub->err,
00506 
00507                                 OCIAttrGet((dvoid *) *row_elem, (ub4) OCI_DTYPE_ROW_CHDES,
00508                                            (dvoid *) &ostr, (ub4 *) &osize,
00509                                            (ub4) OCI_ATTR_CHDES_ROW_ROWID, sub->err)
00510                             )
00511 
00512                             /* get opcode  */
00513 
00514                             OCI_CALL3
00515                             (
00516                                 res, sub->err,
00517 
00518                                 OCIAttrGet((dvoid *) *row_elem, (ub4) OCI_DTYPE_ROW_CHDES,
00519                                            &sub->event.op, (ub4*) NULL,
00520                                            (ub4) OCI_ATTR_CHDES_ROW_OPFLAGS, sub->err)
00521                             )
00522 
00523                             if(osize > (int) sub->event.rowid_size)
00524                             {
00525                                 /* buffer is ANSI  */
00526 
00527                                 sub->event.rowid = (dtext *) OCI_MemRealloc(sub->event.rowid,
00528                                                                             OCI_IPC_STRING,
00529                                                                             sizeof(dtext),
00530                                                                             (size_t) (osize + 1));
00531 
00532                                 sub->event.rowid_size = osize;
00533                             }
00534 
00535                             OCI_CopyString(ostr, sub->event.rowid, &osize,
00536                                            sizeof(char), sizeof(dtext));
00537 
00538                             sub->handler(&sub->event);
00539                         }
00540                     }
00541                 }
00542 
00543                 if (nb_rows == 0)
00544                 {
00545                     sub->handler(&sub->event);
00546                 }
00547             }
00548         }
00549     }
00550     else if (sub->event.type > 0)
00551     {
00552         sub->handler(&sub->event);
00553     }
00554 
00555 #else
00556 
00557     OCI_NOT_USED(ctx);
00558     OCI_NOT_USED(desc);
00559     OCI_NOT_USED(subscrhp);
00560 
00561     OCI_NOT_USED(res);
00562     OCI_NOT_USED(type);
00563     OCI_NOT_USED(ostr);
00564     OCI_NOT_USED(osize);
00565 
00566 #endif
00567 
00568     return OCI_SUCCESS;
00569 }
00570 
00571 /* --------------------------------------------------------------------------------------------- *
00572  * OCI_ProcFailOver
00573  * --------------------------------------------------------------------------------------------- */
00574 
00575 sb4 OCI_ProcFailOver
00576 (
00577     dvoid *svchp,
00578     dvoid *envhp,
00579     dvoid *fo_ctx,
00580     ub4    fo_type,
00581     ub4    fo_event
00582 )
00583 {
00584     OCI_Connection *cn = (OCI_Connection *) fo_ctx;
00585     sb4 ret = OCI_FOC_OK;
00586 
00587     OCI_NOT_USED(envhp);
00588     OCI_NOT_USED(svchp);
00589 
00590     if ((cn != NULL) && (cn->taf_handler != NULL))
00591     {
00592         ret = (sb4) cn->taf_handler(cn, fo_type, fo_event);
00593     }
00594 
00595     return ret;
00596 }
00597 
00598 /* --------------------------------------------------------------------------------------------- *
00599  * OCI_ProcHAEvent
00600  * --------------------------------------------------------------------------------------------- */
00601 
00602 void OCI_ProcHAEvent
00603 (
00604     dvoid     *evtctx,
00605     dvoid     *eventptr
00606 )
00607 {
00608     OCI_List       *list  = OCILib.cons;
00609     OCI_Item       *item  = NULL;
00610     OCIServer      *srvhp = NULL;
00611 
00612     OCI_NOT_USED(evtctx);
00613 
00614 #if OCI_VERSION_COMPILE >= OCI_10_2
00615 
00616     if ((list == NULL) || (OCILib.ha_handler == NULL))
00617     {
00618         return;    
00619     }    
00620     
00621     if (OCILib.version_runtime >= OCI_10_2)
00622     {
00623         OCIEvent        *eventhp = (OCIEvent *) eventptr;
00624         OCI_Timestamp   *tmsp    = NULL;
00625         sword            ret;
00626  
00627         ret = OCIAttrGet((dvoid **) eventhp, (ub4) OCI_HTYPE_SERVER, (dvoid *) &srvhp,
00628                          (ub4 *) NULL, (ub4) OCI_ATTR_HA_SRVFIRST, OCILib.err);
00629 
00630         while ((ret == OCI_SUCCESS) && (srvhp != NULL))
00631         {
00632             if (list->mutex != NULL)
00633             {
00634                 OCI_MutexAcquire(list->mutex);
00635             }
00636 
00637             item = list->head;
00638 
00639             /* for each item in the list, check the connection */
00640 
00641             while (item != NULL)
00642             {
00643                 OCI_Connection *con  = (OCI_Connection *) item->data;        
00644                 OCIDateTime    *dth  = NULL;
00645 
00646                 ub4 event  = OCI_HA_STATUS_DOWN;
00647                 ub4 source = OCI_HA_SOURCE_INSTANCE;
00648 
00649                 if ((con != NULL) && (con->svr == srvhp))
00650                 {
00651                     boolean res  = TRUE;
00652  
00653                     /* get event timestamp */
00654 
00655                     OCI_CALL2
00656                     (
00657                         res, con,
00658 
00659                         OCIAttrGet((dvoid **) eventhp, (ub4) OCI_HTYPE_SERVER, (dvoid *) &dth,
00660                                    (ub4 *) NULL,  (ub4) OCI_ATTR_HA_TIMESTAMP, con->err)
00661 
00662                     )
00663 
00664                     if (res == TRUE)
00665                     {
00666                         res = (OCI_TimestampInit(con, &tmsp, dth, OCI_TIMESTAMP) != NULL);
00667                     }
00668 
00669                     /* get status */
00670 
00671                     if (res == TRUE)
00672                     {
00673                         OCI_CALL2
00674                         (
00675                             res, con,
00676 
00677                             OCIAttrGet((dvoid **) eventhp, (ub4) OCI_HTYPE_SERVER, (dvoid *) &event,
00678                                        (ub4 *) NULL,  (ub4) OCI_ATTR_HA_STATUS, con->err)
00679 
00680                         )
00681                     }
00682 
00683                     /* get source */
00684 
00685                     if (res == TRUE)
00686                     {
00687                         OCI_CALL2
00688                         (
00689                             res, con,
00690 
00691                             OCIAttrGet((dvoid **) eventhp, (ub4) OCI_HTYPE_SERVER, (dvoid *) &source,
00692                                        (ub4 *) NULL,  (ub4) OCI_ATTR_HA_SOURCE, con->err)
00693 
00694                         )
00695                     }
00696 
00697                     /* on success, call the user callback */
00698 
00699                     if (res == TRUE)
00700                     {
00701                         OCILib.ha_handler(con, (unsigned int) source, (unsigned int) event, tmsp);
00702                     }
00703 
00704                     item = item->next;
00705                 }
00706             }
00707 
00708             if (list->mutex != NULL)
00709             {
00710                 OCI_MutexRelease(list->mutex);
00711             }
00712 
00713             ret = OCIAttrGet((dvoid **) srvhp, (ub4) OCI_HTYPE_SERVER, (dvoid *) &srvhp,
00714                              (ub4 *) NULL,  (ub4) OCI_ATTR_HA_SRVNEXT, OCILib.err);
00715 
00716         }
00717 
00718         /* free temporary timestamp object */
00719 
00720         if (tmsp != NULL)
00721         {
00722             tmsp->hstate = OCI_OBJECT_FETCHED_DIRTY;
00723             OCI_TimestampFree(tmsp);
00724         }
00725     }
00726 
00727 #else
00728 
00729     OCI_NOT_USED(eventptr);
00730     OCI_NOT_USED(list);
00731     OCI_NOT_USED(item);
00732     OCI_NOT_USED(srvhp);
00733 
00734 #endif
00735 
00736 }