00001
00002
00003
00004
00005
00006
00007
00008 #include "config.h"
00009
00010 #ifndef lint
00011 static const char revid[] = "$Id: hash__stat_8c-source.html,v 1.1 2008/06/08 10:19:38 sebdiaz Exp $";
00012 #endif
00013
00014 #ifndef NO_SYSTEM_INCLUDES
00015 #include <sys/types.h>
00016
00017 #include <errno.h>
00018 #include <string.h>
00019 #endif
00020
00021 #include "db_int.h"
00022 #include "db_page.h"
00023 #include "db_shash.h"
00024 #include "btree.h"
00025 #include "hash.h"
00026 #include "lock.h"
00027
00028 static int __ham_stat_callback __P((DB *, PAGE *, void *, int *));
00029
00030
00031
00032
00033
00034
00035
00036 int
00037 CDB___ham_stat(dbp, spp, db_malloc, flags)
00038 DB *dbp;
00039 void *spp, *(*db_malloc) __P((size_t));
00040 u_int32_t flags;
00041 {
00042 DB_HASH_STAT *sp;
00043 HASH_CURSOR *hcp;
00044 DBC *dbc;
00045 PAGE *h;
00046 db_pgno_t pgno;
00047 int ret;
00048
00049 PANIC_CHECK(dbp->dbenv);
00050 DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->stat");
00051
00052 sp = NULL;
00053
00054
00055 if ((ret = CDB___db_statchk(dbp, flags)) != 0)
00056 return (ret);
00057
00058 if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0)
00059 return (ret);
00060 hcp = (HASH_CURSOR *)dbc->internal;
00061
00062 if ((ret = CDB___ham_get_meta(dbc)) != 0)
00063 goto err;
00064
00065
00066 if ((ret = CDB___os_malloc(dbp->dbenv, sizeof(*sp), db_malloc, &sp)) != 0)
00067 goto err;
00068 memset(sp, 0, sizeof(*sp));
00069 if (flags == DB_CACHED_COUNTS) {
00070 sp->hash_nkeys = hcp->hdr->dbmeta.key_count;
00071 sp->hash_ndata = hcp->hdr->dbmeta.record_count;
00072 goto done;
00073 }
00074
00075
00076 sp->hash_pagesize = dbp->pgsize;
00077 sp->hash_buckets = hcp->hdr->max_bucket + 1;
00078 sp->hash_magic = hcp->hdr->dbmeta.magic;
00079 sp->hash_version = hcp->hdr->dbmeta.version;
00080 sp->hash_metaflags = hcp->hdr->dbmeta.flags;
00081 sp->hash_nelem = hcp->hdr->nelem;
00082 sp->hash_ffactor = hcp->hdr->ffactor;
00083
00084
00085 for (sp->hash_free = 0, pgno = hcp->hdr->dbmeta.free;
00086 pgno != PGNO_INVALID;) {
00087 ++sp->hash_free;
00088
00089 if ((ret = CDB_memp_fget(dbp->mpf, &pgno, 0, &h)) != 0)
00090 goto err;
00091
00092 pgno = h->next_pgno;
00093 (void)CDB_memp_fput(dbp->mpf, h, 0);
00094 }
00095
00096
00097 if ((ret = CDB___ham_traverse(dbp,
00098 dbc, DB_LOCK_READ, __ham_stat_callback, sp)) != 0)
00099 goto err;
00100
00101 if (!F_ISSET(dbp, DB_AM_RDONLY)) {
00102 if ((ret = CDB___ham_dirty_meta(dbc)) != 0)
00103 goto err;
00104 hcp->hdr->dbmeta.key_count = sp->hash_nkeys;
00105 hcp->hdr->dbmeta.record_count = sp->hash_ndata;
00106 }
00107
00108 done:
00109 if ((ret = CDB___ham_release_meta(dbc)) != 0)
00110 goto err;
00111 if ((ret = dbc->c_close(dbc)) != 0)
00112 goto err;
00113
00114 *(DB_HASH_STAT **)spp = sp;
00115 return (0);
00116
00117 err: if (sp != NULL)
00118 CDB___os_free(sp, sizeof(*sp));
00119 if (hcp->hdr != NULL)
00120 (void)CDB___ham_release_meta(dbc);
00121 (void)dbc->c_close(dbc);
00122 return (ret);
00123
00124 }
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 int
00135 CDB___ham_traverse(dbp, dbc, mode, callback, cookie)
00136 DB *dbp;
00137 DBC *dbc;
00138 db_lockmode_t mode;
00139 int (*callback) __P((DB *, PAGE *, void *, int *));
00140 void *cookie;
00141 {
00142 HASH_CURSOR *hcp;
00143 HKEYDATA *hk;
00144 DBC *opd;
00145 db_pgno_t pgno, opgno;
00146 u_int32_t bucket;
00147 int did_put, i, ret, t_ret;
00148
00149 hcp = (HASH_CURSOR *)dbc->internal;
00150 opd = NULL;
00151 ret = 0;
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161 for (bucket = 0; bucket <= hcp->hdr->max_bucket; bucket++) {
00162 hcp->bucket = bucket;
00163 hcp->pgno = pgno = BUCKET_TO_PAGE(hcp, bucket);
00164 for (ret = CDB___ham_get_cpage(dbc, mode); ret == 0;
00165 ret = CDB___ham_next_cpage(dbc, pgno, 0)) {
00166 pgno = NEXT_PGNO(hcp->page);
00167
00168
00169
00170
00171
00172
00173
00174 for (i = 0; i < NUM_ENT(hcp->page); i++) {
00175 hk = (HKEYDATA *)P_ENTRY(hcp->page, i);
00176 switch (HPAGE_PTYPE(hk)) {
00177 case H_OFFDUP:
00178 memcpy(&opgno, HOFFDUP_PGNO(hk),
00179 sizeof(db_pgno_t));
00180 if ((ret = CDB___db_icursor(dbp, dbc->txn,
00181 dbp->dup_compare == NULL ?
00182 DB_RECNO : DB_BTREE, opgno, 1,
00183 &opd)) != 0)
00184 return (ret);
00185 if ((ret = CDB___bam_traverse(opd,
00186 DB_LOCK_READ, opgno,
00187 __ham_stat_callback, cookie))
00188 != 0)
00189 goto err;
00190 if ((ret = opd->c_close(opd)) != 0)
00191 return (ret);
00192 opd = NULL;
00193 break;
00194 case H_OFFPAGE:
00195
00196
00197
00198
00199
00200
00201
00202 memcpy(&opgno, HOFFPAGE_PGNO(hk),
00203 sizeof(db_pgno_t));
00204 if ((ret = CDB___db_traverse_big(dbp,
00205 opgno, callback, cookie)) != 0)
00206 goto err;
00207 break;
00208 case H_KEYDATA:
00209 break;
00210 }
00211 }
00212
00213
00214 if ((ret = callback(dbp,
00215 hcp->page, cookie, &did_put)) != 0)
00216 goto err;
00217
00218 if (did_put)
00219 hcp->page = NULL;
00220 if (pgno == PGNO_INVALID)
00221 break;
00222 }
00223 if (ret != 0)
00224 goto err;
00225
00226 if (STD_LOCKING(dbc))
00227 (void)CDB_lock_put(dbp->dbenv, &hcp->lock);
00228
00229 if (hcp->page != NULL) {
00230 if ((ret = CDB___ham_put_page(dbc->dbp, hcp->page, 0)) != 0)
00231 return (ret);
00232 hcp->page = NULL;
00233 }
00234
00235 }
00236 err: if (opd != NULL &&
00237 (t_ret = opd->c_close(opd)) != 0 && ret == 0)
00238 ret = t_ret;
00239 return (ret);
00240 }
00241
00242 static int
00243 __ham_stat_callback(dbp, pagep, cookie, putp)
00244 DB *dbp;
00245 PAGE *pagep;
00246 void *cookie;
00247 int *putp;
00248 {
00249 DB_HASH_STAT *sp;
00250 DB_BTREE_STAT bstat;
00251 db_indx_t indx, len, off, tlen, top;
00252 u_int8_t *hk;
00253
00254 *putp = 0;
00255 sp = cookie;
00256
00257 switch (TYPE(pagep)) {
00258 case P_INVALID:
00259
00260
00261
00262
00263 break;
00264 case P_HASH:
00265
00266
00267
00268
00269
00270
00271 if (PREV_PGNO(pagep) == PGNO_INVALID)
00272 sp->hash_bfree += P_FREESPACE(pagep);
00273 else {
00274 sp->hash_overflows++;
00275 sp->hash_ovfl_free += P_FREESPACE(pagep);
00276 }
00277 top = NUM_ENT(pagep);
00278
00279 for (indx = 0; indx < top; indx += P_INDX) {
00280 switch (*H_PAIRDATA(pagep, indx)) {
00281 case H_OFFDUP:
00282 case H_OFFPAGE:
00283 break;
00284 case H_KEYDATA:
00285 sp->hash_ndata++;
00286 break;
00287 case H_DUPLICATE:
00288 tlen = LEN_HDATA(pagep, 0, indx);
00289 hk = H_PAIRDATA(pagep, indx);
00290 for (off = 0; off < tlen;
00291 off += len + 2 * sizeof (db_indx_t)) {
00292 sp->hash_ndata++;
00293 memcpy(&len,
00294 HKEYDATA_DATA(hk)
00295 + off, sizeof(db_indx_t));
00296 }
00297 }
00298 }
00299 sp->hash_nkeys += H_NUMPAIRS(pagep);
00300 break;
00301 case P_IBTREE:
00302 case P_IRECNO:
00303 case P_LBTREE:
00304 case P_LRECNO:
00305 case P_LDUP:
00306
00307
00308
00309
00310
00311 memset(&bstat, 0, sizeof(bstat));
00312 bstat.bt_dup_pgfree = 0;
00313 bstat.bt_int_pgfree = 0;
00314 bstat.bt_leaf_pgfree = 0;
00315 bstat.bt_ndata = 0;
00316 CDB___bam_stat_callback(dbp, pagep, &bstat, putp);
00317 sp->hash_dup++;
00318 sp->hash_dup_free += bstat.bt_leaf_pgfree +
00319 bstat.bt_dup_pgfree + bstat.bt_int_pgfree;
00320 sp->hash_ndata += bstat.bt_ndata;
00321 break;
00322 case P_OVERFLOW:
00323 sp->hash_bigpages++;
00324 sp->hash_big_bfree += P_OVFLSPACE(dbp->pgsize, pagep);
00325 break;
00326 default:
00327 return (CDB___db_unknown_type(dbp->dbenv,
00328 "__ham_stat_callback", TYPE(pagep)));
00329 }
00330
00331 return (0);
00332 }