00001
00002
00003
00004
00005
00006
00007
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 #include "dbinc/log.h"
00023
00024
00025
00026
00027
00028
00029
00030 int
00031 __lock_id_pp(dbenv, idp)
00032 DB_ENV *dbenv;
00033 u_int32_t *idp;
00034 {
00035 DB_THREAD_INFO *ip;
00036 int ret;
00037
00038 PANIC_CHECK(dbenv);
00039 ENV_REQUIRES_CONFIG(dbenv,
00040 dbenv->lk_handle, "DB_ENV->lock_id", DB_INIT_LOCK);
00041
00042 ENV_ENTER(dbenv, ip);
00043 REPLICATION_WRAP(dbenv, (__lock_id(dbenv, idp, NULL)), ret);
00044 ENV_LEAVE(dbenv, ip);
00045 return (ret);
00046 }
00047
00048
00049
00050
00051
00052
00053
00054 int
00055 __lock_id(dbenv, idp, lkp)
00056 DB_ENV *dbenv;
00057 u_int32_t *idp;
00058 DB_LOCKER **lkp;
00059 {
00060 DB_LOCKER *lk;
00061 DB_LOCKTAB *lt;
00062 DB_LOCKREGION *region;
00063 u_int32_t id, *ids, locker_ndx;
00064 int nids, ret;
00065
00066 lt = dbenv->lk_handle;
00067 region = lt->reginfo.primary;
00068 ret = 0;
00069
00070 id = DB_LOCK_INVALIDID;
00071 lk = NULL;
00072
00073 LOCK_SYSTEM_LOCK(dbenv);
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 if (region->stat.st_id == DB_LOCK_MAXID &&
00084 region->stat.st_cur_maxid != DB_LOCK_MAXID)
00085 region->stat.st_id = DB_LOCK_INVALIDID;
00086 if (region->stat.st_id == region->stat.st_cur_maxid) {
00087 if ((ret = __os_malloc(dbenv,
00088 sizeof(u_int32_t) * region->stat.st_nlockers, &ids)) != 0)
00089 goto err;
00090 nids = 0;
00091 for (lk = SH_TAILQ_FIRST(®ion->lockers, __db_locker);
00092 lk != NULL;
00093 lk = SH_TAILQ_NEXT(lk, ulinks, __db_locker))
00094 ids[nids++] = lk->id;
00095 region->stat.st_id = DB_LOCK_INVALIDID;
00096 region->stat.st_cur_maxid = DB_LOCK_MAXID;
00097 if (nids != 0)
00098 __db_idspace(ids, nids,
00099 ®ion->stat.st_id, ®ion->stat.st_cur_maxid);
00100 __os_free(dbenv, ids);
00101 }
00102 id = ++region->stat.st_id;
00103
00104
00105 LOCKER_LOCK(lt, region, id, locker_ndx);
00106 ret = __lock_getlocker(lt, id, locker_ndx, 1, &lk);
00107
00108 err: LOCK_SYSTEM_UNLOCK(dbenv);
00109
00110 if (idp)
00111 *idp = id;
00112 if (lkp)
00113 *lkp = lk;
00114 return (ret);
00115 }
00116
00117
00118
00119
00120
00121
00122 void
00123 __lock_set_thread_id(lref, pid, tid)
00124 DB_LOCKER *lref;
00125 pid_t pid;
00126 db_threadid_t tid;
00127 {
00128 lref->pid = pid;
00129 lref->tid = tid;
00130 }
00131
00132
00133
00134
00135
00136
00137
00138 int
00139 __lock_id_free_pp(dbenv, id)
00140 DB_ENV *dbenv;
00141 u_int32_t id;
00142 {
00143 DB_THREAD_INFO *ip;
00144 int ret;
00145
00146 PANIC_CHECK(dbenv);
00147 ENV_REQUIRES_CONFIG(dbenv,
00148 dbenv->lk_handle, "DB_ENV->lock_id_free", DB_INIT_LOCK);
00149
00150 ENV_ENTER(dbenv, ip);
00151 REPLICATION_WRAP(dbenv, (__lock_id_free(dbenv, id)), ret);
00152 ENV_LEAVE(dbenv, ip);
00153 return (ret);
00154 }
00155
00156
00157
00158
00159
00160
00161
00162 int
00163 __lock_id_free(dbenv, id)
00164 DB_ENV *dbenv;
00165 u_int32_t id;
00166 {
00167 DB_LOCKER *sh_locker;
00168 DB_LOCKTAB *lt;
00169 DB_LOCKREGION *region;
00170 u_int32_t locker_ndx;
00171 int ret;
00172
00173 PANIC_CHECK(dbenv);
00174 ENV_REQUIRES_CONFIG(dbenv,
00175 dbenv->lk_handle, "DB_ENV->lock_id_free", DB_INIT_LOCK);
00176
00177 lt = dbenv->lk_handle;
00178 region = lt->reginfo.primary;
00179
00180 LOCK_SYSTEM_LOCK(dbenv);
00181 LOCKER_LOCK(lt, region, id, locker_ndx);
00182 if ((ret = __lock_getlocker(lt, id, locker_ndx, 0, &sh_locker)) != 0)
00183 goto err;
00184
00185 if (sh_locker == NULL) {
00186 __db_err(dbenv, "Unknown locker ID: %lx", (u_long)id);
00187 ret = EINVAL;
00188 goto err;
00189 }
00190
00191 if (sh_locker->nlocks != 0) {
00192 __db_err(dbenv, "Locker still has locks");
00193 ret = EINVAL;
00194 goto err;
00195 }
00196
00197 __lock_freelocker(lt, region, sh_locker, locker_ndx);
00198
00199 err: LOCK_SYSTEM_UNLOCK(dbenv);
00200 return (ret);
00201 }
00202
00203
00204
00205
00206
00207
00208
00209
00210 int
00211 __lock_id_set(dbenv, cur_id, max_id)
00212 DB_ENV *dbenv;
00213 u_int32_t cur_id, max_id;
00214 {
00215 DB_LOCKTAB *lt;
00216 DB_LOCKREGION *region;
00217
00218 ENV_REQUIRES_CONFIG(dbenv,
00219 dbenv->lk_handle, "lock_id_set", DB_INIT_LOCK);
00220
00221 lt = dbenv->lk_handle;
00222 region = lt->reginfo.primary;
00223 region->stat.st_id = cur_id;
00224 region->stat.st_cur_maxid = max_id;
00225
00226 return (0);
00227 }
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 int
00241 __lock_getlocker(lt, locker, indx, create, retp)
00242 DB_LOCKTAB *lt;
00243 u_int32_t locker, indx;
00244 int create;
00245 DB_LOCKER **retp;
00246 {
00247 DB_ENV *dbenv;
00248 DB_LOCKER *sh_locker;
00249 DB_LOCKREGION *region;
00250
00251 dbenv = lt->dbenv;
00252 region = lt->reginfo.primary;
00253
00254 HASHLOOKUP(lt->locker_tab,
00255 indx, __db_locker, links, locker, sh_locker, __lock_locker_cmp);
00256
00257
00258
00259
00260
00261 if (sh_locker == NULL && create) {
00262
00263 if ((sh_locker = SH_TAILQ_FIRST(
00264 ®ion->free_lockers, __db_locker)) == NULL)
00265 return (__lock_nomem(dbenv, "locker entries"));
00266 SH_TAILQ_REMOVE(
00267 ®ion->free_lockers, sh_locker, links, __db_locker);
00268 if (++region->stat.st_nlockers > region->stat.st_maxnlockers)
00269 region->stat.st_maxnlockers = region->stat.st_nlockers;
00270
00271 sh_locker->id = locker;
00272 dbenv->thread_id(dbenv, &sh_locker->pid, &sh_locker->tid);
00273 sh_locker->dd_id = 0;
00274 sh_locker->master_locker = INVALID_ROFF;
00275 sh_locker->parent_locker = INVALID_ROFF;
00276 SH_LIST_INIT(&sh_locker->child_locker);
00277 sh_locker->flags = 0;
00278 SH_LIST_INIT(&sh_locker->heldby);
00279 sh_locker->nlocks = 0;
00280 sh_locker->nwrites = 0;
00281 sh_locker->lk_timeout = 0;
00282 LOCK_SET_TIME_INVALID(&sh_locker->tx_expire);
00283 LOCK_SET_TIME_INVALID(&sh_locker->lk_expire);
00284
00285 HASHINSERT(lt->locker_tab, indx, __db_locker, links, sh_locker);
00286 SH_TAILQ_INSERT_HEAD(®ion->lockers,
00287 sh_locker, ulinks, __db_locker);
00288 }
00289
00290 *retp = sh_locker;
00291 return (0);
00292 }
00293
00294
00295
00296
00297
00298
00299
00300 int
00301 __lock_addfamilylocker(dbenv, pid, id)
00302 DB_ENV *dbenv;
00303 u_int32_t pid, id;
00304 {
00305 DB_LOCKER *lockerp, *mlockerp;
00306 DB_LOCKREGION *region;
00307 DB_LOCKTAB *lt;
00308 u_int32_t ndx;
00309 int ret;
00310
00311 lt = dbenv->lk_handle;
00312 region = lt->reginfo.primary;
00313 LOCK_SYSTEM_LOCK(dbenv);
00314
00315
00316 LOCKER_LOCK(lt, region, pid, ndx);
00317 if ((ret = __lock_getlocker(lt, pid, ndx, 1, &mlockerp)) != 0)
00318 goto err;
00319
00320
00321
00322
00323
00324
00325
00326
00327 LOCKER_LOCK(lt, region, id, ndx);
00328 if ((ret = __lock_getlocker(lt, id, ndx, 1, &lockerp)) != 0)
00329 goto err;
00330
00331
00332 lockerp->parent_locker = R_OFFSET(<->reginfo, mlockerp);
00333
00334
00335 if (mlockerp->master_locker == INVALID_ROFF)
00336 lockerp->master_locker = R_OFFSET(<->reginfo, mlockerp);
00337 else {
00338 lockerp->master_locker = mlockerp->master_locker;
00339 mlockerp = R_ADDR(<->reginfo, mlockerp->master_locker);
00340 }
00341
00342
00343
00344
00345
00346
00347 SH_LIST_INSERT_HEAD(
00348 &mlockerp->child_locker, lockerp, child_link, __db_locker);
00349
00350 err: LOCK_SYSTEM_UNLOCK(dbenv);
00351
00352 return (ret);
00353 }
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363 int
00364 __lock_freefamilylocker(lt, locker)
00365 DB_LOCKTAB *lt;
00366 u_int32_t locker;
00367 {
00368 DB_ENV *dbenv;
00369 DB_LOCKER *sh_locker;
00370 DB_LOCKREGION *region;
00371 u_int32_t indx;
00372 int ret;
00373
00374 dbenv = lt->dbenv;
00375 region = lt->reginfo.primary;
00376
00377 LOCK_SYSTEM_LOCK(dbenv);
00378 LOCKER_LOCK(lt, region, locker, indx);
00379
00380 if ((ret = __lock_getlocker(lt,
00381 locker, indx, 0, &sh_locker)) != 0 || sh_locker == NULL)
00382 goto err;
00383
00384 if (SH_LIST_FIRST(&sh_locker->heldby, __db_lock) != NULL) {
00385 ret = EINVAL;
00386 __db_err(dbenv, "Freeing locker with locks");
00387 goto err;
00388 }
00389
00390
00391 if (sh_locker->master_locker != INVALID_ROFF)
00392 SH_LIST_REMOVE(sh_locker, child_link, __db_locker);
00393
00394 __lock_freelocker(lt, region, sh_locker, indx);
00395
00396 err: LOCK_SYSTEM_UNLOCK(dbenv);
00397 return (ret);
00398 }
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408 void
00409 __lock_freelocker(lt, region, sh_locker, indx)
00410 DB_LOCKTAB *lt;
00411 DB_LOCKREGION *region;
00412 DB_LOCKER *sh_locker;
00413 u_int32_t indx;
00414
00415 {
00416 HASHREMOVE_EL(
00417 lt->locker_tab, indx, __db_locker, links, sh_locker);
00418 SH_TAILQ_INSERT_HEAD(
00419 ®ion->free_lockers, sh_locker, links, __db_locker);
00420 SH_TAILQ_REMOVE(®ion->lockers, sh_locker, ulinks, __db_locker);
00421 region->stat.st_nlockers--;
00422 }