1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426
|
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997, 1998, 1999
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
static const char sccsid[] = "@(#)db_err.c 11.10 (Sleepycat) 11/8/99";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef _MSC_VER /* WIN32 */
#ifdef __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#endif
#endif
#include "db_int.h"
#include "db_shash.h"
#include "lock.h"
#include "lock_ext.h"
#include "log.h"
#include "log_ext.h"
#include "mp.h"
#include "mp_ext.h"
#include "txn.h"
#include "txn_ext.h"
#include "common_ext.h"
#include "db_auto.h"
static void CDB___db_errcall __P((const DB_ENV *, int, int, const char *, va_list));
static void CDB___db_errfile __P((const DB_ENV *, int, int, const char *, va_list));
/*
* CDB___db_fchk --
* General flags checking routine.
*
* PUBLIC: int CDB___db_fchk __P((DB_ENV *, const char *, u_int32_t, u_int32_t));
*/
int
CDB___db_fchk(dbenv, name, flags, ok_flags)
DB_ENV *dbenv;
const char *name;
u_int32_t flags, ok_flags;
{
return (LF_ISSET(~ok_flags) ? CDB___db_ferr(dbenv, name, 0) : 0);
}
/*
* CDB___db_fcchk --
* General combination flags checking routine.
*
* PUBLIC: int CDB___db_fcchk
* PUBLIC: __P((DB_ENV *, const char *, u_int32_t, u_int32_t, u_int32_t));
*/
int
CDB___db_fcchk(dbenv, name, flags, flag1, flag2)
DB_ENV *dbenv;
const char *name;
u_int32_t flags, flag1, flag2;
{
return (LF_ISSET(flag1) &&
LF_ISSET(flag2) ? CDB___db_ferr(dbenv, name, 1) : 0);
}
/*
* CDB___db_ferr --
* Common flag errors.
*
* PUBLIC: int CDB___db_ferr __P((const DB_ENV *, const char *, int));
*/
int
CDB___db_ferr(dbenv, name, iscombo)
const DB_ENV *dbenv;
const char *name;
int iscombo;
{
CDB___db_err(dbenv, "illegal flag %sspecified to %s",
iscombo ? "combination " : "", name);
return (EINVAL);
}
/*
* CDB___db_pgerr --
* Error when unable to retrieve a specified page.
*
* PUBLIC: int CDB___db_pgerr __P((DB *, db_pgno_t));
*/
int
CDB___db_pgerr(dbp, pgno)
DB *dbp;
db_pgno_t pgno;
{
/*
* Three things are certain:
* Death, taxes, and lost data.
* Guess which has occurred.
*/
CDB___db_err(dbp->dbenv,
"unable to create/retrieve page %lu", (u_long)pgno);
return (CDB___db_panic(dbp->dbenv, EIO));
}
/*
* CDB___db_pgfmt --
* Error when a page has the wrong format.
*
* PUBLIC: int CDB___db_pgfmt __P((DB *, db_pgno_t));
*/
int
CDB___db_pgfmt(dbp, pgno)
DB *dbp;
db_pgno_t pgno;
{
CDB___db_err(dbp->dbenv,
"page %lu: illegal page type or format", (u_long)pgno);
return (CDB___db_panic(dbp->dbenv, EINVAL));
}
#ifdef DIAGNOSTIC
/*
* __db_assert --
* Error when an assertion fails. Only checked if #DIAGNOSTIC defined.
*
* PUBLIC: #ifdef DIAGNOSTIC
* PUBLIC: void __db_assert __P((const char *, const char *, int));
* PUBLIC: #endif
*/
void
__db_assert(failedexpr, file, line)
const char *failedexpr, *file;
int line;
{
(void)fprintf(stderr,
"__db_assert: \"%s\" failed: file \"%s\", line %d\n",
failedexpr, file, line);
fflush(stderr);
/* We want a stack trace of how this could possibly happen. */
abort();
/* NOTREACHED */
}
#endif
/*
* CDB___db_panic_msg --
* Just report that someone else paniced.
*
* PUBLIC: int CDB___db_panic_msg __P((DB_ENV *));
*/
int
CDB___db_panic_msg(dbenv)
DB_ENV *dbenv;
{
CDB___db_err(dbenv, "region error detected; run recovery.");
/* Hack to make fatal errors really fatal... */
fprintf(stderr,"DB_RUNRECOVERY: Fatal error, run database recovery\n");
exit(1);
return (DB_RUNRECOVERY);
}
/*
* CDB___db_panic --
* Lock out the tree due to unrecoverable error.
*
* PUBLIC: int CDB___db_panic __P((DB_ENV *, int));
*/
int
CDB___db_panic(dbenv, errval)
DB_ENV *dbenv;
int errval;
{
if (dbenv != NULL) {
((REGENV *)((REGINFO *)dbenv->reginfo)->addr)->panic = 1;
dbenv->db_panic = errval;
CDB___db_err(dbenv, "PANIC: %s", CDB_db_strerror(errval));
if (dbenv->db_paniccall != NULL)
dbenv->db_paniccall(dbenv, errval);
}
/*
* Chaos reigns within.
* Reflect, repent, and reboot.
* Order shall return.
*/
/* Hack to make fatal errors really fatal... */
fprintf(stderr,"DB_RUNRECOVERY: Fatal error, run database recovery\n");
exit(1);
return (DB_RUNRECOVERY);
}
/*
* CDB_db_strerror --
* ANSI C strerror(3) for DB.
*/
char *
CDB_db_strerror(error)
int error;
{
if (error == 0)
return ("Successful return: 0");
if (error > 0)
return (strerror(error));
/*
* !!!
* The Tcl API requires that some of these return strings be compared
* against strings stored in application scripts. So, any of these
* errors that do not invariably result in a Tcl exception may not be
* altered.
*/
switch (error) {
case DB_INCOMPLETE:
return ("DB_INCOMPLETE: Cache flush was unable to complete");
case DB_KEYEMPTY:
return ("DB_KEYEMPTY: Non-existent key/data pair");
case DB_KEYEXIST:
return ("DB_KEYEXIST: Key/data pair already exists");
case DB_LOCK_DEADLOCK:
return
("DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock");
case DB_LOCK_NOTGRANTED:
return ("DB_LOCK_NOTGRANTED: Lock not granted");
case DB_NOTFOUND:
return ("DB_NOTFOUND: No matching key/data pair found");
case DB_OLD_VERSION:
return ("DB_OLDVERSION: Database requires a version upgrade");
case DB_RUNRECOVERY:
return ("DB_RUNRECOVERY: Fatal error, run database recovery");
default: {
/*
* !!!
* Room for a 64-bit number + slop. This buffer is only used
* if we're given an unknown error, which should never happen.
* Note, however, we're no longer thread-safe if it does.
*/
static char ebuf[40];
(void)snprintf(ebuf, sizeof(ebuf), "Unknown error: %d", error);
return(ebuf);
}
}
}
/*
* CDB___db_err --
* Standard DB error routine. The same as db_errx, except that we
* don't write to stderr if no output mechanism was specified.
*
* PUBLIC: #ifdef __STDC__
* PUBLIC: void CDB___db_err __P((const DB_ENV *, const char *, ...));
* PUBLIC: #else
* PUBLIC: void CDB___db_err();
* PUBLIC: #endif
*/
void
#if defined( __STDC__) || defined(_MSC_VER) /* WIN32 */
CDB___db_err(const DB_ENV *dbenv, const char *fmt, ...)
#else
CDB___db_err(dbenv, fmt, va_alist)
const DB_ENV *dbenv;
const char *fmt;
va_dcl
#endif
{
va_list ap;
#if defined(__STDC__) || defined(_MSC_VER) /* WIN32 */
va_start(ap, fmt);
#else
va_start(ap);
#endif
CDB___db_real_err(dbenv, 0, 0, 0, fmt, ap);
va_end(ap);
}
/*
* CDB___db_real_err --
* All the DB error routines end up here.
*
* PUBLIC: void CDB___db_real_err
* PUBLIC: __P((const DB_ENV *, int, int, int, const char *, va_list));
*/
void
CDB___db_real_err(dbenv, error, error_set, stderr_default, fmt, ap)
const DB_ENV *dbenv;
int error, error_set, stderr_default;
const char *fmt;
va_list ap;
{
if (dbenv != NULL && dbenv->db_errcall != NULL)
CDB___db_errcall(dbenv, error, error_set, fmt, ap);
if (dbenv != NULL && dbenv->db_errfile != NULL)
CDB___db_errfile(dbenv, error, error_set, fmt, ap);
if (stderr_default && (dbenv == NULL ||
(dbenv->db_errcall == NULL && dbenv->db_errfile == NULL)))
CDB___db_errfile(NULL, error, error_set, fmt, ap);
}
/*
* CDB___db_errcall --
* Do the error message work for callback functions.
*/
static void
CDB___db_errcall(dbenv, error, error_set, fmt, ap)
const DB_ENV *dbenv;
int error, error_set;
const char *fmt;
va_list ap;
{
char *p;
char __errbuf[2048]; /* XXX: END OF THE STACK DON'T TRUST SPRINTF. */
p = __errbuf;
if (fmt != NULL) {
p += vsnprintf(__errbuf, sizeof(__errbuf), fmt, ap);
if (error_set) {
*p++ = ':';
*p++ = ' ';
}
}
if (error_set)
(void)strcpy(p, CDB_db_strerror(error));
dbenv->db_errcall(dbenv->db_errpfx, __errbuf);
}
/*
* CDB___db_errfile --
* Do the error message work for FILE *s.
*/
static void
CDB___db_errfile(dbenv, error, error_set, fmt, ap)
const DB_ENV *dbenv;
int error, error_set;
const char *fmt;
va_list ap;
{
FILE *fp;
fp = dbenv == NULL ||
dbenv->db_errfile == NULL ? stderr : dbenv->db_errfile;
if (dbenv != NULL && dbenv->db_errpfx != NULL)
(void)fprintf(fp, "%s: ", dbenv->db_errpfx);
if (fmt != NULL) {
(void)vfprintf(fp, fmt, ap);
if (error_set)
(void)fprintf(fp, ": ");
}
if (error_set)
(void)fprintf(fp, "%s", CDB_db_strerror(error));
(void)fprintf(fp, "\n");
(void)fflush(fp);
}
/*
* CDB___db_logmsg --
* Write information into the DB log.
*
* PUBLIC: #ifdef __STDC__
* PUBLIC: int CDB___db_logmsg __P((DB_ENV *,
* PUBLIC: DB_TXN *, const char *, u_int32_t, const char *, ...));
* PUBLIC: #else
* PUBLIC: int CDB___db_logmsg();
* PUBLIC: #endif
*/
int
#if defined(__STDC__) || defined(_MSC_VER) /* WIN32 */
CDB___db_logmsg(DB_ENV *dbenv,
DB_TXN *txnid, const char *opname, u_int32_t flags, const char *fmt, ...)
#else
CDB___db_logmsg(dbenv, txnid, opname, flags, fmt, va_alist)
DB_ENV *dbenv;
DB_TXN *txnid;
const char *opname, *fmt;
u_int32_t flags;
va_dcl
#endif
{
DBT opdbt, msgdbt;
DB_LSN lsn;
va_list ap;
char __logbuf[2048]; /* XXX: END OF THE STACK DON'T TRUST SPRINTF. */
if (!F_ISSET(dbenv, DB_ENV_LOGGING))
return (0);
memset(&opdbt, 0, sizeof(opdbt));
opdbt.data = (void *)opname;
opdbt.size = strlen(opname) + 1;
memset(&msgdbt, 0, sizeof(msgdbt));
msgdbt.data = __logbuf;
#if defined(__STDC__) || defined(_MSC_VER) /* WIN32 */
va_start(ap, fmt);
#else
va_start(ap);
#endif
msgdbt.size = vsnprintf(__logbuf, sizeof(__logbuf), fmt, ap);
va_end(ap);
return (CDB___db_debug_log(dbenv,
txnid, &lsn, flags, &opdbt, -1, &msgdbt, NULL, 0));
}
|