📄 log_get.c
字号:
/*- * See the file LICENSE for redistribution information. * * Copyright (c) 1996-2004 * Sleepycat Software. All rights reserved. * * $Id: log_get.c,v 11.110 2004/09/17 22:00:31 mjc Exp $ */#include "db_config.h"#ifndef NO_SYSTEM_INCLUDES#include <sys/types.h>#include <string.h>#endif#include "db_int.h"#include "dbinc/crypto.h"#include "dbinc/db_page.h"#include "dbinc/hmac.h"#include "dbinc/log.h"#include "dbinc/hash.h"typedef enum { L_ALREADY, L_ACQUIRED, L_NONE } RLOCK;static int __log_c_close_pp __P((DB_LOGC *, u_int32_t));static int __log_c_get_pp __P((DB_LOGC *, DB_LSN *, DBT *, u_int32_t));static int __log_c_get_int __P((DB_LOGC *, DB_LSN *, DBT *, u_int32_t));static int __log_c_hdrchk __P((DB_LOGC *, DB_LSN *, HDR *, int *));static int __log_c_incursor __P((DB_LOGC *, DB_LSN *, HDR *, u_int8_t **));static int __log_c_inregion __P((DB_LOGC *, DB_LSN *, RLOCK *, DB_LSN *, HDR *, u_int8_t **));static int __log_c_io __P((DB_LOGC *, u_int32_t, u_int32_t, void *, size_t *, int *));static int __log_c_ondisk __P((DB_LOGC *, DB_LSN *, DB_LSN *, u_int32_t, HDR *, u_int8_t **, int *));static int __log_c_set_maxrec __P((DB_LOGC *, char *));static int __log_c_shortread __P((DB_LOGC *, DB_LSN *, int));/* * __log_cursor_pp -- * DB_ENV->log_cursor * * PUBLIC: int __log_cursor_pp __P((DB_ENV *, DB_LOGC **, u_int32_t)); */int__log_cursor_pp(dbenv, logcp, flags) DB_ENV *dbenv; DB_LOGC **logcp; u_int32_t flags;{ int rep_check, ret; PANIC_CHECK(dbenv); ENV_REQUIRES_CONFIG(dbenv, dbenv->lg_handle, "DB_ENV->log_cursor", DB_INIT_LOG); /* Validate arguments. */ if ((ret = __db_fchk(dbenv, "DB_ENV->log_cursor", flags, 0)) != 0) return (ret); rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0; if (rep_check) __env_rep_enter(dbenv); ret = __log_cursor(dbenv, logcp); if (rep_check) __env_db_rep_exit(dbenv); return (ret);}/* * __log_cursor -- * Create a log cursor. * * PUBLIC: int __log_cursor __P((DB_ENV *, DB_LOGC **)); */int__log_cursor(dbenv, logcp) DB_ENV *dbenv; DB_LOGC **logcp;{ DB_LOGC *logc; int ret; *logcp = NULL; /* Allocate memory for the cursor. */ if ((ret = __os_calloc(dbenv, 1, sizeof(DB_LOGC), &logc)) != 0) return (ret); logc->bp_size = DB_LOGC_BUF_SIZE; /* * Set this to something positive. */ logc->bp_maxrec = MEGABYTE; if ((ret = __os_malloc(dbenv, logc->bp_size, &logc->bp)) != 0) { __os_free(dbenv, logc); return (ret); } logc->dbenv = dbenv; logc->close = __log_c_close_pp; logc->get = __log_c_get_pp; *logcp = logc; return (0);}/* * __log_c_close_pp -- * DB_LOGC->close pre/post processing. */static int__log_c_close_pp(logc, flags) DB_LOGC *logc; u_int32_t flags;{ DB_ENV *dbenv; int rep_check, ret; dbenv = logc->dbenv; PANIC_CHECK(dbenv); if ((ret = __db_fchk(dbenv, "DB_LOGC->close", flags, 0)) != 0) return (ret); rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0; if (rep_check) __env_rep_enter(dbenv); ret = __log_c_close(logc); if (rep_check) __env_db_rep_exit(dbenv); return (ret);}/* * __log_c_close -- * DB_LOGC->close. * * PUBLIC: int __log_c_close __P((DB_LOGC *)); */int__log_c_close(logc) DB_LOGC *logc;{ DB_ENV *dbenv; dbenv = logc->dbenv; if (logc->c_fhp != NULL) { (void)__os_closehandle(dbenv, logc->c_fhp); logc->c_fhp = NULL; } if (logc->c_dbt.data != NULL) __os_free(dbenv, logc->c_dbt.data); __os_free(dbenv, logc->bp); __os_free(dbenv, logc); return (0);}/* * __log_c_get_pp -- * DB_LOGC->get pre/post processing. */static int__log_c_get_pp(logc, alsn, dbt, flags) DB_LOGC *logc; DB_LSN *alsn; DBT *dbt; u_int32_t flags;{ DB_ENV *dbenv; int rep_check, ret; dbenv = logc->dbenv; PANIC_CHECK(dbenv); /* Validate arguments. */ switch (flags) { case DB_CURRENT: case DB_FIRST: case DB_LAST: case DB_NEXT: case DB_PREV: break; case DB_SET: if (IS_ZERO_LSN(*alsn)) { __db_err(dbenv, "DB_LOGC->get: invalid LSN: %lu/%lu", (u_long)alsn->file, (u_long)alsn->offset); return (EINVAL); } break; default: return (__db_ferr(dbenv, "DB_LOGC->get", 1)); } rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0; if (rep_check) __env_rep_enter(dbenv); ret = __log_c_get(logc, alsn, dbt, flags); if (rep_check) __env_db_rep_exit(dbenv); return (ret);}/* * __log_c_get -- * DB_LOGC->get. * * PUBLIC: int __log_c_get __P((DB_LOGC *, DB_LSN *, DBT *, u_int32_t)); */int__log_c_get(logc, alsn, dbt, flags) DB_LOGC *logc; DB_LSN *alsn; DBT *dbt; u_int32_t flags;{ DB_ENV *dbenv; DB_LSN saved_lsn; int ret; dbenv = logc->dbenv; /* * On error, we take care not to overwrite the caller's LSN. This * is because callers looking for the end of the log loop using the * DB_NEXT flag, and expect to take the last successful lsn out of * the passed-in structure after DB_LOGC->get fails with DB_NOTFOUND. * * !!! * This line is often flagged an uninitialized memory read during a * Purify or similar tool run, as the application didn't initialize * *alsn. If the application isn't setting the DB_SET flag, there is * no reason it should have initialized *alsn, but we can't know that * and we want to make sure we never overwrite whatever the application * put in there. */ saved_lsn = *alsn; /* * If we get one of the log's header records as a result of doing a * DB_FIRST, DB_NEXT, DB_LAST or DB_PREV, repeat the operation, log * file header records aren't useful to applications. */ if ((ret = __log_c_get_int(logc, alsn, dbt, flags)) != 0) { *alsn = saved_lsn; return (ret); } if (alsn->offset == 0 && (flags == DB_FIRST || flags == DB_NEXT || flags == DB_LAST || flags == DB_PREV)) { switch (flags) { case DB_FIRST: flags = DB_NEXT; break; case DB_LAST: flags = DB_PREV; break; case DB_NEXT: case DB_PREV: default: break; } if (F_ISSET(dbt, DB_DBT_MALLOC)) { __os_free(dbenv, dbt->data); dbt->data = NULL; } if ((ret = __log_c_get_int(logc, alsn, dbt, flags)) != 0) { *alsn = saved_lsn; return (ret); } } return (0);}/* * __log_c_get_int -- * Get a log record; internal version. */static int__log_c_get_int(logc, alsn, dbt, flags) DB_LOGC *logc; DB_LSN *alsn; DBT *dbt; u_int32_t flags;{ DB_CIPHER *db_cipher; DB_ENV *dbenv; DB_LOG *dblp; DB_LSN last_lsn, nlsn; HDR hdr; LOG *lp; RLOCK rlock; logfile_validity status; u_int32_t cnt; u_int8_t *rp; int eof, is_hmac, ret; dbenv = logc->dbenv; dblp = dbenv->lg_handle; lp = dblp->reginfo.primary; is_hmac = 0; /* * We don't acquire the log region lock until we need it, and we * release it as soon as we're done. */ rlock = F_ISSET(logc, DB_LOG_LOCKED) ? L_ALREADY : L_NONE; nlsn = logc->c_lsn; switch (flags) { case DB_NEXT: /* Next log record. */ if (!IS_ZERO_LSN(nlsn)) { /* Increment the cursor by the cursor record size. */ nlsn.offset += logc->c_len; break; } flags = DB_FIRST; /* FALLTHROUGH */ case DB_FIRST: /* First log record. */ /* Find the first log file. */ if ((ret = __log_find(dblp, 1, &cnt, &status)) != 0) goto err; /* * DB_LV_INCOMPLETE: * Theoretically, the log file we want could be created * but not yet written, the "first" log record must be * in the log buffer. * DB_LV_NORMAL: * DB_LV_OLD_READABLE: * We found a log file we can read. * DB_LV_NONEXISTENT: * No log files exist, the "first" log record must be in * the log buffer. * DB_LV_OLD_UNREADABLE: * No readable log files exist, we're at the cross-over * point between two versions. The "first" log record * must be in the log buffer. */ switch (status) { case DB_LV_INCOMPLETE: DB_ASSERT(lp->lsn.file == cnt); /* FALLTHROUGH */ case DB_LV_NORMAL: case DB_LV_OLD_READABLE: nlsn.file = cnt; break; case DB_LV_NONEXISTENT: nlsn.file = 1; DB_ASSERT(lp->lsn.file == nlsn.file); break; case DB_LV_OLD_UNREADABLE: nlsn.file = cnt + 1; DB_ASSERT(lp->lsn.file == nlsn.file); break; } nlsn.offset = 0; break; case DB_CURRENT: /* Current log record. */ break; case DB_PREV: /* Previous log record. */ if (!IS_ZERO_LSN(nlsn)) { /* If at start-of-file, move to the previous file. */ if (nlsn.offset == 0) { if (nlsn.file == 1) { ret = DB_NOTFOUND; goto err; } if ((!lp->db_log_inmemory && (__log_valid(dblp, nlsn.file - 1, 0, NULL, 0, &status) != 0 || (status != DB_LV_NORMAL && status != DB_LV_OLD_READABLE)))) { ret = DB_NOTFOUND; goto err; } --nlsn.file; } nlsn.offset = logc->c_prev; break; } /* FALLTHROUGH */ case DB_LAST: /* Last log record. */ if (rlock == L_NONE) { rlock = L_ACQUIRED; R_LOCK(dbenv, &dblp->reginfo);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -