diff options
Diffstat (limited to 'db2/btree/bt_open.c')
-rw-r--r-- | db2/btree/bt_open.c | 240 |
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); } |