00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "db_config.h"
00011
00012 #ifndef NO_SYSTEM_INCLUDES
00013 #include <sys/types.h>
00014
00015 #include <stdlib.h>
00016 #include <string.h>
00017 #endif
00018
00019 #include "db_int.h"
00020 #include "dbinc/db_page.h"
00021 #include "dbinc/db_am.h"
00022 #include "dbinc/db_shash.h"
00023 #include "dbinc/lock.h"
00024 #include "dbinc/log.h"
00025 #include "dbinc/mp.h"
00026 #include "dbinc/txn.h"
00027
00028 static void __db_msgcall __P((const DB_ENV *, const char *, va_list));
00029 static void __db_msgfile __P((const DB_ENV *, const char *, va_list));
00030
00031
00032
00033
00034
00035
00036
00037 int
00038 __db_fchk(dbenv, name, flags, ok_flags)
00039 DB_ENV *dbenv;
00040 const char *name;
00041 u_int32_t flags, ok_flags;
00042 {
00043 return (LF_ISSET(~ok_flags) ? __db_ferr(dbenv, name, 0) : 0);
00044 }
00045
00046
00047
00048
00049
00050
00051
00052
00053 int
00054 __db_fcchk(dbenv, name, flags, flag1, flag2)
00055 DB_ENV *dbenv;
00056 const char *name;
00057 u_int32_t flags, flag1, flag2;
00058 {
00059 return (LF_ISSET(flag1) &&
00060 LF_ISSET(flag2) ? __db_ferr(dbenv, name, 1) : 0);
00061 }
00062
00063
00064
00065
00066
00067
00068
00069 int
00070 __db_ferr(dbenv, name, iscombo)
00071 const DB_ENV *dbenv;
00072 const char *name;
00073 int iscombo;
00074 {
00075 __db_err(dbenv, "illegal flag %sspecified to %s",
00076 iscombo ? "combination " : "", name);
00077 return (EINVAL);
00078 }
00079
00080
00081
00082
00083
00084
00085
00086 int
00087 __db_fnl(dbenv, name)
00088 const DB_ENV *dbenv;
00089 const char *name;
00090 {
00091 __db_err(dbenv,
00092 "%s: DB_READ_COMMITTED, DB_READ_UNCOMMITTED and DB_RMW require locking",
00093 name);
00094 return (EINVAL);
00095 }
00096
00097
00098
00099
00100
00101
00102
00103 int
00104 __db_pgerr(dbp, pgno, errval)
00105 DB *dbp;
00106 db_pgno_t pgno;
00107 int errval;
00108 {
00109
00110
00111
00112
00113
00114 __db_err(dbp->dbenv,
00115 "unable to create/retrieve page %lu", (u_long)pgno);
00116 return (__db_panic(dbp->dbenv, errval));
00117 }
00118
00119
00120
00121
00122
00123
00124
00125 int
00126 __db_pgfmt(dbenv, pgno)
00127 DB_ENV *dbenv;
00128 db_pgno_t pgno;
00129 {
00130 __db_err(dbenv, "page %lu: illegal page type or format", (u_long)pgno);
00131 return (__db_panic(dbenv, EINVAL));
00132 }
00133
00134 #ifdef DIAGNOSTIC
00135
00136
00137
00138
00139
00140
00141
00142
00143 void
00144 __db_assert(failedexpr, file, line)
00145 const char *failedexpr, *file;
00146 int line;
00147 {
00148 (void)fprintf(stderr,
00149 "__db_assert: \"%s\" failed: file \"%s\", line %d\n",
00150 failedexpr, file, line);
00151 (void)fflush(stderr);
00152
00153
00154 abort();
00155
00156
00157 }
00158 #endif
00159
00160
00161
00162
00163
00164
00165
00166 int
00167 __db_panic_msg(dbenv)
00168 DB_ENV *dbenv;
00169 {
00170 __db_err(dbenv, "PANIC: fatal region error detected; run recovery");
00171
00172 if (dbenv->db_paniccall != NULL)
00173 dbenv->db_paniccall(dbenv, DB_RUNRECOVERY);
00174
00175 return (DB_RUNRECOVERY);
00176 }
00177
00178
00179
00180
00181
00182
00183
00184 int
00185 __db_panic(dbenv, errval)
00186 DB_ENV *dbenv;
00187 int errval;
00188 {
00189 if (dbenv != NULL) {
00190 __db_panic_set(dbenv, 1);
00191
00192 __db_err(dbenv, "PANIC: %s", db_strerror(errval));
00193
00194 if (dbenv->db_paniccall != NULL)
00195 dbenv->db_paniccall(dbenv, errval);
00196 }
00197
00198 #if defined(DIAGNOSTIC) && !defined(CONFIG_TEST)
00199
00200
00201
00202
00203
00204
00205
00206 abort();
00207 #endif
00208
00209
00210
00211
00212
00213
00214 return (DB_RUNRECOVERY);
00215 }
00216
00217
00218
00219
00220
00221
00222
00223 void
00224 __db_panic_set(dbenv, on)
00225 DB_ENV *dbenv;
00226 int on;
00227 {
00228 if (dbenv != NULL && dbenv->reginfo != NULL)
00229 ((REGENV *)
00230 ((REGINFO *)dbenv->reginfo)->primary)->panic = on ? 1 : 0;
00231 }
00232
00233
00234
00235
00236
00237
00238
00239 char *
00240 db_strerror(error)
00241 int error;
00242 {
00243 char *p;
00244
00245 if (error == 0)
00246 return ("Successful return: 0");
00247 if (error > 0) {
00248 if ((p = strerror(error)) != NULL)
00249 return (p);
00250 goto unknown_err;
00251 }
00252
00253
00254
00255
00256
00257
00258
00259
00260 switch (error) {
00261 case DB_BUFFER_SMALL:
00262 return
00263 ("DB_BUFFER_SMALL: User memory too small for return value");
00264 case DB_DONOTINDEX:
00265 return ("DB_DONOTINDEX: Secondary index callback returns null");
00266 case DB_KEYEMPTY:
00267 return ("DB_KEYEMPTY: Non-existent key/data pair");
00268 case DB_KEYEXIST:
00269 return ("DB_KEYEXIST: Key/data pair already exists");
00270 case DB_LOCK_DEADLOCK:
00271 return
00272 ("DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock");
00273 case DB_LOCK_NOTGRANTED:
00274 return ("DB_LOCK_NOTGRANTED: Lock not granted");
00275 case DB_LOG_BUFFER_FULL:
00276 return ("DB_LOG_BUFFER_FULL: In-memory log buffer is full");
00277 case DB_NOSERVER:
00278 return ("DB_NOSERVER: Fatal error, no RPC server");
00279 case DB_NOSERVER_HOME:
00280 return ("DB_NOSERVER_HOME: Home unrecognized at server");
00281 case DB_NOSERVER_ID:
00282 return ("DB_NOSERVER_ID: Identifier unrecognized at server");
00283 case DB_NOTFOUND:
00284 return ("DB_NOTFOUND: No matching key/data pair found");
00285 case DB_OLD_VERSION:
00286 return ("DB_OLDVERSION: Database requires a version upgrade");
00287 case DB_PAGE_NOTFOUND:
00288 return ("DB_PAGE_NOTFOUND: Requested page not found");
00289 case DB_REP_DUPMASTER:
00290 return ("DB_REP_DUPMASTER: A second master site appeared");
00291 case DB_REP_HANDLE_DEAD:
00292 return ("DB_REP_HANDLE_DEAD: Handle is no longer valid");
00293 case DB_REP_HOLDELECTION:
00294 return ("DB_REP_HOLDELECTION: Need to hold an election");
00295 case DB_REP_IGNORE:
00296 return ("DB_REP_IGNORE: Replication record ignored");
00297 case DB_REP_ISPERM:
00298 return ("DB_REP_ISPERM: Permanent record written");
00299 case DB_REP_JOIN_FAILURE:
00300 return
00301 ("DB_REP_JOIN_FAILURE: Unable to join replication group");
00302 case DB_REP_LOCKOUT:
00303 return
00304 ("DB_REP_LOCKOUT: Waiting for replication recovery to complete");
00305 case DB_REP_NEWMASTER:
00306 return ("DB_REP_NEWMASTER: A new master has declared itself");
00307 case DB_REP_NEWSITE:
00308 return ("DB_REP_NEWSITE: A new site has entered the system");
00309 case DB_REP_NOTPERM:
00310 return ("DB_REP_NOTPERM: Permanent log record not written");
00311 case DB_REP_STARTUPDONE:
00312 return
00313 ("DB_REP_STARTUPDONE: Client completed startup synchronization.");
00314 case DB_REP_UNAVAIL:
00315 return ("DB_REP_UNAVAIL: Unable to elect a master");
00316 case DB_RUNRECOVERY:
00317 return ("DB_RUNRECOVERY: Fatal error, run database recovery");
00318 case DB_SECONDARY_BAD:
00319 return
00320 ("DB_SECONDARY_BAD: Secondary index inconsistent with primary");
00321 case DB_VERIFY_BAD:
00322 return ("DB_VERIFY_BAD: Database verification failed");
00323 case DB_VERSION_MISMATCH:
00324 return
00325 ("DB_VERSION_MISMATCH: Database environment version mismatch");
00326 default:
00327 break;
00328 }
00329
00330 unknown_err: {
00331
00332
00333
00334
00335
00336
00337 static char ebuf[40];
00338
00339 (void)snprintf(ebuf, sizeof(ebuf), "Unknown error: %d", error);
00340 return (ebuf);
00341 }
00342 }
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352 void
00353 #ifdef STDC_HEADERS
00354 __db_err(const DB_ENV *dbenv, const char *fmt, ...)
00355 #else
00356 __db_err(dbenv, fmt, va_alist)
00357 const DB_ENV *dbenv;
00358 const char *fmt;
00359 va_dcl
00360 #endif
00361 {
00362 DB_REAL_ERR(dbenv, 0, 0, 0, fmt);
00363 }
00364
00365
00366
00367
00368
00369
00370
00371
00372 void
00373 __db_errcall(dbenv, error, error_set, fmt, ap)
00374 const DB_ENV *dbenv;
00375 int error, error_set;
00376 const char *fmt;
00377 va_list ap;
00378 {
00379 char *p;
00380 char buf[2048];
00381
00382 p = buf;
00383 if (fmt != NULL)
00384 p += vsnprintf(buf, sizeof(buf), fmt, ap);
00385 if (error_set)
00386 p += snprintf(p,
00387 sizeof(buf) - (size_t)(p - buf), ": %s",
00388 db_strerror(error));
00389
00390 dbenv->db_errcall(dbenv, dbenv->db_errpfx, buf);
00391 }
00392
00393
00394
00395
00396
00397
00398
00399
00400 void
00401 __db_errfile(dbenv, error, error_set, fmt, ap)
00402 const DB_ENV *dbenv;
00403 int error, error_set;
00404 const char *fmt;
00405 va_list ap;
00406 {
00407 FILE *fp;
00408
00409 fp = dbenv == NULL ||
00410 dbenv->db_errfile == NULL ? stderr : dbenv->db_errfile;
00411
00412 if (dbenv != NULL && dbenv->db_errpfx != NULL)
00413 (void)fprintf(fp, "%s: ", dbenv->db_errpfx);
00414 if (fmt != NULL) {
00415 (void)vfprintf(fp, fmt, ap);
00416 if (error_set)
00417 (void)fprintf(fp, ": ");
00418 }
00419 if (error_set)
00420 (void)fprintf(fp, "%s", db_strerror(error));
00421 (void)fprintf(fp, "\n");
00422 (void)fflush(fp);
00423 }
00424
00425
00426
00427
00428
00429
00430
00431
00432 void
00433 #ifdef STDC_HEADERS
00434 __db_msgadd(DB_ENV *dbenv, DB_MSGBUF *mbp, const char *fmt, ...)
00435 #else
00436 __db_msgadd(dbenv, mbp, fmt, va_alist)
00437 DB_ENV *dbenv;
00438 DB_MSGBUF *mbp;
00439 const char *fmt;
00440 va_dcl
00441 #endif
00442 {
00443 va_list ap;
00444 size_t len, olen;
00445 char buf[2048];
00446
00447 #ifdef STDC_HEADERS
00448 va_start(ap, fmt);
00449 #else
00450 va_start(ap);
00451 #endif
00452 len = (size_t)vsnprintf(buf, sizeof(buf), fmt, ap);
00453
00454 va_end(ap);
00455
00456
00457
00458
00459
00460
00461 olen = (size_t)(mbp->cur - mbp->buf);
00462 if (olen + len >= mbp->len) {
00463 if (__os_realloc(dbenv, mbp->len + len + 256, &mbp->buf))
00464 return;
00465 mbp->len += (len + 256);
00466 mbp->cur = mbp->buf + olen;
00467 }
00468
00469 memcpy(mbp->cur, buf, len + 1);
00470 mbp->cur += len;
00471 }
00472
00473
00474
00475
00476
00477
00478
00479
00480 void
00481 #ifdef STDC_HEADERS
00482 __db_msg(const DB_ENV *dbenv, const char *fmt, ...)
00483 #else
00484 __db_msg(dbenv, fmt, va_alist)
00485 const DB_ENV *dbenv;
00486 const char *fmt;
00487 va_dcl
00488 #endif
00489 {
00490 DB_REAL_MSG(dbenv, fmt);
00491 }
00492
00493
00494
00495
00496
00497 static void
00498 __db_msgcall(dbenv, fmt, ap)
00499 const DB_ENV *dbenv;
00500 const char *fmt;
00501 va_list ap;
00502 {
00503 char buf[2048];
00504
00505 (void)vsnprintf(buf, sizeof(buf), fmt, ap);
00506
00507 dbenv->db_msgcall(dbenv, buf);
00508 }
00509
00510
00511
00512
00513
00514 static void
00515 __db_msgfile(dbenv, fmt, ap)
00516 const DB_ENV *dbenv;
00517 const char *fmt;
00518 va_list ap;
00519 {
00520 FILE *fp;
00521
00522 fp = dbenv == NULL ||
00523 dbenv->db_msgfile == NULL ? stdout : dbenv->db_msgfile;
00524 (void)vfprintf(fp, fmt, ap);
00525
00526 (void)fprintf(fp, "\n");
00527 (void)fflush(fp);
00528 }
00529
00530
00531
00532
00533
00534
00535 int
00536 __db_unknown_flag(dbenv, routine, flag)
00537 DB_ENV *dbenv;
00538 char *routine;
00539 u_int32_t flag;
00540 {
00541 __db_err(dbenv, "%s: Unknown flag: %#x", routine, (u_int)flag);
00542 DB_ASSERT(0);
00543 return (EINVAL);
00544 }
00545
00546
00547
00548
00549
00550
00551 int
00552 __db_unknown_type(dbenv, routine, type)
00553 DB_ENV *dbenv;
00554 char *routine;
00555 DBTYPE type;
00556 {
00557 __db_err(dbenv,
00558 "%s: Unexpected DB type: %s", routine, __db_dbtype_to_string(type));
00559
00560 DB_ASSERT(0);
00561 return (EINVAL);
00562 }
00563
00564
00565
00566
00567
00568
00569
00570 int
00571 __db_check_txn(dbp, txn, assoc_lid, read_op)
00572 DB *dbp;
00573 DB_TXN *txn;
00574 u_int32_t assoc_lid;
00575 int read_op;
00576 {
00577 DB_ENV *dbenv;
00578 int isp, ret;
00579
00580 dbenv = dbp->dbenv;
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590 if (IS_RECOVERING(dbenv) || F_ISSET(dbp, DB_AM_RECOVER))
00591 return (0);
00592
00593
00594
00595
00596
00597
00598
00599 if (txn == NULL) {
00600 if (dbp->cur_lid >= TXN_MINIMUM)
00601 goto open_err;
00602 } else {
00603 if (!TXN_ON(dbenv))
00604 return (__db_not_txn_env(dbenv));
00605
00606 if (!F_ISSET(dbp, DB_AM_TXN)) {
00607 __db_err(dbenv,
00608 "Transaction specified for a DB handle opened outside a transaction");
00609 return (EINVAL);
00610 }
00611
00612 if (F_ISSET(txn, TXN_DEADLOCK)) {
00613 __db_err(dbenv,
00614 "Previous deadlock return not resolved");
00615 return (EINVAL);
00616 }
00617 if (dbp->cur_lid >= TXN_MINIMUM && dbp->cur_lid != txn->txnid) {
00618 if ((ret = __lock_locker_is_parent(dbenv,
00619 dbp->cur_lid, txn->txnid, &isp)) != 0)
00620 return (ret);
00621 if (!isp)
00622 goto open_err;
00623 }
00624 }
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641 if (!read_op && dbp->associate_lid != DB_LOCK_INVALIDID &&
00642 txn != NULL && dbp->associate_lid != assoc_lid) {
00643 __db_err(dbenv,
00644 "Operation forbidden while secondary index is being created");
00645 return (EINVAL);
00646 }
00647
00648
00649
00650
00651 if (txn != NULL && dbenv != txn->mgrp->dbenv) {
00652 __db_err(dbenv,
00653 "Transaction and database from different environments");
00654 return (EINVAL);
00655 }
00656
00657 return (0);
00658 open_err:
00659 __db_err(dbenv,
00660 "Transaction that opened the DB handle is still active");
00661 return (EINVAL);
00662 }
00663
00664
00665
00666
00667
00668
00669
00670 int
00671 __db_not_txn_env(dbenv)
00672 DB_ENV *dbenv;
00673 {
00674 __db_err(dbenv, "DB environment not configured for transactions");
00675 return (EINVAL);
00676 }
00677
00678
00679
00680
00681
00682
00683
00684 int
00685 __db_rec_toobig(dbenv, data_len, fixed_rec_len)
00686 DB_ENV *dbenv;
00687 u_int32_t data_len, fixed_rec_len;
00688 {
00689 __db_err(dbenv, "%s: length of %lu larger than database's value of %lu",
00690 "Record length error", (u_long)data_len, (u_long)fixed_rec_len);
00691 return (EINVAL);
00692 }
00693
00694
00695
00696
00697
00698
00699
00700 int
00701 __db_rec_repl(dbenv, data_size, data_dlen)
00702 DB_ENV *dbenv;
00703 u_int32_t data_size, data_dlen;
00704 {
00705 __db_err(dbenv,
00706 "%s: replacement length %lu differs from replaced length %lu",
00707 "Record length error", (u_long)data_size, (u_long)data_dlen);
00708 return (EINVAL);
00709 }
00710
00711 #if defined(DIAGNOSTIC) || defined(DEBUG_ROP) || defined(DEBUG_WOP)
00712
00713
00714
00715
00716
00717
00718 int
00719 __dbc_logging(dbc)
00720 DBC *dbc;
00721 {
00722 DB_ENV *dbenv;
00723 DB_REP *db_rep;
00724 int ret;
00725
00726 dbenv = dbc->dbp->dbenv;
00727 db_rep = dbenv->rep_handle;
00728
00729 ret = LOGGING_ON(dbenv) &&
00730 !F_ISSET(dbc, DBC_RECOVER) && !IS_REP_CLIENT(dbenv);
00731
00732
00733
00734
00735 if (db_rep == NULL || F_ISSET(dbc, DBC_RECOVER))
00736 return (ret);
00737
00738 #ifndef DEBUG_ROP
00739
00740
00741
00742
00743
00744 {
00745 REP *rep;
00746
00747 rep = db_rep->region;
00748
00749
00750
00751
00752 if (IS_REP_CLIENT(dbenv) && !F_ISSET(dbc->dbp, DB_AM_CL_WRITER)) {
00753 __db_err(dbenv, "Dbc_logging: Client update");
00754 goto err;
00755 }
00756 if (IS_REP_MASTER(dbenv) && dbc->txn == NULL) {
00757 __db_err(dbenv, "Dbc_logging: Master non-txn update");
00758 goto err;
00759 }
00760 if (0) {
00761 err: __db_err(dbenv, "Rep: flags 0x%lx msg_th %lu, start_th %d",
00762 (u_long)rep->flags, (u_long)rep->msg_th, rep->start_th);
00763 __db_err(dbenv, "Rep: handle %lu, opcnt %lu, in_rec %d",
00764 (u_long)rep->handle_cnt, (u_long)rep->op_cnt,
00765 rep->in_recovery);
00766 abort();
00767 }
00768 }
00769 #endif
00770 return (ret);
00771 }
00772 #endif
00773
00774
00775
00776
00777
00778
00779
00780 int
00781 __db_check_lsn(dbenv, lsn, prev)
00782 DB_ENV *dbenv;
00783 DB_LSN *lsn, *prev;
00784 {
00785 __db_err(dbenv,
00786 "Log sequence error: page LSN %lu %lu; previous LSN %lu %lu",
00787 (u_long)(lsn)->file, (u_long)(lsn)->offset,
00788 (u_long)(prev)->file, (u_long)(prev)->offset);
00789 return (EINVAL);
00790 }
00791
00792
00793
00794
00795
00796
00797 int
00798 __db_rdonly(dbenv, name)
00799 const DB_ENV *dbenv;
00800 const char *name;
00801 {
00802 __db_err(dbenv, "%s: attempt to modify a read-only database", name);
00803 return (EACCES);
00804 }
00805
00806
00807
00808
00809
00810
00811 int
00812 __db_space_err(dbp)
00813 const DB *dbp;
00814 {
00815 __db_err(dbp->dbenv,
00816 "%s: file limited to %lu pages",
00817 dbp->fname, (u_long)dbp->mpf->mfp->maxpgno);
00818 return (ENOSPC);
00819 }
00820
00821
00822
00823
00824
00825
00826
00827
00828 int
00829 __db_failed(dbenv, msg, pid, tid)
00830 const DB_ENV *dbenv;
00831 const char *msg;
00832 pid_t pid;
00833 db_threadid_t tid;
00834 {
00835 char buf[DB_THREADID_STRLEN];
00836
00837 __db_err(dbenv, "Thread/process %s failed: %s",
00838 dbenv->thread_id_string((DB_ENV*)dbenv, pid, tid, buf), msg);
00839 return (DB_RUNRECOVERY);
00840 }