diff options
Diffstat (limited to 'bdb/btree/bt_stat.c')
-rw-r--r-- | bdb/btree/bt_stat.c | 203 |
1 files changed, 102 insertions, 101 deletions
diff --git a/bdb/btree/bt_stat.c b/bdb/btree/bt_stat.c index 349bb40cf8b..4428de98294 100644 --- a/bdb/btree/bt_stat.c +++ b/bdb/btree/bt_stat.c @@ -1,14 +1,14 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1996, 1997, 1998, 1999, 2000 + * Copyright (c) 1996-2002 * Sleepycat Software. All rights reserved. */ #include "db_config.h" #ifndef lint -static const char revid[] = "$Id: bt_stat.c,v 11.29 2000/11/28 21:42:27 bostic Exp $"; +static const char revid[] = "$Id: bt_stat.c,v 11.52 2002/05/30 15:40:27 krinsky Exp $"; #endif /* not lint */ #ifndef NO_SYSTEM_INCLUDES @@ -18,22 +18,22 @@ static const char revid[] = "$Id: bt_stat.c,v 11.29 2000/11/28 21:42:27 bostic E #endif #include "db_int.h" -#include "db_page.h" -#include "db_shash.h" -#include "lock.h" -#include "btree.h" +#include "dbinc/db_page.h" +#include "dbinc/db_shash.h" +#include "dbinc/btree.h" +#include "dbinc/lock.h" +#include "dbinc/log.h" /* * __bam_stat -- * Gather/print the btree statistics * - * PUBLIC: int __bam_stat __P((DB *, void *, void *(*)(size_t), u_int32_t)); + * PUBLIC: int __bam_stat __P((DB *, void *, u_int32_t)); */ int -__bam_stat(dbp, spp, db_malloc, flags) +__bam_stat(dbp, spp, flags) DB *dbp; void *spp; - void *(*db_malloc) __P((size_t)); u_int32_t flags; { BTMETA *meta; @@ -42,9 +42,10 @@ __bam_stat(dbp, spp, db_malloc, flags) DBC *dbc; DB_BTREE_STAT *sp; DB_LOCK lock, metalock; + DB_MPOOLFILE *mpf; PAGE *h; db_pgno_t pgno; - int ret, t_ret; + int ret, t_ret, write_meta; PANIC_CHECK(dbp->dbenv); DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->stat"); @@ -52,9 +53,12 @@ __bam_stat(dbp, spp, db_malloc, flags) meta = NULL; t = dbp->bt_internal; sp = NULL; - metalock.off = lock.off = LOCK_INVALID; + LOCK_INIT(metalock); + LOCK_INIT(lock); + mpf = dbp->mpf; h = NULL; ret = 0; + write_meta = 0; /* Check for invalid flags. */ if ((ret = __db_statchk(dbp, flags)) != 0) @@ -68,52 +72,31 @@ __bam_stat(dbp, spp, db_malloc, flags) DEBUG_LWRITE(dbc, NULL, "bam_stat", NULL, NULL, flags); /* Allocate and clear the structure. */ - if ((ret = __os_malloc(dbp->dbenv, sizeof(*sp), db_malloc, &sp)) != 0) + if ((ret = __os_umalloc(dbp->dbenv, sizeof(*sp), &sp)) != 0) goto err; memset(sp, 0, sizeof(*sp)); - /* If the app just wants the record count, make it fast. */ - if (flags == DB_RECORDCOUNT) { - if ((ret = __db_lget(dbc, 0, - cp->root, DB_LOCK_READ, 0, &lock)) != 0) - goto err; - if ((ret = memp_fget(dbp->mpf, - &cp->root, 0, (PAGE **)&h)) != 0) - goto err; - - sp->bt_nkeys = RE_NREC(h); - - goto done; - } - if (flags == DB_CACHED_COUNTS) { - if ((ret = __db_lget(dbc, - 0, t->bt_meta, DB_LOCK_READ, 0, &lock)) != 0) - goto err; - if ((ret = - memp_fget(dbp->mpf, &t->bt_meta, 0, (PAGE **)&meta)) != 0) - goto err; - sp->bt_nkeys = meta->dbmeta.key_count; - sp->bt_ndata = meta->dbmeta.record_count; - - goto done; - } - /* Get the metadata page for the entire database. */ pgno = PGNO_BASE_MD; if ((ret = __db_lget(dbc, 0, pgno, DB_LOCK_READ, 0, &metalock)) != 0) goto err; - if ((ret = memp_fget(dbp->mpf, &pgno, 0, (PAGE **)&meta)) != 0) + if ((ret = mpf->get(mpf, &pgno, 0, (PAGE **)&meta)) != 0) goto err; + if (flags == DB_RECORDCOUNT || flags == DB_CACHED_COUNTS) + flags = DB_FAST_STAT; + if (flags == DB_FAST_STAT) + goto meta_only; + /* Walk the metadata free list, counting pages. */ for (sp->bt_free = 0, pgno = meta->dbmeta.free; pgno != PGNO_INVALID;) { ++sp->bt_free; - if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0) + if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0) goto err; pgno = h->next_pgno; - if ((ret = memp_fput(dbp->mpf, h, 0)) != 0) + if ((ret = mpf->put(mpf, h, 0)) != 0) goto err; h = NULL; } @@ -122,14 +105,14 @@ __bam_stat(dbp, spp, db_malloc, flags) pgno = cp->root; if ((ret = __db_lget(dbc, 0, pgno, DB_LOCK_READ, 0, &lock)) != 0) goto err; - if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0) + if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0) goto err; /* Get the levels from the root page. */ sp->bt_levels = h->level; /* Discard the root page. */ - if ((ret = memp_fput(dbp->mpf, h, 0)) != 0) + if ((ret = mpf->put(mpf, h, 0)) != 0) goto err; h = NULL; __LPUT(dbc, lock); @@ -143,20 +126,36 @@ __bam_stat(dbp, spp, db_malloc, flags) * Get the subdatabase metadata page if it's not the same as the * one we already have. */ - if (t->bt_meta != PGNO_BASE_MD || !F_ISSET(dbp, DB_AM_RDONLY)) { - if ((ret = memp_fput(dbp->mpf, meta, 0)) != 0) + write_meta = !F_ISSET(dbp, DB_AM_RDONLY); +meta_only: + if (t->bt_meta != PGNO_BASE_MD || write_meta != 0) { + if ((ret = mpf->put(mpf, meta, 0)) != 0) goto err; meta = NULL; __LPUT(dbc, metalock); if ((ret = __db_lget(dbc, - 0, t->bt_meta, F_ISSET(dbp, DB_AM_RDONLY) ? + 0, t->bt_meta, write_meta == 0 ? DB_LOCK_READ : DB_LOCK_WRITE, 0, &metalock)) != 0) goto err; - if ((ret = - memp_fget(dbp->mpf, &t->bt_meta, 0, (PAGE **)&meta)) != 0) + if ((ret = mpf->get(mpf, &t->bt_meta, 0, (PAGE **)&meta)) != 0) goto err; } + if (flags == DB_FAST_STAT) { + if (dbp->type == DB_RECNO || + (dbp->type == DB_BTREE && F_ISSET(dbp, DB_AM_RECNUM))) { + if ((ret = __db_lget(dbc, 0, + cp->root, DB_LOCK_READ, 0, &lock)) != 0) + goto err; + if ((ret = + mpf->get(mpf, &cp->root, 0, (PAGE **)&h)) != 0) + goto err; + + sp->bt_nkeys = RE_NREC(h); + } else + sp->bt_nkeys = meta->dbmeta.key_count; + sp->bt_ndata = meta->dbmeta.record_count; + } /* Get metadata page statistics. */ sp->bt_metaflags = meta->dbmeta.flags; @@ -167,39 +166,33 @@ __bam_stat(dbp, spp, db_malloc, flags) sp->bt_pagesize = meta->dbmeta.pagesize; sp->bt_magic = meta->dbmeta.magic; sp->bt_version = meta->dbmeta.version; - if (!F_ISSET(dbp, DB_AM_RDONLY)) { + + if (write_meta != 0) { meta->dbmeta.key_count = sp->bt_nkeys; meta->dbmeta.record_count = sp->bt_ndata; } - /* Discard the metadata page. */ - if ((ret = memp_fput(dbp->mpf, - meta, F_ISSET(dbp, DB_AM_RDONLY) ? 0 : DB_MPOOL_DIRTY)) != 0) - goto err; - meta = NULL; - __LPUT(dbc, metalock); - -done: *(DB_BTREE_STAT **)spp = sp; - - if (0) { -err: if (sp != NULL) - __os_free(sp, sizeof(*sp)); - } + *(DB_BTREE_STAT **)spp = sp; - if (h != NULL && - (t_ret = memp_fput(dbp->mpf, h, 0)) != 0 && ret == 0) +err: /* Discard the second page. */ + __LPUT(dbc, lock); + if (h != NULL && (t_ret = mpf->put(mpf, h, 0)) != 0 && ret == 0) ret = t_ret; - if (meta != NULL && - (t_ret = memp_fput(dbp->mpf, meta, 0)) != 0 && ret == 0) + /* Discard the metadata page. */ + __LPUT(dbc, metalock); + if (meta != NULL && (t_ret = mpf->put( + mpf, meta, write_meta == 0 ? 0 : DB_MPOOL_DIRTY)) != 0 && ret == 0) ret = t_ret; - if (lock.off != LOCK_INVALID) - __LPUT(dbc, lock); - if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0) ret = t_ret; + if (ret != 0 && sp != NULL) { + __os_ufree(dbp->dbenv, sp); + *(DB_BTREE_STAT **)spp = NULL; + } + return (ret); } @@ -222,22 +215,27 @@ __bam_traverse(dbc, mode, root_pgno, callback, cookie) BKEYDATA *bk; DB *dbp; DB_LOCK lock; + DB_MPOOLFILE *mpf; PAGE *h; RINTERNAL *ri; db_indx_t indx; int already_put, ret, t_ret; dbp = dbc->dbp; + mpf = dbp->mpf; + already_put = 0; if ((ret = __db_lget(dbc, 0, root_pgno, mode, 0, &lock)) != 0) return (ret); - if ((ret = memp_fget(dbp->mpf, &root_pgno, 0, &h)) != 0) - goto err; + if ((ret = mpf->get(mpf, &root_pgno, 0, &h)) != 0) { + __LPUT(dbc, lock); + return (ret); + } switch (TYPE(h)) { case P_IBTREE: for (indx = 0; indx < NUM_ENT(h); indx += O_INDX) { - bi = GET_BINTERNAL(h, indx); + bi = GET_BINTERNAL(dbp, h, indx); if (B_TYPE(bi->type) == B_OVERFLOW && (ret = __db_traverse_big(dbp, ((BOVERFLOW *)bi->data)->pgno, @@ -245,34 +243,34 @@ __bam_traverse(dbc, mode, root_pgno, callback, cookie) goto err; if ((ret = __bam_traverse( dbc, mode, bi->pgno, callback, cookie)) != 0) - break; + goto err; } break; case P_IRECNO: for (indx = 0; indx < NUM_ENT(h); indx += O_INDX) { - ri = GET_RINTERNAL(h, indx); + ri = GET_RINTERNAL(dbp, h, indx); if ((ret = __bam_traverse( dbc, mode, ri->pgno, callback, cookie)) != 0) - break; + goto err; } break; case P_LBTREE: for (indx = 0; indx < NUM_ENT(h); indx += P_INDX) { - bk = GET_BKEYDATA(h, indx); + bk = GET_BKEYDATA(dbp, h, indx); if (B_TYPE(bk->type) == B_OVERFLOW && (ret = __db_traverse_big(dbp, - GET_BOVERFLOW(h, indx)->pgno, + GET_BOVERFLOW(dbp, h, indx)->pgno, callback, cookie)) != 0) goto err; - bk = GET_BKEYDATA(h, indx + O_INDX); + bk = GET_BKEYDATA(dbp, h, indx + O_INDX); if (B_TYPE(bk->type) == B_DUPLICATE && (ret = __bam_traverse(dbc, mode, - GET_BOVERFLOW(h, indx + O_INDX)->pgno, + GET_BOVERFLOW(dbp, h, indx + O_INDX)->pgno, callback, cookie)) != 0) goto err; if (B_TYPE(bk->type) == B_OVERFLOW && (ret = __db_traverse_big(dbp, - GET_BOVERFLOW(h, indx + O_INDX)->pgno, + GET_BOVERFLOW(dbp, h, indx + O_INDX)->pgno, callback, cookie)) != 0) goto err; } @@ -280,22 +278,19 @@ __bam_traverse(dbc, mode, root_pgno, callback, cookie) case P_LDUP: case P_LRECNO: for (indx = 0; indx < NUM_ENT(h); indx += O_INDX) { - bk = GET_BKEYDATA(h, indx); + bk = GET_BKEYDATA(dbp, h, indx); if (B_TYPE(bk->type) == B_OVERFLOW && (ret = __db_traverse_big(dbp, - GET_BOVERFLOW(h, indx)->pgno, + GET_BOVERFLOW(dbp, h, indx)->pgno, callback, cookie)) != 0) goto err; } break; } - already_put = 0; - if ((ret = callback(dbp, h, cookie, &already_put)) != 0) - goto err; + ret = callback(dbp, h, cookie, &already_put); -err: if (!already_put && - (t_ret = memp_fput(dbp->mpf, h, 0)) != 0 && ret != 0) +err: if (!already_put && (t_ret = mpf->put(mpf, h, 0)) != 0 && ret != 0) ret = t_ret; __LPUT(dbc, lock); @@ -316,33 +311,34 @@ __bam_stat_callback(dbp, h, cookie, putp) int *putp; { DB_BTREE_STAT *sp; - db_indx_t indx, top; + db_indx_t indx, *inp, top; u_int8_t type; sp = cookie; *putp = 0; top = NUM_ENT(h); + inp = P_INP(dbp, h); switch (TYPE(h)) { case P_IBTREE: case P_IRECNO: ++sp->bt_int_pg; - sp->bt_int_pgfree += P_FREESPACE(h); + sp->bt_int_pgfree += P_FREESPACE(dbp, h); break; case P_LBTREE: /* Correct for on-page duplicates and deleted items. */ for (indx = 0; indx < top; indx += P_INDX) { if (indx + P_INDX >= top || - h->inp[indx] != h->inp[indx + P_INDX]) + inp[indx] != inp[indx + P_INDX]) ++sp->bt_nkeys; - type = GET_BKEYDATA(h, indx + O_INDX)->type; + type = GET_BKEYDATA(dbp, h, indx + O_INDX)->type; if (!B_DISSET(type) && B_TYPE(type) != B_DUPLICATE) ++sp->bt_ndata; } ++sp->bt_leaf_pg; - sp->bt_leaf_pgfree += P_FREESPACE(h); + sp->bt_leaf_pgfree += P_FREESPACE(dbp, h); break; case P_LRECNO: /* @@ -356,39 +352,39 @@ __bam_stat_callback(dbp, h, cookie, putp) * Correct for deleted items in non-renumbering * Recno databases. */ - if (F_ISSET(dbp, DB_RE_RENUMBER)) + if (F_ISSET(dbp, DB_AM_RENUMBER)) sp->bt_ndata += top; else for (indx = 0; indx < top; indx += O_INDX) { - type = GET_BKEYDATA(h, indx)->type; + type = GET_BKEYDATA(dbp, h, indx)->type; if (!B_DISSET(type)) ++sp->bt_ndata; } ++sp->bt_leaf_pg; - sp->bt_leaf_pgfree += P_FREESPACE(h); + sp->bt_leaf_pgfree += P_FREESPACE(dbp, h); } else { sp->bt_ndata += top; ++sp->bt_dup_pg; - sp->bt_dup_pgfree += P_FREESPACE(h); + sp->bt_dup_pgfree += P_FREESPACE(dbp, h); } break; case P_LDUP: /* Correct for deleted items. */ for (indx = 0; indx < top; indx += O_INDX) - if (!B_DISSET(GET_BKEYDATA(h, indx)->type)) + if (!B_DISSET(GET_BKEYDATA(dbp, h, indx)->type)) ++sp->bt_ndata; ++sp->bt_dup_pg; - sp->bt_dup_pgfree += P_FREESPACE(h); + sp->bt_dup_pgfree += P_FREESPACE(dbp, h); break; case P_OVERFLOW: ++sp->bt_over_pg; - sp->bt_over_pgfree += P_OVFLSPACE(dbp->pgsize, h); + sp->bt_over_pgfree += P_OVFLSPACE(dbp, dbp->pgsize, h); break; default: - return (__db_pgfmt(dbp, h->pgno)); + return (__db_pgfmt(dbp->dbenv, h->pgno)); } return (0); } @@ -421,13 +417,18 @@ __bam_key_range(dbp, txn, dbt, kp, flags) if (flags != 0) return (__db_ferr(dbp->dbenv, "DB->key_range", 0)); + /* Check for consistent transaction usage. */ + if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 1)) != 0) + return (ret); + /* Acquire a cursor. */ if ((ret = dbp->cursor(dbp, txn, &dbc, 0)) != 0) return (ret); DEBUG_LWRITE(dbc, NULL, "bam_key_range", NULL, NULL, 0); - if ((ret = __bam_search(dbc, dbt, S_STK_ONLY, 1, NULL, &exact)) != 0) + if ((ret = __bam_search(dbc, PGNO_INVALID, + dbt, S_STK_ONLY, 1, NULL, &exact)) != 0) goto err; cp = (BTREE_CURSOR *)dbc->internal; |