Main Page | Class Hierarchy | Data Structures | Directories | File List | Data Fields | Related Pages

tcl_txn.c

00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 1999-2005
00005  *      Sleepycat Software.  All rights reserved.
00006  *
00007  * $Id: tcl_txn.c,v 12.8 2005/11/02 20:22:25 bostic Exp $
00008  */
00009 
00010 #include "db_config.h"
00011 
00012 #ifndef NO_SYSTEM_INCLUDES
00013 #include <sys/types.h>
00014 
00015 #include <stdlib.h>
00016 #include <string.h>
00017 #include <tcl.h>
00018 #endif
00019 
00020 #include "db_int.h"
00021 #include "dbinc/tcl_db.h"
00022 
00023 static int tcl_TxnCommit __P((Tcl_Interp *,
00024                int, Tcl_Obj * CONST *, DB_TXN *, DBTCL_INFO *));
00025 static int txn_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST *));
00026 
00027 /*
00028  * _TxnInfoDelete --
00029  *      Removes nested txn info structures that are children
00030  *      of this txn.
00031  *      RECURSIVE:  Transactions can be arbitrarily nested, so we
00032  *      must recurse down until we get them all.
00033  *
00034  * PUBLIC: void _TxnInfoDelete __P((Tcl_Interp *, DBTCL_INFO *));
00035  */
00036 void
00037 _TxnInfoDelete(interp, txnip)
00038         Tcl_Interp *interp;             /* Interpreter */
00039         DBTCL_INFO *txnip;              /* Info for txn */
00040 {
00041         DBTCL_INFO *nextp, *p;
00042 
00043         for (p = LIST_FIRST(&__db_infohead); p != NULL; p = nextp) {
00044                 /*
00045                  * Check if this info structure "belongs" to this
00046                  * txn.  Remove its commands and info structure.
00047                  */
00048                 nextp = LIST_NEXT(p, entries);
00049                 if (p->i_parent == txnip && p->i_type == I_TXN) {
00050                         _TxnInfoDelete(interp, p);
00051                         (void)Tcl_DeleteCommand(interp, p->i_name);
00052                         _DeleteInfo(p);
00053                 }
00054         }
00055 }
00056 
00057 /*
00058  * tcl_TxnCheckpoint --
00059  *
00060  * PUBLIC: int tcl_TxnCheckpoint __P((Tcl_Interp *, int,
00061  * PUBLIC:    Tcl_Obj * CONST*, DB_ENV *));
00062  */
00063 int
00064 tcl_TxnCheckpoint(interp, objc, objv, envp)
00065         Tcl_Interp *interp;             /* Interpreter */
00066         int objc;                       /* How many arguments? */
00067         Tcl_Obj *CONST objv[];          /* The argument objects */
00068         DB_ENV *envp;                   /* Environment pointer */
00069 {
00070         static const char *txnckpopts[] = {
00071                 "-force",
00072                 "-kbyte",
00073                 "-min",
00074                 NULL
00075         };
00076         enum txnckpopts {
00077                 TXNCKP_FORCE,
00078                 TXNCKP_KB,
00079                 TXNCKP_MIN
00080         };
00081         u_int32_t flags;
00082         int i, kb, min, optindex, result, ret;
00083 
00084         result = TCL_OK;
00085         flags = 0;
00086         kb = min = 0;
00087 
00088         /*
00089          * Get the flag index from the object based on the options
00090          * defined above.
00091          */
00092         i = 2;
00093         while (i < objc) {
00094                 if (Tcl_GetIndexFromObj(interp, objv[i],
00095                     txnckpopts, "option", TCL_EXACT, &optindex) != TCL_OK) {
00096                         return (IS_HELP(objv[i]));
00097                 }
00098                 i++;
00099                 switch ((enum txnckpopts)optindex) {
00100                 case TXNCKP_FORCE:
00101                         flags = DB_FORCE;
00102                         break;
00103                 case TXNCKP_KB:
00104                         if (i == objc) {
00105                                 Tcl_WrongNumArgs(interp, 2, objv,
00106                                     "?-kbyte kb?");
00107                                 result = TCL_ERROR;
00108                                 break;
00109                         }
00110                         result = Tcl_GetIntFromObj(interp, objv[i++], &kb);
00111                         break;
00112                 case TXNCKP_MIN:
00113                         if (i == objc) {
00114                                 Tcl_WrongNumArgs(interp, 2, objv, "?-min min?");
00115                                 result = TCL_ERROR;
00116                                 break;
00117                         }
00118                         result = Tcl_GetIntFromObj(interp, objv[i++], &min);
00119                         break;
00120                 }
00121         }
00122         _debug_check();
00123         ret = envp->txn_checkpoint(envp, (u_int32_t)kb, (u_int32_t)min, flags);
00124         result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
00125             "txn checkpoint");
00126         return (result);
00127 }
00128 
00129 /*
00130  * tcl_Txn --
00131  *
00132  * PUBLIC: int tcl_Txn __P((Tcl_Interp *, int,
00133  * PUBLIC:    Tcl_Obj * CONST*, DB_ENV *, DBTCL_INFO *));
00134  */
00135 int
00136 tcl_Txn(interp, objc, objv, envp, envip)
00137         Tcl_Interp *interp;             /* Interpreter */
00138         int objc;                       /* How many arguments? */
00139         Tcl_Obj *CONST objv[];          /* The argument objects */
00140         DB_ENV *envp;                   /* Environment pointer */
00141         DBTCL_INFO *envip;              /* Info pointer */
00142 {
00143         static const char *txnopts[] = {
00144 #ifdef CONFIG_TEST
00145                 "-lock_timeout",
00146                 "-read_committed",
00147                 "-read_uncommitted",
00148                 "-txn_timeout",
00149 #endif
00150                 "-nosync",
00151                 "-nowait",
00152                 "-parent",
00153                 "-sync",
00154                 "-wrnosync",
00155                 NULL
00156         };
00157         enum txnopts {
00158 #ifdef CONFIG_TEST
00159                 TXNLOCK_TIMEOUT,
00160                 TXNREAD_COMMITTED,
00161                 TXNREAD_UNCOMMITTED,
00162                 TXNTIMEOUT,
00163 #endif
00164                 TXNNOSYNC,
00165                 TXNNOWAIT,
00166                 TXNPARENT,
00167                 TXNSYNC,
00168                 TXNWRNOSYNC
00169         };
00170         DBTCL_INFO *ip;
00171         DB_TXN *parent;
00172         DB_TXN *txn;
00173         Tcl_Obj *res;
00174         u_int32_t flag;
00175         int i, optindex, result, ret;
00176         char *arg, msg[MSG_SIZE], newname[MSG_SIZE];
00177 #ifdef CONFIG_TEST
00178         db_timeout_t lk_time, tx_time;
00179         u_int32_t lk_timeflag, tx_timeflag;
00180 #endif
00181 
00182         result = TCL_OK;
00183         memset(newname, 0, MSG_SIZE);
00184 
00185         parent = NULL;
00186         flag = 0;
00187 #ifdef CONFIG_TEST
00188         COMPQUIET(tx_time, 0);
00189         COMPQUIET(lk_time, 0);
00190         lk_timeflag = tx_timeflag = 0;
00191 #endif
00192         i = 2;
00193         while (i < objc) {
00194                 if (Tcl_GetIndexFromObj(interp, objv[i],
00195                     txnopts, "option", TCL_EXACT, &optindex) != TCL_OK) {
00196                         return (IS_HELP(objv[i]));
00197                 }
00198                 i++;
00199                 switch ((enum txnopts)optindex) {
00200 #ifdef CONFIG_TEST
00201                 case TXNLOCK_TIMEOUT:
00202                         lk_timeflag = DB_SET_LOCK_TIMEOUT;
00203                         goto get_timeout;
00204                 case TXNTIMEOUT:
00205                         tx_timeflag = DB_SET_TXN_TIMEOUT;
00206 get_timeout:            if (i >= objc) {
00207                                 Tcl_WrongNumArgs(interp, 2, objv,
00208                                     "?-txn_timestamp time?");
00209                                 return (TCL_ERROR);
00210                         }
00211                         result = Tcl_GetLongFromObj(interp, objv[i++], (long *)
00212                             ((enum txnopts)optindex == TXNLOCK_TIMEOUT ?
00213                             &lk_time : &tx_time));
00214                         if (result != TCL_OK)
00215                                 return (TCL_ERROR);
00216                         break;
00217                 case TXNREAD_COMMITTED:
00218                         flag |= DB_READ_COMMITTED;
00219                         break;
00220                 case TXNREAD_UNCOMMITTED:
00221                         flag |= DB_READ_UNCOMMITTED;
00222                         break;
00223 #endif
00224                 case TXNNOSYNC:
00225                         flag |= DB_TXN_NOSYNC;
00226                         break;
00227                 case TXNNOWAIT:
00228                         flag |= DB_TXN_NOWAIT;
00229                         break;
00230                 case TXNPARENT:
00231                         if (i == objc) {
00232                                 Tcl_WrongNumArgs(interp, 2, objv,
00233                                     "?-parent txn?");
00234                                 result = TCL_ERROR;
00235                                 break;
00236                         }
00237                         arg = Tcl_GetStringFromObj(objv[i++], NULL);
00238                         parent = NAME_TO_TXN(arg);
00239                         if (parent == NULL) {
00240                                 snprintf(msg, MSG_SIZE,
00241                                     "Invalid parent txn: %s\n",
00242                                     arg);
00243                                 Tcl_SetResult(interp, msg, TCL_VOLATILE);
00244                                 return (TCL_ERROR);
00245                         }
00246                         break;
00247                 case TXNSYNC:
00248                         flag |= DB_TXN_SYNC;
00249                         break;
00250                 case TXNWRNOSYNC:
00251                         flag |= DB_TXN_WRITE_NOSYNC;
00252                         break;
00253                 }
00254         }
00255         snprintf(newname, sizeof(newname), "%s.txn%d",
00256             envip->i_name, envip->i_envtxnid);
00257         ip = _NewInfo(interp, NULL, newname, I_TXN);
00258         if (ip == NULL) {
00259                 Tcl_SetResult(interp, "Could not set up info",
00260                     TCL_STATIC);
00261                 return (TCL_ERROR);
00262         }
00263         _debug_check();
00264         ret = envp->txn_begin(envp, parent, &txn, flag);
00265         result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
00266             "txn");
00267         if (result == TCL_ERROR)
00268                 _DeleteInfo(ip);
00269         else {
00270                 /*
00271                  * Success.  Set up return.  Set up new info
00272                  * and command widget for this txn.
00273                  */
00274                 envip->i_envtxnid++;
00275                 if (parent)
00276                         ip->i_parent = _PtrToInfo(parent);
00277                 else
00278                         ip->i_parent = envip;
00279                 _SetInfoData(ip, txn);
00280                 (void)Tcl_CreateObjCommand(interp, newname,
00281                     (Tcl_ObjCmdProc *)txn_Cmd, (ClientData)txn, NULL);
00282                 res = NewStringObj(newname, strlen(newname));
00283                 Tcl_SetObjResult(interp, res);
00284 #ifdef CONFIG_TEST
00285                 if (tx_timeflag != 0) {
00286                         ret = txn->set_timeout(txn, tx_time, tx_timeflag);
00287                         if (ret != 0) {
00288                                 result =
00289                                     _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
00290                                         "set_timeout");
00291                                 _DeleteInfo(ip);
00292                         }
00293                 }
00294                 if (lk_timeflag != 0) {
00295                         ret = txn->set_timeout(txn, lk_time, lk_timeflag);
00296                         if (ret != 0) {
00297                                 result =
00298                                     _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
00299                                         "set_timeout");
00300                                 _DeleteInfo(ip);
00301                         }
00302                 }
00303 #endif
00304         }
00305         return (result);
00306 }
00307 
00308 /*
00309  * tcl_TxnStat --
00310  *
00311  * PUBLIC: int tcl_TxnStat __P((Tcl_Interp *, int,
00312  * PUBLIC:    Tcl_Obj * CONST*, DB_ENV *));
00313  */
00314 int
00315 tcl_TxnStat(interp, objc, objv, envp)
00316         Tcl_Interp *interp;             /* Interpreter */
00317         int objc;                       /* How many arguments? */
00318         Tcl_Obj *CONST objv[];          /* The argument objects */
00319         DB_ENV *envp;                   /* Environment pointer */
00320 {
00321         DBTCL_INFO *ip;
00322         DB_TXN_ACTIVE *p;
00323         DB_TXN_STAT *sp;
00324         Tcl_Obj *myobjv[2], *res, *thislist, *lsnlist;
00325         u_int32_t i;
00326         int myobjc, result, ret;
00327 
00328         result = TCL_OK;
00329         /*
00330          * No args for this.  Error if there are some.
00331          */
00332         if (objc != 2) {
00333                 Tcl_WrongNumArgs(interp, 2, objv, NULL);
00334                 return (TCL_ERROR);
00335         }
00336         _debug_check();
00337         ret = envp->txn_stat(envp, &sp, 0);
00338         result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
00339             "txn stat");
00340         if (result == TCL_ERROR)
00341                 return (result);
00342 
00343         /*
00344          * Have our stats, now construct the name value
00345          * list pairs and free up the memory.
00346          */
00347         res = Tcl_NewObj();
00348         /*
00349          * MAKE_STAT_LIST assumes 'res' and 'error' label.
00350          */
00351         MAKE_STAT_LIST("Region size", sp->st_regsize);
00352         MAKE_STAT_LSN("LSN of last checkpoint", &sp->st_last_ckp);
00353         MAKE_STAT_LIST("Time of last checkpoint", sp->st_time_ckp);
00354         MAKE_STAT_LIST("Last txn ID allocated", sp->st_last_txnid);
00355         MAKE_STAT_LIST("Max Txns", sp->st_maxtxns);
00356         MAKE_STAT_LIST("Number aborted txns", sp->st_naborts);
00357         MAKE_STAT_LIST("Number active txns", sp->st_nactive);
00358         MAKE_STAT_LIST("Maximum  active txns", sp->st_maxnactive);
00359         MAKE_STAT_LIST("Number txns begun", sp->st_nbegins);
00360         MAKE_STAT_LIST("Number committed txns", sp->st_ncommits);
00361         MAKE_STAT_LIST("Number restored txns", sp->st_nrestores);
00362         MAKE_STAT_LIST("Number of region lock waits", sp->st_region_wait);
00363         MAKE_STAT_LIST("Number of region lock nowaits", sp->st_region_nowait);
00364         for (i = 0, p = sp->st_txnarray; i < sp->st_nactive; i++, p++)
00365                 for (ip = LIST_FIRST(&__db_infohead); ip != NULL;
00366                     ip = LIST_NEXT(ip, entries)) {
00367                         if (ip->i_type != I_TXN)
00368                                 continue;
00369                         if (ip->i_type == I_TXN &&
00370                             (ip->i_txnp->id(ip->i_txnp) == p->txnid)) {
00371                                 MAKE_STAT_LSN(ip->i_name, &p->lsn);
00372                                 if (p->parentid != 0)
00373                                         MAKE_STAT_STRLIST("Parent",
00374                                             ip->i_parent->i_name);
00375                                 else
00376                                         MAKE_STAT_LIST("Parent", 0);
00377                                 break;
00378                         }
00379                 }
00380         Tcl_SetObjResult(interp, res);
00381 error:
00382         __os_ufree(envp, sp);
00383         return (result);
00384 }
00385 
00386 /*
00387  * tcl_TxnTimeout --
00388  *
00389  * PUBLIC: int tcl_TxnTimeout __P((Tcl_Interp *, int,
00390  * PUBLIC:    Tcl_Obj * CONST*, DB_ENV *));
00391  */
00392 int
00393 tcl_TxnTimeout(interp, objc, objv, envp)
00394         Tcl_Interp *interp;             /* Interpreter */
00395         int objc;                       /* How many arguments? */
00396         Tcl_Obj *CONST objv[];          /* The argument objects */
00397         DB_ENV *envp;                   /* Environment pointer */
00398 {
00399         long timeout;
00400         int result, ret;
00401 
00402         /*
00403          * One arg, the timeout.
00404          */
00405         if (objc != 3) {
00406                 Tcl_WrongNumArgs(interp, 2, objv, "?timeout?");
00407                 return (TCL_ERROR);
00408         }
00409         result = Tcl_GetLongFromObj(interp, objv[2], &timeout);
00410         if (result != TCL_OK)
00411                 return (result);
00412         _debug_check();
00413         ret = envp->set_timeout(envp, (u_int32_t)timeout, DB_SET_TXN_TIMEOUT);
00414         result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
00415             "lock timeout");
00416         return (result);
00417 }
00418 
00419 /*
00420  * txn_Cmd --
00421  *      Implements the "txn" widget.
00422  */
00423 static int
00424 txn_Cmd(clientData, interp, objc, objv)
00425         ClientData clientData;          /* Txn handle */
00426         Tcl_Interp *interp;             /* Interpreter */
00427         int objc;                       /* How many arguments? */
00428         Tcl_Obj *CONST objv[];          /* The argument objects */
00429 {
00430         static const char *txncmds[] = {
00431 #ifdef CONFIG_TEST
00432                 "discard",
00433                 "getname",
00434                 "id",
00435                 "prepare",
00436                 "setname",
00437 #endif
00438                 "abort",
00439                 "commit",
00440                 "getname",
00441                 "setname",
00442                 NULL
00443         };
00444         enum txncmds {
00445 #ifdef CONFIG_TEST
00446                 TXNDISCARD,
00447                 TXNGETNAME,
00448                 TXNID,
00449                 TXNPREPARE,
00450                 TXNSETNAME,
00451 #endif
00452                 TXNABORT,
00453                 TXNCOMMIT
00454         };
00455         DBTCL_INFO *txnip;
00456         DB_TXN *txnp;
00457         Tcl_Obj *res;
00458         int cmdindex, result, ret;
00459 #ifdef CONFIG_TEST
00460         u_int8_t *gid, garray[DB_XIDDATASIZE];
00461         int length;
00462         const char *name;
00463 #endif
00464 
00465         Tcl_ResetResult(interp);
00466         txnp = (DB_TXN *)clientData;
00467         txnip = _PtrToInfo((void *)txnp);
00468         result = TCL_OK;
00469         if (txnp == NULL) {
00470                 Tcl_SetResult(interp, "NULL txn pointer", TCL_STATIC);
00471                 return (TCL_ERROR);
00472         }
00473         if (txnip == NULL) {
00474                 Tcl_SetResult(interp, "NULL txn info pointer", TCL_STATIC);
00475                 return (TCL_ERROR);
00476         }
00477 
00478         /*
00479          * Get the command name index from the object based on the dbcmds
00480          * defined above.
00481          */
00482         if (Tcl_GetIndexFromObj(interp,
00483             objv[1], txncmds, "command", TCL_EXACT, &cmdindex) != TCL_OK)
00484                 return (IS_HELP(objv[1]));
00485 
00486         res = NULL;
00487         switch ((enum txncmds)cmdindex) {
00488 #ifdef CONFIG_TEST
00489         case TXNDISCARD:
00490                 if (objc != 2) {
00491                         Tcl_WrongNumArgs(interp, 1, objv, NULL);
00492                         return (TCL_ERROR);
00493                 }
00494                 _debug_check();
00495                 ret = txnp->discard(txnp, 0);
00496                 result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
00497                     "txn discard");
00498                 _TxnInfoDelete(interp, txnip);
00499                 (void)Tcl_DeleteCommand(interp, txnip->i_name);
00500                 _DeleteInfo(txnip);
00501                 break;
00502         case TXNID:
00503                 if (objc != 2) {
00504                         Tcl_WrongNumArgs(interp, 1, objv, NULL);
00505                         return (TCL_ERROR);
00506                 }
00507                 _debug_check();
00508                 res = Tcl_NewIntObj((int)txnp->id(txnp));
00509                 break;
00510         case TXNPREPARE:
00511                 if (objc != 3) {
00512                         Tcl_WrongNumArgs(interp, 1, objv, NULL);
00513                         return (TCL_ERROR);
00514                 }
00515                 _debug_check();
00516                 gid = (u_int8_t *)Tcl_GetByteArrayFromObj(objv[2], &length);
00517                 memcpy(garray, gid, (size_t)length);
00518                 ret = txnp->prepare(txnp, garray);
00519                 /*
00520                  * !!!
00521                  * DB_TXN->prepare commits all outstanding children.  But it
00522                  * does NOT destroy the current txn handle.  So, we must call
00523                  * _TxnInfoDelete to recursively remove all nested txn handles,
00524                  * we do not call _DeleteInfo on ourselves.
00525                  */
00526                 _TxnInfoDelete(interp, txnip);
00527                 result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
00528                     "txn prepare");
00529                 break;
00530         case TXNGETNAME:
00531                 if (objc != 2) {
00532                         Tcl_WrongNumArgs(interp, 2, objv, NULL);
00533                         return (TCL_ERROR);
00534                 }
00535                 _debug_check();
00536                 ret = txnp->get_name(txnp, &name);
00537                 if ((result = _ReturnSetup(
00538                     interp, ret, DB_RETOK_STD(ret), "txn getname")) == TCL_OK)
00539                         res = NewStringObj(name, strlen(name));
00540                 break;
00541         case TXNSETNAME:
00542                 if (objc != 3) {
00543                         Tcl_WrongNumArgs(interp, 2, objv, "name");
00544                         return (TCL_ERROR);
00545                 }
00546                 _debug_check();
00547                 ret = txnp->set_name(txnp, Tcl_GetStringFromObj(objv[2], NULL));
00548                 result =
00549                     _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "setname");
00550                 break;
00551 #endif
00552         case TXNABORT:
00553                 if (objc != 2) {
00554                         Tcl_WrongNumArgs(interp, 1, objv, NULL);
00555                         return (TCL_ERROR);
00556                 }
00557                 _debug_check();
00558                 ret = txnp->abort(txnp);
00559                 result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
00560                     "txn abort");
00561                 _TxnInfoDelete(interp, txnip);
00562                 (void)Tcl_DeleteCommand(interp, txnip->i_name);
00563                 _DeleteInfo(txnip);
00564                 break;
00565         case TXNCOMMIT:
00566                 result = tcl_TxnCommit(interp, objc, objv, txnp, txnip);
00567                 _TxnInfoDelete(interp, txnip);
00568                 (void)Tcl_DeleteCommand(interp, txnip->i_name);
00569                 _DeleteInfo(txnip);
00570                 break;
00571         }
00572         /*
00573          * Only set result if we have a res.  Otherwise, lower
00574          * functions have already done so.
00575          */
00576         if (result == TCL_OK && res)
00577                 Tcl_SetObjResult(interp, res);
00578         return (result);
00579 }
00580 
00581 static int
00582 tcl_TxnCommit(interp, objc, objv, txnp, txnip)
00583         Tcl_Interp *interp;             /* Interpreter */
00584         int objc;                       /* How many arguments? */
00585         Tcl_Obj *CONST objv[];          /* The argument objects */
00586         DB_TXN *txnp;                   /* Transaction pointer */
00587         DBTCL_INFO *txnip;              /* Info pointer */
00588 {
00589         static const char *commitopt[] = {
00590                 "-nosync",
00591                 "-sync",
00592                 "-wrnosync",
00593                 NULL
00594         };
00595         enum commitopt {
00596                 COMNOSYNC,
00597                 COMSYNC,
00598                 COMWRNOSYNC
00599         };
00600         u_int32_t flag;
00601         int optindex, result, ret;
00602 
00603         COMPQUIET(txnip, NULL);
00604 
00605         result = TCL_OK;
00606         flag = 0;
00607         if (objc != 2 && objc != 3) {
00608                 Tcl_WrongNumArgs(interp, 1, objv, NULL);
00609                 return (TCL_ERROR);
00610         }
00611         if (objc == 3) {
00612                 if (Tcl_GetIndexFromObj(interp, objv[2], commitopt,
00613                     "option", TCL_EXACT, &optindex) != TCL_OK)
00614                         return (IS_HELP(objv[2]));
00615                 switch ((enum commitopt)optindex) {
00616                 case COMSYNC:
00617                         flag = DB_TXN_SYNC;
00618                         break;
00619                 case COMNOSYNC:
00620                         flag = DB_TXN_NOSYNC;
00621                         break;
00622                 case COMWRNOSYNC:
00623                         flag = DB_TXN_WRITE_NOSYNC;
00624                         break;
00625                 }
00626         }
00627 
00628         _debug_check();
00629         ret = txnp->commit(txnp, flag);
00630         result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
00631             "txn commit");
00632         return (result);
00633 }
00634 
00635 #ifdef CONFIG_TEST
00636 /*
00637  * tcl_TxnRecover --
00638  *
00639  * PUBLIC: int tcl_TxnRecover __P((Tcl_Interp *, int,
00640  * PUBLIC:    Tcl_Obj * CONST*, DB_ENV *, DBTCL_INFO *));
00641  */
00642 int
00643 tcl_TxnRecover(interp, objc, objv, envp, envip)
00644         Tcl_Interp *interp;             /* Interpreter */
00645         int objc;                       /* How many arguments? */
00646         Tcl_Obj *CONST objv[];          /* The argument objects */
00647         DB_ENV *envp;                   /* Environment pointer */
00648         DBTCL_INFO *envip;              /* Info pointer */
00649 {
00650 #define DO_PREPLIST(count)                                              \
00651 for (i = 0; i < count; i++) {                                           \
00652         snprintf(newname, sizeof(newname), "%s.txn%d",                  \
00653             envip->i_name, envip->i_envtxnid);                          \
00654         ip = _NewInfo(interp, NULL, newname, I_TXN);                    \
00655         if (ip == NULL) {                                               \
00656                 Tcl_SetResult(interp, "Could not set up info",          \
00657                     TCL_STATIC);                                        \
00658                 return (TCL_ERROR);                                     \
00659         }                                                               \
00660         envip->i_envtxnid++;                                            \
00661         ip->i_parent = envip;                                           \
00662         p = &prep[i];                                                   \
00663         _SetInfoData(ip, p->txn);                                       \
00664         (void)Tcl_CreateObjCommand(interp, newname,                     \
00665             (Tcl_ObjCmdProc *)txn_Cmd, (ClientData)p->txn, NULL);       \
00666         result = _SetListElem(interp, res, newname, strlen(newname),    \
00667             p->gid, DB_XIDDATASIZE);                                    \
00668         if (result != TCL_OK)                                           \
00669                 goto error;                                             \
00670 }
00671 
00672         DBTCL_INFO *ip;
00673         DB_PREPLIST prep[DBTCL_PREP], *p;
00674         Tcl_Obj *res;
00675         long count, i;
00676         int result, ret;
00677         char newname[MSG_SIZE];
00678 
00679         result = TCL_OK;
00680         /*
00681          * No args for this.  Error if there are some.
00682          */
00683         if (objc != 2) {
00684                 Tcl_WrongNumArgs(interp, 2, objv, NULL);
00685                 return (TCL_ERROR);
00686         }
00687         _debug_check();
00688         ret = envp->txn_recover(envp, prep, DBTCL_PREP, &count, DB_FIRST);
00689         result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
00690             "txn recover");
00691         if (result == TCL_ERROR)
00692                 return (result);
00693         res = Tcl_NewObj();
00694         DO_PREPLIST(count);
00695 
00696         /*
00697          * If count returned is the maximum size we have, then there
00698          * might be more.  Keep going until we get them all.
00699          */
00700         while (count == DBTCL_PREP) {
00701                 ret = envp->txn_recover(
00702                     envp, prep, DBTCL_PREP, &count, DB_NEXT);
00703                 result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
00704                     "txn recover");
00705                 if (result == TCL_ERROR)
00706                         return (result);
00707                 DO_PREPLIST(count);
00708         }
00709         Tcl_SetObjResult(interp, res);
00710 error:
00711         return (result);
00712 }
00713 #endif

Generated on Sun Dec 25 12:14:52 2005 for Berkeley DB 4.4.16 by  doxygen 1.4.2