#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 $" |
|
||||||||||||||||||||||||
|
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 }
|
|
||||||||||||||||
|
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 }
|
|
||||||||||||||||||||
|
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 }
|
|
||||||||||||||||||||||||
|
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 }
|
|
|
|
1.4.3