aboutsummaryrefslogtreecommitdiff
path: root/db2/db/db.c
diff options
context:
space:
mode:
Diffstat (limited to 'db2/db/db.c')
-rw-r--r--db2/db/db.c313
1 files changed, 108 insertions, 205 deletions
diff --git a/db2/db/db.c b/db2/db/db.c
index 70c6c5443b..2b4c270324 100644
--- a/db2/db/db.c
+++ b/db2/db/db.c
@@ -44,7 +44,7 @@
#include "config.h"
#ifndef lint
-static const char sccsid[] = "@(#)db.c 10.57 (Sleepycat) 5/7/98";
+static const char sccsid[] = "@(#)db.c 10.75 (Sleepycat) 12/3/98";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
@@ -67,9 +67,6 @@ static const char sccsid[] = "@(#)db.c 10.57 (Sleepycat) 5/7/98";
#include "db_am.h"
#include "common_ext.h"
-static int db_close __P((DB *, u_int32_t));
-static int db_fd __P((DB *, int *));
-
/*
* If the metadata page has the flag set, set the local flag. If the page
* does NOT have the flag set, return EINVAL if the user's dbinfo argument
@@ -87,11 +84,6 @@ static int db_fd __P((DB *, int *));
} \
}
-#ifdef _LIBC
-#define db_open(fname, type, flags, mode, dbenv, dbinfo, dbpp) \
- __nss_db_open(fname, type, flags, mode, dbenv, dbinfo, dbpp)
-#endif
-
/*
* db_open --
* Main library interface to the DB access methods.
@@ -141,9 +133,10 @@ db_open(fname, type, flags, mode, dbenv, dbinfo, dbpp)
/*
* Specifying a cachesize to db_open(3), after creating an
- * environment, is a common mistake.
+ * environment with DB_INIT_MPOOL, is a common mistake.
*/
- if (dbinfo != NULL && dbinfo->db_cachesize != 0) {
+ if (dbenv->mp_info != NULL &&
+ dbinfo != NULL && dbinfo->db_cachesize != 0) {
__db_err(dbenv,
"cachesize will be ignored if environment exists");
return (EINVAL);
@@ -156,12 +149,16 @@ db_open(fname, type, flags, mode, dbenv, dbinfo, dbpp)
real_name = NULL;
/* Allocate the DB structure, reference the DB_ENV structure. */
- if ((dbp = (DB *)__db_calloc(1, sizeof(DB))) == NULL) {
- __db_err(dbenv, "%s", strerror(ENOMEM));
- return (ENOMEM);
- }
+ if ((ret = __os_calloc(1, sizeof(DB), &dbp)) != 0)
+ return (ret);
dbp->dbenv = dbenv;
+ /* Random initialization. */
+ TAILQ_INIT(&dbp->free_queue);
+ TAILQ_INIT(&dbp->active_queue);
+ if ((ret = __db_init_wrapper(dbp)) != 0)
+ goto err;
+
/* Convert the db_open(3) flags. */
if (LF_ISSET(DB_RDONLY))
F_SET(dbp, DB_AM_RDONLY);
@@ -192,21 +189,16 @@ db_open(fname, type, flags, mode, dbenv, dbinfo, dbpp)
}
/*
- * Always set the master and initialize the queues, so we can
- * use these fields without checking the thread bit.
- */
- dbp->master = dbp;
- LIST_INIT(&dbp->handleq);
- LIST_INSERT_HEAD(&dbp->handleq, dbp, links);
- TAILQ_INIT(&dbp->curs_queue);
-
- /*
* Set based on the dbenv fields, although no logging or transactions
* are possible for temporary files.
*/
if (dbenv != NULL) {
- if (dbenv->lk_info != NULL)
- F_SET(dbp, DB_AM_LOCKING);
+ if (dbenv->lk_info != NULL) {
+ if (F_ISSET(dbenv, DB_ENV_CDB))
+ F_SET(dbp, DB_AM_CDB);
+ else
+ F_SET(dbp, DB_AM_LOCKING);
+ }
if (fname != NULL && dbenv->lg_info != NULL)
F_SET(dbp, DB_AM_LOGGING);
}
@@ -215,9 +207,29 @@ db_open(fname, type, flags, mode, dbenv, dbinfo, dbpp)
if (dbinfo == NULL) {
dbp->pgsize = 0;
dbp->db_malloc = NULL;
+ dbp->dup_compare = NULL;
} else {
+ /*
+ * We don't want anything that's not a power-of-2, as we rely
+ * on that for alignment of various types on the pages.
+ */
+ if ((dbp->pgsize = dbinfo->db_pagesize) != 0 &&
+ (u_int32_t)1 << __db_log2(dbp->pgsize) != dbp->pgsize) {
+ __db_err(dbenv, "page sizes must be a power-of-2");
+ goto einval;
+ }
dbp->pgsize = dbinfo->db_pagesize;
dbp->db_malloc = dbinfo->db_malloc;
+ if (F_ISSET(dbinfo, DB_DUPSORT)) {
+ if (F_ISSET(dbinfo, DB_DUP))
+ dbp->dup_compare = dbinfo->dup_compare == NULL ?
+ __bam_defcmp : dbinfo->dup_compare;
+ else {
+ __db_err(dbenv, "DB_DUPSORT requires DB_DUP");
+ goto einval;
+ }
+ F_CLR(dbinfo, DB_DUPSORT);
+ }
}
/* Fill in the default file mode. */
@@ -235,6 +247,7 @@ db_open(fname, type, flags, mode, dbenv, dbinfo, dbpp)
default:
goto err;
}
+ dbp->byteswapped = F_ISSET(dbp, DB_AM_SWAP) ? 1 : 0;
/*
* If we have a file name, try and read the first page, figure out
@@ -289,7 +302,7 @@ open_retry: if (LF_ISSET(DB_CREATE)) {
* sizes, we limit the default pagesize to 16K.
*/
if (dbp->pgsize == 0) {
- if ((ret = __db_ioinfo(real_name,
+ if ((ret = __os_ioinfo(real_name,
fd, NULL, NULL, &iopsize)) != 0) {
__db_err(dbenv,
"%s: %s", real_name, strerror(ret));
@@ -299,6 +312,14 @@ open_retry: if (LF_ISSET(DB_CREATE)) {
iopsize = 512;
if (iopsize > 16 * 1024)
iopsize = 16 * 1024;
+
+ /*
+ * Sheer paranoia, but we don't want anything that's
+ * not a power-of-2, as we rely on that for alignment
+ * of various types on the pages.
+ */
+ DB_ROUNDOFF(iopsize, 512);
+
dbp->pgsize = iopsize;
F_SET(dbp, DB_AM_PGDEF);
}
@@ -308,11 +329,11 @@ open_retry: if (LF_ISSET(DB_CREATE)) {
* that the meta-data for all access methods fits in 512
* bytes, and that no database will be smaller than that.
*/
- if ((ret = __db_read(fd, mbuf, sizeof(mbuf), &nr)) != 0)
+ if ((ret = __os_read(fd, mbuf, sizeof(mbuf), &nr)) != 0)
goto err;
/* The fd is no longer needed. */
- (void)__db_close(fd);
+ (void)__os_close(fd);
fd = -1;
if (nr != sizeof(mbuf)) {
@@ -337,7 +358,7 @@ open_retry: if (LF_ISSET(DB_CREATE)) {
*/
if (retry_cnt++ < 3 &&
!LF_ISSET(DB_CREATE | DB_TRUNCATE)) {
- __db_sleep(1, 0);
+ __os_sleep(1, 0);
goto open_retry;
}
if (type == DB_UNKNOWN) {
@@ -396,7 +417,7 @@ retry: switch (((BTMETA *)mbuf)->magic) {
/* Copy the file's unique id. */
need_fileid = 0;
- memcpy(dbp->lock.fileid, btm->uid, DB_FILE_ID_LEN);
+ memcpy(dbp->fileid, btm->uid, DB_FILE_ID_LEN);
break;
case DB_HASHMAGIC:
if (type != DB_HASH && type != DB_UNKNOWN)
@@ -425,7 +446,7 @@ retry: switch (((BTMETA *)mbuf)->magic) {
/* Copy the file's unique id. */
need_fileid = 0;
- memcpy(dbp->lock.fileid, hashm->uid, DB_FILE_ID_LEN);
+ memcpy(dbp->fileid, hashm->uid, DB_FILE_ID_LEN);
break;
default:
if (swapped) {
@@ -489,11 +510,9 @@ empty: /*
F_SET(dbp, DB_AM_MLOCAL);
if (dbenv == NULL) {
- if ((dbp->mp_dbenv =
- (DB_ENV *)__db_calloc(sizeof(DB_ENV), 1)) == NULL) {
- ret = ENOMEM;
+ if ((ret = __os_calloc(1,
+ sizeof(DB_ENV), &dbp->mp_dbenv)) != 0)
goto err;
- }
envp = dbp->mp_dbenv;
restore = 0;
@@ -554,20 +573,20 @@ empty: /*
*/
if (need_fileid) {
if (fname == NULL) {
- memset(dbp->lock.fileid, 0, DB_FILE_ID_LEN);
+ memset(dbp->fileid, 0, DB_FILE_ID_LEN);
if (F_ISSET(dbp, DB_AM_LOCKING) &&
(ret = lock_id(dbenv->lk_info,
- (u_int32_t *)dbp->lock.fileid)) != 0)
+ (u_int32_t *)dbp->fileid)) != 0)
goto err;
} else
- if ((ret = __db_fileid(dbenv,
- real_name, 1, dbp->lock.fileid)) != 0)
+ if ((ret = __os_fileid(dbenv,
+ real_name, 1, dbp->fileid)) != 0)
goto err;
}
/* No further use for the real name. */
if (real_name != NULL)
- FREES(real_name);
+ __os_freestr(real_name);
real_name = NULL;
/*
@@ -595,7 +614,7 @@ empty: /*
memset(&finfo, 0, sizeof(finfo));
finfo.ftype = ftype;
finfo.pgcookie = &pgcookie;
- finfo.fileid = dbp->lock.fileid;
+ finfo.fileid = dbp->fileid;
finfo.lsn_offset = 0;
finfo.clear_len = DB_PAGE_CLEAR_LEN;
if ((ret = memp_fopen(dbp->mp, fname,
@@ -605,12 +624,21 @@ empty: /*
/*
* XXX
- * Truly spectacular layering violation. We need a per-thread mutex
- * that lives in shared memory (thanks, HP-UX!) and so we acquire a
- * pointer to the mpool one.
+ * We need a per-thread mutex that lives in shared memory -- HP-UX
+ * can't allocate mutexes in malloc'd memory. Allocate it from the
+ * shared memory region, since it's the only one that is guaranteed
+ * to exist.
*/
- if (F_ISSET(dbp, DB_AM_THREAD))
- dbp->mutexp = dbp->mpf->mutexp;
+ if (F_ISSET(dbp, DB_AM_THREAD)) {
+ if ((ret = __memp_reg_alloc(dbp->mp,
+ sizeof(db_mutex_t), NULL, &dbp->mutexp)) != 0)
+ goto err;
+ /*
+ * Since we only get here if DB_THREAD was specified, we know
+ * we have spinlocks and no file offset argument is needed.
+ */
+ (void)__db_mutex_init(dbp->mutexp, 0);
+ }
/* Get a log file id. */
if (F_ISSET(dbp, DB_AM_LOGGING) &&
@@ -618,18 +646,6 @@ empty: /*
dbp, fname, type, &dbp->log_fileid)) != 0)
goto err;
- /*
- * Get a locker id for this DB, and build the lock cookie: the first
- * db_pgno_t bytes are the page number, the next N bytes are the file
- * id.
- */
- if (F_ISSET(dbp, DB_AM_LOCKING)) {
- if ((ret = lock_id(dbenv->lk_info, &dbp->locker)) != 0)
- goto err;
- dbp->lock_dbt.size = sizeof(dbp->lock);
- dbp->lock_dbt.data = &dbp->lock;
- }
-
/* Call the real open function. */
switch (type) {
case DB_BTREE:
@@ -639,7 +655,7 @@ empty: /*
if (dbinfo != NULL && (ret = __db_fcchk(dbenv,
"db_open", dbinfo->flags, DB_DUP, DB_RECNUM)) != 0)
goto err;
- if ((ret = __bam_open(dbp, type, dbinfo)) != 0)
+ if ((ret = __bam_open(dbp, dbinfo)) != 0)
goto err;
break;
case DB_HASH:
@@ -655,24 +671,20 @@ empty: /*
if (dbinfo != NULL && (ret = __db_fchk(dbenv,
"db_open", dbinfo->flags, DB_INFO_FLAGS)) != 0)
goto err;
- if ((ret = __ram_open(dbp, type, dbinfo)) != 0)
+ if ((ret = __ram_open(dbp, dbinfo)) != 0)
goto err;
break;
default:
abort();
}
- /* Call a local close routine. */
- dbp->close = db_close;
- dbp->fd = db_fd;
-
*dbpp = dbp;
return (0);
einval: ret = EINVAL;
err: /* Close the file descriptor. */
if (fd != -1)
- (void)__db_close(fd);
+ (void)__os_close(fd);
/* Discard the log file id. */
if (dbp->log_fileid != 0)
@@ -688,90 +700,60 @@ err: /* Close the file descriptor. */
/* If we allocated a DB_ENV, discard it. */
if (dbp->mp_dbenv != NULL)
- FREE(dbp->mp_dbenv, sizeof(DB_ENV));
+ __os_free(dbp->mp_dbenv, sizeof(DB_ENV));
if (real_name != NULL)
- FREES(real_name);
+ __os_freestr(real_name);
if (dbp != NULL)
- FREE(dbp, sizeof(DB));
+ __os_free(dbp, sizeof(DB));
return (ret);
}
-#ifdef _LIBC
-# undef db_open
-weak_alias (__nss_db_open, db_open)
-#endif
-
/*
- * db_close --
+ * __db_close --
* Close a DB tree.
+ *
+ * PUBLIC: int __db_close __P((DB *, u_int32_t));
*/
-static int
-db_close(dbp, flags)
+int
+__db_close(dbp, flags)
DB *dbp;
u_int32_t flags;
{
DBC *dbc;
- DB *tdbp;
int ret, t_ret;
+ DB_PANIC_CHECK(dbp);
+
/* Validate arguments. */
- if ((ret = __db_fchk(dbp->dbenv, "db_close", flags, DB_NOSYNC)) != 0)
+ if ((ret = __db_closechk(dbp, flags)) != 0)
return (ret);
/* Sync the underlying file. */
- if (!LF_ISSET(DB_NOSYNC) &&
+ if (flags != DB_NOSYNC &&
(t_ret = dbp->sync(dbp, 0)) != 0 && ret == 0)
ret = t_ret;
/*
- * Call the underlying access method close routine for all the
- * cursors and handles.
+ * Go through the active cursors and call the cursor recycle routine,
+ * which resolves pending operations and moves the cursors onto the
+ * free list. Then, walk the free list and call the cursor destroy
+ * routine.
*/
- for (tdbp = LIST_FIRST(&dbp->handleq);
- tdbp != NULL; tdbp = LIST_NEXT(tdbp, links)) {
- while ((dbc = TAILQ_FIRST(&tdbp->curs_queue)) != NULL)
- switch (tdbp->type) {
- case DB_BTREE:
- if ((t_ret =
- __bam_c_iclose(tdbp, dbc)) != 0 && ret == 0)
- ret = t_ret;
- break;
- case DB_HASH:
- if ((t_ret =
- __ham_c_iclose(tdbp, dbc)) != 0 && ret == 0)
- ret = t_ret;
- break;
- case DB_RECNO:
- if ((t_ret =
- __ram_c_iclose(tdbp, dbc)) != 0 && ret == 0)
- ret = t_ret;
- break;
- default:
- abort();
- }
-
- switch (tdbp->type) {
- case DB_BTREE:
- if ((t_ret = __bam_close(tdbp)) != 0 && ret == 0)
- ret = t_ret;
- break;
- case DB_HASH:
- if ((t_ret = __ham_close(tdbp)) != 0 && ret == 0)
- ret = t_ret;
- break;
- case DB_RECNO:
- if ((t_ret = __ram_close(tdbp)) != 0 && ret == 0)
- ret = t_ret;
- break;
- default:
- abort();
- }
- }
+ while ((dbc = TAILQ_FIRST(&dbp->active_queue)) != NULL)
+ if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
+ ret = t_ret;
+ while ((dbc = TAILQ_FIRST(&dbp->free_queue)) != NULL)
+ if ((t_ret = __db_c_destroy(dbc)) != 0 && ret == 0)
+ ret = t_ret;
+
+ /* Call the access specific close function. */
+ if ((t_ret = dbp->am_close(dbp)) != 0 && ret == 0)
+ ret = t_ret;
/* Sync the memory pool. */
- if (!LF_ISSET(DB_NOSYNC) && (t_ret = memp_fsync(dbp->mpf)) != 0 &&
+ if (flags != DB_NOSYNC && (t_ret = memp_fsync(dbp->mpf)) != 0 &&
t_ret != DB_INCOMPLETE && ret == 0)
ret = t_ret;
@@ -788,91 +770,12 @@ db_close(dbp, flags)
if (F_ISSET(dbp, DB_AM_LOGGING))
(void)log_unregister(dbp->dbenv->lg_info, dbp->log_fileid);
- /* Discard the lock cookie for all handles. */
- for (tdbp = LIST_FIRST(&dbp->handleq);
- tdbp != NULL; tdbp = LIST_NEXT(tdbp, links))
- if (F_ISSET(tdbp, DB_AM_LOCKING)) {
-#ifdef DEBUG
- DB_LOCKREQ request;
-
- /*
- * If we're running tests, display any locks currently
- * held. It's possible that some applications may hold
- * locks for long periods, e.g., conference room locks,
- * but the DB tests should never close holding locks.
- */
- request.op = DB_LOCK_DUMP;
- if ((t_ret = lock_vec(tdbp->dbenv->lk_info,
- tdbp->locker, 0, &request, 1, NULL)) != 0 &&
- ret == 0)
- ret = EAGAIN;
-#endif
- }
-
/* If we allocated a DB_ENV, discard it. */
if (dbp->mp_dbenv != NULL)
- FREE(dbp->mp_dbenv, sizeof(DB_ENV));
+ __os_free(dbp->mp_dbenv, sizeof(DB_ENV));
- /* Free all of the DB's. */
- LIST_REMOVE(dbp, links);
- while ((tdbp = LIST_FIRST(&dbp->handleq)) != NULL) {
- LIST_REMOVE(tdbp, links);
- FREE(tdbp, sizeof(*tdbp));
- }
- FREE(dbp, sizeof(*dbp));
+ /* Free the DB. */
+ __os_free(dbp, sizeof(*dbp));
return (ret);
}
-
-/*
- * db_fd --
- * Return a file descriptor for flock'ing.
- */
-static int
-db_fd(dbp, fdp)
- DB *dbp;
- int *fdp;
-{
- /*
- * XXX
- * Truly spectacular layering violation.
- */
- return (__mp_xxx_fd(dbp->mpf, fdp));
-}
-
-/*
- * __db_pgerr --
- * Error when unable to retrieve a specified page.
- *
- * PUBLIC: int __db_pgerr __P((DB *, db_pgno_t));
- */
-int
-__db_pgerr(dbp, pgno)
- DB *dbp;
- db_pgno_t pgno;
-{
- /*
- * Three things are certain:
- * Death, taxes, and lost data.
- * Guess which has occurred.
- */
- __db_err(dbp->dbenv,
- "unable to create/retrieve page %lu", (u_long)pgno);
- return (__db_panic(dbp));
-}
-
-/*
- * __db_pgfmt --
- * Error when a page has the wrong format.
- *
- * PUBLIC: int __db_pgfmt __P((DB *, db_pgno_t));
- */
-int
-__db_pgfmt(dbp, pgno)
- DB *dbp;
- db_pgno_t pgno;
-{
- __db_err(dbp->dbenv,
- "page %lu: illegal page type or format", (u_long)pgno);
- return (__db_panic(dbp));
-}