db

mp_fopen.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__fopen_8c-source.html,v 1.1 2008年06月08日 10:20:46 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 #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  * MEMP_FREMOVE --
00039  * Discard an MPOOLFILE and any buffers it references: update the flags
00040  * so we never try to write buffers associated with the file, nor can we
00041  * find it when looking for files to join. In addition, clear the ftype
00042  * field, there's no reason to post-process pages, they can be discarded
00043  * by any thread.
00044  */
00045 #define MEMP_FREMOVE(mfp) { \
00046  mfp->ftype = 0; \
00047  F_SET(mfp, MP_DEADFILE); \
00048 }
00049 
00050 /*
00051  * CDB_memp_fopen --
00052  * Open a backing file for the memory pool.
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 /* Validate arguments. */
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  * Transparent I/O compression does not work on mmap'd files.
00085  */
00086 if(LF_ISSET(DB_COMPRESS))
00087 LF_SET(DB_NOMMAP);
00088 
00089 /* Require a non-zero pagesize. */
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  * CDB___memp_fopen --
00103  * Open a backing file for the memory pool; internal version.
00104  *
00105  * PUBLIC: int CDB___memp_fopen __P((DB_MPOOL *, MPOOLFILE *, const char *,
00106  * PUBLIC: u_int32_t, int, size_t, int, DB_MPOOL_FINFO *, DB_MPOOLFILE **));
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  * If mfp is provided, we take the DB_MPOOL_FINFO information from
00135  * the mfp. We don't bother initializing everything, because some
00136  * of them are expensive to acquire. If no mfp is provided and the
00137  * finfop argument is NULL, we default the values.
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 /* Allocate and initialize the per-process structure. */
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 /* Get the real name for this file and open it. */
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  * Don't permit files that aren't a multiple of the pagesize,
00200  * and find the number of the last page in the file, all the
00201  * time being careful not to overflow 32 bits.
00202  *
00203  * !!!
00204  * We can't use off_t's here, or in any code in the mainline
00205  * library for that matter. (We have to use them in the os
00206  * stubs, of course, as there are system calls that take them
00207  * as arguments.) The reason is that some customers build in
00208  * environments where an off_t is 32-bits, but still run where
00209  * offsets are 64-bits, and they pay us a lot of money.
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  * If we're doing a verify, we might have to cope with
00219  * a truncated file; if the file size is not a multiple
00220  * of the page size, round down to a page--we'll
00221  * take care of the partial page outside the memp system.
00222  */
00223 
00224 /* Page sizes have to be a power-of-two, ignore mbytes. */
00225 if (bytes % disk_pagesize != 0) {
00226 if (LF_ISSET(DB_ODDFILESIZE))
00227 /*
00228  * If we're doing a verify, we might
00229  * have to cope with a truncated file;
00230  * round down, we'll worry about the partial
00231  * page outside the memp system.
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 /* Correction: page numbers are zero-based, not 1-based. */
00247 if (last_pgno != 0)
00248 --last_pgno;
00249 else
00250 last_pgno = PGNO_BASE_MD;
00251 
00252 /*
00253  * Get the file id if we weren't given one. Generated file id's
00254  * don't use timestamps, otherwise there'd be no chance of any
00255  * other process joining the party.
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  * If we weren't provided an underlying shared object to join with,
00266  * find/allocate the shared file objects. Also allocate space for
00267  * for the per-process thread lock.
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 /* XXX: KEITH: CLOSE THE FILE ON FAILURE? */
00287 }
00288 
00289 dbmfp->mfp = mfp;
00290 
00291 /*
00292  * If a file:
00293  * + is read-only
00294  * + isn't temporary
00295  * + doesn't require any pgin/pgout support
00296  * + the DB_NOMMAP flag wasn't set (in either the file open or
00297  * the environment in which it was opened)
00298  * + and is less than mp_mmapsize bytes in size
00299  *
00300  * we can mmap it instead of reading/writing buffers. Don't do error
00301  * checking based on the mmap call failure. We want to do normal I/O
00302  * on the file if the reason we failed was because the file was on an
00303  * NFS mounted partition, and we can fail in buffer I/O just as easily
00304  * as here.
00305  *
00306  * XXX
00307  * We'd like to test to see if the file is too big to mmap. Since we
00308  * don't know what size or type off_t's or size_t's are, or the largest
00309  * unsigned integral type is, or what random insanity the local C
00310  * compiler will perpetrate, doing the comparison in a portable way is
00311  * flatly impossible. Hope that mmap fails if the file is too large.
00312  */
00313 #define DB_MAXMMAPSIZE (10 * 1024 * 1024) /* 10 Mb. */
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  * Note that we do not have to free the thread mutex, because we
00351  * never get to here after we have successfully allocated it.
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  * __memp_mf_open --
00365  * Open an MPOOLFILE.
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  * If not creating a temporary file, walk the list of MPOOLFILE's,
00385  * looking for a matching file. Files backed by temporary files
00386  * or previously removed files can't match.
00387  *
00388  * DB_TRUNCATE support.
00389  *
00390  * The fileID is a filesystem unique number (e.g., a UNIX dev/inode
00391  * pair) plus a timestamp. If files are removed and created in less
00392  * than a second, the fileID can be repeated. The problem with
00393  * repetition happens when the file that previously had the fileID
00394  * value still has pages in the pool, since we don't want to use them
00395  * to satisfy requests for the new file.
00396  *
00397  * Because the DB_TRUNCATE flag reuses the dev/inode pair, repeated
00398  * opens with that flag set guarantees matching fileIDs when the
00399  * machine can open a file and then re-open with truncate within a
00400  * second. For this reason, we pass that flag down, and, if we find
00401  * a matching entry, we ensure that it's never found again, and we
00402  * create a new entry for the current request.
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  * It's possible that our needs for pre- and
00426  * post-processing are changing. For example,
00427  * an application created a hash subdatabase
00428  * in a database that was previously all btree.
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 /* Allocate a new MPOOLFILE. */
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 /* Initialize the structure. */
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  * If the user specifies DB_MPOOL_LAST or DB_MPOOL_NEW on a CDB_memp_fget,
00457  * we have to know the last page in the file. Figure it out and save
00458  * it away.
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 /* Copy the file path into shared memory. */
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 /* Copy the file identification string into shared memory. */
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 /* Copy the page cookie into shared memory. */
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 /* Prepend the MPOOLFILE to the list of MPOOLFILE's. */
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  * CDB_memp_fclose --
00517  * Close a backing file for the memory pool.
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  * Remove the DB_MPOOLFILE from the queue. This has to happen before
00541  * we perform any action that can fail, otherwise CDB___memp_close may
00542  * loop infinitely when calling us to discard all of the DB_MPOOLFILEs.
00543  */
00544 for (;;) {
00545 MUTEX_THREAD_LOCK(dbmp->mutexp);
00546 
00547 /*
00548  * We have to reference count DB_MPOOLFILE structures as other
00549  * threads may be using them. The problem only happens if the
00550  * application makes a bad design choice. Here's the path:
00551  *
00552  * Thread A opens a database.
00553  * Thread B uses thread A's DB_MPOOLFILE to write a buffer
00554  * in order to free up memory in the mpool cache.
00555  * Thread A closes the database while thread B is using the
00556  * DB_MPOOLFILE structure.
00557  *
00558  * By opening all databases before creating the threads, and
00559  * closing them after the threads have exited, applications
00560  * get better performance and avoid the problem path entirely.
00561  *
00562  * Regardless, holding the DB_MPOOLFILE to flush a dirty buffer
00563  * is a short-term lock, even in worst case, since we better be
00564  * the only thread of control using the DB_MPOOLFILE structure
00565  * to read pages *into* the cache. Wait until we're the only
00566  * reference holder and remove the DB_MPOOLFILE structure from
00567  * the list, so nobody else can even find it.
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 /* Complain if pinned blocks never returned. */
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 /* Discard any mmap information. */
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 /* Close the file; temporary files may not yet have been created. */
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 /* Discard the thread mutex. */
00598 if (dbmfp->mutexp != NULL)
00599 CDB___db_mutex_free(dbenv, dbmp->reginfo, dbmfp->mutexp);
00600 
00601 /*
00602  * Discard our reference on the the underlying MPOOLFILE, and close
00603  * it if it's no longer useful to anyone.
00604  *
00605  * If we're not discarding it, and it's a temp file, this means
00606  * all the outstanding references belong to unflushed buffers.
00607  * (A temp file can only be referenced by one DB_MPOOLFILE).
00608  * We don't care about preserving any of those buffers, so mark
00609  * the MPOOLFILE as dead so that when we try to flush them,
00610  * even the dirty ones just get discarded.
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 /* Discard the DB_MPOOLFILE structure. */
00621 CDB___os_free(dbmfp, sizeof(DB_MPOOLFILE));
00622 
00623 return (ret);
00624 }
00625 
00626 /*
00627  * CDB___memp_mf_discard --
00628  * Discard an MPOOLFILE.
00629  *
00630  * PUBLIC: void CDB___memp_mf_discard __P((DB_MPOOL *, MPOOLFILE *));
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 /* Delete from the list of MPOOLFILEs. */
00642 SH_TAILQ_REMOVE(&mp->mpfq, mfp, q, __mpoolfile);
00643 
00644 /* Free the space. */
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  * CDB___memp_fremove --
00659  * Remove an underlying file from the system.
00660  *
00661  * PUBLIC: int CDB___memp_fremove __P((DB_MPOOLFILE *));
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  * CDB___memp_fn --
00688  * On errors we print whatever is available as the file name.
00689  *
00690  * PUBLIC: char * CDB___memp_fn __P((DB_MPOOLFILE *));
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  * CDB___memp_fns --
00701  * On errors we print whatever is available as the file name.
00702  *
00703  * PUBLIC: char * CDB___memp_fns __P((DB_MPOOL *, MPOOLFILE *));
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 }

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

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