bt_stat.c File Reference

#include "db_config.h"
#include <sys/types.h>
#include <string.h>
#include "db_int.h"
#include "dbinc/db_page.h"
#include "dbinc/db_shash.h"
#include "dbinc/btree.h"
#include "dbinc/lock.h"
#include "dbinc/log.h"

Go to the source code of this file.

Functions

int __bam_key_range (DB *dbp, DB_TXN *txn, DBT *dbt, DB_KEY_RANGE *kp, u_int32_t flags)
int __bam_stat (DB *dbp, void *spp, u_int32_t flags)
int __bam_stat_callback (DB *dbp, PAGE *h, void *cookie, int *putp)
int __bam_traverse (DBC *dbc, db_lockmode_t mode, db_pgno_t root_pgno, int *callback, void *cookie)

Variables

static const char revid [] = "$Id: bt_stat.c,v 11.52 2002/05/30 15:40:27 krinsky Exp $"


Function Documentation

int __bam_key_range DB dbp,
DB_TXN txn,
DBT dbt,
DB_KEY_RANGE kp,
u_int32_t  flags
 

Definition at line 401 of file bt_stat.c.

References __bam_search(), __db_check_txn(), __db_ferr(), BT_STK_CLR, __cursor::csp, DB_ILLEGAL_BEFORE_OPEN, DB_LOCK_INVALIDID, dbc, DEBUG_LWRITE, __key_range::equal, err, __key_range::greater, __dbc::internal, __key_range::less, NULL, PANIC_CHECK, PGNO_INVALID, S_STK_ONLY, and __cursor::sp.

Referenced by __bam_open().

00407 {
00408         BTREE_CURSOR *cp;
00409         DBC *dbc;
00410         EPG *sp;
00411         double factor;
00412         int exact, ret, t_ret;
00413 
00414         PANIC_CHECK(dbp->dbenv);
00415         DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->key_range");
00416 
00417         if (flags != 0)
00418                 return (__db_ferr(dbp->dbenv, "DB->key_range", 0));
00419 
00420         /* Check for consistent transaction usage. */
00421         if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 1)) != 0)
00422                 return (ret);
00423 
00424         /* Acquire a cursor. */
00425         if ((ret = dbp->cursor(dbp, txn, &dbc, 0)) != 0)
00426                 return (ret);
00427 
00428         DEBUG_LWRITE(dbc, NULL, "bam_key_range", NULL, NULL, 0);
00429 
00430         if ((ret = __bam_search(dbc, PGNO_INVALID,
00431             dbt, S_STK_ONLY, 1, NULL, &exact)) != 0)
00432                 goto err;
00433 
00434         cp = (BTREE_CURSOR *)dbc->internal;
00435         kp->less = kp->greater = 0.0;
00436 
00437         factor = 1.0;
00438         /* Correct the leaf page. */
00439         cp->csp->entries /= 2;
00440         cp->csp->indx /= 2;
00441         for (sp = cp->sp; sp <= cp->csp; ++sp) {
00442                 /*
00443                  * At each level we know that pages greater than indx contain
00444                  * keys greater than what we are looking for and those less
00445                  * than indx are less than.  The one pointed to by indx may
00446                  * have some less, some greater or even equal.  If indx is
00447                  * equal to the number of entries, then the key is out of range
00448                  * and everything is less.
00449                  */
00450                 if (sp->indx == 0)
00451                         kp->greater += factor * (sp->entries - 1)/sp->entries;
00452                 else if (sp->indx == sp->entries)
00453                         kp->less += factor;
00454                 else {
00455                         kp->less += factor * sp->indx / sp->entries;
00456                         kp->greater += factor *
00457                             (sp->entries - sp->indx - 1) / sp->entries;
00458                 }
00459                 factor *= 1.0/sp->entries;
00460         }
00461 
00462         /*
00463          * If there was an exact match then assign 1 n'th to the key itself.
00464          * Otherwise that factor belongs to those greater than the key, unless
00465          * the key was out of range.
00466          */
00467         if (exact)
00468                 kp->equal = factor;
00469         else {
00470                 if (kp->less != 1)
00471                         kp->greater += factor;
00472                 kp->equal = 0;
00473         }
00474 
00475         BT_STK_CLR(cp);
00476 
00477 err:    if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
00478                 ret = t_ret;
00479 
00480         return (ret);
00481 }

