1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1999-2009 Oracle. All rights reserved. 5 * 6 * $Id$ 7 */ 8 9#include "db_config.h" 10 11#include "db_int.h" 12#include "dbinc/db_page.h" 13#include "dbinc/db_am.h" 14#include "dbinc/lock.h" 15#include "dbinc/mp.h" 16#include "dbinc/qam.h" 17 18#ifdef HAVE_STATISTICS 19/* 20 * __qam_stat -- 21 * Gather/print the qam statistics 22 * 23 * PUBLIC: int __qam_stat __P((DBC *, void *, u_int32_t)); 24 */ 25int 26__qam_stat(dbc, spp, flags) 27 DBC *dbc; 28 void *spp; 29 u_int32_t flags; 30{ 31 DB *dbp; 32 DB_LOCK lock; 33 DB_MPOOLFILE *mpf; 34 DB_QUEUE_STAT *sp; 35 PAGE *h; 36 QAMDATA *qp, *ep; 37 QMETA *meta; 38 QUEUE *t; 39 db_indx_t indx; 40 db_pgno_t first, last, pgno, pg_ext, stop; 41 u_int32_t re_len; 42 int ret, t_ret; 43 44 dbp = dbc->dbp; 45 46 LOCK_INIT(lock); 47 mpf = dbp->mpf; 48 sp = NULL; 49 t = dbp->q_internal; 50 51 if (spp == NULL) 52 return (0); 53 54 /* Allocate and clear the structure. */ 55 if ((ret = __os_umalloc(dbp->env, sizeof(*sp), &sp)) != 0) 56 goto err; 57 memset(sp, 0, sizeof(*sp)); 58 59 re_len = ((QUEUE *)dbp->q_internal)->re_len; 60 61 /* Determine the last page of the database. */ 62 if ((ret = __db_lget(dbc, 0, t->q_meta, DB_LOCK_READ, 0, &lock)) != 0) 63 goto err; 64 if ((ret = __memp_fget(mpf, &t->q_meta, 65 dbc->thread_info, dbc->txn, 0, &meta)) != 0) 66 goto err; 67 68 if (flags == DB_FAST_STAT) { 69 sp->qs_nkeys = meta->dbmeta.key_count; 70 sp->qs_ndata = meta->dbmeta.record_count; 71 goto meta_only; 72 } 73 74 first = QAM_RECNO_PAGE(dbp, meta->first_recno); 75 last = QAM_RECNO_PAGE(dbp, meta->cur_recno); 76 77 ret = __memp_fput(mpf, dbc->thread_info, meta, dbc->priority); 78 if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0) 79 ret = t_ret; 80 if (ret != 0) 81 goto err; 82 83 pgno = first; 84 if (first > last) 85 stop = QAM_RECNO_PAGE(dbp, UINT32_MAX); 86 else 87 stop = last; 88 89 /* Dump each page. */ 90 pg_ext = ((QUEUE *)dbp->q_internal)->page_ext; 91begin: 92 /* Walk through the pages and count. */ 93 for (; pgno <= stop; ++pgno) { 94 if ((ret = 95 __db_lget(dbc, 0, pgno, DB_LOCK_READ, 0, &lock)) != 0) 96 goto err; 97 ret = __qam_fget(dbc, &pgno, 0, &h); 98 if (ret == ENOENT) { 99 pgno += pg_ext - 1; 100 continue; 101 } 102 if (ret == DB_PAGE_NOTFOUND) { 103 if (pg_ext == 0) { 104 if (pgno != stop && first != last) 105 goto err; 106 ret = 0; 107 break; 108 } 109 pgno += (pg_ext - ((pgno - 1) % pg_ext)) - 1; 110 continue; 111 } 112 if (ret != 0) 113 goto err; 114 115 ++sp->qs_pages; 116 117 ep = (QAMDATA *)((u_int8_t *)h + dbp->pgsize - re_len); 118 for (indx = 0, qp = QAM_GET_RECORD(dbp, h, indx); 119 qp <= ep; 120 ++indx, qp = QAM_GET_RECORD(dbp, h, indx)) { 121 if (F_ISSET(qp, QAM_VALID)) 122 sp->qs_ndata++; 123 else 124 sp->qs_pgfree += re_len; 125 } 126 127 ret = __qam_fput(dbc, pgno, h, dbc->priority); 128 if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0) 129 ret = t_ret; 130 if (ret != 0) 131 goto err; 132 } 133 134 if ((ret = __LPUT(dbc, lock)) != 0) 135 goto err; 136 if (first > last) { 137 pgno = 1; 138 stop = last; 139 first = last; 140 goto begin; 141 } 142 143 /* Get the meta-data page. */ 144 if ((ret = __db_lget(dbc, 145 0, t->q_meta, F_ISSET(dbp, DB_AM_RDONLY) ? 146 DB_LOCK_READ : DB_LOCK_WRITE, 0, &lock)) != 0) 147 goto err; 148 if ((ret = __memp_fget(mpf, &t->q_meta, dbc->thread_info, dbc->txn, 149 F_ISSET(dbp, DB_AM_RDONLY) ? 0 : DB_MPOOL_DIRTY, &meta)) != 0) 150 goto err; 151 152 if (!F_ISSET(dbp, DB_AM_RDONLY)) 153 meta->dbmeta.key_count = 154 meta->dbmeta.record_count = sp->qs_ndata; 155 sp->qs_nkeys = sp->qs_ndata; 156 157meta_only: 158 /* Get the metadata fields. */ 159 sp->qs_magic = meta->dbmeta.magic; 160 sp->qs_version = meta->dbmeta.version; 161 sp->qs_metaflags = meta->dbmeta.flags; 162 sp->qs_pagesize = meta->dbmeta.pagesize; 163 sp->qs_extentsize = meta->page_ext; 164 sp->qs_re_len = meta->re_len; 165 sp->qs_re_pad = meta->re_pad; 166 sp->qs_first_recno = meta->first_recno; 167 sp->qs_cur_recno = meta->cur_recno; 168 169 /* Discard the meta-data page. */ 170 ret = __memp_fput(mpf, dbc->thread_info, meta, dbc->priority); 171 if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0) 172 ret = t_ret; 173 if (ret != 0) 174 goto err; 175 176 *(DB_QUEUE_STAT **)spp = sp; 177 178 if (0) { 179err: if (sp != NULL) 180 __os_ufree(dbp->env, sp); 181 } 182 183 if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0) 184 ret = t_ret; 185 186 return (ret); 187} 188 189/* 190 * __qam_stat_print -- 191 * Display queue statistics. 192 * 193 * PUBLIC: int __qam_stat_print __P((DBC *, u_int32_t)); 194 */ 195int 196__qam_stat_print(dbc, flags) 197 DBC *dbc; 198 u_int32_t flags; 199{ 200 DB *dbp; 201 DB_QUEUE_STAT *sp; 202 ENV *env; 203 int ret; 204 205 dbp = dbc->dbp; 206 env = dbp->env; 207 208 if ((ret = __qam_stat(dbc, &sp, LF_ISSET(DB_FAST_STAT))) != 0) 209 return (ret); 210 211 if (LF_ISSET(DB_STAT_ALL)) { 212 __db_msg(env, "%s", DB_GLOBAL(db_line)); 213 __db_msg(env, "Default Queue database information:"); 214 } 215 __db_msg(env, "%lx\tQueue magic number", (u_long)sp->qs_magic); 216 __db_msg(env, "%lu\tQueue version number", (u_long)sp->qs_version); 217 __db_dl(env, "Fixed-length record size", (u_long)sp->qs_re_len); 218 __db_msg(env, "%#x\tFixed-length record pad", (int)sp->qs_re_pad); 219 __db_dl(env, 220 "Underlying database page size", (u_long)sp->qs_pagesize); 221 __db_dl(env, 222 "Underlying database extent size", (u_long)sp->qs_extentsize); 223 __db_dl(env, 224 "Number of records in the database", (u_long)sp->qs_nkeys); 225 __db_dl(env, "Number of database pages", (u_long)sp->qs_pages); 226 __db_dl_pct(env, 227 "Number of bytes free in database pages", 228 (u_long)sp->qs_pgfree, 229 DB_PCT_PG(sp->qs_pgfree, sp->qs_pages, sp->qs_pagesize), "ff"); 230 __db_msg(env, 231 "%lu\tFirst undeleted record", (u_long)sp->qs_first_recno); 232 __db_msg(env, 233 "%lu\tNext available record number", (u_long)sp->qs_cur_recno); 234 235 __os_ufree(env, sp); 236 237 return (0); 238} 239 240#else /* !HAVE_STATISTICS */ 241 242int 243__qam_stat(dbc, spp, flags) 244 DBC *dbc; 245 void *spp; 246 u_int32_t flags; 247{ 248 COMPQUIET(spp, NULL); 249 COMPQUIET(flags, 0); 250 251 return (__db_stat_not_built(dbc->env)); 252} 253#endif 254