db_err.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:12k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1996, 1997, 1998, 1999, 2000
  5.  * Sleepycat Software.  All rights reserved.
  6.  */
  7. #include "db_config.h"
  8. #ifndef lint
  9. static const char revid[] = "$Id: db_err.c,v 11.38 2001/01/22 21:50:25 sue Exp $";
  10. #endif /* not lint */
  11. #ifndef NO_SYSTEM_INCLUDES
  12. #include <sys/types.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #endif
  17. #include "db_int.h"
  18. #include "db_shash.h"
  19. #include "lock.h"
  20. #include "lock_ext.h"
  21. #include "log.h"
  22. #include "log_ext.h"
  23. #include "mp.h"
  24. #include "mp_ext.h"
  25. #include "txn.h"
  26. #include "txn_ext.h"
  27. #include "clib_ext.h"
  28. #include "common_ext.h"
  29. #include "db_auto.h"
  30. static void __db_errcall __P((const DB_ENV *, int, int, const char *, va_list));
  31. static void __db_errfile __P((const DB_ENV *, int, int, const char *, va_list));
  32. /*
  33.  * __db_fchk --
  34.  * General flags checking routine.
  35.  *
  36.  * PUBLIC: int __db_fchk __P((DB_ENV *, const char *, u_int32_t, u_int32_t));
  37.  */
  38. int
  39. __db_fchk(dbenv, name, flags, ok_flags)
  40. DB_ENV *dbenv;
  41. const char *name;
  42. u_int32_t flags, ok_flags;
  43. {
  44. return (LF_ISSET(~ok_flags) ? __db_ferr(dbenv, name, 0) : 0);
  45. }
  46. /*
  47.  * __db_fcchk --
  48.  * General combination flags checking routine.
  49.  *
  50.  * PUBLIC: int __db_fcchk
  51.  * PUBLIC:    __P((DB_ENV *, const char *, u_int32_t, u_int32_t, u_int32_t));
  52.  */
  53. int
  54. __db_fcchk(dbenv, name, flags, flag1, flag2)
  55. DB_ENV *dbenv;
  56. const char *name;
  57. u_int32_t flags, flag1, flag2;
  58. {
  59. return (LF_ISSET(flag1) &&
  60.     LF_ISSET(flag2) ? __db_ferr(dbenv, name, 1) : 0);
  61. }
  62. /*
  63.  * __db_ferr --
  64.  * Common flag errors.
  65.  *
  66.  * PUBLIC: int __db_ferr __P((const DB_ENV *, const char *, int));
  67.  */
  68. int
  69. __db_ferr(dbenv, name, iscombo)
  70. const DB_ENV *dbenv;
  71. const char *name;
  72. int iscombo;
  73. {
  74. __db_err(dbenv, "illegal flag %sspecified to %s",
  75.     iscombo ? "combination " : "", name);
  76. return (EINVAL);
  77. }
  78. /*
  79.  * __db_pgerr --
  80.  * Error when unable to retrieve a specified page.
  81.  *
  82.  * PUBLIC: int __db_pgerr __P((DB *, db_pgno_t));
  83.  */
  84. int
  85. __db_pgerr(dbp, pgno)
  86. DB *dbp;
  87. db_pgno_t pgno;
  88. {
  89. /*
  90.  * Three things are certain:
  91.  * Death, taxes, and lost data.
  92.  * Guess which has occurred.
  93.  */
  94. __db_err(dbp->dbenv,
  95.     "unable to create/retrieve page %lu", (u_long)pgno);
  96. return (__db_panic(dbp->dbenv, EIO));
  97. }
  98. /*
  99.  * __db_pgfmt --
  100.  * Error when a page has the wrong format.
  101.  *
  102.  * PUBLIC: int __db_pgfmt __P((DB *, db_pgno_t));
  103.  */
  104. int
  105. __db_pgfmt(dbp, pgno)
  106. DB *dbp;
  107. db_pgno_t pgno;
  108. {
  109. __db_err(dbp->dbenv,
  110.     "page %lu: illegal page type or format", (u_long)pgno);
  111. return (__db_panic(dbp->dbenv, EINVAL));
  112. }
  113. /*
  114.  * __db_eopnotsup --
  115.  * Common operation not supported message.
  116.  *
  117.  * PUBLIC: int __db_eopnotsup __P((const DB_ENV *));
  118.  */
  119. int
  120. __db_eopnotsup(dbenv)
  121. const DB_ENV *dbenv;
  122. {
  123. __db_err(dbenv, "operation not supported");
  124. #ifdef EOPNOTSUPP
  125. return (EOPNOTSUPP);
  126. #else
  127. return (EINVAL);
  128. #endif
  129. }
  130. #ifdef DIAGNOSTIC
  131. /*
  132.  * __db_assert --
  133.  * Error when an assertion fails.  Only checked if #DIAGNOSTIC defined.
  134.  *
  135.  * PUBLIC: #ifdef DIAGNOSTIC
  136.  * PUBLIC: void __db_assert __P((const char *, const char *, int));
  137.  * PUBLIC: #endif
  138.  */
  139. void
  140. __db_assert(failedexpr, file, line)
  141. const char *failedexpr, *file;
  142. int line;
  143. {
  144. (void)fprintf(stderr,
  145.     "__db_assert: "%s" failed: file "%s", line %dn",
  146.     failedexpr, file, line);
  147. fflush(stderr);
  148. /* We want a stack trace of how this could possibly happen. */
  149. abort();
  150. /* NOTREACHED */
  151. }
  152. #endif
  153. /*
  154.  * __db_panic_msg --
  155.  * Just report that someone else paniced.
  156.  *
  157.  * PUBLIC: int __db_panic_msg __P((DB_ENV *));
  158.  */
  159. int
  160. __db_panic_msg(dbenv)
  161. DB_ENV *dbenv;
  162. {
  163. __db_err(dbenv, "region error detected; run recovery.");
  164. return (DB_RUNRECOVERY);
  165. }
  166. /*
  167.  * __db_panic --
  168.  * Lock out the tree due to unrecoverable error.
  169.  *
  170.  * PUBLIC: int __db_panic __P((DB_ENV *, int));
  171.  */
  172. int
  173. __db_panic(dbenv, errval)
  174. DB_ENV *dbenv;
  175. int errval;
  176. {
  177. if (dbenv != NULL) {
  178. ((REGENV *)((REGINFO *)dbenv->reginfo)->primary)->panic = 1;
  179. dbenv->db_panic = errval;
  180. __db_err(dbenv, "PANIC: %s", db_strerror(errval));
  181. if (dbenv->db_paniccall != NULL)
  182. dbenv->db_paniccall(dbenv, errval);
  183. }
  184. /*
  185.  * Chaos reigns within.
  186.  * Reflect, repent, and reboot.
  187.  * Order shall return.
  188.  */
  189. return (DB_RUNRECOVERY);
  190. }
  191. /*
  192.  * db_strerror --
  193.  * ANSI C strerror(3) for DB.
  194.  */
  195. char *
  196. db_strerror(error)
  197. int error;
  198. {
  199. if (error == 0)
  200. return ("Successful return: 0");
  201. if (error > 0)
  202. return (strerror(error));
  203. /*
  204.  * !!!
  205.  * The Tcl API requires that some of these return strings be compared
  206.  * against strings stored in application scripts.  So, any of these
  207.  * errors that do not invariably result in a Tcl exception may not be
  208.  * altered.
  209.  */
  210. switch (error) {
  211. case DB_INCOMPLETE:
  212. return ("DB_INCOMPLETE: Cache flush was unable to complete");
  213. case DB_KEYEMPTY:
  214. return ("DB_KEYEMPTY: Non-existent key/data pair");
  215. case DB_KEYEXIST:
  216. return ("DB_KEYEXIST: Key/data pair already exists");
  217. case DB_LOCK_DEADLOCK:
  218. return
  219.     ("DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock");
  220. case DB_LOCK_NOTGRANTED:
  221. return ("DB_LOCK_NOTGRANTED: Lock not granted");
  222. case DB_NOSERVER:
  223. return ("DB_NOSERVER: Fatal error, no server");
  224. case DB_NOSERVER_HOME:
  225. return ("DB_NOSERVER_HOME: Home unrecognized at server");
  226. case DB_NOSERVER_ID:
  227. return ("DB_NOSERVER_ID: Identifier unrecognized at server");
  228. case DB_NOTFOUND:
  229. return ("DB_NOTFOUND: No matching key/data pair found");
  230. case DB_OLD_VERSION:
  231. return ("DB_OLDVERSION: Database requires a version upgrade");
  232. case DB_RUNRECOVERY:
  233. return ("DB_RUNRECOVERY: Fatal error, run database recovery");
  234. case DB_VERIFY_BAD:
  235. return ("DB_VERIFY_BAD: Database verification failed");
  236. default: {
  237. /*
  238.  * !!!
  239.  * Room for a 64-bit number + slop.  This buffer is only used
  240.  * if we're given an unknown error, which should never happen.
  241.  * Note, however, we're no longer thread-safe if it does.
  242.  */
  243. static char ebuf[40];
  244. (void)snprintf(ebuf, sizeof(ebuf), "Unknown error: %d", error);
  245. return (ebuf);
  246. }
  247. }
  248. }
  249. /*
  250.  * __db_err --
  251.  * Standard DB error routine.  The same as db_errx, except that we
  252.  * don't write to stderr if no output mechanism was specified.
  253.  *
  254.  * PUBLIC: void __db_err __P((const DB_ENV *, const char *, ...));
  255.  */
  256. void
  257. #ifdef __STDC__
  258. __db_err(const DB_ENV *dbenv, const char *fmt, ...)
  259. #else
  260. __db_err(dbenv, fmt, va_alist)
  261. const DB_ENV *dbenv;
  262. const char *fmt;
  263. va_dcl
  264. #endif
  265. {
  266. va_list ap;
  267. /*
  268. XXX
  269. Log the message.
  270. It would be nice to automatically log the error into the log files
  271. if the application is configured for logging.  The problem is that
  272. if we currently hold the log region mutex, we will self-deadlock.
  273. Leave all the structure in place, but turned off.  I'd like to fix
  274. this in the future by detecting if we have the log region already
  275. locked (e.g., a flag in the environment handle), or perhaps even
  276. have a finer granularity so that the only calls to __db_err we
  277. can't log are those made while we have the current log buffer
  278. locked, or perhaps have a separate buffer into which we log error
  279. messages.
  280. #ifdef __STDC__
  281. va_start(ap, fmt);
  282. #else
  283. va_start(ap);
  284. #endif
  285. __db_real_log(dbenv, NULL, "db_err", 0, fmt, ap);
  286. va_end(ap);
  287. #endif
  288. */
  289. /* Tell the application. */
  290. #ifdef __STDC__
  291. va_start(ap, fmt);
  292. #else
  293. va_start(ap);
  294. #endif
  295. __db_real_err(dbenv, 0, 0, 0, fmt, ap);
  296. va_end(ap);
  297. }
  298. /*
  299.  * __db_real_err --
  300.  * All the DB error routines end up here.
  301.  *
  302.  * PUBLIC: void __db_real_err
  303.  * PUBLIC:     __P((const DB_ENV *, int, int, int, const char *, va_list));
  304.  */
  305. void
  306. __db_real_err(dbenv, error, error_set, stderr_default, fmt, ap)
  307. const DB_ENV *dbenv;
  308. int error, error_set, stderr_default;
  309. const char *fmt;
  310. va_list ap;
  311. {
  312. /* Call the user's callback function, if specified. */
  313. if (dbenv != NULL && dbenv->db_errcall != NULL)
  314. __db_errcall(dbenv, error, error_set, fmt, ap);
  315. /* Write to the user's file descriptor, if specified. */
  316. if (dbenv != NULL && dbenv->db_errfile != NULL)
  317. __db_errfile(dbenv, error, error_set, fmt, ap);
  318. /*
  319.  * If we have a default and we didn't do either of the above, write
  320.  * to the default.
  321.  */
  322. if (stderr_default && (dbenv == NULL ||
  323.     (dbenv->db_errcall == NULL && dbenv->db_errfile == NULL)))
  324. __db_errfile(dbenv, error, error_set, fmt, ap);
  325. }
  326. /*
  327.  * __db_errcall --
  328.  * Do the error message work for callback functions.
  329.  */
  330. static void
  331. __db_errcall(dbenv, error, error_set, fmt, ap)
  332. const DB_ENV *dbenv;
  333. int error, error_set;
  334. const char *fmt;
  335. va_list ap;
  336. {
  337. char *p;
  338. char __errbuf[2048]; /* !!!: END OF THE STACK DON'T TRUST SPRINTF. */
  339. p = __errbuf;
  340. if (fmt != NULL) {
  341. p += vsnprintf(__errbuf, sizeof(__errbuf), fmt, ap);
  342. if (error_set) {
  343. *p++ = ':';
  344. *p++ = ' ';
  345. }
  346. }
  347. if (error_set)
  348. (void)strcpy(p, db_strerror(error));
  349. dbenv->db_errcall(dbenv->db_errpfx, __errbuf);
  350. }
  351. /*
  352.  * __db_errfile --
  353.  * Do the error message work for FILE *s.
  354.  */
  355. static void
  356. __db_errfile(dbenv, error, error_set, fmt, ap)
  357. const DB_ENV *dbenv;
  358. int error, error_set;
  359. const char *fmt;
  360. va_list ap;
  361. {
  362. FILE *fp;
  363. fp = dbenv == NULL ||
  364.     dbenv->db_errfile == NULL ? stderr : dbenv->db_errfile;
  365. if (dbenv != NULL && dbenv->db_errpfx != NULL)
  366. (void)fprintf(fp, "%s: ", dbenv->db_errpfx);
  367. if (fmt != NULL) {
  368. (void)vfprintf(fp, fmt, ap);
  369. if (error_set)
  370. (void)fprintf(fp, ": ");
  371. }
  372. if (error_set)
  373. (void)fprintf(fp, "%s", db_strerror(error));
  374. (void)fprintf(fp, "n");
  375. (void)fflush(fp);
  376. }
  377. /*
  378.  * __db_logmsg --
  379.  * Write information into the DB log.
  380.  *
  381.  * PUBLIC: void __db_logmsg __P((const DB_ENV *,
  382.  * PUBLIC:     DB_TXN *, const char *, u_int32_t, const char *, ...));
  383.  */
  384. void
  385. #ifdef __STDC__
  386. __db_logmsg(const DB_ENV *dbenv,
  387.     DB_TXN *txnid, const char *opname, u_int32_t flags, const char *fmt, ...)
  388. #else
  389. __db_logmsg(dbenv, txnid, opname, flags, fmt, va_alist)
  390. const DB_ENV *dbenv;
  391. DB_TXN *txnid;
  392. const char *opname, *fmt;
  393. u_int32_t flags;
  394. va_dcl
  395. #endif
  396. {
  397. va_list ap;
  398. #ifdef __STDC__
  399. va_start(ap, fmt);
  400. #else
  401. va_start(ap);
  402. #endif
  403. __db_real_log(dbenv, txnid, opname, flags, fmt, ap);
  404. va_end(ap);
  405. }
  406. /*
  407.  * __db_real_log --
  408.  * Write information into the DB log.
  409.  *
  410.  * PUBLIC: void __db_real_log __P((const DB_ENV *,
  411.  * PUBLIC:     DB_TXN *, const char *, u_int32_t, const char *, va_list ap));
  412.  */
  413. void
  414. #ifdef __STDC__
  415. __db_real_log(const DB_ENV *dbenv, DB_TXN *txnid,
  416.     const char *opname, u_int32_t flags, const char *fmt, va_list ap)
  417. #else
  418. __db_real_log(dbenv, txnid, opname, flags, fmt, ap)
  419. const DB_ENV *dbenv;
  420. DB_TXN *txnid;
  421. const char *opname, *fmt;
  422. u_int32_t flags;
  423. va_list ap;
  424. #endif
  425. {
  426. DBT opdbt, msgdbt;
  427. DB_LSN lsn;
  428. char __logbuf[2048]; /* !!!: END OF THE STACK DON'T TRUST SPRINTF. */
  429. if (!LOGGING_ON(dbenv))
  430. return;
  431. memset(&opdbt, 0, sizeof(opdbt));
  432. opdbt.data = (void *)opname;
  433. opdbt.size = strlen(opname) + 1;
  434. memset(&msgdbt, 0, sizeof(msgdbt));
  435. msgdbt.data = __logbuf;
  436. msgdbt.size = vsnprintf(__logbuf, sizeof(__logbuf), fmt, ap);
  437. /*
  438.  * XXX
  439.  * Explicitly discard the const.  Otherwise, we have to const DB_ENV
  440.  * references throughout the logging subsystem.
  441.  */
  442. __db_debug_log(
  443.     (DB_ENV *)dbenv, txnid, &lsn, flags, &opdbt, -1, &msgdbt, NULL, 0);
  444. }
  445. /*
  446.  * __db_unknown_flag -- report internal error
  447.  *
  448.  * PUBLIC: int __db_unknown_flag __P((DB_ENV *, char *, u_int32_t));
  449.  */
  450. int
  451. __db_unknown_flag(dbenv, routine, flag)
  452. DB_ENV *dbenv;
  453. char *routine;
  454. u_int32_t flag;
  455. {
  456. __db_err(dbenv, "%s: Unknown flag: 0x%x", routine, flag);
  457. DB_ASSERT(0);
  458. return (EINVAL);
  459. }
  460. /*
  461.  * __db_unknown_type -- report internal error
  462.  *
  463.  * PUBLIC: int __db_unknown_type __P((DB_ENV *, char *, u_int32_t));
  464.  */
  465. int
  466. __db_unknown_type(dbenv, routine, type)
  467. DB_ENV *dbenv;
  468. char *routine;
  469. u_int32_t type;
  470. {
  471. __db_err(dbenv, "%s: Unknown db type: 0x%x", routine, type);
  472. DB_ASSERT(0);
  473. return (EINVAL);
  474. }
  475. #ifdef DIAGNOSTIC
  476. /*
  477.  * __db_missing_txn_err --
  478.  * Cannot combine operations with and without transactions.
  479.  *
  480.  * PUBLIC: #ifdef DIAGNOSTIC
  481.  * PUBLIC: int __db_missing_txn_err __P((DB_ENV *));
  482.  * PUBLIC: #endif
  483.  */
  484. int
  485. __db_missing_txn_err(dbenv)
  486. DB_ENV *dbenv;
  487. {
  488. __db_err(dbenv,
  489.     "DB handle previously used in transaction, missing transaction handle.");
  490. return (EINVAL);
  491. }
  492. #endif