db

mp_region.c

Go to the documentation of this file.
00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 1996, 1997, 1998, 1999, 2000
00005  * Sleepycat Software. All rights reserved.
00006  */
00007 #include "config.h"
00008 
00009 #ifndef lint
00010 static const char revid[] = "$Id: mp__region_8c-source.html,v 1.1 2008年06月08日 10:20:49 sebdiaz Exp $";
00011 #endif /* not lint */
00012 
00013 #ifndef NO_SYSTEM_INCLUDES
00014 #include <sys/types.h>
00015 
00016 #include <errno.h>
00017 #include <string.h>
00018 #endif
00019 
00020 #include "db_int.h"
00021 #include "db_shash.h"
00022 #include "mp.h"
00023 
00024 static int __mpool_init __P((DB_ENV *, DB_MPOOL *, int, int));
00025 
00026 /*
00027  * CDB___memp_open --
00028  * Internal version of memp_open: only called from DB_ENV->open.
00029  *
00030  * PUBLIC: int CDB___memp_open __P((DB_ENV *));
00031  */
00032 int
00033 CDB___memp_open(dbenv)
00034 DB_ENV *dbenv;
00035 {
00036 DB_MPOOL *dbmp;
00037 MPOOL *mp;
00038 REGINFO reginfo;
00039 roff_t reg_size, *regids;
00040 u_int32_t i;
00041 int htab_buckets, ret;
00042 
00043 /* Figure out how big each cache region is. */
00044 reg_size = dbenv->mp_gbytes / dbenv->mp_ncache;
00045 reg_size += (dbenv->mp_gbytes % dbenv->mp_ncache) / dbenv->mp_ncache;
00046 reg_size += dbenv->mp_bytes / dbenv->mp_ncache;
00047 
00048 /*
00049  * Figure out how many hash buckets each region will have. Assume we
00050  * want to keep the hash chains with under 10 pages on each chain. We
00051  * don't know the pagesize in advance, and it may differ for different
00052  * files. Use a pagesize of 1K for the calculation -- we walk these
00053  * chains a lot, they must be kept short.
00054  */
00055 htab_buckets = CDB___db_tablesize((reg_size / (1 * 1024)) / 10);
00056 
00057 /* Create and initialize the DB_MPOOL structure. */
00058 if ((ret = CDB___os_calloc(dbenv, 1, sizeof(*dbmp), &dbmp)) != 0)
00059 return (ret);
00060 LIST_INIT(&dbmp->dbregq);
00061 TAILQ_INIT(&dbmp->dbmfq);
00062 dbmp->dbenv = dbenv;
00063 
00064 /* Join/create the first mpool region. */
00065 reginfo.id = REG_ID_MPOOL;
00066 reginfo.mode = dbenv->db_mode;
00067 if (F_ISSET(dbenv, DB_ENV_CREATE))
00068 F_SET(&reginfo, REGION_CREATE_OK);
00069 if ((ret = CDB___db_r_attach(dbenv, &reginfo, reg_size)) != 0)
00070 goto err;
00071 
00072 /*
00073  * If we created the region, initialize it. Create or join any
00074  * additional regions.
00075  */
00076 if (F_ISSET(&reginfo, REGION_CREATE)) {
00077 /*
00078  * We define how many regions there are going to be, allocate
00079  * the REGINFO structures and create them. Make sure we don't
00080  * clear the wrong entries on error.
00081  */
00082 dbmp->nreg = dbenv->mp_ncache;
00083 if ((ret = CDB___os_calloc(dbenv,
00084 dbmp->nreg, sizeof(REGINFO), &dbmp->reginfo)) != 0)
00085 goto err;
00086 for (i = 0; i < dbmp->nreg; ++i)
00087 dbmp->reginfo[i].id = REG_ID_INVALID;
00088 dbmp->reginfo[0] = reginfo;
00089 
00090 /* Initialize the first region. */
00091 if ((ret = __mpool_init(dbenv, dbmp, 0, htab_buckets)) != 0)
00092 goto err;
00093 
00094 /*
00095  * Create/initialize remaining regions and copy their IDs into
00096  * the first region.
00097  */
00098 mp = R_ADDR(dbmp->reginfo, dbmp->reginfo[0].rp->primary);
00099 regids = R_ADDR(dbmp->reginfo, mp->regids);
00100 for (i = 1; i < dbmp->nreg; ++i) {
00101 dbmp->reginfo[i].id = REG_ID_INVALID;
00102 dbmp->reginfo[i].mode = dbenv->db_mode;
00103 F_SET(&dbmp->reginfo[i], REGION_CREATE_OK);
00104 if ((ret = CDB___db_r_attach(
00105 dbenv, &dbmp->reginfo[i], reg_size)) != 0)
00106 goto err;
00107 if ((ret =
00108 __mpool_init(dbenv, dbmp, i, htab_buckets)) != 0)
00109 goto err;
00110 R_UNLOCK(dbenv, &dbmp->reginfo[i]);
00111 
00112 regids[i] = dbmp->reginfo[i].id;
00113 }
00114 } else {
00115 /*
00116  * Determine how many regions there are going to be, allocate
00117  * the REGINFO structures and fill in local copies of that
00118  * information. Make sure we don't clear the wrong entries on
00119  * error.
00120  */
00121 mp = R_ADDR(&reginfo, reginfo.rp->primary);
00122 dbmp->nreg = mp->nreg;
00123 if ((ret = CDB___os_calloc(dbenv,
00124 dbmp->nreg, sizeof(REGINFO), &dbmp->reginfo)) != 0)
00125 goto err;
00126 for (i = 0; i < dbmp->nreg; ++i)
00127 dbmp->reginfo[i].id = REG_ID_INVALID;
00128 dbmp->reginfo[0] = reginfo;
00129 
00130 /* Join/initialize remaining regions. */
00131 regids = R_ADDR(dbmp->reginfo, mp->regids);
00132 for (i = 1; i < dbmp->nreg; ++i) {
00133 dbmp->reginfo[i].id = regids[i];
00134 dbmp->reginfo[i].mode = 0;
00135 if ((ret = CDB___db_r_attach(
00136 dbenv, &dbmp->reginfo[i], 0)) != 0)
00137 goto err;
00138 R_UNLOCK(dbenv, &dbmp->reginfo[i]);
00139 }
00140 }
00141 
00142 /* Set the local addresses for the regions. */
00143 for (i = 0; i < dbmp->nreg; ++i)
00144 dbmp->reginfo[i].primary =
00145 R_ADDR(&dbmp->reginfo[i], dbmp->reginfo[i].rp->primary);
00146 
00147 R_UNLOCK(dbenv, dbmp->reginfo);
00148 
00149 /* If the region is threaded, allocate a mutex to lock the handles. */
00150 if (F_ISSET(dbenv, DB_ENV_THREAD)) {
00151 if ((ret = CDB___db_mutex_alloc(
00152 dbenv, dbmp->reginfo, &dbmp->mutexp)) != 0) {
00153 goto err;
00154 }
00155 if ((ret =
00156 __db_mutex_init(dbenv, dbmp->mutexp, 0, MUTEX_THREAD)) != 0)
00157 goto err;
00158 }
00159 
00160 dbenv->mp_handle = dbmp;
00161 return (0);
00162 
00163 err: if (dbmp->reginfo[0].addr != NULL) {
00164 if (F_ISSET(dbmp->reginfo, REGION_CREATE))
00165 for (i = 0; i < dbmp->nreg; ++i)
00166 if (dbmp->reginfo[i].id != REG_ID_INVALID)
00167 F_SET(dbmp->reginfo[i].rp, REG_DEAD);
00168 
00169 R_UNLOCK(dbenv, dbmp->reginfo);
00170 
00171 for (i = 0; i < dbmp->nreg; ++i)
00172 if (dbmp->reginfo[i].id != REG_ID_INVALID)
00173 (void)CDB___db_r_detach(
00174 dbenv, &dbmp->reginfo[i], 0);
00175 CDB___os_free(dbmp->reginfo,
00176 dbmp->nreg * sizeof(*dbmp->reginfo));
00177 }
00178 CDB___os_free(dbmp, sizeof(*dbmp));
00179 return (ret);
00180 }
00181 
00182 /*
00183  * __mpool_init --
00184  * Initialize a MPOOL structure in shared memory.
00185  */
00186 static int
00187 __mpool_init(dbenv, dbmp, reginfo_off, htab_buckets)
00188 DB_ENV *dbenv;
00189 DB_MPOOL *dbmp;
00190 int reginfo_off, htab_buckets;
00191 {
00192 DB_HASHTAB *htab;
00193 MPOOL *mp;
00194 REGINFO *reginfo;
00195 int ret;
00196 void *p;
00197 
00198 mp = NULL;
00199 
00200 reginfo = &dbmp->reginfo[reginfo_off];
00201 if ((ret = CDB___db_shalloc(reginfo->addr,
00202 sizeof(MPOOL), MUTEX_ALIGN, &reginfo->primary)) != 0)
00203 goto mem_err;
00204 reginfo->rp->primary = R_OFFSET(reginfo, reginfo->primary);
00205 mp = reginfo->primary;
00206 memset(mp, 0, sizeof(*mp));
00207 
00208 if (reginfo_off == 0) {
00209 SH_TAILQ_INIT(&mp->mpfq);
00210 
00211 if ((ret = __db_mutex_init(dbenv, &mp->sync_mutex,
00212 R_OFFSET(dbmp->reginfo,
00213 &mp->sync_mutex) + DB_FCNTL_OFF_MPOOL, 0)) != 0)
00214 goto err;
00215 
00216 ZERO_LSN(mp->lsn);
00217 mp->lsn_cnt = 0;
00218 
00219 mp->nreg = dbmp->nreg;
00220 if ((ret = CDB___db_shalloc(dbmp->reginfo[0].addr,
00221 dbmp->nreg * sizeof(int), 0, &p)) != 0)
00222 goto mem_err;
00223 mp->regids = R_OFFSET(dbmp->reginfo, p);
00224 }
00225 
00226 SH_TAILQ_INIT(&mp->bhq);
00227 
00228 /* Allocate hash table space and initialize it. */
00229 if ((ret = CDB___db_shalloc(reginfo->addr,
00230 htab_buckets * sizeof(DB_HASHTAB), 0, &htab)) != 0)
00231 goto mem_err;
00232 CDB___db_hashinit(htab, htab_buckets);
00233 mp->htab = R_OFFSET(reginfo, htab);
00234 mp->htab_buckets = htab_buckets;
00235 
00236 return (0);
00237 
00238 mem_err:CDB___db_err(dbenv, "Unable to allocate memory for mpool region");
00239 err: if (reginfo->primary != NULL)
00240 CDB___db_shalloc_free(reginfo->addr, reginfo->primary);
00241 return (ret);
00242 }
00243 
00244 /*
00245  * CDB___memp_close --
00246  * Internal version of memp_close: only called from DB_ENV->close.
00247  *
00248  * PUBLIC: int CDB___memp_close __P((DB_ENV *));
00249  */
00250 int
00251 CDB___memp_close(dbenv)
00252 DB_ENV *dbenv;
00253 {
00254 DB_MPOOL *dbmp;
00255 DB_MPOOLFILE *dbmfp;
00256 DB_MPREG *mpreg;
00257 u_int32_t i;
00258 int ret, t_ret;
00259 
00260 ret = 0;
00261 dbmp = dbenv->mp_handle;
00262 
00263 /* Discard DB_MPREGs. */
00264 while ((mpreg = LIST_FIRST(&dbmp->dbregq)) != NULL) {
00265 LIST_REMOVE(mpreg, q);
00266 CDB___os_free(mpreg, sizeof(DB_MPREG));
00267 }
00268 
00269 /* Discard DB_MPOOLFILEs. */
00270 while ((dbmfp = TAILQ_FIRST(&dbmp->dbmfq)) != NULL) {
00271 if ((t_ret = CDB_memp_fclose(dbmfp)) != 0 && ret == 0)
00272 ret = t_ret;
00273 }
00274 
00275 /* Discard the thread mutex. */
00276 if (dbmp->mutexp != NULL)
00277 CDB___db_mutex_free(dbenv, dbmp->reginfo, dbmp->mutexp);
00278 
00279 /* Detach from the region(s). */
00280 for (i = 0; i < dbmp->nreg; ++i)
00281 if ((t_ret = CDB___db_r_detach(
00282 dbenv, &dbmp->reginfo[i], 0)) != 0 && ret == 0)
00283 ret = t_ret;
00284 
00285 CDB___os_free(dbmp->reginfo, dbmp->nreg * sizeof(*dbmp->reginfo));
00286 CDB___os_free(dbmp, sizeof(*dbmp));
00287 
00288 dbenv->mp_handle = NULL;
00289 return (ret);
00290 }

Generated on Sun Jun 8 10:56:38 2008 for GNUmifluz by doxygen 1.5.5

AltStyle によって変換されたページ (->オリジナル) /