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 #endif
00017
00018 #include "db_int.h"
00019 #include "dbinc/db_shash.h"
00020 #include "dbinc/mp.h"
00021
00022 static int __memp_init __P((DB_ENV *, DB_MPOOL *, u_int, u_int32_t));
00023 static int __memp_init_config __P((DB_ENV *, MPOOL *));
00024 static void __memp_region_size __P((DB_ENV *, roff_t *, u_int32_t *));
00025
00026
00027
00028
00029
00030
00031
00032 int
00033 __memp_open(dbenv)
00034 DB_ENV *dbenv;
00035 {
00036 DB_MPOOL *dbmp;
00037 MPOOL *mp;
00038 REGINFO reginfo;
00039 roff_t reg_size;
00040 u_int i;
00041 u_int32_t htab_buckets, *regids;
00042 int ret;
00043
00044
00045 __memp_region_size(dbenv, ®_size, &htab_buckets);
00046
00047
00048 if ((ret = __os_calloc(dbenv, 1, sizeof(*dbmp), &dbmp)) != 0)
00049 return (ret);
00050 LIST_INIT(&dbmp->dbregq);
00051 TAILQ_INIT(&dbmp->dbmfq);
00052 dbmp->dbenv = dbenv;
00053
00054
00055 memset(®info, 0, sizeof(REGINFO));
00056 reginfo.dbenv = dbenv;
00057 reginfo.type = REGION_TYPE_MPOOL;
00058 reginfo.id = INVALID_REGION_ID;
00059 reginfo.flags = REGION_JOIN_OK;
00060 if (F_ISSET(dbenv, DB_ENV_CREATE))
00061 F_SET(®info, REGION_CREATE_OK);
00062 if ((ret = __db_r_attach(dbenv, ®info, reg_size)) != 0)
00063 goto err;
00064
00065
00066
00067
00068
00069 if (F_ISSET(®info, REGION_CREATE)) {
00070
00071
00072
00073
00074
00075 dbmp->nreg = dbenv->mp_ncache;
00076 if ((ret = __os_calloc(dbenv,
00077 dbmp->nreg, sizeof(REGINFO), &dbmp->reginfo)) != 0)
00078 goto err;
00079
00080 for (i = 0; i < dbmp->nreg; ++i)
00081 dbmp->reginfo[i].id = INVALID_REGION_ID;
00082 dbmp->reginfo[0] = reginfo;
00083
00084
00085 if ((ret = __memp_init(dbenv, dbmp, 0, htab_buckets)) != 0)
00086 goto err;
00087
00088
00089
00090
00091
00092 mp = R_ADDR(dbmp->reginfo, dbmp->reginfo[0].rp->primary);
00093 regids = R_ADDR(dbmp->reginfo, mp->regids);
00094 for (i = 1; i < dbmp->nreg; ++i) {
00095 dbmp->reginfo[i].dbenv = dbenv;
00096 dbmp->reginfo[i].type = REGION_TYPE_MPOOL;
00097 dbmp->reginfo[i].id = INVALID_REGION_ID;
00098 dbmp->reginfo[i].flags = REGION_CREATE_OK;
00099 if ((ret = __db_r_attach(
00100 dbenv, &dbmp->reginfo[i], reg_size)) != 0)
00101 goto err;
00102 if ((ret =
00103 __memp_init(dbenv, dbmp, i, htab_buckets)) != 0)
00104 goto err;
00105
00106 regids[i] = dbmp->reginfo[i].id;
00107 }
00108 } else {
00109
00110
00111
00112
00113
00114 mp = R_ADDR(®info, reginfo.rp->primary);
00115 dbmp->nreg = mp->nreg;
00116 if ((ret = __os_calloc(dbenv,
00117 dbmp->nreg, sizeof(REGINFO), &dbmp->reginfo)) != 0)
00118 goto err;
00119
00120 for (i = 0; i < dbmp->nreg; ++i)
00121 dbmp->reginfo[i].id = INVALID_REGION_ID;
00122 dbmp->reginfo[0] = reginfo;
00123
00124
00125 regids = R_ADDR(dbmp->reginfo, mp->regids);
00126 for (i = 1; i < dbmp->nreg; ++i) {
00127 dbmp->reginfo[i].dbenv = dbenv;
00128 dbmp->reginfo[i].type = REGION_TYPE_MPOOL;
00129 dbmp->reginfo[i].id = regids[i];
00130 dbmp->reginfo[i].flags = REGION_JOIN_OK;
00131 if ((ret = __db_r_attach(
00132 dbenv, &dbmp->reginfo[i], 0)) != 0)
00133 goto err;
00134 }
00135 }
00136
00137
00138 for (i = 0; i < dbmp->nreg; ++i)
00139 dbmp->reginfo[i].primary =
00140 R_ADDR(&dbmp->reginfo[i], dbmp->reginfo[i].rp->primary);
00141
00142
00143 if ((ret = __mutex_alloc(
00144 dbenv, MTX_MPOOL_HANDLE, DB_MUTEX_THREAD, &dbmp->mutex)) != 0)
00145 goto err;
00146
00147 dbenv->mp_handle = dbmp;
00148
00149
00150 if ((ret = __memp_init_config(dbenv, mp)) != 0)
00151 return (ret);
00152
00153 return (0);
00154
00155 err: dbenv->mp_handle = NULL;
00156 if (dbmp->reginfo != NULL && dbmp->reginfo[0].addr != NULL) {
00157 for (i = 0; i < dbmp->nreg; ++i)
00158 if (dbmp->reginfo[i].id != INVALID_REGION_ID)
00159 (void)__db_r_detach(
00160 dbenv, &dbmp->reginfo[i], 0);
00161 __os_free(dbenv, dbmp->reginfo);
00162 }
00163
00164 (void)__mutex_free(dbenv, &dbmp->mutex);
00165 __os_free(dbenv, dbmp);
00166 return (ret);
00167 }
00168
00169
00170
00171
00172
00173 static int
00174 __memp_init(dbenv, dbmp, reginfo_off, htab_buckets)
00175 DB_ENV *dbenv;
00176 DB_MPOOL *dbmp;
00177 u_int reginfo_off;
00178 u_int32_t htab_buckets;
00179 {
00180 DB_MPOOL_HASH *htab;
00181 MPOOL *mp;
00182 REGINFO *reginfo;
00183 u_int32_t i;
00184 int ret;
00185 void *p;
00186
00187 reginfo = &dbmp->reginfo[reginfo_off];
00188 if ((ret = __db_shalloc(
00189 reginfo, sizeof(MPOOL), 0, ®info->primary)) != 0)
00190 goto mem_err;
00191 reginfo->rp->primary = R_OFFSET(reginfo, reginfo->primary);
00192 mp = reginfo->primary;
00193 memset(mp, 0, sizeof(*mp));
00194
00195 if ((ret =
00196 __mutex_alloc(dbenv, MTX_MPOOL_REGION, 0, &mp->mtx_region)) != 0)
00197 return (ret);
00198
00199 if (reginfo_off == 0) {
00200 SH_TAILQ_INIT(&mp->mpfq);
00201
00202 ZERO_LSN(mp->lsn);
00203
00204 mp->nreg = dbmp->nreg;
00205 if ((ret = __db_shalloc(&dbmp->reginfo[0],
00206 dbmp->nreg * sizeof(u_int32_t), 0, &p)) != 0)
00207 goto mem_err;
00208 mp->regids = R_OFFSET(dbmp->reginfo, p);
00209 }
00210
00211
00212 if ((ret = __db_shalloc(reginfo,
00213 htab_buckets * sizeof(DB_MPOOL_HASH), 0, &htab)) != 0)
00214 goto mem_err;
00215 mp->htab = R_OFFSET(reginfo, htab);
00216 for (i = 0; i < htab_buckets; i++) {
00217 if ((ret = __mutex_alloc(
00218 dbenv, MTX_MPOOL_HASH_BUCKET, 0, &htab[i].mtx_hash)) != 0)
00219 return (ret);
00220 SH_TAILQ_INIT(&htab[i].hash_bucket);
00221 htab[i].hash_page_dirty = htab[i].hash_priority = 0;
00222 }
00223 mp->htab_buckets = mp->stat.st_hash_buckets = htab_buckets;
00224
00225
00226
00227
00228
00229 mp->stat.st_gbytes = dbenv->mp_gbytes;
00230 mp->stat.st_bytes = dbenv->mp_bytes;
00231 return (0);
00232
00233 mem_err:__db_err(dbenv, "Unable to allocate memory for mpool region");
00234 return (ret);
00235 }
00236
00237
00238
00239
00240
00241 static void
00242 __memp_region_size(dbenv, reg_sizep, htab_bucketsp)
00243 DB_ENV *dbenv;
00244 roff_t *reg_sizep;
00245 u_int32_t *htab_bucketsp;
00246 {
00247 roff_t reg_size;
00248
00249
00250 reg_size = (roff_t)(dbenv->mp_gbytes / dbenv->mp_ncache) * GIGABYTE;
00251 reg_size += ((roff_t)(dbenv->mp_gbytes %
00252 dbenv->mp_ncache) * GIGABYTE) / dbenv->mp_ncache;
00253 reg_size += dbenv->mp_bytes / dbenv->mp_ncache;
00254 *reg_sizep = reg_size;
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269 *htab_bucketsp = __db_tablesize((u_int32_t)(reg_size / (10 * 1024)));
00270 }
00271
00272
00273
00274
00275
00276
00277
00278 u_int32_t
00279 __memp_region_mutex_count(dbenv)
00280 DB_ENV *dbenv;
00281 {
00282 roff_t reg_size;
00283 u_int32_t htab_buckets;
00284
00285 __memp_region_size(dbenv, ®_size, &htab_buckets);
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295 return (dbenv->mp_ncache * htab_buckets * 21 + 50);
00296 }
00297
00298
00299
00300
00301
00302 static int
00303 __memp_init_config(dbenv, mp)
00304 DB_ENV *dbenv;
00305 MPOOL *mp;
00306 {
00307 MPOOL_SYSTEM_LOCK(dbenv);
00308
00309 if (dbenv->mp_mmapsize != 0)
00310 mp->mp_mmapsize = dbenv->mp_mmapsize;
00311 if (dbenv->mp_maxopenfd != 0)
00312 mp->mp_maxopenfd = dbenv->mp_maxopenfd;
00313 if (dbenv->mp_maxwrite != 0)
00314 mp->mp_maxwrite = dbenv->mp_maxwrite;
00315 if (dbenv->mp_maxwrite_sleep != 0)
00316 mp->mp_maxwrite_sleep = dbenv->mp_maxwrite_sleep;
00317
00318 MPOOL_SYSTEM_UNLOCK(dbenv);
00319
00320 return (0);
00321 }
00322
00323
00324
00325
00326
00327
00328
00329 int
00330 __memp_dbenv_refresh(dbenv)
00331 DB_ENV *dbenv;
00332 {
00333 BH *bhp;
00334 DB_MPOOL *dbmp;
00335 DB_MPOOLFILE *dbmfp;
00336 DB_MPOOL_HASH *hp;
00337 DB_MPREG *mpreg;
00338 MPOOL *mp;
00339 REGINFO *reginfo;
00340 u_int32_t bucket, i;
00341 int ret, t_ret;
00342
00343 ret = 0;
00344 dbmp = dbenv->mp_handle;
00345
00346
00347
00348
00349
00350
00351
00352
00353 if (F_ISSET(dbenv, DB_ENV_PRIVATE))
00354 for (i = 0; i < dbmp->nreg; ++i) {
00355 reginfo = &dbmp->reginfo[i];
00356 mp = reginfo->primary;
00357 for (hp = R_ADDR(reginfo, mp->htab), bucket = 0;
00358 bucket < mp->htab_buckets; ++hp, ++bucket)
00359 while ((bhp = SH_TAILQ_FIRST(
00360 &hp->hash_bucket, __bh)) != NULL)
00361 if ((t_ret = __memp_bhfree(
00362 dbmp, hp, bhp,
00363 BH_FREE_FREEMEM |
00364 BH_FREE_UNLOCKED)) != 0 && ret == 0)
00365 ret = t_ret;
00366 }
00367
00368
00369 while ((dbmfp = TAILQ_FIRST(&dbmp->dbmfq)) != NULL)
00370 if ((t_ret = __memp_fclose(dbmfp, 0)) != 0 && ret == 0)
00371 ret = t_ret;
00372
00373
00374 if (dbmp->pg_inout != NULL)
00375 __os_free(dbenv, dbmp->pg_inout);
00376 while ((mpreg = LIST_FIRST(&dbmp->dbregq)) != NULL) {
00377 LIST_REMOVE(mpreg, q);
00378 __os_free(dbenv, mpreg);
00379 }
00380
00381
00382 if ((t_ret = __mutex_free(dbenv, &dbmp->mutex)) != 0 && ret == 0)
00383 ret = t_ret;
00384
00385 if (F_ISSET(dbenv, DB_ENV_PRIVATE)) {
00386
00387 reginfo = &dbmp->reginfo[0];
00388 mp = dbmp->reginfo[0].primary;
00389 __db_shalloc_free(reginfo, R_ADDR(reginfo, mp->regids));
00390
00391
00392 for (i = 0; i < dbmp->nreg; ++i) {
00393 reginfo = &dbmp->reginfo[i];
00394 mp = reginfo->primary;
00395 __db_shalloc_free(reginfo, R_ADDR(reginfo, mp->htab));
00396 }
00397 }
00398
00399
00400 for (i = 0; i < dbmp->nreg; ++i) {
00401 reginfo = &dbmp->reginfo[i];
00402 if ((t_ret = __db_r_detach(dbenv, reginfo, 0)) != 0 && ret == 0)
00403 ret = t_ret;
00404 }
00405
00406
00407 __os_free(dbenv, dbmp->reginfo);
00408 __os_free(dbenv, dbmp);
00409
00410 dbenv->mp_handle = NULL;
00411 return (ret);
00412 }