1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1996,2008 Oracle. All rights reserved. 5 * 6 * $Id: lock_timer.c,v 12.16 2008/01/08 20:58:41 bostic Exp $ 7 */ 8 9#include "db_config.h" 10 11#include "db_int.h" 12#include "dbinc/lock.h" 13 14/* 15 * __lock_set_timeout -- 16 * Set timeout values in shared memory. 17 * 18 * This is called from the transaction system. We either set the time that 19 * this transaction expires or the amount of time a lock for this transaction 20 * is permitted to wait. 21 * 22 * PUBLIC: int __lock_set_timeout __P((ENV *, 23 * PUBLIC: DB_LOCKER *, db_timeout_t, u_int32_t)); 24 */ 25int 26__lock_set_timeout(env, locker, timeout, op) 27 ENV *env; 28 DB_LOCKER *locker; 29 db_timeout_t timeout; 30 u_int32_t op; 31{ 32 int ret; 33 34 if (locker == NULL) 35 return (0); 36 LOCK_REGION_LOCK(env); 37 ret = __lock_set_timeout_internal(env, locker, timeout, op); 38 LOCK_REGION_UNLOCK(env); 39 return (ret); 40} 41 42/* 43 * __lock_set_timeout_internal 44 * -- set timeout values in shared memory. 45 * 46 * This is the internal version called from the lock system. We either set 47 * the time that this transaction expires or the amount of time that a lock 48 * for this transaction is permitted to wait. 49 * 50 * PUBLIC: int __lock_set_timeout_internal 51 * PUBLIC: __P((ENV *, DB_LOCKER *, db_timeout_t, u_int32_t)); 52 */ 53int 54__lock_set_timeout_internal(env, sh_locker, timeout, op) 55 ENV *env; 56 DB_LOCKER *sh_locker; 57 db_timeout_t timeout; 58 u_int32_t op; 59{ 60 DB_LOCKREGION *region; 61 region = env->lk_handle->reginfo.primary; 62 63 if (op == DB_SET_TXN_TIMEOUT) { 64 if (timeout == 0) 65 timespecclear(&sh_locker->tx_expire); 66 else 67 __lock_expires(env, &sh_locker->tx_expire, timeout); 68 } else if (op == DB_SET_LOCK_TIMEOUT) { 69 sh_locker->lk_timeout = timeout; 70 F_SET(sh_locker, DB_LOCKER_TIMEOUT); 71 } else if (op == DB_SET_TXN_NOW) { 72 timespecclear(&sh_locker->tx_expire); 73 __lock_expires(env, &sh_locker->tx_expire, 0); 74 sh_locker->lk_expire = sh_locker->tx_expire; 75 if (!timespecisset(®ion->next_timeout) || 76 timespeccmp( 77 ®ion->next_timeout, &sh_locker->lk_expire, >)) 78 region->next_timeout = sh_locker->lk_expire; 79 } else 80 return (EINVAL); 81 82 return (0); 83} 84 85/* 86 * __lock_inherit_timeout 87 * -- inherit timeout values from parent locker. 88 * This is called from the transaction system. This will 89 * return EINVAL if the parent does not exist or did not 90 * have a current txn timeout set. 91 * 92 * PUBLIC: int __lock_inherit_timeout __P((ENV *, DB_LOCKER *, DB_LOCKER *)); 93 */ 94int 95__lock_inherit_timeout(env, parent, locker) 96 ENV *env; 97 DB_LOCKER *parent, *locker; 98{ 99 int ret; 100 101 ret = 0; 102 LOCK_REGION_LOCK(env); 103 104 /* 105 * If the parent is not there yet, thats ok. If it 106 * does not have any timouts set, then avoid creating 107 * the child locker at this point. 108 */ 109 if (parent == NULL || 110 (timespecisset(&parent->tx_expire) && 111 !F_ISSET(parent, DB_LOCKER_TIMEOUT))) { 112 ret = EINVAL; 113 goto err; 114 } 115 116 locker->tx_expire = parent->tx_expire; 117 118 if (F_ISSET(parent, DB_LOCKER_TIMEOUT)) { 119 locker->lk_timeout = parent->lk_timeout; 120 F_SET(locker, DB_LOCKER_TIMEOUT); 121 if (!timespecisset(&parent->tx_expire)) 122 ret = EINVAL; 123 } 124 125err: LOCK_REGION_UNLOCK(env); 126 return (ret); 127} 128 129/* 130 * __lock_expires -- 131 * Set the expire time given the time to live. 132 * 133 * PUBLIC: void __lock_expires __P((ENV *, db_timespec *, db_timeout_t)); 134 */ 135void 136__lock_expires(env, timespecp, timeout) 137 ENV *env; 138 db_timespec *timespecp; 139 db_timeout_t timeout; 140{ 141 db_timespec v; 142 143 /* 144 * If timespecp is set then it contains "now". This avoids repeated 145 * system calls to get the time. 146 */ 147 if (!timespecisset(timespecp)) 148 __os_gettime(env, timespecp, 1); 149 150 /* Convert the microsecond timeout argument to a timespec. */ 151 DB_TIMEOUT_TO_TIMESPEC(timeout, &v); 152 153 /* Add the timeout to "now". */ 154 timespecadd(timespecp, &v); 155} 156 157/* 158 * __lock_expired -- determine if a lock has expired. 159 * 160 * PUBLIC: int __lock_expired __P((ENV *, db_timespec *, db_timespec *)); 161 */ 162int 163__lock_expired(env, now, timespecp) 164 ENV *env; 165 db_timespec *now, *timespecp; 166{ 167 if (!timespecisset(timespecp)) 168 return (0); 169 170 if (!timespecisset(now)) 171 __os_gettime(env, now, 1); 172 173 return (timespeccmp(now, timespecp, >=)); 174} 175