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
00023
00024
00025
00026
00027
00028 void
00029 __memp_dbenv_create(dbenv)
00030 DB_ENV *dbenv;
00031 {
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 dbenv->mp_bytes =
00046 32 * ((8 * 1024) + sizeof(BH)) + 37 * sizeof(DB_MPOOL_HASH);
00047 dbenv->mp_ncache = 1;
00048 }
00049
00050
00051
00052
00053
00054
00055
00056
00057 int
00058 __memp_get_cachesize(dbenv, gbytesp, bytesp, ncachep)
00059 DB_ENV *dbenv;
00060 u_int32_t *gbytesp, *bytesp;
00061 int *ncachep;
00062 {
00063 MPOOL *mp;
00064
00065 ENV_NOT_CONFIGURED(dbenv,
00066 dbenv->mp_handle, "DB_ENV->get_cachesize", DB_INIT_MPOOL);
00067
00068 if (MPOOL_ON(dbenv)) {
00069
00070 mp = ((DB_MPOOL *)dbenv->mp_handle)->reginfo[0].primary;
00071 if (gbytesp != NULL)
00072 *gbytesp = mp->stat.st_gbytes;
00073 if (bytesp != NULL)
00074 *bytesp = mp->stat.st_bytes;
00075 if (ncachep != NULL)
00076 *ncachep = (int)mp->nreg;
00077 } else {
00078 if (gbytesp != NULL)
00079 *gbytesp = dbenv->mp_gbytes;
00080 if (bytesp != NULL)
00081 *bytesp = dbenv->mp_bytes;
00082 if (ncachep != NULL)
00083 *ncachep = (int)dbenv->mp_ncache;
00084 }
00085 return (0);
00086 }
00087
00088
00089
00090
00091
00092
00093
00094 int
00095 __memp_set_cachesize(dbenv, gbytes, bytes, arg_ncache)
00096 DB_ENV *dbenv;
00097 u_int32_t gbytes, bytes;
00098 int arg_ncache;
00099 {
00100 u_int ncache;
00101
00102 ENV_ILLEGAL_AFTER_OPEN(dbenv, "DB_ENV->set_cachesize");
00103
00104
00105 ncache = arg_ncache <= 0 ? 1 : (u_int)arg_ncache;
00106
00107
00108
00109
00110
00111 if (sizeof(roff_t) == 4 && gbytes / ncache == 4 && bytes == 0) {
00112 --gbytes;
00113 bytes = GIGABYTE - 1;
00114 } else {
00115 gbytes += bytes / GIGABYTE;
00116 bytes %= GIGABYTE;
00117 }
00118
00119
00120
00121
00122
00123
00124
00125
00126 if (sizeof(roff_t) <= 4) {
00127 if (gbytes / ncache >= 4) {
00128 __db_err(dbenv,
00129 "individual cache size too large: maximum is 4GB");
00130 return (EINVAL);
00131 }
00132 } else
00133 if (gbytes / ncache > 10000) {
00134 __db_err(dbenv,
00135 "individual cache size too large: maximum is 10TB");
00136 return (EINVAL);
00137 }
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 if (gbytes == 0) {
00151 if (bytes < 500 * MEGABYTE)
00152 bytes += (bytes / 4) + 37 * sizeof(DB_MPOOL_HASH);
00153 if (bytes / ncache < DB_CACHESIZE_MIN)
00154 bytes = ncache * DB_CACHESIZE_MIN;
00155 }
00156
00157 dbenv->mp_gbytes = gbytes;
00158 dbenv->mp_bytes = bytes;
00159 dbenv->mp_ncache = ncache;
00160
00161 return (0);
00162 }
00163
00164
00165
00166
00167 int
00168 __memp_get_mp_max_openfd(dbenv, maxopenfdp)
00169 DB_ENV *dbenv;
00170 int *maxopenfdp;
00171 {
00172 DB_MPOOL *dbmp;
00173 MPOOL *mp;
00174
00175 ENV_NOT_CONFIGURED(dbenv,
00176 dbenv->mp_handle, "DB_ENV->get_mp_max_openfd", DB_INIT_MPOOL);
00177
00178 if (MPOOL_ON(dbenv)) {
00179 dbmp = dbenv->mp_handle;
00180 mp = dbmp->reginfo[0].primary;
00181 MPOOL_SYSTEM_LOCK(dbenv);
00182 *maxopenfdp = mp->mp_maxopenfd;
00183 MPOOL_SYSTEM_UNLOCK(dbenv);
00184 } else
00185 *maxopenfdp = dbenv->mp_maxopenfd;
00186 return (0);
00187 }
00188
00189
00190
00191
00192
00193
00194 int
00195 __memp_set_mp_max_openfd(dbenv, maxopenfd)
00196 DB_ENV *dbenv;
00197 int maxopenfd;
00198 {
00199 DB_MPOOL *dbmp;
00200 MPOOL *mp;
00201
00202 ENV_NOT_CONFIGURED(dbenv,
00203 dbenv->mp_handle, "DB_ENV->set_mp_max_openfd", DB_INIT_MPOOL);
00204
00205 if (MPOOL_ON(dbenv)) {
00206 dbmp = dbenv->mp_handle;
00207 mp = dbmp->reginfo[0].primary;
00208 MPOOL_SYSTEM_LOCK(dbenv);
00209 mp->mp_maxopenfd = maxopenfd;
00210 MPOOL_SYSTEM_UNLOCK(dbenv);
00211 } else
00212 dbenv->mp_maxopenfd = maxopenfd;
00213 return (0);
00214 }
00215
00216
00217
00218
00219 int
00220 __memp_get_mp_max_write(dbenv, maxwritep, maxwrite_sleepp)
00221 DB_ENV *dbenv;
00222 int *maxwritep, *maxwrite_sleepp;
00223 {
00224 DB_MPOOL *dbmp;
00225 MPOOL *mp;
00226
00227 ENV_NOT_CONFIGURED(dbenv,
00228 dbenv->mp_handle, "DB_ENV->get_mp_max_write", DB_INIT_MPOOL);
00229
00230 if (MPOOL_ON(dbenv)) {
00231 dbmp = dbenv->mp_handle;
00232 mp = dbmp->reginfo[0].primary;
00233 MPOOL_SYSTEM_LOCK(dbenv);
00234 *maxwritep = mp->mp_maxwrite;
00235 *maxwrite_sleepp = mp->mp_maxwrite_sleep;
00236 MPOOL_SYSTEM_UNLOCK(dbenv);
00237 } else {
00238 *maxwritep = dbenv->mp_maxwrite;
00239 *maxwrite_sleepp = dbenv->mp_maxwrite_sleep;
00240 }
00241 return (0);
00242 }
00243
00244
00245
00246
00247
00248
00249
00250 int
00251 __memp_set_mp_max_write(dbenv, maxwrite, maxwrite_sleep)
00252 DB_ENV *dbenv;
00253 int maxwrite, maxwrite_sleep;
00254 {
00255 DB_MPOOL *dbmp;
00256 MPOOL *mp;
00257
00258 ENV_NOT_CONFIGURED(dbenv,
00259 dbenv->mp_handle, "DB_ENV->get_mp_max_write", DB_INIT_MPOOL);
00260
00261 if (MPOOL_ON(dbenv)) {
00262 dbmp = dbenv->mp_handle;
00263 mp = dbmp->reginfo[0].primary;
00264 MPOOL_SYSTEM_LOCK(dbenv);
00265 mp->mp_maxwrite = maxwrite;
00266 mp->mp_maxwrite_sleep = maxwrite_sleep;
00267 MPOOL_SYSTEM_UNLOCK(dbenv);
00268 } else {
00269 dbenv->mp_maxwrite = maxwrite;
00270 dbenv->mp_maxwrite_sleep = maxwrite_sleep;
00271 }
00272 return (0);
00273 }
00274
00275
00276
00277
00278 int
00279 __memp_get_mp_mmapsize(dbenv, mp_mmapsizep)
00280 DB_ENV *dbenv;
00281 size_t *mp_mmapsizep;
00282 {
00283 DB_MPOOL *dbmp;
00284 MPOOL *mp;
00285
00286 ENV_NOT_CONFIGURED(dbenv,
00287 dbenv->mp_handle, "DB_ENV->get_mp_max_mmapsize", DB_INIT_MPOOL);
00288
00289 if (MPOOL_ON(dbenv)) {
00290 dbmp = dbenv->mp_handle;
00291 mp = dbmp->reginfo[0].primary;
00292 MPOOL_SYSTEM_LOCK(dbenv);
00293 *mp_mmapsizep = mp->mp_mmapsize;
00294 MPOOL_SYSTEM_UNLOCK(dbenv);
00295 } else
00296 *mp_mmapsizep = dbenv->mp_mmapsize;
00297 return (0);
00298 }
00299
00300
00301
00302
00303
00304
00305
00306 int
00307 __memp_set_mp_mmapsize(dbenv, mp_mmapsize)
00308 DB_ENV *dbenv;
00309 size_t mp_mmapsize;
00310 {
00311 DB_MPOOL *dbmp;
00312 MPOOL *mp;
00313
00314 ENV_NOT_CONFIGURED(dbenv,
00315 dbenv->mp_handle, "DB_ENV->get_mp_max_mmapsize", DB_INIT_MPOOL);
00316
00317 if (MPOOL_ON(dbenv)) {
00318 dbmp = dbenv->mp_handle;
00319 mp = dbmp->reginfo[0].primary;
00320 MPOOL_SYSTEM_LOCK(dbenv);
00321 mp->mp_mmapsize = mp_mmapsize;
00322 MPOOL_SYSTEM_UNLOCK(dbenv);
00323 } else
00324 dbenv->mp_mmapsize = mp_mmapsize;
00325 return (0);
00326 }
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338 int
00339 __memp_nameop(dbenv, fileid, newname, fullold, fullnew, inmem)
00340 DB_ENV *dbenv;
00341 u_int8_t *fileid;
00342 const char *newname, *fullold, *fullnew;
00343 int inmem;
00344 {
00345 DB_MPOOL *dbmp;
00346 MPOOL *mp;
00347 MPOOLFILE *save_mfp, *mfp;
00348 roff_t newname_off;
00349 int is_remove, locked, ret;
00350 void *p;
00351
00352 ret = locked = 0;
00353 dbmp = NULL;
00354 save_mfp = mfp = NULL;
00355 is_remove = newname == NULL;
00356 if (!MPOOL_ON(dbenv))
00357 goto fsop;
00358
00359 dbmp = dbenv->mp_handle;
00360 mp = dbmp->reginfo[0].primary;
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372 if (is_remove) {
00373 p = NULL;
00374 COMPQUIET(newname_off, INVALID_ROFF);
00375 } else {
00376 if ((ret = __memp_alloc(dbmp, dbmp->reginfo,
00377 NULL, strlen(newname) + 1, &newname_off, &p)) != 0)
00378 return (ret);
00379 memcpy(p, newname, strlen(newname) + 1);
00380 }
00381
00382 locked = 1;
00383 MPOOL_SYSTEM_LOCK(dbenv);
00384
00385
00386
00387
00388
00389
00390
00391
00392 for (mfp = SH_TAILQ_FIRST(&mp->mpfq, __mpoolfile);
00393 mfp != NULL; mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile)) {
00394
00395 if (mfp->deadfile || F_ISSET(mfp, MP_TEMP))
00396 continue;
00397
00398 if (!is_remove && inmem && mfp->no_backing_file &&
00399 strcmp(newname, R_ADDR(dbmp->reginfo, mfp->path_off))
00400 == 0) {
00401 ret = EEXIST;
00402 goto err;
00403 }
00404
00405
00406 if (memcmp(fileid, R_ADDR(
00407 dbmp->reginfo, mfp->fileid_off), DB_FILE_ID_LEN) != 0)
00408 continue;
00409
00410 if (is_remove) {
00411 MUTEX_LOCK(dbenv, mfp->mutex);
00412
00413
00414
00415
00416
00417
00418 if (mfp->no_backing_file)
00419 mfp->mpf_cnt--;
00420 mfp->deadfile = 1;
00421 MUTEX_UNLOCK(dbenv, mfp->mutex);
00422 } else {
00423
00424
00425
00426
00427 p = R_ADDR(dbmp->reginfo, mfp->path_off);
00428 mfp->path_off = newname_off;
00429 }
00430 save_mfp = mfp;
00431 if (!inmem || is_remove)
00432 break;
00433 }
00434
00435
00436 if (p != NULL)
00437 __db_shalloc_free(&dbmp->reginfo[0], p);
00438
00439 fsop: if (save_mfp == NULL && inmem) {
00440 ret = ENOENT;
00441 goto err;
00442 }
00443
00444
00445
00446
00447
00448 if (save_mfp == NULL || !save_mfp->no_backing_file) {
00449 if (is_remove) {
00450
00451
00452
00453
00454
00455 if ((ret = __os_unlink(dbenv, fullold)) == ENOENT)
00456 ret = 0;
00457 } else {
00458
00459
00460
00461
00462 DB_ASSERT(fullnew != NULL);
00463 if (fullnew == NULL)
00464 return (EINVAL);
00465 ret = __os_rename(dbenv, fullold, fullnew, 1);
00466 }
00467 }
00468
00469 err: if (locked)
00470 MPOOL_SYSTEM_UNLOCK(dbenv);
00471
00472 return (ret);
00473 }
00474
00475
00476
00477
00478
00479
00480
00481 int
00482 __memp_get_refcnt(dbenv, fileid, refp)
00483 DB_ENV *dbenv;
00484 u_int8_t *fileid;
00485 u_int32_t *refp;
00486 {
00487 DB_MPOOL *dbmp;
00488 MPOOL *mp;
00489 MPOOLFILE *mfp;
00490
00491 *refp = 0;
00492
00493 if (!MPOOL_ON(dbenv))
00494 return (0);
00495
00496 dbmp = dbenv->mp_handle;
00497 mp = dbmp->reginfo[0].primary;
00498
00499 MPOOL_SYSTEM_LOCK(dbenv);
00500
00501
00502
00503
00504 for (mfp = SH_TAILQ_FIRST(&mp->mpfq, __mpoolfile);
00505 mfp != NULL; mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile)) {
00506
00507
00508 if (mfp->deadfile || F_ISSET(mfp, MP_TEMP))
00509 continue;
00510
00511
00512 if (memcmp(fileid, R_ADDR(
00513 dbmp->reginfo, mfp->fileid_off), DB_FILE_ID_LEN) != 0)
00514 continue;
00515
00516 MUTEX_LOCK(dbenv, mfp->mutex);
00517 *refp = mfp->mpf_cnt;
00518 MUTEX_UNLOCK(dbenv, mfp->mutex);
00519 break;
00520 }
00521 MPOOL_SYSTEM_UNLOCK(dbenv);
00522
00523 return (0);
00524 }
00525
00526 #ifdef HAVE_FTRUNCATE
00527
00528
00529
00530
00531
00532
00533 int
00534 __memp_ftruncate(dbmfp, pgno, flags)
00535 DB_MPOOLFILE *dbmfp;
00536 db_pgno_t pgno;
00537 u_int32_t flags;
00538 {
00539 DB_ENV *dbenv;
00540 void *pagep;
00541 db_pgno_t last_pgno, pg;
00542 u_int32_t mbytes, bytes, pgsize;
00543 int ret;
00544
00545 dbenv = dbmfp->dbenv;
00546
00547 MPOOL_SYSTEM_LOCK(dbenv);
00548 last_pgno = dbmfp->mfp->last_pgno;
00549 MPOOL_SYSTEM_UNLOCK(dbenv);
00550
00551 if (pgno > last_pgno) {
00552 if (LF_ISSET(MP_TRUNC_RECOVER))
00553 return (0);
00554 __db_err(dbenv, "Truncate beyond the end of file");
00555 return (EINVAL);
00556 }
00557
00558 pg = pgno;
00559 do {
00560 if ((ret =
00561 __memp_fget(dbmfp, &pg, DB_MPOOL_FREE, &pagep)) != 0)
00562 return (ret);
00563 } while (pg++ < last_pgno);
00564
00565
00566
00567
00568
00569
00570
00571 if (!F_ISSET(dbmfp->mfp, MP_TEMP) && !dbmfp->mfp->no_backing_file &&
00572 (ret = __os_truncate(dbenv,
00573 dbmfp->fhp, pgno, dbmfp->mfp->stat.st_pagesize)) != 0) {
00574 if ((__os_ioinfo(dbenv,
00575 NULL, dbmfp->fhp, &mbytes, &bytes, NULL)) != 0)
00576 return (ret);
00577 pgsize = dbmfp->mfp->stat.st_pagesize;
00578 if (pgno < (mbytes * (MEGABYTE / pgsize)) + (bytes / pgsize))
00579 return (ret);
00580 ret = 0;
00581 }
00582
00583
00584
00585
00586
00587
00588 MPOOL_SYSTEM_LOCK(dbenv);
00589 dbmfp->mfp->last_pgno = pgno - 1;
00590 MPOOL_SYSTEM_UNLOCK(dbenv);
00591
00592 return (ret);
00593 }
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606 int
00607 __memp_alloc_freelist(dbmfp, nelems, listp)
00608 DB_MPOOLFILE *dbmfp;
00609 u_int32_t nelems;
00610 db_pgno_t **listp;
00611 {
00612 DB_ENV *dbenv;
00613 DB_MPOOL *dbmp;
00614 MPOOLFILE *mfp;
00615 void *retp;
00616 int ret;
00617
00618 dbenv = dbmfp->dbenv;
00619 dbmp = dbenv->mp_handle;
00620 mfp = dbmfp->mfp;
00621
00622 *listp = NULL;
00623
00624
00625
00626
00627
00628 mfp->free_ref++;
00629 if (mfp->free_size != 0)
00630 return (EBUSY);
00631
00632
00633 mfp->free_cnt = nelems;
00634 if (nelems == 0)
00635 nelems = 50;
00636
00637 if ((ret = __memp_alloc(dbmp, dbmp->reginfo,
00638 NULL, nelems * sizeof(db_pgno_t), &mfp->free_list, &retp)) != 0)
00639 return (ret);
00640
00641 mfp->free_size = nelems * sizeof(db_pgno_t);
00642
00643 *listp = retp;
00644
00645 return (0);
00646 }
00647
00648
00649
00650
00651
00652
00653 void
00654 __memp_free_freelist(dbmfp)
00655 DB_MPOOLFILE *dbmfp;
00656 {
00657 DB_ENV *dbenv;
00658 DB_MPOOL *dbmp;
00659 MPOOLFILE *mfp;
00660
00661 dbenv = dbmfp->dbenv;
00662 dbmp = dbenv->mp_handle;
00663 mfp = dbmfp->mfp;
00664
00665 DB_ASSERT(mfp->free_ref > 0);
00666 if (--mfp->free_ref > 0)
00667 return;
00668
00669 DB_ASSERT(mfp->free_size != 0);
00670
00671 __db_shalloc_free(dbmp->reginfo, R_ADDR(dbmp->reginfo, mfp->free_list));
00672
00673 mfp->free_cnt = 0;
00674 mfp->free_list = 0;
00675 mfp->free_size = 0;
00676 }
00677
00678
00679
00680
00681
00682
00683
00684 int
00685 __memp_get_freelist(dbmfp, nelemp, listp)
00686 DB_MPOOLFILE *dbmfp;
00687 u_int32_t *nelemp;
00688 db_pgno_t **listp;
00689 {
00690 MPOOLFILE *mfp;
00691 DB_ENV *dbenv;
00692 DB_MPOOL *dbmp;
00693
00694 dbenv = dbmfp->dbenv;
00695 dbmp = dbenv->mp_handle;
00696 mfp = dbmfp->mfp;
00697
00698 if (mfp->free_size == 0) {
00699 *nelemp = 0;
00700 *listp = NULL;
00701 return (0);
00702 }
00703
00704 *nelemp = mfp->free_cnt;
00705 *listp = R_ADDR(dbmp->reginfo, mfp->free_list);
00706
00707 return (0);
00708 }
00709
00710
00711
00712
00713
00714
00715
00716 int
00717 __memp_extend_freelist(dbmfp, count, listp)
00718 DB_MPOOLFILE *dbmfp;
00719 u_int32_t count;
00720 db_pgno_t **listp;
00721 {
00722 DB_ENV *dbenv;
00723 DB_MPOOL *dbmp;
00724 MPOOLFILE *mfp;
00725 int ret;
00726 void *retp;
00727
00728 dbenv = dbmfp->dbenv;
00729 dbmp = dbenv->mp_handle;
00730 mfp = dbmfp->mfp;
00731
00732 if (mfp->free_size == 0)
00733 return (EINVAL);
00734
00735 if (count * sizeof(db_pgno_t) > mfp->free_size) {
00736 mfp->free_size =
00737 (size_t)DB_ALIGN(count * sizeof(db_pgno_t), 512);
00738 *listp = R_ADDR(dbmp->reginfo, mfp->free_list);
00739 if ((ret = __memp_alloc(dbmp, dbmp->reginfo,
00740 NULL, mfp->free_size, &mfp->free_list, &retp)) != 0)
00741 return (ret);
00742
00743 memcpy(retp, *listp, mfp->free_cnt * sizeof(db_pgno_t));
00744
00745 __db_shalloc_free(dbmp->reginfo, *listp);
00746 }
00747
00748 mfp->free_cnt = count;
00749 *listp = R_ADDR(dbmp->reginfo, mfp->free_list);
00750
00751 return (0);
00752 }
00753 #endif