int __bam_stat DB dbp,
void *  spp,
u_int32_t  flags
 

Definition at line 34 of file bt_stat.c.

References __bam_stat_callback(), __bam_traverse(), __db_lget(), __db_statchk(), __LPUT, __os_ufree(), __os_umalloc(), DB_AM_RDONLY, DB_AM_RECNUM, DB_BTREE, DB_CACHED_COUNTS, DB_FAST_STAT, DB_ILLEGAL_BEFORE_OPEN, DB_LOCK_READ, DB_LOCK_WRITE, DB_MPOOL_DIRTY, DB_RECNO, DB_RECORDCOUNT, dbc, DEBUG_LWRITE, err, F_ISSET, h, __dbc::internal, _db_page::level, lock, LOCK_INIT, memset, mpf, _db_page::next_pgno, NULL, PANIC_CHECK, PGNO_BASE_MD, PGNO_INVALID, and RE_NREC.

Referenced by __bam_open(), and __ram_open().

00038 {
00039         BTMETA *meta;
00040         BTREE *t;
00041         BTREE_CURSOR *cp;
00042         DBC *dbc;
00043         DB_BTREE_STAT *sp;
00044         DB_LOCK lock, metalock;
00045         DB_MPOOLFILE *mpf;
00046         PAGE *h;
00047         db_pgno_t pgno;
00048         int ret, t_ret, write_meta;
00049 
00050         PANIC_CHECK(dbp->dbenv);
00051         DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->stat");
00052 
00053         meta = NULL;
00054         t = dbp->bt_internal;
00055         sp = NULL;
00056         LOCK_INIT(metalock);
00057         LOCK_INIT(lock);
00058         mpf = dbp->mpf;
00059         h = NULL;
00060         ret = 0;
00061         write_meta = 0;
00062 
00063         /* Check for invalid flags. */
00064         if ((ret = __db_statchk(dbp, flags)) != 0)
00065                 return (ret);
00066 
00067         /* Acquire a cursor. */
00068         if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0)
00069                 return (ret);
00070         cp = (BTREE_CURSOR *)dbc->internal;
00071 
00072         DEBUG_LWRITE(dbc, NULL, "bam_stat", NULL, NULL, flags);
00073 
00074         /* Allocate and clear the structure. */
00075         if ((ret = __os_umalloc(dbp->dbenv, sizeof(*sp), &sp)) != 0)
00076                 goto err;
00077         memset(sp, 0, sizeof(*sp));
00078 
00079         /* Get the metadata page for the entire database. */
00080         pgno = PGNO_BASE_MD;
00081         if ((ret = __db_lget(dbc, 0, pgno, DB_LOCK_READ, 0, &metalock)) != 0)
00082                 goto err;
00083         if ((ret = mpf->get(mpf, &pgno, 0, (PAGE **)&meta)) != 0)
00084                 goto err;
00085 
00086         if (flags == DB_RECORDCOUNT || flags == DB_CACHED_COUNTS)
00087                 flags = DB_FAST_STAT;
00088         if (flags == DB_FAST_STAT)
00089                 goto meta_only;
00090 
00091         /* Walk the metadata free list, counting pages. */
00092         for (sp->bt_free = 0, pgno = meta->dbmeta.free; pgno != PGNO_INVALID;) {
00093                 ++sp->bt_free;
00094 
00095                 if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
00096                         goto err;
00097 
00098                 pgno = h->next_pgno;
00099                 if ((ret = mpf->put(mpf, h, 0)) != 0)
00100                         goto err;
00101                 h = NULL;
00102         }
00103 
00104         /* Get the root page. */
00105         pgno = cp->root;
00106         if ((ret = __db_lget(dbc, 0, pgno, DB_LOCK_READ, 0, &lock)) != 0)
00107                 goto err;
00108         if ((ret = mpf->get(mpf, &pgno, 0, &h)) != 0)
00109                 goto err;
00110 
00111         /* Get the levels from the root page. */
00112         sp->bt_levels = h->level;
00113 
00114         /* Discard the root page. */
00115         if ((ret = mpf->put(mpf, h, 0)) != 0)
00116                 goto err;
00117         h = NULL;
00118         __LPUT(dbc, lock);
00119 
00120         /* Walk the tree. */
00121         if ((ret = __bam_traverse(dbc,
00122             DB_LOCK_READ, cp->root, __bam_stat_callback, sp)) != 0)
00123                 goto err;
00124 
00125         /*
00126          * Get the subdatabase metadata page if it's not the same as the
00127          * one we already have.
00128          */
00129         write_meta = !F_ISSET(dbp, DB_AM_RDONLY);
00130 meta_only:
00131         if (t->bt_meta != PGNO_BASE_MD || write_meta != 0) {
00132                 if ((ret = mpf->put(mpf, meta, 0)) != 0)
00133                         goto err;
00134                 meta = NULL;
00135                 __LPUT(dbc, metalock);
00136 
00137                 if ((ret = __db_lget(dbc,
00138                     0, t->bt_meta, write_meta == 0 ?
00139                     DB_LOCK_READ : DB_LOCK_WRITE, 0, &metalock)) != 0)
00140                         goto err;
00141                 if ((ret = mpf->get(mpf, &t->bt_meta, 0, (PAGE **)&meta)) != 0)
00142                         goto err;
00143         }
00144         if (flags == DB_FAST_STAT) {
00145                 if (dbp->type == DB_RECNO ||
00146                     (dbp->type == DB_BTREE && F_ISSET(dbp, DB_AM_RECNUM))) {
00147                         if ((ret = __db_lget(dbc, 0,
00148                             cp->root, DB_LOCK_READ, 0, &lock)) != 0)
00149                                 goto err;
00150                         if ((ret =
00151                             mpf->get(mpf, &cp->root, 0, (PAGE **)&h)) != 0)
00152                                 goto err;
00153 
00154                         sp->bt_nkeys = RE_NREC(h);
00155                 } else
00156                         sp->bt_nkeys = meta->dbmeta.key_count;
00157                 sp->bt_ndata = meta->dbmeta.record_count;
00158         }
00159 
00160         /* Get metadata page statistics. */
00161         sp->bt_metaflags = meta->dbmeta.flags;
00162         sp->bt_maxkey = meta->maxkey;
00163         sp->bt_minkey = meta->minkey;
00164         sp->bt_re_len = meta->re_len;
00165         sp->bt_re_pad = meta->re_pad;
00166         sp->bt_pagesize = meta->dbmeta.pagesize;
00167         sp->bt_magic = meta->dbmeta.magic;
00168         sp->bt_version = meta->dbmeta.version;
00169 
00170         if (write_meta != 0) {
00171                 meta->dbmeta.key_count = sp->bt_nkeys;
00172                 meta->dbmeta.record_count = sp->bt_ndata;
00173         }
00174 
00175         *(DB_BTREE_STAT **)spp = sp;
00176 
00177 err:    /* Discard the second page. */
00178         __LPUT(dbc, lock);
00179         if (h != NULL && (t_ret = mpf->put(mpf, h, 0)) != 0 && ret == 0)
00180                 ret = t_ret;
00181 
00182         /* Discard the metadata page. */
00183         __LPUT(dbc, metalock);
00184         if (meta != NULL && (t_ret = mpf->put(
00185             mpf, meta, write_meta == 0 ? 0 : DB_MPOOL_DIRTY)) != 0 && ret == 0)
00186                 ret = t_ret;
00187 
00188         if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
00189                 ret = t_ret;
00190 
00191         if (ret != 0 && sp != NULL) {
00192                 __os_ufree(dbp->dbenv, sp);
00193                 *(DB_BTREE_STAT **)spp = NULL;
00194         }
00195 
00196         return (ret);
00197 }

