1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1996-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/btree.h" 14#include "dbinc/hash.h" 15#include "dbinc/qam.h" 16#include "dbinc/lock.h" 17#include "dbinc/log.h" 18#include "dbinc/mp.h" 19#include "dbinc/partition.h" 20 21#ifdef HAVE_STATISTICS 22static int __db_print_all __P((DB *, u_int32_t)); 23static int __db_print_citem __P((DBC *)); 24static int __db_print_cursor __P((DB *)); 25static int __db_print_stats __P((DB *, DB_THREAD_INFO *, u_int32_t)); 26static int __db_stat __P((DB *, DB_THREAD_INFO *, DB_TXN *, void *, u_int32_t)); 27static int __db_stat_arg __P((DB *, u_int32_t)); 28 29/* 30 * __db_stat_pp -- 31 * DB->stat pre/post processing. 32 * 33 * PUBLIC: int __db_stat_pp __P((DB *, DB_TXN *, void *, u_int32_t)); 34 */ 35int 36__db_stat_pp(dbp, txn, spp, flags) 37 DB *dbp; 38 DB_TXN *txn; 39 void *spp; 40 u_int32_t flags; 41{ 42 DB_THREAD_INFO *ip; 43 ENV *env; 44 int handle_check, ret, t_ret; 45 46 env = dbp->env; 47 48 DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->stat"); 49 50 if ((ret = __db_stat_arg(dbp, flags)) != 0) 51 return (ret); 52 53 ENV_ENTER(env, ip); 54 55 /* Check for replication block. */ 56 handle_check = IS_ENV_REPLICATED(env); 57 if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, 58 txn != NULL)) != 0) { 59 handle_check = 0; 60 goto err; 61 } 62 63 ret = __db_stat(dbp, ip, txn, spp, flags); 64 65 /* Release replication block. */ 66 if (handle_check && (t_ret = __env_db_rep_exit(env)) != 0 && ret == 0) 67 ret = t_ret; 68 69err: ENV_LEAVE(env, ip); 70 return (ret); 71} 72 73/* 74 * __db_stat -- 75 * DB->stat. 76 * 77 */ 78static int 79__db_stat(dbp, ip, txn, spp, flags) 80 DB *dbp; 81 DB_THREAD_INFO *ip; 82 DB_TXN *txn; 83 void *spp; 84 u_int32_t flags; 85{ 86 DBC *dbc; 87 ENV *env; 88 int ret, t_ret; 89 90 env = dbp->env; 91 92 /* Acquire a cursor. */ 93 if ((ret = __db_cursor(dbp, ip, txn, 94 &dbc, LF_ISSET(DB_READ_COMMITTED | DB_READ_UNCOMMITTED))) != 0) 95 return (ret); 96 97 DEBUG_LWRITE(dbc, NULL, "DB->stat", NULL, NULL, flags); 98 LF_CLR(DB_READ_COMMITTED | DB_READ_UNCOMMITTED); 99#ifdef HAVE_PARTITION 100 if (DB_IS_PARTITIONED(dbp)) 101 ret = __partition_stat(dbc, spp, flags); 102 else 103#endif 104 switch (dbp->type) { 105 case DB_BTREE: 106 case DB_RECNO: 107 ret = __bam_stat(dbc, spp, flags); 108 break; 109 case DB_HASH: 110 ret = __ham_stat(dbc, spp, flags); 111 break; 112 case DB_QUEUE: 113 ret = __qam_stat(dbc, spp, flags); 114 break; 115 case DB_UNKNOWN: 116 default: 117 ret = (__db_unknown_type(env, "DB->stat", dbp->type)); 118 break; 119 } 120 121 if ((t_ret = __dbc_close(dbc)) != 0 && ret == 0) 122 ret = t_ret; 123 124 return (ret); 125} 126 127/* 128 * __db_stat_arg -- 129 * Check DB->stat arguments. 130 */ 131static int 132__db_stat_arg(dbp, flags) 133 DB *dbp; 134 u_int32_t flags; 135{ 136 ENV *env; 137 138 env = dbp->env; 139 140 /* Check for invalid function flags. */ 141 LF_CLR(DB_READ_COMMITTED | DB_READ_UNCOMMITTED); 142 switch (flags) { 143 case 0: 144 case DB_FAST_STAT: 145 break; 146 default: 147 return (__db_ferr(env, "DB->stat", 0)); 148 } 149 150 return (0); 151} 152 153/* 154 * __db_stat_print_pp -- 155 * DB->stat_print pre/post processing. 156 * 157 * PUBLIC: int __db_stat_print_pp __P((DB *, u_int32_t)); 158 */ 159int 160__db_stat_print_pp(dbp, flags) 161 DB *dbp; 162 u_int32_t flags; 163{ 164 DB_THREAD_INFO *ip; 165 ENV *env; 166 int handle_check, ret, t_ret; 167 168 env = dbp->env; 169 170 DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->stat_print"); 171 172 /* 173 * !!! 174 * The actual argument checking is simple, do it inline. 175 */ 176 if ((ret = __db_fchk(env, 177 "DB->stat_print", flags, DB_FAST_STAT | DB_STAT_ALL)) != 0) 178 return (ret); 179 180 ENV_ENTER(env, ip); 181 182 /* Check for replication block. */ 183 handle_check = IS_ENV_REPLICATED(env); 184 if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, 0)) != 0) { 185 handle_check = 0; 186 goto err; 187 } 188 189 ret = __db_stat_print(dbp, ip, flags); 190 191 /* Release replication block. */ 192 if (handle_check && (t_ret = __env_db_rep_exit(env)) != 0 && ret == 0) 193 ret = t_ret; 194 195err: ENV_LEAVE(env, ip); 196 return (ret); 197} 198 199/* 200 * __db_stat_print -- 201 * DB->stat_print. 202 * 203 * PUBLIC: int __db_stat_print __P((DB *, DB_THREAD_INFO *, u_int32_t)); 204 */ 205int 206__db_stat_print(dbp, ip, flags) 207 DB *dbp; 208 DB_THREAD_INFO *ip; 209 u_int32_t flags; 210{ 211 time_t now; 212 int ret; 213 char time_buf[CTIME_BUFLEN]; 214 215 (void)time(&now); 216 __db_msg(dbp->env, "%.24s\tLocal time", __os_ctime(&now, time_buf)); 217 218 if (LF_ISSET(DB_STAT_ALL) && (ret = __db_print_all(dbp, flags)) != 0) 219 return (ret); 220 221 if ((ret = __db_print_stats(dbp, ip, flags)) != 0) 222 return (ret); 223 224 return (0); 225} 226 227/* 228 * __db_print_stats -- 229 * Display default DB handle statistics. 230 */ 231static int 232__db_print_stats(dbp, ip, flags) 233 DB *dbp; 234 DB_THREAD_INFO *ip; 235 u_int32_t flags; 236{ 237 DBC *dbc; 238 ENV *env; 239 int ret, t_ret; 240 241 env = dbp->env; 242 243 /* Acquire a cursor. */ 244 if ((ret = __db_cursor(dbp, ip, NULL, &dbc, 0)) != 0) 245 return (ret); 246 247 DEBUG_LWRITE(dbc, NULL, "DB->stat_print", NULL, NULL, 0); 248 249 switch (dbp->type) { 250 case DB_BTREE: 251 case DB_RECNO: 252 ret = __bam_stat_print(dbc, flags); 253 break; 254 case DB_HASH: 255 ret = __ham_stat_print(dbc, flags); 256 break; 257 case DB_QUEUE: 258 ret = __qam_stat_print(dbc, flags); 259 break; 260 case DB_UNKNOWN: 261 default: 262 ret = (__db_unknown_type(env, "DB->stat_print", dbp->type)); 263 break; 264 } 265 266 if ((t_ret = __dbc_close(dbc)) != 0 && ret == 0) 267 ret = t_ret; 268 269 return (ret); 270} 271 272/* 273 * __db_print_all -- 274 * Display debugging DB handle statistics. 275 */ 276static int 277__db_print_all(dbp, flags) 278 DB *dbp; 279 u_int32_t flags; 280{ 281 static const FN fn[] = { 282 { DB_AM_CHKSUM, "DB_AM_CHKSUM" }, 283 { DB_AM_COMPENSATE, "DB_AM_COMPENSATE" }, 284 { DB_AM_CREATED, "DB_AM_CREATED" }, 285 { DB_AM_CREATED_MSTR, "DB_AM_CREATED_MSTR" }, 286 { DB_AM_DBM_ERROR, "DB_AM_DBM_ERROR" }, 287 { DB_AM_DELIMITER, "DB_AM_DELIMITER" }, 288 { DB_AM_DISCARD, "DB_AM_DISCARD" }, 289 { DB_AM_DUP, "DB_AM_DUP" }, 290 { DB_AM_DUPSORT, "DB_AM_DUPSORT" }, 291 { DB_AM_ENCRYPT, "DB_AM_ENCRYPT" }, 292 { DB_AM_FIXEDLEN, "DB_AM_FIXEDLEN" }, 293 { DB_AM_INMEM, "DB_AM_INMEM" }, 294 { DB_AM_IN_RENAME, "DB_AM_IN_RENAME" }, 295 { DB_AM_NOT_DURABLE, "DB_AM_NOT_DURABLE" }, 296 { DB_AM_OPEN_CALLED, "DB_AM_OPEN_CALLED" }, 297 { DB_AM_PAD, "DB_AM_PAD" }, 298 { DB_AM_PGDEF, "DB_AM_PGDEF" }, 299 { DB_AM_RDONLY, "DB_AM_RDONLY" }, 300 { DB_AM_READ_UNCOMMITTED, "DB_AM_READ_UNCOMMITTED" }, 301 { DB_AM_RECNUM, "DB_AM_RECNUM" }, 302 { DB_AM_RECOVER, "DB_AM_RECOVER" }, 303 { DB_AM_RENUMBER, "DB_AM_RENUMBER" }, 304 { DB_AM_REVSPLITOFF, "DB_AM_REVSPLITOFF" }, 305 { DB_AM_SECONDARY, "DB_AM_SECONDARY" }, 306 { DB_AM_SNAPSHOT, "DB_AM_SNAPSHOT" }, 307 { DB_AM_SUBDB, "DB_AM_SUBDB" }, 308 { DB_AM_SWAP, "DB_AM_SWAP" }, 309 { DB_AM_TXN, "DB_AM_TXN" }, 310 { DB_AM_VERIFYING, "DB_AM_VERIFYING" }, 311 { 0, NULL } 312 }; 313 ENV *env; 314 char time_buf[CTIME_BUFLEN]; 315 316 env = dbp->env; 317 318 __db_msg(env, "%s", DB_GLOBAL(db_line)); 319 __db_msg(env, "DB handle information:"); 320 STAT_ULONG("Page size", dbp->pgsize); 321 STAT_ISSET("Append recno", dbp->db_append_recno); 322 STAT_ISSET("Feedback", dbp->db_feedback); 323 STAT_ISSET("Dup compare", dbp->dup_compare); 324 STAT_ISSET("App private", dbp->app_private); 325 STAT_ISSET("DbEnv", dbp->env); 326 STAT_STRING("Type", __db_dbtype_to_string(dbp->type)); 327 328 __mutex_print_debug_single(env, "Thread mutex", dbp->mutex, flags); 329 330 STAT_STRING("File", dbp->fname); 331 STAT_STRING("Database", dbp->dname); 332 STAT_HEX("Open flags", dbp->open_flags); 333 334 __db_print_fileid(env, dbp->fileid, "\tFile ID"); 335 336 STAT_ULONG("Cursor adjust ID", dbp->adj_fileid); 337 STAT_ULONG("Meta pgno", dbp->meta_pgno); 338 if (dbp->locker != NULL) 339 STAT_ULONG("Locker ID", dbp->locker->id); 340 if (dbp->cur_locker != NULL) 341 STAT_ULONG("Handle lock", dbp->cur_locker->id); 342 if (dbp->associate_locker != NULL) 343 STAT_ULONG("Associate lock", dbp->associate_locker->id); 344 STAT_ULONG("RPC remote ID", dbp->cl_id); 345 346 __db_msg(env, 347 "%.24s\tReplication handle timestamp", 348 dbp->timestamp == 0 ? "0" : __os_ctime(&dbp->timestamp, time_buf)); 349 350 STAT_ISSET("Secondary callback", dbp->s_callback); 351 STAT_ISSET("Primary handle", dbp->s_primary); 352 353 STAT_ISSET("api internal", dbp->api_internal); 354 STAT_ISSET("Btree/Recno internal", dbp->bt_internal); 355 STAT_ISSET("Hash internal", dbp->h_internal); 356 STAT_ISSET("Queue internal", dbp->q_internal); 357 358 __db_prflags(env, NULL, dbp->flags, fn, NULL, "\tFlags"); 359 360 if (dbp->log_filename == NULL) 361 STAT_ISSET("File naming information", dbp->log_filename); 362 else 363 __dbreg_print_fname(env, dbp->log_filename); 364 365 (void)__db_print_cursor(dbp); 366 367 return (0); 368} 369 370/* 371 * __db_print_cursor -- 372 * Display the cursor active and free queues. 373 */ 374static int 375__db_print_cursor(dbp) 376 DB *dbp; 377{ 378 DBC *dbc; 379 ENV *env; 380 int ret, t_ret; 381 382 env = dbp->env; 383 384 __db_msg(env, "%s", DB_GLOBAL(db_line)); 385 __db_msg(env, "DB handle cursors:"); 386 387 ret = 0; 388 MUTEX_LOCK(dbp->env, dbp->mutex); 389 __db_msg(env, "Active queue:"); 390 TAILQ_FOREACH(dbc, &dbp->active_queue, links) 391 if ((t_ret = __db_print_citem(dbc)) != 0 && ret == 0) 392 ret = t_ret; 393 __db_msg(env, "Join queue:"); 394 TAILQ_FOREACH(dbc, &dbp->join_queue, links) 395 if ((t_ret = __db_print_citem(dbc)) != 0 && ret == 0) 396 ret = t_ret; 397 __db_msg(env, "Free queue:"); 398 TAILQ_FOREACH(dbc, &dbp->free_queue, links) 399 if ((t_ret = __db_print_citem(dbc)) != 0 && ret == 0) 400 ret = t_ret; 401 MUTEX_UNLOCK(dbp->env, dbp->mutex); 402 403 return (ret); 404} 405 406static int 407__db_print_citem(dbc) 408 DBC *dbc; 409{ 410 static const FN fn[] = { 411 { DBC_ACTIVE, "DBC_ACTIVE" }, 412 { DBC_DONTLOCK, "DBC_DONTLOCK" }, 413 { DBC_MULTIPLE, "DBC_MULTIPLE" }, 414 { DBC_MULTIPLE_KEY, "DBC_MULTIPLE_KEY" }, 415 { DBC_OPD, "DBC_OPD" }, 416 { DBC_OWN_LID, "DBC_OWN_LID" }, 417 { DBC_READ_COMMITTED, "DBC_READ_COMMITTED" }, 418 { DBC_READ_UNCOMMITTED, "DBC_READ_UNCOMMITTED" }, 419 { DBC_RECOVER, "DBC_RECOVER" }, 420 { DBC_RMW, "DBC_RMW" }, 421 { DBC_TRANSIENT, "DBC_TRANSIENT" }, 422 { DBC_WAS_READ_COMMITTED,"DBC_WAS_READ_COMMITTED" }, 423 { DBC_WRITECURSOR, "DBC_WRITECURSOR" }, 424 { DBC_WRITER, "DBC_WRITER" }, 425 { 0, NULL } 426 }; 427 DB *dbp; 428 DBC_INTERNAL *cp; 429 ENV *env; 430 431 dbp = dbc->dbp; 432 env = dbp->env; 433 cp = dbc->internal; 434 435 STAT_POINTER("DBC", dbc); 436 STAT_POINTER("Associated dbp", dbc->dbp); 437 STAT_POINTER("Associated txn", dbc->txn); 438 STAT_POINTER("Internal", cp); 439 STAT_HEX("Default locker ID", dbc->lref == NULL ? 0 : dbc->lref->id); 440 STAT_HEX("Locker", P_TO_ULONG(dbc->locker)); 441 STAT_STRING("Type", __db_dbtype_to_string(dbc->dbtype)); 442 443 STAT_POINTER("Off-page duplicate cursor", cp->opd); 444 STAT_POINTER("Referenced page", cp->page); 445 STAT_ULONG("Root", cp->root); 446 STAT_ULONG("Page number", cp->pgno); 447 STAT_ULONG("Page index", cp->indx); 448 STAT_STRING("Lock mode", __db_lockmode_to_string(cp->lock_mode)); 449 __db_prflags(env, NULL, dbc->flags, fn, NULL, "\tFlags"); 450 451 switch (dbc->dbtype) { 452 case DB_BTREE: 453 case DB_RECNO: 454 __bam_print_cursor(dbc); 455 break; 456 case DB_HASH: 457 __ham_print_cursor(dbc); 458 break; 459 case DB_UNKNOWN: 460 DB_ASSERT(env, dbp->type != DB_UNKNOWN); 461 /* FALLTHROUGH */ 462 case DB_QUEUE: 463 default: 464 break; 465 } 466 return (0); 467} 468 469#else /* !HAVE_STATISTICS */ 470 471int 472__db_stat_pp(dbp, txn, spp, flags) 473 DB *dbp; 474 DB_TXN *txn; 475 void *spp; 476 u_int32_t flags; 477{ 478 COMPQUIET(spp, NULL); 479 COMPQUIET(txn, NULL); 480 COMPQUIET(flags, 0); 481 482 return (__db_stat_not_built(dbp->env)); 483} 484 485int 486__db_stat_print_pp(dbp, flags) 487 DB *dbp; 488 u_int32_t flags; 489{ 490 COMPQUIET(flags, 0); 491 492 return (__db_stat_not_built(dbp->env)); 493} 494#endif 495