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

lock_timer.c

00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 1996-2005
00005  *      Sleepycat Software.  All rights reserved.
00006  *
00007  * $Id: lock_timer.c,v 12.2 2005/07/20 16:51:44 bostic Exp $
00008  */
00009 
00010 #include "db_config.h"
00011 
00012 #ifndef NO_SYSTEM_INCLUDES
00013 #include <sys/types.h>
00014 
00015 #include <string.h>
00016 #include <stdlib.h>
00017 #endif
00018 
00019 #include "db_int.h"
00020 #include "dbinc/db_shash.h"
00021 #include "dbinc/lock.h"
00022 
00023 /*
00024  * __lock_set_timeout
00025  *              -- set timeout values in shared memory.
00026  *
00027  * This is called from the transaction system.  We either set the time that
00028  * this transaction expires or the amount of time a lock for this transaction
00029  * is permitted to wait.
00030  *
00031  * PUBLIC: int __lock_set_timeout __P(( DB_ENV *,
00032  * PUBLIC:      u_int32_t, db_timeout_t, u_int32_t));
00033  */
00034 int
00035 __lock_set_timeout(dbenv, locker, timeout, op)
00036         DB_ENV *dbenv;
00037         u_int32_t locker;
00038         db_timeout_t timeout;
00039         u_int32_t op;
00040 {
00041         int ret;
00042 
00043         LOCK_SYSTEM_LOCK(dbenv);
00044         ret = __lock_set_timeout_internal(dbenv, locker, timeout, op);
00045         LOCK_SYSTEM_UNLOCK(dbenv);
00046         return (ret);
00047 }
00048 
00049 /*
00050  * __lock_set_timeout_internal
00051  *              -- set timeout values in shared memory.
00052  *
00053  * This is the internal version called from the lock system.  We either set
00054  * the time that this transaction expires or the amount of time that a lock
00055  * for this transaction is permitted to wait.
00056  *
00057  * PUBLIC: int __lock_set_timeout_internal
00058  * PUBLIC:     __P((DB_ENV *, u_int32_t, db_timeout_t, u_int32_t));
00059  */
00060 int
00061 __lock_set_timeout_internal(dbenv, locker, timeout, op)
00062         DB_ENV *dbenv;
00063         u_int32_t locker;
00064         db_timeout_t timeout;
00065         u_int32_t op;
00066 {
00067         DB_LOCKER *sh_locker;
00068         DB_LOCKREGION *region;
00069         DB_LOCKTAB *lt;
00070         u_int32_t locker_ndx;
00071         int ret;
00072 
00073         lt = dbenv->lk_handle;
00074         region = lt->reginfo.primary;
00075 
00076         LOCKER_LOCK(lt, region, locker, locker_ndx);
00077         ret = __lock_getlocker(lt, locker, locker_ndx, 1, &sh_locker);
00078 
00079         if (ret != 0)
00080                 return (ret);
00081 
00082         if (op == DB_SET_TXN_TIMEOUT) {
00083                 if (timeout == 0)
00084                         LOCK_SET_TIME_INVALID(&sh_locker->tx_expire);
00085                 else
00086                         __lock_expires(dbenv, &sh_locker->tx_expire, timeout);
00087         } else if (op == DB_SET_LOCK_TIMEOUT) {
00088                 sh_locker->lk_timeout = timeout;
00089                 F_SET(sh_locker, DB_LOCKER_TIMEOUT);
00090         } else if (op == DB_SET_TXN_NOW) {
00091                 LOCK_SET_TIME_INVALID(&sh_locker->tx_expire);
00092                 __lock_expires(dbenv, &sh_locker->tx_expire, 0);
00093                 sh_locker->lk_expire = sh_locker->tx_expire;
00094                 if (!LOCK_TIME_ISVALID(&region->next_timeout) ||
00095                     LOCK_TIME_GREATER(
00096                     &region->next_timeout, &sh_locker->lk_expire))
00097                         region->next_timeout = sh_locker->lk_expire;
00098         } else
00099                 return (EINVAL);
00100 
00101         return (0);
00102 }
00103 
00104 /*
00105  * __lock_inherit_timeout
00106  *              -- inherit timeout values from parent locker.
00107  * This is called from the transaction system.  This will
00108  * return EINVAL if the parent does not exist or did not
00109  * have a current txn timeout set.
00110  *
00111  * PUBLIC: int __lock_inherit_timeout __P(( DB_ENV *, u_int32_t, u_int32_t));
00112  */
00113 int
00114 __lock_inherit_timeout(dbenv, parent, locker)
00115         DB_ENV *dbenv;
00116         u_int32_t parent, locker;
00117 {
00118         DB_LOCKER *parent_locker, *sh_locker;
00119         DB_LOCKREGION *region;
00120         DB_LOCKTAB *lt;
00121         u_int32_t locker_ndx;
00122         int ret;
00123 
00124         lt = dbenv->lk_handle;
00125         region = lt->reginfo.primary;
00126         ret = 0;
00127         LOCK_SYSTEM_LOCK(dbenv);
00128 
00129         /* If the parent does not exist, we are done. */
00130         LOCKER_LOCK(lt, region, parent, locker_ndx);
00131         if ((ret = __lock_getlocker(lt,
00132             parent, locker_ndx, 0, &parent_locker)) != 0)
00133                 goto err;
00134 
00135         /*
00136          * If the parent is not there yet, thats ok.  If it
00137          * does not have any timouts set, then avoid creating
00138          * the child locker at this point.
00139          */
00140         if (parent_locker == NULL ||
00141             (LOCK_TIME_ISVALID(&parent_locker->tx_expire) &&
00142             !F_ISSET(parent_locker, DB_LOCKER_TIMEOUT))) {
00143                 ret = EINVAL;
00144                 goto done;
00145         }
00146 
00147         LOCKER_LOCK(lt, region, locker, locker_ndx);
00148         if ((ret = __lock_getlocker(lt,
00149             locker, locker_ndx, 1, &sh_locker)) != 0)
00150                 goto err;
00151 
00152         sh_locker->tx_expire = parent_locker->tx_expire;
00153 
00154         if (F_ISSET(parent_locker, DB_LOCKER_TIMEOUT)) {
00155                 sh_locker->lk_timeout = parent_locker->lk_timeout;
00156                 F_SET(sh_locker, DB_LOCKER_TIMEOUT);
00157                 if (!LOCK_TIME_ISVALID(&parent_locker->tx_expire))
00158                         ret = EINVAL;
00159         }
00160 
00161 done:
00162 err:    LOCK_SYSTEM_UNLOCK(dbenv);
00163         return (ret);
00164 }
00165 
00166 /*
00167  * __lock_expires --
00168  *      Set the expire time given the time to live.  If timevalp is set then
00169  *      it contains "now".  This avoids repeated system calls to get the time.
00170  *
00171  * PUBLIC: void __lock_expires __P((DB_ENV *, db_timeval_t *, db_timeout_t));
00172  */
00173 void
00174 __lock_expires(dbenv, timevalp, timeout)
00175         DB_ENV *dbenv;
00176         db_timeval_t *timevalp;
00177         db_timeout_t timeout;
00178 {
00179         if (!LOCK_TIME_ISVALID(timevalp))
00180                 __os_clock(dbenv, &timevalp->tv_sec, &timevalp->tv_usec);
00181         if (timeout > 1000000) {
00182                 timevalp->tv_sec += timeout / 1000000;
00183                 timevalp->tv_usec += timeout % 1000000;
00184         } else
00185                 timevalp->tv_usec += timeout;
00186 
00187         if (timevalp->tv_usec > 1000000) {
00188                 timevalp->tv_sec++;
00189                 timevalp->tv_usec -= 1000000;
00190         }
00191 }
00192 
00193 /*
00194  * __lock_expired -- determine if a lock has expired.
00195  *
00196  * PUBLIC: int __lock_expired __P((DB_ENV *, db_timeval_t *, db_timeval_t *));
00197  */
00198 int
00199 __lock_expired(dbenv, now, timevalp)
00200         DB_ENV *dbenv;
00201         db_timeval_t *now, *timevalp;
00202 {
00203         if (!LOCK_TIME_ISVALID(timevalp))
00204                 return (0);
00205 
00206         if (!LOCK_TIME_ISVALID(now))
00207                 __os_clock(dbenv, &now->tv_sec, &now->tv_usec);
00208 
00209         return (now->tv_sec > timevalp->tv_sec ||
00210             (now->tv_sec == timevalp->tv_sec &&
00211             now->tv_usec >= timevalp->tv_usec));
00212 }

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