1*7c478bd9Sstevel@tonic-gate /*- 2*7c478bd9Sstevel@tonic-gate * See the file LICENSE for redistribution information. 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * Copyright (c) 1996, 1997, 1998 5*7c478bd9Sstevel@tonic-gate * Sleepycat Software. All rights reserved. 6*7c478bd9Sstevel@tonic-gate */ 7*7c478bd9Sstevel@tonic-gate #include "config.h" 8*7c478bd9Sstevel@tonic-gate 9*7c478bd9Sstevel@tonic-gate #ifndef lint 10*7c478bd9Sstevel@tonic-gate static const char sccsid[] = "@(#)mp_open.c 10.27 (Sleepycat) 10/1/98"; 11*7c478bd9Sstevel@tonic-gate #endif /* not lint */ 12*7c478bd9Sstevel@tonic-gate 13*7c478bd9Sstevel@tonic-gate #ifndef NO_SYSTEM_INCLUDES 14*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 15*7c478bd9Sstevel@tonic-gate 16*7c478bd9Sstevel@tonic-gate #include <errno.h> 17*7c478bd9Sstevel@tonic-gate #include <string.h> 18*7c478bd9Sstevel@tonic-gate #endif 19*7c478bd9Sstevel@tonic-gate 20*7c478bd9Sstevel@tonic-gate #include "db_int.h" 21*7c478bd9Sstevel@tonic-gate #include "shqueue.h" 22*7c478bd9Sstevel@tonic-gate #include "db_shash.h" 23*7c478bd9Sstevel@tonic-gate #include "mp.h" 24*7c478bd9Sstevel@tonic-gate #include "common_ext.h" 25*7c478bd9Sstevel@tonic-gate 26*7c478bd9Sstevel@tonic-gate /* 27*7c478bd9Sstevel@tonic-gate * memp_open -- 28*7c478bd9Sstevel@tonic-gate * Initialize and/or join a memory pool. 29*7c478bd9Sstevel@tonic-gate */ 30*7c478bd9Sstevel@tonic-gate int 31*7c478bd9Sstevel@tonic-gate memp_open(path, flags, mode, dbenv, retp) 32*7c478bd9Sstevel@tonic-gate const char *path; 33*7c478bd9Sstevel@tonic-gate u_int32_t flags; 34*7c478bd9Sstevel@tonic-gate int mode; 35*7c478bd9Sstevel@tonic-gate DB_ENV *dbenv; 36*7c478bd9Sstevel@tonic-gate DB_MPOOL **retp; 37*7c478bd9Sstevel@tonic-gate { 38*7c478bd9Sstevel@tonic-gate DB_MPOOL *dbmp; 39*7c478bd9Sstevel@tonic-gate size_t cachesize; 40*7c478bd9Sstevel@tonic-gate int is_private, ret; 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate /* Validate arguments. */ 43*7c478bd9Sstevel@tonic-gate #ifdef HAVE_SPINLOCKS 44*7c478bd9Sstevel@tonic-gate #define OKFLAGS (DB_CREATE | DB_MPOOL_PRIVATE | DB_NOMMAP | DB_THREAD) 45*7c478bd9Sstevel@tonic-gate #else 46*7c478bd9Sstevel@tonic-gate #define OKFLAGS (DB_CREATE | DB_MPOOL_PRIVATE | DB_NOMMAP) 47*7c478bd9Sstevel@tonic-gate #endif 48*7c478bd9Sstevel@tonic-gate if ((ret = __db_fchk(dbenv, "memp_open", flags, OKFLAGS)) != 0) 49*7c478bd9Sstevel@tonic-gate return (ret); 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate /* Extract fields from DB_ENV structure. */ 52*7c478bd9Sstevel@tonic-gate cachesize = dbenv == NULL ? 0 : dbenv->mp_size; 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate /* Create and initialize the DB_MPOOL structure. */ 55*7c478bd9Sstevel@tonic-gate if ((ret = __os_calloc(1, sizeof(DB_MPOOL), &dbmp)) != 0) 56*7c478bd9Sstevel@tonic-gate return (ret); 57*7c478bd9Sstevel@tonic-gate LIST_INIT(&dbmp->dbregq); 58*7c478bd9Sstevel@tonic-gate TAILQ_INIT(&dbmp->dbmfq); 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate dbmp->dbenv = dbenv; 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate /* Decide if it's possible for anyone else to access the pool. */ 63*7c478bd9Sstevel@tonic-gate is_private = 64*7c478bd9Sstevel@tonic-gate (dbenv == NULL && path == NULL) || LF_ISSET(DB_MPOOL_PRIVATE); 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate /* 67*7c478bd9Sstevel@tonic-gate * Map in the region. We do locking regardless, as portions of it are 68*7c478bd9Sstevel@tonic-gate * implemented in common code (if we put the region in a file, that is). 69*7c478bd9Sstevel@tonic-gate */ 70*7c478bd9Sstevel@tonic-gate F_SET(dbmp, MP_LOCKREGION); 71*7c478bd9Sstevel@tonic-gate if ((ret = __memp_ropen(dbmp, 72*7c478bd9Sstevel@tonic-gate path, cachesize, mode, is_private, LF_ISSET(DB_CREATE))) != 0) 73*7c478bd9Sstevel@tonic-gate goto err; 74*7c478bd9Sstevel@tonic-gate F_CLR(dbmp, MP_LOCKREGION); 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate /* 77*7c478bd9Sstevel@tonic-gate * If there's concurrent access, then we have to lock the region. 78*7c478bd9Sstevel@tonic-gate * If it's threaded, then we have to lock both the handles and the 79*7c478bd9Sstevel@tonic-gate * region, and we need to allocate a mutex for that purpose. 80*7c478bd9Sstevel@tonic-gate */ 81*7c478bd9Sstevel@tonic-gate if (!is_private) 82*7c478bd9Sstevel@tonic-gate F_SET(dbmp, MP_LOCKREGION); 83*7c478bd9Sstevel@tonic-gate if (LF_ISSET(DB_THREAD)) { 84*7c478bd9Sstevel@tonic-gate F_SET(dbmp, MP_LOCKHANDLE | MP_LOCKREGION); 85*7c478bd9Sstevel@tonic-gate LOCKREGION(dbmp); 86*7c478bd9Sstevel@tonic-gate ret = __memp_alloc(dbmp, 87*7c478bd9Sstevel@tonic-gate sizeof(db_mutex_t), NULL, &dbmp->mutexp); 88*7c478bd9Sstevel@tonic-gate UNLOCKREGION(dbmp); 89*7c478bd9Sstevel@tonic-gate if (ret != 0) { 90*7c478bd9Sstevel@tonic-gate (void)memp_close(dbmp); 91*7c478bd9Sstevel@tonic-gate goto err; 92*7c478bd9Sstevel@tonic-gate } 93*7c478bd9Sstevel@tonic-gate LOCKINIT(dbmp, dbmp->mutexp); 94*7c478bd9Sstevel@tonic-gate } 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate *retp = dbmp; 97*7c478bd9Sstevel@tonic-gate return (0); 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate err: if (dbmp != NULL) 100*7c478bd9Sstevel@tonic-gate __os_free(dbmp, sizeof(DB_MPOOL)); 101*7c478bd9Sstevel@tonic-gate return (ret); 102*7c478bd9Sstevel@tonic-gate } 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate /* 105*7c478bd9Sstevel@tonic-gate * memp_close -- 106*7c478bd9Sstevel@tonic-gate * Close a memory pool. 107*7c478bd9Sstevel@tonic-gate */ 108*7c478bd9Sstevel@tonic-gate int 109*7c478bd9Sstevel@tonic-gate memp_close(dbmp) 110*7c478bd9Sstevel@tonic-gate DB_MPOOL *dbmp; 111*7c478bd9Sstevel@tonic-gate { 112*7c478bd9Sstevel@tonic-gate DB_MPOOLFILE *dbmfp; 113*7c478bd9Sstevel@tonic-gate DB_MPREG *mpreg; 114*7c478bd9Sstevel@tonic-gate int ret, t_ret; 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate ret = 0; 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate MP_PANIC_CHECK(dbmp); 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate /* Discard DB_MPREGs. */ 121*7c478bd9Sstevel@tonic-gate while ((mpreg = LIST_FIRST(&dbmp->dbregq)) != NULL) { 122*7c478bd9Sstevel@tonic-gate LIST_REMOVE(mpreg, q); 123*7c478bd9Sstevel@tonic-gate __os_free(mpreg, sizeof(DB_MPREG)); 124*7c478bd9Sstevel@tonic-gate } 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate /* Discard DB_MPOOLFILEs. */ 127*7c478bd9Sstevel@tonic-gate while ((dbmfp = TAILQ_FIRST(&dbmp->dbmfq)) != NULL) 128*7c478bd9Sstevel@tonic-gate if ((t_ret = memp_fclose(dbmfp)) != 0 && ret == 0) 129*7c478bd9Sstevel@tonic-gate ret = t_ret; 130*7c478bd9Sstevel@tonic-gate 131*7c478bd9Sstevel@tonic-gate /* Discard thread mutex. */ 132*7c478bd9Sstevel@tonic-gate if (F_ISSET(dbmp, MP_LOCKHANDLE)) { 133*7c478bd9Sstevel@tonic-gate LOCKREGION(dbmp); 134*7c478bd9Sstevel@tonic-gate __db_shalloc_free(dbmp->addr, dbmp->mutexp); 135*7c478bd9Sstevel@tonic-gate UNLOCKREGION(dbmp); 136*7c478bd9Sstevel@tonic-gate } 137*7c478bd9Sstevel@tonic-gate 138*7c478bd9Sstevel@tonic-gate /* Close the region. */ 139*7c478bd9Sstevel@tonic-gate if ((t_ret = __db_rdetach(&dbmp->reginfo)) != 0 && ret == 0) 140*7c478bd9Sstevel@tonic-gate ret = t_ret; 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate if (dbmp->reginfo.path != NULL) 143*7c478bd9Sstevel@tonic-gate __os_freestr(dbmp->reginfo.path); 144*7c478bd9Sstevel@tonic-gate __os_free(dbmp, sizeof(DB_MPOOL)); 145*7c478bd9Sstevel@tonic-gate 146*7c478bd9Sstevel@tonic-gate return (ret); 147*7c478bd9Sstevel@tonic-gate } 148*7c478bd9Sstevel@tonic-gate 149*7c478bd9Sstevel@tonic-gate /* 150*7c478bd9Sstevel@tonic-gate * __memp_panic -- 151*7c478bd9Sstevel@tonic-gate * Panic a memory pool. 152*7c478bd9Sstevel@tonic-gate * 153*7c478bd9Sstevel@tonic-gate * PUBLIC: void __memp_panic __P((DB_ENV *)); 154*7c478bd9Sstevel@tonic-gate */ 155*7c478bd9Sstevel@tonic-gate void 156*7c478bd9Sstevel@tonic-gate __memp_panic(dbenv) 157*7c478bd9Sstevel@tonic-gate DB_ENV *dbenv; 158*7c478bd9Sstevel@tonic-gate { 159*7c478bd9Sstevel@tonic-gate if (dbenv->mp_info != NULL) 160*7c478bd9Sstevel@tonic-gate dbenv->mp_info->mp->rlayout.panic = 1; 161*7c478bd9Sstevel@tonic-gate } 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate /* 164*7c478bd9Sstevel@tonic-gate * memp_unlink -- 165*7c478bd9Sstevel@tonic-gate * Exit a memory pool. 166*7c478bd9Sstevel@tonic-gate */ 167*7c478bd9Sstevel@tonic-gate int 168*7c478bd9Sstevel@tonic-gate memp_unlink(path, force, dbenv) 169*7c478bd9Sstevel@tonic-gate const char *path; 170*7c478bd9Sstevel@tonic-gate int force; 171*7c478bd9Sstevel@tonic-gate DB_ENV *dbenv; 172*7c478bd9Sstevel@tonic-gate { 173*7c478bd9Sstevel@tonic-gate REGINFO reginfo; 174*7c478bd9Sstevel@tonic-gate int ret; 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate memset(®info, 0, sizeof(reginfo)); 177*7c478bd9Sstevel@tonic-gate reginfo.dbenv = dbenv; 178*7c478bd9Sstevel@tonic-gate reginfo.appname = DB_APP_NONE; 179*7c478bd9Sstevel@tonic-gate if (path != NULL && (ret = __os_strdup(path, ®info.path)) != 0) 180*7c478bd9Sstevel@tonic-gate return (ret); 181*7c478bd9Sstevel@tonic-gate reginfo.file = DB_DEFAULT_MPOOL_FILE; 182*7c478bd9Sstevel@tonic-gate ret = __db_runlink(®info, force); 183*7c478bd9Sstevel@tonic-gate if (reginfo.path != NULL) 184*7c478bd9Sstevel@tonic-gate __os_freestr(reginfo.path); 185*7c478bd9Sstevel@tonic-gate return (ret); 186*7c478bd9Sstevel@tonic-gate } 187*7c478bd9Sstevel@tonic-gate 188*7c478bd9Sstevel@tonic-gate /* 189*7c478bd9Sstevel@tonic-gate * memp_register -- 190*7c478bd9Sstevel@tonic-gate * Register a file type's pgin, pgout routines. 191*7c478bd9Sstevel@tonic-gate */ 192*7c478bd9Sstevel@tonic-gate int 193*7c478bd9Sstevel@tonic-gate memp_register(dbmp, ftype, pgin, pgout) 194*7c478bd9Sstevel@tonic-gate DB_MPOOL *dbmp; 195*7c478bd9Sstevel@tonic-gate int ftype; 196*7c478bd9Sstevel@tonic-gate int (*pgin) __P((db_pgno_t, void *, DBT *)); 197*7c478bd9Sstevel@tonic-gate int (*pgout) __P((db_pgno_t, void *, DBT *)); 198*7c478bd9Sstevel@tonic-gate { 199*7c478bd9Sstevel@tonic-gate DB_MPREG *mpr; 200*7c478bd9Sstevel@tonic-gate int ret; 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate MP_PANIC_CHECK(dbmp); 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate if ((ret = __os_malloc(sizeof(DB_MPREG), NULL, &mpr)) != 0) 205*7c478bd9Sstevel@tonic-gate return (ret); 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate mpr->ftype = ftype; 208*7c478bd9Sstevel@tonic-gate mpr->pgin = pgin; 209*7c478bd9Sstevel@tonic-gate mpr->pgout = pgout; 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate /* 212*7c478bd9Sstevel@tonic-gate * Insert at the head. Because we do a linear walk, we'll find 213*7c478bd9Sstevel@tonic-gate * the most recent registry in the case of multiple entries, so 214*7c478bd9Sstevel@tonic-gate * we don't have to check for multiple registries. 215*7c478bd9Sstevel@tonic-gate */ 216*7c478bd9Sstevel@tonic-gate LOCKHANDLE(dbmp, dbmp->mutexp); 217*7c478bd9Sstevel@tonic-gate LIST_INSERT_HEAD(&dbmp->dbregq, mpr, q); 218*7c478bd9Sstevel@tonic-gate UNLOCKHANDLE(dbmp, dbmp->mutexp); 219*7c478bd9Sstevel@tonic-gate 220*7c478bd9Sstevel@tonic-gate return (0); 221*7c478bd9Sstevel@tonic-gate } 222