aboutsummaryrefslogtreecommitdiff
path: root/db2/btree/bt_open.c
diff options
context:
space:
mode:
Diffstat (limited to 'db2/btree/bt_open.c')
-rw-r--r--db2/btree/bt_open.c240
1 files changed, 101 insertions, 139 deletions
diff --git a/db2/btree/bt_open.c b/db2/btree/bt_open.c
index f5974ec61e..a89cfccb97 100644
--- a/db2/btree/bt_open.c
+++ b/db2/btree/bt_open.c
@@ -47,17 +47,9 @@
#include "config.h"
#ifndef lint
-static const char sccsid[] = "@(#)bt_open.c 10.27 (Sleepycat) 5/6/98";
+static const char sccsid[] = "@(#)bt_open.c 10.39 (Sleepycat) 11/21/98";
#endif /* not lint */
-/*
- * Implementation of btree access method for 4.4BSD.
- *
- * The design here was originally based on that of the btree access method
- * used in the Postgres database system at UC Berkeley. This implementation
- * is wholly independent of the Postgres code.
- */
-
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
@@ -70,40 +62,34 @@ static const char sccsid[] = "@(#)bt_open.c 10.27 (Sleepycat) 5/6/98";
#include "db_page.h"
#include "btree.h"
-static int __bam_keyalloc __P((BTREE *));
-static int __bam_setmeta __P((DB *, BTREE *));
-
/*
* __bam_open --
* Open a btree.
*
- * PUBLIC: int __bam_open __P((DB *, DBTYPE, DB_INFO *));
+ * PUBLIC: int __bam_open __P((DB *, DB_INFO *));
*/
int
-__bam_open(dbp, type, dbinfo)
+__bam_open(dbp, dbinfo)
DB *dbp;
- DBTYPE type;
DB_INFO *dbinfo;
{
BTREE *t;
int ret;
- /* Allocate the btree internal structure. */
- if ((t = (BTREE *)__db_calloc(1, sizeof(BTREE))) == NULL)
- return (ENOMEM);
-
- t->bt_sp = t->bt_csp = t->bt_stack;
- t->bt_esp = t->bt_stack + sizeof(t->bt_stack) / sizeof(t->bt_stack[0]);
-
- if ((type == DB_RECNO || F_ISSET(dbp, DB_BT_RECNUM)) &&
- (ret = __bam_keyalloc(t)) != 0)
- goto err;
+ /* Allocate and initialize the private btree structure. */
+ if ((ret = __os_calloc(1, sizeof(BTREE), &t)) != 0)
+ return (ret);
+ dbp->internal = t;
/*
* Intention is to make sure all of the user's selections are okay
* here and then use them without checking.
*/
- if (dbinfo != NULL) {
+ if (dbinfo == NULL) {
+ t->bt_minkey = DEFMINKEYPAGE;
+ t->bt_compare = __bam_defcmp;
+ t->bt_prefix = __bam_defpfx;
+ } else {
/* Minimum number of keys per page. */
if (dbinfo->bt_minkey == 0)
t->bt_minkey = DEFMINKEYPAGE;
@@ -126,152 +112,125 @@ __bam_open(dbp, type, dbinfo)
* If no comparison, use default comparison. If no comparison
* and no prefix, use default prefix. (We can't default the
* prefix if the user supplies a comparison routine; shortening
- * the keys may break their comparison algorithm.)
+ * the keys may break their comparison algorithm. We don't
+ * permit the user to specify a prefix routine if they didn't
+ * also specify a comparison routine, they can't know enough
+ * about our comparison routine to get it right.)
*/
- t->bt_compare = dbinfo->bt_compare == NULL ?
- __bam_defcmp : dbinfo->bt_compare;
- t->bt_prefix = dbinfo->bt_prefix == NULL ?
- (dbinfo->bt_compare == NULL ?
- __bam_defpfx : NULL) : dbinfo->bt_prefix;
- } else {
- t->bt_minkey = DEFMINKEYPAGE;
- t->bt_compare = __bam_defcmp;
- t->bt_prefix = __bam_defpfx;
+ if ((t->bt_compare = dbinfo->bt_compare) == NULL) {
+ if (dbinfo->bt_prefix != NULL)
+ goto einval;
+ t->bt_compare = __bam_defcmp;
+ t->bt_prefix = __bam_defpfx;
+ } else
+ t->bt_prefix = dbinfo->bt_prefix;
}
- /* Initialize the remaining fields of the DB. */
- dbp->type = type;
- dbp->internal = t;
- dbp->cursor = __bam_cursor;
+ /* Initialize the remaining fields/methods of the DB. */
+ dbp->am_close = __bam_close;
dbp->del = __bam_delete;
- dbp->get = __bam_get;
- dbp->put = __bam_put;
dbp->stat = __bam_stat;
- dbp->sync = __bam_sync;
-
- /*
- * The btree data structure requires that at least two key/data pairs
- * can fit on a page, but other than that there's no fixed requirement.
- * Translate the minimum number of items into the bytes a key/data pair
- * can use before being placed on an overflow page. We calculate for
- * the worst possible alignment by assuming every item requires the
- * maximum alignment for padding.
- *
- * Recno uses the btree bt_ovflsize value -- it's close enough.
- */
- t->bt_ovflsize = (dbp->pgsize - P_OVERHEAD) / (t->bt_minkey * P_INDX)
- - (BKEYDATA_PSIZE(0) + ALIGN(1, 4));
- /* Create a root page if new tree. */
- if ((ret = __bam_setmeta(dbp, t)) != 0)
+ /* Start up the tree. */
+ if ((ret = __bam_read_root(dbp)) != 0)
goto err;
+ /* Set the overflow page size. */
+ __bam_setovflsize(dbp);
+
return (0);
einval: ret = EINVAL;
-err: if (t != NULL) {
- /* If we allocated room for key/data return, discard it. */
- if (t->bt_rkey.data != NULL)
- __db_free(t->bt_rkey.data);
-
- FREE(t, sizeof(BTREE));
- }
+err: __os_free(t, sizeof(BTREE));
return (ret);
}
/*
- * __bam_bdup --
- * Create a BTREE handle for a threaded DB handle.
+ * __bam_close --
+ * Close a btree.
*
- * PUBLIC: int __bam_bdup __P((DB *, DB *));
+ * PUBLIC: int __bam_close __P((DB *));
*/
int
-__bam_bdup(orig, new)
- DB *orig, *new;
+__bam_close(dbp)
+ DB *dbp;
{
- BTREE *t, *ot;
- int ret;
-
- ot = orig->internal;
-
- if ((t = (BTREE *)__db_calloc(1, sizeof(*t))) == NULL)
- return (ENOMEM);
-
- /*
- * !!!
- * Ignore the cursor queue, only the first DB has attached cursors.
- */
+ __os_free(dbp->internal, sizeof(BTREE));
+ dbp->internal = NULL;
- t->bt_sp = t->bt_csp = t->bt_stack;
- t->bt_esp = t->bt_stack + sizeof(t->bt_stack) / sizeof(t->bt_stack[0]);
+ return (0);
+}
- if ((orig->type == DB_RECNO || F_ISSET(orig, DB_BT_RECNUM)) &&
- (ret = __bam_keyalloc(t)) != 0) {
- FREE(t, sizeof(*t));
- return (ret);
- }
+/*
+ * __bam_setovflsize --
+ *
+ * PUBLIC: void __bam_setovflsize __P((DB *));
+ */
+void
+__bam_setovflsize(dbp)
+ DB *dbp;
+{
+ BTREE *t;
- t->bt_maxkey = ot->bt_maxkey;
- t->bt_minkey = ot->bt_minkey;
- t->bt_compare = ot->bt_compare;
- t->bt_prefix = ot->bt_prefix;
- t->bt_ovflsize = ot->bt_ovflsize;
+ t = dbp->internal;
/*
* !!!
- * The entire RECNO structure is shared. If it breaks, the application
- * was misusing it to start with.
+ * Correction for recno, which doesn't know anything about minimum
+ * keys per page.
*/
- t->bt_recno = ot->bt_recno;
-
- new->internal = t;
-
- return (0);
-}
+ if (t->bt_minkey == 0)
+ t->bt_minkey = DEFMINKEYPAGE;
-/*
- * __bam_keyalloc --
- * Allocate return memory for recno keys.
- */
-static int
-__bam_keyalloc(t)
- BTREE *t;
-{
/*
- * Recno keys are always the same size, and we don't want to have
- * to check for space on each return. Allocate it now.
+ * The btree data structure requires that at least two key/data pairs
+ * can fit on a page, but other than that there's no fixed requirement.
+ * Translate the minimum number of items into the bytes a key/data pair
+ * can use before being placed on an overflow page. We calculate for
+ * the worst possible alignment by assuming every item requires the
+ * maximum alignment for padding.
+ *
+ * Recno uses the btree bt_ovflsize value -- it's close enough.
*/
- if ((t->bt_rkey.data = (void *)__db_malloc(sizeof(db_recno_t))) == NULL)
- return (ENOMEM);
- t->bt_rkey.ulen = sizeof(db_recno_t);
- return (0);
+ t->bt_ovflsize = (dbp->pgsize - P_OVERHEAD) / (t->bt_minkey * P_INDX)
+ - (BKEYDATA_PSIZE(0) + ALIGN(1, 4));
}
/*
- * __bam_setmeta --
+ * __bam_read_root --
* Check (and optionally create) a tree.
+ *
+ * PUBLIC: int __bam_read_root __P((DB *));
*/
-static int
-__bam_setmeta(dbp, t)
+int
+__bam_read_root(dbp)
DB *dbp;
- BTREE *t;
{
BTMETA *meta;
- PAGE *root;
+ BTREE *t;
+ DBC *dbc;
DB_LOCK metalock, rootlock;
+ PAGE *root;
db_pgno_t pgno;
- int ret;
+ int ret, t_ret;
+
+ ret = 0;
+ t = dbp->internal;
+
+ /* Get a cursor. */
+ if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0)
+ return (ret);
/* Get, and optionally create the metadata page. */
pgno = PGNO_METADATA;
if ((ret =
- __bam_lget(dbp, 0, PGNO_METADATA, DB_LOCK_WRITE, &metalock)) != 0)
- return (ret);
+ __bam_lget(dbc, 0, PGNO_METADATA, DB_LOCK_WRITE, &metalock)) != 0)
+ goto err;
if ((ret =
- __bam_pget(dbp, (PAGE **)&meta, &pgno, DB_MPOOL_CREATE)) != 0) {
- (void)__BT_LPUT(dbp, metalock);
- return (ret);
+ memp_fget(dbp->mpf, &pgno, DB_MPOOL_CREATE, (PAGE **)&meta)) != 0) {
+ (void)__BT_LPUT(dbc, metalock);
+ goto err;
}
/*
@@ -284,8 +243,8 @@ __bam_setmeta(dbp, t)
t->bt_minkey = meta->minkey;
(void)memp_fput(dbp->mpf, (PAGE *)meta, 0);
- (void)__BT_LPUT(dbp, metalock);
- return (0);
+ (void)__BT_LPUT(dbc, metalock);
+ goto done;
}
/* Initialize the tree structure metadata information. */
@@ -308,16 +267,16 @@ __bam_setmeta(dbp, t)
F_SET(meta, BTM_RECNUM);
if (F_ISSET(dbp, DB_RE_RENUMBER))
F_SET(meta, BTM_RENUMBER);
- memcpy(meta->uid, dbp->lock.fileid, DB_FILE_ID_LEN);
+ memcpy(meta->uid, dbp->fileid, DB_FILE_ID_LEN);
/* Create and initialize a root page. */
pgno = PGNO_ROOT;
if ((ret =
- __bam_lget(dbp, 0, PGNO_ROOT, DB_LOCK_WRITE, &rootlock)) != 0)
- return (ret);
- if ((ret = __bam_pget(dbp, &root, &pgno, DB_MPOOL_CREATE)) != 0) {
- (void)__BT_LPUT(dbp, rootlock);
- return (ret);
+ __bam_lget(dbc, 0, PGNO_ROOT, DB_LOCK_WRITE, &rootlock)) != 0)
+ goto err;
+ if ((ret = memp_fget(dbp->mpf, &pgno, DB_MPOOL_CREATE, &root)) != 0) {
+ (void)__BT_LPUT(dbc, rootlock);
+ goto err;
}
P_INIT(root, dbp->pgsize, PGNO_ROOT, PGNO_INVALID,
PGNO_INVALID, 1, dbp->type == DB_RECNO ? P_LRECNO : P_LBTREE);
@@ -325,9 +284,9 @@ __bam_setmeta(dbp, t)
/* Release the metadata and root pages. */
if ((ret = memp_fput(dbp->mpf, (PAGE *)meta, DB_MPOOL_DIRTY)) != 0)
- return (ret);
+ goto err;
if ((ret = memp_fput(dbp->mpf, root, DB_MPOOL_DIRTY)) != 0)
- return (ret);
+ goto err;
/*
* Flush the metadata and root pages to disk -- since the user can't
@@ -341,8 +300,11 @@ __bam_setmeta(dbp, t)
ret = EINVAL;
/* Release the locks. */
- (void)__BT_LPUT(dbp, metalock);
- (void)__BT_LPUT(dbp, rootlock);
+ (void)__BT_LPUT(dbc, metalock);
+ (void)__BT_LPUT(dbc, rootlock);
+err:
+done: if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
+ ret = t_ret;
return (ret);
}