1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1996,2008 Oracle. All rights reserved. 5 * 6 * $Id: db_err.c,v 12.72 2008/03/12 19:11:53 mbrey 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/lock.h" 15#include "dbinc/log.h" 16#include "dbinc/mp.h" 17#include "dbinc/txn.h" 18 19static void __db_msgcall __P((const DB_ENV *, const char *, va_list)); 20static void __db_msgfile __P((const DB_ENV *, const char *, va_list)); 21 22/* 23 * __db_fchk -- 24 * General flags checking routine. 25 * 26 * PUBLIC: int __db_fchk __P((ENV *, const char *, u_int32_t, u_int32_t)); 27 */ 28int 29__db_fchk(env, name, flags, ok_flags) 30 ENV *env; 31 const char *name; 32 u_int32_t flags, ok_flags; 33{ 34 return (LF_ISSET(~ok_flags) ? __db_ferr(env, name, 0) : 0); 35} 36 37/* 38 * __db_fcchk -- 39 * General combination flags checking routine. 40 * 41 * PUBLIC: int __db_fcchk 42 * PUBLIC: __P((ENV *, const char *, u_int32_t, u_int32_t, u_int32_t)); 43 */ 44int 45__db_fcchk(env, name, flags, flag1, flag2) 46 ENV *env; 47 const char *name; 48 u_int32_t flags, flag1, flag2; 49{ 50 return (LF_ISSET(flag1) && 51 LF_ISSET(flag2) ? __db_ferr(env, name, 1) : 0); 52} 53 54/* 55 * __db_ferr -- 56 * Common flag errors. 57 * 58 * PUBLIC: int __db_ferr __P((const ENV *, const char *, int)); 59 */ 60int 61__db_ferr(env, name, iscombo) 62 const ENV *env; 63 const char *name; 64 int iscombo; 65{ 66 __db_errx(env, "illegal flag %sspecified to %s", 67 iscombo ? "combination " : "", name); 68 return (EINVAL); 69} 70 71/* 72 * __db_fnl -- 73 * Common flag-needs-locking message. 74 * 75 * PUBLIC: int __db_fnl __P((const ENV *, const char *)); 76 */ 77int 78__db_fnl(env, name) 79 const ENV *env; 80 const char *name; 81{ 82 __db_errx(env, 83 "%s: DB_READ_COMMITTED, DB_READ_UNCOMMITTED and DB_RMW require locking", 84 name); 85 return (EINVAL); 86} 87 88/* 89 * __db_pgerr -- 90 * Error when unable to retrieve a specified page. 91 * 92 * PUBLIC: int __db_pgerr __P((DB *, db_pgno_t, int)); 93 */ 94int 95__db_pgerr(dbp, pgno, errval) 96 DB *dbp; 97 db_pgno_t pgno; 98 int errval; 99{ 100 /* 101 * Three things are certain: 102 * Death, taxes, and lost data. 103 * Guess which has occurred. 104 */ 105 __db_errx(dbp->env, 106 "unable to create/retrieve page %lu", (u_long)pgno); 107 return (__env_panic(dbp->env, errval)); 108} 109 110/* 111 * __db_pgfmt -- 112 * Error when a page has the wrong format. 113 * 114 * PUBLIC: int __db_pgfmt __P((ENV *, db_pgno_t)); 115 */ 116int 117__db_pgfmt(env, pgno) 118 ENV *env; 119 db_pgno_t pgno; 120{ 121 __db_errx(env, "page %lu: illegal page type or format", (u_long)pgno); 122 return (__env_panic(env, EINVAL)); 123} 124 125#ifdef DIAGNOSTIC 126/* 127 * __db_assert -- 128 * Error when an assertion fails. Only checked if #DIAGNOSTIC defined. 129 * 130 * PUBLIC: #ifdef DIAGNOSTIC 131 * PUBLIC: void __db_assert __P((ENV *, const char *, const char *, int)); 132 * PUBLIC: #endif 133 */ 134void 135__db_assert(env, e, file, line) 136 ENV *env; 137 const char *e, *file; 138 int line; 139{ 140 __db_errx(env, "assert failure: %s/%d: \"%s\"", file, line, e); 141 142 __os_abort(env); 143 /* NOTREACHED */ 144} 145#endif 146 147/* 148 * __env_panic_msg -- 149 * Just report that someone else paniced. 150 * 151 * PUBLIC: int __env_panic_msg __P((ENV *)); 152 */ 153int 154__env_panic_msg(env) 155 ENV *env; 156{ 157 DB_ENV *dbenv; 158 int ret; 159 160 dbenv = env->dbenv; 161 162 ret = DB_RUNRECOVERY; 163 164 __db_errx(env, "PANIC: fatal region error detected; run recovery"); 165 166 if (dbenv->db_paniccall != NULL) /* Deprecated */ 167 dbenv->db_paniccall(dbenv, ret); 168 DB_EVENT(env, DB_EVENT_PANIC, &ret); 169 170 return (ret); 171} 172 173/* 174 * __env_panic -- 175 * Lock out the database environment due to unrecoverable error. 176 * 177 * PUBLIC: int __env_panic __P((ENV *, int)); 178 */ 179int 180__env_panic(env, errval) 181 ENV *env; 182 int errval; 183{ 184 DB_ENV *dbenv; 185 186 dbenv = env->dbenv; 187 188 if (env != NULL) { 189 __env_panic_set(env, 1); 190 191 __db_err(env, errval, "PANIC"); 192 193 if (dbenv->db_paniccall != NULL) /* Deprecated */ 194 dbenv->db_paniccall(dbenv, errval); 195 DB_EVENT(env, DB_EVENT_PANIC, &errval); 196 } 197 198#if defined(DIAGNOSTIC) && !defined(CONFIG_TEST) 199 /* 200 * We want a stack trace of how this could possibly happen. 201 * 202 * Don't drop core if it's the test suite -- it's reasonable for the 203 * test suite to check to make sure that DB_RUNRECOVERY is returned 204 * under certain conditions. 205 */ 206 __os_abort(env); 207 /* NOTREACHED */ 208#endif 209 210 /* 211 * Chaos reigns within. 212 * Reflect, repent, and reboot. 213 * Order shall return. 214 */ 215 return (DB_RUNRECOVERY); 216} 217 218/* 219 * db_strerror -- 220 * ANSI C strerror(3) for DB. 221 * 222 * EXTERN: char *db_strerror __P((int)); 223 */ 224char * 225db_strerror(error) 226 int error; 227{ 228 char *p; 229 230 if (error == 0) 231 return ("Successful return: 0"); 232 if (error > 0) { 233 if ((p = strerror(error)) != NULL) 234 return (p); 235 return (__db_unknown_error(error)); 236 } 237 238 /* 239 * !!! 240 * The Tcl API requires that some of these return strings be compared 241 * against strings stored in application scripts. So, any of these 242 * errors that do not invariably result in a Tcl exception may not be 243 * altered. 244 */ 245 switch (error) { 246 case DB_BUFFER_SMALL: 247 return 248 ("DB_BUFFER_SMALL: User memory too small for return value"); 249 case DB_DONOTINDEX: 250 return ("DB_DONOTINDEX: Secondary index callback returns null"); 251 case DB_FOREIGN_CONFLICT: 252 return 253 ("DB_FOREIGN_CONFLICT: A foreign database constraint has been violated"); 254 case DB_KEYEMPTY: 255 return ("DB_KEYEMPTY: Non-existent key/data pair"); 256 case DB_KEYEXIST: 257 return ("DB_KEYEXIST: Key/data pair already exists"); 258 case DB_LOCK_DEADLOCK: 259 return 260 ("DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock"); 261 case DB_LOCK_NOTGRANTED: 262 return ("DB_LOCK_NOTGRANTED: Lock not granted"); 263 case DB_LOG_BUFFER_FULL: 264 return ("DB_LOG_BUFFER_FULL: In-memory log buffer is full"); 265 case DB_NOSERVER: 266 return ("DB_NOSERVER: Fatal error, no RPC server"); 267 case DB_NOSERVER_HOME: 268 return ("DB_NOSERVER_HOME: Home unrecognized at server"); 269 case DB_NOSERVER_ID: 270 return ("DB_NOSERVER_ID: Identifier unrecognized at server"); 271 case DB_NOTFOUND: 272 return ("DB_NOTFOUND: No matching key/data pair found"); 273 case DB_OLD_VERSION: 274 return ("DB_OLDVERSION: Database requires a version upgrade"); 275 case DB_PAGE_NOTFOUND: 276 return ("DB_PAGE_NOTFOUND: Requested page not found"); 277 case DB_REP_DUPMASTER: 278 return ("DB_REP_DUPMASTER: A second master site appeared"); 279 case DB_REP_HANDLE_DEAD: 280 return ("DB_REP_HANDLE_DEAD: Handle is no longer valid"); 281 case DB_REP_HOLDELECTION: 282 return ("DB_REP_HOLDELECTION: Need to hold an election"); 283 case DB_REP_IGNORE: 284 return ("DB_REP_IGNORE: Replication record ignored"); 285 case DB_REP_ISPERM: 286 return ("DB_REP_ISPERM: Permanent record written"); 287 case DB_REP_JOIN_FAILURE: 288 return 289 ("DB_REP_JOIN_FAILURE: Unable to join replication group"); 290 case DB_REP_LEASE_EXPIRED: 291 return 292 ("DB_REP_LEASE_EXPIRED: Replication leases have expired"); 293 case DB_REP_LOCKOUT: 294 return 295 ("DB_REP_LOCKOUT: Waiting for replication recovery to complete"); 296 case DB_REP_NEWSITE: 297 return ("DB_REP_NEWSITE: A new site has entered the system"); 298 case DB_REP_NOTPERM: 299 return ("DB_REP_NOTPERM: Permanent log record not written"); 300 case DB_REP_UNAVAIL: 301 return ("DB_REP_UNAVAIL: Unable to elect a master"); 302 case DB_RUNRECOVERY: 303 return ("DB_RUNRECOVERY: Fatal error, run database recovery"); 304 case DB_SECONDARY_BAD: 305 return 306 ("DB_SECONDARY_BAD: Secondary index inconsistent with primary"); 307 case DB_VERIFY_BAD: 308 return ("DB_VERIFY_BAD: Database verification failed"); 309 case DB_VERSION_MISMATCH: 310 return 311 ("DB_VERSION_MISMATCH: Database environment version mismatch"); 312 default: 313 break; 314 } 315 316 return (__db_unknown_error(error)); 317} 318 319/* 320 * __db_unknown_error -- 321 * Format an unknown error value into a static buffer. 322 * 323 * PUBLIC: char *__db_unknown_error __P((int)); 324 */ 325char * 326__db_unknown_error(error) 327 int error; 328{ 329 /* 330 * !!! 331 * Room for a 64-bit number + slop. This buffer is only used 332 * if we're given an unknown error number, which should never 333 * happen. 334 * 335 * We're no longer thread-safe if it does happen, but the worst 336 * result is a corrupted error string because there will always 337 * be a trailing nul byte since the error buffer is nul filled 338 * and longer than any error message. 339 */ 340 (void)snprintf(DB_GLOBAL(error_buf), 341 sizeof(DB_GLOBAL(error_buf)), "Unknown error: %d", error); 342 return (DB_GLOBAL(error_buf)); 343} 344 345/* 346 * __db_syserr -- 347 * Standard error routine. 348 * 349 * PUBLIC: void __db_syserr __P((const ENV *, int, const char *, ...)) 350 * PUBLIC: __attribute__ ((__format__ (__printf__, 3, 4))); 351 */ 352void 353#ifdef STDC_HEADERS 354__db_syserr(const ENV *env, int error, const char *fmt, ...) 355#else 356__db_syserr(env, error, fmt, va_alist) 357 const ENV *env; 358 int error; 359 const char *fmt; 360 va_dcl 361#endif 362{ 363 DB_ENV *dbenv; 364 365 dbenv = env == NULL ? NULL : env->dbenv; 366 367 /* 368 * The same as DB->err, except we don't default to writing to stderr 369 * after any output channel has been configured, and we use a system- 370 * specific function to translate errors to strings. 371 */ 372 DB_REAL_ERR(dbenv, error, DB_ERROR_SYSTEM, 0, fmt); 373} 374 375/* 376 * __db_err -- 377 * Standard error routine. 378 * 379 * PUBLIC: void __db_err __P((const ENV *, int, const char *, ...)) 380 * PUBLIC: __attribute__ ((__format__ (__printf__, 3, 4))); 381 */ 382void 383#ifdef STDC_HEADERS 384__db_err(const ENV *env, int error, const char *fmt, ...) 385#else 386__db_err(env, error, fmt, va_alist) 387 const ENV *env; 388 int error; 389 const char *fmt; 390 va_dcl 391#endif 392{ 393 DB_ENV *dbenv; 394 395 dbenv = env == NULL ? NULL : env->dbenv; 396 397 /* 398 * The same as DB->err, except we don't default to writing to stderr 399 * once an output channel has been configured. 400 */ 401 DB_REAL_ERR(dbenv, error, DB_ERROR_SET, 0, fmt); 402} 403 404/* 405 * __db_errx -- 406 * Standard error routine. 407 * 408 * PUBLIC: void __db_errx __P((const ENV *, const char *, ...)) 409 * PUBLIC: __attribute__ ((__format__ (__printf__, 2, 3))); 410 */ 411void 412#ifdef STDC_HEADERS 413__db_errx(const ENV *env, const char *fmt, ...) 414#else 415__db_errx(env, fmt, va_alist) 416 const ENV *env; 417 const char *fmt; 418 va_dcl 419#endif 420{ 421 DB_ENV *dbenv; 422 423 dbenv = env == NULL ? NULL : env->dbenv; 424 425 /* 426 * The same as DB->errx, except we don't default to writing to stderr 427 * once an output channel has been configured. 428 */ 429 DB_REAL_ERR(dbenv, 0, DB_ERROR_NOT_SET, 0, fmt); 430} 431 432/* 433 * __db_errcall -- 434 * Do the error message work for callback functions. 435 * 436 * PUBLIC: void __db_errcall 437 * PUBLIC: __P((const DB_ENV *, int, db_error_set_t, const char *, va_list)); 438 */ 439void 440__db_errcall(dbenv, error, error_set, fmt, ap) 441 const DB_ENV *dbenv; 442 int error; 443 db_error_set_t error_set; 444 const char *fmt; 445 va_list ap; 446{ 447 char *p; 448 char buf[2048]; /* !!!: END OF THE STACK DON'T TRUST SPRINTF. */ 449 char sysbuf[1024]; /* !!!: END OF THE STACK DON'T TRUST SPRINTF. */ 450 451 p = buf; 452 if (fmt != NULL) 453 p += vsnprintf(buf, sizeof(buf), fmt, ap); 454 if (error_set != DB_ERROR_NOT_SET) 455 p += snprintf(p, 456 sizeof(buf) - (size_t)(p - buf), ": %s", 457 error_set == DB_ERROR_SET ? db_strerror(error) : 458 __os_strerror(error, sysbuf, sizeof(sysbuf))); 459 460 dbenv->db_errcall(dbenv, dbenv->db_errpfx, buf); 461} 462 463/* 464 * __db_errfile -- 465 * Do the error message work for FILE *s. 466 * 467 * PUBLIC: void __db_errfile 468 * PUBLIC: __P((const DB_ENV *, int, db_error_set_t, const char *, va_list)); 469 */ 470void 471__db_errfile(dbenv, error, error_set, fmt, ap) 472 const DB_ENV *dbenv; 473 int error; 474 db_error_set_t error_set; 475 const char *fmt; 476 va_list ap; 477{ 478 FILE *fp; 479 int need_sep; 480 char sysbuf[1024]; /* !!!: END OF THE STACK DON'T TRUST SPRINTF. */ 481 482 fp = dbenv == NULL || 483 dbenv->db_errfile == NULL ? stderr : dbenv->db_errfile; 484 need_sep = 0; 485 486 if (dbenv != NULL && dbenv->db_errpfx != NULL) { 487 (void)fprintf(fp, "%s", dbenv->db_errpfx); 488 need_sep = 1; 489 } 490 if (fmt != NULL && fmt[0] != '\0') { 491 if (need_sep) 492 (void)fprintf(fp, ": "); 493 need_sep = 1; 494 (void)vfprintf(fp, fmt, ap); 495 } 496 if (error_set != DB_ERROR_NOT_SET) 497 (void)fprintf(fp, "%s%s", 498 need_sep ? ": " : "", 499 error_set == DB_ERROR_SET ? db_strerror(error) : 500 __os_strerror(error, sysbuf, sizeof(sysbuf))); 501 (void)fprintf(fp, "\n"); 502 (void)fflush(fp); 503} 504 505/* 506 * __db_msgadd -- 507 * Aggregate a set of strings into a buffer for the callback API. 508 * 509 * PUBLIC: void __db_msgadd __P((ENV *, DB_MSGBUF *, const char *, ...)) 510 * PUBLIC: __attribute__ ((__format__ (__printf__, 3, 4))); 511 */ 512void 513#ifdef STDC_HEADERS 514__db_msgadd(ENV *env, DB_MSGBUF *mbp, const char *fmt, ...) 515#else 516__db_msgadd(env, mbp, fmt, va_alist) 517 ENV *env; 518 DB_MSGBUF *mbp; 519 const char *fmt; 520 va_dcl 521#endif 522{ 523 va_list ap; 524 525#ifdef STDC_HEADERS 526 va_start(ap, fmt); 527#else 528 va_start(ap); 529#endif 530 __db_msgadd_ap(env, mbp, fmt, ap); 531 va_end(ap); 532} 533 534/* 535 * __db_msgadd_ap -- 536 * Aggregate a set of strings into a buffer for the callback API. 537 * 538 * PUBLIC: void __db_msgadd_ap 539 * PUBLIC: __P((ENV *, DB_MSGBUF *, const char *, va_list)); 540 */ 541void 542__db_msgadd_ap(env, mbp, fmt, ap) 543 ENV *env; 544 DB_MSGBUF *mbp; 545 const char *fmt; 546 va_list ap; 547{ 548 size_t len, olen; 549 char buf[2048]; /* !!!: END OF THE STACK DON'T TRUST SPRINTF. */ 550 551 len = (size_t)vsnprintf(buf, sizeof(buf), fmt, ap); 552 553 /* 554 * There's a heap buffer in the ENV handle we use to aggregate the 555 * message chunks. We maintain a pointer to the buffer, the next slot 556 * to be filled in in the buffer, and a total buffer length. 557 */ 558 olen = (size_t)(mbp->cur - mbp->buf); 559 if (olen + len >= mbp->len) { 560 if (__os_realloc(env, mbp->len + len + 256, &mbp->buf)) 561 return; 562 mbp->len += (len + 256); 563 mbp->cur = mbp->buf + olen; 564 } 565 566 memcpy(mbp->cur, buf, len + 1); 567 mbp->cur += len; 568} 569 570/* 571 * __db_msg -- 572 * Standard DB stat message routine. 573 * 574 * PUBLIC: void __db_msg __P((const ENV *, const char *, ...)) 575 * PUBLIC: __attribute__ ((__format__ (__printf__, 2, 3))); 576 */ 577void 578#ifdef STDC_HEADERS 579__db_msg(const ENV *env, const char *fmt, ...) 580#else 581__db_msg(env, fmt, va_alist) 582 const ENV *env; 583 const char *fmt; 584 va_dcl 585#endif 586{ 587 DB_ENV *dbenv; 588 589 dbenv = env == NULL ? NULL : env->dbenv; 590 591 DB_REAL_MSG(dbenv, fmt); 592} 593 594/* 595 * __db_msgcall -- 596 * Do the message work for callback functions. 597 */ 598static void 599__db_msgcall(dbenv, fmt, ap) 600 const DB_ENV *dbenv; 601 const char *fmt; 602 va_list ap; 603{ 604 char buf[2048]; /* !!!: END OF THE STACK DON'T TRUST SPRINTF. */ 605 606 (void)vsnprintf(buf, sizeof(buf), fmt, ap); 607 608 dbenv->db_msgcall(dbenv, buf); 609} 610 611/* 612 * __db_msgfile -- 613 * Do the message work for FILE *s. 614 */ 615static void 616__db_msgfile(dbenv, fmt, ap) 617 const DB_ENV *dbenv; 618 const char *fmt; 619 va_list ap; 620{ 621 FILE *fp; 622 623 fp = dbenv == NULL || 624 dbenv->db_msgfile == NULL ? stdout : dbenv->db_msgfile; 625 (void)vfprintf(fp, fmt, ap); 626 627 (void)fprintf(fp, "\n"); 628 (void)fflush(fp); 629} 630 631/* 632 * __db_unknown_flag -- report internal error 633 * 634 * PUBLIC: int __db_unknown_flag __P((ENV *, char *, u_int32_t)); 635 */ 636int 637__db_unknown_flag(env, routine, flag) 638 ENV *env; 639 char *routine; 640 u_int32_t flag; 641{ 642 __db_errx(env, "%s: Unknown flag: %#x", routine, (u_int)flag); 643 644#ifdef DIAGNOSTIC 645 __os_abort(env); 646 /* NOTREACHED */ 647#endif 648 return (EINVAL); 649} 650 651/* 652 * __db_unknown_type -- report internal database type error 653 * 654 * PUBLIC: int __db_unknown_type __P((ENV *, char *, DBTYPE)); 655 */ 656int 657__db_unknown_type(env, routine, type) 658 ENV *env; 659 char *routine; 660 DBTYPE type; 661{ 662 __db_errx(env, 663 "%s: Unexpected database type: %s", 664 routine, __db_dbtype_to_string(type)); 665 666#ifdef DIAGNOSTIC 667 __os_abort(env); 668 /* NOTREACHED */ 669#endif 670 return (EINVAL); 671} 672 673/* 674 * __db_unknown_path -- report unexpected database code path error. 675 * 676 * PUBLIC: int __db_unknown_path __P((ENV *, char *)); 677 */ 678int 679__db_unknown_path(env, routine) 680 ENV *env; 681 char *routine; 682{ 683 __db_errx(env, "%s: Unexpected code path error", routine); 684 685#ifdef DIAGNOSTIC 686 __os_abort(env); 687 /* NOTREACHED */ 688#endif 689 return (EINVAL); 690} 691 692/* 693 * __db_check_txn -- 694 * Check for common transaction errors. 695 * 696 * PUBLIC: int __db_check_txn __P((DB *, DB_TXN *, DB_LOCKER *, int)); 697 */ 698int 699__db_check_txn(dbp, txn, assoc_locker, read_op) 700 DB *dbp; 701 DB_TXN *txn; 702 DB_LOCKER *assoc_locker; 703 int read_op; 704{ 705 ENV *env; 706 int isp, ret; 707 708 env = dbp->env; 709 710 /* 711 * If we are in recovery or aborting a transaction, then we 712 * don't need to enforce the rules about dbp's not allowing 713 * transactional operations in non-transactional dbps and 714 * vica-versa. This happens all the time as the dbp during 715 * an abort may be transactional, but we undo operations 716 * outside a transaction since we're aborting. 717 */ 718 if (IS_RECOVERING(env) || F_ISSET(dbp, DB_AM_RECOVER)) 719 return (0); 720 721 /* 722 * Check for common transaction errors: 723 * an operation on a handle whose open commit hasn't completed. 724 * a transaction handle in a non-transactional environment 725 * a transaction handle for a non-transactional database 726 */ 727 if (txn == NULL || F_ISSET(txn, TXN_PRIVATE)) { 728 if (dbp->cur_locker != NULL && 729 dbp->cur_locker->id >= TXN_MINIMUM) 730 goto open_err; 731 732 if (!read_op && F_ISSET(dbp, DB_AM_TXN)) { 733 __db_errx(env, 734 "Transaction not specified for a transactional database"); 735 return (EINVAL); 736 } 737 } else if (F_ISSET(txn, TXN_CDSGROUP)) { 738 if (!CDB_LOCKING(env)) { 739 __db_errx(env, 740 "CDS groups can only be used in a CDS environment"); 741 return (EINVAL); 742 } 743 /* 744 * CDS group handles can be passed to any method, since they 745 * only determine locker IDs. 746 */ 747 return (0); 748 } else { 749 if (!TXN_ON(env)) 750 return (__db_not_txn_env(env)); 751 752 if (!F_ISSET(dbp, DB_AM_TXN)) { 753 __db_errx(env, 754 "Transaction specified for a non-transactional database"); 755 return (EINVAL); 756 } 757 758 if (F_ISSET(txn, TXN_DEADLOCK)) 759 return (__db_txn_deadlock_err(env, txn)); 760 if (dbp->cur_locker != NULL && 761 dbp->cur_locker->id >= TXN_MINIMUM && 762 dbp->cur_locker->id != txn->txnid) { 763 if ((ret = __lock_locker_is_parent(env, 764 dbp->cur_locker, txn->locker, &isp)) != 0) 765 return (ret); 766 if (!isp) 767 goto open_err; 768 } 769 } 770 771 /* 772 * If dbp->associate_locker is not NULL, that means we're in 773 * the middle of a DB->associate with DB_CREATE (i.e., a secondary index 774 * creation). 775 * 776 * In addition to the usual transaction rules, we need to lock out 777 * non-transactional updates that aren't part of the associate (and 778 * thus are using some other locker ID). 779 * 780 * Transactional updates should simply block; from the time we 781 * decide to build the secondary until commit, we'll hold a write 782 * lock on all of its pages, so it should be safe to attempt to update 783 * the secondary in another transaction (presumably by updating the 784 * primary). 785 */ 786 if (!read_op && dbp->associate_locker != NULL && 787 txn != NULL && dbp->associate_locker != assoc_locker) { 788 __db_errx(env, 789 "Operation forbidden while secondary index is being created"); 790 return (EINVAL); 791 } 792 793 /* 794 * Check the txn and dbp are from the same env. 795 */ 796 if (txn != NULL && env != txn->mgrp->env) { 797 __db_errx(env, 798 "Transaction and database from different environments"); 799 return (EINVAL); 800 } 801 802 return (0); 803open_err: 804 __db_errx(env, 805 "Transaction that opened the DB handle is still active"); 806 return (EINVAL); 807} 808 809/* 810 * __db_txn_deadlock_err -- 811 * Transaction has allready been deadlocked. 812 * 813 * PUBLIC: int __db_txn_deadlock_err __P((ENV *, DB_TXN *)); 814 */ 815int 816__db_txn_deadlock_err(env, txn) 817 ENV *env; 818 DB_TXN *txn; 819{ 820 const char *name; 821 822 name = NULL; 823 (void)__txn_get_name(txn, &name); 824 825 __db_errx(env, 826 "%s%sprevious transaction deadlock return not resolved", 827 name == NULL ? "" : name, name == NULL ? "" : ": "); 828 829 return (EINVAL); 830} 831 832/* 833 * __db_not_txn_env -- 834 * DB handle must be in an environment that supports transactions. 835 * 836 * PUBLIC: int __db_not_txn_env __P((ENV *)); 837 */ 838int 839__db_not_txn_env(env) 840 ENV *env; 841{ 842 __db_errx(env, "DB environment not configured for transactions"); 843 return (EINVAL); 844} 845 846/* 847 * __db_rec_toobig -- 848 * Fixed record length exceeded error message. 849 * 850 * PUBLIC: int __db_rec_toobig __P((ENV *, u_int32_t, u_int32_t)); 851 */ 852int 853__db_rec_toobig(env, data_len, fixed_rec_len) 854 ENV *env; 855 u_int32_t data_len, fixed_rec_len; 856{ 857 __db_errx(env, 858 "%lu larger than database's maximum record length %lu", 859 (u_long)data_len, (u_long)fixed_rec_len); 860 return (EINVAL); 861} 862 863/* 864 * __db_rec_repl -- 865 * Fixed record replacement length error message. 866 * 867 * PUBLIC: int __db_rec_repl __P((ENV *, u_int32_t, u_int32_t)); 868 */ 869int 870__db_rec_repl(env, data_size, data_dlen) 871 ENV *env; 872 u_int32_t data_size, data_dlen; 873{ 874 __db_errx(env, 875 "%s: replacement length %lu differs from replaced length %lu", 876 "Record length error", (u_long)data_size, (u_long)data_dlen); 877 return (EINVAL); 878} 879 880#if defined(DIAGNOSTIC) || defined(DEBUG_ROP) || defined(DEBUG_WOP) 881/* 882 * __dbc_logging -- 883 * In DIAGNOSTIC mode, check for bad replication combinations. 884 * 885 * PUBLIC: int __dbc_logging __P((DBC *)); 886 */ 887int 888__dbc_logging(dbc) 889 DBC *dbc; 890{ 891 DB_REP *db_rep; 892 ENV *env; 893 int ret; 894 895 env = dbc->env; 896 db_rep = env->rep_handle; 897 898 ret = LOGGING_ON(env) && 899 !F_ISSET(dbc, DBC_RECOVER) && !IS_REP_CLIENT(env); 900 901 /* 902 * If we're not using replication or running recovery, return. 903 */ 904 if (db_rep == NULL || F_ISSET(dbc, DBC_RECOVER)) 905 return (ret); 906 907#ifndef DEBUG_ROP 908 /* 909 * Only check when DEBUG_ROP is not configured. People often do 910 * non-transactional reads, and debug_rop is going to write 911 * a log record. 912 */ 913 { 914 REP *rep; 915 916 rep = db_rep->region; 917 918 /* 919 * If we're a client and not running recovery or non durably, error. 920 */ 921 if (IS_REP_CLIENT(env) && !F_ISSET(dbc->dbp, DB_AM_NOT_DURABLE)) { 922 __db_errx(env, "dbc_logging: Client update"); 923 goto err; 924 } 925 926#ifndef DEBUG_WOP 927 /* 928 * If DEBUG_WOP is enabled, then we'll generate debugging log records 929 * that are non-transactional. This is OK. 930 */ 931 if (IS_REP_MASTER(env) && 932 dbc->txn == NULL && !F_ISSET(dbc->dbp, DB_AM_NOT_DURABLE)) { 933 __db_errx(env, "Dbc_logging: Master non-txn update"); 934 goto err; 935 } 936#endif 937 938 if (0) { 939err: __db_errx(env, "Rep: flags 0x%lx msg_th %lu", 940 (u_long)rep->flags, (u_long)rep->msg_th); 941 __db_errx(env, "Rep: handle %lu, opcnt %lu", 942 (u_long)rep->handle_cnt, (u_long)rep->op_cnt); 943 __os_abort(env); 944 /* NOTREACHED */ 945 } 946 } 947#endif 948 return (ret); 949} 950#endif 951 952/* 953 * __db_check_lsn -- 954 * Display the log sequence error message. 955 * 956 * PUBLIC: int __db_check_lsn __P((ENV *, DB_LSN *, DB_LSN *)); 957 */ 958int 959__db_check_lsn(env, lsn, prev) 960 ENV *env; 961 DB_LSN *lsn, *prev; 962{ 963 __db_errx(env, 964 "Log sequence error: page LSN %lu %lu; previous LSN %lu %lu", 965 (u_long)(lsn)->file, (u_long)(lsn)->offset, 966 (u_long)(prev)->file, (u_long)(prev)->offset); 967 return (EINVAL); 968} 969 970/* 971 * __db_rdonly -- 972 * Common readonly message. 973 * PUBLIC: int __db_rdonly __P((const ENV *, const char *)); 974 */ 975int 976__db_rdonly(env, name) 977 const ENV *env; 978 const char *name; 979{ 980 __db_errx(env, "%s: attempt to modify a read-only database", name); 981 return (EACCES); 982} 983 984/* 985 * __db_space_err -- 986 * Common out of space message. 987 * PUBLIC: int __db_space_err __P((const DB *)); 988 */ 989int 990__db_space_err(dbp) 991 const DB *dbp; 992{ 993 __db_errx(dbp->env, 994 "%s: file limited to %lu pages", 995 dbp->fname, (u_long)dbp->mpf->mfp->maxpgno); 996 return (ENOSPC); 997} 998 999/* 1000 * __db_failed -- 1001 * Common failed thread message. 1002 * 1003 * PUBLIC: int __db_failed __P((const ENV *, 1004 * PUBLIC: const char *, pid_t, db_threadid_t)); 1005 */ 1006int 1007__db_failed(env, msg, pid, tid) 1008 const ENV *env; 1009 const char *msg; 1010 pid_t pid; 1011 db_threadid_t tid; 1012{ 1013 DB_ENV *dbenv; 1014 char buf[DB_THREADID_STRLEN]; 1015 1016 dbenv = env->dbenv; 1017 1018 __db_errx(env, "Thread/process %s failed: %s", 1019 dbenv->thread_id_string(dbenv, pid, tid, buf), msg); 1020 return (DB_RUNRECOVERY); 1021} 1022