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

tcl_lock.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_lock.c,v 12.3 2005/10/28 19:40:27 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 /*
00024  * Prototypes for procedures defined later in this file:
00025  */
00026 #ifdef CONFIG_TEST
00027 static int      lock_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*));
00028 static int      _LockMode __P((Tcl_Interp *, Tcl_Obj *, db_lockmode_t *));
00029 static int      _GetThisLock __P((Tcl_Interp *, DB_ENV *, u_int32_t,
00030                                      u_int32_t, DBT *, db_lockmode_t, char *));
00031 static void     _LockPutInfo __P((Tcl_Interp *, db_lockop_t, DB_LOCK *,
00032                                      u_int32_t, DBT *));
00033 
00034 /*
00035  * tcl_LockDetect --
00036  *
00037  * PUBLIC: int tcl_LockDetect __P((Tcl_Interp *, int,
00038  * PUBLIC:    Tcl_Obj * CONST*, DB_ENV *));
00039  */
00040 int
00041 tcl_LockDetect(interp, objc, objv, envp)
00042         Tcl_Interp *interp;             /* Interpreter */
00043         int objc;                       /* How many arguments? */
00044         Tcl_Obj *CONST objv[];          /* The argument objects */
00045         DB_ENV *envp;                   /* Environment pointer */
00046 {
00047         static const char *ldopts[] = {
00048                 "default",
00049                 "expire",
00050                 "maxlocks",
00051                 "maxwrites",
00052                 "minlocks",
00053                 "minwrites",
00054                 "oldest",
00055                 "random",
00056                 "youngest",
00057                  NULL
00058         };
00059         enum ldopts {
00060                 LD_DEFAULT,
00061                 LD_EXPIRE,
00062                 LD_MAXLOCKS,
00063                 LD_MAXWRITES,
00064                 LD_MINLOCKS,
00065                 LD_MINWRITES,
00066                 LD_OLDEST,
00067                 LD_RANDOM,
00068                 LD_YOUNGEST
00069         };
00070         u_int32_t flag, policy;
00071         int i, optindex, result, ret;
00072 
00073         result = TCL_OK;
00074         flag = policy = 0;
00075         i = 2;
00076         while (i < objc) {
00077                 if (Tcl_GetIndexFromObj(interp, objv[i],
00078                     ldopts, "option", TCL_EXACT, &optindex) != TCL_OK)
00079                         return (IS_HELP(objv[i]));
00080                 i++;
00081                 switch ((enum ldopts)optindex) {
00082                 case LD_DEFAULT:
00083                         FLAG_CHECK(policy);
00084                         policy = DB_LOCK_DEFAULT;
00085                         break;
00086                 case LD_EXPIRE:
00087                         FLAG_CHECK(policy);
00088                         policy = DB_LOCK_EXPIRE;
00089                         break;
00090                 case LD_MAXLOCKS:
00091                         FLAG_CHECK(policy);
00092                         policy = DB_LOCK_MAXLOCKS;
00093                         break;
00094                 case LD_MAXWRITES:
00095                         FLAG_CHECK(policy);
00096                         policy = DB_LOCK_MAXWRITE;
00097                         break;
00098                 case LD_MINLOCKS:
00099                         FLAG_CHECK(policy);
00100                         policy = DB_LOCK_MINLOCKS;
00101                         break;
00102                 case LD_MINWRITES:
00103                         FLAG_CHECK(policy);
00104                         policy = DB_LOCK_MINWRITE;
00105                         break;
00106                 case LD_OLDEST:
00107                         FLAG_CHECK(policy);
00108                         policy = DB_LOCK_OLDEST;
00109                         break;
00110                 case LD_RANDOM:
00111                         FLAG_CHECK(policy);
00112                         policy = DB_LOCK_RANDOM;
00113                         break;
00114                 case LD_YOUNGEST:
00115                         FLAG_CHECK(policy);
00116                         policy = DB_LOCK_YOUNGEST;
00117                         break;
00118                 }
00119         }
00120 
00121         _debug_check();
00122         ret = envp->lock_detect(envp, flag, policy, NULL);
00123         result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "lock detect");
00124         return (result);
00125 }
00126 
00127 /*
00128  * tcl_LockGet --
00129  *
00130  * PUBLIC: int tcl_LockGet __P((Tcl_Interp *, int,
00131  * PUBLIC:    Tcl_Obj * CONST*, DB_ENV *));
00132  */
00133 int
00134 tcl_LockGet(interp, objc, objv, envp)
00135         Tcl_Interp *interp;             /* Interpreter */
00136         int objc;                       /* How many arguments? */
00137         Tcl_Obj *CONST objv[];          /* The argument objects */
00138         DB_ENV *envp;                   /* Environment pointer */
00139 {
00140         static const char *lgopts[] = {
00141                 "-nowait",
00142                  NULL
00143         };
00144         enum lgopts {
00145                 LGNOWAIT
00146         };
00147         DBT obj;
00148         Tcl_Obj *res;
00149         void *otmp;
00150         db_lockmode_t mode;
00151         u_int32_t flag, lockid;
00152         int freeobj, optindex, result, ret;
00153         char newname[MSG_SIZE];
00154 
00155         result = TCL_OK;
00156         freeobj = 0;
00157         memset(newname, 0, MSG_SIZE);
00158         if (objc != 5 && objc != 6) {
00159                 Tcl_WrongNumArgs(interp, 2, objv, "?-nowait? mode id obj");
00160                 return (TCL_ERROR);
00161         }
00162         /*
00163          * Work back from required args.
00164          * Last arg is obj.
00165          * Second last is lock id.
00166          * Third last is lock mode.
00167          */
00168         memset(&obj, 0, sizeof(obj));
00169 
00170         if ((result =
00171             _GetUInt32(interp, objv[objc-2], &lockid)) != TCL_OK)
00172                 return (result);
00173 
00174         ret = _CopyObjBytes(interp, objv[objc-1], &otmp,
00175             &obj.size, &freeobj);
00176         if (ret != 0) {
00177                 result = _ReturnSetup(interp, ret,
00178                     DB_RETOK_STD(ret), "lock get");
00179                 return (result);
00180         }
00181         obj.data = otmp;
00182         if ((result = _LockMode(interp, objv[(objc - 3)], &mode)) != TCL_OK)
00183                 goto out;
00184 
00185         /*
00186          * Any left over arg is the flag.
00187          */
00188         flag = 0;
00189         if (objc == 6) {
00190                 if (Tcl_GetIndexFromObj(interp, objv[(objc - 4)],
00191                     lgopts, "option", TCL_EXACT, &optindex) != TCL_OK)
00192                         return (IS_HELP(objv[(objc - 4)]));
00193                 switch ((enum lgopts)optindex) {
00194                 case LGNOWAIT:
00195                         flag |= DB_LOCK_NOWAIT;
00196                         break;
00197                 }
00198         }
00199 
00200         result = _GetThisLock(interp, envp, lockid, flag, &obj, mode, newname);
00201         if (result == TCL_OK) {
00202                 res = NewStringObj(newname, strlen(newname));
00203                 Tcl_SetObjResult(interp, res);
00204         }
00205 out:
00206         if (freeobj)
00207                 __os_free(envp, otmp);
00208         return (result);
00209 }
00210 
00211 /*
00212  * tcl_LockStat --
00213  *
00214  * PUBLIC: int tcl_LockStat __P((Tcl_Interp *, int,
00215  * PUBLIC:    Tcl_Obj * CONST*, DB_ENV *));
00216  */
00217 int
00218 tcl_LockStat(interp, objc, objv, envp)
00219         Tcl_Interp *interp;             /* Interpreter */
00220         int objc;                       /* How many arguments? */
00221         Tcl_Obj *CONST objv[];          /* The argument objects */
00222         DB_ENV *envp;                   /* Environment pointer */
00223 {
00224         DB_LOCK_STAT *sp;
00225         Tcl_Obj *res;
00226         int result, ret;
00227 
00228         result = TCL_OK;
00229         /*
00230          * No args for this.  Error if there are some.
00231          */
00232         if (objc != 2) {
00233                 Tcl_WrongNumArgs(interp, 2, objv, NULL);
00234                 return (TCL_ERROR);
00235         }
00236         _debug_check();
00237         ret = envp->lock_stat(envp, &sp, 0);
00238         result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "lock stat");
00239         if (result == TCL_ERROR)
00240                 return (result);
00241         /*
00242          * Have our stats, now construct the name value
00243          * list pairs and free up the memory.
00244          */
00245         res = Tcl_NewObj();
00246         /*
00247          * MAKE_STAT_LIST assumes 'res' and 'error' label.
00248          */
00249         MAKE_STAT_LIST("Region size", sp->st_regsize);
00250         MAKE_STAT_LIST("Last allocated locker ID", sp->st_id);
00251         MAKE_STAT_LIST("Current maximum unused locker ID", sp->st_cur_maxid);
00252         MAKE_STAT_LIST("Maximum locks", sp->st_maxlocks);
00253         MAKE_STAT_LIST("Maximum lockers", sp->st_maxlockers);
00254         MAKE_STAT_LIST("Maximum objects", sp->st_maxobjects);
00255         MAKE_STAT_LIST("Lock modes", sp->st_nmodes);
00256         MAKE_STAT_LIST("Current number of locks", sp->st_nlocks);
00257         MAKE_STAT_LIST("Maximum number of locks so far", sp->st_maxnlocks);
00258         MAKE_STAT_LIST("Current number of lockers", sp->st_nlockers);
00259         MAKE_STAT_LIST("Maximum number of lockers so far", sp->st_maxnlockers);
00260         MAKE_STAT_LIST("Current number of objects", sp->st_nobjects);
00261         MAKE_STAT_LIST("Maximum number of objects so far", sp->st_maxnobjects);
00262         MAKE_STAT_LIST("Lock requests", sp->st_nrequests);
00263         MAKE_STAT_LIST("Lock releases", sp->st_nreleases);
00264         MAKE_STAT_LIST("Lock upgrades", sp->st_nupgrade);
00265         MAKE_STAT_LIST("Lock downgrades", sp->st_ndowngrade);
00266         MAKE_STAT_LIST("Number of conflicted locks for which we waited",
00267             sp->st_lock_wait);
00268         MAKE_STAT_LIST("Number of conflicted locks for which we did not wait",
00269             sp->st_lock_nowait);
00270         MAKE_STAT_LIST("Deadlocks detected", sp->st_ndeadlocks);
00271         MAKE_STAT_LIST("Number of region lock waits", sp->st_region_wait);
00272         MAKE_STAT_LIST("Number of region lock nowaits", sp->st_region_nowait);
00273         MAKE_STAT_LIST("Lock timeout value", sp->st_locktimeout);
00274         MAKE_STAT_LIST("Number of lock timeouts", sp->st_nlocktimeouts);
00275         MAKE_STAT_LIST("Transaction timeout value", sp->st_txntimeout);
00276         MAKE_STAT_LIST("Number of transaction timeouts", sp->st_ntxntimeouts);
00277         Tcl_SetObjResult(interp, res);
00278 error:
00279         __os_ufree(envp, sp);
00280         return (result);
00281 }
00282 
00283 /*
00284  * tcl_LockTimeout --
00285  *
00286  * PUBLIC: int tcl_LockTimeout __P((Tcl_Interp *, int,
00287  * PUBLIC:    Tcl_Obj * CONST*, DB_ENV *));
00288  */
00289 int
00290 tcl_LockTimeout(interp, objc, objv, envp)
00291         Tcl_Interp *interp;             /* Interpreter */
00292         int objc;                       /* How many arguments? */
00293         Tcl_Obj *CONST objv[];          /* The argument objects */
00294         DB_ENV *envp;                   /* Environment pointer */
00295 {
00296         long timeout;
00297         int result, ret;
00298 
00299         /*
00300          * One arg, the timeout.
00301          */
00302         if (objc != 3) {
00303                 Tcl_WrongNumArgs(interp, 2, objv, "?timeout?");
00304                 return (TCL_ERROR);
00305         }
00306         result = Tcl_GetLongFromObj(interp, objv[2], &timeout);
00307         if (result != TCL_OK)
00308                 return (result);
00309         _debug_check();
00310         ret = envp->set_timeout(envp, (u_int32_t)timeout, DB_SET_LOCK_TIMEOUT);
00311         result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "lock timeout");
00312         return (result);
00313 }
00314 
00315 /*
00316  * lock_Cmd --
00317  *      Implements the "lock" widget.
00318  */
00319 static int
00320 lock_Cmd(clientData, interp, objc, objv)
00321         ClientData clientData;          /* Lock handle */
00322         Tcl_Interp *interp;             /* Interpreter */
00323         int objc;                       /* How many arguments? */
00324         Tcl_Obj *CONST objv[];          /* The argument objects */
00325 {
00326         static const char *lkcmds[] = {
00327                 "put",
00328                 NULL
00329         };
00330         enum lkcmds {
00331                 LKPUT
00332         };
00333         DB_ENV *env;
00334         DB_LOCK *lock;
00335         DBTCL_INFO *lkip;
00336         int cmdindex, result, ret;
00337 
00338         Tcl_ResetResult(interp);
00339         lock = (DB_LOCK *)clientData;
00340         lkip = _PtrToInfo((void *)lock);
00341         result = TCL_OK;
00342 
00343         if (lock == NULL) {
00344                 Tcl_SetResult(interp, "NULL lock", TCL_STATIC);
00345                 return (TCL_ERROR);
00346         }
00347         if (lkip == NULL) {
00348                 Tcl_SetResult(interp, "NULL lock info pointer", TCL_STATIC);
00349                 return (TCL_ERROR);
00350         }
00351 
00352         env = NAME_TO_ENV(lkip->i_parent->i_name);
00353         /*
00354          * No args for this.  Error if there are some.
00355          */
00356         if (objc != 2) {
00357                 Tcl_WrongNumArgs(interp, 2, objv, NULL);
00358                 return (TCL_ERROR);
00359         }
00360         /*
00361          * Get the command name index from the object based on the dbcmds
00362          * defined above.
00363          */
00364         if (Tcl_GetIndexFromObj(interp,
00365             objv[1], lkcmds, "command", TCL_EXACT, &cmdindex) != TCL_OK)
00366                 return (IS_HELP(objv[1]));
00367 
00368         switch ((enum lkcmds)cmdindex) {
00369         case LKPUT:
00370                 _debug_check();
00371                 ret = env->lock_put(env, lock);
00372                 result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret),
00373                     "lock put");
00374                 (void)Tcl_DeleteCommand(interp, lkip->i_name);
00375                 _DeleteInfo(lkip);
00376                 __os_free(env, lock);
00377                 break;
00378         }
00379         return (result);
00380 }
00381 
00382 /*
00383  * tcl_LockVec --
00384  *
00385  * PUBLIC: int tcl_LockVec __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *));
00386  */
00387 int
00388 tcl_LockVec(interp, objc, objv, envp)
00389         Tcl_Interp *interp;             /* Interpreter */
00390         int objc;                       /* How many arguments? */
00391         Tcl_Obj *CONST objv[];          /* The argument objects */
00392         DB_ENV *envp;                   /* environment pointer */
00393 {
00394         static const char *lvopts[] = {
00395                 "-nowait",
00396                  NULL
00397         };
00398         enum lvopts {
00399                 LVNOWAIT
00400         };
00401         static const char *lkops[] = {
00402                 "get",
00403                 "put",
00404                 "put_all",
00405                 "put_obj",
00406                 "timeout",
00407                  NULL
00408         };
00409         enum lkops {
00410                 LKGET,
00411                 LKPUT,
00412                 LKPUTALL,
00413                 LKPUTOBJ,
00414                 LKTIMEOUT
00415         };
00416 
00417         DB_LOCK *lock;
00418         DB_LOCKREQ list;
00419         DBT obj;
00420         Tcl_Obj **myobjv, *res, *thisop;
00421         void *otmp;
00422         u_int32_t flag, lockid;
00423         int freeobj, i, myobjc, optindex, result, ret;
00424         char *lockname, msg[MSG_SIZE], newname[MSG_SIZE];
00425 
00426         result = TCL_OK;
00427         memset(newname, 0, MSG_SIZE);
00428         memset(&list, 0, sizeof(DB_LOCKREQ));
00429         flag = 0;
00430         freeobj = 0;
00431         otmp = NULL;
00432 
00433         /*
00434          * If -nowait is given, it MUST be first arg.
00435          */
00436         if (Tcl_GetIndexFromObj(interp, objv[2],
00437             lvopts, "option", TCL_EXACT, &optindex) == TCL_OK) {
00438                 switch ((enum lvopts)optindex) {
00439                 case LVNOWAIT:
00440                         flag |= DB_LOCK_NOWAIT;
00441                         break;
00442                 }
00443                 i = 3;
00444         } else {
00445                 if (IS_HELP(objv[2]) == TCL_OK)
00446                         return (TCL_OK);
00447                 Tcl_ResetResult(interp);
00448                 i = 2;
00449         }
00450 
00451         /*
00452          * Our next arg MUST be the locker ID.
00453          */
00454         result = _GetUInt32(interp, objv[i++], &lockid);
00455         if (result != TCL_OK)
00456                 return (result);
00457 
00458         /*
00459          * All other remaining args are operation tuples.
00460          * Go through sequentially to decode, execute and build
00461          * up list of return values.
00462          */
00463         res = Tcl_NewListObj(0, NULL);
00464         while (i < objc) {
00465                 /*
00466                  * Get the list of the tuple.
00467                  */
00468                 lock = NULL;
00469                 result = Tcl_ListObjGetElements(interp, objv[i],
00470                     &myobjc, &myobjv);
00471                 if (result == TCL_OK)
00472                         i++;
00473                 else
00474                         break;
00475                 /*
00476                  * First we will set up the list of requests.
00477                  * We will make a "second pass" after we get back
00478                  * the results from the lock_vec call to create
00479                  * the return list.
00480                  */
00481                 if (Tcl_GetIndexFromObj(interp, myobjv[0],
00482                     lkops, "option", TCL_EXACT, &optindex) != TCL_OK) {
00483                         result = IS_HELP(myobjv[0]);
00484                         goto error;
00485                 }
00486                 switch ((enum lkops)optindex) {
00487                 case LKGET:
00488                         if (myobjc != 3) {
00489                                 Tcl_WrongNumArgs(interp, 1, myobjv,
00490                                     "{get obj mode}");
00491                                 result = TCL_ERROR;
00492                                 goto error;
00493                         }
00494                         result = _LockMode(interp, myobjv[2], &list.mode);
00495                         if (result != TCL_OK)
00496                                 goto error;
00497                         ret = _CopyObjBytes(interp, myobjv[1], &otmp,
00498                             &obj.size, &freeobj);
00499                         if (ret != 0) {
00500                                 result = _ReturnSetup(interp, ret,
00501                                     DB_RETOK_STD(ret), "lock vec");
00502                                 return (result);
00503                         }
00504                         obj.data = otmp;
00505                         ret = _GetThisLock(interp, envp, lockid, flag,
00506                             &obj, list.mode, newname);
00507                         if (ret != 0) {
00508                                 result = _ReturnSetup(interp, ret,
00509                                     DB_RETOK_STD(ret), "lock vec");
00510                                 thisop = Tcl_NewIntObj(ret);
00511                                 (void)Tcl_ListObjAppendElement(interp, res,
00512                                     thisop);
00513                                 goto error;
00514                         }
00515                         thisop = NewStringObj(newname, strlen(newname));
00516                         (void)Tcl_ListObjAppendElement(interp, res, thisop);
00517                         if (freeobj && otmp != NULL) {
00518                                 __os_free(envp, otmp);
00519                                 freeobj = 0;
00520                         }
00521                         continue;
00522                 case LKPUT:
00523                         if (myobjc != 2) {
00524                                 Tcl_WrongNumArgs(interp, 1, myobjv,
00525                                     "{put lock}");
00526                                 result = TCL_ERROR;
00527                                 goto error;
00528                         }
00529                         list.op = DB_LOCK_PUT;
00530                         lockname = Tcl_GetStringFromObj(myobjv[1], NULL);
00531                         lock = NAME_TO_LOCK(lockname);
00532                         if (lock == NULL) {
00533                                 snprintf(msg, MSG_SIZE, "Invalid lock: %s\n",
00534                                     lockname);
00535                                 Tcl_SetResult(interp, msg, TCL_VOLATILE);
00536                                 result = TCL_ERROR;
00537                                 goto error;
00538                         }
00539                         list.lock = *lock;
00540                         break;
00541                 case LKPUTALL:
00542                         if (myobjc != 1) {
00543                                 Tcl_WrongNumArgs(interp, 1, myobjv,
00544                                     "{put_all}");
00545                                 result = TCL_ERROR;
00546                                 goto error;
00547                         }
00548                         list.op = DB_LOCK_PUT_ALL;
00549                         break;
00550                 case LKPUTOBJ:
00551                         if (myobjc != 2) {
00552                                 Tcl_WrongNumArgs(interp, 1, myobjv,
00553                                     "{put_obj obj}");
00554                                 result = TCL_ERROR;
00555                                 goto error;
00556                         }
00557                         list.op = DB_LOCK_PUT_OBJ;
00558                         ret = _CopyObjBytes(interp, myobjv[1], &otmp,
00559                             &obj.size, &freeobj);
00560                         if (ret != 0) {
00561                                 result = _ReturnSetup(interp, ret,
00562                                     DB_RETOK_STD(ret), "lock vec");
00563                                 return (result);
00564                         }
00565                         obj.data = otmp;
00566                         list.obj = &obj;
00567                         break;
00568                 case LKTIMEOUT:
00569                         list.op = DB_LOCK_TIMEOUT;
00570                         break;
00571 
00572                 }
00573                 /*
00574                  * We get here, we have set up our request, now call
00575                  * lock_vec.
00576                  */
00577                 _debug_check();
00578                 ret = envp->lock_vec(envp, lockid, flag, &list, 1, NULL);
00579                 /*
00580                  * Now deal with whether or not the operation succeeded.
00581                  * Get's were done above, all these are only puts.
00582                  */
00583                 thisop = Tcl_NewIntObj(ret);
00584                 result = Tcl_ListObjAppendElement(interp, res, thisop);
00585                 if (ret != 0 && result == TCL_OK)
00586                         result = _ReturnSetup(interp, ret,
00587                             DB_RETOK_STD(ret), "lock put");
00588                 if (freeobj && otmp != NULL) {
00589                         __os_free(envp, otmp);
00590                         freeobj = 0;
00591                 }
00592                 /*
00593                  * We did a put of some kind.  Since we did that,
00594                  * we have to delete the commands associated with
00595                  * any of the locks we just put.
00596                  */
00597                 _LockPutInfo(interp, list.op, lock, lockid, &obj);
00598         }
00599 
00600         if (result == TCL_OK && res)
00601                 Tcl_SetObjResult(interp, res);
00602 error:
00603         return (result);
00604 }
00605 
00606 static int
00607 _LockMode(interp, obj, mode)
00608         Tcl_Interp *interp;
00609         Tcl_Obj *obj;
00610         db_lockmode_t *mode;
00611 {
00612         static const char *lkmode[] = {
00613                 "ng",
00614                 "read",
00615                 "write",
00616                 "iwrite",
00617                 "iread",
00618                 "iwr",
00619                  NULL
00620         };
00621         enum lkmode {
00622                 LK_NG,
00623                 LK_READ,
00624                 LK_WRITE,
00625                 LK_IWRITE,
00626                 LK_IREAD,
00627                 LK_IWR
00628         };
00629         int optindex;
00630 
00631         if (Tcl_GetIndexFromObj(interp, obj, lkmode, "option",
00632             TCL_EXACT, &optindex) != TCL_OK)
00633                 return (IS_HELP(obj));
00634         switch ((enum lkmode)optindex) {
00635         case LK_NG:
00636                 *mode = DB_LOCK_NG;
00637                 break;
00638         case LK_READ:
00639                 *mode = DB_LOCK_READ;
00640                 break;
00641         case LK_WRITE:
00642                 *mode = DB_LOCK_WRITE;
00643                 break;
00644         case LK_IREAD:
00645                 *mode = DB_LOCK_IREAD;
00646                 break;
00647         case LK_IWRITE:
00648                 *mode = DB_LOCK_IWRITE;
00649                 break;
00650         case LK_IWR:
00651                 *mode = DB_LOCK_IWR;
00652                 break;
00653         }
00654         return (TCL_OK);
00655 }
00656 
00657 static void
00658 _LockPutInfo(interp, op, lock, lockid, objp)
00659         Tcl_Interp *interp;
00660         db_lockop_t op;
00661         DB_LOCK *lock;
00662         u_int32_t lockid;
00663         DBT *objp;
00664 {
00665         DBTCL_INFO *p, *nextp;
00666         int found;
00667 
00668         for (p = LIST_FIRST(&__db_infohead); p != NULL; p = nextp) {
00669                 found = 0;
00670                 nextp = LIST_NEXT(p, entries);
00671                 if ((op == DB_LOCK_PUT && (p->i_lock == lock)) ||
00672                     (op == DB_LOCK_PUT_ALL && p->i_locker == lockid) ||
00673                     (op == DB_LOCK_PUT_OBJ && p->i_lockobj.data &&
00674                         memcmp(p->i_lockobj.data, objp->data, objp->size) == 0))
00675                         found = 1;
00676                 if (found) {
00677                         (void)Tcl_DeleteCommand(interp, p->i_name);
00678                         __os_free(NULL, p->i_lock);
00679                         _DeleteInfo(p);
00680                 }
00681         }
00682 }
00683 
00684 static int
00685 _GetThisLock(interp, envp, lockid, flag, objp, mode, newname)
00686         Tcl_Interp *interp;             /* Interpreter */
00687         DB_ENV *envp;                   /* Env handle */
00688         u_int32_t lockid;               /* Locker ID */
00689         u_int32_t flag;                 /* Lock flag */
00690         DBT *objp;                      /* Object to lock */
00691         db_lockmode_t mode;             /* Lock mode */
00692         char *newname;                  /* New command name */
00693 {
00694         DB_LOCK *lock;
00695         DBTCL_INFO *envip, *ip;
00696         int result, ret;
00697 
00698         result = TCL_OK;
00699         envip = _PtrToInfo((void *)envp);
00700         if (envip == NULL) {
00701                 Tcl_SetResult(interp, "Could not find env info\n", TCL_STATIC);
00702                 return (TCL_ERROR);
00703         }
00704         snprintf(newname, MSG_SIZE, "%s.lock%d",
00705             envip->i_name, envip->i_envlockid);
00706         ip = _NewInfo(interp, NULL, newname, I_LOCK);
00707         if (ip == NULL) {
00708                 Tcl_SetResult(interp, "Could not set up info",
00709                     TCL_STATIC);
00710                 return (TCL_ERROR);
00711         }
00712         ret = __os_malloc(envp, sizeof(DB_LOCK), &lock);
00713         if (ret != 0) {
00714                 Tcl_SetResult(interp, db_strerror(ret), TCL_STATIC);
00715                 return (TCL_ERROR);
00716         }
00717         _debug_check();
00718         ret = envp->lock_get(envp, lockid, flag, objp, mode, lock);
00719         result = _ReturnSetup(interp, ret, DB_RETOK_STD(ret), "lock get");
00720         if (result == TCL_ERROR) {
00721                 __os_free(envp, lock);
00722                 _DeleteInfo(ip);
00723                 return (result);
00724         }
00725         /*
00726          * Success.  Set up return.  Set up new info
00727          * and command widget for this lock.
00728          */
00729         ret = __os_malloc(envp, objp->size, &ip->i_lockobj.data);
00730         if (ret != 0) {
00731                 Tcl_SetResult(interp, "Could not duplicate obj",
00732                     TCL_STATIC);
00733                 (void)envp->lock_put(envp, lock);
00734                 __os_free(envp, lock);
00735                 _DeleteInfo(ip);
00736                 result = TCL_ERROR;
00737                 goto error;
00738         }
00739         memcpy(ip->i_lockobj.data, objp->data, objp->size);
00740         ip->i_lockobj.size = objp->size;
00741         envip->i_envlockid++;
00742         ip->i_parent = envip;
00743         ip->i_locker = lockid;
00744         _SetInfoData(ip, lock);
00745         (void)Tcl_CreateObjCommand(interp, newname,
00746             (Tcl_ObjCmdProc *)lock_Cmd, (ClientData)lock, NULL);
00747 error:
00748         return (result);
00749 }
00750 #endif

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