int __bam_stat_callback DB dbp,
PAGE h,
void *  cookie,
int *  putp
 

Definition at line 307 of file bt_stat.c.

References __db_pgfmt(), B_DISSET, B_DUPLICATE, B_TYPE, __db_bt_stat::bt_dup_pg, __db_bt_stat::bt_dup_pgfree, __db_bt_stat::bt_int_pg, __db_bt_stat::bt_int_pgfree, __db_bt_stat::bt_leaf_pg, __db_bt_stat::bt_leaf_pgfree, __db_bt_stat::bt_ndata, __db_bt_stat::bt_nkeys, __db_bt_stat::bt_over_pg, __db_bt_stat::bt_over_pgfree, DB_AM_RENUMBER, DB_RECNO, F_ISSET, GET_BKEYDATA, NUM_ENT, O_INDX, P_FREESPACE, P_IBTREE, P_INDX, P_INP, P_IRECNO, P_LBTREE, P_LDUP, P_LRECNO, P_OVERFLOW, P_OVFLSPACE, _db_page::pgno, top, TYPE, and ndb_logevent::type.

Referenced by __bam_stat(), and __ham_stat_callback().

00312 {
00313         DB_BTREE_STAT *sp;
00314         db_indx_t indx, *inp, top;
00315         u_int8_t type;
00316 
00317         sp = cookie;
00318         *putp = 0;
00319         top = NUM_ENT(h);
00320         inp = P_INP(dbp, h);
00321 
00322         switch (TYPE(h)) {
00323         case P_IBTREE:
00324         case P_IRECNO:
00325                 ++sp->bt_int_pg;
00326                 sp->bt_int_pgfree += P_FREESPACE(dbp, h);
00327                 break;
00328         case P_LBTREE:
00329                 /* Correct for on-page duplicates and deleted items. */
00330                 for (indx = 0; indx < top; indx += P_INDX) {
00331                         if (indx + P_INDX >= top ||
00332                             inp[indx] != inp[indx + P_INDX])
00333                                 ++sp->bt_nkeys;
00334 
00335                         type = GET_BKEYDATA(dbp, h, indx + O_INDX)->type;
00336                         if (!B_DISSET(type) && B_TYPE(type) != B_DUPLICATE)
00337                                 ++sp->bt_ndata;
00338                 }
00339 
00340                 ++sp->bt_leaf_pg;
00341                 sp->bt_leaf_pgfree += P_FREESPACE(dbp, h);
00342                 break;
00343         case P_LRECNO:
00344                 /*
00345                  * If walking a recno tree, then each of these items is a key.
00346                  * Otherwise, we're walking an off-page duplicate set.
00347                  */
00348                 if (dbp->type == DB_RECNO) {
00349                         sp->bt_nkeys += top;
00350 
00351                         /*
00352                          * Correct for deleted items in non-renumbering
00353                          * Recno databases.
00354                          */
00355                         if (F_ISSET(dbp, DB_AM_RENUMBER))
00356                                 sp->bt_ndata += top;
00357                         else
00358                                 for (indx = 0; indx < top; indx += O_INDX) {
00359                                         type = GET_BKEYDATA(dbp, h, indx)->type;
00360                                         if (!B_DISSET(type))
00361                                                 ++sp->bt_ndata;
00362                                 }
00363 
00364                         ++sp->bt_leaf_pg;
00365                         sp->bt_leaf_pgfree += P_FREESPACE(dbp, h);
00366                 } else {
00367                         sp->bt_ndata += top;
00368 
00369                         ++sp->bt_dup_pg;
00370                         sp->bt_dup_pgfree += P_FREESPACE(dbp, h);
00371                 }
00372                 break;
00373         case P_LDUP:
00374                 /* Correct for deleted items. */
00375                 for (indx = 0; indx < top; indx += O_INDX)
00376                         if (!B_DISSET(GET_BKEYDATA(dbp, h, indx)->type))
00377                                 ++sp->bt_ndata;
00378 
00379                 ++sp->bt_dup_pg;
00380                 sp->bt_dup_pgfree += P_FREESPACE(dbp, h);
00381                 break;
00382         case P_OVERFLOW:
00383                 ++sp->bt_over_pg;
00384                 sp->bt_over_pgfree += P_OVFLSPACE(dbp, dbp->pgsize, h);
00385                 break;
00386         default:
00387                 return (__db_pgfmt(dbp->dbenv, h->pgno));
00388         }
00389         return (0);
00390 }

