diff options
Diffstat (limited to 'db2/common')
-rw-r--r-- | db2/common/db_appinit.c | 734 | ||||
-rw-r--r-- | db2/common/db_apprec.c | 247 | ||||
-rw-r--r-- | db2/common/db_byteorder.c | 63 | ||||
-rw-r--r-- | db2/common/db_err.c | 211 | ||||
-rw-r--r-- | db2/common/db_log2.c | 69 | ||||
-rw-r--r-- | db2/common/db_region.c | 873 | ||||
-rw-r--r-- | db2/common/db_salloc.c | 302 | ||||
-rw-r--r-- | db2/common/db_shash.c | 126 |
8 files changed, 0 insertions, 2625 deletions
diff --git a/db2/common/db_appinit.c b/db2/common/db_appinit.c deleted file mode 100644 index e02b1a872d..0000000000 --- a/db2/common/db_appinit.c +++ /dev/null @@ -1,734 +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[] = "@(#)db_appinit.c 10.66 (Sleepycat) 12/7/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <ctype.h> -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#endif - -#include "db_int.h" -#include "shqueue.h" -#include "db_page.h" -#include "btree.h" -#include "hash.h" -#include "log.h" -#include "txn.h" -#include "clib_ext.h" -#include "common_ext.h" - -static int __db_home __P((DB_ENV *, const char *, u_int32_t)); -static int __db_parse __P((DB_ENV *, char *)); -static int __db_tmp_open __P((DB_ENV *, u_int32_t, char *, int *)); - -/* - * This conflict array is used for concurrent db access (cdb). It - * uses the same locks as the db_rw_conflict array, but adds an IW - * mode to be used for write cursors. - */ -static u_int8_t const db_cdb_conflicts[] = { - /* N R W IW */ - /* N */ 0, 0, 0, 0, - /* R */ 0, 0, 1, 0, - /* W */ 0, 1, 1, 1, - /* IW */ 0, 0, 1, 1 -}; - -/* - * db_version -- - * Return version information. - */ -char * -db_version(majverp, minverp, patchp) - int *majverp, *minverp, *patchp; -{ - if (majverp != NULL) - *majverp = DB_VERSION_MAJOR; - if (minverp != NULL) - *minverp = DB_VERSION_MINOR; - if (patchp != NULL) - *patchp = DB_VERSION_PATCH; - return ((char *)DB_VERSION_STRING); -} - -/* - * db_appinit -- - * Initialize the application environment. - */ -int -db_appinit(db_home, db_config, dbenv, flags) - const char *db_home; - char * const *db_config; - DB_ENV *dbenv; - u_int32_t flags; -{ - FILE *fp; - int mode, ret; - char * const *p; - char *lp, buf[MAXPATHLEN * 2]; - - fp = NULL; - - /* Validate arguments. */ - if (dbenv == NULL) - return (EINVAL); - -#ifdef HAVE_SPINLOCKS -#define OKFLAGS \ - (DB_CREATE | DB_INIT_CDB | DB_INIT_LOCK | DB_INIT_LOG | \ - DB_INIT_MPOOL | DB_INIT_TXN | DB_MPOOL_PRIVATE | DB_NOMMAP | \ - DB_RECOVER | DB_RECOVER_FATAL | DB_THREAD | DB_TXN_NOSYNC | \ - DB_USE_ENVIRON | DB_USE_ENVIRON_ROOT) -#else -#define OKFLAGS \ - (DB_CREATE | DB_INIT_CDB | DB_INIT_LOCK | DB_INIT_LOG | \ - DB_INIT_MPOOL | DB_INIT_TXN | DB_MPOOL_PRIVATE | DB_NOMMAP | \ - DB_RECOVER | DB_RECOVER_FATAL | DB_TXN_NOSYNC | \ - DB_USE_ENVIRON | DB_USE_ENVIRON_ROOT) -#endif - if ((ret = __db_fchk(dbenv, "db_appinit", flags, OKFLAGS)) != 0) - return (ret); - - /* Transactions imply logging. */ - if (LF_ISSET(DB_INIT_TXN)) - LF_SET(DB_INIT_LOG); - - /* Convert the db_appinit(3) flags. */ - if (LF_ISSET(DB_THREAD)) - F_SET(dbenv, DB_ENV_THREAD); - - /* Set the database home. */ - if ((ret = __db_home(dbenv, db_home, flags)) != 0) - goto err; - - /* Parse the config array. */ - for (p = db_config; p != NULL && *p != NULL; ++p) - if ((ret = __db_parse(dbenv, *p)) != 0) - goto err; - - /* - * Parse the config file. - * - * XXX - * Don't use sprintf(3)/snprintf(3) -- the former is dangerous, and - * the latter isn't standard, and we're manipulating strings handed - * us by the application. - */ - if (dbenv->db_home != NULL) { -#define CONFIG_NAME "/DB_CONFIG" - if (strlen(dbenv->db_home) + - strlen(CONFIG_NAME) + 1 > sizeof(buf)) { - ret = ENAMETOOLONG; - goto err; - } - (void)strcpy(buf, dbenv->db_home); - (void)strcat(buf, CONFIG_NAME); - if ((fp = fopen(buf, "r")) != NULL) { - while (fgets(buf, sizeof(buf), fp) != NULL) { - if ((lp = strchr(buf, '\n')) == NULL) { - __db_err(dbenv, - "%s: line too long", CONFIG_NAME); - ret = EINVAL; - goto err; - } - *lp = '\0'; - if (buf[0] == '\0' || - buf[0] == '#' || isspace(buf[0])) - continue; - - if ((ret = __db_parse(dbenv, buf)) != 0) - goto err; - } - (void)fclose(fp); - fp = NULL; - } - } - - /* Set up the tmp directory path. */ - if (dbenv->db_tmp_dir == NULL && (ret = __os_tmpdir(dbenv, flags)) != 0) - goto err; - - /* - * Flag that the structure has been initialized by the application. - * Note, this must be set before calling into the subsystems as it - * is used when we're doing file naming. - */ - F_SET(dbenv, DB_ENV_APPINIT); - - /* - * If we are doing recovery, remove all the old shared memory - * regions. - */ - if (LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL)) { - if ((ret = log_unlink(NULL, 1, dbenv)) != 0) - goto err; - if ((ret = memp_unlink(NULL, 1, dbenv)) != 0) - goto err; - if ((ret = lock_unlink(NULL, 1, dbenv)) != 0) - goto err; - if ((ret = txn_unlink(NULL, 1, dbenv)) != 0) - goto err; - } - - /* - * Create the new shared regions. - * - * Default permissions are read-write for both owner and group. - */ - mode = __db_omode("rwrw--"); - if (LF_ISSET(DB_INIT_CDB)) { - if (LF_ISSET(DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN)) { - ret = EINVAL; - goto err; - } - F_SET(dbenv, DB_ENV_CDB); - dbenv->lk_conflicts = db_cdb_conflicts; - dbenv->lk_modes = DB_LOCK_RW_N + 1; - if ((ret = lock_open(NULL, LF_ISSET(DB_CREATE | DB_THREAD), - mode, dbenv, &dbenv->lk_info)) != 0) - goto err; - } - if (LF_ISSET(DB_INIT_LOCK) && (ret = lock_open(NULL, - LF_ISSET(DB_CREATE | DB_THREAD), - mode, dbenv, &dbenv->lk_info)) != 0) - goto err; - if (LF_ISSET(DB_INIT_LOG) && (ret = log_open(NULL, - LF_ISSET(DB_CREATE | DB_THREAD), - mode, dbenv, &dbenv->lg_info)) != 0) - goto err; - if (LF_ISSET(DB_INIT_MPOOL) && (ret = memp_open(NULL, - LF_ISSET(DB_CREATE | DB_MPOOL_PRIVATE | DB_NOMMAP | DB_THREAD), - mode, dbenv, &dbenv->mp_info)) != 0) - goto err; - if (LF_ISSET(DB_INIT_TXN) && (ret = txn_open(NULL, - LF_ISSET(DB_CREATE | DB_THREAD | DB_TXN_NOSYNC), - mode, dbenv, &dbenv->tx_info)) != 0) - goto err; - - /* - * If the application is running with transactions, initialize the - * function tables. Once that's done, do recovery for any previous - * run. - */ - if (LF_ISSET(DB_INIT_TXN)) { - if ((ret = __bam_init_recover(dbenv)) != 0) - goto err; - if ((ret = __db_init_recover(dbenv)) != 0) - goto err; - if ((ret = __ham_init_recover(dbenv)) != 0) - goto err; - if ((ret = __log_init_recover(dbenv)) != 0) - goto err; - if ((ret = __txn_init_recover(dbenv)) != 0) - goto err; - - if (LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL) && - (ret = __db_apprec(dbenv, - LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL))) != 0) - goto err; - } - - return (ret); - -err: if (fp != NULL) - (void)fclose(fp); - - (void)db_appexit(dbenv); - return (ret); -} - -/* - * db_appexit -- - * Close down the default application environment. - */ -int -db_appexit(dbenv) - DB_ENV *dbenv; -{ - int ret, t_ret; - char **p; - - ret = 0; - - /* Close subsystems. */ - if (dbenv->tx_info && (t_ret = txn_close(dbenv->tx_info)) != 0) - if (ret == 0) - ret = t_ret; - if (dbenv->lg_info && (t_ret = log_close(dbenv->lg_info)) != 0) - if (ret == 0) - ret = t_ret; - if (dbenv->mp_info && (t_ret = memp_close(dbenv->mp_info)) != 0) - if (ret == 0) - ret = t_ret; - if (dbenv->lk_info && (t_ret = lock_close(dbenv->lk_info)) != 0) - if (ret == 0) - ret = t_ret; - - /* Clear initialized flag (after subsystems, it affects naming). */ - F_CLR(dbenv, DB_ENV_APPINIT); - - /* Free allocated memory. */ - if (dbenv->db_home != NULL) - __os_freestr(dbenv->db_home); - if ((p = dbenv->db_data_dir) != NULL) { - for (; *p != NULL; ++p) - __os_freestr(*p); - __os_free(dbenv->db_data_dir, - dbenv->data_cnt * sizeof(char **)); - } - if (dbenv->db_log_dir != NULL) - __os_freestr(dbenv->db_log_dir); - if (dbenv->db_tmp_dir != NULL) - __os_freestr(dbenv->db_tmp_dir); - - return (ret); -} - -#define DB_ADDSTR(str) { \ - if ((str) != NULL) { \ - /* If leading slash, start over. */ \ - if (__os_abspath(str)) { \ - p = start; \ - slash = 0; \ - } \ - /* Append to the current string. */ \ - len = strlen(str); \ - if (slash) \ - *p++ = PATH_SEPARATOR[0]; \ - memcpy(p, str, len); \ - p += len; \ - slash = strchr(PATH_SEPARATOR, p[-1]) == NULL; \ - } \ -} - -/* - * __db_appname -- - * Given an optional DB environment, directory and file name and type - * of call, build a path based on the db_appinit(3) rules, and return - * it in allocated space. - * - * PUBLIC: int __db_appname __P((DB_ENV *, - * PUBLIC: APPNAME, const char *, const char *, u_int32_t, int *, char **)); - */ -int -__db_appname(dbenv, appname, dir, file, tmp_oflags, fdp, namep) - DB_ENV *dbenv; - APPNAME appname; - const char *dir, *file; - u_int32_t tmp_oflags; - int *fdp; - char **namep; -{ - DB_ENV etmp; - size_t len; - int data_entry, ret, slash, tmp_create, tmp_free; - const char *a, *b, *c; - char *p, *start; - - a = b = c = NULL; - data_entry = -1; - tmp_create = tmp_free = 0; - - /* - * We don't return a name when creating temporary files, just an fd. - * Default to error now. - */ - if (fdp != NULL) - *fdp = -1; - if (namep != NULL) - *namep = NULL; - - /* - * Absolute path names are never modified. If the file is an absolute - * path, we're done. If the directory is, simply append the file and - * return. - */ - if (file != NULL && __os_abspath(file)) - return (__os_strdup(file, namep)); - if (dir != NULL && __os_abspath(dir)) { - a = dir; - goto done; - } - - /* - * DB_ENV DIR APPNAME RESULT - * ------------------------------------------- - * null null none <tmp>/file - * null set none DIR/file - * set null none DB_HOME/file - * set set none DB_HOME/DIR/file - * - * DB_ENV FILE APPNAME RESULT - * ------------------------------------------- - * null null DB_APP_DATA <tmp>/<create> - * null set DB_APP_DATA ./file - * set null DB_APP_DATA <tmp>/<create> - * set set DB_APP_DATA DB_HOME/DB_DATA_DIR/file - * - * DB_ENV DIR APPNAME RESULT - * ------------------------------------------- - * null null DB_APP_LOG <tmp>/file - * null set DB_APP_LOG DIR/file - * set null DB_APP_LOG DB_HOME/DB_LOG_DIR/file - * set set DB_APP_LOG DB_HOME/DB_LOG_DIR/DIR/file - * - * DB_ENV APPNAME RESULT - * ------------------------------------------- - * null DB_APP_TMP* <tmp>/<create> - * set DB_APP_TMP* DB_HOME/DB_TMP_DIR/<create> - */ -retry: switch (appname) { - case DB_APP_NONE: - if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_APPINIT)) { - if (dir == NULL) - goto tmp; - a = dir; - } else { - a = dbenv->db_home; - b = dir; - } - break; - case DB_APP_DATA: - if (dir != NULL) { - __db_err(dbenv, - "DB_APP_DATA: illegal directory specification"); - return (EINVAL); - } - - if (file == NULL) { - tmp_create = 1; - goto tmp; - } - if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_APPINIT)) - a = PATH_DOT; - else { - a = dbenv->db_home; - if (dbenv->db_data_dir != NULL && - (b = dbenv->db_data_dir[++data_entry]) == NULL) { - data_entry = -1; - b = dbenv->db_data_dir[0]; - } - } - break; - case DB_APP_LOG: - if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_APPINIT)) { - if (dir == NULL) - goto tmp; - a = dir; - } else { - a = dbenv->db_home; - b = dbenv->db_log_dir; - c = dir; - } - break; - case DB_APP_TMP: - if (dir != NULL || file != NULL) { - __db_err(dbenv, - "DB_APP_TMP: illegal directory or file specification"); - return (EINVAL); - } - - tmp_create = 1; - if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_APPINIT)) - goto tmp; - else { - a = dbenv->db_home; - b = dbenv->db_tmp_dir; - } - break; - } - - /* Reference a file from the appropriate temporary directory. */ - if (0) { -tmp: if (dbenv == NULL || !F_ISSET(dbenv, DB_ENV_APPINIT)) { - memset(&etmp, 0, sizeof(etmp)); - if ((ret = __os_tmpdir(&etmp, DB_USE_ENVIRON)) != 0) - return (ret); - tmp_free = 1; - a = etmp.db_tmp_dir; - } else - a = dbenv->db_tmp_dir; - } - -done: len = - (a == NULL ? 0 : strlen(a) + 1) + - (b == NULL ? 0 : strlen(b) + 1) + - (c == NULL ? 0 : strlen(c) + 1) + - (file == NULL ? 0 : strlen(file) + 1); - - /* - * Allocate space to hold the current path information, as well as any - * temporary space that we're going to need to create a temporary file - * name. - */ -#define DB_TRAIL "XXXXXX" - if ((ret = - __os_malloc(len + sizeof(DB_TRAIL) + 10, NULL, &start)) != 0) { - if (tmp_free) - __os_freestr(etmp.db_tmp_dir); - return (ret); - } - - slash = 0; - p = start; - DB_ADDSTR(a); - DB_ADDSTR(b); - DB_ADDSTR(file); - *p = '\0'; - - /* Discard any space allocated to find the temp directory. */ - if (tmp_free) { - __os_freestr(etmp.db_tmp_dir); - tmp_free = 0; - } - - /* - * If we're opening a data file, see if it exists. If it does, - * return it, otherwise, try and find another one to open. - */ - if (data_entry != -1 && __os_exists(start, NULL) != 0) { - __os_freestr(start); - a = b = c = NULL; - goto retry; - } - - /* Create the file if so requested. */ - if (tmp_create && - (ret = __db_tmp_open(dbenv, tmp_oflags, start, fdp)) != 0) { - __os_freestr(start); - return (ret); - } - - if (namep == NULL) - __os_freestr(start); - else - *namep = start; - return (0); -} - -/* - * __db_home -- - * Find the database home. - */ -static int -__db_home(dbenv, db_home, flags) - DB_ENV *dbenv; - const char *db_home; - u_int32_t flags; -{ - const char *p; - - p = db_home; - - /* Use the environment if it's permitted and initialized. */ -#ifdef HAVE_GETUID - if (LF_ISSET(DB_USE_ENVIRON) || - (LF_ISSET(DB_USE_ENVIRON_ROOT) && getuid() == 0)) { -#else - if (LF_ISSET(DB_USE_ENVIRON)) { -#endif - if ((p = getenv("DB_HOME")) == NULL) - p = db_home; - else if (p[0] == '\0') { - __db_err(dbenv, - "illegal DB_HOME environment variable"); - return (EINVAL); - } - } - - if (p == NULL) - return (0); - - return (__os_strdup(p, &dbenv->db_home)); -} - -/* - * __db_parse -- - * Parse a single NAME VALUE pair. - */ -static int -__db_parse(dbenv, s) - DB_ENV *dbenv; - char *s; -{ - int ret; - char *local_s, *name, *value, **p, *tp; - - /* - * We need to strdup the argument in case the caller passed us - * static data. - */ - if ((ret = __os_strdup(s, &local_s)) != 0) - return (ret); - - /* - * Name/value pairs are parsed as two white-space separated strings. - * Leading and trailing white-space is trimmed from the value, but - * it may contain embedded white-space. Note: we use the isspace(3) - * macro because it's more portable, but that means that you can use - * characters like form-feed to separate the strings. - */ - name = local_s; - for (tp = name; *tp != '\0' && !isspace(*tp); ++tp) - ; - if (*tp == '\0' || tp == name) - goto illegal; - *tp = '\0'; - for (++tp; isspace(*tp); ++tp) - ; - if (*tp == '\0') - goto illegal; - value = tp; - for (++tp; *tp != '\0'; ++tp) - ; - for (--tp; isspace(*tp); --tp) - ; - if (tp == value) { -illegal: ret = EINVAL; - __db_err(dbenv, "illegal name-value pair: %s", s); - goto err; - } - *++tp = '\0'; - -#define DATA_INIT_CNT 20 /* Start with 20 data slots. */ - if (!strcmp(name, "DB_DATA_DIR")) { - if (dbenv->db_data_dir == NULL) { - if ((ret = __os_calloc(DATA_INIT_CNT, - sizeof(char **), &dbenv->db_data_dir)) != 0) - goto err; - dbenv->data_cnt = DATA_INIT_CNT; - } else if (dbenv->data_next == dbenv->data_cnt - 1) { - dbenv->data_cnt *= 2; - if ((ret = __os_realloc(&dbenv->db_data_dir, - dbenv->data_cnt * sizeof(char **))) != 0) - goto err; - } - p = &dbenv->db_data_dir[dbenv->data_next++]; - } else if (!strcmp(name, "DB_LOG_DIR")) { - if (dbenv->db_log_dir != NULL) - __os_freestr(dbenv->db_log_dir); - p = &dbenv->db_log_dir; - } else if (!strcmp(name, "DB_TMP_DIR")) { - if (dbenv->db_tmp_dir != NULL) - __os_freestr(dbenv->db_tmp_dir); - p = &dbenv->db_tmp_dir; - } else - goto err; - - ret = __os_strdup(value, p); - -err: __os_freestr(local_s); - return (ret); -} - -/* - * __db_tmp_open -- - * Create a temporary file. - */ -static int -__db_tmp_open(dbenv, flags, path, fdp) - DB_ENV *dbenv; - u_int32_t flags; - char *path; - int *fdp; -{ - u_long pid; - int mode, isdir, ret; - const char *p; - char *trv; - - /* - * Check the target directory; if you have six X's and it doesn't - * exist, this runs for a *very* long time. - */ - if ((ret = __os_exists(path, &isdir)) != 0) { - __db_err(dbenv, "%s: %s", path, strerror(ret)); - return (ret); - } - if (!isdir) { - __db_err(dbenv, "%s: %s", path, strerror(EINVAL)); - return (EINVAL); - } - - /* Build the path. */ - for (trv = path; *trv != '\0'; ++trv) - ; - *trv = PATH_SEPARATOR[0]; - for (p = DB_TRAIL; (*++trv = *p) != '\0'; ++p) - ; - - /* - * Replace the X's with the process ID. Pid should be a pid_t, - * but we use unsigned long for portability. - */ - for (pid = getpid(); *--trv == 'X'; pid /= 10) - switch (pid % 10) { - case 0: *trv = '0'; break; - case 1: *trv = '1'; break; - case 2: *trv = '2'; break; - case 3: *trv = '3'; break; - case 4: *trv = '4'; break; - case 5: *trv = '5'; break; - case 6: *trv = '6'; break; - case 7: *trv = '7'; break; - case 8: *trv = '8'; break; - case 9: *trv = '9'; break; - } - ++trv; - - /* Set up open flags and mode. */ - LF_SET(DB_CREATE | DB_EXCL); - mode = __db_omode("rw----"); - - /* Loop, trying to open a file. */ - for (;;) { - if ((ret = __db_open(path, flags, flags, mode, fdp)) == 0) - return (0); - - /* - * XXX: - * If we don't get an EEXIST error, then there's something - * seriously wrong. Unfortunately, if the implementation - * doesn't return EEXIST for O_CREAT and O_EXCL regardless - * of other possible errors, we've lost. - */ - if (ret != EEXIST) { - __db_err(dbenv, - "tmp_open: %s: %s", path, strerror(ret)); - return (ret); - } - - /* - * Tricky little algorithm for backward compatibility. - * Assumes the ASCII ordering of lower-case characters. - */ - for (;;) { - if (*trv == '\0') - return (EINVAL); - if (*trv == 'z') - *trv++ = 'a'; - else { - if (isdigit(*trv)) - *trv = 'a'; - else - ++*trv; - break; - } - } - } - /* NOTREACHED */ -} diff --git a/db2/common/db_apprec.c b/db2/common/db_apprec.c deleted file mode 100644 index 5e8fec4659..0000000000 --- a/db2/common/db_apprec.c +++ /dev/null @@ -1,247 +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 copyright[] = -"@(#) Copyright (c) 1996, 1997, 1998\n\ - Sleepycat Software Inc. All rights reserved.\n"; -static const char sccsid[] = "@(#)db_apprec.c 10.33 (Sleepycat) 10/5/98"; -#endif - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <string.h> -#include <time.h> -#endif - -#include "db_int.h" -#include "shqueue.h" -#include "db_page.h" -#include "db_dispatch.h" -#include "db_am.h" -#include "log.h" -#include "txn.h" -#include "common_ext.h" - -/* - * __db_apprec -- - * Perform recovery. - * - * PUBLIC: int __db_apprec __P((DB_ENV *, u_int32_t)); - */ -int -__db_apprec(dbenv, flags) - DB_ENV *dbenv; - u_int32_t flags; -{ - DBT data; - DB_LOG *lp; - DB_LSN ckp_lsn, first_lsn, lsn, open_lsn; - __txn_ckp_args *ckp_args; - time_t now; - u_int32_t is_thread; - int ret; - void *txninfo; - - lp = dbenv->lg_info; - - /* Initialize the transaction list. */ - if ((ret = __db_txnlist_init(&txninfo)) != 0) - return (ret); - - /* - * Save the state of the thread flag -- we don't need it on at the - * moment because we're single-threaded until recovery is complete. - */ - is_thread = F_ISSET(lp, DB_AM_THREAD); - F_CLR(lp, DB_AM_THREAD); - - /* - * Recovery is done in three passes: - * Pass #0: - * We need to find the position from which we will open files - * We need to open files beginning with the last to next - * checkpoint because we might have crashed after writing the - * last checkpoint record, but before having written out all - * the open file information. - * Pass #1: - * Read forward through the log from the second to last checkpoint - * opening and closing files so that at the end of the log we have - * the "current" set of files open. - * Pass #2: - * Read backward through the log undoing any uncompleted TXNs. - * If doing catastrophic recovery, we read to the beginning of - * the log, otherwise, to the most recent checkpoint that occurs - * before the most recent checkpoint LSN, which is returned by - * __log_findckp(). During this pass, checkpoint file information - * is ignored, and file openings and closings are undone. - * Pass #3: - * Read forward through the log from the LSN found in pass #2, - * redoing any committed TXNs. During this pass, checkpoint - * file information is ignored, and file openings and closings - * are redone. - */ - - /* - * Find the second to last checkpoint in the log. This is the point - * from which we want to begin pass #1 (the TXN_OPENFILES pass). - */ - memset(&data, 0, sizeof(data)); - ckp_args = NULL; - - if ((ret = log_get(lp, &ckp_lsn, &data, DB_CHECKPOINT)) != 0) { - /* - * If we don't find a checkpoint, start from the beginning. - * If that fails, we're done. Note, we do not require that - * there be log records if we're performing recovery. - */ -first: if ((ret = log_get(lp, &ckp_lsn, &data, DB_FIRST)) != 0) { - if (ret == DB_NOTFOUND) - ret = 0; - else - __db_err(dbenv, "First log record not found"); - goto out; - } - open_lsn = ckp_lsn; - } else if ((ret = __txn_ckp_read(data.data, &ckp_args)) != 0) { - __db_err(dbenv, "Invalid checkpoint record at [%ld][%ld]\n", - (u_long)ckp_lsn.file, (u_long)ckp_lsn.offset); - goto out; - } else if (IS_ZERO_LSN(ckp_args->last_ckp) || - (ret = log_get(lp, &ckp_args->last_ckp, &data, DB_SET)) != 0) - goto first; - else - open_lsn = ckp_args->last_ckp; - - /* - * Now, ckp_lsn is either the lsn of the last checkpoint or the lsn - * of the first record in the log. Open_lsn is the second to last - * checkpoint or the beinning of the log; begin the TXN_OPENFILES - * pass from that lsn, and proceed to the end of the log. - */ - lsn = open_lsn; - for (;;) { - if (dbenv->tx_recover != NULL) - ret = dbenv->tx_recover(lp, - &data, &lsn, TXN_OPENFILES, txninfo); - else - ret = __db_dispatch(lp, - &data, &lsn, TXN_OPENFILES, txninfo); - if (ret != 0 && ret != DB_TXN_CKP) - goto msgerr; - if ((ret = log_get(lp, &lsn, &data, DB_NEXT)) != 0) { - if (ret == DB_NOTFOUND) - break; - goto out; - } - } - - /* - * Pass #2. - * - * Before we can begin pass #2, backward roll phase, we determine how - * far back in the log to recover. If we are doing catastrophic - * recovery, then we go as far back as we have files. If we are - * doing normal recovery, we go as back to the most recent checkpoint - * that occurs before the most recent checkpoint LSN. - */ - if (LF_ISSET(DB_RECOVER_FATAL)) { - ZERO_LSN(first_lsn); - } else - if ((ret = __log_findckp(lp, &first_lsn)) == DB_NOTFOUND) { - /* - * We don't require that log files exist if recovery - * was specified. - */ - ret = 0; - goto out; - } - - if (dbenv->db_verbose) - __db_err(lp->dbenv, "Recovery starting from [%lu][%lu]", - (u_long)first_lsn.file, (u_long)first_lsn.offset); - - for (ret = log_get(lp, &lsn, &data, DB_LAST); - ret == 0 && log_compare(&lsn, &first_lsn) > 0; - ret = log_get(lp, &lsn, &data, DB_PREV)) { - if (dbenv->tx_recover != NULL) - ret = dbenv->tx_recover(lp, - &data, &lsn, TXN_BACKWARD_ROLL, txninfo); - else - ret = __db_dispatch(lp, - &data, &lsn, TXN_BACKWARD_ROLL, txninfo); - if (ret != 0) { - if (ret != DB_TXN_CKP) - goto msgerr; - else - ret = 0; - } - } - if (ret != 0 && ret != DB_NOTFOUND) - goto out; - - /* - * Pass #3. - */ - for (ret = log_get(lp, &lsn, &data, DB_NEXT); - ret == 0; ret = log_get(lp, &lsn, &data, DB_NEXT)) { - if (dbenv->tx_recover != NULL) - ret = dbenv->tx_recover(lp, - &data, &lsn, TXN_FORWARD_ROLL, txninfo); - else - ret = __db_dispatch(lp, - &data, &lsn, TXN_FORWARD_ROLL, txninfo); - if (ret != 0) { - if (ret != DB_TXN_CKP) - goto msgerr; - else - ret = 0; - } - } - if (ret != DB_NOTFOUND) - goto out; - - /* Now close all the db files that are open. */ - __log_close_files(lp); - - /* - * Now set the last checkpoint lsn and the current time, - * take a checkpoint, and reset the txnid. - */ - (void)time(&now); - dbenv->tx_info->region->last_ckp = ckp_lsn; - dbenv->tx_info->region->time_ckp = (u_int32_t)now; - if ((ret = txn_checkpoint(dbenv->tx_info, 0, 0)) != 0) - goto out; - dbenv->tx_info->region->last_txnid = TXN_MINIMUM; - - if (dbenv->db_verbose) { - __db_err(lp->dbenv, "Recovery complete at %.24s", ctime(&now)); - __db_err(lp->dbenv, "%s %lx %s [%lu][%lu]", - "Maximum transaction id", - ((DB_TXNHEAD *)txninfo)->maxid, - "Recovery checkpoint", - (u_long)dbenv->tx_info->region->last_ckp.file, - (u_long)dbenv->tx_info->region->last_ckp.offset); - } - - if (0) { -msgerr: __db_err(dbenv, "Recovery function for LSN %lu %lu failed", - (u_long)lsn.file, (u_long)lsn.offset); - } - -out: F_SET(lp, is_thread); - __db_txnlist_end(txninfo); - if (ckp_args != NULL) - __os_free(ckp_args, sizeof(*ckp_args)); - - return (ret); -} diff --git a/db2/common/db_byteorder.c b/db2/common/db_byteorder.c deleted file mode 100644 index cadf742851..0000000000 --- a/db2/common/db_byteorder.c +++ /dev/null @@ -1,63 +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[] = "@(#)db_byteorder.c 10.5 (Sleepycat) 4/10/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#ifdef HAVE_ENDIAN_H -#include <endian.h> -#if BYTE_ORDER == BIG_ENDIAN -#define WORDS_BIGENDIAN 1 -#endif -#endif - -#include <errno.h> -#endif - -#include "db_int.h" -#include "common_ext.h" - -/* - * __db_byteorder -- - * Return if we need to do byte swapping, checking for illegal - * values. - * - * PUBLIC: int __db_byteorder __P((DB_ENV *, int)); - */ -int -__db_byteorder(dbenv, lorder) - DB_ENV *dbenv; - int lorder; -{ - switch (lorder) { - case 0: - break; - case 1234: -#if defined(WORDS_BIGENDIAN) - return (DB_SWAPBYTES); -#else - break; -#endif - case 4321: -#if defined(WORDS_BIGENDIAN) - break; -#else - return (DB_SWAPBYTES); -#endif - default: - __db_err(dbenv, - "illegal byte order, only big and little-endian supported"); - return (EINVAL); - } - return (0); -} diff --git a/db2/common/db_err.c b/db2/common/db_err.c deleted file mode 100644 index e935ddfcc5..0000000000 --- a/db2/common/db_err.c +++ /dev/null @@ -1,211 +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[] = "@(#)db_err.c 10.42 (Sleepycat) 11/24/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <stdio.h> -#include <string.h> - -#ifdef __STDC__ -#include <stdarg.h> -#else -#include <varargs.h> -#endif -#endif - -#include "db_int.h" -#include "shqueue.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 "clib_ext.h" - -/* - * __db_fchk -- - * General flags checking routine. - * - * PUBLIC: int __db_fchk __P((DB_ENV *, const char *, u_int32_t, u_int32_t)); - */ -int -__db_fchk(dbenv, name, flags, ok_flags) - DB_ENV *dbenv; - const char *name; - u_int32_t flags, ok_flags; -{ - return (flags & ~ok_flags ? __db_ferr(dbenv, name, 0) : 0); -} - -/* - * __db_fcchk -- - * General combination flags checking routine. - * - * PUBLIC: int __db_fcchk - * PUBLIC: __P((DB_ENV *, const char *, u_int32_t, u_int32_t, u_int32_t)); - */ -int -__db_fcchk(dbenv, name, flags, flag1, flag2) - DB_ENV *dbenv; - const char *name; - u_int32_t flags, flag1, flag2; -{ - return ((flags & flag1) && - (flags & flag2) ? __db_ferr(dbenv, name, 1) : 0); -} - -/* - * __db_ferr -- - * Common flag errors. - * - * PUBLIC: int __db_ferr __P((const DB_ENV *, const char *, int)); - */ -int -__db_ferr(dbenv, name, iscombo) - const DB_ENV *dbenv; - const char *name; - int iscombo; -{ - __db_err(dbenv, "illegal flag %sspecified to %s", - iscombo ? "combination " : "", name); - return (EINVAL); -} - -/* - * __db_err -- - * Standard DB error routine. - * - * PUBLIC: #ifdef __STDC__ - * PUBLIC: void __db_err __P((const DB_ENV *dbenv, const char *fmt, ...)); - * PUBLIC: #else - * PUBLIC: void __db_err(); - * PUBLIC: #endif - */ -void -#ifdef __STDC__ -__db_err(const DB_ENV *dbenv, const char *fmt, ...) -#else -__db_err(dbenv, fmt, va_alist) - const DB_ENV *dbenv; - const char *fmt; - va_dcl -#endif -{ - va_list ap; - char errbuf[2048]; /* XXX: END OF THE STACK DON'T TRUST SPRINTF. */ - - if (dbenv == NULL) - return; - - if (dbenv->db_errcall != NULL) { -#ifdef __STDC__ - va_start(ap, fmt); -#else - va_start(ap); -#endif - (void)vsnprintf(errbuf, sizeof(errbuf), fmt, ap); - dbenv->db_errcall(dbenv->db_errpfx, errbuf); - va_end(ap); - } - if (dbenv->db_errfile != NULL) { - if (dbenv->db_errpfx != NULL) - (void)fprintf(dbenv->db_errfile, "%s: ", - dbenv->db_errpfx); -#ifdef __STDC__ - va_start(ap, fmt); -#else - va_start(ap); -#endif - (void)vfprintf(dbenv->db_errfile, fmt, ap); - (void)fprintf(dbenv->db_errfile, "\n"); - (void)fflush(dbenv->db_errfile); - va_end(ap); - } -} - -/* - * __db_pgerr -- - * Error when unable to retrieve a specified page. - * - * PUBLIC: int __db_pgerr __P((DB *, db_pgno_t)); - */ -int -__db_pgerr(dbp, pgno) - DB *dbp; - db_pgno_t pgno; -{ - /* - * Three things are certain: - * Death, taxes, and lost data. - * Guess which has occurred. - */ - __db_err(dbp->dbenv, - "unable to create/retrieve page %lu", (u_long)pgno); - return (__db_panic(dbp->dbenv, EIO)); -} - -/* - * __db_pgfmt -- - * Error when a page has the wrong format. - * - * PUBLIC: int __db_pgfmt __P((DB *, db_pgno_t)); - */ -int -__db_pgfmt(dbp, pgno) - DB *dbp; - db_pgno_t pgno; -{ - __db_err(dbp->dbenv, - "page %lu: illegal page type or format", (u_long)pgno); - return (__db_panic(dbp->dbenv, EINVAL)); -} - -/* - * __db_panic -- - * Lock out the tree due to unrecoverable error. - * - * PUBLIC: int __db_panic __P((DB_ENV *, int)); - */ -int -__db_panic(dbenv, errval) - DB_ENV *dbenv; - int errval; -{ - if (dbenv != NULL) { - dbenv->db_panic = errval; - - (void)__log_panic(dbenv); - (void)__memp_panic(dbenv); - (void)__lock_panic(dbenv); - (void)__txn_panic(dbenv); - - __db_err(dbenv, "PANIC: %s", strerror(errval)); - - if (dbenv->db_paniccall != NULL) - dbenv->db_paniccall(dbenv, errval); - } - - /* - * Chaos reigns within. - * Reflect, repent, and reboot. - * Order shall return. - */ - return (DB_RUNRECOVERY); -} diff --git a/db2/common/db_log2.c b/db2/common/db_log2.c deleted file mode 100644 index d6b14f540b..0000000000 --- a/db2/common/db_log2.c +++ /dev/null @@ -1,69 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - */ -/* - * Copyright (c) 1995, 1996 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Margo Seltzer. - * - * 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[] = "@(#)db_log2.c 10.5 (Sleepycat) 4/26/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> -#endif - -#include "db_int.h" -#include "common_ext.h" - -/* - * PUBLIC: u_int32_t __db_log2 __P((u_int32_t)); - */ -u_int32_t -__db_log2(num) - u_int32_t num; -{ - u_int32_t i, limit; - - limit = 1; - for (i = 0; limit < num; limit = limit << 1, i++) - ; - return (i); -} diff --git a/db2/common/db_region.c b/db2/common/db_region.c deleted file mode 100644 index 12abfa524d..0000000000 --- a/db2/common/db_region.c +++ /dev/null @@ -1,873 +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[] = "@(#)db_region.c 10.53 (Sleepycat) 11/10/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 "common_ext.h" - -static int __db_growregion __P((REGINFO *, size_t)); - -/* - * __db_rattach -- - * Optionally create and attach to a shared memory region. - * - * PUBLIC: int __db_rattach __P((REGINFO *)); - */ -int -__db_rattach(infop) - REGINFO *infop; -{ - RLAYOUT *rlp, rl; - size_t grow_region, size; - ssize_t nr, nw; - u_int32_t flags, mbytes, bytes; - u_int8_t *p; - int malloc_possible, ret, retry_cnt; - - grow_region = 0; - malloc_possible = 1; - ret = retry_cnt = 0; - - /* Round off the requested size to the next page boundary. */ - DB_ROUNDOFF(infop->size, DB_VMPAGESIZE); - - /* Some architectures have hard limits on the maximum region size. */ -#ifdef DB_REGIONSIZE_MAX - if (infop->size > DB_REGIONSIZE_MAX) { - __db_err(infop->dbenv, "__db_rattach: cache size too large"); - return (EINVAL); - } -#endif - - /* Intialize the return information in the REGINFO structure. */ -loop: infop->addr = NULL; - infop->fd = -1; - infop->segid = INVALID_SEGID; - if (infop->name != NULL) { - __os_freestr(infop->name); - infop->name = NULL; - } - F_CLR(infop, REGION_CANGROW | REGION_CREATED); - -#ifndef HAVE_SPINLOCKS - /* - * XXX - * Lacking spinlocks, we must have a file descriptor for fcntl(2) - * locking, which implies using mmap(2) to map in a regular file. - * (Theoretically, we could probably get a file descriptor to lock - * other types of shared regions, but I don't see any reason to - * bother.) - * - * Since we may be using shared memory regions, e.g., shmget(2), - * and not mmap of regular files, the backing file may be only a - * few tens of bytes in length. So, this depends on the ability - * to fcntl lock file offsets much larger than the physical file. - */ - malloc_possible = 0; -#endif - -#ifdef __hppa - /* - * XXX - * HP-UX won't permit mutexes to live in anything but shared memory. - * Instantiate a shared region file on that architecture, regardless. - */ - malloc_possible = 0; -#endif - /* - * If a region is truly private, malloc the memory. That's faster - * than either anonymous memory or a shared file. - */ - if (malloc_possible && F_ISSET(infop, REGION_PRIVATE)) { - if ((ret = __os_malloc(infop->size, NULL, &infop->addr)) != 0) - return (ret); - - /* - * It's sometimes significantly faster to page-fault in all of - * the region's pages before we run the application, as we see - * nasty side-effects when we page-fault while holding various - * locks, i.e., the lock takes a long time to acquire because - * of the underlying page fault, and the other threads convoy - * behind the lock holder. - */ - if (DB_GLOBAL(db_region_init)) - for (p = infop->addr; - p < (u_int8_t *)infop->addr + infop->size; - p += DB_VMPAGESIZE) - p[0] = '\0'; - - F_SET(infop, REGION_CREATED | REGION_MALLOC); - goto region_init; - } - - /* - * Get the name of the region (creating the file if a temporary file - * is being used). The dbenv contains the current DB environment, - * including naming information. The path argument may be a file or - * a directory. If path is a directory, it must exist and file is the - * file name to be created inside the directory. If path is a file, - * then file must be NULL. - */ - if ((ret = __db_appname(infop->dbenv, infop->appname, infop->path, - infop->file, infop->dbflags, &infop->fd, &infop->name)) != 0) - return (ret); - if (infop->fd != -1) - F_SET(infop, REGION_CREATED); - - /* - * Try to create the file, if we have authority. We have to make sure - * that multiple threads/processes attempting to simultaneously create - * the region are properly ordered, so we open it using DB_CREATE and - * DB_EXCL, so two attempts to create the region will return failure in - * one. - */ - if (infop->fd == -1 && infop->dbflags & DB_CREATE) { - flags = infop->dbflags; - LF_SET(DB_EXCL); - if ((ret = __db_open(infop->name, - flags, flags, infop->mode, &infop->fd)) == 0) - F_SET(infop, REGION_CREATED); - else - if (ret != EEXIST) - goto errmsg; - } - - /* If we couldn't create the file, try and open it. */ - if (infop->fd == -1) { - flags = infop->dbflags; - LF_CLR(DB_CREATE | DB_EXCL); - if ((ret = __db_open(infop->name, - flags, flags, infop->mode, &infop->fd)) != 0) - goto errmsg; - } - - /* - * There are three cases we support: - * 1. Named anonymous memory (shmget(2)). - * 2. Unnamed anonymous memory (mmap(2): MAP_ANON/MAP_ANONYMOUS). - * 3. Memory backed by a regular file (mmap(2)). - * - * We instantiate a backing file in all cases, which contains at least - * the RLAYOUT structure, and in case #3, contains the actual region. - * This is necessary for a couple of reasons: - * - * First, the mpool region uses temporary files to name regions, and - * since you may have multiple regions in the same directory, we need - * a filesystem name to ensure that they don't collide. - * - * Second, applications are allowed to forcibly remove regions, even - * if they don't know anything about them other than the name. If a - * region is backed by anonymous memory, there has to be some way for - * the application to find out that information, and, in some cases, - * determine ID information for the anonymous memory. - */ - if (F_ISSET(infop, REGION_CREATED)) { - /* - * If we're using anonymous memory to back this region, set - * the flag. - */ - if (DB_GLOBAL(db_region_anon)) - F_SET(infop, REGION_ANONYMOUS); - - /* - * If we're using a regular file to back a region we created, - * grow it to the specified size. - */ - if (!DB_GLOBAL(db_region_anon) && - (ret = __db_growregion(infop, infop->size)) != 0) - goto err; - } else { - /* - * If we're joining a region, figure out what it looks like. - * - * XXX - * We have to figure out if the file is a regular file backing - * a region that we want to map into our address space, or a - * file with the information we need to find a shared anonymous - * region that we want to map into our address space. - * - * All this noise is because some systems don't have a coherent - * VM and buffer cache, and worse, if you mix operations on the - * VM and buffer cache, half the time you hang the system. - * - * There are two possibilities. If the file is the size of an - * RLAYOUT structure, then we know that the real region is in - * shared memory, because otherwise it would be bigger. (As - * the RLAYOUT structure size is smaller than a disk sector, - * the only way it can be this size is if deliberately written - * that way.) In which case, retrieve the information we need - * from the RLAYOUT structure and use it to acquire the shared - * memory. - * - * If the structure is larger than an RLAYOUT structure, then - * the file is backing the shared memory region, and we use - * the current size of the file without reading any information - * from the file itself so that we don't confuse the VM. - * - * And yes, this makes me want to take somebody and kill them, - * but I can't think of any other solution. - */ - if ((ret = __os_ioinfo(infop->name, - infop->fd, &mbytes, &bytes, NULL)) != 0) - goto errmsg; - size = mbytes * MEGABYTE + bytes; - - if (size <= sizeof(RLAYOUT)) { - /* - * If the size is too small, the read fails or the - * valid flag is incorrect, assume it's because the - * RLAYOUT information hasn't been written out yet, - * and retry. - */ - if (size < sizeof(RLAYOUT)) - goto retry; - if ((ret = - __os_read(infop->fd, &rl, sizeof(rl), &nr)) != 0) - goto retry; - if (rl.valid != DB_REGIONMAGIC) - goto retry; - - /* Copy the size, memory id and characteristics. */ - size = rl.size; - infop->segid = rl.segid; - if (F_ISSET(&rl, REGION_ANONYMOUS)) - F_SET(infop, REGION_ANONYMOUS); - } - - /* - * If the region is larger than we think, that's okay, use the - * current size. If it's smaller than we think, and we were - * just using the default size, that's okay, use the current - * size. If it's smaller than we think and we really care, - * save the size and we'll catch that further down -- we can't - * correct it here because we have to have a lock to grow the - * region. - */ - if (infop->size > size && !F_ISSET(infop, REGION_SIZEDEF)) - grow_region = infop->size; - infop->size = size; - } - - /* - * Map the region into our address space. If we're creating it, the - * underlying routines will make it the right size. - * - * There are at least two cases where we can "reasonably" fail when - * we attempt to map in the region. On Windows/95, closing the last - * reference to a region causes it to be zeroed out. On UNIX, when - * using the shmget(2) interfaces, the region will no longer exist - * if the system was rebooted. In these cases, the underlying map call - * returns EAGAIN, and we *remove* our file and try again. There are - * obvious races in doing this, but it should eventually settle down - * to a winner and then things should proceed normally. - */ - if ((ret = __db_mapregion(infop->name, infop)) != 0) { - if (ret == EAGAIN) { - /* - * Pretend we created the region even if we didn't so - * that our error processing unlinks it. - */ - F_SET(infop, REGION_CREATED); - ret = 0; - goto retry; - } else - goto err; - } - -region_init: - /* - * Initialize the common region information. - * - * !!! - * We have to order the region creates so that two processes don't try - * to simultaneously create the region. This is handled by using the - * DB_CREATE and DB_EXCL flags when we create the "backing" region file. - * - * We also have to order region joins so that processes joining regions - * never see inconsistent data. We'd like to play permissions games - * with the backing file, but we can't because WNT filesystems won't - * open a file mode 0. - */ - rlp = (RLAYOUT *)infop->addr; - if (F_ISSET(infop, REGION_CREATED)) { - /* - * The process creating the region acquires a lock before it - * sets the valid flag. Any processes joining the region will - * check the valid flag before acquiring the lock. - * - * Check the return of __db_mutex_init() and __db_mutex_lock(), - * even though we don't usually check elsewhere. This is the - * first lock we initialize and acquire, and we have to know if - * it fails. (It CAN fail, e.g., SunOS, when using fcntl(2) - * for locking, with an in-memory filesystem specified as the - * database home.) - */ - if ((ret = __db_mutex_init(&rlp->lock, - MUTEX_LOCK_OFFSET(rlp, &rlp->lock))) != 0 || - (ret = __db_mutex_lock(&rlp->lock, infop->fd)) != 0) - goto err; - - /* Initialize the remaining region information. */ - rlp->refcnt = 1; - rlp->size = infop->size; - db_version(&rlp->majver, &rlp->minver, &rlp->patch); - rlp->panic = 0; - rlp->segid = infop->segid; - rlp->flags = 0; - if (F_ISSET(infop, REGION_ANONYMOUS)) - F_SET(rlp, REGION_ANONYMOUS); - - /* - * Fill in the valid field last -- use a magic number, memory - * may not be zero-filled, and we want to minimize the chance - * for collision. - */ - rlp->valid = DB_REGIONMAGIC; - - /* - * If the region is anonymous, write the RLAYOUT information - * into the backing file so that future region join and unlink - * calls can find it. - * - * XXX - * We MUST do the seek before we do the write. On Win95, while - * closing the last reference to an anonymous shared region - * doesn't discard the region, it does zero it out. So, the - * REGION_CREATED may be set, but the file may have already - * been written and the file descriptor may be at the end of - * the file. - */ - if (F_ISSET(infop, REGION_ANONYMOUS)) { - if ((ret = __os_seek(infop->fd, 0, 0, 0, 0, 0)) != 0) - goto err; - if ((ret = - __os_write(infop->fd, rlp, sizeof(*rlp), &nw)) != 0) - goto err; - } - } else { - /* Check to see if the region has had catastrophic failure. */ - if (rlp->panic) { - ret = DB_RUNRECOVERY; - goto err; - } - - /* - * Check the valid flag to ensure the region is initialized. - * If the valid flag has not been set, the mutex may not have - * been initialized, and an attempt to get it could lead to - * random behavior. - */ - if (rlp->valid != DB_REGIONMAGIC) - goto retry; - - /* Get the region lock. */ - (void)__db_mutex_lock(&rlp->lock, infop->fd); - - /* - * We now own the region. There are a couple of things that - * may have gone wrong, however. - * - * Problem #1: while we were waiting for the lock, the region - * was deleted. Detected by re-checking the valid flag, since - * it's cleared by the delete region routines. - */ - if (rlp->valid != DB_REGIONMAGIC) { - (void)__db_mutex_unlock(&rlp->lock, infop->fd); - goto retry; - } - - /* - * Problem #3: when we checked the size of the file, it was - * still growing as part of creation. Detected by the fact - * that infop->size isn't the same size as the region. - */ - if (infop->size != rlp->size) { - (void)__db_mutex_unlock(&rlp->lock, infop->fd); - goto retry; - } - - /* Increment the reference count. */ - ++rlp->refcnt; - } - - /* Return the region in a locked condition. */ - - if (0) { -errmsg: __db_err(infop->dbenv, "%s: %s", infop->name, strerror(ret)); - -err: -retry: /* Discard the region. */ - if (infop->addr != NULL) { - (void)__db_unmapregion(infop); - infop->addr = NULL; - } - - /* Discard the backing file. */ - if (infop->fd != -1) { - (void)__os_close(infop->fd); - infop->fd = -1; - - if (F_ISSET(infop, REGION_CREATED)) - (void)__os_unlink(infop->name); - } - - /* Discard the name. */ - if (infop->name != NULL) { - __os_freestr(infop->name); - infop->name = NULL; - } - - /* - * If we had a temporary error, wait a few seconds and - * try again. - */ - if (ret == 0) { - if (++retry_cnt <= 3) { - __os_sleep(retry_cnt * 2, 0); - goto loop; - } - ret = EAGAIN; - } - } - - /* - * XXX - * HP-UX won't permit mutexes to live in anything but shared memory. - * Instantiate a shared region file on that architecture, regardless. - * - * XXX - * There's a problem in cleaning this up on application exit, or on - * application failure. If an application opens a database without - * an environment, we create a temporary backing mpool region for it. - * That region is marked REGION_PRIVATE, but as HP-UX won't permit - * mutexes to live in anything but shared memory, we instantiate a - * real file plus a memory region of some form. If the application - * crashes, the necessary information to delete the backing file and - * any system region (e.g., the shmget(2) segment ID) is no longer - * available. We can't completely fix the problem, but we try. - * - * The underlying UNIX __db_mapregion() code preferentially uses the - * mmap(2) interface with the MAP_ANON/MAP_ANONYMOUS flags for regions - * that are marked REGION_PRIVATE. This means that we normally aren't - * holding any system resources when we get here, in which case we can - * delete the backing file. This results in a short race, from the - * __db_open() call above to here. - * - * If, for some reason, we are holding system resources when we get - * here, we don't have any choice -- we can't delete the backing file - * because we may need it to detach from the resources. Set the - * REGION_LASTDETACH flag, so that we do all necessary cleanup when - * the application closes the region. - */ - if (F_ISSET(infop, REGION_PRIVATE) && !F_ISSET(infop, REGION_MALLOC)) { - if (F_ISSET(infop, REGION_HOLDINGSYS)) - F_SET(infop, REGION_LASTDETACH); - else { - F_SET(infop, REGION_REMOVED); - F_CLR(infop, REGION_CANGROW); - - (void)__os_close(infop->fd); - (void)__os_unlink(infop->name); - } - } - - return (ret); -} - -/* - * __db_rdetach -- - * De-attach from a shared memory region. - * - * PUBLIC: int __db_rdetach __P((REGINFO *)); - */ -int -__db_rdetach(infop) - REGINFO *infop; -{ - RLAYOUT *rlp; - int detach, ret, t_ret; - - ret = 0; - - /* - * If the region was removed when it was created, no further action - * is required. - */ - if (F_ISSET(infop, REGION_REMOVED)) - goto done; - /* - * If the region was created in memory returned by malloc, the only - * action required is freeing the memory. - */ - if (F_ISSET(infop, REGION_MALLOC)) { - __os_free(infop->addr, 0); - goto done; - } - - /* Otherwise, attach to the region and optionally delete it. */ - rlp = infop->addr; - - /* Get the lock. */ - (void)__db_mutex_lock(&rlp->lock, infop->fd); - - /* Decrement the reference count. */ - if (rlp->refcnt == 0) - __db_err(infop->dbenv, - "region rdetach: reference count went to zero!"); - else - --rlp->refcnt; - - /* - * If we're going to remove the region, clear the valid flag so - * that any region join that's blocked waiting for us will know - * what happened. - */ - detach = 0; - if (F_ISSET(infop, REGION_LASTDETACH)) { - if (rlp->refcnt == 0) { - detach = 1; - rlp->valid = 0; - } else - ret = EBUSY; - } - - /* Release the lock. */ - (void)__db_mutex_unlock(&rlp->lock, infop->fd); - - /* Close the backing file descriptor. */ - (void)__os_close(infop->fd); - infop->fd = -1; - - /* Discard our mapping of the region. */ - if ((t_ret = __db_unmapregion(infop)) != 0 && ret == 0) - ret = t_ret; - - /* Discard the region itself. */ - if (detach) { - if ((t_ret = - __db_unlinkregion(infop->name, infop) != 0) && ret == 0) - ret = t_ret; - if ((t_ret = __os_unlink(infop->name) != 0) && ret == 0) - ret = t_ret; - } - -done: /* Discard the name. */ - if (infop->name != NULL) { - __os_freestr(infop->name); - infop->name = NULL; - } - - return (ret); -} - -/* - * __db_runlink -- - * Remove a region. - * - * PUBLIC: int __db_runlink __P((REGINFO *, int)); - */ -int -__db_runlink(infop, force) - REGINFO *infop; - int force; -{ - RLAYOUT rl, *rlp; - size_t size; - ssize_t nr; - u_int32_t mbytes, bytes; - int fd, ret, t_ret; - char *name; - - /* - * XXX - * We assume that we've created a new REGINFO structure for this - * call, not used one that was already initialized. Regardless, - * if anyone is planning to use it after we're done, they're going - * to be sorely disappointed. - * - * If force isn't set, we attach to the region, set a flag to delete - * the region on last close, and let the region delete code do the - * work. - */ - if (!force) { - if ((ret = __db_rattach(infop)) != 0) - return (ret); - - rlp = (RLAYOUT *)infop->addr; - (void)__db_mutex_unlock(&rlp->lock, infop->fd); - - F_SET(infop, REGION_LASTDETACH); - - return (__db_rdetach(infop)); - } - - /* - * Otherwise, we don't want to attach to the region. We may have been - * called to clean up if a process died leaving a region locked and/or - * corrupted, which could cause the attach to hang. - */ - if ((ret = __db_appname(infop->dbenv, infop->appname, - infop->path, infop->file, infop->dbflags, NULL, &name)) != 0) - return (ret); - - /* - * An underlying file is created for all regions other than private - * (REGION_PRIVATE) ones, regardless of whether or not it's used to - * back the region. If that file doesn't exist, we're done. - */ - if (__os_exists(name, NULL) != 0) { - __os_freestr(name); - return (0); - } - - /* - * See the comments in __db_rattach -- figure out if this is a regular - * file backing a region or if it's a regular file with information - * about a region. - */ - if ((ret = __db_open(name, DB_RDONLY, DB_RDONLY, 0, &fd)) != 0) - goto errmsg; - if ((ret = __os_ioinfo(name, fd, &mbytes, &bytes, NULL)) != 0) - goto errmsg; - size = mbytes * MEGABYTE + bytes; - - if (size <= sizeof(RLAYOUT)) { - if ((ret = __os_read(fd, &rl, sizeof(rl), &nr)) != 0) - goto errmsg; - if (rl.valid != DB_REGIONMAGIC) { - __db_err(infop->dbenv, - "%s: illegal region magic number", name); - ret = EINVAL; - goto err; - } - - /* Set the size, memory id and characteristics. */ - infop->size = rl.size; - infop->segid = rl.segid; - if (F_ISSET(&rl, REGION_ANONYMOUS)) - F_SET(infop, REGION_ANONYMOUS); - } else { - infop->size = size; - infop->segid = INVALID_SEGID; - } - - /* Remove the underlying region. */ - ret = __db_unlinkregion(name, infop); - - /* - * Unlink the backing file. Close the open file descriptor first, - * because some architectures (e.g., Win32) won't unlink a file if - * open file descriptors remain. - */ - (void)__os_close(fd); - if ((t_ret = __os_unlink(name)) != 0 && ret == 0) - ret = t_ret; - - if (0) { -errmsg: __db_err(infop->dbenv, "%s: %s", name, strerror(ret)); -err: (void)__os_close(fd); - } - - __os_freestr(name); - return (ret); -} - -/* - * __db_rgrow -- - * Extend a region. - * - * PUBLIC: int __db_rgrow __P((REGINFO *, size_t)); - */ -int -__db_rgrow(infop, new_size) - REGINFO *infop; - size_t new_size; -{ - RLAYOUT *rlp; - size_t increment; - int ret; - - /* - * !!! - * This routine MUST be called with the region already locked. - */ - - /* The underlying routines have flagged if this region can grow. */ - if (!F_ISSET(infop, REGION_CANGROW)) - return (EINVAL); - - /* - * Round off the requested size to the next page boundary, and - * determine the additional space required. - */ - rlp = (RLAYOUT *)infop->addr; - DB_ROUNDOFF(new_size, DB_VMPAGESIZE); - increment = new_size - rlp->size; - - if ((ret = __db_growregion(infop, increment)) != 0) - return (ret); - - /* Update the on-disk region size. */ - rlp->size = new_size; - - /* Detach from and reattach to the region. */ - return (__db_rreattach(infop, new_size)); -} - -/* - * __db_growregion -- - * Grow a shared memory region. - */ -static int -__db_growregion(infop, increment) - REGINFO *infop; - size_t increment; -{ - db_pgno_t pages; - size_t i; - ssize_t nr, nw; - u_int32_t relative; - int ret; - char buf[DB_VMPAGESIZE]; - - /* Seek to the end of the region. */ - if ((ret = __os_seek(infop->fd, 0, 0, 0, 0, SEEK_END)) != 0) - goto err; - - /* Write nuls to the new bytes. */ - memset(buf, 0, sizeof(buf)); - - /* - * Some systems require that all of the bytes of the region be - * written before it can be mapped and accessed randomly, and - * other systems don't zero out the pages. - */ - if (__db_mapinit()) - /* Extend the region by writing each new page. */ - for (i = 0; i < increment; i += DB_VMPAGESIZE) { - if ((ret = - __os_write(infop->fd, buf, sizeof(buf), &nw)) != 0) - goto err; - if (nw != sizeof(buf)) - goto eio; - } - else { - /* - * Extend the region by writing the last page. If the region - * is >4Gb, increment may be larger than the maximum possible - * seek "relative" argument, as it's an unsigned 32-bit value. - * Break the offset into pages of 1MB each so that we don't - * overflow (2^20 + 2^32 is bigger than any memory I expect - * to see for awhile). - */ - pages = (increment - DB_VMPAGESIZE) / MEGABYTE; - relative = (increment - DB_VMPAGESIZE) % MEGABYTE; - if ((ret = __os_seek(infop->fd, - MEGABYTE, pages, relative, 0, SEEK_CUR)) != 0) - goto err; - if ((ret = __os_write(infop->fd, buf, sizeof(buf), &nw)) != 0) - goto err; - if (nw != sizeof(buf)) - goto eio; - - /* - * It's sometimes significantly faster to page-fault in all of - * the region's pages before we run the application, as we see - * nasty side-effects when we page-fault while holding various - * locks, i.e., the lock takes a long time to acquire because - * of the underlying page fault, and the other threads convoy - * behind the lock holder. - * - * We also use REGION_INIT to guarantee that there is enough - * disk space for the region, so we also write a byte to each - * page. Reading the byte is insufficient as some systems - * (e.g., Solaris) do not instantiate disk pages to satisfy - * a read, and so we don't know if there is enough disk space - * or not. - */ - if (DB_GLOBAL(db_region_init)) { - pages = increment / MEGABYTE; - relative = increment % MEGABYTE; - if ((ret = __os_seek(infop->fd, - MEGABYTE, pages, relative, 1, SEEK_END)) != 0) - goto err; - - /* Write a byte to each page. */ - for (i = 0; i < increment; i += DB_VMPAGESIZE) { - if ((ret = - __os_write(infop->fd, buf, 1, &nr)) != 0) - goto err; - if (nr != 1) - goto eio; - if ((ret = __os_seek(infop->fd, - 0, 0, DB_VMPAGESIZE - 1, 0, SEEK_CUR)) != 0) - goto err; - } - } - } - return (0); - -eio: ret = EIO; -err: __db_err(infop->dbenv, "region grow: %s", strerror(ret)); - return (ret); -} - -/* - * __db_rreattach -- - * Detach from and reattach to a region. - * - * PUBLIC: int __db_rreattach __P((REGINFO *, size_t)); - */ -int -__db_rreattach(infop, new_size) - REGINFO *infop; - size_t new_size; -{ - int ret; - -#ifdef DIAGNOSTIC - if (infop->name == NULL) { - __db_err(infop->dbenv, "__db_rreattach: name was NULL"); - return (EINVAL); - } -#endif - /* - * If we're growing an already mapped region, we have to unmap it - * and get it back. We have it locked, so nobody else can get in, - * which makes it fairly straight-forward to do, as everybody else - * is going to block while we do the unmap/remap. NB: if we fail - * to get it back, the pooch is genuinely screwed, because we can - * never release the lock we're holding. - * - * Detach from the region. We have to do this first so architectures - * that don't permit a file to be mapped into different places in the - * address space simultaneously, e.g., HP's PaRisc, will work. - */ - if ((ret = __db_unmapregion(infop)) != 0) - return (ret); - - /* Update the caller's REGINFO size to the new map size. */ - infop->size = new_size; - - /* Attach to the region. */ - ret = __db_mapregion(infop->name, infop); - - return (ret); -} diff --git a/db2/common/db_salloc.c b/db2/common/db_salloc.c deleted file mode 100644 index d58b79f3c4..0000000000 --- a/db2/common/db_salloc.c +++ /dev/null @@ -1,302 +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[] = "@(#)db_salloc.c 10.14 (Sleepycat) 11/16/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 "common_ext.h" - -/* - * Implement shared memory region allocation, using simple first-fit algorithm. - * The model is that we take a "chunk" of shared memory store and begin carving - * it up into areas, similarly to how malloc works. We do coalescing on free. - * - * The "len" field in the __data struct contains the length of the free region - * (less the size_t bytes that holds the length). We use the address provided - * by the caller to find this length, which allows us to free a chunk without - * requiring that the caller pass in the length of the chunk they're freeing. - */ -SH_LIST_HEAD(__head); -struct __data { - size_t len; - SH_LIST_ENTRY links; -}; - -/* - * __db_shalloc_init -- - * Initialize the area as one large chunk. - * - * PUBLIC: void __db_shalloc_init __P((void *, size_t)); - */ -void -__db_shalloc_init(area, size) - void *area; - size_t size; -{ - struct __data *elp; - struct __head *hp; - - hp = area; - SH_LIST_INIT(hp); - - elp = (struct __data *)(hp + 1); - elp->len = size - sizeof(struct __head) - sizeof(elp->len); - SH_LIST_INSERT_HEAD(hp, elp, links, __data); -} - -/* - * __db_shalloc -- - * Allocate some space from the shared region. - * - * PUBLIC: int __db_shalloc __P((void *, size_t, size_t, void *)); - */ -int -__db_shalloc(p, len, align, retp) - void *p, *retp; - size_t len, align; -{ - struct __data *elp; - size_t *sp; - void *rp; - - /* - * We never allocate less than the size of a struct __data, align - * to less than a size_t boundary, or align to something that's not - * a multiple of a size_t. - */ - if (len < sizeof(struct __data)) - len = sizeof(struct __data); - align = align <= sizeof(size_t) ? - sizeof(size_t) : ALIGN(align, sizeof(size_t)); - - /* Walk the list, looking for a slot. */ - for (elp = SH_LIST_FIRST((struct __head *)p, __data); - elp != NULL; - elp = SH_LIST_NEXT(elp, links, __data)) { - /* - * Calculate the value of the returned pointer if we were to - * use this chunk. - * + Find the end of the chunk. - * + Subtract the memory the user wants. - * + Find the closest previous correctly-aligned address. - */ - rp = (u_int8_t *)elp + sizeof(size_t) + elp->len; - rp = (u_int8_t *)rp - len; - rp = (u_int8_t *)((ALIGNTYPE)rp & ~(align - 1)); - - /* - * Rp may now point before elp->links, in which case the chunk - * was too small, and we have to try again. - */ - if ((u_int8_t *)rp < (u_int8_t *)&elp->links) - continue; - - *(void **)retp = rp; - -#define SHALLOC_FRAGMENT 32 - /* - * If there are at least SHALLOC_FRAGMENT additional bytes of - * memory, divide the chunk into two chunks. - */ - if ((u_int8_t *)rp >= - (u_int8_t *)&elp->links + SHALLOC_FRAGMENT) { - sp = rp; - *--sp = elp->len - - ((u_int8_t *)rp - (u_int8_t *)&elp->links); - elp->len -= *sp + sizeof(size_t); - return (0); - } - - /* - * Otherwise, we return the entire chunk, wasting some amount - * of space to keep the list compact. However, because the - * address we're returning to the user may not be the address - * of the start of the region for alignment reasons, set the - * size_t length fields back to the "real" length field to a - * flag value, so that we can find the real length during free. - */ -#define ILLEGAL_SIZE 1 - SH_LIST_REMOVE(elp, links, __data); - for (sp = rp; (u_int8_t *)--sp >= (u_int8_t *)&elp->links;) - *sp = ILLEGAL_SIZE; - return (0); - } - - /* Nothing found large enough; need to grow the region. */ - return (ENOMEM); -} - -/* - * __db_shalloc_free -- - * Free a shared memory allocation. - * - * PUBLIC: void __db_shalloc_free __P((void *, void *)); - */ -void -__db_shalloc_free(regionp, ptr) - void *regionp, *ptr; -{ - struct __data *elp, *lastp, *newp; - struct __head *hp; - size_t free_size, *sp; - int merged; - - /* - * Step back over flagged length fields to find the beginning of - * the object and its real size. - */ - for (sp = (size_t *)ptr; sp[-1] == ILLEGAL_SIZE; --sp) - ; - ptr = sp; - - newp = (struct __data *)((u_int8_t *)ptr - sizeof(size_t)); - free_size = newp->len; - - /* Trash the returned memory. */ -#ifdef DIAGNOSTIC - memset(ptr, 0xdb, free_size); -#endif - - /* - * Walk the list, looking for where this entry goes. - * - * We keep the free list sorted by address so that coalescing is - * trivial. - * - * XXX - * Probably worth profiling this to see how expensive it is. - */ - hp = (struct __head *)regionp; - for (elp = SH_LIST_FIRST(hp, __data), lastp = NULL; - elp != NULL && (void *)elp < (void *)ptr; - lastp = elp, elp = SH_LIST_NEXT(elp, links, __data)) - ; - - /* - * Elp is either NULL (we reached the end of the list), or the slot - * after the one that's being returned. Lastp is either NULL (we're - * returning the first element of the list) or the element before the - * one being returned. - * - * Check for coalescing with the next element. - */ - merged = 0; - if ((u_int8_t *)ptr + free_size == (u_int8_t *)elp) { - newp->len += elp->len + sizeof(size_t); - SH_LIST_REMOVE(elp, links, __data); - if (lastp != NULL) - SH_LIST_INSERT_AFTER(lastp, newp, links, __data); - else - SH_LIST_INSERT_HEAD(hp, newp, links, __data); - merged = 1; - } - - /* Check for coalescing with the previous element. */ - if (lastp != NULL && (u_int8_t *)lastp + - lastp->len + sizeof(size_t) == (u_int8_t *)newp) { - lastp->len += newp->len + sizeof(size_t); - - /* - * If we have already put the new element into the list take - * it back off again because it's just been merged with the - * previous element. - */ - if (merged) - SH_LIST_REMOVE(newp, links, __data); - merged = 1; - } - - if (!merged) { - if (lastp == NULL) - SH_LIST_INSERT_HEAD(hp, newp, links, __data); - else - SH_LIST_INSERT_AFTER(lastp, newp, links, __data); - } -} - -/* - * __db_shalloc_count -- - * Return the amount of memory on the free list. - * - * PUBLIC: size_t __db_shalloc_count __P((void *)); - */ -size_t -__db_shalloc_count(addr) - void *addr; -{ - struct __data *elp; - size_t count; - - count = 0; - for (elp = SH_LIST_FIRST((struct __head *)addr, __data); - elp != NULL; - elp = SH_LIST_NEXT(elp, links, __data)) - count += elp->len; - - return (count); -} - -/* - * __db_shsizeof -- - * Return the size of a shalloc'd piece of memory. - * - * PUBLIC: size_t __db_shsizeof __P((void *)); - */ -size_t -__db_shsizeof(ptr) - void *ptr; -{ - struct __data *elp; - size_t *sp; - - /* - * Step back over flagged length fields to find the beginning of - * the object and its real size. - */ - for (sp = (size_t *)ptr; sp[-1] == ILLEGAL_SIZE; --sp) - ; - - elp = (struct __data *)((u_int8_t *)sp - sizeof(size_t)); - return (elp->len); -} - -/* - * __db_shalloc_dump -- - * - * PUBLIC: void __db_shalloc_dump __P((void *, FILE *)); - */ -void -__db_shalloc_dump(addr, fp) - void *addr; - FILE *fp; -{ - struct __data *elp; - - /* Make it easy to call from the debugger. */ - if (fp == NULL) - fp = stderr; - - fprintf(fp, "%s\nMemory free list\n", DB_LINE); - - for (elp = SH_LIST_FIRST((struct __head *)addr, __data); - elp != NULL; - elp = SH_LIST_NEXT(elp, links, __data)) - fprintf(fp, "%#lx: %lu\t", (u_long)elp, (u_long)elp->len); - fprintf(fp, "\n"); -} diff --git a/db2/common/db_shash.c b/db2/common/db_shash.c deleted file mode 100644 index 3f48a55907..0000000000 --- a/db2/common/db_shash.c +++ /dev/null @@ -1,126 +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[] = "@(#)db_shash.c 10.9 (Sleepycat) 4/10/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> -#endif - -#include "db_int.h" -#include "shqueue.h" -#include "common_ext.h" - -/* - * Table of good hash values. Up to ~250,000 buckets, we use powers of 2. - * After that, we slow the rate of increase by half. For each choice, we - * then use a nearby prime number as the hash value. - * - * If a terabyte is the maximum cache we'll see, and we assume there are - * 10 1K buckets on each hash chain, then 107374182 is the maximum number - * of buckets we'll ever need. - */ -static const struct { - u_int32_t power; - u_int32_t prime; -} list[] = { - { 64, 67}, /* 2^6 */ - { 128, 131}, /* 2^7 */ - { 256, 257}, /* 2^8 */ - { 512, 521}, /* 2^9 */ - { 1024, 1031}, /* 2^10 */ - { 2048, 2053}, /* 2^11 */ - { 4096, 4099}, /* 2^12 */ - { 8192, 8191}, /* 2^13 */ - { 16384, 16381}, /* 2^14 */ - { 32768, 32771}, /* 2^15 */ - { 65536, 65537}, /* 2^16 */ - { 131072, 131071}, /* 2^17 */ - { 262144, 262147}, /* 2^18 */ - { 393216, 393209}, /* 2^18 + 2^18/2 */ - { 524288, 524287}, /* 2^19 */ - { 786432, 786431}, /* 2^19 + 2^19/2 */ - { 1048576, 1048573}, /* 2^20 */ - { 1572864, 1572869}, /* 2^20 + 2^20/2 */ - { 2097152, 2097169}, /* 2^21 */ - { 3145728, 3145721}, /* 2^21 + 2^21/2 */ - { 4194304, 4194301}, /* 2^22 */ - { 6291456, 6291449}, /* 2^22 + 2^22/2 */ - { 8388608, 8388617}, /* 2^23 */ - { 12582912, 12582917}, /* 2^23 + 2^23/2 */ - { 16777216, 16777213}, /* 2^24 */ - { 25165824, 25165813}, /* 2^24 + 2^24/2 */ - { 33554432, 33554393}, /* 2^25 */ - { 50331648, 50331653}, /* 2^25 + 2^25/2 */ - { 67108864, 67108859}, /* 2^26 */ - { 100663296, 100663291}, /* 2^26 + 2^26/2 */ - { 134217728, 134217757}, /* 2^27 */ - { 201326592, 201326611}, /* 2^27 + 2^27/2 */ - { 268435456, 268435459}, /* 2^28 */ - { 402653184, 402653189}, /* 2^28 + 2^28/2 */ - { 536870912, 536870909}, /* 2^29 */ - { 805306368, 805306357}, /* 2^29 + 2^29/2 */ - {1073741824, 1073741827}, /* 2^30 */ - {0, 0} -}; - -/* - * __db_tablesize -- - * Choose a size for the hash table. - * - * PUBLIC: int __db_tablesize __P((u_int32_t)); - */ -int -__db_tablesize(n_buckets) - u_int32_t n_buckets; -{ - int i; - - /* - * We try to be clever about how big we make the hash tables. Use a - * prime number close to the "suggested" number of elements that will - * be in the hash table. Use 64 as the minimum hash table size. - * - * Ref: Sedgewick, Algorithms in C, "Hash Functions" - */ - if (n_buckets < 64) - n_buckets = 64; - - for (i = 0;; ++i) { - if (list[i].power == 0) { - --i; - break; - } - if (list[i].power >= n_buckets) - break; - } - return (list[i].prime); -} - -/* - * __db_hashinit -- - * Initialize a hash table that resides in shared memory. - * - * PUBLIC: void __db_hashinit __P((void *, u_int32_t)); - */ -void -__db_hashinit(begin, nelements) - void *begin; - u_int32_t nelements; -{ - u_int32_t i; - SH_TAILQ_HEAD(hash_head) *headp; - - headp = (struct hash_head *)begin; - - for (i = 0; i < nelements; i++, headp++) - SH_TAILQ_INIT(headp); -} |