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