diff options
Diffstat (limited to 'db2/log')
-rw-r--r-- | db2/log/log.c | 540 | ||||
-rw-r--r-- | db2/log/log.src | 19 | ||||
-rw-r--r-- | db2/log/log_archive.c | 417 | ||||
-rw-r--r-- | db2/log/log_auto.c | 231 | ||||
-rw-r--r-- | db2/log/log_compare.c | 34 | ||||
-rw-r--r-- | db2/log/log_findckp.c | 141 | ||||
-rw-r--r-- | db2/log/log_get.c | 330 | ||||
-rw-r--r-- | db2/log/log_put.c | 603 | ||||
-rw-r--r-- | db2/log/log_rec.c | 398 | ||||
-rw-r--r-- | db2/log/log_register.c | 208 |
10 files changed, 0 insertions, 2921 deletions
diff --git a/db2/log/log.c b/db2/log/log.c deleted file mode 100644 index ad15f16..0000000 --- a/db2/log/log.c +++ /dev/null @@ -1,540 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - */ -#include "config.h" - -#ifndef lint -static const char sccsid[] = "@(#)log.c 10.63 (Sleepycat) 10/10/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <shqueue.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#endif - -#include "db_int.h" -#include "shqueue.h" -#include "log.h" -#include "db_dispatch.h" -#include "txn.h" -#include "txn_auto.h" -#include "common_ext.h" - -static int __log_recover __P((DB_LOG *)); - -/* - * log_open -- - * Initialize and/or join a log. - */ -int -log_open(path, flags, mode, dbenv, lpp) - const char *path; - u_int32_t flags; - int mode; - DB_ENV *dbenv; - DB_LOG **lpp; -{ - DB_LOG *dblp; - LOG *lp; - int ret; - - /* Validate arguments. */ -#ifdef HAVE_SPINLOCKS -#define OKFLAGS (DB_CREATE | DB_THREAD) -#else -#define OKFLAGS (DB_CREATE) -#endif - if ((ret = __db_fchk(dbenv, "log_open", flags, OKFLAGS)) != 0) - return (ret); - - /* Create and initialize the DB_LOG structure. */ - if ((ret = __os_calloc(1, sizeof(DB_LOG), &dblp)) != 0) - return (ret); - - if (path != NULL && (ret = __os_strdup(path, &dblp->dir)) != 0) - goto err; - - dblp->dbenv = dbenv; - dblp->lfd = -1; - ZERO_LSN(dblp->c_lsn); - dblp->c_fd = -1; - - /* - * The log region isn't fixed size because we store the registered - * file names there. Make it fairly large so that we don't have to - * grow it. - */ -#define DEF_LOG_SIZE (30 * 1024) - - /* Map in the region. */ - dblp->reginfo.dbenv = dbenv; - dblp->reginfo.appname = DB_APP_LOG; - if (path == NULL) - dblp->reginfo.path = NULL; - else - if ((ret = __os_strdup(path, &dblp->reginfo.path)) != 0) - goto err; - dblp->reginfo.file = DB_DEFAULT_LOG_FILE; - dblp->reginfo.mode = mode; - dblp->reginfo.size = DEF_LOG_SIZE; - dblp->reginfo.dbflags = flags; - dblp->reginfo.flags = REGION_SIZEDEF; - if ((ret = __db_rattach(&dblp->reginfo)) != 0) - goto err; - - /* - * The LOG structure is first in the region, the rest of the region - * is free space. - */ - dblp->lp = dblp->reginfo.addr; - dblp->addr = (u_int8_t *)dblp->lp + sizeof(LOG); - - /* Initialize a created region. */ - if (F_ISSET(&dblp->reginfo, REGION_CREATED)) { - __db_shalloc_init(dblp->addr, DEF_LOG_SIZE - sizeof(LOG)); - - /* Initialize the LOG structure. */ - lp = dblp->lp; - lp->persist.lg_max = dbenv == NULL ? 0 : dbenv->lg_max; - if (lp->persist.lg_max == 0) - lp->persist.lg_max = DEFAULT_MAX; - lp->persist.magic = DB_LOGMAGIC; - lp->persist.version = DB_LOGVERSION; - lp->persist.mode = mode; - SH_TAILQ_INIT(&lp->fq); - - /* Initialize LOG LSNs. */ - lp->lsn.file = 1; - lp->lsn.offset = 0; - } - - /* Initialize thread information, mutex. */ - if (LF_ISSET(DB_THREAD)) { - F_SET(dblp, DB_AM_THREAD); - if ((ret = __db_shalloc(dblp->addr, - sizeof(db_mutex_t), MUTEX_ALIGNMENT, &dblp->mutexp)) != 0) - goto err; - (void)__db_mutex_init(dblp->mutexp, 0); - } - - /* - * If doing recovery, try and recover any previous log files before - * releasing the lock. - */ - if (F_ISSET(&dblp->reginfo, REGION_CREATED) && - (ret = __log_recover(dblp)) != 0) - goto err; - - UNLOCK_LOGREGION(dblp); - *lpp = dblp; - return (0); - -err: if (dblp->reginfo.addr != NULL) { - if (dblp->mutexp != NULL) - __db_shalloc_free(dblp->addr, dblp->mutexp); - - UNLOCK_LOGREGION(dblp); - (void)__db_rdetach(&dblp->reginfo); - if (F_ISSET(&dblp->reginfo, REGION_CREATED)) - (void)log_unlink(path, 1, dbenv); - } - - if (dblp->reginfo.path != NULL) - __os_freestr(dblp->reginfo.path); - if (dblp->dir != NULL) - __os_freestr(dblp->dir); - __os_free(dblp, sizeof(*dblp)); - return (ret); -} - -/* - * __log_panic -- - * Panic a log. - * - * PUBLIC: void __log_panic __P((DB_ENV *)); - */ -void -__log_panic(dbenv) - DB_ENV *dbenv; -{ - if (dbenv->lg_info != NULL) - dbenv->lg_info->lp->rlayout.panic = 1; -} - -/* - * __log_recover -- - * Recover a log. - */ -static int -__log_recover(dblp) - DB_LOG *dblp; -{ - DBT dbt; - DB_LSN lsn; - LOG *lp; - u_int32_t chk; - int cnt, found_checkpoint, ret; - - lp = dblp->lp; - - /* - * Find a log file. If none exist, we simply return, leaving - * everything initialized to a new log. - */ - if ((ret = __log_find(dblp, 0, &cnt)) != 0) - return (ret); - if (cnt == 0) - return (0); - - /* - * We have the last useful log file and we've loaded any persistent - * information. Pretend that the log is larger than it can possibly - * be, and read the last file, looking for the last checkpoint and - * the log's end. - */ - lp->lsn.file = cnt + 1; - lp->lsn.offset = 0; - lsn.file = cnt; - lsn.offset = 0; - - /* Set the cursor. Shouldn't fail, leave error messages on. */ - memset(&dbt, 0, sizeof(dbt)); - if ((ret = __log_get(dblp, &lsn, &dbt, DB_SET, 0)) != 0) - return (ret); - - /* - * Read to the end of the file, saving checkpoints. This will fail - * at some point, so turn off error messages. - */ - found_checkpoint = 0; - while (__log_get(dblp, &lsn, &dbt, DB_NEXT, 1) == 0) { - if (dbt.size < sizeof(u_int32_t)) - continue; - memcpy(&chk, dbt.data, sizeof(u_int32_t)); - if (chk == DB_txn_ckp) { - lp->chkpt_lsn = lsn; - found_checkpoint = 1; - } - } - - /* - * We now know where the end of the log is. Set the first LSN that - * we want to return to an application and the LSN of the last known - * record on disk. - */ - lp->lsn = lp->s_lsn = lsn; - lp->lsn.offset += dblp->c_len; - - /* Set up the current buffer information, too. */ - lp->len = dblp->c_len; - lp->b_off = 0; - lp->w_off = lp->lsn.offset; - - /* - * It's possible that we didn't find a checkpoint because there wasn't - * one in the last log file. Start searching. - */ - while (!found_checkpoint && cnt > 1) { - lsn.file = --cnt; - lsn.offset = 0; - - /* Set the cursor. Shouldn't fail, leave error messages on. */ - if ((ret = __log_get(dblp, &lsn, &dbt, DB_SET, 0)) != 0) - return (ret); - - /* - * Read to the end of the file, saving checkpoints. Shouldn't - * fail, leave error messages on. - */ - while (__log_get(dblp, &lsn, &dbt, DB_NEXT, 0) == 0) { - if (dbt.size < sizeof(u_int32_t)) - continue; - memcpy(&chk, dbt.data, sizeof(u_int32_t)); - if (chk == DB_txn_ckp) { - lp->chkpt_lsn = lsn; - found_checkpoint = 1; - } - } - } - /* - * Reset the cursor lsn to the beginning of the log, so that an - * initial call to DB_NEXT does the right thing. - */ - ZERO_LSN(dblp->c_lsn); - - /* If we never find a checkpoint, that's okay, just 0 it out. */ - if (!found_checkpoint) - ZERO_LSN(lp->chkpt_lsn); - - /* - * !!! - * The test suite explicitly looks for this string -- don't change - * it here unless you also change it there. - */ - __db_err(dblp->dbenv, - "Finding last valid log LSN: file: %lu offset %lu", - (u_long)lp->lsn.file, (u_long)lp->lsn.offset); - - return (0); -} - -/* - * __log_find -- - * Try to find a log file. If find_first is set, valp will contain - * the number of the first log file, else it will contain the number of - * the last log file. - * - * PUBLIC: int __log_find __P((DB_LOG *, int, int *)); - */ -int -__log_find(dblp, find_first, valp) - DB_LOG *dblp; - int find_first, *valp; -{ - u_int32_t clv, logval; - int cnt, fcnt, ret; - const char *dir; - char **names, *p, *q; - - *valp = 0; - - /* Find the directory name. */ - if ((ret = __log_name(dblp, 1, &p, NULL, 0)) != 0) - return (ret); - if ((q = __db_rpath(p)) == NULL) - dir = PATH_DOT; - else { - *q = '\0'; - dir = p; - } - - /* Get the list of file names. */ - ret = __os_dirlist(dir, &names, &fcnt); - __os_freestr(p); - if (ret != 0) { - __db_err(dblp->dbenv, "%s: %s", dir, strerror(ret)); - return (ret); - } - - /* - * Search for a valid log file name, return a value of 0 on - * failure. - * - * XXX - * Assumes that atoi(3) returns a 32-bit number. - */ - for (cnt = fcnt, clv = logval = 0; --cnt >= 0;) { - if (strncmp(names[cnt], LFPREFIX, sizeof(LFPREFIX) - 1) != 0) - continue; - - clv = atoi(names[cnt] + (sizeof(LFPREFIX) - 1)); - if (find_first) { - if (logval != 0 && clv > logval) - continue; - } else - if (logval != 0 && clv < logval) - continue; - - if (__log_valid(dblp, clv, 1) == 0) - logval = clv; - } - - *valp = logval; - - /* Discard the list. */ - __os_dirfree(names, fcnt); - - return (0); -} - -/* - * log_valid -- - * Validate a log file. - * - * PUBLIC: int __log_valid __P((DB_LOG *, u_int32_t, int)); - */ -int -__log_valid(dblp, number, set_persist) - DB_LOG *dblp; - u_int32_t number; - int set_persist; -{ - LOGP persist; - ssize_t nw; - char *fname; - int fd, ret; - - /* Try to open the log file. */ - if ((ret = __log_name(dblp, - number, &fname, &fd, DB_RDONLY | DB_SEQUENTIAL)) != 0) { - __os_freestr(fname); - return (ret); - } - - /* Try to read the header. */ - if ((ret = __os_seek(fd, 0, 0, sizeof(HDR), 0, SEEK_SET)) != 0 || - (ret = __os_read(fd, &persist, sizeof(LOGP), &nw)) != 0 || - nw != sizeof(LOGP)) { - if (ret == 0) - ret = EIO; - - (void)__os_close(fd); - - __db_err(dblp->dbenv, - "Ignoring log file: %s: %s", fname, strerror(ret)); - goto err; - } - (void)__os_close(fd); - - /* Validate the header. */ - if (persist.magic != DB_LOGMAGIC) { - __db_err(dblp->dbenv, - "Ignoring log file: %s: magic number %lx, not %lx", - fname, (u_long)persist.magic, (u_long)DB_LOGMAGIC); - ret = EINVAL; - goto err; - } - if (persist.version < DB_LOGOLDVER || persist.version > DB_LOGVERSION) { - __db_err(dblp->dbenv, - "Ignoring log file: %s: unsupported log version %lu", - fname, (u_long)persist.version); - ret = EINVAL; - goto err; - } - - /* - * If we're going to use this log file, set the region's persistent - * information based on the headers. - */ - if (set_persist) { - dblp->lp->persist.lg_max = persist.lg_max; - dblp->lp->persist.mode = persist.mode; - } - ret = 0; - -err: __os_freestr(fname); - return (ret); -} - -/* - * log_close -- - * Close a log. - */ -int -log_close(dblp) - DB_LOG *dblp; -{ - int ret, t_ret; - - LOG_PANIC_CHECK(dblp); - - /* We may have opened files as part of XA; if so, close them. */ - __log_close_files(dblp); - - /* Discard the per-thread pointer. */ - if (dblp->mutexp != NULL) { - LOCK_LOGREGION(dblp); - __db_shalloc_free(dblp->addr, dblp->mutexp); - UNLOCK_LOGREGION(dblp); - } - - /* Close the region. */ - ret = __db_rdetach(&dblp->reginfo); - - /* Close open files, release allocated memory. */ - if (dblp->lfd != -1 && (t_ret = __os_close(dblp->lfd)) != 0 && ret == 0) - ret = t_ret; - if (dblp->c_dbt.data != NULL) - __os_free(dblp->c_dbt.data, dblp->c_dbt.ulen); - if (dblp->c_fd != -1 && - (t_ret = __os_close(dblp->c_fd)) != 0 && ret == 0) - ret = t_ret; - if (dblp->dbentry != NULL) - __os_free(dblp->dbentry, - (dblp->dbentry_cnt * sizeof(DB_ENTRY))); - if (dblp->dir != NULL) - __os_freestr(dblp->dir); - - if (dblp->reginfo.path != NULL) - __os_freestr(dblp->reginfo.path); - __os_free(dblp, sizeof(*dblp)); - - return (ret); -} - -/* - * log_unlink -- - * Exit a log. - */ -int -log_unlink(path, force, dbenv) - const char *path; - int force; - DB_ENV *dbenv; -{ - REGINFO reginfo; - int ret; - - memset(®info, 0, sizeof(reginfo)); - reginfo.dbenv = dbenv; - reginfo.appname = DB_APP_LOG; - if (path != NULL && (ret = __os_strdup(path, ®info.path)) != 0) - return (ret); - reginfo.file = DB_DEFAULT_LOG_FILE; - ret = __db_runlink(®info, force); - if (reginfo.path != NULL) - __os_freestr(reginfo.path); - return (ret); -} - -/* - * log_stat -- - * Return LOG statistics. - */ -int -log_stat(dblp, gspp, db_malloc) - DB_LOG *dblp; - DB_LOG_STAT **gspp; - void *(*db_malloc) __P((size_t)); -{ - LOG *lp; - int ret; - - *gspp = NULL; - lp = dblp->lp; - - LOG_PANIC_CHECK(dblp); - - if ((ret = __os_malloc(sizeof(**gspp), db_malloc, gspp)) != 0) - return (ret); - - /* Copy out the global statistics. */ - LOCK_LOGREGION(dblp); - **gspp = lp->stat; - - (*gspp)->st_magic = lp->persist.magic; - (*gspp)->st_version = lp->persist.version; - (*gspp)->st_mode = lp->persist.mode; - (*gspp)->st_lg_max = lp->persist.lg_max; - - (*gspp)->st_region_nowait = lp->rlayout.lock.mutex_set_nowait; - (*gspp)->st_region_wait = lp->rlayout.lock.mutex_set_wait; - - (*gspp)->st_cur_file = lp->lsn.file; - (*gspp)->st_cur_offset = lp->lsn.offset; - - (*gspp)->st_refcnt = lp->rlayout.refcnt; - (*gspp)->st_regsize = lp->rlayout.size; - - UNLOCK_LOGREGION(dblp); - - return (0); -} diff --git a/db2/log/log.src b/db2/log/log.src deleted file mode 100644 index 12883bd..0000000 --- a/db2/log/log.src +++ /dev/null @@ -1,19 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - * - * @(#)log.src 10.5 (Sleepycat) 4/10/98 - */ - -PREFIX log - -/* Used for registering name/id translations at open or close. */ -BEGIN register -ARG opcode u_int32_t lu -DBT name DBT s -DBT uid DBT s -ARG id u_int32_t lu -ARG ftype DBTYPE lx -END diff --git a/db2/log/log_archive.c b/db2/log/log_archive.c deleted file mode 100644 index 9f3b24d..0000000 --- a/db2/log/log_archive.c +++ /dev/null @@ -1,417 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1997, 1998 - * Sleepycat Software. All rights reserved. - */ - -#include "config.h" - -#ifndef lint -static const char sccsid[] = "@(#)log_archive.c 10.44 (Sleepycat) 10/9/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#endif - -#include "db_int.h" -#include "db_dispatch.h" -#include "shqueue.h" -#include "log.h" -#include "common_ext.h" -#include "clib_ext.h" /* XXX: needed for getcwd. */ - -static int __absname __P((char *, char *, char **)); -static int __build_data __P((DB_LOG *, char *, char ***, void *(*)(size_t))); -static int __cmpfunc __P((const void *, const void *)); -static int __usermem __P((char ***, void *(*)(size_t))); - -/* - * log_archive -- - * Supporting function for db_archive(1). - */ -int -log_archive(dblp, listp, flags, db_malloc) - DB_LOG *dblp; - char ***listp; - u_int32_t flags; - void *(*db_malloc) __P((size_t)); -{ - DBT rec; - DB_LSN stable_lsn; - u_int32_t fnum; - int array_size, n, ret; - char **array, **arrayp, *name, *p, *pref, buf[MAXPATHLEN]; - - name = NULL; - COMPQUIET(fnum, 0); - - LOG_PANIC_CHECK(dblp); - -#define OKFLAGS (DB_ARCH_ABS | DB_ARCH_DATA | DB_ARCH_LOG) - if (flags != 0) { - if ((ret = - __db_fchk(dblp->dbenv, "log_archive", flags, OKFLAGS)) != 0) - return (ret); - if ((ret = - __db_fcchk(dblp->dbenv, - "log_archive", flags, DB_ARCH_DATA, DB_ARCH_LOG)) != 0) - return (ret); - } - - /* - * Get the absolute pathname of the current directory. It would - * be nice to get the shortest pathname of the database directory, - * but that's just not possible. - */ - if (LF_ISSET(DB_ARCH_ABS)) { - errno = 0; - if ((pref = getcwd(buf, sizeof(buf))) == NULL) - return (errno == 0 ? ENOMEM : errno); - } else - pref = NULL; - - switch (LF_ISSET(~DB_ARCH_ABS)) { - case DB_ARCH_DATA: - return (__build_data(dblp, pref, listp, db_malloc)); - case DB_ARCH_LOG: - memset(&rec, 0, sizeof(rec)); - if (F_ISSET(dblp, DB_AM_THREAD)) - F_SET(&rec, DB_DBT_MALLOC); - if ((ret = log_get(dblp, &stable_lsn, &rec, DB_LAST)) != 0) - return (ret); - if (F_ISSET(dblp, DB_AM_THREAD)) - __os_free(rec.data, rec.size); - fnum = stable_lsn.file; - break; - case 0: - if ((ret = __log_findckp(dblp, &stable_lsn)) != 0) { - /* - * A return of DB_NOTFOUND means that we didn't find - * any records in the log (so we are not going to be - * deleting any log files). - */ - if (ret != DB_NOTFOUND) - return (ret); - *listp = NULL; - return (0); - } - /* Remove any log files before the last stable LSN. */ - fnum = stable_lsn.file - 1; - break; - } - -#define LIST_INCREMENT 64 - /* Get some initial space. */ - array_size = 10; - if ((ret = __os_malloc(sizeof(char *) * array_size, NULL, &array)) != 0) - return (ret); - array[0] = NULL; - - /* Build an array of the file names. */ - for (n = 0; fnum > 0; --fnum) { - if ((ret = __log_name(dblp, fnum, &name, NULL, 0)) != 0) - goto err; - if (__os_exists(name, NULL) != 0) { - __os_freestr(name); - name = NULL; - break; - } - - if (n >= array_size - 1) { - array_size += LIST_INCREMENT; - if ((ret = __os_realloc(&array, - sizeof(char *) * array_size)) != 0) - goto err; - } - - if (LF_ISSET(DB_ARCH_ABS)) { - if ((ret = __absname(pref, name, &array[n])) != 0) - goto err; - __os_freestr(name); - } else if ((p = __db_rpath(name)) != NULL) { - if ((ret = __os_strdup(p + 1, &array[n])) != 0) - goto err; - __os_freestr(name); - } else - array[n] = name; - - name = NULL; - array[++n] = NULL; - } - - /* If there's nothing to return, we're done. */ - if (n == 0) { - *listp = NULL; - ret = 0; - goto err; - } - - /* Sort the list. */ - qsort(array, (size_t)n, sizeof(char *), __cmpfunc); - - /* Rework the memory. */ - if ((ret = __usermem(&array, db_malloc)) != 0) - goto err; - - *listp = array; - return (0); - -err: if (array != NULL) { - for (arrayp = array; *arrayp != NULL; ++arrayp) - __os_freestr(*arrayp); - __os_free(array, sizeof(char *) * array_size); - } - if (name != NULL) - __os_freestr(name); - return (ret); -} - -/* - * __build_data -- - * Build a list of datafiles for return. - */ -static int -__build_data(dblp, pref, listp, db_malloc) - DB_LOG *dblp; - char *pref, ***listp; - void *(*db_malloc) __P((size_t)); -{ - DBT rec; - DB_LSN lsn; - __log_register_args *argp; - u_int32_t rectype; - int array_size, last, n, nxt, ret; - char **array, **arrayp, *p, *real_name; - - /* Get some initial space. */ - array_size = 10; - if ((ret = __os_malloc(sizeof(char *) * array_size, NULL, &array)) != 0) - return (ret); - array[0] = NULL; - - memset(&rec, 0, sizeof(rec)); - if (F_ISSET(dblp, DB_AM_THREAD)) - F_SET(&rec, DB_DBT_MALLOC); - for (n = 0, ret = log_get(dblp, &lsn, &rec, DB_FIRST); - ret == 0; ret = log_get(dblp, &lsn, &rec, DB_NEXT)) { - if (rec.size < sizeof(rectype)) { - ret = EINVAL; - __db_err(dblp->dbenv, "log_archive: bad log record"); - goto lg_free; - } - - memcpy(&rectype, rec.data, sizeof(rectype)); - if (rectype != DB_log_register) { - if (F_ISSET(dblp, DB_AM_THREAD)) { - __os_free(rec.data, rec.size); - rec.data = NULL; - } - continue; - } - if ((ret = __log_register_read(rec.data, &argp)) != 0) { - ret = EINVAL; - __db_err(dblp->dbenv, - "log_archive: unable to read log record"); - goto lg_free; - } - - if (n >= array_size - 1) { - array_size += LIST_INCREMENT; - if ((ret = __os_realloc(&array, - sizeof(char *) * array_size)) != 0) - goto lg_free; - } - - if ((ret = __os_strdup(argp->name.data, &array[n])) != 0) { -lg_free: if (F_ISSET(&rec, DB_DBT_MALLOC) && rec.data != NULL) - __os_free(rec.data, rec.size); - goto err1; - } - - array[++n] = NULL; - __os_free(argp, 0); - - if (F_ISSET(dblp, DB_AM_THREAD)) { - __os_free(rec.data, rec.size); - rec.data = NULL; - } - } - - /* If there's nothing to return, we're done. */ - if (n == 0) { - ret = 0; - *listp = NULL; - goto err1; - } - - /* Sort the list. */ - qsort(array, (size_t)n, sizeof(char *), __cmpfunc); - - /* - * Build the real pathnames, discarding nonexistent files and - * duplicates. - */ - for (last = nxt = 0; nxt < n;) { - /* - * Discard duplicates. Last is the next slot we're going - * to return to the user, nxt is the next slot that we're - * going to consider. - */ - if (last != nxt) { - array[last] = array[nxt]; - array[nxt] = NULL; - } - for (++nxt; nxt < n && - strcmp(array[last], array[nxt]) == 0; ++nxt) { - __os_freestr(array[nxt]); - array[nxt] = NULL; - } - - /* Get the real name. */ - if ((ret = __db_appname(dblp->dbenv, - DB_APP_DATA, NULL, array[last], 0, NULL, &real_name)) != 0) - goto err2; - - /* If the file doesn't exist, ignore it. */ - if (__os_exists(real_name, NULL) != 0) { - __os_freestr(real_name); - __os_freestr(array[last]); - array[last] = NULL; - continue; - } - - /* Rework the name as requested by the user. */ - __os_freestr(array[last]); - array[last] = NULL; - if (pref != NULL) { - ret = __absname(pref, real_name, &array[last]); - __os_freestr(real_name); - if (ret != 0) - goto err2; - } else if ((p = __db_rpath(real_name)) != NULL) { - ret = __os_strdup(p + 1, &array[last]); - __os_freestr(real_name); - if (ret != 0) - goto err2; - } else - array[last] = real_name; - ++last; - } - - /* NULL-terminate the list. */ - array[last] = NULL; - - /* Rework the memory. */ - if ((ret = __usermem(&array, db_malloc)) != 0) - goto err1; - - *listp = array; - return (0); - -err2: /* - * XXX - * We've possibly inserted NULLs into the array list, so clean up a - * bit so that the other error processing works. - */ - if (array != NULL) - for (; nxt < n; ++nxt) - __os_freestr(array[nxt]); - /* FALLTHROUGH */ - -err1: if (array != NULL) { - for (arrayp = array; *arrayp != NULL; ++arrayp) - __os_freestr(*arrayp); - __os_free(array, array_size * sizeof(char *)); - } - return (ret); -} - -/* - * __absname -- - * Return an absolute path name for the file. - */ -static int -__absname(pref, name, newnamep) - char *pref, *name, **newnamep; -{ - size_t l_pref, l_name; - int isabspath, ret; - char *newname; - - l_name = strlen(name); - isabspath = __os_abspath(name); - l_pref = isabspath ? 0 : strlen(pref); - - /* Malloc space for concatenating the two. */ - if ((ret = __os_malloc(l_pref + l_name + 2, NULL, &newname)) != 0) - return (ret); - *newnamep = newname; - - /* Build the name. If `name' is an absolute path, ignore any prefix. */ - if (!isabspath) { - memcpy(newname, pref, l_pref); - if (strchr(PATH_SEPARATOR, newname[l_pref - 1]) == NULL) - newname[l_pref++] = PATH_SEPARATOR[0]; - } - memcpy(newname + l_pref, name, l_name + 1); - - return (0); -} - -/* - * __usermem -- - * Create a single chunk of memory that holds the returned information. - * If the user has their own malloc routine, use it. - */ -static int -__usermem(listp, db_malloc) - char ***listp; - void *(*db_malloc) __P((size_t)); -{ - size_t len; - int ret; - char **array, **arrayp, **orig, *strp; - - /* Find out how much space we need. */ - for (len = 0, orig = *listp; *orig != NULL; ++orig) - len += sizeof(char *) + strlen(*orig) + 1; - len += sizeof(char *); - - /* Allocate it and set up the pointers. */ - if ((ret = __os_malloc(len, db_malloc, &array)) != 0) - return (ret); - - strp = (char *)(array + (orig - *listp) + 1); - - /* Copy the original information into the new memory. */ - for (orig = *listp, arrayp = array; *orig != NULL; ++orig, ++arrayp) { - len = strlen(*orig); - memcpy(strp, *orig, len + 1); - *arrayp = strp; - strp += len + 1; - - __os_freestr(*orig); - } - - /* NULL-terminate the list. */ - *arrayp = NULL; - - __os_free(*listp, 0); - *listp = array; - - return (0); -} - -static int -__cmpfunc(p1, p2) - const void *p1, *p2; -{ - return (strcmp(*((char * const *)p1), *((char * const *)p2))); -} diff --git a/db2/log/log_auto.c b/db2/log/log_auto.c deleted file mode 100644 index 92e6826..0000000 --- a/db2/log/log_auto.c +++ /dev/null @@ -1,231 +0,0 @@ -/* Do not edit: automatically built by dist/db_gen.sh. */ -#include "config.h" - -#ifndef NO_SYSTEM_INCLUDES -#include <ctype.h> -#include <errno.h> -#include <stddef.h> -#include <stdlib.h> -#include <string.h> -#endif - -#include "db_int.h" -#include "db_page.h" -#include "db_dispatch.h" -#include "log.h" -#include "db_am.h" -/* - * PUBLIC: int __log_register_log - * PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - * PUBLIC: u_int32_t, const DBT *, const DBT *, u_int32_t, - * PUBLIC: DBTYPE)); - */ -int __log_register_log(logp, txnid, ret_lsnp, flags, - opcode, name, uid, id, ftype) - DB_LOG *logp; - DB_TXN *txnid; - DB_LSN *ret_lsnp; - u_int32_t flags; - u_int32_t opcode; - const DBT *name; - const DBT *uid; - u_int32_t id; - DBTYPE ftype; -{ - DBT logrec; - DB_LSN *lsnp, null_lsn; - u_int32_t zero; - u_int32_t rectype, txn_num; - int ret; - u_int8_t *bp; - - rectype = DB_log_register; - txn_num = txnid == NULL ? 0 : txnid->txnid; - if (txnid == NULL) { - ZERO_LSN(null_lsn); - lsnp = &null_lsn; - } else - lsnp = &txnid->last_lsn; - logrec.size = sizeof(rectype) + sizeof(txn_num) + sizeof(DB_LSN) - + sizeof(opcode) - + sizeof(u_int32_t) + (name == NULL ? 0 : name->size) - + sizeof(u_int32_t) + (uid == NULL ? 0 : uid->size) - + sizeof(id) - + sizeof(ftype); - if ((ret = __os_malloc(logrec.size, NULL, &logrec.data)) != 0) - return (ret); - - bp = logrec.data; - memcpy(bp, &rectype, sizeof(rectype)); - bp += sizeof(rectype); - memcpy(bp, &txn_num, sizeof(txn_num)); - bp += sizeof(txn_num); - memcpy(bp, lsnp, sizeof(DB_LSN)); - bp += sizeof(DB_LSN); - memcpy(bp, &opcode, sizeof(opcode)); - bp += sizeof(opcode); - if (name == NULL) { - zero = 0; - memcpy(bp, &zero, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - } else { - memcpy(bp, &name->size, sizeof(name->size)); - bp += sizeof(name->size); - memcpy(bp, name->data, name->size); - bp += name->size; - } - if (uid == NULL) { - zero = 0; - memcpy(bp, &zero, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - } else { - memcpy(bp, &uid->size, sizeof(uid->size)); - bp += sizeof(uid->size); - memcpy(bp, uid->data, uid->size); - bp += uid->size; - } - memcpy(bp, &id, sizeof(id)); - bp += sizeof(id); - memcpy(bp, &ftype, sizeof(ftype)); - bp += sizeof(ftype); -#ifdef DIAGNOSTIC - if ((u_int32_t)(bp - (u_int8_t *)logrec.data) != logrec.size) - fprintf(stderr, "Error in log record length"); -#endif - ret = __log_put(logp, ret_lsnp, (DBT *)&logrec, flags); - if (txnid != NULL) - txnid->last_lsn = *ret_lsnp; - __os_free(logrec.data, 0); - return (ret); -} - -/* - * PUBLIC: int __log_register_print - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__log_register_print(notused1, dbtp, lsnp, notused2, notused3) - DB_LOG *notused1; - DBT *dbtp; - DB_LSN *lsnp; - int notused2; - void *notused3; -{ - __log_register_args *argp; - u_int32_t i; - u_int ch; - int ret; - - i = 0; - ch = 0; - notused1 = NULL; - notused2 = 0; - notused3 = NULL; - - if ((ret = __log_register_read(dbtp->data, &argp)) != 0) - return (ret); - printf("[%lu][%lu]log_register: rec: %lu txnid %lx prevlsn [%lu][%lu]\n", - (u_long)lsnp->file, - (u_long)lsnp->offset, - (u_long)argp->type, - (u_long)argp->txnid->txnid, - (u_long)argp->prev_lsn.file, - (u_long)argp->prev_lsn.offset); - printf("\topcode: %lu\n", (u_long)argp->opcode); - printf("\tname: "); - for (i = 0; i < argp->name.size; i++) { - ch = ((u_int8_t *)argp->name.data)[i]; - if (isprint(ch) || ch == 0xa) - putchar(ch); - else - printf("%#x ", ch); - } - printf("\n"); - printf("\tuid: "); - for (i = 0; i < argp->uid.size; i++) { - ch = ((u_int8_t *)argp->uid.data)[i]; - if (isprint(ch) || ch == 0xa) - putchar(ch); - else - printf("%#x ", ch); - } - printf("\n"); - printf("\tid: %lu\n", (u_long)argp->id); - printf("\tftype: 0x%lx\n", (u_long)argp->ftype); - printf("\n"); - __os_free(argp, 0); - return (0); -} - -/* - * PUBLIC: int __log_register_read __P((void *, __log_register_args **)); - */ -int -__log_register_read(recbuf, argpp) - void *recbuf; - __log_register_args **argpp; -{ - __log_register_args *argp; - u_int8_t *bp; - int ret; - - ret = __os_malloc(sizeof(__log_register_args) + - sizeof(DB_TXN), NULL, &argp); - if (ret != 0) - return (ret); - argp->txnid = (DB_TXN *)&argp[1]; - bp = recbuf; - memcpy(&argp->type, bp, sizeof(argp->type)); - bp += sizeof(argp->type); - memcpy(&argp->txnid->txnid, bp, sizeof(argp->txnid->txnid)); - bp += sizeof(argp->txnid->txnid); - memcpy(&argp->prev_lsn, bp, sizeof(DB_LSN)); - bp += sizeof(DB_LSN); - memcpy(&argp->opcode, bp, sizeof(argp->opcode)); - bp += sizeof(argp->opcode); - memcpy(&argp->name.size, bp, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - argp->name.data = bp; - bp += argp->name.size; - memcpy(&argp->uid.size, bp, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - argp->uid.data = bp; - bp += argp->uid.size; - memcpy(&argp->id, bp, sizeof(argp->id)); - bp += sizeof(argp->id); - memcpy(&argp->ftype, bp, sizeof(argp->ftype)); - bp += sizeof(argp->ftype); - *argpp = argp; - return (0); -} - -/* - * PUBLIC: int __log_init_print __P((DB_ENV *)); - */ -int -__log_init_print(dbenv) - DB_ENV *dbenv; -{ - int ret; - - if ((ret = __db_add_recovery(dbenv, - __log_register_print, DB_log_register)) != 0) - return (ret); - return (0); -} - -/* - * PUBLIC: int __log_init_recover __P((DB_ENV *)); - */ -int -__log_init_recover(dbenv) - DB_ENV *dbenv; -{ - int ret; - - if ((ret = __db_add_recovery(dbenv, - __log_register_recover, DB_log_register)) != 0) - return (ret); - return (0); -} - diff --git a/db2/log/log_compare.c b/db2/log/log_compare.c deleted file mode 100644 index 320b34a..0000000 --- a/db2/log/log_compare.c +++ /dev/null @@ -1,34 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - */ -#include "config.h" - -#ifndef lint -static const char sccsid[] = "@(#)log_compare.c 10.3 (Sleepycat) 4/10/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> -#endif - -#include "db_int.h" - -/* - * log_compare -- - * Compare two LSN's. - */ -int -log_compare(lsn0, lsn1) - const DB_LSN *lsn0, *lsn1; -{ - if (lsn0->file != lsn1->file) - return (lsn0->file < lsn1->file ? -1 : 1); - - if (lsn0->offset != lsn1->offset) - return (lsn0->offset < lsn1->offset ? -1 : 1); - - return (0); -} diff --git a/db2/log/log_findckp.c b/db2/log/log_findckp.c deleted file mode 100644 index ab13c83..0000000 --- a/db2/log/log_findckp.c +++ /dev/null @@ -1,141 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - */ - -#include "config.h" - -#ifndef lint -static const char sccsid[] = "@(#)log_findckp.c 10.17 (Sleepycat) 9/17/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <string.h> -#endif - -#include "db_int.h" -#include "shqueue.h" -#include "log.h" -#include "txn.h" -#include "common_ext.h" - -/* - * __log_findckp -- - * - * Looks for the most recent checkpoint that occurs before the most recent - * checkpoint LSN, subject to the constraint that there must be at least two - * checkpoints. The reason you need two checkpoints is that you might have - * crashed during the most recent one and may not have a copy of all the - * open files. This is the point from which recovery can start and the - * point up to which archival/truncation can take place. Checkpoints in - * the log look like: - * - * ------------------------------------------------------------------- - * | ckp A, ckplsn 100 | .... record .... | ckp B, ckplsn 600 | ... - * ------------------------------------------------------------------- - * LSN 500 LSN 1000 - * - * If we read what log returns from using the DB_CKP parameter to logput, - * we'll get the record at LSN 1000. The checkpoint LSN there is 600. - * Now we have to scan backwards looking for a checkpoint before LSN 600. - * We find one at 500. This means that we can truncate the log before - * 500 or run recovery beginning at 500. - * - * Returns 0 if we find a suitable checkpoint or we retrieved the - * first record in the log from which to start. - * Returns DB_NOTFOUND if there are no log records. - * Returns errno on error. - * - * PUBLIC: int __log_findckp __P((DB_LOG *, DB_LSN *)); - */ -int -__log_findckp(lp, lsnp) - DB_LOG *lp; - DB_LSN *lsnp; -{ - DBT data; - DB_LSN ckp_lsn, final_ckp, last_ckp, next_lsn; - __txn_ckp_args *ckp_args; - int ret, verbose; - - verbose = lp->dbenv != NULL && lp->dbenv->db_verbose != 0; - - /* - * Need to find the appropriate point from which to begin - * recovery. - */ - memset(&data, 0, sizeof(data)); - if (F_ISSET(lp, DB_AM_THREAD)) - F_SET(&data, DB_DBT_MALLOC); - ZERO_LSN(ckp_lsn); - if ((ret = log_get(lp, &last_ckp, &data, DB_CHECKPOINT)) != 0) { - if (ret == ENOENT) - goto get_first; - else - return (ret); - } - - final_ckp = last_ckp; - next_lsn = last_ckp; - do { - if (F_ISSET(lp, DB_AM_THREAD)) - __os_free(data.data, data.size); - - if ((ret = log_get(lp, &next_lsn, &data, DB_SET)) != 0) - return (ret); - if ((ret = __txn_ckp_read(data.data, &ckp_args)) != 0) { - if (F_ISSET(lp, DB_AM_THREAD)) - __os_free(data.data, data.size); - return (ret); - } - if (IS_ZERO_LSN(ckp_lsn)) - ckp_lsn = ckp_args->ckp_lsn; - if (verbose) { - __db_err(lp->dbenv, "Checkpoint at: [%lu][%lu]", - (u_long)last_ckp.file, (u_long)last_ckp.offset); - __db_err(lp->dbenv, "Checkpoint LSN: [%lu][%lu]", - (u_long)ckp_args->ckp_lsn.file, - (u_long)ckp_args->ckp_lsn.offset); - __db_err(lp->dbenv, "Previous checkpoint: [%lu][%lu]", - (u_long)ckp_args->last_ckp.file, - (u_long)ckp_args->last_ckp.offset); - } - last_ckp = next_lsn; - next_lsn = ckp_args->last_ckp; - __os_free(ckp_args, sizeof(*ckp_args)); - - /* - * Keep looping until either you 1) run out of checkpoints, - * 2) you've found a checkpoint before the most recent - * checkpoint's LSN and you have at least 2 checkpoints. - */ - } while (!IS_ZERO_LSN(next_lsn) && - (log_compare(&last_ckp, &ckp_lsn) > 0 || - log_compare(&final_ckp, &last_ckp) == 0)); - - if (F_ISSET(lp, DB_AM_THREAD)) - __os_free(data.data, data.size); - - /* - * At this point, either, next_lsn is ZERO or ckp_lsn is the - * checkpoint lsn and last_ckp is the LSN of the last checkpoint - * before ckp_lsn. If the compare in the loop is still true, then - * next_lsn must be 0 and we need to roll forward from the - * beginning of the log. - */ - if (log_compare(&last_ckp, &ckp_lsn) > 0 || - log_compare(&final_ckp, &last_ckp) == 0) { -get_first: if ((ret = log_get(lp, &last_ckp, &data, DB_FIRST)) != 0) - return (ret); - if (F_ISSET(lp, DB_AM_THREAD)) - __os_free(data.data, data.size); - } - *lsnp = last_ckp; - - return (IS_ZERO_LSN(last_ckp) ? DB_NOTFOUND : 0); -} diff --git a/db2/log/log_get.c b/db2/log/log_get.c deleted file mode 100644 index de81519..0000000 --- a/db2/log/log_get.c +++ /dev/null @@ -1,330 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - */ -#include "config.h" - -#ifndef lint -static const char sccsid[] = "@(#)log_get.c 10.38 (Sleepycat) 10/3/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <string.h> -#include <unistd.h> -#endif - -#include "db_int.h" -#include "shqueue.h" -#include "db_page.h" -#include "log.h" -#include "hash.h" -#include "common_ext.h" - -/* - * log_get -- - * Get a log record. - */ -int -log_get(dblp, alsn, dbt, flags) - DB_LOG *dblp; - DB_LSN *alsn; - DBT *dbt; - u_int32_t flags; -{ - int ret; - - LOG_PANIC_CHECK(dblp); - - /* Validate arguments. */ - if (flags != DB_CHECKPOINT && flags != DB_CURRENT && - flags != DB_FIRST && flags != DB_LAST && - flags != DB_NEXT && flags != DB_PREV && flags != DB_SET) - return (__db_ferr(dblp->dbenv, "log_get", 1)); - - if (F_ISSET(dblp, DB_AM_THREAD)) { - if (flags == DB_NEXT || flags == DB_PREV || flags == DB_CURRENT) - return (__db_ferr(dblp->dbenv, "log_get", 1)); - if (!F_ISSET(dbt, DB_DBT_USERMEM | DB_DBT_MALLOC)) - return (__db_ferr(dblp->dbenv, "threaded data", 1)); - } - - LOCK_LOGREGION(dblp); - - /* - * If we get one of the log's header records, repeat the operation. - * This assumes that applications don't ever request the log header - * records by LSN, but that seems reasonable to me. - */ - ret = __log_get(dblp, alsn, dbt, flags, 0); - if (ret == 0 && alsn->offset == 0) { - switch (flags) { - case DB_FIRST: - flags = DB_NEXT; - break; - case DB_LAST: - flags = DB_PREV; - break; - } - ret = __log_get(dblp, alsn, dbt, flags, 0); - } - - UNLOCK_LOGREGION(dblp); - - return (ret); -} - -/* - * __log_get -- - * Get a log record; internal version. - * - * PUBLIC: int __log_get __P((DB_LOG *, DB_LSN *, DBT *, u_int32_t, int)); - */ -int -__log_get(dblp, alsn, dbt, flags, silent) - DB_LOG *dblp; - DB_LSN *alsn; - DBT *dbt; - u_int32_t flags; - int silent; -{ - DB_LSN nlsn; - HDR hdr; - LOG *lp; - size_t len; - ssize_t nr; - int cnt, ret; - char *np, *tbuf; - const char *fail; - void *p, *shortp; - - lp = dblp->lp; - fail = np = tbuf = NULL; - - nlsn = dblp->c_lsn; - switch (flags) { - case DB_CHECKPOINT: - nlsn = lp->chkpt_lsn; - if (IS_ZERO_LSN(nlsn)) { - __db_err(dblp->dbenv, - "log_get: unable to find checkpoint record: no checkpoint set."); - ret = ENOENT; - goto err2; - } - break; - case DB_NEXT: /* Next log record. */ - if (!IS_ZERO_LSN(nlsn)) { - /* Increment the cursor by the cursor record size. */ - nlsn.offset += dblp->c_len; - break; - } - /* FALLTHROUGH */ - case DB_FIRST: /* Find the first log record. */ - /* Find the first log file. */ - if ((ret = __log_find(dblp, 1, &cnt)) != 0) - goto err2; - - /* - * We may have only entered records in the buffer, and not - * yet written a log file. If no log files were found and - * there's anything in the buffer, it belongs to file 1. - */ - if (cnt == 0) - cnt = 1; - - nlsn.file = cnt; - 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 || - __log_valid(dblp, nlsn.file - 1, 0) != 0) - return (DB_NOTFOUND); - - --nlsn.file; - nlsn.offset = dblp->c_off; - } else - nlsn.offset = dblp->c_off; - break; - } - /* FALLTHROUGH */ - case DB_LAST: /* Last log record. */ - nlsn.file = lp->lsn.file; - nlsn.offset = lp->lsn.offset - lp->len; - break; - case DB_SET: /* Set log record. */ - nlsn = *alsn; - break; - } - -retry: - /* Return 1 if the request is past end-of-file. */ - if (nlsn.file > lp->lsn.file || - (nlsn.file == lp->lsn.file && nlsn.offset >= lp->lsn.offset)) - return (DB_NOTFOUND); - - /* If we've switched files, discard the current fd. */ - if (dblp->c_lsn.file != nlsn.file && dblp->c_fd != -1) { - (void)__os_close(dblp->c_fd); - dblp->c_fd = -1; - } - - /* If the entire record is in the in-memory buffer, copy it out. */ - if (nlsn.file == lp->lsn.file && nlsn.offset >= lp->w_off) { - /* Copy the header. */ - p = lp->buf + (nlsn.offset - lp->w_off); - memcpy(&hdr, p, sizeof(HDR)); - - /* Copy the record. */ - len = hdr.len - sizeof(HDR); - if ((ret = __db_retcopy(dbt, (u_int8_t *)p + sizeof(HDR), - len, &dblp->c_dbt.data, &dblp->c_dbt.ulen, NULL)) != 0) - goto err1; - goto cksum; - } - - /* Acquire a file descriptor. */ - if (dblp->c_fd == -1) { - if ((ret = __log_name(dblp, nlsn.file, - &np, &dblp->c_fd, DB_RDONLY | DB_SEQUENTIAL)) != 0) { - fail = np; - goto err1; - } - __os_freestr(np); - np = NULL; - } - - /* Seek to the header offset and read the header. */ - if ((ret = - __os_seek(dblp->c_fd, 0, 0, nlsn.offset, 0, SEEK_SET)) != 0) { - fail = "seek"; - goto err1; - } - if ((ret = __os_read(dblp->c_fd, &hdr, sizeof(HDR), &nr)) != 0) { - fail = "read"; - goto err1; - } - if (nr == sizeof(HDR)) - shortp = NULL; - else { - /* If read returns EOF, try the next file. */ - if (nr == 0) { - if (flags != DB_NEXT || nlsn.file == lp->lsn.file) - goto corrupt; - - /* Move to the next file. */ - ++nlsn.file; - nlsn.offset = 0; - goto retry; - } - - /* - * If read returns a short count the rest of the record has - * to be in the in-memory buffer. - */ - if (lp->b_off < sizeof(HDR) - nr) - goto corrupt; - - /* Get the rest of the header from the in-memory buffer. */ - memcpy((u_int8_t *)&hdr + nr, lp->buf, sizeof(HDR) - nr); - shortp = lp->buf + (sizeof(HDR) - nr); - } - - /* - * Check for buffers of 0's, that's what we usually see during - * recovery, although it's certainly not something on which we - * can depend. - */ - if (hdr.len <= sizeof(HDR)) - goto corrupt; - len = hdr.len - sizeof(HDR); - - /* If we've already moved to the in-memory buffer, fill from there. */ - if (shortp != NULL) { - if (lp->b_off < ((u_int8_t *)shortp - lp->buf) + len) - goto corrupt; - if ((ret = __db_retcopy(dbt, shortp, len, - &dblp->c_dbt.data, &dblp->c_dbt.ulen, NULL)) != 0) - goto err1; - goto cksum; - } - - /* - * Allocate temporary memory to hold the record. - * - * XXX - * We're calling malloc(3) with a region locked. This isn't - * a good idea. - */ - if ((ret = __os_malloc(len, NULL, &tbuf)) != 0) - goto err1; - - /* - * Read the record into the buffer. If read returns a short count, - * there was an error or the rest of the record is in the in-memory - * buffer. Note, the information may be garbage if we're in recovery, - * so don't read past the end of the buffer's memory. - */ - if ((ret = __os_read(dblp->c_fd, tbuf, len, &nr)) != 0) { - fail = "read"; - goto err1; - } - if (len - nr > sizeof(lp->buf)) - goto corrupt; - if (nr != (ssize_t)len) { - if (lp->b_off < len - nr) - goto corrupt; - - /* Get the rest of the record from the in-memory buffer. */ - memcpy((u_int8_t *)tbuf + nr, lp->buf, len - nr); - } - - /* Copy the record into the user's DBT. */ - if ((ret = __db_retcopy(dbt, tbuf, len, - &dblp->c_dbt.data, &dblp->c_dbt.ulen, NULL)) != 0) - goto err1; - __os_free(tbuf, 0); - tbuf = NULL; - -cksum: if (hdr.cksum != __ham_func4(dbt->data, dbt->size)) { - if (!silent) - __db_err(dblp->dbenv, "log_get: checksum mismatch"); - goto corrupt; - } - - /* Update the cursor and the return lsn. */ - dblp->c_off = hdr.prev; - dblp->c_len = hdr.len; - dblp->c_lsn = *alsn = nlsn; - - return (0); - -corrupt:/* - * This is the catchall -- for some reason we didn't find enough - * information or it wasn't reasonable information, and it wasn't - * because a system call failed. - */ - ret = EIO; - fail = "read"; - -err1: if (!silent) { - if (fail == NULL) - __db_err(dblp->dbenv, "log_get: %s", strerror(ret)); - else - __db_err(dblp->dbenv, - "log_get: %s: %s", fail, strerror(ret)); - } -err2: if (np != NULL) - __os_freestr(np); - if (tbuf != NULL) - __os_free(tbuf, 0); - return (ret); -} diff --git a/db2/log/log_put.c b/db2/log/log_put.c deleted file mode 100644 index 86de6b0..0000000 --- a/db2/log/log_put.c +++ /dev/null @@ -1,603 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - */ -#include "config.h" - -#ifndef lint -static const char sccsid[] = "@(#)log_put.c 10.44 (Sleepycat) 11/3/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <stdio.h> -#include <string.h> -#include <time.h> -#include <unistd.h> -#endif - -#include "db_int.h" -#include "shqueue.h" -#include "db_page.h" -#include "log.h" -#include "hash.h" -#include "clib_ext.h" -#include "common_ext.h" - -static int __log_fill __P((DB_LOG *, DB_LSN *, void *, u_int32_t)); -static int __log_flush __P((DB_LOG *, const DB_LSN *)); -static int __log_newfd __P((DB_LOG *)); -static int __log_putr __P((DB_LOG *, DB_LSN *, const DBT *, u_int32_t)); -static int __log_write __P((DB_LOG *, void *, u_int32_t)); - -/* - * log_put -- - * Write a log record. - */ -int -log_put(dblp, lsn, dbt, flags) - DB_LOG *dblp; - DB_LSN *lsn; - const DBT *dbt; - u_int32_t flags; -{ - int ret; - - LOG_PANIC_CHECK(dblp); - - /* Validate arguments. */ - if (flags != 0 && flags != DB_CHECKPOINT && - flags != DB_CURLSN && flags != DB_FLUSH) - return (__db_ferr(dblp->dbenv, "log_put", 0)); - - LOCK_LOGREGION(dblp); - ret = __log_put(dblp, lsn, dbt, flags); - UNLOCK_LOGREGION(dblp); - return (ret); -} - -/* - * __log_put -- - * Write a log record; internal version. - * - * PUBLIC: int __log_put __P((DB_LOG *, DB_LSN *, const DBT *, u_int32_t)); - */ -int -__log_put(dblp, lsn, dbt, flags) - DB_LOG *dblp; - DB_LSN *lsn; - const DBT *dbt; - u_int32_t flags; -{ - DBT fid_dbt, t; - DB_LSN r_unused; - FNAME *fnp; - LOG *lp; - u_int32_t lastoff; - int ret; - - lp = dblp->lp; - - /* - * If the application just wants to know where we are, fill in - * the information. Currently used by the transaction manager - * to avoid writing TXN_begin records. - */ - if (flags == DB_CURLSN) { - lsn->file = lp->lsn.file; - lsn->offset = lp->lsn.offset; - return (0); - } - - /* If this information won't fit in the file, swap files. */ - if (lp->lsn.offset + sizeof(HDR) + dbt->size > lp->persist.lg_max) { - if (sizeof(HDR) + - sizeof(LOGP) + dbt->size > lp->persist.lg_max) { - __db_err(dblp->dbenv, - "log_put: record larger than maximum file size"); - return (EINVAL); - } - - /* Flush the log. */ - if ((ret = __log_flush(dblp, NULL)) != 0) - return (ret); - - /* - * Save the last known offset from the previous file, we'll - * need it to initialize the persistent header information. - */ - lastoff = lp->lsn.offset; - - /* Point the current LSN to the new file. */ - ++lp->lsn.file; - lp->lsn.offset = 0; - - /* Reset the file write offset. */ - lp->w_off = 0; - } else - lastoff = 0; - - /* Initialize the LSN information returned to the user. */ - lsn->file = lp->lsn.file; - lsn->offset = lp->lsn.offset; - - /* - * Insert persistent information as the first record in every file. - * Note that the previous length is wrong for the very first record - * of the log, but that's okay, we check for it during retrieval. - */ - if (lp->lsn.offset == 0) { - t.data = &lp->persist; - t.size = sizeof(LOGP); - if ((ret = __log_putr(dblp, lsn, - &t, lastoff == 0 ? 0 : lastoff - lp->len)) != 0) - return (ret); - - /* Update the LSN information returned to the user. */ - lsn->file = lp->lsn.file; - lsn->offset = lp->lsn.offset; - } - - /* Write the application's log record. */ - if ((ret = __log_putr(dblp, lsn, dbt, lp->lsn.offset - lp->len)) != 0) - return (ret); - - /* - * On a checkpoint, we: - * Put out the checkpoint record (above). - * Save the LSN of the checkpoint in the shared region. - * Append the set of file name information into the log. - */ - if (flags == DB_CHECKPOINT) { - lp->chkpt_lsn = *lsn; - - for (fnp = SH_TAILQ_FIRST(&dblp->lp->fq, __fname); - fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) { - if (fnp->ref == 0) /* Entry not in use. */ - continue; - memset(&t, 0, sizeof(t)); - t.data = R_ADDR(dblp, fnp->name_off); - t.size = strlen(t.data) + 1; - memset(&fid_dbt, 0, sizeof(fid_dbt)); - fid_dbt.data = fnp->ufid; - fid_dbt.size = DB_FILE_ID_LEN; - if ((ret = __log_register_log(dblp, NULL, &r_unused, 0, - LOG_CHECKPOINT, &t, &fid_dbt, fnp->id, fnp->s_type)) - != 0) - return (ret); - } - } - - /* - * On a checkpoint or when flush is requested, we: - * Flush the current buffer contents to disk. - * Sync the log to disk. - */ - if (flags == DB_FLUSH || flags == DB_CHECKPOINT) - if ((ret = __log_flush(dblp, NULL)) != 0) - return (ret); - - /* - * On a checkpoint, we: - * Save the time the checkpoint was written. - * Reset the bytes written since the last checkpoint. - */ - if (flags == DB_CHECKPOINT) { - (void)time(&lp->chkpt); - lp->stat.st_wc_bytes = lp->stat.st_wc_mbytes = 0; - } - return (0); -} - -/* - * __log_putr -- - * Actually put a record into the log. - */ -static int -__log_putr(dblp, lsn, dbt, prev) - DB_LOG *dblp; - DB_LSN *lsn; - const DBT *dbt; - u_int32_t prev; -{ - HDR hdr; - LOG *lp; - int ret; - - lp = dblp->lp; - - /* - * Initialize the header. If we just switched files, lsn.offset will - * be 0, and what we really want is the offset of the previous record - * in the previous file. Fortunately, prev holds the value we want. - */ - hdr.prev = prev; - hdr.len = sizeof(HDR) + dbt->size; - hdr.cksum = __ham_func4(dbt->data, dbt->size); - - if ((ret = __log_fill(dblp, lsn, &hdr, sizeof(HDR))) != 0) - return (ret); - lp->len = sizeof(HDR); - lp->lsn.offset += sizeof(HDR); - - if ((ret = __log_fill(dblp, lsn, dbt->data, dbt->size)) != 0) - return (ret); - lp->len += dbt->size; - lp->lsn.offset += dbt->size; - return (0); -} - -/* - * log_flush -- - * Write all records less than or equal to the specified LSN. - */ -int -log_flush(dblp, lsn) - DB_LOG *dblp; - const DB_LSN *lsn; -{ - int ret; - - LOG_PANIC_CHECK(dblp); - - LOCK_LOGREGION(dblp); - ret = __log_flush(dblp, lsn); - UNLOCK_LOGREGION(dblp); - return (ret); -} - -/* - * __log_flush -- - * Write all records less than or equal to the specified LSN; internal - * version. - */ -static int -__log_flush(dblp, lsn) - DB_LOG *dblp; - const DB_LSN *lsn; -{ - DB_LSN t_lsn; - LOG *lp; - int current, ret; - - ret = 0; - lp = dblp->lp; - - /* - * If no LSN specified, flush the entire log by setting the flush LSN - * to the last LSN written in the log. Otherwise, check that the LSN - * isn't a non-existent record for the log. - */ - if (lsn == NULL) { - t_lsn.file = lp->lsn.file; - t_lsn.offset = lp->lsn.offset - lp->len; - lsn = &t_lsn; - } else - if (lsn->file > lp->lsn.file || - (lsn->file == lp->lsn.file && - lsn->offset > lp->lsn.offset - lp->len)) { - __db_err(dblp->dbenv, - "log_flush: LSN past current end-of-log"); - return (EINVAL); - } - - /* - * If the LSN is less than the last-sync'd LSN, we're done. Note, - * the last-sync LSN saved in s_lsn is the LSN of the first byte - * we absolutely know has been written to disk, so the test is <=. - */ - if (lsn->file < lp->s_lsn.file || - (lsn->file == lp->s_lsn.file && lsn->offset <= lp->s_lsn.offset)) - return (0); - - /* - * We may need to write the current buffer. We have to write the - * current buffer if the flush LSN is greater than or equal to the - * buffer's starting LSN. - */ - current = 0; - if (lp->b_off != 0 && log_compare(lsn, &lp->f_lsn) >= 0) { - if ((ret = __log_write(dblp, lp->buf, lp->b_off)) != 0) - return (ret); - - lp->b_off = 0; - current = 1; - } - - /* - * It's possible that this thread may never have written to this log - * file. Acquire a file descriptor if we don't already have one. - */ - if (dblp->lfname != dblp->lp->lsn.file) - if ((ret = __log_newfd(dblp)) != 0) - return (ret); - - /* Sync all writes to disk. */ - if ((ret = __os_fsync(dblp->lfd)) != 0) { - __db_panic(dblp->dbenv, ret); - return (ret); - } - ++lp->stat.st_scount; - - /* - * Set the last-synced LSN, using the LSN of the current buffer. If - * the current buffer was flushed, we know the LSN of the first byte - * of the buffer is on disk, otherwise, we only know that the LSN of - * the record before the one beginning the current buffer is on disk. - * - * XXX - * Check to make sure that the saved lsn isn't 0 before we go making - * this change. If DB_CHECKPOINT was called before we actually wrote - * something, you can end up here without ever having written anything - * to a log file, and decrementing either s_lsn.file or s_lsn.offset - * will cause much sadness later on. - */ - lp->s_lsn = lp->f_lsn; - if (!current && lp->s_lsn.file != 0) { - if (lp->s_lsn.offset == 0) { - --lp->s_lsn.file; - lp->s_lsn.offset = lp->persist.lg_max; - } else - --lp->s_lsn.offset; - } - - return (0); -} - -/* - * __log_fill -- - * Write information into the log. - */ -static int -__log_fill(dblp, lsn, addr, len) - DB_LOG *dblp; - DB_LSN *lsn; - void *addr; - u_int32_t len; -{ - LOG *lp; - u_int32_t nrec; - size_t nw, remain; - int ret; - - /* Copy out the data. */ - for (lp = dblp->lp; len > 0;) { - /* - * If we're beginning a new buffer, note the user LSN to which - * the first byte of the buffer belongs. We have to know this - * when flushing the buffer so that we know if the in-memory - * buffer needs to be flushed. - */ - if (lp->b_off == 0) - lp->f_lsn = *lsn; - - /* - * If we're on a buffer boundary and the data is big enough, - * copy as many records as we can directly from the data. - */ - if (lp->b_off == 0 && len >= sizeof(lp->buf)) { - nrec = len / sizeof(lp->buf); - if ((ret = __log_write(dblp, - addr, nrec * sizeof(lp->buf))) != 0) - return (ret); - addr = (u_int8_t *)addr + nrec * sizeof(lp->buf); - len -= nrec * sizeof(lp->buf); - continue; - } - - /* Figure out how many bytes we can copy this time. */ - remain = sizeof(lp->buf) - lp->b_off; - nw = remain > len ? len : remain; - memcpy(lp->buf + lp->b_off, addr, nw); - addr = (u_int8_t *)addr + nw; - len -= nw; - lp->b_off += nw; - - /* If we fill the buffer, flush it. */ - if (lp->b_off == sizeof(lp->buf)) { - if ((ret = - __log_write(dblp, lp->buf, sizeof(lp->buf))) != 0) - return (ret); - lp->b_off = 0; - } - } - return (0); -} - -/* - * __log_write -- - * Write the log buffer to disk. - */ -static int -__log_write(dblp, addr, len) - DB_LOG *dblp; - void *addr; - u_int32_t len; -{ - LOG *lp; - ssize_t nw; - int ret; - - /* - * If we haven't opened the log file yet or the current one - * has changed, acquire a new log file. - */ - lp = dblp->lp; - if (dblp->lfd == -1 || dblp->lfname != lp->lsn.file) - if ((ret = __log_newfd(dblp)) != 0) - return (ret); - - /* - * Seek to the offset in the file (someone may have written it - * since we last did). - */ - if ((ret = __os_seek(dblp->lfd, 0, 0, lp->w_off, 0, SEEK_SET)) != 0 || - (ret = __os_write(dblp->lfd, addr, len, &nw)) != 0) { - __db_panic(dblp->dbenv, ret); - return (ret); - } - if (nw != (int32_t)len) - return (EIO); - - /* Reset the buffer offset and update the seek offset. */ - lp->w_off += len; - - /* Update written statistics. */ - if ((lp->stat.st_w_bytes += len) >= MEGABYTE) { - lp->stat.st_w_bytes -= MEGABYTE; - ++lp->stat.st_w_mbytes; - } - if ((lp->stat.st_wc_bytes += len) >= MEGABYTE) { - lp->stat.st_wc_bytes -= MEGABYTE; - ++lp->stat.st_wc_mbytes; - } - ++lp->stat.st_wcount; - - return (0); -} - -/* - * log_file -- - * Map a DB_LSN to a file name. - */ -int -log_file(dblp, lsn, namep, len) - DB_LOG *dblp; - const DB_LSN *lsn; - char *namep; - size_t len; -{ - int ret; - char *name; - - LOG_PANIC_CHECK(dblp); - - LOCK_LOGREGION(dblp); - ret = __log_name(dblp, lsn->file, &name, NULL, 0); - UNLOCK_LOGREGION(dblp); - if (ret != 0) - return (ret); - - /* Check to make sure there's enough room and copy the name. */ - if (len < strlen(name) + 1) { - *namep = '\0'; - return (ENOMEM); - } - (void)strcpy(namep, name); - __os_freestr(name); - - return (0); -} - -/* - * __log_newfd -- - * Acquire a file descriptor for the current log file. - */ -static int -__log_newfd(dblp) - DB_LOG *dblp; -{ - int ret; - char *name; - - /* Close any previous file descriptor. */ - if (dblp->lfd != -1) { - (void)__os_close(dblp->lfd); - dblp->lfd = -1; - } - - /* Get the path of the new file and open it. */ - dblp->lfname = dblp->lp->lsn.file; - if ((ret = __log_name(dblp, - dblp->lfname, &name, &dblp->lfd, DB_CREATE | DB_SEQUENTIAL)) != 0) - __db_err(dblp->dbenv, "log_put: %s: %s", name, strerror(ret)); - - __os_freestr(name); - return (ret); -} - -/* - * __log_name -- - * Return the log name for a particular file, and optionally open it. - * - * PUBLIC: int __log_name __P((DB_LOG *, u_int32_t, char **, int *, u_int32_t)); - */ -int -__log_name(dblp, filenumber, namep, fdp, flags) - DB_LOG *dblp; - u_int32_t filenumber, flags; - char **namep; - int *fdp; -{ - int ret; - char *oname; - char old[sizeof(LFPREFIX) + 5 + 20], new[sizeof(LFPREFIX) + 10 + 20]; - - /* - * !!! - * The semantics of this routine are bizarre. - * - * The reason for all of this is that we need a place where we can - * intercept requests for log files, and, if appropriate, check for - * both the old-style and new-style log file names. The trick is - * that all callers of this routine that are opening the log file - * read-only want to use an old-style file name if they can't find - * a match using a new-style name. The only down-side is that some - * callers may check for the old-style when they really don't need - * to, but that shouldn't mess up anything, and we only check for - * the old-style name when we've already failed to find a new-style - * one. - * - * Create a new-style file name, and if we're not going to open the - * file, return regardless. - */ - (void)snprintf(new, sizeof(new), LFNAME, filenumber); - if ((ret = __db_appname(dblp->dbenv, - DB_APP_LOG, dblp->dir, new, 0, NULL, namep)) != 0 || fdp == NULL) - return (ret); - - /* Open the new-style file -- if we succeed, we're done. */ - if ((ret = __db_open(*namep, - flags, flags, dblp->lp->persist.mode, fdp)) == 0) - return (0); - - /* - * The open failed... if the DB_RDONLY flag isn't set, we're done, - * the caller isn't interested in old-style files. - */ - if (!LF_ISSET(DB_RDONLY)) - return (ret); - - /* Create an old-style file name. */ - (void)snprintf(old, sizeof(old), LFNAME_V1, filenumber); - if ((ret = __db_appname(dblp->dbenv, - DB_APP_LOG, dblp->dir, old, 0, NULL, &oname)) != 0) - goto err; - - /* - * Open the old-style file -- if we succeed, we're done. Free the - * space allocated for the new-style name and return the old-style - * name to the caller. - */ - if ((ret = __db_open(oname, - flags, flags, dblp->lp->persist.mode, fdp)) == 0) { - __os_freestr(*namep); - *namep = oname; - return (0); - } - - /* - * Couldn't find either style of name -- return the new-style name - * for the caller's error message. If it's an old-style name that's - * actually missing we're going to confuse the user with the error - * message, but that implies that not only were we looking for an - * old-style name, but we expected it to exist and we weren't just - * looking for any log file. That's not a likely error. - */ -err: __os_freestr(oname); - return (ret); -} diff --git a/db2/log/log_rec.c b/db2/log/log_rec.c deleted file mode 100644 index 8895150..0000000 --- a/db2/log/log_rec.c +++ /dev/null @@ -1,398 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - */ -/* - * Copyright (c) 1995, 1996 - * The President and Fellows of Harvard University. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "config.h" - -#ifndef lint -static const char sccsid[] = "@(#)log_rec.c 10.26 (Sleepycat) 10/21/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <string.h> -#endif - -#include "db_int.h" -#include "shqueue.h" -#include "log.h" -#include "db_dispatch.h" -#include "common_ext.h" - -static int __log_do_open __P((DB_LOG *, - u_int8_t *, char *, DBTYPE, u_int32_t)); -static int __log_lid_to_fname __P((DB_LOG *, u_int32_t, FNAME **)); -static int __log_open_file __P((DB_LOG *, __log_register_args *)); - -/* - * PUBLIC: int __log_register_recover - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__log_register_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __log_register_args *argp; - int ret; - -#ifdef DEBUG_RECOVER - __log_register_print(logp, dbtp, lsnp, redo, info); -#endif - COMPQUIET(info, NULL); - COMPQUIET(lsnp, NULL); - - F_SET(logp, DBC_RECOVER); - - if ((ret = __log_register_read(dbtp->data, &argp)) != 0) - goto out; - - if ((argp->opcode == LOG_CHECKPOINT && redo == TXN_OPENFILES) || - (argp->opcode == LOG_OPEN && - (redo == TXN_REDO || redo == TXN_OPENFILES || - redo == TXN_FORWARD_ROLL)) || - (argp->opcode == LOG_CLOSE && - (redo == TXN_UNDO || redo == TXN_BACKWARD_ROLL))) { - /* - * If we are redoing an open or undoing a close, then we need - * to open a file. - */ - ret = __log_open_file(logp, argp); - if (ret == ENOENT) { - if (redo == TXN_OPENFILES) - __db_err(logp->dbenv, "warning: %s: %s", - argp->name.data, strerror(ENOENT)); - ret = 0; - } - } else if (argp->opcode != LOG_CHECKPOINT) { - /* - * If we are redoing a close or undoing an open, then we need - * to close the file. - * - * If the file is deleted, then we can just ignore this close. - * Otherwise, we should usually have a valid dbp we should - * close or whose reference count should be decremented. - * However, if we shut down without closing a file, we - * may, in fact, not have the file open, and that's OK. - */ - LOCK_LOGTHREAD(logp); - if (logp->dbentry[argp->id].dbp != NULL && - --logp->dbentry[argp->id].refcount == 0) { - ret = logp->dbentry[argp->id].dbp->close( - logp->dbentry[argp->id].dbp, 0); - logp->dbentry[argp->id].dbp = NULL; - } - UNLOCK_LOGTHREAD(logp); - } else if (redo == TXN_UNDO && - (argp->id >= logp->dbentry_cnt || - (!logp->dbentry[argp->id].deleted && - logp->dbentry[argp->id].dbp == NULL))) { - /* - * It's a checkpoint and we are rolling backward. It - * is possible that the system was shut down and thus - * ended with a stable checkpoint; this file was never - * closed and has therefore not been reopened yet. If - * so, we need to try to open it. - */ - ret = __log_open_file(logp, argp); - if (ret == ENOENT) { - __db_err(logp->dbenv, "warning: %s: %s", - argp->name.data, strerror(ENOENT)); - ret = 0; - } - } - -out: F_CLR(logp, DBC_RECOVER); - if (argp != NULL) - __os_free(argp, 0); - return (ret); -} - -/* Hand coded routines. */ - -/* - * Called during log_register recovery. Make sure that we have an - * entry in the dbentry table for this ndx. - * Returns 0 on success, non-zero on error. - */ -static int -__log_open_file(lp, argp) - DB_LOG *lp; - __log_register_args *argp; -{ - LOCK_LOGTHREAD(lp); - if (argp->id < lp->dbentry_cnt && - (lp->dbentry[argp->id].deleted == 1 || - lp->dbentry[argp->id].dbp != NULL)) { - if (argp->opcode != LOG_CHECKPOINT) - lp->dbentry[argp->id].refcount++; - - UNLOCK_LOGTHREAD(lp); - return (0); - } - UNLOCK_LOGTHREAD(lp); - return (__log_do_open(lp, - argp->uid.data, argp->name.data, argp->ftype, argp->id)); -} - -/* - * __log_do_open -- - * Open files referenced in the log. This is the part of the open that - * is not protected by the thread mutex. - */ - -static int -__log_do_open(lp, uid, name, ftype, ndx) - DB_LOG *lp; - u_int8_t *uid; - char *name; - DBTYPE ftype; - u_int32_t ndx; -{ - DB *dbp; - int ret; - - dbp = NULL; - if ((ret = db_open(name, ftype, 0, 0, lp->dbenv, NULL, &dbp)) == 0) { - /* - * Verify that we are opening the same file that we were - * referring to when we wrote this log record. - */ - if (memcmp(uid, dbp->fileid, DB_FILE_ID_LEN) != 0) { - (void)dbp->close(dbp, 0); - dbp = NULL; - ret = ENOENT; - } - } - - if (ret == 0 || ret == ENOENT) - (void)__log_add_logid(lp, dbp, ndx); - - return (ret); -} - -/* - * __log_add_logid -- - * Adds a DB entry to the log's DB entry table. - * - * PUBLIC: int __log_add_logid __P((DB_LOG *, DB *, u_int32_t)); - */ -int -__log_add_logid(logp, dbp, ndx) - DB_LOG *logp; - DB *dbp; - u_int32_t ndx; -{ - u_int32_t i; - int ret; - - ret = 0; - - LOCK_LOGTHREAD(logp); - - /* - * Check if we need to grow the table. Note, ndx is 0-based (the - * index into the DB entry table) an dbentry_cnt is 1-based, the - * number of available slots. - */ - if (logp->dbentry_cnt <= ndx) { - if ((ret = __os_realloc(&logp->dbentry, - (ndx + DB_GROW_SIZE) * sizeof(DB_ENTRY))) != 0) - goto err; - - /* Initialize the new entries. */ - for (i = logp->dbentry_cnt; i < ndx + DB_GROW_SIZE; i++) { - logp->dbentry[i].dbp = NULL; - logp->dbentry[i].deleted = 0; - } - - logp->dbentry_cnt = i; - } - - if (logp->dbentry[ndx].deleted == 0 && logp->dbentry[ndx].dbp == NULL) { - logp->dbentry[ndx].dbp = dbp; - logp->dbentry[ndx].refcount = 1; - logp->dbentry[ndx].deleted = dbp == NULL; - } else - logp->dbentry[ndx].refcount++; - -err: UNLOCK_LOGTHREAD(logp); - return (ret); -} - - -/* - * __db_fileid_to_db -- - * Return the DB corresponding to the specified fileid. - * - * PUBLIC: int __db_fileid_to_db __P((DB_LOG *, DB **, u_int32_t)); - */ -int -__db_fileid_to_db(logp, dbpp, ndx) - DB_LOG *logp; - DB **dbpp; - u_int32_t ndx; -{ - int ret; - char *name; - FNAME *fname; - - ret = 0; - LOCK_LOGTHREAD(logp); - - /* - * Under XA, a process different than the one issuing DB - * operations may abort a transaction. In this case, - * recovery routines are run by a process that does not - * necessarily have the file open. In this case, we must - * open the file explicitly. - */ - if (ndx >= logp->dbentry_cnt || - (!logp->dbentry[ndx].deleted && logp->dbentry[ndx].dbp == NULL)) { - if (__log_lid_to_fname(logp, ndx, &fname) != 0) { - /* Couldn't find entry; this is a fatal error. */ - ret = EINVAL; - goto err; - } - name = R_ADDR(logp, fname->name_off); - /* - * __log_do_open is called without protection of the - * log thread lock. - */ - UNLOCK_LOGTHREAD(logp); - /* - * At this point, we are not holding the thread lock, so - * exit directly instead of going through the exit code - * at the bottom. If the __log_do_open succeeded, then - * we don't need to do any of the remaining error checking - * at the end of this routine. - */ - if ((ret = __log_do_open(logp, - fname->ufid, name, fname->s_type, ndx)) != 0) - return (ret); - *dbpp = logp->dbentry[ndx].dbp; - return (0); - } - - /* - * Return DB_DELETED if the file has been deleted - * (it's not an error). - */ - if (logp->dbentry[ndx].deleted) { - ret = DB_DELETED; - goto err; - } - - /* - * Otherwise return 0, but if we don't have a corresponding DB, - * it's an error. - */ - if ((*dbpp = logp->dbentry[ndx].dbp) == NULL) - ret = ENOENT; - -err: UNLOCK_LOGTHREAD(logp); - return (ret); -} - -/* - * Close files that were opened by the recovery daemon. - * - * PUBLIC: void __log_close_files __P((DB_LOG *)); - */ -void -__log_close_files(logp) - DB_LOG *logp; -{ - u_int32_t i; - - LOCK_LOGTHREAD(logp); - for (i = 0; i < logp->dbentry_cnt; i++) - if (logp->dbentry[i].dbp) { - logp->dbentry[i].dbp->close(logp->dbentry[i].dbp, 0); - logp->dbentry[i].dbp = NULL; - logp->dbentry[i].deleted = 0; - } - F_CLR(logp, DBC_RECOVER); - UNLOCK_LOGTHREAD(logp); -} - -/* - * PUBLIC: void __log_rem_logid __P((DB_LOG *, u_int32_t)); - */ -void -__log_rem_logid(logp, ndx) - DB_LOG *logp; - u_int32_t ndx; -{ - LOCK_LOGTHREAD(logp); - if (--logp->dbentry[ndx].refcount == 0) { - logp->dbentry[ndx].dbp = NULL; - logp->dbentry[ndx].deleted = 0; - } - UNLOCK_LOGTHREAD(logp); -} - -/* - * __log_lid_to_fname -- - * Traverse the shared-memory region looking for the entry that - * matches the passed log fileid. Returns 0 on success; -1 on error. - */ -static int -__log_lid_to_fname(dblp, lid, fnamep) - DB_LOG *dblp; - u_int32_t lid; - FNAME **fnamep; -{ - FNAME *fnp; - - for (fnp = SH_TAILQ_FIRST(&dblp->lp->fq, __fname); - fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) { - if (fnp->ref == 0) /* Entry not in use. */ - continue; - if (fnp->id == lid) { - *fnamep = fnp; - return (0); - } - } - return (-1); -} diff --git a/db2/log/log_register.c b/db2/log/log_register.c deleted file mode 100644 index 22264e3..0000000 --- a/db2/log/log_register.c +++ /dev/null @@ -1,208 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - */ -#include "config.h" - -#ifndef lint -static const char sccsid[] = "@(#)log_register.c 10.22 (Sleepycat) 9/27/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <string.h> -#endif - -#include "db_int.h" -#include "shqueue.h" -#include "log.h" -#include "common_ext.h" - -/* - * log_register -- - * Register a file name. - */ -int -log_register(dblp, dbp, name, type, idp) - DB_LOG *dblp; - DB *dbp; - const char *name; - DBTYPE type; - u_int32_t *idp; -{ - DBT fid_dbt, r_name; - DB_LSN r_unused; - FNAME *fnp, *reuse_fnp; - size_t len; - u_int32_t maxid; - int inserted, ret; - char *fullname; - void *namep; - - inserted = 0; - fullname = NULL; - fnp = namep = reuse_fnp = NULL; - - LOG_PANIC_CHECK(dblp); - - /* Check the arguments. */ - if (type != DB_BTREE && type != DB_HASH && type != DB_RECNO) { - __db_err(dblp->dbenv, "log_register: unknown DB file type"); - return (EINVAL); - } - - /* Get the log file id. */ - if ((ret = __db_appname(dblp->dbenv, - DB_APP_DATA, NULL, name, 0, NULL, &fullname)) != 0) - return (ret); - - LOCK_LOGREGION(dblp); - - /* - * See if we've already got this file in the log, finding the - * (maximum+1) in-use file id and some available file id (if we - * find an available fid, we'll use it, else we'll have to allocate - * one after the maximum that we found). - */ - for (maxid = 0, fnp = SH_TAILQ_FIRST(&dblp->lp->fq, __fname); - fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) { - if (fnp->ref == 0) { /* Entry is not in use. */ - if (reuse_fnp == NULL) - reuse_fnp = fnp; - continue; - } - if (!memcmp(dbp->fileid, fnp->ufid, DB_FILE_ID_LEN)) { - ++fnp->ref; - goto found; - } - if (maxid <= fnp->id) - maxid = fnp->id + 1; - } - - /* Fill in fnp structure. */ - - if (reuse_fnp != NULL) /* Reuse existing one. */ - fnp = reuse_fnp; - else if ((ret = __db_shalloc(dblp->addr, sizeof(FNAME), 0, &fnp)) != 0) - goto err; - else /* Allocate a new one. */ - fnp->id = maxid; - - fnp->ref = 1; - fnp->s_type = type; - memcpy(fnp->ufid, dbp->fileid, DB_FILE_ID_LEN); - - len = strlen(name) + 1; - if ((ret = __db_shalloc(dblp->addr, len, 0, &namep)) != 0) - goto err; - fnp->name_off = R_OFFSET(dblp, namep); - memcpy(namep, name, len); - - /* Only do the insert if we allocated a new fnp. */ - if (reuse_fnp == NULL) - SH_TAILQ_INSERT_HEAD(&dblp->lp->fq, fnp, q, __fname); - inserted = 1; - -found: /* Log the registry. */ - if (!F_ISSET(dblp, DBC_RECOVER)) { - r_name.data = (void *)name; /* XXX: Yuck! */ - r_name.size = strlen(name) + 1; - memset(&fid_dbt, 0, sizeof(fid_dbt)); - fid_dbt.data = dbp->fileid; - fid_dbt.size = DB_FILE_ID_LEN; - if ((ret = __log_register_log(dblp, NULL, &r_unused, - 0, LOG_OPEN, &r_name, &fid_dbt, fnp->id, type)) != 0) - goto err; - if ((ret = __log_add_logid(dblp, dbp, fnp->id)) != 0) - goto err; - } - - if (0) { -err: /* - * XXX - * We should grow the region. - */ - if (inserted) - SH_TAILQ_REMOVE(&dblp->lp->fq, fnp, q, __fname); - if (namep != NULL) - __db_shalloc_free(dblp->addr, namep); - if (fnp != NULL) - __db_shalloc_free(dblp->addr, fnp); - } - - if (idp != NULL) - *idp = fnp->id; - UNLOCK_LOGREGION(dblp); - - if (fullname != NULL) - __os_freestr(fullname); - - return (ret); -} - -/* - * log_unregister -- - * Discard a registered file name. - */ -int -log_unregister(dblp, fid) - DB_LOG *dblp; - u_int32_t fid; -{ - DBT fid_dbt, r_name; - DB_LSN r_unused; - FNAME *fnp; - int ret; - - LOG_PANIC_CHECK(dblp); - - ret = 0; - LOCK_LOGREGION(dblp); - - /* Find the entry in the log. */ - for (fnp = SH_TAILQ_FIRST(&dblp->lp->fq, __fname); - fnp != NULL; fnp = SH_TAILQ_NEXT(fnp, q, __fname)) - if (fid == fnp->id) - break; - if (fnp == NULL) { - __db_err(dblp->dbenv, "log_unregister: non-existent file id"); - ret = EINVAL; - goto ret1; - } - - /* Unlog the registry. */ - if (!F_ISSET(dblp, DBC_RECOVER)) { - memset(&r_name, 0, sizeof(r_name)); - r_name.data = R_ADDR(dblp, fnp->name_off); - r_name.size = strlen(r_name.data) + 1; - memset(&fid_dbt, 0, sizeof(fid_dbt)); - fid_dbt.data = fnp->ufid; - fid_dbt.size = DB_FILE_ID_LEN; - if ((ret = __log_register_log(dblp, NULL, &r_unused, - 0, LOG_CLOSE, &r_name, &fid_dbt, fid, fnp->s_type)) != 0) - goto ret1; - } - - /* - * If more than 1 reference, just decrement the reference and return. - * Otherwise, free the name. - */ - --fnp->ref; - if (fnp->ref == 0) - __db_shalloc_free(dblp->addr, R_ADDR(dblp, fnp->name_off)); - - /* - * Remove from the process local table. If this operation is taking - * place during recovery, then the logid was never added to the table, - * so do not remove it. - */ - if (!F_ISSET(dblp, DBC_RECOVER)) - __log_rem_logid(dblp, fid); - -ret1: UNLOCK_LOGREGION(dblp); - return (ret); -} |