int __bam_traverse DBC dbc,
db_lockmode_t  mode,
db_pgno_t  root_pgno,
int *  callback,
void *  cookie
 

Definition at line 207 of file bt_stat.c.

References __db_lget(), __db_traverse_big(), __LPUT, B_DUPLICATE, B_OVERFLOW, B_TYPE, callback(), _binternal::data, dbp, err, GET_BINTERNAL, GET_BKEYDATA, GET_BOVERFLOW, GET_RINTERNAL, h, lock, __db::mpf, mpf, NUM_ENT, O_INDX, P_IBTREE, P_INDX, P_IRECNO, P_LBTREE, P_LDUP, P_LRECNO, _rinternal::pgno, _binternal::pgno, _bkeydata::type, _binternal::type, and TYPE.

Referenced by __bam_reclaim(), __bam_stat(), __bam_truncate(), and __ham_traverse().

00213 {
00214         BINTERNAL *bi;
00215         BKEYDATA *bk;
00216         DB *dbp;
00217         DB_LOCK lock;
00218         DB_MPOOLFILE *mpf;
00219         PAGE *h;
00220         RINTERNAL *ri;
00221         db_indx_t indx;
00222         int already_put, ret, t_ret;
00223 
00224         dbp = dbc->dbp;
00225         mpf = dbp->mpf;
00226         already_put = 0;
00227 
00228         if ((ret = __db_lget(dbc, 0, root_pgno, mode, 0, &lock)) != 0)
00229                 return (ret);
00230         if ((ret = mpf->get(mpf, &root_pgno, 0, &h)) != 0) {
00231                 __LPUT(dbc, lock);
00232                 return (ret);
00233         }
00234 
00235         switch (TYPE(h)) {
00236         case P_IBTREE:
00237                 for (indx = 0; indx < NUM_ENT(h); indx += O_INDX) {
00238                         bi = GET_BINTERNAL(dbp, h, indx);
00239                         if (B_TYPE(bi->type) == B_OVERFLOW &&
00240                             (ret = __db_traverse_big(dbp,
00241                             ((BOVERFLOW *)bi->data)->pgno,
00242                             callback, cookie)) != 0)
00243                                 goto err;
00244                         if ((ret = __bam_traverse(
00245                             dbc, mode, bi->pgno, callback, cookie)) != 0)
00246                                 goto err;
00247                 }
00248                 break;
00249         case P_IRECNO:
00250                 for (indx = 0; indx < NUM_ENT(h); indx += O_INDX) {
00251                         ri = GET_RINTERNAL(dbp, h, indx);
00252                         if ((ret = __bam_traverse(
00253                             dbc, mode, ri->pgno, callback, cookie)) != 0)
00254                                 goto err;
00255                 }
00256                 break;
00257         case P_LBTREE:
00258                 for (indx = 0; indx < NUM_ENT(h); indx += P_INDX) {
00259                         bk = GET_BKEYDATA(dbp, h, indx);
00260                         if (B_TYPE(bk->type) == B_OVERFLOW &&
00261                             (ret = __db_traverse_big(dbp,
00262                             GET_BOVERFLOW(dbp, h, indx)->pgno,
00263                             callback, cookie)) != 0)
00264                                 goto err;
00265                         bk = GET_BKEYDATA(dbp, h, indx + O_INDX);
00266                         if (B_TYPE(bk->type) == B_DUPLICATE &&
00267                             (ret = __bam_traverse(dbc, mode,
00268                             GET_BOVERFLOW(dbp, h, indx + O_INDX)->pgno,
00269                             callback, cookie)) != 0)
00270                                 goto err;
00271                         if (B_TYPE(bk->type) == B_OVERFLOW &&
00272                             (ret = __db_traverse_big(dbp,
00273                             GET_BOVERFLOW(dbp, h, indx + O_INDX)->pgno,
00274                             callback, cookie)) != 0)
00275                                 goto err;
00276                 }
00277                 break;
00278         case P_LDUP:
00279         case P_LRECNO:
00280                 for (indx = 0; indx < NUM_ENT(h); indx += O_INDX) {
00281                         bk = GET_BKEYDATA(dbp, h, indx);
00282                         if (B_TYPE(bk->type) == B_OVERFLOW &&
00283                             (ret = __db_traverse_big(dbp,
00284                             GET_BOVERFLOW(dbp, h, indx)->pgno,
00285                             callback, cookie)) != 0)
00286                                 goto err;
00287                 }
00288                 break;
00289         }
00290 
00291         ret = callback(dbp, h, cookie, &already_put);
00292 
00293 err:    if (!already_put && (t_ret = mpf->put(mpf, h, 0)) != 0 && ret != 0)
00294                 ret = t_ret;
00295         __LPUT(dbc, lock);
00296 
00297         return (ret);
00298 }


Variable Documentation

const char revid[] = "$Id: bt_stat.c,v 11.52 2002/05/30 15:40:27 krinsky Exp $" [static]
 

Definition at line 11 of file bt_stat.c.


Generated on Wed Jul 20 21:06:35 2005 for MySQL 5.0.9 Beta by  doxygen 1.4.3