diff options
Diffstat (limited to 'db2/mp')
-rw-r--r-- | db2/mp/mp_bh.c | 92 | ||||
-rw-r--r-- | db2/mp/mp_fget.c | 114 | ||||
-rw-r--r-- | db2/mp/mp_fopen.c | 224 | ||||
-rw-r--r-- | db2/mp/mp_fput.c | 6 | ||||
-rw-r--r-- | db2/mp/mp_fset.c | 29 | ||||
-rw-r--r-- | db2/mp/mp_open.c | 13 | ||||
-rw-r--r-- | db2/mp/mp_pr.c | 39 | ||||
-rw-r--r-- | db2/mp/mp_region.c | 27 | ||||
-rw-r--r-- | db2/mp/mp_sync.c | 32 |
9 files changed, 319 insertions, 257 deletions
diff --git a/db2/mp/mp_bh.c b/db2/mp/mp_bh.c index a707603eec..578abedcb6 100644 --- a/db2/mp/mp_bh.c +++ b/db2/mp/mp_bh.c @@ -7,7 +7,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)mp_bh.c 10.21 (Sleepycat) 10/25/97"; +static const char sccsid[] = "@(#)mp_bh.c 10.23 (Sleepycat) 11/26/97"; #endif /* not lint */ #ifndef NO_SYSTEM_INCLUDES @@ -40,7 +40,6 @@ __memp_bhwrite(dbmp, mfp, bhp, restartp, wrotep) BH *bhp; int *restartp, *wrotep; { - DBT dbt; DB_MPOOLFILE *dbmfp; DB_MPREG *mpreg; @@ -53,7 +52,7 @@ __memp_bhwrite(dbmp, mfp, bhp, restartp, wrotep) * Walk the process' DB_MPOOLFILE list and find a file descriptor for * the file. We also check that the descriptor is open for writing. * If we find a descriptor on the file that's not open for writing, we - * try and upgrade it to make it writeable. + * try and upgrade it to make it writeable. If that fails, we're done. */ LOCKHANDLE(dbmp, dbmp->mutexp); for (dbmfp = TAILQ_FIRST(&dbmp->dbmfq); @@ -86,18 +85,34 @@ __memp_bhwrite(dbmp, mfp, bhp, restartp, wrotep) } /* - * Try and open the file; ignore any error, assume it's a permissions - * problem. + * Try and open the file, attaching to the underlying shared area. * * XXX - * There's no negative cache here, so we may repeatedly try and open - * files that we have previously tried (and failed) to open. + * Don't try to attach to temporary files. There are two problems in + * trying to do that. First, if we have different privileges than the + * process that "owns" the temporary file, we might create the backing + * disk file such that the owning process couldn't read/write its own + * buffers, e.g., memp_trickle() running as root creating a file owned + * as root, mode 600. Second, if the temporary file has already been + * created, we don't have any way of finding out what its real name is, + * and, even if we did, it was already unlinked (so that it won't be + * left if the process dies horribly). This decision causes a problem, + * however: if the temporary file consumes the entire buffer cache, + * and the owner doesn't flush the buffers to disk, we could end up + * with resource starvation, and the memp_trickle() thread couldn't do + * anything about it. That's a pretty unlikely scenario, though. + * + * XXX + * There's no negative cache, so we may repeatedly try and open files + * that we have previously tried (and failed) to open. + * + * Ignore any error, assume it's a permissions problem. */ - dbt.size = mfp->pgcookie_len; - dbt.data = R_ADDR(dbmp, mfp->pgcookie_off); - if (__memp_fopen(dbmp, R_ADDR(dbmp, mfp->path_off), - mfp->ftype, 0, 0, mfp->stat.st_pagesize, - mfp->lsn_off, &dbt, R_ADDR(dbmp, mfp->fileid_off), 0, &dbmfp) != 0) + if (F_ISSET(mfp, MP_TEMP)) + return (0); + + if (__memp_fopen(dbmp, mfp, R_ADDR(dbmp, mfp->path_off), mfp->ftype, + 0, 0, mfp->stat.st_pagesize, 0, NULL, NULL, 0, &dbmfp) != 0) return (0); found: return (__memp_pgwrite(dbmfp, bhp, restartp, wrotep)); @@ -144,7 +159,7 @@ __memp_pgread(dbmfp, bhp, can_create) UNLOCKHANDLE(dbmp, dbmfp->mutexp); __db_err(dbmp->dbenv, "%s: page %lu doesn't exist, create flag not set", - dbmfp->path, (u_long)bhp->pgno); + __memp_fn(dbmfp), (u_long)bhp->pgno); goto err; } UNLOCKHANDLE(dbmp, dbmfp->mutexp); @@ -270,12 +285,14 @@ __memp_pgwrite(dbmfp, bhp, restartp, wrotep) /* Temporary files may not yet have been created. */ LOCKHANDLE(dbmp, dbmfp->mutexp); - if (dbmfp->fd == -1 && ((ret = __db_appname(dbenv, DB_APP_TMP, - NULL, NULL, &dbmfp->fd, NULL)) != 0 || dbmfp->fd == -1)) { - UNLOCKHANDLE(dbmp, dbmfp->mutexp); - __db_err(dbenv, "unable to create temporary backing file"); - goto err; - } + if (dbmfp->fd == -1) + if ((ret = __db_appname(dbenv, DB_APP_TMP, + NULL, NULL, &dbmfp->fd, NULL)) != 0 || dbmfp->fd == -1) { + UNLOCKHANDLE(dbmp, dbmfp->mutexp); + __db_err(dbenv, + "unable to create temporary backing file"); + goto err; + } /* Write the page out. */ if ((ret = __db_seek(dbmfp->fd, pagesize, bhp->pgno, 0, SEEK_SET)) != 0) @@ -350,8 +367,8 @@ __memp_pgwrite(dbmfp, bhp, restartp, wrotep) return (0); -syserr: __db_err(dbenv, - "%s: %s failed for page %lu", dbmfp->path, fail, (u_long)bhp->pgno); +syserr: __db_err(dbenv, "%s: %s failed for page %lu", + __memp_fn(dbmfp), fail, (u_long)bhp->pgno); err: UNLOCKBUFFER(dbmp, bhp); LOCKREGION(dbmp); @@ -416,7 +433,7 @@ __memp_pg(dbmfp, bhp, is_pgin) err: UNLOCKHANDLE(dbmp, dbmp->mutexp); __db_err(dbmp->dbenv, "%s: %s failed for page %lu", - dbmfp->path, is_pgin ? "pgin" : "pgout", (u_long)bhp->pgno); + __memp_fn(dbmfp), is_pgin ? "pgin" : "pgout", (u_long)bhp->pgno); return (ret); } @@ -462,7 +479,8 @@ __memp_upgrade(dbmp, dbmfp, mfp) DB_MPOOLFILE *dbmfp; MPOOLFILE *mfp; { - int fd; + int fd, ret; + char *rpath; /* * !!! @@ -477,16 +495,24 @@ __memp_upgrade(dbmp, dbmfp, mfp) if (F_ISSET(dbmfp, MP_UPGRADE_FAIL)) return (1); - /* Try the open. */ - if (__db_open(R_ADDR(dbmp, mfp->path_off), 0, 0, 0, &fd) != 0) { + /* + * Calculate the real name for this file and try to open it read/write. + * We know we have a valid pathname for the file because it's the only + * way we could have gotten a file descriptor of any kind. + */ + if ((ret = __db_appname(dbmp->dbenv, DB_APP_DATA, + NULL, R_ADDR(dbmp, mfp->path_off), NULL, &rpath)) != 0) + return (ret); + if (__db_open(rpath, 0, 0, 0, &fd) != 0) { F_SET(dbmfp, MP_UPGRADE_FAIL); - return (1); + ret = 1; + } else { + /* Swap the descriptors and set the upgrade flag. */ + (void)__db_close(dbmfp->fd); + dbmfp->fd = fd; + F_SET(dbmfp, MP_UPGRADE); + ret = 0; } - - /* Swap the descriptors and set the upgrade flag. */ - (void)__db_close(dbmfp->fd); - dbmfp->fd = fd; - F_SET(dbmfp, MP_UPGRADE); - - return (0); + FREES(rpath); + return (ret); } diff --git a/db2/mp/mp_fget.c b/db2/mp/mp_fget.c index 3f99e60505..1010751c92 100644 --- a/db2/mp/mp_fget.c +++ b/db2/mp/mp_fget.c @@ -7,7 +7,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)mp_fget.c 10.30 (Sleepycat) 10/25/97"; +static const char sccsid[] = "@(#)mp_fget.c 10.32 (Sleepycat) 11/26/97"; #endif /* not lint */ #ifndef NO_SYSTEM_INCLUDES @@ -38,13 +38,11 @@ memp_fget(dbmfp, pgnoaddr, flags, addrp) int flags; void *addrp; { - BH *bhp, *tbhp; + BH *bhp; DB_MPOOL *dbmp; MPOOL *mp; MPOOLFILE *mfp; - db_pgno_t lastpgno; size_t bucket, mf_offset; - off_t size; u_long cnt; int b_incr, b_inserted, readonly_alloc, ret; void *addr; @@ -97,7 +95,7 @@ memp_fget(dbmfp, pgnoaddr, flags, addrp) mf_offset = R_OFFSET(dbmp, mfp); addr = NULL; bhp = NULL; - b_incr = b_inserted = readonly_alloc = ret = 0; + b_incr = b_inserted = ret = 0; LOCKREGION(dbmp); @@ -114,11 +112,10 @@ memp_fget(dbmfp, pgnoaddr, flags, addrp) * It would be possible to do so by reference counting the open * pages from the mmap, but it's unclear to me that it's worth it. */ - if (dbmfp->addr != NULL && dbmfp->mfp->can_mmap) { - lastpgno = dbmfp->len == 0 ? - 0 : (dbmfp->len - 1) / mfp->stat.st_pagesize; + if (dbmfp->addr != NULL && F_ISSET(dbmfp->mfp, MP_CAN_MMAP)) { + readonly_alloc = 0; if (LF_ISSET(DB_MPOOL_LAST)) - *pgnoaddr = lastpgno; + *pgnoaddr = mfp->last_pgno; else { /* * !!! @@ -128,10 +125,10 @@ memp_fget(dbmfp, pgnoaddr, flags, addrp) */ if (LF_ISSET(DB_MPOOL_CREATE | DB_MPOOL_NEW)) readonly_alloc = 1; - else if (*pgnoaddr > lastpgno) { + else if (*pgnoaddr > mfp->last_pgno) { __db_err(dbmp->dbenv, "%s: page %lu doesn't exist", - dbmfp->path, (u_long)*pgnoaddr); + __memp_fn(dbmfp), (u_long)*pgnoaddr); ret = EINVAL; goto err; } @@ -146,79 +143,38 @@ memp_fget(dbmfp, pgnoaddr, flags, addrp) } } - /* - * If requesting the last page or a new page, find the last page. The - * tricky thing is that the user may have created a page already that's - * after any page that exists in the file. - */ - if (LF_ISSET(DB_MPOOL_LAST | DB_MPOOL_NEW)) { - /* - * Temporary files may not yet have been created. - * - * Don't lock -- there are no atomicity issues for stat(2). - */ - if (dbmfp->fd == -1) - size = 0; - else if ((ret = - __db_ioinfo(dbmfp->path, dbmfp->fd, &size, NULL)) != 0) { - __db_err(dbmp->dbenv, - "%s: %s", dbmfp->path, strerror(ret)); - goto err; - } - - *pgnoaddr = size == 0 ? 0 : (size - 1) / mfp->stat.st_pagesize; + /* Check if requesting the last page or a new page. */ + if (LF_ISSET(DB_MPOOL_LAST)) + *pgnoaddr = mfp->last_pgno; - /* - * Walk the list of BH's, looking for later pages. Save the - * pointer if a later page is found so that we don't have to - * search the list twice. - * - * If requesting a new page, return the page one after the last - * page -- which we'll have to create. - */ - for (tbhp = SH_TAILQ_FIRST(&mp->bhq, __bh); - tbhp != NULL; tbhp = SH_TAILQ_NEXT(tbhp, q, __bh)) - if (tbhp->pgno >= *pgnoaddr && - tbhp->mf_offset == mf_offset) { - bhp = tbhp; - *pgnoaddr = bhp->pgno; - } - if (LF_ISSET(DB_MPOOL_NEW)) - ++*pgnoaddr; - } - - /* If we already found the right buffer, return it. */ - if (LF_ISSET(DB_MPOOL_LAST) && bhp != NULL) { - addr = bhp->buf; - goto found; + if (LF_ISSET(DB_MPOOL_NEW)) { + *pgnoaddr = mfp->last_pgno + 1; + goto alloc; } - /* If we haven't checked the BH hash bucket queue, do the search. */ - if (!LF_ISSET(DB_MPOOL_LAST | DB_MPOOL_NEW)) { - bucket = BUCKET(mp, mf_offset, *pgnoaddr); - for (cnt = 0, - bhp = SH_TAILQ_FIRST(&dbmp->htab[bucket], __bh); - bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, hq, __bh)) { - ++cnt; - if (bhp->pgno == *pgnoaddr && - bhp->mf_offset == mf_offset) { - addr = bhp->buf; - ++mp->stat.st_hash_searches; - if (cnt > mp->stat.st_hash_longest) - mp->stat.st_hash_longest = cnt; - mp->stat.st_hash_examined += cnt; - goto found; - } - } - if (cnt != 0) { + /* Check the BH hash bucket queue. */ + bucket = BUCKET(mp, mf_offset, *pgnoaddr); + for (cnt = 0, + bhp = SH_TAILQ_FIRST(&dbmp->htab[bucket], __bh); + bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, hq, __bh)) { + ++cnt; + if (bhp->pgno == *pgnoaddr && bhp->mf_offset == mf_offset) { + addr = bhp->buf; ++mp->stat.st_hash_searches; if (cnt > mp->stat.st_hash_longest) mp->stat.st_hash_longest = cnt; mp->stat.st_hash_examined += cnt; + goto found; } } + if (cnt != 0) { + ++mp->stat.st_hash_searches; + if (cnt > mp->stat.st_hash_longest) + mp->stat.st_hash_longest = cnt; + mp->stat.st_hash_examined += cnt; + } - /* +alloc: /* * Allocate a new buffer header and data space, and mark the contents * as useless. */ @@ -300,7 +256,7 @@ found: /* Increment the reference count. */ if (bhp->ref == UINT16_T_MAX) { __db_err(dbmp->dbenv, "%s: too many references to page %lu", - dbmfp->path, bhp->pgno); + __memp_fn(dbmfp), bhp->pgno); ret = EINVAL; goto err; } @@ -346,6 +302,14 @@ found: /* Increment the reference count. */ ++mfp->stat.st_cache_hit; } + /* + * If we're returning a page after our current notion of the last-page, + * update our information. Note, there's no way to un-instantiate this + * page, it's going to exist whether it's returned to us dirty or not. + */ + if (bhp->pgno > mfp->last_pgno) + mfp->last_pgno = bhp->pgno; + mapret: LOCKHANDLE(dbmp, dbmfp->mutexp); ++dbmfp->pinref; UNLOCKHANDLE(dbmp, dbmfp->mutexp); diff --git a/db2/mp/mp_fopen.c b/db2/mp/mp_fopen.c index de59c9ea9b..bdc4713863 100644 --- a/db2/mp/mp_fopen.c +++ b/db2/mp/mp_fopen.c @@ -7,7 +7,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)mp_fopen.c 10.30 (Sleepycat) 10/25/97"; +static const char sccsid[] = "@(#)mp_fopen.c 10.32 (Sleepycat) 11/26/97"; #endif /* not lint */ #ifndef NO_SYSTEM_INCLUDES @@ -28,8 +28,8 @@ static const char sccsid[] = "@(#)mp_fopen.c 10.30 (Sleepycat) 10/25/97"; #include "common_ext.h" static int __memp_mf_close __P((DB_MPOOL *, DB_MPOOLFILE *)); -static int __memp_mf_open __P((DB_MPOOL *, - DB_MPOOLFILE *, int, size_t, int, DBT *, u_int8_t *, int, MPOOLFILE **)); +static int __memp_mf_open __P((DB_MPOOL *, DB_MPOOLFILE *, + const char *, int, size_t, off_t, int, DBT *, u_int8_t *, MPOOLFILE **)); /* * memp_fopen -- @@ -53,7 +53,13 @@ memp_fopen(dbmp, path, ftype, "memp_fopen", flags, DB_CREATE | DB_NOMMAP | DB_RDONLY)) != 0) return (ret); - return (__memp_fopen(dbmp, path, ftype, + /* Require a non-zero pagesize. */ + if (pagesize == 0) { + __db_err(dbmp->dbenv, "memp_fopen: pagesize not specified"); + return (EINVAL); + } + + return (__memp_fopen(dbmp, NULL, path, ftype, flags, mode, pagesize, lsn_offset, pgcookie, fileid, 1, retp)); } @@ -61,13 +67,14 @@ memp_fopen(dbmp, path, ftype, * __memp_fopen -- * Open a backing file for the memory pool; internal version. * - * PUBLIC: int __memp_fopen __P((DB_MPOOL *, const char *, int, int, - * PUBLIC: int, size_t, int, DBT *, u_int8_t *, int, DB_MPOOLFILE **)); + * PUBLIC: int __memp_fopen __P((DB_MPOOL *, MPOOLFILE *, const char *, int, + * PUBLIC: int, int, size_t, int, DBT *, u_int8_t *, int, DB_MPOOLFILE **)); */ int -__memp_fopen(dbmp, path, +__memp_fopen(dbmp, mfp, path, ftype, flags, mode, pagesize, lsn_offset, pgcookie, fileid, needlock, retp) DB_MPOOL *dbmp; + MPOOLFILE *mfp; const char *path; int ftype, flags, mode, lsn_offset, needlock; size_t pagesize; @@ -77,24 +84,27 @@ __memp_fopen(dbmp, path, { DB_ENV *dbenv; DB_MPOOLFILE *dbmfp; - MPOOLFILE *mfp; off_t size; int ret; + u_int8_t idbuf[DB_FILE_ID_LEN]; + char *rpath; + /* + * XXX + * If mfp is provided, the following arguments do NOT need to be + * specified: + * lsn_offset + * pgcookie + * fileid + */ dbenv = dbmp->dbenv; ret = 0; - - /* Require a non-zero pagesize. */ - if (pagesize == 0) { - __db_err(dbenv, "memp_fopen: pagesize not specified"); - return (EINVAL); - } + rpath = NULL; /* Allocate and initialize the per-process structure. */ if ((dbmfp = (DB_MPOOLFILE *)__db_calloc(1, sizeof(DB_MPOOLFILE))) == NULL) { - __db_err(dbenv, "%s: %s", - path == NULL ? TEMPORARY : path, strerror(ENOMEM)); + __db_err(dbenv, "memp_fopen: %s", strerror(ENOMEM)); return (ENOMEM); } dbmfp->dbmp = dbmp; @@ -109,54 +119,66 @@ __memp_fopen(dbmp, path, ret = EINVAL; goto err; } - dbmfp->path = (char *)TEMPORARY; - F_SET(dbmfp, MP_PATH_TEMP); + size = 0; } else { - /* Calculate the real name for this file. */ + /* Get the real name for this file and open it. */ if ((ret = __db_appname(dbenv, - DB_APP_DATA, NULL, path, NULL, &dbmfp->path)) != 0) + DB_APP_DATA, NULL, path, NULL, &rpath)) != 0) goto err; - F_SET(dbmfp, MP_PATH_ALLOC); - - - /* Open the file. */ - if ((ret = __db_open(dbmfp->path, + if ((ret = __db_open(rpath, LF_ISSET(DB_CREATE | DB_RDONLY), DB_CREATE | DB_RDONLY, mode, &dbmfp->fd)) != 0) { - __db_err(dbenv, "%s: %s", dbmfp->path, strerror(ret)); + __db_err(dbenv, "%s: %s", rpath, strerror(ret)); goto err; } /* Don't permit files that aren't a multiple of the pagesize. */ - if ((ret = - __db_ioinfo(dbmfp->path, dbmfp->fd, &size, NULL)) != 0) { - __db_err(dbenv, "%s: %s", dbmfp->path, strerror(ret)); + if ((ret = __db_ioinfo(rpath, dbmfp->fd, &size, NULL)) != 0) { + __db_err(dbenv, "%s: %s", rpath, strerror(ret)); goto err; } if (size % pagesize) { __db_err(dbenv, "%s: file size not a multiple of the pagesize", - dbmfp->path); + rpath); ret = EINVAL; goto err; } + + /* + * Get the file id if we weren't given one. Generated file id's + * don't use timestamps, otherwise there'd be no chance of any + * other process joining the party. + */ + if (mfp == NULL && fileid == NULL) { + if ((ret = __db_fileid(dbenv, rpath, 0, idbuf)) != 0) + goto err; + fileid = idbuf; + } } /* - * Find/allocate the shared file objects. This includes allocating - * space for the per-process thread lock. + * If we weren't provided an underlying shared object to join with, + * find/allocate the shared file objects. Also allocate space for + * for the per-process thread lock. */ if (needlock) LOCKREGION(dbmp); - ret = __memp_mf_open(dbmp, dbmfp, ftype, pagesize, - lsn_offset, pgcookie, fileid, F_ISSET(dbmfp, MP_PATH_TEMP), &mfp); + + if (mfp == NULL) + ret = __memp_mf_open(dbmp, dbmfp, path, + ftype, pagesize, size, lsn_offset, pgcookie, fileid, &mfp); + else { + ++mfp->ref; + ret = 0; + } if (ret == 0 && F_ISSET(dbmp, MP_LOCKHANDLE) && (ret = __memp_ralloc(dbmp, sizeof(db_mutex_t), NULL, &dbmfp->mutexp)) == 0) LOCKINIT(dbmp, dbmfp->mutexp); + if (needlock) UNLOCKREGION(dbmp); - if (ret != 0) goto err; @@ -184,25 +206,25 @@ __memp_fopen(dbmp, path, * flatly impossible. Hope that mmap fails if the file is too large. */ #define DB_MAXMMAPSIZE (10 * 1024 * 1024) /* 10 Mb. */ - if (mfp->can_mmap) { + if (F_ISSET(mfp, MP_CAN_MMAP)) { if (!F_ISSET(dbmfp, MP_READONLY)) - mfp->can_mmap = 0; + F_CLR(mfp, MP_CAN_MMAP); if (path == NULL) - mfp->can_mmap = 0; + F_CLR(mfp, MP_CAN_MMAP); if (ftype != 0) - mfp->can_mmap = 0; + F_CLR(mfp, MP_CAN_MMAP); if (LF_ISSET(DB_NOMMAP)) - mfp->can_mmap = 0; + F_CLR(mfp, MP_CAN_MMAP); if (size > (dbenv == NULL || dbenv->mp_mmapsize == 0 ? DB_MAXMMAPSIZE : (off_t)dbenv->mp_mmapsize)) - mfp->can_mmap = 0; + F_CLR(mfp, MP_CAN_MMAP); } dbmfp->addr = NULL; - if (mfp->can_mmap) { + if (F_ISSET(mfp, MP_CAN_MMAP)) { dbmfp->len = size; if (__db_map(dbmfp->fd, dbmfp->len, 1, 1, &dbmfp->addr) != 0) { - mfp->can_mmap = 0; dbmfp->addr = NULL; + F_CLR(mfp, MP_CAN_MMAP); } } @@ -217,8 +239,8 @@ err: /* * Note that we do not have to free the thread mutex, because we * never get to here after we have successfully allocated it. */ - if (F_ISSET(dbmfp, MP_PATH_ALLOC)) - FREES(dbmfp->path); + if (rpath != NULL) + FREES(rpath); if (dbmfp->fd != -1) (void)__db_close(dbmfp->fd); if (dbmfp != NULL) @@ -231,78 +253,80 @@ err: /* * Open an MPOOLFILE. */ static int -__memp_mf_open(dbmp, dbmfp, - ftype, pagesize, lsn_offset, pgcookie, fileid, istemp, retp) +__memp_mf_open(dbmp, dbmfp, path, + ftype, pagesize, size, lsn_offset, pgcookie, fileid, retp) DB_MPOOL *dbmp; DB_MPOOLFILE *dbmfp; - int ftype, lsn_offset, istemp; + const char *path; + int ftype, lsn_offset; size_t pagesize; + off_t size; DBT *pgcookie; u_int8_t *fileid; MPOOLFILE **retp; { MPOOLFILE *mfp; int ret; - u_int8_t idbuf[DB_FILE_ID_LEN]; void *p; - /* Temporary files can't match previous files. */ - if (istemp) - goto alloc; +#define ISTEMPORARY (path == NULL) /* - * Get the file id if we weren't give one. Generated file id's don't - * use timestamps, otherwise there'd be no chance of anyone joining - * the party. + * Walk the list of MPOOLFILE's, looking for a matching file. + * Temporary files can't match previous files. */ - if (fileid == NULL) { - if ((ret = - __db_fileid(dbmp->dbenv, dbmfp->path, 0, idbuf)) != 0) - return (ret); - fileid = idbuf; - } - - /* Walk the list of MPOOLFILE's, looking for a matching file. */ - for (mfp = SH_TAILQ_FIRST(&dbmp->mp->mpfq, __mpoolfile); - mfp != NULL; mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile)) - if (!memcmp(fileid, - R_ADDR(dbmp, mfp->fileid_off), DB_FILE_ID_LEN)) { - if (ftype != mfp->ftype || - pagesize != mfp->stat.st_pagesize) { - __db_err(dbmp->dbenv, - "%s: ftype or pagesize changed", - dbmfp->path); - ret = EINVAL; - mfp = NULL; - goto ret1; + if (!ISTEMPORARY) + for (mfp = SH_TAILQ_FIRST(&dbmp->mp->mpfq, __mpoolfile); + mfp != NULL; mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile)) { + if (F_ISSET(mfp, MP_TEMP)) + continue; + if (!memcmp(fileid, + R_ADDR(dbmp, mfp->fileid_off), DB_FILE_ID_LEN)) { + if (ftype != mfp->ftype || + pagesize != mfp->stat.st_pagesize) { + __db_err(dbmp->dbenv, + "%s: ftype or pagesize changed", + path); + return (EINVAL); + } + + /* Found it: increment the reference count. */ + ++mfp->ref; + *retp = mfp; + return (0); } - /* Found it: increment the reference count. */ - ++mfp->ref; - goto ret1; } /* Allocate a new MPOOLFILE. */ -alloc: if ((ret = __memp_ralloc(dbmp, sizeof(MPOOLFILE), NULL, &mfp)) != 0) - goto ret1; + if ((ret = __memp_ralloc(dbmp, sizeof(MPOOLFILE), NULL, &mfp)) != 0) + return (ret); + *retp = mfp; /* Initialize the structure. */ memset(mfp, 0, sizeof(MPOOLFILE)); mfp->ref = 1; mfp->ftype = ftype; - mfp->can_mmap = 1; mfp->lsn_off = lsn_offset; - mfp->stat.st_pagesize = pagesize; - /* Copy the file path into shared memory. */ - if ((ret = __memp_ralloc(dbmp, - strlen(dbmfp->path) + 1, &mfp->path_off, &p)) != 0) - goto err; - memcpy(p, dbmfp->path, strlen(dbmfp->path) + 1); + /* + * If the user specifies DB_MPOOL_LAST or DB_MPOOL_NEW on a memp_fget, + * we have to know the last page in the file. Figure it out and save + * it away. + */ + mfp->stat.st_pagesize = pagesize; + mfp->last_pgno = size == 0 ? 0 : (size - 1) / mfp->stat.st_pagesize; - /* Copy the file identification string into shared memory. */ - if (istemp) - mfp->fileid_off = 0; + F_SET(mfp, MP_CAN_MMAP); + if (ISTEMPORARY) + F_SET(mfp, MP_TEMP); else { + /* Copy the file path into shared memory. */ + if ((ret = __memp_ralloc(dbmp, + strlen(path) + 1, &mfp->path_off, &p)) != 0) + goto err; + memcpy(p, path, strlen(path) + 1); + + /* Copy the file identification string into shared memory. */ if ((ret = __memp_ralloc(dbmp, DB_FILE_ID_LEN, &mfp->fileid_off, &p)) != 0) goto err; @@ -328,15 +352,13 @@ alloc: if ((ret = __memp_ralloc(dbmp, sizeof(MPOOLFILE), NULL, &mfp)) != 0) err: if (mfp->path_off != 0) __db_shalloc_free(dbmp->addr, R_ADDR(dbmp, mfp->path_off)); - if (!istemp) + if (mfp->fileid_off != 0) __db_shalloc_free(dbmp->addr, R_ADDR(dbmp, mfp->fileid_off)); if (mfp != NULL) __db_shalloc_free(dbmp->addr, mfp); mfp = NULL; } - -ret1: *retp = mfp; return (0); } @@ -357,7 +379,7 @@ memp_fclose(dbmfp) /* Complain if pinned blocks never returned. */ if (dbmfp->pinref != 0) __db_err(dbmp->dbenv, "%s: close: %lu blocks left pinned", - dbmfp->path, (u_long)dbmfp->pinref); + __memp_fn(dbmfp), (u_long)dbmfp->pinref); /* Remove the DB_MPOOLFILE structure from the list. */ LOCKHANDLE(dbmp, dbmp->mutexp); @@ -370,18 +392,18 @@ memp_fclose(dbmfp) /* Discard any mmap information. */ if (dbmfp->addr != NULL && (ret = __db_unmap(dbmfp->addr, dbmfp->len)) != 0) - __db_err(dbmp->dbenv, "%s: %s", dbmfp->path, strerror(ret)); + __db_err(dbmp->dbenv, + "%s: %s", __memp_fn(dbmfp), strerror(ret)); /* Close the file; temporary files may not yet have been created. */ if (dbmfp->fd != -1 && (t_ret = __db_close(dbmfp->fd)) != 0) { - __db_err(dbmp->dbenv, "%s: %s", dbmfp->path, strerror(t_ret)); + __db_err(dbmp->dbenv, + "%s: %s", __memp_fn(dbmfp), strerror(t_ret)); if (ret != 0) t_ret = ret; } /* Free memory. */ - if (F_ISSET(dbmfp, MP_PATH_ALLOC)) - FREES(dbmfp->path); if (dbmfp->mutexp != NULL) { LOCKREGION(dbmp); __db_shalloc_free(dbmp->addr, dbmfp->mutexp); @@ -434,7 +456,8 @@ __memp_mf_close(dbmp, dbmfp) if (F_ISSET(bhp, BH_DIRTY)) __db_err(dbmp->dbenv, "%s: close: pgno %lu left dirty; ref %lu", - dbmfp->path, (u_long)bhp->pgno, (u_long)bhp->ref); + __memp_fn(dbmfp), + (u_long)bhp->pgno, (u_long)bhp->ref); #endif if (bhp->mf_offset == mf_offset) { @@ -452,7 +475,8 @@ __memp_mf_close(dbmp, dbmfp) /* Free the space. */ __db_shalloc_free(dbmp->addr, mfp); - __db_shalloc_free(dbmp->addr, R_ADDR(dbmp, mfp->path_off)); + if (mfp->path_off != 0) + __db_shalloc_free(dbmp->addr, R_ADDR(dbmp, mfp->path_off)); if (mfp->fileid_off != 0) __db_shalloc_free(dbmp->addr, R_ADDR(dbmp, mfp->fileid_off)); if (mfp->pgcookie_off != 0) diff --git a/db2/mp/mp_fput.c b/db2/mp/mp_fput.c index 892f179d3a..38e86b8ac5 100644 --- a/db2/mp/mp_fput.c +++ b/db2/mp/mp_fput.c @@ -7,7 +7,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)mp_fput.c 10.14 (Sleepycat) 10/5/97"; +static const char sccsid[] = "@(#)mp_fput.c 10.16 (Sleepycat) 11/26/97"; #endif /* not lint */ #ifndef NO_SYSTEM_INCLUDES @@ -54,7 +54,7 @@ memp_fput(dbmfp, pgaddr, flags) if (LF_ISSET(DB_MPOOL_DIRTY) && F_ISSET(dbmfp, MP_READONLY)) { __db_err(dbmp->dbenv, "%s: dirty flag set for readonly file page", - dbmfp->path); + __memp_fn(dbmfp)); return (EACCES); } } @@ -64,7 +64,7 @@ memp_fput(dbmfp, pgaddr, flags) if (dbmfp->pinref == 0) __db_err(dbmp->dbenv, "%s: put: more blocks returned than retrieved", - dbmfp->path); + __memp_fn(dbmfp)); else --dbmfp->pinref; UNLOCKHANDLE(dbmp, dbmfp->mutexp); diff --git a/db2/mp/mp_fset.c b/db2/mp/mp_fset.c index a7d2706008..2eff7dd74c 100644 --- a/db2/mp/mp_fset.c +++ b/db2/mp/mp_fset.c @@ -7,7 +7,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)mp_fset.c 10.10 (Sleepycat) 10/5/97"; +static const char sccsid[] = "@(#)mp_fset.c 10.12 (Sleepycat) 11/26/97"; #endif /* not lint */ #ifndef NO_SYSTEM_INCLUDES @@ -43,20 +43,21 @@ memp_fset(dbmfp, pgaddr, flags) mp = dbmp->mp; /* Validate arguments. */ - if (flags != 0) { - if ((ret = __db_fchk(dbmp->dbenv, "memp_fset", flags, - DB_MPOOL_DIRTY | DB_MPOOL_CLEAN | DB_MPOOL_DISCARD)) != 0) - return (ret); - if ((ret = __db_fcchk(dbmp->dbenv, "memp_fset", - flags, DB_MPOOL_CLEAN, DB_MPOOL_DIRTY)) != 0) - return (ret); + if (flags == 0) + return (__db_ferr(dbmp->dbenv, "memp_fset", 1)); - if (LF_ISSET(DB_MPOOL_DIRTY) && F_ISSET(dbmfp, MP_READONLY)) { - __db_err(dbmp->dbenv, - "%s: dirty flag set for readonly file page", - dbmfp->path); - return (EACCES); - } + if ((ret = __db_fchk(dbmp->dbenv, "memp_fset", flags, + DB_MPOOL_DIRTY | DB_MPOOL_CLEAN | DB_MPOOL_DISCARD)) != 0) + return (ret); + if ((ret = __db_fcchk(dbmp->dbenv, "memp_fset", + flags, DB_MPOOL_CLEAN, DB_MPOOL_DIRTY)) != 0) + return (ret); + + if (LF_ISSET(DB_MPOOL_DIRTY) && F_ISSET(dbmfp, MP_READONLY)) { + __db_err(dbmp->dbenv, + "%s: dirty flag set for readonly file page", + __memp_fn(dbmfp)); + return (EACCES); } /* Convert the page address to a buffer header. */ diff --git a/db2/mp/mp_open.c b/db2/mp/mp_open.c index 4c19739ebd..ca81f8d6d6 100644 --- a/db2/mp/mp_open.c +++ b/db2/mp/mp_open.c @@ -7,7 +7,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)mp_open.c 10.15 (Sleepycat) 10/25/97"; +static const char sccsid[] = "@(#)mp_open.c 10.16 (Sleepycat) 11/28/97"; #endif /* not lint */ #ifndef NO_SYSTEM_INCLUDES @@ -66,17 +66,6 @@ memp_open(path, flags, mode, dbenv, retp) F_SET(dbmp, MP_ISPRIVATE); /* - * XXX - * HP-UX won't permit mutexes to live in anything but shared memory. - * So, we have to instantiate the shared mpool region file on that - * architecture, regardless. If this turns out to be a performance - * problem, we could probably use anonymous memory instead. - */ -#if defined(__hppa) - F_CLR(dbmp, MP_ISPRIVATE); -#endif - - /* * Map in the region. We do locking regardless, as portions of it are * implemented in common code (if we put the region in a file, that is). */ diff --git a/db2/mp/mp_pr.c b/db2/mp/mp_pr.c index 01f0920df4..6ff1131b6e 100644 --- a/db2/mp/mp_pr.c +++ b/db2/mp/mp_pr.c @@ -7,7 +7,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)mp_pr.c 10.18 (Sleepycat) 11/1/97"; +static const char sccsid[] = "@(#)mp_pr.c 10.20 (Sleepycat) 11/26/97"; #endif /* not lint */ #ifndef NO_SYSTEM_INCLUDES @@ -100,7 +100,7 @@ memp_stat(dbmp, gspp, fspp, db_malloc) mfp = SH_TAILQ_FIRST(&dbmp->mp->mpfq, __mpoolfile); mfp != NULL; ++tfsp, mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile)) { - name = R_ADDR(dbmp, mfp->path_off); + name = __memp_fns(dbmp, mfp); nlen = strlen(name); len = sizeof(DB_MPOOL_FSTAT) + nlen + 1; if ((*tfsp = db_malloc == NULL ? @@ -120,6 +120,37 @@ memp_stat(dbmp, gspp, fspp, db_malloc) } /* + * __memp_fn -- + * On errors we print whatever is available as the file name. + * + * PUBLIC: char * __memp_fn __P((DB_MPOOLFILE *)); + */ +char * +__memp_fn(dbmfp) + DB_MPOOLFILE *dbmfp; +{ + return (__memp_fns(dbmfp->dbmp, dbmfp->mfp)); +} + +/* + * __memp_fns -- + * On errors we print whatever is available as the file name. + * + * PUBLIC: char * __memp_fns __P((DB_MPOOL *, MPOOLFILE *)); + * + */ +char * +__memp_fns(dbmp, mfp) + DB_MPOOL *dbmp; + MPOOLFILE *mfp; +{ + if (mfp->path_off == 0) + return ((char *)"temporary"); + + return ((char *)R_ADDR(dbmp, mfp->path_off)); +} + +/* * __memp_debug -- * Display MPOOL structures. * @@ -152,7 +183,7 @@ __memp_debug(dbmp, fp, data) (void)fprintf(fp, "%lu process-local files\n", cnt); for (dbmfp = TAILQ_FIRST(&dbmp->dbmfq); dbmfp != NULL; dbmfp = TAILQ_NEXT(dbmfp, q)) { - (void)fprintf(fp, "%s\n", dbmfp->path); + (void)fprintf(fp, "%s\n", __memp_fn(dbmfp)); __memp_pdbmf(fp, dbmfp, data); } @@ -285,7 +316,7 @@ __memp_pmf(fp, mfp, data) return; (void)fprintf(fp, " %d references; %s; pagesize: %lu\n", mfp->ref, - mfp->can_mmap ? "mmap" : "read/write", + F_ISSET(mfp, MP_CAN_MMAP) ? "mmap" : "read/write", (u_long)mfp->stat.st_pagesize); } diff --git a/db2/mp/mp_region.c b/db2/mp/mp_region.c index 6b2f93125c..c20e669749 100644 --- a/db2/mp/mp_region.c +++ b/db2/mp/mp_region.c @@ -7,7 +7,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)mp_region.c 10.16 (Sleepycat) 10/25/97"; +static const char sccsid[] = "@(#)mp_region.c 10.18 (Sleepycat) 11/29/97"; #endif /* not lint */ #ifndef NO_SYSTEM_INCLUDES @@ -224,17 +224,28 @@ retry: if (LF_ISSET(DB_CREATE)) { * the file descriptor for locking. However, it should not * be possible for DB_THREAD to be set if HAVE_SPINLOCKS aren't * defined. + * + * XXX + * HP-UX won't permit mutexes to live in anything but shared + * memory. So, instantiate the shared mpool region file on + * that architecture, regardless. If this turns out to be a + * performance problem, we could use anonymous memory instead. */ - if (F_ISSET(dbmp, MP_ISPRIVATE)) { +#if !defined(__hppa) + if (F_ISSET(dbmp, MP_ISPRIVATE)) if ((dbmp->maddr = __db_malloc(rlen)) == NULL) ret = ENOMEM; - else + else { + F_SET(dbmp, MP_MALLOC); ret = __db_rinit(dbmp->dbenv, dbmp->maddr, 0, rlen, 0); - } else + } + else +#endif ret = __db_rcreate(dbmp->dbenv, DB_APP_NONE, path, - DB_DEFAULT_MPOOL_FILE, mode, rlen, &fd, - &dbmp->maddr); + DB_DEFAULT_MPOOL_FILE, mode, rlen, + F_ISSET(dbmp, MP_ISPRIVATE) ? DB_TEMPORARY : 0, + &fd, &dbmp->maddr); if (ret == 0) { /* Put the MPOOL structure first in the region. */ mp = dbmp->maddr; @@ -315,7 +326,7 @@ retry: if (LF_ISSET(DB_CREATE)) { dbmp->fd = fd; /* If we locked the region, release it now. */ - if (!F_ISSET(dbmp, MP_ISPRIVATE)) + if (!F_ISSET(dbmp, MP_MALLOC)) UNLOCKREGION(dbmp); return (0); @@ -339,7 +350,7 @@ int __memp_rclose(dbmp) DB_MPOOL *dbmp; { - if (F_ISSET(dbmp, MP_ISPRIVATE)) { + if (F_ISSET(dbmp, MP_MALLOC)) { __db_free(dbmp->maddr); return (0); } diff --git a/db2/mp/mp_sync.c b/db2/mp/mp_sync.c index 2f042df9e1..47a7f2ebca 100644 --- a/db2/mp/mp_sync.c +++ b/db2/mp/mp_sync.c @@ -7,7 +7,7 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)mp_sync.c 10.15 (Sleepycat) 11/1/97"; +static const char sccsid[] = "@(#)mp_sync.c 10.17 (Sleepycat) 11/26/97"; #endif /* not lint */ #ifndef NO_SYSTEM_INCLUDES @@ -201,7 +201,7 @@ memp_sync(dbmp, lsnp) */ if (!wrote) { __db_err(dbenv, "%s: unable to flush page: %lu", - R_ADDR(dbmp, mfp->path_off), + __memp_fns(dbmp, mfp), (u_long)bharray[next]->pgno); ret = EPERM; goto err; @@ -244,16 +244,24 @@ memp_fsync(dbmfp) size_t mf_offset; int ar_cnt, cnt, nalloc, next, pincnt, notused, ret, wrote; + dbmp = dbmfp->dbmp; + /* * If this handle doesn't have a file descriptor that's open for * writing, or if the file is a temporary, there's no reason to * proceed further. */ - if (F_ISSET(dbmfp, MP_READONLY | MP_PATH_TEMP)) + if (F_ISSET(dbmfp, MP_READONLY)) return (0); ret = 0; - dbmp = dbmfp->dbmp; + LOCKREGION(dbmp); + if (F_ISSET(dbmfp->mfp, MP_TEMP)) + ret = 1; + UNLOCKREGION(dbmp); + if (ret) + return (0); + mf_offset = R_OFFSET(dbmp, dbmfp->mfp); /* @@ -407,18 +415,26 @@ loop: total = mp->stat.st_page_clean + mp->stat.st_page_dirty; continue; mfp = R_ADDR(dbmp, bhp->mf_offset); + + /* + * We can't write to temporary files -- see the comment in + * mp_bh.c:__memp_bhwrite(). + */ + if (F_ISSET(mfp, MP_TEMP)) + continue; + if ((ret = __memp_bhwrite(dbmp, mfp, bhp, ¬used, &wrote)) != 0) goto err; /* - * Any process syncing the shared memory buffer pool - * had better be able to write to any underlying file. - * Be understanding, but firm, on this point. + * Any process syncing the shared memory buffer pool had better + * be able to write to any underlying file. Be understanding, + * but firm, on this point. */ if (!wrote) { __db_err(dbmp->dbenv, "%s: unable to flush page: %lu", - R_ADDR(dbmp, mfp->path_off), (u_long)bhp->pgno); + __memp_fns(dbmp, mfp), (u_long)bhp->pgno); ret = EPERM; goto err; } |