00001
00002
00003
00004
00005
00006
00007 #include "config.h"
00008
00009 #ifndef lint
00010 static const char revid[] = "$Id: mp__fopen_8c-source.html,v 1.1 2008/06/08 10:20:46 sebdiaz Exp $";
00011 #endif
00012
00013 #ifndef NO_SYSTEM_INCLUDES
00014 #include <sys/types.h>
00015
00016 #include <errno.h>
00017 #include <string.h>
00018 #endif
00019
00020 #ifdef HAVE_RPC
00021 #include "db_server.h"
00022 #endif
00023
00024 #include "db_int.h"
00025 #include "db_shash.h"
00026 #include "db_page.h"
00027 #include "mp.h"
00028
00029 #ifdef HAVE_RPC
00030 #include "gen_client_ext.h"
00031 #include "rpc_client_ext.h"
00032 #endif
00033
00034 static int __memp_mf_open __P((DB_MPOOL *, const char *,
00035 size_t, db_pgno_t, DB_MPOOL_FINFO *, u_int32_t, MPOOLFILE **));
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 #define MEMP_FREMOVE(mfp) { \
00046 mfp->ftype = 0; \
00047 F_SET(mfp, MP_DEADFILE); \
00048 }
00049
00050
00051
00052
00053
00054 int
00055 CDB_memp_fopen(dbenv, path, flags, mode, pagesize, finfop, retp)
00056 DB_ENV *dbenv;
00057 const char *path;
00058 u_int32_t flags;
00059 int mode;
00060 size_t pagesize;
00061 DB_MPOOL_FINFO *finfop;
00062 DB_MPOOLFILE **retp;
00063 {
00064 DB_MPOOL *dbmp;
00065 int ret;
00066
00067 #ifdef HAVE_RPC
00068 if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
00069 return (__dbcl_memp_fopen(dbenv, path, flags,
00070 mode, pagesize, finfop, retp));
00071 #endif
00072
00073 PANIC_CHECK(dbenv);
00074 ENV_REQUIRES_CONFIG(dbenv, dbenv->mp_handle, DB_INIT_MPOOL);
00075
00076 dbmp = dbenv->mp_handle;
00077
00078
00079 if ((ret = CDB___db_fchk(dbenv, "CDB_memp_fopen", flags,
00080 DB_CREATE | DB_COMPRESS |
00081 DB_NOMMAP | DB_ODDFILESIZE | DB_RDONLY | DB_TRUNCATE)) != 0)
00082 return (ret);
00083
00084
00085
00086 if(LF_ISSET(DB_COMPRESS))
00087 LF_SET(DB_NOMMAP);
00088
00089
00090 if (pagesize == 0) {
00091 CDB___db_err(dbenv, "CDB_memp_fopen: pagesize not specified");
00092 return (EINVAL);
00093 }
00094 if (finfop != NULL && finfop->clear_len > pagesize)
00095 return (EINVAL);
00096
00097 return (CDB___memp_fopen(dbmp,
00098 NULL, path, flags, mode, pagesize, 1, finfop, retp));
00099 }
00100
00101
00102
00103
00104
00105
00106
00107
00108 int
00109 CDB___memp_fopen(dbmp, mfp, path, flags, mode, pagesize, needlock, finfop, retp)
00110 DB_MPOOL *dbmp;
00111 MPOOLFILE *mfp;
00112 const char *path;
00113 u_int32_t flags;
00114 int mode, needlock;
00115 size_t pagesize;
00116 DB_MPOOL_FINFO *finfop;
00117 DB_MPOOLFILE **retp;
00118 {
00119 DB_ENV *dbenv;
00120 DB_MPOOLFILE *dbmfp;
00121 DB_MPOOL_FINFO finfo;
00122 db_pgno_t last_pgno;
00123 size_t maxmap;
00124 u_int32_t mbytes, bytes, oflags;
00125 int ret;
00126 u_int8_t idbuf[DB_FILE_ID_LEN];
00127 char *rpath;
00128
00129 dbenv = dbmp->dbenv;
00130 ret = 0;
00131 rpath = NULL;
00132
00133
00134
00135
00136
00137
00138
00139 if (finfop == NULL) {
00140 memset(&finfo, 0, sizeof(finfo));
00141 if (mfp != NULL) {
00142 finfo.ftype = mfp->ftype;
00143 finfo.pgcookie = NULL;
00144 finfo.fileid = NULL;
00145 finfo.lsn_offset = mfp->lsn_off;
00146 finfo.clear_len = mfp->clear_len;
00147 } else {
00148 finfo.ftype = 0;
00149 finfo.pgcookie = NULL;
00150 finfo.fileid = NULL;
00151 finfo.lsn_offset = -1;
00152 finfo.clear_len = 0;
00153 }
00154 finfop = &finfo;
00155 }
00156
00157
00158 if ((ret = CDB___os_calloc(dbenv, 1, sizeof(DB_MPOOLFILE), &dbmfp)) != 0)
00159 return (ret);
00160 dbmfp->dbmp = dbmp;
00161 dbmfp->ref = 1;
00162 if (LF_ISSET(DB_RDONLY))
00163 F_SET(dbmfp, MP_READONLY);
00164 if (LF_ISSET(DB_COMPRESS))
00165 F_SET(dbmfp, MP_CMPR);
00166
00167 if (path == NULL) {
00168 if (LF_ISSET(DB_RDONLY)) {
00169 CDB___db_err(dbenv,
00170 "CDB_memp_fopen: temporary files can't be readonly");
00171 ret = EINVAL;
00172 goto err;
00173 }
00174 if (LF_ISSET(DB_COMPRESS)) {
00175 CDB___db_err(dbenv,
00176 "CDB_memp_fopen: temporary files can't be compressed");
00177 ret = EINVAL;
00178 goto err;
00179 }
00180 last_pgno = PGNO_BASE_MD;
00181 } else {
00182 size_t disk_pagesize = F_ISSET(dbmfp, MP_CMPR) ? DB_CMPR_DIVIDE(dbenv, pagesize) : pagesize;
00183
00184 if ((ret = CDB___db_appname(dbenv,
00185 DB_APP_DATA, NULL, path, 0, NULL, &rpath)) != 0)
00186 goto err;
00187 oflags = 0;
00188 if (LF_ISSET(DB_CREATE))
00189 oflags |= DB_OSO_CREATE;
00190 if (LF_ISSET(DB_RDONLY))
00191 oflags |= DB_OSO_RDONLY;
00192 if ((ret =
00193 CDB___os_open(dbenv, rpath, oflags, mode, &dbmfp->fh)) != 0) {
00194 CDB___db_err(dbenv, "%s: %s", rpath, CDB_db_strerror(ret));
00195 goto err;
00196 }
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211 if ((ret = CDB___os_ioinfo(dbenv, rpath,
00212 &dbmfp->fh, &mbytes, &bytes, NULL)) != 0) {
00213 CDB___db_err(dbenv, "%s: %s", rpath, CDB_db_strerror(ret));
00214 goto err;
00215 }
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225 if (bytes % disk_pagesize != 0) {
00226 if (LF_ISSET(DB_ODDFILESIZE))
00227
00228
00229
00230
00231
00232
00233 bytes -= (bytes % disk_pagesize);
00234 else {
00235 CDB___db_err(dbenv,
00236 "%s: file size not a multiple of the pagesize",
00237 rpath);
00238 ret = EINVAL;
00239 goto err;
00240 }
00241 }
00242
00243 last_pgno = mbytes * (MEGABYTE / disk_pagesize);
00244 last_pgno += bytes / disk_pagesize;
00245
00246
00247 if (last_pgno != 0)
00248 --last_pgno;
00249 else
00250 last_pgno = PGNO_BASE_MD;
00251
00252
00253
00254
00255
00256
00257 if (finfop->fileid == NULL) {
00258 if ((ret = CDB___os_fileid(dbenv, rpath, 0, idbuf)) != 0)
00259 goto err;
00260 finfop->fileid = idbuf;
00261 }
00262 }
00263
00264
00265
00266
00267
00268
00269 if (needlock)
00270 R_LOCK(dbenv, dbmp->reginfo);
00271 ret = mfp == NULL ? __memp_mf_open(
00272 dbmp, path, pagesize, last_pgno, finfop, flags, &mfp) : 0;
00273 if (needlock)
00274 R_UNLOCK(dbenv, dbmp->reginfo);
00275 if (ret != 0)
00276 goto err;
00277
00278 if (F_ISSET(dbenv, DB_ENV_THREAD)) {
00279 if ((ret = CDB___db_mutex_alloc(
00280 dbenv, dbmp->reginfo, &dbmfp->mutexp)) != 0)
00281 goto err;
00282 if ((ret = __db_mutex_init(
00283 dbenv, dbmfp->mutexp, 0, MUTEX_THREAD)) != 0)
00284 goto err;
00285
00286
00287 }
00288
00289 dbmfp->mfp = mfp;
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313 #define DB_MAXMMAPSIZE (10 * 1024 * 1024)
00314 if (F_ISSET(mfp, MP_CAN_MMAP)) {
00315 if (!F_ISSET(dbmfp, MP_READONLY))
00316 F_CLR(mfp, MP_CAN_MMAP);
00317 if (path == NULL)
00318 F_CLR(mfp, MP_CAN_MMAP);
00319 if (finfop->ftype != 0)
00320 F_CLR(mfp, MP_CAN_MMAP);
00321 if (LF_ISSET(DB_NOMMAP) || F_ISSET(dbenv, DB_ENV_NOMMAP))
00322 F_CLR(mfp, MP_CAN_MMAP);
00323 maxmap = dbenv->mp_mmapsize == 0 ?
00324 DB_MAXMMAPSIZE : dbenv->mp_mmapsize;
00325 if (mbytes > maxmap / MEGABYTE ||
00326 (mbytes == maxmap / MEGABYTE && bytes >= maxmap % MEGABYTE))
00327 F_CLR(mfp, MP_CAN_MMAP);
00328 }
00329 dbmfp->addr = NULL;
00330 if (F_ISSET(mfp, MP_CAN_MMAP)) {
00331 dbmfp->len = (size_t)mbytes * MEGABYTE + bytes;
00332 if (CDB___os_mapfile(dbenv, rpath,
00333 &dbmfp->fh, dbmfp->len, 1, &dbmfp->addr) != 0) {
00334 dbmfp->addr = NULL;
00335 F_CLR(mfp, MP_CAN_MMAP);
00336 }
00337 }
00338 if (rpath != NULL)
00339 CDB___os_freestr(rpath);
00340
00341 MUTEX_THREAD_LOCK(dbmp->mutexp);
00342 TAILQ_INSERT_TAIL(&dbmp->dbmfq, dbmfp, q);
00343 MUTEX_THREAD_UNLOCK(dbmp->mutexp);
00344
00345 *retp = dbmfp;
00346
00347 return (0);
00348
00349 err:
00350
00351
00352
00353 if (rpath != NULL)
00354 CDB___os_freestr(rpath);
00355 if (F_ISSET(&dbmfp->fh, DB_FH_VALID))
00356 (void)CDB___os_closehandle(&dbmfp->fh);
00357 if (dbmfp != NULL)
00358 CDB___os_free(dbmfp, sizeof(DB_MPOOLFILE));
00359 return (ret);
00360 }
00361 static MPOOL *mp;
00362
00363
00364
00365
00366
00367 static int
00368 __memp_mf_open(dbmp, path, pagesize, last_pgno, finfop, flags, retp)
00369 DB_MPOOL *dbmp;
00370 const char *path;
00371 size_t pagesize;
00372 db_pgno_t last_pgno;
00373 DB_MPOOL_FINFO *finfop;
00374 u_int32_t flags;
00375 MPOOLFILE **retp;
00376 {
00377 MPOOLFILE *mfp;
00378 int ret;
00379 void *p;
00380
00381 #define ISTEMPORARY (path == NULL)
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404 if (!ISTEMPORARY) {
00405 mp = dbmp->reginfo[0].primary;
00406 for (mfp = SH_TAILQ_FIRST(&mp->mpfq, __mpoolfile);
00407 mfp != NULL; mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile)) {
00408 if (F_ISSET(mfp, MP_DEADFILE | MP_TEMP))
00409 continue;
00410 if (memcmp(finfop->fileid, R_ADDR(dbmp->reginfo,
00411 mfp->fileid_off), DB_FILE_ID_LEN) == 0) {
00412 if (LF_ISSET(DB_TRUNCATE)) {
00413 MEMP_FREMOVE(mfp);
00414 continue;
00415 }
00416 if (finfop->clear_len != mfp->clear_len ||
00417 pagesize != mfp->stat.st_pagesize) {
00418 CDB___db_err(dbmp->dbenv,
00419 "%s: page size or clear length changed",
00420 path);
00421 return (EINVAL);
00422 }
00423
00424
00425
00426
00427
00428
00429
00430 if (finfop->ftype != 0)
00431 mfp->ftype = finfop->ftype;
00432
00433 ++mfp->ref_cnt;
00434
00435 *retp = mfp;
00436 return (0);
00437 }
00438 }
00439 }
00440
00441
00442 if ((ret = CDB___memp_alloc(
00443 dbmp, dbmp->reginfo, NULL, sizeof(MPOOLFILE), NULL, &mfp)) != 0)
00444 goto mem_err;
00445 *retp = mfp;
00446
00447
00448 memset(mfp, 0, sizeof(MPOOLFILE));
00449 mfp->ref_cnt = 1;
00450 mfp->ftype = finfop->ftype;
00451 mfp->lsn_off = finfop->lsn_offset;
00452 mfp->clear_len = finfop->clear_len;
00453 mfp->cmpr_free = PGNO_INVALID;
00454
00455
00456
00457
00458
00459
00460 mfp->stat.st_pagesize = pagesize;
00461 mfp->orig_last_pgno = mfp->last_pgno = last_pgno;
00462
00463 if (ISTEMPORARY)
00464 F_SET(mfp, MP_TEMP);
00465 else {
00466
00467 if ((ret = CDB___memp_alloc(dbmp, dbmp->reginfo,
00468 NULL, strlen(path) + 1, &mfp->path_off, &p)) != 0)
00469 goto err;
00470 memcpy(p, path, strlen(path) + 1);
00471
00472
00473 if ((ret = CDB___memp_alloc(dbmp, dbmp->reginfo,
00474 NULL, DB_FILE_ID_LEN, &mfp->fileid_off, &p)) != 0)
00475 goto err;
00476 memcpy(p, finfop->fileid, DB_FILE_ID_LEN);
00477
00478 F_SET(mfp, MP_CAN_MMAP);
00479 }
00480
00481
00482 if (finfop->pgcookie == NULL || finfop->pgcookie->size == 0) {
00483 mfp->pgcookie_len = 0;
00484 mfp->pgcookie_off = 0;
00485 } else {
00486 if ((ret = CDB___memp_alloc(dbmp, dbmp->reginfo,
00487 NULL, finfop->pgcookie->size, &mfp->pgcookie_off, &p)) != 0)
00488 goto err;
00489 memcpy(p, finfop->pgcookie->data, finfop->pgcookie->size);
00490 mfp->pgcookie_len = finfop->pgcookie->size;
00491 }
00492
00493
00494 mp = dbmp->reginfo[0].primary;
00495 SH_TAILQ_INSERT_HEAD(&mp->mpfq, mfp, q, __mpoolfile);
00496
00497 if((ret = CDB___memp_cmpr_open(dbmp->dbenv, mfp, path)) != 0)
00498 goto err;
00499
00500 if (0) {
00501 err: if (mfp->path_off != 0)
00502 CDB___db_shalloc_free(dbmp->reginfo[0].addr,
00503 R_ADDR(dbmp->reginfo, mfp->path_off));
00504 if (mfp->fileid_off != 0)
00505 CDB___db_shalloc_free(dbmp->reginfo[0].addr,
00506 R_ADDR(dbmp->reginfo, mfp->fileid_off));
00507 if (mfp != NULL)
00508 CDB___db_shalloc_free(dbmp->reginfo[0].addr, mfp);
00509 mem_err: CDB___db_err(dbmp->dbenv,
00510 "Unable to allocate memory for mpool file");
00511 }
00512 return (ret);
00513 }
00514
00515
00516
00517
00518
00519 int
00520 CDB_memp_fclose(dbmfp)
00521 DB_MPOOLFILE *dbmfp;
00522 {
00523 DB_ENV *dbenv;
00524 DB_MPOOL *dbmp;
00525 MPOOLFILE *mfp;
00526 int ret, t_ret;
00527
00528 dbmp = dbmfp->dbmp;
00529 dbenv = dbmp->dbenv;
00530 ret = 0;
00531
00532 PANIC_CHECK(dbenv);
00533
00534 #ifdef HAVE_RPC
00535 if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
00536 return (__dbcl_memp_fclose(dbmfp));
00537 #endif
00538
00539
00540
00541
00542
00543
00544 for (;;) {
00545 MUTEX_THREAD_LOCK(dbmp->mutexp);
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569 if (dbmfp->ref == 1) {
00570 TAILQ_REMOVE(&dbmp->dbmfq, dbmfp, q);
00571 break;
00572 }
00573 MUTEX_THREAD_UNLOCK(dbmp->mutexp);
00574
00575 (void)CDB___os_sleep(dbenv, 1, 0);
00576 }
00577 MUTEX_THREAD_UNLOCK(dbmp->mutexp);
00578
00579
00580 if (dbmfp->pinref != 0)
00581 CDB___db_err(dbenv, "%s: close: %lu blocks left pinned",
00582 CDB___memp_fn(dbmfp), (u_long)dbmfp->pinref);
00583
00584
00585 if (dbmfp->addr != NULL &&
00586 (ret = CDB___os_unmapfile(dbenv, dbmfp->addr, dbmfp->len)) != 0)
00587 CDB___db_err(dbenv, "%s: %s", CDB___memp_fn(dbmfp), CDB_db_strerror(ret));
00588
00589
00590 if (F_ISSET(&dbmfp->fh, DB_FH_VALID) &&
00591 (t_ret = CDB___os_closehandle(&dbmfp->fh)) != 0) {
00592 CDB___db_err(dbenv, "%s: %s", CDB___memp_fn(dbmfp), CDB_db_strerror(t_ret));
00593 if (ret != 0)
00594 t_ret = ret;
00595 }
00596
00597
00598 if (dbmfp->mutexp != NULL)
00599 CDB___db_mutex_free(dbenv, dbmp->reginfo, dbmfp->mutexp);
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612 R_LOCK(dbenv, dbmp->reginfo);
00613 mfp = dbmfp->mfp;
00614 if (--mfp->ref_cnt == 0)
00615 CDB___memp_mf_discard(dbmp, mfp);
00616 else if (F_ISSET(mfp, MP_TEMP))
00617 MEMP_FREMOVE(mfp);
00618 R_UNLOCK(dbenv, dbmp->reginfo);
00619
00620
00621 CDB___os_free(dbmfp, sizeof(DB_MPOOLFILE));
00622
00623 return (ret);
00624 }
00625
00626
00627
00628
00629
00630
00631
00632 void
00633 CDB___memp_mf_discard(dbmp, mfp)
00634 DB_MPOOL *dbmp;
00635 MPOOLFILE *mfp;
00636 {
00637 MPOOL *mp;
00638
00639 mp = dbmp->reginfo[0].primary;
00640
00641
00642 SH_TAILQ_REMOVE(&mp->mpfq, mfp, q, __mpoolfile);
00643
00644
00645 if (mfp->path_off != 0)
00646 CDB___db_shalloc_free(dbmp->reginfo[0].addr,
00647 R_ADDR(dbmp->reginfo, mfp->path_off));
00648 if (mfp->fileid_off != 0)
00649 CDB___db_shalloc_free(dbmp->reginfo[0].addr,
00650 R_ADDR(dbmp->reginfo, mfp->fileid_off));
00651 if (mfp->pgcookie_off != 0)
00652 CDB___db_shalloc_free(dbmp->reginfo[0].addr,
00653 R_ADDR(dbmp->reginfo, mfp->pgcookie_off));
00654 CDB___db_shalloc_free(dbmp->reginfo[0].addr, mfp);
00655 }
00656
00657
00658
00659
00660
00661
00662
00663 int
00664 CDB___memp_fremove(dbmfp)
00665 DB_MPOOLFILE *dbmfp;
00666 {
00667 DB_ENV *dbenv;
00668 DB_MPOOL *dbmp;
00669 MPOOLFILE *mfp;
00670
00671 dbmp = dbmfp->dbmp;
00672 dbenv = dbmp->dbenv;
00673 mfp = dbmfp->mfp;
00674
00675 PANIC_CHECK(dbenv);
00676
00677 R_LOCK(dbenv, dbmp->reginfo);
00678
00679 MEMP_FREMOVE(mfp);
00680
00681 R_UNLOCK(dbenv, dbmp->reginfo);
00682
00683 return (0);
00684 }
00685
00686
00687
00688
00689
00690
00691
00692 char *
00693 CDB___memp_fn(dbmfp)
00694 DB_MPOOLFILE *dbmfp;
00695 {
00696 return (CDB___memp_fns(dbmfp->dbmp, dbmfp->mfp));
00697 }
00698
00699
00700
00701
00702
00703
00704
00705
00706 char *
00707 CDB___memp_fns(dbmp, mfp)
00708 DB_MPOOL *dbmp;
00709 MPOOLFILE *mfp;
00710 {
00711 if (mfp->path_off == 0)
00712 return ((char *)"temporary");
00713
00714 return ((char *)R_ADDR(dbmp->reginfo, mfp->path_off));
00715 }