db

db_err.c

Go to the documentation of this file.
00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 1996, 1997, 1998, 1999, 2000
00005  * Sleepycat Software. All rights reserved.
00006  */
00007 
00008 #include "config.h"
00009 
00010 #ifndef lint
00011 static const char revid[] = "$Id: db__err_8c-source.html,v 1.1 2008年06月08日 10:17:27 sebdiaz Exp $";
00012 #endif /* not lint */
00013 
00014 #ifndef NO_SYSTEM_INCLUDES
00015 #include <sys/types.h>
00016 
00017 #include <errno.h>
00018 #include <stdio.h>
00019 #include <stdlib.h>
00020 #include <string.h>
00021 #endif
00022 
00023 #include "db_int.h"
00024 #include "db_shash.h"
00025 #include "lock.h"
00026 #include "lock_ext.h"
00027 #include "log.h"
00028 #include "log_ext.h"
00029 #include "mp.h"
00030 #include "mp_ext.h"
00031 #include "txn.h"
00032 #include "txn_ext.h"
00033 #include "common_ext.h"
00034 #include "db_auto.h"
00035 
00036 static void __db_errcall __P((const DB_ENV *, int, int, const char *, va_list));
00037 static void __db_errfile __P((const DB_ENV *, int, int, const char *, va_list));
00038 
00039 /*
00040  * CDB___db_fchk --
00041  * General flags checking routine.
00042  *
00043  * PUBLIC: int CDB___db_fchk __P((DB_ENV *, const char *, u_int32_t, u_int32_t));
00044  */
00045 int
00046 CDB___db_fchk(dbenv, name, flags, ok_flags)
00047 DB_ENV *dbenv;
00048 const char *name;
00049 u_int32_t flags, ok_flags;
00050 {
00051 return (LF_ISSET(~ok_flags) ? CDB___db_ferr(dbenv, name, 0) : 0);
00052 }
00053 
00054 /*
00055  * CDB___db_fcchk --
00056  * General combination flags checking routine.
00057  *
00058  * PUBLIC: int CDB___db_fcchk
00059  * PUBLIC: __P((DB_ENV *, const char *, u_int32_t, u_int32_t, u_int32_t));
00060  */
00061 int
00062 CDB___db_fcchk(dbenv, name, flags, flag1, flag2)
00063 DB_ENV *dbenv;
00064 const char *name;
00065 u_int32_t flags, flag1, flag2;
00066 {
00067 return (LF_ISSET(flag1) &&
00068 LF_ISSET(flag2) ? CDB___db_ferr(dbenv, name, 1) : 0);
00069 }
00070 
00071 /*
00072  * CDB___db_ferr --
00073  * Common flag errors.
00074  *
00075  * PUBLIC: int CDB___db_ferr __P((const DB_ENV *, const char *, int));
00076  */
00077 int
00078 CDB___db_ferr(dbenv, name, iscombo)
00079 const DB_ENV *dbenv;
00080 const char *name;
00081 int iscombo;
00082 {
00083 CDB___db_err(dbenv, "illegal flag %sspecified to %s",
00084 iscombo ? "combination " : "", name);
00085 return (EINVAL);
00086 }
00087 
00088 /*
00089  * CDB___db_pgerr --
00090  * Error when unable to retrieve a specified page.
00091  *
00092  * PUBLIC: int CDB___db_pgerr __P((DB *, db_pgno_t));
00093  */
00094 int
00095 CDB___db_pgerr(dbp, pgno)
00096 DB *dbp;
00097 db_pgno_t pgno;
00098 {
00099 /*
00100  * Three things are certain:
00101  * Death, taxes, and lost data.
00102  * Guess which has occurred.
00103  */
00104 CDB___db_err(dbp->dbenv,
00105 "unable to create/retrieve page %lu", (u_long)pgno);
00106 return (CDB___db_panic(dbp->dbenv, EIO));
00107 }
00108 
00109 /*
00110  * CDB___db_pgfmt --
00111  * Error when a page has the wrong format.
00112  *
00113  * PUBLIC: int CDB___db_pgfmt __P((DB *, db_pgno_t));
00114  */
00115 int
00116 CDB___db_pgfmt(dbp, pgno)
00117 DB *dbp;
00118 db_pgno_t pgno;
00119 {
00120 CDB___db_err(dbp->dbenv,
00121 "page %lu: illegal page type or format", (u_long)pgno);
00122 return (CDB___db_panic(dbp->dbenv, EINVAL));
00123 }
00124 
00125 /*
00126  * CDB___db_eopnotsup --
00127  * Common operation not supported message.
00128  *
00129  * PUBLIC: int CDB___db_eopnotsup __P((const DB_ENV *));
00130  */
00131 int
00132 CDB___db_eopnotsup(dbenv)
00133 const DB_ENV *dbenv;
00134 {
00135 CDB___db_err(dbenv, "operation not supported");
00136 #ifdef EOPNOTSUPP
00137 return (EOPNOTSUPP);
00138 #else
00139 return (EINVAL);
00140 #endif
00141 }
00142 
00143 #ifdef DIAGNOSTIC
00144 /*
00145  * __db_assert --
00146  * Error when an assertion fails. Only checked if #DIAGNOSTIC defined.
00147  *
00148  * PUBLIC: #ifdef DIAGNOSTIC
00149  * PUBLIC: void __db_assert __P((const char *, const char *, int));
00150  * PUBLIC: #endif
00151  */
00152 void
00153 __db_assert(failedexpr, file, line)
00154 const char *failedexpr, *file;
00155 int line;
00156 {
00157 (void)fprintf(stderr,
00158 "__db_assert: \"%s\" failed: file \"%s\", line %d\n",
00159 failedexpr, file, line);
00160 fflush(stderr);
00161 
00162 /* We want a stack trace of how this could possibly happen. */
00163 abort();
00164 
00165 /* NOTREACHED */
00166 }
00167 #endif
00168 
00169 /*
00170  * CDB___db_panic_msg --
00171  * Just report that someone else paniced.
00172  *
00173  * PUBLIC: int CDB___db_panic_msg __P((DB_ENV *));
00174  */
00175 int
00176 CDB___db_panic_msg(dbenv)
00177 DB_ENV *dbenv;
00178 {
00179 CDB___db_err(dbenv, "region error detected; run recovery.");
00180 return (DB_RUNRECOVERY);
00181 }
00182 
00183 /*
00184  * CDB___db_panic --
00185  * Lock out the tree due to unrecoverable error.
00186  *
00187  * PUBLIC: int CDB___db_panic __P((DB_ENV *, int));
00188  */
00189 int
00190 CDB___db_panic(dbenv, errval)
00191 DB_ENV *dbenv;
00192 int errval;
00193 {
00194 /*
00195  * Drop core if we're running with DIAGNOSTIC defined. Do so before
00196  * we set the panic bits, it's easier to run diagnostic tools on the
00197  * tree then.
00198  */
00199 DB_ASSERT(0);
00200 
00201 if (dbenv != NULL) {
00202 ((REGENV *)((REGINFO *)dbenv->reginfo)->addr)->panic = 1;
00203 
00204 dbenv->db_panic = errval;
00205 
00206 CDB___db_err(dbenv, "PANIC: %s", CDB_db_strerror(errval));
00207 
00208 if (dbenv->db_paniccall != NULL)
00209 dbenv->db_paniccall(dbenv, errval);
00210 }
00211 
00212 /*
00213  * Chaos reigns within.
00214  * Reflect, repent, and reboot.
00215  * Order shall return.
00216  */
00217 return (DB_RUNRECOVERY);
00218 }
00219 
00220 /*
00221  * CDB_db_strerror --
00222  * ANSI C strerror(3) for DB.
00223  */
00224 char *
00225 CDB_db_strerror(error)
00226 int error;
00227 {
00228 if (error == 0)
00229 return ("Successful return: 0");
00230 if (error > 0)
00231 return (strerror(error));
00232 
00233 /*
00234  * !!!
00235  * The Tcl API requires that some of these return strings be compared
00236  * against strings stored in application scripts. So, any of these
00237  * errors that do not invariably result in a Tcl exception may not be
00238  * altered.
00239  */
00240 switch (error) {
00241 case DB_INCOMPLETE:
00242 return ("DB_INCOMPLETE: Cache flush was unable to complete");
00243 case DB_KEYEMPTY:
00244 return ("DB_KEYEMPTY: Non-existent key/data pair");
00245 case DB_KEYEXIST:
00246 return ("DB_KEYEXIST: Key/data pair already exists");
00247 case DB_LOCK_DEADLOCK:
00248 return
00249 ("DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock");
00250 case DB_LOCK_NOTGRANTED:
00251 return ("DB_LOCK_NOTGRANTED: Lock not granted");
00252 case DB_NOSERVER:
00253 return ("DB_NOSERVER: Fatal error, no server");
00254 case DB_NOSERVER_HOME:
00255 return ("DB_NOSERVER_HOME: Home unrecognized at server");
00256 case DB_NOSERVER_ID:
00257 return ("DB_NOSERVER_ID: Identifier unrecognized at server");
00258 case DB_NOTFOUND:
00259 return ("DB_NOTFOUND: No matching key/data pair found");
00260 case DB_OLD_VERSION:
00261 return ("DB_OLDVERSION: Database requires a version upgrade");
00262 case DB_RUNRECOVERY:
00263 return ("DB_RUNRECOVERY: Fatal error, run database recovery");
00264 case DB_VERIFY_BAD:
00265 return ("DB_VERIFY_BAD: Database verification failed");
00266 default: {
00267 /*
00268  * !!!
00269  * Room for a 64-bit number + slop. This buffer is only used
00270  * if we're given an unknown error, which should never happen.
00271  * Note, however, we're no longer thread-safe if it does.
00272  */
00273 static char ebuf[40];
00274 
00275 (void)snprintf(ebuf, sizeof(ebuf), "Unknown error: %d", error);
00276 return(ebuf);
00277 }
00278 }
00279 }
00280 
00281 /*
00282  * CDB___db_err --
00283  * Standard DB error routine. The same as db_errx, except that we
00284  * don't write to stderr if no output mechanism was specified.
00285  *
00286  * PUBLIC: #ifdef __STDC__
00287  * PUBLIC: void CDB___db_err __P((const DB_ENV *, const char *, ...));
00288  * PUBLIC: #else
00289  * PUBLIC: void CDB___db_err();
00290  * PUBLIC: #endif
00291  */
00292 void
00293 #ifdef __STDC__
00294 CDB___db_err(const DB_ENV *dbenv, const char *fmt, ...)
00295 #else
00296 CDB___db_err(dbenv, fmt, va_alist)
00297 const DB_ENV *dbenv;
00298 const char *fmt;
00299 va_dcl
00300 #endif
00301 {
00302 va_list ap;
00303 
00304 /*
00305  XXX
00306  Log the message.
00307 
00308  It would be nice to automatically log the error into the log files
00309  if the application is configured for logging. The problem is that
00310  if we currently hold the log region mutex, we will self-deadlock.
00311  Leave all the structure in place, but turned off. I'd like to fix
00312  this in the future by detecting if we have the log region already
00313  locked (e.g., a flag in the environment handle), or perhaps even
00314  have a finer granularity so that the only calls to CDB___db_err we
00315  can't log are those made while we have the current log buffer
00316  locked, or perhaps have a separate buffer into which we log error
00317  messages.
00318 
00319 #ifdef __STDC__
00320  va_start(ap, fmt);
00321 #else
00322  va_start(ap);
00323 #endif
00324  CDB___db_real_log(dbenv, NULL, "db_err", 0, fmt, ap);
00325 
00326  va_end(ap);
00327 #endif
00328 */
00329 
00330 /* Tell the application. */
00331 #ifdef __STDC__
00332 va_start(ap, fmt);
00333 #else
00334 va_start(ap);
00335 #endif
00336 CDB___db_real_err(dbenv, 0, 0, 0, fmt, ap);
00337 
00338 va_end(ap);
00339 }
00340 
00341 /*
00342  * CDB___db_real_err --
00343  * All the DB error routines end up here.
00344  *
00345  * PUBLIC: void CDB___db_real_err
00346  * PUBLIC: __P((const DB_ENV *, int, int, int, const char *, va_list));
00347  */
00348 void
00349 CDB___db_real_err(dbenv, error, error_set, stderr_default, fmt, ap)
00350 const DB_ENV *dbenv;
00351 int error, error_set, stderr_default;
00352 const char *fmt;
00353 va_list ap;
00354 {
00355 if (dbenv != NULL && dbenv->db_errcall != NULL)
00356 __db_errcall(dbenv, error, error_set, fmt, ap);
00357 
00358 if (dbenv != NULL && dbenv->db_errfile != NULL)
00359 __db_errfile(dbenv, error, error_set, fmt, ap);
00360 
00361 if (stderr_default && (dbenv == NULL ||
00362 (dbenv->db_errcall == NULL && dbenv->db_errfile == NULL)))
00363 __db_errfile(NULL, error, error_set, fmt, ap);
00364 }
00365 
00366 /*
00367  * __db_errcall --
00368  * Do the error message work for callback functions.
00369  */
00370 static void
00371 __db_errcall(dbenv, error, error_set, fmt, ap)
00372 const DB_ENV *dbenv;
00373 int error, error_set;
00374 const char *fmt;
00375 va_list ap;
00376 {
00377 char *p;
00378 char __errbuf[2048]; /* !!!: END OF THE STACK DON'T TRUST SPRINTF. */
00379 
00380 p = __errbuf;
00381 if (fmt != NULL) {
00382 p += vsnprintf(__errbuf, sizeof(__errbuf), fmt, ap);
00383 if (error_set) {
00384 *p++ = ':';
00385 *p++ = ' ';
00386 }
00387 }
00388 if (error_set)
00389 (void)strcpy(p, CDB_db_strerror(error));
00390 
00391 dbenv->db_errcall(dbenv->db_errpfx, __errbuf);
00392 }
00393 
00394 /*
00395  * __db_errfile --
00396  * Do the error message work for FILE *s.
00397  */
00398 static void
00399 __db_errfile(dbenv, error, error_set, fmt, ap)
00400 const DB_ENV *dbenv;
00401 int error, error_set;
00402 const char *fmt;
00403 va_list ap;
00404 {
00405 FILE *fp;
00406 
00407 fp = dbenv == NULL ||
00408 dbenv->db_errfile == NULL ? stderr : dbenv->db_errfile;
00409 
00410 if (dbenv != NULL && dbenv->db_errpfx != NULL)
00411 (void)fprintf(fp, "%s: ", dbenv->db_errpfx);
00412 if (fmt != NULL) {
00413 (void)vfprintf(fp, fmt, ap);
00414 if (error_set)
00415 (void)fprintf(fp, ": ");
00416 }
00417 if (error_set)
00418 (void)fprintf(fp, "%s", CDB_db_strerror(error));
00419 (void)fprintf(fp, "\n");
00420 (void)fflush(fp);
00421 }
00422 
00423 /*
00424  * CDB___db_logmsg --
00425  * Write information into the DB log.
00426  *
00427  * PUBLIC: #ifdef __STDC__
00428  * PUBLIC: void CDB___db_logmsg __P((const DB_ENV *,
00429  * PUBLIC: DB_TXN *, const char *, u_int32_t, const char *, ...));
00430  * PUBLIC: #else
00431  * PUBLIC: void CDB___db_logmsg();
00432  * PUBLIC: #endif
00433  */
00434 void
00435 #ifdef __STDC__
00436 CDB___db_logmsg(const DB_ENV *dbenv,
00437 DB_TXN *txnid, const char *opname, u_int32_t flags, const char *fmt, ...)
00438 #else
00439 CDB___db_logmsg(dbenv, txnid, opname, flags, fmt, va_alist)
00440 const DB_ENV *dbenv;
00441 DB_TXN *txnid;
00442 const char *opname, *fmt;
00443 u_int32_t flags;
00444 va_dcl
00445 #endif
00446 {
00447 va_list ap;
00448 
00449 #ifdef __STDC__
00450 va_start(ap, fmt);
00451 #else
00452 va_start(ap);
00453 #endif
00454 CDB___db_real_log(dbenv, txnid, opname, flags, fmt, ap);
00455 
00456 va_end(ap);
00457 }
00458 
00459 /*
00460  * CDB___db_real_log --
00461  * Write information into the DB log.
00462  *
00463  * PUBLIC: #ifdef __STDC__
00464  * PUBLIC: void CDB___db_real_log __P((const DB_ENV *,
00465  * PUBLIC: DB_TXN *, const char *, u_int32_t, const char *, va_list ap));
00466  * PUBLIC: #else
00467  * PUBLIC: void CDB___db_real_log();
00468  * PUBLIC: #endif
00469  */
00470 void
00471 #ifdef __STDC__
00472 CDB___db_real_log(const DB_ENV *dbenv, DB_TXN *txnid,
00473 const char *opname, u_int32_t flags, const char *fmt, va_list ap)
00474 #else
00475 CDB___db_real_log(dbenv, txnid, opname, flags, fmt, ap)
00476 const DB_ENV *dbenv;
00477 DB_TXN *txnid;
00478 const char *opname, *fmt;
00479 u_int32_t flags;
00480 va_list ap;
00481 #endif
00482 {
00483 DBT opdbt, msgdbt;
00484 DB_LSN lsn;
00485 char __logbuf[2048]; /* !!!: END OF THE STACK DON'T TRUST SPRINTF. */
00486 
00487 if (!LOGGING_ON(dbenv))
00488 return;
00489 
00490 memset(&opdbt, 0, sizeof(opdbt));
00491 opdbt.data = (void *)opname;
00492 opdbt.size = strlen(opname) + 1;
00493 
00494 memset(&msgdbt, 0, sizeof(msgdbt));
00495 msgdbt.data = __logbuf;
00496 msgdbt.size = vsnprintf(__logbuf, sizeof(__logbuf), fmt, ap);
00497 
00498 /*
00499  * XXX
00500  * Explicitly discard the const. Otherwise, we have to const DB_ENV
00501  * references throughout the logging subsystem.
00502  */
00503 CDB___db_debug_log(
00504 (DB_ENV *)dbenv, txnid, &lsn, flags, &opdbt, -1, &msgdbt, NULL, 0);
00505 }
00506 
00507 /*
00508  * CDB___db_unknown_flag -- report internal error
00509  *
00510  * PUBLIC: int CDB___db_unknown_flag __P((DB_ENV *, char *, u_int32_t));
00511  */
00512 int
00513 CDB___db_unknown_flag(dbenv, routine, flag)
00514 DB_ENV *dbenv;
00515 char *routine;
00516 u_int32_t flag;
00517 {
00518 CDB___db_err(dbenv, "%s: Unknown flag: 0x%x", routine, flag);
00519 DB_ASSERT(0);
00520 return (EINVAL);
00521 }
00522 
00523 /*
00524  * CDB___db_unknown_type -- report internal error
00525  *
00526  * PUBLIC: int CDB___db_unknown_type __P((DB_ENV *, char *, u_int32_t));
00527  */
00528 int
00529 CDB___db_unknown_type(dbenv, routine, type)
00530 DB_ENV *dbenv;
00531 char *routine;
00532 u_int32_t type;
00533 {
00534 CDB___db_err(dbenv, "%s: Unknown db type: 0x%x", routine, type);
00535 DB_ASSERT(0);
00536 return (EINVAL);
00537 }
00538 
00539 /*
00540  * CDB___db_child_active_err -- cannot do an update with active child
00541  *
00542  * PUBLIC: int CDB___db_child_active_err __P((DB_ENV *));
00543  */
00544 int
00545 CDB___db_child_active_err(dbenv)
00546 DB_ENV *dbenv;
00547 {
00548 CDB___db_err(dbenv, "Child transaction is active");
00549 return (EPERM);
00550 }

Generated on Sun Jun 8 10:56:36 2008 for GNUmifluz by doxygen 1.5.5

AltStyle によって変換されたページ (->オリジナル) /