1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 2001,2008 Oracle. All rights reserved. 5 * 6 * $Id: rep_stat.c,v 12.36 2008/03/26 21:44:29 ubell Exp $ 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/log.h" 15 16#ifdef HAVE_STATISTICS 17static int __rep_print_all __P((ENV *, u_int32_t)); 18static int __rep_print_stats __P((ENV *, u_int32_t)); 19static int __rep_stat __P((ENV *, DB_REP_STAT **, u_int32_t)); 20 21/* 22 * __rep_stat_pp -- 23 * ENV->rep_stat pre/post processing. 24 * 25 * PUBLIC: int __rep_stat_pp __P((DB_ENV *, DB_REP_STAT **, u_int32_t)); 26 */ 27int 28__rep_stat_pp(dbenv, statp, flags) 29 DB_ENV *dbenv; 30 DB_REP_STAT **statp; 31 u_int32_t flags; 32{ 33 DB_THREAD_INFO *ip; 34 ENV *env; 35 int ret; 36 37 env = dbenv->env; 38 39 ENV_REQUIRES_CONFIG_XX( 40 env, rep_handle, "DB_ENV->rep_stat", DB_INIT_REP); 41 42 if ((ret = __db_fchk(env, 43 "DB_ENV->rep_stat", flags, DB_STAT_CLEAR)) != 0) 44 return (ret); 45 46 ENV_ENTER(env, ip); 47 ret = __rep_stat(env, statp, flags); 48 ENV_LEAVE(env, ip); 49 50 return (ret); 51} 52 53/* 54 * __rep_stat -- 55 * ENV->rep_stat. 56 */ 57static int 58__rep_stat(env, statp, flags) 59 ENV *env; 60 DB_REP_STAT **statp; 61 u_int32_t flags; 62{ 63 DB_LOG *dblp; 64 DB_REP *db_rep; 65 DB_REP_STAT *stats; 66 LOG *lp; 67 REP *rep; 68 u_int32_t queued, startupdone; 69 int dolock, ret; 70 71 db_rep = env->rep_handle; 72 rep = db_rep->region; 73 dblp = env->lg_handle; 74 lp = dblp->reginfo.primary; 75 76 *statp = NULL; 77 78 /* Allocate a stat struct to return to the user. */ 79 if ((ret = __os_umalloc(env, sizeof(DB_REP_STAT), &stats)) != 0) 80 return (ret); 81 82 /* 83 * Read without holding the lock. If we are in client recovery, we 84 * copy just the stats struct so we won't block. We only copy out 85 * those stats that don't require acquiring any mutex. 86 */ 87 dolock = FLD_ISSET(rep->flags, REP_F_RECOVER_MASK) ? 0 : 1; 88 memcpy(stats, &rep->stat, sizeof(*stats)); 89 90 /* Copy out election stats. */ 91 if (F_ISSET(rep, REP_F_EPHASE1)) 92 stats->st_election_status = 1; 93 else if (F_ISSET(rep, REP_F_EPHASE2)) 94 stats->st_election_status = 2; 95 96 stats->st_election_nsites = rep->sites; 97 stats->st_election_cur_winner = rep->winner; 98 stats->st_election_priority = rep->w_priority; 99 stats->st_election_gen = rep->w_gen; 100 stats->st_election_lsn = rep->w_lsn; 101 stats->st_election_votes = rep->votes; 102 stats->st_election_nvotes = rep->nvotes; 103 stats->st_election_tiebreaker = rep->w_tiebreaker; 104 105 /* Copy out other info that's protected by the rep mutex. */ 106 stats->st_env_id = rep->eid; 107 stats->st_env_priority = rep->priority; 108 stats->st_nsites = rep->nsites; 109 stats->st_master = rep->master_id; 110 stats->st_gen = rep->gen; 111 stats->st_egen = rep->egen; 112 113 if (F_ISSET(rep, REP_F_MASTER)) 114 stats->st_status = DB_REP_MASTER; 115 else if (F_ISSET(rep, REP_F_CLIENT)) 116 stats->st_status = DB_REP_CLIENT; 117 else 118 stats->st_status = 0; 119 120 if (LF_ISSET(DB_STAT_CLEAR)) { 121 queued = rep->stat.st_log_queued; 122 startupdone = rep->stat.st_startup_complete; 123 memset(&rep->stat, 0, sizeof(rep->stat)); 124 rep->stat.st_log_queued = rep->stat.st_log_queued_total = 125 rep->stat.st_log_queued_max = queued; 126 rep->stat.st_startup_complete = startupdone; 127 } 128 129 /* 130 * Log-related replication info is stored in the log system and 131 * protected by the log region lock. 132 */ 133 if (dolock) 134 MUTEX_LOCK(env, rep->mtx_clientdb); 135 if (F_ISSET(rep, REP_F_CLIENT)) { 136 stats->st_next_lsn = lp->ready_lsn; 137 stats->st_waiting_lsn = lp->waiting_lsn; 138 stats->st_next_pg = rep->ready_pg; 139 stats->st_waiting_pg = rep->waiting_pg; 140 stats->st_max_lease_sec = (u_int32_t)lp->max_lease_ts.tv_sec; 141 stats->st_max_lease_usec = (u_int32_t) 142 (lp->max_lease_ts.tv_nsec / NS_PER_US); 143 } else { 144 if (F_ISSET(rep, REP_F_MASTER)) { 145 LOG_SYSTEM_LOCK(env); 146 stats->st_next_lsn = lp->lsn; 147 LOG_SYSTEM_UNLOCK(env); 148 } else 149 ZERO_LSN(stats->st_next_lsn); 150 ZERO_LSN(stats->st_waiting_lsn); 151 stats->st_max_lease_sec = 0; 152 stats->st_max_lease_usec = 0; 153 } 154 stats->st_max_perm_lsn = lp->max_perm_lsn; 155 if (dolock) 156 MUTEX_UNLOCK(env, rep->mtx_clientdb); 157 158 *statp = stats; 159 return (0); 160} 161 162/* 163 * __rep_stat_print_pp -- 164 * ENV->rep_stat_print pre/post processing. 165 * 166 * PUBLIC: int __rep_stat_print_pp __P((DB_ENV *, u_int32_t)); 167 */ 168int 169__rep_stat_print_pp(dbenv, flags) 170 DB_ENV *dbenv; 171 u_int32_t flags; 172{ 173 DB_THREAD_INFO *ip; 174 ENV *env; 175 int ret; 176 177 env = dbenv->env; 178 179 ENV_REQUIRES_CONFIG_XX( 180 env, rep_handle, "DB_ENV->rep_stat_print", DB_INIT_REP); 181 182 if ((ret = __db_fchk(env, "DB_ENV->rep_stat_print", 183 flags, DB_STAT_ALL | DB_STAT_CLEAR)) != 0) 184 return (ret); 185 186 ENV_ENTER(env, ip); 187 ret = __rep_stat_print(env, flags); 188 ENV_LEAVE(env, ip); 189 190 return (ret); 191} 192 193/* 194 * __rep_stat_print -- 195 * ENV->rep_stat_print method. 196 * 197 * PUBLIC: int __rep_stat_print __P((ENV *, u_int32_t)); 198 */ 199int 200__rep_stat_print(env, flags) 201 ENV *env; 202 u_int32_t flags; 203{ 204 u_int32_t orig_flags; 205 int ret; 206 207 orig_flags = flags; 208 LF_CLR(DB_STAT_CLEAR | DB_STAT_SUBSYSTEM); 209 if (flags == 0 || LF_ISSET(DB_STAT_ALL)) { 210 ret = __rep_print_stats(env, orig_flags); 211 if (flags == 0 || ret != 0) 212 return (ret); 213 } 214 215 if (LF_ISSET(DB_STAT_ALL) && 216 (ret = __rep_print_all(env, orig_flags)) != 0) 217 return (ret); 218 219 return (0); 220} 221 222/* 223 * __rep_print_stats -- 224 * Print out default statistics. 225 */ 226static int 227__rep_print_stats(env, flags) 228 ENV *env; 229 u_int32_t flags; 230{ 231 DB_REP_STAT *sp; 232 int is_client, ret; 233 char *p; 234 235 if ((ret = __rep_stat(env, &sp, flags)) != 0) 236 return (ret); 237 238 if (LF_ISSET(DB_STAT_ALL)) 239 __db_msg(env, "Default replication region information:"); 240 is_client = 0; 241 switch (sp->st_status) { 242 case DB_REP_MASTER: 243 __db_msg(env, 244 "Environment configured as a replication master"); 245 break; 246 case DB_REP_CLIENT: 247 __db_msg(env, 248 "Environment configured as a replication client"); 249 is_client = 1; 250 break; 251 default: 252 __db_msg(env, 253 "Environment not configured for replication"); 254 break; 255 } 256 257 __db_msg(env, "%lu/%lu\t%s", 258 (u_long)sp->st_next_lsn.file, (u_long)sp->st_next_lsn.offset, 259 is_client ? "Next LSN expected" : "Next LSN to be used"); 260 __db_msg(env, "%lu/%lu\t%s", 261 (u_long)sp->st_waiting_lsn.file, (u_long)sp->st_waiting_lsn.offset, 262 sp->st_waiting_lsn.file == 0 ? 263 "Not waiting for any missed log records" : 264 "LSN of first log record we have after missed log records"); 265 __db_msg(env, "%lu/%lu\t%s", 266 (u_long)sp->st_max_perm_lsn.file, 267 (u_long)sp->st_max_perm_lsn.offset, 268 sp->st_max_perm_lsn.file == 0 ? 269 "No maximum permanent LSN" : 270 "Maximum permanent LSN"); 271 272 __db_dl(env, "Next page number expected", (u_long)sp->st_next_pg); 273 p = sp->st_waiting_pg == PGNO_INVALID ? 274 "Not waiting for any missed pages" : 275 "Page number of first page we have after missed pages"; 276 __db_msg(env, "%lu\t%s", (u_long)sp->st_waiting_pg, p); 277 __db_dl(env, 278 "Number of duplicate master conditions originally detected at this site", 279 (u_long)sp->st_dupmasters); 280 if (sp->st_env_id != DB_EID_INVALID) 281 __db_dl(env, "Current environment ID", (u_long)sp->st_env_id); 282 else 283 __db_msg(env, "No current environment ID"); 284 __db_dl(env, 285 "Current environment priority", (u_long)sp->st_env_priority); 286 __db_dl(env, "Current generation number", (u_long)sp->st_gen); 287 __db_dl(env, 288 "Current election generation number", (u_long)sp->st_egen); 289 __db_dl(env, "Number of duplicate log records received", 290 (u_long)sp->st_log_duplicated); 291 __db_dl(env, "Number of log records currently queued", 292 (u_long)sp->st_log_queued); 293 __db_dl(env, "Maximum number of log records ever queued at once", 294 (u_long)sp->st_log_queued_max); 295 __db_dl(env, "Total number of log records queued", 296 (u_long)sp->st_log_queued_total); 297 __db_dl(env, 298 "Number of log records received and appended to the log", 299 (u_long)sp->st_log_records); 300 __db_dl(env, "Number of log records missed and requested", 301 (u_long)sp->st_log_requested); 302 if (sp->st_master != DB_EID_INVALID) 303 __db_dl(env, "Current master ID", (u_long)sp->st_master); 304 else 305 __db_msg(env, "No current master ID"); 306 __db_dl(env, "Number of times the master has changed", 307 (u_long)sp->st_master_changes); 308 __db_dl(env, 309 "Number of messages received with a bad generation number", 310 (u_long)sp->st_msgs_badgen); 311 __db_dl(env, "Number of messages received and processed", 312 (u_long)sp->st_msgs_processed); 313 __db_dl(env, "Number of messages ignored due to pending recovery", 314 (u_long)sp->st_msgs_recover); 315 __db_dl(env, "Number of failed message sends", 316 (u_long)sp->st_msgs_send_failures); 317 __db_dl(env, "Number of messages sent", (u_long)sp->st_msgs_sent); 318 __db_dl(env, 319 "Number of new site messages received", (u_long)sp->st_newsites); 320 __db_dl(env, 321 "Number of environments believed to be in the replication group", 322 (u_long)sp->st_nsites); 323 __db_dl(env, "Transmission limited", (u_long)sp->st_nthrottles); 324 __db_dl(env, "Number of outdated conditions detected", 325 (u_long)sp->st_outdated); 326 __db_dl(env, "Number of duplicate page records received", 327 (u_long)sp->st_pg_duplicated); 328 __db_dl(env, "Number of page records received and added to databases", 329 (u_long)sp->st_pg_records); 330 __db_dl(env, "Number of page records missed and requested", 331 (u_long)sp->st_pg_requested); 332 if (sp->st_startup_complete == 0) 333 __db_msg(env, "Startup incomplete"); 334 else 335 __db_msg(env, "Startup complete"); 336 __db_dl(env, 337 "Number of transactions applied", (u_long)sp->st_txns_applied); 338 339 __db_dl(env, "Number of startsync messages delayed", 340 (u_long)sp->st_startsync_delayed); 341 342 __db_dl(env, "Number of elections held", (u_long)sp->st_elections); 343 __db_dl(env, 344 "Number of elections won", (u_long)sp->st_elections_won); 345 346 if (sp->st_election_status == 0) { 347 __db_msg(env, "No election in progress"); 348 if (sp->st_election_sec > 0 || sp->st_election_usec > 0) 349 __db_msg(env, 350 "%lu.%.6lu\tDuration of last election (seconds)", 351 (u_long)sp->st_election_sec, 352 (u_long)sp->st_election_usec); 353 } else { 354 __db_dl(env, "Current election phase", 355 (u_long)sp->st_election_status); 356 __db_dl(env, "Election winner", 357 (u_long)sp->st_election_cur_winner); 358 __db_dl(env, "Election generation number", 359 (u_long)sp->st_election_gen); 360 __db_msg(env, "%lu/%lu\tMaximum LSN of election winner", 361 (u_long)sp->st_election_lsn.file, 362 (u_long)sp->st_election_lsn.offset); 363 __db_dl(env, 364 "Number of sites expected to participate in elections", 365 (u_long)sp->st_election_nsites); 366 __db_dl(env, "Number of votes needed to win an election", 367 (u_long)sp->st_election_nvotes); 368 __db_dl(env, 369 "Election priority", (u_long)sp->st_election_priority); 370 __db_dl(env, "Election tiebreaker value", 371 (u_long)sp->st_election_tiebreaker); 372 __db_dl(env, "Votes received this election round", 373 (u_long)sp->st_election_votes); 374 } 375 __db_dl(env, "Number of bulk buffer sends triggered by full buffer", 376 (u_long)sp->st_bulk_fills); 377 __db_dl(env, "Number of single records exceeding bulk buffer size", 378 (u_long)sp->st_bulk_overflows); 379 __db_dl(env, "Number of records added to a bulk buffer", 380 (u_long)sp->st_bulk_records); 381 __db_dl(env, "Number of bulk buffers sent", 382 (u_long)sp->st_bulk_transfers); 383 __db_dl(env, "Number of re-request messages received", 384 (u_long)sp->st_client_rerequests); 385 __db_dl(env, 386 "Number of request messages this client failed to process", 387 (u_long)sp->st_client_svc_miss); 388 __db_dl(env, "Number of request messages received by this client", 389 (u_long)sp->st_client_svc_req); 390 if (sp->st_max_lease_sec > 0 || sp->st_max_lease_usec > 0) 391 __db_msg(env, 392 "%lu.%.6lu\tDuration of maximum lease (seconds)", 393 (u_long)sp->st_max_lease_sec, 394 (u_long)sp->st_max_lease_usec); 395 396 __os_ufree(env, sp); 397 398 return (0); 399} 400 401/* 402 * __rep_print_all -- 403 * Display debugging replication region statistics. 404 */ 405static int 406__rep_print_all(env, flags) 407 ENV *env; 408 u_int32_t flags; 409{ 410 static const FN rep_fn[] = { 411 { REP_F_CLIENT, "REP_F_CLIENT" }, 412 { REP_F_EPHASE1, "REP_F_EPHASE1" }, 413 { REP_F_EPHASE2, "REP_F_EPHASE2" }, 414 { REP_F_INREPELECT, "REP_F_INREPELECT" }, 415 { REP_F_MASTER, "REP_F_MASTER" }, 416 { REP_F_MASTERELECT, "REP_F_MASTERELECT" }, 417 { REP_F_NOARCHIVE, "REP_F_NOARCHIVE" }, 418 { REP_F_READY_API, "REP_F_READY_API" }, 419 { REP_F_READY_MSG, "REP_F_READY_MSG" }, 420 { REP_F_READY_OP, "REP_F_READY_OP" }, 421 { REP_F_RECOVER_LOG, "REP_F_RECOVER_LOG" }, 422 { REP_F_RECOVER_PAGE, "REP_F_RECOVER_PAGE" }, 423 { REP_F_RECOVER_UPDATE, "REP_F_RECOVER_UPDATE" }, 424 { REP_F_RECOVER_VERIFY, "REP_F_RECOVER_VERIFY" }, 425 { REP_F_TALLY, "REP_F_TALLY" }, 426 { 0, NULL } 427 }; 428 static const FN dbrep_fn[] = { 429 { DBREP_OPENFILES, "DBREP_OPENFILES" }, 430 { 0, NULL } 431 }; 432 DB_LOG *dblp; 433 DB_REP *db_rep; 434 DB_THREAD_INFO *ip; 435 LOG *lp; 436 REGENV *renv; 437 REGINFO *infop; 438 REP *rep; 439 char time_buf[CTIME_BUFLEN]; 440 441 db_rep = env->rep_handle; 442 rep = db_rep->region; 443 infop = env->reginfo; 444 renv = infop->primary; 445 ENV_ENTER(env, ip); 446 447 __db_msg(env, "%s", DB_GLOBAL(db_line)); 448 __db_msg(env, "DB_REP handle information:"); 449 450 if (db_rep->rep_db == NULL) 451 STAT_ISSET("Bookkeeping database", db_rep->rep_db); 452 else 453 (void)__db_stat_print(db_rep->rep_db, ip, flags); 454 455 __db_prflags(env, NULL, db_rep->flags, dbrep_fn, NULL, "\tFlags"); 456 457 __db_msg(env, "%s", DB_GLOBAL(db_line)); 458 __db_msg(env, "REP handle information:"); 459 __mutex_print_debug_single(env, 460 "Replication region mutex", rep->mtx_region, flags); 461 __mutex_print_debug_single(env, 462 "Bookkeeping database mutex", rep->mtx_clientdb, flags); 463 464 STAT_LONG("Environment ID", rep->eid); 465 STAT_LONG("Master environment ID", rep->master_id); 466 STAT_ULONG("Election generation", rep->egen); 467 STAT_ULONG("Election generation number", rep->gen); 468 STAT_ULONG("Last generation number in log", rep->recover_gen); 469 STAT_LONG("Space allocated for sites", rep->asites); 470 STAT_LONG("Sites in group", rep->nsites); 471 STAT_LONG("Votes needed for election", rep->nvotes); 472 STAT_LONG("Priority in election", rep->priority); 473 __db_dlbytes(env, "Limit on data sent in a single call", 474 rep->gbytes, (u_long)0, rep->bytes); 475 STAT_LONG("Request gap seconds", rep->request_gap.tv_sec); 476 STAT_LONG("Request gap microseconds", 477 rep->request_gap.tv_nsec / NS_PER_US); 478 STAT_LONG("Maximum gap seconds", rep->max_gap.tv_sec); 479 STAT_LONG("Maximum gap microseconds", 480 rep->max_gap.tv_nsec / NS_PER_US); 481 482 STAT_ULONG("Callers in rep_proc_msg", rep->msg_th); 483 STAT_ULONG("Library handle count", rep->handle_cnt); 484 STAT_ULONG("Multi-step operation count", rep->op_cnt); 485 __db_msg(env, "%.24s\tRecovery timestamp", 486 renv->rep_timestamp == 0 ? 487 "0" : __os_ctime(&renv->rep_timestamp, time_buf)); 488 489 STAT_LONG("Sites heard from", rep->sites); 490 STAT_LONG("Current winner", rep->winner); 491 STAT_LONG("Winner priority", rep->w_priority); 492 STAT_ULONG("Winner generation", rep->w_gen); 493 STAT_LSN("Winner LSN", &rep->w_lsn); 494 STAT_LONG("Winner tiebreaker", rep->w_tiebreaker); 495 STAT_LONG("Votes for this site", rep->votes); 496 497 __db_prflags(env, NULL, rep->flags, rep_fn, NULL, "\tFlags"); 498 499 __db_msg(env, "%s", DB_GLOBAL(db_line)); 500 __db_msg(env, "LOG replication information:"); 501 MUTEX_LOCK(env, rep->mtx_clientdb); 502 dblp = env->lg_handle; 503 lp = (LOG *)dblp->reginfo.primary; 504 STAT_LSN("First log record after a gap", &lp->waiting_lsn); 505 STAT_LSN("Maximum permanent LSN processed", &lp->max_perm_lsn); 506 STAT_LSN("LSN waiting to verify", &lp->verify_lsn); 507 STAT_LSN("Maximum LSN requested", &lp->max_wait_lsn); 508 STAT_LONG("Time to wait before requesting seconds", lp->wait_ts.tv_sec); 509 STAT_LONG("Time to wait before requesting microseconds", 510 lp->wait_ts.tv_nsec / NS_PER_US); 511 STAT_LSN("Next LSN expected", &lp->ready_lsn); 512 STAT_LONG("Maximum lease timestamp seconds", lp->max_lease_ts.tv_sec); 513 STAT_LONG("Maximum lease timestamp microseconds", 514 lp->max_lease_ts.tv_nsec / NS_PER_US); 515 MUTEX_UNLOCK(env, rep->mtx_clientdb); 516 517 return (0); 518} 519 520#else /* !HAVE_STATISTICS */ 521 522int 523__rep_stat_pp(dbenv, statp, flags) 524 DB_ENV *dbenv; 525 DB_REP_STAT **statp; 526 u_int32_t flags; 527{ 528 COMPQUIET(statp, NULL); 529 COMPQUIET(flags, 0); 530 531 return (__db_stat_not_built(dbenv->env)); 532} 533 534int 535__rep_stat_print_pp(dbenv, flags) 536 DB_ENV *dbenv; 537 u_int32_t flags; 538{ 539 COMPQUIET(flags, 0); 540 541 return (__db_stat_not_built(dbenv->env)); 542} 543#endif 544