diff options
213 files changed, 6 insertions, 64297 deletions
@@ -1,5 +1,9 @@ 2000-01-01 Ulrich Drepper <drepper@cygnus.com> + * Makeconfig (all-subdirs): Remove db and db2. + * db/*: Removed. + * db2/*: Removed. + * nss/nss_db/db-XXX.c: Move internal_setent and internal_endent functions from here... * nss/db-alias.c: ...and here... @@ -1,4 +1,4 @@ -# Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc. +# Copyright (C) 1991-1999,2000 Free Software Foundation, Inc. # This file is part of the GNU C Library. # The GNU C Library is free software; you can redistribute it and/or @@ -779,7 +779,7 @@ endif # is more or less arbitrary. The sorting step will take care of the # dependencies. Only the $(binfmt-subdir) should always be kept at the # end of the list. -all-subdirs = csu assert ctype db db2 locale intl catgets math setjmp signal\ +all-subdirs = csu assert ctype locale intl catgets math setjmp signal \ stdlib stdio-common $(stdio) malloc string wcsmbs time dirent \ grp pwd posix io termios resource misc socket sysvipc gmon \ gnulib iconv iconvdata wctype manual shadow md5-crypt po argp \ diff --git a/db/Makefile b/db/Makefile deleted file mode 100644 index ac08e78..0000000 --- a/db/Makefile +++ /dev/null @@ -1,73 +0,0 @@ -# Makefile for 4.4BSD db code in GNU C library. -# This code is taken verbatim from the BSD db 1.85 package. Only this -# Makefile and compat.h were written for GNU libc, and the header files -# moved up to this directory. - -subdir = db - -subdir-dirs = btree db hash mpool recno -vpath %.c $(subdir-dirs) - -extra-libs := libdb1 -extra-libs-others := $(extra-libs) -libdb1-routines := bt_close bt_conv bt_debug bt_delete bt_get \ - bt_open bt_overflow bt_page bt_put bt_search \ - bt_seq bt_split bt_utils \ - db \ - hash hash_bigkey hash_buf hash_func hash_log2 hash_page \ - ndbm \ - mpool \ - rec_close rec_delete rec_get rec_open rec_put rec_search \ - rec_seq rec_utils - -db1-headers := db.h mpool.h ndbm.h -distribute := compat.h \ - btree/btree.h btree/extern.h \ - hash/extern.h hash/hash.h hash/page.h \ - recno/extern.h recno/recno.h \ - $(db1-headers) - -include ../Makeconfig - -install-others := $(db1-headers:%=$(inst_includedir)/db1/%) - -ifeq (yes,$(build-shared)) -install-others += $(inst_slibdir)/libdb.so$(libdb1.so-version) -endif - -$(inst_slibdir)/libdb.so$(libdb1.so-version): $(inst_slibdir)/libdb1-$(version).so $(+force) - rm -f $@ - $(LN_S) $(<F) $@ - -$(db1-headers:%=$(inst_includedir)/db1/%): $(inst_includedir)/db1/%: % $(+force) - $(do-install) - -include ../Rules - -CPPFLAGS += -D__DBINTERFACE_PRIVATE -DUSE_LIBDB1 - -# This file defines some static functions for alternative hash algorithms -# that are not actually used. -CFLAGS-hash_func.c := -Wno-unused - -# The db code outsmarts the compiler frequently. -override CFLAGS += -Wno-uninitialized - -# Force the soname to be libdb.so for compatibility. -LDFLAGS-db1.so = -Wl,-soname=lib$(libprefix)db.so$($(@F)-version) - -# Depend on libc.so so a DT_NEEDED is generated in the shared objects. -# This ensures they will load libc.so for needed symbols if loaded by -# a statically-linked program that hasn't already loaded it. -$(objpfx)libdb1.so: $(objpfx)libdb1_pic.a $(+preinit) $(+postinit) $(+interp) \ - $(common-objpfx)libc.so - -#subdir_install: $(inst_libdir)/libndbm.a -#$(inst_libdir)/libndbm.a: $(inst_libdir)/libdb1.a $(+force) -# $(make-link) -# -#ifeq ($(build-shared),yes) -#subdir_install: $(inst_libdir)/libndbm.so -#$(inst_libdir)/libndbm.so: $(inst_libdir)/libdb1.so $(+force) -# $(make-link) -#endif diff --git a/db/Versions b/db/Versions deleted file mode 100644 index 479604e..0000000 --- a/db/Versions +++ /dev/null @@ -1,10 +0,0 @@ -libdb1 { - GLIBC_2.0 { - # the real DB entry point. - dbopen; __dbopen; - - # The compatibility functions. - dbm_clearerr; dbm_close; dbm_delete; dbm_dirfno; dbm_error; - dbm_fetch; dbm_firstkey; dbm_nextkey; dbm_open; dbm_store; - } -} diff --git a/db/btree/bt_close.c b/db/btree/bt_close.c deleted file mode 100644 index 27f9ab6..0000000 --- a/db/btree/bt_close.c +++ /dev/null @@ -1,182 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * 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. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)bt_close.c 8.7 (Berkeley) 8/17/94"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/param.h> - -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include <db.h> -#include "btree.h" - -static int bt_meta __P((BTREE *)); - -/* - * BT_CLOSE -- Close a btree. - * - * Parameters: - * dbp: pointer to access method - * - * Returns: - * RET_ERROR, RET_SUCCESS - */ -int -__bt_close(dbp) - DB *dbp; -{ - BTREE *t; - int fd; - - t = dbp->internal; - - /* Toss any page pinned across calls. */ - if (t->bt_pinned != NULL) { - mpool_put(t->bt_mp, t->bt_pinned, 0); - t->bt_pinned = NULL; - } - - /* Sync the tree. */ - if (__bt_sync(dbp, 0) == RET_ERROR) - return (RET_ERROR); - - /* Close the memory pool. */ - if (mpool_close(t->bt_mp) == RET_ERROR) - return (RET_ERROR); - - /* Free random memory. */ - if (t->bt_cursor.key.data != NULL) { - free(t->bt_cursor.key.data); - t->bt_cursor.key.size = 0; - t->bt_cursor.key.data = NULL; - } - if (t->bt_rkey.data) { - free(t->bt_rkey.data); - t->bt_rkey.size = 0; - t->bt_rkey.data = NULL; - } - if (t->bt_rdata.data) { - free(t->bt_rdata.data); - t->bt_rdata.size = 0; - t->bt_rdata.data = NULL; - } - - fd = t->bt_fd; - free(t); - free(dbp); - return (close(fd) ? RET_ERROR : RET_SUCCESS); -} - -/* - * BT_SYNC -- sync the btree to disk. - * - * Parameters: - * dbp: pointer to access method - * - * Returns: - * RET_SUCCESS, RET_ERROR. - */ -int -__bt_sync(dbp, flags) - const DB *dbp; - u_int flags; -{ - BTREE *t; - int status; - - t = dbp->internal; - - /* Toss any page pinned across calls. */ - if (t->bt_pinned != NULL) { - mpool_put(t->bt_mp, t->bt_pinned, 0); - t->bt_pinned = NULL; - } - - /* Sync doesn't currently take any flags. */ - if (flags != 0) { - errno = EINVAL; - return (RET_ERROR); - } - - if (F_ISSET(t, B_INMEM | B_RDONLY) || !F_ISSET(t, B_MODIFIED)) - return (RET_SUCCESS); - - if (F_ISSET(t, B_METADIRTY) && bt_meta(t) == RET_ERROR) - return (RET_ERROR); - - if ((status = mpool_sync(t->bt_mp)) == RET_SUCCESS) - F_CLR(t, B_MODIFIED); - - return (status); -} - -/* - * BT_META -- write the tree meta data to disk. - * - * Parameters: - * t: tree - * - * Returns: - * RET_ERROR, RET_SUCCESS - */ -static int -bt_meta(t) - BTREE *t; -{ - BTMETA m; - void *p; - - if ((p = mpool_get(t->bt_mp, P_META, 0)) == NULL) - return (RET_ERROR); - - /* Fill in metadata. */ - m.magic = BTREEMAGIC; - m.version = BTREEVERSION; - m.psize = t->bt_psize; - m.free = t->bt_free; - m.nrecs = t->bt_nrecs; - m.flags = F_ISSET(t, SAVEMETA); - - memmove(p, &m, sizeof(BTMETA)); - mpool_put(t->bt_mp, p, MPOOL_DIRTY); - return (RET_SUCCESS); -} diff --git a/db/btree/bt_conv.c b/db/btree/bt_conv.c deleted file mode 100644 index 1cb208b..0000000 --- a/db/btree/bt_conv.c +++ /dev/null @@ -1,221 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * 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. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)bt_conv.c 8.5 (Berkeley) 8/17/94"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/param.h> - -#include <stdio.h> - -#include <db.h> -#include "btree.h" - -static void mswap __P((PAGE *)); - -/* - * __BT_BPGIN, __BT_BPGOUT -- - * Convert host-specific number layout to/from the host-independent - * format stored on disk. - * - * Parameters: - * t: tree - * pg: page number - * h: page to convert - */ -void -__bt_pgin(t, pg, pp) - void *t; - pgno_t pg; - void *pp; -{ - PAGE *h; - indx_t i, top; - u_char flags; - char *p; - - if (!F_ISSET(((BTREE *)t), B_NEEDSWAP)) - return; - if (pg == P_META) { - mswap(pp); - return; - } - - h = pp; - M_32_SWAP(h->pgno); - M_32_SWAP(h->prevpg); - M_32_SWAP(h->nextpg); - M_32_SWAP(h->flags); - M_16_SWAP(h->lower); - M_16_SWAP(h->upper); - - top = NEXTINDEX(h); - if ((h->flags & P_TYPE) == P_BINTERNAL) - for (i = 0; i < top; i++) { - M_16_SWAP(h->linp[i]); - p = (char *)GETBINTERNAL(h, i); - P_32_SWAP(p); - p += sizeof(u_int32_t); - P_32_SWAP(p); - p += sizeof(pgno_t); - if (*(u_char *)p & P_BIGKEY) { - p += sizeof(u_char); - P_32_SWAP(p); - p += sizeof(pgno_t); - P_32_SWAP(p); - } - } - else if ((h->flags & P_TYPE) == P_BLEAF) - for (i = 0; i < top; i++) { - M_16_SWAP(h->linp[i]); - p = (char *)GETBLEAF(h, i); - P_32_SWAP(p); - p += sizeof(u_int32_t); - P_32_SWAP(p); - p += sizeof(u_int32_t); - flags = *(u_char *)p; - if (flags & (P_BIGKEY | P_BIGDATA)) { - p += sizeof(u_char); - if (flags & P_BIGKEY) { - P_32_SWAP(p); - p += sizeof(pgno_t); - P_32_SWAP(p); - } - if (flags & P_BIGDATA) { - p += sizeof(u_int32_t); - P_32_SWAP(p); - p += sizeof(pgno_t); - P_32_SWAP(p); - } - } - } -} - -void -__bt_pgout(t, pg, pp) - void *t; - pgno_t pg; - void *pp; -{ - PAGE *h; - indx_t i, top; - u_char flags; - char *p; - - if (!F_ISSET(((BTREE *)t), B_NEEDSWAP)) - return; - if (pg == P_META) { - mswap(pp); - return; - } - - h = pp; - top = NEXTINDEX(h); - if ((h->flags & P_TYPE) == P_BINTERNAL) - for (i = 0; i < top; i++) { - p = (char *)GETBINTERNAL(h, i); - P_32_SWAP(p); - p += sizeof(u_int32_t); - P_32_SWAP(p); - p += sizeof(pgno_t); - if (*(u_char *)p & P_BIGKEY) { - p += sizeof(u_char); - P_32_SWAP(p); - p += sizeof(pgno_t); - P_32_SWAP(p); - } - M_16_SWAP(h->linp[i]); - } - else if ((h->flags & P_TYPE) == P_BLEAF) - for (i = 0; i < top; i++) { - p = (char *)GETBLEAF(h, i); - P_32_SWAP(p); - p += sizeof(u_int32_t); - P_32_SWAP(p); - p += sizeof(u_int32_t); - flags = *(u_char *)p; - if (flags & (P_BIGKEY | P_BIGDATA)) { - p += sizeof(u_char); - if (flags & P_BIGKEY) { - P_32_SWAP(p); - p += sizeof(pgno_t); - P_32_SWAP(p); - } - if (flags & P_BIGDATA) { - p += sizeof(u_int32_t); - P_32_SWAP(p); - p += sizeof(pgno_t); - P_32_SWAP(p); - } - } - M_16_SWAP(h->linp[i]); - } - - M_32_SWAP(h->pgno); - M_32_SWAP(h->prevpg); - M_32_SWAP(h->nextpg); - M_32_SWAP(h->flags); - M_16_SWAP(h->lower); - M_16_SWAP(h->upper); -} - -/* - * MSWAP -- Actually swap the bytes on the meta page. - * - * Parameters: - * p: page to convert - */ -static void -mswap(pg) - PAGE *pg; -{ - char *p; - - p = (char *)pg; - P_32_SWAP(p); /* magic */ - p += sizeof(u_int32_t); - P_32_SWAP(p); /* version */ - p += sizeof(u_int32_t); - P_32_SWAP(p); /* psize */ - p += sizeof(u_int32_t); - P_32_SWAP(p); /* free */ - p += sizeof(u_int32_t); - P_32_SWAP(p); /* nrecs */ - p += sizeof(u_int32_t); - P_32_SWAP(p); /* flags */ - p += sizeof(u_int32_t); -} diff --git a/db/btree/bt_debug.c b/db/btree/bt_debug.c deleted file mode 100644 index 3aefbe7..0000000 --- a/db/btree/bt_debug.c +++ /dev/null @@ -1,329 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * 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. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)bt_debug.c 8.5 (Berkeley) 8/17/94"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/param.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <db.h> -#include "btree.h" - -#ifdef DEBUG -/* - * BT_DUMP -- Dump the tree - * - * Parameters: - * dbp: pointer to the DB - */ -void -__bt_dump(dbp) - DB *dbp; -{ - BTREE *t; - PAGE *h; - pgno_t i; - char *sep; - - t = dbp->internal; - (void)fprintf(stderr, "%s: pgsz %d", - F_ISSET(t, B_INMEM) ? "memory" : "disk", t->bt_psize); - if (F_ISSET(t, R_RECNO)) - (void)fprintf(stderr, " keys %lu", t->bt_nrecs); -#undef X -#define X(flag, name) \ - if (F_ISSET(t, flag)) { \ - (void)fprintf(stderr, "%s%s", sep, name); \ - sep = ", "; \ - } - if (t->flags != 0) { - sep = " flags ("; - X(R_FIXLEN, "FIXLEN"); - X(B_INMEM, "INMEM"); - X(B_NODUPS, "NODUPS"); - X(B_RDONLY, "RDONLY"); - X(R_RECNO, "RECNO"); - X(B_METADIRTY,"METADIRTY"); - (void)fprintf(stderr, ")\n"); - } -#undef X - - for (i = P_ROOT; (h = mpool_get(t->bt_mp, i, 0)) != NULL; ++i) { - __bt_dpage(h); - (void)mpool_put(t->bt_mp, h, 0); - } -} - -/* - * BT_DMPAGE -- Dump the meta page - * - * Parameters: - * h: pointer to the PAGE - */ -void -__bt_dmpage(h) - PAGE *h; -{ - BTMETA *m; - char *sep; - - m = (BTMETA *)h; - (void)fprintf(stderr, "magic %lx\n", m->magic); - (void)fprintf(stderr, "version %lu\n", m->version); - (void)fprintf(stderr, "psize %lu\n", m->psize); - (void)fprintf(stderr, "free %lu\n", m->free); - (void)fprintf(stderr, "nrecs %lu\n", m->nrecs); - (void)fprintf(stderr, "flags %lu", m->flags); -#undef X -#define X(flag, name) \ - if (m->flags & flag) { \ - (void)fprintf(stderr, "%s%s", sep, name); \ - sep = ", "; \ - } - if (m->flags) { - sep = " ("; - X(B_NODUPS, "NODUPS"); - X(R_RECNO, "RECNO"); - (void)fprintf(stderr, ")"); - } -} - -/* - * BT_DNPAGE -- Dump the page - * - * Parameters: - * n: page number to dump. - */ -void -__bt_dnpage(dbp, pgno) - DB *dbp; - pgno_t pgno; -{ - BTREE *t; - PAGE *h; - - t = dbp->internal; - if ((h = mpool_get(t->bt_mp, pgno, 0)) != NULL) { - __bt_dpage(h); - (void)mpool_put(t->bt_mp, h, 0); - } -} - -/* - * BT_DPAGE -- Dump the page - * - * Parameters: - * h: pointer to the PAGE - */ -void -__bt_dpage(h) - PAGE *h; -{ - BINTERNAL *bi; - BLEAF *bl; - RINTERNAL *ri; - RLEAF *rl; - indx_t cur, top; - char *sep; - - (void)fprintf(stderr, " page %d: (", h->pgno); -#undef X -#define X(flag, name) \ - if (h->flags & flag) { \ - (void)fprintf(stderr, "%s%s", sep, name); \ - sep = ", "; \ - } - sep = ""; - X(P_BINTERNAL, "BINTERNAL") /* types */ - X(P_BLEAF, "BLEAF") - X(P_RINTERNAL, "RINTERNAL") /* types */ - X(P_RLEAF, "RLEAF") - X(P_OVERFLOW, "OVERFLOW") - X(P_PRESERVE, "PRESERVE"); - (void)fprintf(stderr, ")\n"); -#undef X - - (void)fprintf(stderr, "\tprev %2d next %2d", h->prevpg, h->nextpg); - if (h->flags & P_OVERFLOW) - return; - - top = NEXTINDEX(h); - (void)fprintf(stderr, " lower %3d upper %3d nextind %d\n", - h->lower, h->upper, top); - for (cur = 0; cur < top; cur++) { - (void)fprintf(stderr, "\t[%03d] %4d ", cur, h->linp[cur]); - switch (h->flags & P_TYPE) { - case P_BINTERNAL: - bi = GETBINTERNAL(h, cur); - (void)fprintf(stderr, - "size %03d pgno %03d", bi->ksize, bi->pgno); - if (bi->flags & P_BIGKEY) - (void)fprintf(stderr, " (indirect)"); - else if (bi->ksize) - (void)fprintf(stderr, - " {%.*s}", (int)bi->ksize, bi->bytes); - break; - case P_RINTERNAL: - ri = GETRINTERNAL(h, cur); - (void)fprintf(stderr, "entries %03d pgno %03d", - ri->nrecs, ri->pgno); - break; - case P_BLEAF: - bl = GETBLEAF(h, cur); - if (bl->flags & P_BIGKEY) - (void)fprintf(stderr, - "big key page %lu size %u/", - *(pgno_t *)bl->bytes, - *(u_int32_t *)(bl->bytes + sizeof(pgno_t))); - else if (bl->ksize) - (void)fprintf(stderr, "%s/", bl->bytes); - if (bl->flags & P_BIGDATA) - (void)fprintf(stderr, - "big data page %lu size %u", - *(pgno_t *)(bl->bytes + bl->ksize), - *(u_int32_t *)(bl->bytes + bl->ksize + - sizeof(pgno_t))); - else if (bl->dsize) - (void)fprintf(stderr, "%.*s", - (int)bl->dsize, bl->bytes + bl->ksize); - break; - case P_RLEAF: - rl = GETRLEAF(h, cur); - if (rl->flags & P_BIGDATA) - (void)fprintf(stderr, - "big data page %lu size %u", - *(pgno_t *)rl->bytes, - *(u_int32_t *)(rl->bytes + sizeof(pgno_t))); - else if (rl->dsize) - (void)fprintf(stderr, - "%.*s", (int)rl->dsize, rl->bytes); - break; - } - (void)fprintf(stderr, "\n"); - } -} -#endif - -#ifdef STATISTICS -/* - * BT_STAT -- Gather/print the tree statistics - * - * Parameters: - * dbp: pointer to the DB - */ -void -__bt_stat(dbp) - DB *dbp; -{ - extern u_long bt_cache_hit, bt_cache_miss, bt_pfxsaved, bt_rootsplit; - extern u_long bt_sortsplit, bt_split; - BTREE *t; - PAGE *h; - pgno_t i, pcont, pinternal, pleaf; - u_long ifree, lfree, nkeys; - int levels; - - t = dbp->internal; - pcont = pinternal = pleaf = 0; - nkeys = ifree = lfree = 0; - for (i = P_ROOT; (h = mpool_get(t->bt_mp, i, 0)) != NULL; ++i) { - switch (h->flags & P_TYPE) { - case P_BINTERNAL: - case P_RINTERNAL: - ++pinternal; - ifree += h->upper - h->lower; - break; - case P_BLEAF: - case P_RLEAF: - ++pleaf; - lfree += h->upper - h->lower; - nkeys += NEXTINDEX(h); - break; - case P_OVERFLOW: - ++pcont; - break; - } - (void)mpool_put(t->bt_mp, h, 0); - } - - /* Count the levels of the tree. */ - for (i = P_ROOT, levels = 0 ;; ++levels) { - h = mpool_get(t->bt_mp, i, 0); - if (h->flags & (P_BLEAF|P_RLEAF)) { - if (levels == 0) - levels = 1; - (void)mpool_put(t->bt_mp, h, 0); - break; - } - i = F_ISSET(t, R_RECNO) ? - GETRINTERNAL(h, 0)->pgno : - GETBINTERNAL(h, 0)->pgno; - (void)mpool_put(t->bt_mp, h, 0); - } - - (void)fprintf(stderr, "%d level%s with %ld keys", - levels, levels == 1 ? "" : "s", nkeys); - if (F_ISSET(t, R_RECNO)) - (void)fprintf(stderr, " (%ld header count)", t->bt_nrecs); - (void)fprintf(stderr, - "\n%lu pages (leaf %ld, internal %ld, overflow %ld)\n", - pinternal + pleaf + pcont, pleaf, pinternal, pcont); - (void)fprintf(stderr, "%ld cache hits, %ld cache misses\n", - bt_cache_hit, bt_cache_miss); - (void)fprintf(stderr, "%ld splits (%ld root splits, %ld sort splits)\n", - bt_split, bt_rootsplit, bt_sortsplit); - pleaf *= t->bt_psize - BTDATAOFF; - if (pleaf) - (void)fprintf(stderr, - "%.0f%% leaf fill (%ld bytes used, %ld bytes free)\n", - ((double)(pleaf - lfree) / pleaf) * 100, - pleaf - lfree, lfree); - pinternal *= t->bt_psize - BTDATAOFF; - if (pinternal) - (void)fprintf(stderr, - "%.0f%% internal fill (%ld bytes used, %ld bytes free\n", - ((double)(pinternal - ifree) / pinternal) * 100, - pinternal - ifree, ifree); - if (bt_pfxsaved) - (void)fprintf(stderr, "prefix checking removed %lu bytes.\n", - bt_pfxsaved); -} -#endif diff --git a/db/btree/bt_delete.c b/db/btree/bt_delete.c deleted file mode 100644 index b654c9f..0000000 --- a/db/btree/bt_delete.c +++ /dev/null @@ -1,657 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * 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. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)bt_delete.c 8.13 (Berkeley) 7/28/94"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/types.h> - -#include <errno.h> -#include <stdio.h> -#include <string.h> - -#include <db.h> -#include "btree.h" - -static int __bt_bdelete __P((BTREE *, const DBT *)); -static int __bt_curdel __P((BTREE *, const DBT *, PAGE *, u_int)); -static int __bt_pdelete __P((BTREE *, PAGE *)); -static int __bt_relink __P((BTREE *, PAGE *)); -static int __bt_stkacq __P((BTREE *, PAGE **, CURSOR *)); - -/* - * __bt_delete - * Delete the item(s) referenced by a key. - * - * Return RET_SPECIAL if the key is not found. - */ -int -__bt_delete(dbp, key, flags) - const DB *dbp; - const DBT *key; - u_int flags; -{ - BTREE *t; - CURSOR *c; - PAGE *h; - int status; - - t = dbp->internal; - - /* Toss any page pinned across calls. */ - if (t->bt_pinned != NULL) { - mpool_put(t->bt_mp, t->bt_pinned, 0); - t->bt_pinned = NULL; - } - - /* Check for change to a read-only tree. */ - if (F_ISSET(t, B_RDONLY)) { - errno = EPERM; - return (RET_ERROR); - } - - switch (flags) { - case 0: - status = __bt_bdelete(t, key); - break; - case R_CURSOR: - /* - * If flags is R_CURSOR, delete the cursor. Must already - * have started a scan and not have already deleted it. - */ - c = &t->bt_cursor; - if (F_ISSET(c, CURS_INIT)) { - if (F_ISSET(c, CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE)) - return (RET_SPECIAL); - if ((h = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL) - return (RET_ERROR); - - /* - * If the page is about to be emptied, we'll need to - * delete it, which means we have to acquire a stack. - */ - if (NEXTINDEX(h) == 1) - if (__bt_stkacq(t, &h, &t->bt_cursor)) - return (RET_ERROR); - - status = __bt_dleaf(t, NULL, h, c->pg.index); - - if (NEXTINDEX(h) == 0 && status == RET_SUCCESS) { - if (__bt_pdelete(t, h)) - return (RET_ERROR); - } else - mpool_put(t->bt_mp, - h, status == RET_SUCCESS ? MPOOL_DIRTY : 0); - break; - } - /* FALLTHROUGH */ - default: - errno = EINVAL; - return (RET_ERROR); - } - if (status == RET_SUCCESS) - F_SET(t, B_MODIFIED); - return (status); -} - -/* - * __bt_stkacq -- - * Acquire a stack so we can delete a cursor entry. - * - * Parameters: - * t: tree - * hp: pointer to current, pinned PAGE pointer - * c: pointer to the cursor - * - * Returns: - * 0 on success, 1 on failure - */ -static int -__bt_stkacq(t, hp, c) - BTREE *t; - PAGE **hp; - CURSOR *c; -{ - BINTERNAL *bi; - EPG *e; - EPGNO *parent; - PAGE *h; - indx_t index; - pgno_t pgno; - recno_t nextpg, prevpg; - int exact, level; - - /* - * Find the first occurrence of the key in the tree. Toss the - * currently locked page so we don't hit an already-locked page. - */ - h = *hp; - mpool_put(t->bt_mp, h, 0); - if ((e = __bt_search(t, &c->key, &exact)) == NULL) - return (1); - h = e->page; - - /* See if we got it in one shot. */ - if (h->pgno == c->pg.pgno) - goto ret; - - /* - * Move right, looking for the page. At each move we have to move - * up the stack until we don't have to move to the next page. If - * we have to change pages at an internal level, we have to fix the - * stack back up. - */ - while (h->pgno != c->pg.pgno) { - if ((nextpg = h->nextpg) == P_INVALID) - break; - mpool_put(t->bt_mp, h, 0); - - /* Move up the stack. */ - for (level = 0; (parent = BT_POP(t)) != NULL; ++level) { - /* Get the parent page. */ - if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL) - return (1); - - /* Move to the next index. */ - if (parent->index != NEXTINDEX(h) - 1) { - index = parent->index + 1; - BT_PUSH(t, h->pgno, index); - break; - } - mpool_put(t->bt_mp, h, 0); - } - - /* Restore the stack. */ - while (level--) { - /* Push the next level down onto the stack. */ - bi = GETBINTERNAL(h, index); - pgno = bi->pgno; - BT_PUSH(t, pgno, 0); - - /* Lose the currently pinned page. */ - mpool_put(t->bt_mp, h, 0); - - /* Get the next level down. */ - if ((h = mpool_get(t->bt_mp, pgno, 0)) == NULL) - return (1); - index = 0; - } - mpool_put(t->bt_mp, h, 0); - if ((h = mpool_get(t->bt_mp, nextpg, 0)) == NULL) - return (1); - } - - if (h->pgno == c->pg.pgno) - goto ret; - - /* Reacquire the original stack. */ - mpool_put(t->bt_mp, h, 0); - if ((e = __bt_search(t, &c->key, &exact)) == NULL) - return (1); - h = e->page; - - /* - * Move left, looking for the page. At each move we have to move - * up the stack until we don't have to change pages to move to the - * next page. If we have to change pages at an internal level, we - * have to fix the stack back up. - */ - while (h->pgno != c->pg.pgno) { - if ((prevpg = h->prevpg) == P_INVALID) - break; - mpool_put(t->bt_mp, h, 0); - - /* Move up the stack. */ - for (level = 0; (parent = BT_POP(t)) != NULL; ++level) { - /* Get the parent page. */ - if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL) - return (1); - - /* Move to the next index. */ - if (parent->index != 0) { - index = parent->index - 1; - BT_PUSH(t, h->pgno, index); - break; - } - mpool_put(t->bt_mp, h, 0); - } - - /* Restore the stack. */ - while (level--) { - /* Push the next level down onto the stack. */ - bi = GETBINTERNAL(h, index); - pgno = bi->pgno; - - /* Lose the currently pinned page. */ - mpool_put(t->bt_mp, h, 0); - - /* Get the next level down. */ - if ((h = mpool_get(t->bt_mp, pgno, 0)) == NULL) - return (1); - - index = NEXTINDEX(h) - 1; - BT_PUSH(t, pgno, index); - } - mpool_put(t->bt_mp, h, 0); - if ((h = mpool_get(t->bt_mp, prevpg, 0)) == NULL) - return (1); - } - - -ret: mpool_put(t->bt_mp, h, 0); - return ((*hp = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL); -} - -/* - * __bt_bdelete -- - * Delete all key/data pairs matching the specified key. - * - * Parameters: - * t: tree - * key: key to delete - * - * Returns: - * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found. - */ -static int -__bt_bdelete(t, key) - BTREE *t; - const DBT *key; -{ - EPG *e; - PAGE *h; - int deleted, exact, redo; - - deleted = 0; - - /* Find any matching record; __bt_search pins the page. */ -loop: if ((e = __bt_search(t, key, &exact)) == NULL) - return (deleted ? RET_SUCCESS : RET_ERROR); - if (!exact) { - mpool_put(t->bt_mp, e->page, 0); - return (deleted ? RET_SUCCESS : RET_SPECIAL); - } - - /* - * Delete forward, then delete backward, from the found key. If - * there are duplicates and we reach either side of the page, do - * the key search again, so that we get them all. - */ - redo = 0; - h = e->page; - do { - if (__bt_dleaf(t, key, h, e->index)) { - mpool_put(t->bt_mp, h, 0); - return (RET_ERROR); - } - if (F_ISSET(t, B_NODUPS)) { - if (NEXTINDEX(h) == 0) { - if (__bt_pdelete(t, h)) - return (RET_ERROR); - } else - mpool_put(t->bt_mp, h, MPOOL_DIRTY); - return (RET_SUCCESS); - } - deleted = 1; - } while (e->index < NEXTINDEX(h) && __bt_cmp(t, key, e) == 0); - - /* Check for right-hand edge of the page. */ - if (e->index == NEXTINDEX(h)) - redo = 1; - - /* Delete from the key to the beginning of the page. */ - while (e->index-- > 0) { - if (__bt_cmp(t, key, e) != 0) - break; - if (__bt_dleaf(t, key, h, e->index) == RET_ERROR) { - mpool_put(t->bt_mp, h, 0); - return (RET_ERROR); - } - if (e->index == 0) - redo = 1; - } - - /* Check for an empty page. */ - if (NEXTINDEX(h) == 0) { - if (__bt_pdelete(t, h)) - return (RET_ERROR); - goto loop; - } - - /* Put the page. */ - mpool_put(t->bt_mp, h, MPOOL_DIRTY); - - if (redo) - goto loop; - return (RET_SUCCESS); -} - -/* - * __bt_pdelete -- - * Delete a single page from the tree. - * - * Parameters: - * t: tree - * h: leaf page - * - * Returns: - * RET_SUCCESS, RET_ERROR. - * - * Side-effects: - * mpool_put's the page - */ -static int -__bt_pdelete(t, h) - BTREE *t; - PAGE *h; -{ - BINTERNAL *bi; - PAGE *pg; - EPGNO *parent; - indx_t cnt, index, *ip, offset; - u_int32_t nksize; - char *from; - - /* - * Walk the parent page stack -- a LIFO stack of the pages that were - * traversed when we searched for the page where the delete occurred. - * Each stack entry is a page number and a page index offset. The - * offset is for the page traversed on the search. We've just deleted - * a page, so we have to delete the key from the parent page. - * - * If the delete from the parent page makes it empty, this process may - * continue all the way up the tree. We stop if we reach the root page - * (which is never deleted, it's just not worth the effort) or if the - * delete does not empty the page. - */ - while ((parent = BT_POP(t)) != NULL) { - /* Get the parent page. */ - if ((pg = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL) - return (RET_ERROR); - - index = parent->index; - bi = GETBINTERNAL(pg, index); - - /* Free any overflow pages. */ - if (bi->flags & P_BIGKEY && - __ovfl_delete(t, bi->bytes) == RET_ERROR) { - mpool_put(t->bt_mp, pg, 0); - return (RET_ERROR); - } - - /* - * Free the parent if it has only the one key and it's not the - * root page. If it's the rootpage, turn it back into an empty - * leaf page. - */ - if (NEXTINDEX(pg) == 1) { - if (pg->pgno == P_ROOT) { - pg->lower = BTDATAOFF; - pg->upper = t->bt_psize; - pg->flags = P_BLEAF; - } else { - if (__bt_relink(t, pg) || __bt_free(t, pg)) - return (RET_ERROR); - continue; - } - } else { - /* Pack remaining key items at the end of the page. */ - nksize = NBINTERNAL(bi->ksize); - from = (char *)pg + pg->upper; - memmove(from + nksize, from, (char *)bi - from); - pg->upper += nksize; - - /* Adjust indices' offsets, shift the indices down. */ - offset = pg->linp[index]; - for (cnt = index, ip = &pg->linp[0]; cnt--; ++ip) - if (ip[0] < offset) - ip[0] += nksize; - for (cnt = NEXTINDEX(pg) - index; --cnt; ++ip) - ip[0] = ip[1] < offset ? ip[1] + nksize : ip[1]; - pg->lower -= sizeof(indx_t); - } - - mpool_put(t->bt_mp, pg, MPOOL_DIRTY); - break; - } - - /* Free the leaf page, as long as it wasn't the root. */ - if (h->pgno == P_ROOT) { - mpool_put(t->bt_mp, h, MPOOL_DIRTY); - return (RET_SUCCESS); - } - return (__bt_relink(t, h) || __bt_free(t, h)); -} - -/* - * __bt_dleaf -- - * Delete a single record from a leaf page. - * - * Parameters: - * t: tree - * key: referenced key - * h: page - * index: index on page to delete - * - * Returns: - * RET_SUCCESS, RET_ERROR. - */ -int -__bt_dleaf(t, key, h, index) - BTREE *t; - const DBT *key; - PAGE *h; - u_int index; -{ - BLEAF *bl; - indx_t cnt, *ip, offset; - u_int32_t nbytes; - void *to; - char *from; - - /* If this record is referenced by the cursor, delete the cursor. */ - if (F_ISSET(&t->bt_cursor, CURS_INIT) && - !F_ISSET(&t->bt_cursor, CURS_ACQUIRE) && - t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index == index && - __bt_curdel(t, key, h, index)) - return (RET_ERROR); - - /* If the entry uses overflow pages, make them available for reuse. */ - to = bl = GETBLEAF(h, index); - if (bl->flags & P_BIGKEY && __ovfl_delete(t, bl->bytes) == RET_ERROR) - return (RET_ERROR); - if (bl->flags & P_BIGDATA && - __ovfl_delete(t, bl->bytes + bl->ksize) == RET_ERROR) - return (RET_ERROR); - - /* Pack the remaining key/data items at the end of the page. */ - nbytes = NBLEAF(bl); - from = (char *)h + h->upper; - memmove(from + nbytes, from, (char *)to - from); - h->upper += nbytes; - - /* Adjust the indices' offsets, shift the indices down. */ - offset = h->linp[index]; - for (cnt = index, ip = &h->linp[0]; cnt--; ++ip) - if (ip[0] < offset) - ip[0] += nbytes; - for (cnt = NEXTINDEX(h) - index; --cnt; ++ip) - ip[0] = ip[1] < offset ? ip[1] + nbytes : ip[1]; - h->lower -= sizeof(indx_t); - - /* If the cursor is on this page, adjust it as necessary. */ - if (F_ISSET(&t->bt_cursor, CURS_INIT) && - !F_ISSET(&t->bt_cursor, CURS_ACQUIRE) && - t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index > index) - --t->bt_cursor.pg.index; - - return (RET_SUCCESS); -} - -/* - * __bt_curdel -- - * Delete the cursor. - * - * Parameters: - * t: tree - * key: referenced key (or NULL) - * h: page - * index: index on page to delete - * - * Returns: - * RET_SUCCESS, RET_ERROR. - */ -static int -__bt_curdel(t, key, h, index) - BTREE *t; - const DBT *key; - PAGE *h; - u_int index; -{ - CURSOR *c; - EPG e; - PAGE *pg; - int curcopy, status; - - /* - * If there are duplicates, move forward or backward to one. - * Otherwise, copy the key into the cursor area. - */ - c = &t->bt_cursor; - F_CLR(c, CURS_AFTER | CURS_BEFORE | CURS_ACQUIRE); - - curcopy = 0; - if (!F_ISSET(t, B_NODUPS)) { - /* - * We're going to have to do comparisons. If we weren't - * provided a copy of the key, i.e. the user is deleting - * the current cursor position, get one. - */ - if (key == NULL) { - e.page = h; - e.index = index; - if ((status = __bt_ret(t, &e, - &c->key, &c->key, NULL, NULL, 1)) != RET_SUCCESS) - return (status); - curcopy = 1; - key = &c->key; - } - /* Check previous key, if not at the beginning of the page. */ - if (index > 0) { - e.page = h; - e.index = index - 1; - if (__bt_cmp(t, key, &e) == 0) { - F_SET(c, CURS_BEFORE); - goto dup2; - } - } - /* Check next key, if not at the end of the page. */ - if (index < NEXTINDEX(h) - 1) { - e.page = h; - e.index = index + 1; - if (__bt_cmp(t, key, &e) == 0) { - F_SET(c, CURS_AFTER); - goto dup2; - } - } - /* Check previous key if at the beginning of the page. */ - if (index == 0 && h->prevpg != P_INVALID) { - if ((pg = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL) - return (RET_ERROR); - e.page = pg; - e.index = NEXTINDEX(pg) - 1; - if (__bt_cmp(t, key, &e) == 0) { - F_SET(c, CURS_BEFORE); - goto dup1; - } - mpool_put(t->bt_mp, pg, 0); - } - /* Check next key if at the end of the page. */ - if (index == NEXTINDEX(h) - 1 && h->nextpg != P_INVALID) { - if ((pg = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL) - return (RET_ERROR); - e.page = pg; - e.index = 0; - if (__bt_cmp(t, key, &e) == 0) { - F_SET(c, CURS_AFTER); -dup1: mpool_put(t->bt_mp, pg, 0); -dup2: c->pg.pgno = e.page->pgno; - c->pg.index = e.index; - return (RET_SUCCESS); - } - mpool_put(t->bt_mp, pg, 0); - } - } - e.page = h; - e.index = index; - if (curcopy || (status = - __bt_ret(t, &e, &c->key, &c->key, NULL, NULL, 1)) == RET_SUCCESS) { - F_SET(c, CURS_ACQUIRE); - return (RET_SUCCESS); - } - return (status); -} - -/* - * __bt_relink -- - * Link around a deleted page. - * - * Parameters: - * t: tree - * h: page to be deleted - */ -static int -__bt_relink(t, h) - BTREE *t; - PAGE *h; -{ - PAGE *pg; - - if (h->nextpg != P_INVALID) { - if ((pg = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL) - return (RET_ERROR); - pg->prevpg = h->prevpg; - mpool_put(t->bt_mp, pg, MPOOL_DIRTY); - } - if (h->prevpg != P_INVALID) { - if ((pg = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL) - return (RET_ERROR); - pg->nextpg = h->nextpg; - mpool_put(t->bt_mp, pg, MPOOL_DIRTY); - } - return (0); -} diff --git a/db/btree/bt_get.c b/db/btree/bt_get.c deleted file mode 100644 index 74824c7..0000000 --- a/db/btree/bt_get.c +++ /dev/null @@ -1,105 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * 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. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)bt_get.c 8.6 (Berkeley) 7/20/94"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/types.h> - -#include <errno.h> -#include <stddef.h> -#include <stdio.h> - -#include <db.h> -#include "btree.h" - -/* - * __BT_GET -- Get a record from the btree. - * - * Parameters: - * dbp: pointer to access method - * key: key to find - * data: data to return - * flag: currently unused - * - * Returns: - * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found. - */ -int -__bt_get(dbp, key, data, flags) - const DB *dbp; - const DBT *key; - DBT *data; - u_int flags; -{ - BTREE *t; - EPG *e; - int exact, status; - - t = dbp->internal; - - /* Toss any page pinned across calls. */ - if (t->bt_pinned != NULL) { - mpool_put(t->bt_mp, t->bt_pinned, 0); - t->bt_pinned = NULL; - } - - /* Get currently doesn't take any flags. */ - if (flags) { - errno = EINVAL; - return (RET_ERROR); - } - - if ((e = __bt_search(t, key, &exact)) == NULL) - return (RET_ERROR); - if (!exact) { - mpool_put(t->bt_mp, e->page, 0); - return (RET_SPECIAL); - } - - status = __bt_ret(t, e, NULL, NULL, data, &t->bt_rdata, 0); - - /* - * If the user is doing concurrent access, we copied the - * key/data, toss the page. - */ - if (F_ISSET(t, B_DB_LOCK)) - mpool_put(t->bt_mp, e->page, 0); - else - t->bt_pinned = e->page; - return (status); -} diff --git a/db/btree/bt_open.c b/db/btree/bt_open.c deleted file mode 100644 index 8c2f48e..0000000 --- a/db/btree/bt_open.c +++ /dev/null @@ -1,458 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * 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. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)bt_open.c 8.10 (Berkeley) 8/17/94"; -#endif /* LIBC_SCCS and not lint */ - -/* - * Implementation of btree access method for 4.4BSD. - * - * The design here was originally based on that of the btree access method - * used in the Postgres database system at UC Berkeley. This implementation - * is wholly independent of the Postgres code. - */ - -#include <sys/param.h> -#include <sys/stat.h> - -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include <db.h> -#include "btree.h" - -#ifdef DEBUG -#undef MINPSIZE -#define MINPSIZE 128 -#endif - -static int byteorder __P((void)); -static int nroot __P((BTREE *)); -static int tmp __P((void)); - -/* - * __BT_OPEN -- Open a btree. - * - * Creates and fills a DB struct, and calls the routine that actually - * opens the btree. - * - * Parameters: - * fname: filename (NULL for in-memory trees) - * flags: open flag bits - * mode: open permission bits - * b: BTREEINFO pointer - * - * Returns: - * NULL on failure, pointer to DB on success. - * - */ -DB * -__bt_open(fname, flags, mode, openinfo, dflags) - const char *fname; - int flags, mode, dflags; - const BTREEINFO *openinfo; -{ - struct stat sb; - BTMETA m; - BTREE *t; - BTREEINFO b; - DB *dbp; - pgno_t ncache; - ssize_t nr; - int machine_lorder; - - t = NULL; - - /* - * Intention is to make sure all of the user's selections are okay - * here and then use them without checking. Can't be complete, since - * we don't know the right page size, lorder or flags until the backing - * file is opened. Also, the file's page size can cause the cachesize - * to change. - */ - machine_lorder = byteorder(); - if (openinfo) { - b = *openinfo; - - /* Flags: R_DUP. */ - if (b.flags & ~(R_DUP)) - goto einval; - - /* - * Page size must be indx_t aligned and >= MINPSIZE. Default - * page size is set farther on, based on the underlying file - * transfer size. - */ - if (b.psize && - (b.psize < MINPSIZE || b.psize > MAX_PAGE_OFFSET + 1 || - b.psize & (sizeof(indx_t) - 1))) - goto einval; - - /* Minimum number of keys per page; absolute minimum is 2. */ - if (b.minkeypage) { - if (b.minkeypage < 2) - goto einval; - } else - b.minkeypage = DEFMINKEYPAGE; - - /* If no comparison, use default comparison and prefix. */ - if (b.compare == NULL) { - b.compare = __bt_defcmp; - if (b.prefix == NULL) - b.prefix = __bt_defpfx; - } - - if (b.lorder == 0) - b.lorder = machine_lorder; - } else { - b.compare = __bt_defcmp; - b.cachesize = 0; - b.flags = 0; - b.lorder = machine_lorder; - b.minkeypage = DEFMINKEYPAGE; - b.prefix = __bt_defpfx; - b.psize = 0; - } - - /* Check for the ubiquitous PDP-11. */ - if (b.lorder != BIG_ENDIAN && b.lorder != LITTLE_ENDIAN) - goto einval; - - /* Allocate and initialize DB and BTREE structures. */ - if ((t = (BTREE *)malloc(sizeof(BTREE))) == NULL) - goto err; - memset(t, 0, sizeof(BTREE)); - t->bt_fd = -1; /* Don't close unopened fd on error. */ - t->bt_lorder = b.lorder; - t->bt_order = NOT; - t->bt_cmp = b.compare; - t->bt_pfx = b.prefix; - t->bt_rfd = -1; - - if ((t->bt_dbp = dbp = (DB *)malloc(sizeof(DB))) == NULL) - goto err; - memset(t->bt_dbp, 0, sizeof(DB)); - if (t->bt_lorder != machine_lorder) - F_SET(t, B_NEEDSWAP); - - dbp->type = DB_BTREE; - dbp->internal = t; - dbp->close = __bt_close; - dbp->del = __bt_delete; - dbp->fd = __bt_fd; - dbp->get = __bt_get; - dbp->put = __bt_put; - dbp->seq = __bt_seq; - dbp->sync = __bt_sync; - - /* - * If no file name was supplied, this is an in-memory btree and we - * open a backing temporary file. Otherwise, it's a disk-based tree. - */ - if (fname) { - switch (flags & O_ACCMODE) { - case O_RDONLY: - F_SET(t, B_RDONLY); - break; - case O_RDWR: - break; - case O_WRONLY: - default: - goto einval; - } - - if ((t->bt_fd = open(fname, flags, mode)) < 0) - goto err; - - } else { - if ((flags & O_ACCMODE) != O_RDWR) - goto einval; - if ((t->bt_fd = tmp()) == -1) - goto err; - F_SET(t, B_INMEM); - } - - if (fcntl(t->bt_fd, F_SETFD, 1) == -1) - goto err; - - if (fstat(t->bt_fd, &sb)) - goto err; - if (sb.st_size) { - if ((nr = read(t->bt_fd, &m, sizeof(BTMETA))) < 0) - goto err; - if (nr != sizeof(BTMETA)) - goto eftype; - - /* - * Read in the meta-data. This can change the notion of what - * the lorder, page size and flags are, and, when the page size - * changes, the cachesize value can change too. If the user - * specified the wrong byte order for an existing database, we - * don't bother to return an error, we just clear the NEEDSWAP - * bit. - */ - if (m.magic == BTREEMAGIC) - F_CLR(t, B_NEEDSWAP); - else { - F_SET(t, B_NEEDSWAP); - M_32_SWAP(m.magic); - M_32_SWAP(m.version); - M_32_SWAP(m.psize); - M_32_SWAP(m.free); - M_32_SWAP(m.nrecs); - M_32_SWAP(m.flags); - } - if (m.magic != BTREEMAGIC || m.version != BTREEVERSION) - goto eftype; - if (m.psize < MINPSIZE || m.psize > MAX_PAGE_OFFSET + 1 || - m.psize & (sizeof(indx_t) - 1)) - goto eftype; - if (m.flags & ~SAVEMETA) - goto eftype; - b.psize = m.psize; - F_SET(t, m.flags); - t->bt_free = m.free; - t->bt_nrecs = m.nrecs; - } else { - /* - * Set the page size to the best value for I/O to this file. - * Don't overflow the page offset type. - */ - if (b.psize == 0) { -#ifdef _STATBUF_ST_BLKSIZE - b.psize = sb.st_blksize; -#endif - if (b.psize < MINPSIZE) - b.psize = MINPSIZE; - if (b.psize > MAX_PAGE_OFFSET + 1) - b.psize = MAX_PAGE_OFFSET + 1; - } - - /* Set flag if duplicates permitted. */ - if (!(b.flags & R_DUP)) - F_SET(t, B_NODUPS); - - t->bt_free = P_INVALID; - t->bt_nrecs = 0; - F_SET(t, B_METADIRTY); - } - - t->bt_psize = b.psize; - - /* Set the cache size; must be a multiple of the page size. */ - if (b.cachesize && b.cachesize & (b.psize - 1)) - b.cachesize += (~b.cachesize & (b.psize - 1)) + 1; - if (b.cachesize < b.psize * MINCACHE) - b.cachesize = b.psize * MINCACHE; - - /* Calculate number of pages to cache. */ - ncache = (b.cachesize + t->bt_psize - 1) / t->bt_psize; - - /* - * The btree data structure requires that at least two keys can fit on - * a page, but other than that there's no fixed requirement. The user - * specified a minimum number per page, and we translated that into the - * number of bytes a key/data pair can use before being placed on an - * overflow page. This calculation includes the page header, the size - * of the index referencing the leaf item and the size of the leaf item - * structure. Also, don't let the user specify a minkeypage such that - * a key/data pair won't fit even if both key and data are on overflow - * pages. - */ - t->bt_ovflsize = (t->bt_psize - BTDATAOFF) / b.minkeypage - - (sizeof(indx_t) + NBLEAFDBT(0, 0)); - if (t->bt_ovflsize < NBLEAFDBT(NOVFLSIZE, NOVFLSIZE) + sizeof(indx_t)) - t->bt_ovflsize = - NBLEAFDBT(NOVFLSIZE, NOVFLSIZE) + sizeof(indx_t); - - /* Initialize the buffer pool. */ - if ((t->bt_mp = - mpool_open(NULL, t->bt_fd, t->bt_psize, ncache)) == NULL) - goto err; - if (!F_ISSET(t, B_INMEM)) - mpool_filter(t->bt_mp, __bt_pgin, __bt_pgout, t); - - /* Create a root page if new tree. */ - if (nroot(t) == RET_ERROR) - goto err; - - /* Global flags. */ - if (dflags & DB_LOCK) - F_SET(t, B_DB_LOCK); - if (dflags & DB_SHMEM) - F_SET(t, B_DB_SHMEM); - if (dflags & DB_TXN) - F_SET(t, B_DB_TXN); - - return (dbp); - -einval: errno = EINVAL; - goto err; - -eftype: errno = EFTYPE; - goto err; - -err: if (t) { - if (t->bt_dbp) - free(t->bt_dbp); - if (t->bt_fd != -1) - (void)close(t->bt_fd); - free(t); - } - return (NULL); -} - -/* - * NROOT -- Create the root of a new tree. - * - * Parameters: - * t: tree - * - * Returns: - * RET_ERROR, RET_SUCCESS - */ -static int -nroot(t) - BTREE *t; -{ - PAGE *meta, *root; - pgno_t npg; - - if ((meta = mpool_get(t->bt_mp, 0, 0)) != NULL) { - mpool_put(t->bt_mp, meta, 0); - return (RET_SUCCESS); - } - if (errno != EINVAL) /* It's OK to not exist. */ - return (RET_ERROR); - errno = 0; - - if ((meta = mpool_new(t->bt_mp, &npg)) == NULL) - return (RET_ERROR); - - if ((root = mpool_new(t->bt_mp, &npg)) == NULL) - return (RET_ERROR); - - if (npg != P_ROOT) - return (RET_ERROR); - root->pgno = npg; - root->prevpg = root->nextpg = P_INVALID; - root->lower = BTDATAOFF; - root->upper = t->bt_psize; - root->flags = P_BLEAF; - memset(meta, 0, t->bt_psize); - mpool_put(t->bt_mp, meta, MPOOL_DIRTY); - mpool_put(t->bt_mp, root, MPOOL_DIRTY); - return (RET_SUCCESS); -} - -static int -tmp() -{ - sigset_t set, oset; - int fd; - const char *envtmp; - char *path; - static const char fmt[] = "%s/bt.XXXXXX"; - size_t n; - - envtmp = getenv("TMPDIR"); - if (!envtmp) - envtmp = "/tmp"; - n = strlen (envtmp) + sizeof fmt; -#ifdef __GNUC__ - path = __builtin_alloca(n); -#else - path = malloc(n); -#endif - (void)snprintf(path, n, fmt, envtmp ? envtmp : "/tmp"); - - (void)sigfillset(&set); - (void)sigprocmask(SIG_BLOCK, &set, &oset); - if ((fd = mkstemp(path)) != -1) - (void)unlink(path); - (void)sigprocmask(SIG_SETMASK, &oset, NULL); -#ifndef __GNUC__ - free(path); -#endif - return(fd); -} - -static int -byteorder() -{ - u_int32_t x; - u_char *p; - - x = 0x01020304; - p = (u_char *)&x; - switch (*p) { - case 1: - return (BIG_ENDIAN); - case 4: - return (LITTLE_ENDIAN); - default: - return (0); - } -} - -int -__bt_fd(dbp) - const DB *dbp; -{ - BTREE *t; - - t = dbp->internal; - - /* Toss any page pinned across calls. */ - if (t->bt_pinned != NULL) { - mpool_put(t->bt_mp, t->bt_pinned, 0); - t->bt_pinned = NULL; - } - - /* In-memory database can't have a file descriptor. */ - if (F_ISSET(t, B_INMEM)) { - errno = ENOENT; - return (-1); - } - return (t->bt_fd); -} diff --git a/db/btree/bt_overflow.c b/db/btree/bt_overflow.c deleted file mode 100644 index b28b8e0..0000000 --- a/db/btree/bt_overflow.c +++ /dev/null @@ -1,228 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * 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. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)bt_overflow.c 8.5 (Berkeley) 7/16/94"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/param.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <db.h> -#include "btree.h" - -/* - * Big key/data code. - * - * Big key and data entries are stored on linked lists of pages. The initial - * reference is byte string stored with the key or data and is the page number - * and size. The actual record is stored in a chain of pages linked by the - * nextpg field of the PAGE header. - * - * The first page of the chain has a special property. If the record is used - * by an internal page, it cannot be deleted and the P_PRESERVE bit will be set - * in the header. - * - * XXX - * A single DBT is written to each chain, so a lot of space on the last page - * is wasted. This is a fairly major bug for some data sets. - */ - -/* - * __OVFL_GET -- Get an overflow key/data item. - * - * Parameters: - * t: tree - * p: pointer to { pgno_t, u_int32_t } - * buf: storage address - * bufsz: storage size - * - * Returns: - * RET_ERROR, RET_SUCCESS - */ -int -__ovfl_get(t, p, ssz, buf, bufsz) - BTREE *t; - void *p; - size_t *ssz; - void **buf; - size_t *bufsz; -{ - PAGE *h; - pgno_t pg; - size_t nb, plen; - u_int32_t sz; - - memmove(&pg, p, sizeof(pgno_t)); - memmove(&sz, (char *)p + sizeof(pgno_t), sizeof(u_int32_t)); - *ssz = sz; - -#ifdef DEBUG - if (pg == P_INVALID || sz == 0) - abort(); -#endif - /* Make the buffer bigger as necessary. */ - if (*bufsz < sz) { - *buf = (char *)(*buf == NULL ? malloc(sz) : realloc(*buf, sz)); - if (*buf == NULL) - return (RET_ERROR); - *bufsz = sz; - } - - /* - * Step through the linked list of pages, copying the data on each one - * into the buffer. Never copy more than the data's length. - */ - plen = t->bt_psize - BTDATAOFF; - for (p = *buf;; p = (char *)p + nb, pg = h->nextpg) { - if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) - return (RET_ERROR); - - nb = MIN(sz, plen); - memmove(p, (char *)h + BTDATAOFF, nb); - mpool_put(t->bt_mp, h, 0); - - if ((sz -= nb) == 0) - break; - } - return (RET_SUCCESS); -} - -/* - * __OVFL_PUT -- Store an overflow key/data item. - * - * Parameters: - * t: tree - * data: DBT to store - * pgno: storage page number - * - * Returns: - * RET_ERROR, RET_SUCCESS - */ -int -__ovfl_put(t, dbt, pg) - BTREE *t; - const DBT *dbt; - pgno_t *pg; -{ - PAGE *h, *last; - void *p; - pgno_t npg; - size_t nb, plen; - u_int32_t sz; - - /* - * Allocate pages and copy the key/data record into them. Store the - * number of the first page in the chain. - */ - plen = t->bt_psize - BTDATAOFF; - for (last = NULL, p = dbt->data, sz = dbt->size;; - p = (char *)p + plen, last = h) { - if ((h = __bt_new(t, &npg)) == NULL) - return (RET_ERROR); - - h->pgno = npg; - h->nextpg = h->prevpg = P_INVALID; - h->flags = P_OVERFLOW; - h->lower = h->upper = 0; - - nb = MIN(sz, plen); - memmove((char *)h + BTDATAOFF, p, nb); - - if (last) { - last->nextpg = h->pgno; - mpool_put(t->bt_mp, last, MPOOL_DIRTY); - } else - *pg = h->pgno; - - if ((sz -= nb) == 0) { - mpool_put(t->bt_mp, h, MPOOL_DIRTY); - break; - } - } - return (RET_SUCCESS); -} - -/* - * __OVFL_DELETE -- Delete an overflow chain. - * - * Parameters: - * t: tree - * p: pointer to { pgno_t, u_int32_t } - * - * Returns: - * RET_ERROR, RET_SUCCESS - */ -int -__ovfl_delete(t, p) - BTREE *t; - void *p; -{ - PAGE *h; - pgno_t pg; - size_t plen; - u_int32_t sz; - - memmove(&pg, p, sizeof(pgno_t)); - memmove(&sz, (char *)p + sizeof(pgno_t), sizeof(u_int32_t)); - -#ifdef DEBUG - if (pg == P_INVALID || sz == 0) - abort(); -#endif - if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) - return (RET_ERROR); - - /* Don't delete chains used by internal pages. */ - if (h->flags & P_PRESERVE) { - mpool_put(t->bt_mp, h, 0); - return (RET_SUCCESS); - } - - /* Step through the chain, calling the free routine for each page. */ - for (plen = t->bt_psize - BTDATAOFF;; sz -= plen) { - pg = h->nextpg; - __bt_free(t, h); - if (sz <= plen) - break; - if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) - return (RET_ERROR); - } - return (RET_SUCCESS); -} diff --git a/db/btree/bt_page.c b/db/btree/bt_page.c deleted file mode 100644 index ce9cbf1..0000000 --- a/db/btree/bt_page.c +++ /dev/null @@ -1,100 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. 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. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)bt_page.c 8.3 (Berkeley) 7/14/94"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/types.h> - -#include <stdio.h> - -#include <db.h> -#include "btree.h" - -/* - * __bt_free -- - * Put a page on the freelist. - * - * Parameters: - * t: tree - * h: page to free - * - * Returns: - * RET_ERROR, RET_SUCCESS - * - * Side-effect: - * mpool_put's the page. - */ -int -__bt_free(t, h) - BTREE *t; - PAGE *h; -{ - /* Insert the page at the head of the free list. */ - h->prevpg = P_INVALID; - h->nextpg = t->bt_free; - t->bt_free = h->pgno; - F_SET(t, B_METADIRTY); - - /* Make sure the page gets written back. */ - return (mpool_put(t->bt_mp, h, MPOOL_DIRTY)); -} - -/* - * __bt_new -- - * Get a new page, preferably from the freelist. - * - * Parameters: - * t: tree - * npg: storage for page number. - * - * Returns: - * Pointer to a page, NULL on error. - */ -PAGE * -__bt_new(t, npg) - BTREE *t; - pgno_t *npg; -{ - PAGE *h; - - if (t->bt_free != P_INVALID && - (h = mpool_get(t->bt_mp, t->bt_free, 0)) != NULL) { - *npg = t->bt_free; - t->bt_free = h->nextpg; - F_SET(t, B_METADIRTY); - return (h); - } - return (mpool_new(t->bt_mp, npg)); -} diff --git a/db/btree/bt_put.c b/db/btree/bt_put.c deleted file mode 100644 index 15309c6..0000000 --- a/db/btree/bt_put.c +++ /dev/null @@ -1,321 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * 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. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)bt_put.c 8.8 (Berkeley) 7/26/94"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/types.h> - -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <db.h> -#include "btree.h" - -static EPG *bt_fast __P((BTREE *, const DBT *, const DBT *, int *)); - -/* - * __BT_PUT -- Add a btree item to the tree. - * - * Parameters: - * dbp: pointer to access method - * key: key - * data: data - * flag: R_NOOVERWRITE - * - * Returns: - * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key is already in the - * tree and R_NOOVERWRITE specified. - */ -int -__bt_put(dbp, key, data, flags) - const DB *dbp; - DBT *key; - const DBT *data; - u_int flags; -{ - BTREE *t; - DBT tkey, tdata; - EPG *e; - PAGE *h; - indx_t index, nxtindex; - pgno_t pg; - u_int32_t nbytes; - int dflags, exact, status; - char *dest, db[NOVFLSIZE], kb[NOVFLSIZE]; - - t = dbp->internal; - - /* Toss any page pinned across calls. */ - if (t->bt_pinned != NULL) { - mpool_put(t->bt_mp, t->bt_pinned, 0); - t->bt_pinned = NULL; - } - - /* Check for change to a read-only tree. */ - if (F_ISSET(t, B_RDONLY)) { - errno = EPERM; - return (RET_ERROR); - } - - switch (flags) { - case 0: - case R_NOOVERWRITE: - break; - case R_CURSOR: - /* - * If flags is R_CURSOR, put the cursor. Must already - * have started a scan and not have already deleted it. - */ - if (F_ISSET(&t->bt_cursor, CURS_INIT) && - !F_ISSET(&t->bt_cursor, - CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE)) - break; - /* FALLTHROUGH */ - default: - errno = EINVAL; - return (RET_ERROR); - } - - /* - * If the key/data pair won't fit on a page, store it on overflow - * pages. Only put the key on the overflow page if the pair are - * still too big after moving the data to an overflow page. - * - * XXX - * If the insert fails later on, the overflow pages aren't recovered. - */ - dflags = 0; - if (key->size + data->size > t->bt_ovflsize) { - if (key->size > t->bt_ovflsize) { -storekey: if (__ovfl_put(t, key, &pg) == RET_ERROR) - return (RET_ERROR); - tkey.data = kb; - tkey.size = NOVFLSIZE; - memmove(kb, &pg, sizeof(pgno_t)); - memmove(kb + sizeof(pgno_t), - &key->size, sizeof(u_int32_t)); - dflags |= P_BIGKEY; - key = &tkey; - } - if (key->size + data->size > t->bt_ovflsize) { - if (__ovfl_put(t, data, &pg) == RET_ERROR) - return (RET_ERROR); - tdata.data = db; - tdata.size = NOVFLSIZE; - memmove(db, &pg, sizeof(pgno_t)); - memmove(db + sizeof(pgno_t), - &data->size, sizeof(u_int32_t)); - dflags |= P_BIGDATA; - data = &tdata; - } - if (key->size + data->size > t->bt_ovflsize) - goto storekey; - } - - /* Replace the cursor. */ - if (flags == R_CURSOR) { - if ((h = mpool_get(t->bt_mp, t->bt_cursor.pg.pgno, 0)) == NULL) - return (RET_ERROR); - index = t->bt_cursor.pg.index; - goto delete; - } - - /* - * Find the key to delete, or, the location at which to insert. - * Bt_fast and __bt_search both pin the returned page. - */ - if (t->bt_order == NOT || (e = bt_fast(t, key, data, &exact)) == NULL) - if ((e = __bt_search(t, key, &exact)) == NULL) - return (RET_ERROR); - h = e->page; - index = e->index; - - /* - * Add the key/data pair to the tree. If an identical key is already - * in the tree, and R_NOOVERWRITE is set, an error is returned. If - * R_NOOVERWRITE is not set, the key is either added (if duplicates are - * permitted) or an error is returned. - */ - switch (flags) { - case R_NOOVERWRITE: - if (!exact) - break; - mpool_put(t->bt_mp, h, 0); - return (RET_SPECIAL); - default: - if (!exact || !F_ISSET(t, B_NODUPS)) - break; - /* - * !!! - * Note, the delete may empty the page, so we need to put a - * new entry into the page immediately. - */ -delete: if (__bt_dleaf(t, key, h, index) == RET_ERROR) { - mpool_put(t->bt_mp, h, 0); - return (RET_ERROR); - } - break; - } - - /* - * If not enough room, or the user has put a ceiling on the number of - * keys permitted in the page, split the page. The split code will - * insert the key and data and unpin the current page. If inserting - * into the offset array, shift the pointers up. - */ - nbytes = NBLEAFDBT(key->size, data->size); - if ((u_int32_t) (h->upper - h->lower) < nbytes + sizeof(indx_t)) { - if ((status = __bt_split(t, h, key, - data, dflags, nbytes, index)) != RET_SUCCESS) - return (status); - goto success; - } - - if (index < (nxtindex = NEXTINDEX(h))) - memmove(h->linp + index + 1, h->linp + index, - (nxtindex - index) * sizeof(indx_t)); - h->lower += sizeof(indx_t); - - h->linp[index] = h->upper -= nbytes; - dest = (char *)h + h->upper; - WR_BLEAF(dest, key, data, dflags); - - /* If the cursor is on this page, adjust it as necessary. */ - if (F_ISSET(&t->bt_cursor, CURS_INIT) && - !F_ISSET(&t->bt_cursor, CURS_ACQUIRE) && - t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index >= index) - ++t->bt_cursor.pg.index; - - if (t->bt_order == NOT) { - if (h->nextpg == P_INVALID) { - if (index == NEXTINDEX(h) - 1) { - t->bt_order = FORWARD; - t->bt_last.index = index; - t->bt_last.pgno = h->pgno; - } - } else if (h->prevpg == P_INVALID) { - if (index == 0) { - t->bt_order = BACK; - t->bt_last.index = 0; - t->bt_last.pgno = h->pgno; - } - } - } - - mpool_put(t->bt_mp, h, MPOOL_DIRTY); - -success: - if (flags == R_SETCURSOR) - __bt_setcur(t, e->page->pgno, e->index); - - F_SET(t, B_MODIFIED); - return (RET_SUCCESS); -} - -#ifdef STATISTICS -u_long bt_cache_hit, bt_cache_miss; -#endif - -/* - * BT_FAST -- Do a quick check for sorted data. - * - * Parameters: - * t: tree - * key: key to insert - * - * Returns: - * EPG for new record or NULL if not found. - */ -static EPG * -bt_fast(t, key, data, exactp) - BTREE *t; - const DBT *key, *data; - int *exactp; -{ - PAGE *h; - u_int32_t nbytes; - int cmp; - - if ((h = mpool_get(t->bt_mp, t->bt_last.pgno, 0)) == NULL) { - t->bt_order = NOT; - return (NULL); - } - t->bt_cur.page = h; - t->bt_cur.index = t->bt_last.index; - - /* - * If won't fit in this page or have too many keys in this page, - * have to search to get split stack. - */ - nbytes = NBLEAFDBT(key->size, data->size); - if ((u_int32_t) (h->upper - h->lower) < nbytes + sizeof(indx_t)) - goto miss; - - if (t->bt_order == FORWARD) { - if (t->bt_cur.page->nextpg != P_INVALID) - goto miss; - if (t->bt_cur.index != NEXTINDEX(h) - 1) - goto miss; - if ((cmp = __bt_cmp(t, key, &t->bt_cur)) < 0) - goto miss; - t->bt_last.index = cmp ? ++t->bt_cur.index : t->bt_cur.index; - } else { - if (t->bt_cur.page->prevpg != P_INVALID) - goto miss; - if (t->bt_cur.index != 0) - goto miss; - if ((cmp = __bt_cmp(t, key, &t->bt_cur)) > 0) - goto miss; - t->bt_last.index = 0; - } - *exactp = cmp == 0; -#ifdef STATISTICS - ++bt_cache_hit; -#endif - return (&t->bt_cur); - -miss: -#ifdef STATISTICS - ++bt_cache_miss; -#endif - t->bt_order = NOT; - mpool_put(t->bt_mp, h, 0); - return (NULL); -} diff --git a/db/btree/bt_search.c b/db/btree/bt_search.c deleted file mode 100644 index 485afcb..0000000 --- a/db/btree/bt_search.c +++ /dev/null @@ -1,213 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * 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. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)bt_search.c 8.8 (Berkeley) 7/31/94"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/types.h> - -#include <stdio.h> - -#include <db.h> -#include "btree.h" - -static int __bt_snext __P((BTREE *, PAGE *, const DBT *, int *)); -static int __bt_sprev __P((BTREE *, PAGE *, const DBT *, int *)); - -/* - * __bt_search -- - * Search a btree for a key. - * - * Parameters: - * t: tree to search - * key: key to find - * exactp: pointer to exact match flag - * - * Returns: - * The EPG for matching record, if any, or the EPG for the location - * of the key, if it were inserted into the tree, is entered into - * the bt_cur field of the tree. A pointer to the field is returned. - */ -EPG * -__bt_search(t, key, exactp) - BTREE *t; - const DBT *key; - int *exactp; -{ - PAGE *h; - indx_t base, index, lim; - pgno_t pg; - int cmp; - - BT_CLR(t); - for (pg = P_ROOT;;) { - if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) - return (NULL); - - /* Do a binary search on the current page. */ - t->bt_cur.page = h; - for (base = 0, lim = NEXTINDEX(h); lim; lim >>= 1) { - t->bt_cur.index = index = base + (lim >> 1); - if ((cmp = __bt_cmp(t, key, &t->bt_cur)) == 0) { - if (h->flags & P_BLEAF) { - *exactp = 1; - return (&t->bt_cur); - } - goto next; - } - if (cmp > 0) { - base = index + 1; - --lim; - } - } - - /* - * If it's a leaf page, we're almost done. If no duplicates - * are allowed, or we have an exact match, we're done. Else, - * it's possible that there were matching keys on this page, - * which later deleted, and we're on a page with no matches - * while there are matches on other pages. If at the start or - * end of a page, check the adjacent page. - */ - if (h->flags & P_BLEAF) { - if (!F_ISSET(t, B_NODUPS)) { - if (base == 0 && - h->prevpg != P_INVALID && - __bt_sprev(t, h, key, exactp)) - return (&t->bt_cur); - if (base == NEXTINDEX(h) && - h->nextpg != P_INVALID && - __bt_snext(t, h, key, exactp)) - return (&t->bt_cur); - } - *exactp = 0; - t->bt_cur.index = base; - return (&t->bt_cur); - } - - /* - * No match found. Base is the smallest index greater than - * key and may be zero or a last + 1 index. If it's non-zero, - * decrement by one, and record the internal page which should - * be a parent page for the key. If a split later occurs, the - * inserted page will be to the right of the saved page. - */ - index = base ? base - 1 : base; - -next: BT_PUSH(t, h->pgno, index); - pg = GETBINTERNAL(h, index)->pgno; - mpool_put(t->bt_mp, h, 0); - } -} - -/* - * __bt_snext -- - * Check for an exact match after the key. - * - * Parameters: - * t: tree - * h: current page - * key: key - * exactp: pointer to exact match flag - * - * Returns: - * If an exact match found. - */ -static int -__bt_snext(t, h, key, exactp) - BTREE *t; - PAGE *h; - const DBT *key; - int *exactp; -{ - EPG e; - - /* - * Get the next page. The key is either an exact - * match, or not as good as the one we already have. - */ - if ((e.page = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL) - return (0); - e.index = 0; - if (__bt_cmp(t, key, &e) == 0) { - mpool_put(t->bt_mp, h, 0); - t->bt_cur = e; - *exactp = 1; - return (1); - } - mpool_put(t->bt_mp, e.page, 0); - return (0); -} - -/* - * __bt_sprev -- - * Check for an exact match before the key. - * - * Parameters: - * t: tree - * h: current page - * key: key - * exactp: pointer to exact match flag - * - * Returns: - * If an exact match found. - */ -static int -__bt_sprev(t, h, key, exactp) - BTREE *t; - PAGE *h; - const DBT *key; - int *exactp; -{ - EPG e; - - /* - * Get the previous page. The key is either an exact - * match, or not as good as the one we already have. - */ - if ((e.page = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL) - return (0); - e.index = NEXTINDEX(e.page) - 1; - if (__bt_cmp(t, key, &e) == 0) { - mpool_put(t->bt_mp, h, 0); - t->bt_cur = e; - *exactp = 1; - return (1); - } - mpool_put(t->bt_mp, e.page, 0); - return (0); -} diff --git a/db/btree/bt_seq.c b/db/btree/bt_seq.c deleted file mode 100644 index 90f8960..0000000 --- a/db/btree/bt_seq.c +++ /dev/null @@ -1,460 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * 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. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)bt_seq.c 8.7 (Berkeley) 7/20/94"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/types.h> - -#include <errno.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> - -#include <db.h> -#include "btree.h" - -static int __bt_first __P((BTREE *, const DBT *, EPG *, int *)); -static int __bt_seqadv __P((BTREE *, EPG *, int)); -static int __bt_seqset __P((BTREE *, EPG *, DBT *, int)); - -/* - * Sequential scan support. - * - * The tree can be scanned sequentially, starting from either end of the - * tree or from any specific key. A scan request before any scanning is - * done is initialized as starting from the least node. - */ - -/* - * __bt_seq -- - * Btree sequential scan interface. - * - * Parameters: - * dbp: pointer to access method - * key: key for positioning and return value - * data: data return value - * flags: R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV. - * - * Returns: - * RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key. - */ -int -__bt_seq(dbp, key, data, flags) - const DB *dbp; - DBT *key, *data; - u_int flags; -{ - BTREE *t; - EPG e; - int status; - - t = dbp->internal; - - /* Toss any page pinned across calls. */ - if (t->bt_pinned != NULL) { - mpool_put(t->bt_mp, t->bt_pinned, 0); - t->bt_pinned = NULL; - } - - /* - * If scan uninitialized as yet, or starting at a specific record, set - * the scan to a specific key. Both __bt_seqset and __bt_seqadv pin - * the page the cursor references if they're successful. - */ - switch (flags) { - case R_NEXT: - case R_PREV: - if (F_ISSET(&t->bt_cursor, CURS_INIT)) { - status = __bt_seqadv(t, &e, flags); - break; - } - /* FALLTHROUGH */ - case R_FIRST: - case R_LAST: - case R_CURSOR: - status = __bt_seqset(t, &e, key, flags); - break; - default: - errno = EINVAL; - return (RET_ERROR); - } - - if (status == RET_SUCCESS) { - __bt_setcur(t, e.page->pgno, e.index); - - status = - __bt_ret(t, &e, key, &t->bt_rkey, data, &t->bt_rdata, 0); - - /* - * If the user is doing concurrent access, we copied the - * key/data, toss the page. - */ - if (F_ISSET(t, B_DB_LOCK)) - mpool_put(t->bt_mp, e.page, 0); - else - t->bt_pinned = e.page; - } - return (status); -} - -/* - * __bt_seqset -- - * Set the sequential scan to a specific key. - * - * Parameters: - * t: tree - * ep: storage for returned key - * key: key for initial scan position - * flags: R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV - * - * Side effects: - * Pins the page the cursor references. - * - * Returns: - * RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key. - */ -static int -__bt_seqset(t, ep, key, flags) - BTREE *t; - EPG *ep; - DBT *key; - int flags; -{ - PAGE *h; - pgno_t pg; - int exact; - - /* - * Find the first, last or specific key in the tree and point the - * cursor at it. The cursor may not be moved until a new key has - * been found. - */ - switch (flags) { - case R_CURSOR: /* Keyed scan. */ - /* - * Find the first instance of the key or the smallest key - * which is greater than or equal to the specified key. - */ - if (key->data == NULL || key->size == 0) { - errno = EINVAL; - return (RET_ERROR); - } - return (__bt_first(t, key, ep, &exact)); - case R_FIRST: /* First record. */ - case R_NEXT: - /* Walk down the left-hand side of the tree. */ - for (pg = P_ROOT;;) { - if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) - return (RET_ERROR); - - /* Check for an empty tree. */ - if (NEXTINDEX(h) == 0) { - mpool_put(t->bt_mp, h, 0); - return (RET_SPECIAL); - } - - if (h->flags & (P_BLEAF | P_RLEAF)) - break; - pg = GETBINTERNAL(h, 0)->pgno; - mpool_put(t->bt_mp, h, 0); - } - ep->page = h; - ep->index = 0; - break; - case R_LAST: /* Last record. */ - case R_PREV: - /* Walk down the right-hand side of the tree. */ - for (pg = P_ROOT;;) { - if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) - return (RET_ERROR); - - /* Check for an empty tree. */ - if (NEXTINDEX(h) == 0) { - mpool_put(t->bt_mp, h, 0); - return (RET_SPECIAL); - } - - if (h->flags & (P_BLEAF | P_RLEAF)) - break; - pg = GETBINTERNAL(h, NEXTINDEX(h) - 1)->pgno; - mpool_put(t->bt_mp, h, 0); - } - - ep->page = h; - ep->index = NEXTINDEX(h) - 1; - break; - } - return (RET_SUCCESS); -} - -/* - * __bt_seqadvance -- - * Advance the sequential scan. - * - * Parameters: - * t: tree - * flags: R_NEXT, R_PREV - * - * Side effects: - * Pins the page the new key/data record is on. - * - * Returns: - * RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key. - */ -static int -__bt_seqadv(t, ep, flags) - BTREE *t; - EPG *ep; - int flags; -{ - CURSOR *c; - PAGE *h; - indx_t index; - pgno_t pg; - int exact; - - /* - * There are a couple of states that we can be in. The cursor has - * been initialized by the time we get here, but that's all we know. - */ - c = &t->bt_cursor; - - /* - * The cursor was deleted where there weren't any duplicate records, - * so the key was saved. Find out where that key would go in the - * current tree. It doesn't matter if the returned key is an exact - * match or not -- if it's an exact match, the record was added after - * the delete so we can just return it. If not, as long as there's - * a record there, return it. - */ - if (F_ISSET(c, CURS_ACQUIRE)) - return (__bt_first(t, &c->key, ep, &exact)); - - /* Get the page referenced by the cursor. */ - if ((h = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL) - return (RET_ERROR); - - /* - * Find the next/previous record in the tree and point the cursor at - * it. The cursor may not be moved until a new key has been found. - */ - switch (flags) { - case R_NEXT: /* Next record. */ - /* - * The cursor was deleted in duplicate records, and moved - * forward to a record that has yet to be returned. Clear - * that flag, and return the record. - */ - if (F_ISSET(c, CURS_AFTER)) - goto usecurrent; - index = c->pg.index; - if (++index == NEXTINDEX(h)) { - pg = h->nextpg; - mpool_put(t->bt_mp, h, 0); - if (pg == P_INVALID) - return (RET_SPECIAL); - if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) - return (RET_ERROR); - index = 0; - } - break; - case R_PREV: /* Previous record. */ - /* - * The cursor was deleted in duplicate records, and moved - * backward to a record that has yet to be returned. Clear - * that flag, and return the record. - */ - if (F_ISSET(c, CURS_BEFORE)) { -usecurrent: F_CLR(c, CURS_AFTER | CURS_BEFORE); - ep->page = h; - ep->index = c->pg.index; - return (RET_SUCCESS); - } - index = c->pg.index; - if (index == 0) { - pg = h->prevpg; - mpool_put(t->bt_mp, h, 0); - if (pg == P_INVALID) - return (RET_SPECIAL); - if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) - return (RET_ERROR); - index = NEXTINDEX(h) - 1; - } else - --index; - break; - } - - ep->page = h; - ep->index = index; - return (RET_SUCCESS); -} - -/* - * __bt_first -- - * Find the first entry. - * - * Parameters: - * t: the tree - * key: the key - * erval: return EPG - * exactp: pointer to exact match flag - * - * Returns: - * The first entry in the tree greater than or equal to key, - * or RET_SPECIAL if no such key exists. - */ -static int -__bt_first(t, key, erval, exactp) - BTREE *t; - const DBT *key; - EPG *erval; - int *exactp; -{ - PAGE *h; - EPG *ep, save; - pgno_t pg; - - /* - * Find any matching record; __bt_search pins the page. - * - * If it's an exact match and duplicates are possible, walk backwards - * in the tree until we find the first one. Otherwise, make sure it's - * a valid key (__bt_search may return an index just past the end of a - * page) and return it. - */ - if ((ep = __bt_search(t, key, exactp)) == NULL) - return (RET_SPECIAL); - if (*exactp) { - if (F_ISSET(t, B_NODUPS)) { - *erval = *ep; - return (RET_SUCCESS); - } - - /* - * Walk backwards, as long as the entry matches and there are - * keys left in the tree. Save a copy of each match in case - * we go too far. - */ - save = *ep; - h = ep->page; - do { - if (save.page->pgno != ep->page->pgno) { - mpool_put(t->bt_mp, save.page, 0); - save = *ep; - } else - save.index = ep->index; - - /* - * Don't unpin the page the last (or original) match - * was on, but make sure it's unpinned if an error - * occurs. - */ - if (ep->index == 0) { - if (h->prevpg == P_INVALID) - break; - if (h->pgno != save.page->pgno) - mpool_put(t->bt_mp, h, 0); - if ((h = mpool_get(t->bt_mp, - h->prevpg, 0)) == NULL) { - if (h->pgno == save.page->pgno) - mpool_put(t->bt_mp, - save.page, 0); - return (RET_ERROR); - } - ep->page = h; - ep->index = NEXTINDEX(h); - } - --ep->index; - } while (__bt_cmp(t, key, ep) == 0); - - /* - * Reach here with the last page that was looked at pinned, - * which may or may not be the same as the last (or original) - * match page. If it's not useful, release it. - */ - if (h->pgno != save.page->pgno) - mpool_put(t->bt_mp, h, 0); - - *erval = save; - return (RET_SUCCESS); - } - - /* If at the end of a page, find the next entry. */ - if (ep->index == NEXTINDEX(ep->page)) { - h = ep->page; - pg = h->nextpg; - mpool_put(t->bt_mp, h, 0); - if (pg == P_INVALID) - return (RET_SPECIAL); - if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) - return (RET_ERROR); - ep->index = 0; - ep->page = h; - } - *erval = *ep; - return (RET_SUCCESS); -} - -/* - * __bt_setcur -- - * Set the cursor to an entry in the tree. - * - * Parameters: - * t: the tree - * pgno: page number - * index: page index - */ -void -__bt_setcur(t, pgno, index) - BTREE *t; - pgno_t pgno; - u_int index; -{ - /* Lose any already deleted key. */ - if (t->bt_cursor.key.data != NULL) { - free(t->bt_cursor.key.data); - t->bt_cursor.key.size = 0; - t->bt_cursor.key.data = NULL; - } - F_CLR(&t->bt_cursor, CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE); - - /* Update the cursor. */ - t->bt_cursor.pg.pgno = pgno; - t->bt_cursor.pg.index = index; - F_SET(&t->bt_cursor, CURS_INIT); -} diff --git a/db/btree/bt_split.c b/db/btree/bt_split.c deleted file mode 100644 index 4119ccb..0000000 --- a/db/btree/bt_split.c +++ /dev/null @@ -1,829 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * 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. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)bt_split.c 8.9 (Berkeley) 7/26/94"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/types.h> - -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <db.h> -#include "btree.h" - -static int bt_broot __P((BTREE *, PAGE *, PAGE *, PAGE *)); -static PAGE *bt_page - __P((BTREE *, PAGE *, PAGE **, PAGE **, indx_t *, size_t)); -static int bt_preserve __P((BTREE *, pgno_t)); -static PAGE *bt_psplit - __P((BTREE *, PAGE *, PAGE *, PAGE *, indx_t *, size_t)); -static PAGE *bt_root - __P((BTREE *, PAGE *, PAGE **, PAGE **, indx_t *, size_t)); -static int bt_rroot __P((BTREE *, PAGE *, PAGE *, PAGE *)); -static recno_t rec_total __P((PAGE *)); - -#ifdef STATISTICS -u_long bt_rootsplit, bt_split, bt_sortsplit, bt_pfxsaved; -#endif - -/* - * __BT_SPLIT -- Split the tree. - * - * Parameters: - * t: tree - * sp: page to split - * key: key to insert - * data: data to insert - * flags: BIGKEY/BIGDATA flags - * ilen: insert length - * skip: index to leave open - * - * Returns: - * RET_ERROR, RET_SUCCESS - */ -int -__bt_split(t, sp, key, data, flags, ilen, argskip) - BTREE *t; - PAGE *sp; - const DBT *key, *data; - int flags; - size_t ilen; - u_int32_t argskip; -{ - BINTERNAL *bi; - BLEAF *bl, *tbl; - DBT a, b; - EPGNO *parent; - PAGE *h, *l, *r, *lchild, *rchild; - indx_t nxtindex; - u_int16_t skip; - u_int32_t n, nbytes, nksize; - int parentsplit; - char *dest; - - /* - * Split the page into two pages, l and r. The split routines return - * a pointer to the page into which the key should be inserted and with - * skip set to the offset which should be used. Additionally, l and r - * are pinned. - */ - skip = argskip; - h = sp->pgno == P_ROOT ? - bt_root(t, sp, &l, &r, &skip, ilen) : - bt_page(t, sp, &l, &r, &skip, ilen); - if (h == NULL) - return (RET_ERROR); - - /* - * Insert the new key/data pair into the leaf page. (Key inserts - * always cause a leaf page to split first.) - */ - h->linp[skip] = h->upper -= ilen; - dest = (char *)h + h->upper; - if (F_ISSET(t, R_RECNO)) - WR_RLEAF(dest, data, flags) - else - WR_BLEAF(dest, key, data, flags) - - /* If the root page was split, make it look right. */ - if (sp->pgno == P_ROOT && - (F_ISSET(t, R_RECNO) ? - bt_rroot(t, sp, l, r) : bt_broot(t, sp, l, r)) == RET_ERROR) - goto err2; - - /* - * Now we walk the parent page stack -- a LIFO stack of the pages that - * were traversed when we searched for the page that split. Each stack - * entry is a page number and a page index offset. The offset is for - * the page traversed on the search. We've just split a page, so we - * have to insert a new key into the parent page. - * - * If the insert into the parent page causes it to split, may have to - * continue splitting all the way up the tree. We stop if the root - * splits or the page inserted into didn't have to split to hold the - * new key. Some algorithms replace the key for the old page as well - * as the new page. We don't, as there's no reason to believe that the - * first key on the old page is any better than the key we have, and, - * in the case of a key being placed at index 0 causing the split, the - * key is unavailable. - * - * There are a maximum of 5 pages pinned at any time. We keep the left - * and right pages pinned while working on the parent. The 5 are the - * two children, left parent and right parent (when the parent splits) - * and the root page or the overflow key page when calling bt_preserve. - * This code must make sure that all pins are released other than the - * root page or overflow page which is unlocked elsewhere. - */ - while ((parent = BT_POP(t)) != NULL) { - lchild = l; - rchild = r; - - /* Get the parent page. */ - if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL) - goto err2; - - /* - * The new key goes ONE AFTER the index, because the split - * was to the right. - */ - skip = parent->index + 1; - - /* - * Calculate the space needed on the parent page. - * - * Prefix trees: space hack when inserting into BINTERNAL - * pages. Retain only what's needed to distinguish between - * the new entry and the LAST entry on the page to its left. - * If the keys compare equal, retain the entire key. Note, - * we don't touch overflow keys, and the entire key must be - * retained for the next-to-left most key on the leftmost - * page of each level, or the search will fail. Applicable - * ONLY to internal pages that have leaf pages as children. - * Further reduction of the key between pairs of internal - * pages loses too much information. - */ - switch (rchild->flags & P_TYPE) { - case P_BINTERNAL: - bi = GETBINTERNAL(rchild, 0); - nbytes = NBINTERNAL(bi->ksize); - break; - case P_BLEAF: - bl = GETBLEAF(rchild, 0); - nbytes = NBINTERNAL(bl->ksize); - if (t->bt_pfx && !(bl->flags & P_BIGKEY) && - (h->prevpg != P_INVALID || skip > 1)) { - tbl = GETBLEAF(lchild, NEXTINDEX(lchild) - 1); - a.size = tbl->ksize; - a.data = tbl->bytes; - b.size = bl->ksize; - b.data = bl->bytes; - nksize = t->bt_pfx(&a, &b); - n = NBINTERNAL(nksize); - if (n < nbytes) { -#ifdef STATISTICS - bt_pfxsaved += nbytes - n; -#endif - nbytes = n; - } else - nksize = 0; - } else - nksize = 0; - break; - case P_RINTERNAL: - case P_RLEAF: - nbytes = NRINTERNAL; - break; - default: - abort(); - } - - /* Split the parent page if necessary or shift the indices. */ - if ((u_int32_t) (h->upper - h->lower) - < nbytes + sizeof(indx_t)) { - sp = h; - h = h->pgno == P_ROOT ? - bt_root(t, h, &l, &r, &skip, nbytes) : - bt_page(t, h, &l, &r, &skip, nbytes); - if (h == NULL) - goto err1; - parentsplit = 1; - } else { - if (skip < (nxtindex = NEXTINDEX(h))) - memmove(h->linp + skip + 1, h->linp + skip, - (nxtindex - skip) * sizeof(indx_t)); - h->lower += sizeof(indx_t); - parentsplit = 0; - } - - /* Insert the key into the parent page. */ - switch (rchild->flags & P_TYPE) { - case P_BINTERNAL: - h->linp[skip] = h->upper -= nbytes; - dest = (char *)h + h->linp[skip]; - memmove(dest, bi, nbytes); - ((BINTERNAL *)dest)->pgno = rchild->pgno; - break; - case P_BLEAF: - h->linp[skip] = h->upper -= nbytes; - dest = (char *)h + h->linp[skip]; - WR_BINTERNAL(dest, nksize ? nksize : bl->ksize, - rchild->pgno, bl->flags & P_BIGKEY); - memmove(dest, bl->bytes, nksize ? nksize : bl->ksize); - if (bl->flags & P_BIGKEY && - bt_preserve(t, *(pgno_t *)bl->bytes) == RET_ERROR) - goto err1; - break; - case P_RINTERNAL: - /* - * Update the left page count. If split - * added at index 0, fix the correct page. - */ - if (skip > 0) - dest = (char *)h + h->linp[skip - 1]; - else - dest = (char *)l + l->linp[NEXTINDEX(l) - 1]; - ((RINTERNAL *)dest)->nrecs = rec_total(lchild); - ((RINTERNAL *)dest)->pgno = lchild->pgno; - - /* Update the right page count. */ - h->linp[skip] = h->upper -= nbytes; - dest = (char *)h + h->linp[skip]; - ((RINTERNAL *)dest)->nrecs = rec_total(rchild); - ((RINTERNAL *)dest)->pgno = rchild->pgno; - break; - case P_RLEAF: - /* - * Update the left page count. If split - * added at index 0, fix the correct page. - */ - if (skip > 0) - dest = (char *)h + h->linp[skip - 1]; - else - dest = (char *)l + l->linp[NEXTINDEX(l) - 1]; - ((RINTERNAL *)dest)->nrecs = NEXTINDEX(lchild); - ((RINTERNAL *)dest)->pgno = lchild->pgno; - - /* Update the right page count. */ - h->linp[skip] = h->upper -= nbytes; - dest = (char *)h + h->linp[skip]; - ((RINTERNAL *)dest)->nrecs = NEXTINDEX(rchild); - ((RINTERNAL *)dest)->pgno = rchild->pgno; - break; - default: - abort(); - } - - /* Unpin the held pages. */ - if (!parentsplit) { - mpool_put(t->bt_mp, h, MPOOL_DIRTY); - break; - } - - /* If the root page was split, make it look right. */ - if (sp->pgno == P_ROOT && - (F_ISSET(t, R_RECNO) ? - bt_rroot(t, sp, l, r) : bt_broot(t, sp, l, r)) == RET_ERROR) - goto err1; - - mpool_put(t->bt_mp, lchild, MPOOL_DIRTY); - mpool_put(t->bt_mp, rchild, MPOOL_DIRTY); - } - - /* Unpin the held pages. */ - mpool_put(t->bt_mp, l, MPOOL_DIRTY); - mpool_put(t->bt_mp, r, MPOOL_DIRTY); - - /* Clear any pages left on the stack. */ - return (RET_SUCCESS); - - /* - * If something fails in the above loop we were already walking back - * up the tree and the tree is now inconsistent. Nothing much we can - * do about it but release any memory we're holding. - */ -err1: mpool_put(t->bt_mp, lchild, MPOOL_DIRTY); - mpool_put(t->bt_mp, rchild, MPOOL_DIRTY); - -err2: mpool_put(t->bt_mp, l, 0); - mpool_put(t->bt_mp, r, 0); - __dbpanic(t->bt_dbp); - return (RET_ERROR); -} - -/* - * BT_PAGE -- Split a non-root page of a btree. - * - * Parameters: - * t: tree - * h: root page - * lp: pointer to left page pointer - * rp: pointer to right page pointer - * skip: pointer to index to leave open - * ilen: insert length - * - * Returns: - * Pointer to page in which to insert or NULL on error. - */ -static PAGE * -bt_page(t, h, lp, rp, skip, ilen) - BTREE *t; - PAGE *h, **lp, **rp; - indx_t *skip; - size_t ilen; -{ - PAGE *l, *r, *tp; - pgno_t npg; - -#ifdef STATISTICS - ++bt_split; -#endif - /* Put the new right page for the split into place. */ - if ((r = __bt_new(t, &npg)) == NULL) - return (NULL); - r->pgno = npg; - r->lower = BTDATAOFF; - r->upper = t->bt_psize; - r->nextpg = h->nextpg; - r->prevpg = h->pgno; - r->flags = h->flags & P_TYPE; - - /* - * If we're splitting the last page on a level because we're appending - * a key to it (skip is NEXTINDEX()), it's likely that the data is - * sorted. Adding an empty page on the side of the level is less work - * and can push the fill factor much higher than normal. If we're - * wrong it's no big deal, we'll just do the split the right way next - * time. It may look like it's equally easy to do a similar hack for - * reverse sorted data, that is, split the tree left, but it's not. - * Don't even try. - */ - if (h->nextpg == P_INVALID && *skip == NEXTINDEX(h)) { -#ifdef STATISTICS - ++bt_sortsplit; -#endif - h->nextpg = r->pgno; - r->lower = BTDATAOFF + sizeof(indx_t); - *skip = 0; - *lp = h; - *rp = r; - return (r); - } - - /* Put the new left page for the split into place. */ - if ((l = (PAGE *)malloc(t->bt_psize)) == NULL) { - mpool_put(t->bt_mp, r, 0); - return (NULL); - } -#ifdef PURIFY - memset(l, 0xff, t->bt_psize); -#endif - l->pgno = h->pgno; - l->nextpg = r->pgno; - l->prevpg = h->prevpg; - l->lower = BTDATAOFF; - l->upper = t->bt_psize; - l->flags = h->flags & P_TYPE; - - /* Fix up the previous pointer of the page after the split page. */ - if (h->nextpg != P_INVALID) { - if ((tp = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL) { - free(l); - /* XXX mpool_free(t->bt_mp, r->pgno); */ - return (NULL); - } - tp->prevpg = r->pgno; - mpool_put(t->bt_mp, tp, MPOOL_DIRTY); - } - - /* - * Split right. The key/data pairs aren't sorted in the btree page so - * it's simpler to copy the data from the split page onto two new pages - * instead of copying half the data to the right page and compacting - * the left page in place. Since the left page can't change, we have - * to swap the original and the allocated left page after the split. - */ - tp = bt_psplit(t, h, l, r, skip, ilen); - - /* Move the new left page onto the old left page. */ - memmove(h, l, t->bt_psize); - if (tp == l) - tp = h; - free(l); - - *lp = h; - *rp = r; - return (tp); -} - -/* - * BT_ROOT -- Split the root page of a btree. - * - * Parameters: - * t: tree - * h: root page - * lp: pointer to left page pointer - * rp: pointer to right page pointer - * skip: pointer to index to leave open - * ilen: insert length - * - * Returns: - * Pointer to page in which to insert or NULL on error. - */ -static PAGE * -bt_root(t, h, lp, rp, skip, ilen) - BTREE *t; - PAGE *h, **lp, **rp; - indx_t *skip; - size_t ilen; -{ - PAGE *l, *r, *tp; - pgno_t lnpg, rnpg; - -#ifdef STATISTICS - ++bt_split; - ++bt_rootsplit; -#endif - /* Put the new left and right pages for the split into place. */ - if ((l = __bt_new(t, &lnpg)) == NULL || - (r = __bt_new(t, &rnpg)) == NULL) - return (NULL); - l->pgno = lnpg; - r->pgno = rnpg; - l->nextpg = r->pgno; - r->prevpg = l->pgno; - l->prevpg = r->nextpg = P_INVALID; - l->lower = r->lower = BTDATAOFF; - l->upper = r->upper = t->bt_psize; - l->flags = r->flags = h->flags & P_TYPE; - - /* Split the root page. */ - tp = bt_psplit(t, h, l, r, skip, ilen); - - *lp = l; - *rp = r; - return (tp); -} - -/* - * BT_RROOT -- Fix up the recno root page after it has been split. - * - * Parameters: - * t: tree - * h: root page - * l: left page - * r: right page - * - * Returns: - * RET_ERROR, RET_SUCCESS - */ -static int -bt_rroot(t, h, l, r) - BTREE *t; - PAGE *h, *l, *r; -{ - char *dest; - - /* Insert the left and right keys, set the header information. */ - h->linp[0] = h->upper = t->bt_psize - NRINTERNAL; - dest = (char *)h + h->upper; - WR_RINTERNAL(dest, - l->flags & P_RLEAF ? NEXTINDEX(l) : rec_total(l), l->pgno); - - h->linp[1] = h->upper -= NRINTERNAL; - dest = (char *)h + h->upper; - WR_RINTERNAL(dest, - r->flags & P_RLEAF ? NEXTINDEX(r) : rec_total(r), r->pgno); - - h->lower = BTDATAOFF + 2 * sizeof(indx_t); - - /* Unpin the root page, set to recno internal page. */ - h->flags &= ~P_TYPE; - h->flags |= P_RINTERNAL; - mpool_put(t->bt_mp, h, MPOOL_DIRTY); - - return (RET_SUCCESS); -} - -/* - * BT_BROOT -- Fix up the btree root page after it has been split. - * - * Parameters: - * t: tree - * h: root page - * l: left page - * r: right page - * - * Returns: - * RET_ERROR, RET_SUCCESS - */ -static int -bt_broot(t, h, l, r) - BTREE *t; - PAGE *h, *l, *r; -{ - BINTERNAL *bi; - BLEAF *bl; - u_int32_t nbytes; - char *dest; - - /* - * If the root page was a leaf page, change it into an internal page. - * We copy the key we split on (but not the key's data, in the case of - * a leaf page) to the new root page. - * - * The btree comparison code guarantees that the left-most key on any - * level of the tree is never used, so it doesn't need to be filled in. - */ - nbytes = NBINTERNAL(0); - h->linp[0] = h->upper = t->bt_psize - nbytes; - dest = (char *)h + h->upper; - WR_BINTERNAL(dest, 0, l->pgno, 0); - - switch (h->flags & P_TYPE) { - case P_BLEAF: - bl = GETBLEAF(r, 0); - nbytes = NBINTERNAL(bl->ksize); - h->linp[1] = h->upper -= nbytes; - dest = (char *)h + h->upper; - WR_BINTERNAL(dest, bl->ksize, r->pgno, 0); - memmove(dest, bl->bytes, bl->ksize); - - /* - * If the key is on an overflow page, mark the overflow chain - * so it isn't deleted when the leaf copy of the key is deleted. - */ - if (bl->flags & P_BIGKEY && - bt_preserve(t, *(pgno_t *)bl->bytes) == RET_ERROR) - return (RET_ERROR); - break; - case P_BINTERNAL: - bi = GETBINTERNAL(r, 0); - nbytes = NBINTERNAL(bi->ksize); - h->linp[1] = h->upper -= nbytes; - dest = (char *)h + h->upper; - memmove(dest, bi, nbytes); - ((BINTERNAL *)dest)->pgno = r->pgno; - break; - default: - abort(); - } - - /* There are two keys on the page. */ - h->lower = BTDATAOFF + 2 * sizeof(indx_t); - - /* Unpin the root page, set to btree internal page. */ - h->flags &= ~P_TYPE; - h->flags |= P_BINTERNAL; - mpool_put(t->bt_mp, h, MPOOL_DIRTY); - - return (RET_SUCCESS); -} - -/* - * BT_PSPLIT -- Do the real work of splitting the page. - * - * Parameters: - * t: tree - * h: page to be split - * l: page to put lower half of data - * r: page to put upper half of data - * pskip: pointer to index to leave open - * ilen: insert length - * - * Returns: - * Pointer to page in which to insert. - */ -static PAGE * -bt_psplit(t, h, l, r, pskip, ilen) - BTREE *t; - PAGE *h, *l, *r; - indx_t *pskip; - size_t ilen; -{ - BINTERNAL *bi; - BLEAF *bl; - CURSOR *c; - RLEAF *rl; - PAGE *rval; - void *src; - indx_t full, half, nxt, off, skip, top, used; - u_int32_t nbytes; - int bigkeycnt, isbigkey; - - /* - * Split the data to the left and right pages. Leave the skip index - * open. Additionally, make some effort not to split on an overflow - * key. This makes internal page processing faster and can save - * space as overflow keys used by internal pages are never deleted. - */ - bigkeycnt = 0; - skip = *pskip; - full = t->bt_psize - BTDATAOFF; - half = full / 2; - used = 0; - for (nxt = off = 0, top = NEXTINDEX(h); nxt < top; ++off) { - if (skip == off) { - nbytes = ilen; - isbigkey = 0; /* XXX: not really known. */ - } else - switch (h->flags & P_TYPE) { - case P_BINTERNAL: - src = bi = GETBINTERNAL(h, nxt); - nbytes = NBINTERNAL(bi->ksize); - isbigkey = bi->flags & P_BIGKEY; - break; - case P_BLEAF: - src = bl = GETBLEAF(h, nxt); - nbytes = NBLEAF(bl); - isbigkey = bl->flags & P_BIGKEY; - break; - case P_RINTERNAL: - src = GETRINTERNAL(h, nxt); - nbytes = NRINTERNAL; - isbigkey = 0; - break; - case P_RLEAF: - src = rl = GETRLEAF(h, nxt); - nbytes = NRLEAF(rl); - isbigkey = 0; - break; - default: - abort(); - } - - /* - * If the key/data pairs are substantial fractions of the max - * possible size for the page, it's possible to get situations - * where we decide to try and copy too much onto the left page. - * Make sure that doesn't happen. - */ - if ((skip <= off && used + nbytes + sizeof(indx_t) >= full) - || nxt == top - 1) { - --off; - break; - } - - /* Copy the key/data pair, if not the skipped index. */ - if (skip != off) { - ++nxt; - - l->linp[off] = l->upper -= nbytes; - memmove((char *)l + l->upper, src, nbytes); - } - - used += nbytes + sizeof(indx_t); - if (used >= half) { - if (!isbigkey || bigkeycnt == 3) - break; - else - ++bigkeycnt; - } - } - - /* - * Off is the last offset that's valid for the left page. - * Nxt is the first offset to be placed on the right page. - */ - l->lower += (off + 1) * sizeof(indx_t); - - /* - * If splitting the page that the cursor was on, the cursor has to be - * adjusted to point to the same record as before the split. If the - * cursor is at or past the skipped slot, the cursor is incremented by - * one. If the cursor is on the right page, it is decremented by the - * number of records split to the left page. - */ - c = &t->bt_cursor; - if (F_ISSET(c, CURS_INIT) && c->pg.pgno == h->pgno) { - if (c->pg.index >= skip) - ++c->pg.index; - if (c->pg.index < nxt) /* Left page. */ - c->pg.pgno = l->pgno; - else { /* Right page. */ - c->pg.pgno = r->pgno; - c->pg.index -= nxt; - } - } - - /* - * If the skipped index was on the left page, just return that page. - * Otherwise, adjust the skip index to reflect the new position on - * the right page. - */ - if (skip <= off) { - skip = 0; - rval = l; - } else { - rval = r; - *pskip -= nxt; - } - - for (off = 0; nxt < top; ++off) { - if (skip == nxt) { - ++off; - skip = 0; - } - switch (h->flags & P_TYPE) { - case P_BINTERNAL: - src = bi = GETBINTERNAL(h, nxt); - nbytes = NBINTERNAL(bi->ksize); - break; - case P_BLEAF: - src = bl = GETBLEAF(h, nxt); - nbytes = NBLEAF(bl); - break; - case P_RINTERNAL: - src = GETRINTERNAL(h, nxt); - nbytes = NRINTERNAL; - break; - case P_RLEAF: - src = rl = GETRLEAF(h, nxt); - nbytes = NRLEAF(rl); - break; - default: - abort(); - } - ++nxt; - r->linp[off] = r->upper -= nbytes; - memmove((char *)r + r->upper, src, nbytes); - } - r->lower += off * sizeof(indx_t); - - /* If the key is being appended to the page, adjust the index. */ - if (skip == top) - r->lower += sizeof(indx_t); - - return (rval); -} - -/* - * BT_PRESERVE -- Mark a chain of pages as used by an internal node. - * - * Chains of indirect blocks pointed to by leaf nodes get reclaimed when the - * record that references them gets deleted. Chains pointed to by internal - * pages never get deleted. This routine marks a chain as pointed to by an - * internal page. - * - * Parameters: - * t: tree - * pg: page number of first page in the chain. - * - * Returns: - * RET_SUCCESS, RET_ERROR. - */ -static int -bt_preserve(t, pg) - BTREE *t; - pgno_t pg; -{ - PAGE *h; - - if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) - return (RET_ERROR); - h->flags |= P_PRESERVE; - mpool_put(t->bt_mp, h, MPOOL_DIRTY); - return (RET_SUCCESS); -} - -/* - * REC_TOTAL -- Return the number of recno entries below a page. - * - * Parameters: - * h: page - * - * Returns: - * The number of recno entries below a page. - * - * XXX - * These values could be set by the bt_psplit routine. The problem is that the - * entry has to be popped off of the stack etc. or the values have to be passed - * all the way back to bt_split/bt_rroot and it's not very clean. - */ -static recno_t -rec_total(h) - PAGE *h; -{ - recno_t recs; - indx_t nxt, top; - - for (recs = 0, nxt = 0, top = NEXTINDEX(h); nxt < top; ++nxt) - recs += GETRINTERNAL(h, nxt)->nrecs; - return (recs); -} diff --git a/db/btree/bt_utils.c b/db/btree/bt_utils.c deleted file mode 100644 index 1416c78..0000000 --- a/db/btree/bt_utils.c +++ /dev/null @@ -1,260 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * 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. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)bt_utils.c 8.8 (Berkeley) 7/20/94"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/param.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <db.h> -#include "btree.h" - -/* - * __bt_ret -- - * Build return key/data pair. - * - * Parameters: - * t: tree - * e: key/data pair to be returned - * key: user's key structure (NULL if not to be filled in) - * rkey: memory area to hold key - * data: user's data structure (NULL if not to be filled in) - * rdata: memory area to hold data - * copy: always copy the key/data item - * - * Returns: - * RET_SUCCESS, RET_ERROR. - */ -int -__bt_ret(t, e, key, rkey, data, rdata, copy) - BTREE *t; - EPG *e; - DBT *key, *rkey, *data, *rdata; - int copy; -{ - BLEAF *bl; - void *p; - - bl = GETBLEAF(e->page, e->index); - - /* - * We must copy big keys/data to make them contiguous. Otherwise, - * leave the page pinned and don't copy unless the user specified - * concurrent access. - */ - if (key == NULL) - goto dataonly; - - if (bl->flags & P_BIGKEY) { - if (__ovfl_get(t, bl->bytes, - &key->size, &rkey->data, &rkey->size)) - return (RET_ERROR); - key->data = rkey->data; - } else if (copy || F_ISSET(t, B_DB_LOCK)) { - if (bl->ksize > rkey->size) { - p = (void *)(rkey->data == NULL ? - malloc(bl->ksize) : realloc(rkey->data, bl->ksize)); - if (p == NULL) - return (RET_ERROR); - rkey->data = p; - rkey->size = bl->ksize; - } - memmove(rkey->data, bl->bytes, bl->ksize); - key->size = bl->ksize; - key->data = rkey->data; - } else { - key->size = bl->ksize; - key->data = bl->bytes; - } - -dataonly: - if (data == NULL) - return (RET_SUCCESS); - - if (bl->flags & P_BIGDATA) { - if (__ovfl_get(t, bl->bytes + bl->ksize, - &data->size, &rdata->data, &rdata->size)) - return (RET_ERROR); - data->data = rdata->data; - } else if (copy || F_ISSET(t, B_DB_LOCK)) { - /* Use +1 in case the first record retrieved is 0 length. */ - if (bl->dsize + 1 > rdata->size) { - p = (void *)(rdata->data == NULL ? - malloc(bl->dsize + 1) : - realloc(rdata->data, bl->dsize + 1)); - if (p == NULL) - return (RET_ERROR); - rdata->data = p; - rdata->size = bl->dsize + 1; - } - memmove(rdata->data, bl->bytes + bl->ksize, bl->dsize); - data->size = bl->dsize; - data->data = rdata->data; - } else { - data->size = bl->dsize; - data->data = bl->bytes + bl->ksize; - } - - return (RET_SUCCESS); -} - -/* - * __BT_CMP -- Compare a key to a given record. - * - * Parameters: - * t: tree - * k1: DBT pointer of first arg to comparison - * e: pointer to EPG for comparison - * - * Returns: - * < 0 if k1 is < record - * = 0 if k1 is = record - * > 0 if k1 is > record - */ -int -__bt_cmp(t, k1, e) - BTREE *t; - const DBT *k1; - EPG *e; -{ - BINTERNAL *bi; - BLEAF *bl; - DBT k2; - PAGE *h; - void *bigkey; - - /* - * The left-most key on internal pages, at any level of the tree, is - * guaranteed by the following code to be less than any user key. - * This saves us from having to update the leftmost key on an internal - * page when the user inserts a new key in the tree smaller than - * anything we've yet seen. - */ - h = e->page; - if (e->index == 0 && h->prevpg == P_INVALID && !(h->flags & P_BLEAF)) - return (1); - - bigkey = NULL; - if (h->flags & P_BLEAF) { - bl = GETBLEAF(h, e->index); - if (bl->flags & P_BIGKEY) - bigkey = bl->bytes; - else { - k2.data = bl->bytes; - k2.size = bl->ksize; - } - } else { - bi = GETBINTERNAL(h, e->index); - if (bi->flags & P_BIGKEY) - bigkey = bi->bytes; - else { - k2.data = bi->bytes; - k2.size = bi->ksize; - } - } - - if (bigkey) { - if (__ovfl_get(t, bigkey, - &k2.size, &t->bt_rdata.data, &t->bt_rdata.size)) - return (RET_ERROR); - k2.data = t->bt_rdata.data; - } - return ((*t->bt_cmp)(k1, &k2)); -} - -/* - * __BT_DEFCMP -- Default comparison routine. - * - * Parameters: - * a: DBT #1 - * b: DBT #2 - * - * Returns: - * < 0 if a is < b - * = 0 if a is = b - * > 0 if a is > b - */ -int -__bt_defcmp(a, b) - const DBT *a, *b; -{ - register size_t len; - register u_char *p1, *p2; - - /* - * XXX - * If a size_t doesn't fit in an int, this routine can lose. - * What we need is a integral type which is guaranteed to be - * larger than a size_t, and there is no such thing. - */ - len = MIN(a->size, b->size); - for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2) - if (*p1 != *p2) - return ((int)*p1 - (int)*p2); - return ((int)a->size - (int)b->size); -} - -/* - * __BT_DEFPFX -- Default prefix routine. - * - * Parameters: - * a: DBT #1 - * b: DBT #2 - * - * Returns: - * Number of bytes needed to distinguish b from a. - */ -size_t -__bt_defpfx(a, b) - const DBT *a, *b; -{ - register u_char *p1, *p2; - register size_t cnt, len; - - cnt = 1; - len = MIN(a->size, b->size); - for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2, ++cnt) - if (*p1 != *p2) - return (cnt); - - /* a->size must be <= b->size, or they wouldn't be in this order. */ - return (a->size < b->size ? a->size + 1 : a->size); -} diff --git a/db/btree/btree.h b/db/btree/btree.h deleted file mode 100644 index 45f7c94..0000000 --- a/db/btree/btree.h +++ /dev/null @@ -1,395 +0,0 @@ -/*- - * Copyright (c) 1991, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * 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. - * - * @(#)btree.h 8.11 (Berkeley) 8/17/94 - */ - -/* Macros to set/clear/test flags. */ -#define F_SET(p, f) (p)->flags |= (f) -#define F_CLR(p, f) (p)->flags &= ~(f) -#define F_ISSET(p, f) ((p)->flags & (f)) - -#include <mpool.h> - -#ifdef _LIBC -/* In the GNU C library we must not pollute the namespace because libdb is - needed by libnss_db. */ -#define mpool_open __mpool_open -#define mpool_filter __mpool_filter -#define mpool_new __mpool_new -#define mpool_get __mpool_get -#define mpool_put __mpool_put -#define mpool_sync __mpool_sync -#define mpool_close __mpool_close -#endif - -#define DEFMINKEYPAGE (2) /* Minimum keys per page */ -#define MINCACHE (5) /* Minimum cached pages */ -#define MINPSIZE (512) /* Minimum page size */ - -/* - * Page 0 of a btree file contains a copy of the meta-data. This page is also - * used as an out-of-band page, i.e. page pointers that point to nowhere point - * to page 0. Page 1 is the root of the btree. - */ -#define P_INVALID 0 /* Invalid tree page number. */ -#define P_META 0 /* Tree metadata page number. */ -#define P_ROOT 1 /* Tree root page number. */ - -/* - * There are five page layouts in the btree: btree internal pages (BINTERNAL), - * btree leaf pages (BLEAF), recno internal pages (RINTERNAL), recno leaf pages - * (RLEAF) and overflow pages. All five page types have a page header (PAGE). - * This implementation requires that values within structures NOT be padded. - * (ANSI C permits random padding.) If your compiler pads randomly you'll have - * to do some work to get this package to run. - */ -typedef struct _page { - pgno_t pgno; /* this page's page number */ - pgno_t prevpg; /* left sibling */ - pgno_t nextpg; /* right sibling */ - -#define P_BINTERNAL 0x01 /* btree internal page */ -#define P_BLEAF 0x02 /* leaf page */ -#define P_OVERFLOW 0x04 /* overflow page */ -#define P_RINTERNAL 0x08 /* recno internal page */ -#define P_RLEAF 0x10 /* leaf page */ -#define P_TYPE 0x1f /* type mask */ -#define P_PRESERVE 0x20 /* never delete this chain of pages */ - u_int32_t flags; - - indx_t lower; /* lower bound of free space on page */ - indx_t upper; /* upper bound of free space on page */ - indx_t linp[1]; /* indx_t-aligned VAR. LENGTH DATA */ -} PAGE; - -/* First and next index. */ -#define BTDATAOFF \ - (sizeof(pgno_t) + sizeof(pgno_t) + sizeof(pgno_t) + \ - sizeof(u_int32_t) + sizeof(indx_t) + sizeof(indx_t)) -#define NEXTINDEX(p) (((p)->lower - BTDATAOFF) / sizeof(indx_t)) - -/* - * For pages other than overflow pages, there is an array of offsets into the - * rest of the page immediately following the page header. Each offset is to - * an item which is unique to the type of page. The h_lower offset is just - * past the last filled-in index. The h_upper offset is the first item on the - * page. Offsets are from the beginning of the page. - * - * If an item is too big to store on a single page, a flag is set and the item - * is a { page, size } pair such that the page is the first page of an overflow - * chain with size bytes of item. Overflow pages are simply bytes without any - * external structure. - * - * The page number and size fields in the items are pgno_t-aligned so they can - * be manipulated without copying. (This presumes that 32 bit items can be - * manipulated on this system.) - */ -#define LALIGN(n) (((n) + sizeof(pgno_t) - 1) & ~(sizeof(pgno_t) - 1)) -#define NOVFLSIZE (sizeof(pgno_t) + sizeof(u_int32_t)) - -/* - * For the btree internal pages, the item is a key. BINTERNALs are {key, pgno} - * pairs, such that the key compares less than or equal to all of the records - * on that page. For a tree without duplicate keys, an internal page with two - * consecutive keys, a and b, will have all records greater than or equal to a - * and less than b stored on the page associated with a. Duplicate keys are - * somewhat special and can cause duplicate internal and leaf page records and - * some minor modifications of the above rule. - */ -typedef struct _binternal { - u_int32_t ksize; /* key size */ - pgno_t pgno; /* page number stored on */ -#define P_BIGDATA 0x01 /* overflow data */ -#define P_BIGKEY 0x02 /* overflow key */ - u_char flags; - char bytes[1]; /* data */ -} BINTERNAL; - -/* Get the page's BINTERNAL structure at index indx. */ -#define GETBINTERNAL(pg, indx) \ - ((BINTERNAL *)((char *)(pg) + (pg)->linp[indx])) - -/* Get the number of bytes in the entry. */ -#define NBINTERNAL(len) \ - LALIGN(sizeof(u_int32_t) + sizeof(pgno_t) + sizeof(u_char) + (len)) - -/* Copy a BINTERNAL entry to the page. */ -#define WR_BINTERNAL(p, size, pgno, flags) { \ - *(u_int32_t *)p = size; \ - p += sizeof(u_int32_t); \ - *(pgno_t *)p = pgno; \ - p += sizeof(pgno_t); \ - *(u_char *)p = flags; \ - p += sizeof(u_char); \ -} - -/* - * For the recno internal pages, the item is a page number with the number of - * keys found on that page and below. - */ -typedef struct _rinternal { - recno_t nrecs; /* number of records */ - pgno_t pgno; /* page number stored below */ -} RINTERNAL; - -/* Get the page's RINTERNAL structure at index indx. */ -#define GETRINTERNAL(pg, indx) \ - ((RINTERNAL *)((char *)(pg) + (pg)->linp[indx])) - -/* Get the number of bytes in the entry. */ -#define NRINTERNAL \ - LALIGN(sizeof(recno_t) + sizeof(pgno_t)) - -/* Copy a RINTERNAL entry to the page. */ -#define WR_RINTERNAL(p, nrecs, pgno) { \ - *(recno_t *)p = nrecs; \ - p += sizeof(recno_t); \ - *(pgno_t *)p = pgno; \ -} - -/* For the btree leaf pages, the item is a key and data pair. */ -typedef struct _bleaf { - u_int32_t ksize; /* size of key */ - u_int32_t dsize; /* size of data */ - u_char flags; /* P_BIGDATA, P_BIGKEY */ - char bytes[1]; /* data */ -} BLEAF; - -/* Get the page's BLEAF structure at index indx. */ -#define GETBLEAF(pg, indx) \ - ((BLEAF *)((char *)(pg) + (pg)->linp[indx])) - -/* Get the number of bytes in the entry. */ -#define NBLEAF(p) NBLEAFDBT((p)->ksize, (p)->dsize) - -/* Get the number of bytes in the user's key/data pair. */ -#define NBLEAFDBT(ksize, dsize) \ - LALIGN(sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_char) + \ - (ksize) + (dsize)) - -/* Copy a BLEAF entry to the page. */ -#define WR_BLEAF(p, key, data, flags) { \ - *(u_int32_t *)p = key->size; \ - p += sizeof(u_int32_t); \ - *(u_int32_t *)p = data->size; \ - p += sizeof(u_int32_t); \ - *(u_char *)p = flags; \ - p += sizeof(u_char); \ - memmove(p, key->data, key->size); \ - p += key->size; \ - memmove(p, data->data, data->size); \ -} - -/* For the recno leaf pages, the item is a data entry. */ -typedef struct _rleaf { - u_int32_t dsize; /* size of data */ - u_char flags; /* P_BIGDATA */ - char bytes[1]; -} RLEAF; - -/* Get the page's RLEAF structure at index indx. */ -#define GETRLEAF(pg, indx) \ - ((RLEAF *)((char *)(pg) + (pg)->linp[indx])) - -/* Get the number of bytes in the entry. */ -#define NRLEAF(p) NRLEAFDBT((p)->dsize) - -/* Get the number of bytes from the user's data. */ -#define NRLEAFDBT(dsize) \ - LALIGN(sizeof(u_int32_t) + sizeof(u_char) + (dsize)) - -/* Copy a RLEAF entry to the page. */ -#define WR_RLEAF(p, data, flags) { \ - *(u_int32_t *)p = data->size; \ - p += sizeof(u_int32_t); \ - *(u_char *)p = flags; \ - p += sizeof(u_char); \ - memmove(p, data->data, data->size); \ -} - -/* - * A record in the tree is either a pointer to a page and an index in the page - * or a page number and an index. These structures are used as a cursor, stack - * entry and search returns as well as to pass records to other routines. - * - * One comment about searches. Internal page searches must find the largest - * record less than key in the tree so that descents work. Leaf page searches - * must find the smallest record greater than key so that the returned index - * is the record's correct position for insertion. - */ -typedef struct _epgno { - pgno_t pgno; /* the page number */ - indx_t index; /* the index on the page */ -} EPGNO; - -typedef struct _epg { - PAGE *page; /* the (pinned) page */ - indx_t index; /* the index on the page */ -} EPG; - -/* - * About cursors. The cursor (and the page that contained the key/data pair - * that it referenced) can be deleted, which makes things a bit tricky. If - * there are no duplicates of the cursor key in the tree (i.e. B_NODUPS is set - * or there simply aren't any duplicates of the key) we copy the key that it - * referenced when it's deleted, and reacquire a new cursor key if the cursor - * is used again. If there are duplicates keys, we move to the next/previous - * key, and set a flag so that we know what happened. NOTE: if duplicate (to - * the cursor) keys are added to the tree during this process, it is undefined - * if they will be returned or not in a cursor scan. - * - * The flags determine the possible states of the cursor: - * - * CURS_INIT The cursor references *something*. - * CURS_ACQUIRE The cursor was deleted, and a key has been saved so that - * we can reacquire the right position in the tree. - * CURS_AFTER, CURS_BEFORE - * The cursor was deleted, and now references a key/data pair - * that has not yet been returned, either before or after the - * deleted key/data pair. - * XXX - * This structure is broken out so that we can eventually offer multiple - * cursors as part of the DB interface. - */ -typedef struct _cursor { - EPGNO pg; /* B: Saved tree reference. */ - DBT key; /* B: Saved key, or key.data == NULL. */ - recno_t rcursor; /* R: recno cursor (1-based) */ - -#define CURS_ACQUIRE 0x01 /* B: Cursor needs to be reacquired. */ -#define CURS_AFTER 0x02 /* B: Unreturned cursor after key. */ -#define CURS_BEFORE 0x04 /* B: Unreturned cursor before key. */ -#define CURS_INIT 0x08 /* RB: Cursor initialized. */ - u_int8_t flags; -} CURSOR; - -/* - * The metadata of the tree. The nrecs field is used only by the RECNO code. - * This is because the btree doesn't really need it and it requires that every - * put or delete call modify the metadata. - */ -typedef struct _btmeta { - u_int32_t magic; /* magic number */ - u_int32_t version; /* version */ - u_int32_t psize; /* page size */ - u_int32_t free; /* page number of first free page */ - u_int32_t nrecs; /* R: number of records */ - -#define SAVEMETA (B_NODUPS | R_RECNO) - u_int32_t flags; /* bt_flags & SAVEMETA */ -} BTMETA; - -/* The in-memory btree/recno data structure. */ -typedef struct _btree { - MPOOL *bt_mp; /* memory pool cookie */ - - DB *bt_dbp; /* pointer to enclosing DB */ - - EPG bt_cur; /* current (pinned) page */ - PAGE *bt_pinned; /* page pinned across calls */ - - CURSOR bt_cursor; /* cursor */ - -#define BT_PUSH(t, p, i) { \ - t->bt_sp->pgno = p; \ - t->bt_sp->index = i; \ - ++t->bt_sp; \ -} -#define BT_POP(t) (t->bt_sp == t->bt_stack ? NULL : --t->bt_sp) -#define BT_CLR(t) (t->bt_sp = t->bt_stack) - EPGNO bt_stack[50]; /* stack of parent pages */ - EPGNO *bt_sp; /* current stack pointer */ - - DBT bt_rkey; /* returned key */ - DBT bt_rdata; /* returned data */ - - int bt_fd; /* tree file descriptor */ - - pgno_t bt_free; /* next free page */ - u_int32_t bt_psize; /* page size */ - indx_t bt_ovflsize; /* cut-off for key/data overflow */ - int bt_lorder; /* byte order */ - /* sorted order */ - enum { NOT, BACK, FORWARD } bt_order; - EPGNO bt_last; /* last insert */ - - /* B: key comparison function */ - int (*bt_cmp) __P((const DBT *, const DBT *)); - /* B: prefix comparison function */ - size_t (*bt_pfx) __P((const DBT *, const DBT *)); - /* R: recno input function */ - int (*bt_irec) __P((struct _btree *, recno_t)); - - FILE *bt_rfp; /* R: record FILE pointer */ - int bt_rfd; /* R: record file descriptor */ - - caddr_t bt_cmap; /* R: current point in mapped space */ - caddr_t bt_smap; /* R: start of mapped space */ - caddr_t bt_emap; /* R: end of mapped space */ - size_t bt_msize; /* R: size of mapped region. */ - - recno_t bt_nrecs; /* R: number of records */ - size_t bt_reclen; /* R: fixed record length */ - u_char bt_bval; /* R: delimiting byte/pad character */ - -/* - * NB: - * B_NODUPS and R_RECNO are stored on disk, and may not be changed. - */ -#define B_INMEM 0x00001 /* in-memory tree */ -#define B_METADIRTY 0x00002 /* need to write metadata */ -#define B_MODIFIED 0x00004 /* tree modified */ -#define B_NEEDSWAP 0x00008 /* if byte order requires swapping */ -#define B_RDONLY 0x00010 /* read-only tree */ - -#define B_NODUPS 0x00020 /* no duplicate keys permitted */ -#define R_RECNO 0x00080 /* record oriented tree */ - -#define R_CLOSEFP 0x00040 /* opened a file pointer */ -#define R_EOF 0x00100 /* end of input file reached. */ -#define R_FIXLEN 0x00200 /* fixed length records */ -#define R_MEMMAPPED 0x00400 /* memory mapped file. */ -#define R_INMEM 0x00800 /* in-memory file */ -#define R_MODIFIED 0x01000 /* modified file */ -#define R_RDONLY 0x02000 /* read-only file */ - -#define B_DB_LOCK 0x04000 /* DB_LOCK specified. */ -#define B_DB_SHMEM 0x08000 /* DB_SHMEM specified. */ -#define B_DB_TXN 0x10000 /* DB_TXN specified. */ - u_int32_t flags; -} BTREE; - -#include "extern.h" diff --git a/db/btree/extern.h b/db/btree/extern.h deleted file mode 100644 index ebd9c54..0000000 --- a/db/btree/extern.h +++ /dev/null @@ -1,70 +0,0 @@ -/*- - * Copyright (c) 1991, 1993, 1994 - * The Regents of the University of California. 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. - * - * @(#)extern.h 8.10 (Berkeley) 7/20/94 - */ - -int __bt_close __P((DB *)); -int __bt_cmp __P((BTREE *, const DBT *, EPG *)); -int __bt_crsrdel __P((BTREE *, EPGNO *)); -int __bt_defcmp __P((const DBT *, const DBT *)); -size_t __bt_defpfx __P((const DBT *, const DBT *)); -int __bt_delete __P((const DB *, const DBT *, u_int)); -int __bt_dleaf __P((BTREE *, const DBT *, PAGE *, u_int)); -int __bt_fd __P((const DB *)); -int __bt_free __P((BTREE *, PAGE *)); -int __bt_get __P((const DB *, const DBT *, DBT *, u_int)); -PAGE *__bt_new __P((BTREE *, pgno_t *)); -void __bt_pgin __P((void *, pgno_t, void *)); -void __bt_pgout __P((void *, pgno_t, void *)); -int __bt_push __P((BTREE *, pgno_t, int)); -int __bt_put __P((const DB *dbp, DBT *, const DBT *, u_int)); -int __bt_ret __P((BTREE *, EPG *, DBT *, DBT *, DBT *, DBT *, int)); -EPG *__bt_search __P((BTREE *, const DBT *, int *)); -int __bt_seq __P((const DB *, DBT *, DBT *, u_int)); -void __bt_setcur __P((BTREE *, pgno_t, u_int)); -int __bt_split __P((BTREE *, PAGE *, - const DBT *, const DBT *, int, size_t, u_int32_t)); -int __bt_sync __P((const DB *, u_int)); - -int __ovfl_delete __P((BTREE *, void *)); -int __ovfl_get __P((BTREE *, void *, size_t *, void **, size_t *)); -int __ovfl_put __P((BTREE *, const DBT *, pgno_t *)); - -#ifdef DEBUG -void __bt_dnpage __P((DB *, pgno_t)); -void __bt_dpage __P((PAGE *)); -void __bt_dump __P((DB *)); -#endif -#ifdef STATISTICS -void __bt_stat __P((DB *)); -#endif diff --git a/db/compat.h b/db/compat.h deleted file mode 100644 index 706e582..0000000 --- a/db/compat.h +++ /dev/null @@ -1,49 +0,0 @@ -/* Values for building 4.4 BSD db routines in the GNU C library. */ - -#ifndef _compat_h_ -#define _compat_h_ - -#include <fcntl.h> - -/* - * If you can't provide lock values in the open(2) call. Note, this - * allows races to happen. - */ -#ifndef O_EXLOCK /* 4.4BSD extension. */ -#define O_EXLOCK 0 -#endif - -#ifndef O_SHLOCK /* 4.4BSD extension. */ -#define O_SHLOCK 0 -#endif - -#include <errno.h> - -#ifndef EFTYPE -#define EFTYPE EINVAL /* POSIX 1003.1 format errno. */ -#endif - -#include <unistd.h> -#include <limits.h> - -#ifndef _POSIX_VDISABLE /* POSIX 1003.1 disabling char. */ -#define _POSIX_VDISABLE 0 /* Some systems used 0. */ -#endif - -#include <termios.h> - -#ifndef TCSASOFT /* 4.4BSD extension. */ -#define TCSASOFT 0 -#endif - -#include <sys/param.h> - -#ifndef MAX /* Usually found in <sys/param.h>. */ -#define MAX(_a,_b) ((_a)<(_b)?(_b):(_a)) -#endif -#ifndef MIN /* Usually found in <sys/param.h>. */ -#define MIN(_a,_b) ((_a)<(_b)?(_a):(_b)) -#endif - - -#endif /* compat.h */ diff --git a/db/db.h b/db/db.h deleted file mode 100644 index 183501c..0000000 --- a/db/db.h +++ /dev/null @@ -1,238 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. 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. - * - * @(#)db.h 8.7 (Berkeley) 6/16/94 - */ - -#ifndef _DB_H -#define _DB_H 1 - -#include <sys/types.h> -#include <sys/cdefs.h> - -#include <limits.h> - -#ifdef __DBINTERFACE_PRIVATE -#include <compat.h> -#endif - -#define RET_ERROR -1 /* Return values. */ -#define RET_SUCCESS 0 -#define RET_SPECIAL 1 - -#ifndef __BIT_TYPES_DEFINED__ -#define __BIT_TYPES_DEFINED__ -typedef __signed char int8_t; -typedef unsigned char u_int8_t; -typedef short int16_t; -typedef unsigned short u_int16_t; -typedef int int32_t; -typedef unsigned int u_int32_t; -#ifdef WE_DONT_NEED_QUADS -typedef long long int64_t; -typedef unsigned long long u_int64_t; -#endif -#endif - -#define MAX_PAGE_NUMBER 0xffffffff /* >= # of pages in a file */ -typedef u_int32_t pgno_t; -#define MAX_PAGE_OFFSET 65535 /* >= # of bytes in a page */ -typedef u_int16_t indx_t; -#define MAX_REC_NUMBER 0xffffffff /* >= # of records in a tree */ -typedef u_int32_t recno_t; - -/* Key/data structure -- a Data-Base Thang. */ -typedef struct { - void *data; /* data */ - size_t size; /* data length */ -} DBT; - -/* Routine flags. */ -#define R_CURSOR 1 /* del, put, seq */ -#define __R_UNUSED 2 /* UNUSED */ -#define R_FIRST 3 /* seq */ -#define R_IAFTER 4 /* put (RECNO) */ -#define R_IBEFORE 5 /* put (RECNO) */ -#define R_LAST 6 /* seq (BTREE, RECNO) */ -#define R_NEXT 7 /* seq */ -#define R_NOOVERWRITE 8 /* put */ -#define R_PREV 9 /* seq (BTREE, RECNO) */ -#define R_SETCURSOR 10 /* put (RECNO) */ -#define R_RECNOSYNC 11 /* sync (RECNO) */ - -typedef enum { DB_BTREE, DB_HASH, DB_RECNO } DBTYPE; - -/* - * !!! - * The following flags are included in the dbopen(3) call as part of the - * open(2) flags. In order to avoid conflicts with the open flags, start - * at the top of the 16 or 32-bit number space and work our way down. If - * the open flags were significantly expanded in the future, it could be - * a problem. Wish I'd left another flags word in the dbopen call. - * - * !!! - * None of this stuff is implemented yet. The only reason that it's here - * is so that the access methods can skip copying the key/data pair when - * the DB_LOCK flag isn't set. - */ -#if UINT_MAX > 65535 -#define DB_LOCK 0x20000000 /* Do locking. */ -#define DB_SHMEM 0x40000000 /* Use shared memory. */ -#define DB_TXN 0x80000000 /* Do transactions. */ -#else -#define DB_LOCK 0x2000 /* Do locking. */ -#define DB_SHMEM 0x4000 /* Use shared memory. */ -#define DB_TXN 0x8000 /* Do transactions. */ -#endif - -/* Access method description structure. */ -typedef struct __db { - DBTYPE type; /* Underlying db type. */ - int (*close) (struct __db *); - int (*del) (const struct __db *, const DBT *, u_int); - int (*get) (const struct __db *, const DBT *, DBT *, u_int); - int (*put) (const struct __db *, DBT *, const DBT *, u_int); - int (*seq) (const struct __db *, DBT *, DBT *, u_int); - int (*sync) (const struct __db *, u_int); - void *internal; /* Access method private. */ - int (*fd) (const struct __db *); -} DB; - -#define BTREEMAGIC 0x053162 -#define BTREEVERSION 3 - -/* Structure used to pass parameters to the btree routines. */ -typedef struct { -#define R_DUP 0x01 /* duplicate keys */ - u_long flags; - u_int cachesize; /* bytes to cache */ - int maxkeypage; /* maximum keys per page */ - int minkeypage; /* minimum keys per page */ - u_int psize; /* page size */ - int (*compare) /* comparison function */ - (const DBT *, const DBT *); - size_t (*prefix) /* prefix function */ - (const DBT *, const DBT *); - int lorder; /* byte order */ -} BTREEINFO; - -#define HASHMAGIC 0x061561 -#define HASHVERSION 2 - -/* Structure used to pass parameters to the hashing routines. */ -typedef struct { - u_int bsize; /* bucket size */ - u_int ffactor; /* fill factor */ - u_int nelem; /* number of elements */ - u_int cachesize; /* bytes to cache */ - u_int32_t /* hash function */ - (*hash) (const void *, size_t); - int lorder; /* byte order */ -} HASHINFO; - -/* Structure used to pass parameters to the record routines. */ -typedef struct { -#define R_FIXEDLEN 0x01 /* fixed-length records */ -#define R_NOKEY 0x02 /* key not required */ -#define R_SNAPSHOT 0x04 /* snapshot the input */ - u_long flags; - u_int cachesize; /* bytes to cache */ - u_int psize; /* page size */ - int lorder; /* byte order */ - size_t reclen; /* record length (fixed-length records) */ - u_char bval; /* delimiting byte (variable-length records */ - char *bfname; /* btree file name */ -} RECNOINFO; - -#ifdef __DBINTERFACE_PRIVATE -/* - * Little endian <==> big endian 32-bit swap macros. - * M_32_SWAP swap a memory location - * P_32_SWAP swap a referenced memory location - * P_32_COPY swap from one location to another - */ -#define M_32_SWAP(a) { \ - u_int32_t _tmp = a; \ - ((char *)&a)[0] = ((char *)&_tmp)[3]; \ - ((char *)&a)[1] = ((char *)&_tmp)[2]; \ - ((char *)&a)[2] = ((char *)&_tmp)[1]; \ - ((char *)&a)[3] = ((char *)&_tmp)[0]; \ -} -#define P_32_SWAP(a) { \ - u_int32_t _tmp = *(u_int32_t *)a; \ - ((char *)a)[0] = ((char *)&_tmp)[3]; \ - ((char *)a)[1] = ((char *)&_tmp)[2]; \ - ((char *)a)[2] = ((char *)&_tmp)[1]; \ - ((char *)a)[3] = ((char *)&_tmp)[0]; \ -} -#define P_32_COPY(a, b) { \ - ((char *)&(b))[0] = ((char *)&(a))[3]; \ - ((char *)&(b))[1] = ((char *)&(a))[2]; \ - ((char *)&(b))[2] = ((char *)&(a))[1]; \ - ((char *)&(b))[3] = ((char *)&(a))[0]; \ -} - -/* - * Little endian <==> big endian 16-bit swap macros. - * M_16_SWAP swap a memory location - * P_16_SWAP swap a referenced memory location - * P_16_COPY swap from one location to another - */ -#define M_16_SWAP(a) { \ - u_int16_t _tmp = a; \ - ((char *)&a)[0] = ((char *)&_tmp)[1]; \ - ((char *)&a)[1] = ((char *)&_tmp)[0]; \ -} -#define P_16_SWAP(a) { \ - u_int16_t _tmp = *(u_int16_t *)a; \ - ((char *)a)[0] = ((char *)&_tmp)[1]; \ - ((char *)a)[1] = ((char *)&_tmp)[0]; \ -} -#define P_16_COPY(a, b) { \ - ((char *)&(b))[0] = ((char *)&(a))[1]; \ - ((char *)&(b))[1] = ((char *)&(a))[0]; \ -} -#endif - -__BEGIN_DECLS -DB *__dbopen (const char *, int, int, DBTYPE, const void *) __THROW; -DB *dbopen (const char *, int, int, DBTYPE, const void *) __THROW; - -#ifdef __DBINTERFACE_PRIVATE -DB *__bt_open (const char *, int, int, const BTREEINFO *, int) __THROW; -DB *__hash_open (const char *, int, int, const HASHINFO *, int) __THROW; -DB *__rec_open (const char *, int, int, const RECNOINFO *, int) __THROW; -void __dbpanic (DB *dbp) __THROW; -#endif -__END_DECLS - -#endif /* db.h */ diff --git a/db/db/db.c b/db/db/db.c deleted file mode 100644 index 49f6124..0000000 --- a/db/db/db.c +++ /dev/null @@ -1,113 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. 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. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)db.c 8.4 (Berkeley) 2/21/94"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/types.h> - -#include <errno.h> -#include <fcntl.h> -#include <stddef.h> -#include <stdio.h> - -#include <db.h> - -#ifdef _LIBC -/* In the GNU C library we must not pollute the namespace, because libdb - is needed by libnss_db. */ -#define dbopen __dbopen -#endif - -DB * -dbopen(fname, flags, mode, type, openinfo) - const char *fname; - int flags, mode; - DBTYPE type; - const void *openinfo; -{ - -#define DB_FLAGS (DB_LOCK | DB_SHMEM | DB_TXN) -#define USE_OPEN_FLAGS \ - (O_CREAT | O_EXCL | O_EXLOCK | O_NONBLOCK | O_RDONLY | \ - O_RDWR | O_SHLOCK | O_TRUNC) - - if ((flags & ~(USE_OPEN_FLAGS | DB_FLAGS)) == 0) - switch (type) { - case DB_BTREE: - return (__bt_open(fname, flags & USE_OPEN_FLAGS, - mode, openinfo, flags & DB_FLAGS)); - case DB_HASH: - return (__hash_open(fname, flags & USE_OPEN_FLAGS, - mode, openinfo, flags & DB_FLAGS)); - case DB_RECNO: - return (__rec_open(fname, flags & USE_OPEN_FLAGS, - mode, openinfo, flags & DB_FLAGS)); - } - errno = EINVAL; - return (NULL); -} -#ifdef _LIBC -#undef dbopen -weak_alias (__dbopen, dbopen) -#endif - -static int -__dberr __P((void)) -{ - return (RET_ERROR); -} - -/* - * __DBPANIC -- Stop. - * - * Parameters: - * dbp: pointer to the DB structure. - */ -void -__dbpanic(dbp) - DB *dbp; -{ - /* The only thing that can succeed is a close. */ - dbp->del = (int (*)__P((const struct __db *, - const DBT *, u_int))) __dberr; - dbp->get = (int (*)__P((const struct __db *, - const DBT *, DBT *, u_int))) __dberr; - dbp->put = (int (*)__P((const struct __db *, - DBT *, const DBT *, u_int))) __dberr; - dbp->seq = (int (*)__P((const struct __db *, - DBT *, DBT *, u_int))) __dberr; - dbp->sync = (int (*)__P((const struct __db *, u_int))) __dberr; - dbp->fd = (int (*)__P((const struct __db *))) __dberr; -} diff --git a/db/hash/extern.h b/db/hash/extern.h deleted file mode 100644 index 4f1f23d..0000000 --- a/db/hash/extern.h +++ /dev/null @@ -1,65 +0,0 @@ -/*- - * Copyright (c) 1991, 1993, 1994 - * The Regents of the University of California. 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. - * - * @(#)extern.h 8.4 (Berkeley) 6/16/94 - */ - -BUFHEAD *__add_ovflpage __P((HTAB *, BUFHEAD *)); -int __addel __P((HTAB *, BUFHEAD *, const DBT *, const DBT *)); -int __big_delete __P((HTAB *, BUFHEAD *)); -int __big_insert __P((HTAB *, BUFHEAD *, const DBT *, const DBT *)); -int __big_keydata __P((HTAB *, BUFHEAD *, DBT *, DBT *, int)); -int __big_return __P((HTAB *, BUFHEAD *, int, DBT *, int)); -int __big_split __P((HTAB *, BUFHEAD *, BUFHEAD *, BUFHEAD *, - int, u_int32_t, SPLIT_RETURN *)); -int __buf_free __P((HTAB *, int, int)); -void __buf_init __P((HTAB *, int)); -u_int32_t __call_hash __P((HTAB *, char *, int)); -int __delpair __P((HTAB *, BUFHEAD *, int)); -int __expand_table __P((HTAB *)); -int __find_bigpair __P((HTAB *, BUFHEAD *, int, char *, int)); -u_int16_t __find_last_page __P((HTAB *, BUFHEAD **)); -void __free_ovflpage __P((HTAB *, BUFHEAD *)); -BUFHEAD *__get_buf __P((HTAB *, u_int32_t, BUFHEAD *, int)); -int __get_page __P((HTAB *, char *, u_int32_t, int, int, int)); -int __ibitmap __P((HTAB *, int, int, int)); -u_int32_t __hash_log2 __P((u_int32_t)); -int __put_page __P((HTAB *, char *, u_int32_t, int, int)); -void __reclaim_buf __P((HTAB *, BUFHEAD *)); -int __split_page __P((HTAB *, u_int32_t, u_int32_t)); - -/* Default hash routine. */ -extern u_int32_t (*__default_hash) __P((const void *, size_t)); - -#ifdef HASH_STATISTICS -extern int hash_accesses, hash_collisions, hash_expansions, hash_overflows; -#endif diff --git a/db/hash/hash.c b/db/hash/hash.c deleted file mode 100644 index 99592ea..0000000 --- a/db/hash/hash.c +++ /dev/null @@ -1,999 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * 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. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)hash.c 8.9 (Berkeley) 6/16/94"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/param.h> -#include <sys/stat.h> - -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#ifdef DEBUG -#include <assert.h> -#endif - -#include <db.h> -#include "hash.h" -#include "page.h" -#include "extern.h" - -static int alloc_segs __P((HTAB *, int)); -static int flush_meta __P((HTAB *)); -static int hash_access __P((HTAB *, ACTION, DBT *, DBT *)); -static int hash_close __P((DB *)); -static int hash_delete __P((const DB *, const DBT *, u_int32_t)); -static int hash_fd __P((const DB *)); -static int hash_get __P((const DB *, const DBT *, DBT *, u_int32_t)); -static int hash_put __P((const DB *, DBT *, const DBT *, u_int32_t)); -static void *hash_realloc __P((SEGMENT **, int, int)); -static int hash_seq __P((const DB *, DBT *, DBT *, u_int32_t)); -static int hash_sync __P((const DB *, u_int32_t)); -static int hdestroy __P((HTAB *)); -static HTAB *init_hash __P((HTAB *, const char *, HASHINFO *)); -static int init_htab __P((HTAB *, int)); -#if BYTE_ORDER == LITTLE_ENDIAN -static void swap_header __P((HTAB *)); -static void swap_header_copy __P((HASHHDR *, HASHHDR *)); -#endif - -/* Fast arithmetic, relying on powers of 2, */ -#define MOD(x, y) ((x) & ((y) - 1)) - -#define RETURN_ERROR(ERR, LOC) { save_errno = ERR; goto LOC; } - -/* Return values */ -#define SUCCESS (0) -#define ERROR (-1) -#define ABNORMAL (1) - -#ifdef HASH_STATISTICS -int hash_accesses, hash_collisions, hash_expansions, hash_overflows; -#endif - -/************************** INTERFACE ROUTINES ***************************/ -/* OPEN/CLOSE */ - -extern DB * -__hash_open(file, flags, mode, info, dflags) - const char *file; - int flags, mode, dflags; - const HASHINFO *info; /* Special directives for create */ -{ - HTAB *hashp; - struct stat statbuf; - DB *dbp; - int bpages, hdrsize, new_table, nsegs, save_errno; - - if ((flags & O_ACCMODE) == O_WRONLY) { - errno = EINVAL; - return (NULL); - } - - if (!(hashp = (HTAB *)calloc(1, sizeof(HTAB)))) - return (NULL); - hashp->fp = -1; - - /* - * Even if user wants write only, we need to be able to read - * the actual file, so we need to open it read/write. But, the - * field in the hashp structure needs to be accurate so that - * we can check accesses. - */ - hashp->flags = flags; - - new_table = 0; - if (!file || (flags & O_TRUNC) || - (stat(file, &statbuf) && (errno == ENOENT))) { - if (errno == ENOENT) - errno = 0; /* Just in case someone looks at errno */ - new_table = 1; - } - if (file) { - if ((hashp->fp = open(file, flags, mode)) == -1) - RETURN_ERROR(errno, error0); - (void)fcntl(hashp->fp, F_SETFD, 1); - } - if (new_table) { - if (!(hashp = init_hash(hashp, file, (HASHINFO *)info))) - RETURN_ERROR(errno, error1); - } else { - /* Table already exists */ - if (info && info->hash) - hashp->hash = info->hash; - else - hashp->hash = __default_hash; - - hdrsize = read(hashp->fp, &hashp->hdr, sizeof(HASHHDR)); -#if BYTE_ORDER == LITTLE_ENDIAN - swap_header(hashp); -#endif - if (hdrsize == -1) - RETURN_ERROR(errno, error1); - if (hdrsize != sizeof(HASHHDR)) - RETURN_ERROR(EFTYPE, error1); - /* Verify file type, versions and hash function */ - if (hashp->MAGIC != HASHMAGIC) - RETURN_ERROR(EFTYPE, error1); -#define OLDHASHVERSION 1 - if (hashp->VERSION != HASHVERSION && - hashp->VERSION != OLDHASHVERSION) - RETURN_ERROR(EFTYPE, error1); - if (hashp->hash(CHARKEY, sizeof(CHARKEY)) - != (u_int32_t) hashp->H_CHARKEY) - RETURN_ERROR(EFTYPE, error1); - /* - * Figure out how many segments we need. Max_Bucket is the - * maximum bucket number, so the number of buckets is - * max_bucket + 1. - */ - nsegs = (hashp->MAX_BUCKET + 1 + hashp->SGSIZE - 1) / - hashp->SGSIZE; - hashp->nsegs = 0; - if (alloc_segs(hashp, nsegs)) - /* - * If alloc_segs fails, table will have been destroyed - * and errno will have been set. - */ - return (NULL); - /* Read in bitmaps */ - bpages = (hashp->SPARES[hashp->OVFL_POINT] + - (hashp->BSIZE << BYTE_SHIFT) - 1) >> - (hashp->BSHIFT + BYTE_SHIFT); - - hashp->nmaps = bpages; - (void)memset(&hashp->mapp[0], 0, bpages * sizeof(u_int32_t *)); - } - - /* Initialize Buffer Manager */ - if (info && info->cachesize) - __buf_init(hashp, info->cachesize); - else - __buf_init(hashp, DEF_BUFSIZE); - - hashp->new_file = new_table; - hashp->save_file = file && (hashp->flags & O_ACCMODE) != O_RDONLY; - hashp->cbucket = -1; - if (!(dbp = (DB *)malloc(sizeof(DB)))) { - save_errno = errno; - hdestroy(hashp); - errno = save_errno; - return (NULL); - } - dbp->internal = hashp; - dbp->close = hash_close; - dbp->del = hash_delete; - dbp->fd = hash_fd; - dbp->get = hash_get; - dbp->put = hash_put; - dbp->seq = hash_seq; - dbp->sync = hash_sync; - dbp->type = DB_HASH; - -#ifdef DEBUG - (void)fprintf(stderr, -"%s\n%s%x\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%x\n%s%x\n%s%d\n%s%d\n", - "init_htab:", - "TABLE POINTER ", hashp, - "BUCKET SIZE ", hashp->BSIZE, - "BUCKET SHIFT ", hashp->BSHIFT, - "DIRECTORY SIZE ", hashp->DSIZE, - "SEGMENT SIZE ", hashp->SGSIZE, - "SEGMENT SHIFT ", hashp->SSHIFT, - "FILL FACTOR ", hashp->FFACTOR, - "MAX BUCKET ", hashp->MAX_BUCKET, - "OVFL POINT ", hashp->OVFL_POINT, - "LAST FREED ", hashp->LAST_FREED, - "HIGH MASK ", hashp->HIGH_MASK, - "LOW MASK ", hashp->LOW_MASK, - "NSEGS ", hashp->nsegs, - "NKEYS ", hashp->NKEYS); -#endif -#ifdef HASH_STATISTICS - hash_overflows = hash_accesses = hash_collisions = hash_expansions = 0; -#endif - return (dbp); - -error1: - if (hashp != NULL) - (void)close(hashp->fp); - -error0: - free(hashp); - errno = save_errno; - return (NULL); -} - -static int -hash_close(dbp) - DB *dbp; -{ - HTAB *hashp; - int retval; - - if (!dbp) - return (ERROR); - - hashp = (HTAB *)dbp->internal; - retval = hdestroy(hashp); - free(dbp); - return (retval); -} - -static int -hash_fd(dbp) - const DB *dbp; -{ - HTAB *hashp; - - if (!dbp) - return (ERROR); - - hashp = (HTAB *)dbp->internal; - if (hashp->fp == -1) { - errno = ENOENT; - return (-1); - } - return (hashp->fp); -} - -/************************** LOCAL CREATION ROUTINES **********************/ -static HTAB * -init_hash(hashp, file, info) - HTAB *hashp; - const char *file; - HASHINFO *info; -{ -#ifdef _STATBUF_ST_BLKSIZE - struct stat statbuf; -#endif - int nelem; - - nelem = 1; - hashp->NKEYS = 0; - hashp->LORDER = BYTE_ORDER; - hashp->BSIZE = DEF_BUCKET_SIZE; - hashp->BSHIFT = DEF_BUCKET_SHIFT; - hashp->SGSIZE = DEF_SEGSIZE; - hashp->SSHIFT = DEF_SEGSIZE_SHIFT; - hashp->DSIZE = DEF_DIRSIZE; - hashp->FFACTOR = DEF_FFACTOR; - hashp->hash = __default_hash; - memset(hashp->SPARES, 0, sizeof(hashp->SPARES)); - memset(hashp->BITMAPS, 0, sizeof (hashp->BITMAPS)); - - /* Fix bucket size to be optimal for file system */ -#ifdef _STATBUF_ST_BLKSIZE - if (file != NULL) { - if (stat(file, &statbuf)) - return (NULL); - hashp->BSIZE = statbuf.st_blksize; - hashp->BSHIFT = __hash_log2(hashp->BSIZE); - } -#endif - - if (info) { - if (info->bsize) { - /* Round pagesize up to power of 2 */ - hashp->BSHIFT = __hash_log2(info->bsize); - hashp->BSIZE = 1 << hashp->BSHIFT; - if (hashp->BSIZE > MAX_BSIZE) { - errno = EINVAL; - return (NULL); - } - } - if (info->ffactor) - hashp->FFACTOR = info->ffactor; - if (info->hash) - hashp->hash = info->hash; - if (info->nelem) - nelem = info->nelem; - if (info->lorder) { - if (info->lorder != BIG_ENDIAN && - info->lorder != LITTLE_ENDIAN) { - errno = EINVAL; - return (NULL); - } - hashp->LORDER = info->lorder; - } - } - /* init_htab should destroy the table and set errno if it fails */ - if (init_htab(hashp, nelem)) - return (NULL); - else - return (hashp); -} -/* - * This calls alloc_segs which may run out of memory. Alloc_segs will destroy - * the table and set errno, so we just pass the error information along. - * - * Returns 0 on No Error - */ -static int -init_htab(hashp, nelem) - HTAB *hashp; - int nelem; -{ - register int nbuckets, nsegs; - int l2; - - /* - * Divide number of elements by the fill factor and determine a - * desired number of buckets. Allocate space for the next greater - * power of two number of buckets. - */ - nelem = (nelem - 1) / hashp->FFACTOR + 1; - - l2 = __hash_log2(MAX(nelem, 2)); - nbuckets = 1 << l2; - - hashp->SPARES[l2] = l2 + 1; - hashp->SPARES[l2 + 1] = l2 + 1; - hashp->OVFL_POINT = l2; - hashp->LAST_FREED = 2; - - /* First bitmap page is at: splitpoint l2 page offset 1 */ - if (__ibitmap(hashp, OADDR_OF(l2, 1), l2 + 1, 0)) - return (-1); - - hashp->MAX_BUCKET = hashp->LOW_MASK = nbuckets - 1; - hashp->HIGH_MASK = (nbuckets << 1) - 1; - hashp->HDRPAGES = ((MAX(sizeof(HASHHDR), MINHDRSIZE) - 1) >> - hashp->BSHIFT) + 1; - - nsegs = (nbuckets - 1) / hashp->SGSIZE + 1; - nsegs = 1 << __hash_log2(nsegs); - - if (nsegs > hashp->DSIZE) - hashp->DSIZE = nsegs; - return (alloc_segs(hashp, nsegs)); -} - -/********************** DESTROY/CLOSE ROUTINES ************************/ - -/* - * Flushes any changes to the file if necessary and destroys the hashp - * structure, freeing all allocated space. - */ -static int -hdestroy(hashp) - HTAB *hashp; -{ - int i, save_errno; - - save_errno = 0; - -#ifdef HASH_STATISTICS - (void)fprintf(stderr, "hdestroy: accesses %ld collisions %ld\n", - hash_accesses, hash_collisions); - (void)fprintf(stderr, "hdestroy: expansions %ld\n", - hash_expansions); - (void)fprintf(stderr, "hdestroy: overflows %ld\n", - hash_overflows); - (void)fprintf(stderr, "keys %ld maxp %d segmentcount %d\n", - hashp->NKEYS, hashp->MAX_BUCKET, hashp->nsegs); - - for (i = 0; i < NCACHED; i++) - (void)fprintf(stderr, - "spares[%d] = %d\n", i, hashp->SPARES[i]); -#endif - /* - * Call on buffer manager to free buffers, and if required, - * write them to disk. - */ - if (__buf_free(hashp, 1, hashp->save_file)) - save_errno = errno; - if (hashp->dir) { - free(*hashp->dir); /* Free initial segments */ - /* Free extra segments */ - while (hashp->exsegs--) - free(hashp->dir[--hashp->nsegs]); - free(hashp->dir); - } - if (flush_meta(hashp) && !save_errno) - save_errno = errno; - /* Free Bigmaps */ - for (i = 0; i < hashp->nmaps; i++) - if (hashp->mapp[i]) - free(hashp->mapp[i]); - - if (hashp->fp != -1) - (void)close(hashp->fp); - - free(hashp); - - if (save_errno) { - errno = save_errno; - return (ERROR); - } - return (SUCCESS); -} -/* - * Write modified pages to disk - * - * Returns: - * 0 == OK - * -1 ERROR - */ -static int -hash_sync(dbp, flags) - const DB *dbp; - u_int32_t flags; -{ - HTAB *hashp; - - if (flags != 0) { - errno = EINVAL; - return (ERROR); - } - - if (!dbp) - return (ERROR); - - hashp = (HTAB *)dbp->internal; - if (!hashp->save_file) - return (0); - if (__buf_free(hashp, 0, 1) || flush_meta(hashp)) - return (ERROR); - hashp->new_file = 0; - return (0); -} - -/* - * Returns: - * 0 == OK - * -1 indicates that errno should be set - */ -static int -flush_meta(hashp) - HTAB *hashp; -{ - HASHHDR *whdrp; -#if BYTE_ORDER == LITTLE_ENDIAN - HASHHDR whdr; -#endif - int fp, i, wsize; - - if (!hashp->save_file) - return (0); - hashp->MAGIC = HASHMAGIC; - hashp->VERSION = HASHVERSION; - hashp->H_CHARKEY = hashp->hash(CHARKEY, sizeof(CHARKEY)); - - fp = hashp->fp; - whdrp = &hashp->hdr; -#if BYTE_ORDER == LITTLE_ENDIAN - whdrp = &whdr; - swap_header_copy(&hashp->hdr, whdrp); -#endif - if ((lseek(fp, (off_t)0, SEEK_SET) == -1) || - ((wsize = write(fp, whdrp, sizeof(HASHHDR))) == -1)) - return (-1); - else - if (wsize != sizeof(HASHHDR)) { - errno = EFTYPE; - hashp->errnum = errno; - return (-1); - } - for (i = 0; i < NCACHED; i++) - if (hashp->mapp[i]) - if (__put_page(hashp, (char *)hashp->mapp[i], - hashp->BITMAPS[i], 0, 1)) - return (-1); - return (0); -} - -/*******************************SEARCH ROUTINES *****************************/ -/* - * All the access routines return - * - * Returns: - * 0 on SUCCESS - * 1 to indicate an external ERROR (i.e. key not found, etc) - * -1 to indicate an internal ERROR (i.e. out of memory, etc) - */ -static int -hash_get(dbp, key, data, flag) - const DB *dbp; - const DBT *key; - DBT *data; - u_int32_t flag; -{ - HTAB *hashp; - - hashp = (HTAB *)dbp->internal; - if (flag) { - hashp->errnum = errno = EINVAL; - return (ERROR); - } - return (hash_access(hashp, HASH_GET, (DBT *)key, data)); -} - -static int -hash_put(dbp, key, data, flag) - const DB *dbp; - DBT *key; - const DBT *data; - u_int32_t flag; -{ - HTAB *hashp; - - hashp = (HTAB *)dbp->internal; - if (flag && flag != R_NOOVERWRITE) { - hashp->errnum = errno = EINVAL; - return (ERROR); - } - if ((hashp->flags & O_ACCMODE) == O_RDONLY) { - hashp->errnum = errno = EPERM; - return (ERROR); - } - return (hash_access(hashp, flag == R_NOOVERWRITE ? - HASH_PUTNEW : HASH_PUT, (DBT *)key, (DBT *)data)); -} - -static int -hash_delete(dbp, key, flag) - const DB *dbp; - const DBT *key; - u_int32_t flag; /* Ignored */ -{ - HTAB *hashp; - - hashp = (HTAB *)dbp->internal; - if (flag && flag != R_CURSOR) { - hashp->errnum = errno = EINVAL; - return (ERROR); - } - if ((hashp->flags & O_ACCMODE) == O_RDONLY) { - hashp->errnum = errno = EPERM; - return (ERROR); - } - return (hash_access(hashp, HASH_DELETE, (DBT *)key, NULL)); -} - -/* - * Assume that hashp has been set in wrapper routine. - */ -static int -hash_access(hashp, action, key, val) - HTAB *hashp; - ACTION action; - DBT *key, *val; -{ - register BUFHEAD *rbufp; - BUFHEAD *bufp, *save_bufp; - register u_int16_t *bp; - register int n, ndx, off, size; - register char *kp; - u_int16_t pageno; - -#ifdef HASH_STATISTICS - hash_accesses++; -#endif - - off = hashp->BSIZE; - size = key->size; - kp = (char *)key->data; - rbufp = __get_buf(hashp, __call_hash(hashp, kp, size), NULL, 0); - if (!rbufp) - return (ERROR); - save_bufp = rbufp; - - /* Pin the bucket chain */ - rbufp->flags |= BUF_PIN; - for (bp = (u_int16_t *)rbufp->page, n = *bp++, ndx = 1; ndx < n;) - if (bp[1] >= REAL_KEY) { - /* Real key/data pair */ - if (size == off - *bp && - memcmp(kp, rbufp->page + *bp, size) == 0) - goto found; - off = bp[1]; -#ifdef HASH_STATISTICS - hash_collisions++; -#endif - bp += 2; - ndx += 2; - } else if (bp[1] == OVFLPAGE) { - rbufp = __get_buf(hashp, *bp, rbufp, 0); - if (!rbufp) { - save_bufp->flags &= ~BUF_PIN; - return (ERROR); - } - /* FOR LOOP INIT */ - bp = (u_int16_t *)rbufp->page; - n = *bp++; - ndx = 1; - off = hashp->BSIZE; - } else if (bp[1] < REAL_KEY) { - if ((ndx = - __find_bigpair(hashp, rbufp, ndx, kp, size)) > 0) - goto found; - if (ndx == -2) { - bufp = rbufp; - if (!(pageno = - __find_last_page(hashp, &bufp))) { - ndx = 0; - rbufp = bufp; - break; /* FOR */ - } - rbufp = __get_buf(hashp, pageno, bufp, 0); - if (!rbufp) { - save_bufp->flags &= ~BUF_PIN; - return (ERROR); - } - /* FOR LOOP INIT */ - bp = (u_int16_t *)rbufp->page; - n = *bp++; - ndx = 1; - off = hashp->BSIZE; - } else { - save_bufp->flags &= ~BUF_PIN; - return (ERROR); - } - } - - /* Not found */ - switch (action) { - case HASH_PUT: - case HASH_PUTNEW: - if (__addel(hashp, rbufp, key, val)) { - save_bufp->flags &= ~BUF_PIN; - return (ERROR); - } else { - save_bufp->flags &= ~BUF_PIN; - return (SUCCESS); - } - case HASH_GET: - case HASH_DELETE: - default: - save_bufp->flags &= ~BUF_PIN; - return (ABNORMAL); - } - -found: - switch (action) { - case HASH_PUTNEW: - save_bufp->flags &= ~BUF_PIN; - return (ABNORMAL); - case HASH_GET: - bp = (u_int16_t *)rbufp->page; - if (bp[ndx + 1] < REAL_KEY) { - if (__big_return(hashp, rbufp, ndx, val, 0)) - return (ERROR); - } else { - val->data = (u_char *)rbufp->page + (int)bp[ndx + 1]; - val->size = bp[ndx] - bp[ndx + 1]; - } - break; - case HASH_PUT: - if ((__delpair(hashp, rbufp, ndx)) || - (__addel(hashp, rbufp, key, val))) { - save_bufp->flags &= ~BUF_PIN; - return (ERROR); - } - break; - case HASH_DELETE: - if (__delpair(hashp, rbufp, ndx)) - return (ERROR); - break; - default: - abort(); - } - save_bufp->flags &= ~BUF_PIN; - return (SUCCESS); -} - -static int -hash_seq(dbp, key, data, flag) - const DB *dbp; - DBT *key, *data; - u_int32_t flag; -{ - register u_int32_t bucket; - register BUFHEAD *bufp; - HTAB *hashp; - u_int16_t *bp, ndx; - - hashp = (HTAB *)dbp->internal; - if (flag && flag != R_FIRST && flag != R_NEXT) { - hashp->errnum = errno = EINVAL; - return (ERROR); - } -#ifdef HASH_STATISTICS - hash_accesses++; -#endif - if ((hashp->cbucket < 0) || (flag == R_FIRST)) { - hashp->cbucket = 0; - hashp->cndx = 1; - hashp->cpage = NULL; - } - - for (bp = NULL; !bp || !bp[0]; ) { - if (!(bufp = hashp->cpage)) { - for (bucket = hashp->cbucket; - bucket <= (u_int32_t) hashp->MAX_BUCKET; - bucket++, hashp->cndx = 1) { - bufp = __get_buf(hashp, bucket, NULL, 0); - if (!bufp) - return (ERROR); - hashp->cpage = bufp; - bp = (u_int16_t *)bufp->page; - if (bp[0]) - break; - } - hashp->cbucket = bucket; - if (hashp->cbucket > hashp->MAX_BUCKET) { - hashp->cbucket = -1; - return (ABNORMAL); - } - } else - bp = (u_int16_t *)hashp->cpage->page; - -#ifdef DEBUG - assert(bp); - assert(bufp); -#endif - while (bp[hashp->cndx + 1] == OVFLPAGE) { - bufp = hashp->cpage = - __get_buf(hashp, bp[hashp->cndx], bufp, 0); - if (!bufp) - return (ERROR); - bp = (u_int16_t *)(bufp->page); - hashp->cndx = 1; - } - if (!bp[0]) { - hashp->cpage = NULL; - ++hashp->cbucket; - } - } - ndx = hashp->cndx; - if (bp[ndx + 1] < REAL_KEY) { - if (__big_keydata(hashp, bufp, key, data, 1)) - return (ERROR); - } else { - key->data = (u_char *)hashp->cpage->page + bp[ndx]; - key->size = (ndx > 1 ? bp[ndx - 1] : hashp->BSIZE) - bp[ndx]; - data->data = (u_char *)hashp->cpage->page + bp[ndx + 1]; - data->size = bp[ndx] - bp[ndx + 1]; - ndx += 2; - if (ndx > bp[0]) { - hashp->cpage = NULL; - hashp->cbucket++; - hashp->cndx = 1; - } else - hashp->cndx = ndx; - } - return (SUCCESS); -} - -/********************************* UTILITIES ************************/ - -/* - * Returns: - * 0 ==> OK - * -1 ==> Error - */ -extern int -__expand_table(hashp) - HTAB *hashp; -{ - u_int32_t old_bucket, new_bucket; - int dirsize, new_segnum, spare_ndx; - -#ifdef HASH_STATISTICS - hash_expansions++; -#endif - new_bucket = ++hashp->MAX_BUCKET; - old_bucket = (hashp->MAX_BUCKET & hashp->LOW_MASK); - - new_segnum = new_bucket >> hashp->SSHIFT; - - /* Check if we need a new segment */ - if (new_segnum >= hashp->nsegs) { - /* Check if we need to expand directory */ - if (new_segnum >= hashp->DSIZE) { - /* Reallocate directory */ - dirsize = hashp->DSIZE * sizeof(SEGMENT *); - if (!hash_realloc(&hashp->dir, dirsize, dirsize << 1)) - return (-1); - hashp->DSIZE = dirsize << 1; - } - if ((hashp->dir[new_segnum] = - (SEGMENT)calloc(hashp->SGSIZE, sizeof(SEGMENT))) == NULL) - return (-1); - hashp->exsegs++; - hashp->nsegs++; - } - /* - * If the split point is increasing (MAX_BUCKET's log base 2 - * * increases), we need to copy the current contents of the spare - * split bucket to the next bucket. - */ - spare_ndx = __hash_log2(hashp->MAX_BUCKET + 1); - if (spare_ndx > hashp->OVFL_POINT) { - hashp->SPARES[spare_ndx] = hashp->SPARES[hashp->OVFL_POINT]; - hashp->OVFL_POINT = spare_ndx; - } - - if (new_bucket > (u_int32_t) hashp->HIGH_MASK) { - /* Starting a new doubling */ - hashp->LOW_MASK = hashp->HIGH_MASK; - hashp->HIGH_MASK = new_bucket | hashp->LOW_MASK; - } - /* Relocate records to the new bucket */ - return (__split_page(hashp, old_bucket, new_bucket)); -} - -/* - * If realloc guarantees that the pointer is not destroyed if the realloc - * fails, then this routine can go away. - */ -static void * -hash_realloc(p_ptr, oldsize, newsize) - SEGMENT **p_ptr; - int oldsize, newsize; -{ - register void *p; - - if ((p = malloc(newsize))) { - memmove(p, *p_ptr, oldsize); - memset((char *)p + oldsize, 0, newsize - oldsize); - free(*p_ptr); - *p_ptr = p; - } - return (p); -} - -extern u_int32_t -__call_hash(hashp, k, len) - HTAB *hashp; - char *k; - int len; -{ - int n, bucket; - - n = hashp->hash(k, len); - bucket = n & hashp->HIGH_MASK; - if (bucket > hashp->MAX_BUCKET) - bucket = bucket & hashp->LOW_MASK; - return (bucket); -} - -/* - * Allocate segment table. On error, destroy the table and set errno. - * - * Returns 0 on success - */ -static int -alloc_segs(hashp, nsegs) - HTAB *hashp; - int nsegs; -{ - register int i; - register SEGMENT store; - - int save_errno; - - if ((hashp->dir = - (SEGMENT *)calloc(hashp->DSIZE, sizeof(SEGMENT *))) == NULL) { - save_errno = errno; - (void)hdestroy(hashp); - errno = save_errno; - return (-1); - } - /* Allocate segments */ - if ((store = - (SEGMENT)calloc(nsegs << hashp->SSHIFT, sizeof(SEGMENT))) == NULL) { - save_errno = errno; - (void)hdestroy(hashp); - errno = save_errno; - return (-1); - } - for (i = 0; i < nsegs; i++, hashp->nsegs++) - hashp->dir[i] = &store[i << hashp->SSHIFT]; - return (0); -} - -#if BYTE_ORDER == LITTLE_ENDIAN -/* - * Hashp->hdr needs to be byteswapped. - */ -static void -swap_header_copy(srcp, destp) - HASHHDR *srcp, *destp; -{ - int i; - - P_32_COPY(srcp->magic, destp->magic); - P_32_COPY(srcp->version, destp->version); - P_32_COPY(srcp->lorder, destp->lorder); - P_32_COPY(srcp->bsize, destp->bsize); - P_32_COPY(srcp->bshift, destp->bshift); - P_32_COPY(srcp->dsize, destp->dsize); - P_32_COPY(srcp->ssize, destp->ssize); - P_32_COPY(srcp->sshift, destp->sshift); - P_32_COPY(srcp->ovfl_point, destp->ovfl_point); - P_32_COPY(srcp->last_freed, destp->last_freed); - P_32_COPY(srcp->max_bucket, destp->max_bucket); - P_32_COPY(srcp->high_mask, destp->high_mask); - P_32_COPY(srcp->low_mask, destp->low_mask); - P_32_COPY(srcp->ffactor, destp->ffactor); - P_32_COPY(srcp->nkeys, destp->nkeys); - P_32_COPY(srcp->hdrpages, destp->hdrpages); - P_32_COPY(srcp->h_charkey, destp->h_charkey); - for (i = 0; i < NCACHED; i++) { - P_32_COPY(srcp->spares[i], destp->spares[i]); - P_16_COPY(srcp->bitmaps[i], destp->bitmaps[i]); - } -} - -static void -swap_header(hashp) - HTAB *hashp; -{ - HASHHDR *hdrp; - int i; - - hdrp = &hashp->hdr; - - M_32_SWAP(hdrp->magic); - M_32_SWAP(hdrp->version); - M_32_SWAP(hdrp->lorder); - M_32_SWAP(hdrp->bsize); - M_32_SWAP(hdrp->bshift); - M_32_SWAP(hdrp->dsize); - M_32_SWAP(hdrp->ssize); - M_32_SWAP(hdrp->sshift); - M_32_SWAP(hdrp->ovfl_point); - M_32_SWAP(hdrp->last_freed); - M_32_SWAP(hdrp->max_bucket); - M_32_SWAP(hdrp->high_mask); - M_32_SWAP(hdrp->low_mask); - M_32_SWAP(hdrp->ffactor); - M_32_SWAP(hdrp->nkeys); - M_32_SWAP(hdrp->hdrpages); - M_32_SWAP(hdrp->h_charkey); - for (i = 0; i < NCACHED; i++) { - M_32_SWAP(hdrp->spares[i]); - M_16_SWAP(hdrp->bitmaps[i]); - } -} -#endif diff --git a/db/hash/hash.h b/db/hash/hash.h deleted file mode 100644 index d07db6f..0000000 --- a/db/hash/hash.h +++ /dev/null @@ -1,293 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * 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. - * - * @(#)hash.h 8.3 (Berkeley) 5/31/94 - */ - -/* Operations */ -typedef enum { - HASH_GET, HASH_PUT, HASH_PUTNEW, HASH_DELETE, HASH_FIRST, HASH_NEXT -} ACTION; - -/* Buffer Management structures */ -typedef struct _bufhead BUFHEAD; - -struct _bufhead { - BUFHEAD *prev; /* LRU links */ - BUFHEAD *next; /* LRU links */ - BUFHEAD *ovfl; /* Overflow page buffer header */ - u_int32_t addr; /* Address of this page */ - char *page; /* Actual page data */ - char flags; -#define BUF_MOD 0x0001 -#define BUF_DISK 0x0002 -#define BUF_BUCKET 0x0004 -#define BUF_PIN 0x0008 -}; - -#define IS_BUCKET(X) ((X) & BUF_BUCKET) - -typedef BUFHEAD **SEGMENT; - -/* Hash Table Information */ -typedef struct hashhdr { /* Disk resident portion */ - int magic; /* Magic NO for hash tables */ - int version; /* Version ID */ - u_int32_t lorder; /* Byte Order */ - int bsize; /* Bucket/Page Size */ - int bshift; /* Bucket shift */ - int dsize; /* Directory Size */ - int ssize; /* Segment Size */ - int sshift; /* Segment shift */ - int ovfl_point; /* Where overflow pages are being - * allocated */ - int last_freed; /* Last overflow page freed */ - int max_bucket; /* ID of Maximum bucket in use */ - int high_mask; /* Mask to modulo into entire table */ - int low_mask; /* Mask to modulo into lower half of - * table */ - int ffactor; /* Fill factor */ - int nkeys; /* Number of keys in hash table */ - int hdrpages; /* Size of table header */ - int h_charkey; /* value of hash(CHARKEY) */ -#define NCACHED 32 /* number of bit maps and spare - * points */ - int spares[NCACHED];/* spare pages for overflow */ - u_int16_t bitmaps[NCACHED]; /* address of overflow page - * bitmaps */ -} HASHHDR; - -typedef struct htab { /* Memory resident data structure */ - HASHHDR hdr; /* Header */ - int nsegs; /* Number of allocated segments */ - int exsegs; /* Number of extra allocated - * segments */ - u_int32_t /* Hash function */ - (*hash)__P((const void *, size_t)); - int flags; /* Flag values */ - int fp; /* File pointer */ - char *tmp_buf; /* Temporary Buffer for BIG data */ - char *tmp_key; /* Temporary Buffer for BIG keys */ - BUFHEAD *cpage; /* Current page */ - int cbucket; /* Current bucket */ - int cndx; /* Index of next item on cpage */ - int errnum; /* Error Number -- for DBM - * compatibility */ - int new_file; /* Indicates if fd is backing store - * or no */ - int save_file; /* Indicates whether we need to flush - * file at - * exit */ - u_int32_t *mapp[NCACHED]; /* Pointers to page maps */ - int nmaps; /* Initial number of bitmaps */ - int nbufs; /* Number of buffers left to - * allocate */ - BUFHEAD bufhead; /* Header of buffer lru list */ - SEGMENT *dir; /* Hash Bucket directory */ -} HTAB; - -/* - * Constants - */ -#define MAX_BSIZE 65536 /* 2^16 */ -#define MIN_BUFFERS 6 -#define MINHDRSIZE 512 -#define DEF_BUFSIZE 65536 /* 64 K */ -#define DEF_BUCKET_SIZE 4096 -#define DEF_BUCKET_SHIFT 12 /* log2(BUCKET) */ -#define DEF_SEGSIZE 256 -#define DEF_SEGSIZE_SHIFT 8 /* log2(SEGSIZE) */ -#define DEF_DIRSIZE 256 -#define DEF_FFACTOR 65536 -#define MIN_FFACTOR 4 -#define SPLTMAX 8 -#define CHARKEY "%$sniglet^&" -#define NUMKEY 1038583 -#define BYTE_SHIFT 3 -#define INT_TO_BYTE 2 -#define INT_BYTE_SHIFT 5 -#define ALL_SET ((u_int32_t)0xFFFFFFFF) -#define ALL_CLEAR 0 - -#define PTROF(X) ((BUFHEAD *)((ptrdiff_t)(X)&~0x3)) -#define ISMOD(X) ((u_int32_t)(ptrdiff_t)(X)&0x1) -#define DOMOD(X) ((X) = (char *)((ptrdiff_t)(X)|0x1)) -#define ISDISK(X) ((u_int32_t)(ptrdiff_t)(X)&0x2) -#define DODISK(X) ((X) = (char *)((ptrdiff_t)(X)|0x2)) - -#define BITS_PER_MAP 32 - -/* Given the address of the beginning of a big map, clear/set the nth bit */ -#define CLRBIT(A, N) ((A)[(N)/BITS_PER_MAP] &= ~(1<<((N)%BITS_PER_MAP))) -#define SETBIT(A, N) ((A)[(N)/BITS_PER_MAP] |= (1<<((N)%BITS_PER_MAP))) -#define ISSET(A, N) ((A)[(N)/BITS_PER_MAP] & (1<<((N)%BITS_PER_MAP))) - -/* Overflow management */ -/* - * Overflow page numbers are allocated per split point. At each doubling of - * the table, we can allocate extra pages. So, an overflow page number has - * the top 5 bits indicate which split point and the lower 11 bits indicate - * which page at that split point is indicated (pages within split points are - * numberered starting with 1). - */ - -#define SPLITSHIFT 11 -#define SPLITMASK 0x7FF -#define SPLITNUM(N) (((u_int32_t)(N)) >> SPLITSHIFT) -#define OPAGENUM(N) ((N) & SPLITMASK) -#define OADDR_OF(S,O) ((u_int32_t)((u_int32_t)(S) << SPLITSHIFT) + (O)) - -#define BUCKET_TO_PAGE(B) \ - (B) + hashp->HDRPAGES + ((B) ? hashp->SPARES[__hash_log2((B)+1)-1] : 0) -#define OADDR_TO_PAGE(B) \ - BUCKET_TO_PAGE ( (1 << SPLITNUM((B))) -1 ) + OPAGENUM((B)); - -/* - * page.h contains a detailed description of the page format. - * - * Normally, keys and data are accessed from offset tables in the top of - * each page which point to the beginning of the key and data. There are - * four flag values which may be stored in these offset tables which indicate - * the following: - * - * - * OVFLPAGE Rather than a key data pair, this pair contains - * the address of an overflow page. The format of - * the pair is: - * OVERFLOW_PAGE_NUMBER OVFLPAGE - * - * PARTIAL_KEY This must be the first key/data pair on a page - * and implies that page contains only a partial key. - * That is, the key is too big to fit on a single page - * so it starts on this page and continues on the next. - * The format of the page is: - * KEY_OFF PARTIAL_KEY OVFL_PAGENO OVFLPAGE - * - * KEY_OFF -- offset of the beginning of the key - * PARTIAL_KEY -- 1 - * OVFL_PAGENO - page number of the next overflow page - * OVFLPAGE -- 0 - * - * FULL_KEY This must be the first key/data pair on the page. It - * is used in two cases. - * - * Case 1: - * There is a complete key on the page but no data - * (because it wouldn't fit). The next page contains - * the data. - * - * Page format it: - * KEY_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE - * - * KEY_OFF -- offset of the beginning of the key - * FULL_KEY -- 2 - * OVFL_PAGENO - page number of the next overflow page - * OVFLPAGE -- 0 - * - * Case 2: - * This page contains no key, but part of a large - * data field, which is continued on the next page. - * - * Page format it: - * DATA_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE - * - * KEY_OFF -- offset of the beginning of the data on - * this page - * FULL_KEY -- 2 - * OVFL_PAGENO - page number of the next overflow page - * OVFLPAGE -- 0 - * - * FULL_KEY_DATA - * This must be the first key/data pair on the page. - * There are two cases: - * - * Case 1: - * This page contains a key and the beginning of the - * data field, but the data field is continued on the - * next page. - * - * Page format is: - * KEY_OFF FULL_KEY_DATA OVFL_PAGENO DATA_OFF - * - * KEY_OFF -- offset of the beginning of the key - * FULL_KEY_DATA -- 3 - * OVFL_PAGENO - page number of the next overflow page - * DATA_OFF -- offset of the beginning of the data - * - * Case 2: - * This page contains the last page of a big data pair. - * There is no key, only the tail end of the data - * on this page. - * - * Page format is: - * DATA_OFF FULL_KEY_DATA <OVFL_PAGENO> <OVFLPAGE> - * - * DATA_OFF -- offset of the beginning of the data on - * this page - * FULL_KEY_DATA -- 3 - * OVFL_PAGENO - page number of the next overflow page - * OVFLPAGE -- 0 - * - * OVFL_PAGENO and OVFLPAGE are optional (they are - * not present if there is no next page). - */ - -#define OVFLPAGE 0 -#define PARTIAL_KEY 1 -#define FULL_KEY 2 -#define FULL_KEY_DATA 3 -#define REAL_KEY 4 - -/* Short hands for accessing structure */ -#define BSIZE hdr.bsize -#define BSHIFT hdr.bshift -#define DSIZE hdr.dsize -#define SGSIZE hdr.ssize -#define SSHIFT hdr.sshift -#define LORDER hdr.lorder -#define OVFL_POINT hdr.ovfl_point -#define LAST_FREED hdr.last_freed -#define MAX_BUCKET hdr.max_bucket -#define FFACTOR hdr.ffactor -#define HIGH_MASK hdr.high_mask -#define LOW_MASK hdr.low_mask -#define NKEYS hdr.nkeys -#define HDRPAGES hdr.hdrpages -#define SPARES hdr.spares -#define BITMAPS hdr.bitmaps -#define VERSION hdr.version -#define MAGIC hdr.magic -#define NEXT_FREE hdr.next_free -#define H_CHARKEY hdr.h_charkey diff --git a/db/hash/hash_bigkey.c b/db/hash/hash_bigkey.c deleted file mode 100644 index 94c6408..0000000 --- a/db/hash/hash_bigkey.c +++ /dev/null @@ -1,668 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * 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. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)hash_bigkey.c 8.3 (Berkeley) 5/31/94"; -#endif /* LIBC_SCCS and not lint */ - -/* - * PACKAGE: hash - * DESCRIPTION: - * Big key/data handling for the hashing package. - * - * ROUTINES: - * External - * __big_keydata - * __big_split - * __big_insert - * __big_return - * __big_delete - * __find_last_page - * Internal - * collect_key - * collect_data - */ - -#include <sys/param.h> - -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#ifdef DEBUG -#include <assert.h> -#endif - -#include <db.h> -#include "hash.h" -#include "page.h" -#include "extern.h" - -static int collect_key __P((HTAB *, BUFHEAD *, int, DBT *, int)); -static int collect_data __P((HTAB *, BUFHEAD *, int, int)); - -/* - * Big_insert - * - * You need to do an insert and the key/data pair is too big - * - * Returns: - * 0 ==> OK - *-1 ==> ERROR - */ -extern int -__big_insert(hashp, bufp, key, val) - HTAB *hashp; - BUFHEAD *bufp; - const DBT *key, *val; -{ - register u_int16_t *p; - int key_size, n, val_size; - u_int16_t space, move_bytes, off; - char *cp, *key_data, *val_data; - - cp = bufp->page; /* Character pointer of p. */ - p = (u_int16_t *)cp; - - key_data = (char *)key->data; - key_size = key->size; - val_data = (char *)val->data; - val_size = val->size; - - /* First move the Key */ - for (space = FREESPACE(p) - BIGOVERHEAD; key_size; - space = FREESPACE(p) - BIGOVERHEAD) { - move_bytes = MIN(space, key_size); - off = OFFSET(p) - move_bytes; - memmove(cp + off, key_data, move_bytes); - key_size -= move_bytes; - key_data += move_bytes; - n = p[0]; - p[++n] = off; - p[0] = ++n; - FREESPACE(p) = off - PAGE_META(n); - OFFSET(p) = off; - p[n] = PARTIAL_KEY; - bufp = __add_ovflpage(hashp, bufp); - if (!bufp) - return (-1); - n = p[0]; - if (!key_size) { - if (FREESPACE(p)) { - move_bytes = MIN(FREESPACE(p), val_size); - off = OFFSET(p) - move_bytes; - p[n] = off; - memmove(cp + off, val_data, move_bytes); - val_data += move_bytes; - val_size -= move_bytes; - p[n - 2] = FULL_KEY_DATA; - FREESPACE(p) = FREESPACE(p) - move_bytes; - OFFSET(p) = off; - } else - p[n - 2] = FULL_KEY; - } - p = (u_int16_t *)bufp->page; - cp = bufp->page; - bufp->flags |= BUF_MOD; - } - - /* Now move the data */ - for (space = FREESPACE(p) - BIGOVERHEAD; val_size; - space = FREESPACE(p) - BIGOVERHEAD) { - move_bytes = MIN(space, val_size); - /* - * Here's the hack to make sure that if the data ends on the - * same page as the key ends, FREESPACE is at least one. - */ - if ((int) space == val_size && (size_t) val_size == val->size) - move_bytes--; - off = OFFSET(p) - move_bytes; - memmove(cp + off, val_data, move_bytes); - val_size -= move_bytes; - val_data += move_bytes; - n = p[0]; - p[++n] = off; - p[0] = ++n; - FREESPACE(p) = off - PAGE_META(n); - OFFSET(p) = off; - if (val_size) { - p[n] = FULL_KEY; - bufp = __add_ovflpage(hashp, bufp); - if (!bufp) - return (-1); - cp = bufp->page; - p = (u_int16_t *)cp; - } else - p[n] = FULL_KEY_DATA; - bufp->flags |= BUF_MOD; - } - return (0); -} - -/* - * Called when bufp's page contains a partial key (index should be 1) - * - * All pages in the big key/data pair except bufp are freed. We cannot - * free bufp because the page pointing to it is lost and we can't get rid - * of its pointer. - * - * Returns: - * 0 => OK - *-1 => ERROR - */ -extern int -__big_delete(hashp, bufp) - HTAB *hashp; - BUFHEAD *bufp; -{ - register BUFHEAD *last_bfp, *rbufp; - u_int16_t *bp, pageno; - int key_done, n; - - rbufp = bufp; - last_bfp = NULL; - bp = (u_int16_t *)bufp->page; - pageno = 0; - key_done = 0; - - while (!key_done || (bp[2] != FULL_KEY_DATA)) { - if (bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA) - key_done = 1; - - /* - * If there is freespace left on a FULL_KEY_DATA page, then - * the data is short and fits entirely on this page, and this - * is the last page. - */ - if (bp[2] == FULL_KEY_DATA && FREESPACE(bp)) - break; - pageno = bp[bp[0] - 1]; - rbufp->flags |= BUF_MOD; - rbufp = __get_buf(hashp, pageno, rbufp, 0); - if (last_bfp) - __free_ovflpage(hashp, last_bfp); - last_bfp = rbufp; - if (!rbufp) - return (-1); /* Error. */ - bp = (u_int16_t *)rbufp->page; - } - - /* - * If we get here then rbufp points to the last page of the big - * key/data pair. Bufp points to the first one -- it should now be - * empty pointing to the next page after this pair. Can't free it - * because we don't have the page pointing to it. - */ - - /* This is information from the last page of the pair. */ - n = bp[0]; - pageno = bp[n - 1]; - - /* Now, bp is the first page of the pair. */ - bp = (u_int16_t *)bufp->page; - if (n > 2) { - /* There is an overflow page. */ - bp[1] = pageno; - bp[2] = OVFLPAGE; - bufp->ovfl = rbufp->ovfl; - } else - /* This is the last page. */ - bufp->ovfl = NULL; - n -= 2; - bp[0] = n; - FREESPACE(bp) = hashp->BSIZE - PAGE_META(n); - OFFSET(bp) = hashp->BSIZE - 1; - - bufp->flags |= BUF_MOD; - if (rbufp) - __free_ovflpage(hashp, rbufp); - if (last_bfp && last_bfp != rbufp) - __free_ovflpage(hashp, last_bfp); - - hashp->NKEYS--; - return (0); -} -/* - * Returns: - * 0 = key not found - * -1 = get next overflow page - * -2 means key not found and this is big key/data - * -3 error - */ -extern int -__find_bigpair(hashp, bufp, ndx, key, size) - HTAB *hashp; - BUFHEAD *bufp; - int ndx; - char *key; - int size; -{ - register u_int16_t *bp; - register char *p; - int ksize; - u_int16_t bytes; - char *kkey; - - bp = (u_int16_t *)bufp->page; - p = bufp->page; - ksize = size; - kkey = key; - - for (bytes = hashp->BSIZE - bp[ndx]; - bytes <= size && bp[ndx + 1] == PARTIAL_KEY; - bytes = hashp->BSIZE - bp[ndx]) { - if (memcmp(p + bp[ndx], kkey, bytes)) - return (-2); - kkey += bytes; - ksize -= bytes; - bufp = __get_buf(hashp, bp[ndx + 2], bufp, 0); - if (!bufp) - return (-3); - p = bufp->page; - bp = (u_int16_t *)p; - ndx = 1; - } - - if (bytes != ksize || memcmp(p + bp[ndx], kkey, bytes)) { -#ifdef HASH_STATISTICS - ++hash_collisions; -#endif - return (-2); - } else - return (ndx); -} - -/* - * Given the buffer pointer of the first overflow page of a big pair, - * find the end of the big pair - * - * This will set bpp to the buffer header of the last page of the big pair. - * It will return the pageno of the overflow page following the last page - * of the pair; 0 if there isn't any (i.e. big pair is the last key in the - * bucket) - */ -extern u_int16_t -__find_last_page(hashp, bpp) - HTAB *hashp; - BUFHEAD **bpp; -{ - BUFHEAD *bufp; - u_int16_t *bp, pageno; - int n; - - bufp = *bpp; - bp = (u_int16_t *)bufp->page; - for (;;) { - n = bp[0]; - - /* - * This is the last page if: the tag is FULL_KEY_DATA and - * either only 2 entries OVFLPAGE marker is explicit there - * is freespace on the page. - */ - if (bp[2] == FULL_KEY_DATA && - ((n == 2) || (bp[n] == OVFLPAGE) || (FREESPACE(bp)))) - break; - - pageno = bp[n - 1]; - bufp = __get_buf(hashp, pageno, bufp, 0); - if (!bufp) - return (0); /* Need to indicate an error! */ - bp = (u_int16_t *)bufp->page; - } - - *bpp = bufp; - if (bp[0] > 2) - return (bp[3]); - else - return (0); -} - -/* - * Return the data for the key/data pair that begins on this page at this - * index (index should always be 1). - */ -extern int -__big_return(hashp, bufp, ndx, val, set_current) - HTAB *hashp; - BUFHEAD *bufp; - int ndx; - DBT *val; - int set_current; -{ - BUFHEAD *save_p; - u_int16_t *bp, len, off, save_addr; - char *tp; - - bp = (u_int16_t *)bufp->page; - while (bp[ndx + 1] == PARTIAL_KEY) { - bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); - if (!bufp) - return (-1); - bp = (u_int16_t *)bufp->page; - ndx = 1; - } - - if (bp[ndx + 1] == FULL_KEY) { - bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); - if (!bufp) - return (-1); - bp = (u_int16_t *)bufp->page; - save_p = bufp; - save_addr = save_p->addr; - off = bp[1]; - len = 0; - } else - if (!FREESPACE(bp)) { - /* - * This is a hack. We can't distinguish between - * FULL_KEY_DATA that contains complete data or - * incomplete data, so we require that if the data - * is complete, there is at least 1 byte of free - * space left. - */ - off = bp[bp[0]]; - len = bp[1] - off; - save_p = bufp; - save_addr = bufp->addr; - bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); - if (!bufp) - return (-1); - bp = (u_int16_t *)bufp->page; - } else { - /* The data is all on one page. */ - tp = (char *)bp; - off = bp[bp[0]]; - val->data = (u_char *)tp + off; - val->size = bp[1] - off; - if (set_current) { - if (bp[0] == 2) { /* No more buckets in - * chain */ - hashp->cpage = NULL; - hashp->cbucket++; - hashp->cndx = 1; - } else { - hashp->cpage = __get_buf(hashp, - bp[bp[0] - 1], bufp, 0); - if (!hashp->cpage) - return (-1); - hashp->cndx = 1; - if (!((u_int16_t *) - hashp->cpage->page)[0]) { - hashp->cbucket++; - hashp->cpage = NULL; - } - } - } - return (0); - } - - val->size = collect_data(hashp, bufp, (int)len, set_current); - if (val->size == (size_t) -1) - return (-1); - if (save_p->addr != save_addr) { - /* We are pretty short on buffers. */ - errno = EINVAL; /* OUT OF BUFFERS */ - return (-1); - } - memmove(hashp->tmp_buf, (save_p->page) + off, len); - val->data = (u_char *)hashp->tmp_buf; - return (0); -} -/* - * Count how big the total datasize is by recursing through the pages. Then - * allocate a buffer and copy the data as you recurse up. - */ -static int -collect_data(hashp, bufp, len, set) - HTAB *hashp; - BUFHEAD *bufp; - int len, set; -{ - register u_int16_t *bp; - register char *p; - BUFHEAD *xbp; - u_int16_t save_addr; - int mylen, totlen; - - p = bufp->page; - bp = (u_int16_t *)p; - mylen = hashp->BSIZE - bp[1]; - save_addr = bufp->addr; - - if (bp[2] == FULL_KEY_DATA) { /* End of Data */ - totlen = len + mylen; - if (hashp->tmp_buf) - free(hashp->tmp_buf); - if ((hashp->tmp_buf = (char *)malloc(totlen)) == NULL) - return (-1); - if (set) { - hashp->cndx = 1; - if (bp[0] == 2) { /* No more buckets in chain */ - hashp->cpage = NULL; - hashp->cbucket++; - } else { - hashp->cpage = - __get_buf(hashp, bp[bp[0] - 1], bufp, 0); - if (!hashp->cpage) - return (-1); - else if (!((u_int16_t *)hashp->cpage->page)[0]) { - hashp->cbucket++; - hashp->cpage = NULL; - } - } - } - } else { - xbp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); - if (!xbp || ((totlen = - collect_data(hashp, xbp, len + mylen, set)) < 1)) - return (-1); - } - if (bufp->addr != save_addr) { - errno = EINVAL; /* Out of buffers. */ - return (-1); - } - memmove(&hashp->tmp_buf[len], (bufp->page) + bp[1], mylen); - return (totlen); -} - -/* - * Fill in the key and data for this big pair. - */ -extern int -__big_keydata(hashp, bufp, key, val, set) - HTAB *hashp; - BUFHEAD *bufp; - DBT *key, *val; - int set; -{ - key->size = collect_key(hashp, bufp, 0, val, set); - if (key->size == (size_t) -1) - return (-1); - key->data = (u_char *)hashp->tmp_key; - return (0); -} - -/* - * Count how big the total key size is by recursing through the pages. Then - * collect the data, allocate a buffer and copy the key as you recurse up. - */ -static int -collect_key(hashp, bufp, len, val, set) - HTAB *hashp; - BUFHEAD *bufp; - int len; - DBT *val; - int set; -{ - BUFHEAD *xbp; - char *p; - int mylen, totlen; - u_int16_t *bp, save_addr; - - p = bufp->page; - bp = (u_int16_t *)p; - mylen = hashp->BSIZE - bp[1]; - - save_addr = bufp->addr; - totlen = len + mylen; - if (bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA) { /* End of Key. */ - if (hashp->tmp_key != NULL) - free(hashp->tmp_key); - if ((hashp->tmp_key = (char *)malloc(totlen)) == NULL) - return (-1); - if (__big_return(hashp, bufp, 1, val, set)) - return (-1); - } else { - xbp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); - if (!xbp || ((totlen = - collect_key(hashp, xbp, totlen, val, set)) < 1)) - return (-1); - } - if (bufp->addr != save_addr) { - errno = EINVAL; /* MIS -- OUT OF BUFFERS */ - return (-1); - } - memmove(&hashp->tmp_key[len], (bufp->page) + bp[1], mylen); - return (totlen); -} - -/* - * Returns: - * 0 => OK - * -1 => error - */ -extern int -__big_split(hashp, op, np, big_keyp, addr, obucket, ret) - HTAB *hashp; - BUFHEAD *op; /* Pointer to where to put keys that go in old bucket */ - BUFHEAD *np; /* Pointer to new bucket page */ - /* Pointer to first page containing the big key/data */ - BUFHEAD *big_keyp; - int addr; /* Address of big_keyp */ - u_int32_t obucket;/* Old Bucket */ - SPLIT_RETURN *ret; -{ - register BUFHEAD *tmpp; - register u_int16_t *tp; - BUFHEAD *bp; - DBT key, val; - u_int32_t change; - u_int16_t free_space, n, off; - - bp = big_keyp; - - /* Now figure out where the big key/data goes */ - if (__big_keydata(hashp, big_keyp, &key, &val, 0)) - return (-1); - change = (__call_hash(hashp, key.data, key.size) != obucket); - - if ((ret->next_addr = __find_last_page(hashp, &big_keyp))) { - if (!(ret->nextp = - __get_buf(hashp, ret->next_addr, big_keyp, 0))) - return (-1);; - } else - ret->nextp = NULL; - - /* Now make one of np/op point to the big key/data pair */ -#ifdef DEBUG - assert(np->ovfl == NULL); -#endif - if (change) - tmpp = np; - else - tmpp = op; - - tmpp->flags |= BUF_MOD; -#ifdef DEBUG1 - (void)fprintf(stderr, - "BIG_SPLIT: %d->ovfl was %d is now %d\n", tmpp->addr, - (tmpp->ovfl ? tmpp->ovfl->addr : 0), (bp ? bp->addr : 0)); -#endif - tmpp->ovfl = bp; /* one of op/np point to big_keyp */ - tp = (u_int16_t *)tmpp->page; -#ifdef DEBUG - assert(FREESPACE(tp) >= OVFLSIZE); -#endif - n = tp[0]; - off = OFFSET(tp); - free_space = FREESPACE(tp); - tp[++n] = (u_int16_t)addr; - tp[++n] = OVFLPAGE; - tp[0] = n; - OFFSET(tp) = off; - FREESPACE(tp) = free_space - OVFLSIZE; - - /* - * Finally, set the new and old return values. BIG_KEYP contains a - * pointer to the last page of the big key_data pair. Make sure that - * big_keyp has no following page (2 elements) or create an empty - * following page. - */ - - ret->newp = np; - ret->oldp = op; - - tp = (u_int16_t *)big_keyp->page; - big_keyp->flags |= BUF_MOD; - if (tp[0] > 2) { - /* - * There may be either one or two offsets on this page. If - * there is one, then the overflow page is linked on normally - * and tp[4] is OVFLPAGE. If there are two, tp[4] contains - * the second offset and needs to get stuffed in after the - * next overflow page is added. - */ - n = tp[4]; - free_space = FREESPACE(tp); - off = OFFSET(tp); - tp[0] -= 2; - FREESPACE(tp) = free_space + OVFLSIZE; - OFFSET(tp) = off; - tmpp = __add_ovflpage(hashp, big_keyp); - if (!tmpp) - return (-1); - tp[4] = n; - } else - tmpp = big_keyp; - - if (change) - ret->newp = tmpp; - else - ret->oldp = tmpp; - return (0); -} diff --git a/db/hash/hash_buf.c b/db/hash/hash_buf.c deleted file mode 100644 index 92e1f93..0000000 --- a/db/hash/hash_buf.c +++ /dev/null @@ -1,355 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * 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. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)hash_buf.c 8.5 (Berkeley) 7/15/94"; -#endif /* LIBC_SCCS and not lint */ - -/* - * PACKAGE: hash - * - * DESCRIPTION: - * Contains buffer management - * - * ROUTINES: - * External - * __buf_init - * __get_buf - * __buf_free - * __reclaim_buf - * Internal - * newbuf - */ - -#include <sys/param.h> - -#include <errno.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> - -#ifdef DEBUG -#include <assert.h> -#endif - -#include <db.h> -#include "hash.h" -#include "page.h" -#include "extern.h" - -static BUFHEAD *newbuf __P((HTAB *, u_int32_t, BUFHEAD *)); - -/* Unlink B from its place in the lru */ -#define BUF_REMOVE(B) { \ - (B)->prev->next = (B)->next; \ - (B)->next->prev = (B)->prev; \ -} - -/* Insert B after P */ -#define BUF_INSERT(B, P) { \ - (B)->next = (P)->next; \ - (B)->prev = (P); \ - (P)->next = (B); \ - (B)->next->prev = (B); \ -} - -#define MRU hashp->bufhead.next -#define LRU hashp->bufhead.prev - -#define MRU_INSERT(B) BUF_INSERT((B), &hashp->bufhead) -#define LRU_INSERT(B) BUF_INSERT((B), LRU) - -/* - * We are looking for a buffer with address "addr". If prev_bp is NULL, then - * address is a bucket index. If prev_bp is not NULL, then it points to the - * page previous to an overflow page that we are trying to find. - * - * CAVEAT: The buffer header accessed via prev_bp's ovfl field may no longer - * be valid. Therefore, you must always verify that its address matches the - * address you are seeking. - */ -extern BUFHEAD * -__get_buf(hashp, addr, prev_bp, newpage) - HTAB *hashp; - u_int32_t addr; - BUFHEAD *prev_bp; - int newpage; /* If prev_bp set, indicates a new overflow page. */ -{ - register BUFHEAD *bp; - register u_int32_t is_disk_mask; - register int is_disk, segment_ndx; - SEGMENT segp; - - is_disk = 0; - is_disk_mask = 0; - if (prev_bp) { - bp = prev_bp->ovfl; - if (!bp || (bp->addr != addr)) - bp = NULL; - if (!newpage) - is_disk = BUF_DISK; - } else { - /* Grab buffer out of directory */ - segment_ndx = addr & (hashp->SGSIZE - 1); - - /* valid segment ensured by __call_hash() */ - segp = hashp->dir[addr >> hashp->SSHIFT]; -#ifdef DEBUG - assert(segp != NULL); -#endif - bp = PTROF(segp[segment_ndx]); - is_disk_mask = ISDISK(segp[segment_ndx]); - is_disk = is_disk_mask || !hashp->new_file; - } - - if (!bp) { - bp = newbuf(hashp, addr, prev_bp); - if (!bp || - __get_page(hashp, bp->page, addr, !prev_bp, is_disk, 0)) - return (NULL); - if (!prev_bp) - segp[segment_ndx] = - (BUFHEAD *)((ptrdiff_t)bp | is_disk_mask); - } else { - BUF_REMOVE(bp); - MRU_INSERT(bp); - } - return (bp); -} - -/* - * We need a buffer for this page. Either allocate one, or evict a resident - * one (if we have as many buffers as we're allowed) and put this one in. - * - * If newbuf finds an error (returning NULL), it also sets errno. - */ -static BUFHEAD * -newbuf(hashp, addr, prev_bp) - HTAB *hashp; - u_int32_t addr; - BUFHEAD *prev_bp; -{ - register BUFHEAD *bp; /* The buffer we're going to use */ - register BUFHEAD *xbp; /* Temp pointer */ - register BUFHEAD *next_xbp; - SEGMENT segp; - int segment_ndx; - u_int16_t oaddr, *shortp; - - oaddr = 0; - bp = LRU; - /* - * If LRU buffer is pinned, the buffer pool is too small. We need to - * allocate more buffers. - */ - if (hashp->nbufs || (bp->flags & BUF_PIN)) { - /* Allocate a new one */ - if ((bp = (BUFHEAD *)malloc(sizeof(BUFHEAD))) == NULL) - return (NULL); -#ifdef PURIFY - memset(bp, 0xff, sizeof(BUFHEAD)); -#endif - if ((bp->page = (char *)malloc(hashp->BSIZE)) == NULL) { - free(bp); - return (NULL); - } -#ifdef PURIFY - memset(bp->page, 0xff, hashp->BSIZE); -#endif - if (hashp->nbufs) - hashp->nbufs--; - } else { - /* Kick someone out */ - BUF_REMOVE(bp); - /* - * If this is an overflow page with addr 0, it's already been - * flushed back in an overflow chain and initialized. - */ - if ((bp->addr != 0) || (bp->flags & BUF_BUCKET)) { - /* - * Set oaddr before __put_page so that you get it - * before bytes are swapped. - */ - shortp = (u_int16_t *)bp->page; - if (shortp[0]) - oaddr = shortp[shortp[0] - 1]; - if ((bp->flags & BUF_MOD) && __put_page(hashp, bp->page, - bp->addr, (int)IS_BUCKET(bp->flags), 0)) - return (NULL); - /* - * Update the pointer to this page (i.e. invalidate it). - * - * If this is a new file (i.e. we created it at open - * time), make sure that we mark pages which have been - * written to disk so we retrieve them from disk later, - * rather than allocating new pages. - */ - if (IS_BUCKET(bp->flags)) { - segment_ndx = bp->addr & (hashp->SGSIZE - 1); - segp = hashp->dir[bp->addr >> hashp->SSHIFT]; -#ifdef DEBUG - assert(segp != NULL); -#endif - - if (hashp->new_file && - ((bp->flags & BUF_MOD) || - ISDISK(segp[segment_ndx]))) - segp[segment_ndx] = (BUFHEAD *)BUF_DISK; - else - segp[segment_ndx] = NULL; - } - /* - * Since overflow pages can only be access by means of - * their bucket, free overflow pages associated with - * this bucket. - */ - for (xbp = bp; xbp->ovfl;) { - next_xbp = xbp->ovfl; - xbp->ovfl = 0; - xbp = next_xbp; - - /* Check that ovfl pointer is up date. */ - if (IS_BUCKET(xbp->flags) || - (oaddr != xbp->addr)) - break; - - shortp = (u_int16_t *)xbp->page; - if (shortp[0]) - /* set before __put_page */ - oaddr = shortp[shortp[0] - 1]; - if ((xbp->flags & BUF_MOD) && __put_page(hashp, - xbp->page, xbp->addr, 0, 0)) - return (NULL); - xbp->addr = 0; - xbp->flags = 0; - BUF_REMOVE(xbp); - LRU_INSERT(xbp); - } - } - } - - /* Now assign this buffer */ - bp->addr = addr; -#ifdef DEBUG1 - (void)fprintf(stderr, "NEWBUF1: %d->ovfl was %d is now %d\n", - bp->addr, (bp->ovfl ? bp->ovfl->addr : 0), 0); -#endif - bp->ovfl = NULL; - if (prev_bp) { - /* - * If prev_bp is set, this is an overflow page, hook it in to - * the buffer overflow links. - */ -#ifdef DEBUG1 - (void)fprintf(stderr, "NEWBUF2: %d->ovfl was %d is now %d\n", - prev_bp->addr, (prev_bp->ovfl ? bp->ovfl->addr : 0), - (bp ? bp->addr : 0)); -#endif - prev_bp->ovfl = bp; - bp->flags = 0; - } else - bp->flags = BUF_BUCKET; - MRU_INSERT(bp); - return (bp); -} - -extern void -__buf_init(hashp, nbytes) - HTAB *hashp; - int nbytes; -{ - BUFHEAD *bfp; - int npages; - - bfp = &(hashp->bufhead); - npages = (nbytes + hashp->BSIZE - 1) >> hashp->BSHIFT; - npages = MAX(npages, MIN_BUFFERS); - - hashp->nbufs = npages; - bfp->next = bfp; - bfp->prev = bfp; - /* - * This space is calloc'd so these are already null. - * - * bfp->ovfl = NULL; - * bfp->flags = 0; - * bfp->page = NULL; - * bfp->addr = 0; - */ -} - -extern int -__buf_free(hashp, do_free, to_disk) - HTAB *hashp; - int do_free, to_disk; -{ - BUFHEAD *bp; - - /* Need to make sure that buffer manager has been initialized */ - if (!LRU) - return (0); - for (bp = LRU; bp != &hashp->bufhead;) { - /* Check that the buffer is valid */ - if (bp->addr || IS_BUCKET(bp->flags)) { - if (to_disk && (bp->flags & BUF_MOD) && - __put_page(hashp, bp->page, - bp->addr, IS_BUCKET(bp->flags), 0)) - return (-1); - } - /* Check if we are freeing stuff */ - if (do_free) { - if (bp->page) - free(bp->page); - BUF_REMOVE(bp); - free(bp); - bp = LRU; - } else - bp = bp->prev; - } - return (0); -} - -extern void -__reclaim_buf(hashp, bp) - HTAB *hashp; - BUFHEAD *bp; -{ - bp->ovfl = 0; - bp->addr = 0; - bp->flags = 0; - BUF_REMOVE(bp); - LRU_INSERT(bp); -} diff --git a/db/hash/hash_func.c b/db/hash/hash_func.c deleted file mode 100644 index a5ec434..0000000 --- a/db/hash/hash_func.c +++ /dev/null @@ -1,212 +0,0 @@ -/*- - * Copyright (c) 1990, 1993 - * 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. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)hash_func.c 8.2 (Berkeley) 2/21/94"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/types.h> - -#include <db.h> -#include "hash.h" -#include "page.h" -#include "extern.h" - -static u_int32_t hash1 __P((const void *, size_t)); -static u_int32_t hash2 __P((const void *, size_t)); -static u_int32_t hash3 __P((const void *, size_t)); -static u_int32_t hash4 __P((const void *, size_t)); - -/* Global default hash function */ -u_int32_t (*__default_hash) __P((const void *, size_t)) = hash4; - -/* - * HASH FUNCTIONS - * - * Assume that we've already split the bucket to which this key hashes, - * calculate that bucket, and check that in fact we did already split it. - * - * This came from ejb's hsearch. - */ - -#define PRIME1 37 -#define PRIME2 1048583 - -static u_int32_t -hash1(keyarg, len) - const void *keyarg; - register size_t len; -{ - register const u_char *key; - register u_int32_t h; - - /* Convert string to integer */ - for (key = keyarg, h = 0; len--;) - h = h * PRIME1 ^ (*key++ - ' '); - h %= PRIME2; - return (h); -} - -/* - * Phong's linear congruential hash - */ -#define dcharhash(h, c) ((h) = 0x63c63cd9*(h) + 0x9c39c33d + (c)) - -static u_int32_t -hash2(keyarg, len) - const void *keyarg; - size_t len; -{ - register const u_char *e, *key; - register u_int32_t h; - register u_char c; - - key = keyarg; - e = key + len; - for (h = 0; key != e;) { - c = *key++; - if (!c && key > e) - break; - dcharhash(h, c); - } - return (h); -} - -/* - * This is INCREDIBLY ugly, but fast. We break the string up into 8 byte - * units. On the first time through the loop we get the "leftover bytes" - * (strlen % 8). On every other iteration, we perform 8 HASHC's so we handle - * all 8 bytes. Essentially, this saves us 7 cmp & branch instructions. If - * this routine is heavily used enough, it's worth the ugly coding. - * - * OZ's original sdbm hash - */ -static u_int32_t -hash3(keyarg, len) - const void *keyarg; - register size_t len; -{ - register const u_char *key; - register size_t loop; - register u_int32_t h; - -#define HASHC h = *key++ + 65599 * h - - h = 0; - key = keyarg; - if (len > 0) { - loop = (len + 8 - 1) >> 3; - - switch (len & (8 - 1)) { - case 0: - do { - HASHC; - /* FALLTHROUGH */ - case 7: - HASHC; - /* FALLTHROUGH */ - case 6: - HASHC; - /* FALLTHROUGH */ - case 5: - HASHC; - /* FALLTHROUGH */ - case 4: - HASHC; - /* FALLTHROUGH */ - case 3: - HASHC; - /* FALLTHROUGH */ - case 2: - HASHC; - /* FALLTHROUGH */ - case 1: - HASHC; - } while (--loop); - } - } - return (h); -} - -/* Hash function from Chris Torek. */ -static u_int32_t -hash4(keyarg, len) - const void *keyarg; - register size_t len; -{ - register const u_char *key; - register size_t loop; - register u_int32_t h; - -#define HASH4a h = (h << 5) - h + *key++; -#define HASH4b h = (h << 5) + h + *key++; -#define HASH4 HASH4b - - h = 0; - key = keyarg; - if (len > 0) { - loop = (len + 8 - 1) >> 3; - - switch (len & (8 - 1)) { - case 0: - do { - HASH4; - /* FALLTHROUGH */ - case 7: - HASH4; - /* FALLTHROUGH */ - case 6: - HASH4; - /* FALLTHROUGH */ - case 5: - HASH4; - /* FALLTHROUGH */ - case 4: - HASH4; - /* FALLTHROUGH */ - case 3: - HASH4; - /* FALLTHROUGH */ - case 2: - HASH4; - /* FALLTHROUGH */ - case 1: - HASH4; - } while (--loop); - } - } - return (h); -} diff --git a/db/hash/hash_log2.c b/db/hash/hash_log2.c deleted file mode 100644 index 6bcf9c1..0000000 --- a/db/hash/hash_log2.c +++ /dev/null @@ -1,56 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * 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. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)hash_log2.c 8.2 (Berkeley) 5/31/94"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/types.h> - -#include <db.h> - -u_int32_t __hash_log2 __P((u_int32_t)); - -u_int32_t -__hash_log2(num) - u_int32_t num; -{ - register u_int32_t i, limit; - - limit = 1; - for (i = 0; limit < num; limit = limit << 1, i++); - return (i); -} diff --git a/db/hash/hash_page.c b/db/hash/hash_page.c deleted file mode 100644 index e1dfe6b..0000000 --- a/db/hash/hash_page.c +++ /dev/null @@ -1,944 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * 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. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)hash_page.c 8.7 (Berkeley) 8/16/94"; -#endif /* LIBC_SCCS and not lint */ - -/* - * PACKAGE: hashing - * - * DESCRIPTION: - * Page manipulation for hashing package. - * - * ROUTINES: - * - * External - * __get_page - * __add_ovflpage - * Internal - * overflow_page - * open_temp - */ - -#include <sys/types.h> - -#include <errno.h> -#include <fcntl.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#ifdef DEBUG -#include <assert.h> -#endif - -#include <db.h> -#include "hash.h" -#include "page.h" -#include "extern.h" - -static u_int32_t *fetch_bitmap __P((HTAB *, int)); -static u_int32_t first_free __P((u_int32_t)); -static int open_temp __P((HTAB *)); -static u_int16_t overflow_page __P((HTAB *)); -static void putpair __P((char *, const DBT *, const DBT *)); -static void squeeze_key __P((u_int16_t *, const DBT *, const DBT *)); -static int ugly_split - __P((HTAB *, u_int32_t, BUFHEAD *, BUFHEAD *, int, int)); - -#define PAGE_INIT(P) { \ - ((u_int16_t *)(P))[0] = 0; \ - ((u_int16_t *)(P))[1] = hashp->BSIZE - 3 * sizeof(u_int16_t); \ - ((u_int16_t *)(P))[2] = hashp->BSIZE; \ -} - -/* - * This is called AFTER we have verified that there is room on the page for - * the pair (PAIRFITS has returned true) so we go right ahead and start moving - * stuff on. - */ -static void -putpair(p, key, val) - char *p; - const DBT *key, *val; -{ - register u_int16_t *bp, n, off; - - bp = (u_int16_t *)p; - - /* Enter the key first. */ - n = bp[0]; - - off = OFFSET(bp) - key->size; - memmove(p + off, key->data, key->size); - bp[++n] = off; - - /* Now the data. */ - off -= val->size; - memmove(p + off, val->data, val->size); - bp[++n] = off; - - /* Adjust page info. */ - bp[0] = n; - bp[n + 1] = off - ((n + 3) * sizeof(u_int16_t)); - bp[n + 2] = off; -} - -/* - * Returns: - * 0 OK - * -1 error - */ -extern int -__delpair(hashp, bufp, ndx) - HTAB *hashp; - BUFHEAD *bufp; - register int ndx; -{ - register u_int16_t *bp, newoff; - register int n; - u_int16_t pairlen; - - bp = (u_int16_t *)bufp->page; - n = bp[0]; - - if (bp[ndx + 1] < REAL_KEY) - return (__big_delete(hashp, bufp)); - if (ndx != 1) - newoff = bp[ndx - 1]; - else - newoff = hashp->BSIZE; - pairlen = newoff - bp[ndx + 1]; - - if (ndx != (n - 1)) { - /* Hard Case -- need to shuffle keys */ - register int i; - register char *src = bufp->page + (int)OFFSET(bp); - register char *dst = src + (int)pairlen; - memmove(dst, src, bp[ndx + 1] - OFFSET(bp)); - - /* Now adjust the pointers */ - for (i = ndx + 2; i <= n; i += 2) { - if (bp[i + 1] == OVFLPAGE) { - bp[i - 2] = bp[i]; - bp[i - 1] = bp[i + 1]; - } else { - bp[i - 2] = bp[i] + pairlen; - bp[i - 1] = bp[i + 1] + pairlen; - } - } - } - /* Finally adjust the page data */ - bp[n] = OFFSET(bp) + pairlen; - bp[n - 1] = bp[n + 1] + pairlen + 2 * sizeof(u_int16_t); - bp[0] = n - 2; - hashp->NKEYS--; - - bufp->flags |= BUF_MOD; - return (0); -} -/* - * Returns: - * 0 ==> OK - * -1 ==> Error - */ -extern int -__split_page(hashp, obucket, nbucket) - HTAB *hashp; - u_int32_t obucket, nbucket; -{ - register BUFHEAD *new_bufp, *old_bufp; - register u_int16_t *ino; - register char *np; - DBT key, val; - int n, ndx, retval; - u_int16_t copyto, diff, off, moved; - char *op; - - copyto = (u_int16_t)hashp->BSIZE; - off = (u_int16_t)hashp->BSIZE; - old_bufp = __get_buf(hashp, obucket, NULL, 0); - if (old_bufp == NULL) - return (-1); - new_bufp = __get_buf(hashp, nbucket, NULL, 0); - if (new_bufp == NULL) - return (-1); - - old_bufp->flags |= (BUF_MOD | BUF_PIN); - new_bufp->flags |= (BUF_MOD | BUF_PIN); - - ino = (u_int16_t *)(op = old_bufp->page); - np = new_bufp->page; - - moved = 0; - - for (n = 1, ndx = 1; n < ino[0]; n += 2) { - if (ino[n + 1] < REAL_KEY) { - retval = ugly_split(hashp, obucket, old_bufp, new_bufp, - (int)copyto, (int)moved); - old_bufp->flags &= ~BUF_PIN; - new_bufp->flags &= ~BUF_PIN; - return (retval); - - } - key.data = (u_char *)op + ino[n]; - key.size = off - ino[n]; - - if (__call_hash(hashp, key.data, key.size) == obucket) { - /* Don't switch page */ - diff = copyto - off; - if (diff) { - copyto = ino[n + 1] + diff; - memmove(op + copyto, op + ino[n + 1], - off - ino[n + 1]); - ino[ndx] = copyto + ino[n] - ino[n + 1]; - ino[ndx + 1] = copyto; - } else - copyto = ino[n + 1]; - ndx += 2; - } else { - /* Switch page */ - val.data = (u_char *)op + ino[n + 1]; - val.size = ino[n] - ino[n + 1]; - putpair(np, &key, &val); - moved += 2; - } - - off = ino[n + 1]; - } - - /* Now clean up the page */ - ino[0] -= moved; - FREESPACE(ino) = copyto - sizeof(u_int16_t) * (ino[0] + 3); - OFFSET(ino) = copyto; - -#ifdef DEBUG3 - (void)fprintf(stderr, "split %d/%d\n", - ((u_int16_t *)np)[0] / 2, - ((u_int16_t *)op)[0] / 2); -#endif - /* unpin both pages */ - old_bufp->flags &= ~BUF_PIN; - new_bufp->flags &= ~BUF_PIN; - return (0); -} - -/* - * Called when we encounter an overflow or big key/data page during split - * handling. This is special cased since we have to begin checking whether - * the key/data pairs fit on their respective pages and because we may need - * overflow pages for both the old and new pages. - * - * The first page might be a page with regular key/data pairs in which case - * we have a regular overflow condition and just need to go on to the next - * page or it might be a big key/data pair in which case we need to fix the - * big key/data pair. - * - * Returns: - * 0 ==> success - * -1 ==> failure - */ -static int -ugly_split(hashp, obucket, old_bufp, new_bufp, copyto, moved) - HTAB *hashp; - u_int32_t obucket; /* Same as __split_page. */ - BUFHEAD *old_bufp, *new_bufp; - int copyto; /* First byte on page which contains key/data values. */ - int moved; /* Number of pairs moved to new page. */ -{ - register BUFHEAD *bufp; /* Buffer header for ino */ - register u_int16_t *ino; /* Page keys come off of */ - register u_int16_t *np; /* New page */ - register u_int16_t *op; /* Page keys go on to if they aren't moving */ - - BUFHEAD *last_bfp; /* Last buf header OVFL needing to be freed */ - DBT key, val; - SPLIT_RETURN ret; - u_int16_t n, off, ov_addr, scopyto; - char *cino; /* Character value of ino */ - - bufp = old_bufp; - ino = (u_int16_t *)old_bufp->page; - np = (u_int16_t *)new_bufp->page; - op = (u_int16_t *)old_bufp->page; - last_bfp = NULL; - scopyto = (u_int16_t)copyto; /* ANSI */ - - n = ino[0] - 1; - while (n < ino[0]) { - if (ino[2] < REAL_KEY && ino[2] != OVFLPAGE) { - if (__big_split(hashp, old_bufp, - new_bufp, bufp, bufp->addr, obucket, &ret)) - return (-1); - old_bufp = ret.oldp; - if (!old_bufp) - return (-1); - op = (u_int16_t *)old_bufp->page; - new_bufp = ret.newp; - if (!new_bufp) - return (-1); - np = (u_int16_t *)new_bufp->page; - bufp = ret.nextp; - if (!bufp) - return (0); - cino = (char *)bufp->page; - ino = (u_int16_t *)cino; - last_bfp = ret.nextp; - } else if (ino[n + 1] == OVFLPAGE) { - ov_addr = ino[n]; - /* - * Fix up the old page -- the extra 2 are the fields - * which contained the overflow information. - */ - ino[0] -= (moved + 2); - FREESPACE(ino) = - scopyto - sizeof(u_int16_t) * (ino[0] + 3); - OFFSET(ino) = scopyto; - - bufp = __get_buf(hashp, ov_addr, bufp, 0); - if (!bufp) - return (-1); - - ino = (u_int16_t *)bufp->page; - n = 1; - scopyto = hashp->BSIZE; - moved = 0; - - if (last_bfp) - __free_ovflpage(hashp, last_bfp); - last_bfp = bufp; - } - /* Move regular sized pairs of there are any */ - off = hashp->BSIZE; - for (n = 1; (n < ino[0]) && (ino[n + 1] >= REAL_KEY); n += 2) { - cino = (char *)ino; - key.data = (u_char *)cino + ino[n]; - key.size = off - ino[n]; - val.data = (u_char *)cino + ino[n + 1]; - val.size = ino[n] - ino[n + 1]; - off = ino[n + 1]; - - if (__call_hash(hashp, key.data, key.size) == obucket) { - /* Keep on old page */ - if (PAIRFITS(op, (&key), (&val))) - putpair((char *)op, &key, &val); - else { - old_bufp = - __add_ovflpage(hashp, old_bufp); - if (!old_bufp) - return (-1); - op = (u_int16_t *)old_bufp->page; - putpair((char *)op, &key, &val); - } - old_bufp->flags |= BUF_MOD; - } else { - /* Move to new page */ - if (PAIRFITS(np, (&key), (&val))) - putpair((char *)np, &key, &val); - else { - new_bufp = - __add_ovflpage(hashp, new_bufp); - if (!new_bufp) - return (-1); - np = (u_int16_t *)new_bufp->page; - putpair((char *)np, &key, &val); - } - new_bufp->flags |= BUF_MOD; - } - } - } - if (last_bfp) - __free_ovflpage(hashp, last_bfp); - return (0); -} - -/* - * Add the given pair to the page - * - * Returns: - * 0 ==> OK - * 1 ==> failure - */ -extern int -__addel(hashp, bufp, key, val) - HTAB *hashp; - BUFHEAD *bufp; - const DBT *key, *val; -{ - register u_int16_t *bp, *sop; - int do_expand; - - bp = (u_int16_t *)bufp->page; - do_expand = 0; - while (bp[0] && (bp[2] < REAL_KEY || bp[bp[0]] < REAL_KEY)) - /* Exception case */ - if (bp[2] == FULL_KEY_DATA && bp[0] == 2) - /* This is the last page of a big key/data pair - and we need to add another page */ - break; - else if (bp[2] < REAL_KEY && bp[bp[0]] != OVFLPAGE) { - bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); - if (!bufp) - return (-1); - bp = (u_int16_t *)bufp->page; - } else - /* Try to squeeze key on this page */ - if (FREESPACE(bp) > PAIRSIZE(key, val)) { - squeeze_key(bp, key, val); - return (0); - } else { - bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0); - if (!bufp) - return (-1); - bp = (u_int16_t *)bufp->page; - } - - if (PAIRFITS(bp, key, val)) - putpair(bufp->page, key, val); - else { - do_expand = 1; - bufp = __add_ovflpage(hashp, bufp); - if (!bufp) - return (-1); - sop = (u_int16_t *)bufp->page; - - if (PAIRFITS(sop, key, val)) - putpair((char *)sop, key, val); - else - if (__big_insert(hashp, bufp, key, val)) - return (-1); - } - bufp->flags |= BUF_MOD; - /* - * If the average number of keys per bucket exceeds the fill factor, - * expand the table. - */ - hashp->NKEYS++; - if (do_expand || - (hashp->NKEYS / (hashp->MAX_BUCKET + 1) > hashp->FFACTOR)) - return (__expand_table(hashp)); - return (0); -} - -/* - * - * Returns: - * pointer on success - * NULL on error - */ -extern BUFHEAD * -__add_ovflpage(hashp, bufp) - HTAB *hashp; - BUFHEAD *bufp; -{ - register u_int16_t *sp; - u_int16_t ndx, ovfl_num; -#ifdef DEBUG1 - int tmp1, tmp2; -#endif - sp = (u_int16_t *)bufp->page; - - /* Check if we are dynamically determining the fill factor */ - if (hashp->FFACTOR == DEF_FFACTOR) { - hashp->FFACTOR = sp[0] >> 1; - if (hashp->FFACTOR < MIN_FFACTOR) - hashp->FFACTOR = MIN_FFACTOR; - } - bufp->flags |= BUF_MOD; - ovfl_num = overflow_page(hashp); -#ifdef DEBUG1 - tmp1 = bufp->addr; - tmp2 = bufp->ovfl ? bufp->ovfl->addr : 0; -#endif - if (!ovfl_num || !(bufp->ovfl = __get_buf(hashp, ovfl_num, bufp, 1))) - return (NULL); - bufp->ovfl->flags |= BUF_MOD; -#ifdef DEBUG1 - (void)fprintf(stderr, "ADDOVFLPAGE: %d->ovfl was %d is now %d\n", - tmp1, tmp2, bufp->ovfl->addr); -#endif - ndx = sp[0]; - /* - * Since a pair is allocated on a page only if there's room to add - * an overflow page, we know that the OVFL information will fit on - * the page. - */ - sp[ndx + 4] = OFFSET(sp); - sp[ndx + 3] = FREESPACE(sp) - OVFLSIZE; - sp[ndx + 1] = ovfl_num; - sp[ndx + 2] = OVFLPAGE; - sp[0] = ndx + 2; -#ifdef HASH_STATISTICS - hash_overflows++; -#endif - return (bufp->ovfl); -} - -/* - * Returns: - * 0 indicates SUCCESS - * -1 indicates FAILURE - */ -extern int -__get_page(hashp, p, bucket, is_bucket, is_disk, is_bitmap) - HTAB *hashp; - char *p; - u_int32_t bucket; - int is_bucket, is_disk, is_bitmap; -{ - register int fd, page, size; - int rsize; - u_int16_t *bp; - - fd = hashp->fp; - size = hashp->BSIZE; - - if ((fd == -1) || !is_disk) { - PAGE_INIT(p); - return (0); - } - if (is_bucket) - page = BUCKET_TO_PAGE(bucket); - else - page = OADDR_TO_PAGE(bucket); - if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) || - ((rsize = read(fd, p, size)) == -1)) - return (-1); - bp = (u_int16_t *)p; - if (!rsize) - bp[0] = 0; /* We hit the EOF, so initialize a new page */ - else - if (rsize != size) { - errno = EFTYPE; - return (-1); - } - if (!is_bitmap && !bp[0]) { - PAGE_INIT(p); - } else - if (hashp->LORDER != BYTE_ORDER) { - register int i, max; - - if (is_bitmap) { - max = hashp->BSIZE >> 2; /* divide by 4 */ - for (i = 0; i < max; i++) - M_32_SWAP(((int *)p)[i]); - } else { - M_16_SWAP(bp[0]); - max = bp[0] + 2; - for (i = 1; i <= max; i++) - M_16_SWAP(bp[i]); - } - } - return (0); -} - -/* - * Write page p to disk - * - * Returns: - * 0 ==> OK - * -1 ==>failure - */ -extern int -__put_page(hashp, p, bucket, is_bucket, is_bitmap) - HTAB *hashp; - char *p; - u_int32_t bucket; - int is_bucket, is_bitmap; -{ - register int fd, page, size; - int wsize; - - size = hashp->BSIZE; - if ((hashp->fp == -1) && open_temp(hashp)) - return (-1); - fd = hashp->fp; - - if (hashp->LORDER != BYTE_ORDER) { - register int i; - register int max; - - if (is_bitmap) { - max = hashp->BSIZE >> 2; /* divide by 4 */ - for (i = 0; i < max; i++) - M_32_SWAP(((int *)p)[i]); - } else { - max = ((u_int16_t *)p)[0] + 2; - for (i = 0; i <= max; i++) - M_16_SWAP(((u_int16_t *)p)[i]); - } - } - if (is_bucket) - page = BUCKET_TO_PAGE(bucket); - else - page = OADDR_TO_PAGE(bucket); - if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) || - ((wsize = write(fd, p, size)) == -1)) - /* Errno is set */ - return (-1); - if (wsize != size) { - errno = EFTYPE; - return (-1); - } - return (0); -} - -#define BYTE_MASK ((1 << INT_BYTE_SHIFT) -1) -/* - * Initialize a new bitmap page. Bitmap pages are left in memory - * once they are read in. - */ -extern int -__ibitmap(hashp, pnum, nbits, ndx) - HTAB *hashp; - int pnum, nbits, ndx; -{ - u_int32_t *ip; - int clearbytes, clearints; - - if ((ip = (u_int32_t *)malloc(hashp->BSIZE)) == NULL) - return (1); - hashp->nmaps++; - clearints = ((nbits - 1) >> INT_BYTE_SHIFT) + 1; - clearbytes = clearints << INT_TO_BYTE; - (void)memset((char *)ip, 0, clearbytes); - (void)memset(((char *)ip) + clearbytes, 0xFF, - hashp->BSIZE - clearbytes); - ip[clearints - 1] = ALL_SET << (nbits & BYTE_MASK); - SETBIT(ip, 0); - hashp->BITMAPS[ndx] = (u_int16_t)pnum; - hashp->mapp[ndx] = ip; - return (0); -} - -static u_int32_t -first_free(map) - u_int32_t map; -{ - register u_int32_t i, mask; - - mask = 0x1; - for (i = 0; i < BITS_PER_MAP; i++) { - if (!(mask & map)) - return (i); - mask = mask << 1; - } - return (i); -} - -static u_int16_t -overflow_page(hashp) - HTAB *hashp; -{ - register u_int32_t *freep; - register int max_free, offset, splitnum; - u_int16_t addr; - int bit, first_page, free_bit, free_page, i, in_use_bits, j; -#ifdef DEBUG2 - int tmp1, tmp2; -#endif - splitnum = hashp->OVFL_POINT; - max_free = hashp->SPARES[splitnum]; - - free_page = (max_free - 1) >> (hashp->BSHIFT + BYTE_SHIFT); - free_bit = (max_free - 1) & ((hashp->BSIZE << BYTE_SHIFT) - 1); - - /* Look through all the free maps to find the first free block */ - first_page = hashp->LAST_FREED >>(hashp->BSHIFT + BYTE_SHIFT); - for ( i = first_page; i <= free_page; i++ ) { - if (!(freep = (u_int32_t *)hashp->mapp[i]) && - !(freep = fetch_bitmap(hashp, i))) - return (0); - if (i == free_page) - in_use_bits = free_bit; - else - in_use_bits = (hashp->BSIZE << BYTE_SHIFT) - 1; - - if (i == first_page) { - bit = hashp->LAST_FREED & - ((hashp->BSIZE << BYTE_SHIFT) - 1); - j = bit / BITS_PER_MAP; - bit = bit & ~(BITS_PER_MAP - 1); - } else { - bit = 0; - j = 0; - } - for (; bit <= in_use_bits; j++, bit += BITS_PER_MAP) - if (freep[j] != ALL_SET) - goto found; - } - - /* No Free Page Found */ - hashp->LAST_FREED = hashp->SPARES[splitnum]; - hashp->SPARES[splitnum]++; - offset = hashp->SPARES[splitnum] - - (splitnum ? hashp->SPARES[splitnum - 1] : 0); - -#define OVMSG "HASH: Out of overflow pages. Increase page size\n" - if (offset > SPLITMASK) { - if (++splitnum >= NCACHED) { - (void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1); - return (0); - } - hashp->OVFL_POINT = splitnum; - hashp->SPARES[splitnum] = hashp->SPARES[splitnum-1]; - hashp->SPARES[splitnum-1]--; - offset = 1; - } - - /* Check if we need to allocate a new bitmap page */ - if (free_bit == (hashp->BSIZE << BYTE_SHIFT) - 1) { - free_page++; - if (free_page >= NCACHED) { - (void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1); - return (0); - } - /* - * This is tricky. The 1 indicates that you want the new page - * allocated with 1 clear bit. Actually, you are going to - * allocate 2 pages from this map. The first is going to be - * the map page, the second is the overflow page we were - * looking for. The init_bitmap routine automatically, sets - * the first bit of itself to indicate that the bitmap itself - * is in use. We would explicitly set the second bit, but - * don't have to if we tell init_bitmap not to leave it clear - * in the first place. - */ - if (__ibitmap(hashp, - (int)OADDR_OF(splitnum, offset), 1, free_page)) - return (0); - hashp->SPARES[splitnum]++; -#ifdef DEBUG2 - free_bit = 2; -#endif - offset++; - if (offset > SPLITMASK) { - if (++splitnum >= NCACHED) { - (void)write(STDERR_FILENO, OVMSG, - sizeof(OVMSG) - 1); - return (0); - } - hashp->OVFL_POINT = splitnum; - hashp->SPARES[splitnum] = hashp->SPARES[splitnum-1]; - hashp->SPARES[splitnum-1]--; - offset = 0; - } - } else { - /* - * Free_bit addresses the last used bit. Bump it to address - * the first available bit. - */ - free_bit++; - SETBIT(freep, free_bit); - } - - /* Calculate address of the new overflow page */ - addr = OADDR_OF(splitnum, offset); -#ifdef DEBUG2 - (void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n", - addr, free_bit, free_page); -#endif - return (addr); - -found: - bit = bit + first_free(freep[j]); - SETBIT(freep, bit); -#ifdef DEBUG2 - tmp1 = bit; - tmp2 = i; -#endif - /* - * Bits are addressed starting with 0, but overflow pages are addressed - * beginning at 1. Bit is a bit addressnumber, so we need to increment - * it to convert it to a page number. - */ - bit = 1 + bit + (i * (hashp->BSIZE << BYTE_SHIFT)); - if (bit >= hashp->LAST_FREED) - hashp->LAST_FREED = bit - 1; - - /* Calculate the split number for this page */ - for (i = 0; (i < splitnum) && (bit > hashp->SPARES[i]); i++); - offset = (i ? bit - hashp->SPARES[i - 1] : bit); - if (offset >= SPLITMASK) - return (0); /* Out of overflow pages */ - addr = OADDR_OF(i, offset); -#ifdef DEBUG2 - (void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n", - addr, tmp1, tmp2); -#endif - - /* Allocate and return the overflow page */ - return (addr); -} - -/* - * Mark this overflow page as free. - */ -extern void -__free_ovflpage(hashp, obufp) - HTAB *hashp; - BUFHEAD *obufp; -{ - register u_int16_t addr; - u_int32_t *freep; - int bit_address, free_page, free_bit; - u_int16_t ndx; - - addr = obufp->addr; -#ifdef DEBUG1 - (void)fprintf(stderr, "Freeing %d\n", addr); -#endif - ndx = (((u_int16_t)addr) >> SPLITSHIFT); - bit_address = - (ndx ? hashp->SPARES[ndx - 1] : 0) + (addr & SPLITMASK) - 1; - if (bit_address < hashp->LAST_FREED) - hashp->LAST_FREED = bit_address; - free_page = (bit_address >> (hashp->BSHIFT + BYTE_SHIFT)); - free_bit = bit_address & ((hashp->BSIZE << BYTE_SHIFT) - 1); - - if (!(freep = hashp->mapp[free_page])) - freep = fetch_bitmap(hashp, free_page); -#ifdef DEBUG - /* - * This had better never happen. It means we tried to read a bitmap - * that has already had overflow pages allocated off it, and we - * failed to read it from the file. - */ - if (!freep) - assert(0); -#endif - CLRBIT(freep, free_bit); -#ifdef DEBUG2 - (void)fprintf(stderr, "FREE_OVFLPAGE: ADDR: %d BIT: %d PAGE %d\n", - obufp->addr, free_bit, free_page); -#endif - __reclaim_buf(hashp, obufp); -} - -/* - * Returns: - * 0 success - * -1 failure - */ -static int -open_temp(hashp) - HTAB *hashp; -{ - sigset_t set, oset; - static char namestr[] = "_hashXXXXXX"; - - /* Block signals; make sure file goes away at process exit. */ - (void)sigfillset(&set); - (void)sigprocmask(SIG_BLOCK, &set, &oset); - if ((hashp->fp = mkstemp(namestr)) != -1) { - (void)unlink(namestr); - (void)fcntl(hashp->fp, F_SETFD, 1); - } - (void)sigprocmask(SIG_SETMASK, &oset, (sigset_t *)NULL); - return (hashp->fp != -1 ? 0 : -1); -} - -/* - * We have to know that the key will fit, but the last entry on the page is - * an overflow pair, so we need to shift things. - */ -static void -squeeze_key(sp, key, val) - u_int16_t *sp; - const DBT *key, *val; -{ - register char *p; - u_int16_t free_space, n, off, pageno; - - p = (char *)sp; - n = sp[0]; - free_space = FREESPACE(sp); - off = OFFSET(sp); - - pageno = sp[n - 1]; - off -= key->size; - sp[n - 1] = off; - memmove(p + off, key->data, key->size); - off -= val->size; - sp[n] = off; - memmove(p + off, val->data, val->size); - sp[0] = n + 2; - sp[n + 1] = pageno; - sp[n + 2] = OVFLPAGE; - FREESPACE(sp) = free_space - PAIRSIZE(key, val); - OFFSET(sp) = off; -} - -static u_int32_t * -fetch_bitmap(hashp, ndx) - HTAB *hashp; - int ndx; -{ - if (ndx >= hashp->nmaps) - return (NULL); - if ((hashp->mapp[ndx] = (u_int32_t *)malloc(hashp->BSIZE)) == NULL) - return (NULL); - if (__get_page(hashp, - (char *)hashp->mapp[ndx], hashp->BITMAPS[ndx], 0, 1, 1)) { - free(hashp->mapp[ndx]); - return (NULL); - } - return (hashp->mapp[ndx]); -} - -#ifdef DEBUG4 -int -print_chain(addr) - int addr; -{ - BUFHEAD *bufp; - short *bp, oaddr; - - (void)fprintf(stderr, "%d ", addr); - bufp = __get_buf(hashp, addr, NULL, 0); - bp = (short *)bufp->page; - while (bp[0] && ((bp[bp[0]] == OVFLPAGE) || - ((bp[0] > 2) && bp[2] < REAL_KEY))) { - oaddr = bp[bp[0] - 1]; - (void)fprintf(stderr, "%d ", (int)oaddr); - bufp = __get_buf(hashp, (int)oaddr, bufp, 0); - bp = (short *)bufp->page; - } - (void)fprintf(stderr, "\n"); -} -#endif diff --git a/db/hash/ndbm.c b/db/hash/ndbm.c deleted file mode 100644 index 83aa766..0000000 --- a/db/hash/ndbm.c +++ /dev/null @@ -1,215 +0,0 @@ -/*- - * Copyright (c) 1990, 1993 - * 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. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)ndbm.c 8.4 (Berkeley) 7/21/94"; -#endif /* LIBC_SCCS and not lint */ - -/* - * This package provides a dbm compatible interface to the new hashing - * package described in db(3). - */ - -#include <sys/param.h> - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> - -#include <ndbm.h> -#include "hash.h" - -/* - * Returns: - * *DBM on success - * NULL on failure - */ -extern DBM * -dbm_open(file, flags, mode) - const char *file; - int flags, mode; -{ - DBM *db; - HASHINFO info; - const size_t len = strlen(file) + sizeof (DBM_SUFFIX); -#ifdef __GNUC__ - char path[len]; -#else - char *path = malloc(len); - if (path == NULL) - return NULL; -#endif - - info.bsize = 4096; - info.ffactor = 40; - info.nelem = 1; - info.cachesize = 0; - info.hash = NULL; - info.lorder = 0; - (void)strcpy(path, file); - (void)strcat(path, DBM_SUFFIX); - db = (DBM *)__hash_open(path, flags, mode, &info, 0); -#ifndef __GNUC__ - free(path); -#endif - return db; -} - -extern void -dbm_close(db) - DBM *db; -{ - (void)(db->close)(db); -} - -/* - * Returns: - * DATUM on success - * NULL on failure - */ -extern datum -dbm_fetch(db, key) - DBM *db; - datum key; -{ - datum retval; - int status; - - status = (db->get)(db, (DBT *)&key, (DBT *)&retval, 0); - if (status) { - retval.dptr = NULL; - retval.dsize = 0; - } - return (retval); -} - -/* - * Returns: - * DATUM on success - * NULL on failure - */ -extern datum -dbm_firstkey(db) - DBM *db; -{ - int status; - datum retdata, retkey; - - status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_FIRST); - if (status) - retkey.dptr = NULL; - return (retkey); -} - -/* - * Returns: - * DATUM on success - * NULL on failure - */ -extern datum -dbm_nextkey(db) - DBM *db; -{ - int status; - datum retdata, retkey; - - status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_NEXT); - if (status) - retkey.dptr = NULL; - return (retkey); -} -/* - * Returns: - * 0 on success - * <0 failure - */ -extern int -dbm_delete(db, key) - DBM *db; - datum key; -{ - int status; - - status = (db->del)(db, (DBT *)&key, 0); - if (status) - return (-1); - else - return (0); -} - -/* - * Returns: - * 0 on success - * <0 failure - * 1 if DBM_INSERT and entry exists - */ -extern int -dbm_store(db, key, content, flags) - DBM *db; - datum key, content; - int flags; -{ - return ((db->put)(db, (DBT *)&key, (DBT *)&content, - (flags == DBM_INSERT) ? R_NOOVERWRITE : 0)); -} - -extern int -dbm_error(db) - DBM *db; -{ - HTAB *hp; - - hp = (HTAB *)db->internal; - return (hp->errnum); -} - -extern int -dbm_clearerr(db) - DBM *db; -{ - HTAB *hp; - - hp = (HTAB *)db->internal; - hp->errnum = 0; - return (0); -} - -extern int -dbm_dirfno(db) - DBM *db; -{ - return(((HTAB *)db->internal)->fp); -} diff --git a/db/hash/page.h b/db/hash/page.h deleted file mode 100644 index 0fc0d5a..0000000 --- a/db/hash/page.h +++ /dev/null @@ -1,92 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * 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. - * - * @(#)page.h 8.2 (Berkeley) 5/31/94 - */ - -/* - * Definitions for hashing page file format. - */ - -/* - * routines dealing with a data page - * - * page format: - * +------------------------------+ - * p | n | keyoff | datoff | keyoff | - * +------------+--------+--------+ - * | datoff | free | ptr | --> | - * +--------+---------------------+ - * | F R E E A R E A | - * +--------------+---------------+ - * | <---- - - - | data | - * +--------+-----+----+----------+ - * | key | data | key | - * +--------+----------+----------+ - * - * Pointer to the free space is always: p[p[0] + 2] - * Amount of free space on the page is: p[p[0] + 1] - */ - -/* - * How many bytes required for this pair? - * 2 shorts in the table at the top of the page + room for the - * key and room for the data - * - * We prohibit entering a pair on a page unless there is also room to append - * an overflow page. The reason for this it that you can get in a situation - * where a single key/data pair fits on a page, but you can't append an - * overflow page and later you'd have to split the key/data and handle like - * a big pair. - * You might as well do this up front. - */ - -#define PAIRSIZE(K,D) (2*sizeof(u_int16_t) + (K)->size + (D)->size) -#define BIGOVERHEAD (4*sizeof(u_int16_t)) -#define KEYSIZE(K) (4*sizeof(u_int16_t) + (K)->size); -#define OVFLSIZE (2*sizeof(u_int16_t)) -#define FREESPACE(P) ((P)[(P)[0]+1]) -#define OFFSET(P) ((P)[(P)[0]+2]) -#define PAIRFITS(P,K,D) \ - (((P)[2] >= REAL_KEY) && \ - (PAIRSIZE((K),(D)) + OVFLSIZE) <= FREESPACE((P))) -#define PAGE_META(N) (((N)+3) * sizeof(u_int16_t)) - -typedef struct { - BUFHEAD *newp; - BUFHEAD *oldp; - BUFHEAD *nextp; - u_int16_t next_addr; -} SPLIT_RETURN; diff --git a/db/mpool.h b/db/mpool.h deleted file mode 100644 index 22c9fea..0000000 --- a/db/mpool.h +++ /dev/null @@ -1,112 +0,0 @@ -/*- - * Copyright (c) 1991, 1993, 1994 - * The Regents of the University of California. 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. - * - * @(#)mpool.h 8.2 (Berkeley) 7/14/94 - */ - -#ifndef _MPOOL_H -#define _MPOOL_H 1 - -#include <sys/queue.h> - -/* - * The memory pool scheme is a simple one. Each in-memory page is referenced - * by a bucket which is threaded in up to two of three ways. All active pages - * are threaded on a hash chain (hashed by page number) and an lru chain. - * Inactive pages are threaded on a free chain. Each reference to a memory - * pool is handed an opaque MPOOL cookie which stores all of this information. - */ -#define HASHSIZE 128 -#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) - -/* The BKT structures are the elements of the queues. */ -typedef struct _bkt { - CIRCLEQ_ENTRY(_bkt) hq; /* hash queue */ - CIRCLEQ_ENTRY(_bkt) q; /* lru queue */ - void *page; /* page */ - pgno_t pgno; /* page number */ - -#define MPOOL_DIRTY 0x01 /* page needs to be written */ -#define MPOOL_PINNED 0x02 /* page is pinned into memory */ - u_int8_t flags; /* flags */ -} BKT; - -typedef struct MPOOL { - CIRCLEQ_HEAD(_lqh, _bkt) lqh; /* lru queue head */ - /* hash queue array */ - CIRCLEQ_HEAD(_hqh, _bkt) hqh[HASHSIZE]; - pgno_t curcache; /* current number of cached pages */ - pgno_t maxcache; /* max number of cached pages */ - pgno_t npages; /* number of pages in the file */ - u_long pagesize; /* file page size */ - int fd; /* file descriptor */ - /* page in conversion routine */ - void (*pgin) __PMT((void *, pgno_t, void *)); - /* page out conversion routine */ - void (*pgout) __PMT((void *, pgno_t, void *)); - void *pgcookie; /* cookie for page in/out routines */ -#ifdef STATISTICS - u_long cachehit; - u_long cachemiss; - u_long pagealloc; - u_long pageflush; - u_long pageget; - u_long pagenew; - u_long pageput; - u_long pageread; - u_long pagewrite; -#endif -} MPOOL; - -__BEGIN_DECLS -MPOOL *__mpool_open __P((void *, int, pgno_t, pgno_t)); -MPOOL *mpool_open __P((void *, int, pgno_t, pgno_t)); -void __mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), - void (*)(void *, pgno_t, void *), void *)); -void mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *), - void (*)(void *, pgno_t, void *), void *)); -void *__mpool_new __P((MPOOL *, pgno_t *)); -void *mpool_new __P((MPOOL *, pgno_t *)); -void *__mpool_get __P((MPOOL *, pgno_t, u_int)); -void *mpool_get __P((MPOOL *, pgno_t, u_int)); -int __mpool_put __P((MPOOL *, void *, u_int)); -int mpool_put __P((MPOOL *, void *, u_int)); -int __mpool_sync __P((MPOOL *)); -int mpool_sync __P((MPOOL *)); -int __mpool_close __P((MPOOL *)); -int mpool_close __P((MPOOL *)); -#ifdef STATISTICS -void mpool_stat __P((MPOOL *)); -#endif -__END_DECLS - -#endif /* mpool.h */ diff --git a/db/mpool/mpool.c b/db/mpool/mpool.c deleted file mode 100644 index 7ced76f..0000000 --- a/db/mpool/mpool.c +++ /dev/null @@ -1,493 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. 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. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)mpool.c 8.5 (Berkeley) 7/26/94"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/param.h> -#include <sys/queue.h> -#include <sys/stat.h> - -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include <db.h> - -#define __MPOOLINTERFACE_PRIVATE -#include <mpool.h> - -#ifdef _LIBC -/* In the GNU C library we must not pollute the namespace because libdb is - needed by libnss_db. */ -#define mpool_open __mpool_open -#define mpool_filter __mpool_filter -#define mpool_new __mpool_new -#define mpool_get __mpool_get -#define mpool_put __mpool_put -#define mpool_sync __mpool_sync -#define mpool_close __mpool_close -#endif - -static BKT *mpool_bkt __P((MPOOL *)); -static BKT *mpool_look __P((MPOOL *, pgno_t)); -static int mpool_write __P((MPOOL *, BKT *)); - -/* - * mpool_open -- - * Initialize a memory pool. - */ -MPOOL * -mpool_open(key, fd, pagesize, maxcache) - void *key; - int fd; - pgno_t pagesize, maxcache; -{ - struct stat sb; - MPOOL *mp; - int entry; - - /* - * Get information about the file. - * - * XXX - * We don't currently handle pipes, although we should. - */ - if (fstat(fd, &sb)) - return (NULL); - if (!S_ISREG(sb.st_mode)) { - errno = ESPIPE; - return (NULL); - } - - /* Allocate and initialize the MPOOL cookie. */ - if ((mp = (MPOOL *)calloc(1, sizeof(MPOOL))) == NULL) - return (NULL); - CIRCLEQ_INIT(&mp->lqh); - for (entry = 0; entry < HASHSIZE; ++entry) - CIRCLEQ_INIT(&mp->hqh[entry]); - mp->maxcache = maxcache; - mp->npages = sb.st_size / pagesize; - mp->pagesize = pagesize; - mp->fd = fd; - return (mp); -} - -/* - * mpool_filter -- - * Initialize input/output filters. - */ -void -mpool_filter(mp, pgin, pgout, pgcookie) - MPOOL *mp; - void (*pgin) __P((void *, pgno_t, void *)); - void (*pgout) __P((void *, pgno_t, void *)); - void *pgcookie; -{ - mp->pgin = pgin; - mp->pgout = pgout; - mp->pgcookie = pgcookie; -} - -/* - * mpool_new -- - * Get a new page of memory. - */ -void * -mpool_new(mp, pgnoaddr) - MPOOL *mp; - pgno_t *pgnoaddr; -{ - struct _hqh *head; - BKT *bp; - - if (mp->npages == MAX_PAGE_NUMBER) { - (void)fprintf(stderr, "mpool_new: page allocation overflow.\n"); - abort(); - } -#ifdef STATISTICS - ++mp->pagenew; -#endif - /* - * Get a BKT from the cache. Assign a new page number, attach - * it to the head of the hash chain, the tail of the lru chain, - * and return. - */ - if ((bp = mpool_bkt(mp)) == NULL) - return (NULL); - *pgnoaddr = bp->pgno = mp->npages++; - bp->flags = MPOOL_PINNED; - - head = &mp->hqh[HASHKEY(bp->pgno)]; - CIRCLEQ_INSERT_HEAD(head, bp, hq); - CIRCLEQ_INSERT_TAIL(&mp->lqh, bp, q); - return (bp->page); -} - -/* - * mpool_get - * Get a page. - */ -void * -mpool_get(mp, pgno, flags) - MPOOL *mp; - pgno_t pgno; - u_int flags; /* XXX not used? */ -{ - struct _hqh *head; - BKT *bp; - off_t off; - int nr; - - /* Check for attempt to retrieve a non-existent page. */ - if (pgno >= mp->npages) { - errno = EINVAL; - return (NULL); - } - -#ifdef STATISTICS - ++mp->pageget; -#endif - - /* Check for a page that is cached. */ - if ((bp = mpool_look(mp, pgno)) != NULL) { -#ifdef DEBUG - if (bp->flags & MPOOL_PINNED) { - (void)fprintf(stderr, - "mpool_get: page %d already pinned\n", bp->pgno); - abort(); - } -#endif - /* - * Move the page to the head of the hash chain and the tail - * of the lru chain. - */ - head = &mp->hqh[HASHKEY(bp->pgno)]; - CIRCLEQ_REMOVE(head, bp, hq); - CIRCLEQ_INSERT_HEAD(head, bp, hq); - CIRCLEQ_REMOVE(&mp->lqh, bp, q); - CIRCLEQ_INSERT_TAIL(&mp->lqh, bp, q); - - /* Return a pinned page. */ - bp->flags |= MPOOL_PINNED; - return (bp->page); - } - - /* Get a page from the cache. */ - if ((bp = mpool_bkt(mp)) == NULL) - return (NULL); - - /* Read in the contents. */ -#ifdef STATISTICS - ++mp->pageread; -#endif - off = mp->pagesize * pgno; - if (lseek(mp->fd, off, SEEK_SET) != off) - return (NULL); - if ((u_long) (nr = read(mp->fd, bp->page, mp->pagesize)) - != mp->pagesize) { - if (nr >= 0) - errno = EFTYPE; - return (NULL); - } - - /* Set the page number, pin the page. */ - bp->pgno = pgno; - bp->flags = MPOOL_PINNED; - - /* - * Add the page to the head of the hash chain and the tail - * of the lru chain. - */ - head = &mp->hqh[HASHKEY(bp->pgno)]; - CIRCLEQ_INSERT_HEAD(head, bp, hq); - CIRCLEQ_INSERT_TAIL(&mp->lqh, bp, q); - - /* Run through the user's filter. */ - if (mp->pgin != NULL) - (mp->pgin)(mp->pgcookie, bp->pgno, bp->page); - - return (bp->page); -} - -/* - * mpool_put - * Return a page. - */ -int -mpool_put(mp, page, flags) - MPOOL *mp; - void *page; - u_int flags; -{ - BKT *bp; - -#ifdef STATISTICS - ++mp->pageput; -#endif - bp = (BKT *)((char *)page - sizeof(BKT)); -#ifdef DEBUG - if (!(bp->flags & MPOOL_PINNED)) { - (void)fprintf(stderr, - "mpool_put: page %d not pinned\n", bp->pgno); - abort(); - } -#endif - bp->flags &= ~MPOOL_PINNED; - bp->flags |= flags & MPOOL_DIRTY; - return (RET_SUCCESS); -} - -/* - * mpool_close - * Close the buffer pool. - */ -int -mpool_close(mp) - MPOOL *mp; -{ - BKT *bp; - - /* Free up any space allocated to the lru pages. */ - while ((bp = mp->lqh.cqh_first) != (void *)&mp->lqh) { - CIRCLEQ_REMOVE(&mp->lqh, mp->lqh.cqh_first, q); - free(bp); - } - - /* Free the MPOOL cookie. */ - free(mp); - return (RET_SUCCESS); -} - -/* - * mpool_sync - * Sync the pool to disk. - */ -int -mpool_sync(mp) - MPOOL *mp; -{ - BKT *bp; - - /* Walk the lru chain, flushing any dirty pages to disk. */ - for (bp = mp->lqh.cqh_first; - bp != (void *)&mp->lqh; bp = bp->q.cqe_next) - if (bp->flags & MPOOL_DIRTY && - mpool_write(mp, bp) == RET_ERROR) - return (RET_ERROR); - - /* Sync the file descriptor. */ - return (fsync(mp->fd) ? RET_ERROR : RET_SUCCESS); -} - -#ifdef _LIBC -#undef mpool_open -#undef mpool_filter -#undef mpool_new -#undef mpool_get -#undef mpool_put -#undef mpool_close -#undef mpool_sync -weak_alias (__mpool_open, mpool_open) -weak_alias (__mpool_filter, mpool_filter) -weak_alias (__mpool_new, mpool_new) -weak_alias (__mpool_get, mpool_get) -weak_alias (__mpool_put, mpool_put) -weak_alias (__mpool_close, mpool_close) -weak_alias (__mpool_sync, mpool_sync) -#endif - -/* - * mpool_bkt - * Get a page from the cache (or create one). - */ -static BKT * -mpool_bkt(mp) - MPOOL *mp; -{ - struct _hqh *head; - BKT *bp; - - /* If under the max cached, always create a new page. */ - if (mp->curcache < mp->maxcache) - goto new; - - /* - * If the cache is max'd out, walk the lru list for a buffer we - * can flush. If we find one, write it (if necessary) and take it - * off any lists. If we don't find anything we grow the cache anyway. - * The cache never shrinks. - */ - for (bp = mp->lqh.cqh_first; - bp != (void *)&mp->lqh; bp = bp->q.cqe_next) - if (!(bp->flags & MPOOL_PINNED)) { - /* Flush if dirty. */ - if (bp->flags & MPOOL_DIRTY && - mpool_write(mp, bp) == RET_ERROR) - return (NULL); -#ifdef STATISTICS - ++mp->pageflush; -#endif - /* Remove from the hash and lru queues. */ - head = &mp->hqh[HASHKEY(bp->pgno)]; - CIRCLEQ_REMOVE(head, bp, hq); - CIRCLEQ_REMOVE(&mp->lqh, bp, q); -#ifdef DEBUG - { void *spage; - spage = bp->page; - memset(bp, 0xff, sizeof(BKT) + mp->pagesize); - bp->page = spage; - } -#endif - return (bp); - } - -new: if ((bp = (BKT *)malloc(sizeof(BKT) + mp->pagesize)) == NULL) - return (NULL); -#ifdef STATISTICS - ++mp->pagealloc; -#endif -#if defined(DEBUG) || defined(PURIFY) - memset(bp, 0xff, sizeof(BKT) + mp->pagesize); -#endif - bp->page = (char *)bp + sizeof(BKT); - ++mp->curcache; - return (bp); -} - -/* - * mpool_write - * Write a page to disk. - */ -static int -mpool_write(mp, bp) - MPOOL *mp; - BKT *bp; -{ - off_t off; - -#ifdef STATISTICS - ++mp->pagewrite; -#endif - - /* Run through the user's filter. */ - if (mp->pgout) - (mp->pgout)(mp->pgcookie, bp->pgno, bp->page); - - off = mp->pagesize * bp->pgno; - if (lseek(mp->fd, off, SEEK_SET) != off) - return (RET_ERROR); - if ((u_long) write(mp->fd, bp->page, mp->pagesize) != mp->pagesize) - return (RET_ERROR); - - bp->flags &= ~MPOOL_DIRTY; - return (RET_SUCCESS); -} - -/* - * mpool_look - * Lookup a page in the cache. - */ -static BKT * -mpool_look(mp, pgno) - MPOOL *mp; - pgno_t pgno; -{ - struct _hqh *head; - BKT *bp; - - head = &mp->hqh[HASHKEY(pgno)]; - for (bp = head->cqh_first; bp != (void *)head; bp = bp->hq.cqe_next) - if (bp->pgno == pgno) { -#ifdef STATISTICS - ++mp->cachehit; -#endif - return (bp); - } -#ifdef STATISTICS - ++mp->cachemiss; -#endif - return (NULL); -} - -#ifdef STATISTICS -/* - * mpool_stat - * Print out cache statistics. - */ -void -mpool_stat(mp) - MPOOL *mp; -{ - BKT *bp; - int cnt; - char *sep; - - (void)fprintf(stderr, "%lu pages in the file\n", mp->npages); - (void)fprintf(stderr, - "page size %lu, cacheing %lu pages of %lu page max cache\n", - mp->pagesize, mp->curcache, mp->maxcache); - (void)fprintf(stderr, "%lu page puts, %lu page gets, %lu page new\n", - mp->pageput, mp->pageget, mp->pagenew); - (void)fprintf(stderr, "%lu page allocs, %lu page flushes\n", - mp->pagealloc, mp->pageflush); - if (mp->cachehit + mp->cachemiss) - (void)fprintf(stderr, - "%.0f%% cache hit rate (%lu hits, %lu misses)\n", - ((double)mp->cachehit / (mp->cachehit + mp->cachemiss)) - * 100, mp->cachehit, mp->cachemiss); - (void)fprintf(stderr, "%lu page reads, %lu page writes\n", - mp->pageread, mp->pagewrite); - - sep = ""; - cnt = 0; - for (bp = mp->lqh.cqh_first; - bp != (void *)&mp->lqh; bp = bp->q.cqe_next) { - (void)fprintf(stderr, "%s%d", sep, bp->pgno); - if (bp->flags & MPOOL_DIRTY) - (void)fprintf(stderr, "d"); - if (bp->flags & MPOOL_PINNED) - (void)fprintf(stderr, "P"); - if (++cnt == 10) { - sep = "\n"; - cnt = 0; - } else - sep = ", "; - - } - (void)fprintf(stderr, "\n"); -} -#endif diff --git a/db/ndbm.h b/db/ndbm.h deleted file mode 100644 index b05aa56..0000000 --- a/db/ndbm.h +++ /dev/null @@ -1,79 +0,0 @@ -/*- - * Copyright (c) 1990, 1993 - * 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. - * - * @(#)ndbm.h 8.1 (Berkeley) 6/2/93 - */ - -#ifndef _NDBM_H -#define _NDBM_H 1 - -#include <db.h> - -/* Map dbm interface onto db(3). */ -#define DBM_RDONLY O_RDONLY - -/* Flags to dbm_store(). */ -#define DBM_INSERT 0 -#define DBM_REPLACE 1 - -/* - * The db(3) support for ndbm(3) always appends this suffix to the - * file name to avoid overwriting the user's original database. - */ -#define DBM_SUFFIX ".db" - -typedef struct { - char *dptr; - int dsize; -} datum; - -typedef DB DBM; -#define dbm_pagfno(a) DBM_PAGFNO_NOT_AVAILABLE - -__BEGIN_DECLS -void dbm_close (DBM *); -int dbm_delete (DBM *, datum); -datum dbm_fetch (DBM *, datum); -datum dbm_firstkey (DBM *); -long dbm_forder (DBM *, datum); -datum dbm_nextkey (DBM *); -DBM *dbm_open (const char *, int, int); -int dbm_store (DBM *, datum, datum, int); -int dbm_dirfno (DBM *); -int dbm_error (DBM *); -int dbm_clearerr (DBM *); -__END_DECLS - -#endif /* ndbm.h */ diff --git a/db/recno/extern.h b/db/recno/extern.h deleted file mode 100644 index feed434..0000000 --- a/db/recno/extern.h +++ /dev/null @@ -1,54 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. 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. - * - * @(#)extern.h 8.3 (Berkeley) 6/4/94 - */ - -#include "../btree/extern.h" - -int __rec_close __P((DB *)); -int __rec_delete __P((const DB *, const DBT *, u_int)); -int __rec_dleaf __P((BTREE *, PAGE *, u_int32_t)); -int __rec_fd __P((const DB *)); -int __rec_fmap __P((BTREE *, recno_t)); -int __rec_fout __P((BTREE *)); -int __rec_fpipe __P((BTREE *, recno_t)); -int __rec_get __P((const DB *, const DBT *, DBT *, u_int)); -int __rec_iput __P((BTREE *, recno_t, const DBT *, u_int)); -int __rec_put __P((const DB *dbp, DBT *, const DBT *, u_int)); -int __rec_ret __P((BTREE *, EPG *, recno_t, DBT *, DBT *)); -EPG *__rec_search __P((BTREE *, recno_t, enum SRCHOP)); -int __rec_seq __P((const DB *, DBT *, DBT *, u_int)); -int __rec_sync __P((const DB *, u_int)); -int __rec_vmap __P((BTREE *, recno_t)); -int __rec_vout __P((BTREE *)); -int __rec_vpipe __P((BTREE *, recno_t)); diff --git a/db/recno/rec_close.c b/db/recno/rec_close.c deleted file mode 100644 index 8a3c4d7..0000000 --- a/db/recno/rec_close.c +++ /dev/null @@ -1,183 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. 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. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)rec_close.c 8.6 (Berkeley) 8/18/94"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/types.h> -#include <sys/uio.h> -#include <sys/mman.h> - -#include <errno.h> -#include <limits.h> -#include <stdio.h> -#include <unistd.h> - -#include <db.h> -#include "recno.h" - -/* - * __REC_CLOSE -- Close a recno tree. - * - * Parameters: - * dbp: pointer to access method - * - * Returns: - * RET_ERROR, RET_SUCCESS - */ -int -__rec_close(dbp) - DB *dbp; -{ - BTREE *t; - int status; - - t = dbp->internal; - - /* Toss any page pinned across calls. */ - if (t->bt_pinned != NULL) { - mpool_put(t->bt_mp, t->bt_pinned, 0); - t->bt_pinned = NULL; - } - - if (__rec_sync(dbp, 0) == RET_ERROR) - return (RET_ERROR); - - /* Committed to closing. */ - status = RET_SUCCESS; - if (F_ISSET(t, R_MEMMAPPED) && munmap(t->bt_smap, t->bt_msize)) - status = RET_ERROR; - - if (!F_ISSET(t, R_INMEM)) { - if (F_ISSET(t, R_CLOSEFP)) { - if (fclose(t->bt_rfp)) - status = RET_ERROR; - } else - if (close(t->bt_rfd)) - status = RET_ERROR; - } - - if (__bt_close(dbp) == RET_ERROR) - status = RET_ERROR; - - return (status); -} - -/* - * __REC_SYNC -- sync the recno tree to disk. - * - * Parameters: - * dbp: pointer to access method - * - * Returns: - * RET_SUCCESS, RET_ERROR. - */ -int -__rec_sync(dbp, flags) - const DB *dbp; - u_int flags; -{ - struct iovec iov[2]; - BTREE *t; - DBT data, key; - off_t off; - recno_t scursor, trec; - int status; - - t = dbp->internal; - - /* Toss any page pinned across calls. */ - if (t->bt_pinned != NULL) { - mpool_put(t->bt_mp, t->bt_pinned, 0); - t->bt_pinned = NULL; - } - - if (flags == R_RECNOSYNC) - return (__bt_sync(dbp, 0)); - - if (F_ISSET(t, R_RDONLY | R_INMEM) || !F_ISSET(t, R_MODIFIED)) - return (RET_SUCCESS); - - /* Read any remaining records into the tree. */ - if (!F_ISSET(t, R_EOF) && t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR) - return (RET_ERROR); - - /* Rewind the file descriptor. */ - if (lseek(t->bt_rfd, (off_t)0, SEEK_SET) != 0) - return (RET_ERROR); - - /* Save the cursor. */ - scursor = t->bt_cursor.rcursor; - - key.size = sizeof(recno_t); - key.data = &trec; - - if (F_ISSET(t, R_FIXLEN)) { - /* - * We assume that fixed length records are all fixed length. - * Any that aren't are either EINVAL'd or corrected by the - * record put code. - */ - status = (dbp->seq)(dbp, &key, &data, R_FIRST); - while (status == RET_SUCCESS) { - if ((size_t) write(t->bt_rfd, data.data, data.size) != data.size) - return (RET_ERROR); - status = (dbp->seq)(dbp, &key, &data, R_NEXT); - } - } else { - iov[1].iov_base = &t->bt_bval; - iov[1].iov_len = 1; - - status = (dbp->seq)(dbp, &key, &data, R_FIRST); - while (status == RET_SUCCESS) { - iov[0].iov_base = data.data; - iov[0].iov_len = data.size; - if ((size_t) writev(t->bt_rfd, iov, 2) != data.size + 1) - return (RET_ERROR); - status = (dbp->seq)(dbp, &key, &data, R_NEXT); - } - } - - /* Restore the cursor. */ - t->bt_cursor.rcursor = scursor; - - if (status == RET_ERROR) - return (RET_ERROR); - if ((off = lseek(t->bt_rfd, (off_t)0, SEEK_CUR)) == -1) - return (RET_ERROR); - if (ftruncate(t->bt_rfd, off)) - return (RET_ERROR); - F_CLR(t, R_MODIFIED); - return (RET_SUCCESS); -} diff --git a/db/recno/rec_delete.c b/db/recno/rec_delete.c deleted file mode 100644 index a16593d..0000000 --- a/db/recno/rec_delete.c +++ /dev/null @@ -1,197 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * 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. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)rec_delete.c 8.7 (Berkeley) 7/14/94"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/types.h> - -#include <errno.h> -#include <stdio.h> -#include <string.h> - -#include <db.h> -#include "recno.h" - -static int rec_rdelete __P((BTREE *, recno_t)); - -/* - * __REC_DELETE -- Delete the item(s) referenced by a key. - * - * Parameters: - * dbp: pointer to access method - * key: key to delete - * flags: R_CURSOR if deleting what the cursor references - * - * Returns: - * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found. - */ -int -__rec_delete(dbp, key, flags) - const DB *dbp; - const DBT *key; - u_int flags; -{ - BTREE *t; - recno_t nrec; - int status; - - t = dbp->internal; - - /* Toss any page pinned across calls. */ - if (t->bt_pinned != NULL) { - mpool_put(t->bt_mp, t->bt_pinned, 0); - t->bt_pinned = NULL; - } - - switch(flags) { - case 0: - if ((nrec = *(recno_t *)key->data) == 0) - goto einval; - if (nrec > t->bt_nrecs) - return (RET_SPECIAL); - --nrec; - status = rec_rdelete(t, nrec); - break; - case R_CURSOR: - if (!F_ISSET(&t->bt_cursor, CURS_INIT)) - goto einval; - if (t->bt_nrecs == 0) - return (RET_SPECIAL); - status = rec_rdelete(t, t->bt_cursor.rcursor - 1); - if (status == RET_SUCCESS) - --t->bt_cursor.rcursor; - break; - default: -einval: errno = EINVAL; - return (RET_ERROR); - } - - if (status == RET_SUCCESS) - F_SET(t, B_MODIFIED | R_MODIFIED); - return (status); -} - -/* - * REC_RDELETE -- Delete the data matching the specified key. - * - * Parameters: - * tree: tree - * nrec: record to delete - * - * Returns: - * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found. - */ -static int -rec_rdelete(t, nrec) - BTREE *t; - recno_t nrec; -{ - EPG *e; - PAGE *h; - int status; - - /* Find the record; __rec_search pins the page. */ - if ((e = __rec_search(t, nrec, SDELETE)) == NULL) - return (RET_ERROR); - - /* Delete the record. */ - h = e->page; - status = __rec_dleaf(t, h, e->index); - if (status != RET_SUCCESS) { - mpool_put(t->bt_mp, h, 0); - return (status); - } - mpool_put(t->bt_mp, h, MPOOL_DIRTY); - return (RET_SUCCESS); -} - -/* - * __REC_DLEAF -- Delete a single record from a recno leaf page. - * - * Parameters: - * t: tree - * index: index on current page to delete - * - * Returns: - * RET_SUCCESS, RET_ERROR. - */ -int -__rec_dleaf(t, h, index) - BTREE *t; - PAGE *h; - u_int32_t index; -{ - RLEAF *rl; - indx_t *ip, cnt, offset; - u_int32_t nbytes; - char *from; - void *to; - - /* - * Delete a record from a recno leaf page. Internal records are never - * deleted from internal pages, regardless of the records that caused - * them to be added being deleted. Pages made empty by deletion are - * not reclaimed. They are, however, made available for reuse. - * - * Pack the remaining entries at the end of the page, shift the indices - * down, overwriting the deleted record and its index. If the record - * uses overflow pages, make them available for reuse. - */ - to = rl = GETRLEAF(h, index); - if (rl->flags & P_BIGDATA && __ovfl_delete(t, rl->bytes) == RET_ERROR) - return (RET_ERROR); - nbytes = NRLEAF(rl); - - /* - * Compress the key/data pairs. Compress and adjust the [BR]LEAF - * offsets. Reset the headers. - */ - from = (char *)h + h->upper; - memmove(from + nbytes, from, (char *)to - from); - h->upper += nbytes; - - offset = h->linp[index]; - for (cnt = &h->linp[index] - (ip = &h->linp[0]); cnt--; ++ip) - if (ip[0] < offset) - ip[0] += nbytes; - for (cnt = &h->linp[NEXTINDEX(h)] - ip; --cnt; ++ip) - ip[0] = ip[1] < offset ? ip[1] + nbytes : ip[1]; - h->lower -= sizeof(indx_t); - --t->bt_nrecs; - return (RET_SUCCESS); -} diff --git a/db/recno/rec_get.c b/db/recno/rec_get.c deleted file mode 100644 index 47dd773..0000000 --- a/db/recno/rec_get.c +++ /dev/null @@ -1,311 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. 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. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)rec_get.c 8.9 (Berkeley) 8/18/94"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/types.h> - -#include <errno.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include <db.h> -#include "recno.h" - -/* - * __REC_GET -- Get a record from the btree. - * - * Parameters: - * dbp: pointer to access method - * key: key to find - * data: data to return - * flag: currently unused - * - * Returns: - * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found. - */ -int -__rec_get(dbp, key, data, flags) - const DB *dbp; - const DBT *key; - DBT *data; - u_int flags; -{ - BTREE *t; - EPG *e; - recno_t nrec; - int status; - - t = dbp->internal; - - /* Toss any page pinned across calls. */ - if (t->bt_pinned != NULL) { - mpool_put(t->bt_mp, t->bt_pinned, 0); - t->bt_pinned = NULL; - } - - /* Get currently doesn't take any flags, and keys of 0 are illegal. */ - if (flags || (nrec = *(recno_t *)key->data) == 0) { - errno = EINVAL; - return (RET_ERROR); - } - - /* - * If we haven't seen this record yet, try to find it in the - * original file. - */ - if (nrec > t->bt_nrecs) { - if (F_ISSET(t, R_EOF | R_INMEM)) - return (RET_SPECIAL); - if ((status = t->bt_irec(t, nrec)) != RET_SUCCESS) - return (status); - } - - --nrec; - if ((e = __rec_search(t, nrec, SEARCH)) == NULL) - return (RET_ERROR); - - status = __rec_ret(t, e, 0, NULL, data); - if (F_ISSET(t, B_DB_LOCK)) - mpool_put(t->bt_mp, e->page, 0); - else - t->bt_pinned = e->page; - return (status); -} - -/* - * __REC_FPIPE -- Get fixed length records from a pipe. - * - * Parameters: - * t: tree - * cnt: records to read - * - * Returns: - * RET_ERROR, RET_SUCCESS - */ -int -__rec_fpipe(t, top) - BTREE *t; - recno_t top; -{ - DBT data; - recno_t nrec; - size_t len; - int ch; - u_char *p; - - if (t->bt_rdata.size < t->bt_reclen) { - t->bt_rdata.data = t->bt_rdata.data == NULL ? - malloc(t->bt_reclen) : - realloc(t->bt_rdata.data, t->bt_reclen); - if (t->bt_rdata.data == NULL) - return (RET_ERROR); - t->bt_rdata.size = t->bt_reclen; - } - data.data = t->bt_rdata.data; - data.size = t->bt_reclen; - - for (nrec = t->bt_nrecs; nrec < top;) { - len = t->bt_reclen; - for (p = t->bt_rdata.data;; *p++ = ch) - if ((ch = getc(t->bt_rfp)) == EOF || !--len) { - if (ch != EOF) - *p = ch; - if (len != 0) - memset(p, t->bt_bval, len); - if (__rec_iput(t, - nrec, &data, 0) != RET_SUCCESS) - return (RET_ERROR); - ++nrec; - break; - } - if (ch == EOF) - break; - } - if (nrec < top) { - F_SET(t, R_EOF); - return (RET_SPECIAL); - } - return (RET_SUCCESS); -} - -/* - * __REC_VPIPE -- Get variable length records from a pipe. - * - * Parameters: - * t: tree - * cnt: records to read - * - * Returns: - * RET_ERROR, RET_SUCCESS - */ -int -__rec_vpipe(t, top) - BTREE *t; - recno_t top; -{ - DBT data; - recno_t nrec; - indx_t len; - size_t sz; - int bval, ch; - u_char *p; - - bval = t->bt_bval; - for (nrec = t->bt_nrecs; nrec < top; ++nrec) { - for (p = t->bt_rdata.data, - sz = t->bt_rdata.size;; *p++ = ch, --sz) { - if ((ch = getc(t->bt_rfp)) == EOF || ch == bval) { - data.data = t->bt_rdata.data; - data.size = p - (u_char *)t->bt_rdata.data; - if (ch == EOF && data.size == 0) - break; - if (__rec_iput(t, nrec, &data, 0) - != RET_SUCCESS) - return (RET_ERROR); - break; - } - if (sz == 0) { - len = p - (u_char *)t->bt_rdata.data; - t->bt_rdata.size += (sz = 256); - t->bt_rdata.data = t->bt_rdata.data == NULL ? - malloc(t->bt_rdata.size) : - realloc(t->bt_rdata.data, t->bt_rdata.size); - if (t->bt_rdata.data == NULL) - return (RET_ERROR); - p = (u_char *)t->bt_rdata.data + len; - } - } - if (ch == EOF) - break; - } - if (nrec < top) { - F_SET(t, R_EOF); - return (RET_SPECIAL); - } - return (RET_SUCCESS); -} - -/* - * __REC_FMAP -- Get fixed length records from a file. - * - * Parameters: - * t: tree - * cnt: records to read - * - * Returns: - * RET_ERROR, RET_SUCCESS - */ -int -__rec_fmap(t, top) - BTREE *t; - recno_t top; -{ - DBT data; - recno_t nrec; - u_char *sp, *ep, *p; - size_t len; - - if (t->bt_rdata.size < t->bt_reclen) { - t->bt_rdata.data = t->bt_rdata.data == NULL ? - malloc(t->bt_reclen) : - realloc(t->bt_rdata.data, t->bt_reclen); - if (t->bt_rdata.data == NULL) - return (RET_ERROR); - t->bt_rdata.size = t->bt_reclen; - } - data.data = t->bt_rdata.data; - data.size = t->bt_reclen; - - sp = (u_char *)t->bt_cmap; - ep = (u_char *)t->bt_emap; - for (nrec = t->bt_nrecs; nrec < top; ++nrec) { - if (sp >= ep) { - F_SET(t, R_EOF); - return (RET_SPECIAL); - } - len = t->bt_reclen; - for (p = t->bt_rdata.data; - sp < ep && len > 0; *p++ = *sp++, --len); - if (len != 0) - memset(p, t->bt_bval, len); - if (__rec_iput(t, nrec, &data, 0) != RET_SUCCESS) - return (RET_ERROR); - } - t->bt_cmap = (caddr_t)sp; - return (RET_SUCCESS); -} - -/* - * __REC_VMAP -- Get variable length records from a file. - * - * Parameters: - * t: tree - * cnt: records to read - * - * Returns: - * RET_ERROR, RET_SUCCESS - */ -int -__rec_vmap(t, top) - BTREE *t; - recno_t top; -{ - DBT data; - u_char *sp, *ep; - recno_t nrec; - int bval; - - sp = (u_char *)t->bt_cmap; - ep = (u_char *)t->bt_emap; - bval = t->bt_bval; - - for (nrec = t->bt_nrecs; nrec < top; ++nrec) { - if (sp >= ep) { - F_SET(t, R_EOF); - return (RET_SPECIAL); - } - for (data.data = sp; sp < ep && *sp != bval; ++sp); - data.size = sp - (u_char *)data.data; - if (__rec_iput(t, nrec, &data, 0) != RET_SUCCESS) - return (RET_ERROR); - ++sp; - } - t->bt_cmap = (caddr_t)sp; - return (RET_SUCCESS); -} diff --git a/db/recno/rec_open.c b/db/recno/rec_open.c deleted file mode 100644 index 51d8a3c..0000000 --- a/db/recno/rec_open.c +++ /dev/null @@ -1,241 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * 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. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)rec_open.c 8.10 (Berkeley) 9/1/94"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/types.h> -#include <sys/mman.h> -#include <sys/stat.h> - -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <stddef.h> -#include <stdio.h> -#include <unistd.h> - -#include <db.h> -#include "recno.h" - -DB * -__rec_open(fname, flags, mode, openinfo, dflags) - const char *fname; - int flags, mode, dflags; - const RECNOINFO *openinfo; -{ - BTREE *t; - BTREEINFO btopeninfo; - DB *dbp; - PAGE *h; - struct stat sb; - int rfd, sverrno; - - /* Open the user's file -- if this fails, we're done. */ - if (fname != NULL && (rfd = open(fname, flags, mode)) < 0) - return (NULL); - - /* Create a btree in memory (backed by disk). */ - dbp = NULL; - if (openinfo) { - if (openinfo->flags & ~(R_FIXEDLEN | R_NOKEY | R_SNAPSHOT)) - goto einval; - btopeninfo.flags = 0; - btopeninfo.cachesize = openinfo->cachesize; - btopeninfo.maxkeypage = 0; - btopeninfo.minkeypage = 0; - btopeninfo.psize = openinfo->psize; - btopeninfo.compare = NULL; - btopeninfo.prefix = NULL; - btopeninfo.lorder = openinfo->lorder; - dbp = __bt_open(openinfo->bfname, - O_RDWR, S_IRUSR | S_IWUSR, &btopeninfo, dflags); - } else - dbp = __bt_open(NULL, O_RDWR, S_IRUSR | S_IWUSR, NULL, dflags); - if (dbp == NULL) - goto err; - - /* - * Some fields in the tree structure are recno specific. Fill them - * in and make the btree structure look like a recno structure. We - * don't change the bt_ovflsize value, it's close enough and slightly - * bigger. - */ - t = dbp->internal; - if (openinfo) { - if (openinfo->flags & R_FIXEDLEN) { - F_SET(t, R_FIXLEN); - t->bt_reclen = openinfo->reclen; - if (t->bt_reclen == 0) - goto einval; - } - t->bt_bval = openinfo->bval; - } else - t->bt_bval = '\n'; - - F_SET(t, R_RECNO); - if (fname == NULL) - F_SET(t, R_EOF | R_INMEM); - else - t->bt_rfd = rfd; - - if (fname != NULL) { - /* - * In 4.4BSD, stat(2) returns true for ISSOCK on pipes. - * Unfortunately, that's not portable, so we use lseek - * and check the errno values. - */ - errno = 0; - if (lseek(rfd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE) { - switch (flags & O_ACCMODE) { - case O_RDONLY: - F_SET(t, R_RDONLY); - break; - default: - goto einval; - } -slow: if ((t->bt_rfp = fdopen(rfd, "r")) == NULL) - goto err; - F_SET(t, R_CLOSEFP); - t->bt_irec = - F_ISSET(t, R_FIXLEN) ? __rec_fpipe : __rec_vpipe; - } else { - switch (flags & O_ACCMODE) { - case O_RDONLY: - F_SET(t, R_RDONLY); - break; - case O_RDWR: - break; - default: - goto einval; - } - - if (fstat(rfd, &sb)) - goto err; - /* - * Kluge -- we'd like to test to see if the file is too - * big to mmap. Since, we don't know what size or type - * off_t's or size_t's are, what the largest unsigned - * integral type is, or what random insanity the local - * C compiler will perpetrate, doing the comparison in - * a portable way is flatly impossible. Hope that mmap - * fails if the file is too large. - */ - if (sb.st_size == 0) - F_SET(t, R_EOF); - else { -#ifdef MMAP_NOT_AVAILABLE - /* - * XXX - * Mmap doesn't work correctly on many current - * systems. In particular, it can fail subtly, - * with cache coherency problems. Don't use it - * for now. - */ - t->bt_msize = sb.st_size; - if ((t->bt_smap = mmap(NULL, t->bt_msize, - PROT_READ, MAP_PRIVATE, rfd, - (off_t)0)) == (caddr_t)-1) - goto slow; - t->bt_cmap = t->bt_smap; - t->bt_emap = t->bt_smap + sb.st_size; - t->bt_irec = F_ISSET(t, R_FIXLEN) ? - __rec_fmap : __rec_vmap; - F_SET(t, R_MEMMAPPED); -#else - goto slow; -#endif - } - } - } - - /* Use the recno routines. */ - dbp->close = __rec_close; - dbp->del = __rec_delete; - dbp->fd = __rec_fd; - dbp->get = __rec_get; - dbp->put = __rec_put; - dbp->seq = __rec_seq; - dbp->sync = __rec_sync; - - /* If the root page was created, reset the flags. */ - if ((h = mpool_get(t->bt_mp, P_ROOT, 0)) == NULL) - goto err; - if ((h->flags & P_TYPE) == P_BLEAF) { - F_CLR(h, P_TYPE); - F_SET(h, P_RLEAF); - mpool_put(t->bt_mp, h, MPOOL_DIRTY); - } else - mpool_put(t->bt_mp, h, 0); - - if (openinfo && openinfo->flags & R_SNAPSHOT && - !F_ISSET(t, R_EOF | R_INMEM) && - t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR) - goto err; - return (dbp); - -einval: errno = EINVAL; -err: sverrno = errno; - if (dbp != NULL) - (void)__bt_close(dbp); - if (fname != NULL) - (void)close(rfd); - errno = sverrno; - return (NULL); -} - -int -__rec_fd(dbp) - const DB *dbp; -{ - BTREE *t; - - t = dbp->internal; - - /* Toss any page pinned across calls. */ - if (t->bt_pinned != NULL) { - mpool_put(t->bt_mp, t->bt_pinned, 0); - t->bt_pinned = NULL; - } - - /* In-memory database can't have a file descriptor. */ - if (F_ISSET(t, R_INMEM)) { - errno = ENOENT; - return (-1); - } - return (t->bt_rfd); -} diff --git a/db/recno/rec_put.c b/db/recno/rec_put.c deleted file mode 100644 index 5454c40..0000000 --- a/db/recno/rec_put.c +++ /dev/null @@ -1,280 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. 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. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)rec_put.c 8.7 (Berkeley) 8/18/94"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/types.h> - -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <db.h> -#include "recno.h" - -/* - * __REC_PUT -- Add a recno item to the tree. - * - * Parameters: - * dbp: pointer to access method - * key: key - * data: data - * flag: R_CURSOR, R_IAFTER, R_IBEFORE, R_NOOVERWRITE - * - * Returns: - * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key is - * already in the tree and R_NOOVERWRITE specified. - */ -int -__rec_put(dbp, key, data, flags) - const DB *dbp; - DBT *key; - const DBT *data; - u_int flags; -{ - BTREE *t; - DBT fdata, tdata; - recno_t nrec; - int status; - - t = dbp->internal; - - /* Toss any page pinned across calls. */ - if (t->bt_pinned != NULL) { - mpool_put(t->bt_mp, t->bt_pinned, 0); - t->bt_pinned = NULL; - } - - /* - * If using fixed-length records, and the record is long, return - * EINVAL. If it's short, pad it out. Use the record data return - * memory, it's only short-term. - */ - if (F_ISSET(t, R_FIXLEN) && data->size != t->bt_reclen) { - if (data->size > t->bt_reclen) - goto einval; - - if (t->bt_rdata.size < t->bt_reclen) { - t->bt_rdata.data = t->bt_rdata.data == NULL ? - malloc(t->bt_reclen) : - realloc(t->bt_rdata.data, t->bt_reclen); - if (t->bt_rdata.data == NULL) - return (RET_ERROR); - t->bt_rdata.size = t->bt_reclen; - } - memmove(t->bt_rdata.data, data->data, data->size); - memset((char *)t->bt_rdata.data + data->size, - t->bt_bval, t->bt_reclen - data->size); - fdata.data = t->bt_rdata.data; - fdata.size = t->bt_reclen; - } else { - fdata.data = data->data; - fdata.size = data->size; - } - - switch (flags) { - case R_CURSOR: - if (!F_ISSET(&t->bt_cursor, CURS_INIT)) - goto einval; - nrec = t->bt_cursor.rcursor; - break; - case R_SETCURSOR: - if ((nrec = *(recno_t *)key->data) == 0) - goto einval; - break; - case R_IAFTER: - if ((nrec = *(recno_t *)key->data) == 0) { - nrec = 1; - flags = R_IBEFORE; - } - break; - case 0: - case R_IBEFORE: - if ((nrec = *(recno_t *)key->data) == 0) - goto einval; - break; - case R_NOOVERWRITE: - if ((nrec = *(recno_t *)key->data) == 0) - goto einval; - if (nrec <= t->bt_nrecs) - return (RET_SPECIAL); - break; - default: -einval: errno = EINVAL; - return (RET_ERROR); - } - - /* - * Make sure that records up to and including the put record are - * already in the database. If skipping records, create empty ones. - */ - if (nrec > t->bt_nrecs) { - if (!F_ISSET(t, R_EOF | R_INMEM) && - t->bt_irec(t, nrec) == RET_ERROR) - return (RET_ERROR); - if (nrec > t->bt_nrecs + 1) { - if (F_ISSET(t, R_FIXLEN)) { - if ((tdata.data = - (void *)malloc(t->bt_reclen)) == NULL) - return (RET_ERROR); - tdata.size = t->bt_reclen; - memset(tdata.data, t->bt_bval, tdata.size); - } else { - tdata.data = NULL; - tdata.size = 0; - } - while (nrec > t->bt_nrecs + 1) - if (__rec_iput(t, - t->bt_nrecs, &tdata, 0) != RET_SUCCESS) - return (RET_ERROR); - if (F_ISSET(t, R_FIXLEN)) - free(tdata.data); - } - } - - if ((status = __rec_iput(t, nrec - 1, &fdata, flags)) != RET_SUCCESS) - return (status); - - if (flags == R_SETCURSOR) - t->bt_cursor.rcursor = nrec; - - F_SET(t, R_MODIFIED); - return (__rec_ret(t, NULL, nrec, key, NULL)); -} - -/* - * __REC_IPUT -- Add a recno item to the tree. - * - * Parameters: - * t: tree - * nrec: record number - * data: data - * - * Returns: - * RET_ERROR, RET_SUCCESS - */ -int -__rec_iput(t, nrec, data, flags) - BTREE *t; - recno_t nrec; - const DBT *data; - u_int flags; -{ - DBT tdata; - EPG *e; - PAGE *h; - indx_t index, nxtindex; - pgno_t pg; - u_int32_t nbytes; - int dflags, status; - char *dest, db[NOVFLSIZE]; - - /* - * If the data won't fit on a page, store it on indirect pages. - * - * XXX - * If the insert fails later on, these pages aren't recovered. - */ - if (data->size > t->bt_ovflsize) { - if (__ovfl_put(t, data, &pg) == RET_ERROR) - return (RET_ERROR); - tdata.data = db; - tdata.size = NOVFLSIZE; - *(pgno_t *)db = pg; - *(u_int32_t *)(db + sizeof(pgno_t)) = data->size; - dflags = P_BIGDATA; - data = &tdata; - } else - dflags = 0; - - /* __rec_search pins the returned page. */ - if ((e = __rec_search(t, nrec, - nrec > t->bt_nrecs || flags == R_IAFTER || flags == R_IBEFORE ? - SINSERT : SEARCH)) == NULL) - return (RET_ERROR); - - h = e->page; - index = e->index; - - /* - * Add the specified key/data pair to the tree. The R_IAFTER and - * R_IBEFORE flags insert the key after/before the specified key. - * - * Pages are split as required. - */ - switch (flags) { - case R_IAFTER: - ++index; - break; - case R_IBEFORE: - break; - default: - if (nrec < t->bt_nrecs && - __rec_dleaf(t, h, index) == RET_ERROR) { - mpool_put(t->bt_mp, h, 0); - return (RET_ERROR); - } - break; - } - - /* - * If not enough room, split the page. The split code will insert - * the key and data and unpin the current page. If inserting into - * the offset array, shift the pointers up. - */ - nbytes = NRLEAFDBT(data->size); - if ((u_int32_t) (h->upper - h->lower) < nbytes + sizeof(indx_t)) { - status = __bt_split(t, h, NULL, data, dflags, nbytes, index); - if (status == RET_SUCCESS) - ++t->bt_nrecs; - return (status); - } - - if (index < (nxtindex = NEXTINDEX(h))) - memmove(h->linp + index + 1, h->linp + index, - (nxtindex - index) * sizeof(indx_t)); - h->lower += sizeof(indx_t); - - h->linp[index] = h->upper -= nbytes; - dest = (char *)h + h->upper; - WR_RLEAF(dest, data, dflags); - - ++t->bt_nrecs; - F_SET(t, B_MODIFIED); - mpool_put(t->bt_mp, h, MPOOL_DIRTY); - - return (RET_SUCCESS); -} diff --git a/db/recno/rec_search.c b/db/recno/rec_search.c deleted file mode 100644 index acc109e..0000000 --- a/db/recno/rec_search.c +++ /dev/null @@ -1,126 +0,0 @@ -/*- - * Copyright (c) 1990, 1993 - * The Regents of the University of California. 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. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)rec_search.c 8.4 (Berkeley) 7/14/94"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/types.h> - -#include <errno.h> -#include <stdio.h> - -#include <db.h> -#include "recno.h" - -/* - * __REC_SEARCH -- Search a btree for a key. - * - * Parameters: - * t: tree to search - * recno: key to find - * op: search operation - * - * Returns: - * EPG for matching record, if any, or the EPG for the location of the - * key, if it were inserted into the tree. - * - * Returns: - * The EPG for matching record, if any, or the EPG for the location - * of the key, if it were inserted into the tree, is entered into - * the bt_cur field of the tree. A pointer to the field is returned. - */ -EPG * -__rec_search(t, recno, op) - BTREE *t; - recno_t recno; - enum SRCHOP op; -{ - register indx_t index; - register PAGE *h; - EPGNO *parent; - RINTERNAL *r; - pgno_t pg; - indx_t top; - recno_t total; - int sverrno; - - BT_CLR(t); - for (pg = P_ROOT, total = 0;;) { - if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) - goto err; - if (h->flags & P_RLEAF) { - t->bt_cur.page = h; - t->bt_cur.index = recno - total; - return (&t->bt_cur); - } - for (index = 0, top = NEXTINDEX(h);;) { - r = GETRINTERNAL(h, index); - if (++index == top || total + r->nrecs > recno) - break; - total += r->nrecs; - } - - BT_PUSH(t, pg, index - 1); - - pg = r->pgno; - switch (op) { - case SDELETE: - --GETRINTERNAL(h, (index - 1))->nrecs; - mpool_put(t->bt_mp, h, MPOOL_DIRTY); - break; - case SINSERT: - ++GETRINTERNAL(h, (index - 1))->nrecs; - mpool_put(t->bt_mp, h, MPOOL_DIRTY); - break; - case SEARCH: - mpool_put(t->bt_mp, h, 0); - break; - } - - } - /* Try and recover the tree. */ -err: sverrno = errno; - if (op != SEARCH) - while ((parent = BT_POP(t)) != NULL) { - if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL) - break; - if (op == SINSERT) - --GETRINTERNAL(h, parent->index)->nrecs; - else - ++GETRINTERNAL(h, parent->index)->nrecs; - mpool_put(t->bt_mp, h, MPOOL_DIRTY); - } - errno = sverrno; - return (NULL); -} diff --git a/db/recno/rec_seq.c b/db/recno/rec_seq.c deleted file mode 100644 index 2f8c769..0000000 --- a/db/recno/rec_seq.c +++ /dev/null @@ -1,131 +0,0 @@ -/*- - * Copyright (c) 1991, 1993, 1994 - * The Regents of the University of California. 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. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)rec_seq.c 8.3 (Berkeley) 7/14/94"; -#endif /* not lint */ - -#include <sys/types.h> - -#include <errno.h> -#include <limits.h> -#include <stdio.h> -#include <string.h> - -#include <db.h> -#include "recno.h" - -/* - * __REC_SEQ -- Recno sequential scan interface. - * - * Parameters: - * dbp: pointer to access method - * key: key for positioning and return value - * data: data return value - * flags: R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV. - * - * Returns: - * RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key. - */ -int -__rec_seq(dbp, key, data, flags) - const DB *dbp; - DBT *key, *data; - u_int flags; -{ - BTREE *t; - EPG *e; - recno_t nrec; - int status; - - t = dbp->internal; - - /* Toss any page pinned across calls. */ - if (t->bt_pinned != NULL) { - mpool_put(t->bt_mp, t->bt_pinned, 0); - t->bt_pinned = NULL; - } - - switch(flags) { - case R_CURSOR: - if ((nrec = *(recno_t *)key->data) == 0) - goto einval; - break; - case R_NEXT: - if (F_ISSET(&t->bt_cursor, CURS_INIT)) { - nrec = t->bt_cursor.rcursor + 1; - break; - } - /* FALLTHROUGH */ - case R_FIRST: - nrec = 1; - break; - case R_PREV: - if (F_ISSET(&t->bt_cursor, CURS_INIT)) { - if ((nrec = t->bt_cursor.rcursor - 1) == 0) - return (RET_SPECIAL); - break; - } - /* FALLTHROUGH */ - case R_LAST: - if (!F_ISSET(t, R_EOF | R_INMEM) && - t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR) - return (RET_ERROR); - nrec = t->bt_nrecs; - break; - default: -einval: errno = EINVAL; - return (RET_ERROR); - } - - if (t->bt_nrecs == 0 || nrec > t->bt_nrecs) { - if (!F_ISSET(t, R_EOF | R_INMEM) && - (status = t->bt_irec(t, nrec)) != RET_SUCCESS) - return (status); - if (t->bt_nrecs == 0 || nrec > t->bt_nrecs) - return (RET_SPECIAL); - } - - if ((e = __rec_search(t, nrec - 1, SEARCH)) == NULL) - return (RET_ERROR); - - F_SET(&t->bt_cursor, CURS_INIT); - t->bt_cursor.rcursor = nrec; - - status = __rec_ret(t, e, nrec, key, data); - if (F_ISSET(t, B_DB_LOCK)) - mpool_put(t->bt_mp, e->page, 0); - else - t->bt_pinned = e->page; - return (status); -} diff --git a/db/recno/rec_utils.c b/db/recno/rec_utils.c deleted file mode 100644 index c4c0380..0000000 --- a/db/recno/rec_utils.c +++ /dev/null @@ -1,122 +0,0 @@ -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. 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. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)rec_utils.c 8.6 (Berkeley) 7/16/94"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/param.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <db.h> -#include "recno.h" - -/* - * __rec_ret -- - * Build return data. - * - * Parameters: - * t: tree - * e: key/data pair to be returned - * nrec: record number - * key: user's key structure - * data: user's data structure - * - * Returns: - * RET_SUCCESS, RET_ERROR. - */ -int -__rec_ret(t, e, nrec, key, data) - BTREE *t; - EPG *e; - recno_t nrec; - DBT *key, *data; -{ - RLEAF *rl; - void *p; - - if (key == NULL) - goto dataonly; - - /* We have to copy the key, it's not on the page. */ - if (sizeof(recno_t) > t->bt_rkey.size) { - p = (void *)(t->bt_rkey.data == NULL ? - malloc(sizeof(recno_t)) : - realloc(t->bt_rkey.data, sizeof(recno_t))); - if (p == NULL) - return (RET_ERROR); - t->bt_rkey.data = p; - t->bt_rkey.size = sizeof(recno_t); - } - memmove(t->bt_rkey.data, &nrec, sizeof(recno_t)); - key->size = sizeof(recno_t); - key->data = t->bt_rkey.data; - -dataonly: - if (data == NULL) - return (RET_SUCCESS); - - /* - * We must copy big keys/data to make them contiguous. Otherwise, - * leave the page pinned and don't copy unless the user specified - * concurrent access. - */ - rl = GETRLEAF(e->page, e->index); - if (rl->flags & P_BIGDATA) { - if (__ovfl_get(t, rl->bytes, - &data->size, &t->bt_rdata.data, &t->bt_rdata.size)) - return (RET_ERROR); - data->data = t->bt_rdata.data; - } else if (F_ISSET(t, B_DB_LOCK)) { - /* Use +1 in case the first record retrieved is 0 length. */ - if (rl->dsize + 1 > t->bt_rdata.size) { - p = (void *)(t->bt_rdata.data == NULL ? - malloc(rl->dsize + 1) : - realloc(t->bt_rdata.data, rl->dsize + 1)); - if (p == NULL) - return (RET_ERROR); - t->bt_rdata.data = p; - t->bt_rdata.size = rl->dsize + 1; - } - memmove(t->bt_rdata.data, rl->bytes, rl->dsize); - data->size = rl->dsize; - data->data = t->bt_rdata.data; - } else { - data->size = rl->dsize; - data->data = rl->bytes; - } - return (RET_SUCCESS); -} diff --git a/db/recno/recno.h b/db/recno/recno.h deleted file mode 100644 index bec772c..0000000 --- a/db/recno/recno.h +++ /dev/null @@ -1,39 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. 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. - * - * @(#)recno.h 8.1 (Berkeley) 6/4/93 - */ - -enum SRCHOP { SDELETE, SINSERT, SEARCH}; /* Rec_search operation. */ - -#include "../btree/btree.h" -#include "extern.h" diff --git a/db2/LICENSE b/db2/LICENSE deleted file mode 100644 index 17ee9b9..0000000 --- a/db2/LICENSE +++ /dev/null @@ -1,116 +0,0 @@ -/*- - * @(#)LICENSE 10.8 (Sleepycat) 5/1/98 - */ - -The following are the copyrights and redistribution conditions that apply to -this copy of the Berkeley DB software. For a license to use, redistribute -or sell Berkeley DB software under conditions other than those described here, -or to purchase support for this software, please contact Sleepycat Software at -one of the following addresses: - - Sleepycat Software db@sleepycat.com - 394 E. Riding Dr. +1-617-633-2429 - Carlisle, MA 01741 - USA - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -/* - * Copyright (c) 1990, 1993, 1994, 1995, 1996, 1997, 1998 - * Sleepycat Software. 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. Redistributions in any form must be accompanied by information on - * how to obtain complete source code for the DB software and any - * accompanying software that uses the DB software. The source code - * must either be included in the distribution or be available for no - * more than the cost of distribution plus a nominal fee, and must be - * freely redistributable under reasonable conditions. For an - * executable file, complete source code means the source code for all - * modules it contains. It does not mean source code for modules or - * files that typically accompany the operating system on which the - * executable file runs, e.g., standard library modules or system - * header files. - * - * THIS SOFTWARE IS PROVIDED BY SLEEPYCAT SOFTWARE ``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 SLEEPYCAT SOFTWARE 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. - */ -/* - * Copyright (c) 1990, 1993, 1994, 1995 - * The Regents of the University of California. 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. - */ -/* - * 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 Harvard University - * 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 HARVARD AND ITS 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 HARVARD OR ITS 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. - */ diff --git a/db2/Makefile b/db2/Makefile deleted file mode 100644 index 77aa60c..0000000 --- a/db2/Makefile +++ /dev/null @@ -1,126 +0,0 @@ -# Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc. -# This file is part of the GNU C Library. - -# The GNU C Library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Library General Public License as -# published by the Free Software Foundation; either version 2 of the -# License, or (at your option) any later version. - -# The GNU C Library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Library General Public License for more details. - -# You should have received a copy of the GNU Library General Public -# License along with the GNU C Library; see the file COPYING.LIB. If not, -# write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -# -# Sub-makefile for libdb. -# -# The code is lifted straight from the db 2.7.5 distribution -# with minimal changes. -# - -subdir = db2 - -subdir-dirs = btree common db db185 dbm hash lock log mp mutex os txn \ - progs/db_archive progs/db_checkpoint progs/db_deadlock \ - progs/db_dump progs/db_dump185 progs/db_load progs/db_printlog \ - progs/db_recover progs/db_stat clib xa - -headers = db.h db_185.h - -distribute = db_int.h config.h compat.h clib/getlong.c btree/btree.src \ - db/db.src db185/db185_int.h hash/hash.src log/log.src \ - txn/txn.src README LICENSE \ - $(addprefix include/,btree.h btree_auto.h btree_ext.h \ - clib_ext.h common_ext.h cxx_int.h \ - db_185.h.src db_am.h db_auto.h db_cxx.h \ - db_dispatch.h db_ext.h db_join.h \ - db_page.h db_shash.h db_swap.h \ - hash.h hash_auto.h hash_ext.h lock.h \ - lock_ext.h log.h log_auto.h log_ext.h \ - mp.h mp_ext.h mutex_ext.h os_ext.h queue.h \ - shqueue.h txn.h txn_auto.h txn_ext.h \ - os.h os_jump.h xa.h xa_ext.h) \ - $(addprefix mutex/,x86.gcc uts4_cc.s sparc.gcc parisc.gcc \ - README 68020.gcc tsl_parisc.s sco.cc) \ - $(addprefix progs/db_printlog/,README commit.awk count.awk \ - pgno.awk range.awk status.awk \ - txn.awk) - -vpath %.c $(subdir-dirs) - -extra-libs := libdb -extra-libs-others := $(extra-libs) -extra-objs = getlong.o - -libdb-routines := bt_compare bt_conv bt_curadj bt_cursor bt_delete \ - bt_open bt_page bt_put bt_rec bt_recno bt_rsearch bt_search \ - bt_split bt_stat btree_auto db db_appinit db_apprec \ - db_auto db_iface db_am db_join \ - db_byteorder db_conv db_dispatch db_dup db_err db_log2 os_alloc \ - os_abs os_config os_dir os_fid os_fsync os_map os_oflags \ - os_open os_rpath os_rw os_seek os_sleep os_stat os_unlink \ - os_spin os_tmpdir db_overflow db_pr db_rec db_region db_ret \ - db_salloc db_shash hash hash_auto hash_conv \ - hash_dup hash_func hash_page hash_rec hash_stat lock \ - lock_conflict lock_deadlock lock_region lock_util log log_archive \ - log_auto log_compare log_findckp log_get log_put log_rec \ - log_register mp_bh mp_fget mp_fopen mp_fput mp_fset \ - mp_open mp_pr mp_region mp_sync mutex txn txn_auto \ - txn_rec dbm db185 xa xa_db xa_map - -others := makedb db_dump185 db_archive db_checkpoint db_deadlock \ - db_dump db_load db_recover db_stat db_printlog -install-bin := makedb db_dump185 db_archive db_checkpoint db_deadlock \ - db_dump db_load db_recover db_stat db_printlog - -include ../Rules - -CPPFLAGS += -I./include -include ./compat.h - -$(objpfx)db_checkpoint: $(objpfx)getlong.o -$(objpfx)db_deadlock: $(objpfx)getlong.o -$(objpfx)db_load: $(objpfx)getlong.o - -ifeq ($(build-shared),yes) -$(objpfx)makedb: $(objpfx)libdb.so$(libdb.so-version) -$(objpfx)db_dump185: $(objpfx)libdb.so$(libdb.so-version) -$(objpfx)db_archive: $(objpfx)libdb.so$(libdb.so-version) -$(objpfx)db_checkpoint: $(objpfx)libdb.so$(libdb.so-version) -$(objpfx)db_deadlock: $(objpfx)libdb.so$(libdb.so-version) -$(objpfx)db_dump: $(objpfx)libdb.so$(libdb.so-version) -$(objpfx)db_load: $(objpfx)libdb.so$(libdb.so-version) -$(objpfx)db_printlog: $(objpfx)libdb.so$(libdb.so-version) -$(objpfx)db_recover: $(objpfx)libdb.so$(libdb.so-version) -$(objpfx)db_stat: $(objpfx)libdb.so$(libdb.so-version) -else -$(objpfx)makedb: $(objpfx)libdb.a -$(objpfx)db_dump185: $(objpfx)libdb.a -$(objpfx)db_archive: $(objpfx)libdb.a -$(objpfx)db_checkpoint: $(objpfx)libdb.a -$(objpfx)db_deadlock: $(objpfx)libdb.a -$(objpfx)db_dump: $(objpfx)libdb.a -$(objpfx)db_load: $(objpfx)libdb.a -$(objpfx)db_printlog: $(objpfx)libdb.a -$(objpfx)db_recover: $(objpfx)libdb.a -$(objpfx)db_stat: $(objpfx)libdb.a -endif - -# Depend on libc.so so a DT_NEEDED is generated in the shared objects. -$(objpfx)libdb.so: $(common-objpfx)libc.so - -ifeq ($(build-static),yes) -subdir_install: $(inst_libdir)/libndbm.a -$(inst_libdir)/libndbm.a: $(inst_libdir)/libdb.a $(+force) - $(make-link) -endif - -ifeq ($(build-shared),yes) -subdir_install: $(inst_libdir)/libndbm.so -$(inst_libdir)/libndbm.so: $(inst_libdir)/libdb.so $(+force) - $(make-link) -endif diff --git a/db2/README b/db2/README deleted file mode 100644 index 2671e7f..0000000 --- a/db2/README +++ /dev/null @@ -1,13 +0,0 @@ -As a special exception, when Berkeley DB is distributed along with the -GNU C Library, in any program which uses the GNU C Library in accord -with that library's distribution terms, it is also permitted for -Berkeley DB to be loaded dynamically by the GNU C Library to implement -standard ISO/IEC 9945 and Unix interface functionality. - -Sleepycat Software, Inc. - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The LICENSE file, mentioned in the beginning of the source files, can -be found in this directory and also with all the other relevant -license texts in the manual. diff --git a/db2/Versions b/db2/Versions deleted file mode 100644 index a32945a..0000000 --- a/db2/Versions +++ /dev/null @@ -1,58 +0,0 @@ -libdb { - GLIBC_2.0 { - # db 1.85 interface - dbopen; __dbopen; - - # The compatibility functions. - dbm_clearerr; dbm_close; dbm_delete; dbm_dirfno; dbm_error; - dbm_fetch; dbm_firstkey; dbminit; dbm_nextkey; dbm_open; - dbm_pagfno; dbm_store; - } - GLIBC_2.1 { - # db.2.x interface - # Internal functions used by db maintenance programs - __bam_init_print; __bam_pgin; __bam_pgout; - __db_dispatch;__db_dump; __db_err; __db_init_print;__db_jump; - __db_omode;__db_prdbt; - __ham_init_print; __ham_pgin; __ham_pgout; - __lock_dump_region; - __log_init_print; - __memp_dump_region; - __txn_init_print; - - # Functions used by other libraries. - __nss_db_open; - - # Constants - db_rw_conflicts; db_riw_conflicts; - - # Functions - db_appexit; db_appinit; db_jump_set; db_open; db_value_set; - db_version; - lock_close; lock_detect; lock_get; lock_id; lock_open; lock_put; - lock_stat; lock_unlink; lock_vec; log_archive; log_close; - log_compare; log_file; log_flush; log_get; log_open; log_put; - log_register; log_stat; log_unlink; log_unregister; - - memp_close; memp_fclose; memp_fget; memp_fopen; memp_fput; - memp_fset; memp_fsync; memp_open; memp_register; memp_stat; - memp_sync; memp_trickle; memp_unlink; - - txn_abort; txn_begin; txn_checkpoint; txn_close; txn_commit; - txn_id; txn_open; txn_prepare; txn_stat; txn_unlink; - - # compatibility interface for ndbm - __db_ndbm_clearerr; __db_ndbm_close; __db_ndbm_delete; - __db_ndbm_dirfno; __db_ndbm_error; __db_ndbm_fetch; - __db_ndbm_firstkey; __db_ndbm_nextkey; __db_ndbm_open; - __db_ndbm_pagfno; __db_ndbm_rdonly; __db_ndbm_store; - - # compatibility interface for dbm - __db_dbm_delete; __db_dbm_fetch; __db_dbm_firstkey; __db_dbm_init; - __db_dbm_nextkey; __db_dbm_store; - } - GLIBC_2.2 { - # Internal functions. - __ham_get_page; __ham_put_page; - } -} diff --git a/db2/btree/bt_compare.c b/db2/btree/bt_compare.c deleted file mode 100644 index c60f920..0000000 --- a/db2/btree/bt_compare.c +++ /dev/null @@ -1,195 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994, 1995, 1996 - * Keith Bostic. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994, 1995 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * 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[] = "@(#)bt_compare.c 10.14 (Sleepycat) 10/9/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <string.h> -#endif - -#include "db_int.h" -#include "db_page.h" -#include "btree.h" - -/* - * __bam_cmp -- - * Compare a key to a given record. - * - * PUBLIC: int __bam_cmp __P((DB *, const DBT *, - * PUBLIC: PAGE *, u_int32_t, int (*)(const DBT *, const DBT *))); - */ -int -__bam_cmp(dbp, dbt, h, indx, func) - DB *dbp; - const DBT *dbt; - PAGE *h; - u_int32_t indx; - int (*func)__P((const DBT *, const DBT *)); -{ - BINTERNAL *bi; - BKEYDATA *bk; - BOVERFLOW *bo; - DBT pg_dbt; - int ret; - - /* - * Returns: - * < 0 if dbt is < page record - * = 0 if dbt is = page record - * > 0 if dbt is > page record - * - * !!! - * We do not clear the pg_dbt DBT even though it's likely to contain - * random bits. That should be okay, because the app's comparison - * routine had better not be looking at fields other than data/size. - * We don't clear it because we go through this path a lot and it's - * expensive. - */ - if (TYPE(h) == P_LBTREE || TYPE(h) == P_DUPLICATE) { - bk = GET_BKEYDATA(h, indx); - if (B_TYPE(bk->type) == B_OVERFLOW) - bo = (BOVERFLOW *)bk; - else { - pg_dbt.data = bk->data; - pg_dbt.size = bk->len; - return (func(dbt, &pg_dbt)); - } - } else { - /* - * The following code guarantees that the left-most key on an - * internal page at any level of the btree is less than any - * user specified key. This saves us from having to update the - * leftmost key on an internal page when the user inserts a new - * key in the tree smaller than anything we've seen before. - */ - if (indx == 0 && h->prev_pgno == PGNO_INVALID) - return (1); - - bi = GET_BINTERNAL(h, indx); - if (B_TYPE(bi->type) == B_OVERFLOW) - bo = (BOVERFLOW *)(bi->data); - else { - pg_dbt.data = bi->data; - pg_dbt.size = bi->len; - return (func(dbt, &pg_dbt)); - } - } - - /* - * Overflow. - * - * XXX - * We ignore __db_moff() errors, because we have no way of returning - * them. - */ - (void) __db_moff(dbp, - dbt, bo->pgno, bo->tlen, func == __bam_defcmp ? NULL : func, &ret); - return (ret); -} - -/* - * __bam_defcmp -- - * Default comparison routine. - * - * PUBLIC: int __bam_defcmp __P((const DBT *, const DBT *)); - */ -int -__bam_defcmp(a, b) - const DBT *a, *b; -{ - size_t len; - u_int8_t *p1, *p2; - - /* - * Returns: - * < 0 if a is < b - * = 0 if a is = b - * > 0 if a is > b - * - * XXX - * If a size_t doesn't fit into a long, or if the difference between - * any two characters doesn't fit into an int, this routine can lose. - * What we need is a signed integral type that's guaranteed to be at - * least as large as a size_t, and there is no such thing. - */ - len = a->size > b->size ? b->size : a->size; - for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2) - if (*p1 != *p2) - return ((long)*p1 - (long)*p2); - return ((long)a->size - (long)b->size); -} - -/* - * __bam_defpfx -- - * Default prefix routine. - * - * PUBLIC: size_t __bam_defpfx __P((const DBT *, const DBT *)); - */ -size_t -__bam_defpfx(a, b) - const DBT *a, *b; -{ - size_t cnt, len; - u_int8_t *p1, *p2; - - cnt = 1; - len = a->size > b->size ? b->size : a->size; - for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2, ++cnt) - if (*p1 != *p2) - return (cnt); - - /* - * We know that a->size must be <= b->size, or they wouldn't be - * in this order. - */ - return (a->size < b->size ? a->size + 1 : a->size); -} diff --git a/db2/btree/bt_conv.c b/db2/btree/bt_conv.c deleted file mode 100644 index a306908..0000000 --- a/db2/btree/bt_conv.c +++ /dev/null @@ -1,94 +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[] = "@(#)bt_conv.c 10.7 (Sleepycat) 9/20/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> -#endif - -#include "db_int.h" -#include "db_page.h" -#include "db_swap.h" -#include "btree.h" - -/* - * __bam_pgin -- - * Convert host-specific page layout from the host-independent format - * stored on disk. - * - * PUBLIC: int __bam_pgin __P((db_pgno_t, void *, DBT *)); - */ -int -__bam_pgin(pg, pp, cookie) - db_pgno_t pg; - void *pp; - DBT *cookie; -{ - DB_PGINFO *pginfo; - - pginfo = (DB_PGINFO *)cookie->data; - if (!pginfo->needswap) - return (0); - return (pg == PGNO_METADATA ? - __bam_mswap(pp) : __db_pgin(pg, pginfo->db_pagesize, pp)); -} - -/* - * __bam_pgout -- - * Convert host-specific page layout to the host-independent format - * stored on disk. - * - * PUBLIC: int __bam_pgout __P((db_pgno_t, void *, DBT *)); - */ -int -__bam_pgout(pg, pp, cookie) - db_pgno_t pg; - void *pp; - DBT *cookie; -{ - DB_PGINFO *pginfo; - - pginfo = (DB_PGINFO *)cookie->data; - if (!pginfo->needswap) - return (0); - return (pg == PGNO_METADATA ? - __bam_mswap(pp) : __db_pgout(pg, pginfo->db_pagesize, pp)); -} - -/* - * __bam_mswap -- - * Swap the bytes on the btree metadata page. - * - * PUBLIC: int __bam_mswap __P((PAGE *)); - */ -int -__bam_mswap(pg) - PAGE *pg; -{ - u_int8_t *p; - - p = (u_int8_t *)pg; - - /* Swap the meta-data information. */ - SWAP32(p); /* lsn.file */ - SWAP32(p); /* lsn.offset */ - SWAP32(p); /* pgno */ - SWAP32(p); /* magic */ - SWAP32(p); /* version */ - SWAP32(p); /* pagesize */ - SWAP32(p); /* maxkey */ - SWAP32(p); /* minkey */ - SWAP32(p); /* free */ - SWAP32(p); /* flags */ - - return (0); -} diff --git a/db2/btree/bt_curadj.c b/db2/btree/bt_curadj.c deleted file mode 100644 index 9b86fbb..0000000 --- a/db2/btree/bt_curadj.c +++ /dev/null @@ -1,272 +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[] = "@(#)bt_curadj.c 10.69 (Sleepycat) 12/2/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <stdlib.h> -#endif - -#include "db_int.h" -#include "db_page.h" -#include "btree.h" - -#ifdef DEBUG -/* - * __bam_cprint -- - * Display the current cursor list. - * - * PUBLIC: int __bam_cprint __P((DB *)); - */ -int -__bam_cprint(dbp) - DB *dbp; -{ - CURSOR *cp; - DBC *dbc; - - DB_THREAD_LOCK(dbp); - for (dbc = TAILQ_FIRST(&dbp->active_queue); - dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { - cp = (CURSOR *)dbc->internal; - fprintf(stderr, - "%#0x->%#0x: page: %lu index: %lu dpage %lu dindex: %lu recno: %lu", - (u_int)dbc, (u_int)cp, (u_long)cp->pgno, (u_long)cp->indx, - (u_long)cp->dpgno, (u_long)cp->dindx, (u_long)cp->recno); - if (F_ISSET(cp, C_DELETED)) - fprintf(stderr, " (deleted)"); - fprintf(stderr, "\n"); - } - DB_THREAD_UNLOCK(dbp); - - return (0); -} -#endif /* DEBUG */ - -/* - * __bam_ca_delete -- - * Update the cursors when items are deleted and when already deleted - * items are overwritten. Return the number of relevant cursors found. - * - * PUBLIC: int __bam_ca_delete __P((DB *, db_pgno_t, u_int32_t, int)); - */ -int -__bam_ca_delete(dbp, pgno, indx, delete) - DB *dbp; - db_pgno_t pgno; - u_int32_t indx; - int delete; -{ - DBC *dbc; - CURSOR *cp; - int count; /* !!!: Has to contain max number of cursors. */ - - /* Recno is responsible for its own adjustments. */ - if (dbp->type == DB_RECNO) - return (0); - - /* - * Adjust the cursors. We don't have to review the cursors for any - * thread of control other than the current one, because we have the - * page write locked at this point, and any other thread of control - * had better be using a different locker ID, meaning only cursors in - * our thread of control can be on the page. - * - * It's possible for multiple cursors within the thread to have write - * locks on the same page, but, cursors within a thread must be single - * threaded, so all we're locking here is the cursor linked list. - */ - DB_THREAD_LOCK(dbp); - for (count = 0, dbc = TAILQ_FIRST(&dbp->active_queue); - dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { - cp = (CURSOR *)dbc->internal; - - if ((cp->pgno == pgno && cp->indx == indx) || - (cp->dpgno == pgno && cp->dindx == indx)) { - if (delete) - F_SET(cp, C_DELETED); - else - F_CLR(cp, C_DELETED); - ++count; - } - } - DB_THREAD_UNLOCK(dbp); - - return (count); -} - -/* - * __bam_ca_di -- - * Adjust the cursors during a delete or insert. - * - * PUBLIC: void __bam_ca_di __P((DB *, db_pgno_t, u_int32_t, int)); - */ -void -__bam_ca_di(dbp, pgno, indx, adjust) - DB *dbp; - db_pgno_t pgno; - u_int32_t indx; - int adjust; -{ - CURSOR *cp; - DBC *dbc; - - /* Recno is responsible for its own adjustments. */ - if (dbp->type == DB_RECNO) - return; - - /* - * Adjust the cursors. See the comment in __bam_ca_delete(). - */ - DB_THREAD_LOCK(dbp); - for (dbc = TAILQ_FIRST(&dbp->active_queue); - dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { - cp = (CURSOR *)dbc->internal; - if (cp->pgno == pgno && cp->indx >= indx) - cp->indx += adjust; - if (cp->dpgno == pgno && cp->dindx >= indx) - cp->dindx += adjust; - } - DB_THREAD_UNLOCK(dbp); -} - -/* - * __bam_ca_dup -- - * Adjust the cursors when moving items from a leaf page to a duplicates - * page. - * - * PUBLIC: void __bam_ca_dup __P((DB *, - * PUBLIC: db_pgno_t, u_int32_t, u_int32_t, db_pgno_t, u_int32_t)); - */ -void -__bam_ca_dup(dbp, fpgno, first, fi, tpgno, ti) - DB *dbp; - db_pgno_t fpgno, tpgno; - u_int32_t first, fi, ti; -{ - CURSOR *cp; - DBC *dbc; - - /* Recno is responsible for its own adjustments. */ - if (dbp->type == DB_RECNO) - return; - - /* - * Adjust the cursors. See the comment in __bam_ca_delete(). - */ - DB_THREAD_LOCK(dbp); - for (dbc = TAILQ_FIRST(&dbp->active_queue); - dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { - cp = (CURSOR *)dbc->internal; - /* - * Ignore matching entries that have already been moved, - * we move from the same location on the leaf page more - * than once. - */ - if (cp->dpgno == PGNO_INVALID && - cp->pgno == fpgno && cp->indx == fi) { - cp->indx = first; - cp->dpgno = tpgno; - cp->dindx = ti; - } - } - DB_THREAD_UNLOCK(dbp); -} - -/* - * __bam_ca_rsplit -- - * Adjust the cursors when doing reverse splits. - * - * PUBLIC: void __bam_ca_rsplit __P((DB *, db_pgno_t, db_pgno_t)); - */ -void -__bam_ca_rsplit(dbp, fpgno, tpgno) - DB *dbp; - db_pgno_t fpgno, tpgno; -{ - CURSOR *cp; - DBC *dbc; - - /* Recno is responsible for its own adjustments. */ - if (dbp->type == DB_RECNO) - return; - - /* - * Adjust the cursors. See the comment in __bam_ca_delete(). - */ - DB_THREAD_LOCK(dbp); - for (dbc = TAILQ_FIRST(&dbp->active_queue); - dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { - cp = (CURSOR *)dbc->internal; - if (cp->pgno == fpgno) - cp->pgno = tpgno; - } - DB_THREAD_UNLOCK(dbp); -} - -/* - * __bam_ca_split -- - * Adjust the cursors when splitting a page. - * - * PUBLIC: void __bam_ca_split __P((DB *, - * PUBLIC: db_pgno_t, db_pgno_t, db_pgno_t, u_int32_t, int)); - */ -void -__bam_ca_split(dbp, ppgno, lpgno, rpgno, split_indx, cleft) - DB *dbp; - db_pgno_t ppgno, lpgno, rpgno; - u_int32_t split_indx; - int cleft; -{ - DBC *dbc; - CURSOR *cp; - - /* Recno is responsible for its own adjustments. */ - if (dbp->type == DB_RECNO) - return; - - /* - * Adjust the cursors. See the comment in __bam_ca_delete(). - * - * If splitting the page that a cursor was on, the cursor has to be - * adjusted to point to the same record as before the split. Most - * of the time we don't adjust pointers to the left page, because - * we're going to copy its contents back over the original page. If - * the cursor is on the right page, it is decremented by the number of - * records split to the left page. - */ - DB_THREAD_LOCK(dbp); - for (dbc = TAILQ_FIRST(&dbp->active_queue); - dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { - cp = (CURSOR *)dbc->internal; - if (cp->pgno == ppgno) { - if (cp->indx < split_indx) { - if (cleft) - cp->pgno = lpgno; - } else { - cp->pgno = rpgno; - cp->indx -= split_indx; - } - } - if (cp->dpgno == ppgno) { - if (cp->dindx < split_indx) { - if (cleft) - cp->dpgno = lpgno; - } else { - cp->dpgno = rpgno; - cp->dindx -= split_indx; - } - } - } - DB_THREAD_UNLOCK(dbp); -} diff --git a/db2/btree/bt_cursor.c b/db2/btree/bt_cursor.c deleted file mode 100644 index 10bc095..0000000 --- a/db2/btree/bt_cursor.c +++ /dev/null @@ -1,1913 +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[] = "@(#)bt_cursor.c 10.81 (Sleepycat) 12/16/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#endif - -#include "db_int.h" -#include "db_page.h" -#include "btree.h" -#include "shqueue.h" -#include "db_shash.h" -#include "lock.h" -#include "lock_ext.h" - -static int __bam_c_close __P((DBC *)); -static int __bam_c_del __P((DBC *, u_int32_t)); -static int __bam_c_destroy __P((DBC *)); -static int __bam_c_first __P((DBC *, CURSOR *)); -static int __bam_c_get __P((DBC *, DBT *, DBT *, u_int32_t)); -static int __bam_c_getstack __P((DBC *, CURSOR *)); -static int __bam_c_last __P((DBC *, CURSOR *)); -static int __bam_c_next __P((DBC *, CURSOR *, int)); -static int __bam_c_physdel __P((DBC *, CURSOR *, PAGE *)); -static int __bam_c_prev __P((DBC *, CURSOR *)); -static int __bam_c_put __P((DBC *, DBT *, DBT *, u_int32_t)); -static void __bam_c_reset __P((CURSOR *)); -static int __bam_c_rget __P((DBC *, DBT *, u_int32_t)); -static int __bam_c_search __P((DBC *, CURSOR *, const DBT *, u_int32_t, int *)); -static int __bam_dsearch __P((DBC *, CURSOR *, DBT *, u_int32_t *)); - -/* Discard the current page/lock held by a cursor. */ -#undef DISCARD -#define DISCARD(dbc, cp) { \ - if ((cp)->page != NULL) { \ - (void)memp_fput((dbc)->dbp->mpf, (cp)->page, 0); \ - (cp)->page = NULL; \ - } \ - if ((cp)->lock != LOCK_INVALID) { \ - (void)__BT_TLPUT((dbc), (cp)->lock); \ - (cp)->lock = LOCK_INVALID; \ - } \ -} - -/* If the cursor references a deleted record. */ -#undef IS_CUR_DELETED -#define IS_CUR_DELETED(cp) \ - (((cp)->dpgno == PGNO_INVALID && \ - B_DISSET(GET_BKEYDATA((cp)->page, \ - (cp)->indx + O_INDX)->type)) || \ - ((cp)->dpgno != PGNO_INVALID && \ - B_DISSET(GET_BKEYDATA((cp)->page, (cp)->dindx)->type))) - -/* If the cursor and index combination references a deleted record. */ -#undef IS_DELETED -#define IS_DELETED(cp, indx) \ - (((cp)->dpgno == PGNO_INVALID && \ - B_DISSET(GET_BKEYDATA((cp)->page, (indx) + O_INDX)->type)) || \ - ((cp)->dpgno != PGNO_INVALID && \ - B_DISSET(GET_BKEYDATA((cp)->page, (indx))->type))) - -/* - * Test to see if two cursors could point to duplicates of the same key, - * whether on-page or off-page. The leaf page numbers must be the same - * in both cases. In the case of off-page duplicates, the key indices - * on the leaf page will be the same. In the case of on-page duplicates, - * the duplicate page number must not be set, and the key index offsets - * must be the same. For the last test, as the saved copy of the cursor - * will not have a valid page pointer, we use the cursor's. - */ -#undef POSSIBLE_DUPLICATE -#define POSSIBLE_DUPLICATE(cursor, saved_copy) \ - ((cursor)->pgno == (saved_copy).pgno && \ - ((cursor)->indx == (saved_copy).indx || \ - ((cursor)->dpgno == PGNO_INVALID && \ - (saved_copy).dpgno == PGNO_INVALID && \ - (cursor)->page->inp[(cursor)->indx] == \ - (cursor)->page->inp[(saved_copy).indx]))) - -/* - * __bam_c_reset -- - * Initialize internal cursor structure. - */ -static void -__bam_c_reset(cp) - CURSOR *cp; -{ - cp->sp = cp->csp = cp->stack; - cp->esp = cp->stack + sizeof(cp->stack) / sizeof(cp->stack[0]); - cp->page = NULL; - cp->pgno = PGNO_INVALID; - cp->indx = 0; - cp->dpgno = PGNO_INVALID; - cp->dindx = 0; - cp->lock = LOCK_INVALID; - cp->mode = DB_LOCK_NG; - cp->recno = RECNO_OOB; - cp->flags = 0; -} - -/* - * __bam_c_init -- - * Initialize the access private portion of a cursor - * - * PUBLIC: int __bam_c_init __P((DBC *)); - */ -int -__bam_c_init(dbc) - DBC *dbc; -{ - DB *dbp; - CURSOR *cp; - int ret; - - if ((ret = __os_calloc(1, sizeof(CURSOR), &cp)) != 0) - return (ret); - - dbp = dbc->dbp; - cp->dbc = dbc; - - /* - * Logical record numbers are always the same size, and we don't want - * to have to check for space every time we return one. Allocate it - * in advance. - */ - if (dbp->type == DB_RECNO || F_ISSET(dbp, DB_BT_RECNUM)) { - if ((ret = __os_malloc(sizeof(db_recno_t), - NULL, &dbc->rkey.data)) != 0) { - __os_free(cp, sizeof(CURSOR)); - return (ret); - } - dbc->rkey.ulen = sizeof(db_recno_t); - } - - /* Initialize methods. */ - dbc->internal = cp; - if (dbp->type == DB_BTREE) { - dbc->c_am_close = __bam_c_close; - dbc->c_am_destroy = __bam_c_destroy; - dbc->c_del = __bam_c_del; - dbc->c_get = __bam_c_get; - dbc->c_put = __bam_c_put; - } else { - dbc->c_am_close = __bam_c_close; - dbc->c_am_destroy = __bam_c_destroy; - dbc->c_del = __ram_c_del; - dbc->c_get = __ram_c_get; - dbc->c_put = __ram_c_put; - } - - /* Initialize dynamic information. */ - __bam_c_reset(cp); - - return (0); -} - -/* - * __bam_c_close -- - * Close down the cursor from a single use. - */ -static int -__bam_c_close(dbc) - DBC *dbc; -{ - CURSOR *cp; - DB *dbp; - int ret; - - dbp = dbc->dbp; - cp = dbc->internal; - ret = 0; - - /* - * If a cursor deleted a btree key, perform the actual deletion. - * (Recno keys are either deleted immediately or never deleted.) - */ - if (dbp->type == DB_BTREE && F_ISSET(cp, C_DELETED)) - ret = __bam_c_physdel(dbc, cp, NULL); - - /* Discard any locks not acquired inside of a transaction. */ - if (cp->lock != LOCK_INVALID) { - (void)__BT_TLPUT(dbc, cp->lock); - cp->lock = LOCK_INVALID; - } - - /* Sanity checks. */ -#ifdef DIAGNOSTIC - if (cp->csp != cp->stack) - __db_err(dbp->dbenv, "btree cursor close: stack not empty"); -#endif - - /* Initialize dynamic information. */ - __bam_c_reset(cp); - - return (ret); -} - -/* - * __bam_c_destroy -- - * Close a single cursor -- internal version. - */ -static int -__bam_c_destroy(dbc) - DBC *dbc; -{ - /* Discard the structures. */ - __os_free(dbc->internal, sizeof(CURSOR)); - - return (0); -} - -/* - * __bam_c_del -- - * Delete using a cursor. - */ -static int -__bam_c_del(dbc, flags) - DBC *dbc; - u_int32_t flags; -{ - CURSOR *cp; - DB *dbp; - DB_LOCK lock; - PAGE *h; - db_pgno_t pgno; - db_indx_t indx; - int ret; - - dbp = dbc->dbp; - cp = dbc->internal; - h = NULL; - - DB_PANIC_CHECK(dbp); - - /* Check for invalid flags. */ - if ((ret = __db_cdelchk(dbp, flags, - F_ISSET(dbp, DB_AM_RDONLY), cp->pgno != PGNO_INVALID)) != 0) - return (ret); - - /* - * If we are running CDB, this had better be either a write - * cursor or an immediate writer. - */ - if (F_ISSET(dbp, DB_AM_CDB)) - if (!F_ISSET(dbc, DBC_RMW | DBC_WRITER)) - return (EINVAL); - - DEBUG_LWRITE(dbc, dbc->txn, "bam_c_del", NULL, NULL, flags); - - /* If already deleted, return failure. */ - if (F_ISSET(cp, C_DELETED)) - return (DB_KEYEMPTY); - - /* - * We don't physically delete the record until the cursor moves, - * so we have to have a long-lived write lock on the page instead - * of a long-lived read lock. Note, we have to have a read lock - * to even get here, so we simply discard it. - */ - if (F_ISSET(dbp, DB_AM_LOCKING) && cp->mode != DB_LOCK_WRITE) { - if ((ret = __bam_lget(dbc, - 0, cp->pgno, DB_LOCK_WRITE, &lock)) != 0) - goto err; - (void)__BT_TLPUT(dbc, cp->lock); - cp->lock = lock; - cp->mode = DB_LOCK_WRITE; - } - - /* - * Acquire the underlying page (which may be different from the above - * page because it may be a duplicate page), and set the on-page and - * in-cursor delete flags. We don't need to lock it as we've already - * write-locked the page leading to it. - */ - if (cp->dpgno == PGNO_INVALID) { - pgno = cp->pgno; - indx = cp->indx; - } else { - pgno = cp->dpgno; - indx = cp->dindx; - } - - if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0) - goto err; - - /* Log the change. */ - if (DB_LOGGING(dbc) && - (ret = __bam_cdel_log(dbp->dbenv->lg_info, dbc->txn, &LSN(h), - 0, dbp->log_fileid, PGNO(h), &LSN(h), indx)) != 0) { - (void)memp_fput(dbp->mpf, h, 0); - goto err; - } - - /* - * Set the intent-to-delete flag on the page and update all cursors. */ - if (cp->dpgno == PGNO_INVALID) - B_DSET(GET_BKEYDATA(h, indx + O_INDX)->type); - else - B_DSET(GET_BKEYDATA(h, indx)->type); - (void)__bam_ca_delete(dbp, pgno, indx, 1); - - ret = memp_fput(dbp->mpf, h, DB_MPOOL_DIRTY); - h = NULL; - - /* - * If the tree has record numbers, we have to adjust the counts. - * - * !!! - * This test is right -- we don't yet support duplicates and record - * numbers in the same tree, so ignore duplicates if DB_BT_RECNUM - * set. - */ - if (F_ISSET(dbp, DB_BT_RECNUM)) { - if ((ret = __bam_c_getstack(dbc, cp)) != 0) - goto err; - if ((ret = __bam_adjust(dbc, -1)) != 0) - goto err; - (void)__bam_stkrel(dbc, 0); - } - -err: if (h != NULL) - (void)memp_fput(dbp->mpf, h, 0); - return (ret); -} - -/* - * __bam_c_get -- - * Get using a cursor (btree). - */ -static int -__bam_c_get(dbc, key, data, flags) - DBC *dbc; - DBT *key, *data; - u_int32_t flags; -{ - CURSOR *cp, copy, start; - DB *dbp; - PAGE *h; - int exact, ret, tmp_rmw; - - dbp = dbc->dbp; - cp = dbc->internal; - - DB_PANIC_CHECK(dbp); - - /* Check for invalid flags. */ - if ((ret = __db_cgetchk(dbp, - key, data, flags, cp->pgno != PGNO_INVALID)) != 0) - return (ret); - - /* Clear OR'd in additional bits so we can check for flag equality. */ - tmp_rmw = 0; - if (LF_ISSET(DB_RMW)) { - if (!F_ISSET(dbp, DB_AM_CDB)) { - tmp_rmw = 1; - F_SET(dbc, DBC_RMW); - } - LF_CLR(DB_RMW); - } - - DEBUG_LREAD(dbc, dbc->txn, "bam_c_get", - flags == DB_SET || flags == DB_SET_RANGE ? key : NULL, NULL, flags); - - /* - * Return a cursor's record number. It has nothing to do with the - * cursor get code except that it's been rammed into the interface. - */ - if (flags == DB_GET_RECNO) { - ret = __bam_c_rget(dbc, data, flags); - if (tmp_rmw) - F_CLR(dbc, DBC_RMW); - return (ret); - } - - /* - * Initialize the cursor for a new retrieval. Clear the cursor's - * page pointer, it was set before this operation, and no longer - * has any meaning. - */ - cp->page = NULL; - copy = *cp; - cp->lock = LOCK_INVALID; - - switch (flags) { - case DB_CURRENT: - /* It's not possible to return a deleted record. */ - if (F_ISSET(cp, C_DELETED)) { - ret = DB_KEYEMPTY; - goto err; - } - - /* Acquire the current page. */ - if ((ret = __bam_lget(dbc, - 0, cp->pgno, DB_LOCK_READ, &cp->lock)) == 0) - ret = memp_fget(dbp->mpf, - cp->dpgno == PGNO_INVALID ? &cp->pgno : &cp->dpgno, - 0, &cp->page); - if (ret != 0) - goto err; - break; - case DB_NEXT_DUP: - if (cp->pgno == PGNO_INVALID) { - ret = EINVAL; - goto err; - } - if ((ret = __bam_c_next(dbc, cp, 1)) != 0) - goto err; - - /* Make sure we didn't go past the end of the duplicates. */ - if (!POSSIBLE_DUPLICATE(cp, copy)) { - ret = DB_NOTFOUND; - goto err; - } - break; - case DB_NEXT: - if (cp->pgno != PGNO_INVALID) { - if ((ret = __bam_c_next(dbc, cp, 1)) != 0) - goto err; - break; - } - /* FALLTHROUGH */ - case DB_FIRST: - if ((ret = __bam_c_first(dbc, cp)) != 0) - goto err; - break; - case DB_PREV: - if (cp->pgno != PGNO_INVALID) { - if ((ret = __bam_c_prev(dbc, cp)) != 0) - goto err; - break; - } - /* FALLTHROUGH */ - case DB_LAST: - if ((ret = __bam_c_last(dbc, cp)) != 0) - goto err; - break; - case DB_SET: - if ((ret = __bam_c_search(dbc, cp, key, flags, &exact)) != 0) - goto err; - - /* - * We cannot currently be referencing a deleted record, but we - * may be referencing off-page duplicates. - * - * If we're referencing off-page duplicates, move off-page. - * If we moved off-page, move to the next non-deleted record. - * If we moved to the next non-deleted record, check to make - * sure we didn't switch records because our current record - * had no non-deleted data items. - */ - start = *cp; - if ((ret = __bam_dup(dbc, cp, cp->indx, 0)) != 0) - goto err; - if (cp->dpgno != PGNO_INVALID && IS_CUR_DELETED(cp)) { - if ((ret = __bam_c_next(dbc, cp, 0)) != 0) - goto err; - if (!POSSIBLE_DUPLICATE(cp, start)) { - ret = DB_NOTFOUND; - goto err; - } - } - break; - case DB_SET_RECNO: - if ((ret = __bam_c_search(dbc, cp, key, flags, &exact)) != 0) - goto err; - break; - case DB_GET_BOTH: - if (F_ISSET(dbc, DBC_CONTINUE | DBC_KEYSET)) { - /* Acquire the current page. */ - if ((ret = memp_fget(dbp->mpf, - cp->dpgno == PGNO_INVALID ? &cp->pgno : &cp->dpgno, - 0, &cp->page)) != 0) - goto err; - - /* If DBC_CONTINUE, move to the next item. */ - if (F_ISSET(dbc, DBC_CONTINUE) && - (ret = __bam_c_next(dbc, cp, 1)) != 0) - goto err; - } else { - if ((ret = - __bam_c_search(dbc, cp, key, flags, &exact)) != 0) - goto err; - - /* - * We may be referencing a duplicates page. Move to - * the first duplicate. - */ - if ((ret = __bam_dup(dbc, cp, cp->indx, 0)) != 0) - goto err; - } - - /* Search for a matching entry. */ - if ((ret = __bam_dsearch(dbc, cp, data, NULL)) != 0) - goto err; - - /* Ignore deleted entries. */ - if (IS_CUR_DELETED(cp)) { - ret = DB_NOTFOUND; - goto err; - } - break; - case DB_SET_RANGE: - if ((ret = __bam_c_search(dbc, cp, key, flags, &exact)) != 0) - goto err; - - /* - * As we didn't require an exact match, the search function - * may have returned an entry past the end of the page. If - * so, move to the next entry. - */ - if (cp->indx == NUM_ENT(cp->page) && - (ret = __bam_c_next(dbc, cp, 0)) != 0) - goto err; - - /* - * We may be referencing off-page duplicates, if so, move - * off-page. - */ - if ((ret = __bam_dup(dbc, cp, cp->indx, 0)) != 0) - goto err; - - /* - * We may be referencing a deleted record, if so, move to - * the next non-deleted record. - */ - if (IS_CUR_DELETED(cp) && (ret = __bam_c_next(dbc, cp, 0)) != 0) - goto err; - break; - } - - /* - * Return the key if the user didn't give us one. If we've moved to - * a duplicate page, we may no longer have a pointer to the main page, - * so we have to go get it. We know that it's already read-locked, - * however, so we don't have to acquire a new lock. - */ - if (flags != DB_SET) { - if (cp->dpgno != PGNO_INVALID) { - if ((ret = memp_fget(dbp->mpf, &cp->pgno, 0, &h)) != 0) - goto err; - } else - h = cp->page; - ret = __db_ret(dbp, - h, cp->indx, key, &dbc->rkey.data, &dbc->rkey.ulen); - if (cp->dpgno != PGNO_INVALID) - (void)memp_fput(dbp->mpf, h, 0); - if (ret) - goto err; - } - - /* Return the data. */ - if ((ret = __db_ret(dbp, cp->page, - cp->dpgno == PGNO_INVALID ? cp->indx + O_INDX : cp->dindx, - data, &dbc->rdata.data, &dbc->rdata.ulen)) != 0) - goto err; - - /* - * If the previous cursor record has been deleted, physically delete - * the entry from the page. We clear the deleted flag before we call - * the underlying delete routine so that, if an error occurs, and we - * restore the cursor, the deleted flag is cleared. This is because, - * if we manage to physically modify the page, and then restore the - * cursor, we might try to repeat the page modification when closing - * the cursor. - */ - if (F_ISSET(©, C_DELETED)) { - F_CLR(©, C_DELETED); - if ((ret = __bam_c_physdel(dbc, ©, cp->page)) != 0) - goto err; - } - F_CLR(cp, C_DELETED); - - /* Release the previous lock, if any; the current lock is retained. */ - if (copy.lock != LOCK_INVALID) - (void)__BT_TLPUT(dbc, copy.lock); - - /* Release the current page. */ - if ((ret = memp_fput(dbp->mpf, cp->page, 0)) != 0) - goto err; - - if (0) { -err: if (cp->page != NULL) - (void)memp_fput(dbp->mpf, cp->page, 0); - if (cp->lock != LOCK_INVALID) - (void)__BT_TLPUT(dbc, cp->lock); - *cp = copy; - } - - /* Release temporary lock upgrade. */ - if (tmp_rmw) - F_CLR(dbc, DBC_RMW); - - return (ret); -} - -/* - * __bam_dsearch -- - * Search for a matching data item (or the first data item that's - * equal to or greater than the one we're searching for). - */ -static int -__bam_dsearch(dbc, cp, data, iflagp) - DBC *dbc; - CURSOR *cp; - DBT *data; - u_int32_t *iflagp; -{ - DB *dbp; - CURSOR copy, last; - int cmp, ret; - - dbp = dbc->dbp; - - /* - * If iflagp is non-NULL, we're doing an insert. - * - * If the duplicates are off-page, use the duplicate search routine. - */ - if (cp->dpgno != PGNO_INVALID) { - if ((ret = __db_dsearch(dbc, iflagp != NULL, - data, cp->dpgno, &cp->dindx, &cp->page, &cmp)) != 0) - return (ret); - cp->dpgno = cp->page->pgno; - - if (iflagp == NULL) { - if (cmp != 0) - return (DB_NOTFOUND); - return (0); - } - *iflagp = DB_BEFORE; - return (0); - } - - /* Otherwise, do the search ourselves. */ - copy = *cp; - for (;;) { - /* Save the last interesting cursor position. */ - last = *cp; - - /* See if the data item matches the one we're looking for. */ - if ((cmp = __bam_cmp(dbp, data, cp->page, cp->indx + O_INDX, - dbp->dup_compare == NULL ? - __bam_defcmp : dbp->dup_compare)) == 0) { - if (iflagp != NULL) - *iflagp = DB_AFTER; - return (0); - } - - /* - * If duplicate entries are sorted, we're done if we find a - * page entry that sorts greater than the application item. - * If doing an insert, return success, otherwise DB_NOTFOUND. - */ - if (dbp->dup_compare != NULL && cmp < 0) { - if (iflagp == NULL) - return (DB_NOTFOUND); - *iflagp = DB_BEFORE; - return (0); - } - - /* - * Move to the next item. If we reach the end of the page and - * we're doing an insert, set the cursor to the last item and - * set the referenced memory location so callers know to insert - * after the item, instead of before it. If not inserting, we - * return DB_NOTFOUND. - */ - if ((cp->indx += P_INDX) >= NUM_ENT(cp->page)) { - if (iflagp == NULL) - return (DB_NOTFOUND); - goto use_last; - } - - /* - * Make sure we didn't go past the end of the duplicates. The - * error conditions are the same as above. - */ - if (!POSSIBLE_DUPLICATE(cp, copy)) { - if (iflagp == NULL) - return (DB_NOTFOUND); -use_last: *cp = last; - *iflagp = DB_AFTER; - return (0); - } - } - /* NOTREACHED */ -} - -/* - * __bam_c_rget -- - * Return the record number for a cursor. - */ -static int -__bam_c_rget(dbc, data, flags) - DBC *dbc; - DBT *data; - u_int32_t flags; -{ - CURSOR *cp; - DB *dbp; - DBT dbt; - db_recno_t recno; - int exact, ret; - - COMPQUIET(flags, 0); - dbp = dbc->dbp; - cp = dbc->internal; - - /* Get the page with the current item on it. */ - if ((ret = memp_fget(dbp->mpf, &cp->pgno, 0, &cp->page)) != 0) - return (ret); - - /* Get a copy of the key. */ - memset(&dbt, 0, sizeof(DBT)); - dbt.flags = DB_DBT_MALLOC | DB_DBT_INTERNAL; - if ((ret = __db_ret(dbp, cp->page, cp->indx, &dbt, NULL, NULL)) != 0) - goto err; - - exact = 1; - if ((ret = __bam_search(dbc, &dbt, - F_ISSET(dbc, DBC_RMW) ? S_FIND_WR : S_FIND, - 1, &recno, &exact)) != 0) - goto err; - - ret = __db_retcopy(data, &recno, sizeof(recno), - &dbc->rdata.data, &dbc->rdata.ulen, dbp->db_malloc); - - /* Release the stack. */ - __bam_stkrel(dbc, 0); - -err: (void)memp_fput(dbp->mpf, cp->page, 0); - __os_free(dbt.data, dbt.size); - return (ret); -} - -/* - * __bam_c_put -- - * Put using a cursor. - */ -static int -__bam_c_put(dbc, key, data, flags) - DBC *dbc; - DBT *key, *data; - u_int32_t flags; -{ - CURSOR *cp, copy; - DB *dbp; - DBT dbt; - db_indx_t indx; - db_pgno_t pgno; - u_int32_t iiflags, iiop; - int exact, needkey, ret, stack; - void *arg; - - dbp = dbc->dbp; - cp = dbc->internal; - - DB_PANIC_CHECK(dbp); - - DEBUG_LWRITE(dbc, dbc->txn, "bam_c_put", - flags == DB_KEYFIRST || flags == DB_KEYLAST ? key : NULL, - data, flags); - - if ((ret = __db_cputchk(dbp, key, data, flags, - F_ISSET(dbp, DB_AM_RDONLY), cp->pgno != PGNO_INVALID)) != 0) - return (ret); - - /* - * If we are running CDB, this had better be either a write - * cursor or an immediate writer. If it's a regular writer, - * that means we have an IWRITE lock and we need to upgrade - * it to a write lock. - */ - if (F_ISSET(dbp, DB_AM_CDB)) { - if (!F_ISSET(dbc, DBC_RMW | DBC_WRITER)) - return (EINVAL); - - if (F_ISSET(dbc, DBC_RMW) && - (ret = lock_get(dbp->dbenv->lk_info, dbc->locker, - DB_LOCK_UPGRADE, &dbc->lock_dbt, DB_LOCK_WRITE, - &dbc->mylock)) != 0) - return (EAGAIN); - } - - if (0) { -split: /* - * To split, we need a valid key for the page. Since it's a - * cursor, we have to build one. - * - * Acquire a copy of a key from the page. - */ - if (needkey) { - memset(&dbt, 0, sizeof(DBT)); - if ((ret = __db_ret(dbp, cp->page, indx, - &dbt, &dbc->rkey.data, &dbc->rkey.ulen)) != 0) - goto err; - arg = &dbt; - } else - arg = key; - - /* - * Discard any locks and pinned pages (the locks are discarded - * even if we're running with transactions, as they lock pages - * that we're sorry we ever acquired). If stack is set and the - * cursor entries are valid, they point to the same entries as - * the stack, don't free them twice. - */ - if (stack) { - (void)__bam_stkrel(dbc, 1); - stack = 0; - } else - DISCARD(dbc, cp); - - /* - * Restore the cursor to its original value. This is necessary - * for two reasons. First, we are about to copy it in case of - * error, again. Second, we adjust cursors during the split, - * and we have to ensure this cursor is adjusted appropriately, - * along with all the other cursors. - */ - *cp = copy; - - if ((ret = __bam_split(dbc, arg)) != 0) - goto err; - } - - /* - * Initialize the cursor for a new retrieval. Clear the cursor's - * page pointer, it was set before this operation, and no longer - * has any meaning. - */ - cp->page = NULL; - copy = *cp; - cp->lock = LOCK_INVALID; - - iiflags = needkey = ret = stack = 0; - switch (flags) { - case DB_AFTER: - case DB_BEFORE: - case DB_CURRENT: - needkey = 1; - if (cp->dpgno == PGNO_INVALID) { - pgno = cp->pgno; - indx = cp->indx; - } else { - pgno = cp->dpgno; - indx = cp->dindx; - } - - /* - * !!! - * This test is right -- we don't yet support duplicates and - * record numbers in the same tree, so ignore duplicates if - * DB_BT_RECNUM set. - */ - if (F_ISSET(dbp, DB_BT_RECNUM) && - (flags != DB_CURRENT || F_ISSET(cp, C_DELETED))) { - /* Acquire a complete stack. */ - if ((ret = __bam_c_getstack(dbc, cp)) != 0) - goto err; - cp->page = cp->csp->page; - - stack = 1; - iiflags = BI_DOINCR; - } else { - /* Acquire the current page. */ - if ((ret = __bam_lget(dbc, - 0, cp->pgno, DB_LOCK_WRITE, &cp->lock)) == 0) - ret = memp_fget(dbp->mpf, &pgno, 0, &cp->page); - if (ret != 0) - goto err; - - iiflags = 0; - } - - /* - * If the user has specified a duplicate comparison function, - * we return an error if DB_CURRENT was specified and the - * replacement data doesn't compare equal to the current data. - * This stops apps from screwing up the duplicate sort order. - */ - if (flags == DB_CURRENT && dbp->dup_compare != NULL) - if (__bam_cmp(dbp, data, - cp->page, indx, dbp->dup_compare) != 0) { - ret = EINVAL; - goto err; - } - - iiop = flags; - break; - case DB_KEYFIRST: - case DB_KEYLAST: - /* - * If we have a duplicate comparison function, we position to - * the first of any on-page duplicates, and use __bam_dsearch - * to search for the right slot. Otherwise, we position to - * the first/last of any on-page duplicates based on the flag - * value. - */ - if ((ret = __bam_c_search(dbc, cp, key, - flags == DB_KEYFIRST || dbp->dup_compare != NULL ? - DB_KEYFIRST : DB_KEYLAST, &exact)) != 0) - goto err; - stack = 1; - - /* - * If an exact match: - * If duplicates aren't supported, replace the current - * item. (When implementing the DB->put function, our - * caller has already checked the DB_NOOVERWRITE flag.) - * - * If there's a duplicate comparison function, find the - * correct slot for this duplicate item. - * - * If there's no duplicate comparison function, set the - * insert flag based on the argument flags. - * - * If there's no match, the search function returned the - * smallest slot greater than the key, use it. - */ - if (exact) { - if (F_ISSET(dbp, DB_AM_DUP)) { - /* - * If at off-page duplicate page, move to the - * first or last entry -- if a comparison - * function was specified, start searching at - * the first entry. Otherwise, move based on - * the DB_KEYFIRST/DB_KEYLAST flags. - */ - if ((ret = __bam_dup(dbc, cp, cp->indx, - dbp->dup_compare == NULL && - flags != DB_KEYFIRST)) != 0) - goto err; - - /* - * If there's a comparison function, search for - * the correct slot. Otherwise, set the insert - * flag based on the argment flag. - */ - if (dbp->dup_compare == NULL) - iiop = flags == DB_KEYFIRST ? - DB_BEFORE : DB_AFTER; - else - if ((ret = __bam_dsearch(dbc, - cp, data, &iiop)) != 0) - goto err; - } else - iiop = DB_CURRENT; - iiflags = 0; - } else { - iiop = DB_BEFORE; - iiflags = BI_NEWKEY; - } - - if (cp->dpgno == PGNO_INVALID) { - pgno = cp->pgno; - indx = cp->indx; - } else { - pgno = cp->dpgno; - indx = cp->dindx; - } - break; - } - - ret = __bam_iitem(dbc, &cp->page, &indx, key, data, iiop, iiflags); - - if (ret == DB_NEEDSPLIT) - goto split; - if (ret != 0) - goto err; - - /* - * Reset any cursors referencing this item that might have the item - * marked for deletion. - */ - if (iiop == DB_CURRENT) { - (void)__bam_ca_delete(dbp, pgno, indx, 0); - - /* - * It's also possible that we are the cursor that had the - * item marked for deletion, in which case we want to make - * sure that we don't delete it because we had the delete - * flag set already. - */ - if (cp->pgno == copy.pgno && cp->indx == copy.indx && - cp->dpgno == copy.dpgno && cp->dindx == copy.dindx) - F_CLR(©, C_DELETED); - } - - /* - * Update the cursor to point to the new entry. The new entry was - * stored on the current page, because we split pages until it was - * possible. - */ - if (cp->dpgno == PGNO_INVALID) - cp->indx = indx; - else - cp->dindx = indx; - - /* - * If the previous cursor record has been deleted, physically delete - * the entry from the page. We clear the deleted flag before we call - * the underlying delete routine so that, if an error occurs, and we - * restore the cursor, the deleted flag is cleared. This is because, - * if we manage to physically modify the page, and then restore the - * cursor, we might try to repeat the page modification when closing - * the cursor. - */ - if (F_ISSET(©, C_DELETED)) { - F_CLR(©, C_DELETED); - if ((ret = __bam_c_physdel(dbc, ©, cp->page)) != 0) - goto err; - } - F_CLR(cp, C_DELETED); - - /* Release the previous lock, if any; the current lock is retained. */ - if (copy.lock != LOCK_INVALID) - (void)__BT_TLPUT(dbc, copy.lock); - - /* - * Discard any pages pinned in the tree and their locks, except for - * the leaf page, for which we only discard the pin, not the lock. - * - * Note, the leaf page participated in the stack we acquired, and so - * we have to adjust the stack as necessary. If there was only a - * single page on the stack, we don't have to free further stack pages. - */ - if (stack && BT_STK_POP(cp) != NULL) - (void)__bam_stkrel(dbc, 0); - - /* Release the current page. */ - if ((ret = memp_fput(dbp->mpf, cp->page, 0)) != 0) - goto err; - - if (0) { -err: /* Discard any pinned pages. */ - if (stack) - (void)__bam_stkrel(dbc, 0); - else - DISCARD(dbc, cp); - *cp = copy; - } - - if (F_ISSET(dbp, DB_AM_CDB) && F_ISSET(dbc, DBC_RMW)) - (void)__lock_downgrade(dbp->dbenv->lk_info, dbc->mylock, - DB_LOCK_IWRITE, 0); - - return (ret); -} - -/* - * __bam_c_first -- - * Return the first record. - */ -static int -__bam_c_first(dbc, cp) - DBC *dbc; - CURSOR *cp; -{ - DB *dbp; - db_pgno_t pgno; - int ret; - - dbp = dbc->dbp; - - /* Walk down the left-hand side of the tree. */ - for (pgno = PGNO_ROOT;;) { - if ((ret = - __bam_lget(dbc, 0, pgno, DB_LOCK_READ, &cp->lock)) != 0) - return (ret); - if ((ret = memp_fget(dbp->mpf, &pgno, 0, &cp->page)) != 0) - return (ret); - - /* If we find a leaf page, we're done. */ - if (ISLEAF(cp->page)) - break; - - pgno = GET_BINTERNAL(cp->page, 0)->pgno; - DISCARD(dbc, cp); - } - - cp->pgno = cp->page->pgno; - cp->indx = 0; - cp->dpgno = PGNO_INVALID; - - /* Check for duplicates. */ - if ((ret = __bam_dup(dbc, cp, cp->indx, 0)) != 0) - return (ret); - - /* If on an empty page or a deleted record, move to the next one. */ - if (NUM_ENT(cp->page) == 0 || IS_CUR_DELETED(cp)) - if ((ret = __bam_c_next(dbc, cp, 0)) != 0) - return (ret); - - return (0); -} - -/* - * __bam_c_last -- - * Return the last record. - */ -static int -__bam_c_last(dbc, cp) - DBC *dbc; - CURSOR *cp; -{ - DB *dbp; - db_pgno_t pgno; - int ret; - - dbp = dbc->dbp; - - /* Walk down the right-hand side of the tree. */ - for (pgno = PGNO_ROOT;;) { - if ((ret = - __bam_lget(dbc, 0, pgno, DB_LOCK_READ, &cp->lock)) != 0) - return (ret); - if ((ret = memp_fget(dbp->mpf, &pgno, 0, &cp->page)) != 0) - return (ret); - - /* If we find a leaf page, we're done. */ - if (ISLEAF(cp->page)) - break; - - pgno = - GET_BINTERNAL(cp->page, NUM_ENT(cp->page) - O_INDX)->pgno; - DISCARD(dbc, cp); - } - - cp->pgno = cp->page->pgno; - cp->indx = NUM_ENT(cp->page) == 0 ? 0 : NUM_ENT(cp->page) - P_INDX; - cp->dpgno = PGNO_INVALID; - - /* Check for duplicates. */ - if ((ret = __bam_dup(dbc, cp, cp->indx, 1)) != 0) - return (ret); - - /* If on an empty page or a deleted record, move to the next one. */ - if (NUM_ENT(cp->page) == 0 || IS_CUR_DELETED(cp)) - if ((ret = __bam_c_prev(dbc, cp)) != 0) - return (ret); - - return (0); -} - -/* - * __bam_c_next -- - * Move to the next record. - */ -static int -__bam_c_next(dbc, cp, initial_move) - DBC *dbc; - CURSOR *cp; - int initial_move; -{ - DB *dbp; - db_indx_t adjust, indx; - db_pgno_t pgno; - int ret; - - dbp = dbc->dbp; - - /* - * We're either moving through a page of duplicates or a btree leaf - * page. - */ - if (cp->dpgno == PGNO_INVALID) { - adjust = dbp->type == DB_BTREE ? P_INDX : O_INDX; - pgno = cp->pgno; - indx = cp->indx; - } else { - adjust = O_INDX; - pgno = cp->dpgno; - indx = cp->dindx; - } - if (cp->page == NULL) { - if ((ret = - __bam_lget(dbc, 0, pgno, DB_LOCK_READ, &cp->lock)) != 0) - return (ret); - if ((ret = memp_fget(dbp->mpf, &pgno, 0, &cp->page)) != 0) - return (ret); - } - - /* - * If at the end of the page, move to a subsequent page. - * - * !!! - * Check for >= NUM_ENT. If we're here as the result of a search that - * landed us on NUM_ENT, we'll increment indx before we test. - * - * !!! - * This code handles empty pages and pages with only deleted entries. - */ - if (initial_move) - indx += adjust; - for (;;) { - if (indx >= NUM_ENT(cp->page)) { - /* - * If we're in a btree leaf page, we've reached the end - * of the tree. If we've reached the end of a page of - * duplicates, continue from the btree leaf page where - * we found this page of duplicates. - */ - pgno = cp->page->next_pgno; - if (pgno == PGNO_INVALID) { - /* If in a btree leaf page, it's EOF. */ - if (cp->dpgno == PGNO_INVALID) - return (DB_NOTFOUND); - - /* Continue from the last btree leaf page. */ - cp->dpgno = PGNO_INVALID; - - adjust = P_INDX; - pgno = cp->pgno; - indx = cp->indx + P_INDX; - } else - indx = 0; - - DISCARD(dbc, cp); - if ((ret = __bam_lget(dbc, - 0, pgno, DB_LOCK_READ, &cp->lock)) != 0) - return (ret); - if ((ret = - memp_fget(dbp->mpf, &pgno, 0, &cp->page)) != 0) - return (ret); - continue; - } - - /* Ignore deleted records. */ - if (IS_DELETED(cp, indx)) { - indx += adjust; - continue; - } - - /* - * If we're not in a duplicates page, check to see if we've - * found a page of duplicates, in which case we move to the - * first entry. - */ - if (cp->dpgno == PGNO_INVALID) { - cp->pgno = cp->page->pgno; - cp->indx = indx; - - if ((ret = __bam_dup(dbc, cp, indx, 0)) != 0) - return (ret); - if (cp->dpgno != PGNO_INVALID) { - indx = cp->dindx; - adjust = O_INDX; - continue; - } - } else { - cp->dpgno = cp->page->pgno; - cp->dindx = indx; - } - break; - } - return (0); -} - -/* - * __bam_c_prev -- - * Move to the previous record. - */ -static int -__bam_c_prev(dbc, cp) - DBC *dbc; - CURSOR *cp; -{ - DB *dbp; - db_indx_t indx, adjust; - db_pgno_t pgno; - int ret, set_indx; - - dbp = dbc->dbp; - - /* - * We're either moving through a page of duplicates or a btree leaf - * page. - */ - if (cp->dpgno == PGNO_INVALID) { - adjust = dbp->type == DB_BTREE ? P_INDX : O_INDX; - pgno = cp->pgno; - indx = cp->indx; - } else { - adjust = O_INDX; - pgno = cp->dpgno; - indx = cp->dindx; - } - if (cp->page == NULL) { - if ((ret = - __bam_lget(dbc, 0, pgno, DB_LOCK_READ, &cp->lock)) != 0) - return (ret); - if ((ret = memp_fget(dbp->mpf, &pgno, 0, &cp->page)) != 0) - return (ret); - } - - /* - * If at the beginning of the page, move to any previous one. - * - * !!! - * This code handles empty pages and pages with only deleted entries. - */ - for (;;) { - if (indx == 0) { - /* - * If we're in a btree leaf page, we've reached the - * beginning of the tree. If we've reached the first - * of a page of duplicates, continue from the btree - * leaf page where we found this page of duplicates. - */ - pgno = cp->page->prev_pgno; - if (pgno == PGNO_INVALID) { - /* If in a btree leaf page, it's SOF. */ - if (cp->dpgno == PGNO_INVALID) - return (DB_NOTFOUND); - - /* Continue from the last btree leaf page. */ - cp->dpgno = PGNO_INVALID; - - adjust = P_INDX; - pgno = cp->pgno; - indx = cp->indx; - set_indx = 0; - } else - set_indx = 1; - - DISCARD(dbc, cp); - if ((ret = __bam_lget(dbc, - 0, pgno, DB_LOCK_READ, &cp->lock)) != 0) - return (ret); - if ((ret = - memp_fget(dbp->mpf, &pgno, 0, &cp->page)) != 0) - return (ret); - - if (set_indx) - indx = NUM_ENT(cp->page); - if (indx == 0) - continue; - } - - /* Ignore deleted records. */ - indx -= adjust; - if (IS_DELETED(cp, indx)) - continue; - - /* - * If we're not in a duplicates page, check to see if we've - * found a page of duplicates, in which case we move to the - * last entry. - */ - if (cp->dpgno == PGNO_INVALID) { - cp->pgno = cp->page->pgno; - cp->indx = indx; - - if ((ret = __bam_dup(dbc, cp, indx, 1)) != 0) - return (ret); - if (cp->dpgno != PGNO_INVALID) { - indx = cp->dindx + O_INDX; - adjust = O_INDX; - continue; - } - } else { - cp->dpgno = cp->page->pgno; - cp->dindx = indx; - } - break; - } - return (0); -} - -/* - * __bam_c_search -- - * Move to a specified record. - */ -static int -__bam_c_search(dbc, cp, key, flags, exactp) - DBC *dbc; - CURSOR *cp; - const DBT *key; - u_int32_t flags; - int *exactp; -{ - BTREE *t; - DB *dbp; - DB_LOCK lock; - PAGE *h; - db_recno_t recno; - db_indx_t indx; - u_int32_t sflags; - int cmp, needexact, ret; - - dbp = dbc->dbp; - t = dbp->internal; - - /* Find an entry in the database. */ - switch (flags) { - case DB_SET_RECNO: - if ((ret = __ram_getno(dbc, key, &recno, 0)) != 0) - return (ret); - sflags = F_ISSET(dbc, DBC_RMW) ? S_FIND_WR : S_FIND; - needexact = *exactp = 1; - ret = __bam_rsearch(dbc, &recno, sflags, 1, exactp); - break; - case DB_SET: - case DB_GET_BOTH: - sflags = F_ISSET(dbc, DBC_RMW) ? S_FIND_WR : S_FIND; - needexact = *exactp = 1; - goto search; - case DB_SET_RANGE: - sflags = F_ISSET(dbc, DBC_RMW) ? S_FIND_WR : S_FIND; - needexact = *exactp = 0; - goto search; - case DB_KEYFIRST: - sflags = S_KEYFIRST; - goto fast_search; - case DB_KEYLAST: - sflags = S_KEYLAST; -fast_search: needexact = *exactp = 0; - /* - * If the application has a history of inserting into the first - * or last pages of the database, we check those pages first to - * avoid doing a full search. - * - * Record numbers can't be fast-tracked, the entire tree has to - * be locked. - */ - h = NULL; - lock = LOCK_INVALID; - if (F_ISSET(dbp, DB_BT_RECNUM)) - goto search; - - /* Check if the application has a history of sorted input. */ - if (t->bt_lpgno == PGNO_INVALID) - goto search; - - /* - * Lock and retrieve the page on which we did the last insert. - * It's okay if it doesn't exist, or if it's not the page type - * we expected, it just means that the world changed. - */ - if (__bam_lget(dbc, 0, t->bt_lpgno, DB_LOCK_WRITE, &lock)) - goto fast_miss; - if (memp_fget(dbp->mpf, &t->bt_lpgno, 0, &h)) - goto fast_miss; - if (TYPE(h) != P_LBTREE) - goto fast_miss; - if (NUM_ENT(h) == 0) - goto fast_miss; - - /* - * What we do here is test to see if we're at the beginning or - * end of the tree and if the new item sorts before/after the - * first/last page entry. We don't try and catch inserts into - * the middle of the tree (although we could, as long as there - * were two keys on the page and we saved both the index and - * the page number of the last insert). - */ - if (h->next_pgno == PGNO_INVALID) { - indx = NUM_ENT(h) - P_INDX; - if ((cmp = - __bam_cmp(dbp, key, h, indx, t->bt_compare)) < 0) - goto try_begin; - if (cmp > 0) { - indx += P_INDX; - goto fast_hit; - } - - /* - * Found a duplicate. If doing DB_KEYLAST, we're at - * the correct position, otherwise, move to the first - * of the duplicates. - */ - if (flags == DB_KEYLAST) - goto fast_hit; - for (; - indx > 0 && h->inp[indx - P_INDX] == h->inp[indx]; - indx -= P_INDX) - ; - goto fast_hit; - } -try_begin: if (h->prev_pgno == PGNO_INVALID) { - indx = 0; - if ((cmp = - __bam_cmp(dbp, key, h, indx, t->bt_compare)) > 0) - goto fast_miss; - if (cmp < 0) - goto fast_hit; - /* - * Found a duplicate. If doing DB_KEYFIRST, we're at - * the correct position, otherwise, move to the last - * of the duplicates. - */ - if (flags == DB_KEYFIRST) - goto fast_hit; - for (; - indx < (db_indx_t)(NUM_ENT(h) - P_INDX) && - h->inp[indx] == h->inp[indx + P_INDX]; - indx += P_INDX) - ; - goto fast_hit; - } - goto fast_miss; - -fast_hit: /* Set the exact match flag, we may have found a duplicate. */ - *exactp = cmp == 0; - - /* Enter the entry in the stack. */ - BT_STK_CLR(cp); - BT_STK_ENTER(cp, h, indx, lock, ret); - break; - -fast_miss: if (h != NULL) - (void)memp_fput(dbp->mpf, h, 0); - if (lock != LOCK_INVALID) - (void)__BT_LPUT(dbc, lock); - -search: ret = __bam_search(dbc, key, sflags, 1, NULL, exactp); - break; - default: /* XXX: Impossible. */ - abort(); - /* NOTREACHED */ - } - if (ret != 0) - return (ret); - - /* - * Initialize the cursor to reference it. This has to be done - * before we return (even with DB_NOTFOUND) because we have to - * free the page(s) we locked in __bam_search. - */ - cp->page = cp->csp->page; - cp->pgno = cp->csp->page->pgno; - cp->indx = cp->csp->indx; - cp->lock = cp->csp->lock; - cp->dpgno = PGNO_INVALID; - - /* - * If we inserted a key into the first or last slot of the tree, - * remember where it was so we can do it more quickly next time. - */ - if (flags == DB_KEYFIRST || flags == DB_KEYLAST) - t->bt_lpgno = - ((cp->page->next_pgno == PGNO_INVALID && - cp->indx >= NUM_ENT(cp->page)) || - (cp->page->prev_pgno == PGNO_INVALID && cp->indx == 0)) ? - cp->pgno : PGNO_INVALID; - - /* If we need an exact match and didn't find one, we're done. */ - if (needexact && *exactp == 0) - return (DB_NOTFOUND); - - return (0); -} - -/* - * __bam_dup -- - * Check for an off-page duplicates entry, and if found, move to the - * first or last entry. - * - * PUBLIC: int __bam_dup __P((DBC *, CURSOR *, u_int32_t, int)); - */ -int -__bam_dup(dbc, cp, indx, last_dup) - DBC *dbc; - CURSOR *cp; - u_int32_t indx; - int last_dup; -{ - BOVERFLOW *bo; - DB *dbp; - db_pgno_t pgno; - int ret; - - dbp = dbc->dbp; - - /* - * Check for an overflow entry. If we find one, move to the - * duplicates page, and optionally move to the last record on - * that page. - * - * !!! - * We don't lock duplicates pages, we've already got the correct - * lock on the main page. - */ - bo = GET_BOVERFLOW(cp->page, indx + O_INDX); - if (B_TYPE(bo->type) != B_DUPLICATE) - return (0); - - pgno = bo->pgno; - if ((ret = memp_fput(dbp->mpf, cp->page, 0)) != 0) - return (ret); - cp->page = NULL; - if (last_dup) { - if ((ret = __db_dend(dbc, pgno, &cp->page)) != 0) - return (ret); - indx = NUM_ENT(cp->page) - O_INDX; - } else { - if ((ret = memp_fget(dbp->mpf, &pgno, 0, &cp->page)) != 0) - return (ret); - indx = 0; - } - - /* Update the cursor's duplicate information. */ - cp->dpgno = cp->page->pgno; - cp->dindx = indx; - - return (0); -} - -/* - * __bam_c_physdel -- - * Actually do the cursor deletion. - */ -static int -__bam_c_physdel(dbc, cp, h) - DBC *dbc; - CURSOR *cp; - PAGE *h; -{ - enum { DELETE_ITEM, DELETE_PAGE, NOTHING_FURTHER } cmd; - BOVERFLOW bo; - DB *dbp; - DBT dbt; - DB_LOCK lock; - db_indx_t indx; - db_pgno_t pgno, next_pgno, prev_pgno; - int delete_page, local_page, ret; - - dbp = dbc->dbp; - - delete_page = ret = 0; - - /* Figure out what we're deleting. */ - if (cp->dpgno == PGNO_INVALID) { - pgno = cp->pgno; - indx = cp->indx; - } else { - pgno = cp->dpgno; - indx = cp->dindx; - } - - /* - * If the item is referenced by another cursor, set that cursor's - * delete flag and leave it up to it to do the delete. - * - * !!! - * This test for > 0 is a tricky. There are two ways that we can - * be called here. Either we are closing the cursor or we've moved - * off the page with the deleted entry. In the first case, we've - * already removed the cursor from the active queue, so we won't see - * it in __bam_ca_delete. In the second case, it will be on a different - * item, so we won't bother with it in __bam_ca_delete. - */ - if (__bam_ca_delete(dbp, pgno, indx, 1) > 0) - return (0); - - /* - * If this is concurrent DB, upgrade the lock if necessary. - */ - if (F_ISSET(dbp, DB_AM_CDB) && F_ISSET(dbc, DBC_RMW) && - (ret = lock_get(dbp->dbenv->lk_info, - dbc->locker, DB_LOCK_UPGRADE, &dbc->lock_dbt, DB_LOCK_WRITE, - &dbc->mylock)) != 0) - return (EAGAIN); - - /* - * If we don't already have the page locked, get it and delete the - * items. - */ - if ((h == NULL || h->pgno != pgno)) { - if ((ret = __bam_lget(dbc, 0, pgno, DB_LOCK_WRITE, &lock)) != 0) - return (ret); - if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0) - return (ret); - local_page = 1; - } else - local_page = 0; - - /* - * If we're deleting a duplicate entry and there are other duplicate - * entries remaining, call the common code to do the work and fix up - * the parent page as necessary. Otherwise, do a normal btree delete. - * - * There are 5 possible cases: - * - * 1. It's not a duplicate item: do a normal btree delete. - * 2. It's a duplicate item: - * 2a: We delete an item from a page of duplicates, but there are - * more items on the page. - * 2b: We delete the last item from a page of duplicates, deleting - * the last duplicate. - * 2c: We delete the last item from a page of duplicates, but there - * is a previous page of duplicates. - * 2d: We delete the last item from a page of duplicates, but there - * is a following page of duplicates. - * - * In the case of: - * - * 1: There's nothing further to do. - * 2a: There's nothing further to do. - * 2b: Do the normal btree delete instead of a duplicate delete, as - * that deletes both the duplicate chain and the parent page's - * entry. - * 2c: There's nothing further to do. - * 2d: Delete the duplicate, and update the parent page's entry. - */ - if (TYPE(h) == P_DUPLICATE) { - pgno = PGNO(h); - prev_pgno = PREV_PGNO(h); - next_pgno = NEXT_PGNO(h); - - if (NUM_ENT(h) == 1 && - prev_pgno == PGNO_INVALID && next_pgno == PGNO_INVALID) - cmd = DELETE_PAGE; - else { - cmd = DELETE_ITEM; - - /* Delete the duplicate. */ - if ((ret = __db_drem(dbc, &h, indx, __bam_free)) != 0) - goto err; - - /* - * 2a: h != NULL, h->pgno == pgno - * 2b: We don't reach this clause, as the above test - * was true. - * 2c: h == NULL, prev_pgno != PGNO_INVALID - * 2d: h != NULL, next_pgno != PGNO_INVALID - * - * Test for 2a and 2c: if we didn't empty the current - * page or there was a previous page of duplicates, we - * don't need to touch the parent page. - */ - if ((h != NULL && pgno == h->pgno) || - prev_pgno != PGNO_INVALID) - cmd = NOTHING_FURTHER; - } - - /* - * Release any page we're holding and its lock. - * - * !!! - * If there is no subsequent page in the duplicate chain, then - * __db_drem will have put page "h" and set it to NULL. - */ - if (local_page) { - if (h != NULL) - (void)memp_fput(dbp->mpf, h, 0); - (void)__BT_TLPUT(dbc, lock); - local_page = 0; - } - - if (cmd == NOTHING_FURTHER) - goto done; - - /* Acquire the parent page and switch the index to its entry. */ - if ((ret = - __bam_lget(dbc, 0, cp->pgno, DB_LOCK_WRITE, &lock)) != 0) - goto err; - if ((ret = memp_fget(dbp->mpf, &cp->pgno, 0, &h)) != 0) { - (void)__BT_TLPUT(dbc, lock); - goto err; - } - local_page = 1; - indx = cp->indx; - - if (cmd == DELETE_PAGE) - goto btd; - - /* - * Copy, delete, update, add-back the parent page's data entry. - * - * XXX - * This may be a performance/logging problem. We should add a - * log message which simply logs/updates a random set of bytes - * on a page, and use it instead of doing a delete/add pair. - */ - indx += O_INDX; - bo = *GET_BOVERFLOW(h, indx); - (void)__db_ditem(dbc, h, indx, BOVERFLOW_SIZE); - bo.pgno = next_pgno; - memset(&dbt, 0, sizeof(dbt)); - dbt.data = &bo; - dbt.size = BOVERFLOW_SIZE; - (void)__db_pitem(dbc, h, indx, BOVERFLOW_SIZE, &dbt, NULL); - (void)memp_fset(dbp->mpf, h, DB_MPOOL_DIRTY); - goto done; - } - -btd: /* - * If the page is going to be emptied, delete it. To delete a leaf - * page we need a copy of a key from the page. We use the 0th page - * index since it's the last key that the page held. - * - * We malloc the page information instead of using the return key/data - * memory because we've already set them -- the reason we've already - * set them is because we're (potentially) about to do a reverse split, - * which would make our saved page information useless. - * - * !!! - * The following operations to delete a page might deadlock. I think - * that's OK. The problem is if we're deleting an item because we're - * closing cursors because we've already deadlocked and want to call - * txn_abort(). If we fail due to deadlock, we leave a locked empty - * page in the tree, which won't be empty long because we're going to - * undo the delete. - */ - if (NUM_ENT(h) == 2 && h->pgno != PGNO_ROOT) { - memset(&dbt, 0, sizeof(DBT)); - dbt.flags = DB_DBT_MALLOC | DB_DBT_INTERNAL; - if ((ret = __db_ret(dbp, h, 0, &dbt, NULL, NULL)) != 0) - goto err; - delete_page = 1; - } - - /* - * Do a normal btree delete. - * - * !!! - * Delete the key item first, otherwise the duplicate checks in - * __bam_ditem() won't work! - */ - if ((ret = __bam_ditem(dbc, h, indx)) != 0) - goto err; - if ((ret = __bam_ditem(dbc, h, indx)) != 0) - goto err; - - /* Discard any remaining locks/pages. */ - if (local_page) { - (void)memp_fput(dbp->mpf, h, 0); - (void)__BT_TLPUT(dbc, lock); - local_page = 0; - } - - /* Delete the page if it was emptied. */ - if (delete_page) - ret = __bam_dpage(dbc, &dbt); - -err: -done: if (delete_page) - __os_free(dbt.data, dbt.size); - - if (local_page) { - /* - * It's possible for h to be NULL, as __db_drem may have - * been relinking pages by the time that it deadlocked. - */ - if (h != NULL) - (void)memp_fput(dbp->mpf, h, 0); - (void)__BT_TLPUT(dbc, lock); - } - - if (F_ISSET(dbp, DB_AM_CDB) && F_ISSET(dbc, DBC_RMW)) - (void)__lock_downgrade(dbp->dbenv->lk_info, dbc->mylock, - DB_LOCK_IWRITE, 0); - - return (ret); -} - -/* - * __bam_c_getstack -- - * Acquire a full stack for a cursor. - */ -static int -__bam_c_getstack(dbc, cp) - DBC *dbc; - CURSOR *cp; -{ - DB *dbp; - DBT dbt; - PAGE *h; - db_pgno_t pgno; - int exact, ret; - - dbp = dbc->dbp; - h = NULL; - memset(&dbt, 0, sizeof(DBT)); - ret = 0; - - /* Get the page with the current item on it. */ - pgno = cp->pgno; - if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0) - return (ret); - - /* Get a copy of a key from the page. */ - dbt.flags = DB_DBT_MALLOC | DB_DBT_INTERNAL; - if ((ret = __db_ret(dbp, h, 0, &dbt, NULL, NULL)) != 0) - goto err; - - /* Get a write-locked stack for that page. */ - exact = 0; - ret = __bam_search(dbc, &dbt, S_KEYFIRST, 1, NULL, &exact); - - /* We no longer need the key or the page. */ -err: if (h != NULL) - (void)memp_fput(dbp->mpf, h, 0); - if (dbt.data != NULL) - __os_free(dbt.data, dbt.size); - return (ret); -} diff --git a/db2/btree/bt_delete.c b/db2/btree/bt_delete.c deleted file mode 100644 index d623bd8..0000000 --- a/db2/btree/bt_delete.c +++ /dev/null @@ -1,589 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994, 1995, 1996 - * Keith Bostic. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994, 1995 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * 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[] = "@(#)bt_delete.c 10.43 (Sleepycat) 12/7/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <string.h> -#endif - -#include "db_int.h" -#include "db_page.h" -#include "btree.h" - -/* - * __bam_delete -- - * Delete the items referenced by a key. - * - * PUBLIC: int __bam_delete __P((DB *, DB_TXN *, DBT *, u_int32_t)); - */ -int -__bam_delete(dbp, txn, key, flags) - DB *dbp; - DB_TXN *txn; - DBT *key; - u_int32_t flags; -{ - DBC *dbc; - DBT data; - u_int32_t f_init, f_next; - int ret, t_ret; - - DB_PANIC_CHECK(dbp); - - /* Check for invalid flags. */ - if ((ret = - __db_delchk(dbp, key, flags, F_ISSET(dbp, DB_AM_RDONLY))) != 0) - return (ret); - - /* Allocate a cursor. */ - if ((ret = dbp->cursor(dbp, txn, &dbc, DB_WRITELOCK)) != 0) - return (ret); - - DEBUG_LWRITE(dbc, txn, "bam_delete", key, NULL, flags); - - /* - * Walk a cursor through the key/data pairs, deleting as we go. Set - * the DB_DBT_USERMEM flag, as this might be a threaded application - * and the flags checking will catch us. We don't actually want the - * keys or data, so request a partial of length 0. - */ - memset(&data, 0, sizeof(data)); - F_SET(&data, DB_DBT_USERMEM | DB_DBT_PARTIAL); - - /* If locking, set read-modify-write flag. */ - f_init = DB_SET; - f_next = DB_NEXT_DUP; - if (dbp->dbenv != NULL && dbp->dbenv->lk_info != NULL) { - f_init |= DB_RMW; - f_next |= DB_RMW; - } - - /* Walk through the set of key/data pairs, deleting as we go. */ - if ((ret = dbc->c_get(dbc, key, &data, f_init)) != 0) - goto err; - for (;;) { - if ((ret = dbc->c_del(dbc, 0)) != 0) - goto err; - if ((ret = dbc->c_get(dbc, key, &data, f_next)) != 0) { - if (ret == DB_NOTFOUND) { - ret = 0; - break; - } - goto err; - } - } - -err: /* Discard the cursor. */ - if ((t_ret = dbc->c_close(dbc)) != 0 && - (ret == 0 || ret == DB_NOTFOUND)) - ret = t_ret; - - return (ret); -} - -/* - * __bam_ditem -- - * Delete one or more entries from a page. - * - * PUBLIC: int __bam_ditem __P((DBC *, PAGE *, u_int32_t)); - */ -int -__bam_ditem(dbc, h, indx) - DBC *dbc; - PAGE *h; - u_int32_t indx; -{ - BINTERNAL *bi; - BKEYDATA *bk; - BOVERFLOW *bo; - DB *dbp; - u_int32_t nbytes; - int ret; - - dbp = dbc->dbp; - - switch (TYPE(h)) { - case P_IBTREE: - bi = GET_BINTERNAL(h, indx); - switch (B_TYPE(bi->type)) { - case B_DUPLICATE: - case B_OVERFLOW: - nbytes = BINTERNAL_SIZE(bi->len); - bo = (BOVERFLOW *)bi->data; - goto offpage; - case B_KEYDATA: - nbytes = BINTERNAL_SIZE(bi->len); - break; - default: - return (__db_pgfmt(dbp, h->pgno)); - } - break; - case P_IRECNO: - nbytes = RINTERNAL_SIZE; - break; - case P_LBTREE: - /* - * If it's a duplicate key, discard the index and don't touch - * the actual page item. - * - * XXX - * This works because no data item can have an index matching - * any other index so even if the data item is in a key "slot", - * it won't match any other index. - */ - if ((indx % 2) == 0) { - /* - * Check for a duplicate after us on the page. NOTE: - * we have to delete the key item before deleting the - * data item, otherwise the "indx + P_INDX" calculation - * won't work! - */ - if (indx + P_INDX < (u_int32_t)NUM_ENT(h) && - h->inp[indx] == h->inp[indx + P_INDX]) - return (__bam_adjindx(dbc, - h, indx, indx + O_INDX, 0)); - /* - * Check for a duplicate before us on the page. It - * doesn't matter if we delete the key item before or - * after the data item for the purposes of this one. - */ - if (indx > 0 && h->inp[indx] == h->inp[indx - P_INDX]) - return (__bam_adjindx(dbc, - h, indx, indx - P_INDX, 0)); - } - /* FALLTHROUGH */ - case P_LRECNO: - bk = GET_BKEYDATA(h, indx); - switch (B_TYPE(bk->type)) { - case B_DUPLICATE: - case B_OVERFLOW: - nbytes = BOVERFLOW_SIZE; - bo = GET_BOVERFLOW(h, indx); - -offpage: /* Delete duplicate/offpage chains. */ - if (B_TYPE(bo->type) == B_DUPLICATE) { - if ((ret = - __db_ddup(dbc, bo->pgno, __bam_free)) != 0) - return (ret); - } else - if ((ret = - __db_doff(dbc, bo->pgno, __bam_free)) != 0) - return (ret); - break; - case B_KEYDATA: - nbytes = BKEYDATA_SIZE(bk->len); - break; - default: - return (__db_pgfmt(dbp, h->pgno)); - } - break; - default: - return (__db_pgfmt(dbp, h->pgno)); - } - - /* Delete the item. */ - if ((ret = __db_ditem(dbc, h, indx, nbytes)) != 0) - return (ret); - - /* Mark the page dirty. */ - return (memp_fset(dbp->mpf, h, DB_MPOOL_DIRTY)); -} - -/* - * __bam_adjindx -- - * Adjust an index on the page. - * - * PUBLIC: int __bam_adjindx __P((DBC *, PAGE *, u_int32_t, u_int32_t, int)); - */ -int -__bam_adjindx(dbc, h, indx, indx_copy, is_insert) - DBC *dbc; - PAGE *h; - u_int32_t indx, indx_copy; - int is_insert; -{ - DB *dbp; - db_indx_t copy; - int ret; - - dbp = dbc->dbp; - - /* Log the change. */ - if (DB_LOGGING(dbc) && - (ret = __bam_adj_log(dbp->dbenv->lg_info, dbc->txn, &LSN(h), - 0, dbp->log_fileid, PGNO(h), &LSN(h), indx, indx_copy, - (u_int32_t)is_insert)) != 0) - return (ret); - - if (is_insert) { - copy = h->inp[indx_copy]; - if (indx != NUM_ENT(h)) - memmove(&h->inp[indx + O_INDX], &h->inp[indx], - sizeof(db_indx_t) * (NUM_ENT(h) - indx)); - h->inp[indx] = copy; - ++NUM_ENT(h); - } else { - --NUM_ENT(h); - if (indx != NUM_ENT(h)) - memmove(&h->inp[indx], &h->inp[indx + O_INDX], - sizeof(db_indx_t) * (NUM_ENT(h) - indx)); - } - - /* Mark the page dirty. */ - ret = memp_fset(dbp->mpf, h, DB_MPOOL_DIRTY); - - /* Adjust the cursors. */ - __bam_ca_di(dbp, h->pgno, indx, is_insert ? 1 : -1); - return (0); -} - -/* - * __bam_dpage -- - * Delete a page from the tree. - * - * PUBLIC: int __bam_dpage __P((DBC *, const DBT *)); - */ -int -__bam_dpage(dbc, key) - DBC *dbc; - const DBT *key; -{ - CURSOR *cp; - DB *dbp; - DB_LOCK lock; - PAGE *h; - db_pgno_t pgno; - int level; /* !!!: has to hold number of tree levels. */ - int exact, ret; - - dbp = dbc->dbp; - cp = dbc->internal; - ret = 0; - - /* - * The locking protocol is that we acquire locks by walking down the - * tree, to avoid the obvious deadlocks. - * - * Call __bam_search to reacquire the empty leaf page, but this time - * get both the leaf page and it's parent, locked. Walk back up the - * tree, until we have the top pair of pages that we want to delete. - * Once we have the top page that we want to delete locked, lock the - * underlying pages and check to make sure they're still empty. If - * they are, delete them. - */ - for (level = LEAFLEVEL;; ++level) { - /* Acquire a page and its parent, locked. */ - if ((ret = - __bam_search(dbc, key, S_WRPAIR, level, NULL, &exact)) != 0) - return (ret); - - /* - * If we reach the root or the page isn't going to be empty - * when we delete one record, quit. - */ - h = cp->csp[-1].page; - if (h->pgno == PGNO_ROOT || NUM_ENT(h) != 1) - break; - - /* Release the two locked pages. */ - (void)memp_fput(dbp->mpf, cp->csp[-1].page, 0); - (void)__BT_TLPUT(dbc, cp->csp[-1].lock); - (void)memp_fput(dbp->mpf, cp->csp[0].page, 0); - (void)__BT_TLPUT(dbc, cp->csp[0].lock); - } - - /* - * Leave the stack pointer one after the last entry, we may be about - * to push more items on the stack. - */ - ++cp->csp; - - /* - * cp->csp[-2].page is the top page, which we're not going to delete, - * and cp->csp[-1].page is the first page we are going to delete. - * - * Walk down the chain, acquiring the rest of the pages until we've - * retrieved the leaf page. If we find any pages that aren't going - * to be emptied by the delete, someone else added something while we - * were walking the tree, and we discontinue the delete. - */ - for (h = cp->csp[-1].page;;) { - if (ISLEAF(h)) { - if (NUM_ENT(h) != 0) - goto release; - break; - } else - if (NUM_ENT(h) != 1) - goto release; - - /* - * Get the next page, write lock it and push it onto the stack. - * We know it's index 0, because it can only have one element. - */ - pgno = TYPE(h) == P_IBTREE ? - GET_BINTERNAL(h, 0)->pgno : GET_RINTERNAL(h, 0)->pgno; - - if ((ret = __bam_lget(dbc, 0, pgno, DB_LOCK_WRITE, &lock)) != 0) - goto release; - if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0) - goto release; - BT_STK_PUSH(cp, h, 0, lock, ret); - } - - /* Adjust back to reference the last page on the stack. */ - BT_STK_POP(cp); - - /* Delete the pages. */ - return (__bam_dpages(dbc)); - -release: - /* Adjust back to reference the last page on the stack. */ - BT_STK_POP(cp); - - /* Discard any locked pages and return. */ - __bam_stkrel(dbc, 0); - - return (ret); -} - -/* - * __bam_dpages -- - * Delete a set of locked pages. - * - * PUBLIC: int __bam_dpages __P((DBC *)); - */ -int -__bam_dpages(dbc) - DBC *dbc; -{ - CURSOR *cp; - DB *dbp; - DBT a, b; - DB_LOCK c_lock, p_lock; - EPG *epg; - PAGE *child, *parent; - db_indx_t nitems; - db_pgno_t pgno; - db_recno_t rcnt; - int done, ret; - - dbp = dbc->dbp; - cp = dbc->internal; - epg = cp->sp; - - /* - * !!! - * There is an interesting deadlock situation here. We have to relink - * the leaf page chain around the leaf page being deleted. Consider - * a cursor walking through the leaf pages, that has the previous page - * read-locked and is waiting on a lock for the page we're deleting. - * It will deadlock here. This is a problem, because if our process is - * selected to resolve the deadlock, we'll leave an empty leaf page - * that we can never again access by walking down the tree. So, before - * we unlink the subtree, we relink the leaf page chain. - */ - if ((ret = __db_relink(dbc, DB_REM_PAGE, cp->csp->page, NULL, 1)) != 0) - goto release; - - /* - * We have the entire stack of deletable pages locked. - * - * Delete the highest page in the tree's reference to the underlying - * stack of pages. Then, release that page, letting the rest of the - * tree get back to business. - */ - if ((ret = __bam_ditem(dbc, epg->page, epg->indx)) != 0) { -release: (void)__bam_stkrel(dbc, 0); - return (ret); - } - - pgno = epg->page->pgno; - nitems = NUM_ENT(epg->page); - - (void)memp_fput(dbp->mpf, epg->page, 0); - (void)__BT_TLPUT(dbc, epg->lock); - - /* - * Free the rest of the stack of pages. - * - * !!! - * Don't bother checking for errors. We've unlinked the subtree from - * the tree, and there's no possibility of recovery outside of doing - * TXN rollback. - */ - while (++epg <= cp->csp) { - /* - * Delete page entries so they will be restored as part of - * recovery. - */ - if (NUM_ENT(epg->page) != 0) - (void)__bam_ditem(dbc, epg->page, epg->indx); - - (void)__bam_free(dbc, epg->page); - (void)__BT_TLPUT(dbc, epg->lock); - } - BT_STK_CLR(cp); - - /* - * Try and collapse the tree a level -- this is only applicable - * if we've deleted the next-to-last element from the root page. - * - * There are two cases when collapsing a tree. - * - * If we've just deleted the last item from the root page, there is no - * further work to be done. The code above has emptied the root page - * and freed all pages below it. - */ - if (pgno != PGNO_ROOT || nitems != 1) - return (0); - - /* - * If we just deleted the next-to-last item from the root page, the - * tree can collapse one or more levels. While there remains only a - * single item on the root page, write lock the last page referenced - * by the root page and copy it over the root page. If we can't get a - * write lock, that's okay, the tree just stays deeper than we'd like. - */ - for (done = 0; !done;) { - /* Initialize. */ - parent = child = NULL; - p_lock = c_lock = LOCK_INVALID; - - /* Lock the root. */ - pgno = PGNO_ROOT; - if ((ret = - __bam_lget(dbc, 0, pgno, DB_LOCK_WRITE, &p_lock)) != 0) - goto stop; - if ((ret = memp_fget(dbp->mpf, &pgno, 0, &parent)) != 0) - goto stop; - - if (NUM_ENT(parent) != 1 || - (TYPE(parent) != P_IBTREE && TYPE(parent) != P_IRECNO)) - goto stop; - - pgno = TYPE(parent) == P_IBTREE ? - GET_BINTERNAL(parent, 0)->pgno : - GET_RINTERNAL(parent, 0)->pgno; - - /* Lock the child page. */ - if ((ret = - __bam_lget(dbc, 0, pgno, DB_LOCK_WRITE, &c_lock)) != 0) - goto stop; - if ((ret = memp_fget(dbp->mpf, &pgno, 0, &child)) != 0) - goto stop; - - /* Log the change. */ - if (DB_LOGGING(dbc)) { - memset(&a, 0, sizeof(a)); - a.data = child; - a.size = dbp->pgsize; - memset(&b, 0, sizeof(b)); - b.data = P_ENTRY(parent, 0); - b.size = BINTERNAL_SIZE(((BINTERNAL *)b.data)->len); - __bam_rsplit_log(dbp->dbenv->lg_info, dbc->txn, - &child->lsn, 0, dbp->log_fileid, child->pgno, &a, - RE_NREC(parent), &b, &parent->lsn); - } - - /* - * Make the switch. - * - * One fixup -- if the tree has record numbers and we're not - * converting to a leaf page, we have to preserve the total - * record count. Note that we are about to overwrite everything - * on the parent, including its LSN. This is actually OK, - * because the above log message, which describes this update, - * stores its LSN on the child page. When the child is copied - * to the parent, the correct LSN is going to copied into - * place in the parent. - */ - COMPQUIET(rcnt, 0); - if (TYPE(child) == P_IRECNO || - (TYPE(child) == P_IBTREE && F_ISSET(dbp, DB_BT_RECNUM))) - rcnt = RE_NREC(parent); - memcpy(parent, child, dbp->pgsize); - parent->pgno = PGNO_ROOT; - if (TYPE(child) == P_IRECNO || - (TYPE(child) == P_IBTREE && F_ISSET(dbp, DB_BT_RECNUM))) - RE_NREC_SET(parent, rcnt); - - /* Mark the pages dirty. */ - memp_fset(dbp->mpf, parent, DB_MPOOL_DIRTY); - memp_fset(dbp->mpf, child, DB_MPOOL_DIRTY); - - /* Adjust the cursors. */ - __bam_ca_rsplit(dbp, child->pgno, PGNO_ROOT); - - /* - * Free the page copied onto the root page and discard its - * lock. (The call to __bam_free() discards our reference - * to the page.) - */ - (void)__bam_free(dbc, child); - child = NULL; - - if (0) { -stop: done = 1; - } - if (p_lock != LOCK_INVALID) - (void)__BT_TLPUT(dbc, p_lock); - if (parent != NULL) - memp_fput(dbp->mpf, parent, 0); - if (c_lock != LOCK_INVALID) - (void)__BT_TLPUT(dbc, c_lock); - if (child != NULL) - memp_fput(dbp->mpf, child, 0); - } - - return (0); -} diff --git a/db2/btree/bt_open.c b/db2/btree/bt_open.c deleted file mode 100644 index a89cfcc..0000000 --- a/db2/btree/bt_open.c +++ /dev/null @@ -1,310 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994, 1995, 1996 - * Keith Bostic. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994, 1995 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * 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[] = "@(#)bt_open.c 10.39 (Sleepycat) 11/21/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <limits.h> -#include <string.h> -#endif - -#include "db_int.h" -#include "db_page.h" -#include "btree.h" - -/* - * __bam_open -- - * Open a btree. - * - * PUBLIC: int __bam_open __P((DB *, DB_INFO *)); - */ -int -__bam_open(dbp, dbinfo) - DB *dbp; - DB_INFO *dbinfo; -{ - BTREE *t; - int ret; - - /* Allocate and initialize the private btree structure. */ - if ((ret = __os_calloc(1, sizeof(BTREE), &t)) != 0) - return (ret); - dbp->internal = t; - - /* - * Intention is to make sure all of the user's selections are okay - * here and then use them without checking. - */ - if (dbinfo == NULL) { - t->bt_minkey = DEFMINKEYPAGE; - t->bt_compare = __bam_defcmp; - t->bt_prefix = __bam_defpfx; - } else { - /* Minimum number of keys per page. */ - if (dbinfo->bt_minkey == 0) - t->bt_minkey = DEFMINKEYPAGE; - else { - if (dbinfo->bt_minkey < 2) - goto einval; - t->bt_minkey = dbinfo->bt_minkey; - } - - /* Maximum number of keys per page. */ - if (dbinfo->bt_maxkey == 0) - t->bt_maxkey = 0; - else { - if (dbinfo->bt_maxkey < 1) - goto einval; - t->bt_maxkey = dbinfo->bt_maxkey; - } - - /* - * If no comparison, use default comparison. If no comparison - * and no prefix, use default prefix. (We can't default the - * prefix if the user supplies a comparison routine; shortening - * the keys may break their comparison algorithm. We don't - * permit the user to specify a prefix routine if they didn't - * also specify a comparison routine, they can't know enough - * about our comparison routine to get it right.) - */ - if ((t->bt_compare = dbinfo->bt_compare) == NULL) { - if (dbinfo->bt_prefix != NULL) - goto einval; - t->bt_compare = __bam_defcmp; - t->bt_prefix = __bam_defpfx; - } else - t->bt_prefix = dbinfo->bt_prefix; - } - - /* Initialize the remaining fields/methods of the DB. */ - dbp->am_close = __bam_close; - dbp->del = __bam_delete; - dbp->stat = __bam_stat; - - /* Start up the tree. */ - if ((ret = __bam_read_root(dbp)) != 0) - goto err; - - /* Set the overflow page size. */ - __bam_setovflsize(dbp); - - return (0); - -einval: ret = EINVAL; - -err: __os_free(t, sizeof(BTREE)); - return (ret); -} - -/* - * __bam_close -- - * Close a btree. - * - * PUBLIC: int __bam_close __P((DB *)); - */ -int -__bam_close(dbp) - DB *dbp; -{ - __os_free(dbp->internal, sizeof(BTREE)); - dbp->internal = NULL; - - return (0); -} - -/* - * __bam_setovflsize -- - * - * PUBLIC: void __bam_setovflsize __P((DB *)); - */ -void -__bam_setovflsize(dbp) - DB *dbp; -{ - BTREE *t; - - t = dbp->internal; - - /* - * !!! - * Correction for recno, which doesn't know anything about minimum - * keys per page. - */ - if (t->bt_minkey == 0) - t->bt_minkey = DEFMINKEYPAGE; - - /* - * The btree data structure requires that at least two key/data pairs - * can fit on a page, but other than that there's no fixed requirement. - * Translate the minimum number of items into the bytes a key/data pair - * can use before being placed on an overflow page. We calculate for - * the worst possible alignment by assuming every item requires the - * maximum alignment for padding. - * - * Recno uses the btree bt_ovflsize value -- it's close enough. - */ - t->bt_ovflsize = (dbp->pgsize - P_OVERHEAD) / (t->bt_minkey * P_INDX) - - (BKEYDATA_PSIZE(0) + ALIGN(1, 4)); -} - -/* - * __bam_read_root -- - * Check (and optionally create) a tree. - * - * PUBLIC: int __bam_read_root __P((DB *)); - */ -int -__bam_read_root(dbp) - DB *dbp; -{ - BTMETA *meta; - BTREE *t; - DBC *dbc; - DB_LOCK metalock, rootlock; - PAGE *root; - db_pgno_t pgno; - int ret, t_ret; - - ret = 0; - t = dbp->internal; - - /* Get a cursor. */ - if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0) - return (ret); - - /* Get, and optionally create the metadata page. */ - pgno = PGNO_METADATA; - if ((ret = - __bam_lget(dbc, 0, PGNO_METADATA, DB_LOCK_WRITE, &metalock)) != 0) - goto err; - if ((ret = - memp_fget(dbp->mpf, &pgno, DB_MPOOL_CREATE, (PAGE **)&meta)) != 0) { - (void)__BT_LPUT(dbc, metalock); - goto err; - } - - /* - * If the magic number is correct, we're not creating the tree. - * Correct any fields that may not be right. Note, all of the - * local flags were set by db_open(3). - */ - if (meta->magic != 0) { - t->bt_maxkey = meta->maxkey; - t->bt_minkey = meta->minkey; - - (void)memp_fput(dbp->mpf, (PAGE *)meta, 0); - (void)__BT_LPUT(dbc, metalock); - goto done; - } - - /* Initialize the tree structure metadata information. */ - memset(meta, 0, sizeof(BTMETA)); - ZERO_LSN(meta->lsn); - meta->pgno = PGNO_METADATA; - meta->magic = DB_BTREEMAGIC; - meta->version = DB_BTREEVERSION; - meta->pagesize = dbp->pgsize; - meta->maxkey = t->bt_maxkey; - meta->minkey = t->bt_minkey; - meta->free = PGNO_INVALID; - if (dbp->type == DB_RECNO) - F_SET(meta, BTM_RECNO); - if (F_ISSET(dbp, DB_AM_DUP)) - F_SET(meta, BTM_DUP); - if (F_ISSET(dbp, DB_RE_FIXEDLEN)) - F_SET(meta, BTM_FIXEDLEN); - if (F_ISSET(dbp, DB_BT_RECNUM)) - F_SET(meta, BTM_RECNUM); - if (F_ISSET(dbp, DB_RE_RENUMBER)) - F_SET(meta, BTM_RENUMBER); - memcpy(meta->uid, dbp->fileid, DB_FILE_ID_LEN); - - /* Create and initialize a root page. */ - pgno = PGNO_ROOT; - if ((ret = - __bam_lget(dbc, 0, PGNO_ROOT, DB_LOCK_WRITE, &rootlock)) != 0) - goto err; - if ((ret = memp_fget(dbp->mpf, &pgno, DB_MPOOL_CREATE, &root)) != 0) { - (void)__BT_LPUT(dbc, rootlock); - goto err; - } - P_INIT(root, dbp->pgsize, PGNO_ROOT, PGNO_INVALID, - PGNO_INVALID, 1, dbp->type == DB_RECNO ? P_LRECNO : P_LBTREE); - ZERO_LSN(root->lsn); - - /* Release the metadata and root pages. */ - if ((ret = memp_fput(dbp->mpf, (PAGE *)meta, DB_MPOOL_DIRTY)) != 0) - goto err; - if ((ret = memp_fput(dbp->mpf, root, DB_MPOOL_DIRTY)) != 0) - goto err; - - /* - * Flush the metadata and root pages to disk -- since the user can't - * transaction protect open, the pages have to exist during recovery. - * - * XXX - * It's not useful to return not-yet-flushed here -- convert it to - * an error. - */ - if ((ret = memp_fsync(dbp->mpf)) == DB_INCOMPLETE) - ret = EINVAL; - - /* Release the locks. */ - (void)__BT_LPUT(dbc, metalock); - (void)__BT_LPUT(dbc, rootlock); - -err: -done: if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0) - ret = t_ret; - return (ret); -} diff --git a/db2/btree/bt_page.c b/db2/btree/bt_page.c deleted file mode 100644 index 6ccd68a..0000000 --- a/db2/btree/bt_page.c +++ /dev/null @@ -1,317 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994, 1995, 1996 - * Keith Bostic. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994, 1995 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * 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[] = "@(#)bt_page.c 10.17 (Sleepycat) 1/3/99"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <string.h> -#endif - -#include "db_int.h" -#include "db_page.h" -#include "btree.h" - -/* - * __bam_new -- - * Get a new page, preferably from the freelist. - * - * PUBLIC: int __bam_new __P((DBC *, u_int32_t, PAGE **)); - */ -int -__bam_new(dbc, type, pagepp) - DBC *dbc; - u_int32_t type; - PAGE **pagepp; -{ - BTMETA *meta; - DB *dbp; - DB_LOCK metalock; - PAGE *h; - db_pgno_t pgno; - int ret; - - dbp = dbc->dbp; - meta = NULL; - h = NULL; - metalock = LOCK_INVALID; - - pgno = PGNO_METADATA; - if ((ret = __bam_lget(dbc, 0, pgno, DB_LOCK_WRITE, &metalock)) != 0) - goto err; - if ((ret = memp_fget(dbp->mpf, &pgno, 0, (PAGE **)&meta)) != 0) - goto err; - - if (meta->free == PGNO_INVALID) { - if ((ret = memp_fget(dbp->mpf, &pgno, DB_MPOOL_NEW, &h)) != 0) - goto err; - ZERO_LSN(h->lsn); - h->pgno = pgno; - } else { - pgno = meta->free; - if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0) - goto err; - meta->free = h->next_pgno; - } - - /* Log the change. */ - if (DB_LOGGING(dbc)) { - if ((ret = __bam_pg_alloc_log(dbp->dbenv->lg_info, dbc->txn, - &meta->lsn, 0, dbp->log_fileid, &meta->lsn, &h->lsn, - h->pgno, (u_int32_t)type, meta->free)) != 0) - goto err; - LSN(h) = LSN(meta); - } - - (void)memp_fput(dbp->mpf, (PAGE *)meta, DB_MPOOL_DIRTY); - (void)__BT_TLPUT(dbc, metalock); - - P_INIT(h, dbp->pgsize, h->pgno, PGNO_INVALID, PGNO_INVALID, 0, type); - *pagepp = h; - return (0); - -err: if (h != NULL) - (void)memp_fput(dbp->mpf, h, 0); - if (meta != NULL) - (void)memp_fput(dbp->mpf, meta, 0); - if (metalock != LOCK_INVALID) - (void)__BT_TLPUT(dbc, metalock); - return (ret); -} - -/* - * __bam_lput -- - * The standard lock put call. - * - * PUBLIC: int __bam_lput __P((DBC *, DB_LOCK)); - */ -int -__bam_lput(dbc, lock) - DBC *dbc; - DB_LOCK lock; -{ - return (__BT_LPUT(dbc, lock)); -} - -/* - * __bam_free -- - * Add a page to the head of the freelist. - * - * PUBLIC: int __bam_free __P((DBC *, PAGE *)); - */ -int -__bam_free(dbc, h) - DBC *dbc; - PAGE *h; -{ - BTMETA *meta; - DB *dbp; - DBT ldbt; - DB_LOCK metalock; - db_pgno_t pgno; - u_int32_t dirty_flag; - int ret, t_ret; - - dbp = dbc->dbp; - - /* - * Retrieve the metadata page and insert the page at the head of - * the free list. If either the lock get or page get routines - * fail, then we need to put the page with which we were called - * back because our caller assumes we take care of it. - */ - dirty_flag = 0; - pgno = PGNO_METADATA; - if ((ret = __bam_lget(dbc, 0, pgno, DB_LOCK_WRITE, &metalock)) != 0) - goto err; - if ((ret = memp_fget(dbp->mpf, &pgno, 0, (PAGE **)&meta)) != 0) { - (void)__BT_TLPUT(dbc, metalock); - goto err; - } - - /* Log the change. */ - if (DB_LOGGING(dbc)) { - memset(&ldbt, 0, sizeof(ldbt)); - ldbt.data = h; - ldbt.size = P_OVERHEAD; - if ((ret = __bam_pg_free_log(dbp->dbenv->lg_info, - dbc->txn, &meta->lsn, 0, dbp->log_fileid, h->pgno, - &meta->lsn, &ldbt, meta->free)) != 0) { - (void)memp_fput(dbp->mpf, (PAGE *)meta, 0); - (void)__BT_TLPUT(dbc, metalock); - return (ret); - } - LSN(h) = LSN(meta); - } - - /* - * The page should have nothing interesting on it, re-initialize it, - * leaving only the page number and the LSN. - */ -#ifdef DIAGNOSTIC - { db_pgno_t __pgno; DB_LSN __lsn; - __pgno = h->pgno; - __lsn = h->lsn; - memset(h, 0xdb, dbp->pgsize); - h->pgno = __pgno; - h->lsn = __lsn; - } -#endif - P_INIT(h, dbp->pgsize, h->pgno, PGNO_INVALID, meta->free, 0, P_INVALID); - - /* Link the page on the metadata free list. */ - meta->free = h->pgno; - - /* Discard the metadata page. */ - ret = memp_fput(dbp->mpf, (PAGE *)meta, DB_MPOOL_DIRTY); - if ((t_ret = __BT_TLPUT(dbc, metalock)) != 0) - ret = t_ret; - - /* Discard the caller's page reference. */ - dirty_flag = DB_MPOOL_DIRTY; -err: if ((t_ret = memp_fput(dbp->mpf, h, dirty_flag)) != 0 && ret == 0) - ret = t_ret; - - /* - * XXX - * We have to unlock the caller's page in the caller! - */ - return (ret); -} - -#ifdef DEBUG -/* - * __bam_lt -- - * Print out the list of locks currently held by a cursor. - * - * PUBLIC: int __bam_lt __P((DBC *)); - */ -int -__bam_lt(dbc) - DBC *dbc; -{ - DB *dbp; - DB_LOCKREQ req; - - dbp = dbc->dbp; - if (F_ISSET(dbp, DB_AM_LOCKING)) { - req.op = DB_LOCK_DUMP; - lock_vec(dbp->dbenv->lk_info, dbc->locker, 0, &req, 1, NULL); - } - return (0); -} -#endif - -/* - * __bam_lget -- - * The standard lock get call. - * - * PUBLIC: int __bam_lget - * PUBLIC: __P((DBC *, int, db_pgno_t, db_lockmode_t, DB_LOCK *)); - */ -int -__bam_lget(dbc, do_couple, pgno, mode, lockp) - DBC *dbc; - int do_couple; - db_pgno_t pgno; - db_lockmode_t mode; - DB_LOCK *lockp; -{ - DB *dbp; - DB_LOCKREQ couple[2]; - int ret; - - dbp = dbc->dbp; - - if (!F_ISSET(dbp, DB_AM_LOCKING)) { - *lockp = LOCK_INVALID; - return (0); - } - - dbc->lock.pgno = pgno; - - /* - * If the object not currently locked, acquire the lock and return, - * otherwise, lock couple. If we fail and it's not a system error, - * convert to EAGAIN. - */ - if (do_couple) { - couple[0].op = DB_LOCK_GET; - couple[0].obj = &dbc->lock_dbt; - couple[0].mode = mode; - couple[1].op = DB_LOCK_PUT; - couple[1].lock = *lockp; - - if (dbc->txn == NULL) - ret = lock_vec(dbp->dbenv->lk_info, - dbc->locker, 0, couple, 2, NULL); - else - ret = lock_tvec(dbp->dbenv->lk_info, - dbc->txn, 0, couple, 2, NULL); - if (ret != 0) { - /* If we fail, discard the lock we held. */ - __BT_LPUT(dbc, *lockp); - - return (ret < 0 ? EAGAIN : ret); - } - *lockp = couple[0].lock; - } else { - if (dbc->txn == NULL) - ret = lock_get(dbp->dbenv->lk_info, - dbc->locker, 0, &dbc->lock_dbt, mode, lockp); - else - ret = lock_tget(dbp->dbenv->lk_info, - dbc->txn, 0, &dbc->lock_dbt, mode, lockp); - return (ret < 0 ? EAGAIN : ret); - } - return (0); -} diff --git a/db2/btree/bt_put.c b/db2/btree/bt_put.c deleted file mode 100644 index 0d7a698..0000000 --- a/db2/btree/bt_put.c +++ /dev/null @@ -1,831 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994, 1995, 1996 - * Keith Bostic. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994, 1995 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * 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[] = "@(#)bt_put.c 10.54 (Sleepycat) 12/6/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <string.h> -#endif - -#include "db_int.h" -#include "db_page.h" -#include "btree.h" - -static int __bam_fixed __P((DBC *, DBT *)); -static int __bam_ndup __P((DBC *, PAGE *, u_int32_t)); -static int __bam_ovput __P((DBC *, PAGE *, u_int32_t, DBT *)); -static int __bam_partial __P((DBC *, - DBT *, PAGE *, u_int32_t, u_int32_t, u_int32_t)); -static u_int32_t __bam_partsize __P((DBT *, PAGE *, u_int32_t)); - -/* - * __bam_iitem -- - * Insert an item into the tree. - * - * PUBLIC: int __bam_iitem __P((DBC *, - * PUBLIC: PAGE **, db_indx_t *, DBT *, DBT *, u_int32_t, u_int32_t)); - */ -int -__bam_iitem(dbc, hp, indxp, key, data, op, flags) - DBC *dbc; - PAGE **hp; - db_indx_t *indxp; - DBT *key, *data; - u_int32_t op, flags; -{ - BTREE *t; - BKEYDATA *bk; - DB *dbp; - DBT tdbt; - PAGE *h; - db_indx_t indx, nbytes; - u_int32_t data_size, have_bytes, need_bytes, needed; - int bigkey, bigdata, dupadjust, replace, ret; - - COMPQUIET(bk, NULL); - - dbp = dbc->dbp; - t = dbp->internal; - h = *hp; - indx = *indxp; - dupadjust = replace = 0; - - /* - * If it's a page of duplicates, call the common code to do the work. - * - * !!! - * Here's where the hp and indxp are important. The duplicate code - * may decide to rework/rearrange the pages and indices we're using, - * so the caller must understand that the page stack may change. - */ - if (TYPE(h) == P_DUPLICATE) { - /* Adjust the index for the new item if it's a DB_AFTER op. */ - if (op == DB_AFTER) - ++*indxp; - - /* Remove the current item if it's a DB_CURRENT op. */ - if (op == DB_CURRENT) { - bk = GET_BKEYDATA(*hp, *indxp); - switch (B_TYPE(bk->type)) { - case B_KEYDATA: - nbytes = BKEYDATA_SIZE(bk->len); - break; - case B_OVERFLOW: - nbytes = BOVERFLOW_SIZE; - break; - default: - return (__db_pgfmt(dbp, h->pgno)); - } - if ((ret = __db_ditem(dbc, *hp, *indxp, nbytes)) != 0) - return (ret); - } - - /* Put the new/replacement item onto the page. */ - if ((ret = __db_dput(dbc, data, hp, indxp, __bam_new)) != 0) - return (ret); - - goto done; - } - - /* Handle fixed-length records: build the real record. */ - if (F_ISSET(dbp, DB_RE_FIXEDLEN) && data->size != t->recno->re_len) { - tdbt = *data; - if ((ret = __bam_fixed(dbc, &tdbt)) != 0) - return (ret); - data = &tdbt; - } - - /* - * Figure out how much space the data will take, including if it's a - * partial record. If either of the key or data items won't fit on - * a page, we'll have to store them on overflow pages. - */ - bigkey = LF_ISSET(BI_NEWKEY) && key->size > t->bt_ovflsize; - data_size = F_ISSET(data, DB_DBT_PARTIAL) ? - __bam_partsize(data, h, indx) : data->size; - bigdata = data_size > t->bt_ovflsize; - - needed = 0; - if (LF_ISSET(BI_NEWKEY)) { - /* If BI_NEWKEY is set we're adding a new key and data pair. */ - if (bigkey) - needed += BOVERFLOW_PSIZE; - else - needed += BKEYDATA_PSIZE(key->size); - if (bigdata) - needed += BOVERFLOW_PSIZE; - else - needed += BKEYDATA_PSIZE(data_size); - } else { - /* - * We're either overwriting the data item of a key/data pair - * or we're adding the data item only, i.e. a new duplicate. - */ - if (op == DB_CURRENT) { - bk = GET_BKEYDATA(h, - indx + (TYPE(h) == P_LBTREE ? O_INDX : 0)); - if (B_TYPE(bk->type) == B_KEYDATA) - have_bytes = BKEYDATA_PSIZE(bk->len); - else - have_bytes = BOVERFLOW_PSIZE; - need_bytes = 0; - } else { - have_bytes = 0; - need_bytes = sizeof(db_indx_t); - } - if (bigdata) - need_bytes += BOVERFLOW_PSIZE; - else - need_bytes += BKEYDATA_PSIZE(data_size); - - if (have_bytes < need_bytes) - needed += need_bytes - have_bytes; - } - - /* - * If there's not enough room, or the user has put a ceiling on the - * number of keys permitted in the page, split the page. - * - * XXX - * The t->bt_maxkey test here may be insufficient -- do we have to - * check in the btree split code, so we don't undo it there!?!? - */ - if (P_FREESPACE(h) < needed || - (t->bt_maxkey != 0 && NUM_ENT(h) > t->bt_maxkey)) - return (DB_NEEDSPLIT); - - /* Handle partial puts: build the real record. */ - if (F_ISSET(data, DB_DBT_PARTIAL)) { - tdbt = *data; - if ((ret = __bam_partial(dbc, - &tdbt, h, indx, data_size, flags)) != 0) - return (ret); - data = &tdbt; - } - - /* - * The code breaks it up into six cases: - * - * 1. Append a new key/data pair. - * 2. Insert a new key/data pair. - * 3. Append a new data item (a new duplicate). - * 4. Insert a new data item (a new duplicate). - * 5. Overflow item: delete and re-add the data item. - * 6. Replace the data item. - */ - if (LF_ISSET(BI_NEWKEY)) { - switch (op) { - case DB_AFTER: /* 1. Append a new key/data pair. */ - indx += 2; - *indxp += 2; - break; - case DB_BEFORE: /* 2. Insert a new key/data pair. */ - break; - default: - return (EINVAL); - } - - /* Add the key. */ - if (bigkey) { - if ((ret = __bam_ovput(dbc, h, indx, key)) != 0) - return (ret); - } else - if ((ret = __db_pitem(dbc, h, indx, - BKEYDATA_SIZE(key->size), NULL, key)) != 0) - return (ret); - ++indx; - } else { - switch (op) { - case DB_AFTER: /* 3. Append a new data item. */ - if (TYPE(h) == P_LBTREE) { - /* - * Adjust the cursor and copy in the key for - * the duplicate. - */ - if ((ret = __bam_adjindx(dbc, - h, indx + P_INDX, indx, 1)) != 0) - return (ret); - - indx += 3; - dupadjust = 1; - - *indxp += 2; - } else { - ++indx; - __bam_ca_di(dbp, h->pgno, indx, 1); - - *indxp += 1; - } - break; - case DB_BEFORE: /* 4. Insert a new data item. */ - if (TYPE(h) == P_LBTREE) { - /* - * Adjust the cursor and copy in the key for - * the duplicate. - */ - if ((ret = - __bam_adjindx(dbc, h, indx, indx, 1)) != 0) - return (ret); - - ++indx; - dupadjust = 1; - } else - __bam_ca_di(dbp, h->pgno, indx, 1); - break; - case DB_CURRENT: - if (TYPE(h) == P_LBTREE) - ++indx; - - /* - * 5. Delete/re-add the data item. - * - * If we're dealing with offpage items, we have to - * delete and then re-add the item. - */ - if (bigdata || B_TYPE(bk->type) != B_KEYDATA) { - if ((ret = __bam_ditem(dbc, h, indx)) != 0) - return (ret); - break; - } - - /* 6. Replace the data item. */ - replace = 1; - break; - default: - return (EINVAL); - } - } - - /* Add the data. */ - if (bigdata) { - if ((ret = __bam_ovput(dbc, h, indx, data)) != 0) - return (ret); - } else { - BKEYDATA __bk; - DBT __hdr; - - if (LF_ISSET(BI_DELETED)) { - B_TSET(__bk.type, B_KEYDATA, 1); - __bk.len = data->size; - __hdr.data = &__bk; - __hdr.size = SSZA(BKEYDATA, data); - ret = __db_pitem(dbc, h, indx, - BKEYDATA_SIZE(data->size), &__hdr, data); - } else if (replace) - ret = __bam_ritem(dbc, h, indx, data); - else - ret = __db_pitem(dbc, h, indx, - BKEYDATA_SIZE(data->size), NULL, data); - if (ret != 0) - return (ret); - } - - if ((ret = memp_fset(dbp->mpf, h, DB_MPOOL_DIRTY)) != 0) - return (ret); - - /* - * If the page is at least 50% full, and we added a duplicate, see if - * that set of duplicates takes up at least 25% of the space. If it - * does, move it off onto its own page. - */ - if (dupadjust && P_FREESPACE(h) <= dbp->pgsize / 2) { - --indx; - if ((ret = __bam_ndup(dbc, h, indx)) != 0) - return (ret); - } - - /* - * If we've changed the record count, update the tree. Record counts - * need to be updated in recno databases and in btree databases where - * we are supporting records. In both cases, adjust the count if the - * operation wasn't performed on the current record or when the caller - * overrides and wants the adjustment made regardless. - */ -done: if (LF_ISSET(BI_DOINCR) || - (op != DB_CURRENT && - (F_ISSET(dbp, DB_BT_RECNUM) || dbp->type == DB_RECNO))) - if ((ret = __bam_adjust(dbc, 1)) != 0) - return (ret); - - /* If we've modified a recno file, set the flag */ - if (t->recno != NULL) - F_SET(t->recno, RECNO_MODIFIED); - - return (ret); -} - -/* - * __bam_partsize -- - * Figure out how much space a partial data item is in total. - */ -static u_int32_t -__bam_partsize(data, h, indx) - DBT *data; - PAGE *h; - u_int32_t indx; -{ - BKEYDATA *bk; - u_int32_t nbytes; - - /* - * Figure out how much total space we'll need. If the record doesn't - * already exist, it's simply the data we're provided. - */ - if (indx >= NUM_ENT(h)) - return (data->doff + data->size); - - /* - * Otherwise, it's the data provided plus any already existing data - * that we're not replacing. - */ - bk = GET_BKEYDATA(h, indx + (TYPE(h) == P_LBTREE ? O_INDX : 0)); - nbytes = - B_TYPE(bk->type) == B_OVERFLOW ? ((BOVERFLOW *)bk)->tlen : bk->len; - - /* - * There are really two cases here: - * - * Case 1: We are replacing some bytes that do not exist (i.e., they - * are past the end of the record). In this case the number of bytes - * we are replacing is irrelevant and all we care about is how many - * bytes we are going to add from offset. So, the new record length - * is going to be the size of the new bytes (size) plus wherever those - * new bytes begin (doff). - * - * Case 2: All the bytes we are replacing exist. Therefore, the new - * size is the oldsize (nbytes) minus the bytes we are replacing (dlen) - * plus the bytes we are adding (size). - */ - if (nbytes < data->doff + data->dlen) /* Case 1 */ - return (data->doff + data->size); - - return (nbytes + data->size - data->dlen); /* Case 2 */ -} - -/* - * OVPUT -- - * Copy an overflow item onto a page. - */ -#undef OVPUT -#define OVPUT(h, indx, bo) do { \ - DBT __hdr; \ - memset(&__hdr, 0, sizeof(__hdr)); \ - __hdr.data = &bo; \ - __hdr.size = BOVERFLOW_SIZE; \ - if ((ret = __db_pitem(dbc, \ - h, indx, BOVERFLOW_SIZE, &__hdr, NULL)) != 0) \ - return (ret); \ -} while (0) - -/* - * __bam_ovput -- - * Build an overflow item and put it on the page. - */ -static int -__bam_ovput(dbc, h, indx, item) - DBC *dbc; - PAGE *h; - u_int32_t indx; - DBT *item; -{ - BOVERFLOW bo; - int ret; - - UMRW(bo.unused1); - B_TSET(bo.type, B_OVERFLOW, 0); - UMRW(bo.unused2); - if ((ret = __db_poff(dbc, item, &bo.pgno, __bam_new)) != 0) - return (ret); - bo.tlen = item->size; - - OVPUT(h, indx, bo); - - return (0); -} - -/* - * __bam_ritem -- - * Replace an item on a page. - * - * PUBLIC: int __bam_ritem __P((DBC *, PAGE *, u_int32_t, DBT *)); - */ -int -__bam_ritem(dbc, h, indx, data) - DBC *dbc; - PAGE *h; - u_int32_t indx; - DBT *data; -{ - BKEYDATA *bk; - DB *dbp; - DBT orig, repl; - db_indx_t cnt, lo, ln, min, off, prefix, suffix; - int32_t nbytes; - int ret; - u_int8_t *p, *t; - - dbp = dbc->dbp; - - /* - * Replace a single item onto a page. The logic figuring out where - * to insert and whether it fits is handled in the caller. All we do - * here is manage the page shuffling. - */ - bk = GET_BKEYDATA(h, indx); - - /* Log the change. */ - if (DB_LOGGING(dbc)) { - /* - * We might as well check to see if the two data items share - * a common prefix and suffix -- it can save us a lot of log - * message if they're large. - */ - min = data->size < bk->len ? data->size : bk->len; - for (prefix = 0, - p = bk->data, t = data->data; - prefix < min && *p == *t; ++prefix, ++p, ++t) - ; - - min -= prefix; - for (suffix = 0, - p = (u_int8_t *)bk->data + bk->len - 1, - t = (u_int8_t *)data->data + data->size - 1; - suffix < min && *p == *t; ++suffix, --p, --t) - ; - - /* We only log the parts of the keys that have changed. */ - orig.data = (u_int8_t *)bk->data + prefix; - orig.size = bk->len - (prefix + suffix); - repl.data = (u_int8_t *)data->data + prefix; - repl.size = data->size - (prefix + suffix); - if ((ret = __bam_repl_log(dbp->dbenv->lg_info, dbc->txn, - &LSN(h), 0, dbp->log_fileid, PGNO(h), &LSN(h), - (u_int32_t)indx, (u_int32_t)B_DISSET(bk->type), - &orig, &repl, (u_int32_t)prefix, (u_int32_t)suffix)) != 0) - return (ret); - } - - /* - * Set references to the first in-use byte on the page and the - * first byte of the item being replaced. - */ - p = (u_int8_t *)h + HOFFSET(h); - t = (u_int8_t *)bk; - - /* - * If the entry is growing in size, shift the beginning of the data - * part of the page down. If the entry is shrinking in size, shift - * the beginning of the data part of the page up. Use memmove(3), - * the regions overlap. - */ - lo = BKEYDATA_SIZE(bk->len); - ln = BKEYDATA_SIZE(data->size); - if (lo != ln) { - nbytes = lo - ln; /* Signed difference. */ - if (p == t) /* First index is fast. */ - h->inp[indx] += nbytes; - else { /* Else, shift the page. */ - memmove(p + nbytes, p, t - p); - - /* Adjust the indices' offsets. */ - off = h->inp[indx]; - for (cnt = 0; cnt < NUM_ENT(h); ++cnt) - if (h->inp[cnt] <= off) - h->inp[cnt] += nbytes; - } - - /* Clean up the page and adjust the item's reference. */ - HOFFSET(h) += nbytes; - t += nbytes; - } - - /* Copy the new item onto the page. */ - bk = (BKEYDATA *)t; - B_TSET(bk->type, B_KEYDATA, 0); - bk->len = data->size; - memcpy(bk->data, data->data, data->size); - - return (0); -} - -/* - * __bam_ndup -- - * Check to see if the duplicate set at indx should have its own page. - * If it should, create it. - */ -static int -__bam_ndup(dbc, h, indx) - DBC *dbc; - PAGE *h; - u_int32_t indx; -{ - BKEYDATA *bk; - BOVERFLOW bo; - DB *dbp; - DBT hdr; - PAGE *cp; - db_indx_t cnt, cpindx, first, sz; - int ret; - - dbp = dbc->dbp; - - while (indx > 0 && h->inp[indx] == h->inp[indx - P_INDX]) - indx -= P_INDX; - for (cnt = 0, sz = 0, first = indx;; ++cnt, indx += P_INDX) { - if (indx >= NUM_ENT(h) || h->inp[first] != h->inp[indx]) - break; - bk = GET_BKEYDATA(h, indx); - sz += B_TYPE(bk->type) == B_KEYDATA ? - BKEYDATA_PSIZE(bk->len) : BOVERFLOW_PSIZE; - bk = GET_BKEYDATA(h, indx + O_INDX); - sz += B_TYPE(bk->type) == B_KEYDATA ? - BKEYDATA_PSIZE(bk->len) : BOVERFLOW_PSIZE; - } - - /* - * If this set of duplicates is using more than 25% of the page, move - * them off. The choice of 25% is a WAG, but it has to be small enough - * that we can always split regardless of the presence of duplicates. - */ - if (sz < dbp->pgsize / 4) - return (0); - - /* Get a new page. */ - if ((ret = __bam_new(dbc, P_DUPLICATE, &cp)) != 0) - return (ret); - - /* - * Move this set of duplicates off the page. First points to the first - * key of the first duplicate key/data pair, cnt is the number of pairs - * we're dealing with. - */ - memset(&hdr, 0, sizeof(hdr)); - for (indx = first + O_INDX, cpindx = 0;; ++cpindx) { - /* Copy the entry to the new page. */ - bk = GET_BKEYDATA(h, indx); - hdr.data = bk; - hdr.size = B_TYPE(bk->type) == B_KEYDATA ? - BKEYDATA_SIZE(bk->len) : BOVERFLOW_SIZE; - if ((ret = - __db_pitem(dbc, cp, cpindx, hdr.size, &hdr, NULL)) != 0) - goto err; - - /* - * Move cursors referencing the old entry to the new entry. - * Done after the page put because __db_pitem() adjusts - * cursors on the new page, and before the delete because - * __db_ditem adjusts cursors on the old page. - */ - __bam_ca_dup(dbp, - PGNO(h), first, indx - O_INDX, PGNO(cp), cpindx); - - /* Delete the data item. */ - if ((ret = __db_ditem(dbc, h, indx, hdr.size)) != 0) - goto err; - - /* Delete all but the first reference to the key. */ - if (--cnt == 0) - break; - if ((ret = __bam_adjindx(dbc, h, indx, first, 0)) != 0) - goto err; - } - - /* Put in a new data item that points to the duplicates page. */ - UMRW(bo.unused1); - B_TSET(bo.type, B_DUPLICATE, 0); - UMRW(bo.unused2); - bo.pgno = cp->pgno; - bo.tlen = 0; - - OVPUT(h, indx, bo); - - return (memp_fput(dbp->mpf, cp, DB_MPOOL_DIRTY)); - -err: (void)__bam_free(dbc, cp); - return (ret); -} - -/* - * __bam_fixed -- - * Build the real record for a fixed length put. - */ -static int -__bam_fixed(dbc, dbt) - DBC *dbc; - DBT *dbt; -{ - DB *dbp; - RECNO *rp; - int ret; - - dbp = dbc->dbp; - rp = ((BTREE *)dbp->internal)->recno; - - /* - * If database contains fixed-length records, and the record is long, - * return EINVAL. - */ - if (dbt->size > rp->re_len) - return (EINVAL); - - /* - * The caller checked to see if it was just right, so we know it's - * short. Pad it out. We use the record data return memory, it's - * only a short-term use. - */ - if (dbc->rdata.ulen < rp->re_len) { - if ((ret = __os_realloc(&dbc->rdata.data, rp->re_len)) != 0) { - dbc->rdata.ulen = 0; - dbc->rdata.data = NULL; - return (ret); - } - dbc->rdata.ulen = rp->re_len; - } - memcpy(dbc->rdata.data, dbt->data, dbt->size); - memset((u_int8_t *)dbc->rdata.data + dbt->size, - rp->re_pad, rp->re_len - dbt->size); - - /* - * Clean up our flags and other information just in case, and - * change the caller's DBT to reference our created record. - */ - dbc->rdata.size = rp->re_len; - dbc->rdata.dlen = 0; - dbc->rdata.doff = 0; - dbc->rdata.flags = 0; - *dbt = dbc->rdata; - - return (0); -} - -/* - * __bam_partial -- - * Build the real record for a partial put. - */ -static int -__bam_partial(dbc, dbt, h, indx, nbytes, flags) - DBC *dbc; - DBT *dbt; - PAGE *h; - u_int32_t indx, nbytes, flags; -{ - BKEYDATA *bk, tbk; - BOVERFLOW *bo; - DB *dbp; - DBT copy; - u_int32_t len, tlen; - u_int8_t *p; - int ret; - - COMPQUIET(bo, NULL); - - dbp = dbc->dbp; - - /* We use the record data return memory, it's only a short-term use. */ - if (dbc->rdata.ulen < nbytes) { - if ((ret = __os_realloc(&dbc->rdata.data, nbytes)) != 0) { - dbc->rdata.ulen = 0; - dbc->rdata.data = NULL; - return (ret); - } - dbc->rdata.ulen = nbytes; - } - - /* - * We use nul bytes for any part of the record that isn't specified; - * get it over with. - */ - memset(dbc->rdata.data, 0, nbytes); - - /* - * In the next clauses, we need to do three things: a) set p to point - * to the place at which to copy the user's data, b) set tlen to the - * total length of the record, not including the bytes contributed by - * the user, and c) copy any valid data from an existing record. - */ - if (LF_ISSET(BI_NEWKEY)) { - tlen = dbt->doff; - p = (u_int8_t *)dbc->rdata.data + dbt->doff; - goto ucopy; - } - - /* Find the current record. */ - if (indx < NUM_ENT(h)) { - bk = GET_BKEYDATA(h, indx + (TYPE(h) == P_LBTREE ? O_INDX : 0)); - bo = (BOVERFLOW *)bk; - } else { - bk = &tbk; - B_TSET(bk->type, B_KEYDATA, 0); - bk->len = 0; - } - if (B_TYPE(bk->type) == B_OVERFLOW) { - /* - * In the case of an overflow record, we shift things around - * in the current record rather than allocate a separate copy. - */ - memset(©, 0, sizeof(copy)); - if ((ret = __db_goff(dbp, ©, bo->tlen, - bo->pgno, &dbc->rdata.data, &dbc->rdata.ulen)) != 0) - return (ret); - - /* Skip any leading data from the original record. */ - tlen = dbt->doff; - p = (u_int8_t *)dbc->rdata.data + dbt->doff; - - /* - * Copy in any trailing data from the original record. - * - * If the original record was larger than the original offset - * plus the bytes being deleted, there is trailing data in the - * original record we need to preserve. If we aren't deleting - * the same number of bytes as we're inserting, copy it up or - * down, into place. - * - * Use memmove(), the regions may overlap. - */ - if (bo->tlen > dbt->doff + dbt->dlen) { - len = bo->tlen - (dbt->doff + dbt->dlen); - if (dbt->dlen != dbt->size) - memmove(p + dbt->size, p + dbt->dlen, len); - tlen += len; - } - } else { - /* Copy in any leading data from the original record. */ - memcpy(dbc->rdata.data, - bk->data, dbt->doff > bk->len ? bk->len : dbt->doff); - tlen = dbt->doff; - p = (u_int8_t *)dbc->rdata.data + dbt->doff; - - /* Copy in any trailing data from the original record. */ - len = dbt->doff + dbt->dlen; - if (bk->len > len) { - memcpy(p + dbt->size, bk->data + len, bk->len - len); - tlen += bk->len - len; - } - } - -ucopy: /* - * Copy in the application provided data -- p and tlen must have been - * initialized above. - */ - memcpy(p, dbt->data, dbt->size); - tlen += dbt->size; - - /* Set the DBT to reference our new record. */ - dbc->rdata.size = tlen; - dbc->rdata.dlen = 0; - dbc->rdata.doff = 0; - dbc->rdata.flags = 0; - *dbt = dbc->rdata; - return (0); -} diff --git a/db2/btree/bt_rec.c b/db2/btree/bt_rec.c deleted file mode 100644 index de6b3b7..0000000 --- a/db2/btree/bt_rec.c +++ /dev/null @@ -1,903 +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[] = "@(#)bt_rec.c 10.28 (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 "db_page.h" -#include "shqueue.h" -#include "hash.h" -#include "btree.h" -#include "log.h" -#include "common_ext.h" - -/* - * __bam_pg_alloc_recover -- - * Recovery function for pg_alloc. - * - * PUBLIC: int __bam_pg_alloc_recover - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__bam_pg_alloc_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __bam_pg_alloc_args *argp; - BTMETA *meta; - DB_MPOOLFILE *mpf; - PAGE *pagep; - DB *file_dbp; - DBC *dbc; - db_pgno_t pgno; - int cmp_n, cmp_p, modified, ret; - - REC_PRINT(__bam_pg_alloc_print); - REC_INTRO(__bam_pg_alloc_read); - - /* - * Fix up the allocated page. If we're redoing the operation, we have - * to get the page (creating it if it doesn't exist), and update its - * LSN. If we're undoing the operation, we have to reset the page's - * LSN and put it on the free list. - * - * Fix up the metadata page. If we're redoing the operation, we have - * to get the metadata page and update its LSN and its free pointer. - * If we're undoing the operation and the page was ever created, we put - * it on the freelist. - */ - pgno = PGNO_METADATA; - if ((ret = memp_fget(mpf, &pgno, 0, &meta)) != 0) { - /* The metadata page must always exist. */ - (void)__db_pgerr(file_dbp, pgno); - goto out; - } - if ((ret = memp_fget(mpf, &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0) { - /* - * We specify creation and check for it later, because this - * operation was supposed to create the page, and even in - * the undo case it's going to get linked onto the freelist - * which we're also fixing up. - */ - (void)__db_pgerr(file_dbp, argp->pgno); - (void)memp_fput(mpf, meta, 0); - goto out; - } - - /* Fix up the allocated page. */ - modified = 0; - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &argp->page_lsn); - if (cmp_p == 0 && redo) { - /* Need to redo update described. */ - P_INIT(pagep, file_dbp->pgsize, - argp->pgno, PGNO_INVALID, PGNO_INVALID, 0, argp->ptype); - - pagep->lsn = *lsnp; - modified = 1; - } else if (cmp_n == 0 && !redo) { - /* Need to undo update described. */ - P_INIT(pagep, file_dbp->pgsize, - argp->pgno, PGNO_INVALID, meta->free, 0, P_INVALID); - - pagep->lsn = argp->page_lsn; - modified = 1; - } - if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) { - (void)memp_fput(mpf, meta, 0); - goto out; - } - - /* Fix up the metadata page. */ - modified = 0; - cmp_n = log_compare(lsnp, &LSN(meta)); - cmp_p = log_compare(&LSN(meta), &argp->meta_lsn); - if (cmp_p == 0 && redo) { - /* Need to redo update described. */ - meta->lsn = *lsnp; - meta->free = argp->next; - modified = 1; - } else if (cmp_n == 0 && !redo) { - /* Need to undo update described. */ - meta->lsn = argp->meta_lsn; - meta->free = argp->pgno; - modified = 1; - } - if ((ret = memp_fput(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0) - goto out; - -done: *lsnp = argp->prev_lsn; - ret = 0; - -out: REC_CLOSE; -} - -/* - * __bam_pg_free_recover -- - * Recovery function for pg_free. - * - * PUBLIC: int __bam_pg_free_recover - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__bam_pg_free_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __bam_pg_free_args *argp; - BTMETA *meta; - DB *file_dbp; - DBC *dbc; - DB_MPOOLFILE *mpf; - PAGE *pagep; - db_pgno_t pgno; - int cmp_n, cmp_p, modified, ret; - - REC_PRINT(__bam_pg_free_print); - REC_INTRO(__bam_pg_free_read); - - /* - * Fix up the freed page. If we're redoing the operation we get the - * page and explicitly discard its contents, then update its LSN. If - * we're undoing the operation, we get the page and restore its header. - */ - if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { - /* - * We don't automatically create the page. The only way the - * page might not exist is if the alloc never happened, and - * the only way the alloc might never have happened is if we - * are undoing, in which case there's no reason to create the - * page. - */ - if (!redo) - goto done; - (void)__db_pgerr(file_dbp, argp->pgno); - goto out; - } - modified = 0; - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &LSN(argp->header.data)); - if (cmp_p == 0 && redo) { - /* Need to redo update described. */ - P_INIT(pagep, file_dbp->pgsize, - pagep->pgno, PGNO_INVALID, argp->next, 0, P_INVALID); - pagep->lsn = *lsnp; - - modified = 1; - } else if (cmp_n == 0 && !redo) { - /* Need to undo update described. */ - memcpy(pagep, argp->header.data, argp->header.size); - - modified = 1; - } - if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) - goto out; - - /* - * Fix up the metadata page. If we're redoing or undoing the operation - * we get the page and update its LSN and free pointer. - */ - pgno = PGNO_METADATA; - if ((ret = memp_fget(mpf, &pgno, 0, &meta)) != 0) { - /* The metadata page must always exist. */ - (void)__db_pgerr(file_dbp, pgno); - goto out; - } - - modified = 0; - cmp_n = log_compare(lsnp, &LSN(meta)); - cmp_p = log_compare(&LSN(meta), &argp->meta_lsn); - if (cmp_p == 0 && redo) { - /* Need to redo update described. */ - meta->free = argp->pgno; - - meta->lsn = *lsnp; - modified = 1; - } else if (cmp_n == 0 && !redo) { - /* Need to undo update described. */ - meta->free = argp->next; - - meta->lsn = argp->meta_lsn; - modified = 1; - } - if ((ret = memp_fput(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0) - goto out; - -done: *lsnp = argp->prev_lsn; - ret = 0; - -out: REC_CLOSE; -} - -/* - * __bam_split_recover -- - * Recovery function for split. - * - * PUBLIC: int __bam_split_recover - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__bam_split_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __bam_split_args *argp; - DB *file_dbp; - DBC *dbc; - DB_MPOOLFILE *mpf; - PAGE *_lp, *lp, *np, *pp, *_rp, *rp, *sp; - db_pgno_t pgno; - int l_update, p_update, r_update, ret, rootsplit, t_ret; - - REC_PRINT(__bam_split_print); - - mpf = NULL; - _lp = lp = np = pp = _rp = rp = NULL; - - REC_INTRO(__bam_split_read); - - /* - * There are two kinds of splits that we have to recover from. The - * first is a root-page split, where the root page is split from a - * leaf page into an internal page and two new leaf pages are created. - * The second is where a page is split into two pages, and a new key - * is inserted into the parent page. - */ - sp = argp->pg.data; - pgno = PGNO(sp); - rootsplit = pgno == PGNO_ROOT; - if (memp_fget(mpf, &argp->left, 0, &lp) != 0) - lp = NULL; - if (memp_fget(mpf, &argp->right, 0, &rp) != 0) - rp = NULL; - - if (redo) { - l_update = r_update = p_update = 0; - /* - * Decide if we need to resplit the page. - * - * If this is a root split, then the root has to exist, it's - * the page we're splitting and it gets modified. If this is - * not a root split, then the left page has to exist, for the - * same reason. - */ - if (rootsplit) { - if ((ret = memp_fget(mpf, &pgno, 0, &pp)) != 0) { - (void)__db_pgerr(file_dbp, pgno); - pp = NULL; - goto out; - } - p_update = - log_compare(&LSN(pp), &LSN(argp->pg.data)) == 0; - } else - if (lp == NULL) { - (void)__db_pgerr(file_dbp, argp->left); - goto out; - } - if (lp == NULL || log_compare(&LSN(lp), &argp->llsn) == 0) - l_update = 1; - if (rp == NULL || log_compare(&LSN(rp), &argp->rlsn) == 0) - r_update = 1; - if (!p_update && !l_update && !r_update) - goto done; - - /* Allocate and initialize new left/right child pages. */ - if ((ret = __os_malloc(file_dbp->pgsize, NULL, &_lp)) != 0 || - (ret = __os_malloc(file_dbp->pgsize, NULL, &_rp)) != 0) - goto out; - if (rootsplit) { - P_INIT(_lp, file_dbp->pgsize, argp->left, - PGNO_INVALID, - ISINTERNAL(sp) ? PGNO_INVALID : argp->right, - LEVEL(sp), TYPE(sp)); - P_INIT(_rp, file_dbp->pgsize, argp->right, - ISINTERNAL(sp) ? PGNO_INVALID : argp->left, - PGNO_INVALID, LEVEL(sp), TYPE(sp)); - } else { - P_INIT(_lp, file_dbp->pgsize, PGNO(sp), - ISINTERNAL(sp) ? PGNO_INVALID : PREV_PGNO(sp), - ISINTERNAL(sp) ? PGNO_INVALID : argp->right, - LEVEL(sp), TYPE(sp)); - P_INIT(_rp, file_dbp->pgsize, argp->right, - ISINTERNAL(sp) ? PGNO_INVALID : sp->pgno, - ISINTERNAL(sp) ? PGNO_INVALID : NEXT_PGNO(sp), - LEVEL(sp), TYPE(sp)); - } - - /* Split the page. */ - if ((ret = __bam_copy(file_dbp, sp, _lp, 0, argp->indx)) != 0 || - (ret = __bam_copy(file_dbp, sp, _rp, argp->indx, - NUM_ENT(sp))) != 0) - goto out; - - /* If the left child is wrong, update it. */ - if (lp == NULL && (ret = - memp_fget(mpf, &argp->left, DB_MPOOL_CREATE, &lp)) != 0) { - (void)__db_pgerr(file_dbp, argp->left); - lp = NULL; - goto out; - } - if (l_update) { - memcpy(lp, _lp, file_dbp->pgsize); - lp->lsn = *lsnp; - if ((ret = memp_fput(mpf, lp, DB_MPOOL_DIRTY)) != 0) - goto out; - lp = NULL; - } - - /* If the right child is wrong, update it. */ - if (rp == NULL && (ret = memp_fget(mpf, - &argp->right, DB_MPOOL_CREATE, &rp)) != 0) { - (void)__db_pgerr(file_dbp, argp->right); - rp = NULL; - goto out; - } - if (r_update) { - memcpy(rp, _rp, file_dbp->pgsize); - rp->lsn = *lsnp; - if ((ret = memp_fput(mpf, rp, DB_MPOOL_DIRTY)) != 0) - goto out; - rp = NULL; - } - - /* - * If the parent page is wrong, update it. This is of interest - * only if it was a root split, since root splits create parent - * pages. All other splits modify a parent page, but those are - * separately logged and recovered. - */ - if (rootsplit && p_update) { - if (file_dbp->type == DB_BTREE) - P_INIT(pp, file_dbp->pgsize, - PGNO_ROOT, PGNO_INVALID, PGNO_INVALID, - _lp->level + 1, P_IBTREE); - else - P_INIT(pp, file_dbp->pgsize, - PGNO_ROOT, PGNO_INVALID, PGNO_INVALID, - _lp->level + 1, P_IRECNO); - RE_NREC_SET(pp, - file_dbp->type == DB_RECNO || - F_ISSET(file_dbp, DB_BT_RECNUM) ? - __bam_total(_lp) + __bam_total(_rp) : 0); - pp->lsn = *lsnp; - if ((ret = memp_fput(mpf, pp, DB_MPOOL_DIRTY)) != 0) - goto out; - pp = NULL; - } - - /* - * Finally, redo the next-page link if necessary. This is of - * interest only if it wasn't a root split -- inserting a new - * page in the tree requires that any following page have its - * previous-page pointer updated to our new page. The next - * page must exist because we're redoing the operation. - */ - if (!rootsplit && !IS_ZERO_LSN(argp->nlsn)) { - if ((ret = memp_fget(mpf, &argp->npgno, 0, &np)) != 0) { - (void)__db_pgerr(file_dbp, argp->npgno); - np = NULL; - goto out; - } - if (log_compare(&LSN(np), &argp->nlsn) == 0) { - PREV_PGNO(np) = argp->right; - np->lsn = *lsnp; - if ((ret = - memp_fput(mpf, np, DB_MPOOL_DIRTY)) != 0) - goto out; - np = NULL; - } - } - } else { - /* - * If the split page is wrong, replace its contents with the - * logged page contents. If the page doesn't exist, it means - * that the create of the page never happened, nor did any of - * the adds onto the page that caused the split, and there's - * really no undo-ing to be done. - */ - if ((ret = memp_fget(mpf, &pgno, 0, &pp)) != 0) { - pp = NULL; - goto lrundo; - } - if (log_compare(lsnp, &LSN(pp)) == 0) { - memcpy(pp, argp->pg.data, argp->pg.size); - if ((ret = memp_fput(mpf, pp, DB_MPOOL_DIRTY)) != 0) - goto out; - pp = NULL; - } - - /* - * If it's a root split and the left child ever existed, update - * its LSN. (If it's not a root split, we've updated the left - * page already -- it's the same as the split page.) If the - * right child ever existed, root split or not, update its LSN. - * The undo of the page allocation(s) will restore them to the - * free list. - */ -lrundo: if ((rootsplit && lp != NULL) || rp != NULL) { - if (rootsplit && lp != NULL && - log_compare(lsnp, &LSN(lp)) == 0) { - lp->lsn = argp->llsn; - if ((ret = - memp_fput(mpf, lp, DB_MPOOL_DIRTY)) != 0) - goto out; - lp = NULL; - } - if (rp != NULL && - log_compare(lsnp, &LSN(rp)) == 0) { - rp->lsn = argp->rlsn; - if ((ret = - memp_fput(mpf, rp, DB_MPOOL_DIRTY)) != 0) - goto out; - rp = NULL; - } - } - - /* - * Finally, undo the next-page link if necessary. This is of - * interest only if it wasn't a root split -- inserting a new - * page in the tree requires that any following page have its - * previous-page pointer updated to our new page. Since it's - * possible that the next-page never existed, we ignore it as - * if there's nothing to undo. - */ - if (!rootsplit && !IS_ZERO_LSN(argp->nlsn)) { - if ((ret = memp_fget(mpf, &argp->npgno, 0, &np)) != 0) { - np = NULL; - goto done; - } - if (log_compare(lsnp, &LSN(np)) == 0) { - PREV_PGNO(np) = argp->left; - np->lsn = argp->nlsn; - if (memp_fput(mpf, np, DB_MPOOL_DIRTY)) - goto out; - np = NULL; - } - } - } - -done: *lsnp = argp->prev_lsn; - ret = 0; - -out: /* Free any pages that weren't dirtied. */ - if (pp != NULL && (t_ret = memp_fput(mpf, pp, 0)) != 0 && ret == 0) - ret = t_ret; - if (lp != NULL && (t_ret = memp_fput(mpf, lp, 0)) != 0 && ret == 0) - ret = t_ret; - if (np != NULL && (t_ret = memp_fput(mpf, np, 0)) != 0 && ret == 0) - ret = t_ret; - if (rp != NULL && (t_ret = memp_fput(mpf, rp, 0)) != 0 && ret == 0) - ret = t_ret; - - /* Free any allocated space. */ - if (_lp != NULL) - __os_free(_lp, file_dbp->pgsize); - if (_rp != NULL) - __os_free(_rp, file_dbp->pgsize); - - REC_CLOSE; -} - -/* - * __bam_rsplit_recover -- - * Recovery function for a reverse split. - * - * PUBLIC: int __bam_rsplit_recover - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__bam_rsplit_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __bam_rsplit_args *argp; - DB *file_dbp; - DBC *dbc; - DB_MPOOLFILE *mpf; - PAGE *pagep; - db_pgno_t pgno; - int cmp_n, cmp_p, modified, ret; - - REC_PRINT(__bam_rsplit_print); - REC_INTRO(__bam_rsplit_read); - - /* Fix the root page. */ - pgno = PGNO_ROOT; - if ((ret = memp_fget(mpf, &pgno, 0, &pagep)) != 0) { - /* The root page must always exist. */ - __db_pgerr(file_dbp, pgno); - goto out; - } - modified = 0; - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &argp->rootlsn); - if (cmp_p == 0 && redo) { - /* Need to redo update described. */ - memcpy(pagep, argp->pgdbt.data, argp->pgdbt.size); - pagep->pgno = PGNO_ROOT; - pagep->lsn = *lsnp; - modified = 1; - } else if (cmp_n == 0 && !redo) { - /* Need to undo update described. */ - P_INIT(pagep, file_dbp->pgsize, PGNO_ROOT, - argp->nrec, PGNO_INVALID, pagep->level + 1, - file_dbp->type == DB_BTREE ? P_IBTREE : P_IRECNO); - if ((ret = __db_pitem(dbc, pagep, 0, - argp->rootent.size, &argp->rootent, NULL)) != 0) - goto out; - pagep->lsn = argp->rootlsn; - modified = 1; - } - if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) - goto out; - - /* - * Fix the page copied over the root page. It's possible that the - * page never made it to disk, so if we're undo-ing and the page - * doesn't exist, it's okay and there's nothing further to do. - */ - if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { - if (!redo) - goto done; - (void)__db_pgerr(file_dbp, argp->pgno); - goto out; - } - modified = 0; - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &LSN(argp->pgdbt.data)); - if (cmp_p == 0 && redo) { - /* Need to redo update described. */ - pagep->lsn = *lsnp; - modified = 1; - } else if (cmp_n == 0 && !redo) { - /* Need to undo update described. */ - memcpy(pagep, argp->pgdbt.data, argp->pgdbt.size); - modified = 1; - } - if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) - goto out; - -done: *lsnp = argp->prev_lsn; - ret = 0; - -out: REC_CLOSE; -} - -/* - * __bam_adj_recover -- - * Recovery function for adj. - * - * PUBLIC: int __bam_adj_recover - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__bam_adj_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __bam_adj_args *argp; - DB *file_dbp; - DBC *dbc; - DB_MPOOLFILE *mpf; - PAGE *pagep; - int cmp_n, cmp_p, modified, ret; - - REC_PRINT(__bam_adj_print); - REC_INTRO(__bam_adj_read); - - /* Get the page; if it never existed and we're undoing, we're done. */ - if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { - if (!redo) - goto done; - (void)__db_pgerr(file_dbp, argp->pgno); - goto out; - } - - modified = 0; - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &argp->lsn); - if (cmp_p == 0 && redo) { - /* Need to redo update described. */ - if ((ret = __bam_adjindx(dbc, - pagep, argp->indx, argp->indx_copy, argp->is_insert)) != 0) - goto err; - - LSN(pagep) = *lsnp; - modified = 1; - } else if (cmp_n == 0 && !redo) { - /* Need to undo update described. */ - if ((ret = __bam_adjindx(dbc, - pagep, argp->indx, argp->indx_copy, !argp->is_insert)) != 0) - goto err; - - LSN(pagep) = argp->lsn; - modified = 1; - } - if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) - goto out; - -done: *lsnp = argp->prev_lsn; - ret = 0; - - if (0) { -err: (void)memp_fput(mpf, pagep, 0); - } -out: REC_CLOSE; -} - -/* - * __bam_cadjust_recover -- - * Recovery function for the adjust of a count change in an internal - * page. - * - * PUBLIC: int __bam_cadjust_recover - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__bam_cadjust_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __bam_cadjust_args *argp; - DB *file_dbp; - DBC *dbc; - DB_MPOOLFILE *mpf; - PAGE *pagep; - int cmp_n, cmp_p, modified, ret; - - REC_PRINT(__bam_cadjust_print); - REC_INTRO(__bam_cadjust_read); - - /* Get the page; if it never existed and we're undoing, we're done. */ - if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { - if (!redo) - goto done; - (void)__db_pgerr(file_dbp, argp->pgno); - goto out; - } - - modified = 0; - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &argp->lsn); - if (cmp_p == 0 && redo) { - /* Need to redo update described. */ - if (file_dbp->type == DB_BTREE && - F_ISSET(file_dbp, DB_BT_RECNUM)) { - GET_BINTERNAL(pagep, argp->indx)->nrecs += argp->adjust; - if (argp->total && PGNO(pagep) == PGNO_ROOT) - RE_NREC_ADJ(pagep, argp->adjust); - } - if (file_dbp->type == DB_RECNO) { - GET_RINTERNAL(pagep, argp->indx)->nrecs += argp->adjust; - if (argp->total && PGNO(pagep) == PGNO_ROOT) - RE_NREC_ADJ(pagep, argp->adjust); - } - - LSN(pagep) = *lsnp; - modified = 1; - } else if (cmp_n == 0 && !redo) { - /* Need to undo update described. */ - if (file_dbp->type == DB_BTREE && - F_ISSET(file_dbp, DB_BT_RECNUM)) { - GET_BINTERNAL(pagep, argp->indx)->nrecs -= argp->adjust; - if (argp->total && PGNO(pagep) == PGNO_ROOT) - RE_NREC_ADJ(pagep, argp->adjust); - } - if (file_dbp->type == DB_RECNO) { - GET_RINTERNAL(pagep, argp->indx)->nrecs -= argp->adjust; - if (argp->total && PGNO(pagep) == PGNO_ROOT) - RE_NREC_ADJ(pagep, -(argp->adjust)); - } - LSN(pagep) = argp->lsn; - modified = 1; - } - if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) - goto out; - -done: *lsnp = argp->prev_lsn; - ret = 0; - -out: REC_CLOSE; -} - -/* - * __bam_cdel_recover -- - * Recovery function for the intent-to-delete of a cursor record. - * - * PUBLIC: int __bam_cdel_recover - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__bam_cdel_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __bam_cdel_args *argp; - DB *file_dbp; - DBC *dbc; - DB_MPOOLFILE *mpf; - PAGE *pagep; - int cmp_n, cmp_p, modified, ret; - - REC_PRINT(__bam_cdel_print); - REC_INTRO(__bam_cdel_read); - - /* Get the page; if it never existed and we're undoing, we're done. */ - if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { - if (!redo) - goto done; - (void)__db_pgerr(file_dbp, argp->pgno); - goto out; - } - - modified = 0; - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &argp->lsn); - if (cmp_p == 0 && redo) { - /* Need to redo update described. */ - if (pagep->type == P_DUPLICATE) - B_DSET(GET_BKEYDATA(pagep, argp->indx)->type); - else - B_DSET(GET_BKEYDATA(pagep, argp->indx + O_INDX)->type); - - LSN(pagep) = *lsnp; - modified = 1; - } else if (cmp_n == 0 && !redo) { - /* Need to undo update described. */ - if (pagep->type == P_DUPLICATE) - B_DCLR(GET_BKEYDATA(pagep, argp->indx)->type); - else - B_DCLR(GET_BKEYDATA(pagep, argp->indx + O_INDX)->type); - - LSN(pagep) = argp->lsn; - modified = 1; - } - if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) - goto out; - -done: *lsnp = argp->prev_lsn; - ret = 0; - -out: REC_CLOSE; -} - -/* - * __bam_repl_recover -- - * Recovery function for page item replacement. - * - * PUBLIC: int __bam_repl_recover - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__bam_repl_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __bam_repl_args *argp; - BKEYDATA *bk; - DB *file_dbp; - DBC *dbc; - DBT dbt; - DB_MPOOLFILE *mpf; - PAGE *pagep; - int cmp_n, cmp_p, modified, ret; - u_int8_t *p; - - REC_PRINT(__bam_repl_print); - REC_INTRO(__bam_repl_read); - - /* Get the page; if it never existed and we're undoing, we're done. */ - if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { - if (!redo) - goto done; - (void)__db_pgerr(file_dbp, argp->pgno); - goto out; - } - bk = GET_BKEYDATA(pagep, argp->indx); - - modified = 0; - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &argp->lsn); - if (cmp_p == 0 && redo) { - /* - * Need to redo update described. - * - * Re-build the replacement item. - */ - memset(&dbt, 0, sizeof(dbt)); - dbt.size = argp->prefix + argp->suffix + argp->repl.size; - if ((ret = __os_malloc(dbt.size, NULL, &dbt.data)) != 0) - goto err; - p = dbt.data; - memcpy(p, bk->data, argp->prefix); - p += argp->prefix; - memcpy(p, argp->repl.data, argp->repl.size); - p += argp->repl.size; - memcpy(p, bk->data + (bk->len - argp->suffix), argp->suffix); - - ret = __bam_ritem(dbc, pagep, argp->indx, &dbt); - __os_free(dbt.data, dbt.size); - if (ret != 0) - goto err; - - LSN(pagep) = *lsnp; - modified = 1; - } else if (cmp_n == 0 && !redo) { - /* - * Need to undo update described. - * - * Re-build the original item. - */ - memset(&dbt, 0, sizeof(dbt)); - dbt.size = argp->prefix + argp->suffix + argp->orig.size; - if ((ret = __os_malloc(dbt.size, NULL, &dbt.data)) != 0) - goto err; - p = dbt.data; - memcpy(p, bk->data, argp->prefix); - p += argp->prefix; - memcpy(p, argp->orig.data, argp->orig.size); - p += argp->orig.size; - memcpy(p, bk->data + (bk->len - argp->suffix), argp->suffix); - - ret = __bam_ritem(dbc, pagep, argp->indx, &dbt); - __os_free(dbt.data, dbt.size); - if (ret != 0) - goto err; - - /* Reset the deleted flag, if necessary. */ - if (argp->isdeleted) - B_DSET(GET_BKEYDATA(pagep, argp->indx)->type); - - LSN(pagep) = argp->lsn; - modified = 1; - } - if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) - goto out; - -done: *lsnp = argp->prev_lsn; - ret = 0; - - if (0) { -err: (void)memp_fput(mpf, pagep, 0); - } -out: REC_CLOSE; -} diff --git a/db2/btree/bt_recno.c b/db2/btree/bt_recno.c deleted file mode 100644 index c69877f..0000000 --- a/db2/btree/bt_recno.c +++ /dev/null @@ -1,1356 +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[] = "@(#)bt_recno.c 10.53 (Sleepycat) 12/11/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <limits.h> -#include <string.h> -#endif - -#include "db_int.h" -#include "db_page.h" -#include "btree.h" -#include "db_ext.h" -#include "shqueue.h" -#include "db_shash.h" -#include "lock.h" -#include "lock_ext.h" - -static int __ram_add __P((DBC *, db_recno_t *, DBT *, u_int32_t, u_int32_t)); -static int __ram_delete __P((DB *, DB_TXN *, DBT *, u_int32_t)); -static int __ram_fmap __P((DBC *, db_recno_t)); -static int __ram_i_delete __P((DBC *)); -static int __ram_put __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t)); -static int __ram_source __P((DB *, RECNO *, const char *)); -static int __ram_sync __P((DB *, u_int32_t)); -static int __ram_update __P((DBC *, db_recno_t, int)); -static int __ram_vmap __P((DBC *, db_recno_t)); -static int __ram_writeback __P((DBC *)); - -/* - * In recno, there are two meanings to the on-page "deleted" flag. If we're - * re-numbering records, it means the record was implicitly created. We skip - * over implicitly created records if doing a cursor "next" or "prev", and - * return DB_KEYEMPTY if they're explicitly requested.. If not re-numbering - * records, it means that the record was implicitly created, or was deleted. - * We skip over implicitly created or deleted records if doing a cursor "next" - * or "prev", and return DB_KEYEMPTY if they're explicitly requested. - * - * If we're re-numbering records, then we have to detect in the cursor that - * a record was deleted, and adjust the cursor as necessary on the next get. - * If we're not re-numbering records, then we can detect that a record has - * been deleted by looking at the actual on-page record, so we completely - * ignore the cursor's delete flag. This is different from the B+tree code. - * It also maintains whether the cursor references a deleted record in the - * cursor, and it doesn't always check the on-page value. - */ -#define CD_SET(dbp, cp) { \ - if (F_ISSET(dbp, DB_RE_RENUMBER)) \ - F_SET(cp, C_DELETED); \ -} -#define CD_CLR(dbp, cp) { \ - if (F_ISSET(dbp, DB_RE_RENUMBER)) \ - F_CLR(cp, C_DELETED); \ -} -#define CD_ISSET(dbp, cp) \ - (F_ISSET(dbp, DB_RE_RENUMBER) && F_ISSET(cp, C_DELETED)) - -/* - * __ram_open -- - * Recno open function. - * - * PUBLIC: int __ram_open __P((DB *, DB_INFO *)); - */ -int -__ram_open(dbp, dbinfo) - DB *dbp; - DB_INFO *dbinfo; -{ - BTREE *t; - DBC *dbc; - RECNO *rp; - int ret, t_ret; - - /* Allocate and initialize the private btree structure. */ - if ((ret = __os_calloc(1, sizeof(BTREE), &t)) != 0) - return (ret); - dbp->internal = t; - __bam_setovflsize(dbp); - - /* Allocate and initialize the private recno structure. */ - if ((ret = __os_calloc(1, sizeof(*rp), &rp)) != 0) - return (ret); - /* Link in the private recno structure. */ - t->recno = rp; - - /* - * Intention is to make sure all of the user's selections are okay - * here and then use them without checking. - */ - if (dbinfo == NULL) { - rp->re_delim = '\n'; - rp->re_pad = ' '; - rp->re_fd = -1; - F_SET(rp, RECNO_EOF); - } else { - /* - * If the user specified a source tree, open it and map it in. - * - * !!! - * We don't complain if the user specified transactions or - * threads. It's possible to make it work, but you'd better - * know what you're doing! - */ - if (dbinfo->re_source == NULL) { - rp->re_fd = -1; - F_SET(rp, RECNO_EOF); - } else { - if ((ret = - __ram_source(dbp, rp, dbinfo->re_source)) != 0) - goto err; - } - - /* Copy delimiter, length and padding values. */ - rp->re_delim = - F_ISSET(dbp, DB_RE_DELIMITER) ? dbinfo->re_delim : '\n'; - rp->re_pad = F_ISSET(dbp, DB_RE_PAD) ? dbinfo->re_pad : ' '; - - if (F_ISSET(dbp, DB_RE_FIXEDLEN)) { - if ((rp->re_len = dbinfo->re_len) == 0) { - __db_err(dbp->dbenv, - "record length must be greater than 0"); - ret = EINVAL; - goto err; - } - } else - rp->re_len = 0; - } - - /* Initialize the remaining fields/methods of the DB. */ - dbp->am_close = __ram_close; - dbp->del = __ram_delete; - dbp->put = __ram_put; - dbp->stat = __bam_stat; - dbp->sync = __ram_sync; - - /* Start up the tree. */ - if ((ret = __bam_read_root(dbp)) != 0) - goto err; - - /* Set the overflow page size. */ - __bam_setovflsize(dbp); - - /* If we're snapshotting an underlying source file, do it now. */ - if (dbinfo != NULL && F_ISSET(dbinfo, DB_SNAPSHOT)) { - /* Allocate a cursor. */ - if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0) - goto err; - - /* Do the snapshot. */ - if ((ret = __ram_update(dbc, - DB_MAX_RECORDS, 0)) != 0 && ret == DB_NOTFOUND) - ret = 0; - - /* Discard the cursor. */ - if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0) - ret = t_ret; - - if (ret != 0) - goto err; - } - - return (0); - -err: /* If we mmap'd a source file, discard it. */ - if (rp->re_smap != NULL) - (void)__db_unmapfile(rp->re_smap, rp->re_msize); - - /* If we opened a source file, discard it. */ - if (rp->re_fd != -1) - (void)__os_close(rp->re_fd); - if (rp->re_source != NULL) - __os_freestr(rp->re_source); - - __os_free(rp, sizeof(*rp)); - - return (ret); -} - -/* - * __ram_delete -- - * Recno db->del function. - */ -static int -__ram_delete(dbp, txn, key, flags) - DB *dbp; - DB_TXN *txn; - DBT *key; - u_int32_t flags; -{ - CURSOR *cp; - DBC *dbc; - db_recno_t recno; - int ret, t_ret; - - DB_PANIC_CHECK(dbp); - - /* Check for invalid flags. */ - if ((ret = __db_delchk(dbp, - key, flags, F_ISSET(dbp, DB_AM_RDONLY))) != 0) - return (ret); - - /* Acquire a cursor. */ - if ((ret = dbp->cursor(dbp, txn, &dbc, DB_WRITELOCK)) != 0) - return (ret); - - DEBUG_LWRITE(dbc, txn, "ram_delete", key, NULL, flags); - - /* Check the user's record number and fill in as necessary. */ - if ((ret = __ram_getno(dbc, key, &recno, 0)) != 0) - goto err; - - /* Do the delete. */ - cp = dbc->internal; - cp->recno = recno; - ret = __ram_i_delete(dbc); - - /* Release the cursor. */ -err: if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0) - ret = t_ret; - - return (ret); -} - -/* - * __ram_i_delete -- - * Internal version of recno delete, called by __ram_delete and - * __ram_c_del. - */ -static int -__ram_i_delete(dbc) - DBC *dbc; -{ - BKEYDATA bk; - BTREE *t; - CURSOR *cp; - DB *dbp; - DBT hdr, data; - PAGE *h; - db_indx_t indx; - int exact, ret, stack; - - dbp = dbc->dbp; - cp = dbc->internal; - t = dbp->internal; - stack = 0; - - /* - * If this is CDB and this isn't a write cursor, then it's an error. - * If it is a write cursor, but we don't yet hold the write lock, then - * we need to upgrade to the write lock. - */ - if (F_ISSET(dbp, DB_AM_CDB)) { - /* Make sure it's a valid update cursor. */ - if (!F_ISSET(dbc, DBC_RMW | DBC_WRITER)) - return (EINVAL); - - if (F_ISSET(dbc, DBC_RMW) && - (ret = lock_get(dbp->dbenv->lk_info, dbc->locker, - DB_LOCK_UPGRADE, &dbc->lock_dbt, DB_LOCK_WRITE, - &dbc->mylock)) != 0) - return (EAGAIN); - } - - /* Search the tree for the key; delete only deletes exact matches. */ - if ((ret = __bam_rsearch(dbc, &cp->recno, S_DELETE, 1, &exact)) != 0) - goto err; - if (!exact) { - ret = DB_NOTFOUND; - goto err; - } - stack = 1; - - h = cp->csp->page; - indx = cp->csp->indx; - - /* - * If re-numbering records, the on-page deleted flag can only mean - * that this record was implicitly created. Applications aren't - * permitted to delete records they never created, return an error. - * - * If not re-numbering records, the on-page deleted flag means that - * this record was implicitly created, or, was deleted at some time. - * The former is an error because applications aren't permitted to - * delete records they never created, the latter is an error because - * if the record was "deleted", we could never have found it. - */ - if (B_DISSET(GET_BKEYDATA(h, indx)->type)) { - ret = DB_KEYEMPTY; - goto err; - } - - if (F_ISSET(dbp, DB_RE_RENUMBER)) { - /* Delete the item, adjust the counts, adjust the cursors. */ - if ((ret = __bam_ditem(dbc, h, indx)) != 0) - goto err; - __bam_adjust(dbc, -1); - __ram_ca(dbp, cp->recno, CA_DELETE); - - /* - * If the page is empty, delete it. The whole tree is locked - * so there are no preparations to make. - */ - if (NUM_ENT(h) == 0 && h->pgno != PGNO_ROOT) { - stack = 0; - ret = __bam_dpages(dbc); - } - } else { - /* Use a delete/put pair to replace the record with a marker. */ - if ((ret = __bam_ditem(dbc, h, indx)) != 0) - goto err; - - B_TSET(bk.type, B_KEYDATA, 1); - bk.len = 0; - memset(&hdr, 0, sizeof(hdr)); - hdr.data = &bk; - hdr.size = SSZA(BKEYDATA, data); - memset(&data, 0, sizeof(data)); - data.data = (char *)""; - data.size = 0; - if ((ret = __db_pitem(dbc, - h, indx, BKEYDATA_SIZE(0), &hdr, &data)) != 0) - goto err; - } - F_SET(t->recno, RECNO_MODIFIED); - -err: if (stack) - __bam_stkrel(dbc, 0); - - /* If we upgraded the CDB lock upon entry; downgrade it now. */ - if (F_ISSET(dbp, DB_AM_CDB) && F_ISSET(dbc, DBC_RMW)) - (void)__lock_downgrade(dbp->dbenv->lk_info, dbc->mylock, - DB_LOCK_IWRITE, 0); - return (ret); -} - -/* - * __ram_put -- - * Recno db->put function. - */ -static int -__ram_put(dbp, txn, key, data, flags) - DB *dbp; - DB_TXN *txn; - DBT *key, *data; - u_int32_t flags; -{ - DBC *dbc; - db_recno_t recno; - int ret, t_ret; - - DB_PANIC_CHECK(dbp); - - /* Check for invalid flags. */ - if ((ret = __db_putchk(dbp, - key, data, flags, F_ISSET(dbp, DB_AM_RDONLY), 0)) != 0) - return (ret); - - /* Allocate a cursor. */ - if ((ret = dbp->cursor(dbp, txn, &dbc, DB_WRITELOCK)) != 0) - return (ret); - - DEBUG_LWRITE(dbc, txn, "ram_put", key, data, flags); - - /* - * If we're appending to the tree, make sure we've read in all of - * the backing source file. Otherwise, check the user's record - * number and fill in as necessary. - */ - ret = flags == DB_APPEND ? - __ram_update(dbc, DB_MAX_RECORDS, 0) : - __ram_getno(dbc, key, &recno, 1); - - /* Add the record. */ - if (ret == 0) - ret = __ram_add(dbc, &recno, data, flags, 0); - - /* Discard the cursor. */ - if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0) - ret = t_ret; - - /* Return the record number if we're appending to the tree. */ - if (ret == 0 && flags == DB_APPEND) - *(db_recno_t *)key->data = recno; - - return (ret); -} - -/* - * __ram_sync -- - * Recno db->sync function. - */ -static int -__ram_sync(dbp, flags) - DB *dbp; - u_int32_t flags; -{ - DBC *dbc; - int ret, t_ret; - - /* - * Sync the underlying btree. - * - * !!! - * We don't need to do a panic check or flags check, the "real" - * sync function does all that for us. - */ - if ((ret = __db_sync(dbp, flags)) != 0) - return (ret); - - /* Allocate a cursor. */ - if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0) - return (ret); - - DEBUG_LWRITE(dbc, NULL, "ram_sync", NULL, NULL, flags); - - /* Copy back the backing source file. */ - ret = __ram_writeback(dbc); - - /* Discard the cursor. */ - if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0) - ret = t_ret; - - return (ret); -} - -/* - * __ram_close -- - * Recno db->close function. - * - * PUBLIC: int __ram_close __P((DB *)); - */ -int -__ram_close(dbp) - DB *dbp; -{ - RECNO *rp; - - rp = ((BTREE *)dbp->internal)->recno; - - /* Close any underlying mmap region. */ - if (rp->re_smap != NULL) - (void)__db_unmapfile(rp->re_smap, rp->re_msize); - - /* Close any backing source file descriptor. */ - if (rp->re_fd != -1) - (void)__os_close(rp->re_fd); - - /* Free any backing source file name. */ - if (rp->re_source != NULL) - __os_freestr(rp->re_source); - - /* Free allocated memory. */ - __os_free(rp, sizeof(RECNO)); - ((BTREE *)dbp->internal)->recno = NULL; - - /* Close the underlying btree. */ - return (__bam_close(dbp)); -} - -/* - * __ram_c_del -- - * Recno cursor->c_del function. - * - * PUBLIC: int __ram_c_del __P((DBC *, u_int32_t)); - */ -int -__ram_c_del(dbc, flags) - DBC *dbc; - u_int32_t flags; -{ - CURSOR *cp; - DB *dbp; - int ret; - - dbp = dbc->dbp; - cp = dbc->internal; - - DB_PANIC_CHECK(dbp); - - /* Check for invalid flags. */ - if ((ret = __db_cdelchk(dbp, flags, - F_ISSET(dbp, DB_AM_RDONLY), cp->recno != RECNO_OOB)) != 0) - return (ret); - - DEBUG_LWRITE(dbc, dbc->txn, "ram_c_del", NULL, NULL, flags); - - /* - * If we are running CDB, this had better be either a write - * cursor or an immediate writer. - */ - if (F_ISSET(dbp, DB_AM_CDB)) - if (!F_ISSET(dbc, DBC_RMW | DBC_WRITER)) - return (EINVAL); - - /* - * The semantics of cursors during delete are as follows: if record - * numbers are mutable (DB_RE_RENUMBER is set), deleting a record - * causes the cursor to automatically point to the record immediately - * following. In this case it is possible to use a single cursor for - * repeated delete operations, without intervening operations. - * - * If record numbers are not mutable, then records are replaced with - * a marker containing a delete flag. If the record referenced by - * this cursor has already been deleted, we will detect that as part - * of the delete operation, and fail. - */ - return (__ram_i_delete(dbc)); -} - -/* - * __ram_c_get -- - * Recno cursor->c_get function. - * - * PUBLIC: int __ram_c_get __P((DBC *, DBT *, DBT *, u_int32_t)); - */ -int -__ram_c_get(dbc, key, data, flags) - DBC *dbc; - DBT *key, *data; - u_int32_t flags; -{ - CURSOR *cp, copy; - DB *dbp; - PAGE *h; - db_indx_t indx; - int exact, ret, stack, tmp_rmw; - - dbp = dbc->dbp; - cp = dbc->internal; - - DB_PANIC_CHECK(dbp); - - /* Check for invalid flags. */ - if ((ret = __db_cgetchk(dbc->dbp, - key, data, flags, cp->recno != RECNO_OOB)) != 0) - return (ret); - - /* Clear OR'd in additional bits so we can check for flag equality. */ - tmp_rmw = 0; - if (LF_ISSET(DB_RMW)) { - if (!F_ISSET(dbp, DB_AM_CDB)) { - tmp_rmw = 1; - F_SET(dbc, DBC_RMW); - } - LF_CLR(DB_RMW); - } - - DEBUG_LREAD(dbc, dbc->txn, "ram_c_get", - flags == DB_SET || flags == DB_SET_RANGE ? key : NULL, NULL, flags); - - /* Initialize the cursor for a new retrieval. */ - copy = *cp; - -retry: /* Update the record number. */ - stack = 0; - switch (flags) { - case DB_CURRENT: - /* - * If record numbers are mutable: if we just deleted a record, - * there is no action necessary, we return the record following - * the deleted item by virtue of renumbering the tree. - */ - break; - case DB_NEXT: - /* - * If record numbers are mutable: if we just deleted a record, - * we have to avoid incrementing the record number so that we - * return the right record by virtue of renumbering the tree. - */ - if (CD_ISSET(dbp, cp)) - break; - - if (cp->recno != RECNO_OOB) { - ++cp->recno; - break; - } - /* FALLTHROUGH */ - case DB_FIRST: - flags = DB_NEXT; - cp->recno = 1; - break; - case DB_PREV: - if (cp->recno != RECNO_OOB) { - if (cp->recno == 1) { - ret = DB_NOTFOUND; - goto err; - } - --cp->recno; - break; - } - /* FALLTHROUGH */ - case DB_LAST: - flags = DB_PREV; - if (((ret = __ram_update(dbc, - DB_MAX_RECORDS, 0)) != 0) && ret != DB_NOTFOUND) - goto err; - if ((ret = __bam_nrecs(dbc, &cp->recno)) != 0) - goto err; - if (cp->recno == 0) { - ret = DB_NOTFOUND; - goto err; - } - break; - case DB_SET: - case DB_SET_RANGE: - if ((ret = __ram_getno(dbc, key, &cp->recno, 0)) != 0) - goto err; - break; - } - - /* Return the key if the user didn't give us one. */ - if (flags != DB_SET && flags != DB_SET_RANGE && - (ret = __db_retcopy(key, &cp->recno, sizeof(cp->recno), - &dbc->rkey.data, &dbc->rkey.ulen, dbp->db_malloc)) != 0) - goto err; - - /* Search the tree for the record. */ - if ((ret = __bam_rsearch(dbc, &cp->recno, - F_ISSET(dbc, DBC_RMW) ? S_FIND_WR : S_FIND, 1, &exact)) != 0) - goto err; - stack = 1; - if (!exact) { - ret = DB_NOTFOUND; - goto err; - } - h = cp->csp->page; - indx = cp->csp->indx; - - /* - * If re-numbering records, the on-page deleted flag means this record - * was implicitly created. If not re-numbering records, the on-page - * deleted flag means this record was implicitly created, or, it was - * deleted at some time. Regardless, we skip such records if doing - * cursor next/prev operations, and fail if the application requested - * them explicitly. - */ - if (B_DISSET(GET_BKEYDATA(h, indx)->type)) { - if (flags == DB_NEXT || flags == DB_PREV) { - (void)__bam_stkrel(dbc, 0); - goto retry; - } - ret = DB_KEYEMPTY; - goto err; - } - - /* Return the data item. */ - if ((ret = __db_ret(dbp, - h, indx, data, &dbc->rdata.data, &dbc->rdata.ulen)) != 0) - goto err; - - /* The cursor was reset, no further delete adjustment is necessary. */ - CD_CLR(dbp, cp); - -err: if (stack) - (void)__bam_stkrel(dbc, 0); - - /* Release temporary lock upgrade. */ - if (tmp_rmw) - F_CLR(dbc, DBC_RMW); - - if (ret != 0) - *cp = copy; - - return (ret); -} - -/* - * __ram_c_put -- - * Recno cursor->c_put function. - * - * PUBLIC: int __ram_c_put __P((DBC *, DBT *, DBT *, u_int32_t)); - */ -int -__ram_c_put(dbc, key, data, flags) - DBC *dbc; - DBT *key, *data; - u_int32_t flags; -{ - CURSOR *cp, copy; - DB *dbp; - int exact, ret; - void *arg; - - dbp = dbc->dbp; - cp = dbc->internal; - - DB_PANIC_CHECK(dbp); - - if ((ret = __db_cputchk(dbc->dbp, key, data, flags, - F_ISSET(dbc->dbp, DB_AM_RDONLY), cp->recno != RECNO_OOB)) != 0) - return (ret); - - DEBUG_LWRITE(dbc, dbc->txn, "ram_c_put", NULL, data, flags); - - /* - * If we are running CDB, this had better be either a write - * cursor or an immediate writer. If it's a regular writer, - * that means we have an IWRITE lock and we need to upgrade - * it to a write lock. - */ - if (F_ISSET(dbp, DB_AM_CDB)) { - if (!F_ISSET(dbc, DBC_RMW | DBC_WRITER)) - return (EINVAL); - - if (F_ISSET(dbc, DBC_RMW) && - (ret = lock_get(dbp->dbenv->lk_info, dbc->locker, - DB_LOCK_UPGRADE, &dbc->lock_dbt, DB_LOCK_WRITE, - &dbc->mylock)) != 0) - return (EAGAIN); - } - - /* Initialize the cursor for a new retrieval. */ - copy = *cp; - - /* - * To split, we need a valid key for the page. Since it's a cursor, - * we have to build one. - * - * The split code discards all short-term locks and stack pages. - */ - if (0) { -split: arg = &cp->recno; - if ((ret = __bam_split(dbc, arg)) != 0) - goto err; - } - - if ((ret = __bam_rsearch(dbc, &cp->recno, S_INSERT, 1, &exact)) != 0) - goto err; - if (!exact) { - ret = DB_NOTFOUND; - goto err; - } - if ((ret = __bam_iitem(dbc, &cp->csp->page, - &cp->csp->indx, key, data, flags, 0)) == DB_NEEDSPLIT) { - if ((ret = __bam_stkrel(dbc, 0)) != 0) - goto err; - goto split; - } - if ((ret = __bam_stkrel(dbc, 0)) != 0) - goto err; - - switch (flags) { - case DB_AFTER: - /* Adjust the cursors. */ - __ram_ca(dbp, cp->recno, CA_IAFTER); - - /* Set this cursor to reference the new record. */ - cp->recno = copy.recno + 1; - break; - case DB_BEFORE: - /* Adjust the cursors. */ - __ram_ca(dbp, cp->recno, CA_IBEFORE); - - /* Set this cursor to reference the new record. */ - cp->recno = copy.recno; - break; - } - - /* The cursor was reset, no further delete adjustment is necessary. */ - CD_CLR(dbp, cp); - -err: if (F_ISSET(dbp, DB_AM_CDB) && F_ISSET(dbc, DBC_RMW)) - (void)__lock_downgrade(dbp->dbenv->lk_info, dbc->mylock, - DB_LOCK_IWRITE, 0); - - if (ret != 0) - *cp = copy; - - return (ret); -} - -/* - * __ram_ca -- - * Adjust cursors. - * - * PUBLIC: void __ram_ca __P((DB *, db_recno_t, ca_recno_arg)); - */ -void -__ram_ca(dbp, recno, op) - DB *dbp; - db_recno_t recno; - ca_recno_arg op; -{ - CURSOR *cp; - DBC *dbc; - - /* - * Adjust the cursors. See the comment in __bam_ca_delete(). - */ - DB_THREAD_LOCK(dbp); - for (dbc = TAILQ_FIRST(&dbp->active_queue); - dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { - cp = dbc->internal; - switch (op) { - case CA_DELETE: - if (recno > cp->recno) - --cp->recno; - if (recno == cp->recno) - CD_SET(dbp, cp); - break; - case CA_IAFTER: - if (recno > cp->recno) - ++cp->recno; - break; - case CA_IBEFORE: - if (recno >= cp->recno) - ++cp->recno; - break; - } - } - DB_THREAD_UNLOCK(dbp); -} - -/* - * __ram_getno -- - * Check the user's record number, and make sure we've seen it. - * - * PUBLIC: int __ram_getno __P((DBC *, const DBT *, db_recno_t *, int)); - */ -int -__ram_getno(dbc, key, rep, can_create) - DBC *dbc; - const DBT *key; - db_recno_t *rep; - int can_create; -{ - DB *dbp; - db_recno_t recno; - - dbp = dbc->dbp; - - /* Check the user's record number. */ - if ((recno = *(db_recno_t *)key->data) == 0) { - __db_err(dbp->dbenv, "illegal record number of 0"); - return (EINVAL); - } - if (rep != NULL) - *rep = recno; - - /* - * Btree can neither create records nor read them in. Recno can - * do both, see if we can find the record. - */ - return (dbp->type == DB_RECNO ? - __ram_update(dbc, recno, can_create) : 0); -} - -/* - * __ram_update -- - * Ensure the tree has records up to and including the specified one. - */ -static int -__ram_update(dbc, recno, can_create) - DBC *dbc; - db_recno_t recno; - int can_create; -{ - BTREE *t; - DB *dbp; - RECNO *rp; - db_recno_t nrecs; - int ret; - - dbp = dbc->dbp; - t = dbp->internal; - rp = t->recno; - - /* - * If we can't create records and we've read the entire backing input - * file, we're done. - */ - if (!can_create && F_ISSET(rp, RECNO_EOF)) - return (0); - - /* - * If we haven't seen this record yet, try to get it from the original - * file. - */ - if ((ret = __bam_nrecs(dbc, &nrecs)) != 0) - return (ret); - if (!F_ISSET(rp, RECNO_EOF) && recno > nrecs) { - if ((ret = rp->re_irec(dbc, recno)) != 0) - return (ret); - if ((ret = __bam_nrecs(dbc, &nrecs)) != 0) - return (ret); - } - - /* - * If we can create records, create empty ones up to the requested - * record. - */ - if (!can_create || recno <= nrecs + 1) - return (0); - - dbc->rdata.dlen = 0; - dbc->rdata.doff = 0; - dbc->rdata.flags = 0; - if (F_ISSET(dbp, DB_RE_FIXEDLEN)) { - if (dbc->rdata.ulen < rp->re_len) { - if ((ret = - __os_realloc(&dbc->rdata.data, rp->re_len)) != 0) { - dbc->rdata.ulen = 0; - dbc->rdata.data = NULL; - return (ret); - } - dbc->rdata.ulen = rp->re_len; - } - dbc->rdata.size = rp->re_len; - memset(dbc->rdata.data, rp->re_pad, rp->re_len); - } else - dbc->rdata.size = 0; - - while (recno > ++nrecs) - if ((ret = __ram_add(dbc, - &nrecs, &dbc->rdata, 0, BI_DELETED)) != 0) - return (ret); - return (0); -} - -/* - * __ram_source -- - * Load information about the backing file. - */ -static int -__ram_source(dbp, rp, fname) - DB *dbp; - RECNO *rp; - const char *fname; -{ - size_t size; - u_int32_t bytes, mbytes, oflags; - int ret; - - /* - * !!! - * The caller has full responsibility for cleaning up on error -- - * (it has to anyway, in case it fails after this routine succeeds). - */ - if ((ret = __db_appname(dbp->dbenv, - DB_APP_DATA, NULL, fname, 0, NULL, &rp->re_source)) != 0) - return (ret); - - oflags = F_ISSET(dbp, DB_AM_RDONLY) ? DB_RDONLY : 0; - if ((ret = - __db_open(rp->re_source, oflags, oflags, 0, &rp->re_fd)) != 0) { - __db_err(dbp->dbenv, "%s: %s", rp->re_source, strerror(ret)); - return (ret); - } - - /* - * XXX - * We'd like to test to see if the file is too big to mmap. Since we - * don't know what size or type off_t's or size_t's are, or the largest - * unsigned integral type is, or what random insanity the local C - * compiler will perpetrate, doing the comparison in a portable way is - * flatly impossible. Hope that mmap fails if the file is too large. - */ - if ((ret = __os_ioinfo(rp->re_source, - rp->re_fd, &mbytes, &bytes, NULL)) != 0) { - __db_err(dbp->dbenv, "%s: %s", rp->re_source, strerror(ret)); - return (ret); - } - if (mbytes == 0 && bytes == 0) { - F_SET(rp, RECNO_EOF); - return (0); - } - - size = mbytes * MEGABYTE + bytes; - if ((ret = __db_mapfile(rp->re_source, - rp->re_fd, (size_t)size, 1, &rp->re_smap)) != 0) - return (ret); - rp->re_cmap = rp->re_smap; - rp->re_emap = (u_int8_t *)rp->re_smap + (rp->re_msize = size); - rp->re_irec = F_ISSET(dbp, DB_RE_FIXEDLEN) ? __ram_fmap : __ram_vmap; - return (0); -} - -/* - * __ram_writeback -- - * Rewrite the backing file. - */ -static int -__ram_writeback(dbc) - DBC *dbc; -{ - DB *dbp; - DBT key, data; - RECNO *rp; - db_recno_t keyno; - ssize_t nw; - int fd, ret, t_ret; - u_int8_t delim, *pad; - - dbp = dbc->dbp; - rp = ((BTREE *)dbp->internal)->recno; - - /* If the file wasn't modified, we're done. */ - if (!F_ISSET(rp, RECNO_MODIFIED)) - return (0); - - /* If there's no backing source file, we're done. */ - if (rp->re_source == NULL) { - F_CLR(rp, RECNO_MODIFIED); - return (0); - } - - /* - * Read any remaining records into the tree. - * - * !!! - * This is why we can't support transactions when applications specify - * backing (re_source) files. At this point we have to read in the - * rest of the records from the file so that we can write all of the - * records back out again, which could modify a page for which we'd - * have to log changes and which we don't have locked. This could be - * partially fixed by taking a snapshot of the entire file during the - * db_open(), or, since db_open() isn't transaction protected, as part - * of the first DB operation. But, if a checkpoint occurs then, the - * part of the log holding the copy of the file could be discarded, and - * that would make it impossible to recover in the face of disaster. - * This could all probably be fixed, but it would require transaction - * protecting the backing source file, i.e. mpool would have to know - * about it, and we don't want to go there. - */ - if ((ret = - __ram_update(dbc, DB_MAX_RECORDS, 0)) != 0 && ret != DB_NOTFOUND) - return (ret); - - /* - * !!! - * Close any underlying mmap region. This is required for Windows NT - * (4.0, Service Pack 2) -- if the file is still mapped, the following - * open will fail. - */ - if (rp->re_smap != NULL) { - (void)__db_unmapfile(rp->re_smap, rp->re_msize); - rp->re_smap = NULL; - } - - /* Get rid of any backing file descriptor, just on GP's. */ - if (rp->re_fd != -1) { - (void)__os_close(rp->re_fd); - rp->re_fd = -1; - } - - /* Open the file, truncating it. */ - if ((ret = __db_open(rp->re_source, - DB_SEQUENTIAL | DB_TRUNCATE, - DB_SEQUENTIAL | DB_TRUNCATE, 0, &fd)) != 0) { - __db_err(dbp->dbenv, "%s: %s", rp->re_source, strerror(ret)); - return (ret); - } - - /* - * We step through the records, writing each one out. Use the record - * number and the dbp->get() function, instead of a cursor, so we find - * and write out "deleted" or non-existent records. - */ - memset(&key, 0, sizeof(key)); - memset(&data, 0, sizeof(data)); - key.size = sizeof(db_recno_t); - key.data = &keyno; - - /* - * We'll need the delimiter if we're doing variable-length records, - * and the pad character if we're doing fixed-length records. - */ - delim = rp->re_delim; - if (F_ISSET(dbp, DB_RE_FIXEDLEN)) { - if ((ret = __os_malloc(rp->re_len, NULL, &pad)) != 0) - goto err; - memset(pad, rp->re_pad, rp->re_len); - } else - COMPQUIET(pad, NULL); - for (keyno = 1;; ++keyno) { - switch (ret = dbp->get(dbp, NULL, &key, &data, 0)) { - case 0: - if ((ret = - __os_write(fd, data.data, data.size, &nw)) != 0) - goto err; - if (nw != (ssize_t)data.size) { - ret = EIO; - goto err; - } - break; - case DB_KEYEMPTY: - if (F_ISSET(dbp, DB_RE_FIXEDLEN)) { - if ((ret = - __os_write(fd, pad, rp->re_len, &nw)) != 0) - goto err; - if (nw != (ssize_t)rp->re_len) { - ret = EIO; - goto err; - } - } - break; - case DB_NOTFOUND: - ret = 0; - goto done; - } - if (!F_ISSET(dbp, DB_RE_FIXEDLEN)) { - if ((ret = __os_write(fd, &delim, 1, &nw)) != 0) - goto err; - if (nw != 1) { - ret = EIO; - goto err; - } - } - } - -err: -done: /* Close the file descriptor. */ - if ((t_ret = __os_close(fd)) != 0 || ret == 0) - ret = t_ret; - - if (ret == 0) - F_CLR(rp, RECNO_MODIFIED); - return (ret); -} - -/* - * __ram_fmap -- - * Get fixed length records from a file. - */ -static int -__ram_fmap(dbc, top) - DBC *dbc; - db_recno_t top; -{ - DB *dbp; - DBT data; - RECNO *rp; - db_recno_t recno; - u_int32_t len; - u_int8_t *sp, *ep, *p; - int ret; - - if ((ret = __bam_nrecs(dbc, &recno)) != 0) - return (ret); - - dbp = dbc->dbp; - rp = ((BTREE *)(dbp->internal))->recno; - - if (dbc->rdata.ulen < rp->re_len) { - if ((ret = __os_realloc(&dbc->rdata.data, rp->re_len)) != 0) { - dbc->rdata.ulen = 0; - dbc->rdata.data = NULL; - return (ret); - } - dbc->rdata.ulen = rp->re_len; - } - - memset(&data, 0, sizeof(data)); - data.data = dbc->rdata.data; - data.size = rp->re_len; - - sp = (u_int8_t *)rp->re_cmap; - ep = (u_int8_t *)rp->re_emap; - while (recno < top) { - if (sp >= ep) { - F_SET(rp, RECNO_EOF); - return (DB_NOTFOUND); - } - len = rp->re_len; - for (p = dbc->rdata.data; - sp < ep && len > 0; *p++ = *sp++, --len) - ; - - /* - * Another process may have read this record from the input - * file and stored it into the database already, in which - * case we don't need to repeat that operation. We detect - * this by checking if the last record we've read is greater - * or equal to the number of records in the database. - * - * XXX - * We should just do a seek, since the records are fixed - * length. - */ - if (rp->re_last >= recno) { - if (len != 0) - memset(p, rp->re_pad, len); - - ++recno; - if ((ret = __ram_add(dbc, &recno, &data, 0, 0)) != 0) - return (ret); - } - ++rp->re_last; - } - rp->re_cmap = sp; - return (0); -} - -/* - * __ram_vmap -- - * Get variable length records from a file. - */ -static int -__ram_vmap(dbc, top) - DBC *dbc; - db_recno_t top; -{ - DBT data; - RECNO *rp; - db_recno_t recno; - u_int8_t *sp, *ep; - int delim, ret; - - rp = ((BTREE *)(dbc->dbp->internal))->recno; - - if ((ret = __bam_nrecs(dbc, &recno)) != 0) - return (ret); - - memset(&data, 0, sizeof(data)); - - delim = rp->re_delim; - - sp = (u_int8_t *)rp->re_cmap; - ep = (u_int8_t *)rp->re_emap; - while (recno < top) { - if (sp >= ep) { - F_SET(rp, RECNO_EOF); - return (DB_NOTFOUND); - } - for (data.data = sp; sp < ep && *sp != delim; ++sp) - ; - - /* - * Another process may have read this record from the input - * file and stored it into the database already, in which - * case we don't need to repeat that operation. We detect - * this by checking if the last record we've read is greater - * or equal to the number of records in the database. - */ - if (rp->re_last >= recno) { - data.size = sp - (u_int8_t *)data.data; - ++recno; - if ((ret = __ram_add(dbc, &recno, &data, 0, 0)) != 0) - return (ret); - } - ++rp->re_last; - ++sp; - } - rp->re_cmap = sp; - return (0); -} - -/* - * __ram_add -- - * Add records into the tree. - */ -static int -__ram_add(dbc, recnop, data, flags, bi_flags) - DBC *dbc; - db_recno_t *recnop; - DBT *data; - u_int32_t flags, bi_flags; -{ - BKEYDATA *bk; - CURSOR *cp; - DB *dbp; - PAGE *h; - db_indx_t indx; - int exact, isdeleted, ret, stack; - - dbp = dbc->dbp; - cp = dbc->internal; - -retry: /* Find the slot for insertion. */ - if ((ret = __bam_rsearch(dbc, recnop, - S_INSERT | (flags == DB_APPEND ? S_APPEND : 0), 1, &exact)) != 0) - return (ret); - h = cp->csp->page; - indx = cp->csp->indx; - stack = 1; - - /* - * If re-numbering records, the on-page deleted flag means this record - * was implicitly created. If not re-numbering records, the on-page - * deleted flag means this record was implicitly created, or, it was - * deleted at some time. - * - * If DB_NOOVERWRITE is set and the item already exists in the tree, - * return an error unless the item was either marked for deletion or - * only implicitly created. - */ - isdeleted = 0; - if (exact) { - bk = GET_BKEYDATA(h, indx); - if (B_DISSET(bk->type)) - isdeleted = 1; - else - if (flags == DB_NOOVERWRITE) { - ret = DB_KEYEXIST; - goto err; - } - } - - /* - * Select the arguments for __bam_iitem() and do the insert. If the - * key is an exact match, or we're replacing the data item with a - * new data item, replace the current item. If the key isn't an exact - * match, we're inserting a new key/data pair, before the search - * location. - */ - switch (ret = __bam_iitem(dbc, - &h, &indx, NULL, data, exact ? DB_CURRENT : DB_BEFORE, bi_flags)) { - case 0: - /* - * Don't adjust anything. - * - * If we inserted a record, no cursors need adjusting because - * the only new record it's possible to insert is at the very - * end of the tree. The necessary adjustments to the internal - * page counts were made by __bam_iitem(). - * - * If we overwrote a record, no cursors need adjusting because - * future DBcursor->get calls will simply return the underlying - * record (there's no adjustment made for the DB_CURRENT flag - * when a cursor get operation immediately follows a cursor - * delete operation, and the normal adjustment for the DB_NEXT - * flag is still correct). - */ - break; - case DB_NEEDSPLIT: - /* Discard the stack of pages and split the page. */ - (void)__bam_stkrel(dbc, 0); - stack = 0; - - if ((ret = __bam_split(dbc, recnop)) != 0) - goto err; - - goto retry; - /* NOTREACHED */ - default: - goto err; - } - - -err: if (stack) - __bam_stkrel(dbc, 0); - - return (ret); -} diff --git a/db2/btree/bt_rsearch.c b/db2/btree/bt_rsearch.c deleted file mode 100644 index 8efe405..0000000 --- a/db2/btree/bt_rsearch.c +++ /dev/null @@ -1,391 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994, 1995, 1996 - * Keith Bostic. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993 - * The Regents of the University of California. 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[] = "@(#)bt_rsearch.c 10.21 (Sleepycat) 12/2/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> -#endif - -#include "db_int.h" -#include "db_page.h" -#include "btree.h" - -/* - * __bam_rsearch -- - * Search a btree for a record number. - * - * PUBLIC: int __bam_rsearch __P((DBC *, db_recno_t *, u_int32_t, int, int *)); - */ -int -__bam_rsearch(dbc, recnop, flags, stop, exactp) - DBC *dbc; - db_recno_t *recnop; - u_int32_t flags; - int stop, *exactp; -{ - BINTERNAL *bi; - CURSOR *cp; - DB *dbp; - DB_LOCK lock; - PAGE *h; - RINTERNAL *ri; - db_indx_t indx, top; - db_pgno_t pg; - db_recno_t i, recno, total; - int ret, stack; - - dbp = dbc->dbp; - cp = dbc->internal; - - BT_STK_CLR(cp); - - /* - * There are several ways we search a btree tree. The flags argument - * specifies if we're acquiring read or write locks and if we are - * locking pairs of pages. In addition, if we're adding or deleting - * an item, we have to lock the entire tree, regardless. See btree.h - * for more details. - * - * If write-locking pages, we need to know whether or not to acquire a - * write lock on a page before getting it. This depends on how deep it - * is in tree, which we don't know until we acquire the root page. So, - * if we need to lock the root page we may have to upgrade it later, - * because we won't get the correct lock initially. - * - * Retrieve the root page. - */ - pg = PGNO_ROOT; - stack = LF_ISSET(S_STACK); - if ((ret = __bam_lget(dbc, - 0, pg, stack ? DB_LOCK_WRITE : DB_LOCK_READ, &lock)) != 0) - return (ret); - if ((ret = memp_fget(dbp->mpf, &pg, 0, &h)) != 0) { - (void)__BT_LPUT(dbc, lock); - return (ret); - } - - /* - * Decide if we need to save this page; if we do, write lock it. - * We deliberately don't lock-couple on this call. If the tree - * is tiny, i.e., one page, and two threads are busily updating - * the root page, we're almost guaranteed deadlocks galore, as - * each one gets a read lock and then blocks the other's attempt - * for a write lock. - */ - if (!stack && - ((LF_ISSET(S_PARENT) && (u_int8_t)(stop + 1) >= h->level) || - (LF_ISSET(S_WRITE) && h->level == LEAFLEVEL))) { - (void)memp_fput(dbp->mpf, h, 0); - (void)__BT_LPUT(dbc, lock); - if ((ret = __bam_lget(dbc, 0, pg, DB_LOCK_WRITE, &lock)) != 0) - return (ret); - if ((ret = memp_fget(dbp->mpf, &pg, 0, &h)) != 0) { - (void)__BT_LPUT(dbc, lock); - return (ret); - } - stack = 1; - } - - /* - * If appending to the tree, set the record number now -- we have the - * root page locked. - * - * Delete only deletes exact matches, read only returns exact matches. - * Note, this is different from __bam_search(), which returns non-exact - * matches for read. - * - * The record may not exist. We can only return the correct location - * for the record immediately after the last record in the tree, so do - * a fast check now. - */ - total = RE_NREC(h); - if (LF_ISSET(S_APPEND)) { - *exactp = 0; - *recnop = recno = total + 1; - } else { - recno = *recnop; - if (recno <= total) - *exactp = 1; - else { - *exactp = 0; - if (!LF_ISSET(S_PAST_EOF) || recno > total + 1) { - (void)memp_fput(dbp->mpf, h, 0); - (void)__BT_LPUT(dbc, lock); - return (DB_NOTFOUND); - } - } - } - - /* - * !!! - * Record numbers in the tree are 0-based, but the recno is - * 1-based. All of the calculations below have to take this - * into account. - */ - for (total = 0;;) { - switch (TYPE(h)) { - case P_LBTREE: - recno -= total; - - /* - * There may be logically deleted records on the page, - * walk the page correcting for them. The record may - * not exist if there are enough deleted records in the - * page. - */ - if (recno <= (db_recno_t)NUM_ENT(h) / P_INDX) - for (i = recno - 1;; --i) { - if (B_DISSET(GET_BKEYDATA(h, - i * P_INDX + O_INDX)->type)) - ++recno; - if (i == 0) - break; - } - if (recno > (db_recno_t)NUM_ENT(h) / P_INDX) { - *exactp = 0; - if (!LF_ISSET(S_PAST_EOF) || recno > - (db_recno_t)(NUM_ENT(h) / P_INDX + 1)) { - ret = DB_NOTFOUND; - goto err; - } - - } - - /* Correct from 1-based to 0-based for a page offset. */ - --recno; - BT_STK_ENTER(cp, h, recno * P_INDX, lock, ret); - return (ret); - case P_IBTREE: - for (indx = 0, top = NUM_ENT(h);;) { - bi = GET_BINTERNAL(h, indx); - if (++indx == top || total + bi->nrecs >= recno) - break; - total += bi->nrecs; - } - pg = bi->pgno; - break; - case P_LRECNO: - recno -= total; - - /* Correct from 1-based to 0-based for a page offset. */ - --recno; - BT_STK_ENTER(cp, h, recno, lock, ret); - return (ret); - case P_IRECNO: - for (indx = 0, top = NUM_ENT(h);;) { - ri = GET_RINTERNAL(h, indx); - if (++indx == top || total + ri->nrecs >= recno) - break; - total += ri->nrecs; - } - pg = ri->pgno; - break; - default: - return (__db_pgfmt(dbp, h->pgno)); - } - --indx; - - if (stack) { - /* Return if this is the lowest page wanted. */ - if (LF_ISSET(S_PARENT) && stop == h->level) { - BT_STK_ENTER(cp, h, indx, lock, ret); - return (ret); - } - BT_STK_PUSH(cp, h, indx, lock, ret); - if (ret != 0) - goto err; - - if ((ret = - __bam_lget(dbc, 0, pg, DB_LOCK_WRITE, &lock)) != 0) - goto err; - } else { - /* - * Decide if we want to return a pointer to the next - * page in the stack. If we do, write lock it and - * never unlock it. - */ - if ((LF_ISSET(S_PARENT) && - (u_int8_t)(stop + 1) >= (u_int8_t)(h->level - 1)) || - (h->level - 1) == LEAFLEVEL) - stack = 1; - - (void)memp_fput(dbp->mpf, h, 0); - - if ((ret = - __bam_lget(dbc, 1, pg, stack && LF_ISSET(S_WRITE) ? - DB_LOCK_WRITE : DB_LOCK_READ, &lock)) != 0) - goto err; - } - - if ((ret = memp_fget(dbp->mpf, &pg, 0, &h)) != 0) - goto err; - } - /* NOTREACHED */ - -err: BT_STK_POP(cp); - __bam_stkrel(dbc, 0); - return (ret); -} - -/* - * __bam_adjust -- - * Adjust the tree after adding or deleting a record. - * - * PUBLIC: int __bam_adjust __P((DBC *, int32_t)); - */ -int -__bam_adjust(dbc, adjust) - DBC *dbc; - int32_t adjust; -{ - CURSOR *cp; - DB *dbp; - EPG *epg; - PAGE *h; - int ret; - - dbp = dbc->dbp; - cp = dbc->internal; - - /* Update the record counts for the tree. */ - for (epg = cp->sp; epg <= cp->csp; ++epg) { - h = epg->page; - if (TYPE(h) == P_IBTREE || TYPE(h) == P_IRECNO) { - if (DB_LOGGING(dbc) && - (ret = __bam_cadjust_log(dbp->dbenv->lg_info, - dbc->txn, &LSN(h), 0, dbp->log_fileid, - PGNO(h), &LSN(h), (u_int32_t)epg->indx, - adjust, 1)) != 0) - return (ret); - - if (TYPE(h) == P_IBTREE) - GET_BINTERNAL(h, epg->indx)->nrecs += adjust; - else - GET_RINTERNAL(h, epg->indx)->nrecs += adjust; - - if (PGNO(h) == PGNO_ROOT) - RE_NREC_ADJ(h, adjust); - - if ((ret = memp_fset(dbp->mpf, h, DB_MPOOL_DIRTY)) != 0) - return (ret); - } - } - return (0); -} - -/* - * __bam_nrecs -- - * Return the number of records in the tree. - * - * PUBLIC: int __bam_nrecs __P((DBC *, db_recno_t *)); - */ -int -__bam_nrecs(dbc, rep) - DBC *dbc; - db_recno_t *rep; -{ - DB *dbp; - DB_LOCK lock; - PAGE *h; - db_pgno_t pgno; - int ret; - - dbp = dbc->dbp; - - pgno = PGNO_ROOT; - if ((ret = __bam_lget(dbc, 0, pgno, DB_LOCK_READ, &lock)) != 0) - return (ret); - if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0) - return (ret); - - *rep = RE_NREC(h); - - (void)memp_fput(dbp->mpf, h, 0); - (void)__BT_TLPUT(dbc, lock); - - return (0); -} - -/* - * __bam_total -- - * Return the number of records below a page. - * - * PUBLIC: db_recno_t __bam_total __P((PAGE *)); - */ -db_recno_t -__bam_total(h) - PAGE *h; -{ - db_recno_t nrecs; - db_indx_t indx, top; - - nrecs = 0; - top = NUM_ENT(h); - - switch (TYPE(h)) { - case P_LBTREE: - /* Check for logically deleted records. */ - for (indx = 0; indx < top; indx += P_INDX) - if (!B_DISSET(GET_BKEYDATA(h, indx + O_INDX)->type)) - ++nrecs; - break; - case P_IBTREE: - for (indx = 0; indx < top; indx += O_INDX) - nrecs += GET_BINTERNAL(h, indx)->nrecs; - break; - case P_LRECNO: - nrecs = NUM_ENT(h); - break; - case P_IRECNO: - for (indx = 0; indx < top; indx += O_INDX) - nrecs += GET_RINTERNAL(h, indx)->nrecs; - break; - } - - return (nrecs); -} diff --git a/db2/btree/bt_search.c b/db2/btree/bt_search.c deleted file mode 100644 index 1f439a4..0000000 --- a/db2/btree/bt_search.c +++ /dev/null @@ -1,369 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994, 1995, 1996 - * Keith Bostic. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994, 1995 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * 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[] = "@(#)bt_search.c 10.25 (Sleepycat) 12/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 "db_page.h" -#include "btree.h" - -/* - * __bam_search -- - * Search a btree for a key. - * - * PUBLIC: int __bam_search __P((DBC *, - * PUBLIC: const DBT *, u_int32_t, int, db_recno_t *, int *)); - */ -int -__bam_search(dbc, key, flags, stop, recnop, exactp) - DBC *dbc; - const DBT *key; - u_int32_t flags; - int stop, *exactp; - db_recno_t *recnop; -{ - BTREE *t; - CURSOR *cp; - DB *dbp; - DB_LOCK lock; - PAGE *h; - db_indx_t base, i, indx, lim; - db_pgno_t pg; - db_recno_t recno; - int cmp, jump, ret, stack; - - dbp = dbc->dbp; - cp = dbc->internal; - t = dbp->internal; - recno = 0; - - BT_STK_CLR(cp); - - /* - * There are several ways we search a btree tree. The flags argument - * specifies if we're acquiring read or write locks, if we position - * to the first or last item in a set of duplicates, if we return - * deleted items, and if we are locking pairs of pages. In addition, - * if we're modifying record numbers, we have to lock the entire tree - * regardless. See btree.h for more details. - * - * If write-locking pages, we need to know whether or not to acquire a - * write lock on a page before getting it. This depends on how deep it - * is in tree, which we don't know until we acquire the root page. So, - * if we need to lock the root page we may have to upgrade it later, - * because we won't get the correct lock initially. - * - * Retrieve the root page. - */ - pg = PGNO_ROOT; - stack = F_ISSET(dbp, DB_BT_RECNUM) && LF_ISSET(S_STACK); - if ((ret = __bam_lget(dbc, - 0, pg, stack ? DB_LOCK_WRITE : DB_LOCK_READ, &lock)) != 0) - return (ret); - if ((ret = memp_fget(dbp->mpf, &pg, 0, &h)) != 0) { - (void)__BT_LPUT(dbc, lock); - return (ret); - } - - /* - * Decide if we need to save this page; if we do, write lock it. - * We deliberately don't lock-couple on this call. If the tree - * is tiny, i.e., one page, and two threads are busily updating - * the root page, we're almost guaranteed deadlocks galore, as - * each one gets a read lock and then blocks the other's attempt - * for a write lock. - */ - if (!stack && - ((LF_ISSET(S_PARENT) && (u_int8_t)(stop + 1) >= h->level) || - (LF_ISSET(S_WRITE) && h->level == LEAFLEVEL))) { - (void)memp_fput(dbp->mpf, h, 0); - (void)__BT_LPUT(dbc, lock); - if ((ret = __bam_lget(dbc, 0, pg, DB_LOCK_WRITE, &lock)) != 0) - return (ret); - if ((ret = memp_fget(dbp->mpf, &pg, 0, &h)) != 0) { - (void)__BT_LPUT(dbc, lock); - return (ret); - } - stack = 1; - } - - for (;;) { - /* - * Do a binary search on the current page. If we're searching - * a leaf page, we have to manipulate the indices in groups of - * two. If we're searching an internal page, they're an index - * per page item. If we find an exact match on a leaf page, - * we're done. - */ - jump = TYPE(h) == P_LBTREE ? P_INDX : O_INDX; - for (base = 0, - lim = NUM_ENT(h) / (db_indx_t)jump; lim != 0; lim >>= 1) { - indx = base + ((lim >> 1) * jump); - if ((cmp = - __bam_cmp(dbp, key, h, indx, t->bt_compare)) == 0) { - if (TYPE(h) == P_LBTREE) - goto match; - goto next; - } - if (cmp > 0) { - base = indx + jump; - --lim; - } - } - - /* - * No match found. Base is the smallest index greater than - * key and may be zero or a last + O_INDX index. - * - * If it's a leaf page, return base as the "found" value. - * Delete only deletes exact matches. - */ - if (TYPE(h) == P_LBTREE) { - *exactp = 0; - - if (LF_ISSET(S_EXACT)) - goto notfound; - - /* - * !!! - * Possibly returning a deleted record -- DB_SET_RANGE, - * DB_KEYFIRST and DB_KEYLAST don't require an exact - * match, and we don't want to walk multiple pages here - * to find an undeleted record. This is handled in the - * __bam_c_search() routine. - */ - BT_STK_ENTER(cp, h, base, lock, ret); - return (ret); - } - - /* - * If it's not a leaf page, record the internal page (which is - * a parent page for the key). Decrement the base by 1 if it's - * non-zero so that if a split later occurs, the inserted page - * will be to the right of the saved page. - */ - indx = base > 0 ? base - O_INDX : base; - - /* - * If we're trying to calculate the record number, sum up - * all the record numbers on this page up to the indx point. - */ - if (recnop != NULL) - for (i = 0; i < indx; ++i) - recno += GET_BINTERNAL(h, i)->nrecs; - -next: pg = GET_BINTERNAL(h, indx)->pgno; - if (stack) { - /* Return if this is the lowest page wanted. */ - if (LF_ISSET(S_PARENT) && stop == h->level) { - BT_STK_ENTER(cp, h, indx, lock, ret); - return (ret); - } - BT_STK_PUSH(cp, h, indx, lock, ret); - if (ret != 0) - goto err; - - if ((ret = - __bam_lget(dbc, 0, pg, DB_LOCK_WRITE, &lock)) != 0) - goto err; - } else { - /* - * Decide if we want to return a reference to the next - * page in the return stack. If so, lock it and never - * unlock it. - */ - if ((LF_ISSET(S_PARENT) && - (u_int8_t)(stop + 1) >= (u_int8_t)(h->level - 1)) || - (h->level - 1) == LEAFLEVEL) - stack = 1; - - (void)memp_fput(dbp->mpf, h, 0); - - if ((ret = - __bam_lget(dbc, 1, pg, stack && LF_ISSET(S_WRITE) ? - DB_LOCK_WRITE : DB_LOCK_READ, &lock)) != 0) - goto err; - } - if ((ret = memp_fget(dbp->mpf, &pg, 0, &h)) != 0) - goto err; - } - /* NOTREACHED */ - -match: *exactp = 1; - - /* - * If we're trying to calculate the record number, add in the - * offset on this page and correct for the fact that records - * in the tree are 0-based. - */ - if (recnop != NULL) - *recnop = recno + (indx / P_INDX) + 1; - - /* - * If we got here, we know that we have a btree leaf page. - * - * If there are duplicates, go to the first/last one. This is - * safe because we know that we're not going to leave the page, - * all duplicate sets that are not on overflow pages exist on a - * single leaf page. - */ - if (LF_ISSET(S_DUPLAST)) - while (indx < (db_indx_t)(NUM_ENT(h) - P_INDX) && - h->inp[indx] == h->inp[indx + P_INDX]) - indx += P_INDX; - else - while (indx > 0 && - h->inp[indx] == h->inp[indx - P_INDX]) - indx -= P_INDX; - - /* - * Now check if we are allowed to return deleted items; if not - * find the next (or previous) non-deleted item. - */ - if (LF_ISSET(S_DELNO)) { - if (LF_ISSET(S_DUPLAST)) - while (B_DISSET(GET_BKEYDATA(h, indx + O_INDX)->type) && - indx > 0 && - h->inp[indx] == h->inp[indx - P_INDX]) - indx -= P_INDX; - else - while (B_DISSET(GET_BKEYDATA(h, indx + O_INDX)->type) && - indx < (db_indx_t)(NUM_ENT(h) - P_INDX) && - h->inp[indx] == h->inp[indx + P_INDX]) - indx += P_INDX; - - if (B_DISSET(GET_BKEYDATA(h, indx + O_INDX)->type)) - goto notfound; - } - - BT_STK_ENTER(cp, h, indx, lock, ret); - return (ret); - -notfound: - (void)memp_fput(dbp->mpf, h, 0); - (void)__BT_LPUT(dbc, lock); - ret = DB_NOTFOUND; - -err: if (cp->csp > cp->sp) { - BT_STK_POP(cp); - __bam_stkrel(dbc, 0); - } - return (ret); -} - -/* - * __bam_stkrel -- - * Release all pages currently held in the stack. - * - * PUBLIC: int __bam_stkrel __P((DBC *, int)); - */ -int -__bam_stkrel(dbc, nolocks) - DBC *dbc; - int nolocks; -{ - CURSOR *cp; - DB *dbp; - EPG *epg; - - dbp = dbc->dbp; - cp = dbc->internal; - - /* Release inner pages first. */ - for (epg = cp->sp; epg <= cp->csp; ++epg) { - if (epg->page != NULL) - (void)memp_fput(dbp->mpf, epg->page, 0); - if (epg->lock != LOCK_INVALID) { - if (nolocks) - (void)__BT_LPUT(dbc, epg->lock); - else - (void)__BT_TLPUT(dbc, epg->lock); - } - } - - /* Clear the stack, all pages have been released. */ - BT_STK_CLR(cp); - - return (0); -} - -/* - * __bam_stkgrow -- - * Grow the stack. - * - * PUBLIC: int __bam_stkgrow __P((CURSOR *)); - */ -int -__bam_stkgrow(cp) - CURSOR *cp; -{ - EPG *p; - size_t entries; - int ret; - - entries = cp->esp - cp->sp; - - if ((ret = __os_calloc(entries * 2, sizeof(EPG), &p)) != 0) - return (ret); - memcpy(p, cp->sp, entries * sizeof(EPG)); - if (cp->sp != cp->stack) - __os_free(cp->sp, entries * sizeof(EPG)); - cp->sp = p; - cp->csp = p + entries; - cp->esp = p + entries * 2; - return (0); -} diff --git a/db2/btree/bt_split.c b/db2/btree/bt_split.c deleted file mode 100644 index 1d8e926..0000000 --- a/db2/btree/bt_split.c +++ /dev/null @@ -1,966 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994, 1995, 1996 - * Keith Bostic. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994, 1995 - * The Regents of the University of California. 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[] = "@(#)bt_split.c 10.33 (Sleepycat) 10/13/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <limits.h> -#include <string.h> -#endif - -#include "db_int.h" -#include "db_page.h" -#include "btree.h" - -static int __bam_broot __P((DBC *, PAGE *, PAGE *, PAGE *)); -static int __bam_page __P((DBC *, EPG *, EPG *)); -static int __bam_pinsert __P((DBC *, EPG *, PAGE *, PAGE *)); -static int __bam_psplit __P((DBC *, EPG *, PAGE *, PAGE *, db_indx_t *)); -static int __bam_root __P((DBC *, EPG *)); -static int __ram_root __P((DBC *, PAGE *, PAGE *, PAGE *)); - -/* - * __bam_split -- - * Split a page. - * - * PUBLIC: int __bam_split __P((DBC *, void *)); - */ -int -__bam_split(dbc, arg) - DBC *dbc; - void *arg; -{ - CURSOR *cp; - DB *dbp; - enum { UP, DOWN } dir; - int exact, level, ret; - - dbp = dbc->dbp; - cp = dbc->internal; - - /* - * The locking protocol we use to avoid deadlock to acquire locks by - * walking down the tree, but we do it as lazily as possible, locking - * the root only as a last resort. We expect all stack pages to have - * been discarded before we're called; we discard all short-term locks. - * - * When __bam_split is first called, we know that a leaf page was too - * full for an insert. We don't know what leaf page it was, but we - * have the key/recno that caused the problem. We call XX_search to - * reacquire the leaf page, but this time get both the leaf page and - * its parent, locked. We then split the leaf page and see if the new - * internal key will fit into the parent page. If it will, we're done. - * - * If it won't, we discard our current locks and repeat the process, - * only this time acquiring the parent page and its parent, locked. - * This process repeats until we succeed in the split, splitting the - * root page as the final resort. The entire process then repeats, - * as necessary, until we split a leaf page. - * - * XXX - * A traditional method of speeding this up is to maintain a stack of - * the pages traversed in the original search. You can detect if the - * stack is correct by storing the page's LSN when it was searched and - * comparing that LSN with the current one when it's locked during the - * split. This would be an easy change for this code, but I have no - * numbers that indicate it's worthwhile. - */ - for (dir = UP, level = LEAFLEVEL;; dir == UP ? ++level : --level) { - /* - * Acquire a page and its parent, locked. - */ - if ((ret = (dbp->type == DB_BTREE ? - __bam_search(dbc, arg, S_WRPAIR, level, NULL, &exact) : - __bam_rsearch(dbc, - (db_recno_t *)arg, S_WRPAIR, level, &exact))) != 0) - return (ret); - - /* Split the page. */ - ret = cp->csp[0].page->pgno == PGNO_ROOT ? - __bam_root(dbc, &cp->csp[0]) : - __bam_page(dbc, &cp->csp[-1], &cp->csp[0]); - BT_STK_CLR(cp); - - switch (ret) { - case 0: - /* Once we've split the leaf page, we're done. */ - if (level == LEAFLEVEL) - return (0); - - /* Switch directions. */ - if (dir == UP) - dir = DOWN; - break; - case DB_NEEDSPLIT: - /* - * It's possible to fail to split repeatedly, as other - * threads may be modifying the tree, or the page usage - * is sufficiently bad that we don't get enough space - * the first time. - */ - if (dir == DOWN) - dir = UP; - break; - default: - return (ret); - } - } - /* NOTREACHED */ -} - -/* - * __bam_root -- - * Split the root page of a btree. - */ -static int -__bam_root(dbc, cp) - DBC *dbc; - EPG *cp; -{ - DB *dbp; - PAGE *lp, *rp; - db_indx_t split; - int ret; - - dbp = dbc->dbp; - - /* Yeah, right. */ - if (cp->page->level >= MAXBTREELEVEL) { - ret = ENOSPC; - goto err; - } - - /* Create new left and right pages for the split. */ - lp = rp = NULL; - if ((ret = __bam_new(dbc, TYPE(cp->page), &lp)) != 0 || - (ret = __bam_new(dbc, TYPE(cp->page), &rp)) != 0) - goto err; - P_INIT(lp, dbp->pgsize, lp->pgno, - PGNO_INVALID, ISINTERNAL(cp->page) ? PGNO_INVALID : rp->pgno, - cp->page->level, TYPE(cp->page)); - P_INIT(rp, dbp->pgsize, rp->pgno, - ISINTERNAL(cp->page) ? PGNO_INVALID : lp->pgno, PGNO_INVALID, - cp->page->level, TYPE(cp->page)); - - /* Split the page. */ - if ((ret = __bam_psplit(dbc, cp, lp, rp, &split)) != 0) - goto err; - - /* Log the change. */ - if (DB_LOGGING(dbc)) { - DBT __a; - DB_LSN __lsn; - memset(&__a, 0, sizeof(__a)); - __a.data = cp->page; - __a.size = dbp->pgsize; - ZERO_LSN(__lsn); - if ((ret = __bam_split_log(dbp->dbenv->lg_info, dbc->txn, - &LSN(cp->page), 0, dbp->log_fileid, PGNO(lp), &LSN(lp), - PGNO(rp), &LSN(rp), (u_int32_t)NUM_ENT(lp), 0, &__lsn, - &__a)) != 0) - goto err; - LSN(lp) = LSN(rp) = LSN(cp->page); - } - - /* Clean up the new root page. */ - if ((ret = (dbp->type == DB_RECNO ? - __ram_root(dbc, cp->page, lp, rp) : - __bam_broot(dbc, cp->page, lp, rp))) != 0) - goto err; - - /* Adjust any cursors. Do it last so we don't have to undo it. */ - __bam_ca_split(dbp, cp->page->pgno, lp->pgno, rp->pgno, split, 1); - - /* Success -- write the real pages back to the store. */ - (void)memp_fput(dbp->mpf, cp->page, DB_MPOOL_DIRTY); - (void)__BT_TLPUT(dbc, cp->lock); - (void)memp_fput(dbp->mpf, lp, DB_MPOOL_DIRTY); - (void)memp_fput(dbp->mpf, rp, DB_MPOOL_DIRTY); - - return (0); - -err: if (lp != NULL) - (void)__bam_free(dbc, lp); - if (rp != NULL) - (void)__bam_free(dbc, rp); - (void)memp_fput(dbp->mpf, cp->page, 0); - (void)__BT_TLPUT(dbc, cp->lock); - return (ret); -} - -/* - * __bam_page -- - * Split the non-root page of a btree. - */ -static int -__bam_page(dbc, pp, cp) - DBC *dbc; - EPG *pp, *cp; -{ - DB *dbp; - DB_LOCK tplock; - PAGE *lp, *rp, *tp; - db_indx_t split; - int ret; - - dbp = dbc->dbp; - lp = rp = tp = NULL; - ret = -1; - - /* Create new right page for the split. */ - if ((ret = __bam_new(dbc, TYPE(cp->page), &rp)) != 0) - goto err; - P_INIT(rp, dbp->pgsize, rp->pgno, - ISINTERNAL(cp->page) ? PGNO_INVALID : cp->page->pgno, - ISINTERNAL(cp->page) ? PGNO_INVALID : cp->page->next_pgno, - cp->page->level, TYPE(cp->page)); - - /* Create new left page for the split. */ - if ((ret = __os_malloc(dbp->pgsize, NULL, &lp)) != 0) - goto err; - P_INIT(lp, dbp->pgsize, cp->page->pgno, - ISINTERNAL(cp->page) ? PGNO_INVALID : cp->page->prev_pgno, - ISINTERNAL(cp->page) ? PGNO_INVALID : rp->pgno, - cp->page->level, TYPE(cp->page)); - ZERO_LSN(lp->lsn); - - /* - * Split right. - * - * Only the indices are sorted on the page, i.e., the key/data pairs - * aren't, so it's simpler to copy the data from the split page onto - * two new pages instead of copying half the data to the right page - * and compacting the left page in place. Since the left page can't - * change, we swap the original and the allocated left page after the - * split. - */ - if ((ret = __bam_psplit(dbc, cp, lp, rp, &split)) != 0) - goto err; - - /* - * Fix up the previous pointer of any leaf page following the split - * page. - * - * !!! - * There are interesting deadlock situations here as we write-lock a - * page that's not in our direct ancestry. Consider a cursor walking - * through the leaf pages, that has the previous page read-locked and - * is waiting on a lock for the page we just split. It will deadlock - * here. If this is a problem, we can fail in the split; it's not a - * problem as the split will succeed after the cursor passes through - * the page we're splitting. - */ - if (TYPE(cp->page) == P_LBTREE && rp->next_pgno != PGNO_INVALID) { - if ((ret = __bam_lget(dbc, - 0, rp->next_pgno, DB_LOCK_WRITE, &tplock)) != 0) - goto err; - if ((ret = memp_fget(dbp->mpf, &rp->next_pgno, 0, &tp)) != 0) - goto err; - } - - /* Insert the new pages into the parent page. */ - if ((ret = __bam_pinsert(dbc, pp, lp, rp)) != 0) - goto err; - - /* Log the change. */ - if (DB_LOGGING(dbc)) { - DBT __a; - DB_LSN __lsn; - memset(&__a, 0, sizeof(__a)); - __a.data = cp->page; - __a.size = dbp->pgsize; - if (tp == NULL) - ZERO_LSN(__lsn); - if ((ret = __bam_split_log(dbp->dbenv->lg_info, dbc->txn, - &cp->page->lsn, 0, dbp->log_fileid, PGNO(cp->page), - &LSN(cp->page), PGNO(rp), &LSN(rp), (u_int32_t)NUM_ENT(lp), - tp == NULL ? 0 : PGNO(tp), - tp == NULL ? &__lsn : &LSN(tp), &__a)) != 0) - goto err; - - LSN(lp) = LSN(rp) = LSN(cp->page); - if (tp != NULL) - LSN(tp) = LSN(cp->page); - } - - /* Copy the allocated page into place. */ - memcpy(cp->page, lp, LOFFSET(lp)); - memcpy((u_int8_t *)cp->page + HOFFSET(lp), - (u_int8_t *)lp + HOFFSET(lp), dbp->pgsize - HOFFSET(lp)); - __os_free(lp, dbp->pgsize); - lp = NULL; - - /* Finish the next-page link. */ - if (tp != NULL) - tp->prev_pgno = rp->pgno; - - /* Adjust any cursors. Do so last so we don't have to undo it. */ - __bam_ca_split(dbp, cp->page->pgno, cp->page->pgno, rp->pgno, split, 0); - - /* Success -- write the real pages back to the store. */ - (void)memp_fput(dbp->mpf, pp->page, DB_MPOOL_DIRTY); - (void)__BT_TLPUT(dbc, pp->lock); - (void)memp_fput(dbp->mpf, cp->page, DB_MPOOL_DIRTY); - (void)__BT_TLPUT(dbc, cp->lock); - (void)memp_fput(dbp->mpf, rp, DB_MPOOL_DIRTY); - if (tp != NULL) { - (void)memp_fput(dbp->mpf, tp, DB_MPOOL_DIRTY); - (void)__BT_TLPUT(dbc, tplock); - } - return (0); - -err: if (lp != NULL) - __os_free(lp, dbp->pgsize); - if (rp != NULL) - (void)__bam_free(dbc, rp); - if (tp != NULL) { - (void)memp_fput(dbp->mpf, tp, 0); - if (ret == DB_NEEDSPLIT) - (void)__BT_LPUT(dbc, tplock); - else - (void)__BT_TLPUT(dbc, tplock); - } - (void)memp_fput(dbp->mpf, pp->page, 0); - if (ret == DB_NEEDSPLIT) - (void)__BT_LPUT(dbc, pp->lock); - else - (void)__BT_TLPUT(dbc, pp->lock); - (void)memp_fput(dbp->mpf, cp->page, 0); - if (ret == DB_NEEDSPLIT) - (void)__BT_LPUT(dbc, cp->lock); - else - (void)__BT_TLPUT(dbc, cp->lock); - return (ret); -} - -/* - * __bam_broot -- - * Fix up the btree root page after it has been split. - */ -static int -__bam_broot(dbc, rootp, lp, rp) - DBC *dbc; - PAGE *rootp, *lp, *rp; -{ - BINTERNAL bi, *child_bi; - BKEYDATA *child_bk; - DB *dbp; - DBT hdr, data; - int ret; - - dbp = dbc->dbp; - - /* - * If the root page was a leaf page, change it into an internal page. - * We copy the key we split on (but not the key's data, in the case of - * a leaf page) to the new root page. - */ - P_INIT(rootp, dbp->pgsize, - PGNO_ROOT, PGNO_INVALID, PGNO_INVALID, lp->level + 1, P_IBTREE); - - memset(&data, 0, sizeof(data)); - memset(&hdr, 0, sizeof(hdr)); - - /* - * The btree comparison code guarantees that the left-most key on any - * level of the tree is never used, so it doesn't need to be filled in. - */ - memset(&bi, 0, sizeof(bi)); - bi.len = 0; - B_TSET(bi.type, B_KEYDATA, 0); - bi.pgno = lp->pgno; - if (F_ISSET(dbp, DB_BT_RECNUM)) { - bi.nrecs = __bam_total(lp); - RE_NREC_SET(rootp, bi.nrecs); - } - hdr.data = &bi; - hdr.size = SSZA(BINTERNAL, data); - if ((ret = - __db_pitem(dbc, rootp, 0, BINTERNAL_SIZE(0), &hdr, NULL)) != 0) - return (ret); - - switch (TYPE(rp)) { - case P_IBTREE: - /* Copy the first key of the child page onto the root page. */ - child_bi = GET_BINTERNAL(rp, 0); - - bi.len = child_bi->len; - B_TSET(bi.type, child_bi->type, 0); - bi.pgno = rp->pgno; - if (F_ISSET(dbp, DB_BT_RECNUM)) { - bi.nrecs = __bam_total(rp); - RE_NREC_ADJ(rootp, bi.nrecs); - } - hdr.data = &bi; - hdr.size = SSZA(BINTERNAL, data); - data.data = child_bi->data; - data.size = child_bi->len; - if ((ret = __db_pitem(dbc, rootp, 1, - BINTERNAL_SIZE(child_bi->len), &hdr, &data)) != 0) - return (ret); - - /* Increment the overflow ref count. */ - if (B_TYPE(child_bi->type) == B_OVERFLOW) - if ((ret = __db_ovref(dbc, - ((BOVERFLOW *)(child_bi->data))->pgno, 1)) != 0) - return (ret); - break; - case P_LBTREE: - /* Copy the first key of the child page onto the root page. */ - child_bk = GET_BKEYDATA(rp, 0); - switch (B_TYPE(child_bk->type)) { - case B_KEYDATA: - bi.len = child_bk->len; - B_TSET(bi.type, child_bk->type, 0); - bi.pgno = rp->pgno; - if (F_ISSET(dbp, DB_BT_RECNUM)) { - bi.nrecs = __bam_total(rp); - RE_NREC_ADJ(rootp, bi.nrecs); - } - hdr.data = &bi; - hdr.size = SSZA(BINTERNAL, data); - data.data = child_bk->data; - data.size = child_bk->len; - if ((ret = __db_pitem(dbc, rootp, 1, - BINTERNAL_SIZE(child_bk->len), &hdr, &data)) != 0) - return (ret); - break; - case B_DUPLICATE: - case B_OVERFLOW: - bi.len = BOVERFLOW_SIZE; - B_TSET(bi.type, child_bk->type, 0); - bi.pgno = rp->pgno; - if (F_ISSET(dbp, DB_BT_RECNUM)) { - bi.nrecs = __bam_total(rp); - RE_NREC_ADJ(rootp, bi.nrecs); - } - hdr.data = &bi; - hdr.size = SSZA(BINTERNAL, data); - data.data = child_bk; - data.size = BOVERFLOW_SIZE; - if ((ret = __db_pitem(dbc, rootp, 1, - BINTERNAL_SIZE(BOVERFLOW_SIZE), &hdr, &data)) != 0) - return (ret); - - /* Increment the overflow ref count. */ - if (B_TYPE(child_bk->type) == B_OVERFLOW) - if ((ret = __db_ovref(dbc, - ((BOVERFLOW *)child_bk)->pgno, 1)) != 0) - return (ret); - break; - default: - return (__db_pgfmt(dbp, rp->pgno)); - } - break; - default: - return (__db_pgfmt(dbp, rp->pgno)); - } - return (0); -} - -/* - * __ram_root -- - * Fix up the recno root page after it has been split. - */ -static int -__ram_root(dbc, rootp, lp, rp) - DBC *dbc; - PAGE *rootp, *lp, *rp; -{ - DB *dbp; - DBT hdr; - RINTERNAL ri; - int ret; - - dbp = dbc->dbp; - - /* Initialize the page. */ - P_INIT(rootp, dbp->pgsize, - PGNO_ROOT, PGNO_INVALID, PGNO_INVALID, lp->level + 1, P_IRECNO); - - /* Initialize the header. */ - memset(&hdr, 0, sizeof(hdr)); - hdr.data = &ri; - hdr.size = RINTERNAL_SIZE; - - /* Insert the left and right keys, set the header information. */ - ri.pgno = lp->pgno; - ri.nrecs = __bam_total(lp); - if ((ret = __db_pitem(dbc, rootp, 0, RINTERNAL_SIZE, &hdr, NULL)) != 0) - return (ret); - RE_NREC_SET(rootp, ri.nrecs); - ri.pgno = rp->pgno; - ri.nrecs = __bam_total(rp); - if ((ret = __db_pitem(dbc, rootp, 1, RINTERNAL_SIZE, &hdr, NULL)) != 0) - return (ret); - RE_NREC_ADJ(rootp, ri.nrecs); - return (0); -} - -/* - * __bam_pinsert -- - * Insert a new key into a parent page, completing the split. - */ -static int -__bam_pinsert(dbc, parent, lchild, rchild) - DBC *dbc; - EPG *parent; - PAGE *lchild, *rchild; -{ - BINTERNAL bi, *child_bi; - BKEYDATA *child_bk, *tmp_bk; - BTREE *t; - DB *dbp; - DBT a, b, hdr, data; - PAGE *ppage; - RINTERNAL ri; - db_indx_t off; - db_recno_t nrecs; - u_int32_t n, nbytes, nksize; - int ret; - - dbp = dbc->dbp; - t = dbp->internal; - ppage = parent->page; - - /* If handling record numbers, count records split to the right page. */ - nrecs = dbp->type == DB_RECNO || F_ISSET(dbp, DB_BT_RECNUM) ? - __bam_total(rchild) : 0; - - /* - * Now we insert the new page's first key into the parent page, which - * completes the split. The parent points to a PAGE and a page index - * offset, where the new key goes ONE AFTER the index, because we split - * to the right. - * - * XXX - * Some btree algorithms replace the key for the old page as well as - * the new page. We don't, as there's no reason to believe that the - * first key on the old page is any better than the key we have, and, - * in the case of a key being placed at index 0 causing the split, the - * key is unavailable. - */ - off = parent->indx + O_INDX; - - /* - * Calculate the space needed on the parent page. - * - * Prefix trees: space hack used when inserting into BINTERNAL pages. - * Retain only what's needed to distinguish between the new entry and - * the LAST entry on the page to its left. If the keys compare equal, - * retain the entire key. We ignore overflow keys, and the entire key - * must be retained for the next-to-leftmost key on the leftmost page - * of each level, or the search will fail. Applicable ONLY to internal - * pages that have leaf pages as children. Further reduction of the - * key between pairs of internal pages loses too much information. - */ - switch (TYPE(rchild)) { - case P_IBTREE: - child_bi = GET_BINTERNAL(rchild, 0); - nbytes = BINTERNAL_PSIZE(child_bi->len); - - if (P_FREESPACE(ppage) < nbytes) - return (DB_NEEDSPLIT); - - /* Add a new record for the right page. */ - memset(&bi, 0, sizeof(bi)); - bi.len = child_bi->len; - B_TSET(bi.type, child_bi->type, 0); - bi.pgno = rchild->pgno; - bi.nrecs = nrecs; - memset(&hdr, 0, sizeof(hdr)); - hdr.data = &bi; - hdr.size = SSZA(BINTERNAL, data); - memset(&data, 0, sizeof(data)); - data.data = child_bi->data; - data.size = child_bi->len; - if ((ret = __db_pitem(dbc, ppage, off, - BINTERNAL_SIZE(child_bi->len), &hdr, &data)) != 0) - return (ret); - - /* Increment the overflow ref count. */ - if (B_TYPE(child_bi->type) == B_OVERFLOW) - if ((ret = __db_ovref(dbc, - ((BOVERFLOW *)(child_bi->data))->pgno, 1)) != 0) - return (ret); - break; - case P_LBTREE: - child_bk = GET_BKEYDATA(rchild, 0); - switch (B_TYPE(child_bk->type)) { - case B_KEYDATA: - nbytes = BINTERNAL_PSIZE(child_bk->len); - nksize = child_bk->len; - if (t->bt_prefix == NULL) - goto noprefix; - if (ppage->prev_pgno == PGNO_INVALID && off <= 1) - goto noprefix; - tmp_bk = GET_BKEYDATA(lchild, NUM_ENT(lchild) - P_INDX); - if (B_TYPE(tmp_bk->type) != B_KEYDATA) - goto noprefix; - memset(&a, 0, sizeof(a)); - a.size = tmp_bk->len; - a.data = tmp_bk->data; - memset(&b, 0, sizeof(b)); - b.size = child_bk->len; - b.data = child_bk->data; - nksize = t->bt_prefix(&a, &b); - if ((n = BINTERNAL_PSIZE(nksize)) < nbytes) - nbytes = n; - else -noprefix: nksize = child_bk->len; - - if (P_FREESPACE(ppage) < nbytes) - return (DB_NEEDSPLIT); - - memset(&bi, 0, sizeof(bi)); - bi.len = nksize; - B_TSET(bi.type, child_bk->type, 0); - bi.pgno = rchild->pgno; - bi.nrecs = nrecs; - memset(&hdr, 0, sizeof(hdr)); - hdr.data = &bi; - hdr.size = SSZA(BINTERNAL, data); - memset(&data, 0, sizeof(data)); - data.data = child_bk->data; - data.size = nksize; - if ((ret = __db_pitem(dbc, ppage, off, - BINTERNAL_SIZE(nksize), &hdr, &data)) != 0) - return (ret); - break; - case B_DUPLICATE: - case B_OVERFLOW: - nbytes = BINTERNAL_PSIZE(BOVERFLOW_SIZE); - - if (P_FREESPACE(ppage) < nbytes) - return (DB_NEEDSPLIT); - - memset(&bi, 0, sizeof(bi)); - bi.len = BOVERFLOW_SIZE; - B_TSET(bi.type, child_bk->type, 0); - bi.pgno = rchild->pgno; - bi.nrecs = nrecs; - memset(&hdr, 0, sizeof(hdr)); - hdr.data = &bi; - hdr.size = SSZA(BINTERNAL, data); - memset(&data, 0, sizeof(data)); - data.data = child_bk; - data.size = BOVERFLOW_SIZE; - if ((ret = __db_pitem(dbc, ppage, off, - BINTERNAL_SIZE(BOVERFLOW_SIZE), &hdr, &data)) != 0) - return (ret); - - /* Increment the overflow ref count. */ - if (B_TYPE(child_bk->type) == B_OVERFLOW) - if ((ret = __db_ovref(dbc, - ((BOVERFLOW *)child_bk)->pgno, 1)) != 0) - return (ret); - break; - default: - return (__db_pgfmt(dbp, rchild->pgno)); - } - break; - case P_IRECNO: - case P_LRECNO: - nbytes = RINTERNAL_PSIZE; - - if (P_FREESPACE(ppage) < nbytes) - return (DB_NEEDSPLIT); - - /* Add a new record for the right page. */ - memset(&hdr, 0, sizeof(hdr)); - hdr.data = &ri; - hdr.size = RINTERNAL_SIZE; - ri.pgno = rchild->pgno; - ri.nrecs = nrecs; - if ((ret = __db_pitem(dbc, - ppage, off, RINTERNAL_SIZE, &hdr, NULL)) != 0) - return (ret); - break; - default: - return (__db_pgfmt(dbp, rchild->pgno)); - } - - /* Adjust the parent page's left page record count. */ - if (dbp->type == DB_RECNO || F_ISSET(dbp, DB_BT_RECNUM)) { - /* Log the change. */ - if (DB_LOGGING(dbc) && - (ret = __bam_cadjust_log(dbp->dbenv->lg_info, - dbc->txn, &LSN(ppage), 0, dbp->log_fileid, - PGNO(ppage), &LSN(ppage), (u_int32_t)parent->indx, - -(int32_t)nrecs, (int32_t)0)) != 0) - return (ret); - - /* Update the left page count. */ - if (dbp->type == DB_RECNO) - GET_RINTERNAL(ppage, parent->indx)->nrecs -= nrecs; - else - GET_BINTERNAL(ppage, parent->indx)->nrecs -= nrecs; - } - - return (0); -} - -/* - * __bam_psplit -- - * Do the real work of splitting the page. - */ -static int -__bam_psplit(dbc, cp, lp, rp, splitret) - DBC *dbc; - EPG *cp; - PAGE *lp, *rp; - db_indx_t *splitret; -{ - DB *dbp; - PAGE *pp; - db_indx_t half, nbytes, off, splitp, top; - int adjust, cnt, isbigkey, ret; - - dbp = dbc->dbp; - pp = cp->page; - adjust = TYPE(pp) == P_LBTREE ? P_INDX : O_INDX; - - /* - * If we're splitting the first (last) page on a level because we're - * inserting (appending) a key to it, it's likely that the data is - * sorted. Moving a single item to the new page is less work and can - * push the fill factor higher than normal. If we're wrong it's not - * a big deal, we'll just do the split the right way next time. - */ - off = 0; - if (NEXT_PGNO(pp) == PGNO_INVALID && - ((ISINTERNAL(pp) && cp->indx == NUM_ENT(cp->page) - 1) || - (!ISINTERNAL(pp) && cp->indx == NUM_ENT(cp->page)))) - off = NUM_ENT(cp->page) - adjust; - else if (PREV_PGNO(pp) == PGNO_INVALID && cp->indx == 0) - off = adjust; - - if (off != 0) - goto sort; - - /* - * Split the data to the left and right pages. Try not to split on - * an overflow key. (Overflow keys on internal pages will slow down - * searches.) Refuse to split in the middle of a set of duplicates. - * - * First, find the optimum place to split. - * - * It's possible to try and split past the last record on the page if - * there's a very large record at the end of the page. Make sure this - * doesn't happen by bounding the check at the next-to-last entry on - * the page. - * - * Note, we try and split half the data present on the page. This is - * because another process may have already split the page and left - * it half empty. We don't try and skip the split -- we don't know - * how much space we're going to need on the page, and we may need up - * to half the page for a big item, so there's no easy test to decide - * if we need to split or not. Besides, if two threads are inserting - * data into the same place in the database, we're probably going to - * need more space soon anyway. - */ - top = NUM_ENT(pp) - adjust; - half = (dbp->pgsize - HOFFSET(pp)) / 2; - for (nbytes = 0, off = 0; off < top && nbytes < half; ++off) - switch (TYPE(pp)) { - case P_IBTREE: - if (B_TYPE(GET_BINTERNAL(pp, off)->type) == B_KEYDATA) - nbytes += - BINTERNAL_SIZE(GET_BINTERNAL(pp, off)->len); - else - nbytes += BINTERNAL_SIZE(BOVERFLOW_SIZE); - break; - case P_LBTREE: - if (B_TYPE(GET_BKEYDATA(pp, off)->type) == B_KEYDATA) - nbytes += - BKEYDATA_SIZE(GET_BKEYDATA(pp, off)->len); - else - nbytes += BOVERFLOW_SIZE; - - ++off; - if (B_TYPE(GET_BKEYDATA(pp, off)->type) == B_KEYDATA) - nbytes += - BKEYDATA_SIZE(GET_BKEYDATA(pp, off)->len); - else - nbytes += BOVERFLOW_SIZE; - break; - case P_IRECNO: - nbytes += RINTERNAL_SIZE; - break; - case P_LRECNO: - nbytes += BKEYDATA_SIZE(GET_BKEYDATA(pp, off)->len); - break; - default: - return (__db_pgfmt(dbp, pp->pgno)); - } -sort: splitp = off; - - /* - * Splitp is either at or just past the optimum split point. If - * it's a big key, try and find something close by that's not. - */ - if (TYPE(pp) == P_IBTREE) - isbigkey = B_TYPE(GET_BINTERNAL(pp, off)->type) != B_KEYDATA; - else if (TYPE(pp) == P_LBTREE) - isbigkey = B_TYPE(GET_BKEYDATA(pp, off)->type) != B_KEYDATA; - else - isbigkey = 0; - if (isbigkey) - for (cnt = 1; cnt <= 3; ++cnt) { - off = splitp + cnt * adjust; - if (off < (db_indx_t)NUM_ENT(pp) && - ((TYPE(pp) == P_IBTREE && - B_TYPE(GET_BINTERNAL(pp,off)->type) == B_KEYDATA) || - B_TYPE(GET_BKEYDATA(pp, off)->type) == B_KEYDATA)) { - splitp = off; - break; - } - if (splitp <= (db_indx_t)(cnt * adjust)) - continue; - off = splitp - cnt * adjust; - if (TYPE(pp) == P_IBTREE ? - B_TYPE(GET_BINTERNAL(pp, off)->type) == B_KEYDATA : - B_TYPE(GET_BKEYDATA(pp, off)->type) == B_KEYDATA) { - splitp = off; - break; - } - } - - /* - * We can't split in the middle a set of duplicates. We know that - * no duplicate set can take up more than about 25% of the page, - * because that's the point where we push it off onto a duplicate - * page set. So, this loop can't be unbounded. - */ - if (F_ISSET(dbp, DB_AM_DUP) && TYPE(pp) == P_LBTREE && - pp->inp[splitp] == pp->inp[splitp - adjust]) - for (cnt = 1;; ++cnt) { - off = splitp + cnt * adjust; - if (off < NUM_ENT(pp) && - pp->inp[splitp] != pp->inp[off]) { - splitp = off; - break; - } - if (splitp <= (db_indx_t)(cnt * adjust)) - continue; - off = splitp - cnt * adjust; - if (pp->inp[splitp] != pp->inp[off]) { - splitp = off + adjust; - break; - } - } - - - /* We're going to split at splitp. */ - if ((ret = __bam_copy(dbp, pp, lp, 0, splitp)) != 0) - return (ret); - if ((ret = __bam_copy(dbp, pp, rp, splitp, NUM_ENT(pp))) != 0) - return (ret); - - *splitret = splitp; - return (0); -} - -/* - * __bam_copy -- - * Copy a set of records from one page to another. - * - * PUBLIC: int __bam_copy __P((DB *, PAGE *, PAGE *, u_int32_t, u_int32_t)); - */ -int -__bam_copy(dbp, pp, cp, nxt, stop) - DB *dbp; - PAGE *pp, *cp; - u_int32_t nxt, stop; -{ - db_indx_t nbytes, off; - - /* - * Copy the rest of the data to the right page. Nxt is the next - * offset placed on the target page. - */ - for (off = 0; nxt < stop; ++nxt, ++NUM_ENT(cp), ++off) { - switch (TYPE(pp)) { - case P_IBTREE: - if (B_TYPE(GET_BINTERNAL(pp, nxt)->type) == B_KEYDATA) - nbytes = - BINTERNAL_SIZE(GET_BINTERNAL(pp, nxt)->len); - else - nbytes = BINTERNAL_SIZE(BOVERFLOW_SIZE); - break; - case P_LBTREE: - /* - * If we're on a key and it's a duplicate, just copy - * the offset. - */ - if (off != 0 && (nxt % P_INDX) == 0 && - pp->inp[nxt] == pp->inp[nxt - P_INDX]) { - cp->inp[off] = cp->inp[off - P_INDX]; - continue; - } - /* FALLTHROUGH */ - case P_LRECNO: - if (B_TYPE(GET_BKEYDATA(pp, nxt)->type) == B_KEYDATA) - nbytes = - BKEYDATA_SIZE(GET_BKEYDATA(pp, nxt)->len); - else - nbytes = BOVERFLOW_SIZE; - break; - case P_IRECNO: - nbytes = RINTERNAL_SIZE; - break; - default: - return (__db_pgfmt(dbp, pp->pgno)); - } - cp->inp[off] = HOFFSET(cp) -= nbytes; - memcpy(P_ENTRY(cp, off), P_ENTRY(pp, nxt), nbytes); - } - return (0); -} diff --git a/db2/btree/bt_stat.c b/db2/btree/bt_stat.c deleted file mode 100644 index 855ef40..0000000 --- a/db2/btree/bt_stat.c +++ /dev/null @@ -1,198 +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[] = "@(#)bt_stat.c 10.27 (Sleepycat) 11/25/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <string.h> -#endif - -#include "db_int.h" -#include "db_page.h" -#include "btree.h" - -/* - * __bam_stat -- - * Gather/print the btree statistics - * - * PUBLIC: int __bam_stat __P((DB *, void *, void *(*)(size_t), u_int32_t)); - */ -int -__bam_stat(dbp, spp, db_malloc, flags) - DB *dbp; - void *spp; - void *(*db_malloc) __P((size_t)); - u_int32_t flags; -{ - BTMETA *meta; - BTREE *t; - DBC *dbc; - DB_BTREE_STAT *sp; - DB_LOCK lock; - PAGE *h; - db_pgno_t lastpgno, pgno; - int ret, t_ret; - - DB_PANIC_CHECK(dbp); - - /* Check for invalid flags. */ - if ((ret = __db_statchk(dbp, flags)) != 0) - return (ret); - - if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0) - return (ret); - - DEBUG_LWRITE(dbc, NULL, "bam_stat", NULL, NULL, flags); - - t = dbp->internal; - - if (spp == NULL) - return (0); - - /* Allocate and clear the structure. */ - if ((ret = __os_malloc(sizeof(*sp), db_malloc, &sp)) != 0) - goto err; - memset(sp, 0, sizeof(*sp)); - - /* If the app just wants the record count, make it fast. */ - if (flags == DB_RECORDCOUNT) { - pgno = PGNO_ROOT; - if ((ret = __bam_lget(dbc, 0, pgno, DB_LOCK_READ, &lock)) != 0) - goto err; - if ((ret = memp_fget(dbp->mpf, &pgno, 0, (PAGE **)&h)) != 0) - goto err; - - sp->bt_nrecs = RE_NREC(h); - - (void)memp_fput(dbp->mpf, h, 0); - (void)__BT_LPUT(dbc, lock); - goto done; - } - - /* Get the meta-data page. */ - pgno = PGNO_METADATA; - if ((ret = __bam_lget(dbc, 0, pgno, DB_LOCK_READ, &lock)) != 0) - goto err; - if ((ret = memp_fget(dbp->mpf, &pgno, 0, (PAGE **)&meta)) != 0) - goto err; - - /* Translate the metadata flags. */ - if (F_ISSET(meta, BTM_DUP)) - sp->bt_flags |= DB_DUP; - if (F_ISSET(meta, BTM_FIXEDLEN)) - sp->bt_flags |= DB_FIXEDLEN; - if (F_ISSET(meta, BTM_RECNUM)) - sp->bt_flags |= DB_RECNUM; - if (F_ISSET(meta, BTM_RENUMBER)) - sp->bt_flags |= DB_RENUMBER; - - /* Get the remaining metadata fields. */ - sp->bt_minkey = meta->minkey; - sp->bt_maxkey = meta->maxkey; - sp->bt_re_len = meta->re_len; - sp->bt_re_pad = meta->re_pad; - sp->bt_magic = meta->magic; - sp->bt_version = meta->version; - - /* Get the page size from the DB. */ - sp->bt_pagesize = dbp->pgsize; - - /* Walk the free list, counting pages. */ - for (sp->bt_free = 0, pgno = meta->free; pgno != PGNO_INVALID;) { - ++sp->bt_free; - - if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0) { - (void)memp_fput(dbp->mpf, meta, 0); - (void)__BT_TLPUT(dbc, lock); - goto err; - } - pgno = h->next_pgno; - (void)memp_fput(dbp->mpf, h, 0); - } - - /* Discard the meta-data page. */ - (void)memp_fput(dbp->mpf, meta, 0); - (void)__BT_TLPUT(dbc, lock); - - /* Determine the last page of the database. */ - if ((ret = memp_fget(dbp->mpf, &lastpgno, DB_MPOOL_LAST, &h)) != 0) - goto err; - (void)memp_fput(dbp->mpf, h, 0); - - /* Get the root page. */ - pgno = PGNO_ROOT; - if ((ret = __bam_lget(dbc, 0, PGNO_ROOT, DB_LOCK_READ, &lock)) != 0) - goto err; - if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0) { - (void)__BT_LPUT(dbc, lock); - goto err; - } - - /* Get the levels from the root page. */ - sp->bt_levels = h->level; - - /* Walk the page list, counting things. */ - for (;;) { - switch (TYPE(h)) { - case P_INVALID: - break; - case P_IBTREE: - case P_IRECNO: - ++sp->bt_int_pg; - sp->bt_int_pgfree += HOFFSET(h) - LOFFSET(h); - break; - case P_LBTREE: - ++sp->bt_leaf_pg; - sp->bt_leaf_pgfree += HOFFSET(h) - LOFFSET(h); - sp->bt_nrecs += NUM_ENT(h) / P_INDX; - break; - case P_LRECNO: - ++sp->bt_leaf_pg; - sp->bt_leaf_pgfree += HOFFSET(h) - LOFFSET(h); - sp->bt_nrecs += NUM_ENT(h); - break; - case P_DUPLICATE: - ++sp->bt_dup_pg; - /* XXX MARGO: sp->bt_dup_pgfree; */ - break; - case P_OVERFLOW: - ++sp->bt_over_pg; - /* XXX MARGO: sp->bt_over_pgfree; */ - break; - default: - (void)memp_fput(dbp->mpf, h, 0); - (void)__BT_LPUT(dbc, lock); - return (__db_pgfmt(dbp, pgno)); - } - - (void)memp_fput(dbp->mpf, h, 0); - (void)__BT_LPUT(dbc, lock); - - if (++pgno > lastpgno) - break; - if (__bam_lget(dbc, 0, pgno, DB_LOCK_READ, &lock)) - break; - if (memp_fget(dbp->mpf, &pgno, 0, &h) != 0) { - (void)__BT_LPUT(dbc, lock); - break; - } - } - -done: *(DB_BTREE_STAT **)spp = sp; - ret = 0; - -err: if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0) - ret = t_ret; - return (ret); -} diff --git a/db2/btree/btree_auto.c b/db2/btree/btree_auto.c deleted file mode 100644 index 95ea76e..0000000 --- a/db2/btree/btree_auto.c +++ /dev/null @@ -1,1508 +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 "btree.h" -#include "db_am.h" -/* - * PUBLIC: int __bam_pg_alloc_log - * PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - * PUBLIC: u_int32_t, DB_LSN *, DB_LSN *, db_pgno_t, - * PUBLIC: u_int32_t, db_pgno_t)); - */ -int __bam_pg_alloc_log(logp, txnid, ret_lsnp, flags, - fileid, meta_lsn, page_lsn, pgno, ptype, next) - DB_LOG *logp; - DB_TXN *txnid; - DB_LSN *ret_lsnp; - u_int32_t flags; - u_int32_t fileid; - DB_LSN * meta_lsn; - DB_LSN * page_lsn; - db_pgno_t pgno; - u_int32_t ptype; - db_pgno_t next; -{ - DBT logrec; - DB_LSN *lsnp, null_lsn; - u_int32_t rectype, txn_num; - int ret; - u_int8_t *bp; - - rectype = DB_bam_pg_alloc; - 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(fileid) - + sizeof(*meta_lsn) - + sizeof(*page_lsn) - + sizeof(pgno) - + sizeof(ptype) - + sizeof(next); - 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, &fileid, sizeof(fileid)); - bp += sizeof(fileid); - if (meta_lsn != NULL) - memcpy(bp, meta_lsn, sizeof(*meta_lsn)); - else - memset(bp, 0, sizeof(*meta_lsn)); - bp += sizeof(*meta_lsn); - if (page_lsn != NULL) - memcpy(bp, page_lsn, sizeof(*page_lsn)); - else - memset(bp, 0, sizeof(*page_lsn)); - bp += sizeof(*page_lsn); - memcpy(bp, &pgno, sizeof(pgno)); - bp += sizeof(pgno); - memcpy(bp, &ptype, sizeof(ptype)); - bp += sizeof(ptype); - memcpy(bp, &next, sizeof(next)); - bp += sizeof(next); -#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 __bam_pg_alloc_print - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__bam_pg_alloc_print(notused1, dbtp, lsnp, notused2, notused3) - DB_LOG *notused1; - DBT *dbtp; - DB_LSN *lsnp; - int notused2; - void *notused3; -{ - __bam_pg_alloc_args *argp; - u_int32_t i; - u_int ch; - int ret; - - i = 0; - ch = 0; - notused1 = NULL; - notused2 = 0; - notused3 = NULL; - - if ((ret = __bam_pg_alloc_read(dbtp->data, &argp)) != 0) - return (ret); - printf("[%lu][%lu]bam_pg_alloc: 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("\tfileid: %lu\n", (u_long)argp->fileid); - printf("\tmeta_lsn: [%lu][%lu]\n", - (u_long)argp->meta_lsn.file, (u_long)argp->meta_lsn.offset); - printf("\tpage_lsn: [%lu][%lu]\n", - (u_long)argp->page_lsn.file, (u_long)argp->page_lsn.offset); - printf("\tpgno: %lu\n", (u_long)argp->pgno); - printf("\tptype: %lu\n", (u_long)argp->ptype); - printf("\tnext: %lu\n", (u_long)argp->next); - printf("\n"); - __os_free(argp, 0); - return (0); -} - -/* - * PUBLIC: int __bam_pg_alloc_read __P((void *, __bam_pg_alloc_args **)); - */ -int -__bam_pg_alloc_read(recbuf, argpp) - void *recbuf; - __bam_pg_alloc_args **argpp; -{ - __bam_pg_alloc_args *argp; - u_int8_t *bp; - int ret; - - ret = __os_malloc(sizeof(__bam_pg_alloc_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->fileid, bp, sizeof(argp->fileid)); - bp += sizeof(argp->fileid); - memcpy(&argp->meta_lsn, bp, sizeof(argp->meta_lsn)); - bp += sizeof(argp->meta_lsn); - memcpy(&argp->page_lsn, bp, sizeof(argp->page_lsn)); - bp += sizeof(argp->page_lsn); - memcpy(&argp->pgno, bp, sizeof(argp->pgno)); - bp += sizeof(argp->pgno); - memcpy(&argp->ptype, bp, sizeof(argp->ptype)); - bp += sizeof(argp->ptype); - memcpy(&argp->next, bp, sizeof(argp->next)); - bp += sizeof(argp->next); - *argpp = argp; - return (0); -} - -/* - * PUBLIC: int __bam_pg_free_log - * PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - * PUBLIC: u_int32_t, db_pgno_t, DB_LSN *, const DBT *, - * PUBLIC: db_pgno_t)); - */ -int __bam_pg_free_log(logp, txnid, ret_lsnp, flags, - fileid, pgno, meta_lsn, header, next) - DB_LOG *logp; - DB_TXN *txnid; - DB_LSN *ret_lsnp; - u_int32_t flags; - u_int32_t fileid; - db_pgno_t pgno; - DB_LSN * meta_lsn; - const DBT *header; - db_pgno_t next; -{ - 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_bam_pg_free; - 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(fileid) - + sizeof(pgno) - + sizeof(*meta_lsn) - + sizeof(u_int32_t) + (header == NULL ? 0 : header->size) - + sizeof(next); - 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, &fileid, sizeof(fileid)); - bp += sizeof(fileid); - memcpy(bp, &pgno, sizeof(pgno)); - bp += sizeof(pgno); - if (meta_lsn != NULL) - memcpy(bp, meta_lsn, sizeof(*meta_lsn)); - else - memset(bp, 0, sizeof(*meta_lsn)); - bp += sizeof(*meta_lsn); - if (header == NULL) { - zero = 0; - memcpy(bp, &zero, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - } else { - memcpy(bp, &header->size, sizeof(header->size)); - bp += sizeof(header->size); - memcpy(bp, header->data, header->size); - bp += header->size; - } - memcpy(bp, &next, sizeof(next)); - bp += sizeof(next); -#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 __bam_pg_free_print - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__bam_pg_free_print(notused1, dbtp, lsnp, notused2, notused3) - DB_LOG *notused1; - DBT *dbtp; - DB_LSN *lsnp; - int notused2; - void *notused3; -{ - __bam_pg_free_args *argp; - u_int32_t i; - u_int ch; - int ret; - - i = 0; - ch = 0; - notused1 = NULL; - notused2 = 0; - notused3 = NULL; - - if ((ret = __bam_pg_free_read(dbtp->data, &argp)) != 0) - return (ret); - printf("[%lu][%lu]bam_pg_free: 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("\tfileid: %lu\n", (u_long)argp->fileid); - printf("\tpgno: %lu\n", (u_long)argp->pgno); - printf("\tmeta_lsn: [%lu][%lu]\n", - (u_long)argp->meta_lsn.file, (u_long)argp->meta_lsn.offset); - printf("\theader: "); - for (i = 0; i < argp->header.size; i++) { - ch = ((u_int8_t *)argp->header.data)[i]; - if (isprint(ch) || ch == 0xa) - putchar(ch); - else - printf("%#x ", ch); - } - printf("\n"); - printf("\tnext: %lu\n", (u_long)argp->next); - printf("\n"); - __os_free(argp, 0); - return (0); -} - -/* - * PUBLIC: int __bam_pg_free_read __P((void *, __bam_pg_free_args **)); - */ -int -__bam_pg_free_read(recbuf, argpp) - void *recbuf; - __bam_pg_free_args **argpp; -{ - __bam_pg_free_args *argp; - u_int8_t *bp; - int ret; - - ret = __os_malloc(sizeof(__bam_pg_free_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->fileid, bp, sizeof(argp->fileid)); - bp += sizeof(argp->fileid); - memcpy(&argp->pgno, bp, sizeof(argp->pgno)); - bp += sizeof(argp->pgno); - memcpy(&argp->meta_lsn, bp, sizeof(argp->meta_lsn)); - bp += sizeof(argp->meta_lsn); - memcpy(&argp->header.size, bp, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - argp->header.data = bp; - bp += argp->header.size; - memcpy(&argp->next, bp, sizeof(argp->next)); - bp += sizeof(argp->next); - *argpp = argp; - return (0); -} - -/* - * PUBLIC: int __bam_split_log - * PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - * PUBLIC: u_int32_t, db_pgno_t, DB_LSN *, db_pgno_t, - * PUBLIC: DB_LSN *, u_int32_t, db_pgno_t, DB_LSN *, - * PUBLIC: const DBT *)); - */ -int __bam_split_log(logp, txnid, ret_lsnp, flags, - fileid, left, llsn, right, rlsn, indx, - npgno, nlsn, pg) - DB_LOG *logp; - DB_TXN *txnid; - DB_LSN *ret_lsnp; - u_int32_t flags; - u_int32_t fileid; - db_pgno_t left; - DB_LSN * llsn; - db_pgno_t right; - DB_LSN * rlsn; - u_int32_t indx; - db_pgno_t npgno; - DB_LSN * nlsn; - const DBT *pg; -{ - 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_bam_split; - 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(fileid) - + sizeof(left) - + sizeof(*llsn) - + sizeof(right) - + sizeof(*rlsn) - + sizeof(indx) - + sizeof(npgno) - + sizeof(*nlsn) - + sizeof(u_int32_t) + (pg == NULL ? 0 : pg->size); - 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, &fileid, sizeof(fileid)); - bp += sizeof(fileid); - memcpy(bp, &left, sizeof(left)); - bp += sizeof(left); - if (llsn != NULL) - memcpy(bp, llsn, sizeof(*llsn)); - else - memset(bp, 0, sizeof(*llsn)); - bp += sizeof(*llsn); - memcpy(bp, &right, sizeof(right)); - bp += sizeof(right); - if (rlsn != NULL) - memcpy(bp, rlsn, sizeof(*rlsn)); - else - memset(bp, 0, sizeof(*rlsn)); - bp += sizeof(*rlsn); - memcpy(bp, &indx, sizeof(indx)); - bp += sizeof(indx); - memcpy(bp, &npgno, sizeof(npgno)); - bp += sizeof(npgno); - if (nlsn != NULL) - memcpy(bp, nlsn, sizeof(*nlsn)); - else - memset(bp, 0, sizeof(*nlsn)); - bp += sizeof(*nlsn); - if (pg == NULL) { - zero = 0; - memcpy(bp, &zero, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - } else { - memcpy(bp, &pg->size, sizeof(pg->size)); - bp += sizeof(pg->size); - memcpy(bp, pg->data, pg->size); - bp += pg->size; - } -#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 __bam_split_print - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__bam_split_print(notused1, dbtp, lsnp, notused2, notused3) - DB_LOG *notused1; - DBT *dbtp; - DB_LSN *lsnp; - int notused2; - void *notused3; -{ - __bam_split_args *argp; - u_int32_t i; - u_int ch; - int ret; - - i = 0; - ch = 0; - notused1 = NULL; - notused2 = 0; - notused3 = NULL; - - if ((ret = __bam_split_read(dbtp->data, &argp)) != 0) - return (ret); - printf("[%lu][%lu]bam_split: 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("\tfileid: %lu\n", (u_long)argp->fileid); - printf("\tleft: %lu\n", (u_long)argp->left); - printf("\tllsn: [%lu][%lu]\n", - (u_long)argp->llsn.file, (u_long)argp->llsn.offset); - printf("\tright: %lu\n", (u_long)argp->right); - printf("\trlsn: [%lu][%lu]\n", - (u_long)argp->rlsn.file, (u_long)argp->rlsn.offset); - printf("\tindx: %lu\n", (u_long)argp->indx); - printf("\tnpgno: %lu\n", (u_long)argp->npgno); - printf("\tnlsn: [%lu][%lu]\n", - (u_long)argp->nlsn.file, (u_long)argp->nlsn.offset); - printf("\tpg: "); - for (i = 0; i < argp->pg.size; i++) { - ch = ((u_int8_t *)argp->pg.data)[i]; - if (isprint(ch) || ch == 0xa) - putchar(ch); - else - printf("%#x ", ch); - } - printf("\n"); - printf("\n"); - __os_free(argp, 0); - return (0); -} - -/* - * PUBLIC: int __bam_split_read __P((void *, __bam_split_args **)); - */ -int -__bam_split_read(recbuf, argpp) - void *recbuf; - __bam_split_args **argpp; -{ - __bam_split_args *argp; - u_int8_t *bp; - int ret; - - ret = __os_malloc(sizeof(__bam_split_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->fileid, bp, sizeof(argp->fileid)); - bp += sizeof(argp->fileid); - memcpy(&argp->left, bp, sizeof(argp->left)); - bp += sizeof(argp->left); - memcpy(&argp->llsn, bp, sizeof(argp->llsn)); - bp += sizeof(argp->llsn); - memcpy(&argp->right, bp, sizeof(argp->right)); - bp += sizeof(argp->right); - memcpy(&argp->rlsn, bp, sizeof(argp->rlsn)); - bp += sizeof(argp->rlsn); - memcpy(&argp->indx, bp, sizeof(argp->indx)); - bp += sizeof(argp->indx); - memcpy(&argp->npgno, bp, sizeof(argp->npgno)); - bp += sizeof(argp->npgno); - memcpy(&argp->nlsn, bp, sizeof(argp->nlsn)); - bp += sizeof(argp->nlsn); - memcpy(&argp->pg.size, bp, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - argp->pg.data = bp; - bp += argp->pg.size; - *argpp = argp; - return (0); -} - -/* - * PUBLIC: int __bam_rsplit_log - * PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - * PUBLIC: u_int32_t, db_pgno_t, const DBT *, db_pgno_t, - * PUBLIC: const DBT *, DB_LSN *)); - */ -int __bam_rsplit_log(logp, txnid, ret_lsnp, flags, - fileid, pgno, pgdbt, nrec, rootent, rootlsn) - DB_LOG *logp; - DB_TXN *txnid; - DB_LSN *ret_lsnp; - u_int32_t flags; - u_int32_t fileid; - db_pgno_t pgno; - const DBT *pgdbt; - db_pgno_t nrec; - const DBT *rootent; - DB_LSN * rootlsn; -{ - 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_bam_rsplit; - 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(fileid) - + sizeof(pgno) - + sizeof(u_int32_t) + (pgdbt == NULL ? 0 : pgdbt->size) - + sizeof(nrec) - + sizeof(u_int32_t) + (rootent == NULL ? 0 : rootent->size) - + sizeof(*rootlsn); - 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, &fileid, sizeof(fileid)); - bp += sizeof(fileid); - memcpy(bp, &pgno, sizeof(pgno)); - bp += sizeof(pgno); - if (pgdbt == NULL) { - zero = 0; - memcpy(bp, &zero, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - } else { - memcpy(bp, &pgdbt->size, sizeof(pgdbt->size)); - bp += sizeof(pgdbt->size); - memcpy(bp, pgdbt->data, pgdbt->size); - bp += pgdbt->size; - } - memcpy(bp, &nrec, sizeof(nrec)); - bp += sizeof(nrec); - if (rootent == NULL) { - zero = 0; - memcpy(bp, &zero, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - } else { - memcpy(bp, &rootent->size, sizeof(rootent->size)); - bp += sizeof(rootent->size); - memcpy(bp, rootent->data, rootent->size); - bp += rootent->size; - } - if (rootlsn != NULL) - memcpy(bp, rootlsn, sizeof(*rootlsn)); - else - memset(bp, 0, sizeof(*rootlsn)); - bp += sizeof(*rootlsn); -#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 __bam_rsplit_print - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__bam_rsplit_print(notused1, dbtp, lsnp, notused2, notused3) - DB_LOG *notused1; - DBT *dbtp; - DB_LSN *lsnp; - int notused2; - void *notused3; -{ - __bam_rsplit_args *argp; - u_int32_t i; - u_int ch; - int ret; - - i = 0; - ch = 0; - notused1 = NULL; - notused2 = 0; - notused3 = NULL; - - if ((ret = __bam_rsplit_read(dbtp->data, &argp)) != 0) - return (ret); - printf("[%lu][%lu]bam_rsplit: 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("\tfileid: %lu\n", (u_long)argp->fileid); - printf("\tpgno: %lu\n", (u_long)argp->pgno); - printf("\tpgdbt: "); - for (i = 0; i < argp->pgdbt.size; i++) { - ch = ((u_int8_t *)argp->pgdbt.data)[i]; - if (isprint(ch) || ch == 0xa) - putchar(ch); - else - printf("%#x ", ch); - } - printf("\n"); - printf("\tnrec: %lu\n", (u_long)argp->nrec); - printf("\trootent: "); - for (i = 0; i < argp->rootent.size; i++) { - ch = ((u_int8_t *)argp->rootent.data)[i]; - if (isprint(ch) || ch == 0xa) - putchar(ch); - else - printf("%#x ", ch); - } - printf("\n"); - printf("\trootlsn: [%lu][%lu]\n", - (u_long)argp->rootlsn.file, (u_long)argp->rootlsn.offset); - printf("\n"); - __os_free(argp, 0); - return (0); -} - -/* - * PUBLIC: int __bam_rsplit_read __P((void *, __bam_rsplit_args **)); - */ -int -__bam_rsplit_read(recbuf, argpp) - void *recbuf; - __bam_rsplit_args **argpp; -{ - __bam_rsplit_args *argp; - u_int8_t *bp; - int ret; - - ret = __os_malloc(sizeof(__bam_rsplit_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->fileid, bp, sizeof(argp->fileid)); - bp += sizeof(argp->fileid); - memcpy(&argp->pgno, bp, sizeof(argp->pgno)); - bp += sizeof(argp->pgno); - memcpy(&argp->pgdbt.size, bp, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - argp->pgdbt.data = bp; - bp += argp->pgdbt.size; - memcpy(&argp->nrec, bp, sizeof(argp->nrec)); - bp += sizeof(argp->nrec); - memcpy(&argp->rootent.size, bp, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - argp->rootent.data = bp; - bp += argp->rootent.size; - memcpy(&argp->rootlsn, bp, sizeof(argp->rootlsn)); - bp += sizeof(argp->rootlsn); - *argpp = argp; - return (0); -} - -/* - * PUBLIC: int __bam_adj_log - * PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - * PUBLIC: u_int32_t, db_pgno_t, DB_LSN *, u_int32_t, - * PUBLIC: u_int32_t, u_int32_t)); - */ -int __bam_adj_log(logp, txnid, ret_lsnp, flags, - fileid, pgno, lsn, indx, indx_copy, is_insert) - DB_LOG *logp; - DB_TXN *txnid; - DB_LSN *ret_lsnp; - u_int32_t flags; - u_int32_t fileid; - db_pgno_t pgno; - DB_LSN * lsn; - u_int32_t indx; - u_int32_t indx_copy; - u_int32_t is_insert; -{ - DBT logrec; - DB_LSN *lsnp, null_lsn; - u_int32_t rectype, txn_num; - int ret; - u_int8_t *bp; - - rectype = DB_bam_adj; - 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(fileid) - + sizeof(pgno) - + sizeof(*lsn) - + sizeof(indx) - + sizeof(indx_copy) - + sizeof(is_insert); - 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, &fileid, sizeof(fileid)); - bp += sizeof(fileid); - memcpy(bp, &pgno, sizeof(pgno)); - bp += sizeof(pgno); - if (lsn != NULL) - memcpy(bp, lsn, sizeof(*lsn)); - else - memset(bp, 0, sizeof(*lsn)); - bp += sizeof(*lsn); - memcpy(bp, &indx, sizeof(indx)); - bp += sizeof(indx); - memcpy(bp, &indx_copy, sizeof(indx_copy)); - bp += sizeof(indx_copy); - memcpy(bp, &is_insert, sizeof(is_insert)); - bp += sizeof(is_insert); -#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 __bam_adj_print - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__bam_adj_print(notused1, dbtp, lsnp, notused2, notused3) - DB_LOG *notused1; - DBT *dbtp; - DB_LSN *lsnp; - int notused2; - void *notused3; -{ - __bam_adj_args *argp; - u_int32_t i; - u_int ch; - int ret; - - i = 0; - ch = 0; - notused1 = NULL; - notused2 = 0; - notused3 = NULL; - - if ((ret = __bam_adj_read(dbtp->data, &argp)) != 0) - return (ret); - printf("[%lu][%lu]bam_adj: 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("\tfileid: %lu\n", (u_long)argp->fileid); - printf("\tpgno: %lu\n", (u_long)argp->pgno); - printf("\tlsn: [%lu][%lu]\n", - (u_long)argp->lsn.file, (u_long)argp->lsn.offset); - printf("\tindx: %lu\n", (u_long)argp->indx); - printf("\tindx_copy: %lu\n", (u_long)argp->indx_copy); - printf("\tis_insert: %lu\n", (u_long)argp->is_insert); - printf("\n"); - __os_free(argp, 0); - return (0); -} - -/* - * PUBLIC: int __bam_adj_read __P((void *, __bam_adj_args **)); - */ -int -__bam_adj_read(recbuf, argpp) - void *recbuf; - __bam_adj_args **argpp; -{ - __bam_adj_args *argp; - u_int8_t *bp; - int ret; - - ret = __os_malloc(sizeof(__bam_adj_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->fileid, bp, sizeof(argp->fileid)); - bp += sizeof(argp->fileid); - memcpy(&argp->pgno, bp, sizeof(argp->pgno)); - bp += sizeof(argp->pgno); - memcpy(&argp->lsn, bp, sizeof(argp->lsn)); - bp += sizeof(argp->lsn); - memcpy(&argp->indx, bp, sizeof(argp->indx)); - bp += sizeof(argp->indx); - memcpy(&argp->indx_copy, bp, sizeof(argp->indx_copy)); - bp += sizeof(argp->indx_copy); - memcpy(&argp->is_insert, bp, sizeof(argp->is_insert)); - bp += sizeof(argp->is_insert); - *argpp = argp; - return (0); -} - -/* - * PUBLIC: int __bam_cadjust_log - * PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - * PUBLIC: u_int32_t, db_pgno_t, DB_LSN *, u_int32_t, - * PUBLIC: int32_t, int32_t)); - */ -int __bam_cadjust_log(logp, txnid, ret_lsnp, flags, - fileid, pgno, lsn, indx, adjust, total) - DB_LOG *logp; - DB_TXN *txnid; - DB_LSN *ret_lsnp; - u_int32_t flags; - u_int32_t fileid; - db_pgno_t pgno; - DB_LSN * lsn; - u_int32_t indx; - int32_t adjust; - int32_t total; -{ - DBT logrec; - DB_LSN *lsnp, null_lsn; - u_int32_t rectype, txn_num; - int ret; - u_int8_t *bp; - - rectype = DB_bam_cadjust; - 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(fileid) - + sizeof(pgno) - + sizeof(*lsn) - + sizeof(indx) - + sizeof(adjust) - + sizeof(total); - 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, &fileid, sizeof(fileid)); - bp += sizeof(fileid); - memcpy(bp, &pgno, sizeof(pgno)); - bp += sizeof(pgno); - if (lsn != NULL) - memcpy(bp, lsn, sizeof(*lsn)); - else - memset(bp, 0, sizeof(*lsn)); - bp += sizeof(*lsn); - memcpy(bp, &indx, sizeof(indx)); - bp += sizeof(indx); - memcpy(bp, &adjust, sizeof(adjust)); - bp += sizeof(adjust); - memcpy(bp, &total, sizeof(total)); - bp += sizeof(total); -#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 __bam_cadjust_print - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__bam_cadjust_print(notused1, dbtp, lsnp, notused2, notused3) - DB_LOG *notused1; - DBT *dbtp; - DB_LSN *lsnp; - int notused2; - void *notused3; -{ - __bam_cadjust_args *argp; - u_int32_t i; - u_int ch; - int ret; - - i = 0; - ch = 0; - notused1 = NULL; - notused2 = 0; - notused3 = NULL; - - if ((ret = __bam_cadjust_read(dbtp->data, &argp)) != 0) - return (ret); - printf("[%lu][%lu]bam_cadjust: 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("\tfileid: %lu\n", (u_long)argp->fileid); - printf("\tpgno: %lu\n", (u_long)argp->pgno); - printf("\tlsn: [%lu][%lu]\n", - (u_long)argp->lsn.file, (u_long)argp->lsn.offset); - printf("\tindx: %lu\n", (u_long)argp->indx); - printf("\tadjust: %ld\n", (long)argp->adjust); - printf("\ttotal: %ld\n", (long)argp->total); - printf("\n"); - __os_free(argp, 0); - return (0); -} - -/* - * PUBLIC: int __bam_cadjust_read __P((void *, __bam_cadjust_args **)); - */ -int -__bam_cadjust_read(recbuf, argpp) - void *recbuf; - __bam_cadjust_args **argpp; -{ - __bam_cadjust_args *argp; - u_int8_t *bp; - int ret; - - ret = __os_malloc(sizeof(__bam_cadjust_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->fileid, bp, sizeof(argp->fileid)); - bp += sizeof(argp->fileid); - memcpy(&argp->pgno, bp, sizeof(argp->pgno)); - bp += sizeof(argp->pgno); - memcpy(&argp->lsn, bp, sizeof(argp->lsn)); - bp += sizeof(argp->lsn); - memcpy(&argp->indx, bp, sizeof(argp->indx)); - bp += sizeof(argp->indx); - memcpy(&argp->adjust, bp, sizeof(argp->adjust)); - bp += sizeof(argp->adjust); - memcpy(&argp->total, bp, sizeof(argp->total)); - bp += sizeof(argp->total); - *argpp = argp; - return (0); -} - -/* - * PUBLIC: int __bam_cdel_log - * PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - * PUBLIC: u_int32_t, db_pgno_t, DB_LSN *, u_int32_t)); - */ -int __bam_cdel_log(logp, txnid, ret_lsnp, flags, - fileid, pgno, lsn, indx) - DB_LOG *logp; - DB_TXN *txnid; - DB_LSN *ret_lsnp; - u_int32_t flags; - u_int32_t fileid; - db_pgno_t pgno; - DB_LSN * lsn; - u_int32_t indx; -{ - DBT logrec; - DB_LSN *lsnp, null_lsn; - u_int32_t rectype, txn_num; - int ret; - u_int8_t *bp; - - rectype = DB_bam_cdel; - 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(fileid) - + sizeof(pgno) - + sizeof(*lsn) - + sizeof(indx); - 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, &fileid, sizeof(fileid)); - bp += sizeof(fileid); - memcpy(bp, &pgno, sizeof(pgno)); - bp += sizeof(pgno); - if (lsn != NULL) - memcpy(bp, lsn, sizeof(*lsn)); - else - memset(bp, 0, sizeof(*lsn)); - bp += sizeof(*lsn); - memcpy(bp, &indx, sizeof(indx)); - bp += sizeof(indx); -#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 __bam_cdel_print - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__bam_cdel_print(notused1, dbtp, lsnp, notused2, notused3) - DB_LOG *notused1; - DBT *dbtp; - DB_LSN *lsnp; - int notused2; - void *notused3; -{ - __bam_cdel_args *argp; - u_int32_t i; - u_int ch; - int ret; - - i = 0; - ch = 0; - notused1 = NULL; - notused2 = 0; - notused3 = NULL; - - if ((ret = __bam_cdel_read(dbtp->data, &argp)) != 0) - return (ret); - printf("[%lu][%lu]bam_cdel: 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("\tfileid: %lu\n", (u_long)argp->fileid); - printf("\tpgno: %lu\n", (u_long)argp->pgno); - printf("\tlsn: [%lu][%lu]\n", - (u_long)argp->lsn.file, (u_long)argp->lsn.offset); - printf("\tindx: %lu\n", (u_long)argp->indx); - printf("\n"); - __os_free(argp, 0); - return (0); -} - -/* - * PUBLIC: int __bam_cdel_read __P((void *, __bam_cdel_args **)); - */ -int -__bam_cdel_read(recbuf, argpp) - void *recbuf; - __bam_cdel_args **argpp; -{ - __bam_cdel_args *argp; - u_int8_t *bp; - int ret; - - ret = __os_malloc(sizeof(__bam_cdel_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->fileid, bp, sizeof(argp->fileid)); - bp += sizeof(argp->fileid); - memcpy(&argp->pgno, bp, sizeof(argp->pgno)); - bp += sizeof(argp->pgno); - memcpy(&argp->lsn, bp, sizeof(argp->lsn)); - bp += sizeof(argp->lsn); - memcpy(&argp->indx, bp, sizeof(argp->indx)); - bp += sizeof(argp->indx); - *argpp = argp; - return (0); -} - -/* - * PUBLIC: int __bam_repl_log - * PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - * PUBLIC: u_int32_t, db_pgno_t, DB_LSN *, u_int32_t, - * PUBLIC: u_int32_t, const DBT *, const DBT *, u_int32_t, - * PUBLIC: u_int32_t)); - */ -int __bam_repl_log(logp, txnid, ret_lsnp, flags, - fileid, pgno, lsn, indx, isdeleted, orig, - repl, prefix, suffix) - DB_LOG *logp; - DB_TXN *txnid; - DB_LSN *ret_lsnp; - u_int32_t flags; - u_int32_t fileid; - db_pgno_t pgno; - DB_LSN * lsn; - u_int32_t indx; - u_int32_t isdeleted; - const DBT *orig; - const DBT *repl; - u_int32_t prefix; - u_int32_t suffix; -{ - 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_bam_repl; - 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(fileid) - + sizeof(pgno) - + sizeof(*lsn) - + sizeof(indx) - + sizeof(isdeleted) - + sizeof(u_int32_t) + (orig == NULL ? 0 : orig->size) - + sizeof(u_int32_t) + (repl == NULL ? 0 : repl->size) - + sizeof(prefix) - + sizeof(suffix); - 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, &fileid, sizeof(fileid)); - bp += sizeof(fileid); - memcpy(bp, &pgno, sizeof(pgno)); - bp += sizeof(pgno); - if (lsn != NULL) - memcpy(bp, lsn, sizeof(*lsn)); - else - memset(bp, 0, sizeof(*lsn)); - bp += sizeof(*lsn); - memcpy(bp, &indx, sizeof(indx)); - bp += sizeof(indx); - memcpy(bp, &isdeleted, sizeof(isdeleted)); - bp += sizeof(isdeleted); - if (orig == NULL) { - zero = 0; - memcpy(bp, &zero, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - } else { - memcpy(bp, &orig->size, sizeof(orig->size)); - bp += sizeof(orig->size); - memcpy(bp, orig->data, orig->size); - bp += orig->size; - } - if (repl == NULL) { - zero = 0; - memcpy(bp, &zero, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - } else { - memcpy(bp, &repl->size, sizeof(repl->size)); - bp += sizeof(repl->size); - memcpy(bp, repl->data, repl->size); - bp += repl->size; - } - memcpy(bp, &prefix, sizeof(prefix)); - bp += sizeof(prefix); - memcpy(bp, &suffix, sizeof(suffix)); - bp += sizeof(suffix); -#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 __bam_repl_print - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__bam_repl_print(notused1, dbtp, lsnp, notused2, notused3) - DB_LOG *notused1; - DBT *dbtp; - DB_LSN *lsnp; - int notused2; - void *notused3; -{ - __bam_repl_args *argp; - u_int32_t i; - u_int ch; - int ret; - - i = 0; - ch = 0; - notused1 = NULL; - notused2 = 0; - notused3 = NULL; - - if ((ret = __bam_repl_read(dbtp->data, &argp)) != 0) - return (ret); - printf("[%lu][%lu]bam_repl: 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("\tfileid: %lu\n", (u_long)argp->fileid); - printf("\tpgno: %lu\n", (u_long)argp->pgno); - printf("\tlsn: [%lu][%lu]\n", - (u_long)argp->lsn.file, (u_long)argp->lsn.offset); - printf("\tindx: %lu\n", (u_long)argp->indx); - printf("\tisdeleted: %lu\n", (u_long)argp->isdeleted); - printf("\torig: "); - for (i = 0; i < argp->orig.size; i++) { - ch = ((u_int8_t *)argp->orig.data)[i]; - if (isprint(ch) || ch == 0xa) - putchar(ch); - else - printf("%#x ", ch); - } - printf("\n"); - printf("\trepl: "); - for (i = 0; i < argp->repl.size; i++) { - ch = ((u_int8_t *)argp->repl.data)[i]; - if (isprint(ch) || ch == 0xa) - putchar(ch); - else - printf("%#x ", ch); - } - printf("\n"); - printf("\tprefix: %lu\n", (u_long)argp->prefix); - printf("\tsuffix: %lu\n", (u_long)argp->suffix); - printf("\n"); - __os_free(argp, 0); - return (0); -} - -/* - * PUBLIC: int __bam_repl_read __P((void *, __bam_repl_args **)); - */ -int -__bam_repl_read(recbuf, argpp) - void *recbuf; - __bam_repl_args **argpp; -{ - __bam_repl_args *argp; - u_int8_t *bp; - int ret; - - ret = __os_malloc(sizeof(__bam_repl_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->fileid, bp, sizeof(argp->fileid)); - bp += sizeof(argp->fileid); - memcpy(&argp->pgno, bp, sizeof(argp->pgno)); - bp += sizeof(argp->pgno); - memcpy(&argp->lsn, bp, sizeof(argp->lsn)); - bp += sizeof(argp->lsn); - memcpy(&argp->indx, bp, sizeof(argp->indx)); - bp += sizeof(argp->indx); - memcpy(&argp->isdeleted, bp, sizeof(argp->isdeleted)); - bp += sizeof(argp->isdeleted); - memcpy(&argp->orig.size, bp, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - argp->orig.data = bp; - bp += argp->orig.size; - memcpy(&argp->repl.size, bp, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - argp->repl.data = bp; - bp += argp->repl.size; - memcpy(&argp->prefix, bp, sizeof(argp->prefix)); - bp += sizeof(argp->prefix); - memcpy(&argp->suffix, bp, sizeof(argp->suffix)); - bp += sizeof(argp->suffix); - *argpp = argp; - return (0); -} - -/* - * PUBLIC: int __bam_init_print __P((DB_ENV *)); - */ -int -__bam_init_print(dbenv) - DB_ENV *dbenv; -{ - int ret; - - if ((ret = __db_add_recovery(dbenv, - __bam_pg_alloc_print, DB_bam_pg_alloc)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __bam_pg_free_print, DB_bam_pg_free)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __bam_split_print, DB_bam_split)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __bam_rsplit_print, DB_bam_rsplit)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __bam_adj_print, DB_bam_adj)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __bam_cadjust_print, DB_bam_cadjust)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __bam_cdel_print, DB_bam_cdel)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __bam_repl_print, DB_bam_repl)) != 0) - return (ret); - return (0); -} - -/* - * PUBLIC: int __bam_init_recover __P((DB_ENV *)); - */ -int -__bam_init_recover(dbenv) - DB_ENV *dbenv; -{ - int ret; - - if ((ret = __db_add_recovery(dbenv, - __bam_pg_alloc_recover, DB_bam_pg_alloc)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __bam_pg_free_recover, DB_bam_pg_free)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __bam_split_recover, DB_bam_split)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __bam_rsplit_recover, DB_bam_rsplit)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __bam_adj_recover, DB_bam_adj)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __bam_cadjust_recover, DB_bam_cadjust)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __bam_cdel_recover, DB_bam_cdel)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __bam_repl_recover, DB_bam_repl)) != 0) - return (ret); - return (0); -} - diff --git a/db2/clib/getlong.c b/db2/clib/getlong.c deleted file mode 100644 index 4e144b1..0000000 --- a/db2/clib/getlong.c +++ /dev/null @@ -1,48 +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[] = "@(#)getlong.c 10.3 (Sleepycat) 4/10/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <errno.h> -#include <limits.h> -#include <stdlib.h> -#endif - -#include "db.h" -#include "clib_ext.h" - -/* - * get_long -- - * Return a long value inside of basic parameters. - * - * PUBLIC: void get_long __P((char *, long, long, long *)); - */ -void -get_long(p, min, max, storep) - char *p; - long min, max, *storep; -{ - long val; - char *end; - - __set_errno(0); - val = strtol(p, &end, 10); - if ((val == LONG_MIN || val == LONG_MAX) && errno == ERANGE) - err(1, "%s", p); - if (p[0] == '\0' || end[0] != '\0') - errx(1, "%s: Invalid numeric argument", p); - if (val < min) - errx(1, "%s: Less than minimum value (%ld)", p, min); - if (val > max) - errx(1, "%s: Greater than maximum value (%ld)", p, max); - *storep = val; -} diff --git a/db2/common/db_appinit.c b/db2/common/db_appinit.c deleted file mode 100644 index e02b1a8..0000000 --- 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 5e8fec4..0000000 --- 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 cadf742..0000000 --- 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 e935ddf..0000000 --- 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 d6b14f5..0000000 --- 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 12abfa5..0000000 --- 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 d58b79f..0000000 --- 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 3f48a55..0000000 --- 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); -} diff --git a/db2/compat.h b/db2/compat.h deleted file mode 100644 index 51008af..0000000 --- a/db2/compat.h +++ /dev/null @@ -1,19 +0,0 @@ -/* Compatibility gunk for the db library. */ - -#include <sys/types.h> -#include <errno.h> - -#include <sys/stat.h> -#ifdef _STATBUF_ST_BLKSIZE -# define HAVE_ST_BLKSIZE -#endif - - -#ifndef EFTYPE -# define EFTYPE EINVAL -#endif - -/* Emulate Solaris llseek(). */ -typedef loff_t offset_t; - -extern int llseek (int fd, loff_t offset, int whence); diff --git a/db2/config.h b/db2/config.h deleted file mode 100644 index 6f09795..0000000 --- a/db2/config.h +++ /dev/null @@ -1,150 +0,0 @@ -/* config.h. Generated automatically by configure. */ -/* config.h.in. Generated automatically from configure.in by autoheader. */ - -/* ...but edited by hand to be used in GNU libc. */ - -/* Define to empty if the keyword does not work. */ -/* #undef const */ - -/* Define to `int' if <sys/types.h> doesn't define. */ -/* #undef mode_t */ - -/* Define to `long' if <sys/types.h> doesn't define. */ -/* #undef off_t */ - -/* Define to `int' if <sys/types.h> doesn't define. */ -/* #undef pid_t */ - -/* Define to `unsigned' if <sys/types.h> doesn't define. */ -/* #undef size_t */ - -/* Define if the `S_IS*' macros in <sys/stat.h> do not work properly. */ -/* #undef STAT_MACROS_BROKEN */ - -/* Define if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Say we have endian.h. */ -#define HAVE_ENDIAN_H 1 - -/* Define to `int' if <sys/types.h> doesn't define. */ -/* #undef ssize_t */ - -/* Define if you want a debugging version. */ -/* #undef DEBUG */ - -/* Define if you want a version with run-time diagnostic checking. */ -/* #undef DIAGNOSTIC */ - -/* Define if you have sigfillset (and sigprocmask). */ -#define HAVE_SIGFILLSET 1 - -/* Define if building on AIX, HP, Solaris to get big-file environment. */ -/* #undef HAVE_FILE_OFFSET_BITS */ -#ifdef HAVE_FILE_OFFSET_BITS -#define _FILE_OFFSET_BITS 64 -#endif - -/* Define if you have spinlocks. */ -/* #undef HAVE_SPINLOCKS */ - -/* Define if you want to use mc68020/gcc assembly spinlocks. */ -/* #undef HAVE_ASSEM_MC68020_GCC */ - -/* Define if you want to use parisc/gcc assembly spinlocks. */ -/* #undef HAVE_ASSEM_PARISC_GCC */ - -/* Define if you want to use sco/cc assembly spinlocks. */ -/* #undef HAVE_ASSEM_SCO_CC */ - -/* Define if you want to use sparc/gcc assembly spinlocks. */ -/* #undef HAVE_ASSEM_SPARC_GCC */ - -/* Define if you want to use uts4/cc assembly spinlocks. */ -/* #undef HAVE_ASSEM_UTS4_CC */ - -/* Define if you want to use x86/gcc assembly spinlocks. */ -/* #undef HAVE_ASSEM_X86_GCC */ - -/* Define if you have the AIX _check_lock spinlocks. */ -/* #undef HAVE_FUNC_AIX */ - -/* Define if you have the OSF1 or HPPA msemaphore spinlocks. */ -/* #undef HAVE_FUNC_MSEM */ - -/* Define if you have the SGI abilock_t spinlocks. */ -/* #undef HAVE_FUNC_SGI */ - -/* Define if you have the ReliantUNIX spinlock_t spinlocks. */ -/* #undef HAVE_FUNC_RELIANT */ - -/* Define if you have the Solaris mutex_t spinlocks. */ -/* #undef HAVE_FUNC_SOLARIS */ - -/* Define if your sprintf returns a pointer, not a length. */ -/* #undef SPRINTF_RET_CHARPNT */ - -/* Define if you have the getcwd function. */ -#define HAVE_GETCWD 1 - -/* Define if you have the getopt function. */ -#define HAVE_GETOPT 1 - -/* Define if you have the getuid function. */ -#define HAVE_GETUID 1 - -/* Define if you have the memcmp function. */ -#define HAVE_MEMCMP 1 - -/* Define if you have the memcpy function. */ -#define HAVE_MEMCPY 1 - -/* Define if you have the memmove function. */ -#define HAVE_MEMMOVE 1 - -/* Define if you have the mmap function. */ -#define HAVE_MMAP 1 - -/* Define if you have the raise function. */ -#define HAVE_RAISE 1 - -/* Define if you have the select function. */ -#define HAVE_SELECT 1 - -/* Define if you have the shmget function. */ -#define HAVE_SHMGET 1 - -/* Define if you have the snprintf function. */ -#define HAVE_SNPRINTF 1 - -/* Define if you have the strerror function. */ -#define HAVE_STRERROR 1 - -/* Define if you have the strsep function. */ -#define HAVE_STRSEP 1 - -/* Define if you have the sysconf function. */ -#define HAVE_SYSCONF 1 - -/* Define if you have the vsnprintf function. */ -#define HAVE_VSNPRINTF 1 - -/* Define if you have the <dirent.h> header file. */ -#define HAVE_DIRENT_H 1 - -/* Define if you have the <ndir.h> header file. */ -/* #undef HAVE_NDIR_H */ - -/* Define if you have the <sys/dir.h> header file. */ -/* #undef HAVE_SYS_DIR_H */ - -/* Define if you have the <sys/ndir.h> header file. */ -/* #undef HAVE_SYS_NDIR_H */ - -/* Define if you have the <sys/select.h> header file. */ -#define HAVE_SYS_SELECT_H 1 - -/* Define if you have the <sys/time.h> header file. */ -#define HAVE_SYS_TIME_H 1 - -#include_next <config.h> diff --git a/db2/db.h b/db2/db.h deleted file mode 100644 index 306f2ff..0000000 --- a/db2/db.h +++ /dev/null @@ -1,1033 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - * - * @(#)db.h 10.174 (Sleepycat) 1/3/99 - */ - -#ifndef _DB_H_ -#define _DB_H_ - -#ifndef __NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <stdio.h> -#endif - -/* - * XXX - * MacOS: ensure that Metrowerks C makes enumeration types int sized. - */ -#ifdef __MWERKS__ -#pragma enumsalwaysint on -#endif - -/* - * XXX - * Handle function prototypes and the keyword "const". This steps on name - * space that DB doesn't control, but all of the other solutions are worse. - * - * XXX - * While Microsoft's compiler is ANSI C compliant, it doesn't have _STDC_ - * defined by default, you specify a command line flag or #pragma to turn - * it on. Don't do that, however, because some of Microsoft's own header - * files won't compile. - */ -#undef __P -#if defined(__STDC__) || defined(__cplusplus) || defined(_MSC_VER) -#define __P(protos) protos /* ANSI C prototypes */ -#else -#define const -#define __P(protos) () /* K&R C preprocessor */ -#endif - -/* - * !!! - * DB needs basic information about specifically sized types. If they're - * not provided by the system, typedef them here. - * - * We protect them against multiple inclusion using __BIT_TYPES_DEFINED__, - * as does BIND and Kerberos, since we don't know for sure what #include - * files the user is using. - * - * !!! - * We also provide the standard u_int, u_long etc., if they're not provided - * by the system. - */ - -#define DB_VERSION_MAJOR 2 -#define DB_VERSION_MINOR 7 -#define DB_VERSION_PATCH 5 -#define DB_VERSION_STRING "Sleepycat Software: Berkeley DB 2.7.5: (04/18/99)" - -typedef u_int32_t db_pgno_t; /* Page number type. */ -typedef u_int16_t db_indx_t; /* Page offset type. */ -#define DB_MAX_PAGES 0xffffffff /* >= # of pages in a file */ - -typedef u_int32_t db_recno_t; /* Record number type. */ -#define DB_MAX_RECORDS 0xffffffff /* >= # of records in a tree */ - -typedef size_t DB_LOCK; /* Object returned by lock manager. */ - -/* Forward structure declarations, so applications get type checking. */ -struct __db; typedef struct __db DB; -#ifdef DB_DBM_HSEARCH - typedef struct __db DBM; -#endif -struct __db_bt_stat; typedef struct __db_bt_stat DB_BTREE_STAT; -struct __db_dbt; typedef struct __db_dbt DBT; -struct __db_env; typedef struct __db_env DB_ENV; -struct __db_ilock; typedef struct __db_ilock DB_LOCK_ILOCK; -struct __db_info; typedef struct __db_info DB_INFO; -struct __db_lock_stat; typedef struct __db_lock_stat DB_LOCK_STAT; -struct __db_lockregion; typedef struct __db_lockregion DB_LOCKREGION; -struct __db_lockreq; typedef struct __db_lockreq DB_LOCKREQ; -struct __db_locktab; typedef struct __db_locktab DB_LOCKTAB; -struct __db_log; typedef struct __db_log DB_LOG; -struct __db_log_stat; typedef struct __db_log_stat DB_LOG_STAT; -struct __db_lsn; typedef struct __db_lsn DB_LSN; -struct __db_mpool; typedef struct __db_mpool DB_MPOOL; -struct __db_mpool_finfo;typedef struct __db_mpool_finfo DB_MPOOL_FINFO; -struct __db_mpool_fstat;typedef struct __db_mpool_fstat DB_MPOOL_FSTAT; -struct __db_mpool_stat; typedef struct __db_mpool_stat DB_MPOOL_STAT; -struct __db_mpoolfile; typedef struct __db_mpoolfile DB_MPOOLFILE; -struct __db_txn; typedef struct __db_txn DB_TXN; -struct __db_txn_active; typedef struct __db_txn_active DB_TXN_ACTIVE; -struct __db_txn_stat; typedef struct __db_txn_stat DB_TXN_STAT; -struct __db_txnmgr; typedef struct __db_txnmgr DB_TXNMGR; -struct __db_txnregion; typedef struct __db_txnregion DB_TXNREGION; -struct __dbc; typedef struct __dbc DBC; - -/* Key/data structure -- a Data-Base Thang. */ -struct __db_dbt { - void *data; /* key/data */ - u_int32_t size; /* key/data length */ - u_int32_t ulen; /* RO: length of user buffer. */ - u_int32_t dlen; /* RO: get/put record length. */ - u_int32_t doff; /* RO: get/put record offset. */ - -#define DB_DBT_INTERNAL 0x01 /* Ignore user's malloc (internal). */ -#define DB_DBT_MALLOC 0x02 /* Return in allocated memory. */ -#define DB_DBT_PARTIAL 0x04 /* Partial put/get. */ -#define DB_DBT_USERMEM 0x08 /* Return in user's memory. */ - u_int32_t flags; -}; - -/* - * DB run-time interface configuration. - * - * There are a set of functions that the application can replace with its - * own versions, and some other knobs which can be turned at run-time. - */ -#define DB_FUNC_CLOSE 1 /* POSIX 1003.1 close. */ -#define DB_FUNC_DIRFREE 2 /* DB: free directory list. */ -#define DB_FUNC_DIRLIST 3 /* DB: create directory list. */ -#define DB_FUNC_EXISTS 4 /* DB: return if file exists. */ -#define DB_FUNC_FREE 5 /* ANSI C free. */ -#define DB_FUNC_FSYNC 6 /* POSIX 1003.1 fsync. */ -#define DB_FUNC_IOINFO 7 /* DB: return file I/O information. */ -#define DB_FUNC_MALLOC 8 /* ANSI C malloc. */ -#define DB_FUNC_MAP 9 /* DB: map file into shared memory. */ -#define DB_FUNC_OPEN 10 /* POSIX 1003.1 open. */ -#define DB_FUNC_READ 11 /* POSIX 1003.1 read. */ -#define DB_FUNC_REALLOC 12 /* ANSI C realloc. */ -#define DB_FUNC_RUNLINK 13 /* DB: remove a shared region. */ -#define DB_FUNC_SEEK 14 /* POSIX 1003.1 lseek. */ -#define DB_FUNC_SLEEP 15 /* DB: sleep secs/usecs. */ -#define DB_FUNC_UNLINK 16 /* POSIX 1003.1 unlink. */ -#define DB_FUNC_UNMAP 17 /* DB: unmap shared memory file. */ -#define DB_FUNC_WRITE 18 /* POSIX 1003.1 write. */ -#define DB_FUNC_YIELD 19 /* DB: yield thread to scheduler. */ -#define DB_MUTEXLOCKS 20 /* DB: turn off all mutex locks. */ -#define DB_PAGEYIELD 21 /* DB: yield the CPU on pool get. */ -#define DB_REGION_ANON 22 /* DB: anonymous, unnamed regions. */ -#define DB_REGION_INIT 23 /* DB: page-fault regions in create. */ -#define DB_REGION_NAME 24 /* DB: anonymous, named regions. */ -#define DB_TSL_SPINS 25 /* DB: initialize spin count. */ - -/* - * Database configuration and initialization. - */ - /* - * Flags understood by both db_open(3) and db_appinit(3). - */ -#define DB_CREATE 0x000001 /* O_CREAT: create file as necessary. */ -#define DB_NOMMAP 0x000002 /* Don't mmap underlying file. */ -#define DB_THREAD 0x000004 /* Free-thread DB package handles. */ - -/* - * Flags understood by db_appinit(3). - */ -/* 0x000007 COMMON MASK. */ -#define DB_INIT_CDB 0x000008 /* Concurrent Access Methods. */ -#define DB_INIT_LOCK 0x000010 /* Initialize locking. */ -#define DB_INIT_LOG 0x000020 /* Initialize logging. */ -#define DB_INIT_MPOOL 0x000040 /* Initialize mpool. */ -#define DB_INIT_TXN 0x000080 /* Initialize transactions. */ -#define DB_MPOOL_PRIVATE 0x000100 /* Mpool: private memory pool. */ -#define DB_RECOVER 0x000200 /* Run normal recovery. */ -#define DB_RECOVER_FATAL 0x000400 /* Run catastrophic recovery. */ -#define DB_TXN_NOSYNC 0x000800 /* Do not sync log on commit. */ -#define DB_USE_ENVIRON 0x001000 /* Use the environment. */ -#define DB_USE_ENVIRON_ROOT 0x002000 /* Use the environment if root. */ - -/* - * Flags understood by db_open(3). - * - * DB_EXCL and DB_TEMPORARY are internal only, and are not documented. - * DB_SEQUENTIAL is currently internal, but may be exported some day. - */ -/* 0x000007 COMMON MASK. */ -/* 0x001fff ALREADY USED. */ -#define DB_EXCL 0x002000 /* O_EXCL: exclusive open (internal). */ -#define DB_RDONLY 0x004000 /* O_RDONLY: read-only. */ -#define DB_SEQUENTIAL 0x008000 /* Sequential access (internal). */ -#define DB_TEMPORARY 0x010000 /* Remove on last close (internal). */ -#define DB_TRUNCATE 0x020000 /* O_TRUNCATE: replace existing DB. */ - -/* - * Deadlock detector modes; used in the DBENV structure to configure the - * locking subsystem. - */ -#define DB_LOCK_NORUN 0 -#define DB_LOCK_DEFAULT 1 /* Default policy. */ -#define DB_LOCK_OLDEST 2 /* Abort oldest transaction. */ -#define DB_LOCK_RANDOM 3 /* Abort random transaction. */ -#define DB_LOCK_YOUNGEST 4 /* Abort youngest transaction. */ - -struct __db_env { - int db_lorder; /* Byte order. */ - - /* Error message callback. */ - void (*db_errcall) (const char *, char *); - FILE *db_errfile; /* Error message file stream. */ - const char *db_errpfx; /* Error message prefix. */ - int db_verbose; /* Generate debugging messages. */ - int db_panic; /* Panic flag, callback function. */ - void (*db_paniccall) (DB_ENV *, int); - - /* User paths. */ - char *db_home; /* Database home. */ - char *db_log_dir; /* Database log file directory. */ - char *db_tmp_dir; /* Database tmp file directory. */ - - char **db_data_dir; /* Database data file directories. */ - int data_cnt; /* Database data file slots. */ - int data_next; /* Next Database data file slot. */ - - /* Locking. */ - DB_LOCKTAB *lk_info; /* Return from lock_open(). */ - const u_int8_t *lk_conflicts; /* Two dimensional conflict matrix. */ - u_int32_t lk_modes; /* Number of lock modes in table. */ - u_int32_t lk_max; /* Maximum number of locks. */ - u_int32_t lk_detect; /* Deadlock detect on all conflicts. */ - - /* Logging. */ - DB_LOG *lg_info; /* Return from log_open(). */ - u_int32_t lg_max; /* Maximum file size. */ - - /* Memory pool. */ - DB_MPOOL *mp_info; /* Return from memp_open(). */ - size_t mp_mmapsize; /* Maximum file size for mmap. */ - size_t mp_size; /* Bytes in the mpool cache. */ - - /* Transactions. */ - DB_TXNMGR *tx_info; /* Return from txn_open(). */ - u_int32_t tx_max; /* Maximum number of transactions. */ - int (*tx_recover) /* Dispatch function for recovery. */ - (DB_LOG *, DBT *, DB_LSN *, int, void *); - - /* - * XA support. - * - * !!! - * Explicit representations of structures in queue.h. - * - * TAILQ_ENTRY(__db_env); - */ - struct { - struct __db_env *tqe_next; - struct __db_env **tqe_prev; - } links; - int xa_rmid; /* XA Resource Manager ID. */ - DB_TXN *xa_txn; /* XA Current transaction. */ - -#define DB_ENV_APPINIT 0x01 /* Paths initialized by db_appinit(). */ -#define DB_ENV_CDB 0x02 /* Concurrent DB product. */ -#define DB_ENV_STANDALONE 0x04 /* Test: freestanding environment. */ -#define DB_ENV_THREAD 0x08 /* DB_ENV is multi-threaded. */ - u_int32_t flags; /* Flags. */ -}; - -/******************************************************* - * Access methods. - *******************************************************/ -/* - * !!! - * Changes here must be reflected in java/src/com/sleepycat/db/Db.java. - */ -typedef enum { - DB_BTREE=1, /* B+tree. */ - DB_HASH, /* Extended Linear Hashing. */ - DB_RECNO, /* Fixed and variable-length records. */ - DB_UNKNOWN /* Figure it out on open. */ -} DBTYPE; - -#define DB_BTREEVERSION 6 /* Current btree version. */ -#define DB_BTREEOLDVER 6 /* Oldest btree version supported. */ -#define DB_BTREEMAGIC 0x053162 - -#define DB_HASHVERSION 5 /* Current hash version. */ -#define DB_HASHOLDVER 4 /* Oldest hash version supported. */ -#define DB_HASHMAGIC 0x061561 - -#define DB_LOGVERSION 2 /* Current log version. */ -#define DB_LOGOLDVER 2 /* Oldest log version supported. */ -#define DB_LOGMAGIC 0x040988 - -struct __db_info { - int db_lorder; /* Byte order. */ - size_t db_cachesize; /* Underlying cache size. */ - size_t db_pagesize; /* Underlying page size. */ - - /* Local heap allocation. */ - void *(*db_malloc) (size_t); - int (*dup_compare) /* Duplicate compare function. */ - (const DBT *, const DBT *); - - /* Btree access method. */ - u_int32_t bt_maxkey; /* Maximum keys per page. */ - u_int32_t bt_minkey; /* Minimum keys per page. */ - int (*bt_compare) /* Comparison function. */ - (const DBT *, const DBT *); - size_t (*bt_prefix) /* Prefix function. */ - (const DBT *, const DBT *); - - /* Hash access method. */ - u_int32_t h_ffactor; /* Fill factor. */ - u_int32_t h_nelem; /* Number of elements. */ - u_int32_t (*h_hash) /* Hash function. */ - (const void *, u_int32_t); - - /* Recno access method. */ - int re_pad; /* Fixed-length padding byte. */ - int re_delim; /* Variable-length delimiting byte. */ - u_int32_t re_len; /* Length for fixed-length records. */ - char *re_source; /* Source file name. */ - -#define DB_DELIMITER 0x0001 /* Recno: re_delim set. */ -#define DB_DUP 0x0002 /* Btree, Hash: duplicate keys. */ -#define DB_DUPSORT 0x0004 /* Btree, Hash: duplicate keys. */ -#define DB_FIXEDLEN 0x0008 /* Recno: fixed-length records. */ -#define DB_PAD 0x0010 /* Recno: re_pad set. */ -#define DB_RECNUM 0x0020 /* Btree: record numbers. */ -#define DB_RENUMBER 0x0040 /* Recno: renumber on insert/delete. */ -#define DB_SNAPSHOT 0x0080 /* Recno: snapshot the input. */ - u_int32_t flags; -}; - -/* - * DB access method and cursor operation values. Each value is an operation - * code to which additional bit flags are added. - */ -#define DB_AFTER 1 /* c_put() */ -#define DB_APPEND 2 /* put() */ -#define DB_BEFORE 3 /* c_put() */ -#define DB_CHECKPOINT 4 /* log_put(), log_get() */ -#define DB_CURLSN 5 /* log_put() */ -#define DB_CURRENT 6 /* c_get(), c_put(), log_get() */ -#define DB_FIRST 7 /* c_get(), log_get() */ -#define DB_FLUSH 8 /* log_put() */ -#define DB_GET_BOTH 9 /* get(), c_get() */ -#define DB_GET_RECNO 10 /* c_get() */ -#define DB_JOIN_ITEM 11 /* c_get(); do not do primary lookup */ -#define DB_KEYFIRST 12 /* c_put() */ -#define DB_KEYLAST 13 /* c_put() */ -#define DB_LAST 14 /* c_get(), log_get() */ -#define DB_NEXT 15 /* c_get(), log_get() */ -#define DB_NEXT_DUP 16 /* c_get() */ -#define DB_NOOVERWRITE 17 /* put() */ -#define DB_NOSYNC 18 /* close() */ -#define DB_PREV 19 /* c_get(), log_get() */ -#define DB_RECORDCOUNT 20 /* stat() */ -#define DB_SET 21 /* c_get(), log_get() */ -#define DB_SET_RANGE 22 /* c_get() */ -#define DB_SET_RECNO 23 /* get(), c_get() */ -#define DB_WRITELOCK 24 /* cursor() (internal) */ - -#define DB_OPFLAGS_MASK 0x1f /* Mask for operations flags. */ -#define DB_RMW 0x80000000 /* Acquire write flag immediately. */ - -/* - * DB (user visible) error return codes. - * - * !!! - * Changes to any of the user visible error return codes must be reflected - * in java/src/com/sleepycat/db/Db.java. - */ -#define DB_INCOMPLETE ( -1) /* Sync didn't finish. */ -#define DB_KEYEMPTY ( -2) /* The key/data pair was deleted or - was never created by the user. */ -#define DB_KEYEXIST ( -3) /* The key/data pair already exists. */ -#define DB_LOCK_DEADLOCK ( -4) /* Locker killed to resolve deadlock. */ -#define DB_LOCK_NOTGRANTED ( -5) /* Lock unavailable, no-wait set. */ -#define DB_LOCK_NOTHELD ( -6) /* Lock not held by locker. */ -#define DB_NOTFOUND ( -7) /* Key/data pair not found (EOF). */ -#define DB_RUNRECOVERY ( -8) /* Panic return. */ - -/* DB (private) error return codes. */ -#define DB_DELETED ( -9) /* Recovery file marked deleted. */ -#define DB_NEEDSPLIT (-10) /* Page needs to be split. */ -#define DB_SWAPBYTES (-11) /* Database needs byte swapping. */ -#define DB_TXN_CKP (-12) /* Encountered ckp record in log. */ - -#define DB_FILE_ID_LEN 20 /* DB file ID length. */ - -/* DB access method description structure. */ -struct __db { - void *mutexp; /* Synchronization for free threading */ - - /* Documented, returned information. */ - DBTYPE type; /* DB access method. */ - int byteswapped; /* Database byte order is swapped. */ - - DB_ENV *dbenv; /* DB_ENV structure. */ - DB_ENV *mp_dbenv; /* DB_ENV for local mpool creation. */ - - void *internal; /* Access method private. */ - - DB_MPOOL *mp; /* The access method's mpool. */ - DB_MPOOLFILE *mpf; /* The access method's mpool file. */ - - /* - * !!! - * Explicit representations of structures in queue.h. - * - * TAILQ_HEAD(free_queue, __dbc); - * TAILQ_HEAD(active_queue, __dbc); - */ - struct { - struct __dbc *tqh_first; - struct __dbc **tqh_last; - } free_queue; - struct { - struct __dbc *tqh_first; - struct __dbc **tqh_last; - } active_queue; - - u_int8_t fileid[DB_FILE_ID_LEN]; /* Uniquely identify this file for - locking. */ - u_int32_t log_fileid; /* Logging file id. */ - size_t pgsize; /* Logical page size of file. */ - - /* Local heap allocation. */ - void *(*db_malloc) (size_t); - int (*dup_compare) /* Duplicate compare function. */ - (const DBT *, const DBT *); - u_int32_t (*h_hash) /* Hash function. */ - (const void *, u_int32_t); - - /* Functions. */ - int (*am_close) (DB *); - int (*close) (DB *, u_int32_t); - int (*cursor) (DB *, DB_TXN *, DBC **, u_int32_t); - int (*del) (DB *, DB_TXN *, DBT *, u_int32_t); - int (*fd) (DB *, int *); - int (*get) (DB *, DB_TXN *, DBT *, DBT *, u_int32_t); - int (*join) (DB *, DBC **, u_int32_t, DBC **); - int (*put) (DB *, DB_TXN *, DBT *, DBT *, u_int32_t); - int (*stat) (DB *, void *, void *(*)(size_t), u_int32_t); - int (*sync) (DB *, u_int32_t); - -#define DB_AM_CDB 0x000001 /* Concurrent Access Methods. */ -#define DB_AM_DUP 0x000002 /* DB_DUP (internal). */ -#define DB_AM_INMEM 0x000004 /* In-memory; no sync on close. */ -#define DB_AM_LOCKING 0x000008 /* Perform locking. */ -#define DB_AM_LOGGING 0x000010 /* Perform logging. */ -#define DB_AM_MLOCAL 0x000020 /* Database memory pool is local. */ -#define DB_AM_PGDEF 0x000040 /* Page size was defaulted. */ -#define DB_AM_RDONLY 0x000080 /* Database is readonly. */ -#define DB_AM_SWAP 0x000100 /* Pages need to be byte-swapped. */ -#define DB_AM_THREAD 0x000200 /* DB is multi-threaded. */ -#define DB_BT_RECNUM 0x000400 /* DB_RECNUM (internal). */ -#define DB_DBM_ERROR 0x000800 /* Error in DBM/NDBM database. */ -#define DB_RE_DELIMITER 0x001000 /* DB_DELIMITER (internal). */ -#define DB_RE_FIXEDLEN 0x002000 /* DB_FIXEDLEN (internal). */ -#define DB_RE_PAD 0x004000 /* DB_PAD (internal). */ -#define DB_RE_RENUMBER 0x008000 /* DB_RENUMBER (internal). */ -#define DB_RE_SNAPSHOT 0x010000 /* DB_SNAPSHOT (internal). */ - u_int32_t flags; -}; - -struct __db_ilock { /* Internal DB access method lock. */ - db_pgno_t pgno; /* Page being locked. */ - u_int8_t fileid[DB_FILE_ID_LEN];/* File id. */ -}; - -/* Cursor description structure. */ -struct __dbc { - DB *dbp; /* Related DB access method. */ - DB_TXN *txn; /* Associated transaction. */ - - /* - * !!! - * Explicit representations of structures in queue.h. - * - * TAILQ_ENTRY(__dbc); - */ - struct { - struct __dbc *tqe_next; - struct __dbc **tqe_prev; - } links; - - u_int32_t lid; /* Default process' locker id. */ - u_int32_t locker; /* Locker for this operation. */ - DBT lock_dbt; /* DBT referencing lock. */ - DB_LOCK_ILOCK lock; /* Object to be locked. */ - DB_LOCK mylock; /* Lock held on this cursor. */ - - DBT rkey; /* Returned key. */ - DBT rdata; /* Returned data. */ - - int (*c_am_close) (DBC *); - int (*c_am_destroy) (DBC *); - int (*c_close) (DBC *); - int (*c_del) (DBC *, u_int32_t); - int (*c_get) (DBC *, DBT *, DBT *, u_int32_t); - int (*c_put) (DBC *, DBT *, DBT *, u_int32_t); - - void *internal; /* Access method private. */ - -#define DBC_CONTINUE 0x001 /* Continue dup search: next item. */ -#define DBC_KEYSET 0x002 /* Continue dup search: current item. */ -#define DBC_RECOVER 0x004 /* In recovery (do not log or lock). */ -#define DBC_RMW 0x008 /* Acquire write flag in read op. */ -#define DBC_WRITER 0x010 /* Cursor immediately writing (CDB). */ - u_int32_t flags; -}; - -/* Btree/recno statistics structure. */ -struct __db_bt_stat { - u_int32_t bt_flags; /* Open flags. */ - u_int32_t bt_maxkey; /* Maxkey value. */ - u_int32_t bt_minkey; /* Minkey value. */ - u_int32_t bt_re_len; /* Fixed-length record length. */ - u_int32_t bt_re_pad; /* Fixed-length record pad. */ - u_int32_t bt_pagesize; /* Page size. */ - u_int32_t bt_levels; /* Tree levels. */ - u_int32_t bt_nrecs; /* Number of records. */ - u_int32_t bt_int_pg; /* Internal pages. */ - u_int32_t bt_leaf_pg; /* Leaf pages. */ - u_int32_t bt_dup_pg; /* Duplicate pages. */ - u_int32_t bt_over_pg; /* Overflow pages. */ - u_int32_t bt_free; /* Pages on the free list. */ - u_int32_t bt_int_pgfree; /* Bytes free in internal pages. */ - u_int32_t bt_leaf_pgfree; /* Bytes free in leaf pages. */ - u_int32_t bt_dup_pgfree; /* Bytes free in duplicate pages. */ - u_int32_t bt_over_pgfree; /* Bytes free in overflow pages. */ - u_int32_t bt_magic; /* Magic number. */ - u_int32_t bt_version; /* Version number. */ -}; - -/* Hash statistics structure. */ -struct __db_h_stat { - u_int32_t hash_accesses; /* Number of accesses to this table. */ - u_int32_t hash_collisions; /* Number of collisions on search. */ - u_int32_t hash_expansions; /* Number of times we added a bucket. */ - u_int32_t hash_overflows; /* Number of overflow pages. */ - u_int32_t hash_bigpages; /* Number of big key/data pages. */ - u_int32_t hash_dup; /* Number of dup pages. */ - u_int32_t hash_free; /* Pages on the free list. */ - u_int32_t hash_bfree; /* Bytes free on bucket pages. */ - u_int32_t hash_dup_free; /* Bytes free on duplicate pages. */ - u_int32_t hash_big_bfree; /* Bytes free on big item pages. */ - u_int32_t hash_buckets; /* Number of hash buckets. */ - u_int32_t hash_put; /* Number of puts. */ - u_int32_t hash_deleted; /* Number of deletes. */ - u_int32_t hash_get; /* Number of gets. */ - u_int32_t hash_magic; /* Magic number. */ - u_int32_t hash_version; /* Version number. */ - u_int32_t hash_pagesize; /* Page size. */ - u_int32_t hash_nrecs; /* Number of records. */ -}; - -#if defined(__cplusplus) -extern "C" { -#endif -int db_appinit (const char *, char * const *, DB_ENV *, u_int32_t); -int db_appexit (DB_ENV *); -int db_jump_set (void *, int); -int db_open (const char *, - DBTYPE, u_int32_t, int, DB_ENV *, DB_INFO *, DB **); -int db_value_set (int, int); -char *db_version (int *, int *, int *); -int db_xa_open (const char *, DBTYPE, u_int32_t, int, DB_INFO *, DB **); -#if defined(__cplusplus) -} -#endif - -/******************************************************* - * Locking - *******************************************************/ -#define DB_LOCKVERSION 1 -#define DB_LOCKMAGIC 0x090193 - -/* Flag values for lock_vec(), lock_get(). */ -#define DB_LOCK_NOWAIT 0x01 /* Don't wait on unavailable lock. */ -#define DB_LOCK_UPGRADE 0x02 /* Upgrade an existing lock instead - of granting a new one (internal). */ - -/* Flag values for lock_detect(). */ -#define DB_LOCK_CONFLICT 0x01 /* Run on any conflict. */ - -/* - * Request types. - * - * !!! - * Changes here must be reflected in java/src/com/sleepycat/db/Db.java. - */ -typedef enum { - DB_LOCK_DUMP=0, /* Display held locks. */ - DB_LOCK_GET, /* Get the lock. */ - DB_LOCK_INHERIT, /* Pass locks to parent. */ - DB_LOCK_PUT, /* Release the lock. */ - DB_LOCK_PUT_ALL, /* Release locker's locks. */ - DB_LOCK_PUT_OBJ /* Release locker's locks on obj. */ -} db_lockop_t; - -/* - * Simple R/W lock modes and for multi-granularity intention locking. - * - * !!! - * These values are NOT random, as they are used as an index into the lock - * conflicts arrays, i.e., DB_LOCK_IWRITE must be == 3, and DB_LOCK_IREAD - * must be == 4. - * - * !!! - * Changes here must be reflected in java/src/com/sleepycat/db/Db.java. - */ -typedef enum { - DB_LOCK_NG=0, /* Not granted. */ - DB_LOCK_READ, /* Shared/read. */ - DB_LOCK_WRITE, /* Exclusive/write. */ - DB_LOCK_IWRITE, /* Intent exclusive/write. */ - DB_LOCK_IREAD, /* Intent to share/read. */ - DB_LOCK_IWR /* Intent to read and write. */ -} db_lockmode_t; - -/* - * Status of a lock. - */ -typedef enum { - DB_LSTAT_ABORTED, /* Lock belongs to an aborted txn. */ - DB_LSTAT_ERR, /* Lock is bad. */ - DB_LSTAT_FREE, /* Lock is unallocated. */ - DB_LSTAT_HELD, /* Lock is currently held. */ - DB_LSTAT_NOGRANT, /* Lock was not granted. */ - DB_LSTAT_PENDING, /* Lock was waiting and has been - * promoted; waiting for the owner - * to run and upgrade it to held. */ - DB_LSTAT_WAITING /* Lock is on the wait queue. */ -} db_status_t; - -/* Lock request structure. */ -struct __db_lockreq { - db_lockop_t op; /* Operation. */ - db_lockmode_t mode; /* Requested mode. */ - u_int32_t locker; /* Locker identity. */ - DBT *obj; /* Object being locked. */ - DB_LOCK lock; /* Lock returned. */ -}; - -/* - * Commonly used conflict matrices. - * - * Standard Read/Write (or exclusive/shared) locks. - */ -#define DB_LOCK_RW_N 3 -extern const u_int8_t db_rw_conflicts[]; - -/* Multi-granularity locking. */ -#define DB_LOCK_RIW_N 6 -extern const u_int8_t db_riw_conflicts[]; - -struct __db_lock_stat { - u_int32_t st_magic; /* Lock file magic number. */ - u_int32_t st_version; /* Lock file version number. */ - u_int32_t st_maxlocks; /* Maximum number of locks in table. */ - u_int32_t st_nmodes; /* Number of lock modes. */ - u_int32_t st_numobjs; /* Number of objects. */ - u_int32_t st_nlockers; /* Number of lockers. */ - u_int32_t st_nconflicts; /* Number of lock conflicts. */ - u_int32_t st_nrequests; /* Number of lock gets. */ - u_int32_t st_nreleases; /* Number of lock puts. */ - u_int32_t st_ndeadlocks; /* Number of lock deadlocks. */ - u_int32_t st_region_wait; /* Region lock granted after wait. */ - u_int32_t st_region_nowait; /* Region lock granted without wait. */ - u_int32_t st_refcnt; /* Region reference count. */ - u_int32_t st_regsize; /* Region size. */ -}; - -#if defined(__cplusplus) -extern "C" { -#endif -int lock_close (DB_LOCKTAB *); -int lock_detect (DB_LOCKTAB *, u_int32_t, u_int32_t); -int lock_get (DB_LOCKTAB *, - u_int32_t, u_int32_t, const DBT *, db_lockmode_t, DB_LOCK *); -int lock_id (DB_LOCKTAB *, u_int32_t *); -int lock_open (const char *, u_int32_t, int, DB_ENV *, DB_LOCKTAB **); -int lock_put (DB_LOCKTAB *, DB_LOCK); -int lock_tget (DB_LOCKTAB *, - DB_TXN *, u_int32_t, const DBT *, db_lockmode_t, DB_LOCK *); -int lock_stat (DB_LOCKTAB *, DB_LOCK_STAT **, void *(*)(size_t)); -int lock_unlink (const char *, int, DB_ENV *); -int lock_vec (DB_LOCKTAB *, - u_int32_t, u_int32_t, DB_LOCKREQ *, int, DB_LOCKREQ **); -int lock_tvec (DB_LOCKTAB *, - DB_TXN *, u_int32_t, DB_LOCKREQ *, int, DB_LOCKREQ **); -#if defined(__cplusplus) -} -#endif - -/******************************************************* - * Logging. - *******************************************************/ -/* Flag values for log_archive(). */ -#define DB_ARCH_ABS 0x001 /* Absolute pathnames. */ -#define DB_ARCH_DATA 0x002 /* Data files. */ -#define DB_ARCH_LOG 0x004 /* Log files. */ - -/* - * A DB_LSN has two parts, a fileid which identifies a specific file, and an - * offset within that file. The fileid is an unsigned 4-byte quantity that - * uniquely identifies a file within the log directory -- currently a simple - * counter inside the log. The offset is also an unsigned 4-byte value. The - * log manager guarantees the offset is never more than 4 bytes by switching - * to a new log file before the maximum length imposed by an unsigned 4-byte - * offset is reached. - */ -struct __db_lsn { - u_int32_t file; /* File ID. */ - u_int32_t offset; /* File offset. */ -}; - -/* Log statistics structure. */ -struct __db_log_stat { - u_int32_t st_magic; /* Log file magic number. */ - u_int32_t st_version; /* Log file version number. */ - int st_mode; /* Log file mode. */ - u_int32_t st_lg_max; /* Maximum log file size. */ - u_int32_t st_w_bytes; /* Bytes to log. */ - u_int32_t st_w_mbytes; /* Megabytes to log. */ - u_int32_t st_wc_bytes; /* Bytes to log since checkpoint. */ - u_int32_t st_wc_mbytes; /* Megabytes to log since checkpoint. */ - u_int32_t st_wcount; /* Total syncs to the log. */ - u_int32_t st_scount; /* Total writes to the log. */ - u_int32_t st_region_wait; /* Region lock granted after wait. */ - u_int32_t st_region_nowait; /* Region lock granted without wait. */ - u_int32_t st_cur_file; /* Current log file number. */ - u_int32_t st_cur_offset; /* Current log file offset. */ - u_int32_t st_refcnt; /* Region reference count. */ - u_int32_t st_regsize; /* Region size. */ -}; - -#if defined(__cplusplus) -extern "C" { -#endif -int log_archive (DB_LOG *, char **[], u_int32_t, void *(*)(size_t)); -int log_close (DB_LOG *); -int log_compare (const DB_LSN *, const DB_LSN *); -int log_file (DB_LOG *, const DB_LSN *, char *, size_t); -int log_flush (DB_LOG *, const DB_LSN *); -int log_get (DB_LOG *, DB_LSN *, DBT *, u_int32_t); -int log_open (const char *, u_int32_t, int, DB_ENV *, DB_LOG **); -int log_put (DB_LOG *, DB_LSN *, const DBT *, u_int32_t); -int log_register (DB_LOG *, DB *, const char *, DBTYPE, u_int32_t *); -int log_stat (DB_LOG *, DB_LOG_STAT **, void *(*)(size_t)); -int log_unlink (const char *, int, DB_ENV *); -int log_unregister (DB_LOG *, u_int32_t); -#if defined(__cplusplus) -} -#endif - -/******************************************************* - * Mpool - *******************************************************/ -/* Flag values for memp_fget(). */ -#define DB_MPOOL_CREATE 0x001 /* Create a page. */ -#define DB_MPOOL_LAST 0x002 /* Return the last page. */ -#define DB_MPOOL_NEW 0x004 /* Create a new page. */ - -/* Flag values for memp_fput(), memp_fset(). */ -#define DB_MPOOL_CLEAN 0x001 /* Clear modified bit. */ -#define DB_MPOOL_DIRTY 0x002 /* Page is modified. */ -#define DB_MPOOL_DISCARD 0x004 /* Don't cache the page. */ - -/* Mpool statistics structure. */ -struct __db_mpool_stat { - size_t st_cachesize; /* Cache size. */ - u_int32_t st_cache_hit; /* Pages found in the cache. */ - u_int32_t st_cache_miss; /* Pages not found in the cache. */ - u_int32_t st_map; /* Pages from mapped files. */ - u_int32_t st_page_create; /* Pages created in the cache. */ - u_int32_t st_page_in; /* Pages read in. */ - u_int32_t st_page_out; /* Pages written out. */ - u_int32_t st_ro_evict; /* Clean pages forced from the cache. */ - u_int32_t st_rw_evict; /* Dirty pages forced from the cache. */ - u_int32_t st_hash_buckets; /* Number of hash buckets. */ - u_int32_t st_hash_searches; /* Total hash chain searches. */ - u_int32_t st_hash_longest; /* Longest hash chain searched. */ - u_int32_t st_hash_examined; /* Total hash entries searched. */ - u_int32_t st_page_clean; /* Clean pages. */ - u_int32_t st_page_dirty; /* Dirty pages. */ - u_int32_t st_page_trickle; /* Pages written by memp_trickle. */ - u_int32_t st_region_wait; /* Region lock granted after wait. */ - u_int32_t st_region_nowait; /* Region lock granted without wait. */ - u_int32_t st_refcnt; /* Region reference count. */ - u_int32_t st_regsize; /* Region size. */ -}; - -/* Mpool file open information structure. */ -struct __db_mpool_finfo { - int ftype; /* File type. */ - DBT *pgcookie; /* Byte-string passed to pgin/pgout. */ - u_int8_t *fileid; /* Unique file ID. */ - int32_t lsn_offset; /* LSN offset in page. */ - u_int32_t clear_len; /* Cleared length on created pages. */ -}; - -/* Mpool file statistics structure. */ -struct __db_mpool_fstat { - char *file_name; /* File name. */ - size_t st_pagesize; /* Page size. */ - u_int32_t st_cache_hit; /* Pages found in the cache. */ - u_int32_t st_cache_miss; /* Pages not found in the cache. */ - u_int32_t st_map; /* Pages from mapped files. */ - u_int32_t st_page_create; /* Pages created in the cache. */ - u_int32_t st_page_in; /* Pages read in. */ - u_int32_t st_page_out; /* Pages written out. */ -}; - -#if defined(__cplusplus) -extern "C" { -#endif -int memp_close (DB_MPOOL *); -int memp_fclose (DB_MPOOLFILE *); -int memp_fget (DB_MPOOLFILE *, db_pgno_t *, u_int32_t, void *); -int memp_fopen (DB_MPOOL *, const char *, - u_int32_t, int, size_t, DB_MPOOL_FINFO *, DB_MPOOLFILE **); -int memp_fput (DB_MPOOLFILE *, void *, u_int32_t); -int memp_fset (DB_MPOOLFILE *, void *, u_int32_t); -int memp_fsync (DB_MPOOLFILE *); -int memp_open (const char *, u_int32_t, int, DB_ENV *, DB_MPOOL **); -int memp_register (DB_MPOOL *, int, - int (*)(db_pgno_t, void *, DBT *), - int (*)(db_pgno_t, void *, DBT *)); -int memp_stat (DB_MPOOL *, - DB_MPOOL_STAT **, DB_MPOOL_FSTAT ***, void *(*)(size_t)); -int memp_sync (DB_MPOOL *, DB_LSN *); -int memp_trickle (DB_MPOOL *, int, int *); -int memp_unlink (const char *, int, DB_ENV *); -#if defined(__cplusplus) -} -#endif - -/******************************************************* - * Transactions. - *******************************************************/ -#define DB_TXNVERSION 1 -#define DB_TXNMAGIC 0x041593 - -/* Operations values to the tx_recover() function. */ -#define DB_TXN_BACKWARD_ROLL 1 /* Read the log backwards. */ -#define DB_TXN_FORWARD_ROLL 2 /* Read the log forwards. */ -#define DB_TXN_OPENFILES 3 /* Read for open files. */ -#define DB_TXN_REDO 4 /* Redo the operation. */ -#define DB_TXN_UNDO 5 /* Undo the operation. */ - -/* Internal transaction status values. */ - -/* Transaction statistics structure. */ -struct __db_txn_active { - u_int32_t txnid; /* Transaction ID */ - DB_LSN lsn; /* Lsn of the begin record */ -}; - -struct __db_txn_stat { - DB_LSN st_last_ckp; /* lsn of the last checkpoint */ - DB_LSN st_pending_ckp; /* last checkpoint did not finish */ - time_t st_time_ckp; /* time of last checkpoint */ - u_int32_t st_last_txnid; /* last transaction id given out */ - u_int32_t st_maxtxns; /* maximum number of active txns */ - u_int32_t st_naborts; /* number of aborted transactions */ - u_int32_t st_nbegins; /* number of begun transactions */ - u_int32_t st_ncommits; /* number of committed transactions */ - u_int32_t st_nactive; /* number of active transactions */ - DB_TXN_ACTIVE - *st_txnarray; /* array of active transactions */ - u_int32_t st_region_wait; /* Region lock granted after wait. */ - u_int32_t st_region_nowait; /* Region lock granted without wait. */ - u_int32_t st_refcnt; /* Region reference count. */ - u_int32_t st_regsize; /* Region size. */ -}; - -#if defined(__cplusplus) -extern "C" { -#endif -int txn_abort (DB_TXN *); -int txn_begin (DB_TXNMGR *, DB_TXN *, DB_TXN **); -int txn_checkpoint (const DB_TXNMGR *, u_int32_t, u_int32_t); -int txn_commit (DB_TXN *); -int txn_close (DB_TXNMGR *); -u_int32_t txn_id (DB_TXN *); -int txn_open (const char *, u_int32_t, int, DB_ENV *, DB_TXNMGR **); -int txn_prepare (DB_TXN *); -int txn_stat (DB_TXNMGR *, DB_TXN_STAT **, void *(*)(size_t)); -int txn_unlink (const char *, int, DB_ENV *); -#if defined(__cplusplus) -} -#endif - -#ifndef DB_DBM_HSEARCH -#define DB_DBM_HSEARCH 0 /* No historic interfaces by default. */ -#endif -#if DB_DBM_HSEARCH != 0 -/******************************************************* - * Dbm/Ndbm historic interfaces. - *******************************************************/ -#define DBM_INSERT 0 /* Flags to dbm_store(). */ -#define DBM_REPLACE 1 - -/* - * The db(3) support for ndbm(3) always appends this suffix to the - * file name to avoid overwriting the user's original database. - */ -#define DBM_SUFFIX ".db" - -#if defined(_XPG4_2) -typedef struct { - char *dptr; - size_t dsize; -} datum; -#else -typedef struct { - char *dptr; - int dsize; -} datum; -#endif - -/* - * Translate DBM calls into DB calls so that DB doesn't step on the - * application's name space. - * - * The global variables dbrdonly, dirf and pagf were not retained when - * 4BSD replaced the dbm interface with ndbm, and are not support here. - */ -#define dbminit(a) __db_dbm_init(a) -#define dbmclose __db_dbm_close -#if !defined(__cplusplus) -#define delete(a) __db_dbm_delete(a) -#endif -#define fetch(a) __db_dbm_fetch(a) -#define firstkey __db_dbm_firstkey -#define nextkey(a) __db_dbm_nextkey(a) -#define store(a, b) __db_dbm_store(a, b) - -/* Prototype the DB calls. */ -#if defined(__cplusplus) -extern "C" { -#endif -int __db_dbm_close (void); -int __db_dbm_dbrdonly (void); -int __db_dbm_delete (datum); -int __db_dbm_dirf (void); -datum __db_dbm_fetch (datum); -datum __db_dbm_firstkey (void); -int __db_dbm_init (char *); -datum __db_dbm_nextkey (datum); -int __db_dbm_pagf (void); -int __db_dbm_store (datum, datum); -#if defined(__cplusplus) -} -#endif - -/* - * Translate NDBM calls into DB calls so that DB doesn't step on the - * application's name space. - */ -#define dbm_clearerr(a) __db_ndbm_clearerr(a) -#define dbm_close(a) __db_ndbm_close(a) -#define dbm_delete(a, b) __db_ndbm_delete(a, b) -#define dbm_dirfno(a) __db_ndbm_dirfno(a) -#define dbm_error(a) __db_ndbm_error(a) -#define dbm_fetch(a, b) __db_ndbm_fetch(a, b) -#define dbm_firstkey(a) __db_ndbm_firstkey(a) -#define dbm_nextkey(a) __db_ndbm_nextkey(a) -#define dbm_open(a, b, c) __db_ndbm_open(a, b, c) -#define dbm_pagfno(a) __db_ndbm_pagfno(a) -#define dbm_rdonly(a) __db_ndbm_rdonly(a) -#define dbm_store(a, b, c, d) __db_ndbm_store(a, b, c, d) - -/* Prototype the DB calls. */ -#if defined(__cplusplus) -extern "C" { -#endif -int __db_ndbm_clearerr (DBM *); -void __db_ndbm_close (DBM *); -int __db_ndbm_delete (DBM *, datum); -int __db_ndbm_dirfno (DBM *); -int __db_ndbm_error (DBM *); -datum __db_ndbm_fetch (DBM *, datum); -datum __db_ndbm_firstkey (DBM *); -datum __db_ndbm_nextkey (DBM *); -DBM *__db_ndbm_open (const char *, int, int); -int __db_ndbm_pagfno (DBM *); -int __db_ndbm_rdonly (DBM *); -int __db_ndbm_store (DBM *, datum, datum, int); -#if defined(__cplusplus) -} -#endif - -/******************************************************* - * Hsearch historic interface. - *******************************************************/ -typedef enum { - FIND, ENTER -} ACTION; - -typedef struct entry { - char *key; - char *data; -} ENTRY; - -/* - * Translate HSEARCH calls into DB calls so that DB doesn't step on the - * application's name space. - */ -#define hcreate(a) __db_hcreate(a) -#define hdestroy __db_hdestroy -#define hsearch(a, b) __db_hsearch(a, b) - -/* Prototype the DB calls. */ -#if defined(__cplusplus) -extern "C" { -#endif -int __db_hcreate (size_t); -void __db_hdestroy (void); -ENTRY *__db_hsearch (ENTRY, ACTION); -#if defined(__cplusplus) -} -#endif -#endif /* DB_DBM_HSEARCH */ - -/* - * XXX - * MacOS: Reset Metrowerks C enum sizes. - */ -#ifdef __MWERKS__ -#pragma enumsalwaysint reset -#endif -#endif /* !_DB_H_ */ diff --git a/db2/db/db.c b/db2/db/db.c deleted file mode 100644 index 9f79fd6..0000000 --- a/db2/db/db.c +++ /dev/null @@ -1,791 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994, 1995, 1996 - * Keith Bostic. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994, 1995 - * The Regents of the University of California. 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[] = "@(#)db.c 10.75 (Sleepycat) 12/3/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <stddef.h> -#include <stdlib.h> -#include <string.h> -#endif - -#include "db_int.h" -#include "shqueue.h" -#include "db_page.h" -#include "db_shash.h" -#include "db_swap.h" -#include "btree.h" -#include "hash.h" -#include "mp.h" -#include "db_am.h" -#include "common_ext.h" - -/* - * If the metadata page has the flag set, set the local flag. If the page - * does NOT have the flag set, return EINVAL if the user's dbinfo argument - * caused us to already set the local flag. - */ -#define DBINFO_FCHK(dbp, fn, meta_flags, m_name, dbp_name) { \ - if ((meta_flags) & (m_name)) \ - F_SET(dbp, dbp_name); \ - else \ - if (F_ISSET(dbp, dbp_name)) { \ - __db_err(dbenv, \ - "%s: %s specified in dbinfo argument but not set in file", \ - fname, fn); \ - goto einval; \ - } \ -} - -#ifdef _LIBC -#define db_open(fname, type, flags, mode, dbenv, dbinfo, dbpp) \ - __nss_db_open(fname, type, flags, mode, dbenv, dbinfo, dbpp) -#endif - -/* - * db_open -- - * Main library interface to the DB access methods. - */ -int -db_open(fname, type, flags, mode, dbenv, dbinfo, dbpp) - const char *fname; - DBTYPE type; - u_int32_t flags; - int mode; - DB_ENV *dbenv; - DB_INFO *dbinfo; - DB **dbpp; -{ - BTMETA *btm; - DB *dbp; - DBT pgcookie; - DB_ENV *envp, t_dbenv; - DB_MPOOL_FINFO finfo; - DB_PGINFO pginfo; - HASHHDR *hashm; - size_t cachesize; - ssize_t nr; - u_int32_t iopsize; - int fd, ftype, need_fileid, restore, ret, retry_cnt, swapped; - char *real_name, mbuf[512]; - - /* Validate arguments. */ -#ifdef HAVE_SPINLOCKS -#define OKFLAGS (DB_CREATE | DB_NOMMAP | DB_RDONLY | DB_THREAD | DB_TRUNCATE) -#else -#define OKFLAGS (DB_CREATE | DB_NOMMAP | DB_RDONLY | DB_TRUNCATE) -#endif - if ((ret = __db_fchk(dbenv, "db_open", flags, OKFLAGS)) != 0) - return (ret); - - if (dbenv != NULL) { - /* - * You can't specify threads during the db_open() if the - * environment wasn't configured with them. - */ - if (LF_ISSET(DB_THREAD) && !F_ISSET(dbenv, DB_ENV_THREAD)) { - __db_err(dbenv, - "environment not created using DB_THREAD"); - return (EINVAL); - } - - /* - * Specifying a cachesize to db_open(3), after creating an - * environment with DB_INIT_MPOOL, is a common mistake. - */ - if (dbenv->mp_info != NULL && - dbinfo != NULL && dbinfo->db_cachesize != 0) { - __db_err(dbenv, - "cachesize will be ignored if environment exists"); - return (EINVAL); - } - } - - /* Initialize for error return. */ - fd = -1; - need_fileid = 1; - real_name = NULL; - - /* Allocate the DB structure, reference the DB_ENV structure. */ - if ((ret = __os_calloc(1, sizeof(DB), &dbp)) != 0) - return (ret); - dbp->dbenv = dbenv; - - /* Random initialization. */ - TAILQ_INIT(&dbp->free_queue); - TAILQ_INIT(&dbp->active_queue); - if ((ret = __db_init_wrapper(dbp)) != 0) - goto err; - - /* Convert the db_open(3) flags. */ - if (LF_ISSET(DB_RDONLY)) - F_SET(dbp, DB_AM_RDONLY); - if (LF_ISSET(DB_THREAD)) - F_SET(dbp, DB_AM_THREAD); - - /* Convert the dbinfo structure flags. */ - if (dbinfo != NULL) { - /* - * !!! - * We can't check for illegal flags until we know what type - * of open we're doing. - */ - if (F_ISSET(dbinfo, DB_DELIMITER)) - F_SET(dbp, DB_RE_DELIMITER); - if (F_ISSET(dbinfo, DB_DUP)) - F_SET(dbp, DB_AM_DUP); - if (F_ISSET(dbinfo, DB_FIXEDLEN)) - F_SET(dbp, DB_RE_FIXEDLEN); - if (F_ISSET(dbinfo, DB_PAD)) - F_SET(dbp, DB_RE_PAD); - if (F_ISSET(dbinfo, DB_RECNUM)) - F_SET(dbp, DB_BT_RECNUM); - if (F_ISSET(dbinfo, DB_RENUMBER)) - F_SET(dbp, DB_RE_RENUMBER); - if (F_ISSET(dbinfo, DB_SNAPSHOT)) - F_SET(dbp, DB_RE_SNAPSHOT); - } - - /* - * Set based on the dbenv fields, although no logging or transactions - * are possible for temporary files. - */ - if (dbenv != NULL) { - if (dbenv->lk_info != NULL) { - if (F_ISSET(dbenv, DB_ENV_CDB)) - F_SET(dbp, DB_AM_CDB); - else - F_SET(dbp, DB_AM_LOCKING); - } - if (fname != NULL && dbenv->lg_info != NULL) - F_SET(dbp, DB_AM_LOGGING); - } - - /* Set the common fields. */ - if (dbinfo == NULL) { - dbp->pgsize = 0; - dbp->db_malloc = NULL; - dbp->dup_compare = NULL; - } else { - /* - * We don't want anything that's not a power-of-2, as we rely - * on that for alignment of various types on the pages. - */ - if ((dbp->pgsize = dbinfo->db_pagesize) != 0 && - (u_int32_t)1 << __db_log2(dbp->pgsize) != dbp->pgsize) { - __db_err(dbenv, "page sizes must be a power-of-2"); - goto einval; - } - dbp->pgsize = dbinfo->db_pagesize; - dbp->db_malloc = dbinfo->db_malloc; - if (F_ISSET(dbinfo, DB_DUPSORT)) { - if (F_ISSET(dbinfo, DB_DUP)) - dbp->dup_compare = dbinfo->dup_compare == NULL ? - __bam_defcmp : dbinfo->dup_compare; - else { - __db_err(dbenv, "DB_DUPSORT requires DB_DUP"); - goto einval; - } - F_CLR(dbinfo, DB_DUPSORT); - } - } - - /* Fill in the default file mode. */ - if (mode == 0) - mode = __db_omode("rwrw--"); - - /* Check if the user wants us to swap byte order. */ - if (dbinfo != NULL) - switch (ret = __db_byteorder(dbenv, dbinfo->db_lorder)) { - case 0: - break; - case DB_SWAPBYTES: - F_SET(dbp, DB_AM_SWAP); - break; - default: - goto err; - } - dbp->byteswapped = F_ISSET(dbp, DB_AM_SWAP) ? 1 : 0; - - /* - * If we have a file name, try and read the first page, figure out - * what type of file it is, and initialize everything we can based - * on that file's meta-data page. - * - * XXX - * We don't actually expect zero-length strings as arguments. We - * do the check, permitting them, because scripting languages, e.g., - * the Tcl test suite, doesn't know anything about passing NULL's. - */ - if (fname != NULL && fname[0] != '\0') { - /* Get the real file name. */ - if ((ret = __db_appname(dbenv, - DB_APP_DATA, NULL, fname, 0, NULL, &real_name)) != 0) - goto err; - - /* - * Open the backing file. We need to make sure that multiple - * processes attempting to create the file at the same time - * are properly ordered so that only one of them creates the - * "unique" file id, so we open it O_EXCL and O_CREAT so two - * simultaneous attempts to create the region will return - * failure in one of the attempts. If we're one of the ones - * that fail, we simply retry without the O_CREAT flag, which - * will require that the meta-data page exist. - */ - retry_cnt = 0; -open_retry: if (LF_ISSET(DB_CREATE)) { - if ((ret = __db_open(real_name, flags | DB_EXCL, - OKFLAGS | DB_EXCL, mode, &fd)) != 0) { - if (ret == EEXIST) { - LF_CLR(DB_CREATE); - goto open_retry; - } else { - __db_err(dbenv, - "%s: %s", fname, strerror(ret)); - goto err; - } - } - } else - if ((ret = __db_open(real_name, - flags, OKFLAGS, mode, &fd)) != 0) { - __db_err(dbenv, "%s: %s", fname, strerror(ret)); - goto err; - } - - /* - * Use the optimum I/O size as the pagesize if a pagesize not - * specified. Some filesystems have 64K as their optimum I/O - * size, but as that results in impossibly large default cache - * sizes, we limit the default pagesize to 16K. - */ - if (dbp->pgsize == 0) { - if ((ret = __os_ioinfo(real_name, - fd, NULL, NULL, &iopsize)) != 0) { - __db_err(dbenv, - "%s: %s", real_name, strerror(ret)); - goto err; - } - if (iopsize < 512) - iopsize = 512; - if (iopsize > 16 * 1024) - iopsize = 16 * 1024; - - /* - * Sheer paranoia, but we don't want anything that's - * not a power-of-2, as we rely on that for alignment - * of various types on the pages. - */ - DB_ROUNDOFF(iopsize, 512); - - dbp->pgsize = iopsize; - F_SET(dbp, DB_AM_PGDEF); - } - - /* - * Try and read the first disk sector -- this code assumes - * that the meta-data for all access methods fits in 512 - * bytes, and that no database will be smaller than that. - */ - if ((ret = __os_read(fd, mbuf, sizeof(mbuf), &nr)) != 0) - goto err; - - /* The fd is no longer needed. */ - (void)__os_close(fd); - fd = -1; - - if (nr != sizeof(mbuf)) { - if (nr != 0) { - __db_err(dbenv, - "%s: unexpected file format", fname); - goto einval; - } - /* - * The only way we can reach here with the DB_CREATE - * flag set is if we created the file. If that's not - * the case, then a) someone else created the file - * but has not yet written out the meta-data page, or - * b) we truncated the file (DB_TRUNCATE) leaving it - * zero-length. In the case of a), we want to sleep - * and give the file creator some time to write the - * metadata page. In the case of b), charge forward. - * Note, there is a race in the case of two processes - * opening the file with the DB_TRUNCATE flag set at - * roughly the same time, and they could theoretically - * hurt each other, although it's pretty unlikely. - */ - if (retry_cnt++ < 3 && - !LF_ISSET(DB_CREATE | DB_TRUNCATE)) { - __os_sleep(1, 0); - goto open_retry; - } - if (type == DB_UNKNOWN) { - __db_err(dbenv, - "%s: DBTYPE of unknown with empty file", - fname); - goto einval; - } - goto empty; - } - - /* - * A found file overrides some user information. We'll check - * for possible error conditions based on conflicts between - * the file and the user's arguments below. - */ - swapped = 0; - F_CLR(dbp, DB_AM_SWAP); - -retry: switch (((BTMETA *)mbuf)->magic) { - case DB_BTREEMAGIC: - if (type != DB_BTREE && - type != DB_RECNO && type != DB_UNKNOWN) - goto einval; - - btm = (BTMETA *)mbuf; - if (swapped && (ret = __bam_mswap((PAGE *)btm)) != 0) - goto err; - - if (btm->version < DB_BTREEOLDVER || - btm->version > DB_BTREEVERSION) { - __db_err(dbenv, - "%s: unsupported btree version number %lu", - fname, (u_long)btm->version); - goto einval; - } - dbp->pgsize = btm->pagesize; - F_CLR(dbp, DB_AM_PGDEF); - - if ((ret = __db_fchk(dbenv, - "db_open", btm->flags, BTM_MASK)) != 0) - goto err; - DBINFO_FCHK(dbp, "DB_DUP", - btm->flags, BTM_DUP, DB_AM_DUP); - if (F_ISSET(btm, BTM_RECNO)) { - DBINFO_FCHK(dbp, "DB_FIXEDLEN", - btm->flags, BTM_FIXEDLEN, DB_RE_FIXEDLEN); - DBINFO_FCHK(dbp, "DB_RENUMBER", - btm->flags, BTM_RENUMBER, DB_RE_RENUMBER); - type = DB_RECNO; - } else { - DBINFO_FCHK(dbp, "DB_RECNUM", - btm->flags, BTM_RECNUM, DB_BT_RECNUM); - type = DB_BTREE; - } - - /* Copy the file's unique id. */ - need_fileid = 0; - memcpy(dbp->fileid, btm->uid, DB_FILE_ID_LEN); - break; - case DB_HASHMAGIC: - if (type != DB_HASH && type != DB_UNKNOWN) - goto einval; - - hashm = (HASHHDR *)mbuf; - if (swapped && (ret = __ham_mswap((PAGE *)hashm)) != 0) - goto err; - - if (hashm->version < DB_HASHOLDVER || - hashm->version > DB_HASHVERSION) { - __db_err(dbenv, - "%s: unsupported hash version number %lu", - fname, hashm->version); - goto einval; - } - dbp->pgsize = hashm->pagesize; - F_CLR(dbp, DB_AM_PGDEF); - - if ((ret = __db_fchk(dbenv, - "db_open", hashm->flags, DB_HASH_DUP)) != 0) - goto err; - DBINFO_FCHK(dbp, "DB_DUP", - hashm->flags, DB_HASH_DUP, DB_AM_DUP); - type = DB_HASH; - - /* Copy the file's unique id. */ - need_fileid = 0; - memcpy(dbp->fileid, hashm->uid, DB_FILE_ID_LEN); - break; - default: - if (swapped) { - __db_err(dbenv, "unrecognized file type"); - goto einval; - } - M_32_SWAP(((BTMETA *)mbuf)->magic); - F_SET(dbp, DB_AM_SWAP); - - swapped = 1; - goto retry; - } - } else { - fname = real_name = NULL; - - if (type == DB_UNKNOWN) { - __db_err(dbenv, - "DBTYPE of unknown without existing file"); - goto einval; - } - F_SET(dbp, DB_AM_INMEM); - } - -empty: /* - * By the time we get here we've either set the type or we're taking - * it from the user. - */ - dbp->type = type; - - /* - * Set the page size to the best value for I/O to this file. Don't - * overflow the page offset type. The page size must be db_indx_t - * aligned and >= MIN_PAGE_SIZE. - * - * XXX - * Should we be checking for a page size that's not a multiple of 512? - */ - if (dbp->pgsize == 0) { - F_SET(dbp, DB_AM_PGDEF); - dbp->pgsize = 8 * 1024; - } - if (dbp->pgsize < DB_MIN_PGSIZE || - dbp->pgsize > DB_MAX_PGSIZE || - dbp->pgsize & (sizeof(db_indx_t) - 1)) { - __db_err(dbenv, "illegal page size"); - goto einval; - } - - /* - * If no mpool supplied by the application, attach to a local, - * created buffer pool. - * - * XXX - * If the user has a DB_ENV structure, we have to use a temporary - * one so that we don't step on their values. If the user doesn't, - * we have to create one, and keep it around until the call to the - * memp_close() function. This is all so the mpool functions get - * the error stuff right. - */ - if (dbenv == NULL || dbenv->mp_info == NULL) { - F_SET(dbp, DB_AM_MLOCAL); - - if (dbenv == NULL) { - if ((ret = __os_calloc(1, - sizeof(DB_ENV), &dbp->mp_dbenv)) != 0) - goto err; - - envp = dbp->mp_dbenv; - restore = 0; - } else { - t_dbenv = *dbenv; - - envp = dbenv; - restore = 1; - } - - /* - * Set and/or correct the cache size; must be a multiple of - * the page size. - */ - if (dbinfo == NULL || dbinfo->db_cachesize == 0) - cachesize = dbp->pgsize * DB_MINCACHE; - else { - cachesize = dbinfo->db_cachesize; - if (cachesize & (dbp->pgsize - 1)) - cachesize += - (~cachesize & (dbp->pgsize - 1)) + 1; - if (cachesize < dbp->pgsize * DB_MINCACHE) - cachesize = dbp->pgsize * DB_MINCACHE; - if (cachesize < 20 * 1024) - cachesize = 20 * 1024; - } - envp->mp_size = cachesize; - - if ((ret = memp_open(NULL, DB_CREATE | DB_MPOOL_PRIVATE | - (F_ISSET(dbp, DB_AM_THREAD) ? DB_THREAD : 0), - __db_omode("rw----"), envp, &dbp->mp)) != 0) - goto err; - if (restore) - *dbenv = t_dbenv; - } else - dbp->mp = dbenv->mp_info; - - /* Register DB's pgin/pgout functions. */ - if ((ret = memp_register(dbp->mp, - DB_FTYPE_BTREE, __bam_pgin, __bam_pgout)) != 0) - goto err; - if ((ret = memp_register(dbp->mp, - DB_FTYPE_HASH, __ham_pgin, __ham_pgout)) != 0) - goto err; - - /* - * If we don't already have one, get a unique file ID. If the file - * is a temporary file, then we have to create a unique file ID -- - * no backing file will be created until the mpool cache is filled - * forcing it to go to disk. The created ID must never match any - * potential real file ID -- we know it won't because real file IDs - * contain a time stamp after the dev/ino pair, and we're simply - * storing a 4-byte locker ID. - * - * XXX - * Store the file id in the locker structure -- we can get it from - * there as necessary, and it saves having two copies. - */ - if (need_fileid) { - if (fname == NULL) { - memset(dbp->fileid, 0, DB_FILE_ID_LEN); - if (F_ISSET(dbp, DB_AM_LOCKING) && - (ret = lock_id(dbenv->lk_info, - (u_int32_t *)dbp->fileid)) != 0) - goto err; - } else - if ((ret = __os_fileid(dbenv, - real_name, 1, dbp->fileid)) != 0) - goto err; - } - - /* No further use for the real name. */ - if (real_name != NULL) - __os_freestr(real_name); - real_name = NULL; - - /* - * Open a backing file in the memory pool. - * - * If we need to process the file's pages on I/O, set the file type. - * If it's a hash file, always call pgin and pgout routines. This - * means that hash files can never be mapped into process memory. If - * it's a btree file and requires swapping, we need to page the file - * in and out. This has to be right -- we can't mmap files that are - * being paged in and out. - */ - if (type == DB_HASH) - ftype = DB_FTYPE_HASH; - else - ftype = F_ISSET(dbp, DB_AM_SWAP) ? DB_FTYPE_BTREE : 0; - pginfo.db_pagesize = dbp->pgsize; - pginfo.needswap = F_ISSET(dbp, DB_AM_SWAP); - pgcookie.data = &pginfo; - pgcookie.size = sizeof(DB_PGINFO); - - /* - * Set up additional memp_fopen information. - */ - memset(&finfo, 0, sizeof(finfo)); - finfo.ftype = ftype; - finfo.pgcookie = &pgcookie; - finfo.fileid = dbp->fileid; - finfo.lsn_offset = 0; - finfo.clear_len = DB_PAGE_CLEAR_LEN; - if ((ret = memp_fopen(dbp->mp, fname, - F_ISSET(dbp, DB_AM_RDONLY) ? DB_RDONLY : 0, - 0, dbp->pgsize, &finfo, &dbp->mpf)) != 0) - goto err; - - /* - * XXX - * We need a per-thread mutex that lives in shared memory -- HP-UX - * can't allocate mutexes in malloc'd memory. Allocate it from the - * shared memory region, since it's the only one that is guaranteed - * to exist. - */ - if (F_ISSET(dbp, DB_AM_THREAD)) { - if ((ret = __memp_reg_alloc(dbp->mp, - sizeof(db_mutex_t), NULL, &dbp->mutexp)) != 0) - goto err; - /* - * Since we only get here if DB_THREAD was specified, we know - * we have spinlocks and no file offset argument is needed. - */ - (void)__db_mutex_init(dbp->mutexp, 0); - } - - /* Get a log file id. */ - if (F_ISSET(dbp, DB_AM_LOGGING) && - (ret = log_register(dbenv->lg_info, - dbp, fname, type, &dbp->log_fileid)) != 0) - goto err; - - /* Call the real open function. */ - switch (type) { - case DB_BTREE: - if (dbinfo != NULL && (ret = __db_fchk(dbenv, - "db_open", dbinfo->flags, DB_RECNUM | DB_DUP)) != 0) - goto err; - if (dbinfo != NULL && (ret = __db_fcchk(dbenv, - "db_open", dbinfo->flags, DB_DUP, DB_RECNUM)) != 0) - goto err; - if ((ret = __bam_open(dbp, dbinfo)) != 0) - goto err; - break; - case DB_HASH: - if (dbinfo != NULL && (ret = __db_fchk(dbenv, - "db_open", dbinfo->flags, DB_DUP)) != 0) - goto err; - if ((ret = __ham_open(dbp, dbinfo)) != 0) - goto err; - break; - case DB_RECNO: -#define DB_INFO_FLAGS \ - (DB_DELIMITER | DB_FIXEDLEN | DB_PAD | DB_RENUMBER | DB_SNAPSHOT) - if (dbinfo != NULL && (ret = __db_fchk(dbenv, - "db_open", dbinfo->flags, DB_INFO_FLAGS)) != 0) - goto err; - if ((ret = __ram_open(dbp, dbinfo)) != 0) - goto err; - break; - default: - abort(); - } - - *dbpp = dbp; - return (0); - -einval: ret = EINVAL; -err: /* Close the file descriptor. */ - if (fd != -1) - (void)__os_close(fd); - - /* Discard the log file id. */ - if (dbp->log_fileid != 0) - (void)log_unregister(dbenv->lg_info, dbp->log_fileid); - - /* Close the memory pool file. */ - if (dbp->mpf != NULL) - (void)memp_fclose(dbp->mpf); - - /* If the memory pool was local, close it. */ - if (F_ISSET(dbp, DB_AM_MLOCAL) && dbp->mp != NULL) - (void)memp_close(dbp->mp); - - /* If we allocated a DB_ENV, discard it. */ - if (dbp->mp_dbenv != NULL) - __os_free(dbp->mp_dbenv, sizeof(DB_ENV)); - - if (real_name != NULL) - __os_freestr(real_name); - if (dbp != NULL) - __os_free(dbp, sizeof(DB)); - - return (ret); -} - -#ifdef _LIBC -# undef db_open -weak_alias (__nss_db_open, db_open) -#endif - -/* - * __db_close -- - * Close a DB tree. - * - * PUBLIC: int __db_close __P((DB *, u_int32_t)); - */ -int -__db_close(dbp, flags) - DB *dbp; - u_int32_t flags; -{ - DBC *dbc; - int ret, t_ret; - - DB_PANIC_CHECK(dbp); - - /* Validate arguments. */ - if ((ret = __db_closechk(dbp, flags)) != 0) - return (ret); - - /* Sync the underlying file. */ - if (flags != DB_NOSYNC && - (t_ret = dbp->sync(dbp, 0)) != 0 && ret == 0) - ret = t_ret; - - /* - * Go through the active cursors and call the cursor recycle routine, - * which resolves pending operations and moves the cursors onto the - * free list. Then, walk the free list and call the cursor destroy - * routine. - */ - while ((dbc = TAILQ_FIRST(&dbp->active_queue)) != NULL) - if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0) - ret = t_ret; - while ((dbc = TAILQ_FIRST(&dbp->free_queue)) != NULL) - if ((t_ret = __db_c_destroy(dbc)) != 0 && ret == 0) - ret = t_ret; - - /* Call the access specific close function. */ - if ((t_ret = dbp->am_close(dbp)) != 0 && ret == 0) - ret = t_ret; - - /* Sync the memory pool. */ - if (flags != DB_NOSYNC && (t_ret = memp_fsync(dbp->mpf)) != 0 && - t_ret != DB_INCOMPLETE && ret == 0) - ret = t_ret; - - /* Close the memory pool file. */ - if ((t_ret = memp_fclose(dbp->mpf)) != 0 && ret == 0) - ret = t_ret; - - /* If the memory pool was local, close it. */ - if (F_ISSET(dbp, DB_AM_MLOCAL) && - (t_ret = memp_close(dbp->mp)) != 0 && ret == 0) - ret = t_ret; - - /* Discard the log file id. */ - if (F_ISSET(dbp, DB_AM_LOGGING)) - (void)log_unregister(dbp->dbenv->lg_info, dbp->log_fileid); - - /* If we allocated a DB_ENV, discard it. */ - if (dbp->mp_dbenv != NULL) - __os_free(dbp->mp_dbenv, sizeof(DB_ENV)); - - /* Free the DB. */ - __os_free(dbp, sizeof(*dbp)); - - return (ret); -} diff --git a/db2/db/db_am.c b/db2/db/db_am.c deleted file mode 100644 index e02ad57..0000000 --- a/db2/db/db_am.c +++ /dev/null @@ -1,430 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1998 - * Sleepycat Software. All rights reserved. - */ - -#include "config.h" - -#ifndef lint -static const char sccsid[] = "@(#)db_am.c 10.15 (Sleepycat) 12/30/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#endif - -#include "db_int.h" -#include "shqueue.h" -#include "db_page.h" -#include "db_shash.h" -#include "mp.h" -#include "btree.h" -#include "hash.h" -#include "db_am.h" -#include "db_ext.h" - -static int __db_c_close __P((DBC *)); -static int __db_cursor __P((DB *, DB_TXN *, DBC **, u_int32_t)); -static int __db_fd __P((DB *, int *)); -static int __db_get __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t)); -static int __db_put __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t)); - -/* - * __db_init_wrapper -- - * Wrapper layer to implement generic DB functions. - * - * PUBLIC: int __db_init_wrapper __P((DB *)); - */ -int -__db_init_wrapper(dbp) - DB *dbp; -{ - dbp->close = __db_close; - dbp->cursor = __db_cursor; - dbp->del = NULL; /* !!! Must be set by access method. */ - dbp->fd = __db_fd; - dbp->get = __db_get; - dbp->join = __db_join; - dbp->put = __db_put; - dbp->stat = NULL; /* !!! Must be set by access method. */ - dbp->sync = __db_sync; - - return (0); -} - -/* - * __db_cursor -- - * Allocate and return a cursor. - */ -static int -__db_cursor(dbp, txn, dbcp, flags) - DB *dbp; - DB_TXN *txn; - DBC **dbcp; - u_int32_t flags; -{ - DBC *dbc, *adbc; - int ret; - db_lockmode_t mode; - u_int32_t op; - - DB_PANIC_CHECK(dbp); - - /* Take one from the free list if it's available. */ - DB_THREAD_LOCK(dbp); - if ((dbc = TAILQ_FIRST(&dbp->free_queue)) != NULL) - TAILQ_REMOVE(&dbp->free_queue, dbc, links); - else { - DB_THREAD_UNLOCK(dbp); - - if ((ret = __os_calloc(1, sizeof(DBC), &dbc)) != 0) - return (ret); - - dbc->dbp = dbp; - dbc->c_close = __db_c_close; - - /* Set up locking information. */ - if (F_ISSET(dbp, DB_AM_LOCKING | DB_AM_CDB)) { - /* - * If we are not threaded, then there is no need to - * create new locker ids. We know that no one else - * is running concurrently using this DB, so we can - * take a peek at any cursors on the active queue. - */ - if (!F_ISSET(dbp, DB_AM_THREAD) && - (adbc = TAILQ_FIRST(&dbp->active_queue)) != NULL) - dbc->lid = adbc->lid; - else - if ((ret = lock_id(dbp->dbenv->lk_info, - &dbc->lid)) != 0) - goto err; - - memcpy(dbc->lock.fileid, dbp->fileid, DB_FILE_ID_LEN); - if (F_ISSET(dbp, DB_AM_CDB)) { - dbc->lock_dbt.size = DB_FILE_ID_LEN; - dbc->lock_dbt.data = dbc->lock.fileid; - } else { - dbc->lock_dbt.size = sizeof(dbc->lock); - dbc->lock_dbt.data = &dbc->lock; - } - } - - switch (dbp->type) { - case DB_BTREE: - case DB_RECNO: - if ((ret = __bam_c_init(dbc)) != 0) - goto err; - break; - case DB_HASH: - if ((ret = __ham_c_init(dbc)) != 0) - goto err; - break; - default: - ret = EINVAL; - goto err; - } - - DB_THREAD_LOCK(dbp); - } - - if ((dbc->txn = txn) == NULL) - dbc->locker = dbc->lid; - else - dbc->locker = txn->txnid; - - TAILQ_INSERT_TAIL(&dbp->active_queue, dbc, links); - DB_THREAD_UNLOCK(dbp); - - /* - * If this is the concurrent DB product, then we do all locking - * in the interface, which is right here. - */ - if (F_ISSET(dbp, DB_AM_CDB)) { - op = LF_ISSET(DB_OPFLAGS_MASK); - mode = (op == DB_WRITELOCK) ? DB_LOCK_WRITE : - (LF_ISSET(DB_RMW) ? DB_LOCK_IWRITE : DB_LOCK_READ); - if ((ret = lock_get(dbp->dbenv->lk_info, dbc->locker, 0, - &dbc->lock_dbt, mode, &dbc->mylock)) != 0) { - (void)__db_c_close(dbc); - return (EAGAIN); - } - if (LF_ISSET(DB_RMW)) - F_SET(dbc, DBC_RMW); - if (op == DB_WRITELOCK) - F_SET(dbc, DBC_WRITER); - } - - *dbcp = dbc; - return (0); - -err: __os_free(dbc, sizeof(*dbc)); - return (ret); -} - -/* - * __db_c_close -- - * Close the cursor (recycle for later use). - */ -static int -__db_c_close(dbc) - DBC *dbc; -{ - DB *dbp; - int ret, t_ret; - - dbp = dbc->dbp; - - DB_PANIC_CHECK(dbp); - - ret = 0; - - /* - * We cannot release the lock until after we've called the - * access method specific routine, since btrees may have pending - * deletes. - */ - - /* Remove the cursor from the active queue. */ - DB_THREAD_LOCK(dbp); - TAILQ_REMOVE(&dbp->active_queue, dbc, links); - DB_THREAD_UNLOCK(dbp); - - /* Call the access specific cursor close routine. */ - if ((t_ret = dbc->c_am_close(dbc)) != 0 && ret == 0) - t_ret = ret; - - /* Release the lock. */ - if (F_ISSET(dbc->dbp, DB_AM_CDB) && dbc->mylock != LOCK_INVALID) { - ret = lock_put(dbc->dbp->dbenv->lk_info, dbc->mylock); - dbc->mylock = LOCK_INVALID; - } - - /* Clean up the cursor. */ - dbc->flags = 0; - -#ifdef DEBUG - /* - * Check for leftover locks, unless we're running with transactions. - * - * If we're running tests, display any locks currently held. It's - * possible that some applications may hold locks for long periods, - * e.g., conference room locks, but the DB tests should never close - * holding locks. - */ - if (F_ISSET(dbp, DB_AM_LOCKING) && dbc->lid == dbc->locker) { - DB_LOCKREQ request; - - request.op = DB_LOCK_DUMP; - if ((t_ret = lock_vec(dbp->dbenv->lk_info, - dbc->locker, 0, &request, 1, NULL)) != 0 && ret == 0) - ret = EAGAIN; - } -#endif - /* Move the cursor to the free queue. */ - DB_THREAD_LOCK(dbp); - TAILQ_INSERT_TAIL(&dbp->free_queue, dbc, links); - DB_THREAD_UNLOCK(dbp); - - return (ret); -} - -#ifdef DEBUG -/* - * __db_cprint -- - * Display the current cursor list. - * - * PUBLIC: int __db_cprint __P((DB *)); - */ -int -__db_cprint(dbp) - DB *dbp; -{ - static const FN fn[] = { - { DBC_RECOVER, "recover" }, - { DBC_RMW, "read-modify-write" }, - { 0 }, - }; - DBC *dbc; - - DB_THREAD_LOCK(dbp); - for (dbc = TAILQ_FIRST(&dbp->active_queue); - dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { - fprintf(stderr, - "%#0x: dbp: %#0x txn: %#0x lid: %lu locker: %lu", - (u_int)dbc, (u_int)dbc->dbp, (u_int)dbc->txn, - (u_long)dbc->lid, (u_long)dbc->locker); - __db_prflags(dbc->flags, fn, stderr); - fprintf(stderr, "\n"); - } - DB_THREAD_UNLOCK(dbp); - - return (0); -} -#endif /* DEBUG */ - -/* - * __db_c_destroy -- - * Destroy the cursor. - * - * PUBLIC: int __db_c_destroy __P((DBC *)); - */ -int -__db_c_destroy(dbc) - DBC *dbc; -{ - DB *dbp; - int ret; - - dbp = dbc->dbp; - - /* Remove the cursor from the free queue. */ - DB_THREAD_LOCK(dbp); - TAILQ_REMOVE(&dbp->free_queue, dbc, links); - DB_THREAD_UNLOCK(dbp); - - /* Call the access specific cursor destroy routine. */ - ret = dbc->c_am_destroy == NULL ? 0 : dbc->c_am_destroy(dbc); - - /* Free up allocated memory. */ - if (dbc->rkey.data != NULL) - __os_free(dbc->rkey.data, dbc->rkey.ulen); - if (dbc->rdata.data != NULL) - __os_free(dbc->rdata.data, dbc->rdata.ulen); - __os_free(dbc, sizeof(*dbc)); - - return (0); -} - -/* - * db_fd -- - * Return a file descriptor for flock'ing. - */ -static int -__db_fd(dbp, fdp) - DB *dbp; - int *fdp; -{ - DB_PANIC_CHECK(dbp); - - /* - * XXX - * Truly spectacular layering violation. - */ - return (__mp_xxx_fd(dbp->mpf, fdp)); -} - -/* - * __db_get -- - * Return a key/data pair. - */ -static int -__db_get(dbp, txn, key, data, flags) - DB *dbp; - DB_TXN *txn; - DBT *key, *data; - u_int32_t flags; -{ - DBC *dbc; - int ret, t_ret; - - DB_PANIC_CHECK(dbp); - - if ((ret = __db_getchk(dbp, key, data, flags)) != 0) - return (ret); - - if ((ret = dbp->cursor(dbp, txn, &dbc, 0)) != 0) - return (ret); - - DEBUG_LREAD(dbc, txn, "__db_get", key, NULL, flags); - - ret = dbc->c_get(dbc, key, data, - flags == 0 || flags == DB_RMW ? flags | DB_SET : flags); - - if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0) - ret = t_ret; - - return (ret); -} - -/* - * __db_put -- - * Store a key/data pair. - */ -static int -__db_put(dbp, txn, key, data, flags) - DB *dbp; - DB_TXN *txn; - DBT *key, *data; - u_int32_t flags; -{ - DBC *dbc; - DBT tdata; - int ret, t_ret; - - DB_PANIC_CHECK(dbp); - - if ((ret = __db_putchk(dbp, key, data, - flags, F_ISSET(dbp, DB_AM_RDONLY), F_ISSET(dbp, DB_AM_DUP))) != 0) - return (ret); - - if ((ret = dbp->cursor(dbp, txn, &dbc, DB_WRITELOCK)) != 0) - return (ret); - - DEBUG_LWRITE(dbc, txn, "__db_put", key, data, flags); - - if (flags == DB_NOOVERWRITE) { - /* - * Set DB_DBT_USERMEM, this might be a threaded application and - * the flags checking will catch us. We don't want the actual - * data, so request a partial of length 0. - */ - memset(&tdata, 0, sizeof(tdata)); - F_SET(&tdata, DB_DBT_USERMEM | DB_DBT_PARTIAL); - if ((ret = dbc->c_get(dbc, key, &tdata, DB_SET | DB_RMW)) == 0) - ret = DB_KEYEXIST; - else - ret = 0; - } - if (ret == 0) - ret = dbc->c_put(dbc, key, data, DB_KEYLAST); - - if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0) - ret = t_ret; - - return (ret); -} - -/* - * __db_sync -- - * Flush the database cache. - * - * PUBLIC: int __db_sync __P((DB *, u_int32_t)); - */ -int -__db_sync(dbp, flags) - DB *dbp; - u_int32_t flags; -{ - int ret; - - DB_PANIC_CHECK(dbp); - - if ((ret = __db_syncchk(dbp, flags)) != 0) - return (ret); - - /* If it wasn't possible to modify the file, we're done. */ - if (F_ISSET(dbp, DB_AM_INMEM | DB_AM_RDONLY)) - return (0); - - /* Flush any dirty pages from the cache to the backing file. */ - if ((ret = memp_fsync(dbp->mpf)) == DB_INCOMPLETE) - ret = 0; - - return (ret); -} diff --git a/db2/db/db_auto.c b/db2/db/db_auto.c deleted file mode 100644 index e3dba23..0000000 --- a/db2/db/db_auto.c +++ /dev/null @@ -1,1357 +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 "db_am.h" -/* - * PUBLIC: int __db_addrem_log - * PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - * PUBLIC: u_int32_t, u_int32_t, db_pgno_t, u_int32_t, - * PUBLIC: size_t, const DBT *, const DBT *, DB_LSN *)); - */ -int __db_addrem_log(logp, txnid, ret_lsnp, flags, - opcode, fileid, pgno, indx, nbytes, hdr, - dbt, pagelsn) - DB_LOG *logp; - DB_TXN *txnid; - DB_LSN *ret_lsnp; - u_int32_t flags; - u_int32_t opcode; - u_int32_t fileid; - db_pgno_t pgno; - u_int32_t indx; - size_t nbytes; - const DBT *hdr; - const DBT *dbt; - DB_LSN * pagelsn; -{ - 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_db_addrem; - 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(fileid) - + sizeof(pgno) - + sizeof(indx) - + sizeof(nbytes) - + sizeof(u_int32_t) + (hdr == NULL ? 0 : hdr->size) - + sizeof(u_int32_t) + (dbt == NULL ? 0 : dbt->size) - + sizeof(*pagelsn); - 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); - memcpy(bp, &fileid, sizeof(fileid)); - bp += sizeof(fileid); - memcpy(bp, &pgno, sizeof(pgno)); - bp += sizeof(pgno); - memcpy(bp, &indx, sizeof(indx)); - bp += sizeof(indx); - memcpy(bp, &nbytes, sizeof(nbytes)); - bp += sizeof(nbytes); - if (hdr == NULL) { - zero = 0; - memcpy(bp, &zero, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - } else { - memcpy(bp, &hdr->size, sizeof(hdr->size)); - bp += sizeof(hdr->size); - memcpy(bp, hdr->data, hdr->size); - bp += hdr->size; - } - if (dbt == NULL) { - zero = 0; - memcpy(bp, &zero, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - } else { - memcpy(bp, &dbt->size, sizeof(dbt->size)); - bp += sizeof(dbt->size); - memcpy(bp, dbt->data, dbt->size); - bp += dbt->size; - } - if (pagelsn != NULL) - memcpy(bp, pagelsn, sizeof(*pagelsn)); - else - memset(bp, 0, sizeof(*pagelsn)); - bp += sizeof(*pagelsn); -#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 __db_addrem_print - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__db_addrem_print(notused1, dbtp, lsnp, notused2, notused3) - DB_LOG *notused1; - DBT *dbtp; - DB_LSN *lsnp; - int notused2; - void *notused3; -{ - __db_addrem_args *argp; - u_int32_t i; - u_int ch; - int ret; - - i = 0; - ch = 0; - notused1 = NULL; - notused2 = 0; - notused3 = NULL; - - if ((ret = __db_addrem_read(dbtp->data, &argp)) != 0) - return (ret); - printf("[%lu][%lu]db_addrem: 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("\tfileid: %lu\n", (u_long)argp->fileid); - printf("\tpgno: %lu\n", (u_long)argp->pgno); - printf("\tindx: %lu\n", (u_long)argp->indx); - printf("\tnbytes: %lu\n", (u_long)argp->nbytes); - printf("\thdr: "); - for (i = 0; i < argp->hdr.size; i++) { - ch = ((u_int8_t *)argp->hdr.data)[i]; - if (isprint(ch) || ch == 0xa) - putchar(ch); - else - printf("%#x ", ch); - } - printf("\n"); - printf("\tdbt: "); - for (i = 0; i < argp->dbt.size; i++) { - ch = ((u_int8_t *)argp->dbt.data)[i]; - if (isprint(ch) || ch == 0xa) - putchar(ch); - else - printf("%#x ", ch); - } - printf("\n"); - printf("\tpagelsn: [%lu][%lu]\n", - (u_long)argp->pagelsn.file, (u_long)argp->pagelsn.offset); - printf("\n"); - __os_free(argp, 0); - return (0); -} - -/* - * PUBLIC: int __db_addrem_read __P((void *, __db_addrem_args **)); - */ -int -__db_addrem_read(recbuf, argpp) - void *recbuf; - __db_addrem_args **argpp; -{ - __db_addrem_args *argp; - u_int8_t *bp; - int ret; - - ret = __os_malloc(sizeof(__db_addrem_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->fileid, bp, sizeof(argp->fileid)); - bp += sizeof(argp->fileid); - memcpy(&argp->pgno, bp, sizeof(argp->pgno)); - bp += sizeof(argp->pgno); - memcpy(&argp->indx, bp, sizeof(argp->indx)); - bp += sizeof(argp->indx); - memcpy(&argp->nbytes, bp, sizeof(argp->nbytes)); - bp += sizeof(argp->nbytes); - memcpy(&argp->hdr.size, bp, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - argp->hdr.data = bp; - bp += argp->hdr.size; - memcpy(&argp->dbt.size, bp, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - argp->dbt.data = bp; - bp += argp->dbt.size; - memcpy(&argp->pagelsn, bp, sizeof(argp->pagelsn)); - bp += sizeof(argp->pagelsn); - *argpp = argp; - return (0); -} - -/* - * PUBLIC: int __db_split_log - * PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - * PUBLIC: u_int32_t, u_int32_t, db_pgno_t, const DBT *, - * PUBLIC: DB_LSN *)); - */ -int __db_split_log(logp, txnid, ret_lsnp, flags, - opcode, fileid, pgno, pageimage, pagelsn) - DB_LOG *logp; - DB_TXN *txnid; - DB_LSN *ret_lsnp; - u_int32_t flags; - u_int32_t opcode; - u_int32_t fileid; - db_pgno_t pgno; - const DBT *pageimage; - DB_LSN * pagelsn; -{ - 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_db_split; - 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(fileid) - + sizeof(pgno) - + sizeof(u_int32_t) + (pageimage == NULL ? 0 : pageimage->size) - + sizeof(*pagelsn); - 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); - memcpy(bp, &fileid, sizeof(fileid)); - bp += sizeof(fileid); - memcpy(bp, &pgno, sizeof(pgno)); - bp += sizeof(pgno); - if (pageimage == NULL) { - zero = 0; - memcpy(bp, &zero, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - } else { - memcpy(bp, &pageimage->size, sizeof(pageimage->size)); - bp += sizeof(pageimage->size); - memcpy(bp, pageimage->data, pageimage->size); - bp += pageimage->size; - } - if (pagelsn != NULL) - memcpy(bp, pagelsn, sizeof(*pagelsn)); - else - memset(bp, 0, sizeof(*pagelsn)); - bp += sizeof(*pagelsn); -#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 __db_split_print - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__db_split_print(notused1, dbtp, lsnp, notused2, notused3) - DB_LOG *notused1; - DBT *dbtp; - DB_LSN *lsnp; - int notused2; - void *notused3; -{ - __db_split_args *argp; - u_int32_t i; - u_int ch; - int ret; - - i = 0; - ch = 0; - notused1 = NULL; - notused2 = 0; - notused3 = NULL; - - if ((ret = __db_split_read(dbtp->data, &argp)) != 0) - return (ret); - printf("[%lu][%lu]db_split: 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("\tfileid: %lu\n", (u_long)argp->fileid); - printf("\tpgno: %lu\n", (u_long)argp->pgno); - printf("\tpageimage: "); - for (i = 0; i < argp->pageimage.size; i++) { - ch = ((u_int8_t *)argp->pageimage.data)[i]; - if (isprint(ch) || ch == 0xa) - putchar(ch); - else - printf("%#x ", ch); - } - printf("\n"); - printf("\tpagelsn: [%lu][%lu]\n", - (u_long)argp->pagelsn.file, (u_long)argp->pagelsn.offset); - printf("\n"); - __os_free(argp, 0); - return (0); -} - -/* - * PUBLIC: int __db_split_read __P((void *, __db_split_args **)); - */ -int -__db_split_read(recbuf, argpp) - void *recbuf; - __db_split_args **argpp; -{ - __db_split_args *argp; - u_int8_t *bp; - int ret; - - ret = __os_malloc(sizeof(__db_split_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->fileid, bp, sizeof(argp->fileid)); - bp += sizeof(argp->fileid); - memcpy(&argp->pgno, bp, sizeof(argp->pgno)); - bp += sizeof(argp->pgno); - memcpy(&argp->pageimage.size, bp, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - argp->pageimage.data = bp; - bp += argp->pageimage.size; - memcpy(&argp->pagelsn, bp, sizeof(argp->pagelsn)); - bp += sizeof(argp->pagelsn); - *argpp = argp; - return (0); -} - -/* - * PUBLIC: int __db_big_log - * PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - * PUBLIC: u_int32_t, u_int32_t, db_pgno_t, db_pgno_t, - * PUBLIC: db_pgno_t, const DBT *, DB_LSN *, DB_LSN *, - * PUBLIC: DB_LSN *)); - */ -int __db_big_log(logp, txnid, ret_lsnp, flags, - opcode, fileid, pgno, prev_pgno, next_pgno, dbt, - pagelsn, prevlsn, nextlsn) - DB_LOG *logp; - DB_TXN *txnid; - DB_LSN *ret_lsnp; - u_int32_t flags; - u_int32_t opcode; - u_int32_t fileid; - db_pgno_t pgno; - db_pgno_t prev_pgno; - db_pgno_t next_pgno; - const DBT *dbt; - DB_LSN * pagelsn; - DB_LSN * prevlsn; - DB_LSN * nextlsn; -{ - 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_db_big; - 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(fileid) - + sizeof(pgno) - + sizeof(prev_pgno) - + sizeof(next_pgno) - + sizeof(u_int32_t) + (dbt == NULL ? 0 : dbt->size) - + sizeof(*pagelsn) - + sizeof(*prevlsn) - + sizeof(*nextlsn); - 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); - memcpy(bp, &fileid, sizeof(fileid)); - bp += sizeof(fileid); - memcpy(bp, &pgno, sizeof(pgno)); - bp += sizeof(pgno); - memcpy(bp, &prev_pgno, sizeof(prev_pgno)); - bp += sizeof(prev_pgno); - memcpy(bp, &next_pgno, sizeof(next_pgno)); - bp += sizeof(next_pgno); - if (dbt == NULL) { - zero = 0; - memcpy(bp, &zero, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - } else { - memcpy(bp, &dbt->size, sizeof(dbt->size)); - bp += sizeof(dbt->size); - memcpy(bp, dbt->data, dbt->size); - bp += dbt->size; - } - if (pagelsn != NULL) - memcpy(bp, pagelsn, sizeof(*pagelsn)); - else - memset(bp, 0, sizeof(*pagelsn)); - bp += sizeof(*pagelsn); - if (prevlsn != NULL) - memcpy(bp, prevlsn, sizeof(*prevlsn)); - else - memset(bp, 0, sizeof(*prevlsn)); - bp += sizeof(*prevlsn); - if (nextlsn != NULL) - memcpy(bp, nextlsn, sizeof(*nextlsn)); - else - memset(bp, 0, sizeof(*nextlsn)); - bp += sizeof(*nextlsn); -#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 __db_big_print - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__db_big_print(notused1, dbtp, lsnp, notused2, notused3) - DB_LOG *notused1; - DBT *dbtp; - DB_LSN *lsnp; - int notused2; - void *notused3; -{ - __db_big_args *argp; - u_int32_t i; - u_int ch; - int ret; - - i = 0; - ch = 0; - notused1 = NULL; - notused2 = 0; - notused3 = NULL; - - if ((ret = __db_big_read(dbtp->data, &argp)) != 0) - return (ret); - printf("[%lu][%lu]db_big: 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("\tfileid: %lu\n", (u_long)argp->fileid); - printf("\tpgno: %lu\n", (u_long)argp->pgno); - printf("\tprev_pgno: %lu\n", (u_long)argp->prev_pgno); - printf("\tnext_pgno: %lu\n", (u_long)argp->next_pgno); - printf("\tdbt: "); - for (i = 0; i < argp->dbt.size; i++) { - ch = ((u_int8_t *)argp->dbt.data)[i]; - if (isprint(ch) || ch == 0xa) - putchar(ch); - else - printf("%#x ", ch); - } - printf("\n"); - printf("\tpagelsn: [%lu][%lu]\n", - (u_long)argp->pagelsn.file, (u_long)argp->pagelsn.offset); - printf("\tprevlsn: [%lu][%lu]\n", - (u_long)argp->prevlsn.file, (u_long)argp->prevlsn.offset); - printf("\tnextlsn: [%lu][%lu]\n", - (u_long)argp->nextlsn.file, (u_long)argp->nextlsn.offset); - printf("\n"); - __os_free(argp, 0); - return (0); -} - -/* - * PUBLIC: int __db_big_read __P((void *, __db_big_args **)); - */ -int -__db_big_read(recbuf, argpp) - void *recbuf; - __db_big_args **argpp; -{ - __db_big_args *argp; - u_int8_t *bp; - int ret; - - ret = __os_malloc(sizeof(__db_big_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->fileid, bp, sizeof(argp->fileid)); - bp += sizeof(argp->fileid); - memcpy(&argp->pgno, bp, sizeof(argp->pgno)); - bp += sizeof(argp->pgno); - memcpy(&argp->prev_pgno, bp, sizeof(argp->prev_pgno)); - bp += sizeof(argp->prev_pgno); - memcpy(&argp->next_pgno, bp, sizeof(argp->next_pgno)); - bp += sizeof(argp->next_pgno); - memcpy(&argp->dbt.size, bp, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - argp->dbt.data = bp; - bp += argp->dbt.size; - memcpy(&argp->pagelsn, bp, sizeof(argp->pagelsn)); - bp += sizeof(argp->pagelsn); - memcpy(&argp->prevlsn, bp, sizeof(argp->prevlsn)); - bp += sizeof(argp->prevlsn); - memcpy(&argp->nextlsn, bp, sizeof(argp->nextlsn)); - bp += sizeof(argp->nextlsn); - *argpp = argp; - return (0); -} - -/* - * PUBLIC: int __db_ovref_log - * PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - * PUBLIC: u_int32_t, db_pgno_t, int32_t, DB_LSN *)); - */ -int __db_ovref_log(logp, txnid, ret_lsnp, flags, - fileid, pgno, adjust, lsn) - DB_LOG *logp; - DB_TXN *txnid; - DB_LSN *ret_lsnp; - u_int32_t flags; - u_int32_t fileid; - db_pgno_t pgno; - int32_t adjust; - DB_LSN * lsn; -{ - DBT logrec; - DB_LSN *lsnp, null_lsn; - u_int32_t rectype, txn_num; - int ret; - u_int8_t *bp; - - rectype = DB_db_ovref; - 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(fileid) - + sizeof(pgno) - + sizeof(adjust) - + sizeof(*lsn); - 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, &fileid, sizeof(fileid)); - bp += sizeof(fileid); - memcpy(bp, &pgno, sizeof(pgno)); - bp += sizeof(pgno); - memcpy(bp, &adjust, sizeof(adjust)); - bp += sizeof(adjust); - if (lsn != NULL) - memcpy(bp, lsn, sizeof(*lsn)); - else - memset(bp, 0, sizeof(*lsn)); - bp += sizeof(*lsn); -#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 __db_ovref_print - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__db_ovref_print(notused1, dbtp, lsnp, notused2, notused3) - DB_LOG *notused1; - DBT *dbtp; - DB_LSN *lsnp; - int notused2; - void *notused3; -{ - __db_ovref_args *argp; - u_int32_t i; - u_int ch; - int ret; - - i = 0; - ch = 0; - notused1 = NULL; - notused2 = 0; - notused3 = NULL; - - if ((ret = __db_ovref_read(dbtp->data, &argp)) != 0) - return (ret); - printf("[%lu][%lu]db_ovref: 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("\tfileid: %lu\n", (u_long)argp->fileid); - printf("\tpgno: %lu\n", (u_long)argp->pgno); - printf("\tadjust: %ld\n", (long)argp->adjust); - printf("\tlsn: [%lu][%lu]\n", - (u_long)argp->lsn.file, (u_long)argp->lsn.offset); - printf("\n"); - __os_free(argp, 0); - return (0); -} - -/* - * PUBLIC: int __db_ovref_read __P((void *, __db_ovref_args **)); - */ -int -__db_ovref_read(recbuf, argpp) - void *recbuf; - __db_ovref_args **argpp; -{ - __db_ovref_args *argp; - u_int8_t *bp; - int ret; - - ret = __os_malloc(sizeof(__db_ovref_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->fileid, bp, sizeof(argp->fileid)); - bp += sizeof(argp->fileid); - memcpy(&argp->pgno, bp, sizeof(argp->pgno)); - bp += sizeof(argp->pgno); - memcpy(&argp->adjust, bp, sizeof(argp->adjust)); - bp += sizeof(argp->adjust); - memcpy(&argp->lsn, bp, sizeof(argp->lsn)); - bp += sizeof(argp->lsn); - *argpp = argp; - return (0); -} - -/* - * PUBLIC: int __db_relink_log - * PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - * PUBLIC: u_int32_t, u_int32_t, db_pgno_t, DB_LSN *, - * PUBLIC: db_pgno_t, DB_LSN *, db_pgno_t, DB_LSN *)); - */ -int __db_relink_log(logp, txnid, ret_lsnp, flags, - opcode, fileid, pgno, lsn, prev, lsn_prev, - next, lsn_next) - DB_LOG *logp; - DB_TXN *txnid; - DB_LSN *ret_lsnp; - u_int32_t flags; - u_int32_t opcode; - u_int32_t fileid; - db_pgno_t pgno; - DB_LSN * lsn; - db_pgno_t prev; - DB_LSN * lsn_prev; - db_pgno_t next; - DB_LSN * lsn_next; -{ - DBT logrec; - DB_LSN *lsnp, null_lsn; - u_int32_t rectype, txn_num; - int ret; - u_int8_t *bp; - - rectype = DB_db_relink; - 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(fileid) - + sizeof(pgno) - + sizeof(*lsn) - + sizeof(prev) - + sizeof(*lsn_prev) - + sizeof(next) - + sizeof(*lsn_next); - 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); - memcpy(bp, &fileid, sizeof(fileid)); - bp += sizeof(fileid); - memcpy(bp, &pgno, sizeof(pgno)); - bp += sizeof(pgno); - if (lsn != NULL) - memcpy(bp, lsn, sizeof(*lsn)); - else - memset(bp, 0, sizeof(*lsn)); - bp += sizeof(*lsn); - memcpy(bp, &prev, sizeof(prev)); - bp += sizeof(prev); - if (lsn_prev != NULL) - memcpy(bp, lsn_prev, sizeof(*lsn_prev)); - else - memset(bp, 0, sizeof(*lsn_prev)); - bp += sizeof(*lsn_prev); - memcpy(bp, &next, sizeof(next)); - bp += sizeof(next); - if (lsn_next != NULL) - memcpy(bp, lsn_next, sizeof(*lsn_next)); - else - memset(bp, 0, sizeof(*lsn_next)); - bp += sizeof(*lsn_next); -#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 __db_relink_print - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__db_relink_print(notused1, dbtp, lsnp, notused2, notused3) - DB_LOG *notused1; - DBT *dbtp; - DB_LSN *lsnp; - int notused2; - void *notused3; -{ - __db_relink_args *argp; - u_int32_t i; - u_int ch; - int ret; - - i = 0; - ch = 0; - notused1 = NULL; - notused2 = 0; - notused3 = NULL; - - if ((ret = __db_relink_read(dbtp->data, &argp)) != 0) - return (ret); - printf("[%lu][%lu]db_relink: 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("\tfileid: %lu\n", (u_long)argp->fileid); - printf("\tpgno: %lu\n", (u_long)argp->pgno); - printf("\tlsn: [%lu][%lu]\n", - (u_long)argp->lsn.file, (u_long)argp->lsn.offset); - printf("\tprev: %lu\n", (u_long)argp->prev); - printf("\tlsn_prev: [%lu][%lu]\n", - (u_long)argp->lsn_prev.file, (u_long)argp->lsn_prev.offset); - printf("\tnext: %lu\n", (u_long)argp->next); - printf("\tlsn_next: [%lu][%lu]\n", - (u_long)argp->lsn_next.file, (u_long)argp->lsn_next.offset); - printf("\n"); - __os_free(argp, 0); - return (0); -} - -/* - * PUBLIC: int __db_relink_read __P((void *, __db_relink_args **)); - */ -int -__db_relink_read(recbuf, argpp) - void *recbuf; - __db_relink_args **argpp; -{ - __db_relink_args *argp; - u_int8_t *bp; - int ret; - - ret = __os_malloc(sizeof(__db_relink_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->fileid, bp, sizeof(argp->fileid)); - bp += sizeof(argp->fileid); - memcpy(&argp->pgno, bp, sizeof(argp->pgno)); - bp += sizeof(argp->pgno); - memcpy(&argp->lsn, bp, sizeof(argp->lsn)); - bp += sizeof(argp->lsn); - memcpy(&argp->prev, bp, sizeof(argp->prev)); - bp += sizeof(argp->prev); - memcpy(&argp->lsn_prev, bp, sizeof(argp->lsn_prev)); - bp += sizeof(argp->lsn_prev); - memcpy(&argp->next, bp, sizeof(argp->next)); - bp += sizeof(argp->next); - memcpy(&argp->lsn_next, bp, sizeof(argp->lsn_next)); - bp += sizeof(argp->lsn_next); - *argpp = argp; - return (0); -} - -/* - * PUBLIC: int __db_addpage_log - * PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - * PUBLIC: u_int32_t, db_pgno_t, DB_LSN *, db_pgno_t, - * PUBLIC: DB_LSN *)); - */ -int __db_addpage_log(logp, txnid, ret_lsnp, flags, - fileid, pgno, lsn, nextpgno, nextlsn) - DB_LOG *logp; - DB_TXN *txnid; - DB_LSN *ret_lsnp; - u_int32_t flags; - u_int32_t fileid; - db_pgno_t pgno; - DB_LSN * lsn; - db_pgno_t nextpgno; - DB_LSN * nextlsn; -{ - DBT logrec; - DB_LSN *lsnp, null_lsn; - u_int32_t rectype, txn_num; - int ret; - u_int8_t *bp; - - rectype = DB_db_addpage; - 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(fileid) - + sizeof(pgno) - + sizeof(*lsn) - + sizeof(nextpgno) - + sizeof(*nextlsn); - 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, &fileid, sizeof(fileid)); - bp += sizeof(fileid); - memcpy(bp, &pgno, sizeof(pgno)); - bp += sizeof(pgno); - if (lsn != NULL) - memcpy(bp, lsn, sizeof(*lsn)); - else - memset(bp, 0, sizeof(*lsn)); - bp += sizeof(*lsn); - memcpy(bp, &nextpgno, sizeof(nextpgno)); - bp += sizeof(nextpgno); - if (nextlsn != NULL) - memcpy(bp, nextlsn, sizeof(*nextlsn)); - else - memset(bp, 0, sizeof(*nextlsn)); - bp += sizeof(*nextlsn); -#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 __db_addpage_print - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__db_addpage_print(notused1, dbtp, lsnp, notused2, notused3) - DB_LOG *notused1; - DBT *dbtp; - DB_LSN *lsnp; - int notused2; - void *notused3; -{ - __db_addpage_args *argp; - u_int32_t i; - u_int ch; - int ret; - - i = 0; - ch = 0; - notused1 = NULL; - notused2 = 0; - notused3 = NULL; - - if ((ret = __db_addpage_read(dbtp->data, &argp)) != 0) - return (ret); - printf("[%lu][%lu]db_addpage: 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("\tfileid: %lu\n", (u_long)argp->fileid); - printf("\tpgno: %lu\n", (u_long)argp->pgno); - printf("\tlsn: [%lu][%lu]\n", - (u_long)argp->lsn.file, (u_long)argp->lsn.offset); - printf("\tnextpgno: %lu\n", (u_long)argp->nextpgno); - printf("\tnextlsn: [%lu][%lu]\n", - (u_long)argp->nextlsn.file, (u_long)argp->nextlsn.offset); - printf("\n"); - __os_free(argp, 0); - return (0); -} - -/* - * PUBLIC: int __db_addpage_read __P((void *, __db_addpage_args **)); - */ -int -__db_addpage_read(recbuf, argpp) - void *recbuf; - __db_addpage_args **argpp; -{ - __db_addpage_args *argp; - u_int8_t *bp; - int ret; - - ret = __os_malloc(sizeof(__db_addpage_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->fileid, bp, sizeof(argp->fileid)); - bp += sizeof(argp->fileid); - memcpy(&argp->pgno, bp, sizeof(argp->pgno)); - bp += sizeof(argp->pgno); - memcpy(&argp->lsn, bp, sizeof(argp->lsn)); - bp += sizeof(argp->lsn); - memcpy(&argp->nextpgno, bp, sizeof(argp->nextpgno)); - bp += sizeof(argp->nextpgno); - memcpy(&argp->nextlsn, bp, sizeof(argp->nextlsn)); - bp += sizeof(argp->nextlsn); - *argpp = argp; - return (0); -} - -/* - * PUBLIC: int __db_debug_log - * PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - * PUBLIC: const DBT *, u_int32_t, const DBT *, const DBT *, - * PUBLIC: u_int32_t)); - */ -int __db_debug_log(logp, txnid, ret_lsnp, flags, - op, fileid, key, data, arg_flags) - DB_LOG *logp; - DB_TXN *txnid; - DB_LSN *ret_lsnp; - u_int32_t flags; - const DBT *op; - u_int32_t fileid; - const DBT *key; - const DBT *data; - u_int32_t arg_flags; -{ - 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_db_debug; - 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(u_int32_t) + (op == NULL ? 0 : op->size) - + sizeof(fileid) - + sizeof(u_int32_t) + (key == NULL ? 0 : key->size) - + sizeof(u_int32_t) + (data == NULL ? 0 : data->size) - + sizeof(arg_flags); - 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); - if (op == NULL) { - zero = 0; - memcpy(bp, &zero, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - } else { - memcpy(bp, &op->size, sizeof(op->size)); - bp += sizeof(op->size); - memcpy(bp, op->data, op->size); - bp += op->size; - } - memcpy(bp, &fileid, sizeof(fileid)); - bp += sizeof(fileid); - if (key == NULL) { - zero = 0; - memcpy(bp, &zero, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - } else { - memcpy(bp, &key->size, sizeof(key->size)); - bp += sizeof(key->size); - memcpy(bp, key->data, key->size); - bp += key->size; - } - if (data == NULL) { - zero = 0; - memcpy(bp, &zero, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - } else { - memcpy(bp, &data->size, sizeof(data->size)); - bp += sizeof(data->size); - memcpy(bp, data->data, data->size); - bp += data->size; - } - memcpy(bp, &arg_flags, sizeof(arg_flags)); - bp += sizeof(arg_flags); -#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 __db_debug_print - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__db_debug_print(notused1, dbtp, lsnp, notused2, notused3) - DB_LOG *notused1; - DBT *dbtp; - DB_LSN *lsnp; - int notused2; - void *notused3; -{ - __db_debug_args *argp; - u_int32_t i; - u_int ch; - int ret; - - i = 0; - ch = 0; - notused1 = NULL; - notused2 = 0; - notused3 = NULL; - - if ((ret = __db_debug_read(dbtp->data, &argp)) != 0) - return (ret); - printf("[%lu][%lu]db_debug: 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("\top: "); - for (i = 0; i < argp->op.size; i++) { - ch = ((u_int8_t *)argp->op.data)[i]; - if (isprint(ch) || ch == 0xa) - putchar(ch); - else - printf("%#x ", ch); - } - printf("\n"); - printf("\tfileid: %lu\n", (u_long)argp->fileid); - printf("\tkey: "); - for (i = 0; i < argp->key.size; i++) { - ch = ((u_int8_t *)argp->key.data)[i]; - if (isprint(ch) || ch == 0xa) - putchar(ch); - else - printf("%#x ", ch); - } - printf("\n"); - printf("\tdata: "); - for (i = 0; i < argp->data.size; i++) { - ch = ((u_int8_t *)argp->data.data)[i]; - if (isprint(ch) || ch == 0xa) - putchar(ch); - else - printf("%#x ", ch); - } - printf("\n"); - printf("\targ_flags: %lu\n", (u_long)argp->arg_flags); - printf("\n"); - __os_free(argp, 0); - return (0); -} - -/* - * PUBLIC: int __db_debug_read __P((void *, __db_debug_args **)); - */ -int -__db_debug_read(recbuf, argpp) - void *recbuf; - __db_debug_args **argpp; -{ - __db_debug_args *argp; - u_int8_t *bp; - int ret; - - ret = __os_malloc(sizeof(__db_debug_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->op.size, bp, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - argp->op.data = bp; - bp += argp->op.size; - memcpy(&argp->fileid, bp, sizeof(argp->fileid)); - bp += sizeof(argp->fileid); - memcpy(&argp->key.size, bp, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - argp->key.data = bp; - bp += argp->key.size; - memcpy(&argp->data.size, bp, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - argp->data.data = bp; - bp += argp->data.size; - memcpy(&argp->arg_flags, bp, sizeof(argp->arg_flags)); - bp += sizeof(argp->arg_flags); - *argpp = argp; - return (0); -} - -/* - * PUBLIC: int __db_init_print __P((DB_ENV *)); - */ -int -__db_init_print(dbenv) - DB_ENV *dbenv; -{ - int ret; - - if ((ret = __db_add_recovery(dbenv, - __db_addrem_print, DB_db_addrem)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __db_split_print, DB_db_split)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __db_big_print, DB_db_big)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __db_ovref_print, DB_db_ovref)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __db_relink_print, DB_db_relink)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __db_addpage_print, DB_db_addpage)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __db_debug_print, DB_db_debug)) != 0) - return (ret); - return (0); -} - -/* - * PUBLIC: int __db_init_recover __P((DB_ENV *)); - */ -int -__db_init_recover(dbenv) - DB_ENV *dbenv; -{ - int ret; - - if ((ret = __db_add_recovery(dbenv, - __db_addrem_recover, DB_db_addrem)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __db_split_recover, DB_db_split)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __db_big_recover, DB_db_big)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __db_ovref_recover, DB_db_ovref)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __db_relink_recover, DB_db_relink)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __db_addpage_recover, DB_db_addpage)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __db_debug_recover, DB_db_debug)) != 0) - return (ret); - return (0); -} - diff --git a/db2/db/db_conv.c b/db2/db/db_conv.c deleted file mode 100644 index 8b5cf5f..0000000 --- a/db2/db/db_conv.c +++ /dev/null @@ -1,255 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994, 1995, 1996 - * Keith Bostic. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994, 1995 - * The Regents of the University of California. 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[] = "@(#)db_conv.c 10.13 (Sleepycat) 4/26/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <string.h> -#endif - -#include "db_int.h" -#include "db_page.h" -#include "db_swap.h" -#include "db_am.h" - -static int __db_convert __P((db_pgno_t, void *, size_t, int)); - -/* - * __db_pgin -- - * - * PUBLIC: int __db_pgin __P((db_pgno_t, size_t, void *)); - */ -int -__db_pgin(pg, pagesize, pp) - db_pgno_t pg; - size_t pagesize; - void *pp; -{ - return (__db_convert(pg, pp, pagesize, 1)); -} - -/* - * __db_pgout -- - * - * PUBLIC: int __db_pgout __P((db_pgno_t, size_t, void *)); - */ -int -__db_pgout(pg, pagesize, pp) - db_pgno_t pg; - size_t pagesize; - void *pp; -{ - return (__db_convert(pg, pp, pagesize, 0)); -} - -/* - * __db_convert -- - * Actually convert a page. - */ -static int -__db_convert(pg, pp, pagesize, pgin) - db_pgno_t pg; - void *pp; - size_t pagesize; - int pgin; -{ - BINTERNAL *bi; - BKEYDATA *bk; - BOVERFLOW *bo; - PAGE *h; - RINTERNAL *ri; - db_indx_t i, len, tmp; - u_int8_t *p, *end; - - COMPQUIET(pg, 0); - - h = pp; - if (pgin) { - M_32_SWAP(h->lsn.file); - M_32_SWAP(h->lsn.offset); - M_32_SWAP(h->pgno); - M_32_SWAP(h->prev_pgno); - M_32_SWAP(h->next_pgno); - M_16_SWAP(h->entries); - M_16_SWAP(h->hf_offset); - } - - switch (h->type) { - case P_HASH: - for (i = 0; i < NUM_ENT(h); i++) { - if (pgin) - M_16_SWAP(h->inp[i]); - - switch (HPAGE_TYPE(h, i)) { - case H_KEYDATA: - break; - case H_DUPLICATE: - len = LEN_HKEYDATA(h, pagesize, i); - p = HKEYDATA_DATA(P_ENTRY(h, i)); - for (end = p + len; p < end;) { - if (pgin) { - P_16_SWAP(p); - memcpy(&tmp, - p, sizeof(db_indx_t)); - p += sizeof(db_indx_t); - } else { - memcpy(&tmp, - p, sizeof(db_indx_t)); - SWAP16(p); - } - p += tmp; - SWAP16(p); - } - break; - case H_OFFDUP: - p = HOFFPAGE_PGNO(P_ENTRY(h, i)); - SWAP32(p); /* pgno */ - break; - case H_OFFPAGE: - p = HOFFPAGE_PGNO(P_ENTRY(h, i)); - SWAP32(p); /* pgno */ - SWAP32(p); /* tlen */ - break; - } - - } - - /* - * The offsets in the inp array are used to determine - * the size of entries on a page; therefore they - * cannot be converted until we've done all the - * entries. - */ - if (!pgin) - for (i = 0; i < NUM_ENT(h); i++) - M_16_SWAP(h->inp[i]); - break; - case P_LBTREE: - case P_LRECNO: - case P_DUPLICATE: - for (i = 0; i < NUM_ENT(h); i++) { - if (pgin) - M_16_SWAP(h->inp[i]); - - bk = GET_BKEYDATA(h, i); - switch (B_TYPE(bk->type)) { - case B_KEYDATA: - M_16_SWAP(bk->len); - break; - case B_DUPLICATE: - case B_OVERFLOW: - bo = (BOVERFLOW *)bk; - M_32_SWAP(bo->pgno); - M_32_SWAP(bo->tlen); - break; - } - - if (!pgin) - M_16_SWAP(h->inp[i]); - } - break; - case P_IBTREE: - for (i = 0; i < NUM_ENT(h); i++) { - if (pgin) - M_16_SWAP(h->inp[i]); - - bi = GET_BINTERNAL(h, i); - M_16_SWAP(bi->len); - M_32_SWAP(bi->pgno); - M_32_SWAP(bi->nrecs); - - switch (B_TYPE(bi->type)) { - case B_KEYDATA: - break; - case B_DUPLICATE: - case B_OVERFLOW: - bo = (BOVERFLOW *)bi->data; - M_32_SWAP(bo->pgno); - M_32_SWAP(bo->tlen); - break; - } - - if (!pgin) - M_16_SWAP(h->inp[i]); - } - break; - case P_IRECNO: - for (i = 0; i < NUM_ENT(h); i++) { - if (pgin) - M_16_SWAP(h->inp[i]); - - ri = GET_RINTERNAL(h, i); - M_32_SWAP(ri->pgno); - M_32_SWAP(ri->nrecs); - - if (!pgin) - M_16_SWAP(h->inp[i]); - } - break; - case P_OVERFLOW: - case P_INVALID: - /* Nothing to do. */ - break; - default: - return (EINVAL); - } - - if (!pgin) { - /* Swap the header information. */ - M_32_SWAP(h->lsn.file); - M_32_SWAP(h->lsn.offset); - M_32_SWAP(h->pgno); - M_32_SWAP(h->prev_pgno); - M_32_SWAP(h->next_pgno); - M_16_SWAP(h->entries); - M_16_SWAP(h->hf_offset); - } - return (0); -} diff --git a/db2/db/db_dispatch.c b/db2/db/db_dispatch.c deleted file mode 100644 index 616d08c..0000000 --- a/db2/db/db_dispatch.c +++ /dev/null @@ -1,316 +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. - * - * 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_dispatch.c 10.20 (Sleepycat) 10/10/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <shqueue.h> -#include <stddef.h> -#include <stdlib.h> -#include <string.h> -#endif - -#include "db_int.h" -#include "db_page.h" -#include "db_dispatch.h" -#include "db_am.h" -#include "common_ext.h" -#include "log_auto.h" -#include "txn.h" -#include "txn_auto.h" - -/* - * Data structures to manage the DB dispatch table. The dispatch table - * is a dynamically allocated array of pointers to dispatch functions. - * The dispatch_size is the number of entries possible in the current - * dispatch table and the dispatch_valid is the number of valid entries - * in the dispatch table. - */ -static int (**dispatch_table) __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -static u_int32_t dispatch_size = 0; - -/* - * __db_dispatch -- - * - * This is the transaction dispatch function used by the db access methods. - * It is designed to handle the record format used by all the access - * methods (the one automatically generated by the db_{h,log,read}.sh - * scripts in the tools directory). An application using a different - * recovery paradigm will supply a different dispatch function to txn_open. - * - * PUBLIC: int __db_dispatch __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__db_dispatch(logp, db, lsnp, redo, info) - DB_LOG *logp; /* The log file. */ - DBT *db; /* The log record upon which to dispatch. */ - DB_LSN *lsnp; /* The lsn of the record being dispatched. */ - int redo; /* Redo this op (or undo it). */ - void *info; -{ - u_int32_t rectype, txnid; - - memcpy(&rectype, db->data, sizeof(rectype)); - memcpy(&txnid, (u_int8_t *)db->data + sizeof(rectype), sizeof(txnid)); - - switch (redo) { - case TXN_REDO: - case TXN_UNDO: - return ((dispatch_table[rectype])(logp, db, lsnp, redo, info)); - case TXN_OPENFILES: - if (rectype < DB_txn_BEGIN ) - return ((dispatch_table[rectype])(logp, - db, lsnp, redo, info)); - break; - case TXN_BACKWARD_ROLL: - /* - * Running full recovery in the backward pass. If we've - * seen this txnid before and added to it our commit list, - * then we do nothing during this pass. If we've never - * seen it, then we call the appropriate recovery routine - * in "abort mode". - */ - if (rectype == DB_log_register || rectype == DB_txn_ckp || - __db_txnlist_find(info, txnid) == DB_NOTFOUND) - return ((dispatch_table[rectype])(logp, - db, lsnp, TXN_UNDO, info)); - break; - case TXN_FORWARD_ROLL: - /* - * In the forward pass, if we haven't seen the transaction, - * do nothing, else recovery it. - */ - if (rectype == DB_log_register || rectype == DB_txn_ckp || - __db_txnlist_find(info, txnid) != DB_NOTFOUND) - return ((dispatch_table[rectype])(logp, - db, lsnp, TXN_REDO, info)); - break; - default: - abort(); - } - return (0); -} - -/* - * __db_add_recovery -- - * - * PUBLIC: int __db_add_recovery __P((DB_ENV *, - * PUBLIC: int (*)(DB_LOG *, DBT *, DB_LSN *, int, void *), u_int32_t)); - */ -int -__db_add_recovery(dbenv, func, ndx) - DB_ENV *dbenv; - int (*func) __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - u_int32_t ndx; -{ - u_int32_t i; - int ret; - - COMPQUIET(dbenv, NULL); /* !!!: not currently used. */ - - /* Check if we have to grow the table. */ - if (ndx >= dispatch_size) { - if ((ret = __os_realloc(&dispatch_table, - (DB_user_BEGIN + dispatch_size) * - sizeof(dispatch_table[0]))) != 0) - return (ret); - for (i = dispatch_size, - dispatch_size += DB_user_BEGIN; i < dispatch_size; ++i) - dispatch_table[i] = NULL; - } - - dispatch_table[ndx] = func; - return (0); -} - -/* - * __db_txnlist_init -- - * Initialize transaction linked list. - * - * PUBLIC: int __db_txnlist_init __P((void *)); - */ -int -__db_txnlist_init(retp) - void *retp; -{ - DB_TXNHEAD *headp; - int ret; - - if ((ret = __os_malloc(sizeof(DB_TXNHEAD), NULL, &headp)) != 0) - return (ret); - - LIST_INIT(&headp->head); - headp->maxid = 0; - headp->generation = 1; - - *(void **)retp = headp; - return (0); -} - -/* - * __db_txnlist_add -- - * Add an element to our transaction linked list. - * - * PUBLIC: int __db_txnlist_add __P((void *, u_int32_t)); - */ -int -__db_txnlist_add(listp, txnid) - void *listp; - u_int32_t txnid; -{ - DB_TXNHEAD *hp; - DB_TXNLIST *elp; - int ret; - - if ((ret = __os_malloc(sizeof(DB_TXNLIST), NULL, &elp)) != 0) - return (ret); - - elp->txnid = txnid; - hp = (DB_TXNHEAD *)listp; - LIST_INSERT_HEAD(&hp->head, elp, links); - if (txnid > hp->maxid) - hp->maxid = txnid; - elp->generation = hp->generation; - - return (0); -} - -/* - * __db_txnlist_find -- - * Checks to see if a txnid with the current generation is in the - * txnid list. - * - * PUBLIC: int __db_txnlist_find __P((void *, u_int32_t)); - */ -int -__db_txnlist_find(listp, txnid) - void *listp; - u_int32_t txnid; -{ - DB_TXNHEAD *hp; - DB_TXNLIST *p; - - if ((hp = (DB_TXNHEAD *)listp) == NULL) - return (DB_NOTFOUND); - - for (p = hp->head.lh_first; p != NULL; p = p->links.le_next) - if (p->txnid == txnid && hp->generation == p->generation) - return (0); - - return (DB_NOTFOUND); -} - -/* - * __db_txnlist_end -- - * Discard transaction linked list. - * - * PUBLIC: void __db_txnlist_end __P((void *)); - */ -void -__db_txnlist_end(listp) - void *listp; -{ - DB_TXNHEAD *hp; - DB_TXNLIST *p; - - hp = (DB_TXNHEAD *)listp; - while ((p = LIST_FIRST(&hp->head)) != LIST_END(&hp->head)) { - LIST_REMOVE(p, links); - __os_free(p, 0); - } - __os_free(listp, sizeof(DB_TXNHEAD)); -} - -/* - * __db_txnlist_gen -- - * Change the current generation number. - * - * PUBLIC: void __db_txnlist_gen __P((void *, int)); - */ -void -__db_txnlist_gen(listp, incr) - void *listp; - int incr; -{ - DB_TXNHEAD *hp; - - /* - * During recovery generation numbers keep track of how many "restart" - * checkpoints we've seen. Restart checkpoints occur whenever we take - * a checkpoint and there are no outstanding transactions. When that - * happens, we can reset transaction IDs back to 1. It always happens - * at recovery and it prevents us from exhausting the transaction IDs - * name space. - */ - hp = (DB_TXNHEAD *)listp; - hp->generation += incr; -} - -#ifdef DEBUG -/* - * __db_txnlist_print -- - * Print out the transaction list. - * - * PUBLIC: void __db_txnlist_print __P((void *)); - */ -void -__db_txnlist_print(listp) - void *listp; -{ - DB_TXNHEAD *hp; - DB_TXNLIST *p; - - hp = (DB_TXNHEAD *)listp; - printf("Maxid: %lu Generation: %lu\n", (u_long)hp->maxid, - (u_long)hp->generation); - for (p = hp->head.lh_first; p != NULL; p = p->links.le_next) - printf("TXNID: %lu(%lu)\n", (u_long)p->txnid, - (u_long)p->generation); -} -#endif diff --git a/db2/db/db_dup.c b/db2/db/db_dup.c deleted file mode 100644 index 2673bbc..0000000 --- a/db2/db/db_dup.c +++ /dev/null @@ -1,947 +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_dup.c 10.35 (Sleepycat) 12/2/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <string.h> -#endif - -#include "db_int.h" -#include "db_page.h" -#include "btree.h" -#include "db_am.h" - -static int __db_addpage __P((DBC *, - PAGE **, db_indx_t *, int (*)(DBC *, u_int32_t, PAGE **))); -static int __db_dsplit __P((DBC *, - PAGE **, db_indx_t *, u_int32_t, int (*)(DBC *, u_int32_t, PAGE **))); - -/* - * __db_dput -- - * Put a duplicate item onto a duplicate page at the given index. - * - * PUBLIC: int __db_dput __P((DBC *, DBT *, - * PUBLIC: PAGE **, db_indx_t *, int (*)(DBC *, u_int32_t, PAGE **))); - */ -int -__db_dput(dbc, dbt, pp, indxp, newfunc) - DBC *dbc; - DBT *dbt; - PAGE **pp; - db_indx_t *indxp; - int (*newfunc) __P((DBC *, u_int32_t, PAGE **)); -{ - BOVERFLOW bo; - DBT *data_dbtp, hdr_dbt, *hdr_dbtp; - PAGE *pagep; - db_indx_t size, isize; - db_pgno_t pgno; - int ret; - - /* - * We need some access method independent threshold for when we put - * a duplicate item onto an overflow page. - */ - if (dbt->size > 0.25 * dbc->dbp->pgsize) { - if ((ret = __db_poff(dbc, dbt, &pgno, newfunc)) != 0) - return (ret); - UMRW(bo.unused1); - B_TSET(bo.type, B_OVERFLOW, 0); - UMRW(bo.unused2); - bo.tlen = dbt->size; - bo.pgno = pgno; - hdr_dbt.data = &bo; - hdr_dbt.size = isize = BOVERFLOW_SIZE; - hdr_dbtp = &hdr_dbt; - size = BOVERFLOW_PSIZE; - data_dbtp = NULL; - } else { - size = BKEYDATA_PSIZE(dbt->size); - isize = BKEYDATA_SIZE(dbt->size); - hdr_dbtp = NULL; - data_dbtp = dbt; - } - - pagep = *pp; - if (size > P_FREESPACE(pagep)) { - if (*indxp == NUM_ENT(*pp) && NEXT_PGNO(*pp) == PGNO_INVALID) - ret = __db_addpage(dbc, pp, indxp, newfunc); - else - ret = __db_dsplit(dbc, pp, indxp, isize, newfunc); - if (ret != 0) - /* - * XXX - * Pages not returned to free list. - */ - return (ret); - pagep = *pp; - } - - /* - * Now, pagep references the page on which to insert and indx is the - * the location to insert. - */ - if ((ret = __db_pitem(dbc, - pagep, (u_int32_t)*indxp, isize, hdr_dbtp, data_dbtp)) != 0) - return (ret); - - (void)memp_fset(dbc->dbp->mpf, pagep, DB_MPOOL_DIRTY); - return (0); -} - -/* - * __db_drem -- - * Remove a duplicate at the given index on the given page. - * - * PUBLIC: int __db_drem __P((DBC *, - * PUBLIC: PAGE **, u_int32_t, int (*)(DBC *, PAGE *))); - */ -int -__db_drem(dbc, pp, indx, freefunc) - DBC *dbc; - PAGE **pp; - u_int32_t indx; - int (*freefunc) __P((DBC *, PAGE *)); -{ - PAGE *pagep; - int ret; - - pagep = *pp; - - /* Check if we are freeing a big item. */ - if (B_TYPE(GET_BKEYDATA(pagep, indx)->type) == B_OVERFLOW) { - if ((ret = __db_doff(dbc, - GET_BOVERFLOW(pagep, indx)->pgno, freefunc)) != 0) - return (ret); - ret = __db_ditem(dbc, pagep, indx, BOVERFLOW_SIZE); - } else - ret = __db_ditem(dbc, pagep, indx, - BKEYDATA_SIZE(GET_BKEYDATA(pagep, indx)->len)); - if (ret != 0) - return (ret); - - if (NUM_ENT(pagep) == 0) { - /* - * If the page is emptied, then the page is freed and the pp - * parameter is set to reference the next, locked page in the - * duplicate chain, if one exists. If there was no such page, - * then it is set to NULL. - * - * !!! - * __db_relink will set the dirty bit for us. - */ - if ((ret = __db_relink(dbc, DB_REM_PAGE, pagep, pp, 0)) != 0) - return (ret); - if ((ret = freefunc(dbc, pagep)) != 0) - return (ret); - } else - (void)memp_fset(dbc->dbp->mpf, pagep, DB_MPOOL_DIRTY); - - return (0); -} - -/* - * __db_dend -- - * Find the last page in a set of offpage duplicates. - * - * PUBLIC: int __db_dend __P((DBC *, db_pgno_t, PAGE **)); - */ -int -__db_dend(dbc, pgno, pp) - DBC *dbc; - db_pgno_t pgno; - PAGE **pp; -{ - DB *dbp; - PAGE *h; - int ret; - - dbp = dbc->dbp; - - /* - * This implements DB_KEYLAST. The last page is returned in pp; pgno - * should be the page number of the first page of the duplicate chain. - * - * *pp may be non-NULL -- if given a valid page use it. - */ - if (*pp != NULL) - goto started; - for (;;) { - if ((ret = memp_fget(dbp->mpf, &pgno, 0, pp)) != 0) { - (void)__db_pgerr(dbp, pgno); - return (ret); - } -started: h = *pp; - - if ((pgno = NEXT_PGNO(h)) == PGNO_INVALID) - break; - - if ((ret = memp_fput(dbp->mpf, h, 0)) != 0) - return (ret); - } - return (0); -} - -/* - * __db_dsplit -- - * Split a page of duplicates, calculating the split point based - * on an element of size "size" being added at "*indxp". - * On entry hp contains a pointer to the page-pointer of the original - * page. On exit, it returns a pointer to the page containing "*indxp" - * and "indxp" has been modified to reflect the index on the new page - * where the element should be added. The function returns with - * the page on which the insert should happen, not yet put. - */ -static int -__db_dsplit(dbc, hp, indxp, size, newfunc) - DBC *dbc; - PAGE **hp; - db_indx_t *indxp; - u_int32_t size; - int (*newfunc) __P((DBC *, u_int32_t, PAGE **)); -{ - PAGE *h, *np, *tp; - BKEYDATA *bk; - DBT page_dbt; - DB *dbp; - size_t pgsize; - db_indx_t halfbytes, i, indx, lastsum, nindex, oindex, s, sum; - int did_indx, ret, t_ret; - - h = *hp; - indx = *indxp; - ret = 0; - dbp = dbc->dbp; - pgsize = dbp->pgsize; - - /* Create a temporary page to do compaction onto. */ - if ((ret = __os_malloc(pgsize, NULL, &tp)) != 0) - return (ret); - - /* Create new page for the split. */ - if ((ret = newfunc(dbc, P_DUPLICATE, &np)) != 0) { - __os_free(tp, pgsize); - return (ret); - } - - P_INIT(np, pgsize, PGNO(np), PGNO(h), NEXT_PGNO(h), 0, - P_DUPLICATE); - P_INIT(tp, pgsize, PGNO(h), PREV_PGNO(h), PGNO(np), 0, - P_DUPLICATE); - - /* Figure out the split point */ - halfbytes = (pgsize - HOFFSET(h)) / 2; - did_indx = 0; - for (sum = 0, lastsum = 0, i = 0; i < NUM_ENT(h); i++) { - if (i == indx) { - sum += size; - did_indx = 1; - if (lastsum < halfbytes && sum >= halfbytes) { - /* We've crossed the halfway point. */ - if ((db_indx_t)(halfbytes - lastsum) < - (db_indx_t)(sum - halfbytes)) { - *hp = np; - *indxp = 0; - } else - *indxp = i; - break; - } - *indxp = i; - lastsum = sum; - } - if (B_TYPE(GET_BKEYDATA(h, i)->type) == B_KEYDATA) - sum += BKEYDATA_SIZE(GET_BKEYDATA(h, i)->len); - else - sum += BOVERFLOW_SIZE; - - if (lastsum < halfbytes && sum >= halfbytes) { - /* We've crossed the halfway point. */ - if ((db_indx_t)(sum - halfbytes) < - (db_indx_t)(halfbytes - lastsum)) - i++; - break; - } - } - /* - * Check if we have set the return values of the index pointer and - * page pointer. - */ - if (!did_indx) { - *hp = np; - *indxp = indx - i; - } - - if (DB_LOGGING(dbc)) { - page_dbt.size = dbp->pgsize; - page_dbt.data = h; - if ((ret = __db_split_log(dbp->dbenv->lg_info, - dbc->txn, &LSN(h), 0, DB_SPLITOLD, dbp->log_fileid, - PGNO(h), &page_dbt, &LSN(h))) != 0) { - __os_free(tp, pgsize); - return (ret); - } - LSN(tp) = LSN(h); - } - - /* - * If it's a btree, adjust the cursors. - * - * i is the index of the first element to move onto the new page. - */ - if (dbp->type == DB_BTREE) - __bam_ca_split(dbp, PGNO(h), PGNO(h), PGNO(np), i, 0); - - for (nindex = 0, oindex = i; oindex < NUM_ENT(h); oindex++) { - bk = GET_BKEYDATA(h, oindex); - if (B_TYPE(bk->type) == B_KEYDATA) - s = BKEYDATA_SIZE(bk->len); - else - s = BOVERFLOW_SIZE; - - np->inp[nindex++] = HOFFSET(np) -= s; - memcpy((u_int8_t *)np + HOFFSET(np), bk, s); - NUM_ENT(np)++; - } - - /* - * Now do data compaction by copying the remaining stuff onto the - * temporary page and then copying it back to the real page. - */ - for (nindex = 0, oindex = 0; oindex < i; oindex++) { - bk = GET_BKEYDATA(h, oindex); - if (B_TYPE(bk->type) == B_KEYDATA) - s = BKEYDATA_SIZE(bk->len); - else - s = BOVERFLOW_SIZE; - - tp->inp[nindex++] = HOFFSET(tp) -= s; - memcpy((u_int8_t *)tp + HOFFSET(tp), bk, s); - NUM_ENT(tp)++; - } - - /* - * This page (the temporary) should be only half full, so we do two - * memcpy's, one for the top of the page and one for the bottom of - * the page. This way we avoid copying the middle which should be - * about half a page. - */ - memcpy(h, tp, LOFFSET(tp)); - memcpy((u_int8_t *)h + HOFFSET(tp), - (u_int8_t *)tp + HOFFSET(tp), pgsize - HOFFSET(tp)); - __os_free(tp, pgsize); - - if (DB_LOGGING(dbc)) { - /* - * XXX - * If either of these fails, are we leaving pages pinned? - * Yes, but it seems like this happens in error case. - */ - page_dbt.size = pgsize; - page_dbt.data = h; - if ((ret = __db_split_log(dbp->dbenv->lg_info, - dbc->txn, &LSN(h), 0, DB_SPLITNEW, dbp->log_fileid, - PGNO(h), &page_dbt, &LSN(h))) != 0) - return (ret); - - page_dbt.size = pgsize; - page_dbt.data = np; - if ((ret = __db_split_log(dbp->dbenv->lg_info, - dbc->txn, &LSN(np), 0, DB_SPLITNEW, dbp->log_fileid, - PGNO(np), &page_dbt, &LSN(np))) != 0) - return (ret); - } - - /* - * Finally, if there was a next page after the page being - * split, fix its prev pointer. - */ - if (np->next_pgno != PGNO_INVALID) - ret = __db_relink(dbc, DB_ADD_PAGE, np, NULL, 1); - - /* - * Figure out if the location we're interested in is on the new - * page, and if so, reset the callers' pointer. Push the other - * page back to the store. - */ - if (*hp == h) - t_ret = memp_fput(dbp->mpf, np, DB_MPOOL_DIRTY); - else - t_ret = memp_fput(dbp->mpf, h, DB_MPOOL_DIRTY); - - return (ret != 0 ? ret : t_ret); -} - -/* - * __db_ditem -- - * Remove an item from a page. - * - * PUBLIC: int __db_ditem __P((DBC *, PAGE *, u_int32_t, u_int32_t)); - */ -int -__db_ditem(dbc, pagep, indx, nbytes) - DBC *dbc; - PAGE *pagep; - u_int32_t indx, nbytes; -{ - DB *dbp; - DBT ldbt; - db_indx_t cnt, offset; - int ret; - u_int8_t *from; - - dbp = dbc->dbp; - if (DB_LOGGING(dbc)) { - ldbt.data = P_ENTRY(pagep, indx); - ldbt.size = nbytes; - if ((ret = __db_addrem_log(dbp->dbenv->lg_info, dbc->txn, - &LSN(pagep), 0, DB_REM_DUP, dbp->log_fileid, PGNO(pagep), - (u_int32_t)indx, nbytes, &ldbt, NULL, &LSN(pagep))) != 0) - return (ret); - } - - /* - * If there's only a single item on the page, we don't have to - * work hard. - */ - if (NUM_ENT(pagep) == 1) { - NUM_ENT(pagep) = 0; - HOFFSET(pagep) = dbp->pgsize; - return (0); - } - - /* - * Pack the remaining key/data items at the end of the page. Use - * memmove(3), the regions may overlap. - */ - from = (u_int8_t *)pagep + HOFFSET(pagep); - memmove(from + nbytes, from, pagep->inp[indx] - HOFFSET(pagep)); - HOFFSET(pagep) += nbytes; - - /* Adjust the indices' offsets. */ - offset = pagep->inp[indx]; - for (cnt = 0; cnt < NUM_ENT(pagep); ++cnt) - if (pagep->inp[cnt] < offset) - pagep->inp[cnt] += nbytes; - - /* Shift the indices down. */ - --NUM_ENT(pagep); - if (indx != NUM_ENT(pagep)) - memmove(&pagep->inp[indx], &pagep->inp[indx + 1], - sizeof(db_indx_t) * (NUM_ENT(pagep) - indx)); - - /* If it's a btree, adjust the cursors. */ - if (dbp->type == DB_BTREE) - __bam_ca_di(dbp, PGNO(pagep), indx, -1); - - return (0); -} - -/* - * __db_pitem -- - * Put an item on a page. - * - * PUBLIC: int __db_pitem - * PUBLIC: __P((DBC *, PAGE *, u_int32_t, u_int32_t, DBT *, DBT *)); - */ -int -__db_pitem(dbc, pagep, indx, nbytes, hdr, data) - DBC *dbc; - PAGE *pagep; - u_int32_t indx; - u_int32_t nbytes; - DBT *hdr, *data; -{ - DB *dbp; - BKEYDATA bk; - DBT thdr; - int ret; - u_int8_t *p; - - /* - * Put a single item onto a page. The logic figuring out where to - * insert and whether it fits is handled in the caller. All we do - * here is manage the page shuffling. We cheat a little bit in that - * we don't want to copy the dbt on a normal put twice. If hdr is - * NULL, we create a BKEYDATA structure on the page, otherwise, just - * copy the caller's information onto the page. - * - * This routine is also used to put entries onto the page where the - * entry is pre-built, e.g., during recovery. In this case, the hdr - * will point to the entry, and the data argument will be NULL. - * - * !!! - * There's a tremendous potential for off-by-one errors here, since - * the passed in header sizes must be adjusted for the structure's - * placeholder for the trailing variable-length data field. - */ - dbp = dbc->dbp; - if (DB_LOGGING(dbc)) - if ((ret = __db_addrem_log(dbp->dbenv->lg_info, dbc->txn, - &LSN(pagep), 0, DB_ADD_DUP, dbp->log_fileid, PGNO(pagep), - (u_int32_t)indx, nbytes, hdr, data, &LSN(pagep))) != 0) - return (ret); - - if (hdr == NULL) { - B_TSET(bk.type, B_KEYDATA, 0); - bk.len = data == NULL ? 0 : data->size; - - thdr.data = &bk; - thdr.size = SSZA(BKEYDATA, data); - hdr = &thdr; - } - - /* Adjust the index table, then put the item on the page. */ - if (indx != NUM_ENT(pagep)) - memmove(&pagep->inp[indx + 1], &pagep->inp[indx], - sizeof(db_indx_t) * (NUM_ENT(pagep) - indx)); - HOFFSET(pagep) -= nbytes; - pagep->inp[indx] = HOFFSET(pagep); - ++NUM_ENT(pagep); - - p = P_ENTRY(pagep, indx); - memcpy(p, hdr->data, hdr->size); - if (data != NULL) - memcpy(p + hdr->size, data->data, data->size); - - /* If it's a btree, adjust the cursors. */ - if (dbp->type == DB_BTREE) - __bam_ca_di(dbp, PGNO(pagep), indx, 1); - - return (0); -} - -/* - * __db_relink -- - * Relink around a deleted page. - * - * PUBLIC: int __db_relink __P((DBC *, u_int32_t, PAGE *, PAGE **, int)); - */ -int -__db_relink(dbc, add_rem, pagep, new_next, needlock) - DBC *dbc; - u_int32_t add_rem; - PAGE *pagep, **new_next; - int needlock; -{ - DB *dbp; - PAGE *np, *pp; - DB_LOCK npl, ppl; - DB_LSN *nlsnp, *plsnp; - int ret; - - ret = 0; - np = pp = NULL; - npl = ppl = LOCK_INVALID; - nlsnp = plsnp = NULL; - dbp = dbc->dbp; - - /* - * Retrieve and lock the one/two pages. For a remove, we may need - * two pages (the before and after). For an add, we only need one - * because, the split took care of the prev. - */ - if (pagep->next_pgno != PGNO_INVALID) { - if (needlock && (ret = __bam_lget(dbc, - 0, pagep->next_pgno, DB_LOCK_WRITE, &npl)) != 0) - goto err; - if ((ret = memp_fget(dbp->mpf, - &pagep->next_pgno, 0, &np)) != 0) { - (void)__db_pgerr(dbp, pagep->next_pgno); - goto err; - } - nlsnp = &np->lsn; - } - if (add_rem == DB_REM_PAGE && pagep->prev_pgno != PGNO_INVALID) { - if (needlock && (ret = __bam_lget(dbc, - 0, pagep->prev_pgno, DB_LOCK_WRITE, &ppl)) != 0) - goto err; - if ((ret = memp_fget(dbp->mpf, - &pagep->prev_pgno, 0, &pp)) != 0) { - (void)__db_pgerr(dbp, pagep->next_pgno); - goto err; - } - plsnp = &pp->lsn; - } - - /* Log the change. */ - if (DB_LOGGING(dbc)) { - if ((ret = __db_relink_log(dbp->dbenv->lg_info, dbc->txn, - &pagep->lsn, 0, add_rem, dbp->log_fileid, - pagep->pgno, &pagep->lsn, - pagep->prev_pgno, plsnp, pagep->next_pgno, nlsnp)) != 0) - goto err; - if (np != NULL) - np->lsn = pagep->lsn; - if (pp != NULL) - pp->lsn = pagep->lsn; - } - - /* - * Modify and release the two pages. - * - * !!! - * The parameter new_next gets set to the page following the page we - * are removing. If there is no following page, then new_next gets - * set to NULL. - */ - if (np != NULL) { - if (add_rem == DB_ADD_PAGE) - np->prev_pgno = pagep->pgno; - else - np->prev_pgno = pagep->prev_pgno; - if (new_next == NULL) - ret = memp_fput(dbp->mpf, np, DB_MPOOL_DIRTY); - else { - *new_next = np; - ret = memp_fset(dbp->mpf, np, DB_MPOOL_DIRTY); - } - if (ret != 0) - goto err; - if (needlock) - (void)__bam_lput(dbc, npl); - } else if (new_next != NULL) - *new_next = NULL; - - if (pp != NULL) { - pp->next_pgno = pagep->next_pgno; - if ((ret = memp_fput(dbp->mpf, pp, DB_MPOOL_DIRTY)) != 0) - goto err; - if (needlock) - (void)__bam_lput(dbc, ppl); - } - return (0); - -err: if (np != NULL) - (void)memp_fput(dbp->mpf, np, 0); - if (needlock && npl != LOCK_INVALID) - (void)__bam_lput(dbc, npl); - if (pp != NULL) - (void)memp_fput(dbp->mpf, pp, 0); - if (needlock && ppl != LOCK_INVALID) - (void)__bam_lput(dbc, ppl); - return (ret); -} - -/* - * __db_ddup -- - * Delete an offpage chain of duplicates. - * - * PUBLIC: int __db_ddup __P((DBC *, db_pgno_t, int (*)(DBC *, PAGE *))); - */ -int -__db_ddup(dbc, pgno, freefunc) - DBC *dbc; - db_pgno_t pgno; - int (*freefunc) __P((DBC *, PAGE *)); -{ - DB *dbp; - PAGE *pagep; - DBT tmp_dbt; - int ret; - - dbp = dbc->dbp; - do { - if ((ret = memp_fget(dbp->mpf, &pgno, 0, &pagep)) != 0) { - (void)__db_pgerr(dbp, pgno); - return (ret); - } - - if (DB_LOGGING(dbc)) { - tmp_dbt.data = pagep; - tmp_dbt.size = dbp->pgsize; - if ((ret = __db_split_log(dbp->dbenv->lg_info, - dbc->txn, &LSN(pagep), 0, DB_SPLITOLD, - dbp->log_fileid, PGNO(pagep), &tmp_dbt, - &LSN(pagep))) != 0) - return (ret); - } - pgno = pagep->next_pgno; - if ((ret = freefunc(dbc, pagep)) != 0) - return (ret); - } while (pgno != PGNO_INVALID); - - return (0); -} - -/* - * __db_addpage -- - * Create a new page and link it onto the next_pgno field of the - * current page. - */ -static int -__db_addpage(dbc, hp, indxp, newfunc) - DBC *dbc; - PAGE **hp; - db_indx_t *indxp; - int (*newfunc) __P((DBC *, u_int32_t, PAGE **)); -{ - DB *dbp; - PAGE *newpage; - int ret; - - dbp = dbc->dbp; - if ((ret = newfunc(dbc, P_DUPLICATE, &newpage)) != 0) - return (ret); - - if (DB_LOGGING(dbc)) { - if ((ret = __db_addpage_log(dbp->dbenv->lg_info, - dbc->txn, &LSN(*hp), 0, dbp->log_fileid, - PGNO(*hp), &LSN(*hp), PGNO(newpage), &LSN(newpage))) != 0) { - return (ret); - } - LSN(newpage) = LSN(*hp); - } - - PREV_PGNO(newpage) = PGNO(*hp); - NEXT_PGNO(*hp) = PGNO(newpage); - - if ((ret = memp_fput(dbp->mpf, *hp, DB_MPOOL_DIRTY)) != 0) - return (ret); - *hp = newpage; - *indxp = 0; - return (0); -} - -/* - * __db_dsearch -- - * Search a set of duplicates for the proper position for a new duplicate. - * - * + pgno is the page number of the page on which to begin searching. - * Since we can continue duplicate searches, it might not be the first - * page. - * - * + If we are continuing a search, then *pp may be non-NULL in which - * case we do not have to retrieve the page. - * - * + If we are continuing a search, then *indxp contains the first - * on pgno of where we should begin the search. - * - * NOTE: if there is no comparison function, then continuing is - * meaningless, and *pp should always be NULL and *indxp will be - * ignored. - * - * 3 return values:: - * - * + pp is the returned page pointer of where this element should go. - * + indxp is the returned index on that page - * + cmpp is the returned final comparison result. - * - * PUBLIC: int __db_dsearch __P((DBC *, - * PUBLIC: int, DBT *, db_pgno_t, db_indx_t *, PAGE **, int *)); - */ -int -__db_dsearch(dbc, is_insert, dbt, pgno, indxp, pp, cmpp) - DBC *dbc; - int is_insert, *cmpp; - DBT *dbt; - db_pgno_t pgno; - db_indx_t *indxp; - PAGE **pp; -{ - DB *dbp; - PAGE *h; - db_indx_t base, indx, lim, save_indx; - db_pgno_t save_pgno; - int ret; - - dbp = dbc->dbp; - - if (dbp->dup_compare == NULL) { - /* - * We may have been given a valid page, but we may not be - * able to use it. The problem is that the application is - * doing a join and we're trying to continue the search, - * but since the items aren't sorted, we can't. Discard - * the page if it's not the one we're going to start with - * anyway. - */ - if (*pp != NULL && (*pp)->pgno != pgno) { - if ((ret = memp_fput(dbp->mpf, *pp, 0)) != 0) - return (ret); - *pp = NULL; - } - - /* - * If no duplicate function is specified, just go to the end - * of the duplicate set. - */ - if (is_insert) { - if ((ret = __db_dend(dbc, pgno, pp)) != 0) - return (ret); - *indxp = NUM_ENT(*pp); - return (0); - } - - /* - * We are looking for a specific duplicate, so do a linear - * search. - */ - if (*pp != NULL) - goto nocmp_started; - for (;;) { - if ((ret = memp_fget(dbp->mpf, &pgno, 0, pp)) != 0) - goto pg_err; -nocmp_started: h = *pp; - - for (*indxp = 0; *indxp < NUM_ENT(h); ++*indxp) { - if ((*cmpp = __bam_cmp(dbp, - dbt, h, *indxp, __bam_defcmp)) != 0) - continue; - /* - * The duplicate may have already been deleted, - * if it's a btree page, in which case we skip - * it. - */ - if (dbp->type == DB_BTREE && - B_DISSET(GET_BKEYDATA(h, *indxp)->type)) - continue; - - return (0); - } - - if ((pgno = h->next_pgno) == PGNO_INVALID) - break; - - if ((ret = memp_fput(dbp->mpf, h, 0)) != 0) - return (ret); - } - *cmpp = 1; /* We didn't succeed... */ - return (0); - } - - /* - * We have a comparison routine, i.e., the duplicates are sorted. - * Walk through the chain of duplicates, checking the last entry - * on each page to decide if it's the page we want to search. - * - * *pp may be non-NULL -- if we were given a valid page (e.g., are - * in mid-search), then use the provided page. - */ - if (*pp != NULL) - goto cmp_started; - for (;;) { - if ((ret = memp_fget(dbp->mpf, &pgno, 0, pp)) != 0) - goto pg_err; -cmp_started: h = *pp; - - if ((pgno = h->next_pgno) == PGNO_INVALID || __bam_cmp(dbp, - dbt, h, h->entries - 1, dbp->dup_compare) <= 0) - break; - /* - * Even when continuing a search, make sure we don't skip - * entries on a new page - */ - *indxp = 0; - - if ((ret = memp_fput(dbp->mpf, h, 0)) != 0) - return (ret); - } - - /* Next, do a binary search on the page. */ - base = F_ISSET(dbc, DBC_CONTINUE) ? *indxp : 0; - for (lim = NUM_ENT(h) - base; lim != 0; lim >>= 1) { - indx = base + (lim >> 1); - if ((*cmpp = __bam_cmp(dbp, - dbt, h, indx, dbp->dup_compare)) == 0) { - *indxp = indx; - - if (dbp->type != DB_BTREE || - !B_DISSET(GET_BKEYDATA(h, *indxp)->type)) - return (0); - goto check_delete; - } - if (*cmpp > 0) { - base = indx + 1; - lim--; - } - } - - /* - * Base references the smallest index larger than the supplied DBT's - * data item, potentially both 0 and NUM_ENT. - */ - *indxp = base; - return (0); - -check_delete: - /* - * The duplicate may have already been deleted, if it's a btree page, - * in which case we wander around, hoping to find an entry that hasn't - * been deleted. First, wander in a forwardly direction. - */ - save_pgno = (*pp)->pgno; - save_indx = *indxp; - for (++*indxp;;) { - for (; *indxp < NUM_ENT(h); ++*indxp) { - if ((*cmpp = __bam_cmp(dbp, - dbt, h, *indxp, dbp->dup_compare)) != 0) - goto check_delete_rev; - - if (!B_DISSET(GET_BKEYDATA(h, *indxp)->type)) - return (0); - } - if ((pgno = h->next_pgno) == PGNO_INVALID) - break; - - if ((ret = memp_fput(dbp->mpf, h, 0)) != 0) - return (ret); - - if ((ret = memp_fget(dbp->mpf, &pgno, 0, pp)) != 0) - goto pg_err; - h = *pp; - - *indxp = 0; - } - -check_delete_rev: - /* Go back to where we started, and wander in a backwardly direction. */ - if (h->pgno != save_pgno) { - if ((ret = memp_fput(dbp->mpf, h, 0)) != 0) - return (ret); - if ((ret = memp_fget(dbp->mpf, &save_pgno, 0, pp)) != 0) - goto pg_err; - h = *pp; - } - - for (;;) { - while (*indxp > 0) { - --*indxp; - if ((*cmpp = __bam_cmp(dbp, - dbt, h, *indxp, dbp->dup_compare)) != 0) - goto check_delete_fail; - - if (!B_DISSET(GET_BKEYDATA(h, *indxp)->type)) - return (0); - } - if ((pgno = h->prev_pgno) == PGNO_INVALID) - break; - - if ((ret = memp_fput(dbp->mpf, h, 0)) != 0) - return (ret); - - if ((ret = memp_fget(dbp->mpf, &pgno, 0, pp)) != 0) - goto pg_err; - h = *pp; - - *indxp = NUM_ENT(h); - } - -check_delete_fail: - *cmpp = 1; /* We didn't succeed... */ - return (0); - -pg_err: __db_pgerr(dbp, pgno); - return (ret); -} diff --git a/db2/db/db_iface.c b/db2/db/db_iface.c deleted file mode 100644 index 4ebf3ba..0000000 --- a/db2/db/db_iface.c +++ /dev/null @@ -1,488 +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_iface.c 10.40 (Sleepycat) 12/19/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#endif - -#include "db_int.h" -#include "db_page.h" -#include "db_auto.h" -#include "db_ext.h" -#include "common_ext.h" - -static int __db_keyempty __P((const DB_ENV *)); -static int __db_rdonly __P((const DB_ENV *, const char *)); -static int __dbt_ferr __P((const DB *, const char *, const DBT *, int)); - -/* - * __db_cdelchk -- - * Common cursor delete argument checking routine. - * - * PUBLIC: int __db_cdelchk __P((const DB *, u_int32_t, int, int)); - */ -int -__db_cdelchk(dbp, flags, isrdonly, isvalid) - const DB *dbp; - u_int32_t flags; - int isrdonly, isvalid; -{ - /* Check for changes to a read-only tree. */ - if (isrdonly) - return (__db_rdonly(dbp->dbenv, "c_del")); - - /* Check for invalid function flags. */ - switch (flags) { - case 0: - break; - default: - return (__db_ferr(dbp->dbenv, "DBcursor->c_del", 0)); - } - - /* - * The cursor must be initialized, return -1 for an invalid cursor, - * otherwise 0. - */ - return (isvalid ? 0 : EINVAL); -} - -/* - * __db_cgetchk -- - * Common cursor get argument checking routine. - * - * PUBLIC: int __db_cgetchk __P((const DB *, DBT *, DBT *, u_int32_t, int)); - */ -int -__db_cgetchk(dbp, key, data, flags, isvalid) - const DB *dbp; - DBT *key, *data; - u_int32_t flags; - int isvalid; -{ - int key_einval, key_flags, ret; - - key_einval = key_flags = 0; - - /* Check for invalid function flags. */ - LF_CLR(DB_RMW); - switch (flags) { - case DB_NEXT_DUP: - if (dbp->type == DB_RECNO) - goto err; - /* FALLTHROUGH */ - case DB_CURRENT: - case DB_FIRST: - case DB_LAST: - case DB_NEXT: - case DB_PREV: - key_flags = 1; - break; - case DB_GET_BOTH: - case DB_SET_RANGE: - key_einval = key_flags = 1; - break; - case DB_SET: - key_einval = 1; - break; - case DB_GET_RECNO: - if (!F_ISSET(dbp, DB_BT_RECNUM)) - goto err; - break; - case DB_SET_RECNO: - if (!F_ISSET(dbp, DB_BT_RECNUM)) - goto err; - key_einval = key_flags = 1; - break; - default: -err: return (__db_ferr(dbp->dbenv, "DBcursor->c_get", 0)); - } - - /* Check for invalid key/data flags. */ - if ((ret = __dbt_ferr(dbp, "key", key, 0)) != 0) - return (ret); - if ((ret = __dbt_ferr(dbp, "data", data, 0)) != 0) - return (ret); - - /* Check for missing keys. */ - if (key_einval && (key->data == NULL || key->size == 0)) - return (__db_keyempty(dbp->dbenv)); - - /* - * The cursor must be initialized for DB_CURRENT, return -1 for an - * invalid cursor, otherwise 0. - */ - return (isvalid || flags != DB_CURRENT ? 0 : EINVAL); -} - -/* - * __db_cputchk -- - * Common cursor put argument checking routine. - * - * PUBLIC: int __db_cputchk __P((const DB *, - * PUBLIC: const DBT *, DBT *, u_int32_t, int, int)); - */ -int -__db_cputchk(dbp, key, data, flags, isrdonly, isvalid) - const DB *dbp; - const DBT *key; - DBT *data; - u_int32_t flags; - int isrdonly, isvalid; -{ - int key_einval, key_flags, ret; - - key_einval = key_flags = 0; - - /* Check for changes to a read-only tree. */ - if (isrdonly) - return (__db_rdonly(dbp->dbenv, "c_put")); - - /* Check for invalid function flags. */ - switch (flags) { - case DB_AFTER: - case DB_BEFORE: - if (dbp->dup_compare != NULL) - goto err; - if (dbp->type == DB_RECNO && !F_ISSET(dbp, DB_RE_RENUMBER)) - goto err; - if (dbp->type != DB_RECNO && !F_ISSET(dbp, DB_AM_DUP)) - goto err; - break; - case DB_CURRENT: - /* - * If there is a comparison function, doing a DB_CURRENT - * must not change the part of the data item that is used - * for the comparison. - */ - break; - case DB_KEYFIRST: - case DB_KEYLAST: - if (dbp->type == DB_RECNO) - goto err; - key_einval = key_flags = 1; - break; - default: -err: return (__db_ferr(dbp->dbenv, "DBcursor->c_put", 0)); - } - - /* Check for invalid key/data flags. */ - if (key_flags && (ret = __dbt_ferr(dbp, "key", key, 0)) != 0) - return (ret); - if ((ret = __dbt_ferr(dbp, "data", data, 0)) != 0) - return (ret); - - /* Check for missing keys. */ - if (key_einval && (key->data == NULL || key->size == 0)) - return (__db_keyempty(dbp->dbenv)); - - /* - * The cursor must be initialized for anything other than DB_KEYFIRST - * and DB_KEYLAST, return -1 for an invalid cursor, otherwise 0. - */ - return (isvalid || - flags == DB_KEYFIRST || flags == DB_KEYLAST ? 0 : EINVAL); -} - -/* - * __db_closechk -- - * DB->close flag check. - * - * PUBLIC: int __db_closechk __P((const DB *, u_int32_t)); - */ -int -__db_closechk(dbp, flags) - const DB *dbp; - u_int32_t flags; -{ - /* Check for invalid function flags. */ - if (flags != 0 && flags != DB_NOSYNC) - return (__db_ferr(dbp->dbenv, "DB->close", 0)); - - return (0); -} - -/* - * __db_delchk -- - * Common delete argument checking routine. - * - * PUBLIC: int __db_delchk __P((const DB *, DBT *, u_int32_t, int)); - */ -int -__db_delchk(dbp, key, flags, isrdonly) - const DB *dbp; - DBT *key; - u_int32_t flags; - int isrdonly; -{ - /* Check for changes to a read-only tree. */ - if (isrdonly) - return (__db_rdonly(dbp->dbenv, "delete")); - - /* Check for invalid function flags. */ - switch (flags) { - case 0: - break; - default: - return (__db_ferr(dbp->dbenv, "DB->del", 0)); - } - - /* Check for missing keys. */ - if (key->data == NULL || key->size == 0) - return (__db_keyempty(dbp->dbenv)); - - return (0); -} - -/* - * __db_getchk -- - * Common get argument checking routine. - * - * PUBLIC: int __db_getchk __P((const DB *, const DBT *, DBT *, u_int32_t)); - */ -int -__db_getchk(dbp, key, data, flags) - const DB *dbp; - const DBT *key; - DBT *data; - u_int32_t flags; -{ - int ret; - - /* Check for invalid function flags. */ - LF_CLR(DB_RMW); - switch (flags) { - case 0: - case DB_GET_BOTH: - break; - case DB_SET_RECNO: - if (!F_ISSET(dbp, DB_BT_RECNUM)) - goto err; - break; - default: -err: return (__db_ferr(dbp->dbenv, "DB->get", 0)); - } - - /* Check for invalid key/data flags. */ - if ((ret = __dbt_ferr(dbp, "key", key, flags == DB_SET_RECNO)) != 0) - return (ret); - if ((ret = __dbt_ferr(dbp, "data", data, 1)) != 0) - return (ret); - - /* Check for missing keys. */ - if (key->data == NULL || key->size == 0) - return (__db_keyempty(dbp->dbenv)); - - return (0); -} - -/* - * __db_joinchk -- - * Common join argument checking routine. - * - * PUBLIC: int __db_joinchk __P((const DB *, u_int32_t)); - */ -int -__db_joinchk(dbp, flags) - const DB *dbp; - u_int32_t flags; -{ - if (flags != 0) - return (__db_ferr(dbp->dbenv, "DB->join", 0)); - - return (0); -} - -/* - * __db_putchk -- - * Common put argument checking routine. - * - * PUBLIC: int __db_putchk - * PUBLIC: __P((const DB *, DBT *, const DBT *, u_int32_t, int, int)); - */ -int -__db_putchk(dbp, key, data, flags, isrdonly, isdup) - const DB *dbp; - DBT *key; - const DBT *data; - u_int32_t flags; - int isrdonly, isdup; -{ - int ret; - - /* Check for changes to a read-only tree. */ - if (isrdonly) - return (__db_rdonly(dbp->dbenv, "put")); - - /* Check for invalid function flags. */ - switch (flags) { - case 0: - case DB_NOOVERWRITE: - break; - case DB_APPEND: - if (dbp->type != DB_RECNO) - goto err; - break; - default: -err: return (__db_ferr(dbp->dbenv, "DB->put", 0)); - } - - /* Check for invalid key/data flags. */ - if ((ret = __dbt_ferr(dbp, "key", key, 0)) != 0) - return (ret); - if ((ret = __dbt_ferr(dbp, "data", data, 0)) != 0) - return (ret); - - /* Check for missing keys. */ - if (key->data == NULL || key->size == 0) - return (__db_keyempty(dbp->dbenv)); - - /* Check for partial puts in the presence of duplicates. */ - if (isdup && F_ISSET(data, DB_DBT_PARTIAL)) { - __db_err(dbp->dbenv, -"a partial put in the presence of duplicates requires a cursor operation"); - return (EINVAL); - } - - return (0); -} - -/* - * __db_statchk -- - * Common stat argument checking routine. - * - * PUBLIC: int __db_statchk __P((const DB *, u_int32_t)); - */ -int -__db_statchk(dbp, flags) - const DB *dbp; - u_int32_t flags; -{ - /* Check for invalid function flags. */ - switch (flags) { - case 0: - break; - case DB_RECORDCOUNT: - if (dbp->type == DB_RECNO) - break; - if (dbp->type == DB_BTREE && F_ISSET(dbp, DB_BT_RECNUM)) - break; - goto err; - default: -err: return (__db_ferr(dbp->dbenv, "DB->stat", 0)); - } - - return (0); -} - -/* - * __db_syncchk -- - * Common sync argument checking routine. - * - * PUBLIC: int __db_syncchk __P((const DB *, u_int32_t)); - */ -int -__db_syncchk(dbp, flags) - const DB *dbp; - u_int32_t flags; -{ - /* Check for invalid function flags. */ - switch (flags) { - case 0: - break; - default: - return (__db_ferr(dbp->dbenv, "DB->sync", 0)); - } - - return (0); -} - -/* - * __dbt_ferr -- - * Check a DBT for flag errors. - */ -static int -__dbt_ferr(dbp, name, dbt, check_thread) - const DB *dbp; - const char *name; - const DBT *dbt; - int check_thread; -{ - int ret; - - /* - * Check for invalid DBT flags. We allow any of the flags to be - * specified to any DB or DBcursor call so that applications can - * set DB_DBT_MALLOC when retrieving a data item from a secondary - * database and then specify that same DBT as a key to a primary - * database, without having to clear flags. - */ - if ((ret = __db_fchk(dbp->dbenv, name, dbt->flags, - DB_DBT_MALLOC | DB_DBT_USERMEM | DB_DBT_PARTIAL)) != 0) - return (ret); - if ((ret = __db_fcchk(dbp->dbenv, name, - dbt->flags, DB_DBT_MALLOC, DB_DBT_USERMEM)) != 0) - return (ret); - - if (check_thread && F_ISSET(dbp, DB_AM_THREAD) && - !F_ISSET(dbt, DB_DBT_MALLOC | DB_DBT_USERMEM)) { - __db_err(dbp->dbenv, - "missing flag thread flag for %s DBT", name); - return (EINVAL); - } - return (0); -} - -/* - * __db_eopnotsup -- - * Common operation not supported message. - * - * PUBLIC: int __db_eopnotsup __P((const DB_ENV *)); - */ -int -__db_eopnotsup(dbenv) - const DB_ENV *dbenv; -{ - __db_err(dbenv, "operation not supported"); -#ifdef EOPNOTSUPP - return (EOPNOTSUPP); -#else - return (EINVAL); -#endif -} - -/* - * __db_keyempty -- - * Common missing or empty key value message. - */ -static int -__db_keyempty(dbenv) - const DB_ENV *dbenv; -{ - __db_err(dbenv, "missing or empty key value specified"); - return (EINVAL); -} - -/* - * __db_rdonly -- - * Common readonly message. - */ -static int -__db_rdonly(dbenv, name) - const DB_ENV *dbenv; - const char *name; -{ - __db_err(dbenv, "%s: attempt to modify a read-only tree", name); - return (EACCES); -} diff --git a/db2/db/db_join.c b/db2/db/db_join.c deleted file mode 100644 index a4051c2..0000000 --- a/db2/db/db_join.c +++ /dev/null @@ -1,271 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1998 - * Sleepycat Software. All rights reserved. - */ - -#include "config.h" - -#ifndef lint -static const char sccsid[] = "@(#)db_join.c 10.10 (Sleepycat) 10/9/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <string.h> -#endif - -#include "db_int.h" -#include "db_page.h" -#include "db_join.h" -#include "db_am.h" -#include "common_ext.h" - -static int __db_join_close __P((DBC *)); -static int __db_join_del __P((DBC *, u_int32_t)); -static int __db_join_get __P((DBC *, DBT *, DBT *, u_int32_t)); -static int __db_join_put __P((DBC *, DBT *, DBT *, u_int32_t)); - -/* - * This is the duplicate-assisted join functionality. Right now we're - * going to write it such that we return one item at a time, although - * I think we may need to optimize it to return them all at once. - * It should be easier to get it working this way, and I believe that - * changing it should be fairly straightforward. - * - * XXX - * Right now we do not maintain the number of duplicates so we do - * not optimize the join. If the caller does, then best performance - * will be achieved by putting the cursor with the smallest cardinality - * first. - * - * The first cursor moves sequentially through the duplicate set while - * the others search explicitly for the duplicate in question. - * - */ - -/* - * __db_join -- - * This is the interface to the duplicate-assisted join functionality. - * In the same way that cursors mark a position in a database, a cursor - * can mark a position in a join. While most cursors are created by the - * cursor method of a DB, join cursors are created through an explicit - * call to DB->join. - * - * The curslist is an array of existing, intialized cursors and primary - * is the DB of the primary file. The data item that joins all the - * cursors in the curslist is used as the key into the primary and that - * key and data are returned. When no more items are left in the join - * set, the c_next operation off the join cursor will return DB_NOTFOUND. - * - * PUBLIC: int __db_join __P((DB *, DBC **, u_int32_t, DBC **)); - */ -int -__db_join(primary, curslist, flags, dbcp) - DB *primary; - DBC **curslist, **dbcp; - u_int32_t flags; -{ - DBC *dbc; - JOIN_CURSOR *jc; - int i, ret; - - DB_PANIC_CHECK(primary); - - if ((ret = __db_joinchk(primary, flags)) != 0) - return (ret); - - if (curslist == NULL || curslist[0] == NULL) - return (EINVAL); - - dbc = NULL; - jc = NULL; - - if ((ret = __os_calloc(1, sizeof(DBC), &dbc)) != 0) - goto err; - - if ((ret = __os_calloc(1, sizeof(JOIN_CURSOR), &jc)) != 0) - goto err; - - if ((ret = __os_malloc(256, NULL, &jc->j_key.data)) != 0) - goto err; - jc->j_key.ulen = 256; - F_SET(&jc->j_key, DB_DBT_USERMEM); - - for (jc->j_curslist = curslist; - *jc->j_curslist != NULL; jc->j_curslist++) - ; - if ((ret = __os_calloc((jc->j_curslist - curslist + 1), - sizeof(DBC *), &jc->j_curslist)) != 0) - goto err; - for (i = 0; curslist[i] != NULL; i++) { - if (i != 0) - F_SET(curslist[i], DBC_KEYSET); - jc->j_curslist[i] = curslist[i]; - } - - dbc->c_close = __db_join_close; - dbc->c_del = __db_join_del; - dbc->c_get = __db_join_get; - dbc->c_put = __db_join_put; - dbc->internal = jc; - dbc->dbp = primary; - jc->j_init = 1; - jc->j_primary = primary; - - *dbcp = dbc; - - return (0); - -err: if (jc != NULL) { - if (jc->j_curslist != NULL) - __os_free(jc->j_curslist, - (jc->j_curslist - curslist + 1) * sizeof(DBC *)); - __os_free(jc, sizeof(JOIN_CURSOR)); - } - if (dbc != NULL) - __os_free(dbc, sizeof(DBC)); - return (ret); -} - -static int -__db_join_put(dbc, key, data, flags) - DBC *dbc; - DBT *key; - DBT *data; - u_int32_t flags; -{ - DB_PANIC_CHECK(dbc->dbp); - - COMPQUIET(key, NULL); - COMPQUIET(data, NULL); - COMPQUIET(flags, 0); - return (EINVAL); -} - -static int -__db_join_del(dbc, flags) - DBC *dbc; - u_int32_t flags; -{ - DB_PANIC_CHECK(dbc->dbp); - - COMPQUIET(flags, 0); - return (EINVAL); -} - -static int -__db_join_get(dbc, key, data, flags) - DBC *dbc; - DBT *key, *data; - u_int32_t flags; -{ - DB *dbp; - DBC **cpp; - JOIN_CURSOR *jc; - int ret; - u_int32_t operation; - - dbp = dbc->dbp; - - DB_PANIC_CHECK(dbp); - - operation = LF_ISSET(DB_OPFLAGS_MASK); - if (operation != 0 && operation != DB_JOIN_ITEM) - return (__db_ferr(dbp->dbenv, "DBcursor->c_get", 0)); - - LF_CLR(DB_OPFLAGS_MASK); - if ((ret = - __db_fchk(dbp->dbenv, "DBcursor->c_get", flags, DB_RMW)) != 0) - return (ret); - - jc = (JOIN_CURSOR *)dbc->internal; -retry: - ret = jc->j_curslist[0]->c_get(jc->j_curslist[0], - &jc->j_key, key, jc->j_init ? DB_CURRENT : DB_NEXT_DUP); - - if (ret == ENOMEM) { - jc->j_key.ulen <<= 1; - if ((ret = __os_realloc(&jc->j_key.data, jc->j_key.ulen)) != 0) - return (ret); - goto retry; - } - if (ret != 0) - return (ret); - - jc->j_init = 0; - do { - /* - * We have the first element; now look for it in the - * other cursors. - */ - for (cpp = jc->j_curslist + 1; *cpp != NULL; cpp++) { -retry2: if ((ret = ((*cpp)->c_get)(*cpp, - &jc->j_key, key, DB_GET_BOTH)) == DB_NOTFOUND) - break; - if (ret == ENOMEM) { - jc->j_key.ulen <<= 1; - if ((ret = __os_realloc(&jc->j_key.data, - jc->j_key.ulen)) != 0) - return (ret); - goto retry2; - } - if (F_ISSET(*cpp, DBC_KEYSET)) { - F_CLR(*cpp, DBC_KEYSET); - F_SET(*cpp, DBC_CONTINUE); - } - } - - /* - * If we got out of here with ret != 0, then we failed to - * find the duplicate in one of the files, so we go on to - * the next item in the outermost relation. If ret was - * equal to 0, then we've got something to return. - */ - if (ret == 0) - break; - } while ((ret = jc->j_curslist[0]->c_get(jc->j_curslist[0], - &jc->j_key, key, DB_NEXT_DUP)) == 0); - - /* - * If ret != 0 here, we've exhausted the first file. Otherwise, - * key and data are set and we need to do the lookup on the - * primary. - */ - if (ret != 0) - return (ret); - - if (operation == DB_JOIN_ITEM) - return (0); - else - return ((jc->j_primary->get)(jc->j_primary, - jc->j_curslist[0]->txn, key, data, 0)); -} - -static int -__db_join_close(dbc) - DBC *dbc; -{ - JOIN_CURSOR *jc; - int i; - - DB_PANIC_CHECK(dbc->dbp); - - jc = (JOIN_CURSOR *)dbc->internal; - - /* - * Clear the optimization flag in the cursors. - */ - for (i = 0; jc->j_curslist[i] != NULL; i++) - F_CLR(jc->j_curslist[i], DBC_CONTINUE | DBC_KEYSET); - - __os_free(jc->j_curslist, 0); - __os_free(jc->j_key.data, jc->j_key.ulen); - __os_free(jc, sizeof(JOIN_CURSOR)); - __os_free(dbc, sizeof(DBC)); - - return (0); -} diff --git a/db2/db/db_overflow.c b/db2/db/db_overflow.c deleted file mode 100644 index 0efcc9d..0000000 --- a/db2/db/db_overflow.c +++ /dev/null @@ -1,407 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994, 1995, 1996 - * Keith Bostic. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994, 1995 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * 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_overflow.c 10.21 (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 "db_page.h" -#include "db_am.h" -#include "common_ext.h" - -/* - * Big key/data code. - * - * Big key and data entries are stored on linked lists of pages. The initial - * reference is a structure with the total length of the item and the page - * number where it begins. Each entry in the linked list contains a pointer - * to the next page of data, and so on. - */ - -/* - * __db_goff -- - * Get an offpage item. - * - * PUBLIC: int __db_goff __P((DB *, DBT *, - * PUBLIC: u_int32_t, db_pgno_t, void **, u_int32_t *)); - */ -int -__db_goff(dbp, dbt, tlen, pgno, bpp, bpsz) - DB *dbp; - DBT *dbt; - u_int32_t tlen; - db_pgno_t pgno; - void **bpp; - u_int32_t *bpsz; -{ - PAGE *h; - db_indx_t bytes; - u_int32_t curoff, needed, start; - u_int8_t *p, *src; - int ret; - - /* - * Check if the buffer is big enough; if it is not and we are - * allowed to malloc space, then we'll malloc it. If we are - * not (DB_DBT_USERMEM), then we'll set the dbt and return - * appropriately. - */ - if (F_ISSET(dbt, DB_DBT_PARTIAL)) { - start = dbt->doff; - needed = dbt->dlen; - } else { - start = 0; - needed = tlen; - } - - /* Allocate any necessary memory. */ - if (F_ISSET(dbt, DB_DBT_USERMEM)) { - if (needed > dbt->ulen) { - dbt->size = needed; - return (ENOMEM); - } - } else if (F_ISSET(dbt, DB_DBT_MALLOC)) { - if ((ret = - __os_malloc(needed, dbp->db_malloc, &dbt->data)) != 0) - return (ret); - } else if (*bpsz == 0 || *bpsz < needed) { - if ((ret = __os_realloc(bpp, needed)) != 0) - return (ret); - *bpsz = needed; - dbt->data = *bpp; - } else - dbt->data = *bpp; - - /* - * Step through the linked list of pages, copying the data on each - * one into the buffer. Never copy more than the total data length. - */ - dbt->size = needed; - for (curoff = 0, p = dbt->data; pgno != P_INVALID && needed > 0;) { - if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0) { - (void)__db_pgerr(dbp, pgno); - return (ret); - } - /* Check if we need any bytes from this page. */ - if (curoff + OV_LEN(h) >= start) { - src = (u_int8_t *)h + P_OVERHEAD; - bytes = OV_LEN(h); - if (start > curoff) { - src += start - curoff; - bytes -= start - curoff; - } - if (bytes > needed) - bytes = needed; - memcpy(p, src, bytes); - p += bytes; - needed -= bytes; - } - curoff += OV_LEN(h); - pgno = h->next_pgno; - memp_fput(dbp->mpf, h, 0); - } - return (0); -} - -/* - * __db_poff -- - * Put an offpage item. - * - * PUBLIC: int __db_poff __P((DBC *, const DBT *, db_pgno_t *, - * PUBLIC: int (*)(DBC *, u_int32_t, PAGE **))); - */ -int -__db_poff(dbc, dbt, pgnop, newfunc) - DBC *dbc; - const DBT *dbt; - db_pgno_t *pgnop; - int (*newfunc) __P((DBC *, u_int32_t, PAGE **)); -{ - DB *dbp; - PAGE *pagep, *lastp; - DB_LSN new_lsn, null_lsn; - DBT tmp_dbt; - db_indx_t pagespace; - u_int32_t sz; - u_int8_t *p; - int ret; - - /* - * Allocate pages and copy the key/data item into them. Calculate the - * number of bytes we get for pages we fill completely with a single - * item. - */ - dbp = dbc->dbp; - pagespace = P_MAXSPACE(dbp->pgsize); - - lastp = NULL; - for (p = dbt->data, - sz = dbt->size; sz > 0; p += pagespace, sz -= pagespace) { - /* - * Reduce pagespace so we terminate the loop correctly and - * don't copy too much data. - */ - if (sz < pagespace) - pagespace = sz; - - /* - * Allocate and initialize a new page and copy all or part of - * the item onto the page. If sz is less than pagespace, we - * have a partial record. - */ - if ((ret = newfunc(dbc, P_OVERFLOW, &pagep)) != 0) - return (ret); - if (DB_LOGGING(dbc)) { - tmp_dbt.data = p; - tmp_dbt.size = pagespace; - ZERO_LSN(null_lsn); - if ((ret = __db_big_log(dbp->dbenv->lg_info, dbc->txn, - &new_lsn, 0, DB_ADD_BIG, dbp->log_fileid, - PGNO(pagep), lastp ? PGNO(lastp) : PGNO_INVALID, - PGNO_INVALID, &tmp_dbt, &LSN(pagep), - lastp == NULL ? &null_lsn : &LSN(lastp), - &null_lsn)) != 0) - return (ret); - - /* Move lsn onto page. */ - if (lastp) - LSN(lastp) = new_lsn; - LSN(pagep) = new_lsn; - } - - P_INIT(pagep, dbp->pgsize, - PGNO(pagep), PGNO_INVALID, PGNO_INVALID, 0, P_OVERFLOW); - OV_LEN(pagep) = pagespace; - OV_REF(pagep) = 1; - memcpy((u_int8_t *)pagep + P_OVERHEAD, p, pagespace); - - /* - * If this is the first entry, update the user's info. - * Otherwise, update the entry on the last page filled - * in and release that page. - */ - if (lastp == NULL) - *pgnop = PGNO(pagep); - else { - lastp->next_pgno = PGNO(pagep); - pagep->prev_pgno = PGNO(lastp); - (void)memp_fput(dbp->mpf, lastp, DB_MPOOL_DIRTY); - } - lastp = pagep; - } - (void)memp_fput(dbp->mpf, lastp, DB_MPOOL_DIRTY); - return (0); -} - -/* - * __db_ovref -- - * Increment/decrement the reference count on an overflow page. - * - * PUBLIC: int __db_ovref __P((DBC *, db_pgno_t, int32_t)); - */ -int -__db_ovref(dbc, pgno, adjust) - DBC *dbc; - db_pgno_t pgno; - int32_t adjust; -{ - DB *dbp; - PAGE *h; - int ret; - - dbp = dbc->dbp; - if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0) { - (void)__db_pgerr(dbp, pgno); - return (ret); - } - - if (DB_LOGGING(dbc)) - if ((ret = __db_ovref_log(dbp->dbenv->lg_info, dbc->txn, - &LSN(h), 0, dbp->log_fileid, h->pgno, adjust, - &LSN(h))) != 0) - return (ret); - OV_REF(h) += adjust; - - (void)memp_fput(dbp->mpf, h, DB_MPOOL_DIRTY); - return (0); -} - -/* - * __db_doff -- - * Delete an offpage chain of overflow pages. - * - * PUBLIC: int __db_doff __P((DBC *, db_pgno_t, int (*)(DBC *, PAGE *))); - */ -int -__db_doff(dbc, pgno, freefunc) - DBC *dbc; - db_pgno_t pgno; - int (*freefunc) __P((DBC *, PAGE *)); -{ - DB *dbp; - PAGE *pagep; - DB_LSN null_lsn; - DBT tmp_dbt; - int ret; - - dbp = dbc->dbp; - do { - if ((ret = memp_fget(dbp->mpf, &pgno, 0, &pagep)) != 0) { - (void)__db_pgerr(dbp, pgno); - return (ret); - } - - /* - * If it's an overflow page and it's referenced by more than - * one key/data item, decrement the reference count and return. - */ - if (TYPE(pagep) == P_OVERFLOW && OV_REF(pagep) > 1) { - (void)memp_fput(dbp->mpf, pagep, 0); - return (__db_ovref(dbc, pgno, -1)); - } - - if (DB_LOGGING(dbc)) { - tmp_dbt.data = (u_int8_t *)pagep + P_OVERHEAD; - tmp_dbt.size = OV_LEN(pagep); - ZERO_LSN(null_lsn); - if ((ret = __db_big_log(dbp->dbenv->lg_info, dbc->txn, - &LSN(pagep), 0, DB_REM_BIG, dbp->log_fileid, - PGNO(pagep), PREV_PGNO(pagep), NEXT_PGNO(pagep), - &tmp_dbt, &LSN(pagep), &null_lsn, &null_lsn)) != 0) - return (ret); - } - pgno = pagep->next_pgno; - if ((ret = freefunc(dbc, pagep)) != 0) - return (ret); - } while (pgno != PGNO_INVALID); - - return (0); -} - -/* - * __db_moff -- - * Match on overflow pages. - * - * Given a starting page number and a key, return <0, 0, >0 to indicate if the - * key on the page is less than, equal to or greater than the key specified. - * We optimize this by doing chunk at a time comparison unless the user has - * specified a comparison function. In this case, we need to materialize - * the entire object and call their comparison routine. - * - * PUBLIC: int __db_moff __P((DB *, const DBT *, db_pgno_t, u_int32_t, - * PUBLIC: int (*)(const DBT *, const DBT *), int *)); - */ -int -__db_moff(dbp, dbt, pgno, tlen, cmpfunc, cmpp) - DB *dbp; - const DBT *dbt; - db_pgno_t pgno; - u_int32_t tlen; - int (*cmpfunc) __P((const DBT *, const DBT *)), *cmpp; -{ - PAGE *pagep; - DBT local_dbt; - void *buf; - u_int32_t bufsize, cmp_bytes, key_left; - u_int8_t *p1, *p2; - int ret; - - /* - * If there is a user-specified comparison function, build a - * contiguous copy of the key, and call it. - */ - if (cmpfunc != NULL) { - memset(&local_dbt, 0, sizeof(local_dbt)); - buf = NULL; - bufsize = 0; - - if ((ret = __db_goff(dbp, - &local_dbt, tlen, pgno, &buf, &bufsize)) != 0) - return (ret); - *cmpp = cmpfunc(&local_dbt, dbt); - __os_free(buf, bufsize); - return (0); - } - - /* While there are both keys to compare. */ - for (*cmpp = 0, p1 = dbt->data, - key_left = dbt->size; key_left > 0 && pgno != PGNO_INVALID;) { - if ((ret = memp_fget(dbp->mpf, &pgno, 0, &pagep)) != 0) - return (ret); - - cmp_bytes = OV_LEN(pagep) < key_left ? OV_LEN(pagep) : key_left; - key_left -= cmp_bytes; - for (p2 = - (u_int8_t *)pagep + P_OVERHEAD; cmp_bytes-- > 0; ++p1, ++p2) - if (*p1 != *p2) { - *cmpp = (long)*p1 - (long)*p2; - break; - } - pgno = NEXT_PGNO(pagep); - if ((ret = memp_fput(dbp->mpf, pagep, 0)) != 0) - return (ret); - if (*cmpp != 0) - return (0); - } - if (key_left > 0) /* DBT is longer than page key. */ - *cmpp = -1; - else if (pgno != PGNO_INVALID) /* DBT is shorter than page key. */ - *cmpp = 1; - else - *cmpp = 0; - - return (0); -} diff --git a/db2/db/db_pr.c b/db2/db/db_pr.c deleted file mode 100644 index 7f4364c..0000000 --- a/db2/db/db_pr.c +++ /dev/null @@ -1,831 +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_pr.c 10.40 (Sleepycat) 11/22/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 "db_page.h" -#include "btree.h" -#include "hash.h" -#include "db_am.h" - -static void __db_proff __P((void *)); -static void __db_psize __P((DB_MPOOLFILE *)); - -/* - * __db_loadme -- - * Force loading of this file. - * - * PUBLIC: void __db_loadme __P((void)); - */ -void -__db_loadme() -{ - getpid(); -} - -static FILE *set_fp; - -/* - * 64K is the maximum page size, so by default we check for offsets - * larger than that, and, where possible, we refine the test. - */ -#define PSIZE_BOUNDARY (64 * 1024 + 1) -static size_t set_psize = PSIZE_BOUNDARY; - -/* - * __db_prinit -- - * Initialize tree printing routines. - * - * PUBLIC: FILE *__db_prinit __P((FILE *)); - */ -FILE * -__db_prinit(fp) - FILE *fp; -{ - if (set_fp == NULL) - set_fp = fp == NULL ? stdout : fp; - return (set_fp); -} - -/* - * __db_dump -- - * Dump the tree to a file. - * - * PUBLIC: int __db_dump __P((DB *, char *, int)); - */ -int -__db_dump(dbp, name, all) - DB *dbp; - char *name; - int all; -{ - FILE *fp, *save_fp; - - COMPQUIET(save_fp, NULL); - - if (set_psize == PSIZE_BOUNDARY) - __db_psize(dbp->mpf); - - if (name != NULL) { - if ((fp = fopen(name, "w")) == NULL) - return (errno); - save_fp = set_fp; - set_fp = fp; - } else - fp = __db_prinit(NULL); - - (void)__db_prdb(dbp); - if (dbp->type == DB_HASH) - (void)__db_prhash(dbp); - else - (void)__db_prbtree(dbp); - fprintf(fp, "%s\n", DB_LINE); - __db_prtree(dbp->mpf, all); - - if (name != NULL) { - (void)fclose(fp); - set_fp = save_fp; - } - return (0); -} - -/* - * __db_prdb -- - * Print out the DB structure information. - * - * PUBLIC: int __db_prdb __P((DB *)); - */ -int -__db_prdb(dbp) - DB *dbp; -{ - static const FN fn[] = { - { DB_AM_DUP, "duplicates" }, - { DB_AM_INMEM, "in-memory" }, - { DB_AM_LOCKING, "locking" }, - { DB_AM_LOGGING, "logging" }, - { DB_AM_MLOCAL, "local mpool" }, - { DB_AM_PGDEF, "default page size" }, - { DB_AM_RDONLY, "read-only" }, - { DB_AM_SWAP, "needswap" }, - { DB_AM_THREAD, "thread" }, - { DB_BT_RECNUM, "btree:recnum" }, - { DB_DBM_ERROR, "dbm/ndbm error" }, - { DB_RE_DELIMITER, "recno:delimiter" }, - { DB_RE_FIXEDLEN, "recno:fixed-length" }, - { DB_RE_PAD, "recno:pad" }, - { DB_RE_RENUMBER, "recno:renumber" }, - { DB_RE_SNAPSHOT, "recno:snapshot" }, - { 0 }, - }; - FILE *fp; - const char *t; - - fp = __db_prinit(NULL); - - switch (dbp->type) { - case DB_BTREE: - t = "btree"; - break; - case DB_HASH: - t = "hash"; - break; - case DB_RECNO: - t = "recno"; - break; - default: - t = "UNKNOWN"; - break; - } - - fprintf(fp, "%s ", t); - __db_prflags(dbp->flags, fn, fp); - fprintf(fp, "\n"); - - return (0); -} - -/* - * __db_prbtree -- - * Print out the btree internal information. - * - * PUBLIC: int __db_prbtree __P((DB *)); - */ -int -__db_prbtree(dbp) - DB *dbp; -{ - static const FN mfn[] = { - { BTM_DUP, "duplicates" }, - { BTM_RECNO, "recno" }, - { BTM_RECNUM, "btree:recnum" }, - { BTM_FIXEDLEN, "recno:fixed-length" }, - { BTM_RENUMBER, "recno:renumber" }, - { 0 }, - }; - DBC *dbc; - BTMETA *mp; - BTREE *t; - FILE *fp; - PAGE *h; - RECNO *rp; - db_pgno_t i; - int cnt, ret; - const char *sep; - - t = dbp->internal; - fp = __db_prinit(NULL); - if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0) - return (ret); - - (void)fprintf(fp, "%s\nOn-page metadata:\n", DB_LINE); - - i = PGNO_METADATA; - if ((ret = memp_fget(dbp->mpf, &i, 0, (PAGE **)&mp)) != 0) { - (void)dbc->c_close(dbc); - return (ret); - } - - fprintf(fp, "lsn.file: %lu lsn.offset: %lu\n", - (u_long)LSN(mp).file, (u_long)LSN(mp).offset); - (void)fprintf(fp, "magic %#lx\n", (u_long)mp->magic); - (void)fprintf(fp, "version %#lx\n", (u_long)mp->version); - (void)fprintf(fp, "pagesize %lu\n", (u_long)mp->pagesize); - (void)fprintf(fp, "maxkey: %lu minkey: %lu\n", - (u_long)mp->maxkey, (u_long)mp->minkey); - - (void)fprintf(fp, "free list: %lu", (u_long)mp->free); - for (i = mp->free, cnt = 0, sep = ", "; i != PGNO_INVALID;) { - if ((ret = memp_fget(dbp->mpf, &i, 0, &h)) != 0) - return (ret); - i = h->next_pgno; - (void)memp_fput(dbp->mpf, h, 0); - (void)fprintf(fp, "%s%lu", sep, (u_long)i); - if (++cnt % 10 == 0) { - (void)fprintf(fp, "\n"); - cnt = 0; - sep = ""; - } else - sep = ", "; - } - (void)fprintf(fp, "\n"); - - (void)fprintf(fp, "flags %#lx", (u_long)mp->flags); - __db_prflags(mp->flags, mfn, fp); - (void)fprintf(fp, "\n"); - (void)memp_fput(dbp->mpf, mp, 0); - - (void)fprintf(fp, "%s\nDB_INFO:\n", DB_LINE); - (void)fprintf(fp, "bt_maxkey: %lu bt_minkey: %lu\n", - (u_long)t->bt_maxkey, (u_long)t->bt_minkey); - (void)fprintf(fp, "bt_compare: %#lx bt_prefix: %#lx\n", - (u_long)t->bt_compare, (u_long)t->bt_prefix); - if ((rp = t->recno) != NULL) { - (void)fprintf(fp, - "re_delim: %#lx re_pad: %#lx re_len: %lu re_source: %s\n", - (u_long)rp->re_delim, (u_long)rp->re_pad, - (u_long)rp->re_len, - rp->re_source == NULL ? "" : rp->re_source); - (void)fprintf(fp, - "cmap: %#lx smap: %#lx emap: %#lx msize: %lu\n", - (u_long)rp->re_cmap, (u_long)rp->re_smap, - (u_long)rp->re_emap, (u_long)rp->re_msize); - } - (void)fprintf(fp, "ovflsize: %lu\n", (u_long)t->bt_ovflsize); - (void)fflush(fp); - return (dbc->c_close(dbc)); -} - -/* - * __db_prhash -- - * Print out the hash internal information. - * - * PUBLIC: int __db_prhash __P((DB *)); - */ -int -__db_prhash(dbp) - DB *dbp; -{ - FILE *fp; - DBC *dbc; - HASH_CURSOR *hcp; - int i, put_page, ret; - db_pgno_t pgno; - - fp = __db_prinit(NULL); - if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0) - return (ret); - hcp = (HASH_CURSOR *)dbc->internal; - - /* - * In this case, hcp->hdr will never be null, if we decide - * to pass dbc's to this routine instead, then it could be. - */ - if (hcp->hdr == NULL) { - pgno = PGNO_METADATA; - if ((ret = memp_fget(dbp->mpf, &pgno, 0, &hcp->hdr)) != 0) - return (ret); - put_page = 1; - } else - put_page = 0; - - fprintf(fp, "\tmagic %#lx\n", (u_long)hcp->hdr->magic); - fprintf(fp, "\tversion %lu\n", (u_long)hcp->hdr->version); - fprintf(fp, "\tpagesize %lu\n", (u_long)hcp->hdr->pagesize); - fprintf(fp, "\tovfl_point %lu\n", (u_long)hcp->hdr->ovfl_point); - fprintf(fp, "\tlast_freed %lu\n", (u_long)hcp->hdr->last_freed); - fprintf(fp, "\tmax_bucket %lu\n", (u_long)hcp->hdr->max_bucket); - fprintf(fp, "\thigh_mask %#lx\n", (u_long)hcp->hdr->high_mask); - fprintf(fp, "\tlow_mask %#lx\n", (u_long)hcp->hdr->low_mask); - fprintf(fp, "\tffactor %lu\n", (u_long)hcp->hdr->ffactor); - fprintf(fp, "\tnelem %lu\n", (u_long)hcp->hdr->nelem); - fprintf(fp, "\th_charkey %#lx\n", (u_long)hcp->hdr->h_charkey); - - for (i = 0; i < NCACHED; i++) - fprintf(fp, "%lu ", (u_long)hcp->hdr->spares[i]); - fprintf(fp, "\n"); - - (void)fflush(fp); - if (put_page) { - (void)memp_fput(dbp->mpf, (PAGE *)hcp->hdr, 0); - hcp->hdr = NULL; - } - return (dbc->c_close(dbc)); -} - -/* - * __db_prtree -- - * Print out the entire tree. - * - * PUBLIC: int __db_prtree __P((DB_MPOOLFILE *, int)); - */ -int -__db_prtree(mpf, all) - DB_MPOOLFILE *mpf; - int all; -{ - PAGE *h; - db_pgno_t i; - - if (set_psize == PSIZE_BOUNDARY) - __db_psize(mpf); - - for (i = PGNO_ROOT;; ++i) { - if (memp_fget(mpf, &i, 0, &h) != 0) - break; - (void)__db_prpage(h, all); - (void)memp_fput(mpf, h, 0); - } - (void)fflush(__db_prinit(NULL)); - return (0); -} - -/* - * __db_prnpage - * -- Print out a specific page. - * - * PUBLIC: int __db_prnpage __P((DB_MPOOLFILE *, db_pgno_t)); - */ -int -__db_prnpage(mpf, pgno) - DB_MPOOLFILE *mpf; - db_pgno_t pgno; -{ - PAGE *h; - int ret; - - if (set_psize == PSIZE_BOUNDARY) - __db_psize(mpf); - - if ((ret = memp_fget(mpf, &pgno, 0, &h)) != 0) - return (ret); - - ret = __db_prpage(h, 1); - (void)fflush(__db_prinit(NULL)); - - (void)memp_fput(mpf, h, 0); - return (ret); -} - -/* - * __db_prpage - * -- Print out a page. - * - * PUBLIC: int __db_prpage __P((PAGE *, int)); - */ -int -__db_prpage(h, all) - PAGE *h; - int all; -{ - BINTERNAL *bi; - BKEYDATA *bk; - HOFFPAGE a_hkd; - FILE *fp; - RINTERNAL *ri; - db_indx_t dlen, len, i; - db_pgno_t pgno; - int deleted, ret; - const char *s; - u_int8_t *ep, *hk, *p; - void *sp; - - fp = __db_prinit(NULL); - - switch (TYPE(h)) { - case P_DUPLICATE: - s = "duplicate"; - break; - case P_HASH: - s = "hash"; - break; - case P_IBTREE: - s = "btree internal"; - break; - case P_INVALID: - s = "invalid"; - break; - case P_IRECNO: - s = "recno internal"; - break; - case P_LBTREE: - s = "btree leaf"; - break; - case P_LRECNO: - s = "recno leaf"; - break; - case P_OVERFLOW: - s = "overflow"; - break; - default: - fprintf(fp, "ILLEGAL PAGE TYPE: page: %lu type: %lu\n", - (u_long)h->pgno, (u_long)TYPE(h)); - return (1); - } - fprintf(fp, "page %4lu: (%s)\n", (u_long)h->pgno, s); - fprintf(fp, " lsn.file: %lu lsn.offset: %lu", - (u_long)LSN(h).file, (u_long)LSN(h).offset); - if (TYPE(h) == P_IBTREE || TYPE(h) == P_IRECNO || - (TYPE(h) == P_LRECNO && h->pgno == PGNO_ROOT)) - fprintf(fp, " total records: %4lu", (u_long)RE_NREC(h)); - fprintf(fp, "\n"); - if (TYPE(h) != P_IBTREE && TYPE(h) != P_IRECNO) - fprintf(fp, " prev: %4lu next: %4lu", - (u_long)PREV_PGNO(h), (u_long)NEXT_PGNO(h)); - if (TYPE(h) == P_IBTREE || TYPE(h) == P_LBTREE) - fprintf(fp, " level: %2lu", (u_long)h->level); - if (TYPE(h) == P_OVERFLOW) { - fprintf(fp, " ref cnt: %4lu ", (u_long)OV_REF(h)); - __db_pr((u_int8_t *)h + P_OVERHEAD, OV_LEN(h)); - return (0); - } - fprintf(fp, " entries: %4lu", (u_long)NUM_ENT(h)); - fprintf(fp, " offset: %4lu\n", (u_long)HOFFSET(h)); - - if (!all || TYPE(h) == P_INVALID) - return (0); - - ret = 0; - for (i = 0; i < NUM_ENT(h); i++) { - if (P_ENTRY(h, i) - (u_int8_t *)h < P_OVERHEAD || - (size_t)(P_ENTRY(h, i) - (u_int8_t *)h) >= set_psize) { - fprintf(fp, - "ILLEGAL PAGE OFFSET: indx: %lu of %lu\n", - (u_long)i, (u_long)h->inp[i]); - ret = EINVAL; - continue; - } - deleted = 0; - switch (TYPE(h)) { - case P_HASH: - case P_IBTREE: - case P_IRECNO: - sp = P_ENTRY(h, i); - break; - case P_LBTREE: - sp = P_ENTRY(h, i); - deleted = i % 2 == 0 && - B_DISSET(GET_BKEYDATA(h, i + O_INDX)->type); - break; - case P_LRECNO: - case P_DUPLICATE: - sp = P_ENTRY(h, i); - deleted = B_DISSET(GET_BKEYDATA(h, i)->type); - break; - default: - fprintf(fp, - "ILLEGAL PAGE ITEM: %lu\n", (u_long)TYPE(h)); - ret = EINVAL; - continue; - } - fprintf(fp, " %s[%03lu] %4lu ", - deleted ? "D" : " ", (u_long)i, (u_long)h->inp[i]); - switch (TYPE(h)) { - case P_HASH: - hk = sp; - switch (HPAGE_PTYPE(hk)) { - case H_OFFDUP: - memcpy(&pgno, - HOFFDUP_PGNO(hk), sizeof(db_pgno_t)); - fprintf(fp, - "%4lu [offpage dups]\n", (u_long)pgno); - break; - case H_DUPLICATE: - /* - * If this is the first item on a page, then - * we cannot figure out how long it is, so - * we only print the first one in the duplicate - * set. - */ - if (i != 0) - len = LEN_HKEYDATA(h, 0, i); - else - len = 1; - - fprintf(fp, "Duplicates:\n"); - for (p = HKEYDATA_DATA(hk), - ep = p + len; p < ep;) { - memcpy(&dlen, p, sizeof(db_indx_t)); - p += sizeof(db_indx_t); - fprintf(fp, "\t\t"); - __db_pr(p, dlen); - p += sizeof(db_indx_t) + dlen; - } - break; - case H_KEYDATA: - if (i != 0) - __db_pr(HKEYDATA_DATA(hk), - LEN_HKEYDATA(h, 0, i)); - else - fprintf(fp, "%s\n", HKEYDATA_DATA(hk)); - break; - case H_OFFPAGE: - memcpy(&a_hkd, hk, HOFFPAGE_SIZE); - fprintf(fp, - "overflow: total len: %4lu page: %4lu\n", - (u_long)a_hkd.tlen, (u_long)a_hkd.pgno); - break; - } - break; - case P_IBTREE: - bi = sp; - fprintf(fp, "count: %4lu pgno: %4lu ", - (u_long)bi->nrecs, (u_long)bi->pgno); - switch (B_TYPE(bi->type)) { - case B_KEYDATA: - __db_pr(bi->data, bi->len); - break; - case B_DUPLICATE: - case B_OVERFLOW: - __db_proff(bi->data); - break; - default: - fprintf(fp, "ILLEGAL BINTERNAL TYPE: %lu\n", - (u_long)B_TYPE(bi->type)); - ret = EINVAL; - break; - } - break; - case P_IRECNO: - ri = sp; - fprintf(fp, "entries %4lu pgno %4lu\n", - (u_long)ri->nrecs, (u_long)ri->pgno); - break; - case P_LBTREE: - case P_LRECNO: - case P_DUPLICATE: - bk = sp; - switch (B_TYPE(bk->type)) { - case B_KEYDATA: - __db_pr(bk->data, bk->len); - break; - case B_DUPLICATE: - case B_OVERFLOW: - __db_proff(bk); - break; - default: - fprintf(fp, - "ILLEGAL DUPLICATE/LBTREE/LRECNO TYPE: %lu\n", - (u_long)B_TYPE(bk->type)); - ret = EINVAL; - break; - } - break; - } - } - (void)fflush(fp); - return (ret); -} - -/* - * __db_isbad - * -- Decide if a page is corrupted. - * - * PUBLIC: int __db_isbad __P((PAGE *, int)); - */ -int -__db_isbad(h, die) - PAGE *h; - int die; -{ - BINTERNAL *bi; - BKEYDATA *bk; - FILE *fp; - db_indx_t i; - u_int type; - - fp = __db_prinit(NULL); - - switch (TYPE(h)) { - case P_DUPLICATE: - case P_HASH: - case P_IBTREE: - case P_INVALID: - case P_IRECNO: - case P_LBTREE: - case P_LRECNO: - case P_OVERFLOW: - break; - default: - fprintf(fp, "ILLEGAL PAGE TYPE: page: %lu type: %lu\n", - (u_long)h->pgno, (u_long)TYPE(h)); - goto bad; - } - - for (i = 0; i < NUM_ENT(h); i++) { - if (P_ENTRY(h, i) - (u_int8_t *)h < P_OVERHEAD || - (size_t)(P_ENTRY(h, i) - (u_int8_t *)h) >= set_psize) { - fprintf(fp, - "ILLEGAL PAGE OFFSET: indx: %lu of %lu\n", - (u_long)i, (u_long)h->inp[i]); - goto bad; - } - switch (TYPE(h)) { - case P_HASH: - type = HPAGE_TYPE(h, i); - if (type != H_OFFDUP && - type != H_DUPLICATE && - type != H_KEYDATA && - type != H_OFFPAGE) { - fprintf(fp, "ILLEGAL HASH TYPE: %lu\n", - (u_long)type); - goto bad; - } - break; - case P_IBTREE: - bi = GET_BINTERNAL(h, i); - if (B_TYPE(bi->type) != B_KEYDATA && - B_TYPE(bi->type) != B_DUPLICATE && - B_TYPE(bi->type) != B_OVERFLOW) { - fprintf(fp, "ILLEGAL BINTERNAL TYPE: %lu\n", - (u_long)B_TYPE(bi->type)); - goto bad; - } - break; - case P_IRECNO: - case P_LBTREE: - case P_LRECNO: - break; - case P_DUPLICATE: - bk = GET_BKEYDATA(h, i); - if (B_TYPE(bk->type) != B_KEYDATA && - B_TYPE(bk->type) != B_DUPLICATE && - B_TYPE(bk->type) != B_OVERFLOW) { - fprintf(fp, - "ILLEGAL DUPLICATE/LBTREE/LRECNO TYPE: %lu\n", - (u_long)B_TYPE(bk->type)); - goto bad; - } - break; - default: - fprintf(fp, - "ILLEGAL PAGE ITEM: %lu\n", (u_long)TYPE(h)); - goto bad; - } - } - return (0); - -bad: if (die) { - abort(); - /* NOTREACHED */ - } - return (1); -} - -/* - * __db_pr -- - * Print out a data element. - * - * PUBLIC: void __db_pr __P((u_int8_t *, u_int32_t)); - */ -void -__db_pr(p, len) - u_int8_t *p; - u_int32_t len; -{ - FILE *fp; - u_int lastch; - int i; - - fp = __db_prinit(NULL); - - fprintf(fp, "len: %3lu", (u_long)len); - lastch = '.'; - if (len != 0) { - fprintf(fp, " data: "); - for (i = len <= 20 ? len : 20; i > 0; --i, ++p) { - lastch = *p; - if (isprint(*p) || *p == '\n') - fprintf(fp, "%c", *p); - else - fprintf(fp, "0x%.2x", (u_int)*p); - } - if (len > 20) { - fprintf(fp, "..."); - lastch = '.'; - } - } - if (lastch != '\n') - fprintf(fp, "\n"); -} - -/* - * __db_prdbt -- - * Print out a DBT data element. - * - * PUBLIC: int __db_prdbt __P((DBT *, int, FILE *)); - */ -int -__db_prdbt(dbtp, checkprint, fp) - DBT *dbtp; - int checkprint; - FILE *fp; -{ - static const char hex[] = "0123456789abcdef"; - u_int8_t *p; - u_int32_t len; - - /* - * !!! - * This routine is the routine that dumps out items in the format - * used by db_dump(1) and db_load(1). This means that the format - * cannot change. - */ - if (checkprint) { - for (len = dbtp->size, p = dbtp->data; len--; ++p) - if (isprint(*p)) { - if (*p == '\\' && fprintf(fp, "\\") != 1) - return (EIO); - if (fprintf(fp, "%c", *p) != 1) - return (EIO); - } else - if (fprintf(fp, "\\%c%c", - hex[(u_int8_t)(*p & 0xf0) >> 4], - hex[*p & 0x0f]) != 3) - return (EIO); - } else - for (len = dbtp->size, p = dbtp->data; len--; ++p) - if (fprintf(fp, "%c%c", - hex[(u_int8_t)(*p & 0xf0) >> 4], - hex[*p & 0x0f]) != 2) - return (EIO); - - return (fprintf(fp, "\n") == 1 ? 0 : EIO); -} - -/* - * __db_proff -- - * Print out an off-page element. - */ -static void -__db_proff(vp) - void *vp; -{ - FILE *fp; - BOVERFLOW *bo; - - fp = __db_prinit(NULL); - - bo = vp; - switch (B_TYPE(bo->type)) { - case B_OVERFLOW: - fprintf(fp, "overflow: total len: %4lu page: %4lu\n", - (u_long)bo->tlen, (u_long)bo->pgno); - break; - case B_DUPLICATE: - fprintf(fp, "duplicate: page: %4lu\n", (u_long)bo->pgno); - break; - } -} - -/* - * __db_prflags -- - * Print out flags values. - * - * PUBLIC: void __db_prflags __P((u_int32_t, const FN *, FILE *)); - */ -void -__db_prflags(flags, fn, fp) - u_int32_t flags; - FN const *fn; - FILE *fp; -{ - const FN *fnp; - int found; - const char *sep; - - sep = " ("; - for (found = 0, fnp = fn; fnp->mask != 0; ++fnp) - if (LF_ISSET(fnp->mask)) { - fprintf(fp, "%s%s", sep, fnp->name); - sep = ", "; - found = 1; - } - if (found) - fprintf(fp, ")"); -} - -/* - * __db_psize -- - * Get the page size. - */ -static void -__db_psize(mpf) - DB_MPOOLFILE *mpf; -{ - BTMETA *mp; - db_pgno_t pgno; - - set_psize = PSIZE_BOUNDARY - 1; - - pgno = PGNO_METADATA; - if (memp_fget(mpf, &pgno, 0, &mp) != 0) - return; - - switch (mp->magic) { - case DB_BTREEMAGIC: - case DB_HASHMAGIC: - set_psize = mp->pagesize; - break; - } - (void)memp_fput(mpf, mp, 0); -} diff --git a/db2/db/db_rec.c b/db2/db/db_rec.c deleted file mode 100644 index 7f577b5..0000000 --- a/db2/db/db_rec.c +++ /dev/null @@ -1,616 +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_rec.c 10.19 (Sleepycat) 9/27/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <string.h> -#endif - -#include "db_int.h" -#include "shqueue.h" -#include "db_page.h" -#include "log.h" -#include "hash.h" -#include "btree.h" - -/* - * PUBLIC: int __db_addrem_recover - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - * - * This log message is generated whenever we add or remove a duplicate - * to/from a duplicate page. On recover, we just do the opposite. - */ -int -__db_addrem_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __db_addrem_args *argp; - DB *file_dbp; - DBC *dbc; - DB_MPOOLFILE *mpf; - PAGE *pagep; - u_int32_t change; - int cmp_n, cmp_p, ret; - - REC_PRINT(__db_addrem_print); - REC_INTRO(__db_addrem_read); - - if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { - if (!redo) { - /* - * We are undoing and the page doesn't exist. That - * is equivalent to having a pagelsn of 0, so we - * would not have to undo anything. In this case, - * don't bother creating a page. - */ - goto done; - } else - if ((ret = memp_fget(mpf, - &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0) - goto out; - } - - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &argp->pagelsn); - change = 0; - if ((cmp_p == 0 && redo && argp->opcode == DB_ADD_DUP) || - (cmp_n == 0 && !redo && argp->opcode == DB_REM_DUP)) { - - /* Need to redo an add, or undo a delete. */ - if ((ret = __db_pitem(dbc, pagep, argp->indx, argp->nbytes, - argp->hdr.size == 0 ? NULL : &argp->hdr, - argp->dbt.size == 0 ? NULL : &argp->dbt)) != 0) - goto out; - - change = DB_MPOOL_DIRTY; - - } else if ((cmp_n == 0 && !redo && argp->opcode == DB_ADD_DUP) || - (cmp_p == 0 && redo && argp->opcode == DB_REM_DUP)) { - /* Need to undo an add, or redo a delete. */ - if ((ret = __db_ditem(dbc, - pagep, argp->indx, argp->nbytes)) != 0) - goto out; - change = DB_MPOOL_DIRTY; - } - - if (change) { - if (redo) - LSN(pagep) = *lsnp; - else - LSN(pagep) = argp->pagelsn; - } - - if ((ret = memp_fput(mpf, pagep, change)) != 0) - goto out; - -done: *lsnp = argp->prev_lsn; - ret = 0; - -out: REC_CLOSE; -} - -/* - * PUBLIC: int __db_split_recover __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__db_split_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __db_split_args *argp; - DB *file_dbp; - DBC *dbc; - DB_MPOOLFILE *mpf; - PAGE *pagep; - int change, cmp_n, cmp_p, ret; - - REC_PRINT(__db_split_print); - REC_INTRO(__db_split_read); - - if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { - if (!redo) { - /* - * We are undoing and the page doesn't exist. That - * is equivalent to having a pagelsn of 0, so we - * would not have to undo anything. In this case, - * don't bother creating a page. - */ - goto done; - } else - if ((ret = memp_fget(mpf, - &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0) - goto out; - } - - /* - * There are two types of log messages here, one for the old page - * and one for the new pages created. The original image in the - * SPLITOLD record is used for undo. The image in the SPLITNEW - * is used for redo. We should never have a case where there is - * a redo operation and the SPLITOLD record is on disk, but not - * the SPLITNEW record. Therefore, we only redo NEW messages - * and only undo OLD messages. - */ - - change = 0; - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &argp->pagelsn); - if (cmp_p == 0 && redo) { - if (argp->opcode == DB_SPLITNEW) { - /* Need to redo the split described. */ - memcpy(pagep, - argp->pageimage.data, argp->pageimage.size); - } - LSN(pagep) = *lsnp; - change = DB_MPOOL_DIRTY; - } else if (cmp_n == 0 && !redo) { - if (argp->opcode == DB_SPLITOLD) { - /* Put back the old image. */ - memcpy(pagep, - argp->pageimage.data, argp->pageimage.size); - } - LSN(pagep) = argp->pagelsn; - change = DB_MPOOL_DIRTY; - } - if ((ret = memp_fput(mpf, pagep, change)) != 0) - goto out; - -done: *lsnp = argp->prev_lsn; - ret = 0; - -out: REC_CLOSE; -} - -/* - * PUBLIC: int __db_big_recover __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__db_big_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __db_big_args *argp; - DB *file_dbp; - DBC *dbc; - DB_MPOOLFILE *mpf; - PAGE *pagep; - u_int32_t change; - int cmp_n, cmp_p, ret; - - REC_PRINT(__db_big_print); - REC_INTRO(__db_big_read); - - if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { - if (!redo) { - /* - * We are undoing and the page doesn't exist. That - * is equivalent to having a pagelsn of 0, so we - * would not have to undo anything. In this case, - * don't bother creating a page. - */ - ret = 0; - goto ppage; - } else - if ((ret = memp_fget(mpf, - &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0) - goto out; - } - - /* - * There are three pages we need to check. The one on which we are - * adding data, the previous one whose next_pointer may have - * been updated, and the next one whose prev_pointer may have - * been updated. - */ - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &argp->pagelsn); - change = 0; - if ((cmp_p == 0 && redo && argp->opcode == DB_ADD_BIG) || - (cmp_n == 0 && !redo && argp->opcode == DB_REM_BIG)) { - /* We are either redo-ing an add, or undoing a delete. */ - P_INIT(pagep, file_dbp->pgsize, argp->pgno, argp->prev_pgno, - argp->next_pgno, 0, P_OVERFLOW); - OV_LEN(pagep) = argp->dbt.size; - OV_REF(pagep) = 1; - memcpy((u_int8_t *)pagep + P_OVERHEAD, argp->dbt.data, - argp->dbt.size); - PREV_PGNO(pagep) = argp->prev_pgno; - change = DB_MPOOL_DIRTY; - } else if ((cmp_n == 0 && !redo && argp->opcode == DB_ADD_BIG) || - (cmp_p == 0 && redo && argp->opcode == DB_REM_BIG)) { - /* - * We are either undo-ing an add or redo-ing a delete. - * The page is about to be reclaimed in either case, so - * there really isn't anything to do here. - */ - change = DB_MPOOL_DIRTY; - } - if (change) - LSN(pagep) = redo ? *lsnp : argp->pagelsn; - - if ((ret = memp_fput(mpf, pagep, change)) != 0) - goto out; - - /* Now check the previous page. */ -ppage: if (argp->prev_pgno != PGNO_INVALID) { - change = 0; - if ((ret = memp_fget(mpf, &argp->prev_pgno, 0, &pagep)) != 0) { - if (!redo) { - /* - * We are undoing and the page doesn't exist. - * That is equivalent to having a pagelsn of 0, - * so we would not have to undo anything. In - * this case, don't bother creating a page. - */ - *lsnp = argp->prev_lsn; - ret = 0; - goto npage; - } else - if ((ret = memp_fget(mpf, &argp->prev_pgno, - DB_MPOOL_CREATE, &pagep)) != 0) - goto out; - } - - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &argp->prevlsn); - - if ((cmp_p == 0 && redo && argp->opcode == DB_ADD_BIG) || - (cmp_n == 0 && !redo && argp->opcode == DB_REM_BIG)) { - /* Redo add, undo delete. */ - NEXT_PGNO(pagep) = argp->pgno; - change = DB_MPOOL_DIRTY; - } else if ((cmp_n == 0 && - !redo && argp->opcode == DB_ADD_BIG) || - (cmp_p == 0 && redo && argp->opcode == DB_REM_BIG)) { - /* Redo delete, undo add. */ - NEXT_PGNO(pagep) = argp->next_pgno; - change = DB_MPOOL_DIRTY; - } - if (change) - LSN(pagep) = redo ? *lsnp : argp->prevlsn; - if ((ret = memp_fput(mpf, pagep, change)) != 0) - goto out; - } - - /* Now check the next page. Can only be set on a delete. */ -npage: if (argp->next_pgno != PGNO_INVALID) { - change = 0; - if ((ret = memp_fget(mpf, &argp->next_pgno, 0, &pagep)) != 0) { - if (!redo) { - /* - * We are undoing and the page doesn't exist. - * That is equivalent to having a pagelsn of 0, - * so we would not have to undo anything. In - * this case, don't bother creating a page. - */ - goto done; - } else - if ((ret = memp_fget(mpf, &argp->next_pgno, - DB_MPOOL_CREATE, &pagep)) != 0) - goto out; - } - - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &argp->nextlsn); - if (cmp_p == 0 && redo) { - PREV_PGNO(pagep) = PGNO_INVALID; - change = DB_MPOOL_DIRTY; - } else if (cmp_n == 0 && !redo) { - PREV_PGNO(pagep) = argp->pgno; - change = DB_MPOOL_DIRTY; - } - if (change) - LSN(pagep) = redo ? *lsnp : argp->nextlsn; - if ((ret = memp_fput(mpf, pagep, change)) != 0) - goto out; - } - -done: *lsnp = argp->prev_lsn; - ret = 0; - -out: REC_CLOSE; -} - -/* - * __db_ovref_recover -- - * Recovery function for __db_ovref(). - * - * PUBLIC: int __db_ovref_recover __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__db_ovref_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __db_ovref_args *argp; - DB *file_dbp; - DBC *dbc; - DB_MPOOLFILE *mpf; - PAGE *pagep; - int modified, ret; - - REC_PRINT(__db_ovref_print); - REC_INTRO(__db_ovref_read); - - if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { - (void)__db_pgerr(file_dbp, argp->pgno); - goto out; - } - - modified = 0; - if (log_compare(&LSN(pagep), &argp->lsn) == 0 && redo) { - /* Need to redo update described. */ - OV_REF(pagep) += argp->adjust; - - pagep->lsn = *lsnp; - modified = 1; - } else if (log_compare(lsnp, &LSN(pagep)) == 0 && !redo) { - /* Need to undo update described. */ - OV_REF(pagep) -= argp->adjust; - - pagep->lsn = argp->lsn; - modified = 1; - } - if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) - goto out; - -done: *lsnp = argp->prev_lsn; - ret = 0; - -out: REC_CLOSE; -} - -/* - * __db_relink_recover -- - * Recovery function for relink. - * - * PUBLIC: int __db_relink_recover - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__db_relink_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __db_relink_args *argp; - DB *file_dbp; - DBC *dbc; - DB_MPOOLFILE *mpf; - PAGE *pagep; - int cmp_n, cmp_p, modified, ret; - - REC_PRINT(__db_relink_print); - REC_INTRO(__db_relink_read); - - /* - * There are up to three pages we need to check -- the page, and the - * previous and next pages, if they existed. For a page add operation, - * the current page is the result of a split and is being recovered - * elsewhere, so all we need do is recover the next page. - */ - if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { - if (redo) { - (void)__db_pgerr(file_dbp, argp->pgno); - goto out; - } - goto next; - } - if (argp->opcode == DB_ADD_PAGE) - goto next; - - modified = 0; - if (log_compare(&LSN(pagep), &argp->lsn) == 0 && redo) { - /* Redo the relink. */ - pagep->lsn = *lsnp; - modified = 1; - } else if (log_compare(lsnp, &LSN(pagep)) == 0 && !redo) { - /* Undo the relink. */ - pagep->next_pgno = argp->next; - pagep->prev_pgno = argp->prev; - - pagep->lsn = argp->lsn; - modified = 1; - } - if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) - goto out; - -next: if ((ret = memp_fget(mpf, &argp->next, 0, &pagep)) != 0) { - if (redo) { - (void)__db_pgerr(file_dbp, argp->next); - goto out; - } - goto prev; - } - modified = 0; - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &argp->lsn_next); - if ((argp->opcode == DB_REM_PAGE && cmp_p == 0 && redo) || - (argp->opcode == DB_ADD_PAGE && cmp_n == 0 && !redo)) { - /* Redo the remove or undo the add. */ - pagep->prev_pgno = argp->prev; - - pagep->lsn = *lsnp; - modified = 1; - } else if ((argp->opcode == DB_REM_PAGE && cmp_n == 0 && !redo) || - (argp->opcode == DB_ADD_PAGE && cmp_p == 0 && redo)) { - /* Undo the remove or redo the add. */ - pagep->prev_pgno = argp->pgno; - - pagep->lsn = argp->lsn_next; - modified = 1; - } - if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) - goto out; - if (argp->opcode == DB_ADD_PAGE) - goto done; - -prev: if ((ret = memp_fget(mpf, &argp->prev, 0, &pagep)) != 0) { - if (redo) { - (void)__db_pgerr(file_dbp, argp->prev); - goto out; - } - goto done; - } - modified = 0; - if (log_compare(&LSN(pagep), &argp->lsn_prev) == 0 && redo) { - /* Redo the relink. */ - pagep->next_pgno = argp->next; - - pagep->lsn = *lsnp; - modified = 1; - } else if (log_compare(lsnp, &LSN(pagep)) == 0 && !redo) { - /* Undo the relink. */ - pagep->next_pgno = argp->pgno; - - pagep->lsn = argp->lsn_prev; - modified = 1; - } - if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) - goto out; - -done: *lsnp = argp->prev_lsn; - ret = 0; - -out: REC_CLOSE; -} - -/* - * PUBLIC: int __db_addpage_recover - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__db_addpage_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __db_addpage_args *argp; - DB *file_dbp; - DBC *dbc; - DB_MPOOLFILE *mpf; - PAGE *pagep; - u_int32_t change; - int cmp_n, cmp_p, ret; - - REC_PRINT(__db_addpage_print); - REC_INTRO(__db_addpage_read); - - /* - * We need to check two pages: the old one and the new one onto - * which we're going to add duplicates. Do the old one first. - */ - if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) - goto out; - - change = 0; - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &argp->lsn); - if (cmp_p == 0 && redo) { - NEXT_PGNO(pagep) = argp->nextpgno; - - LSN(pagep) = *lsnp; - change = DB_MPOOL_DIRTY; - } else if (cmp_n == 0 && !redo) { - NEXT_PGNO(pagep) = PGNO_INVALID; - - LSN(pagep) = argp->lsn; - change = DB_MPOOL_DIRTY; - } - if ((ret = memp_fput(mpf, pagep, change)) != 0) - goto out; - - if ((ret = memp_fget(mpf, &argp->nextpgno, 0, &pagep)) != 0) { - if (!redo) { - /* - * We are undoing and the page doesn't exist. That - * is equivalent to having a pagelsn of 0, so we - * would not have to undo anything. In this case, - * don't bother creating a page. - */ - goto done; - } else - if ((ret = memp_fget(mpf, - &argp->nextpgno, DB_MPOOL_CREATE, &pagep)) != 0) - goto out; - } - - change = 0; - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &argp->nextlsn); - if (cmp_p == 0 && redo) { - PREV_PGNO(pagep) = argp->pgno; - - LSN(pagep) = *lsnp; - change = DB_MPOOL_DIRTY; - } else if (cmp_n == 0 && !redo) { - PREV_PGNO(pagep) = PGNO_INVALID; - - LSN(pagep) = argp->nextlsn; - change = DB_MPOOL_DIRTY; - } - if ((ret = memp_fput(mpf, pagep, change)) != 0) - goto out; - -done: *lsnp = argp->prev_lsn; - ret = 0; - -out: REC_CLOSE; -} - -/* - * __db_debug_recover -- - * Recovery function for debug. - * - * PUBLIC: int __db_debug_recover __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__db_debug_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __db_debug_args *argp; - int ret; - - COMPQUIET(redo, 0); - COMPQUIET(logp, NULL); - - REC_PRINT(__db_debug_print); - REC_NOOP_INTRO(__db_debug_read); - - *lsnp = argp->prev_lsn; - ret = 0; - - REC_NOOP_CLOSE; -} diff --git a/db2/db/db_ret.c b/db2/db/db_ret.c deleted file mode 100644 index 9f0d0ec..0000000 --- a/db2/db/db_ret.c +++ /dev/null @@ -1,153 +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_ret.c 10.16 (Sleepycat) 10/4/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <string.h> -#endif - -#include "db_int.h" -#include "db_page.h" -#include "btree.h" -#include "db_am.h" - -/* - * __db_ret -- - * Build return DBT. - * - * PUBLIC: int __db_ret __P((DB *, - * PUBLIC: PAGE *, u_int32_t, DBT *, void **, u_int32_t *)); - */ -int -__db_ret(dbp, h, indx, dbt, memp, memsize) - DB *dbp; - PAGE *h; - u_int32_t indx; - DBT *dbt; - void **memp; - u_int32_t *memsize; -{ - BKEYDATA *bk; - HOFFPAGE ho; - BOVERFLOW *bo; - u_int32_t len; - u_int8_t *hk; - void *data; - - switch (TYPE(h)) { - case P_HASH: - hk = P_ENTRY(h, indx); - if (HPAGE_PTYPE(hk) == H_OFFPAGE) { - memcpy(&ho, hk, sizeof(HOFFPAGE)); - return (__db_goff(dbp, dbt, - ho.tlen, ho.pgno, memp, memsize)); - } - len = LEN_HKEYDATA(h, dbp->pgsize, indx); - data = HKEYDATA_DATA(hk); - break; - case P_DUPLICATE: - case P_LBTREE: - case P_LRECNO: - bk = GET_BKEYDATA(h, indx); - if (B_TYPE(bk->type) == B_OVERFLOW) { - bo = (BOVERFLOW *)bk; - return (__db_goff(dbp, dbt, - bo->tlen, bo->pgno, memp, memsize)); - } - len = bk->len; - data = bk->data; - break; - default: - return (__db_pgfmt(dbp, h->pgno)); - } - - return (__db_retcopy(dbt, data, len, memp, memsize, - F_ISSET(dbt, DB_DBT_INTERNAL) ? NULL : dbp->db_malloc)); -} - -/* - * __db_retcopy -- - * Copy the returned data into the user's DBT, handling special flags. - * - * PUBLIC: int __db_retcopy __P((DBT *, - * PUBLIC: void *, u_int32_t, void **, u_int32_t *, void *(*)(size_t))); - */ -int -__db_retcopy(dbt, data, len, memp, memsize, db_malloc) - DBT *dbt; - void *data; - u_int32_t len; - void **memp; - u_int32_t *memsize; - void *(*db_malloc) __P((size_t)); -{ - int ret; - - /* If returning a partial record, reset the length. */ - if (F_ISSET(dbt, DB_DBT_PARTIAL)) { - data = (u_int8_t *)data + dbt->doff; - if (len > dbt->doff) { - len -= dbt->doff; - if (len > dbt->dlen) - len = dbt->dlen; - } else - len = 0; - } - - /* - * Return the length of the returned record in the DBT size field. - * This satisfies the requirement that if we're using user memory - * and insufficient memory was provided, return the amount necessary - * in the size field. - */ - dbt->size = len; - - /* - * Allocate memory to be owned by the application: DB_DBT_MALLOC. - * - * !!! - * We always allocate memory, even if we're copying out 0 bytes. This - * guarantees consistency, i.e., the application can always free memory - * without concern as to how many bytes of the record were requested. - * - * Use the memory specified by the application: DB_DBT_USERMEM. - * - * !!! - * If the length we're going to copy is 0, the application-supplied - * memory pointer is allowed to be NULL. - */ - if (F_ISSET(dbt, DB_DBT_MALLOC)) { - if ((ret = __os_malloc(len, db_malloc, &dbt->data)) != 0) - return (ret); - } else if (F_ISSET(dbt, DB_DBT_USERMEM)) { - if (len != 0 && (dbt->data == NULL || dbt->ulen < len)) - return (ENOMEM); - } else if (memp == NULL || memsize == NULL) { - return (EINVAL); - } else { - if (len != 0 && (*memsize == 0 || *memsize < len)) { - if ((ret = __os_realloc(memp, len)) != 0) { - *memsize = 0; - return (ret); - } - *memsize = len; - } - dbt->data = *memp; - } - - if (len != 0) - memcpy(dbt->data, data, len); - return (0); -} diff --git a/db2/db185/db185.c b/db2/db185/db185.c deleted file mode 100644 index 739ada8..0000000 --- a/db2/db185/db185.c +++ /dev/null @@ -1,493 +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[] = "@(#)db185.c 8.21 (Sleepycat) 11/22/98"; -#endif - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <fcntl.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#endif - -#include "db_int.h" -#include "db185_int.h" -#include "common_ext.h" - -#ifndef STDERR_FILENO -#define STDERR_FILENO 2 -#endif - -static int db185_close __P((DB185 *)); -static int db185_del __P((const DB185 *, const DBT185 *, u_int)); -static int db185_fd __P((const DB185 *)); -static int db185_get __P((const DB185 *, const DBT185 *, DBT185 *, u_int)); -static int db185_put __P((const DB185 *, DBT185 *, const DBT185 *, u_int)); -static int db185_seq __P((const DB185 *, DBT185 *, DBT185 *, u_int)); -static int db185_sync __P((const DB185 *, u_int)); - -DB185 * -dbopen(file, oflags, mode, type, openinfo) - const char *file; - int oflags, mode; - DBTYPE type; - const void *openinfo; -{ - const BTREEINFO *bi; - const HASHINFO *hi; - const RECNOINFO *ri; - DB *dbp; - DB185 *db185p; - DB_INFO dbinfo, *dbinfop; - ssize_t nw; - int fd, s_errno; - - if ((errno = __os_calloc(1, sizeof(DB185), &db185p)) != 0) - return (NULL); - dbinfop = NULL; - memset(&dbinfo, 0, sizeof(dbinfo)); - - /* - * !!! - * The DBTYPE enum wasn't initialized in DB 185, so it's off-by-one - * from DB 2.0. - */ - switch (type) { - case 0: /* DB_BTREE */ - type = DB_BTREE; - if ((bi = openinfo) != NULL) { - dbinfop = &dbinfo; - if (bi->flags & ~R_DUP) - goto einval; - if (bi->flags & R_DUP) - dbinfop->flags |= DB_DUP; - dbinfop->db_cachesize = bi->cachesize; - dbinfop->bt_maxkey = bi->maxkeypage; - dbinfop->bt_minkey = bi->minkeypage; - dbinfop->db_pagesize = bi->psize; - /* - * !!! - * Comparisons and prefix calls work because the DBT - * structures in 1.85 and 2.0 have the same initial - * fields. - */ - dbinfop->bt_compare = bi->compare; - dbinfop->bt_prefix = bi->prefix; - dbinfop->db_lorder = bi->lorder; - } - break; - case 1: /* DB_HASH */ - type = DB_HASH; - if ((hi = openinfo) != NULL) { - dbinfop = &dbinfo; - dbinfop->db_pagesize = hi->bsize; - dbinfop->h_ffactor = hi->ffactor; - dbinfop->h_nelem = hi->nelem; - dbinfop->db_cachesize = hi->cachesize; - dbinfop->h_hash = (u_int32_t (*) - __P((const void *, u_int32_t)))hi->hash; - dbinfop->db_lorder = hi->lorder; - } - - break; - case 2: /* DB_RECNO */ - type = DB_RECNO; - dbinfop = &dbinfo; - - /* DB 1.85 did renumbering by default. */ - dbinfop->flags |= DB_RENUMBER; - - /* - * !!! - * The file name given to DB 1.85 recno is the name of the DB - * 2.0 backing file. If the file doesn't exist, create it if - * the user has the O_CREAT flag set, DB 1.85 did it for you, - * and DB 2.0 doesn't. - * - * !!! - * Setting the file name to NULL specifies that we're creating - * a temporary backing file, in DB 2.X. If we're opening the - * DB file read-only, change the flags to read-write, because - * temporary backing files cannot be opened read-only, and DB - * 2.X will return an error. We are cheating here -- if the - * application does a put on the database, it will succeed -- - * although that would be a stupid thing for the application - * to do. - * - * !!! - * Note, the file name in DB 1.85 was a const -- we don't do - * that in DB 2.0, so do that cast. - */ - if (file != NULL) { - if (oflags & O_CREAT && __os_exists(file, NULL) != 0) - if (__os_open(file, oflags, mode, &fd) == 0) - (void)__os_close(fd); - dbinfop->re_source = (char *)file; - - if (O_RDONLY) - oflags &= ~O_RDONLY; - oflags |= O_RDWR; - file = NULL; - } - - if ((ri = openinfo) != NULL) { - /* - * !!! - * We can't support the bfname field. - */ -#define BFMSG "DB: DB 1.85's recno bfname field is not supported.\n" - if (ri->bfname != NULL) { - (void)__os_write(STDERR_FILENO, - BFMSG, sizeof(BFMSG) - 1, &nw); - goto einval; - } - - if (ri->flags & ~(R_FIXEDLEN | R_NOKEY | R_SNAPSHOT)) - goto einval; - if (ri->flags & R_FIXEDLEN) { - dbinfop->flags |= DB_FIXEDLEN; - if (ri->bval != 0) { - dbinfop->flags |= DB_PAD; - dbinfop->re_pad = ri->bval; - } - } else - if (ri->bval != 0) { - dbinfop->flags |= DB_DELIMITER; - dbinfop->re_delim = ri->bval; - } - - /* - * !!! - * We ignore the R_NOKEY flag, but that's okay, it was - * only an optimization that was never implemented. - */ - - if (ri->flags & R_SNAPSHOT) - dbinfop->flags |= DB_SNAPSHOT; - - dbinfop->db_cachesize = ri->cachesize; - dbinfop->db_pagesize = ri->psize; - dbinfop->db_lorder = ri->lorder; - dbinfop->re_len = ri->reclen; - } - break; - default: - goto einval; - } - - db185p->close = db185_close; - db185p->del = db185_del; - db185p->fd = db185_fd; - db185p->get = db185_get; - db185p->put = db185_put; - db185p->seq = db185_seq; - db185p->sync = db185_sync; - - /* - * !!! - * Store the returned pointer to the real DB 2.0 structure in the - * internal pointer. Ugly, but we're not going for pretty, here. - */ - if ((errno = db_open(file, - type, __db_oflags(oflags), mode, NULL, dbinfop, &dbp)) != 0) { - __os_free(db185p, sizeof(DB185)); - return (NULL); - } - - /* Create the cursor used for sequential ops. */ - if ((errno = dbp->cursor(dbp, NULL, &((DB185 *)db185p)->dbc, 0)) != 0) { - s_errno = errno; - (void)dbp->close(dbp, 0); - __os_free(db185p, sizeof(DB185)); - errno = s_errno; - return (NULL); - } - - db185p->internal = dbp; - return (db185p); - -einval: __os_free(db185p, sizeof(DB185)); - errno = EINVAL; - return (NULL); -} - -static int -db185_close(db185p) - DB185 *db185p; -{ - DB *dbp; - - dbp = (DB *)db185p->internal; - - errno = dbp->close(dbp, 0); - - __os_free(db185p, sizeof(DB185)); - - return (errno == 0 ? 0 : -1); -} - -static int -db185_del(db185p, key185, flags) - const DB185 *db185p; - const DBT185 *key185; - u_int flags; -{ - DB *dbp; - DBT key; - - dbp = (DB *)db185p->internal; - - memset(&key, 0, sizeof(key)); - key.data = key185->data; - key.size = key185->size; - - if (flags & ~R_CURSOR) - goto einval; - if (flags & R_CURSOR) - errno = db185p->dbc->c_del(db185p->dbc, 0); - else - errno = dbp->del(dbp, NULL, &key, 0); - - switch (errno) { - case 0: - return (0); - case DB_NOTFOUND: - return (1); - } - return (-1); - -einval: errno = EINVAL; - return (-1); -} - -static int -db185_fd(db185p) - const DB185 *db185p; -{ - DB *dbp; - int fd; - - dbp = (DB *)db185p->internal; - - return ((errno = dbp->fd(dbp, &fd)) == 0 ? fd : -1); -} - -static int -db185_get(db185p, key185, data185, flags) - const DB185 *db185p; - const DBT185 *key185; - DBT185 *data185; - u_int flags; -{ - DB *dbp; - DBT key, data; - - dbp = (DB *)db185p->internal; - - memset(&key, 0, sizeof(key)); - key.data = key185->data; - key.size = key185->size; - memset(&data, 0, sizeof(data)); - data.data = data185->data; - data.size = data185->size; - - if (flags) - goto einval; - - switch (errno = dbp->get(dbp, NULL, &key, &data, 0)) { - case 0: - data185->data = data.data; - data185->size = data.size; - return (0); - case DB_NOTFOUND: - return (1); - } - return (-1); - -einval: errno = EINVAL; - return (-1); -} - -static int -db185_put(db185p, key185, data185, flags) - const DB185 *db185p; - DBT185 *key185; - const DBT185 *data185; - u_int flags; -{ - DB *dbp; - DBC *dbcp_put; - DBT key, data; - int s_errno; - - dbp = (DB *)db185p->internal; - - memset(&key, 0, sizeof(key)); - key.data = key185->data; - key.size = key185->size; - memset(&data, 0, sizeof(data)); - data.data = data185->data; - data.size = data185->size; - - switch (flags) { - case 0: - errno = dbp->put(dbp, NULL, &key, &data, 0); - break; - case R_CURSOR: - errno = - db185p->dbc->c_put(db185p->dbc, &key, &data, DB_CURRENT); - break; - case R_IAFTER: - case R_IBEFORE: - if (dbp->type != DB_RECNO) - goto einval; - - if ((errno = dbp->cursor(dbp, NULL, &dbcp_put, 0)) != 0) - return (-1); - if ((errno = - dbcp_put->c_get(dbcp_put, &key, &data, DB_SET)) != 0) { - s_errno = errno; - (void)dbcp_put->c_close(dbcp_put); - errno = s_errno; - return (-1); - } - memset(&data, 0, sizeof(data)); - data.data = data185->data; - data.size = data185->size; - errno = dbcp_put->c_put(dbcp_put, - &key, &data, flags == R_IAFTER ? DB_AFTER : DB_BEFORE); - s_errno = errno; - (void)dbcp_put->c_close(dbcp_put); - errno = s_errno; - break; - case R_NOOVERWRITE: - errno = dbp->put(dbp, NULL, &key, &data, DB_NOOVERWRITE); - break; - case R_SETCURSOR: - if (dbp->type != DB_BTREE && dbp->type != DB_RECNO) - goto einval; - - if ((errno = dbp->put(dbp, NULL, &key, &data, 0)) != 0) - break; - errno = - db185p->dbc->c_get(db185p->dbc, &key, &data, DB_SET_RANGE); - break; - default: - goto einval; - } - - switch (errno) { - case 0: - key185->data = key.data; - key185->size = key.size; - return (0); - case DB_KEYEXIST: - return (1); - } - return (-1); - -einval: errno = EINVAL; - return (-1); -} - -static int -db185_seq(db185p, key185, data185, flags) - const DB185 *db185p; - DBT185 *key185, *data185; - u_int flags; -{ - DB *dbp; - DBT key, data; - - dbp = (DB *)db185p->internal; - - memset(&key, 0, sizeof(key)); - key.data = key185->data; - key.size = key185->size; - memset(&data, 0, sizeof(data)); - data.data = data185->data; - data.size = data185->size; - - switch (flags) { - case R_CURSOR: - flags = DB_SET_RANGE; - break; - case R_FIRST: - flags = DB_FIRST; - break; - case R_LAST: - if (dbp->type != DB_BTREE && dbp->type != DB_RECNO) - goto einval; - flags = DB_LAST; - break; - case R_NEXT: - flags = DB_NEXT; - break; - case R_PREV: - if (dbp->type != DB_BTREE && dbp->type != DB_RECNO) - goto einval; - flags = DB_PREV; - break; - default: - goto einval; - } - switch (errno = db185p->dbc->c_get(db185p->dbc, &key, &data, flags)) { - case 0: - key185->data = key.data; - key185->size = key.size; - data185->data = data.data; - data185->size = data.size; - return (0); - case DB_NOTFOUND: - return (1); - } - return (-1); - -einval: errno = EINVAL; - return (-1); -} - -static int -db185_sync(db185p, flags) - const DB185 *db185p; - u_int flags; -{ - DB *dbp; - ssize_t nw; - - dbp = (DB *)db185p->internal; - - switch (flags) { - case 0: - break; - case R_RECNOSYNC: - /* - * !!! - * We can't support the R_RECNOSYNC flag. - */ -#define RSMSG "DB: DB 1.85's R_RECNOSYNC sync flag is not supported.\n" - (void)__os_write(STDERR_FILENO, RSMSG, sizeof(RSMSG) - 1, &nw); - goto einval; - default: - goto einval; - } - - return ((errno = dbp->sync(dbp, 0)) == 0 ? 0 : -1); - -einval: errno = EINVAL; - return (-1); -} diff --git a/db2/db185/db185_int.h b/db2/db185/db185_int.h deleted file mode 100644 index f7d7af5..0000000 --- a/db2/db185/db185_int.h +++ /dev/null @@ -1,138 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1997, 1998 - * Sleepycat Software. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994, 1995, 1996 - * Keith Bostic. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. 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. - * - * @(#)db185_int.h 8.7 (Sleepycat) 4/10/98 - */ - -#ifndef _DB185_H_ -#define _DB185_H_ - -/* Routine flags. */ -#define R_CURSOR 1 /* del, put, seq */ -#define __R_UNUSED 2 /* UNUSED */ -#define R_FIRST 3 /* seq */ -#define R_IAFTER 4 /* put (RECNO) */ -#define R_IBEFORE 5 /* put (RECNO) */ -#define R_LAST 6 /* seq (BTREE, RECNO) */ -#define R_NEXT 7 /* seq */ -#define R_NOOVERWRITE 8 /* put */ -#define R_PREV 9 /* seq (BTREE, RECNO) */ -#define R_SETCURSOR 10 /* put (RECNO) */ -#define R_RECNOSYNC 11 /* sync (RECNO) */ - -typedef struct { - void *data; /* data */ - size_t size; /* data length */ -} DBT185; - -/* Access method description structure. */ -typedef struct __db185 { - DBTYPE type; /* Underlying db type. */ - int (*close) __P((struct __db185 *)); - int (*del) __P((const struct __db185 *, const DBT185 *, u_int)); - int (*get) - __P((const struct __db185 *, const DBT185 *, DBT185 *, u_int)); - int (*put) - __P((const struct __db185 *, DBT185 *, const DBT185 *, u_int)); - int (*seq) - __P((const struct __db185 *, DBT185 *, DBT185 *, u_int)); - int (*sync) __P((const struct __db185 *, u_int)); - void *internal; /* Access method private. */ - int (*fd) __P((const struct __db185 *)); - - /* - * !!! - * Added to the end of the DB 1.85 DB structure, it's needed to - * hold the DB 2.0 cursor used for DB 1.85 sequential operations. - */ - DBC *dbc; /* DB 1.85 sequential cursor. */ -} DB185; - -/* Structure used to pass parameters to the btree routines. */ -typedef struct { -#define R_DUP 0x01 /* duplicate keys */ - u_int32_t flags; - u_int32_t cachesize; /* bytes to cache */ - u_int32_t maxkeypage; /* maximum keys per page */ - u_int32_t minkeypage; /* minimum keys per page */ - u_int32_t psize; /* page size */ - int (*compare) /* comparison function */ - __P((const DBT *, const DBT *)); - size_t (*prefix) /* prefix function */ - __P((const DBT *, const DBT *)); - int lorder; /* byte order */ -} BTREEINFO; - -/* Structure used to pass parameters to the hashing routines. */ -typedef struct { - u_int32_t bsize; /* bucket size */ - u_int32_t ffactor; /* fill factor */ - u_int32_t nelem; /* number of elements */ - u_int32_t cachesize; /* bytes to cache */ - u_int32_t /* hash function */ - (*hash) __P((const void *, size_t)); - int lorder; /* byte order */ -} HASHINFO; - -/* Structure used to pass parameters to the record routines. */ -typedef struct { -#define R_FIXEDLEN 0x01 /* fixed-length records */ -#define R_NOKEY 0x02 /* key not required */ -#define R_SNAPSHOT 0x04 /* snapshot the input */ - u_int32_t flags; - u_int32_t cachesize; /* bytes to cache */ - u_int32_t psize; /* page size */ - int lorder; /* byte order */ - size_t reclen; /* record length (fixed-length records) */ - u_char bval; /* delimiting byte (variable-length records */ - char *bfname; /* btree file name */ -} RECNOINFO; - -#if defined(__cplusplus) -extern "C" { -#endif -DB185 *__dbopen __P((const char *, int, int, DBTYPE, const void *)); -DB185 *dbopen __P((const char *, int, int, DBTYPE, const void *)); -#if defined(__cplusplus) -}; -#endif -#endif /* !_DB185_H_ */ diff --git a/db2/db_185.h b/db2/db_185.h deleted file mode 100644 index 456a8b4..0000000 --- a/db2/db_185.h +++ /dev/null @@ -1,178 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. 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. - * - * @(#)db_185.h.src 8.7 (Sleepycat) 4/10/98 - */ - -#ifndef _DB_185_H_ -#define _DB_185_H_ - -#include <sys/types.h> - -#include <limits.h> - -/* - * XXX - * Handle function prototypes and the keyword "const". This steps on name - * space that DB doesn't control, but all of the other solutions are worse. - */ -#undef __P -#if defined(__STDC__) || defined(__cplusplus) -#define __P(protos) protos /* ANSI C prototypes */ -#else -#define const -#define __P(protos) () /* K&R C preprocessor */ -#endif - -#define RET_ERROR -1 /* Return values. */ -#define RET_SUCCESS 0 -#define RET_SPECIAL 1 - -#ifndef __BIT_TYPES_DEFINED__ -#define __BIT_TYPES_DEFINED__ -@u_int8_decl@ -@int16_decl@ -@u_int16_decl@ -@int32_decl@ -@u_int32_decl@ -#endif - -/* - * XXX - * SGI/IRIX already has a pgno_t. - */ -#ifdef sgi -#define pgno_t db_pgno_t -#endif - -#define MAX_PAGE_NUMBER 0xffffffff /* >= # of pages in a file */ -typedef u_int32_t pgno_t; -#define MAX_PAGE_OFFSET 65535 /* >= # of bytes in a page */ -typedef u_int16_t indx_t; -#define MAX_REC_NUMBER 0xffffffff /* >= # of records in a tree */ -typedef u_int32_t recno_t; - -/* Key/data structure -- a Data-Base Thang. */ -typedef struct { - void *data; /* data */ - size_t size; /* data length */ -} DBT; - -/* Routine flags. */ -#define R_CURSOR 1 /* del, put, seq */ -#define __R_UNUSED 2 /* UNUSED */ -#define R_FIRST 3 /* seq */ -#define R_IAFTER 4 /* put (RECNO) */ -#define R_IBEFORE 5 /* put (RECNO) */ -#define R_LAST 6 /* seq (BTREE, RECNO) */ -#define R_NEXT 7 /* seq */ -#define R_NOOVERWRITE 8 /* put */ -#define R_PREV 9 /* seq (BTREE, RECNO) */ -#define R_SETCURSOR 10 /* put (RECNO) */ -#define R_RECNOSYNC 11 /* sync (RECNO) */ - -typedef enum { DB_BTREE, DB_HASH, DB_RECNO } DBTYPE; - -/* Access method description structure. */ -typedef struct __db { - DBTYPE type; /* Underlying db type. */ - int (*close) (struct __db *); - int (*del) (const struct __db *, const DBT *, u_int); - int (*get) (const struct __db *, const DBT *, DBT *, u_int); - int (*put) (const struct __db *, DBT *, const DBT *, u_int); - int (*seq) (const struct __db *, DBT *, DBT *, u_int); - int (*sync) (const struct __db *, u_int); - void *internal; /* Access method private. */ - int (*fd) (const struct __db *); -} DB; - -#define BTREEMAGIC 0x053162 -#define BTREEVERSION 3 - -/* Structure used to pass parameters to the btree routines. */ -typedef struct { -#define R_DUP 0x01 /* duplicate keys */ - u_int32_t flags; - u_int32_t cachesize; /* bytes to cache */ - u_int32_t maxkeypage; /* maximum keys per page */ - u_int32_t minkeypage; /* minimum keys per page */ - u_int32_t psize; /* page size */ - int (*compare) /* comparison function */ - (const DBT *, const DBT *); - size_t (*prefix) /* prefix function */ - (const DBT *, const DBT *); - int lorder; /* byte order */ -} BTREEINFO; - -#define HASHMAGIC 0x061561 -#define HASHVERSION 2 - -/* Structure used to pass parameters to the hashing routines. */ -typedef struct { - u_int32_t bsize; /* bucket size */ - u_int32_t ffactor; /* fill factor */ - u_int32_t nelem; /* number of elements */ - u_int32_t cachesize; /* bytes to cache */ - u_int32_t /* hash function */ - (*hash) (const void *, size_t); - int lorder; /* byte order */ -} HASHINFO; - -/* Structure used to pass parameters to the record routines. */ -typedef struct { -#define R_FIXEDLEN 0x01 /* fixed-length records */ -#define R_NOKEY 0x02 /* key not required */ -#define R_SNAPSHOT 0x04 /* snapshot the input */ - u_int32_t flags; - u_int32_t cachesize; /* bytes to cache */ - u_int32_t psize; /* page size */ - int lorder; /* byte order */ - size_t reclen; /* record length (fixed-length records) */ - u_char bval; /* delimiting byte (variable-length records */ - char *bfname; /* btree file name */ -} RECNOINFO; - -#if defined(__cplusplus) -extern "C" { -#endif -DB *dbopen (const char *, int, int, DBTYPE, const void *); - -#if defined(__cplusplus) -} -#endif -#endif /* !_DB_185_H_ */ diff --git a/db2/db_int.h b/db2/db_int.h deleted file mode 100644 index 228c7ab..0000000 --- a/db2/db_int.h +++ /dev/null @@ -1,407 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - * - * @(#)db_int.h 10.77 (Sleepycat) 1/3/99 - */ - -#ifndef _DB_INTERNAL_H_ -#define _DB_INTERNAL_H_ - -#include <db.h> /* Standard DB include file. */ -#include "queue.h" -#include "shqueue.h" - -/******************************************************* - * General purpose constants and macros. - *******************************************************/ -#define UINT16_T_MAX 0xffff /* Maximum 16 bit unsigned. */ -#define UINT32_T_MAX 0xffffffff /* Maximum 32 bit unsigned. */ - -#define DB_MIN_PGSIZE 0x000200 /* Minimum page size. */ -#define DB_MAX_PGSIZE 0x010000 /* Maximum page size. */ - -#define DB_MINCACHE 10 /* Minimum cached pages */ - -#define MEGABYTE 1048576 - -/* - * If we are unable to determine the underlying filesystem block size, use - * 8K on the grounds that most OS's use less than 8K as their VM page size. - */ -#define DB_DEF_IOSIZE (8 * 1024) - -/* - * Aligning items to particular sizes or in pages or memory. ALIGNP is a - * separate macro, as we've had to cast the pointer to different integral - * types on different architectures. - * - * We cast pointers into unsigned longs when manipulating them because C89 - * guarantees that u_long is the largest available integral type and further, - * to never generate overflows. However, neither C89 or C9X requires that - * any integer type be large enough to hold a pointer, although C9X created - * the intptr_t type, which is guaranteed to hold a pointer but may or may - * not exist. At some point in the future, we should test for intptr_t and - * use it where available. - */ -#undef ALIGNTYPE -#define ALIGNTYPE u_long -#undef ALIGNP -#define ALIGNP(value, bound) ALIGN((ALIGNTYPE)value, bound) -#undef ALIGN -#define ALIGN(value, bound) (((value) + (bound) - 1) & ~((bound) - 1)) - -/* - * There are several on-page structures that are declared to have a number of - * fields followed by a variable length array of items. The structure size - * without including the variable length array or the address of the first of - * those elements can be found using SSZ. - * - * This macro can also be used to find the offset of a structure element in a - * structure. This is used in various places to copy structure elements from - * unaligned memory references, e.g., pointers into a packed page. - * - * There are two versions because compilers object if you take the address of - * an array. - */ -#undef SSZ -#define SSZ(name, field) ((int)&(((name *)0)->field)) - -#undef SSZA -#define SSZA(name, field) ((int)&(((name *)0)->field[0])) - -/* Macros to return per-process address, offsets based on shared regions. */ -#define R_ADDR(base, offset) ((void *)((u_int8_t *)((base)->addr) + offset)) -#define R_OFFSET(base, p) ((u_int8_t *)(p) - (u_int8_t *)(base)->addr) - -#define DB_DEFAULT 0x000000 /* No flag was specified. */ - -/* Structure used to print flag values. */ -typedef struct __fn { - u_int32_t mask; /* Flag value. */ - const char *name; /* Flag name. */ -} FN; - -/* Set, clear and test flags. */ -#define F_SET(p, f) (p)->flags |= (f) -#define F_CLR(p, f) (p)->flags &= ~(f) -#define F_ISSET(p, f) ((p)->flags & (f)) -#define LF_SET(f) (flags |= (f)) -#define LF_CLR(f) (flags &= ~(f)) -#define LF_ISSET(f) (flags & (f)) - -/* - * Panic check: - * All interfaces check the panic flag, if it's set, the tree is dead. - */ -#define DB_PANIC_CHECK(dbp) { \ - if ((dbp)->dbenv != NULL && (dbp)->dbenv->db_panic != 0) \ - return (DB_RUNRECOVERY); \ -} - -/* Display separator string. */ -#undef DB_LINE -#define DB_LINE "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=" - -/* Unused, or not-used-yet variable. "Shut that bloody compiler up!" */ -#define COMPQUIET(n, v) (n) = (v) - -/* - * Purify and similar run-time tools complain about unitialized reads/writes - * for structure fields whose only purpose is padding. - */ -#define UMRW(v) (v) = 0 - -/* - * Win16 needs specific syntax on callback functions. Nobody else cares. - */ -#ifndef DB_CALLBACK -#define DB_CALLBACK /* Nothing. */ -#endif - -/******************************************************* - * Files. - *******************************************************/ - /* - * We use 1024 as the maximum path length. It's too hard to figure out what - * the real path length is, as it was traditionally stored in <sys/param.h>, - * and that file isn't always available. - */ -#undef MAXPATHLEN -#define MAXPATHLEN 1024 - -#define PATH_DOT "." /* Current working directory. */ -#define PATH_SEPARATOR "/" /* Path separator character. */ - -/******************************************************* - * Mutex support. - *******************************************************/ -typedef u_int32_t tsl_t; - -/* - * !!! - * Various systems require different alignments for mutexes (the worst we've - * seen so far is 16-bytes on some HP architectures). The mutex (tsl_t) must - * be first in the db_mutex_t structure, which must itself be first in the - * region. This ensures the alignment is as returned by mmap(2), which should - * be sufficient. All other mutex users must ensure proper alignment locally. - */ -#define MUTEX_ALIGNMENT 1 - -/* - * The offset of a mutex in memory. - * - * !!! - * Not an off_t, so backing file offsets MUST be less than 4Gb. See the - * off field of the db_mutex_t as well. - */ -#define MUTEX_LOCK_OFFSET(a, b) ((u_int32_t)((u_int8_t *)b - (u_int8_t *)a)) - -typedef struct _db_mutex_t { -#ifdef HAVE_SPINLOCKS - tsl_t tsl_resource; /* Resource test and set. */ -#ifdef DIAGNOSTIC - u_int32_t pid; /* Lock holder: 0 or process pid. */ -#endif -#else - u_int32_t off; /* Backing file offset. */ - u_int32_t pid; /* Lock holder: 0 or process pid. */ -#endif - u_int32_t spins; /* Spins before block. */ - u_int32_t mutex_set_wait; /* Granted after wait. */ - u_int32_t mutex_set_nowait; /* Granted without waiting. */ -} db_mutex_t; - -#include "mutex_ext.h" - -/******************************************************* - * Access methods. - *******************************************************/ -/* Lock/unlock a DB thread. */ -#define DB_THREAD_LOCK(dbp) \ - if (F_ISSET(dbp, DB_AM_THREAD)) \ - (void)__db_mutex_lock((db_mutex_t *)(dbp)->mutexp, -1); -#define DB_THREAD_UNLOCK(dbp) \ - if (F_ISSET(dbp, DB_AM_THREAD)) \ - (void)__db_mutex_unlock((db_mutex_t *)(dbp)->mutexp, -1); - -/******************************************************* - * Environment. - *******************************************************/ -/* Type passed to __db_appname(). */ -typedef enum { - DB_APP_NONE=0, /* No type (region). */ - DB_APP_DATA, /* Data file. */ - DB_APP_LOG, /* Log file. */ - DB_APP_TMP /* Temporary file. */ -} APPNAME; - -/******************************************************* - * Shared memory regions. - *******************************************************/ -/* - * The shared memory regions share an initial structure so that the general - * region code can handle races between the region being deleted and other - * processes waiting on the region mutex. - * - * !!! - * Note, the mutex must be the first entry in the region; see comment above. - */ -typedef struct _rlayout { - db_mutex_t lock; /* Region mutex. */ -#define DB_REGIONMAGIC 0x120897 - u_int32_t valid; /* Valid magic number. */ - u_int32_t refcnt; /* Region reference count. */ - size_t size; /* Region length. */ - int majver; /* Major version number. */ - int minver; /* Minor version number. */ - int patch; /* Patch version number. */ - int panic; /* Region is dead. */ -#define INVALID_SEGID -1 - int segid; /* shmget(2) ID, or Win16 segment ID. */ - -#define REGION_ANONYMOUS 0x01 /* Region is/should be in anon mem. */ - u_int32_t flags; -} RLAYOUT; - -/* - * DB creates all regions on 4K boundaries out of sheer paranoia, so that - * we don't make the underlying VM unhappy. - */ -#define DB_VMPAGESIZE (4 * 1024) -#define DB_ROUNDOFF(n, round) { \ - (n) += (round) - 1; \ - (n) -= (n) % (round); \ -} - -/* - * The interface to region attach is nasty, there is a lot of complex stuff - * going on, which has to be retained between create/attach and detach. The - * REGINFO structure keeps track of it. - */ -struct __db_reginfo; typedef struct __db_reginfo REGINFO; -struct __db_reginfo { - /* Arguments. */ - DB_ENV *dbenv; /* Region naming info. */ - APPNAME appname; /* Region naming info. */ - char *path; /* Region naming info. */ - const char *file; /* Region naming info. */ - int mode; /* Region mode, if a file. */ - size_t size; /* Region size. */ - u_int32_t dbflags; /* Region file open flags, if a file. */ - - /* Results. */ - char *name; /* Region name. */ - void *addr; /* Region address. */ - int fd; /* Fcntl(2) locking file descriptor. - NB: this is only valid if a regular - file is backing the shared region, - and mmap(2) is being used to map it - into our address space. */ - int segid; /* shmget(2) ID, or Win16 segment ID. */ - void *wnt_handle; /* Win/NT HANDLE. */ - - /* Shared flags. */ -/* 0x0001 COMMON MASK with RLAYOUT structure. */ -#define REGION_CANGROW 0x0002 /* Can grow. */ -#define REGION_CREATED 0x0004 /* Created. */ -#define REGION_HOLDINGSYS 0x0008 /* Holding system resources. */ -#define REGION_LASTDETACH 0x0010 /* Delete on last detach. */ -#define REGION_MALLOC 0x0020 /* Created in malloc'd memory. */ -#define REGION_PRIVATE 0x0040 /* Private to thread/process. */ -#define REGION_REMOVED 0x0080 /* Already deleted. */ -#define REGION_SIZEDEF 0x0100 /* Use default region size if exists. */ - u_int32_t flags; -}; - -/******************************************************* - * Mpool. - *******************************************************/ -/* - * File types for DB access methods. Negative numbers are reserved to DB. - */ -#define DB_FTYPE_BTREE -1 /* Btree. */ -#define DB_FTYPE_HASH -2 /* Hash. */ - -/* Structure used as the DB pgin/pgout pgcookie. */ -typedef struct __dbpginfo { - size_t db_pagesize; /* Underlying page size. */ - int needswap; /* If swapping required. */ -} DB_PGINFO; - -/******************************************************* - * Log. - *******************************************************/ -/* Initialize an LSN to 'zero'. */ -#define ZERO_LSN(LSN) { \ - (LSN).file = 0; \ - (LSN).offset = 0; \ -} - -/* Return 1 if LSN is a 'zero' lsn, otherwise return 0. */ -#define IS_ZERO_LSN(LSN) ((LSN).file == 0) - -/* Test if we need to log a change. */ -#define DB_LOGGING(dbc) \ - (F_ISSET((dbc)->dbp, DB_AM_LOGGING) && !F_ISSET(dbc, DBC_RECOVER)) - -#ifdef DIAGNOSTIC -/* - * Debugging macro to log operations. - * If DEBUG_WOP is defined, log operations that modify the database. - * If DEBUG_ROP is defined, log operations that read the database. - * - * D dbp - * T txn - * O operation (string) - * K key - * A data - * F flags - */ -#define LOG_OP(C, T, O, K, A, F) { \ - DB_LSN _lsn; \ - DBT _op; \ - if (DB_LOGGING((C))) { \ - memset(&_op, 0, sizeof(_op)); \ - _op.data = O; \ - _op.size = strlen(O) + 1; \ - (void)__db_debug_log((C)->dbp->dbenv->lg_info, \ - T, &_lsn, 0, &_op, (C)->dbp->log_fileid, K, A, F); \ - } \ -} -#ifdef DEBUG_ROP -#define DEBUG_LREAD(C, T, O, K, A, F) LOG_OP(C, T, O, K, A, F) -#else -#define DEBUG_LREAD(C, T, O, K, A, F) -#endif -#ifdef DEBUG_WOP -#define DEBUG_LWRITE(C, T, O, K, A, F) LOG_OP(C, T, O, K, A, F) -#else -#define DEBUG_LWRITE(C, T, O, K, A, F) -#endif -#else -#define DEBUG_LREAD(C, T, O, K, A, F) -#define DEBUG_LWRITE(C, T, O, K, A, F) -#endif /* DIAGNOSTIC */ - -/******************************************************* - * Transactions and recovery. - *******************************************************/ -/* - * Out of band value for a lock. The locks are returned to callers as offsets - * into the lock regions. Since the RLAYOUT structure begins all regions, an - * offset of 0 is guaranteed not to be a valid lock. - */ -#define LOCK_INVALID 0 - -/* The structure allocated for every transaction. */ -struct __db_txn { - DB_TXNMGR *mgrp; /* Pointer to transaction manager. */ - DB_TXN *parent; /* Pointer to transaction's parent. */ - DB_LSN last_lsn; /* Lsn of last log write. */ - u_int32_t txnid; /* Unique transaction id. */ - size_t off; /* Detail structure within region. */ - TAILQ_ENTRY(__db_txn) links; /* Links transactions off manager. */ - TAILQ_HEAD(__kids, __db_txn) kids; /* Child transactions. */ - TAILQ_ENTRY(__db_txn) klinks; /* Links child transactions. */ - -#define TXN_MALLOC 0x01 /* Structure allocated by TXN system. */ - u_int32_t flags; -}; - -/******************************************************* - * Global variables. - *******************************************************/ -/* - * !!! - * Initialized in os/os_config.c, don't change this unless you change it - * as well. - */ - -struct __rmname { - char *dbhome; - int rmid; - TAILQ_ENTRY(__rmname) links; -}; - -typedef struct __db_globals { - int db_mutexlocks; /* DB_MUTEXLOCKS */ - int db_pageyield; /* DB_PAGEYIELD */ - int db_region_anon; /* DB_REGION_ANON, DB_REGION_NAME */ - int db_region_init; /* DB_REGION_INIT */ - int db_tsl_spins; /* DB_TSL_SPINS */ - /* XA: list of opened environments. */ - TAILQ_HEAD(__db_envq, __db_env) db_envq; - /* XA: list of id to dbhome mappings. */ - TAILQ_HEAD(__db_nameq, __rmname) db_nameq; -} DB_GLOBALS; - -extern DB_GLOBALS __db_global_values; -#define DB_GLOBAL(v) __db_global_values.v - -#include "os.h" -#include "os_ext.h" - -#endif /* !_DB_INTERNAL_H_ */ diff --git a/db2/hash/hash.c b/db2/hash/hash.c deleted file mode 100644 index 0d202fc..0000000 --- a/db2/hash/hash.c +++ /dev/null @@ -1,1337 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994 - * Margo Seltzer. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994 - * 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[] = "@(#)hash.c 10.63 (Sleepycat) 12/11/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#endif - -#include "db_int.h" -#include "shqueue.h" -#include "db_page.h" -#include "db_am.h" -#include "db_ext.h" -#include "hash.h" -#include "btree.h" -#include "log.h" -#include "db_shash.h" -#include "lock.h" -#include "lock_ext.h" - -static int __ham_c_close __P((DBC *)); -static int __ham_c_del __P((DBC *, u_int32_t)); -static int __ham_c_destroy __P((DBC *)); -static int __ham_c_get __P((DBC *, DBT *, DBT *, u_int32_t)); -static int __ham_c_put __P((DBC *, DBT *, DBT *, u_int32_t)); -static int __ham_delete __P((DB *, DB_TXN *, DBT *, u_int32_t)); -static int __ham_dup_return __P((DBC *, DBT *, u_int32_t)); -static int __ham_expand_table __P((DBC *)); -static void __ham_init_htab __P((DBC *, u_int32_t, u_int32_t)); -static int __ham_lookup __P((DBC *, const DBT *, u_int32_t, db_lockmode_t)); -static int __ham_overwrite __P((DBC *, DBT *)); - -/************************** INTERFACE ROUTINES ***************************/ -/* OPEN/CLOSE */ - -/* - * __ham_open -- - * - * PUBLIC: int __ham_open __P((DB *, DB_INFO *)); - */ -int -__ham_open(dbp, dbinfo) - DB *dbp; - DB_INFO *dbinfo; -{ - DB_ENV *dbenv; - DBC *dbc; - HASH_CURSOR *hcp; - int file_existed, ret; - - dbc = NULL; - dbenv = dbp->dbenv; - - /* Set the hash function if specified by the user. */ - if (dbinfo != NULL && dbinfo->h_hash != NULL) - dbp->h_hash = dbinfo->h_hash; - - /* - * Initialize the remaining fields of the dbp. The only function - * that differs from the default set is __ham_stat(). - */ - dbp->internal = NULL; - dbp->am_close = __ham_close; - dbp->del = __ham_delete; - dbp->stat = __ham_stat; - - /* Get a cursor we can use for the rest of this function. */ - if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0) - goto out; - - hcp = (HASH_CURSOR *)dbc->internal; - GET_META(dbp, hcp, ret); - if (ret != 0) - goto out; - - /* - * If this is a new file, initialize it, and put it back dirty. - */ - - /* Initialize the hdr structure */ - if (hcp->hdr->magic == DB_HASHMAGIC) { - file_existed = 1; - /* File exists, verify the data in the header. */ - if (dbp->h_hash == NULL) - dbp->h_hash = - hcp->hdr->version < 5 ? __ham_func4 : __ham_func5; - if (dbp->h_hash(CHARKEY, sizeof(CHARKEY)) != - hcp->hdr->h_charkey) { - __db_err(dbp->dbenv, "hash: incompatible hash function"); - ret = EINVAL; - goto out; - } - if (F_ISSET(hcp->hdr, DB_HASH_DUP)) - F_SET(dbp, DB_AM_DUP); - } else { - /* - * File does not exist, we must initialize the header. If - * locking is enabled that means getting a write lock first. - */ - file_existed = 0; - if (F_ISSET(dbp, DB_AM_LOCKING) && - ((ret = lock_put(dbenv->lk_info, hcp->hlock)) != 0 || - (ret = lock_get(dbenv->lk_info, dbc->locker, 0, - &dbc->lock_dbt, DB_LOCK_WRITE, &hcp->hlock)) != 0)) { - if (ret < 0) - ret = EAGAIN; - goto out; - } - - __ham_init_htab(dbc, dbinfo != NULL ? dbinfo->h_nelem : 0, - dbinfo != NULL ? dbinfo->h_ffactor : 0); - if (F_ISSET(dbp, DB_AM_DUP)) - F_SET(hcp->hdr, DB_HASH_DUP); - if ((ret = __ham_dirty_page(dbp, (PAGE *)hcp->hdr)) != 0) - goto out; - } - - /* Release the meta data page */ - RELEASE_META(dbp, hcp); - if ((ret = dbc->c_close(dbc)) != 0) - goto out; - - /* Sync the file so that we know that the meta data goes to disk. */ - if (!file_existed && (ret = dbp->sync(dbp, 0)) != 0) - goto out; - return (0); - -out: (void)__ham_close(dbp); - return (ret); -} - -/* - * PUBLIC: int __ham_close __P((DB *)); - */ -int -__ham_close(dbp) - DB *dbp; -{ - COMPQUIET(dbp, NULL); - return (0); -} - -/************************** LOCAL CREATION ROUTINES **********************/ -/* - * Returns 0 on No Error - */ -static void -__ham_init_htab(dbc, nelem, ffactor) - DBC *dbc; - u_int32_t nelem, ffactor; -{ - DB *dbp; - HASH_CURSOR *hcp; - int32_t l2, nbuckets; - - hcp = (HASH_CURSOR *)dbc->internal; - dbp = dbc->dbp; - memset(hcp->hdr, 0, sizeof(HASHHDR)); - hcp->hdr->ffactor = ffactor; - hcp->hdr->pagesize = dbp->pgsize; - ZERO_LSN(hcp->hdr->lsn); - hcp->hdr->magic = DB_HASHMAGIC; - hcp->hdr->version = DB_HASHVERSION; - - if (dbp->h_hash == NULL) - dbp->h_hash = hcp->hdr->version < 5 ? __ham_func4 : __ham_func5; - hcp->hdr->h_charkey = dbp->h_hash(CHARKEY, sizeof(CHARKEY)); - if (nelem != 0 && hcp->hdr->ffactor != 0) { - nelem = (nelem - 1) / hcp->hdr->ffactor + 1; - l2 = __db_log2(nelem > 2 ? nelem : 2); - } else - l2 = 2; - - nbuckets = 1 << l2; - - hcp->hdr->ovfl_point = l2; - hcp->hdr->last_freed = PGNO_INVALID; - - hcp->hdr->max_bucket = hcp->hdr->high_mask = nbuckets - 1; - hcp->hdr->low_mask = (nbuckets >> 1) - 1; - memcpy(hcp->hdr->uid, dbp->fileid, DB_FILE_ID_LEN); -} - -static int -__ham_delete(dbp, txn, key, flags) - DB *dbp; - DB_TXN *txn; - DBT *key; - u_int32_t flags; -{ - DBC *dbc; - HASH_CURSOR *hcp; - int ret, tret; - - DB_PANIC_CHECK(dbp); - - if ((ret = - __db_delchk(dbp, key, flags, F_ISSET(dbp, DB_AM_RDONLY))) != 0) - return (ret); - - if ((ret = dbp->cursor(dbp, txn, &dbc, DB_WRITELOCK)) != 0) - return (ret); - - DEBUG_LWRITE(dbc, txn, "ham_delete", key, NULL, flags); - - hcp = (HASH_CURSOR *)dbc->internal; - GET_META(dbp, hcp, ret); - if (ret != 0) - goto out; - - hcp->stats.hash_deleted++; - if ((ret = __ham_lookup(dbc, key, 0, DB_LOCK_WRITE)) == 0) { - if (F_ISSET(hcp, H_OK)) - ret = __ham_del_pair(dbc, 1); - else - ret = DB_NOTFOUND; - } - - RELEASE_META(dbp, hcp); -out: if ((tret = dbc->c_close(dbc)) != 0 && ret == 0) - ret = tret; - return (ret); -} - -/* ****************** CURSORS ********************************** */ -/* - * __ham_c_init -- - * Initialize the hash-specific portion of a cursor. - * - * PUBLIC: int __ham_c_init __P((DBC *)); - */ -int -__ham_c_init(dbc) - DBC *dbc; - { - HASH_CURSOR *new_curs; - int ret; - - if ((ret = __os_calloc(1, sizeof(struct cursor_t), &new_curs)) != 0) - return (ret); - if ((ret = - __os_malloc(dbc->dbp->pgsize, NULL, &new_curs->split_buf)) != 0) { - __os_free(new_curs, sizeof(*new_curs)); - return (ret); - } - - new_curs->dbc = dbc; - - dbc->internal = new_curs; - dbc->c_am_close = __ham_c_close; - dbc->c_am_destroy = __ham_c_destroy; - dbc->c_del = __ham_c_del; - dbc->c_get = __ham_c_get; - dbc->c_put = __ham_c_put; - - __ham_item_init(new_curs); - - return (0); -} - -/* - * __ham_c_close -- - * Close down the cursor from a single use. - */ -static int -__ham_c_close(dbc) - DBC *dbc; -{ - int ret; - - if ((ret = __ham_item_done(dbc, 0)) != 0) - return (ret); - - __ham_item_init((HASH_CURSOR *)dbc->internal); - return (0); -} - -/* - * __ham_c_destroy -- - * Cleanup the access method private part of a cursor. - */ -static int -__ham_c_destroy(dbc) - DBC *dbc; -{ - HASH_CURSOR *hcp; - - hcp = (HASH_CURSOR *)dbc->internal; - if (hcp->split_buf != NULL) - __os_free(hcp->split_buf, dbc->dbp->pgsize); - __os_free(hcp, sizeof(HASH_CURSOR)); - - return (0); -} - -static int -__ham_c_del(dbc, flags) - DBC *dbc; - u_int32_t flags; -{ - DB *dbp; - DBT repldbt; - HASH_CURSOR *hcp; - HASH_CURSOR save_curs; - db_pgno_t ppgno, chg_pgno; - int ret, t_ret; - - DEBUG_LWRITE(dbc, dbc->txn, "ham_c_del", NULL, NULL, flags); - dbp = dbc->dbp; - DB_PANIC_CHECK(dbp); - hcp = (HASH_CURSOR *)dbc->internal; - - if ((ret = __db_cdelchk(dbc->dbp, flags, - F_ISSET(dbc->dbp, DB_AM_RDONLY), IS_VALID(hcp))) != 0) - return (ret); - - if (F_ISSET(hcp, H_DELETED)) - return (DB_NOTFOUND); - - /* - * If we are in the concurrent DB product and this cursor - * is not a write cursor, then this request is invalid. - * If it is a simple write cursor, then we need to upgrade its - * lock. - */ - if (F_ISSET(dbp, DB_AM_CDB)) { - /* Make sure it's a valid update cursor. */ - if (!F_ISSET(dbc, DBC_RMW | DBC_WRITER)) - return (EINVAL); - - if (F_ISSET(dbc, DBC_RMW) && - (ret = lock_get(dbp->dbenv->lk_info, dbc->locker, - DB_LOCK_UPGRADE, &dbc->lock_dbt, DB_LOCK_WRITE, - &dbc->mylock)) != 0) - return (EAGAIN); - } - - GET_META(dbp, hcp, ret); - if (ret != 0) - return (ret); - - SAVE_CURSOR(hcp, &save_curs); - hcp->stats.hash_deleted++; - - if ((ret = __ham_get_cpage(dbc, DB_LOCK_WRITE)) != 0) - goto out; - if (F_ISSET(hcp, H_ISDUP) && hcp->dpgno != PGNO_INVALID) { - /* - * We are about to remove a duplicate from offpage. - * - * There are 4 cases. - * 1. We will remove an item on a page, but there are more - * items on that page. - * 2. We will remove the last item on a page, but there is a - * following page of duplicates. - * 3. We will remove the last item on a page, this page was the - * last page in a duplicate set, but there were dups before - * it. - * 4. We will remove the last item on a page, removing the last - * duplicate. - * In case 1 hcp->dpagep is unchanged. - * In case 2 hcp->dpagep comes back pointing to the next dup - * page. - * In case 3 hcp->dpagep comes back NULL. - * In case 4 hcp->dpagep comes back NULL. - * - * Case 4 results in deleting the pair off the master page. - * The normal code for doing this knows how to delete the - * duplicates, so we will handle this case in the normal code. - */ - ppgno = PREV_PGNO(hcp->dpagep); - if (ppgno == PGNO_INVALID && - NEXT_PGNO(hcp->dpagep) == PGNO_INVALID && - NUM_ENT(hcp->dpagep) == 1) - goto normal; - - /* Remove item from duplicate page. */ - chg_pgno = hcp->dpgno; - if ((ret = __db_drem(dbc, - &hcp->dpagep, hcp->dndx, __ham_del_page)) != 0) - goto out; - - if (hcp->dpagep == NULL) { - if (ppgno != PGNO_INVALID) { /* Case 3 */ - hcp->dpgno = ppgno; - if ((ret = __ham_get_cpage(dbc, - DB_LOCK_READ)) != 0) - goto out; - hcp->dndx = NUM_ENT(hcp->dpagep); - F_SET(hcp, H_DELETED); - } else { /* Case 4 */ - ret = __ham_del_pair(dbc, 1); - hcp->dpgno = PGNO_INVALID; - /* - * Delpair updated the cursor queue, so we - * don't have to do that here. - */ - chg_pgno = PGNO_INVALID; - } - } else if (PGNO(hcp->dpagep) != hcp->dpgno) { - hcp->dndx = 0; /* Case 2 */ - hcp->dpgno = PGNO(hcp->dpagep); - if (ppgno == PGNO_INVALID) - memcpy(HOFFDUP_PGNO(P_ENTRY(hcp->pagep, - H_DATAINDEX(hcp->bndx))), - &hcp->dpgno, sizeof(db_pgno_t)); - /* - * We need to put the master page here, because - * although we have a duplicate page, the master - * page is dirty, and ham_item_done assumes that - * if you have a duplicate page, it's the only one - * that can be dirty. - */ - ret = __ham_put_page(dbp, hcp->pagep, 1); - hcp->pagep = NULL; - F_SET(hcp, H_DELETED); - } else /* Case 1 */ - F_SET(hcp, H_DELETED); - if (chg_pgno != PGNO_INVALID) - __ham_c_update(hcp, chg_pgno, 0, 0, 1); - } else if (F_ISSET(hcp, H_ISDUP)) { /* on page */ - if (hcp->dup_off == 0 && DUP_SIZE(hcp->dup_len) == - LEN_HDATA(hcp->pagep, hcp->hdr->pagesize, hcp->bndx)) - ret = __ham_del_pair(dbc, 1); - else { - repldbt.flags = 0; - F_SET(&repldbt, DB_DBT_PARTIAL); - repldbt.doff = hcp->dup_off; - repldbt.dlen = DUP_SIZE(hcp->dup_len); - repldbt.size = 0; - repldbt.data = - HKEYDATA_DATA(H_PAIRDATA(hcp->pagep, hcp->bndx)); - ret = __ham_replpair(dbc, &repldbt, 0); - hcp->dup_tlen -= DUP_SIZE(hcp->dup_len); - F_SET(hcp, H_DELETED); - __ham_c_update(hcp, hcp->pgno, - DUP_SIZE(hcp->dup_len), 0, 1); - } - - } else - /* Not a duplicate */ -normal: ret = __ham_del_pair(dbc, 1); - -out: if ((t_ret = __ham_item_done(dbc, ret == 0)) != 0 && ret == 0) - ret = t_ret; - RELEASE_META(dbp, hcp); - RESTORE_CURSOR(dbp, hcp, &save_curs, ret); - if (F_ISSET(dbp, DB_AM_CDB) && F_ISSET(dbc, DBC_RMW)) - (void)__lock_downgrade(dbp->dbenv->lk_info, dbc->mylock, - DB_LOCK_IWRITE, 0); - return (ret); -} - -static int -__ham_c_get(dbc, key, data, flags) - DBC *dbc; - DBT *key; - DBT *data; - u_int32_t flags; -{ - DB *dbp; - HASH_CURSOR *hcp, save_curs; - db_lockmode_t lock_type; - int get_key, ret, t_ret; - - DEBUG_LREAD(dbc, dbc->txn, "ham_c_get", - flags == DB_SET || flags == DB_SET_RANGE ? key : NULL, - NULL, flags); - - hcp = (HASH_CURSOR *)dbc->internal; - dbp = dbc->dbp; - DB_PANIC_CHECK(dbp); - SAVE_CURSOR(hcp, &save_curs); - if ((ret = - __db_cgetchk(dbp, key, data, flags, IS_VALID(hcp))) != 0) - return (ret); - - /* Clear OR'd in additional bits so we can check for flag equality. */ - if (LF_ISSET(DB_RMW)) { - lock_type = DB_LOCK_WRITE; - LF_CLR(DB_RMW); - } else - lock_type = DB_LOCK_READ; - - GET_META(dbp, hcp, ret); - if (ret != 0) - return (ret); - hcp->stats.hash_get++; - hcp->seek_size = 0; - - ret = 0; - get_key = 1; - switch (flags) { - case DB_PREV: - if (hcp->bucket != BUCKET_INVALID) { - ret = __ham_item_prev(dbc, lock_type); - break; - } - /* FALLTHROUGH */ - case DB_LAST: - ret = __ham_item_last(dbc, lock_type); - break; - case DB_FIRST: - ret = __ham_item_first(dbc, lock_type); - break; - case DB_NEXT_DUP: - if (hcp->bucket == BUCKET_INVALID) - ret = EINVAL; - else { - F_SET(hcp, H_DUPONLY); - ret = __ham_item_next(dbc, lock_type); - } - break; - case DB_NEXT: - if (hcp->bucket == BUCKET_INVALID) - hcp->bucket = 0; - ret = __ham_item_next(dbc, lock_type); - break; - case DB_SET: - case DB_SET_RANGE: - case DB_GET_BOTH: - if (F_ISSET(dbc, DBC_CONTINUE)) { - F_SET(hcp, H_DUPONLY); - ret = __ham_item_next(dbc, lock_type); - } else if (F_ISSET(dbc, DBC_KEYSET)) - ret = __ham_item(dbc, lock_type); - else - ret = __ham_lookup(dbc, key, 0, lock_type); - get_key = 0; - break; - case DB_CURRENT: - if (F_ISSET(hcp, H_DELETED)) { - ret = DB_KEYEMPTY; - goto out; - } - - ret = __ham_item(dbc, lock_type); - break; - } - - /* - * Must always enter this loop to do error handling and - * check for big key/data pair. - */ - while (1) { - if (ret != 0 && ret != DB_NOTFOUND) - goto out1; - else if (F_ISSET(hcp, H_OK)) { - /* Get the key. */ - if (get_key && (ret = __db_ret(dbp, hcp->pagep, - H_KEYINDEX(hcp->bndx), key, &dbc->rkey.data, - &dbc->rkey.size)) != 0) - goto out1; - - ret = __ham_dup_return(dbc, data, flags); - break; - } else if (!F_ISSET(hcp, H_NOMORE)) { - abort(); - break; - } - - /* - * Ran out of entries in a bucket; change buckets. - */ - switch (flags) { - case DB_LAST: - case DB_PREV: - ret = __ham_item_done(dbc, 0); - if (hcp->bucket == 0) { - ret = DB_NOTFOUND; - goto out1; - } - hcp->bucket--; - hcp->bndx = NDX_INVALID; - if (ret == 0) - ret = __ham_item_prev(dbc, lock_type); - break; - case DB_FIRST: - case DB_NEXT: - ret = __ham_item_done(dbc, 0); - hcp->bndx = NDX_INVALID; - hcp->bucket++; - hcp->pgno = PGNO_INVALID; - hcp->pagep = NULL; - if (hcp->bucket > hcp->hdr->max_bucket) { - ret = DB_NOTFOUND; - goto out1; - } - if (ret == 0) - ret = __ham_item_next(dbc, lock_type); - break; - case DB_GET_BOTH: - case DB_NEXT_DUP: - case DB_SET: - case DB_SET_RANGE: - /* Key not found. */ - ret = DB_NOTFOUND; - goto out1; - } - } -out1: if ((t_ret = __ham_item_done(dbc, 0)) != 0 && ret == 0) - ret = t_ret; -out: RELEASE_META(dbp, hcp); - RESTORE_CURSOR(dbp, hcp, &save_curs, ret); - return (ret); -} - -static int -__ham_c_put(dbc, key, data, flags) - DBC *dbc; - DBT *key; - DBT *data; - u_int32_t flags; -{ - DB *dbp; - DBT tmp_val, *myval; - HASH_CURSOR *hcp, save_curs; - u_int32_t nbytes; - int ret, t_ret; - - dbp = dbc->dbp; - DB_PANIC_CHECK(dbp); - DEBUG_LWRITE(dbc, dbc->txn, "ham_c_put", - flags == DB_KEYFIRST || flags == DB_KEYLAST ? key : NULL, - data, flags); - hcp = (HASH_CURSOR *)dbc->internal; - - if ((ret = __db_cputchk(dbp, key, data, flags, - F_ISSET(dbp, DB_AM_RDONLY), IS_VALID(hcp))) != 0) - return (ret); - - if (F_ISSET(hcp, H_DELETED) && - flags != DB_KEYFIRST && flags != DB_KEYLAST) - return (DB_NOTFOUND); - - /* - * If we are in the concurrent DB product and this cursor - * is not a write cursor, then this request is invalid. - * If it is a simple write cursor, then we need to upgrade its - * lock. - */ - if (F_ISSET(dbp, DB_AM_CDB)) { - /* Make sure it's a valid update cursor. */ - if (!F_ISSET(dbc, DBC_RMW | DBC_WRITER)) - return (EINVAL); - - if (F_ISSET(dbc, DBC_RMW) && - (ret = lock_get(dbp->dbenv->lk_info, dbc->locker, - DB_LOCK_UPGRADE, &dbc->lock_dbt, DB_LOCK_WRITE, - &dbc->mylock)) != 0) - return (EAGAIN); - } - - GET_META(dbp, hcp, ret); - if (ret != 0) - return (ret); - - SAVE_CURSOR(hcp, &save_curs); - hcp->stats.hash_put++; - - switch (flags) { - case DB_KEYLAST: - case DB_KEYFIRST: - nbytes = (ISBIG(hcp, key->size) ? HOFFPAGE_PSIZE : - HKEYDATA_PSIZE(key->size)) + - (ISBIG(hcp, data->size) ? HOFFPAGE_PSIZE : - HKEYDATA_PSIZE(data->size)); - if ((ret = __ham_lookup(dbc, - key, nbytes, DB_LOCK_WRITE)) == DB_NOTFOUND) { - ret = 0; - if (hcp->seek_found_page != PGNO_INVALID && - hcp->seek_found_page != hcp->pgno) { - if ((ret = __ham_item_done(dbc, 0)) != 0) - goto out; - hcp->pgno = hcp->seek_found_page; - hcp->bndx = NDX_INVALID; - } - - if (F_ISSET(data, DB_DBT_PARTIAL) && data->doff != 0) { - /* - * A partial put, but the key does not exist - * and we are not beginning the write at 0. - * We must create a data item padded up to doff - * and then write the new bytes represented by - * val. - */ - if ((ret = __ham_init_dbt(&tmp_val, - data->size + data->doff, - &dbc->rdata.data, &dbc->rdata.size)) == 0) { - memset(tmp_val.data, 0, data->doff); - memcpy((u_int8_t *)tmp_val.data + - data->doff, data->data, data->size); - myval = &tmp_val; - } - } else - myval = (DBT *)data; - - if (ret == 0) - ret = __ham_add_el(dbc, key, myval, H_KEYDATA); - goto done; - } - break; - case DB_BEFORE: - case DB_AFTER: - case DB_CURRENT: - ret = __ham_item(dbc, DB_LOCK_WRITE); - break; - } - - if (ret == 0) { - if ((flags == DB_CURRENT && !F_ISSET(hcp, H_ISDUP)) || - ((flags == DB_KEYFIRST || flags == DB_KEYLAST) && - !F_ISSET(dbp, DB_AM_DUP))) - ret = __ham_overwrite(dbc, data); - else - ret = __ham_add_dup(dbc, data, flags); - } - -done: if (ret == 0 && F_ISSET(hcp, H_EXPAND)) { - ret = __ham_expand_table(dbc); - F_CLR(hcp, H_EXPAND); - } - - if ((t_ret = __ham_item_done(dbc, ret == 0)) != 0 && ret == 0) - ret = t_ret; - -out: RELEASE_META(dbp, hcp); - RESTORE_CURSOR(dbp, hcp, &save_curs, ret); - if (F_ISSET(dbp, DB_AM_CDB) && F_ISSET(dbc, DBC_RMW)) - (void)__lock_downgrade(dbp->dbenv->lk_info, dbc->mylock, - DB_LOCK_IWRITE, 0); - return (ret); -} - -/********************************* UTILITIES ************************/ - -/* - * __ham_expand_table -- - */ -static int -__ham_expand_table(dbc) - DBC *dbc; -{ - DB *dbp; - HASH_CURSOR *hcp; - DB_LSN new_lsn; - u_int32_t old_bucket, new_bucket, spare_ndx; - int ret; - - dbp = dbc->dbp; - hcp = (HASH_CURSOR *)dbc->internal; - ret = 0; - DIRTY_META(dbp, hcp, ret); - if (ret) - return (ret); - - /* - * If the split point is about to increase, make sure that we - * have enough extra pages. The calculation here is weird. - * We'd like to do this after we've upped max_bucket, but it's - * too late then because we've logged the meta-data split. What - * we'll do between then and now is increment max bucket and then - * see what the log of one greater than that is; here we have to - * look at the log of max + 2. VERY NASTY STUFF. - */ - if (__db_log2(hcp->hdr->max_bucket + 2) > hcp->hdr->ovfl_point) { - /* - * We are about to shift the split point. Make sure that - * if the next doubling is going to be big (more than 8 - * pages), we have some extra pages around. - */ - if (hcp->hdr->max_bucket + 1 >= 8 && - hcp->hdr->spares[hcp->hdr->ovfl_point] < - hcp->hdr->spares[hcp->hdr->ovfl_point - 1] + - hcp->hdr->ovfl_point + 1) - __ham_init_ovflpages(dbc); - } - - /* Now we can log the meta-data split. */ - if (DB_LOGGING(dbc)) { - if ((ret = __ham_splitmeta_log(dbp->dbenv->lg_info, - dbc->txn, &new_lsn, 0, dbp->log_fileid, - hcp->hdr->max_bucket, hcp->hdr->ovfl_point, - hcp->hdr->spares[hcp->hdr->ovfl_point], - &hcp->hdr->lsn)) != 0) - return (ret); - - hcp->hdr->lsn = new_lsn; - } - - hcp->stats.hash_expansions++; - new_bucket = ++hcp->hdr->max_bucket; - old_bucket = (hcp->hdr->max_bucket & hcp->hdr->low_mask); - - /* - * If the split point is increasing, copy the current contents - * of the spare split bucket to the next bucket. - */ - spare_ndx = __db_log2(hcp->hdr->max_bucket + 1); - if (spare_ndx > hcp->hdr->ovfl_point) { - hcp->hdr->spares[spare_ndx] = - hcp->hdr->spares[hcp->hdr->ovfl_point]; - hcp->hdr->ovfl_point = spare_ndx; - } - - if (new_bucket > hcp->hdr->high_mask) { - /* Starting a new doubling */ - hcp->hdr->low_mask = hcp->hdr->high_mask; - hcp->hdr->high_mask = new_bucket | hcp->hdr->low_mask; - } - - if (BUCKET_TO_PAGE(hcp, new_bucket) > MAX_PAGES(hcp)) { - __db_err(dbp->dbenv, - "hash: Cannot allocate new bucket. Pages exhausted."); - return (ENOSPC); - } - - /* Relocate records to the new bucket */ - return (__ham_split_page(dbc, old_bucket, new_bucket)); -} - -/* - * PUBLIC: u_int32_t __ham_call_hash __P((HASH_CURSOR *, u_int8_t *, int32_t)); - */ -u_int32_t -__ham_call_hash(hcp, k, len) - HASH_CURSOR *hcp; - u_int8_t *k; - int32_t len; -{ - u_int32_t n, bucket; - - n = (u_int32_t)(hcp->dbc->dbp->h_hash(k, len)); - - bucket = n & hcp->hdr->high_mask; - if (bucket > hcp->hdr->max_bucket) - bucket = bucket & hcp->hdr->low_mask; - return (bucket); -} - -/* - * Check for duplicates, and call __db_ret appropriately. Release - * everything held by the cursor. - */ -static int -__ham_dup_return(dbc, val, flags) - DBC *dbc; - DBT *val; - u_int32_t flags; -{ - DB *dbp; - HASH_CURSOR *hcp; - PAGE *pp; - DBT *myval, tmp_val; - db_indx_t ndx; - db_pgno_t pgno; - u_int32_t off, tlen; - u_int8_t *hk, type; - int cmp, ret; - db_indx_t len; - - /* Check for duplicate and return the first one. */ - dbp = dbc->dbp; - hcp = (HASH_CURSOR *)dbc->internal; - ndx = H_DATAINDEX(hcp->bndx); - type = HPAGE_TYPE(hcp->pagep, ndx); - pp = hcp->pagep; - myval = val; - - /* - * There are 4 cases: - * 1. We are not in duplicate, simply call db_ret. - * 2. We are looking at keys and stumbled onto a duplicate. - * 3. We are in the middle of a duplicate set. (ISDUP set) - * 4. This is a duplicate and we need to return a specific item. - */ - - /* - * Here we check for the case where we just stumbled onto a - * duplicate. In this case, we do initialization and then - * let the normal duplicate code handle it. - */ - if (!F_ISSET(hcp, H_ISDUP)) { - if (type == H_DUPLICATE) { - F_SET(hcp, H_ISDUP); - hcp->dup_tlen = LEN_HDATA(hcp->pagep, - hcp->hdr->pagesize, hcp->bndx); - hk = H_PAIRDATA(hcp->pagep, hcp->bndx); - if (flags == DB_LAST || flags == DB_PREV) { - hcp->dndx = 0; - hcp->dup_off = 0; - do { - memcpy(&len, - HKEYDATA_DATA(hk) + hcp->dup_off, - sizeof(db_indx_t)); - hcp->dup_off += DUP_SIZE(len); - hcp->dndx++; - } while (hcp->dup_off < hcp->dup_tlen); - hcp->dup_off -= DUP_SIZE(len); - hcp->dndx--; - } else { - memcpy(&len, - HKEYDATA_DATA(hk), sizeof(db_indx_t)); - hcp->dup_off = 0; - hcp->dndx = 0; - } - hcp->dup_len = len; - } else if (type == H_OFFDUP) { - F_SET(hcp, H_ISDUP); - memcpy(&pgno, HOFFDUP_PGNO(P_ENTRY(hcp->pagep, ndx)), - sizeof(db_pgno_t)); - if (flags == DB_LAST || flags == DB_PREV) { - if ((ret = __db_dend(dbc, - pgno, &hcp->dpagep)) != 0) - return (ret); - hcp->dpgno = PGNO(hcp->dpagep); - hcp->dndx = NUM_ENT(hcp->dpagep) - 1; - } else if ((ret = __ham_next_cpage(dbc, - pgno, 0, H_ISDUP)) != 0) - return (ret); - } - } - - /* - * If we are retrieving a specific key/data pair, then we - * may need to adjust the cursor before returning data. - */ - if (flags == DB_GET_BOTH) { - if (F_ISSET(hcp, H_ISDUP)) { - if (hcp->dpgno != PGNO_INVALID) { - if ((ret = __db_dsearch(dbc, 0, val, - hcp->dpgno, &hcp->dndx, &hcp->dpagep, &cmp)) - != 0) - return (ret); - if (cmp == 0) - hcp->dpgno = PGNO(hcp->dpagep); - } else { - __ham_dsearch(dbc, val, &off, &cmp); - hcp->dup_off = off; - } - } else { - hk = H_PAIRDATA(hcp->pagep, hcp->bndx); - if (((HKEYDATA *)hk)->type == H_OFFPAGE) { - memcpy(&tlen, - HOFFPAGE_TLEN(hk), sizeof(u_int32_t)); - memcpy(&pgno, - HOFFPAGE_PGNO(hk), sizeof(db_pgno_t)); - if ((ret = __db_moff(dbp, val, - pgno, tlen, dbp->dup_compare, &cmp)) != 0) - return (ret); - } else { - /* - * We do not zero tmp_val since the comparison - * routines may only look at data and size. - */ - tmp_val.data = HKEYDATA_DATA(hk); - tmp_val.size = LEN_HDATA(hcp->pagep, - dbp->pgsize, hcp->bndx); - cmp = dbp->dup_compare == NULL ? - __bam_defcmp(&tmp_val, val) : - dbp->dup_compare(&tmp_val, val); - } - } - - if (cmp != 0) - return (DB_NOTFOUND); - } - - /* - * Now, everything is initialized, grab a duplicate if - * necessary. - */ - if (F_ISSET(hcp, H_ISDUP)) { - if (hcp->dpgno != PGNO_INVALID) { - pp = hcp->dpagep; - ndx = hcp->dndx; - } else { - /* - * Copy the DBT in case we are retrieving into user - * memory and we need the parameters for it. If the - * user requested a partial, then we need to adjust - * the user's parameters to get the partial of the - * duplicate which is itself a partial. - */ - memcpy(&tmp_val, val, sizeof(*val)); - if (F_ISSET(&tmp_val, DB_DBT_PARTIAL)) { - /* - * Take the user's length unless it would go - * beyond the end of the duplicate. - */ - if (tmp_val.doff + hcp->dup_off > hcp->dup_len) - tmp_val.dlen = 0; - else if (tmp_val.dlen + tmp_val.doff > - hcp->dup_len) - tmp_val.dlen = - hcp->dup_len - tmp_val.doff; - - /* - * Calculate the new offset. - */ - tmp_val.doff += hcp->dup_off; - } else { - F_SET(&tmp_val, DB_DBT_PARTIAL); - tmp_val.dlen = hcp->dup_len; - tmp_val.doff = hcp->dup_off + sizeof(db_indx_t); - } - myval = &tmp_val; - } - } - - /* - * Finally, if we had a duplicate, pp, ndx, and myval should be - * set appropriately. - */ - if ((ret = __db_ret(dbp, pp, ndx, myval, &dbc->rdata.data, - &dbc->rdata.size)) != 0) - return (ret); - - /* - * In case we sent a temporary off to db_ret, set the real - * return values. - */ - val->data = myval->data; - val->size = myval->size; - - return (0); -} - -static int -__ham_overwrite(dbc, nval) - DBC *dbc; - DBT *nval; -{ - HASH_CURSOR *hcp; - DBT *myval, tmp_val; - u_int8_t *hk; - - hcp = (HASH_CURSOR *)dbc->internal; - if (F_ISSET(dbc->dbp, DB_AM_DUP)) - return (__ham_add_dup(dbc, nval, DB_KEYLAST)); - else if (!F_ISSET(nval, DB_DBT_PARTIAL)) { - /* Put/overwrite */ - memcpy(&tmp_val, nval, sizeof(*nval)); - F_SET(&tmp_val, DB_DBT_PARTIAL); - tmp_val.doff = 0; - hk = H_PAIRDATA(hcp->pagep, hcp->bndx); - if (HPAGE_PTYPE(hk) == H_OFFPAGE) - memcpy(&tmp_val.dlen, - HOFFPAGE_TLEN(hk), sizeof(u_int32_t)); - else - tmp_val.dlen = LEN_HDATA(hcp->pagep, - hcp->hdr->pagesize,hcp->bndx); - myval = &tmp_val; - } else /* Regular partial put */ - myval = nval; - - return (__ham_replpair(dbc, myval, 0)); -} - -/* - * Given a key and a cursor, sets the cursor to the page/ndx on which - * the key resides. If the key is found, the cursor H_OK flag is set - * and the pagep, bndx, pgno (dpagep, dndx, dpgno) fields are set. - * If the key is not found, the H_OK flag is not set. If the sought - * field is non-0, the pagep, bndx, pgno (dpagep, dndx, dpgno) fields - * are set indicating where an add might take place. If it is 0, - * non of the cursor pointer field are valid. - */ -static int -__ham_lookup(dbc, key, sought, mode) - DBC *dbc; - const DBT *key; - u_int32_t sought; - db_lockmode_t mode; -{ - DB *dbp; - HASH_CURSOR *hcp; - db_pgno_t pgno; - u_int32_t tlen; - int match, ret, t_ret; - u_int8_t *hk; - - dbp = dbc->dbp; - hcp = (HASH_CURSOR *)dbc->internal; - /* - * Set up cursor so that we're looking for space to add an item - * as we cycle through the pages looking for the key. - */ - if ((ret = __ham_item_reset(dbc)) != 0) - return (ret); - hcp->seek_size = sought; - - hcp->bucket = __ham_call_hash(hcp, (u_int8_t *)key->data, key->size); - while (1) { - if ((ret = __ham_item_next(dbc, mode)) != 0) - return (ret); - - if (F_ISSET(hcp, H_NOMORE)) - break; - - hk = H_PAIRKEY(hcp->pagep, hcp->bndx); - switch (HPAGE_PTYPE(hk)) { - case H_OFFPAGE: - memcpy(&tlen, HOFFPAGE_TLEN(hk), sizeof(u_int32_t)); - if (tlen == key->size) { - memcpy(&pgno, - HOFFPAGE_PGNO(hk), sizeof(db_pgno_t)); - if ((ret = __db_moff(dbp, - key, pgno, tlen, NULL, &match)) != 0) - return (ret); - if (match == 0) { - F_SET(hcp, H_OK); - return (0); - } - } - break; - case H_KEYDATA: - if (key->size == LEN_HKEY(hcp->pagep, - hcp->hdr->pagesize, hcp->bndx) && - memcmp(key->data, - HKEYDATA_DATA(hk), key->size) == 0) { - F_SET(hcp, H_OK); - return (0); - } - break; - case H_DUPLICATE: - case H_OFFDUP: - /* - * These are errors because keys are never - * duplicated, only data items are. - */ - return (__db_pgfmt(dbp, PGNO(hcp->pagep))); - } - hcp->stats.hash_collisions++; - } - - /* - * Item was not found, adjust cursor properly. - */ - - if (sought != 0) - return (ret); - - if ((t_ret = __ham_item_done(dbc, 0)) != 0 && ret == 0) - ret = t_ret; - return (ret); -} - -/* - * Initialize a dbt using some possibly already allocated storage - * for items. - * PUBLIC: int __ham_init_dbt __P((DBT *, u_int32_t, void **, u_int32_t *)); - */ -int -__ham_init_dbt(dbt, size, bufp, sizep) - DBT *dbt; - u_int32_t size; - void **bufp; - u_int32_t *sizep; -{ - int ret; - - memset(dbt, 0, sizeof(*dbt)); - if (*sizep < size) { - if ((ret = __os_realloc(bufp, size)) != 0) { - *sizep = 0; - return (ret); - } - *sizep = size; - } - dbt->data = *bufp; - dbt->size = size; - return (0); -} - -/* - * Adjust the cursor after an insert or delete. The cursor passed is - * the one that was operated upon; we just need to check any of the - * others. - * - * len indicates the length of the item added/deleted - * add indicates if the item indicated by the cursor has just been - * added (add == 1) or deleted (add == 0). - * dup indicates if the addition occurred into a duplicate set. - * - * PUBLIC: void __ham_c_update - * PUBLIC: __P((HASH_CURSOR *, db_pgno_t, u_int32_t, int, int)); - */ -void -__ham_c_update(hcp, chg_pgno, len, add, is_dup) - HASH_CURSOR *hcp; - db_pgno_t chg_pgno; - u_int32_t len; - int add, is_dup; -{ - DB *dbp; - DBC *cp; - HASH_CURSOR *lcp; - int page_deleted; - - /* - * Regular adds are always at the end of a given page, so we never - * have to adjust anyone's cursor after a regular add. - */ - if (!is_dup && add) - return; - - /* - * Determine if a page was deleted. If this is a regular update - * (i.e., not is_dup) then the deleted page's number will be that in - * chg_pgno, and the pgno in the cursor will be different. If this - * was an onpage-duplicate, then the same conditions apply. If this - * was an off-page duplicate, then we need to verify if hcp->dpgno - * is the same (no delete) or different (delete) than chg_pgno. - */ - if (!is_dup || hcp->dpgno == PGNO_INVALID) - page_deleted = - chg_pgno != PGNO_INVALID && chg_pgno != hcp->pgno; - else - page_deleted = - chg_pgno != PGNO_INVALID && chg_pgno != hcp->dpgno; - - dbp = hcp->dbc->dbp; - DB_THREAD_LOCK(dbp); - - for (cp = TAILQ_FIRST(&dbp->active_queue); cp != NULL; - cp = TAILQ_NEXT(cp, links)) { - if (cp->internal == hcp) - continue; - - lcp = (HASH_CURSOR *)cp->internal; - - if (!is_dup && lcp->pgno != chg_pgno) - continue; - - if (is_dup) { - if (F_ISSET(hcp, H_DELETED) && lcp->pgno != chg_pgno) - continue; - if (!F_ISSET(hcp, H_DELETED) && lcp->dpgno != chg_pgno) - continue; - } - - if (page_deleted) { - if (is_dup) { - lcp->dpgno = hcp->dpgno; - lcp->dndx = hcp->dndx; - } else { - lcp->pgno = hcp->pgno; - lcp->bndx = hcp->bndx; - lcp->bucket = hcp->bucket; - } - F_CLR(lcp, H_ISDUP); - continue; - } - - if (!is_dup && lcp->bndx > hcp->bndx) - lcp->bndx--; - else if (!is_dup && lcp->bndx == hcp->bndx) - F_SET(lcp, H_DELETED); - else if (is_dup && lcp->bndx == hcp->bndx) { - /* Assign dpgno in case there was page conversion. */ - lcp->dpgno = hcp->dpgno; - if (add && lcp->dndx >= hcp->dndx ) - lcp->dndx++; - else if (!add && lcp->dndx > hcp->dndx) - lcp->dndx--; - else if (!add && lcp->dndx == hcp->dndx) - F_SET(lcp, H_DELETED); - - /* Now adjust on-page information. */ - if (lcp->dpgno == PGNO_INVALID) { - if (add) { - lcp->dup_tlen += len; - if (lcp->dndx > hcp->dndx) - lcp->dup_off += len; - } else { - lcp->dup_tlen -= len; - if (lcp->dndx > hcp->dndx) - lcp->dup_off -= len; - } - } - } - } - DB_THREAD_UNLOCK(dbp); -} diff --git a/db2/hash/hash.src b/db2/hash/hash.src deleted file mode 100644 index 8a51283..0000000 --- a/db2/hash/hash.src +++ /dev/null @@ -1,231 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - */ -/* - * Copyright (c) 1995, 1996 - * Margo Seltzer. All rights reserved. - */ -/* - * Copyright (c) 1995, 1996 - * The President and Fellows of Harvard University. 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. - * - * @(#)hash.src 10.3 (Sleepycat) 4/10/98 - */ - -/* - * This is the source file used to create the logging functions for the - * hash package. Each access method (or set of routines wishing to register - * record types with the transaction system) should have a file like this. - * Each type of log record and its parameters is defined. The basic - * format of a record definition is: - * - * BEGIN <RECORD_TYPE> - * ARG|STRING|POINTER <variable name> <variable type> <printf format> - * ... - * END - * ARG the argument is a simple parameter of the type * specified. - * DBT the argument is a DBT (db.h) containing a length and pointer. - * PTR the argument is a pointer to the data type specified; the entire - * type should be logged. - * - * There are a set of shell scripts of the form xxx.sh that generate c - * code and or h files to process these. (This is probably better done - * in a single PERL script, but for now, this works.) - * - * The DB recovery system requires the following three fields appear in - * every record, and will assign them to the per-record-type structures - * as well as making them the first parameters to the appropriate logging - * call. - * rectype: record-type, identifies the structure and log/read call - * txnid: transaction id, a DBT in this implementation - * prev: the last LSN for this transaction - */ - -/* - * Use the argument of PREFIX as the prefix for all record types, - * routines, id numbers, etc. - */ -PREFIX ham - -/* - * HASH-insdel: used for hash to insert/delete a pair of entries onto a master - * page. The pair might be regular key/data pairs or they might be the - * structures that refer to off page items, duplicates or offpage duplicates. - * opcode - PUTPAIR/DELPAIR + big masks - * fileid - identifies the file referenced - * pgno - page within file - * ndx - index on the page of the item being added (item index) - * pagelsn - lsn on the page before the update - * key - the key being inserted - * data - the data being inserted - */ -BEGIN insdel -ARG opcode u_int32_t lu -ARG fileid u_int32_t lu -ARG pgno db_pgno_t lu -ARG ndx u_int32_t lu -POINTER pagelsn DB_LSN * lu -DBT key DBT s -DBT data DBT s -END - -/* - * Used to add and remove overflow pages. - * prev_pgno is the previous page that is going to get modified to - * point to this one. If this is the first page in a chain - * then prev_pgno should be PGNO_INVALID. - * new_pgno is the page being allocated. - * next_pgno is the page that follows this one. On allocation, - * this should be PGNO_INVALID. For deletes, it may exist. - * pagelsn is the old lsn on the page. - */ -BEGIN newpage -ARG opcode u_int32_t lu -ARG fileid u_int32_t lu -ARG prev_pgno db_pgno_t lu -POINTER prevlsn DB_LSN * lu -ARG new_pgno db_pgno_t lu -POINTER pagelsn DB_LSN * lu -ARG next_pgno db_pgno_t lu -POINTER nextlsn DB_LSN * lu -END - -/* - * Splitting requires two types of log messages. The first - * logs the meta-data of the split. The second logs the - * data on the original page. To redo the split, we have - * to visit the new page (pages) and add the items back - * on the page if they are not yet there. - * For the meta-data split - * bucket: max_bucket in table before split - * ovflpoint: overflow point before split. - * spares: spares[ovflpoint] before split. - */ -BEGIN splitmeta -ARG fileid u_int32_t lu -ARG bucket u_int32_t lu -ARG ovflpoint u_int32_t lu -ARG spares u_int32_t lu -POINTER metalsn DB_LSN * lu -END - -BEGIN splitdata -ARG fileid u_int32_t lu -ARG opcode u_int32_t lu -ARG pgno db_pgno_t lu -DBT pageimage DBT s -POINTER pagelsn DB_LSN * lu -END - -/* - * HASH-replace: is used for hash to handle partial puts that only - * affect a single master page. - * fileid - identifies the file referenced - * pgno - page within file - * ndx - index on the page of the item being modified (item index) - * pagelsn - lsn on the page before the update - * off - offset in the old item where the new item is going. - * olditem - DBT that describes the part of the item being replaced. - * newitem - DBT of the new item. - * makedup - this was a replacement that made an item a duplicate. - */ -BEGIN replace -ARG fileid u_int32_t lu -ARG pgno db_pgno_t lu -ARG ndx u_int32_t lu -POINTER pagelsn DB_LSN * lu -ARG off int32_t ld -DBT olditem DBT s -DBT newitem DBT s -ARG makedup u_int32_t lu -END - -/* - * HASH-newpgno: is used to record getting/deleting a new page number. - * This doesn't require much data modification, just modifying the - * meta-data. - * pgno is the page being allocated/freed. - * free_pgno is the next_pgno on the free list. - * old_type was the type of a page being deallocated. - * old_pgno was the next page number before the deallocation. We use it - * to indicate whether we incremented the spares count or not - * during this allocation. - */ -BEGIN newpgno -ARG opcode u_int32_t lu -ARG fileid u_int32_t lu -ARG pgno db_pgno_t lu -ARG free_pgno db_pgno_t lu -ARG old_type u_int32_t lu -ARG old_pgno db_pgno_t lu -ARG new_type u_int32_t lu -POINTER pagelsn DB_LSN * lu -POINTER metalsn DB_LSN * lu -END - -/* - * ovfl: initialize a set of overflow pages. - */ -BEGIN ovfl -ARG fileid u_int32_t lu -ARG start_pgno db_pgno_t lu -ARG npages u_int32_t lu -ARG free_pgno db_pgno_t lu -ARG ovflpoint u_int32_t lu -POINTER metalsn DB_LSN * lu -END - -/* - * Used when we empty the first page in a bucket and there are pages - * after it. The page after it gets copied into the bucket page (since - * bucket pages have to be in fixed locations). - * pgno: the bucket page - * pagelsn: the old LSN on the bucket page - * next_pgno: the page number of the next page - * nnext_pgno: page after next_pgno (may need to change its prev) - * nnextlsn: the LSN of nnext_pgno. - */ -BEGIN copypage -ARG fileid u_int32_t lu -ARG pgno db_pgno_t lu -POINTER pagelsn DB_LSN * lu -ARG next_pgno db_pgno_t lu -POINTER nextlsn DB_LSN * lu -ARG nnext_pgno db_pgno_t lu -POINTER nnextlsn DB_LSN * lu -DBT page DBT s -END diff --git a/db2/hash/hash_auto.c b/db2/hash/hash_auto.c deleted file mode 100644 index 94a1dff..0000000 --- a/db2/hash/hash_auto.c +++ /dev/null @@ -1,1554 +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 "hash.h" -#include "db_am.h" -/* - * PUBLIC: int __ham_insdel_log - * PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - * PUBLIC: u_int32_t, u_int32_t, db_pgno_t, u_int32_t, - * PUBLIC: DB_LSN *, const DBT *, const DBT *)); - */ -int __ham_insdel_log(logp, txnid, ret_lsnp, flags, - opcode, fileid, pgno, ndx, pagelsn, key, - data) - DB_LOG *logp; - DB_TXN *txnid; - DB_LSN *ret_lsnp; - u_int32_t flags; - u_int32_t opcode; - u_int32_t fileid; - db_pgno_t pgno; - u_int32_t ndx; - DB_LSN * pagelsn; - const DBT *key; - const DBT *data; -{ - 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_ham_insdel; - 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(fileid) - + sizeof(pgno) - + sizeof(ndx) - + sizeof(*pagelsn) - + sizeof(u_int32_t) + (key == NULL ? 0 : key->size) - + sizeof(u_int32_t) + (data == NULL ? 0 : data->size); - 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); - memcpy(bp, &fileid, sizeof(fileid)); - bp += sizeof(fileid); - memcpy(bp, &pgno, sizeof(pgno)); - bp += sizeof(pgno); - memcpy(bp, &ndx, sizeof(ndx)); - bp += sizeof(ndx); - if (pagelsn != NULL) - memcpy(bp, pagelsn, sizeof(*pagelsn)); - else - memset(bp, 0, sizeof(*pagelsn)); - bp += sizeof(*pagelsn); - if (key == NULL) { - zero = 0; - memcpy(bp, &zero, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - } else { - memcpy(bp, &key->size, sizeof(key->size)); - bp += sizeof(key->size); - memcpy(bp, key->data, key->size); - bp += key->size; - } - if (data == NULL) { - zero = 0; - memcpy(bp, &zero, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - } else { - memcpy(bp, &data->size, sizeof(data->size)); - bp += sizeof(data->size); - memcpy(bp, data->data, data->size); - bp += data->size; - } -#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 __ham_insdel_print - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__ham_insdel_print(notused1, dbtp, lsnp, notused2, notused3) - DB_LOG *notused1; - DBT *dbtp; - DB_LSN *lsnp; - int notused2; - void *notused3; -{ - __ham_insdel_args *argp; - u_int32_t i; - u_int ch; - int ret; - - i = 0; - ch = 0; - notused1 = NULL; - notused2 = 0; - notused3 = NULL; - - if ((ret = __ham_insdel_read(dbtp->data, &argp)) != 0) - return (ret); - printf("[%lu][%lu]ham_insdel: 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("\tfileid: %lu\n", (u_long)argp->fileid); - printf("\tpgno: %lu\n", (u_long)argp->pgno); - printf("\tndx: %lu\n", (u_long)argp->ndx); - printf("\tpagelsn: [%lu][%lu]\n", - (u_long)argp->pagelsn.file, (u_long)argp->pagelsn.offset); - printf("\tkey: "); - for (i = 0; i < argp->key.size; i++) { - ch = ((u_int8_t *)argp->key.data)[i]; - if (isprint(ch) || ch == 0xa) - putchar(ch); - else - printf("%#x ", ch); - } - printf("\n"); - printf("\tdata: "); - for (i = 0; i < argp->data.size; i++) { - ch = ((u_int8_t *)argp->data.data)[i]; - if (isprint(ch) || ch == 0xa) - putchar(ch); - else - printf("%#x ", ch); - } - printf("\n"); - printf("\n"); - __os_free(argp, 0); - return (0); -} - -/* - * PUBLIC: int __ham_insdel_read __P((void *, __ham_insdel_args **)); - */ -int -__ham_insdel_read(recbuf, argpp) - void *recbuf; - __ham_insdel_args **argpp; -{ - __ham_insdel_args *argp; - u_int8_t *bp; - int ret; - - ret = __os_malloc(sizeof(__ham_insdel_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->fileid, bp, sizeof(argp->fileid)); - bp += sizeof(argp->fileid); - memcpy(&argp->pgno, bp, sizeof(argp->pgno)); - bp += sizeof(argp->pgno); - memcpy(&argp->ndx, bp, sizeof(argp->ndx)); - bp += sizeof(argp->ndx); - memcpy(&argp->pagelsn, bp, sizeof(argp->pagelsn)); - bp += sizeof(argp->pagelsn); - memcpy(&argp->key.size, bp, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - argp->key.data = bp; - bp += argp->key.size; - memcpy(&argp->data.size, bp, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - argp->data.data = bp; - bp += argp->data.size; - *argpp = argp; - return (0); -} - -/* - * PUBLIC: int __ham_newpage_log - * PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - * PUBLIC: u_int32_t, u_int32_t, db_pgno_t, DB_LSN *, - * PUBLIC: db_pgno_t, DB_LSN *, db_pgno_t, DB_LSN *)); - */ -int __ham_newpage_log(logp, txnid, ret_lsnp, flags, - opcode, fileid, prev_pgno, prevlsn, new_pgno, pagelsn, - next_pgno, nextlsn) - DB_LOG *logp; - DB_TXN *txnid; - DB_LSN *ret_lsnp; - u_int32_t flags; - u_int32_t opcode; - u_int32_t fileid; - db_pgno_t prev_pgno; - DB_LSN * prevlsn; - db_pgno_t new_pgno; - DB_LSN * pagelsn; - db_pgno_t next_pgno; - DB_LSN * nextlsn; -{ - DBT logrec; - DB_LSN *lsnp, null_lsn; - u_int32_t rectype, txn_num; - int ret; - u_int8_t *bp; - - rectype = DB_ham_newpage; - 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(fileid) - + sizeof(prev_pgno) - + sizeof(*prevlsn) - + sizeof(new_pgno) - + sizeof(*pagelsn) - + sizeof(next_pgno) - + sizeof(*nextlsn); - 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); - memcpy(bp, &fileid, sizeof(fileid)); - bp += sizeof(fileid); - memcpy(bp, &prev_pgno, sizeof(prev_pgno)); - bp += sizeof(prev_pgno); - if (prevlsn != NULL) - memcpy(bp, prevlsn, sizeof(*prevlsn)); - else - memset(bp, 0, sizeof(*prevlsn)); - bp += sizeof(*prevlsn); - memcpy(bp, &new_pgno, sizeof(new_pgno)); - bp += sizeof(new_pgno); - if (pagelsn != NULL) - memcpy(bp, pagelsn, sizeof(*pagelsn)); - else - memset(bp, 0, sizeof(*pagelsn)); - bp += sizeof(*pagelsn); - memcpy(bp, &next_pgno, sizeof(next_pgno)); - bp += sizeof(next_pgno); - if (nextlsn != NULL) - memcpy(bp, nextlsn, sizeof(*nextlsn)); - else - memset(bp, 0, sizeof(*nextlsn)); - bp += sizeof(*nextlsn); -#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 __ham_newpage_print - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__ham_newpage_print(notused1, dbtp, lsnp, notused2, notused3) - DB_LOG *notused1; - DBT *dbtp; - DB_LSN *lsnp; - int notused2; - void *notused3; -{ - __ham_newpage_args *argp; - u_int32_t i; - u_int ch; - int ret; - - i = 0; - ch = 0; - notused1 = NULL; - notused2 = 0; - notused3 = NULL; - - if ((ret = __ham_newpage_read(dbtp->data, &argp)) != 0) - return (ret); - printf("[%lu][%lu]ham_newpage: 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("\tfileid: %lu\n", (u_long)argp->fileid); - printf("\tprev_pgno: %lu\n", (u_long)argp->prev_pgno); - printf("\tprevlsn: [%lu][%lu]\n", - (u_long)argp->prevlsn.file, (u_long)argp->prevlsn.offset); - printf("\tnew_pgno: %lu\n", (u_long)argp->new_pgno); - printf("\tpagelsn: [%lu][%lu]\n", - (u_long)argp->pagelsn.file, (u_long)argp->pagelsn.offset); - printf("\tnext_pgno: %lu\n", (u_long)argp->next_pgno); - printf("\tnextlsn: [%lu][%lu]\n", - (u_long)argp->nextlsn.file, (u_long)argp->nextlsn.offset); - printf("\n"); - __os_free(argp, 0); - return (0); -} - -/* - * PUBLIC: int __ham_newpage_read __P((void *, __ham_newpage_args **)); - */ -int -__ham_newpage_read(recbuf, argpp) - void *recbuf; - __ham_newpage_args **argpp; -{ - __ham_newpage_args *argp; - u_int8_t *bp; - int ret; - - ret = __os_malloc(sizeof(__ham_newpage_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->fileid, bp, sizeof(argp->fileid)); - bp += sizeof(argp->fileid); - memcpy(&argp->prev_pgno, bp, sizeof(argp->prev_pgno)); - bp += sizeof(argp->prev_pgno); - memcpy(&argp->prevlsn, bp, sizeof(argp->prevlsn)); - bp += sizeof(argp->prevlsn); - memcpy(&argp->new_pgno, bp, sizeof(argp->new_pgno)); - bp += sizeof(argp->new_pgno); - memcpy(&argp->pagelsn, bp, sizeof(argp->pagelsn)); - bp += sizeof(argp->pagelsn); - memcpy(&argp->next_pgno, bp, sizeof(argp->next_pgno)); - bp += sizeof(argp->next_pgno); - memcpy(&argp->nextlsn, bp, sizeof(argp->nextlsn)); - bp += sizeof(argp->nextlsn); - *argpp = argp; - return (0); -} - -/* - * PUBLIC: int __ham_splitmeta_log - * PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - * PUBLIC: u_int32_t, u_int32_t, u_int32_t, u_int32_t, - * PUBLIC: DB_LSN *)); - */ -int __ham_splitmeta_log(logp, txnid, ret_lsnp, flags, - fileid, bucket, ovflpoint, spares, metalsn) - DB_LOG *logp; - DB_TXN *txnid; - DB_LSN *ret_lsnp; - u_int32_t flags; - u_int32_t fileid; - u_int32_t bucket; - u_int32_t ovflpoint; - u_int32_t spares; - DB_LSN * metalsn; -{ - DBT logrec; - DB_LSN *lsnp, null_lsn; - u_int32_t rectype, txn_num; - int ret; - u_int8_t *bp; - - rectype = DB_ham_splitmeta; - 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(fileid) - + sizeof(bucket) - + sizeof(ovflpoint) - + sizeof(spares) - + sizeof(*metalsn); - 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, &fileid, sizeof(fileid)); - bp += sizeof(fileid); - memcpy(bp, &bucket, sizeof(bucket)); - bp += sizeof(bucket); - memcpy(bp, &ovflpoint, sizeof(ovflpoint)); - bp += sizeof(ovflpoint); - memcpy(bp, &spares, sizeof(spares)); - bp += sizeof(spares); - if (metalsn != NULL) - memcpy(bp, metalsn, sizeof(*metalsn)); - else - memset(bp, 0, sizeof(*metalsn)); - bp += sizeof(*metalsn); -#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 __ham_splitmeta_print - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__ham_splitmeta_print(notused1, dbtp, lsnp, notused2, notused3) - DB_LOG *notused1; - DBT *dbtp; - DB_LSN *lsnp; - int notused2; - void *notused3; -{ - __ham_splitmeta_args *argp; - u_int32_t i; - u_int ch; - int ret; - - i = 0; - ch = 0; - notused1 = NULL; - notused2 = 0; - notused3 = NULL; - - if ((ret = __ham_splitmeta_read(dbtp->data, &argp)) != 0) - return (ret); - printf("[%lu][%lu]ham_splitmeta: 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("\tfileid: %lu\n", (u_long)argp->fileid); - printf("\tbucket: %lu\n", (u_long)argp->bucket); - printf("\tovflpoint: %lu\n", (u_long)argp->ovflpoint); - printf("\tspares: %lu\n", (u_long)argp->spares); - printf("\tmetalsn: [%lu][%lu]\n", - (u_long)argp->metalsn.file, (u_long)argp->metalsn.offset); - printf("\n"); - __os_free(argp, 0); - return (0); -} - -/* - * PUBLIC: int __ham_splitmeta_read __P((void *, __ham_splitmeta_args **)); - */ -int -__ham_splitmeta_read(recbuf, argpp) - void *recbuf; - __ham_splitmeta_args **argpp; -{ - __ham_splitmeta_args *argp; - u_int8_t *bp; - int ret; - - ret = __os_malloc(sizeof(__ham_splitmeta_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->fileid, bp, sizeof(argp->fileid)); - bp += sizeof(argp->fileid); - memcpy(&argp->bucket, bp, sizeof(argp->bucket)); - bp += sizeof(argp->bucket); - memcpy(&argp->ovflpoint, bp, sizeof(argp->ovflpoint)); - bp += sizeof(argp->ovflpoint); - memcpy(&argp->spares, bp, sizeof(argp->spares)); - bp += sizeof(argp->spares); - memcpy(&argp->metalsn, bp, sizeof(argp->metalsn)); - bp += sizeof(argp->metalsn); - *argpp = argp; - return (0); -} - -/* - * PUBLIC: int __ham_splitdata_log - * PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - * PUBLIC: u_int32_t, u_int32_t, db_pgno_t, const DBT *, - * PUBLIC: DB_LSN *)); - */ -int __ham_splitdata_log(logp, txnid, ret_lsnp, flags, - fileid, opcode, pgno, pageimage, pagelsn) - DB_LOG *logp; - DB_TXN *txnid; - DB_LSN *ret_lsnp; - u_int32_t flags; - u_int32_t fileid; - u_int32_t opcode; - db_pgno_t pgno; - const DBT *pageimage; - DB_LSN * pagelsn; -{ - 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_ham_splitdata; - 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(fileid) - + sizeof(opcode) - + sizeof(pgno) - + sizeof(u_int32_t) + (pageimage == NULL ? 0 : pageimage->size) - + sizeof(*pagelsn); - 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, &fileid, sizeof(fileid)); - bp += sizeof(fileid); - memcpy(bp, &opcode, sizeof(opcode)); - bp += sizeof(opcode); - memcpy(bp, &pgno, sizeof(pgno)); - bp += sizeof(pgno); - if (pageimage == NULL) { - zero = 0; - memcpy(bp, &zero, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - } else { - memcpy(bp, &pageimage->size, sizeof(pageimage->size)); - bp += sizeof(pageimage->size); - memcpy(bp, pageimage->data, pageimage->size); - bp += pageimage->size; - } - if (pagelsn != NULL) - memcpy(bp, pagelsn, sizeof(*pagelsn)); - else - memset(bp, 0, sizeof(*pagelsn)); - bp += sizeof(*pagelsn); -#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 __ham_splitdata_print - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__ham_splitdata_print(notused1, dbtp, lsnp, notused2, notused3) - DB_LOG *notused1; - DBT *dbtp; - DB_LSN *lsnp; - int notused2; - void *notused3; -{ - __ham_splitdata_args *argp; - u_int32_t i; - u_int ch; - int ret; - - i = 0; - ch = 0; - notused1 = NULL; - notused2 = 0; - notused3 = NULL; - - if ((ret = __ham_splitdata_read(dbtp->data, &argp)) != 0) - return (ret); - printf("[%lu][%lu]ham_splitdata: 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("\tfileid: %lu\n", (u_long)argp->fileid); - printf("\topcode: %lu\n", (u_long)argp->opcode); - printf("\tpgno: %lu\n", (u_long)argp->pgno); - printf("\tpageimage: "); - for (i = 0; i < argp->pageimage.size; i++) { - ch = ((u_int8_t *)argp->pageimage.data)[i]; - if (isprint(ch) || ch == 0xa) - putchar(ch); - else - printf("%#x ", ch); - } - printf("\n"); - printf("\tpagelsn: [%lu][%lu]\n", - (u_long)argp->pagelsn.file, (u_long)argp->pagelsn.offset); - printf("\n"); - __os_free(argp, 0); - return (0); -} - -/* - * PUBLIC: int __ham_splitdata_read __P((void *, __ham_splitdata_args **)); - */ -int -__ham_splitdata_read(recbuf, argpp) - void *recbuf; - __ham_splitdata_args **argpp; -{ - __ham_splitdata_args *argp; - u_int8_t *bp; - int ret; - - ret = __os_malloc(sizeof(__ham_splitdata_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->fileid, bp, sizeof(argp->fileid)); - bp += sizeof(argp->fileid); - memcpy(&argp->opcode, bp, sizeof(argp->opcode)); - bp += sizeof(argp->opcode); - memcpy(&argp->pgno, bp, sizeof(argp->pgno)); - bp += sizeof(argp->pgno); - memcpy(&argp->pageimage.size, bp, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - argp->pageimage.data = bp; - bp += argp->pageimage.size; - memcpy(&argp->pagelsn, bp, sizeof(argp->pagelsn)); - bp += sizeof(argp->pagelsn); - *argpp = argp; - return (0); -} - -/* - * PUBLIC: int __ham_replace_log - * PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - * PUBLIC: u_int32_t, db_pgno_t, u_int32_t, DB_LSN *, - * PUBLIC: int32_t, const DBT *, const DBT *, u_int32_t)); - */ -int __ham_replace_log(logp, txnid, ret_lsnp, flags, - fileid, pgno, ndx, pagelsn, off, olditem, - newitem, makedup) - DB_LOG *logp; - DB_TXN *txnid; - DB_LSN *ret_lsnp; - u_int32_t flags; - u_int32_t fileid; - db_pgno_t pgno; - u_int32_t ndx; - DB_LSN * pagelsn; - int32_t off; - const DBT *olditem; - const DBT *newitem; - u_int32_t makedup; -{ - 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_ham_replace; - 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(fileid) - + sizeof(pgno) - + sizeof(ndx) - + sizeof(*pagelsn) - + sizeof(off) - + sizeof(u_int32_t) + (olditem == NULL ? 0 : olditem->size) - + sizeof(u_int32_t) + (newitem == NULL ? 0 : newitem->size) - + sizeof(makedup); - 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, &fileid, sizeof(fileid)); - bp += sizeof(fileid); - memcpy(bp, &pgno, sizeof(pgno)); - bp += sizeof(pgno); - memcpy(bp, &ndx, sizeof(ndx)); - bp += sizeof(ndx); - if (pagelsn != NULL) - memcpy(bp, pagelsn, sizeof(*pagelsn)); - else - memset(bp, 0, sizeof(*pagelsn)); - bp += sizeof(*pagelsn); - memcpy(bp, &off, sizeof(off)); - bp += sizeof(off); - if (olditem == NULL) { - zero = 0; - memcpy(bp, &zero, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - } else { - memcpy(bp, &olditem->size, sizeof(olditem->size)); - bp += sizeof(olditem->size); - memcpy(bp, olditem->data, olditem->size); - bp += olditem->size; - } - if (newitem == NULL) { - zero = 0; - memcpy(bp, &zero, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - } else { - memcpy(bp, &newitem->size, sizeof(newitem->size)); - bp += sizeof(newitem->size); - memcpy(bp, newitem->data, newitem->size); - bp += newitem->size; - } - memcpy(bp, &makedup, sizeof(makedup)); - bp += sizeof(makedup); -#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 __ham_replace_print - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__ham_replace_print(notused1, dbtp, lsnp, notused2, notused3) - DB_LOG *notused1; - DBT *dbtp; - DB_LSN *lsnp; - int notused2; - void *notused3; -{ - __ham_replace_args *argp; - u_int32_t i; - u_int ch; - int ret; - - i = 0; - ch = 0; - notused1 = NULL; - notused2 = 0; - notused3 = NULL; - - if ((ret = __ham_replace_read(dbtp->data, &argp)) != 0) - return (ret); - printf("[%lu][%lu]ham_replace: 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("\tfileid: %lu\n", (u_long)argp->fileid); - printf("\tpgno: %lu\n", (u_long)argp->pgno); - printf("\tndx: %lu\n", (u_long)argp->ndx); - printf("\tpagelsn: [%lu][%lu]\n", - (u_long)argp->pagelsn.file, (u_long)argp->pagelsn.offset); - printf("\toff: %ld\n", (long)argp->off); - printf("\tolditem: "); - for (i = 0; i < argp->olditem.size; i++) { - ch = ((u_int8_t *)argp->olditem.data)[i]; - if (isprint(ch) || ch == 0xa) - putchar(ch); - else - printf("%#x ", ch); - } - printf("\n"); - printf("\tnewitem: "); - for (i = 0; i < argp->newitem.size; i++) { - ch = ((u_int8_t *)argp->newitem.data)[i]; - if (isprint(ch) || ch == 0xa) - putchar(ch); - else - printf("%#x ", ch); - } - printf("\n"); - printf("\tmakedup: %lu\n", (u_long)argp->makedup); - printf("\n"); - __os_free(argp, 0); - return (0); -} - -/* - * PUBLIC: int __ham_replace_read __P((void *, __ham_replace_args **)); - */ -int -__ham_replace_read(recbuf, argpp) - void *recbuf; - __ham_replace_args **argpp; -{ - __ham_replace_args *argp; - u_int8_t *bp; - int ret; - - ret = __os_malloc(sizeof(__ham_replace_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->fileid, bp, sizeof(argp->fileid)); - bp += sizeof(argp->fileid); - memcpy(&argp->pgno, bp, sizeof(argp->pgno)); - bp += sizeof(argp->pgno); - memcpy(&argp->ndx, bp, sizeof(argp->ndx)); - bp += sizeof(argp->ndx); - memcpy(&argp->pagelsn, bp, sizeof(argp->pagelsn)); - bp += sizeof(argp->pagelsn); - memcpy(&argp->off, bp, sizeof(argp->off)); - bp += sizeof(argp->off); - memcpy(&argp->olditem.size, bp, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - argp->olditem.data = bp; - bp += argp->olditem.size; - memcpy(&argp->newitem.size, bp, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - argp->newitem.data = bp; - bp += argp->newitem.size; - memcpy(&argp->makedup, bp, sizeof(argp->makedup)); - bp += sizeof(argp->makedup); - *argpp = argp; - return (0); -} - -/* - * PUBLIC: int __ham_newpgno_log - * PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - * PUBLIC: u_int32_t, u_int32_t, db_pgno_t, db_pgno_t, - * PUBLIC: u_int32_t, db_pgno_t, u_int32_t, DB_LSN *, - * PUBLIC: DB_LSN *)); - */ -int __ham_newpgno_log(logp, txnid, ret_lsnp, flags, - opcode, fileid, pgno, free_pgno, old_type, old_pgno, - new_type, pagelsn, metalsn) - DB_LOG *logp; - DB_TXN *txnid; - DB_LSN *ret_lsnp; - u_int32_t flags; - u_int32_t opcode; - u_int32_t fileid; - db_pgno_t pgno; - db_pgno_t free_pgno; - u_int32_t old_type; - db_pgno_t old_pgno; - u_int32_t new_type; - DB_LSN * pagelsn; - DB_LSN * metalsn; -{ - DBT logrec; - DB_LSN *lsnp, null_lsn; - u_int32_t rectype, txn_num; - int ret; - u_int8_t *bp; - - rectype = DB_ham_newpgno; - 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(fileid) - + sizeof(pgno) - + sizeof(free_pgno) - + sizeof(old_type) - + sizeof(old_pgno) - + sizeof(new_type) - + sizeof(*pagelsn) - + sizeof(*metalsn); - 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); - memcpy(bp, &fileid, sizeof(fileid)); - bp += sizeof(fileid); - memcpy(bp, &pgno, sizeof(pgno)); - bp += sizeof(pgno); - memcpy(bp, &free_pgno, sizeof(free_pgno)); - bp += sizeof(free_pgno); - memcpy(bp, &old_type, sizeof(old_type)); - bp += sizeof(old_type); - memcpy(bp, &old_pgno, sizeof(old_pgno)); - bp += sizeof(old_pgno); - memcpy(bp, &new_type, sizeof(new_type)); - bp += sizeof(new_type); - if (pagelsn != NULL) - memcpy(bp, pagelsn, sizeof(*pagelsn)); - else - memset(bp, 0, sizeof(*pagelsn)); - bp += sizeof(*pagelsn); - if (metalsn != NULL) - memcpy(bp, metalsn, sizeof(*metalsn)); - else - memset(bp, 0, sizeof(*metalsn)); - bp += sizeof(*metalsn); -#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 __ham_newpgno_print - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__ham_newpgno_print(notused1, dbtp, lsnp, notused2, notused3) - DB_LOG *notused1; - DBT *dbtp; - DB_LSN *lsnp; - int notused2; - void *notused3; -{ - __ham_newpgno_args *argp; - u_int32_t i; - u_int ch; - int ret; - - i = 0; - ch = 0; - notused1 = NULL; - notused2 = 0; - notused3 = NULL; - - if ((ret = __ham_newpgno_read(dbtp->data, &argp)) != 0) - return (ret); - printf("[%lu][%lu]ham_newpgno: 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("\tfileid: %lu\n", (u_long)argp->fileid); - printf("\tpgno: %lu\n", (u_long)argp->pgno); - printf("\tfree_pgno: %lu\n", (u_long)argp->free_pgno); - printf("\told_type: %lu\n", (u_long)argp->old_type); - printf("\told_pgno: %lu\n", (u_long)argp->old_pgno); - printf("\tnew_type: %lu\n", (u_long)argp->new_type); - printf("\tpagelsn: [%lu][%lu]\n", - (u_long)argp->pagelsn.file, (u_long)argp->pagelsn.offset); - printf("\tmetalsn: [%lu][%lu]\n", - (u_long)argp->metalsn.file, (u_long)argp->metalsn.offset); - printf("\n"); - __os_free(argp, 0); - return (0); -} - -/* - * PUBLIC: int __ham_newpgno_read __P((void *, __ham_newpgno_args **)); - */ -int -__ham_newpgno_read(recbuf, argpp) - void *recbuf; - __ham_newpgno_args **argpp; -{ - __ham_newpgno_args *argp; - u_int8_t *bp; - int ret; - - ret = __os_malloc(sizeof(__ham_newpgno_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->fileid, bp, sizeof(argp->fileid)); - bp += sizeof(argp->fileid); - memcpy(&argp->pgno, bp, sizeof(argp->pgno)); - bp += sizeof(argp->pgno); - memcpy(&argp->free_pgno, bp, sizeof(argp->free_pgno)); - bp += sizeof(argp->free_pgno); - memcpy(&argp->old_type, bp, sizeof(argp->old_type)); - bp += sizeof(argp->old_type); - memcpy(&argp->old_pgno, bp, sizeof(argp->old_pgno)); - bp += sizeof(argp->old_pgno); - memcpy(&argp->new_type, bp, sizeof(argp->new_type)); - bp += sizeof(argp->new_type); - memcpy(&argp->pagelsn, bp, sizeof(argp->pagelsn)); - bp += sizeof(argp->pagelsn); - memcpy(&argp->metalsn, bp, sizeof(argp->metalsn)); - bp += sizeof(argp->metalsn); - *argpp = argp; - return (0); -} - -/* - * PUBLIC: int __ham_ovfl_log - * PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - * PUBLIC: u_int32_t, db_pgno_t, u_int32_t, db_pgno_t, - * PUBLIC: u_int32_t, DB_LSN *)); - */ -int __ham_ovfl_log(logp, txnid, ret_lsnp, flags, - fileid, start_pgno, npages, free_pgno, ovflpoint, metalsn) - DB_LOG *logp; - DB_TXN *txnid; - DB_LSN *ret_lsnp; - u_int32_t flags; - u_int32_t fileid; - db_pgno_t start_pgno; - u_int32_t npages; - db_pgno_t free_pgno; - u_int32_t ovflpoint; - DB_LSN * metalsn; -{ - DBT logrec; - DB_LSN *lsnp, null_lsn; - u_int32_t rectype, txn_num; - int ret; - u_int8_t *bp; - - rectype = DB_ham_ovfl; - 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(fileid) - + sizeof(start_pgno) - + sizeof(npages) - + sizeof(free_pgno) - + sizeof(ovflpoint) - + sizeof(*metalsn); - 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, &fileid, sizeof(fileid)); - bp += sizeof(fileid); - memcpy(bp, &start_pgno, sizeof(start_pgno)); - bp += sizeof(start_pgno); - memcpy(bp, &npages, sizeof(npages)); - bp += sizeof(npages); - memcpy(bp, &free_pgno, sizeof(free_pgno)); - bp += sizeof(free_pgno); - memcpy(bp, &ovflpoint, sizeof(ovflpoint)); - bp += sizeof(ovflpoint); - if (metalsn != NULL) - memcpy(bp, metalsn, sizeof(*metalsn)); - else - memset(bp, 0, sizeof(*metalsn)); - bp += sizeof(*metalsn); -#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 __ham_ovfl_print - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__ham_ovfl_print(notused1, dbtp, lsnp, notused2, notused3) - DB_LOG *notused1; - DBT *dbtp; - DB_LSN *lsnp; - int notused2; - void *notused3; -{ - __ham_ovfl_args *argp; - u_int32_t i; - u_int ch; - int ret; - - i = 0; - ch = 0; - notused1 = NULL; - notused2 = 0; - notused3 = NULL; - - if ((ret = __ham_ovfl_read(dbtp->data, &argp)) != 0) - return (ret); - printf("[%lu][%lu]ham_ovfl: 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("\tfileid: %lu\n", (u_long)argp->fileid); - printf("\tstart_pgno: %lu\n", (u_long)argp->start_pgno); - printf("\tnpages: %lu\n", (u_long)argp->npages); - printf("\tfree_pgno: %lu\n", (u_long)argp->free_pgno); - printf("\tovflpoint: %lu\n", (u_long)argp->ovflpoint); - printf("\tmetalsn: [%lu][%lu]\n", - (u_long)argp->metalsn.file, (u_long)argp->metalsn.offset); - printf("\n"); - __os_free(argp, 0); - return (0); -} - -/* - * PUBLIC: int __ham_ovfl_read __P((void *, __ham_ovfl_args **)); - */ -int -__ham_ovfl_read(recbuf, argpp) - void *recbuf; - __ham_ovfl_args **argpp; -{ - __ham_ovfl_args *argp; - u_int8_t *bp; - int ret; - - ret = __os_malloc(sizeof(__ham_ovfl_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->fileid, bp, sizeof(argp->fileid)); - bp += sizeof(argp->fileid); - memcpy(&argp->start_pgno, bp, sizeof(argp->start_pgno)); - bp += sizeof(argp->start_pgno); - memcpy(&argp->npages, bp, sizeof(argp->npages)); - bp += sizeof(argp->npages); - memcpy(&argp->free_pgno, bp, sizeof(argp->free_pgno)); - bp += sizeof(argp->free_pgno); - memcpy(&argp->ovflpoint, bp, sizeof(argp->ovflpoint)); - bp += sizeof(argp->ovflpoint); - memcpy(&argp->metalsn, bp, sizeof(argp->metalsn)); - bp += sizeof(argp->metalsn); - *argpp = argp; - return (0); -} - -/* - * PUBLIC: int __ham_copypage_log - * PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - * PUBLIC: u_int32_t, db_pgno_t, DB_LSN *, db_pgno_t, - * PUBLIC: DB_LSN *, db_pgno_t, DB_LSN *, const DBT *)); - */ -int __ham_copypage_log(logp, txnid, ret_lsnp, flags, - fileid, pgno, pagelsn, next_pgno, nextlsn, nnext_pgno, - nnextlsn, page) - DB_LOG *logp; - DB_TXN *txnid; - DB_LSN *ret_lsnp; - u_int32_t flags; - u_int32_t fileid; - db_pgno_t pgno; - DB_LSN * pagelsn; - db_pgno_t next_pgno; - DB_LSN * nextlsn; - db_pgno_t nnext_pgno; - DB_LSN * nnextlsn; - const DBT *page; -{ - 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_ham_copypage; - 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(fileid) - + sizeof(pgno) - + sizeof(*pagelsn) - + sizeof(next_pgno) - + sizeof(*nextlsn) - + sizeof(nnext_pgno) - + sizeof(*nnextlsn) - + sizeof(u_int32_t) + (page == NULL ? 0 : page->size); - 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, &fileid, sizeof(fileid)); - bp += sizeof(fileid); - memcpy(bp, &pgno, sizeof(pgno)); - bp += sizeof(pgno); - if (pagelsn != NULL) - memcpy(bp, pagelsn, sizeof(*pagelsn)); - else - memset(bp, 0, sizeof(*pagelsn)); - bp += sizeof(*pagelsn); - memcpy(bp, &next_pgno, sizeof(next_pgno)); - bp += sizeof(next_pgno); - if (nextlsn != NULL) - memcpy(bp, nextlsn, sizeof(*nextlsn)); - else - memset(bp, 0, sizeof(*nextlsn)); - bp += sizeof(*nextlsn); - memcpy(bp, &nnext_pgno, sizeof(nnext_pgno)); - bp += sizeof(nnext_pgno); - if (nnextlsn != NULL) - memcpy(bp, nnextlsn, sizeof(*nnextlsn)); - else - memset(bp, 0, sizeof(*nnextlsn)); - bp += sizeof(*nnextlsn); - if (page == NULL) { - zero = 0; - memcpy(bp, &zero, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - } else { - memcpy(bp, &page->size, sizeof(page->size)); - bp += sizeof(page->size); - memcpy(bp, page->data, page->size); - bp += page->size; - } -#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 __ham_copypage_print - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__ham_copypage_print(notused1, dbtp, lsnp, notused2, notused3) - DB_LOG *notused1; - DBT *dbtp; - DB_LSN *lsnp; - int notused2; - void *notused3; -{ - __ham_copypage_args *argp; - u_int32_t i; - u_int ch; - int ret; - - i = 0; - ch = 0; - notused1 = NULL; - notused2 = 0; - notused3 = NULL; - - if ((ret = __ham_copypage_read(dbtp->data, &argp)) != 0) - return (ret); - printf("[%lu][%lu]ham_copypage: 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("\tfileid: %lu\n", (u_long)argp->fileid); - printf("\tpgno: %lu\n", (u_long)argp->pgno); - printf("\tpagelsn: [%lu][%lu]\n", - (u_long)argp->pagelsn.file, (u_long)argp->pagelsn.offset); - printf("\tnext_pgno: %lu\n", (u_long)argp->next_pgno); - printf("\tnextlsn: [%lu][%lu]\n", - (u_long)argp->nextlsn.file, (u_long)argp->nextlsn.offset); - printf("\tnnext_pgno: %lu\n", (u_long)argp->nnext_pgno); - printf("\tnnextlsn: [%lu][%lu]\n", - (u_long)argp->nnextlsn.file, (u_long)argp->nnextlsn.offset); - printf("\tpage: "); - for (i = 0; i < argp->page.size; i++) { - ch = ((u_int8_t *)argp->page.data)[i]; - if (isprint(ch) || ch == 0xa) - putchar(ch); - else - printf("%#x ", ch); - } - printf("\n"); - printf("\n"); - __os_free(argp, 0); - return (0); -} - -/* - * PUBLIC: int __ham_copypage_read __P((void *, __ham_copypage_args **)); - */ -int -__ham_copypage_read(recbuf, argpp) - void *recbuf; - __ham_copypage_args **argpp; -{ - __ham_copypage_args *argp; - u_int8_t *bp; - int ret; - - ret = __os_malloc(sizeof(__ham_copypage_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->fileid, bp, sizeof(argp->fileid)); - bp += sizeof(argp->fileid); - memcpy(&argp->pgno, bp, sizeof(argp->pgno)); - bp += sizeof(argp->pgno); - memcpy(&argp->pagelsn, bp, sizeof(argp->pagelsn)); - bp += sizeof(argp->pagelsn); - memcpy(&argp->next_pgno, bp, sizeof(argp->next_pgno)); - bp += sizeof(argp->next_pgno); - memcpy(&argp->nextlsn, bp, sizeof(argp->nextlsn)); - bp += sizeof(argp->nextlsn); - memcpy(&argp->nnext_pgno, bp, sizeof(argp->nnext_pgno)); - bp += sizeof(argp->nnext_pgno); - memcpy(&argp->nnextlsn, bp, sizeof(argp->nnextlsn)); - bp += sizeof(argp->nnextlsn); - memcpy(&argp->page.size, bp, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - argp->page.data = bp; - bp += argp->page.size; - *argpp = argp; - return (0); -} - -/* - * PUBLIC: int __ham_init_print __P((DB_ENV *)); - */ -int -__ham_init_print(dbenv) - DB_ENV *dbenv; -{ - int ret; - - if ((ret = __db_add_recovery(dbenv, - __ham_insdel_print, DB_ham_insdel)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __ham_newpage_print, DB_ham_newpage)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __ham_splitmeta_print, DB_ham_splitmeta)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __ham_splitdata_print, DB_ham_splitdata)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __ham_replace_print, DB_ham_replace)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __ham_newpgno_print, DB_ham_newpgno)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __ham_ovfl_print, DB_ham_ovfl)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __ham_copypage_print, DB_ham_copypage)) != 0) - return (ret); - return (0); -} - -/* - * PUBLIC: int __ham_init_recover __P((DB_ENV *)); - */ -int -__ham_init_recover(dbenv) - DB_ENV *dbenv; -{ - int ret; - - if ((ret = __db_add_recovery(dbenv, - __ham_insdel_recover, DB_ham_insdel)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __ham_newpage_recover, DB_ham_newpage)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __ham_splitmeta_recover, DB_ham_splitmeta)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __ham_splitdata_recover, DB_ham_splitdata)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __ham_replace_recover, DB_ham_replace)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __ham_newpgno_recover, DB_ham_newpgno)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __ham_ovfl_recover, DB_ham_ovfl)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __ham_copypage_recover, DB_ham_copypage)) != 0) - return (ret); - return (0); -} - diff --git a/db2/hash/hash_conv.c b/db2/hash/hash_conv.c deleted file mode 100644 index c6d0ba4..0000000 --- a/db2/hash/hash_conv.c +++ /dev/null @@ -1,109 +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[] = "@(#)hash_conv.c 10.5 (Sleepycat) 4/10/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> -#endif - -#include "db_int.h" -#include "db_page.h" -#include "db_swap.h" -#include "hash.h" - -/* - * __ham_pgin -- - * Convert host-specific page layout from the host-independent format - * stored on disk. - * - * PUBLIC: int __ham_pgin __P((db_pgno_t, void *, DBT *)); - */ -int -__ham_pgin(pg, pp, cookie) - db_pgno_t pg; - void *pp; - DBT *cookie; -{ - DB_PGINFO *pginfo; - u_int32_t tpgno; - - pginfo = (DB_PGINFO *)cookie->data; - tpgno = PGNO((PAGE *)pp); - if (pginfo->needswap) - M_32_SWAP(tpgno); - - if (pg != PGNO_METADATA && pg != tpgno) { - P_INIT(pp, pginfo->db_pagesize, - pg, PGNO_INVALID, PGNO_INVALID, 0, P_HASH); - return (0); - } - - if (!pginfo->needswap) - return (0); - return (pg == PGNO_METADATA ? - __ham_mswap(pp) : __db_pgin(pg, pginfo->db_pagesize, pp)); -} - -/* - * __ham_pgout -- - * Convert host-specific page layout to the host-independent format - * stored on disk. - * - * PUBLIC: int __ham_pgout __P((db_pgno_t, void *, DBT *)); - */ -int -__ham_pgout(pg, pp, cookie) - db_pgno_t pg; - void *pp; - DBT *cookie; -{ - DB_PGINFO *pginfo; - - pginfo = (DB_PGINFO *)cookie->data; - if (!pginfo->needswap) - return (0); - return (pg == PGNO_METADATA ? - __ham_mswap(pp) : __db_pgout(pg, pginfo->db_pagesize, pp)); -} - -/* - * __ham_mswap -- - * Swap the bytes on the hash metadata page. - * - * PUBLIC: int __ham_mswap __P((void *)); - */ -int -__ham_mswap(pg) - void *pg; -{ - u_int8_t *p; - int i; - - p = (u_int8_t *)pg; - SWAP32(p); /* lsn part 1 */ - SWAP32(p); /* lsn part 2 */ - SWAP32(p); /* pgno */ - SWAP32(p); /* magic */ - SWAP32(p); /* version */ - SWAP32(p); /* pagesize */ - SWAP32(p); /* ovfl_point */ - SWAP32(p); /* last_freed */ - SWAP32(p); /* max_bucket */ - SWAP32(p); /* high_mask */ - SWAP32(p); /* low_mask */ - SWAP32(p); /* ffactor */ - SWAP32(p); /* nelem */ - SWAP32(p); /* h_charkey */ - SWAP32(p); /* flags */ - for (i = 0; i < NCACHED; ++i) - SWAP32(p); /* spares */ - return (0); -} diff --git a/db2/hash/hash_dup.c b/db2/hash/hash_dup.c deleted file mode 100644 index bb34664..0000000 --- a/db2/hash/hash_dup.c +++ /dev/null @@ -1,656 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994 - * 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[] = "@(#)hash_dup.c 10.27 (Sleepycat) 12/6/98"; -#endif /* not lint */ - -/* - * PACKAGE: hashing - * - * DESCRIPTION: - * Manipulation of duplicates for the hash package. - * - * ROUTINES: - * - * External - * __add_dup - * Internal - */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <string.h> -#endif - -#include "db_int.h" -#include "db_page.h" -#include "hash.h" -#include "btree.h" - -static int __ham_check_move __P((DBC *, int32_t)); -static int __ham_dup_convert __P((DBC *)); -static int __ham_make_dup __P((const DBT *, DBT *d, void **, u_int32_t *)); - -/* - * Called from hash_access to add a duplicate key. nval is the new - * value that we want to add. The flags correspond to the flag values - * to cursor_put indicating where to add the new element. - * There are 4 cases. - * Case 1: The existing duplicate set already resides on a separate page. - * We can use common code for this. - * Case 2: The element is small enough to just be added to the existing set. - * Case 3: The element is large enough to be a big item, so we're going to - * have to push the set onto a new page. - * Case 4: The element is large enough to push the duplicate set onto a - * separate page. - * - * PUBLIC: int __ham_add_dup __P((DBC *, DBT *, u_int32_t)); - */ -int -__ham_add_dup(dbc, nval, flags) - DBC *dbc; - DBT *nval; - u_int32_t flags; -{ - DB *dbp; - HASH_CURSOR *hcp; - DBT dbt, pval, tmp_val; - u_int32_t del_len, new_size; - int cmp, ret; - u_int8_t *hk; - - dbp = dbc->dbp; - hcp = (HASH_CURSOR *)dbc->internal; - if (flags == DB_CURRENT && hcp->dpgno == PGNO_INVALID) - del_len = hcp->dup_len; - else - del_len = 0; - - if ((ret = __ham_check_move(dbc, - (int32_t)DUP_SIZE(nval->size) - (int32_t)del_len)) != 0) - return (ret); - - /* - * Check if resulting duplicate set is going to need to go - * onto a separate duplicate page. If so, convert the - * duplicate set and add the new one. After conversion, - * hcp->dndx is the first free ndx or the index of the - * current pointer into the duplicate set. - */ - hk = H_PAIRDATA(hcp->pagep, hcp->bndx); - new_size = DUP_SIZE(nval->size) - del_len + LEN_HKEYDATA(hcp->pagep, - hcp->hdr->pagesize, H_DATAINDEX(hcp->bndx)); - - /* - * We convert to off-page duplicates if the item is a big item, - * the addition of the new item will make the set large, or - * if there isn't enough room on this page to add the next item. - */ - if (HPAGE_PTYPE(hk) != H_OFFDUP && - (HPAGE_PTYPE(hk) == H_OFFPAGE || ISBIG(hcp, new_size) || - DUP_SIZE(nval->size) - del_len > P_FREESPACE(hcp->pagep))) { - - if ((ret = __ham_dup_convert(dbc)) != 0) - return (ret); - else - hk = H_PAIRDATA(hcp->pagep, hcp->bndx); - } - - /* There are two separate cases here: on page and off page. */ - if (HPAGE_PTYPE(hk) != H_OFFDUP) { - if (HPAGE_PTYPE(hk) != H_DUPLICATE) { - HPAGE_PTYPE(hk) = H_DUPLICATE; - pval.flags = 0; - pval.data = HKEYDATA_DATA(hk); - pval.size = LEN_HDATA(hcp->pagep, dbp->pgsize, - hcp->bndx); - if ((ret = - __ham_make_dup(&pval, &tmp_val, &dbc->rdata.data, - &dbc->rdata.size)) != 0 || (ret = - __ham_replpair(dbc, &tmp_val, 1)) != 0) - return (ret); - } - - /* Now make the new entry a duplicate. */ - if ((ret = __ham_make_dup(nval, - &tmp_val, &dbc->rdata.data, &dbc->rdata.size)) != 0) - return (ret); - - tmp_val.dlen = 0; - switch (flags) { /* On page. */ - case DB_KEYFIRST: - case DB_KEYLAST: - if (dbp->dup_compare != NULL) - __ham_dsearch(dbc, nval, &tmp_val.doff, &cmp); - else if (flags == DB_KEYFIRST) - tmp_val.doff = 0; - else - tmp_val.doff = LEN_HDATA(hcp->pagep, - hcp->hdr->pagesize, hcp->bndx); - break; - case DB_CURRENT: - /* - * If we have a sort function, we need to verify that - * the new item sorts identically to the old item. - */ - if (dbp->dup_compare != NULL) { - dbt.data = HKEYDATA_DATA(H_PAIRDATA(hcp->pagep, - hcp->bndx)) + hcp->dup_off; - dbt.size = DUP_SIZE(hcp->dup_len); - if (dbp->dup_compare(nval, &dbt) != 0) - return (EINVAL); - } - tmp_val.doff = hcp->dup_off; - tmp_val.dlen = DUP_SIZE(hcp->dup_len); - break; - case DB_BEFORE: - tmp_val.doff = hcp->dup_off; - break; - case DB_AFTER: - tmp_val.doff = hcp->dup_off + DUP_SIZE(hcp->dup_len); - break; - } - /* Add the duplicate. */ - ret = __ham_replpair(dbc, &tmp_val, 0); - if (ret == 0) - ret = __ham_dirty_page(dbp, hcp->pagep); - __ham_c_update(hcp, hcp->pgno, tmp_val.size, 1, 1); - return (ret); - } - - /* If we get here, then we're on duplicate pages. */ - if (hcp->dpgno == PGNO_INVALID) { - memcpy(&hcp->dpgno, HOFFDUP_PGNO(hk), sizeof(db_pgno_t)); - hcp->dndx = 0; - } - - switch (flags) { - case DB_KEYFIRST: - if (dbp->dup_compare != NULL) - goto sorted_dups; - /* - * The only way that we are already on a dup page is - * if we just converted the on-page representation. - * In that case, we've only got one page of duplicates. - */ - if (hcp->dpagep == NULL && (ret = - __db_dend(dbc, hcp->dpgno, &hcp->dpagep)) != 0) - return (ret); - hcp->dndx = 0; - break; - case DB_KEYLAST: - if (dbp->dup_compare != NULL) { -sorted_dups: if ((ret = __db_dsearch(dbc, 1, nval, - hcp->dpgno, &hcp->dndx, &hcp->dpagep, &cmp)) != 0) - return (ret); - if (cmp == 0) - hcp->dpgno = PGNO(hcp->dpagep); - } else { - if (hcp->dpagep == NULL && (ret = - __db_dend(dbc, hcp->dpgno, &hcp->dpagep)) != 0) - return (ret); - hcp->dpgno = PGNO(hcp->dpagep); - hcp->dndx = NUM_ENT(hcp->dpagep); - } - break; - case DB_CURRENT: - if (dbp->dup_compare != NULL && __bam_cmp(dbp, - nval, hcp->dpagep, hcp->dndx, dbp->dup_compare) != 0) - return (EINVAL); - switch (GET_BKEYDATA(hcp->dpagep, hcp->dndx)->type) { - case B_KEYDATA: - del_len = BKEYDATA_SIZE(GET_BKEYDATA(hcp->dpagep, - hcp->dndx)->len); - break; - case B_OVERFLOW: - del_len = BOVERFLOW_SIZE; - break; - } - if ((ret = - __db_ditem(dbc, hcp->dpagep, hcp->dndx, del_len)) != 0) - return (ret); - break; - case DB_BEFORE: /* The default behavior is correct. */ - break; - case DB_AFTER: - hcp->dndx++; - break; - } - - ret = __db_dput(dbc, - nval, &hcp->dpagep, &hcp->dndx, __ham_overflow_page); - hcp->pgno = PGNO(hcp->pagep); - __ham_c_update(hcp, hcp->pgno, nval->size, 1, 1); - return (ret); -} - -/* - * Convert an on-page set of duplicates to an offpage set of duplicates. - */ -static int -__ham_dup_convert(dbc) - DBC *dbc; -{ - DB *dbp; - HASH_CURSOR *hcp; - BOVERFLOW bo; - DBT dbt; - HOFFPAGE ho; - db_indx_t dndx, i, len, off; - int ret; - u_int8_t *p, *pend; - - /* - * Create a new page for the duplicates. - */ - dbp = dbc->dbp; - hcp = (HASH_CURSOR *)dbc->internal; - if ((ret = - __ham_overflow_page(dbc, P_DUPLICATE, &hcp->dpagep)) != 0) - return (ret); - hcp->dpagep->type = P_DUPLICATE; - hcp->dpgno = PGNO(hcp->dpagep); - - /* - * Now put the duplicates onto the new page. - */ - dndx = 0; - dbt.flags = 0; - switch (HPAGE_PTYPE(H_PAIRDATA(hcp->pagep, hcp->bndx))) { - case H_KEYDATA: - /* Simple case, one key on page; move it to dup page. */ - dbt.size = - LEN_HDATA(hcp->pagep, hcp->hdr->pagesize, hcp->bndx); - dbt.data = HKEYDATA_DATA(H_PAIRDATA(hcp->pagep, hcp->bndx)); - ret = __db_pitem(dbc, hcp->dpagep, - (u_int32_t)dndx, BKEYDATA_SIZE(dbt.size), NULL, &dbt); - if (ret == 0) - __ham_dirty_page(dbp, hcp->dpagep); - break; - case H_OFFPAGE: - /* Simple case, one key on page; move it to dup page. */ - memcpy(&ho, - P_ENTRY(hcp->pagep, H_DATAINDEX(hcp->bndx)), HOFFPAGE_SIZE); - UMRW(bo.unused1); - B_TSET(bo.type, ho.type, 0); - UMRW(bo.unused2); - bo.pgno = ho.pgno; - bo.tlen = ho.tlen; - dbt.size = BOVERFLOW_SIZE; - dbt.data = &bo; - - ret = __db_pitem(dbc, hcp->dpagep, - (u_int32_t)dndx, dbt.size, &dbt, NULL); - if (ret == 0) - __ham_dirty_page(dbp, hcp->dpagep); - break; - case H_DUPLICATE: - p = HKEYDATA_DATA(H_PAIRDATA(hcp->pagep, hcp->bndx)); - pend = p + - LEN_HDATA(hcp->pagep, hcp->hdr->pagesize, hcp->bndx); - - /* - * We need to maintain the duplicate cursor position. - * Keep track of where we are in the duplicate set via - * the offset, and when it matches the one in the cursor, - * set the off-page duplicate cursor index to the current - * index. - */ - for (off = 0, i = 0; p < pend; i++) { - if (off == hcp->dup_off) - dndx = i; - memcpy(&len, p, sizeof(db_indx_t)); - dbt.size = len; - p += sizeof(db_indx_t); - dbt.data = p; - p += len + sizeof(db_indx_t); - off += len + 2 * sizeof(db_indx_t); - ret = __db_dput(dbc, &dbt, - &hcp->dpagep, &i, __ham_overflow_page); - if (ret != 0) - break; - } - break; - default: - ret = __db_pgfmt(dbp, (u_long)hcp->pgno); - break; - } - if (ret == 0) { - /* - * Now attach this to the source page in place of - * the old duplicate item. - */ - __ham_move_offpage(dbc, hcp->pagep, - (u_int32_t)H_DATAINDEX(hcp->bndx), hcp->dpgno); - - /* Can probably just do a "put" here. */ - ret = __ham_dirty_page(dbp, hcp->pagep); - hcp->dndx = dndx; - } else { - (void)__ham_del_page(dbc, hcp->dpagep); - hcp->dpagep = NULL; - } - return (ret); -} - -static int -__ham_make_dup(notdup, duplicate, bufp, sizep) - const DBT *notdup; - DBT *duplicate; - void **bufp; - u_int32_t *sizep; -{ - db_indx_t tsize, item_size; - int ret; - u_int8_t *p; - - item_size = (db_indx_t)notdup->size; - tsize = DUP_SIZE(item_size); - if ((ret = __ham_init_dbt(duplicate, tsize, bufp, sizep)) != 0) - return (ret); - - duplicate->dlen = 0; - duplicate->flags = notdup->flags; - F_SET(duplicate, DB_DBT_PARTIAL); - - p = duplicate->data; - memcpy(p, &item_size, sizeof(db_indx_t)); - p += sizeof(db_indx_t); - memcpy(p, notdup->data, notdup->size); - p += notdup->size; - memcpy(p, &item_size, sizeof(db_indx_t)); - - duplicate->doff = 0; - duplicate->dlen = notdup->size; - - return (0); -} - -static int -__ham_check_move(dbc, add_len) - DBC *dbc; - int32_t add_len; -{ - DB *dbp; - HASH_CURSOR *hcp; - DBT k, d; - DB_LSN new_lsn; - PAGE *next_pagep; - db_pgno_t next_pgno; - u_int32_t new_datalen, old_len, rectype; - u_int8_t *hk; - int ret; - - dbp = dbc->dbp; - hcp = (HASH_CURSOR *)dbc->internal; - /* - * Check if we can do whatever we need to on this page. If not, - * then we'll have to move the current element to a new page. - */ - hk = H_PAIRDATA(hcp->pagep, hcp->bndx); - - /* - * If the item is already off page duplicates or an offpage item, - * then we know we can do whatever we need to do in-place - */ - if (HPAGE_PTYPE(hk) == H_OFFDUP || HPAGE_PTYPE(hk) == H_OFFPAGE) - return (0); - - old_len = - LEN_HITEM(hcp->pagep, hcp->hdr->pagesize, H_DATAINDEX(hcp->bndx)); - new_datalen = old_len - HKEYDATA_SIZE(0) + add_len; - - /* - * We need to add a new page under two conditions: - * 1. The addition makes the total data length cross the BIG - * threshold and the OFFDUP structure won't fit on this page. - * 2. The addition does not make the total data cross the - * threshold, but the new data won't fit on the page. - * If neither of these is true, then we can return. - */ - if (ISBIG(hcp, new_datalen) && (old_len > HOFFDUP_SIZE || - HOFFDUP_SIZE - old_len <= P_FREESPACE(hcp->pagep))) - return (0); - - if (!ISBIG(hcp, new_datalen) && - add_len <= (int32_t)P_FREESPACE(hcp->pagep)) - return (0); - - /* - * If we get here, then we need to move the item to a new page. - * Check if there are more pages in the chain. - */ - - new_datalen = ISBIG(hcp, new_datalen) ? - HOFFDUP_SIZE : HKEYDATA_SIZE(new_datalen); - - next_pagep = NULL; - for (next_pgno = NEXT_PGNO(hcp->pagep); next_pgno != PGNO_INVALID; - next_pgno = NEXT_PGNO(next_pagep)) { - if (next_pagep != NULL && - (ret = __ham_put_page(dbp, next_pagep, 0)) != 0) - return (ret); - - if ((ret = - __ham_get_page(dbp, next_pgno, &next_pagep)) != 0) - return (ret); - - if (P_FREESPACE(next_pagep) >= new_datalen) - break; - } - - /* No more pages, add one. */ - if (next_pagep == NULL && (ret = __ham_add_ovflpage(dbc, - hcp->pagep, 0, &next_pagep)) != 0) - return (ret); - - /* Add new page at the end of the chain. */ - if (P_FREESPACE(next_pagep) < new_datalen && (ret = - __ham_add_ovflpage(dbc, next_pagep, 1, &next_pagep)) != 0) - return (ret); - - /* Copy the item to the new page. */ - if (DB_LOGGING(hcp->dbc)) { - rectype = PUTPAIR; - k.flags = 0; - d.flags = 0; - if (HPAGE_PTYPE( - H_PAIRKEY(hcp->pagep, hcp->bndx)) == H_OFFPAGE) { - rectype |= PAIR_KEYMASK; - k.data = H_PAIRKEY(hcp->pagep, hcp->bndx); - k.size = HOFFPAGE_SIZE; - } else { - k.data = - HKEYDATA_DATA(H_PAIRKEY(hcp->pagep, hcp->bndx)); - k.size = LEN_HKEY(hcp->pagep, - hcp->hdr->pagesize, hcp->bndx); - } - - if (HPAGE_PTYPE(hk) == H_OFFPAGE) { - rectype |= PAIR_DATAMASK; - d.data = H_PAIRDATA(hcp->pagep, hcp->bndx); - d.size = HOFFPAGE_SIZE; - } else { - d.data = - HKEYDATA_DATA(H_PAIRDATA(hcp->pagep, hcp->bndx)); - d.size = LEN_HDATA(hcp->pagep, - hcp->hdr->pagesize, hcp->bndx); - } - - - if ((ret = __ham_insdel_log(dbp->dbenv->lg_info, - dbc->txn, &new_lsn, 0, rectype, - dbp->log_fileid, PGNO(next_pagep), - (u_int32_t)H_NUMPAIRS(next_pagep), &LSN(next_pagep), - &k, &d)) != 0) - return (ret); - - /* Move lsn onto page. */ - LSN(next_pagep) = new_lsn; /* Structure assignment. */ - } - - __ham_copy_item(dbp->pgsize, - hcp->pagep, H_KEYINDEX(hcp->bndx), next_pagep); - __ham_copy_item(dbp->pgsize, - hcp->pagep, H_DATAINDEX(hcp->bndx), next_pagep); - - /* Now delete the pair from the current page. */ - ret = __ham_del_pair(dbc, 0); - - (void)__ham_put_page(dbp, hcp->pagep, 1); - hcp->pagep = next_pagep; - hcp->pgno = PGNO(hcp->pagep); - hcp->bndx = H_NUMPAIRS(hcp->pagep) - 1; - F_SET(hcp, H_EXPAND); - return (ret); -} - -/* - * __ham_move_offpage -- - * Replace an onpage set of duplicates with the OFFDUP structure - * that references the duplicate page. - * - * XXX - * This is really just a special case of __onpage_replace; we should - * probably combine them. - * - * PUBLIC: void __ham_move_offpage __P((DBC *, PAGE *, u_int32_t, db_pgno_t)); - */ -void -__ham_move_offpage(dbc, pagep, ndx, pgno) - DBC *dbc; - PAGE *pagep; - u_int32_t ndx; - db_pgno_t pgno; -{ - DB *dbp; - HASH_CURSOR *hcp; - DBT new_dbt; - DBT old_dbt; - HOFFDUP od; - db_indx_t i; - int32_t shrink; - u_int8_t *src; - - dbp = dbc->dbp; - hcp = (HASH_CURSOR *)dbc->internal; - od.type = H_OFFDUP; - UMRW(od.unused[0]); - UMRW(od.unused[1]); - UMRW(od.unused[2]); - od.pgno = pgno; - - if (DB_LOGGING(dbc)) { - new_dbt.data = &od; - new_dbt.size = HOFFDUP_SIZE; - old_dbt.data = P_ENTRY(pagep, ndx); - old_dbt.size = LEN_HITEM(pagep, hcp->hdr->pagesize, ndx); - (void)__ham_replace_log(dbp->dbenv->lg_info, - dbc->txn, &LSN(pagep), 0, dbp->log_fileid, - PGNO(pagep), (u_int32_t)ndx, &LSN(pagep), -1, - &old_dbt, &new_dbt, 0); - } - - shrink = - LEN_HITEM(pagep, hcp->hdr->pagesize, ndx) - HOFFDUP_SIZE; - - if (shrink != 0) { - /* Copy data. */ - src = (u_int8_t *)(pagep) + HOFFSET(pagep); - memmove(src + shrink, src, pagep->inp[ndx] - HOFFSET(pagep)); - HOFFSET(pagep) += shrink; - - /* Update index table. */ - for (i = ndx; i < NUM_ENT(pagep); i++) - pagep->inp[i] += shrink; - } - - /* Now copy the offdup entry onto the page. */ - memcpy(P_ENTRY(pagep, ndx), &od, HOFFDUP_SIZE); -} - -/* - * __ham_dsearch: - * Locate a particular duplicate in a duplicate set. - * - * PUBLIC: void __ham_dsearch __P((DBC *, DBT *, u_int32_t *, int *)); - */ -void -__ham_dsearch(dbc, dbt, offp, cmpp) - DBC *dbc; - DBT *dbt; - u_int32_t *offp; - int *cmpp; -{ - DB *dbp; - HASH_CURSOR *hcp; - DBT cur; - db_indx_t i, len; - int (*func) __P((const DBT *, const DBT *)); - u_int8_t *data; - - dbp = dbc->dbp; - hcp = (HASH_CURSOR *)dbc->internal; - if (dbp->dup_compare == NULL) - func = __bam_defcmp; - else - func = dbp->dup_compare; - - i = F_ISSET(dbc, DBC_CONTINUE) ? hcp->dup_off: 0; - data = HKEYDATA_DATA(H_PAIRDATA(hcp->pagep, hcp->bndx)) + i; - while (i < LEN_HDATA(hcp->pagep, hcp->hdr->pagesize, hcp->bndx)) { - memcpy(&len, data, sizeof(db_indx_t)); - data += sizeof(db_indx_t); - cur.data = data; - cur.size = (u_int32_t)len; - *cmpp = func(dbt, &cur); - if (*cmpp == 0 || (*cmpp < 0 && dbp->dup_compare != NULL)) - break; - i += len + 2 * sizeof(db_indx_t); - data += len + sizeof(db_indx_t); - } - *offp = i; -} diff --git a/db2/hash/hash_func.c b/db2/hash/hash_func.c deleted file mode 100644 index 9131098..0000000 --- a/db2/hash/hash_func.c +++ /dev/null @@ -1,219 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993 - * Margo Seltzer. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993 - * 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[] = "@(#)hash_func.c 10.8 (Sleepycat) 4/10/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> -#endif - -#include "db_int.h" -#include "db_page.h" -#include "hash.h" - -/* - * __ham_func2 -- - * Phong Vo's linear congruential hash. - * - * PUBLIC: u_int32_t __ham_func2 __P((const void *, u_int32_t)); - */ -#define DCHARHASH(h, c) ((h) = 0x63c63cd9*(h) + 0x9c39c33d + (c)) - -u_int32_t -__ham_func2(key, len) - const void *key; - u_int32_t len; -{ - const u_int8_t *e, *k; - u_int32_t h; - u_int8_t c; - - k = key; - e = k + len; - for (h = 0; k != e;) { - c = *k++; - if (!c && k > e) - break; - DCHARHASH(h, c); - } - return (h); -} - -/* - * __ham_func3 -- - * Ozan Yigit's original sdbm hash. - * - * Ugly, but fast. Break the string up into 8 byte units. On the first time - * through the loop get the "leftover bytes" (strlen % 8). On every other - * iteration, perform 8 HASHC's so we handle all 8 bytes. Essentially, this - * saves us 7 cmp & branch instructions. - * - * PUBLIC: u_int32_t __ham_func3 __P((const void *, u_int32_t)); - */ -u_int32_t -__ham_func3(key, len) - const void *key; - u_int32_t len; -{ - const u_int8_t *k; - u_int32_t n, loop; - - if (len == 0) - return (0); - -#define HASHC n = *k++ + 65599 * n - n = 0; - k = key; - - loop = (len + 8 - 1) >> 3; - switch (len & (8 - 1)) { - case 0: - do { - HASHC; - case 7: - HASHC; - case 6: - HASHC; - case 5: - HASHC; - case 4: - HASHC; - case 3: - HASHC; - case 2: - HASHC; - case 1: - HASHC; - } while (--loop); - } - return (n); -} - -/* - * __ham_func4 -- - * Chris Torek's hash function. Although this function performs only - * slightly worse than __ham_func5 on strings, it performs horribly on - * numbers. - * - * PUBLIC: u_int32_t __ham_func4 __P((const void *, u_int32_t)); - */ -u_int32_t -__ham_func4(key, len) - const void *key; - u_int32_t len; -{ - const u_int8_t *k; - u_int32_t h, loop; - - if (len == 0) - return (0); - -#define HASH4a h = (h << 5) - h + *k++; -#define HASH4b h = (h << 5) + h + *k++; -#define HASH4 HASH4b - h = 0; - k = key; - - loop = (len + 8 - 1) >> 3; - switch (len & (8 - 1)) { - case 0: - do { - HASH4; - case 7: - HASH4; - case 6: - HASH4; - case 5: - HASH4; - case 4: - HASH4; - case 3: - HASH4; - case 2: - HASH4; - case 1: - HASH4; - } while (--loop); - } - return (h); -} - -/* - * Fowler/Noll/Vo hash - * - * The basis of the hash algorithm was taken from an idea sent by email to the - * IEEE Posix P1003.2 mailing list from Phong Vo (kpv@research.att.com) and - * Glenn Fowler (gsf@research.att.com). Landon Curt Noll (chongo@toad.com) - * later improved on their algorithm. - * - * The magic is in the interesting relationship between the special prime - * 16777619 (2^24 + 403) and 2^32 and 2^8. - * - * This hash produces the fewest collisions of any function that we've seen so - * far, and works well on both numbers and strings. - * - * PUBLIC: u_int32_t __ham_func5 __P((const void *, u_int32_t)); - */ -u_int32_t -__ham_func5(key, len) - const void *key; - u_int32_t len; -{ - const u_int8_t *k, *e; - u_int32_t h; - - k = key; - e = k + len; - for (h = 0; k < e; ++k) { - h *= 16777619; - h ^= *k; - } - return (h); -} diff --git a/db2/hash/hash_page.c b/db2/hash/hash_page.c deleted file mode 100644 index 3419c12..0000000 --- a/db2/hash/hash_page.c +++ /dev/null @@ -1,1929 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994 - * Margo Seltzer. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994 - * 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[] = "@(#)hash_page.c 10.55 (Sleepycat) 1/3/99"; -#endif /* not lint */ - -/* - * PACKAGE: hashing - * - * DESCRIPTION: - * Page manipulation for hashing package. - * - * ROUTINES: - * - * External - * __get_page - * __add_ovflpage - * __overflow_page - * Internal - * open_temp - */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <string.h> -#endif - -#include "db_int.h" -#include "db_page.h" -#include "hash.h" - -static int __ham_lock_bucket __P((DBC *, db_lockmode_t)); - -#ifdef DEBUG_SLOW -static void __account_page(DB *, db_pgno_t, int); -#endif - -/* - * PUBLIC: int __ham_item __P((DBC *, db_lockmode_t)); - */ -int -__ham_item(dbc, mode) - DBC *dbc; - db_lockmode_t mode; -{ - DB *dbp; - HASH_CURSOR *hcp; - db_pgno_t next_pgno; - int ret; - - dbp = dbc->dbp; - hcp = (HASH_CURSOR *)dbc->internal; - - if (F_ISSET(hcp, H_DELETED)) - return (EINVAL); - F_CLR(hcp, H_OK | H_NOMORE); - - /* Check if we need to get a page for this cursor. */ - if ((ret = __ham_get_cpage(dbc, mode)) != 0) - return (ret); - - /* Check if we are looking for space in which to insert an item. */ - if (hcp->seek_size && hcp->seek_found_page == PGNO_INVALID - && hcp->seek_size < P_FREESPACE(hcp->pagep)) - hcp->seek_found_page = hcp->pgno; - - /* Check if we need to go on to the next page. */ - if (F_ISSET(hcp, H_ISDUP) && hcp->dpgno == PGNO_INVALID) - /* - * ISDUP is set, and offset is at the beginning of the datum. - * We need to grab the length of the datum, then set the datum - * pointer to be the beginning of the datum. - */ - memcpy(&hcp->dup_len, - HKEYDATA_DATA(H_PAIRDATA(hcp->pagep, hcp->bndx)) + - hcp->dup_off, sizeof(db_indx_t)); - else if (F_ISSET(hcp, H_ISDUP)) { - /* Make sure we're not about to run off the page. */ - if (hcp->dpagep == NULL && (ret = __ham_get_page(dbp, - hcp->dpgno, &hcp->dpagep)) != 0) - return (ret); - - if (hcp->dndx >= NUM_ENT(hcp->dpagep)) { - if (NEXT_PGNO(hcp->dpagep) == PGNO_INVALID) { - if (F_ISSET(hcp, H_DUPONLY)) { - F_CLR(hcp, H_OK); - F_SET(hcp, H_NOMORE); - return (0); - } - if ((ret = __ham_put_page(dbp, - hcp->dpagep, 0)) != 0) - return (ret); - F_CLR(hcp, H_ISDUP); - hcp->dpagep = NULL; - hcp->dpgno = PGNO_INVALID; - hcp->dndx = NDX_INVALID; - hcp->bndx++; - } else if ((ret = __ham_next_cpage(dbc, - NEXT_PGNO(hcp->dpagep), 0, H_ISDUP)) != 0) - return (ret); - } - } - - if (hcp->bndx >= (db_indx_t)H_NUMPAIRS(hcp->pagep)) { - /* Fetch next page. */ - if (NEXT_PGNO(hcp->pagep) == PGNO_INVALID) { - F_SET(hcp, H_NOMORE); - if (hcp->dpagep != NULL && - (ret = __ham_put_page(dbp, hcp->dpagep, 0)) != 0) - return (ret); - hcp->dpgno = PGNO_INVALID; - return (DB_NOTFOUND); - } - next_pgno = NEXT_PGNO(hcp->pagep); - hcp->bndx = 0; - if ((ret = __ham_next_cpage(dbc, next_pgno, 0, 0)) != 0) - return (ret); - } - - F_SET(hcp, H_OK); - return (0); -} - -/* - * PUBLIC: int __ham_item_reset __P((DBC *)); - */ -int -__ham_item_reset(dbc) - DBC *dbc; -{ - HASH_CURSOR *hcp; - DB *dbp; - int ret; - - ret = 0; - dbp = dbc->dbp; - hcp = (HASH_CURSOR *)dbc->internal; - if (hcp->pagep != NULL) - ret = __ham_put_page(dbp, hcp->pagep, 0); - if (ret == 0 && hcp->dpagep != NULL) - ret = __ham_put_page(dbp, hcp->dpagep, 0); - - __ham_item_init(hcp); - return (ret); -} - -/* - * PUBLIC: void __ham_item_init __P((HASH_CURSOR *)); - */ -void -__ham_item_init(hcp) - HASH_CURSOR *hcp; -{ - /* - * If this cursor still holds any locks, we must - * release them if we are not running with transactions. - */ - if (hcp->lock && hcp->dbc->txn == NULL) - (void)lock_put(hcp->dbc->dbp->dbenv->lk_info, hcp->lock); - - /* - * The following fields must *not* be initialized here - * because they may have meaning across inits. - * hlock, hdr, split_buf, stats - */ - hcp->bucket = BUCKET_INVALID; - hcp->lbucket = BUCKET_INVALID; - hcp->lock = 0; - hcp->pagep = NULL; - hcp->pgno = PGNO_INVALID; - hcp->bndx = NDX_INVALID; - hcp->dpagep = NULL; - hcp->dpgno = PGNO_INVALID; - hcp->dndx = NDX_INVALID; - hcp->dup_off = 0; - hcp->dup_len = 0; - hcp->dup_tlen = 0; - hcp->seek_size = 0; - hcp->seek_found_page = PGNO_INVALID; - hcp->flags = 0; -} - -/* - * PUBLIC: int __ham_item_done __P((DBC *, int)); - */ -int -__ham_item_done(dbc, dirty) - DBC *dbc; - int dirty; -{ - DB *dbp; - HASH_CURSOR *hcp; - int ret, t_ret; - - dbp = dbc->dbp; - hcp = (HASH_CURSOR *)dbc->internal; - t_ret = ret = 0; - - if (hcp->pagep) - ret = __ham_put_page(dbp, hcp->pagep, - dirty && hcp->dpagep == NULL); - hcp->pagep = NULL; - - if (hcp->dpagep) - t_ret = __ham_put_page(dbp, hcp->dpagep, dirty); - hcp->dpagep = NULL; - - if (ret == 0 && t_ret != 0) - ret = t_ret; - - /* - * We don't throw out the page number since we might want to - * continue getting on this page. - */ - return (ret != 0 ? ret : t_ret); -} - -/* - * Returns the last item in a bucket. - * - * PUBLIC: int __ham_item_last __P((DBC *, db_lockmode_t)); - */ -int -__ham_item_last(dbc, mode) - DBC *dbc; - db_lockmode_t mode; -{ - HASH_CURSOR *hcp; - int ret; - - hcp = (HASH_CURSOR *)dbc->internal; - if ((ret = __ham_item_reset(dbc)) != 0) - return (ret); - - hcp->bucket = hcp->hdr->max_bucket; - F_SET(hcp, H_OK); - return (__ham_item_prev(dbc, mode)); -} - -/* - * PUBLIC: int __ham_item_first __P((DBC *, db_lockmode_t)); - */ -int -__ham_item_first(dbc, mode) - DBC *dbc; - db_lockmode_t mode; -{ - HASH_CURSOR *hcp; - int ret; - - hcp = (HASH_CURSOR *)dbc->internal; - if ((ret = __ham_item_reset(dbc)) != 0) - return (ret); - F_SET(hcp, H_OK); - hcp->bucket = 0; - return (__ham_item_next(dbc, mode)); -} - -/* - * __ham_item_prev -- - * Returns a pointer to key/data pair on a page. In the case of - * bigkeys, just returns the page number and index of the bigkey - * pointer pair. - * - * PUBLIC: int __ham_item_prev __P((DBC *, db_lockmode_t)); - */ -int -__ham_item_prev(dbc, mode) - DBC *dbc; - db_lockmode_t mode; -{ - DB *dbp; - HASH_CURSOR *hcp; - db_pgno_t next_pgno; - int ret; - - dbp = dbc->dbp; - hcp = (HASH_CURSOR *)dbc->internal; - /* - * There are N cases for backing up in a hash file. - * Case 1: In the middle of a page, no duplicates, just dec the index. - * Case 2: In the middle of a duplicate set, back up one. - * Case 3: At the beginning of a duplicate set, get out of set and - * back up to next key. - * Case 4: At the beginning of a page; go to previous page. - * Case 5: At the beginning of a bucket; go to prev bucket. - */ - F_CLR(hcp, H_OK | H_NOMORE | H_DELETED); - - /* - * First handle the duplicates. Either you'll get the key here - * or you'll exit the duplicate set and drop into the code below - * to handle backing up through keys. - */ - if (F_ISSET(hcp, H_ISDUP)) { - if (hcp->dpgno == PGNO_INVALID) { - /* Duplicates are on-page. */ - if (hcp->dup_off != 0) { - if ((ret = __ham_get_cpage(dbc, mode)) != 0) - return (ret); - else { - HASH_CURSOR *h; - h = hcp; - memcpy(&h->dup_len, HKEYDATA_DATA( - H_PAIRDATA(h->pagep, h->bndx)) - + h->dup_off - sizeof(db_indx_t), - sizeof(db_indx_t)); - hcp->dup_off -= - DUP_SIZE(hcp->dup_len); - hcp->dndx--; - return (__ham_item(dbc, mode)); - } - } - } else if (hcp->dndx > 0) { /* Duplicates are off-page. */ - hcp->dndx--; - return (__ham_item(dbc, mode)); - } else if ((ret = __ham_get_cpage(dbc, mode)) != 0) - return (ret); - else if (PREV_PGNO(hcp->dpagep) == PGNO_INVALID) { - if (F_ISSET(hcp, H_DUPONLY)) { - F_CLR(hcp, H_OK); - F_SET(hcp, H_NOMORE); - return (0); - } else { - F_CLR(hcp, H_ISDUP); /* End of dups */ - hcp->dpgno = PGNO_INVALID; - if (hcp->dpagep != NULL) - (void)__ham_put_page(dbp, - hcp->dpagep, 0); - hcp->dpagep = NULL; - } - } else if ((ret = __ham_next_cpage(dbc, - PREV_PGNO(hcp->dpagep), 0, H_ISDUP)) != 0) - return (ret); - else { - hcp->dndx = NUM_ENT(hcp->pagep) - 1; - return (__ham_item(dbc, mode)); - } - } - - /* - * If we get here, we are not in a duplicate set, and just need - * to back up the cursor. There are still three cases: - * midpage, beginning of page, beginning of bucket. - */ - - if (F_ISSET(hcp, H_DUPONLY)) { - F_CLR(hcp, H_OK); - F_SET(hcp, H_NOMORE); - return (0); - } - - if (hcp->bndx == 0) { /* Beginning of page. */ - if ((ret = __ham_get_cpage(dbc, mode)) != 0) - return (ret); - hcp->pgno = PREV_PGNO(hcp->pagep); - if (hcp->pgno == PGNO_INVALID) { - /* Beginning of bucket. */ - F_SET(hcp, H_NOMORE); - return (DB_NOTFOUND); - } else if ((ret = - __ham_next_cpage(dbc, hcp->pgno, 0, 0)) != 0) - return (ret); - else - hcp->bndx = H_NUMPAIRS(hcp->pagep); - } - - /* - * Either we've got the cursor set up to be decremented, or we - * have to find the end of a bucket. - */ - if (hcp->bndx == NDX_INVALID) { - if (hcp->pagep == NULL) - next_pgno = BUCKET_TO_PAGE(hcp, hcp->bucket); - else - goto got_page; - - do { - if ((ret = __ham_next_cpage(dbc, next_pgno, 0, 0)) != 0) - return (ret); -got_page: next_pgno = NEXT_PGNO(hcp->pagep); - hcp->bndx = H_NUMPAIRS(hcp->pagep); - } while (next_pgno != PGNO_INVALID); - - if (hcp->bndx == 0) { - /* Bucket was empty. */ - F_SET(hcp, H_NOMORE); - return (DB_NOTFOUND); - } - } - - hcp->bndx--; - - return (__ham_item(dbc, mode)); -} - -/* - * Sets the cursor to the next key/data pair on a page. - * - * PUBLIC: int __ham_item_next __P((DBC *, db_lockmode_t)); - */ -int -__ham_item_next(dbc, mode) - DBC *dbc; - db_lockmode_t mode; -{ - HASH_CURSOR *hcp; - - hcp = (HASH_CURSOR *)dbc->internal; - /* - * Deleted on-page duplicates are a weird case. If we delete the last - * one, then our cursor is at the very end of a duplicate set and - * we actually need to go on to the next key. - */ - if (F_ISSET(hcp, H_DELETED)) { - if (hcp->bndx != NDX_INVALID && - F_ISSET(hcp, H_ISDUP) && - hcp->dpgno == PGNO_INVALID && - hcp->dup_tlen == hcp->dup_off) { - if (F_ISSET(hcp, H_DUPONLY)) { - F_CLR(hcp, H_OK); - F_SET(hcp, H_NOMORE); - return (0); - } else { - F_CLR(hcp, H_ISDUP); - hcp->dpgno = PGNO_INVALID; - hcp->bndx++; - } - } else if (!F_ISSET(hcp, H_ISDUP) && - F_ISSET(hcp, H_DUPONLY)) { - F_CLR(hcp, H_OK); - F_SET(hcp, H_NOMORE); - return (0); - } - F_CLR(hcp, H_DELETED); - } else if (hcp->bndx == NDX_INVALID) { - hcp->bndx = 0; - hcp->dpgno = PGNO_INVALID; - F_CLR(hcp, H_ISDUP); - } else if (F_ISSET(hcp, H_ISDUP) && hcp->dpgno != PGNO_INVALID) - hcp->dndx++; - else if (F_ISSET(hcp, H_ISDUP)) { - if (hcp->dup_off + DUP_SIZE(hcp->dup_len) >= - hcp->dup_tlen && F_ISSET(hcp, H_DUPONLY)) { - F_CLR(hcp, H_OK); - F_SET(hcp, H_NOMORE); - return (0); - } - hcp->dndx++; - hcp->dup_off += DUP_SIZE(hcp->dup_len); - if (hcp->dup_off >= hcp->dup_tlen) { - F_CLR(hcp, H_ISDUP); - hcp->dpgno = PGNO_INVALID; - hcp->bndx++; - } - } else if (F_ISSET(hcp, H_DUPONLY)) { - F_CLR(hcp, H_OK); - F_SET(hcp, H_NOMORE); - return (0); - } else - hcp->bndx++; - - return (__ham_item(dbc, mode)); -} - -/* - * PUBLIC: void __ham_putitem __P((PAGE *p, const DBT *, int)); - * - * This is a little bit sleazy in that we're overloading the meaning - * of the H_OFFPAGE type here. When we recover deletes, we have the - * entire entry instead of having only the DBT, so we'll pass type - * H_OFFPAGE to mean, "copy the whole entry" as opposed to constructing - * an H_KEYDATA around it. - */ -void -__ham_putitem(p, dbt, type) - PAGE *p; - const DBT *dbt; - int type; -{ - u_int16_t n, off; - - n = NUM_ENT(p); - - /* Put the item element on the page. */ - if (type == H_OFFPAGE) { - off = HOFFSET(p) - dbt->size; - HOFFSET(p) = p->inp[n] = off; - memcpy(P_ENTRY(p, n), dbt->data, dbt->size); - } else { - off = HOFFSET(p) - HKEYDATA_SIZE(dbt->size); - HOFFSET(p) = p->inp[n] = off; - PUT_HKEYDATA(P_ENTRY(p, n), dbt->data, dbt->size, type); - } - - /* Adjust page info. */ - NUM_ENT(p) += 1; -} - -/* - * PUBLIC: void __ham_reputpair - * PUBLIC: __P((PAGE *p, u_int32_t, u_int32_t, const DBT *, const DBT *)); - * - * This is a special case to restore a key/data pair to its original - * location during recovery. We are guaranteed that the pair fits - * on the page and is not the last pair on the page (because if it's - * the last pair, the normal insert works). - */ -void -__ham_reputpair(p, psize, ndx, key, data) - PAGE *p; - u_int32_t psize, ndx; - const DBT *key, *data; -{ - db_indx_t i, movebytes, newbytes; - u_int8_t *from; - - /* First shuffle the existing items up on the page. */ - movebytes = - (ndx == 0 ? psize : p->inp[H_DATAINDEX(ndx - 1)]) - HOFFSET(p); - newbytes = key->size + data->size; - from = (u_int8_t *)p + HOFFSET(p); - memmove(from - newbytes, from, movebytes); - - /* - * Adjust the indices and move them up 2 spaces. Note that we - * have to check the exit condition inside the loop just in case - * we are dealing with index 0 (db_indx_t's are unsigned). - */ - for (i = NUM_ENT(p) - 1; ; i-- ) { - p->inp[i + 2] = p->inp[i] - newbytes; - if (i == H_KEYINDEX(ndx)) - break; - } - - /* Put the key and data on the page. */ - p->inp[H_KEYINDEX(ndx)] = - (ndx == 0 ? psize : p->inp[H_DATAINDEX(ndx - 1)]) - key->size; - p->inp[H_DATAINDEX(ndx)] = p->inp[H_KEYINDEX(ndx)] - data->size; - memcpy(P_ENTRY(p, H_KEYINDEX(ndx)), key->data, key->size); - memcpy(P_ENTRY(p, H_DATAINDEX(ndx)), data->data, data->size); - - /* Adjust page info. */ - HOFFSET(p) -= newbytes; - NUM_ENT(p) += 2; -} - - -/* - * PUBLIC: int __ham_del_pair __P((DBC *, int)); - */ -int -__ham_del_pair(dbc, reclaim_page) - DBC *dbc; - int reclaim_page; -{ - DB *dbp; - HASH_CURSOR *hcp; - DBT data_dbt, key_dbt; - DB_ENV *dbenv; - DB_LSN new_lsn, *n_lsn, tmp_lsn; - PAGE *p; - db_indx_t ndx; - db_pgno_t chg_pgno, pgno; - int ret, tret; - - dbp = dbc->dbp; - hcp = (HASH_CURSOR *)dbc->internal; - - dbenv = dbp->dbenv; - ndx = hcp->bndx; - if (hcp->pagep == NULL && - (ret = __ham_get_page(dbp, hcp->pgno, &hcp->pagep)) != 0) - return (ret); - - p = hcp->pagep; - - /* - * We optimize for the normal case which is when neither the key nor - * the data are large. In this case, we write a single log record - * and do the delete. If either is large, we'll call __big_delete - * to remove the big item and then update the page to remove the - * entry referring to the big item. - */ - ret = 0; - if (HPAGE_PTYPE(H_PAIRKEY(p, ndx)) == H_OFFPAGE) { - memcpy(&pgno, HOFFPAGE_PGNO(P_ENTRY(p, H_KEYINDEX(ndx))), - sizeof(db_pgno_t)); - ret = __db_doff(dbc, pgno, __ham_del_page); - } - - if (ret == 0) - switch (HPAGE_PTYPE(H_PAIRDATA(p, ndx))) { - case H_OFFPAGE: - memcpy(&pgno, - HOFFPAGE_PGNO(P_ENTRY(p, H_DATAINDEX(ndx))), - sizeof(db_pgno_t)); - ret = __db_doff(dbc, pgno, __ham_del_page); - break; - case H_OFFDUP: - memcpy(&pgno, - HOFFDUP_PGNO(P_ENTRY(p, H_DATAINDEX(ndx))), - sizeof(db_pgno_t)); - ret = __db_ddup(dbc, pgno, __ham_del_page); - F_CLR(hcp, H_ISDUP); - break; - case H_DUPLICATE: - /* - * If we delete a pair that is/was a duplicate, then - * we had better clear the flag so that we update the - * cursor appropriately. - */ - F_CLR(hcp, H_ISDUP); - break; - } - - if (ret) - return (ret); - - /* Now log the delete off this page. */ - if (DB_LOGGING(dbc)) { - key_dbt.data = P_ENTRY(p, H_KEYINDEX(ndx)); - key_dbt.size = - LEN_HITEM(p, hcp->hdr->pagesize, H_KEYINDEX(ndx)); - data_dbt.data = P_ENTRY(p, H_DATAINDEX(ndx)); - data_dbt.size = - LEN_HITEM(p, hcp->hdr->pagesize, H_DATAINDEX(ndx)); - - if ((ret = __ham_insdel_log(dbenv->lg_info, - dbc->txn, &new_lsn, 0, DELPAIR, - dbp->log_fileid, PGNO(p), (u_int32_t)ndx, - &LSN(p), &key_dbt, &data_dbt)) != 0) - return (ret); - - /* Move lsn onto page. */ - LSN(p) = new_lsn; - } - - __ham_dpair(dbp, p, ndx); - - /* - * If we are locking, we will not maintain this, because it is - * a hot spot. - * XXX perhaps we can retain incremental numbers and apply them - * later. - */ - if (!F_ISSET(dbp, DB_AM_LOCKING)) - --hcp->hdr->nelem; - - /* - * If we need to reclaim the page, then check if the page is empty. - * There are two cases. If it's empty and it's not the first page - * in the bucket (i.e., the bucket page) then we can simply remove - * it. If it is the first chain in the bucket, then we need to copy - * the second page into it and remove the second page. - */ - if (reclaim_page && NUM_ENT(p) == 0 && PREV_PGNO(p) == PGNO_INVALID && - NEXT_PGNO(p) != PGNO_INVALID) { - PAGE *n_pagep, *nn_pagep; - db_pgno_t tmp_pgno; - - /* - * First page in chain is empty and we know that there - * are more pages in the chain. - */ - if ((ret = - __ham_get_page(dbp, NEXT_PGNO(p), &n_pagep)) != 0) - return (ret); - - if (NEXT_PGNO(n_pagep) != PGNO_INVALID) { - if ((ret = - __ham_get_page(dbp, NEXT_PGNO(n_pagep), - &nn_pagep)) != 0) { - (void) __ham_put_page(dbp, n_pagep, 0); - return (ret); - } - } - - if (DB_LOGGING(dbc)) { - key_dbt.data = n_pagep; - key_dbt.size = hcp->hdr->pagesize; - if ((ret = __ham_copypage_log(dbenv->lg_info, - dbc->txn, &new_lsn, 0, dbp->log_fileid, PGNO(p), - &LSN(p), PGNO(n_pagep), &LSN(n_pagep), - NEXT_PGNO(n_pagep), - NEXT_PGNO(n_pagep) == PGNO_INVALID ? NULL : - &LSN(nn_pagep), &key_dbt)) != 0) - return (ret); - - /* Move lsn onto page. */ - LSN(p) = new_lsn; /* Structure assignment. */ - LSN(n_pagep) = new_lsn; - if (NEXT_PGNO(n_pagep) != PGNO_INVALID) - LSN(nn_pagep) = new_lsn; - } - if (NEXT_PGNO(n_pagep) != PGNO_INVALID) { - PREV_PGNO(nn_pagep) = PGNO(p); - (void)__ham_put_page(dbp, nn_pagep, 1); - } - - tmp_pgno = PGNO(p); - tmp_lsn = LSN(p); - memcpy(p, n_pagep, hcp->hdr->pagesize); - PGNO(p) = tmp_pgno; - LSN(p) = tmp_lsn; - PREV_PGNO(p) = PGNO_INVALID; - - /* - * Cursor is advanced to the beginning of the next page. - */ - hcp->bndx = 0; - hcp->pgno = PGNO(p); - F_SET(hcp, H_DELETED); - chg_pgno = PGNO(p); - if ((ret = __ham_dirty_page(dbp, p)) != 0 || - (ret = __ham_del_page(dbc, n_pagep)) != 0) - return (ret); - } else if (reclaim_page && - NUM_ENT(p) == 0 && PREV_PGNO(p) != PGNO_INVALID) { - PAGE *n_pagep, *p_pagep; - - if ((ret = - __ham_get_page(dbp, PREV_PGNO(p), &p_pagep)) != 0) - return (ret); - - if (NEXT_PGNO(p) != PGNO_INVALID) { - if ((ret = __ham_get_page(dbp, - NEXT_PGNO(p), &n_pagep)) != 0) { - (void)__ham_put_page(dbp, p_pagep, 0); - return (ret); - } - n_lsn = &LSN(n_pagep); - } else { - n_pagep = NULL; - n_lsn = NULL; - } - - NEXT_PGNO(p_pagep) = NEXT_PGNO(p); - if (n_pagep != NULL) - PREV_PGNO(n_pagep) = PGNO(p_pagep); - - if (DB_LOGGING(dbc)) { - if ((ret = __ham_newpage_log(dbenv->lg_info, - dbc->txn, &new_lsn, 0, DELOVFL, - dbp->log_fileid, PREV_PGNO(p), &LSN(p_pagep), - PGNO(p), &LSN(p), NEXT_PGNO(p), n_lsn)) != 0) - return (ret); - - /* Move lsn onto page. */ - LSN(p_pagep) = new_lsn; /* Structure assignment. */ - if (n_pagep) - LSN(n_pagep) = new_lsn; - LSN(p) = new_lsn; - } - hcp->pgno = NEXT_PGNO(p); - hcp->bndx = 0; - /* - * Since we are about to delete the cursor page and we have - * just moved the cursor, we need to make sure that the - * old page pointer isn't left hanging around in the cursor. - */ - hcp->pagep = NULL; - chg_pgno = PGNO(p); - ret = __ham_del_page(dbc, p); - if ((tret = __ham_put_page(dbp, p_pagep, 1)) != 0 && - ret == 0) - ret = tret; - if (n_pagep != NULL && - (tret = __ham_put_page(dbp, n_pagep, 1)) != 0 && - ret == 0) - ret = tret; - if (ret != 0) - return (ret); - } else { - /* - * Mark item deleted so that we don't try to return it, and - * so that we update the cursor correctly on the next call - * to next. - */ - F_SET(hcp, H_DELETED); - chg_pgno = hcp->pgno; - ret = __ham_dirty_page(dbp, p); - } - __ham_c_update(hcp, chg_pgno, 0, 0, 0); - - /* - * Since we just deleted a pair from the master page, anything - * in hcp->dpgno should be cleared. - */ - hcp->dpgno = PGNO_INVALID; - - F_CLR(hcp, H_OK); - return (ret); -} - -/* - * __ham_replpair -- - * Given the key data indicated by the cursor, replace part/all of it - * according to the fields in the dbt. - * - * PUBLIC: int __ham_replpair __P((DBC *, DBT *, u_int32_t)); - */ -int -__ham_replpair(dbc, dbt, make_dup) - DBC *dbc; - DBT *dbt; - u_int32_t make_dup; -{ - DB *dbp; - HASH_CURSOR *hcp; - DBT old_dbt, tdata, tmp; - DB_LSN new_lsn; - int32_t change; /* XXX: Possible overflow. */ - u_int32_t len; - int is_big, ret, type; - u_int8_t *beg, *dest, *end, *hk, *src; - - /* - * Big item replacements are handled in generic code. - * Items that fit on the current page fall into 4 classes. - * 1. On-page element, same size - * 2. On-page element, new is bigger (fits) - * 3. On-page element, new is bigger (does not fit) - * 4. On-page element, old is bigger - * Numbers 1, 2, and 4 are essentially the same (and should - * be the common case). We handle case 3 as a delete and - * add. - */ - dbp = dbc->dbp; - hcp = (HASH_CURSOR *)dbc->internal; - - /* - * We need to compute the number of bytes that we are adding or - * removing from the entry. Normally, we can simply substract - * the number of bytes we are replacing (dbt->dlen) from the - * number of bytes we are inserting (dbt->size). However, if - * we are doing a partial put off the end of a record, then this - * formula doesn't work, because we are essentially adding - * new bytes. - */ - change = dbt->size - dbt->dlen; - - hk = H_PAIRDATA(hcp->pagep, hcp->bndx); - is_big = HPAGE_PTYPE(hk) == H_OFFPAGE; - - if (is_big) - memcpy(&len, HOFFPAGE_TLEN(hk), sizeof(u_int32_t)); - else - len = LEN_HKEYDATA(hcp->pagep, - dbp->pgsize, H_DATAINDEX(hcp->bndx)); - - if (dbt->doff + dbt->dlen > len) - change += dbt->doff + dbt->dlen - len; - - - if (change > (int32_t)P_FREESPACE(hcp->pagep) || is_big) { - /* - * Case 3 -- two subcases. - * A. This is not really a partial operation, but an overwrite. - * Simple del and add works. - * B. This is a partial and we need to construct the data that - * we are really inserting (yuck). - * In both cases, we need to grab the key off the page (in - * some cases we could do this outside of this routine; for - * cleanliness we do it here. If you happen to be on a big - * key, this could be a performance hit). - */ - tmp.flags = 0; - F_SET(&tmp, DB_DBT_MALLOC | DB_DBT_INTERNAL); - if ((ret = - __db_ret(dbp, hcp->pagep, H_KEYINDEX(hcp->bndx), - &tmp, &dbc->rkey.data, &dbc->rkey.size)) != 0) - return (ret); - - if (dbt->doff == 0 && dbt->dlen == len) { - ret = __ham_del_pair(dbc, 0); - if (ret == 0) - ret = __ham_add_el(dbc, &tmp, dbt, H_KEYDATA); - } else { /* Case B */ - type = HPAGE_PTYPE(hk) != H_OFFPAGE ? - HPAGE_PTYPE(hk) : H_KEYDATA; - tdata.flags = 0; - F_SET(&tdata, DB_DBT_MALLOC | DB_DBT_INTERNAL); - - if ((ret = __db_ret(dbp, hcp->pagep, - H_DATAINDEX(hcp->bndx), &tdata, &dbc->rdata.data, - &dbc->rdata.size)) != 0) - goto err; - - /* Now we can delete the item. */ - if ((ret = __ham_del_pair(dbc, 0)) != 0) { - __os_free(tdata.data, tdata.size); - goto err; - } - - /* Now shift old data around to make room for new. */ - if (change > 0) { - if ((ret = __os_realloc(&tdata.data, - tdata.size + change)) != 0) - return (ret); - memset((u_int8_t *)tdata.data + tdata.size, - 0, change); - } - end = (u_int8_t *)tdata.data + tdata.size; - - src = (u_int8_t *)tdata.data + dbt->doff + dbt->dlen; - if (src < end && tdata.size > dbt->doff + dbt->dlen) { - len = tdata.size - dbt->doff - dbt->dlen; - dest = src + change; - memmove(dest, src, len); - } - memcpy((u_int8_t *)tdata.data + dbt->doff, - dbt->data, dbt->size); - tdata.size += change; - - /* Now add the pair. */ - ret = __ham_add_el(dbc, &tmp, &tdata, type); - __os_free(tdata.data, tdata.size); - } -err: __os_free(tmp.data, tmp.size); - return (ret); - } - - /* - * Set up pointer into existing data. Do it before the log - * message so we can use it inside of the log setup. - */ - beg = HKEYDATA_DATA(H_PAIRDATA(hcp->pagep, hcp->bndx)); - beg += dbt->doff; - - /* - * If we are going to have to move bytes at all, figure out - * all the parameters here. Then log the call before moving - * anything around. - */ - if (DB_LOGGING(dbc)) { - old_dbt.data = beg; - old_dbt.size = dbt->dlen; - if ((ret = __ham_replace_log(dbp->dbenv->lg_info, - dbc->txn, &new_lsn, 0, dbp->log_fileid, PGNO(hcp->pagep), - (u_int32_t)H_DATAINDEX(hcp->bndx), &LSN(hcp->pagep), - (u_int32_t)dbt->doff, &old_dbt, dbt, make_dup)) != 0) - return (ret); - - LSN(hcp->pagep) = new_lsn; /* Structure assignment. */ - } - - __ham_onpage_replace(hcp->pagep, dbp->pgsize, - (u_int32_t)H_DATAINDEX(hcp->bndx), (int32_t)dbt->doff, change, dbt); - - return (0); -} - -/* - * Replace data on a page with new data, possibly growing or shrinking what's - * there. This is called on two different occasions. On one (from replpair) - * we are interested in changing only the data. On the other (from recovery) - * we are replacing the entire data (header and all) with a new element. In - * the latter case, the off argument is negative. - * pagep: the page that we're changing - * ndx: page index of the element that is growing/shrinking. - * off: Offset at which we are beginning the replacement. - * change: the number of bytes (+ or -) that the element is growing/shrinking. - * dbt: the new data that gets written at beg. - * PUBLIC: void __ham_onpage_replace __P((PAGE *, size_t, u_int32_t, int32_t, - * PUBLIC: int32_t, DBT *)); - */ -void -__ham_onpage_replace(pagep, pgsize, ndx, off, change, dbt) - PAGE *pagep; - size_t pgsize; - u_int32_t ndx; - int32_t off; - int32_t change; - DBT *dbt; -{ - db_indx_t i; - int32_t len; - u_int8_t *src, *dest; - int zero_me; - - if (change != 0) { - zero_me = 0; - src = (u_int8_t *)(pagep) + HOFFSET(pagep); - if (off < 0) - len = pagep->inp[ndx] - HOFFSET(pagep); - else if ((u_int32_t)off >= LEN_HKEYDATA(pagep, pgsize, ndx)) { - len = HKEYDATA_DATA(P_ENTRY(pagep, ndx)) + - LEN_HKEYDATA(pagep, pgsize, ndx) - src; - zero_me = 1; - } else - len = (HKEYDATA_DATA(P_ENTRY(pagep, ndx)) + off) - src; - dest = src - change; - memmove(dest, src, len); - if (zero_me) - memset(dest + len, 0, change); - - /* Now update the indices. */ - for (i = ndx; i < NUM_ENT(pagep); i++) - pagep->inp[i] -= change; - HOFFSET(pagep) -= change; - } - if (off >= 0) - memcpy(HKEYDATA_DATA(P_ENTRY(pagep, ndx)) + off, - dbt->data, dbt->size); - else - memcpy(P_ENTRY(pagep, ndx), dbt->data, dbt->size); -} - -/* - * PUBLIC: int __ham_split_page __P((DBC *, u_int32_t, u_int32_t)); - */ -int -__ham_split_page(dbc, obucket, nbucket) - DBC *dbc; - u_int32_t obucket, nbucket; -{ - DB *dbp; - HASH_CURSOR *hcp; - DBT key, page_dbt; - DB_ENV *dbenv; - DB_LSN new_lsn; - PAGE **pp, *old_pagep, *temp_pagep, *new_pagep; - db_indx_t n; - db_pgno_t bucket_pgno, next_pgno; - u_int32_t big_len, len; - int ret, tret; - void *big_buf; - - dbp = dbc->dbp; - hcp = (HASH_CURSOR *)dbc->internal; - dbenv = dbp->dbenv; - temp_pagep = old_pagep = new_pagep = NULL; - - bucket_pgno = BUCKET_TO_PAGE(hcp, obucket); - if ((ret = __ham_get_page(dbp, bucket_pgno, &old_pagep)) != 0) - return (ret); - if ((ret = __ham_new_page(dbp, BUCKET_TO_PAGE(hcp, nbucket), P_HASH, - &new_pagep)) != 0) - goto err; - - temp_pagep = hcp->split_buf; - memcpy(temp_pagep, old_pagep, hcp->hdr->pagesize); - - if (DB_LOGGING(dbc)) { - page_dbt.size = hcp->hdr->pagesize; - page_dbt.data = old_pagep; - if ((ret = __ham_splitdata_log(dbenv->lg_info, - dbc->txn, &new_lsn, 0, dbp->log_fileid, SPLITOLD, - PGNO(old_pagep), &page_dbt, &LSN(old_pagep))) != 0) - goto err; - } - - P_INIT(old_pagep, hcp->hdr->pagesize, PGNO(old_pagep), PGNO_INVALID, - PGNO_INVALID, 0, P_HASH); - - if (DB_LOGGING(dbc)) - LSN(old_pagep) = new_lsn; /* Structure assignment. */ - - big_len = 0; - big_buf = NULL; - key.flags = 0; - while (temp_pagep != NULL) { - for (n = 0; n < (db_indx_t)H_NUMPAIRS(temp_pagep); n++) { - if ((ret = - __db_ret(dbp, temp_pagep, H_KEYINDEX(n), - &key, &big_buf, &big_len)) != 0) - goto err; - - if (__ham_call_hash(hcp, key.data, key.size) - == obucket) - pp = &old_pagep; - else - pp = &new_pagep; - - /* - * Figure out how many bytes we need on the new - * page to store the key/data pair. - */ - - len = LEN_HITEM(temp_pagep, hcp->hdr->pagesize, - H_DATAINDEX(n)) + - LEN_HITEM(temp_pagep, hcp->hdr->pagesize, - H_KEYINDEX(n)) + - 2 * sizeof(db_indx_t); - - if (P_FREESPACE(*pp) < len) { - if (DB_LOGGING(dbc)) { - page_dbt.size = hcp->hdr->pagesize; - page_dbt.data = *pp; - if ((ret = __ham_splitdata_log( - dbenv->lg_info, dbc->txn, - &new_lsn, 0, dbp->log_fileid, - SPLITNEW, PGNO(*pp), &page_dbt, - &LSN(*pp))) != 0) - goto err; - LSN(*pp) = new_lsn; - } - if ((ret = - __ham_add_ovflpage(dbc, *pp, 1, pp)) != 0) - goto err; - } - __ham_copy_item(dbp->pgsize, - temp_pagep, H_KEYINDEX(n), *pp); - __ham_copy_item(dbp->pgsize, - temp_pagep, H_DATAINDEX(n), *pp); - } - next_pgno = NEXT_PGNO(temp_pagep); - - /* Clear temp_page; if it's a link overflow page, free it. */ - if (PGNO(temp_pagep) != bucket_pgno && (ret = - __ham_del_page(dbc, temp_pagep)) != 0) - goto err; - - if (next_pgno == PGNO_INVALID) - temp_pagep = NULL; - else if ((ret = - __ham_get_page(dbp, next_pgno, &temp_pagep)) != 0) - goto err; - - if (temp_pagep != NULL && DB_LOGGING(dbc)) { - page_dbt.size = hcp->hdr->pagesize; - page_dbt.data = temp_pagep; - if ((ret = __ham_splitdata_log(dbenv->lg_info, - dbc->txn, &new_lsn, 0, dbp->log_fileid, - SPLITOLD, PGNO(temp_pagep), - &page_dbt, &LSN(temp_pagep))) != 0) - goto err; - LSN(temp_pagep) = new_lsn; - } - } - if (big_buf != NULL) - __os_free(big_buf, big_len); - - /* - * If the original bucket spanned multiple pages, then we've got - * a pointer to a page that used to be on the bucket chain. It - * should be deleted. - */ - if (temp_pagep != NULL && PGNO(temp_pagep) != bucket_pgno && - (ret = __ham_del_page(dbc, temp_pagep)) != 0) - goto err; - - /* - * Write new buckets out. - */ - if (DB_LOGGING(dbc)) { - page_dbt.size = hcp->hdr->pagesize; - page_dbt.data = old_pagep; - if ((ret = __ham_splitdata_log(dbenv->lg_info, - dbc->txn, &new_lsn, 0, dbp->log_fileid, - SPLITNEW, PGNO(old_pagep), - &page_dbt, &LSN(old_pagep))) != 0) - goto err; - LSN(old_pagep) = new_lsn; - - page_dbt.data = new_pagep; - if ((ret = __ham_splitdata_log(dbenv->lg_info, - dbc->txn, &new_lsn, 0, dbp->log_fileid, - SPLITNEW, PGNO(new_pagep), &page_dbt, &LSN(new_pagep))) != 0) - goto err; - LSN(new_pagep) = new_lsn; - } - ret = __ham_put_page(dbp, old_pagep, 1); - if ((tret = __ham_put_page(dbp, new_pagep, 1)) != 0 && - ret == 0) - ret = tret; - - if (0) { -err: if (old_pagep != NULL) - (void)__ham_put_page(dbp, old_pagep, 1); - if (new_pagep != NULL) - (void)__ham_put_page(dbp, new_pagep, 1); - if (temp_pagep != NULL && PGNO(temp_pagep) != bucket_pgno) - (void)__ham_put_page(dbp, temp_pagep, 1); - } - return (ret); -} - -/* - * Add the given pair to the page. The page in question may already be - * held (i.e. it was already gotten). If it is, then the page is passed - * in via the pagep parameter. On return, pagep will contain the page - * to which we just added something. This allows us to link overflow - * pages and return the new page having correctly put the last page. - * - * PUBLIC: int __ham_add_el __P((DBC *, const DBT *, const DBT *, int)); - */ -int -__ham_add_el(dbc, key, val, type) - DBC *dbc; - const DBT *key, *val; - int type; -{ - DB *dbp; - HASH_CURSOR *hcp; - const DBT *pkey, *pdata; - DBT key_dbt, data_dbt; - DB_LSN new_lsn; - HOFFPAGE doff, koff; - db_pgno_t next_pgno; - u_int32_t data_size, key_size, pairsize, rectype; - int do_expand, is_keybig, is_databig, ret; - int key_type, data_type; - - dbp = dbc->dbp; - hcp = (HASH_CURSOR *)dbc->internal; - do_expand = 0; - - if (hcp->pagep == NULL && (ret = __ham_get_page(dbp, - hcp->seek_found_page != PGNO_INVALID ? hcp->seek_found_page : - hcp->pgno, &hcp->pagep)) != 0) - return (ret); - - key_size = HKEYDATA_PSIZE(key->size); - data_size = HKEYDATA_PSIZE(val->size); - is_keybig = ISBIG(hcp, key->size); - is_databig = ISBIG(hcp, val->size); - if (is_keybig) - key_size = HOFFPAGE_PSIZE; - if (is_databig) - data_size = HOFFPAGE_PSIZE; - - pairsize = key_size + data_size; - - /* Advance to first page in chain with room for item. */ - while (H_NUMPAIRS(hcp->pagep) && NEXT_PGNO(hcp->pagep) != - PGNO_INVALID) { - /* - * This may not be the end of the chain, but the pair may fit - * anyway. Check if it's a bigpair that fits or a regular - * pair that fits. - */ - if (P_FREESPACE(hcp->pagep) >= pairsize) - break; - next_pgno = NEXT_PGNO(hcp->pagep); - if ((ret = - __ham_next_cpage(dbc, next_pgno, 0, 0)) != 0) - return (ret); - } - - /* - * Check if we need to allocate a new page. - */ - if (P_FREESPACE(hcp->pagep) < pairsize) { - do_expand = 1; - if ((ret = __ham_add_ovflpage(dbc, - hcp->pagep, 1, &hcp->pagep)) != 0) - return (ret); - hcp->pgno = PGNO(hcp->pagep); - } - - /* - * Update cursor. - */ - hcp->bndx = H_NUMPAIRS(hcp->pagep); - F_CLR(hcp, H_DELETED); - if (is_keybig) { - koff.type = H_OFFPAGE; - UMRW(koff.unused[0]); - UMRW(koff.unused[1]); - UMRW(koff.unused[2]); - if ((ret = __db_poff(dbc, - key, &koff.pgno, __ham_overflow_page)) != 0) - return (ret); - koff.tlen = key->size; - key_dbt.data = &koff; - key_dbt.size = sizeof(koff); - pkey = &key_dbt; - key_type = H_OFFPAGE; - } else { - pkey = key; - key_type = H_KEYDATA; - } - - if (is_databig) { - doff.type = H_OFFPAGE; - UMRW(doff.unused[0]); - UMRW(doff.unused[1]); - UMRW(doff.unused[2]); - if ((ret = __db_poff(dbc, - val, &doff.pgno, __ham_overflow_page)) != 0) - return (ret); - doff.tlen = val->size; - data_dbt.data = &doff; - data_dbt.size = sizeof(doff); - pdata = &data_dbt; - data_type = H_OFFPAGE; - } else { - pdata = val; - data_type = type; - } - - if (DB_LOGGING(dbc)) { - rectype = PUTPAIR; - if (is_databig) - rectype |= PAIR_DATAMASK; - if (is_keybig) - rectype |= PAIR_KEYMASK; - - if ((ret = __ham_insdel_log(dbp->dbenv->lg_info, - dbc->txn, &new_lsn, 0, rectype, - dbp->log_fileid, PGNO(hcp->pagep), - (u_int32_t)H_NUMPAIRS(hcp->pagep), - &LSN(hcp->pagep), pkey, pdata)) != 0) - return (ret); - - /* Move lsn onto page. */ - LSN(hcp->pagep) = new_lsn; /* Structure assignment. */ - } - - __ham_putitem(hcp->pagep, pkey, key_type); - __ham_putitem(hcp->pagep, pdata, data_type); - - /* - * For splits, we are going to update item_info's page number - * field, so that we can easily return to the same page the - * next time we come in here. For other operations, this shouldn't - * matter, since odds are this is the last thing that happens before - * we return to the user program. - */ - hcp->pgno = PGNO(hcp->pagep); - - /* - * XXX Maybe keep incremental numbers here - */ - if (!F_ISSET(dbp, DB_AM_LOCKING)) - hcp->hdr->nelem++; - - if (do_expand || (hcp->hdr->ffactor != 0 && - (u_int32_t)H_NUMPAIRS(hcp->pagep) > hcp->hdr->ffactor)) - F_SET(hcp, H_EXPAND); - return (0); -} - - -/* - * Special __putitem call used in splitting -- copies one entry to - * another. Works for all types of hash entries (H_OFFPAGE, H_KEYDATA, - * H_DUPLICATE, H_OFFDUP). Since we log splits at a high level, we - * do not need to do any logging here. - * - * PUBLIC: void __ham_copy_item __P((size_t, PAGE *, u_int32_t, PAGE *)); - */ -void -__ham_copy_item(pgsize, src_page, src_ndx, dest_page) - size_t pgsize; - PAGE *src_page; - u_int32_t src_ndx; - PAGE *dest_page; -{ - u_int32_t len; - void *src, *dest; - - /* - * Copy the key and data entries onto this new page. - */ - src = P_ENTRY(src_page, src_ndx); - - /* Set up space on dest. */ - len = LEN_HITEM(src_page, pgsize, src_ndx); - HOFFSET(dest_page) -= len; - dest_page->inp[NUM_ENT(dest_page)] = HOFFSET(dest_page); - dest = P_ENTRY(dest_page, NUM_ENT(dest_page)); - NUM_ENT(dest_page)++; - - memcpy(dest, src, len); -} - -/* - * - * Returns: - * pointer on success - * NULL on error - * - * PUBLIC: int __ham_add_ovflpage __P((DBC *, PAGE *, int, PAGE **)); - */ -int -__ham_add_ovflpage(dbc, pagep, release, pp) - DBC *dbc; - PAGE *pagep; - int release; - PAGE **pp; -{ - DB *dbp; - HASH_CURSOR *hcp; - DB_LSN new_lsn; - PAGE *new_pagep; - int ret; - - dbp = dbc->dbp; - hcp = (HASH_CURSOR *)dbc->internal; - - if ((ret = __ham_overflow_page(dbc, P_HASH, &new_pagep)) != 0) - return (ret); - - if (DB_LOGGING(dbc)) { - if ((ret = __ham_newpage_log(dbp->dbenv->lg_info, - dbc->txn, &new_lsn, 0, PUTOVFL, - dbp->log_fileid, PGNO(pagep), &LSN(pagep), - PGNO(new_pagep), &LSN(new_pagep), PGNO_INVALID, NULL)) != 0) - return (ret); - - /* Move lsn onto page. */ - LSN(pagep) = LSN(new_pagep) = new_lsn; - } - NEXT_PGNO(pagep) = PGNO(new_pagep); - PREV_PGNO(new_pagep) = PGNO(pagep); - - if (release) - ret = __ham_put_page(dbp, pagep, 1); - - hcp->stats.hash_overflows++; - *pp = new_pagep; - return (ret); -} - - -/* - * PUBLIC: int __ham_new_page __P((DB *, u_int32_t, u_int32_t, PAGE **)); - */ -int -__ham_new_page(dbp, addr, type, pp) - DB *dbp; - u_int32_t addr, type; - PAGE **pp; -{ - PAGE *pagep; - int ret; - - if ((ret = memp_fget(dbp->mpf, - &addr, DB_MPOOL_CREATE, &pagep)) != 0) - return (ret); - - /* This should not be necessary because page-in should do it. */ - P_INIT(pagep, dbp->pgsize, addr, PGNO_INVALID, PGNO_INVALID, 0, type); - - *pp = pagep; - return (0); -} - -/* - * PUBLIC: int __ham_del_page __P((DBC *, PAGE *)); - */ -int -__ham_del_page(dbc, pagep) - DBC *dbc; - PAGE *pagep; -{ - DB *dbp; - HASH_CURSOR *hcp; - DB_LSN new_lsn; - int ret; - - dbp = dbc->dbp; - hcp = (HASH_CURSOR *)dbc->internal; - ret = 0; - DIRTY_META(dbp, hcp, ret); - if (ret != 0) { - if (ret != EAGAIN) - __db_err(dbp->dbenv, - "free_ovflpage: unable to lock meta data page %s\n", - strerror(ret)); - /* - * If we are going to return an error, then we should free - * the page, so it doesn't stay pinned forever. - */ - (void)__ham_put_page(dbp, pagep, 0); - return (ret); - } - - if (DB_LOGGING(dbc)) { - if ((ret = __ham_newpgno_log(dbp->dbenv->lg_info, - dbc->txn, &new_lsn, 0, DELPGNO, - dbp->log_fileid, PGNO(pagep), hcp->hdr->last_freed, - (u_int32_t)TYPE(pagep), NEXT_PGNO(pagep), P_INVALID, - &LSN(pagep), &hcp->hdr->lsn)) != 0) - return (ret); - - hcp->hdr->lsn = new_lsn; - LSN(pagep) = new_lsn; - } - -#ifdef DIAGNOSTIC - { - db_pgno_t __pgno; - DB_LSN __lsn; - __pgno = pagep->pgno; - __lsn = pagep->lsn; - memset(pagep, 0xdb, dbp->pgsize); - pagep->pgno = __pgno; - pagep->lsn = __lsn; - } -#endif - TYPE(pagep) = P_INVALID; - NEXT_PGNO(pagep) = hcp->hdr->last_freed; - hcp->hdr->last_freed = PGNO(pagep); - - return (__ham_put_page(dbp, pagep, 1)); -} - - -/* - * PUBLIC: int __ham_put_page __P((DB *, PAGE *, int32_t)); - */ -int -__ham_put_page(dbp, pagep, is_dirty) - DB *dbp; - PAGE *pagep; - int32_t is_dirty; -{ -#ifdef DEBUG_SLOW - __account_page(dbp, ((BKT *)((char *)pagep - sizeof(BKT)))->pgno, -1); -#endif - return (memp_fput(dbp->mpf, pagep, (is_dirty ? DB_MPOOL_DIRTY : 0))); -} - -/* - * __ham_dirty_page -- - * Mark a page dirty. - * - * PUBLIC: int __ham_dirty_page __P((DB *, PAGE *)); - */ -int -__ham_dirty_page(dbp, pagep) - DB *dbp; - PAGE *pagep; -{ - return (memp_fset(dbp->mpf, pagep, DB_MPOOL_DIRTY)); -} - -/* - * PUBLIC: int __ham_get_page __P((DB *, db_pgno_t, PAGE **)); - */ -int -__ham_get_page(dbp, addr, pagep) - DB *dbp; - db_pgno_t addr; - PAGE **pagep; -{ - int ret; - - ret = memp_fget(dbp->mpf, &addr, DB_MPOOL_CREATE, pagep); -#ifdef DEBUG_SLOW - if (*pagep != NULL) - __account_page(dbp, addr, 1); -#endif - return (ret); -} - -/* - * PUBLIC: int __ham_overflow_page - * PUBLIC: __P((DBC *, u_int32_t, PAGE **)); - */ -int -__ham_overflow_page(dbc, type, pp) - DBC *dbc; - u_int32_t type; - PAGE **pp; -{ - DB *dbp; - HASH_CURSOR *hcp; - DB_LSN *lsnp, new_lsn; - PAGE *p; - db_pgno_t new_addr, next_free, newalloc_flag; - u_int32_t offset, splitnum; - int ret; - - ret = 0; - dbp = dbc->dbp; - hcp = (HASH_CURSOR *)dbc->internal; - DIRTY_META(dbp, hcp, ret); - if (ret != 0) - return (ret); - - /* - * This routine is split up into two parts. First we have - * to figure out the address of the new page that we are - * allocating. Then we have to log the allocation. Only - * after the log do we get to complete allocation of the - * new page. - */ - new_addr = hcp->hdr->last_freed; - if (new_addr != PGNO_INVALID) { - if ((ret = __ham_get_page(dbp, new_addr, &p)) != 0) - return (ret); - next_free = NEXT_PGNO(p); - lsnp = &LSN(p); - newalloc_flag = 0; - } else { - splitnum = hcp->hdr->ovfl_point; - hcp->hdr->spares[splitnum]++; - offset = hcp->hdr->spares[splitnum] - - (splitnum ? hcp->hdr->spares[splitnum - 1] : 0); - new_addr = PGNO_OF(hcp, hcp->hdr->ovfl_point, offset); - if (new_addr > MAX_PAGES(hcp)) { - __db_err(dbp->dbenv, "hash: out of file pages"); - hcp->hdr->spares[splitnum]--; - return (ENOMEM); - } - next_free = PGNO_INVALID; - p = NULL; - lsnp = NULL; - newalloc_flag = 1; - } - - if (DB_LOGGING(dbc)) { - if ((ret = __ham_newpgno_log(dbp->dbenv->lg_info, - dbc->txn, &new_lsn, 0, ALLOCPGNO, - dbp->log_fileid, new_addr, next_free, - 0, newalloc_flag, type, lsnp, &hcp->hdr->lsn)) != 0) - return (ret); - - hcp->hdr->lsn = new_lsn; - if (lsnp != NULL) - *lsnp = new_lsn; - } - - if (p != NULL) { - /* We just took something off the free list, initialize it. */ - hcp->hdr->last_freed = next_free; - P_INIT(p, hcp->hdr->pagesize, PGNO(p), PGNO_INVALID, - PGNO_INVALID, 0, (u_int8_t)type); - } else { - /* Get the new page. */ - if ((ret = __ham_new_page(dbp, new_addr, type, &p)) != 0) - return (ret); - } - if (DB_LOGGING(dbc)) - LSN(p) = new_lsn; - - *pp = p; - return (0); -} - -#ifdef DEBUG -/* - * PUBLIC: #ifdef DEBUG - * PUBLIC: db_pgno_t __bucket_to_page __P((HASH_CURSOR *, db_pgno_t)); - * PUBLIC: #endif - */ -db_pgno_t -__bucket_to_page(hcp, n) - HASH_CURSOR *hcp; - db_pgno_t n; -{ - int ret_val; - - ret_val = n + 1; - if (n != 0) - ret_val += hcp->hdr->spares[__db_log2(n + 1) - 1]; - return (ret_val); -} -#endif - -/* - * Create a bunch of overflow pages at the current split point. - * PUBLIC: void __ham_init_ovflpages __P((DBC *)); - */ -void -__ham_init_ovflpages(dbc) - DBC *dbc; -{ - DB *dbp; - HASH_CURSOR *hcp; - DB_LSN new_lsn; - PAGE *p; - db_pgno_t last_pgno, new_pgno; - u_int32_t i, curpages, numpages; - - dbp = dbc->dbp; - hcp = (HASH_CURSOR *)dbc->internal; - - curpages = hcp->hdr->spares[hcp->hdr->ovfl_point] - - hcp->hdr->spares[hcp->hdr->ovfl_point - 1]; - numpages = hcp->hdr->ovfl_point + 1 - curpages; - - last_pgno = hcp->hdr->last_freed; - new_pgno = PGNO_OF(hcp, hcp->hdr->ovfl_point, curpages + 1); - if (DB_LOGGING(dbc)) { - (void)__ham_ovfl_log(dbp->dbenv->lg_info, - dbc->txn, &new_lsn, 0, dbp->log_fileid, new_pgno, - numpages, last_pgno, hcp->hdr->ovfl_point, &hcp->hdr->lsn); - hcp->hdr->lsn = new_lsn; - } else - ZERO_LSN(new_lsn); - - hcp->hdr->spares[hcp->hdr->ovfl_point] += numpages; - for (i = numpages; i > 0; i--) { - if (__ham_new_page(dbp, - PGNO_OF(hcp, hcp->hdr->ovfl_point, curpages + i), - P_INVALID, &p) != 0) - break; - LSN(p) = new_lsn; - NEXT_PGNO(p) = last_pgno; - last_pgno = PGNO(p); - (void)__ham_put_page(dbp, p, 1); - } - hcp->hdr->last_freed = last_pgno; -} - -/* - * PUBLIC: int __ham_get_cpage __P((DBC *, db_lockmode_t)); - */ -int -__ham_get_cpage(dbc, mode) - DBC *dbc; - db_lockmode_t mode; -{ - DB *dbp; - HASH_CURSOR *hcp; - int ret; - - dbp = dbc->dbp; - hcp = (HASH_CURSOR *)dbc->internal; - - /* - * There are three cases with respect to buckets and locks. If there - * is no lock held, then if we are locking, we should get the lock. - * If there is a lock held and it's for the current bucket, we don't - * need to do anything. If there is a lock, but it's for a different - * bucket, then we need to release and get. - */ - if (F_ISSET(dbp, DB_AM_LOCKING)) { - if (hcp->lock != 0 && hcp->lbucket != hcp->bucket) { - /* - * If this is the original lock, don't release it, - * because we may need to restore it upon exit. - */ - if (dbc->txn == NULL && - !F_ISSET(hcp, H_ORIGINAL) && (ret = - lock_put(dbp->dbenv->lk_info, hcp->lock)) != 0) - return (ret); - F_CLR(hcp, H_ORIGINAL); - hcp->lock = 0; - } - if (hcp->lock == 0 && (ret = __ham_lock_bucket(dbc, mode)) != 0) - return (ret); - hcp->lbucket = hcp->bucket; - } - - if (hcp->pagep == NULL) { - if (hcp->pgno == PGNO_INVALID) { - hcp->pgno = BUCKET_TO_PAGE(hcp, hcp->bucket); - hcp->bndx = 0; - } - - if ((ret = - __ham_get_page(dbp, hcp->pgno, &hcp->pagep)) != 0) - return (ret); - } - - if (hcp->dpgno != PGNO_INVALID && hcp->dpagep == NULL) - if ((ret = - __ham_get_page(dbp, hcp->dpgno, &hcp->dpagep)) != 0) - return (ret); - return (0); -} - -/* - * Get a new page at the cursor, putting the last page if necessary. - * If the flag is set to H_ISDUP, then we are talking about the - * duplicate page, not the main page. - * - * PUBLIC: int __ham_next_cpage __P((DBC *, db_pgno_t, int, u_int32_t)); - */ -int -__ham_next_cpage(dbc, pgno, dirty, flags) - DBC *dbc; - db_pgno_t pgno; - int dirty; - u_int32_t flags; -{ - DB *dbp; - HASH_CURSOR *hcp; - PAGE *p; - int ret; - - dbp = dbc->dbp; - hcp = (HASH_CURSOR *)dbc->internal; - if (LF_ISSET(H_ISDUP) && hcp->dpagep != NULL && - (ret = __ham_put_page(dbp, hcp->dpagep, dirty)) != 0) - return (ret); - else if (!LF_ISSET(H_ISDUP) && hcp->pagep != NULL && - (ret = __ham_put_page(dbp, hcp->pagep, dirty)) != 0) - return (ret); - - if ((ret = __ham_get_page(dbp, pgno, &p)) != 0) - return (ret); - - if (LF_ISSET(H_ISDUP)) { - hcp->dpagep = p; - hcp->dpgno = pgno; - hcp->dndx = 0; - } else { - hcp->pagep = p; - hcp->pgno = pgno; - hcp->bndx = 0; - } - - return (0); -} - -/* - * __ham_lock_bucket -- - * Get the lock on a particular bucket. - */ -static int -__ham_lock_bucket(dbc, mode) - DBC *dbc; - db_lockmode_t mode; -{ - HASH_CURSOR *hcp; - int ret; - - hcp = (HASH_CURSOR *)dbc->internal; - dbc->lock.pgno = (db_pgno_t)(hcp->bucket); - if (dbc->txn == NULL) - ret = lock_get(dbc->dbp->dbenv->lk_info, dbc->locker, 0, - &dbc->lock_dbt, mode, &hcp->lock); - else - ret = lock_tget(dbc->dbp->dbenv->lk_info, dbc->txn, 0, - &dbc->lock_dbt, mode, &hcp->lock); - - return (ret < 0 ? EAGAIN : ret); -} - -/* - * __ham_dpair -- - * Delete a pair on a page, paying no attention to what the pair - * represents. The caller is responsible for freeing up duplicates - * or offpage entries that might be referenced by this pair. - * - * PUBLIC: void __ham_dpair __P((DB *, PAGE *, u_int32_t)); - */ -void -__ham_dpair(dbp, p, pndx) - DB *dbp; - PAGE *p; - u_int32_t pndx; -{ - db_indx_t delta, n; - u_int8_t *dest, *src; - - /* - * Compute "delta", the amount we have to shift all of the - * offsets. To find the delta, we just need to calculate - * the size of the pair of elements we are removing. - */ - delta = H_PAIRSIZE(p, dbp->pgsize, pndx); - - /* - * The hard case: we want to remove something other than - * the last item on the page. We need to shift data and - * offsets down. - */ - if ((db_indx_t)pndx != H_NUMPAIRS(p) - 1) { - /* - * Move the data: src is the first occupied byte on - * the page. (Length is delta.) - */ - src = (u_int8_t *)p + HOFFSET(p); - - /* - * Destination is delta bytes beyond src. This might - * be an overlapping copy, so we have to use memmove. - */ - dest = src + delta; - memmove(dest, src, p->inp[H_DATAINDEX(pndx)] - HOFFSET(p)); - } - - /* Adjust the offsets. */ - for (n = (db_indx_t)pndx; n < (db_indx_t)(H_NUMPAIRS(p) - 1); n++) { - p->inp[H_KEYINDEX(n)] = p->inp[H_KEYINDEX(n+1)] + delta; - p->inp[H_DATAINDEX(n)] = p->inp[H_DATAINDEX(n+1)] + delta; - } - - /* Adjust page metadata. */ - HOFFSET(p) = HOFFSET(p) + delta; - NUM_ENT(p) = NUM_ENT(p) - 2; -} diff --git a/db2/hash/hash_rec.c b/db2/hash/hash_rec.c deleted file mode 100644 index b58f2c6..0000000 --- a/db2/hash/hash_rec.c +++ /dev/null @@ -1,986 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - */ -/* - * Copyright (c) 1995, 1996 - * Margo Seltzer. All rights reserved. - */ -/* - * Copyright (c) 1995, 1996 - * The President and Fellows of Harvard University. 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[] = "@(#)hash_rec.c 10.22 (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 "db_page.h" -#include "hash.h" -#include "btree.h" -#include "log.h" -#include "common_ext.h" - -/* - * __ham_insdel_recover -- - * - * PUBLIC: int __ham_insdel_recover - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__ham_insdel_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __ham_insdel_args *argp; - DB *file_dbp; - DBC *dbc; - HASH_CURSOR *hcp; - DB_MPOOLFILE *mpf; - PAGE *pagep; - u_int32_t op; - int cmp_n, cmp_p, getmeta, ret; - - getmeta = 0; - hcp = NULL; - REC_PRINT(__ham_insdel_print); - REC_INTRO(__ham_insdel_read); - hcp = (HASH_CURSOR *)dbc->internal; - - ret = memp_fget(mpf, &argp->pgno, 0, &pagep); - if (ret != 0) { - if (!redo) { - /* - * We are undoing and the page doesn't exist. That - * is equivalent to having a pagelsn of 0, so we - * would not have to undo anything. In this case, - * don't bother creating a page. - */ - goto done; - } else if ((ret = memp_fget(mpf, &argp->pgno, - DB_MPOOL_CREATE, &pagep)) != 0) - goto out; - } - - GET_META(file_dbp, hcp, ret); - if (ret != 0) - goto out; - getmeta = 1; - - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &argp->pagelsn); - /* - * Two possible things going on: - * redo a delete/undo a put: delete the item from the page. - * redo a put/undo a delete: add the item to the page. - * If we are undoing a delete, then the information logged is the - * entire entry off the page, not just the data of a dbt. In - * this case, we want to copy it back onto the page verbatim. - * We do this by calling __putitem with the type H_OFFPAGE instead - * of H_KEYDATA. - */ - op = OPCODE_OF(argp->opcode); - - if ((op == DELPAIR && cmp_n == 0 && !redo) || - (op == PUTPAIR && cmp_p == 0 && redo)) { - /* - * Need to redo a PUT or undo a delete. If we are undoing a - * delete, we've got to restore the item back to its original - * position. That's a royal pain in the butt (because we do - * not store item lengths on the page), but there's no choice. - */ - if (op != DELPAIR || - argp->ndx == (u_int32_t)H_NUMPAIRS(pagep)) { - __ham_putitem(pagep, &argp->key, - !redo || PAIR_ISKEYBIG(argp->opcode) ? - H_OFFPAGE : H_KEYDATA); - __ham_putitem(pagep, &argp->data, - !redo || PAIR_ISDATABIG(argp->opcode) ? - H_OFFPAGE : H_KEYDATA); - } else - (void) __ham_reputpair(pagep, hcp->hdr->pagesize, - argp->ndx, &argp->key, &argp->data); - - LSN(pagep) = redo ? *lsnp : argp->pagelsn; - if ((ret = __ham_put_page(file_dbp, pagep, 1)) != 0) - goto out; - - } else if ((op == DELPAIR && cmp_p == 0 && redo) - || (op == PUTPAIR && cmp_n == 0 && !redo)) { - /* Need to undo a put or redo a delete. */ - __ham_dpair(file_dbp, pagep, argp->ndx); - LSN(pagep) = redo ? *lsnp : argp->pagelsn; - if ((ret = __ham_put_page(file_dbp, (PAGE *)pagep, 1)) != 0) - goto out; - } else - if ((ret = __ham_put_page(file_dbp, (PAGE *)pagep, 0)) != 0) - goto out; - - /* Return the previous LSN. */ -done: *lsnp = argp->prev_lsn; - ret = 0; - -out: if (getmeta) - RELEASE_META(file_dbp, hcp); - REC_CLOSE; -} - -/* - * __ham_newpage_recover -- - * This log message is used when we add/remove overflow pages. This - * message takes care of the pointer chains, not the data on the pages. - * - * PUBLIC: int __ham_newpage_recover - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__ham_newpage_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __ham_newpage_args *argp; - DB *file_dbp; - DBC *dbc; - HASH_CURSOR *hcp; - DB_MPOOLFILE *mpf; - PAGE *pagep; - int cmp_n, cmp_p, change, getmeta, ret; - - getmeta = 0; - hcp = NULL; - REC_PRINT(__ham_newpage_print); - REC_INTRO(__ham_newpage_read); - hcp = (HASH_CURSOR *)dbc->internal; - - ret = memp_fget(mpf, &argp->new_pgno, 0, &pagep); - if (ret != 0) { - if (!redo) { - /* - * We are undoing and the page doesn't exist. That - * is equivalent to having a pagelsn of 0, so we - * would not have to undo anything. In this case, - * don't bother creating a page. - */ - ret = 0; - goto ppage; - } else if ((ret = memp_fget(mpf, &argp->new_pgno, - DB_MPOOL_CREATE, &pagep)) != 0) - goto out; - } - - GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret); - if (ret != 0) - goto out; - getmeta = 1; - - /* - * There are potentially three pages we need to check: the one - * that we created/deleted, the one before it and the one after - * it. - */ - - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &argp->pagelsn); - change = 0; - - if ((cmp_p == 0 && redo && argp->opcode == PUTOVFL) || - (cmp_n == 0 && !redo && argp->opcode == DELOVFL)) { - /* Redo a create new page or undo a delete new page. */ - P_INIT(pagep, file_dbp->pgsize, argp->new_pgno, - argp->prev_pgno, argp->next_pgno, 0, P_HASH); - change = 1; - } else if ((cmp_p == 0 && redo && argp->opcode == DELOVFL) || - (cmp_n == 0 && !redo && argp->opcode == PUTOVFL)) { - /* - * Redo a delete or undo a create new page. All we - * really need to do is change the LSN. - */ - change = 1; - } - - if (!change) { - if ((ret = __ham_put_page(file_dbp, (PAGE *)pagep, 0)) != 0) - goto out; - } else { - LSN(pagep) = redo ? *lsnp : argp->pagelsn; - if ((ret = __ham_put_page(file_dbp, (PAGE *)pagep, 1)) != 0) - goto out; - } - - /* Now do the prev page. */ -ppage: if (argp->prev_pgno != PGNO_INVALID) { - ret = memp_fget(mpf, &argp->prev_pgno, 0, &pagep); - - if (ret != 0) { - if (!redo) { - /* - * We are undoing and the page doesn't exist. - * That is equivalent to having a pagelsn of 0, - * so we would not have to undo anything. In - * this case, don't bother creating a page. - */ - ret = 0; - goto npage; - } else if ((ret = - memp_fget(mpf, &argp->prev_pgno, - DB_MPOOL_CREATE, &pagep)) != 0) - goto out; - } - - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &argp->prevlsn); - change = 0; - - if ((cmp_p == 0 && redo && argp->opcode == PUTOVFL) || - (cmp_n == 0 && !redo && argp->opcode == DELOVFL)) { - /* Redo a create new page or undo a delete new page. */ - pagep->next_pgno = argp->new_pgno; - change = 1; - } else if ((cmp_p == 0 && redo && argp->opcode == DELOVFL) || - (cmp_n == 0 && !redo && argp->opcode == PUTOVFL)) { - /* Redo a delete or undo a create new page. */ - pagep->next_pgno = argp->next_pgno; - change = 1; - } - - if (!change) { - if ((ret = - __ham_put_page(file_dbp, (PAGE *)pagep, 0)) != 0) - goto out; - } else { - LSN(pagep) = redo ? *lsnp : argp->prevlsn; - if ((ret = - __ham_put_page(file_dbp, (PAGE *)pagep, 1)) != 0) - goto out; - } - } - - /* Now time to do the next page */ -npage: if (argp->next_pgno != PGNO_INVALID) { - ret = memp_fget(mpf, &argp->next_pgno, 0, &pagep); - - if (ret != 0) { - if (!redo) { - /* - * We are undoing and the page doesn't exist. - * That is equivalent to having a pagelsn of 0, - * so we would not have to undo anything. In - * this case, don't bother creating a page. - */ - goto done; - } else if ((ret = - memp_fget(mpf, &argp->next_pgno, - DB_MPOOL_CREATE, &pagep)) != 0) - goto out; - } - - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &argp->nextlsn); - change = 0; - - if ((cmp_p == 0 && redo && argp->opcode == PUTOVFL) || - (cmp_n == 0 && !redo && argp->opcode == DELOVFL)) { - /* Redo a create new page or undo a delete new page. */ - pagep->prev_pgno = argp->new_pgno; - change = 1; - } else if ((cmp_p == 0 && redo && argp->opcode == DELOVFL) || - (cmp_n == 0 && !redo && argp->opcode == PUTOVFL)) { - /* Redo a delete or undo a create new page. */ - pagep->prev_pgno = argp->prev_pgno; - change = 1; - } - - if (!change) { - if ((ret = - __ham_put_page(file_dbp, (PAGE *)pagep, 0)) != 0) - goto out; - } else { - LSN(pagep) = redo ? *lsnp : argp->nextlsn; - if ((ret = - __ham_put_page(file_dbp, (PAGE *)pagep, 1)) != 0) - goto out; - } - } -done: *lsnp = argp->prev_lsn; - ret = 0; - -out: if (getmeta) - RELEASE_META(file_dbp, hcp); - REC_CLOSE; -} - - -/* - * __ham_replace_recover -- - * This log message refers to partial puts that are local to a single - * page. You can think of them as special cases of the more general - * insdel log message. - * - * PUBLIC: int __ham_replace_recover - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__ham_replace_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __ham_replace_args *argp; - DB *file_dbp; - DBC *dbc; - HASH_CURSOR *hcp; - DB_MPOOLFILE *mpf; - DBT dbt; - PAGE *pagep; - int32_t grow; - int change, cmp_n, cmp_p, getmeta, ret; - u_int8_t *hk; - - getmeta = 0; - hcp = NULL; - REC_PRINT(__ham_replace_print); - REC_INTRO(__ham_replace_read); - hcp = (HASH_CURSOR *)dbc->internal; - - ret = memp_fget(mpf, &argp->pgno, 0, &pagep); - if (ret != 0) { - if (!redo) { - /* - * We are undoing and the page doesn't exist. That - * is equivalent to having a pagelsn of 0, so we - * would not have to undo anything. In this case, - * don't bother creating a page. - */ - goto done; - } else if ((ret = memp_fget(mpf, &argp->pgno, - DB_MPOOL_CREATE, &pagep)) != 0) - goto out; - } - - GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret); - if (ret != 0) - goto out; - getmeta = 1; - - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &argp->pagelsn); - - if (cmp_p == 0 && redo) { - change = 1; - /* Reapply the change as specified. */ - dbt.data = argp->newitem.data; - dbt.size = argp->newitem.size; - grow = argp->newitem.size - argp->olditem.size; - LSN(pagep) = *lsnp; - } else if (cmp_n == 0 && !redo) { - change = 1; - /* Undo the already applied change. */ - dbt.data = argp->olditem.data; - dbt.size = argp->olditem.size; - grow = argp->olditem.size - argp->newitem.size; - LSN(pagep) = argp->pagelsn; - } else { - change = 0; - grow = 0; - } - - if (change) { - __ham_onpage_replace(pagep, - file_dbp->pgsize, argp->ndx, argp->off, grow, &dbt); - if (argp->makedup) { - hk = P_ENTRY(pagep, argp->ndx); - if (redo) - HPAGE_PTYPE(hk) = H_DUPLICATE; - else - HPAGE_PTYPE(hk) = H_KEYDATA; - } - } - - if ((ret = __ham_put_page(file_dbp, pagep, change)) != 0) - goto out; - -done: *lsnp = argp->prev_lsn; - ret = 0; - -out: if (getmeta) - RELEASE_META(file_dbp, hcp); - REC_CLOSE; -} - -/* - * __ham_newpgno_recover -- - * This log message is used when allocating or deleting an overflow - * page. It takes care of modifying the meta data. - * - * PUBLIC: int __ham_newpgno_recover - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__ham_newpgno_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __ham_newpgno_args *argp; - DB *file_dbp; - DBC *dbc; - HASH_CURSOR *hcp; - DB_MPOOLFILE *mpf; - PAGE *pagep; - int change, cmp_n, cmp_p, getmeta, ret; - - getmeta = 0; - hcp = NULL; - REC_PRINT(__ham_newpgno_print); - REC_INTRO(__ham_newpgno_read); - hcp = (HASH_CURSOR *)dbc->internal; - - GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret); - if (ret != 0) - goto out; - getmeta = 1; - - /* - * There are two phases to the recovery here. First we need - * to update the meta data; then we need to update the page. - * We'll do the meta-data first. - */ - cmp_n = log_compare(lsnp, &hcp->hdr->lsn); - cmp_p = log_compare(&hcp->hdr->lsn, &argp->metalsn); - - change = 0; - if ((cmp_p == 0 && redo && argp->opcode == ALLOCPGNO) || - (cmp_n == 0 && !redo && argp->opcode == DELPGNO)) { - /* Need to redo an allocation or undo a deletion. */ - hcp->hdr->last_freed = argp->free_pgno; - if (redo && argp->old_pgno != 0) /* Must be ALLOCPGNO */ - hcp->hdr->spares[hcp->hdr->ovfl_point]++; - change = 1; - } else if (cmp_p == 0 && redo && argp->opcode == DELPGNO) { - /* Need to redo a deletion */ - hcp->hdr->last_freed = argp->pgno; - change = 1; - } else if (cmp_n == 0 && !redo && argp->opcode == ALLOCPGNO) { - /* undo an allocation. */ - if (argp->old_pgno == 0) - hcp->hdr->last_freed = argp->pgno; - else { - hcp->hdr->spares[hcp->hdr->ovfl_point]--; - hcp->hdr->last_freed = 0; - } - change = 1; - } - if (change) { - hcp->hdr->lsn = redo ? *lsnp : argp->metalsn; - F_SET(hcp, H_DIRTY); - } - - - /* Now check the newly allocated/freed page. */ - ret = memp_fget(mpf, &argp->pgno, 0, &pagep); - - if (ret != 0) { - if (!redo) { - /* - * We are undoing and the page doesn't exist. That - * is equivalent to having a pagelsn of 0, so we - * would not have to undo anything. In this case, - * don't bother creating a page. - */ - goto done; - } else if ((ret = memp_fget(mpf, &argp->pgno, - DB_MPOOL_CREATE, &pagep)) != 0) - goto out; - } - - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &argp->pagelsn); - - change = 0; - if (cmp_p == 0 && redo && argp->opcode == ALLOCPGNO) { - /* Need to redo an allocation. */ - P_INIT(pagep, file_dbp->pgsize, argp->pgno, PGNO_INVALID, - PGNO_INVALID, 0, argp->new_type); - change = 1; - } else if (cmp_n == 0 && !redo && argp->opcode == DELPGNO) { - /* Undoing a delete. */ - P_INIT(pagep, file_dbp->pgsize, argp->pgno, PGNO_INVALID, - argp->old_pgno, 0, argp->old_type); - change = 1; - } else if ((cmp_p == 0 && redo && argp->opcode == DELPGNO) || - (cmp_n == 0 && !redo && argp->opcode == ALLOCPGNO)) { - /* Need to redo a deletion or undo an allocation. */ - NEXT_PGNO(pagep) = argp->free_pgno; - TYPE(pagep) = P_INVALID; - change = 1; - } - if (change) - LSN(pagep) = redo ? *lsnp : argp->pagelsn; - - if ((ret = __ham_put_page(file_dbp, pagep, change)) != 0) - goto out; - -done: *lsnp = argp->prev_lsn; - ret = 0; - -out: if (getmeta) - RELEASE_META(file_dbp, hcp); - REC_CLOSE; - -} - -/* - * __ham_splitmeta_recover -- - * This is the meta-data part of the split. Records the new and old - * bucket numbers and the new/old mask information. - * - * PUBLIC: int __ham_splitmeta_recover - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__ham_splitmeta_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __ham_splitmeta_args *argp; - DB *file_dbp; - DBC *dbc; - HASH_CURSOR *hcp; - DB_MPOOLFILE *mpf; - int change, cmp_n, cmp_p, getmeta, ret; - u_int32_t pow; - - getmeta = 0; - hcp = NULL; - REC_PRINT(__ham_splitmeta_print); - REC_INTRO(__ham_splitmeta_read); - hcp = (HASH_CURSOR *)dbc->internal; - - GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret); - if (ret != 0) - goto out; - getmeta = 1; - - /* - * There are two phases to the recovery here. First we need - * to update the meta data; then we need to update the page. - * We'll do the meta-data first. - */ - cmp_n = log_compare(lsnp, &hcp->hdr->lsn); - cmp_p = log_compare(&hcp->hdr->lsn, &argp->metalsn); - - change = 0; - if (cmp_p == 0 && redo) { - /* Need to redo the split information. */ - hcp->hdr->max_bucket = argp->bucket + 1; - pow = __db_log2(hcp->hdr->max_bucket + 1); - if (pow > hcp->hdr->ovfl_point) { - hcp->hdr->spares[pow] = - hcp->hdr->spares[hcp->hdr->ovfl_point]; - hcp->hdr->ovfl_point = pow; - } - if (hcp->hdr->max_bucket > hcp->hdr->high_mask) { - hcp->hdr->low_mask = hcp->hdr->high_mask; - hcp->hdr->high_mask = - hcp->hdr->max_bucket | hcp->hdr->low_mask; - } - change = 1; - } else if (cmp_n == 0 && !redo) { - /* Need to undo the split information. */ - hcp->hdr->max_bucket = argp->bucket; - hcp->hdr->ovfl_point = argp->ovflpoint; - hcp->hdr->spares[hcp->hdr->ovfl_point] = argp->spares; - pow = 1 << __db_log2(hcp->hdr->max_bucket + 1); - hcp->hdr->high_mask = pow - 1; - hcp->hdr->low_mask = (pow >> 1) - 1; - change = 1; - } - if (change) { - hcp->hdr->lsn = redo ? *lsnp : argp->metalsn; - F_SET(hcp, H_DIRTY); - } - -done: *lsnp = argp->prev_lsn; - ret = 0; - -out: if (getmeta) - RELEASE_META(file_dbp, hcp); - REC_CLOSE; -} - -/* - * __ham_splitdata_recover -- - * - * PUBLIC: int __ham_splitdata_recover - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__ham_splitdata_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __ham_splitdata_args *argp; - DB *file_dbp; - DBC *dbc; - HASH_CURSOR *hcp; - DB_MPOOLFILE *mpf; - PAGE *pagep; - int change, cmp_n, cmp_p, getmeta, ret; - - getmeta = 0; - hcp = NULL; - REC_PRINT(__ham_splitdata_print); - REC_INTRO(__ham_splitdata_read); - hcp = (HASH_CURSOR *)dbc->internal; - - ret = memp_fget(mpf, &argp->pgno, 0, &pagep); - if (ret != 0) { - if (!redo) { - /* - * We are undoing and the page doesn't exist. That - * is equivalent to having a pagelsn of 0, so we - * would not have to undo anything. In this case, - * don't bother creating a page. - */ - goto done; - } else if ((ret = memp_fget(mpf, &argp->pgno, - DB_MPOOL_CREATE, &pagep)) != 0) - goto out; - } - - GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret); - if (ret != 0) - goto out; - getmeta = 1; - - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &argp->pagelsn); - - /* - * There are two types of log messages here, one for the old page - * and one for the new pages created. The original image in the - * SPLITOLD record is used for undo. The image in the SPLITNEW - * is used for redo. We should never have a case where there is - * a redo operation and the SPLITOLD record is on disk, but not - * the SPLITNEW record. Therefore, we only have work to do when - * redo NEW messages and undo OLD messages, but we have to update - * LSNs in both cases. - */ - change = 0; - if (cmp_p == 0 && redo) { - if (argp->opcode == SPLITNEW) - /* Need to redo the split described. */ - memcpy(pagep, argp->pageimage.data, - argp->pageimage.size); - LSN(pagep) = *lsnp; - change = 1; - } else if (cmp_n == 0 && !redo) { - if (argp->opcode == SPLITOLD) { - /* Put back the old image. */ - memcpy(pagep, argp->pageimage.data, - argp->pageimage.size); - } else - P_INIT(pagep, file_dbp->pgsize, argp->pgno, - PGNO_INVALID, PGNO_INVALID, 0, P_HASH); - LSN(pagep) = argp->pagelsn; - change = 1; - } - if ((ret = __ham_put_page(file_dbp, pagep, change)) != 0) - goto out; - -done: *lsnp = argp->prev_lsn; - ret = 0; - -out: if (getmeta) - RELEASE_META(file_dbp, hcp); - REC_CLOSE; -} - -/* - * __ham_ovfl_recover -- - * This message is generated when we initialize a set of overflow pages. - * - * PUBLIC: int __ham_ovfl_recover - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__ham_ovfl_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __ham_ovfl_args *argp; - DB *file_dbp; - DBC *dbc; - HASH_CURSOR *hcp; - DB_MPOOLFILE *mpf; - PAGE *pagep; - db_pgno_t max_pgno, pgno; - int cmp_n, cmp_p, getmeta, ret; - - getmeta = 0; - hcp = NULL; - REC_PRINT(__ham_ovfl_print); - REC_INTRO(__ham_ovfl_read); - hcp = (HASH_CURSOR *)dbc->internal; - - GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret); - if (ret != 0) - goto out; - getmeta = 1; - - cmp_n = log_compare(lsnp, &hcp->hdr->lsn); - cmp_p = log_compare(&hcp->hdr->lsn, &argp->metalsn); - - if (cmp_p == 0 && redo) { - /* Redo the allocation. */ - hcp->hdr->last_freed = argp->start_pgno; - hcp->hdr->spares[argp->ovflpoint] += argp->npages; - hcp->hdr->lsn = *lsnp; - F_SET(hcp, H_DIRTY); - } else if (cmp_n == 0 && !redo) { - hcp->hdr->last_freed = argp->free_pgno; - hcp->hdr->spares[argp->ovflpoint] -= argp->npages; - hcp->hdr->lsn = argp->metalsn; - F_SET(hcp, H_DIRTY); - } - - max_pgno = argp->start_pgno + argp->npages - 1; - ret = 0; - for (pgno = argp->start_pgno; pgno <= max_pgno; pgno++) { - if ((ret = memp_fget(mpf, &pgno, 0, &pagep)) != 0) { - if (!redo) { - ret = 0; - continue; - } - if ((ret = memp_fget(mpf, - &pgno, DB_MPOOL_CREATE, &pagep)) != 0) - goto out; - } - if (redo && log_compare((const DB_LSN *)lsnp, - (const DB_LSN *)&LSN(pagep)) > 0) { - P_INIT(pagep, file_dbp->pgsize, pgno, PGNO_INVALID, - pgno == max_pgno ? argp->free_pgno : pgno + 1, - 0, P_HASH); - LSN(pagep) = *lsnp; - ret = __ham_put_page(file_dbp, pagep, 1); - } else if (!redo) { - ZERO_LSN(pagep->lsn); - ret = __ham_put_page(file_dbp, pagep, 1); - } else - ret = __ham_put_page(file_dbp, pagep, 0); - if (ret) - goto out; - } - -done: *lsnp = argp->prev_lsn; - ret = 0; - -out: if (getmeta) - RELEASE_META(file_dbp, hcp); - REC_CLOSE; -} - -/* - * __ham_copypage_recover -- - * Recovery function for copypage. - * - * PUBLIC: int __ham_copypage_recover - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__ham_copypage_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __ham_copypage_args *argp; - DB *file_dbp; - DBC *dbc; - HASH_CURSOR *hcp; - DB_MPOOLFILE *mpf; - PAGE *pagep; - int cmp_n, cmp_p, getmeta, modified, ret; - - getmeta = 0; - hcp = NULL; - REC_PRINT(__ham_copypage_print); - REC_INTRO(__ham_copypage_read); - hcp = (HASH_CURSOR *)dbc->internal; - - GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret); - if (ret != 0) - goto out; - getmeta = 1; - modified = 0; - - /* This is the bucket page. */ - ret = memp_fget(mpf, &argp->pgno, 0, &pagep); - if (ret != 0) { - if (!redo) { - /* - * We are undoing and the page doesn't exist. That - * is equivalent to having a pagelsn of 0, so we - * would not have to undo anything. In this case, - * don't bother creating a page. - */ - ret = 0; - goto donext; - } else if ((ret = memp_fget(mpf, &argp->pgno, - DB_MPOOL_CREATE, &pagep)) != 0) - goto out; - } - - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &argp->pagelsn); - - if (cmp_p == 0 && redo) { - /* Need to redo update described. */ - memcpy(pagep, argp->page.data, argp->page.size); - LSN(pagep) = *lsnp; - modified = 1; - } else if (cmp_n == 0 && !redo) { - /* Need to undo update described. */ - P_INIT(pagep, hcp->hdr->pagesize, argp->pgno, PGNO_INVALID, - argp->next_pgno, 0, P_HASH); - LSN(pagep) = argp->pagelsn; - modified = 1; - } - if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) - goto out; - - /* Now fix up the "next" page. */ -donext: ret = memp_fget(mpf, &argp->next_pgno, 0, &pagep); - if (ret != 0) { - if (!redo) { - /* - * We are undoing and the page doesn't exist. That - * is equivalent to having a pagelsn of 0, so we - * would not have to undo anything. In this case, - * don't bother creating a page. - */ - ret = 0; - goto do_nn; - } else if ((ret = memp_fget(mpf, &argp->next_pgno, - DB_MPOOL_CREATE, &pagep)) != 0) - goto out; - } - - /* There is nothing to do in the REDO case; only UNDO. */ - - cmp_n = log_compare(lsnp, &LSN(pagep)); - if (cmp_n == 0 && !redo) { - /* Need to undo update described. */ - memcpy(pagep, argp->page.data, argp->page.size); - modified = 1; - } - if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) - goto out; - - /* Now fix up the next's next page. */ -do_nn: if (argp->nnext_pgno == PGNO_INVALID) - goto done; - - ret = memp_fget(mpf, &argp->nnext_pgno, 0, &pagep); - if (ret != 0) { - if (!redo) { - /* - * We are undoing and the page doesn't exist. That - * is equivalent to having a pagelsn of 0, so we - * would not have to undo anything. In this case, - * don't bother creating a page. - */ - goto done; - } else if ((ret = memp_fget(mpf, &argp->nnext_pgno, - DB_MPOOL_CREATE, &pagep)) != 0) - goto out; - } - - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &argp->nnextlsn); - - if (cmp_p == 0 && redo) { - /* Need to redo update described. */ - PREV_PGNO(pagep) = argp->pgno; - LSN(pagep) = *lsnp; - modified = 1; - } else if (cmp_n == 0 && !redo) { - /* Need to undo update described. */ - PREV_PGNO(pagep) = argp->next_pgno; - LSN(pagep) = argp->nnextlsn; - modified = 1; - } - if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) - goto out; - -done: *lsnp = argp->prev_lsn; - ret = 0; - -out: if (getmeta) - RELEASE_META(file_dbp, hcp); - REC_CLOSE; -} diff --git a/db2/hash/hash_stat.c b/db2/hash/hash_stat.c deleted file mode 100644 index 1b493d5..0000000 --- a/db2/hash/hash_stat.c +++ /dev/null @@ -1,44 +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[] = "@(#)hash_stat.c 10.12 (Sleepycat) 12/19/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#endif - -#include "db_int.h" -#include "db_page.h" -#include "hash.h" - -/* - * __ham_stat -- - * Gather/print the hash statistics - * - * PUBLIC: int __ham_stat __P((DB *, void *, void *(*)(size_t), u_int32_t)); - */ -int -__ham_stat(dbp, spp, db_malloc, flags) - DB *dbp; - void *spp; - void *(*db_malloc) __P((size_t)); - u_int32_t flags; -{ - COMPQUIET(spp, NULL); - COMPQUIET(db_malloc, NULL); - COMPQUIET(flags, 0); - - DB_PANIC_CHECK(dbp); - - return (__db_eopnotsup(dbp->dbenv)); -} diff --git a/db2/include/btree.h b/db2/include/btree.h deleted file mode 100644 index b0c04b1..0000000 --- a/db2/include/btree.h +++ /dev/null @@ -1,263 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994, 1995, 1996 - * Keith Bostic. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994, 1995 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Olson. - * - * 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. - * - * @(#)btree.h 10.26 (Sleepycat) 12/16/98 - */ - -/* Forward structure declarations. */ -struct __btree; typedef struct __btree BTREE; -struct __cursor; typedef struct __cursor CURSOR; -struct __epg; typedef struct __epg EPG; -struct __recno; typedef struct __recno RECNO; - -#define DEFMINKEYPAGE (2) - -#define ISINTERNAL(p) (TYPE(p) == P_IBTREE || TYPE(p) == P_IRECNO) -#define ISLEAF(p) (TYPE(p) == P_LBTREE || TYPE(p) == P_LRECNO) - -/* - * If doing transactions we have to hold the locks associated with a data item - * from a page for the entire transaction. However, we don't have to hold the - * locks associated with walking the tree. Distinguish between the two so that - * we don't tie up the internal pages of the tree longer than necessary. - */ -#define __BT_LPUT(dbc, lock) \ - (F_ISSET((dbc)->dbp, DB_AM_LOCKING) ? \ - lock_put((dbc)->dbp->dbenv->lk_info, lock) : 0) -#define __BT_TLPUT(dbc, lock) \ - (F_ISSET((dbc)->dbp, DB_AM_LOCKING) && (dbc)->txn == NULL ? \ - lock_put((dbc)->dbp->dbenv->lk_info, lock) : 0) - -/* - * Flags to __bam_search() and __bam_rsearch(). - * - * Note, internal page searches must find the largest record less than key in - * the tree so that descents work. Leaf page searches must find the smallest - * record greater than key so that the returned index is the record's correct - * position for insertion. - * - * The flags parameter to the search routines describes three aspects of the - * search: the type of locking required (including if we're locking a pair of - * pages), the item to return in the presence of duplicates and whether or not - * to return deleted entries. To simplify both the mnemonic representation - * and the code that checks for various cases, we construct a set of bitmasks. - */ -#define S_READ 0x00001 /* Read locks. */ -#define S_WRITE 0x00002 /* Write locks. */ - -#define S_APPEND 0x00040 /* Append to the tree. */ -#define S_DELNO 0x00080 /* Don't return deleted items. */ -#define S_DUPFIRST 0x00100 /* Return first duplicate. */ -#define S_DUPLAST 0x00200 /* Return last duplicate. */ -#define S_EXACT 0x00400 /* Exact items only. */ -#define S_PARENT 0x00800 /* Lock page pair. */ -#define S_STACK 0x01000 /* Need a complete stack. */ -#define S_PAST_EOF 0x02000 /* If doing insert search (or keyfirst - * or keylast operations), or a split - * on behalf of an insert, it's okay to - * return an entry one past end-of-page. - */ - -#define S_DELETE (S_WRITE | S_DUPFIRST | S_DELNO | S_EXACT | S_STACK) -#define S_FIND (S_READ | S_DUPFIRST | S_DELNO) -#define S_FIND_WR (S_WRITE | S_DUPFIRST | S_DELNO) -#define S_INSERT (S_WRITE | S_DUPLAST | S_PAST_EOF | S_STACK) -#define S_KEYFIRST (S_WRITE | S_DUPFIRST | S_PAST_EOF | S_STACK) -#define S_KEYLAST (S_WRITE | S_DUPLAST | S_PAST_EOF | S_STACK) -#define S_WRPAIR (S_WRITE | S_DUPLAST | S_PAST_EOF | S_PARENT) - -/* - * Flags to __bam_iitem(). - */ -#define BI_DELETED 0x01 /* Key/data pair only placeholder. */ -#define BI_DOINCR 0x02 /* Increment the record count. */ -#define BI_NEWKEY 0x04 /* New key. */ - -/* - * Various routines pass around page references. A page reference can be a - * pointer to the page or a page number; for either, an indx can designate - * an item on the page. - */ -struct __epg { - PAGE *page; /* The page. */ - db_indx_t indx; /* The index on the page. */ - DB_LOCK lock; /* The page's lock. */ -}; - -/* - * We maintain a stack of the pages that we're locking in the tree. Btree's - * (currently) only save two levels of the tree at a time, so the default - * stack is always large enough. Recno trees have to lock the entire tree to - * do inserts/deletes, however. Grow the stack as necessary. - */ -#define BT_STK_CLR(c) \ - ((c)->csp = (c)->sp) - -#define BT_STK_ENTER(c, pagep, page_indx, lock, ret) do { \ - if ((ret = \ - (c)->csp == (c)->esp ? __bam_stkgrow(c) : 0) == 0) { \ - (c)->csp->page = pagep; \ - (c)->csp->indx = page_indx; \ - (c)->csp->lock = lock; \ - } \ -} while (0) - -#define BT_STK_PUSH(c, pagep, page_indx, lock, ret) do { \ - BT_STK_ENTER(c, pagep, page_indx, lock, ret); \ - ++(c)->csp; \ -} while (0) - -#define BT_STK_POP(c) \ - ((c)->csp == (c)->stack ? NULL : --(c)->csp) - -/* - * Arguments passed to __bam_ca_replace(). - */ -typedef enum { - REPLACE_SETUP, - REPLACE_SUCCESS, - REPLACE_FAILED -} ca_replace_arg; - -/* Arguments passed to __ram_ca(). */ -typedef enum { - CA_DELETE, - CA_IAFTER, - CA_IBEFORE -} ca_recno_arg; - -#define RECNO_OOB 0 /* Illegal record number. */ - -/* Btree/Recno cursor. */ -struct __cursor { - DBC *dbc; /* Enclosing DBC. */ - - /* Per-thread information: shared by btree/recno. */ - EPG *sp; /* Stack pointer. */ - EPG *csp; /* Current stack entry. */ - EPG *esp; /* End stack pointer. */ - EPG stack[5]; - - /* Per-thread information: btree private. */ - PAGE *page; /* Cursor page. */ - - db_pgno_t pgno; /* Page. */ - db_indx_t indx; /* Page item ref'd by the cursor. */ - - db_pgno_t dpgno; /* Duplicate page. */ - db_indx_t dindx; /* Page item ref'd by the cursor. */ - - DB_LOCK lock; /* Cursor read lock. */ - db_lockmode_t mode; /* Lock mode. */ - - /* Per-thread information: recno private. */ - db_recno_t recno; /* Current record number. */ - - /* - * Btree: - * We set a flag in the cursor structure if the underlying object has - * been deleted. It's not strictly necessary, we could get the same - * information by looking at the page itself. - * - * Recno: - * When renumbering recno databases during deletes, cursors referencing - * "deleted" records end up positioned between two records, and so must - * be specially adjusted on the next operation. - */ -#define C_DELETED 0x0001 /* Record was deleted. */ - u_int32_t flags; -}; - -/* - * The in-memory recno data structure. - * - * !!! - * These fields are ignored as far as multi-threading is concerned. There - * are no transaction semantics associated with backing files, nor is there - * any thread protection. - */ -struct __recno { - int re_delim; /* Variable-length delimiting byte. */ - int re_pad; /* Fixed-length padding byte. */ - u_int32_t re_len; /* Length for fixed-length records. */ - - char *re_source; /* Source file name. */ - int re_fd; /* Source file descriptor */ - db_recno_t re_last; /* Last record number read. */ - void *re_cmap; /* Current point in mapped space. */ - void *re_smap; /* Start of mapped space. */ - void *re_emap; /* End of mapped space. */ - size_t re_msize; /* Size of mapped region. */ - /* Recno input function. */ - int (*re_irec) __P((DBC *, db_recno_t)); - -#define RECNO_EOF 0x0001 /* EOF on backing source file. */ -#define RECNO_MODIFIED 0x0002 /* Tree was modified. */ - u_int32_t flags; -}; - -/* - * The in-memory, per-tree btree data structure. - */ -struct __btree { - db_pgno_t bt_lpgno; /* Last insert location. */ - - db_indx_t bt_maxkey; /* Maximum keys per page. */ - db_indx_t bt_minkey; /* Minimum keys per page. */ - - int (*bt_compare) /* Comparison function. */ - __P((const DBT *, const DBT *)); - size_t(*bt_prefix) /* Prefix function. */ - __P((const DBT *, const DBT *)); - - db_indx_t bt_ovflsize; /* Maximum key/data on-page size. */ - - RECNO *recno; /* Private recno structure. */ -}; - -#include "btree_auto.h" -#include "btree_ext.h" -#include "db_am.h" -#include "common_ext.h" diff --git a/db2/include/btree_auto.h b/db2/include/btree_auto.h deleted file mode 100644 index 041b80f..0000000 --- a/db2/include/btree_auto.h +++ /dev/null @@ -1,127 +0,0 @@ -/* Do not edit: automatically built by dist/db_gen.sh. */ -#ifndef bam_AUTO_H -#define bam_AUTO_H - -#define DB_bam_pg_alloc (DB_bam_BEGIN + 1) - -typedef struct _bam_pg_alloc_args { - u_int32_t type; - DB_TXN *txnid; - DB_LSN prev_lsn; - u_int32_t fileid; - DB_LSN meta_lsn; - DB_LSN page_lsn; - db_pgno_t pgno; - u_int32_t ptype; - db_pgno_t next; -} __bam_pg_alloc_args; - - -#define DB_bam_pg_free (DB_bam_BEGIN + 2) - -typedef struct _bam_pg_free_args { - u_int32_t type; - DB_TXN *txnid; - DB_LSN prev_lsn; - u_int32_t fileid; - db_pgno_t pgno; - DB_LSN meta_lsn; - DBT header; - db_pgno_t next; -} __bam_pg_free_args; - - -#define DB_bam_split (DB_bam_BEGIN + 3) - -typedef struct _bam_split_args { - u_int32_t type; - DB_TXN *txnid; - DB_LSN prev_lsn; - u_int32_t fileid; - db_pgno_t left; - DB_LSN llsn; - db_pgno_t right; - DB_LSN rlsn; - u_int32_t indx; - db_pgno_t npgno; - DB_LSN nlsn; - DBT pg; -} __bam_split_args; - - -#define DB_bam_rsplit (DB_bam_BEGIN + 4) - -typedef struct _bam_rsplit_args { - u_int32_t type; - DB_TXN *txnid; - DB_LSN prev_lsn; - u_int32_t fileid; - db_pgno_t pgno; - DBT pgdbt; - db_pgno_t nrec; - DBT rootent; - DB_LSN rootlsn; -} __bam_rsplit_args; - - -#define DB_bam_adj (DB_bam_BEGIN + 5) - -typedef struct _bam_adj_args { - u_int32_t type; - DB_TXN *txnid; - DB_LSN prev_lsn; - u_int32_t fileid; - db_pgno_t pgno; - DB_LSN lsn; - u_int32_t indx; - u_int32_t indx_copy; - u_int32_t is_insert; -} __bam_adj_args; - - -#define DB_bam_cadjust (DB_bam_BEGIN + 6) - -typedef struct _bam_cadjust_args { - u_int32_t type; - DB_TXN *txnid; - DB_LSN prev_lsn; - u_int32_t fileid; - db_pgno_t pgno; - DB_LSN lsn; - u_int32_t indx; - int32_t adjust; - int32_t total; -} __bam_cadjust_args; - - -#define DB_bam_cdel (DB_bam_BEGIN + 7) - -typedef struct _bam_cdel_args { - u_int32_t type; - DB_TXN *txnid; - DB_LSN prev_lsn; - u_int32_t fileid; - db_pgno_t pgno; - DB_LSN lsn; - u_int32_t indx; -} __bam_cdel_args; - - -#define DB_bam_repl (DB_bam_BEGIN + 8) - -typedef struct _bam_repl_args { - u_int32_t type; - DB_TXN *txnid; - DB_LSN prev_lsn; - u_int32_t fileid; - db_pgno_t pgno; - DB_LSN lsn; - u_int32_t indx; - u_int32_t isdeleted; - DBT orig; - DBT repl; - u_int32_t prefix; - u_int32_t suffix; -} __bam_repl_args; - -#endif diff --git a/db2/include/btree_ext.h b/db2/include/btree_ext.h deleted file mode 100644 index fbc2ed9..0000000 --- a/db2/include/btree_ext.h +++ /dev/null @@ -1,132 +0,0 @@ -/* DO NOT EDIT: automatically built by dist/distrib. */ -#ifndef _btree_ext_h_ -#define _btree_ext_h_ -int __bam_cmp __P((DB *, const DBT *, - PAGE *, u_int32_t, int (*)(const DBT *, const DBT *))); -int __bam_defcmp __P((const DBT *, const DBT *)); -size_t __bam_defpfx __P((const DBT *, const DBT *)); -int __bam_pgin __P((db_pgno_t, void *, DBT *)); -int __bam_pgout __P((db_pgno_t, void *, DBT *)); -int __bam_mswap __P((PAGE *)); -int __bam_cprint __P((DB *)); -int __bam_ca_delete __P((DB *, db_pgno_t, u_int32_t, int)); -void __bam_ca_di __P((DB *, db_pgno_t, u_int32_t, int)); -void __bam_ca_dup __P((DB *, - db_pgno_t, u_int32_t, u_int32_t, db_pgno_t, u_int32_t)); -void __bam_ca_rsplit __P((DB *, db_pgno_t, db_pgno_t)); -void __bam_ca_split __P((DB *, - db_pgno_t, db_pgno_t, db_pgno_t, u_int32_t, int)); -int __bam_c_init __P((DBC *)); -int __bam_dup __P((DBC *, CURSOR *, u_int32_t, int)); -int __bam_delete __P((DB *, DB_TXN *, DBT *, u_int32_t)); -int __bam_ditem __P((DBC *, PAGE *, u_int32_t)); -int __bam_adjindx __P((DBC *, PAGE *, u_int32_t, u_int32_t, int)); -int __bam_dpage __P((DBC *, const DBT *)); -int __bam_dpages __P((DBC *)); -int __bam_open __P((DB *, DB_INFO *)); -int __bam_close __P((DB *)); -void __bam_setovflsize __P((DB *)); -int __bam_read_root __P((DB *)); -int __bam_new __P((DBC *, u_int32_t, PAGE **)); -int __bam_lput __P((DBC *, DB_LOCK)); -int __bam_free __P((DBC *, PAGE *)); -int __bam_lt __P((DBC *)); -int __bam_lget - __P((DBC *, int, db_pgno_t, db_lockmode_t, DB_LOCK *)); -int __bam_iitem __P((DBC *, - PAGE **, db_indx_t *, DBT *, DBT *, u_int32_t, u_int32_t)); -int __bam_ritem __P((DBC *, PAGE *, u_int32_t, DBT *)); -int __bam_pg_alloc_recover - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __bam_pg_free_recover - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __bam_split_recover - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __bam_rsplit_recover - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __bam_adj_recover - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __bam_cadjust_recover - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __bam_cdel_recover - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __bam_repl_recover - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __ram_open __P((DB *, DB_INFO *)); -int __ram_close __P((DB *)); -int __ram_c_del __P((DBC *, u_int32_t)); -int __ram_c_get __P((DBC *, DBT *, DBT *, u_int32_t)); -int __ram_c_put __P((DBC *, DBT *, DBT *, u_int32_t)); -void __ram_ca __P((DB *, db_recno_t, ca_recno_arg)); -int __ram_getno __P((DBC *, const DBT *, db_recno_t *, int)); -int __bam_rsearch __P((DBC *, db_recno_t *, u_int32_t, int, int *)); -int __bam_adjust __P((DBC *, int32_t)); -int __bam_nrecs __P((DBC *, db_recno_t *)); -db_recno_t __bam_total __P((PAGE *)); -int __bam_search __P((DBC *, - const DBT *, u_int32_t, int, db_recno_t *, int *)); -int __bam_stkrel __P((DBC *, int)); -int __bam_stkgrow __P((CURSOR *)); -int __bam_split __P((DBC *, void *)); -int __bam_copy __P((DB *, PAGE *, PAGE *, u_int32_t, u_int32_t)); -int __bam_stat __P((DB *, void *, void *(*)(size_t), u_int32_t)); -int __bam_pg_alloc_log - __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - u_int32_t, DB_LSN *, DB_LSN *, db_pgno_t, - u_int32_t, db_pgno_t)); -int __bam_pg_alloc_print - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __bam_pg_alloc_read __P((void *, __bam_pg_alloc_args **)); -int __bam_pg_free_log - __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - u_int32_t, db_pgno_t, DB_LSN *, const DBT *, - db_pgno_t)); -int __bam_pg_free_print - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __bam_pg_free_read __P((void *, __bam_pg_free_args **)); -int __bam_split_log - __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - u_int32_t, db_pgno_t, DB_LSN *, db_pgno_t, - DB_LSN *, u_int32_t, db_pgno_t, DB_LSN *, - const DBT *)); -int __bam_split_print - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __bam_split_read __P((void *, __bam_split_args **)); -int __bam_rsplit_log - __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - u_int32_t, db_pgno_t, const DBT *, db_pgno_t, - const DBT *, DB_LSN *)); -int __bam_rsplit_print - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __bam_rsplit_read __P((void *, __bam_rsplit_args **)); -int __bam_adj_log - __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - u_int32_t, db_pgno_t, DB_LSN *, u_int32_t, - u_int32_t, u_int32_t)); -int __bam_adj_print - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __bam_adj_read __P((void *, __bam_adj_args **)); -int __bam_cadjust_log - __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - u_int32_t, db_pgno_t, DB_LSN *, u_int32_t, - int32_t, int32_t)); -int __bam_cadjust_print - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __bam_cadjust_read __P((void *, __bam_cadjust_args **)); -int __bam_cdel_log - __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - u_int32_t, db_pgno_t, DB_LSN *, u_int32_t)); -int __bam_cdel_print - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __bam_cdel_read __P((void *, __bam_cdel_args **)); -int __bam_repl_log - __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - u_int32_t, db_pgno_t, DB_LSN *, u_int32_t, - u_int32_t, const DBT *, const DBT *, u_int32_t, - u_int32_t)); -int __bam_repl_print - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __bam_repl_read __P((void *, __bam_repl_args **)); -int __bam_init_print __P((DB_ENV *)); -int __bam_init_recover __P((DB_ENV *)); -#endif /* _btree_ext_h_ */ diff --git a/db2/include/clib_ext.h b/db2/include/clib_ext.h deleted file mode 100644 index 2566b84..0000000 --- a/db2/include/clib_ext.h +++ /dev/null @@ -1,59 +0,0 @@ -/* DO NOT EDIT: automatically built by dist/distrib. */ -#ifndef _clib_ext_h_ -#define _clib_ext_h_ -#ifdef __STDC__ -void err __P((int eval, const char *, ...)); -#else -void err(); -#endif -#ifdef __STDC__ -void errx __P((int eval, const char *, ...)); -#else -void errx(); -#endif -#ifdef __STDC__ -void warn __P((const char *, ...)); -#else -void warn(); -#endif -#ifdef __STDC__ -void warnx __P((const char *, ...)); -#else -void warnx(); -#endif -#ifndef HAVE_GETCWD -char *getcwd __P((char *, size_t)); -#endif -void get_long __P((char *, long, long, long *)); -#ifndef HAVE_GETOPT -int getopt __P((int, char * const *, const char *)); -#endif -#ifndef HAVE_MEMCMP -int memcmp __P((const void *, const void *, size_t)); -#endif -#ifndef HAVE_MEMCPY -void *memcpy __P((void *, const void *, size_t)); -#endif -#ifndef HAVE_MEMMOVE -void *memmove __P((void *, const void *, size_t)); -#endif -#ifndef HAVE_RAISE -int raise __P((int)); -#endif -#ifndef HAVE_SNPRINTF -#ifdef __STDC__ -int snprintf __P((char *, size_t, const char *, ...)); -#else -int snprintf(); -#endif -#endif -#ifndef HAVE_STRERROR -char *strerror __P((int)); -#endif -#ifndef HAVE_STRSEP -char *strsep __P((char **, const char *)); -#endif -#ifndef HAVE_VSNPRINTF -int vsnprintf(); -#endif -#endif /* _clib_ext_h_ */ diff --git a/db2/include/common_ext.h b/db2/include/common_ext.h deleted file mode 100644 index 33fb0cb..0000000 --- a/db2/include/common_ext.h +++ /dev/null @@ -1,34 +0,0 @@ -/* DO NOT EDIT: automatically built by dist/distrib. */ -#ifndef _common_ext_h_ -#define _common_ext_h_ -int __db_appname __P((DB_ENV *, - APPNAME, const char *, const char *, u_int32_t, int *, char **)); -int __db_apprec __P((DB_ENV *, u_int32_t)); -int __db_byteorder __P((DB_ENV *, int)); -int __db_fchk __P((DB_ENV *, const char *, u_int32_t, u_int32_t)); -int __db_fcchk - __P((DB_ENV *, const char *, u_int32_t, u_int32_t, u_int32_t)); -int __db_ferr __P((const DB_ENV *, const char *, int)); -#ifdef __STDC__ -void __db_err __P((const DB_ENV *dbenv, const char *fmt, ...)); -#else -void __db_err(); -#endif -int __db_pgerr __P((DB *, db_pgno_t)); -int __db_pgfmt __P((DB *, db_pgno_t)); -int __db_panic __P((DB_ENV *, int)); -u_int32_t __db_log2 __P((u_int32_t)); -int __db_rattach __P((REGINFO *)); -int __db_rdetach __P((REGINFO *)); -int __db_runlink __P((REGINFO *, int)); -int __db_rgrow __P((REGINFO *, size_t)); -int __db_rreattach __P((REGINFO *, size_t)); -void __db_shalloc_init __P((void *, size_t)); -int __db_shalloc __P((void *, size_t, size_t, void *)); -void __db_shalloc_free __P((void *, void *)); -size_t __db_shalloc_count __P((void *)); -size_t __db_shsizeof __P((void *)); -void __db_shalloc_dump __P((void *, FILE *)); -int __db_tablesize __P((u_int32_t)); -void __db_hashinit __P((void *, u_int32_t)); -#endif /* _common_ext_h_ */ diff --git a/db2/include/cxx_int.h b/db2/include/cxx_int.h deleted file mode 100644 index 0a59de4..0000000 --- a/db2/include/cxx_int.h +++ /dev/null @@ -1,118 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1997, 1998 - * Sleepycat Software. All rights reserved. - * - * @(#)cxx_int.h 10.5 (Sleepycat) 4/10/98 - */ - -#ifndef _CXX_INT_H_ -#define _CXX_INT_H_ - -// private data structures known to the implementation only - -#include <assert.h> // used by defines below - -// -// Using FooImp classes will allow the implementation to change in the -// future without any modification to user code or even to header files -// that the user includes. FooImp * is just like void * except that it -// provides a little extra protection, since you cannot randomly assign -// any old pointer to a FooImp* as you can with void *. Currently, a -// pointer to such an opaque class is always just a pointer to the -// appropriate underlying implementation struct. These are converted -// back and forth using the various overloaded wrap()/unwrap() methods. -// This is essentially a use of the "Bridge" Design Pattern. -// -// WRAPPED_CLASS implements the appropriate wrap() and unwrap() methods -// for a wrapper class that has an underlying pointer representation. -// -#define WRAPPED_CLASS(_WRAPPER_CLASS, _IMP_CLASS, _WRAPPED_TYPE) \ - \ - class _IMP_CLASS {}; \ - \ - inline _WRAPPED_TYPE unwrap(_WRAPPER_CLASS *val) \ - { \ - if (!val) return 0; \ - return (_WRAPPED_TYPE)(val->imp()); \ - } \ - \ - inline const _WRAPPED_TYPE unwrapConst(const _WRAPPER_CLASS *val) \ - { \ - if (!val) return 0; \ - return (const _WRAPPED_TYPE)(val->imp()); \ - } \ - \ - inline _IMP_CLASS *wrap(_WRAPPED_TYPE val) \ - { \ - return (_IMP_CLASS*)val; \ - } - -WRAPPED_CLASS(DbLockTab, DbLockTabImp, DB_LOCKTAB*) -WRAPPED_CLASS(DbLog, DbLogImp, DB_LOG*) -WRAPPED_CLASS(DbMpool, DbMpoolImp, DB_MPOOL*) -WRAPPED_CLASS(DbMpoolFile, DbMpoolFileImp, DB_MPOOLFILE*) -WRAPPED_CLASS(Db, DbImp, DB*) -WRAPPED_CLASS(DbTxn, DbTxnImp, DB_TXN*) -WRAPPED_CLASS(DbTxnMgr, DbTxnMgrImp, DB_TXNMGR*) - -// Macros that handle detected errors, in case we want to -// change the default behavior. runtime_error() throws an -// exception by default. -// -// Since it's unusual to throw an exception in a destructor, -// we have a separate macro. For now, we silently ignore such -// detected errors. -// -#define DB_ERROR(caller, ecode) \ - DbEnv::runtime_error(caller, ecode) - -#define DB_DESTRUCTOR_ERROR(caller, ecode) \ - DbEnv::runtime_error(caller, ecode, 1) - - -//////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////// -// -// These defines are for tedious flag or field set/get access methods. -// - -// Define setName() and getName() methods that twiddle -// the _flags field. -// -#define DB_FLAG_METHODS(_class, _flags, _cxx_name, _flag_name) \ - \ -void _class::set##_cxx_name(int onOrOff) \ -{ \ - if (onOrOff) \ - _flags |= _flag_name; \ - else \ - _flags &= ~(_flag_name); \ -} \ - \ -int _class::get##_cxx_name() const \ -{ \ - return (_flags & _flag_name) ? 1 : 0; \ -} - - -#define DB_RO_ACCESS(_class, _type, _cxx_name, _field) \ - \ -_type _class::get_##_cxx_name() const \ -{ \ - return _field; \ -} - -#define DB_WO_ACCESS(_class, _type, _cxx_name, _field) \ - \ -void _class::set_##_cxx_name(_type value) \ -{ \ - _field = value; \ -} \ - -#define DB_RW_ACCESS(_class, _type, _cxx_name, _field) \ - DB_RO_ACCESS(_class, _type, _cxx_name, _field) \ - DB_WO_ACCESS(_class, _type, _cxx_name, _field) - -#endif /* !_CXX_INT_H_ */ diff --git a/db2/include/db_185.h.src b/db2/include/db_185.h.src deleted file mode 100644 index a928ca8..0000000 --- a/db2/include/db_185.h.src +++ /dev/null @@ -1,178 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. 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. - * - * @(#)db_185.h.src 8.7 (Sleepycat) 4/10/98 - */ - -#ifndef _DB_185_H_ -#define _DB_185_H_ - -#include <sys/types.h> - -#include <limits.h> - -/* - * XXX - * Handle function prototypes and the keyword "const". This steps on name - * space that DB doesn't control, but all of the other solutions are worse. - */ -#undef __P -#if defined(__STDC__) || defined(__cplusplus) -#define __P(protos) protos /* ANSI C prototypes */ -#else -#define const -#define __P(protos) () /* K&R C preprocessor */ -#endif - -#define RET_ERROR -1 /* Return values. */ -#define RET_SUCCESS 0 -#define RET_SPECIAL 1 - -#ifndef __BIT_TYPES_DEFINED__ -#define __BIT_TYPES_DEFINED__ -@u_int8_decl@ -@int16_decl@ -@u_int16_decl@ -@int32_decl@ -@u_int32_decl@ -#endif - -/* - * XXX - * SGI/IRIX already has a pgno_t. - */ -#ifdef sgi -#define pgno_t db_pgno_t -#endif - -#define MAX_PAGE_NUMBER 0xffffffff /* >= # of pages in a file */ -typedef u_int32_t pgno_t; -#define MAX_PAGE_OFFSET 65535 /* >= # of bytes in a page */ -typedef u_int16_t indx_t; -#define MAX_REC_NUMBER 0xffffffff /* >= # of records in a tree */ -typedef u_int32_t recno_t; - -/* Key/data structure -- a Data-Base Thang. */ -typedef struct { - void *data; /* data */ - size_t size; /* data length */ -} DBT; - -/* Routine flags. */ -#define R_CURSOR 1 /* del, put, seq */ -#define __R_UNUSED 2 /* UNUSED */ -#define R_FIRST 3 /* seq */ -#define R_IAFTER 4 /* put (RECNO) */ -#define R_IBEFORE 5 /* put (RECNO) */ -#define R_LAST 6 /* seq (BTREE, RECNO) */ -#define R_NEXT 7 /* seq */ -#define R_NOOVERWRITE 8 /* put */ -#define R_PREV 9 /* seq (BTREE, RECNO) */ -#define R_SETCURSOR 10 /* put (RECNO) */ -#define R_RECNOSYNC 11 /* sync (RECNO) */ - -typedef enum { DB_BTREE, DB_HASH, DB_RECNO } DBTYPE; - -/* Access method description structure. */ -typedef struct __db { - DBTYPE type; /* Underlying db type. */ - int (*close) __P((struct __db *)); - int (*del) __P((const struct __db *, const DBT *, u_int)); - int (*get) __P((const struct __db *, const DBT *, DBT *, u_int)); - int (*put) __P((const struct __db *, DBT *, const DBT *, u_int)); - int (*seq) __P((const struct __db *, DBT *, DBT *, u_int)); - int (*sync) __P((const struct __db *, u_int)); - void *internal; /* Access method private. */ - int (*fd) __P((const struct __db *)); -} DB; - -#define BTREEMAGIC 0x053162 -#define BTREEVERSION 3 - -/* Structure used to pass parameters to the btree routines. */ -typedef struct { -#define R_DUP 0x01 /* duplicate keys */ - u_int32_t flags; - u_int32_t cachesize; /* bytes to cache */ - u_int32_t maxkeypage; /* maximum keys per page */ - u_int32_t minkeypage; /* minimum keys per page */ - u_int32_t psize; /* page size */ - int (*compare) /* comparison function */ - __P((const DBT *, const DBT *)); - size_t (*prefix) /* prefix function */ - __P((const DBT *, const DBT *)); - int lorder; /* byte order */ -} BTREEINFO; - -#define HASHMAGIC 0x061561 -#define HASHVERSION 2 - -/* Structure used to pass parameters to the hashing routines. */ -typedef struct { - u_int32_t bsize; /* bucket size */ - u_int32_t ffactor; /* fill factor */ - u_int32_t nelem; /* number of elements */ - u_int32_t cachesize; /* bytes to cache */ - u_int32_t /* hash function */ - (*hash) __P((const void *, size_t)); - int lorder; /* byte order */ -} HASHINFO; - -/* Structure used to pass parameters to the record routines. */ -typedef struct { -#define R_FIXEDLEN 0x01 /* fixed-length records */ -#define R_NOKEY 0x02 /* key not required */ -#define R_SNAPSHOT 0x04 /* snapshot the input */ - u_int32_t flags; - u_int32_t cachesize; /* bytes to cache */ - u_int32_t psize; /* page size */ - int lorder; /* byte order */ - size_t reclen; /* record length (fixed-length records) */ - u_char bval; /* delimiting byte (variable-length records */ - char *bfname; /* btree file name */ -} RECNOINFO; - -#if defined(__cplusplus) -extern "C" { -#endif -DB *dbopen __P((const char *, int, int, DBTYPE, const void *)); - -#if defined(__cplusplus) -} -#endif -#endif /* !_DB_185_H_ */ diff --git a/db2/include/db_am.h b/db2/include/db_am.h deleted file mode 100644 index fe2176d..0000000 --- a/db2/include/db_am.h +++ /dev/null @@ -1,86 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - * - * @(#)db_am.h 10.15 (Sleepycat) 11/22/98 - */ -#ifndef _DB_AM_H -#define _DB_AM_H - -#define DB_ISBIG 0x01 -#define DB_ADD_DUP 0x10 -#define DB_REM_DUP 0x20 -#define DB_ADD_BIG 0x30 -#define DB_REM_BIG 0x40 -#define DB_SPLITOLD 0x50 -#define DB_SPLITNEW 0x60 -#define DB_ADD_PAGE 0x70 -#define DB_REM_PAGE 0x80 - -/* - * Standard initialization and shutdown macros for all recovery functions. - * - * Requires the following local variables: - * - * DB *file_dbp, *mdbp; - * DB_MPOOLFILE *mpf; - * int ret; - */ -#define REC_INTRO(func) { \ - file_dbp = NULL; \ - dbc = NULL; \ - if ((ret = func(dbtp->data, &argp)) != 0) \ - goto out; \ - if ((ret = \ - __db_fileid_to_db(logp, &file_dbp, argp->fileid)) != 0) { \ - if (ret == DB_DELETED) { \ - ret = 0; \ - goto done; \ - } \ - goto out; \ - } \ - if (file_dbp == NULL) \ - goto out; \ - if ((ret = file_dbp->cursor(file_dbp, NULL, &dbc, 0)) != 0) \ - goto out; \ - F_SET(dbc, DBC_RECOVER); \ - mpf = file_dbp->mpf; \ -} - -#define REC_CLOSE { \ - if (argp != NULL) \ - __os_free(argp, sizeof(*argp)); \ - if (dbc != NULL) \ - dbc->c_close(dbc); \ - return (ret); \ -} - -/* - * No-op versions of the same macros. - */ -#define REC_NOOP_INTRO(func) { \ - if ((ret = func(dbtp->data, &argp)) != 0) \ - return (ret); \ -} -#define REC_NOOP_CLOSE { \ - if (argp != NULL) \ - __os_free(argp, sizeof(*argp)); \ - return (ret); \ -} - -/* - * Standard debugging macro for all recovery functions. - */ -#ifdef DEBUG_RECOVER -#define REC_PRINT(func) \ - (void)func(logp, dbtp, lsnp, redo, info); -#else -#define REC_PRINT(func) \ - COMPQUIET(info, NULL); -#endif - -#include "db_auto.h" -#include "db_ext.h" -#endif diff --git a/db2/include/db_auto.h b/db2/include/db_auto.h deleted file mode 100644 index 0d1e43a..0000000 --- a/db2/include/db_auto.h +++ /dev/null @@ -1,111 +0,0 @@ -/* Do not edit: automatically built by dist/db_gen.sh. */ -#ifndef db_AUTO_H -#define db_AUTO_H - -#define DB_db_addrem (DB_db_BEGIN + 1) - -typedef struct _db_addrem_args { - u_int32_t type; - DB_TXN *txnid; - DB_LSN prev_lsn; - u_int32_t opcode; - u_int32_t fileid; - db_pgno_t pgno; - u_int32_t indx; - size_t nbytes; - DBT hdr; - DBT dbt; - DB_LSN pagelsn; -} __db_addrem_args; - - -#define DB_db_split (DB_db_BEGIN + 2) - -typedef struct _db_split_args { - u_int32_t type; - DB_TXN *txnid; - DB_LSN prev_lsn; - u_int32_t opcode; - u_int32_t fileid; - db_pgno_t pgno; - DBT pageimage; - DB_LSN pagelsn; -} __db_split_args; - - -#define DB_db_big (DB_db_BEGIN + 3) - -typedef struct _db_big_args { - u_int32_t type; - DB_TXN *txnid; - DB_LSN prev_lsn; - u_int32_t opcode; - u_int32_t fileid; - db_pgno_t pgno; - db_pgno_t prev_pgno; - db_pgno_t next_pgno; - DBT dbt; - DB_LSN pagelsn; - DB_LSN prevlsn; - DB_LSN nextlsn; -} __db_big_args; - - -#define DB_db_ovref (DB_db_BEGIN + 4) - -typedef struct _db_ovref_args { - u_int32_t type; - DB_TXN *txnid; - DB_LSN prev_lsn; - u_int32_t fileid; - db_pgno_t pgno; - int32_t adjust; - DB_LSN lsn; -} __db_ovref_args; - - -#define DB_db_relink (DB_db_BEGIN + 5) - -typedef struct _db_relink_args { - u_int32_t type; - DB_TXN *txnid; - DB_LSN prev_lsn; - u_int32_t opcode; - u_int32_t fileid; - db_pgno_t pgno; - DB_LSN lsn; - db_pgno_t prev; - DB_LSN lsn_prev; - db_pgno_t next; - DB_LSN lsn_next; -} __db_relink_args; - - -#define DB_db_addpage (DB_db_BEGIN + 6) - -typedef struct _db_addpage_args { - u_int32_t type; - DB_TXN *txnid; - DB_LSN prev_lsn; - u_int32_t fileid; - db_pgno_t pgno; - DB_LSN lsn; - db_pgno_t nextpgno; - DB_LSN nextlsn; -} __db_addpage_args; - - -#define DB_db_debug (DB_db_BEGIN + 7) - -typedef struct _db_debug_args { - u_int32_t type; - DB_TXN *txnid; - DB_LSN prev_lsn; - DBT op; - u_int32_t fileid; - DBT key; - DBT data; - u_int32_t arg_flags; -} __db_debug_args; - -#endif diff --git a/db2/include/db_cxx.h b/db2/include/db_cxx.h deleted file mode 100644 index f415d59..0000000 --- a/db2/include/db_cxx.h +++ /dev/null @@ -1,861 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1997, 1998 - * Sleepycat Software. All rights reserved. - * - * @(#)db_cxx.h 10.30 (Sleepycat) 11/22/98 - */ - -#ifndef _DB_CXX_H_ -#define _DB_CXX_H_ -// -// C++ assumptions: -// -// To ensure portability to many platforms, both new and old, we make -// few assumptions about the C++ compiler and library. For example, -// we do not expect STL, templates or namespaces to be available. The -// "newest" C++ feature used is exceptions, which are used liberally -// to transmit error information. Even the use of exceptions can be -// disabled at runtime, see setErrorModel(). -// -// C++ naming conventions: -// -// - All top level class names start with Db. -// - All class members start with lower case letter. -// - All private data members are suffixed with underscore. -// - Use underscores to divide names into multiple words. -// - Simple data accessors are named with get_ or set_ prefix. -// - All method names are taken from names of functions in the C -// layer of db (usually by dropping a prefix like "db_"). -// These methods have the same argument types and order, -// other than dropping the explicit arg that acts as "this". -// -// As a rule, each DbFoo object has exactly one underlying DB_FOO struct -// (defined in db.h) associated with it. In many cases, we inherit directly -// from the DB_FOO structure to make this relationship explicit. Often, -// the underlying C layer allocates and deallocates these structures, so -// there is no easy way to add any data to the DbFoo class. When you see -// a comment about whether data is permitted to be added, this is what -// is going on. Of course, if we need to add data to such C++ classes -// in the future, we will arrange to have an indirect pointer to the -// DB_FOO struct (as some of the classes already have). -// - - -//////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////// -// -// Forward declarations -// - -#include <iostream.h> -#include <db.h> - -class Db; // forward -class Dbc; // forward -class DbEnv; // forward -class DbException; // forward -class DbInfo; // forward -class DbLock; // forward -class DbLockTab; // forward -class DbLog; // forward -class DbLsn; // forward -class DbMpool; // forward -class DbMpoolFile; // forward -class Dbt; // forward -class DbTxn; // forward -class DbTxnMgr; // forward - -// These classes are not defined here and should be invisible -// to the user, but some compilers require forward references. -// There is one for each use of the DEFINE_DB_CLASS macro. - -class DbLockTabImp; -class DbLogImp; -class DbMpoolImp; -class DbMpoolFileImp; -class DbImp; -class DbTxnImp; -class DbTxnMgrImp; - - -//////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////// -// -// Mechanisms for declaring classes -// - -// -// Every class defined in this file has an _exported next to the class name. -// This is needed for WinTel machines so that the class methods can -// be exported or imported in a DLL as appropriate. Users of the DLL -// use the define DB_USE_DLL. When the DLL is built, DB_CREATE_DLL -// must be defined. -// -#if defined(_MSC_VER) - -# if defined(DB_CREATE_DLL) -# define _exported __declspec(dllexport) // creator of dll -# elif defined(DB_USE_DLL) -# define _exported __declspec(dllimport) // user of dll -# else -# define _exported // static lib creator or user -# endif - -#else - -# define _exported - -#endif - -// DEFINE_DB_CLASS defines an imp_ data member and imp() accessor. -// The underlying type is a pointer to an opaque *Imp class, that -// gets converted to the correct implementation class by the implementation. -// -// Since these defines use "private/public" labels, and leave the access -// being "private", we always use these by convention before any data -// members in the private section of a class. Keeping them in the -// private section also emphasizes that they are off limits to user code. -// -#define DEFINE_DB_CLASS(name) \ - public: class name##Imp* imp() { return imp_; } \ - public: const class name##Imp* imp() const { return imp_; } \ - private: class name##Imp* imp_ - - -//////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////// -// -// Turn off inappropriate compiler warnings -// - -#ifdef _MSC_VER - -// These are level 4 warnings that are explicitly disabled. -// With Visual C++, by default you do not see above level 3 unless -// you use /W4. But we like to compile with the highest level -// warnings to catch other errors. -// -// 4201: nameless struct/union -// triggered by standard include file <winnt.h> -// -// 4514: unreferenced inline function has been removed -// certain include files in MSVC define methods that are not called -// -#pragma warning(disable: 4201 4514) - -#endif - -//////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////// -// -// Exception classes -// - -// Almost any error in the DB library throws a DbException. -// Every exception should be considered an abnormality -// (e.g. bug, misuse of DB, file system error). -// -// NOTE: We would like to inherit from class exception and -// let it handle what(), but there are -// MSVC++ problems when <exception> is included. -// -class _exported DbException -{ -public: - virtual ~DbException(); - DbException(int err); - DbException(const char *description); - DbException(const char *prefix, int err); - DbException(const char *prefix1, const char *prefix2, int err); - const int get_errno(); - virtual const char *what() const; - - DbException(const DbException &); - DbException &operator = (const DbException &); - -private: - char *what_; - int err_; // errno -}; - - -//////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////// -// -// Lock classes -// - -class _exported DbLock -{ - friend class DbLockTab; - -public: - DbLock(); - - int put(DbLockTab *locktab); - - DbLock(const DbLock &); - DbLock &operator = (const DbLock &); - -protected: - // We can add data to this class if needed - // since its contained class is not allocated by db. - // (see comment at top) - - DbLock(DB_LOCK); - DB_LOCK lock_; -}; - -class _exported DbLockTab -{ - friend class DbEnv; - -public: - int close(); - int detect(u_int32_t flags, int atype); - int get(u_int32_t locker, u_int32_t flags, const Dbt *obj, - db_lockmode_t lock_mode, DbLock *lock); - int id(u_int32_t *idp); - int stat(DB_LOCK_STAT **statp, void *(*db_malloc)(size_t)); - int vec(u_int32_t locker, u_int32_t flags, DB_LOCKREQ list[], - int nlist, DB_LOCKREQ **elistp); - - // Create or remove new locktab files - // - static int open(const char *dir, u_int32_t flags, int mode, - DbEnv* dbenv, DbLockTab **regionp); - static int unlink(const char *dir, int force, DbEnv* dbenv); - -private: - // We can add data to this class if needed - // since it is implemented via a pointer. - // (see comment at top) - - // copying not allowed - // - DbLockTab(const DbLockTab &); - DbLockTab &operator = (const DbLockTab &); - - // Note: use DbLockTab::open() or DbEnv::get_lk_info() - // to get pointers to a DbLockTab, - // and call DbLockTab::close() rather than delete to release them. - // - DbLockTab(); - ~DbLockTab(); - - DEFINE_DB_CLASS(DbLockTab); -}; - - -//////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////// -// -// Log classes -// - -class _exported DbLsn : protected DB_LSN -{ - friend class DbLog; // friendship needed to cast to base class - friend class DbMpool; -}; - -class _exported DbLog -{ - friend class DbEnv; - -public: - int archive(char **list[], u_int32_t flags, void *(*db_malloc)(size_t)); - int close(); - static int compare(const DbLsn *lsn0, const DbLsn *lsn1); - int file(DbLsn *lsn, char *namep, int len); - int flush(const DbLsn *lsn); - int get(DbLsn *lsn, Dbt *data, u_int32_t flags); - int put(DbLsn *lsn, const Dbt *data, u_int32_t flags); - - // Normally these would be called register and unregister to - // parallel the C interface, but "register" is a reserved word. - // - int db_register(Db *dbp, const char *name, DBTYPE type, u_int32_t *fidp); - int db_unregister(u_int32_t fid); - - // Create or remove new log files - // - static int open(const char *dir, u_int32_t flags, int mode, - DbEnv* dbenv, DbLog **regionp); - static int unlink(const char *dir, int force, DbEnv* dbenv); - -private: - // We can add data to this class if needed - // since it is implemented via a pointer. - // (see comment at top) - - // Note: use DbLog::open() or DbEnv::get_lg_info() - // to get pointers to a DbLog, - // and call DbLog::close() rather than delete to release them. - // - DbLog(); - ~DbLog(); - - // no copying - DbLog(const DbLog &); - operator = (const DbLog &); - - DEFINE_DB_CLASS(DbLog); -}; - - -//////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////// -// -// Memory pool classes -// - -class _exported DbMpoolFile -{ - friend class DbEnv; - -public: - int close(); - int get(db_pgno_t *pgnoaddr, u_int32_t flags, void *pagep); - int put(void *pgaddr, u_int32_t flags); - int set(void *pgaddr, u_int32_t flags); - int sync(); - - static int open(DbMpool *mp, const char *file, - u_int32_t flags, int mode, size_t pagesize, - DB_MPOOL_FINFO *finfop, DbMpoolFile **mpf); - -private: - // We can add data to this class if needed - // since it is implemented via a pointer. - // (see comment at top) - - // Note: use DbMpoolFile::open() - // to get pointers to a DbMpoolFile, - // and call DbMpoolFile::close() rather than delete to release them. - // - DbMpoolFile(); - - // Shut g++ up. -protected: - ~DbMpoolFile(); - -private: - // no copying - DbMpoolFile(const DbMpoolFile &); - operator = (const DbMpoolFile &); - - DEFINE_DB_CLASS(DbMpoolFile); -}; - -class _exported DbMpool -{ - friend class DbEnv; - -public: - int close(); - - // access to low level interface - // Normally this would be called register to parallel - // the C interface, but "register" is a reserved word. - // - int db_register(int ftype, - int (*pgin)(db_pgno_t pgno, void *pgaddr, DBT *pgcookie), - int (*pgout)(db_pgno_t pgno, void *pgaddr, DBT *pgcookie)); - - int stat(DB_MPOOL_STAT **gsp, DB_MPOOL_FSTAT ***fsp, - void *(*db_malloc)(size_t)); - int sync(DbLsn *lsn); - int trickle(int pct, int *nwrotep); - - // Create or remove new mpool files - // - static int open(const char *dir, u_int32_t flags, int mode, - DbEnv* dbenv, DbMpool **regionp); - static int unlink(const char *dir, int force, DbEnv* dbenv); - -private: - // We can add data to this class if needed - // since it is implemented via a pointer. - // (see comment at top) - - // Note: use DbMpool::open() or DbEnv::get_mp_info() - // to get pointers to a DbMpool, - // and call DbMpool::close() rather than delete to release them. - // - DbMpool(); - ~DbMpool(); - - // no copying - DbMpool(const DbMpool &); - DbMpool &operator = (const DbMpool &); - - DEFINE_DB_CLASS(DbMpool); -}; - - -//////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////// -// -// Transaction classes -// - -class _exported DbTxnMgr -{ - friend class DbEnv; - -public: - int begin(DbTxn *pid, DbTxn **tid); - int checkpoint(u_int32_t kbyte, u_int32_t min) const; - int close(); - int stat(DB_TXN_STAT **statp, void *(*db_malloc)(size_t)); - - // Create or remove new txnmgr files - // - static int open(const char *dir, u_int32_t flags, int mode, - DbEnv* dbenv, DbTxnMgr **regionp); - static int unlink(const char *dir, int force, DbEnv* dbenv); - -private: - // We can add data to this class if needed - // since it is implemented via a pointer. - // (see comment at top) - - // Note: use DbTxnMgr::open() or DbEnv::get_tx_info() - // to get pointers to a DbTxnMgr, - // and call DbTxnMgr::close() rather than delete to release them. - // - DbTxnMgr(); - ~DbTxnMgr(); - - // no copying - DbTxnMgr(const DbTxnMgr &); - operator = (const DbTxnMgr &); - - DEFINE_DB_CLASS(DbTxnMgr); -}; - -class _exported DbTxn -{ - friend class DbTxnMgr; - -public: - int abort(); - int commit(); - u_int32_t id(); - int prepare(); - -private: - // We can add data to this class if needed - // since it is implemented via a pointer. - // (see comment at top) - - // Note: use DbTxnMgr::begin() to get pointers to a DbTxn, - // and call DbTxn::abort() or DbTxn::commit rather than - // delete to release them. - // - DbTxn(); - ~DbTxn(); - - // no copying - DbTxn(const DbTxn &); - operator = (const DbTxn &); - - DEFINE_DB_CLASS(DbTxn); -}; - - -//////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////// -// -// Application classes -// - -// -// A set of application options - define how this application uses -// the db library. -// -class _exported DbInfo : protected DB_INFO -{ - friend class DbEnv; - friend class Db; - -public: - DbInfo(); - ~DbInfo(); - - // Byte order. - void set_lorder(int); - - // Underlying cache size. - void set_cachesize(size_t); - - // Underlying page size. - void set_pagesize(size_t); - - // Local heap allocation. - typedef void *(*db_malloc_fcn)(size_t); - void set_malloc(db_malloc_fcn); - - // Duplicate compare function. - typedef int (*dup_compare_fcn)(const DBT *, const DBT *); - void set_dup_compare(dup_compare_fcn); - - //////////////////////////////////////////////////////////////// - // Btree access method. - - // Maximum keys per page. - void set_bt_maxkey(int); - - // Minimum keys per page. - void set_bt_minkey(int); - - // Comparison function. - typedef int (*bt_compare_fcn)(const DBT *, const DBT *); - void set_bt_compare(bt_compare_fcn); - - // Prefix function. - typedef size_t (*bt_prefix_fcn)(const DBT *, const DBT *); - void set_bt_prefix(bt_prefix_fcn); - - //////////////////////////////////////////////////////////////// - // Hash access method. - - // Fill factor. - void set_h_ffactor(u_int32_t); - - // Number of elements. - void set_h_nelem(u_int32_t); - - // Hash function. - typedef u_int32_t (*h_hash_fcn)(const void *, u_int32_t); - void set_h_hash(h_hash_fcn); - - //////////////////////////////////////////////////////////////// - // Recno access method. - - // Fixed-length padding byte. - void set_re_pad(int); - - // Variable-length delimiting byte. - void set_re_delim(int); - - // Length for fixed-length records. - void set_re_len(u_int32_t); - - // Source file name. - void set_re_source(char *); - - // Note: some flags are set as side effects of calling - // above "set" methods. - // - void set_flags(u_int32_t); - - - // (deep) copying of this object is allowed. - // - DbInfo(const DbInfo &); - DbInfo &operator = (const DbInfo &); - -private: - // We can add data to this class if needed - // since parent class is not allocated by db. - // (see comment at top) -}; - -// -// Base application class. Provides functions for opening a database. -// User of this library can use this class as a starting point for -// developing a DB application - derive their application class from -// this one, add application control logic. -// -// Note that if you use the default constructor, you must explicitly -// call appinit() before any other db activity (e.g. opening files) -// -class _exported DbEnv : protected DB_ENV -{ - friend class DbTxnMgr; - friend class DbLog; - friend class DbLockTab; - friend class DbMpool; - friend class Db; - -public: - - ~DbEnv(); - - // This constructor can be used to immediately initialize the - // application with these arguments. Do not use it if you - // need to set other parameters via the access methods. - // - DbEnv(const char *homeDir, char *const *db_config, u_int32_t flags); - - // Use this constructor if you wish to *delay* the initialization - // of the db library. This is useful if you need to set - // any particular parameters via the access methods below. - // Then call appinit() to complete the initialization. - // - DbEnv(); - - // Used in conjunction with the default constructor to - // complete the initialization of the db library. - // - int appinit(const char *homeDir, char *const *db_config, u_int32_t flags); - - // Called automatically when DbEnv is destroyed, or can be - // called at any time to shut down Db. - // - int appexit(); - - // Version information. A static method so it can be obtained anytime. - // - static char *version(int *major, int *minor, int *patch); - - //////////////////////////////////////////////////////////////// - // simple get/set access methods - // - // If you are calling set_ methods, you need to - // use the default constructor along with appinit(). - - // Byte order. - void set_lorder(int); - - // Panic callback. - typedef void (*db_paniccall_fcn)(DbEnv *, int); - void set_paniccall(db_paniccall_fcn); - - // Error message callback. - typedef void (*db_errcall_fcn)(const char *, char *); - void set_errcall(db_errcall_fcn); - - // Error message file stream. - void set_errfile(FILE *); - - // Error message prefix. - void set_errpfx(const char *); - - // Generate debugging messages. - void set_verbose(int); - - //////////////////////////////////////////////////////////////// - // Locking. - - // Return from lock_open(). - DbLockTab *get_lk_info() const; - - // Two dimensional conflict matrix. - void set_lk_conflicts(u_int8_t *); - - // Number of lock modes in table. - void set_lk_modes(int); - - // Maximum number of locks. - void set_lk_max(u_int32_t); - - // Deadlock detect on every conflict. - void set_lk_detect(u_int32_t); - - - //////////////////////////////////////////////////////////////// - // Logging. - - // Return from log_open(). - DbLog *get_lg_info() const; - - // Maximum file size. - void set_lg_max(u_int32_t); - - - //////////////////////////////////////////////////////////////// - // Memory pool. - - // Return from memp_open(). - DbMpool *get_mp_info() const; - - // Maximum file size for mmap. - void set_mp_mmapsize(size_t); - - // Bytes in the mpool cache. - void set_mp_size(size_t); - - - //////////////////////////////////////////////////////////////// - // Transactions. - - // Return from txn_open(). - DbTxnMgr *get_tx_info() const; - - // Maximum number of transactions. - void set_tx_max(u_int32_t); - - // Dispatch function for recovery. - typedef int (*tx_recover_fcn)(DB_LOG *, DBT *, DB_LSN *, int, void *); - void set_tx_recover(tx_recover_fcn); - - // Flags. - void set_flags(u_int32_t); - - //////////////////////////////////////////////////////////////// - // The default error model is to throw an exception whenever - // an error occurs. This generally allows for cleaner logic - // for transaction processing, as a try block can surround a - // single transaction. Alternatively, since almost every method - // returns an error code (errno), the error model can be set to - // not throw exceptions, and instead return the appropriate code. - // - enum ErrorModel { Exception, ErrorReturn }; - void set_error_model(ErrorModel); - - // If an error is detected and the error call function - // or stream is set, a message is dispatched or printed. - // If a prefix is set, each message is prefixed. - // - // You can use set_errcall() or set_errfile() above to control - // error functionality using a C model. Alternatively, you can - // call set_error_stream() to force all errors to a C++ stream. - // It is unwise to mix these approaches. - // - void set_error_stream(class ostream*); - - // used internally - static int runtime_error(const char *caller, int err, - int in_destructor = 0, int force_throw = 0); - -private: - // We can add data to this class if needed - // since parent class is not allocated by db. - // (see comment at top) - - // no copying - DbEnv(const DbEnv &); - operator = (const DbEnv &); - - ErrorModel error_model_; - static void stream_error_function(const char *, char *); - static ostream *error_stream_; -}; - -//////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////// -// -// Table access classes -// - -// -// Represents a database table = a set of keys with associated values. -// -class _exported Db -{ - friend class DbEnv; - -public: - int close(u_int32_t flags); - int cursor(DbTxn *txnid, Dbc **cursorp, u_int32_t flags); - int del(DbTxn *txnid, Dbt *key, u_int32_t flags); - int fd(int *fdp); - int get(DbTxn *txnid, Dbt *key, Dbt *data, u_int32_t flags); - int join(Dbc **curslist, u_int32_t flags, Dbc **dbcp); - int put(DbTxn *txnid, Dbt *key, Dbt *data, u_int32_t flags); - int stat(void *sp, void *(*db_malloc)(size_t), u_int32_t flags); - int sync(u_int32_t flags); - - int get_byteswapped() const; - DBTYPE get_type() const; - - static int open(const char *fname, DBTYPE type, u_int32_t flags, - int mode, DbEnv *dbenv, DbInfo *info, Db **dbpp); - - static int xa_open(const char *fname, DBTYPE type, u_int32_t flags, - int mode, DbInfo *info, Db **dbpp); -private: - // We can add data to this class if needed - // since it is implemented via a pointer. - // (see comment at top) - - // Note: use Db::open() to get initialize pointers to a Db, - // and call Db::close() rather than delete to release them. - Db(); - ~Db(); - - // no copying - Db(const Db &); - Db &operator = (const Db &); - - DEFINE_DB_CLASS(Db); -}; - -// -// A chunk of data, maybe a key or value. -// -class _exported Dbt : private DBT -{ - friend class Dbc; - friend class Db; - friend class DbLog; - friend class DbMpoolFile; - friend class DbLockTab; - -public: - - // key/data - void *get_data() const; - void set_data(void *); - - // key/data length - u_int32_t get_size() const; - void set_size(u_int32_t); - - // RO: length of user buffer. - u_int32_t get_ulen() const; - void set_ulen(u_int32_t); - - // RO: get/put record length. - u_int32_t get_dlen() const; - void set_dlen(u_int32_t); - - // RO: get/put record offset. - u_int32_t get_doff() const; - void set_doff(u_int32_t); - - // flags - u_int32_t get_flags() const; - void set_flags(u_int32_t); - - Dbt(void *data, size_t size); - Dbt(); - ~Dbt(); - Dbt(const Dbt &); - Dbt &operator = (const Dbt &); - -private: - // We can add data to this class if needed - // since parent class is not allocated by db. - // (see comment at top) -}; - -class _exported Dbc : protected DBC -{ - friend class Db; - -public: - int close(); - int del(u_int32_t flags); - int get(Dbt* key, Dbt *data, u_int32_t flags); - int put(Dbt* key, Dbt *data, u_int32_t flags); - -private: - // No data is permitted in this class (see comment at top) - - // Note: use Db::cursor() to get pointers to a Dbc, - // and call Dbc::close() rather than delete to release them. - // - Dbc(); - ~Dbc(); - - // no copying - Dbc(const Dbc &); - Dbc &operator = (const Dbc &); -}; -#endif /* !_DB_CXX_H_ */ diff --git a/db2/include/db_dispatch.h b/db2/include/db_dispatch.h deleted file mode 100644 index 8f5e217..0000000 --- a/db2/include/db_dispatch.h +++ /dev/null @@ -1,77 +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. - * - * @(#)db_dispatch.h 10.4 (Sleepycat) 5/3/98 - */ - -#ifndef _DB_DISPATCH_H -#define _DB_DISPATCH_H - -struct __db_txnhead; typedef struct __db_txnhead DB_TXNHEAD; -struct __db_txnlist; typedef struct __db_txnlist DB_TXNLIST; - -/* - * Declarations and typedefs for the list of transaction IDs used during - * recovery. - */ -struct __db_txnhead { - LIST_HEAD(__db_headlink, __db_txnlist) head; - u_int32_t maxid; - int32_t generation; -}; - -struct __db_txnlist { - LIST_ENTRY(__db_txnlist) links; - u_int32_t txnid; - int32_t generation; -}; - -#define DB_log_BEGIN 0 -#define DB_txn_BEGIN 5 -#define DB_ham_BEGIN 20 -#define DB_db_BEGIN 40 -#define DB_bam_BEGIN 50 -#define DB_ram_BEGIN 100 -#define DB_user_BEGIN 150 - -#define TXN_UNDO 0 -#define TXN_REDO 1 -#define TXN_BACKWARD_ROLL -1 -#define TXN_FORWARD_ROLL -2 -#define TXN_OPENFILES -3 -#endif diff --git a/db2/include/db_ext.h b/db2/include/db_ext.h deleted file mode 100644 index 1ad1643..0000000 --- a/db2/include/db_ext.h +++ /dev/null @@ -1,132 +0,0 @@ -/* DO NOT EDIT: automatically built by dist/distrib. */ -#ifndef _db_ext_h_ -#define _db_ext_h_ -int __db_close __P((DB *, u_int32_t)); -int __db_init_wrapper __P((DB *)); -int __db_cprint __P((DB *)); -int __db_c_destroy __P((DBC *)); -int __db_sync __P((DB *, u_int32_t)); -int __db_addrem_log - __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - u_int32_t, u_int32_t, db_pgno_t, u_int32_t, - size_t, const DBT *, const DBT *, DB_LSN *)); -int __db_addrem_print - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __db_addrem_read __P((void *, __db_addrem_args **)); -int __db_split_log - __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - u_int32_t, u_int32_t, db_pgno_t, const DBT *, - DB_LSN *)); -int __db_split_print - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __db_split_read __P((void *, __db_split_args **)); -int __db_big_log - __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - u_int32_t, u_int32_t, db_pgno_t, db_pgno_t, - db_pgno_t, const DBT *, DB_LSN *, DB_LSN *, - DB_LSN *)); -int __db_big_print - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __db_big_read __P((void *, __db_big_args **)); -int __db_ovref_log - __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - u_int32_t, db_pgno_t, int32_t, DB_LSN *)); -int __db_ovref_print - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __db_ovref_read __P((void *, __db_ovref_args **)); -int __db_relink_log - __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - u_int32_t, u_int32_t, db_pgno_t, DB_LSN *, - db_pgno_t, DB_LSN *, db_pgno_t, DB_LSN *)); -int __db_relink_print - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __db_relink_read __P((void *, __db_relink_args **)); -int __db_addpage_log - __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - u_int32_t, db_pgno_t, DB_LSN *, db_pgno_t, - DB_LSN *)); -int __db_addpage_print - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __db_addpage_read __P((void *, __db_addpage_args **)); -int __db_debug_log - __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - const DBT *, u_int32_t, const DBT *, const DBT *, - u_int32_t)); -int __db_debug_print - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __db_debug_read __P((void *, __db_debug_args **)); -int __db_init_print __P((DB_ENV *)); -int __db_init_recover __P((DB_ENV *)); -int __db_pgin __P((db_pgno_t, size_t, void *)); -int __db_pgout __P((db_pgno_t, size_t, void *)); -int __db_dispatch __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __db_add_recovery __P((DB_ENV *, - int (*)(DB_LOG *, DBT *, DB_LSN *, int, void *), u_int32_t)); -int __db_txnlist_init __P((void *)); -int __db_txnlist_add __P((void *, u_int32_t)); -int __db_txnlist_find __P((void *, u_int32_t)); -void __db_txnlist_end __P((void *)); -void __db_txnlist_gen __P((void *, int)); -void __db_txnlist_print __P((void *)); -int __db_dput __P((DBC *, DBT *, - PAGE **, db_indx_t *, int (*)(DBC *, u_int32_t, PAGE **))); -int __db_drem __P((DBC *, - PAGE **, u_int32_t, int (*)(DBC *, PAGE *))); -int __db_dend __P((DBC *, db_pgno_t, PAGE **)); - int __db_ditem __P((DBC *, PAGE *, u_int32_t, u_int32_t)); -int __db_pitem - __P((DBC *, PAGE *, u_int32_t, u_int32_t, DBT *, DBT *)); -int __db_relink __P((DBC *, u_int32_t, PAGE *, PAGE **, int)); -int __db_ddup __P((DBC *, db_pgno_t, int (*)(DBC *, PAGE *))); -int __db_dsearch __P((DBC *, - int, DBT *, db_pgno_t, db_indx_t *, PAGE **, int *)); -int __db_cdelchk __P((const DB *, u_int32_t, int, int)); -int __db_cgetchk __P((const DB *, DBT *, DBT *, u_int32_t, int)); -int __db_cputchk __P((const DB *, - const DBT *, DBT *, u_int32_t, int, int)); -int __db_closechk __P((const DB *, u_int32_t)); -int __db_delchk __P((const DB *, DBT *, u_int32_t, int)); -int __db_getchk __P((const DB *, const DBT *, DBT *, u_int32_t)); -int __db_joinchk __P((const DB *, u_int32_t)); -int __db_putchk - __P((const DB *, DBT *, const DBT *, u_int32_t, int, int)); -int __db_statchk __P((const DB *, u_int32_t)); -int __db_syncchk __P((const DB *, u_int32_t)); -int __db_eopnotsup __P((const DB_ENV *)); -int __db_join __P((DB *, DBC **, u_int32_t, DBC **)); -int __db_goff __P((DB *, DBT *, - u_int32_t, db_pgno_t, void **, u_int32_t *)); -int __db_poff __P((DBC *, const DBT *, db_pgno_t *, - int (*)(DBC *, u_int32_t, PAGE **))); -int __db_ovref __P((DBC *, db_pgno_t, int32_t)); -int __db_doff __P((DBC *, db_pgno_t, int (*)(DBC *, PAGE *))); -int __db_moff __P((DB *, const DBT *, db_pgno_t, u_int32_t, - int (*)(const DBT *, const DBT *), int *)); -void __db_loadme __P((void)); -FILE *__db_prinit __P((FILE *)); -int __db_dump __P((DB *, char *, int)); -int __db_prdb __P((DB *)); -int __db_prbtree __P((DB *)); -int __db_prhash __P((DB *)); -int __db_prtree __P((DB_MPOOLFILE *, int)); -int __db_prnpage __P((DB_MPOOLFILE *, db_pgno_t)); -int __db_prpage __P((PAGE *, int)); -int __db_isbad __P((PAGE *, int)); -void __db_pr __P((u_int8_t *, u_int32_t)); -int __db_prdbt __P((DBT *, int, FILE *)); -void __db_prflags __P((u_int32_t, const FN *, FILE *)); -int __db_addrem_recover - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __db_split_recover __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __db_big_recover __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __db_ovref_recover __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __db_relink_recover - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __db_addpage_recover - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __db_debug_recover __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __db_ret __P((DB *, - PAGE *, u_int32_t, DBT *, void **, u_int32_t *)); -int __db_retcopy __P((DBT *, - void *, u_int32_t, void **, u_int32_t *, void *(*)(size_t))); -#endif /* _db_ext_h_ */ diff --git a/db2/include/db_join.h b/db2/include/db_join.h deleted file mode 100644 index cb27e21..0000000 --- a/db2/include/db_join.h +++ /dev/null @@ -1,23 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1998 - * Sleepycat Software. All rights reserved. - * - * @(#)db_join.h 10.2 (Sleepycat) 10/4/98 - */ - -#ifndef _DB_JOIN_H -#define _DB_JOIN_H -/* - * Joins use a join cursor that is similar to a regular DB cursor except - * that it only supports c_get and c_close functionality. Also, it does - * not support the full range of flags for get. - */ -typedef struct __join_cursor { - u_int32_t j_init; /* Set when cursor is initialized. */ - DBC **j_curslist; /* Array of cursors in the join. */ - DB *j_primary; /* Primary dbp. */ - DBT j_key; /* Used to do lookups. */ -} JOIN_CURSOR; -#endif diff --git a/db2/include/db_page.h b/db2/include/db_page.h deleted file mode 100644 index 5c9ca67..0000000 --- a/db2/include/db_page.h +++ /dev/null @@ -1,512 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - * - * @(#)db_page.h 10.18 (Sleepycat) 12/2/98 - */ - -#ifndef _DB_PAGE_H_ -#define _DB_PAGE_H_ - -/* - * DB page formats. - * - * This implementation requires that values within the following structures - * NOT be padded -- note, ANSI C permits random padding within structures. - * If your compiler pads randomly you can just forget ever making DB run on - * your system. In addition, no data type can require larger alignment than - * its own size, e.g., a 4-byte data element may not require 8-byte alignment. - * - * Note that key/data lengths are often stored in db_indx_t's -- this is - * not accidental, nor does it limit the key/data size. If the key/data - * item fits on a page, it's guaranteed to be small enough to fit into a - * db_indx_t, and storing it in one saves space. - */ - -#define PGNO_METADATA 0 /* Metadata page number. */ -#define PGNO_INVALID 0 /* Metadata page number, therefore illegal. */ -#define PGNO_ROOT 1 /* Root is page #1. */ - -/* - * When we create pages in mpool, we ask mpool to clear some number of bytes - * in the header. This number must be at least as big as the regular page - * headers and cover enough of the btree and hash meta-data pages to obliterate - * the magic and version numbers. - */ -#define DB_PAGE_CLEAR_LEN 32 - -/************************************************************************ - BTREE METADATA PAGE LAYOUT - ************************************************************************/ - -/* - * Btree metadata page layout: - */ -typedef struct _btmeta { - DB_LSN lsn; /* 00-07: LSN. */ - db_pgno_t pgno; /* 08-11: Current page number. */ - u_int32_t magic; /* 12-15: Magic number. */ - u_int32_t version; /* 16-19: Version. */ - u_int32_t pagesize; /* 20-23: Pagesize. */ - u_int32_t maxkey; /* 24-27: Btree: Maxkey. */ - u_int32_t minkey; /* 28-31: Btree: Minkey. */ - u_int32_t free; /* 32-35: Free list page number. */ -#define BTM_DUP 0x001 /* Duplicates. */ -#define BTM_RECNO 0x002 /* Recno tree. */ -#define BTM_RECNUM 0x004 /* Btree: maintain record count. */ -#define BTM_FIXEDLEN 0x008 /* Recno: fixed length records. */ -#define BTM_RENUMBER 0x010 /* Recno: renumber on insert/delete. */ -#define BTM_MASK 0x01f - u_int32_t flags; /* 36-39: Flags. */ - u_int32_t re_len; /* 40-43: Recno: fixed-length record length. */ - u_int32_t re_pad; /* 44-47: Recno: fixed-length record pad. */ - /* 48-67: Unique file ID. */ - u_int8_t uid[DB_FILE_ID_LEN]; -} BTMETA; - -/************************************************************************ - HASH METADATA PAGE LAYOUT - ************************************************************************/ - -/* - * Hash metadata page layout: - */ -/* Hash Table Information */ -typedef struct hashhdr { /* Disk resident portion */ - DB_LSN lsn; /* 00-07: LSN of the header page */ - db_pgno_t pgno; /* 08-11: Page number (btree compatibility). */ - u_int32_t magic; /* 12-15: Magic NO for hash tables */ - u_int32_t version; /* 16-19: Version ID */ - u_int32_t pagesize; /* 20-23: Bucket/Page Size */ - u_int32_t ovfl_point; /* 24-27: Overflow page allocation location */ - u_int32_t last_freed; /* 28-31: Last freed overflow page pgno */ - u_int32_t max_bucket; /* 32-35: ID of Maximum bucket in use */ - u_int32_t high_mask; /* 36-39: Modulo mask into table */ - u_int32_t low_mask; /* 40-43: Modulo mask into table lower half */ - u_int32_t ffactor; /* 44-47: Fill factor */ - u_int32_t nelem; /* 48-51: Number of keys in hash table */ - u_int32_t h_charkey; /* 52-55: Value of hash(CHARKEY) */ -#define DB_HASH_DUP 0x01 - u_int32_t flags; /* 56-59: Allow duplicates. */ -#define NCACHED 32 /* number of spare points */ - /* 60-187: Spare pages for overflow */ - u_int32_t spares[NCACHED]; - /* 188-207: Unique file ID. */ - u_int8_t uid[DB_FILE_ID_LEN]; - - /* - * Minimum page size is 256. - */ -} HASHHDR; - -/************************************************************************ - MAIN PAGE LAYOUT - ************************************************************************/ - -/* - * +-----------------------------------+ - * | lsn | pgno | prev pgno | - * +-----------------------------------+ - * | next pgno | entries | hf offset | - * +-----------------------------------+ - * | level | type | index | - * +-----------------------------------+ - * | index | free --> | - * +-----------+-----------------------+ - * | F R E E A R E A | - * +-----------------------------------+ - * | <-- free | item | - * +-----------------------------------+ - * | item | item | item | - * +-----------------------------------+ - * - * sizeof(PAGE) == 26 bytes, and the following indices are guaranteed to be - * two-byte aligned. - * - * For hash and btree leaf pages, index items are paired, e.g., inp[0] is the - * key for inp[1]'s data. All other types of pages only contain single items. - */ -typedef struct _db_page { - DB_LSN lsn; /* 00-07: Log sequence number. */ - db_pgno_t pgno; /* 08-11: Current page number. */ - db_pgno_t prev_pgno; /* 12-15: Previous page number. */ - db_pgno_t next_pgno; /* 16-19: Next page number. */ - db_indx_t entries; /* 20-21: Number of item pairs on the page. */ - db_indx_t hf_offset; /* 22-23: High free byte page offset. */ - - /* - * The btree levels are numbered from the leaf to the root, starting - * with 1, so the leaf is level 1, its parent is level 2, and so on. - * We maintain this level on all btree pages, but the only place that - * we actually need it is on the root page. It would not be difficult - * to hide the byte on the root page once it becomes an internal page, - * so we could get this byte back if we needed it for something else. - */ -#define LEAFLEVEL 1 -#define MAXBTREELEVEL 255 - u_int8_t level; /* 24: Btree tree level. */ - -#define P_INVALID 0 /* Invalid page type. */ -#define P_DUPLICATE 1 /* Duplicate. */ -#define P_HASH 2 /* Hash. */ -#define P_IBTREE 3 /* Btree internal. */ -#define P_IRECNO 4 /* Recno internal. */ -#define P_LBTREE 5 /* Btree leaf. */ -#define P_LRECNO 6 /* Recno leaf. */ -#define P_OVERFLOW 7 /* Overflow. */ - u_int8_t type; /* 25: Page type. */ - db_indx_t inp[1]; /* Variable length index of items. */ -} PAGE; - -/* Element macros. */ -#define LSN(p) (((PAGE *)p)->lsn) -#define PGNO(p) (((PAGE *)p)->pgno) -#define PREV_PGNO(p) (((PAGE *)p)->prev_pgno) -#define NEXT_PGNO(p) (((PAGE *)p)->next_pgno) -#define NUM_ENT(p) (((PAGE *)p)->entries) -#define HOFFSET(p) (((PAGE *)p)->hf_offset) -#define LEVEL(p) (((PAGE *)p)->level) -#define TYPE(p) (((PAGE *)p)->type) - -/* - * !!! - * The next_pgno and prev_pgno fields are not maintained for btree and recno - * internal pages. It's a minor performance improvement, and more, it's - * hard to do when deleting internal pages, and it decreases the chance of - * deadlock during deletes and splits. - * - * !!! - * The btree/recno access method needs db_recno_t bytes of space on the root - * page to specify how many records are stored in the tree. (The alternative - * is to store the number of records in the meta-data page, which will create - * a second hot spot in trees being actively modified, or recalculate it from - * the BINTERNAL fields on each access.) Overload the prev_pgno field. - */ -#define RE_NREC(p) \ - (TYPE(p) == P_LBTREE ? NUM_ENT(p) / 2 : \ - TYPE(p) == P_LRECNO ? NUM_ENT(p) : PREV_PGNO(p)) -#define RE_NREC_ADJ(p, adj) \ - PREV_PGNO(p) += adj; -#define RE_NREC_SET(p, num) \ - PREV_PGNO(p) = num; - -/* - * Initialize a page. - * - * !!! - * Don't modify the page's LSN, code depends on it being unchanged after a - * P_INIT call. - */ -#define P_INIT(pg, pg_size, n, pg_prev, pg_next, btl, pg_type) do { \ - PGNO(pg) = n; \ - PREV_PGNO(pg) = pg_prev; \ - NEXT_PGNO(pg) = pg_next; \ - NUM_ENT(pg) = 0; \ - HOFFSET(pg) = pg_size; \ - LEVEL(pg) = btl; \ - TYPE(pg) = pg_type; \ -} while (0) - -/* Page header length (offset to first index). */ -#define P_OVERHEAD (SSZA(PAGE, inp)) - -/* First free byte. */ -#define LOFFSET(pg) (P_OVERHEAD + NUM_ENT(pg) * sizeof(db_indx_t)) - -/* Free space on the page. */ -#define P_FREESPACE(pg) (HOFFSET(pg) - LOFFSET(pg)) - -/* Get a pointer to the bytes at a specific index. */ -#define P_ENTRY(pg, indx) ((u_int8_t *)pg + ((PAGE *)pg)->inp[indx]) - -/************************************************************************ - OVERFLOW PAGE LAYOUT - ************************************************************************/ - -/* - * Overflow items are referenced by HOFFPAGE and BOVERFLOW structures, which - * store a page number (the first page of the overflow item) and a length - * (the total length of the overflow item). The overflow item consists of - * some number of overflow pages, linked by the next_pgno field of the page. - * A next_pgno field of PGNO_INVALID flags the end of the overflow item. - * - * Overflow page overloads: - * The amount of overflow data stored on each page is stored in the - * hf_offset field. - * - * The implementation reference counts overflow items as it's possible - * for them to be promoted onto btree internal pages. The reference - * count is stored in the entries field. - */ -#define OV_LEN(p) (((PAGE *)p)->hf_offset) -#define OV_REF(p) (((PAGE *)p)->entries) - -/* Maximum number of bytes that you can put on an overflow page. */ -#define P_MAXSPACE(psize) ((psize) - P_OVERHEAD) - -/************************************************************************ - HASH PAGE LAYOUT - ************************************************************************/ - -/* Each index references a group of bytes on the page. */ -#define H_KEYDATA 1 /* Key/data item. */ -#define H_DUPLICATE 2 /* Duplicate key/data item. */ -#define H_OFFPAGE 3 /* Overflow key/data item. */ -#define H_OFFDUP 4 /* Overflow page of duplicates. */ - -/* - * !!! - * Items on hash pages are (potentially) unaligned, so we can never cast the - * (page + offset) pointer to an HKEYDATA, HOFFPAGE or HOFFDUP structure, as - * we do with B+tree on-page structures. Because we frequently want the type - * field, it requires no alignment, and it's in the same location in all three - * structures, there's a pair of macros. - */ -#define HPAGE_PTYPE(p) (*(u_int8_t *)p) -#define HPAGE_TYPE(pg, indx) (*P_ENTRY(pg, indx)) - -/* - * The first and second types are H_KEYDATA and H_DUPLICATE, represented - * by the HKEYDATA structure: - * - * +-----------------------------------+ - * | type | key/data ... | - * +-----------------------------------+ - * - * For duplicates, the data field encodes duplicate elements in the data - * field: - * - * +---------------------------------------------------------------+ - * | type | len1 | element1 | len1 | len2 | element2 | len2 | - * +---------------------------------------------------------------+ - * - * Thus, by keeping track of the offset in the element, we can do both - * backward and forward traversal. - */ -typedef struct _hkeydata { - u_int8_t type; /* 00: Page type. */ - u_int8_t data[1]; /* Variable length key/data item. */ -} HKEYDATA; -#define HKEYDATA_DATA(p) (((u_int8_t *)p) + SSZA(HKEYDATA, data)) - -/* - * The length of any HKEYDATA item. Note that indx is an element index, - * not a PAIR index. - */ -#define LEN_HITEM(pg, pgsize, indx) \ - (((indx) == 0 ? pgsize : pg->inp[indx - 1]) - pg->inp[indx]) - -#define LEN_HKEYDATA(pg, psize, indx) \ - (((indx) == 0 ? psize : pg->inp[indx - 1]) - \ - pg->inp[indx] - HKEYDATA_SIZE(0)) - -/* - * Page space required to add a new HKEYDATA item to the page, with and - * without the index value. - */ -#define HKEYDATA_SIZE(len) \ - ((len) + SSZA(HKEYDATA, data)) -#define HKEYDATA_PSIZE(len) \ - (HKEYDATA_SIZE(len) + sizeof(db_indx_t)) - -/* Put a HKEYDATA item at the location referenced by a page entry. */ -#define PUT_HKEYDATA(pe, kd, len, type) { \ - ((HKEYDATA *)pe)->type = type; \ - memcpy((u_int8_t *)pe + sizeof(u_int8_t), kd, len); \ -} - -/* - * Macros the describe the page layout in terms of key-data pairs. - * The use of "pindex" indicates that the argument is the index - * expressed in pairs instead of individual elements. - */ -#define H_NUMPAIRS(pg) (NUM_ENT(pg) / 2) -#define H_KEYINDEX(pindx) (2 * (pindx)) -#define H_DATAINDEX(pindx) ((2 * (pindx)) + 1) -#define H_PAIRKEY(pg, pindx) P_ENTRY(pg, H_KEYINDEX(pindx)) -#define H_PAIRDATA(pg, pindx) P_ENTRY(pg, H_DATAINDEX(pindx)) -#define H_PAIRSIZE(pg, psize, pindx) \ - (LEN_HITEM(pg, psize, H_KEYINDEX(pindx)) + \ - LEN_HITEM(pg, psize, H_DATAINDEX(pindx))) -#define LEN_HDATA(p, psize, pindx) LEN_HKEYDATA(p, psize, H_DATAINDEX(pindx)) -#define LEN_HKEY(p, psize, pindx) LEN_HKEYDATA(p, psize, H_KEYINDEX(pindx)) - -/* - * The third type is the H_OFFPAGE, represented by the HOFFPAGE structure: - */ -typedef struct _hoffpage { - u_int8_t type; /* 00: Page type and delete flag. */ - u_int8_t unused[3]; /* 01-03: Padding, unused. */ - db_pgno_t pgno; /* 04-07: Offpage page number. */ - u_int32_t tlen; /* 08-11: Total length of item. */ -} HOFFPAGE; - -#define HOFFPAGE_PGNO(p) (((u_int8_t *)p) + SSZ(HOFFPAGE, pgno)) -#define HOFFPAGE_TLEN(p) (((u_int8_t *)p) + SSZ(HOFFPAGE, tlen)) - -/* - * Page space required to add a new HOFFPAGE item to the page, with and - * without the index value. - */ -#define HOFFPAGE_SIZE (sizeof(HOFFPAGE)) -#define HOFFPAGE_PSIZE (HOFFPAGE_SIZE + sizeof(db_indx_t)) - -/* - * The fourth type is H_OFFDUP represented by the HOFFDUP structure: - */ -typedef struct _hoffdup { - u_int8_t type; /* 00: Page type and delete flag. */ - u_int8_t unused[3]; /* 01-03: Padding, unused. */ - db_pgno_t pgno; /* 04-07: Offpage page number. */ -} HOFFDUP; -#define HOFFDUP_PGNO(p) (((u_int8_t *)p) + SSZ(HOFFDUP, pgno)) - -/* - * Page space required to add a new HOFFDUP item to the page, with and - * without the index value. - */ -#define HOFFDUP_SIZE (sizeof(HOFFDUP)) -#define HOFFDUP_PSIZE (HOFFDUP_SIZE + sizeof(db_indx_t)) - -/************************************************************************ - BTREE PAGE LAYOUT - ************************************************************************/ - -/* Each index references a group of bytes on the page. */ -#define B_KEYDATA 1 /* Key/data item. */ -#define B_DUPLICATE 2 /* Duplicate key/data item. */ -#define B_OVERFLOW 3 /* Overflow key/data item. */ - -/* - * We have to store a deleted entry flag in the page. The reason is complex, - * but the simple version is that we can't delete on-page items referenced by - * a cursor -- the return order of subsequent insertions might be wrong. The - * delete flag is an overload of the top bit of the type byte. - */ -#define B_DELETE (0x80) -#define B_DCLR(t) (t) &= ~B_DELETE -#define B_DSET(t) (t) |= B_DELETE -#define B_DISSET(t) ((t) & B_DELETE) - -#define B_TYPE(t) ((t) & ~B_DELETE) -#define B_TSET(t, type, deleted) { \ - (t) = (type); \ - if (deleted) \ - B_DSET(t); \ -} - -/* - * The first type is B_KEYDATA, represented by the BKEYDATA structure: - */ -typedef struct _bkeydata { - db_indx_t len; /* 00-01: Key/data item length. */ - u_int8_t type; /* 02: Page type AND DELETE FLAG. */ - u_int8_t data[1]; /* Variable length key/data item. */ -} BKEYDATA; - -/* Get a BKEYDATA item for a specific index. */ -#define GET_BKEYDATA(pg, indx) \ - ((BKEYDATA *)P_ENTRY(pg, indx)) - -/* - * Page space required to add a new BKEYDATA item to the page, with and - * without the index value. - */ -#define BKEYDATA_SIZE(len) \ - ALIGN((len) + SSZA(BKEYDATA, data), 4) -#define BKEYDATA_PSIZE(len) \ - (BKEYDATA_SIZE(len) + sizeof(db_indx_t)) - -/* - * The second and third types are B_DUPLICATE and B_OVERFLOW, represented - * by the BOVERFLOW structure. - */ -typedef struct _boverflow { - db_indx_t unused1; /* 00-01: Padding, unused. */ - u_int8_t type; /* 02: Page type AND DELETE FLAG. */ - u_int8_t unused2; /* 03: Padding, unused. */ - db_pgno_t pgno; /* 04-07: Next page number. */ - u_int32_t tlen; /* 08-11: Total length of item. */ -} BOVERFLOW; - -/* Get a BOVERFLOW item for a specific index. */ -#define GET_BOVERFLOW(pg, indx) \ - ((BOVERFLOW *)P_ENTRY(pg, indx)) - -/* - * Page space required to add a new BOVERFLOW item to the page, with and - * without the index value. - */ -#define BOVERFLOW_SIZE \ - ALIGN(sizeof(BOVERFLOW), 4) -#define BOVERFLOW_PSIZE \ - (BOVERFLOW_SIZE + sizeof(db_indx_t)) - -/* - * Btree leaf and hash page layouts group indices in sets of two, one - * for the key and one for the data. Everything else does it in sets - * of one to save space. I use the following macros so that it's real - * obvious what's going on... - */ -#define O_INDX 1 -#define P_INDX 2 - -/************************************************************************ - BTREE INTERNAL PAGE LAYOUT - ************************************************************************/ - -/* - * Btree internal entry. - */ -typedef struct _binternal { - db_indx_t len; /* 00-01: Key/data item length. */ - u_int8_t type; /* 02: Page type AND DELETE FLAG. */ - u_int8_t unused; /* 03: Padding, unused. */ - db_pgno_t pgno; /* 04-07: Page number of referenced page. */ - db_recno_t nrecs; /* 08-11: Subtree record count. */ - u_int8_t data[1]; /* Variable length key item. */ -} BINTERNAL; - -/* Get a BINTERNAL item for a specific index. */ -#define GET_BINTERNAL(pg, indx) \ - ((BINTERNAL *)P_ENTRY(pg, indx)) - -/* - * Page space required to add a new BINTERNAL item to the page, with and - * without the index value. - */ -#define BINTERNAL_SIZE(len) \ - ALIGN((len) + SSZA(BINTERNAL, data), 4) -#define BINTERNAL_PSIZE(len) \ - (BINTERNAL_SIZE(len) + sizeof(db_indx_t)) - -/************************************************************************ - RECNO INTERNAL PAGE LAYOUT - ************************************************************************/ - -/* - * The recno internal entry. - * - * XXX - * Why not fold this into the db_indx_t structure, it's fixed length? - */ -typedef struct _rinternal { - db_pgno_t pgno; /* 00-03: Page number of referenced page. */ - db_recno_t nrecs; /* 04-07: Subtree record count. */ -} RINTERNAL; - -/* Get a RINTERNAL item for a specific index. */ -#define GET_RINTERNAL(pg, indx) \ - ((RINTERNAL *)P_ENTRY(pg, indx)) - -/* - * Page space required to add a new RINTERNAL item to the page, with and - * without the index value. - */ -#define RINTERNAL_SIZE \ - ALIGN(sizeof(RINTERNAL), 4) -#define RINTERNAL_PSIZE \ - (RINTERNAL_SIZE + sizeof(db_indx_t)) -#endif /* _DB_PAGE_H_ */ diff --git a/db2/include/db_shash.h b/db2/include/db_shash.h deleted file mode 100644 index 35ade39..0000000 --- a/db2/include/db_shash.h +++ /dev/null @@ -1,106 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - * - * @(#)db_shash.h 10.3 (Sleepycat) 4/10/98 - */ - -/* Hash Headers */ -typedef SH_TAILQ_HEAD(hash_head) DB_HASHTAB; - -/* - * HASHLOOKUP -- - * - * Look up something in a shared memory hash table. The "elt" argument - * should be a key, and cmp_func must know how to compare a key to whatever - * structure it is that appears in the hash table. The comparison function - * cmp_func is called as: cmp_func(lookup_elt, table_elt); - * begin: address of the beginning of the hash table. - * type: the structure type of the elements that are linked in each bucket. - * field: the name of the field by which the "type" structures are linked. - * elt: the item for which we are searching in the hash table. - * result: the variable into which we'll store the element if we find it. - * nelems: the number of buckets in the hash table. - * hash_func: the hash function that operates on elements of the type of elt - * cmp_func: compare elements of the type of elt with those in the table (of - * type "type"). - * - * If the element is not in the hash table, this macro exits with result - * set to NULL. - */ -#define HASHLOOKUP(begin, type, field, elt, r, n, hash, cmp) do { \ - DB_HASHTAB *__bucket; \ - u_int32_t __ndx; \ - \ - __ndx = hash(elt) % (n); \ - __bucket = &begin[__ndx]; \ - for (r = SH_TAILQ_FIRST(__bucket, type); \ - r != NULL; r = SH_TAILQ_NEXT(r, field, type)) \ - if (cmp(elt, r)) \ - break; \ -} while(0) - -/* - * HASHINSERT -- - * - * Insert a new entry into the hash table. This assumes that lookup has - * failed; don't call it if you haven't already called HASHLOOKUP. - * begin: the beginning address of the hash table. - * type: the structure type of the elements that are linked in each bucket. - * field: the name of the field by which the "type" structures are linked. - * elt: the item to be inserted. - * nelems: the number of buckets in the hash table. - * hash_func: the hash function that operates on elements of the type of elt - */ -#define HASHINSERT(begin, type, field, elt, n, hash) do { \ - u_int32_t __ndx; \ - DB_HASHTAB *__bucket; \ - \ - __ndx = hash(elt) % (n); \ - __bucket = &begin[__ndx]; \ - SH_TAILQ_INSERT_HEAD(__bucket, elt, field, type); \ -} while(0) - -/* - * HASHREMOVE -- - * Remove the entry with a key == elt. - * begin: address of the beginning of the hash table. - * type: the structure type of the elements that are linked in each bucket. - * field: the name of the field by which the "type" structures are linked. - * elt: the item to be deleted. - * nelems: the number of buckets in the hash table. - * hash_func: the hash function that operates on elements of the type of elt - * cmp_func: compare elements of the type of elt with those in the table (of - * type "type"). - */ -#define HASHREMOVE(begin, type, field, elt, n, hash, cmp) { \ - u_int32_t __ndx; \ - DB_HASHTAB *__bucket; \ - SH_TAILQ_ENTRY *__entp; \ - \ - __ndx = hash(elt) % (n); \ - __bucket = &begin[__ndx]; \ - HASHLOOKUP(begin, type, field, elt, __entp, n, hash, cmp); \ - SH_TAILQ_REMOVE(__bucket, __entp, field, type); \ -} - -/* - * HASHREMOVE_EL -- - * Given the object "obj" in the table, remove it. - * begin: address of the beginning of the hash table. - * type: the structure type of the elements that are linked in each bucket. - * field: the name of the field by which the "type" structures are linked. - * obj: the object in the table that we with to delete. - * nelems: the number of buckets in the hash table. - * hash_func: the hash function that operates on elements of the type of elt - */ -#define HASHREMOVE_EL(begin, type, field, obj, n, hash) { \ - u_int32_t __ndx; \ - DB_HASHTAB *__bucket; \ - \ - __ndx = hash(obj) % (n); \ - __bucket = &begin[__ndx]; \ - SH_TAILQ_REMOVE(__bucket, obj, field, type); \ -} diff --git a/db2/include/db_swap.h b/db2/include/db_swap.h deleted file mode 100644 index 9f94ed7..0000000 --- a/db2/include/db_swap.h +++ /dev/null @@ -1,105 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. 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. - * - * @(#)db_swap.h 10.5 (Sleepycat) 4/10/98 - */ - -#ifndef _DB_SWAP_H_ -#define _DB_SWAP_H_ - -/* - * Little endian <==> big endian 32-bit swap macros. - * M_32_SWAP swap a memory location - * P_32_COPY copy potentially unaligned 4 byte quantities - * P_32_SWAP swap a referenced memory location - */ -#define M_32_SWAP(a) { \ - u_int32_t _tmp; \ - _tmp = a; \ - ((u_int8_t *)&a)[0] = ((u_int8_t *)&_tmp)[3]; \ - ((u_int8_t *)&a)[1] = ((u_int8_t *)&_tmp)[2]; \ - ((u_int8_t *)&a)[2] = ((u_int8_t *)&_tmp)[1]; \ - ((u_int8_t *)&a)[3] = ((u_int8_t *)&_tmp)[0]; \ -} -#define P_32_COPY(a, b) { \ - ((u_int8_t *)b)[0] = ((u_int8_t *)a)[0]; \ - ((u_int8_t *)b)[1] = ((u_int8_t *)a)[1]; \ - ((u_int8_t *)b)[2] = ((u_int8_t *)a)[2]; \ - ((u_int8_t *)b)[3] = ((u_int8_t *)a)[3]; \ -} -#define P_32_SWAP(a) { \ - u_int32_t _tmp; \ - P_32_COPY(a, &_tmp); \ - ((u_int8_t *)a)[0] = ((u_int8_t *)&_tmp)[3]; \ - ((u_int8_t *)a)[1] = ((u_int8_t *)&_tmp)[2]; \ - ((u_int8_t *)a)[2] = ((u_int8_t *)&_tmp)[1]; \ - ((u_int8_t *)a)[3] = ((u_int8_t *)&_tmp)[0]; \ -} - -/* - * Little endian <==> big endian 16-bit swap macros. - * M_16_SWAP swap a memory location - * P_16_COPY copy potentially unaligned 2 byte quantities - * P_16_SWAP swap a referenced memory location - */ -#define M_16_SWAP(a) { \ - u_int16_t _tmp; \ - _tmp = (u_int16_t)a; \ - ((u_int8_t *)&a)[0] = ((u_int8_t *)&_tmp)[1]; \ - ((u_int8_t *)&a)[1] = ((u_int8_t *)&_tmp)[0]; \ -} -#define P_16_COPY(a, b) { \ - ((u_int8_t *)b)[0] = ((u_int8_t *)a)[0]; \ - ((u_int8_t *)b)[1] = ((u_int8_t *)a)[1]; \ -} -#define P_16_SWAP(a) { \ - u_int16_t _tmp; \ - P_16_COPY(a, &_tmp); \ - ((u_int8_t *)a)[0] = ((u_int8_t *)&_tmp)[1]; \ - ((u_int8_t *)a)[1] = ((u_int8_t *)&_tmp)[0]; \ -} - -#define SWAP32(p) { \ - P_32_SWAP(p); \ - (p) += sizeof(u_int32_t); \ -} -#define SWAP16(p) { \ - P_16_SWAP(p); \ - (p) += sizeof(u_int16_t); \ -} -#endif /* !_DB_SWAP_H_ */ diff --git a/db2/include/hash.h b/db2/include/hash.h deleted file mode 100644 index 5d85a2a..0000000 --- a/db2/include/hash.h +++ /dev/null @@ -1,199 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994 - * Margo Seltzer. All rights reserved. - */ -/* - * Copyright (c) 1990, 1993, 1994 - * 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. - * - * @(#)hash.h 10.14 (Sleepycat) 10/4/98 - */ - -/* Cursor structure definitions. */ -typedef struct cursor_t { - DBC *dbc; - - /* Per-thread information */ - DB_LOCK hlock; /* Metadata page lock. */ - HASHHDR *hdr; /* Pointer to meta-data page. */ - PAGE *split_buf; /* Temporary buffer for splits. */ - struct __db_h_stat stats; /* Hash statistics. */ - - /* Hash cursor information */ - db_pgno_t bucket; /* Bucket we are traversing. */ - db_pgno_t lbucket; /* Bucket for which we are locked. */ - DB_LOCK lock; /* Lock held on the current bucket. */ - PAGE *pagep; /* The current page. */ - db_pgno_t pgno; /* Current page number. */ - db_indx_t bndx; /* Index within the current page. */ - PAGE *dpagep; /* Duplicate page pointer. */ - db_pgno_t dpgno; /* Duplicate page number. */ - db_indx_t dndx; /* Index within a duplicate set. */ - db_indx_t dup_off; /* Offset within a duplicate set. */ - db_indx_t dup_len; /* Length of current duplicate. */ - db_indx_t dup_tlen; /* Total length of duplicate entry. */ - u_int32_t seek_size; /* Number of bytes we need for add. */ - db_pgno_t seek_found_page;/* Page on which we can insert. */ - -#define H_DELETED 0x0001 /* Cursor item is deleted. */ -#define H_DUPONLY 0x0002 /* Dups only; do not change key. */ -#define H_EXPAND 0x0004 /* Table expanded. */ -#define H_ISDUP 0x0008 /* Cursor is within duplicate set. */ -#define H_NOMORE 0x0010 /* No more entries in bucket. */ -#define H_OK 0x0020 /* Request succeeded. */ -#define H_DIRTY 0x0040 /* Meta-data page needs to be written */ -#define H_ORIGINAL 0x0080 /* Bucket lock existed on entry. */ - u_int32_t flags; -} HASH_CURSOR; - -#define IS_VALID(C) ((C)->bucket != BUCKET_INVALID) - -#define SAVE_CURSOR(ORIG, COPY) { \ - F_SET((ORIG), H_ORIGINAL); \ - *(COPY) = *(ORIG); \ -} - -#define RESTORE_CURSOR(D, ORIG, COPY, RET) { \ - if ((RET) == 0) { \ - if ((ORIG)->dbc->txn == NULL && \ - (COPY)->lock != 0 && (ORIG)->lock != (COPY)->lock) \ - (void)lock_put((D)->dbenv->lk_info, (COPY)->lock); \ - } else { \ - if ((ORIG)->dbc->txn == NULL && \ - (ORIG)->lock != 0 && (ORIG)->lock != (COPY)->lock) \ - (void)lock_put((D)->dbenv->lk_info, (ORIG)->lock); \ - *ORIG = *COPY; \ - } \ -} - -/* - * More interface macros used to get/release the meta data page. - */ -#define GET_META(D, I, R) { \ - if (F_ISSET(D, DB_AM_LOCKING) && \ - !F_ISSET((I)->dbc, DBC_RECOVER)) { \ - (I)->dbc->lock.pgno = BUCKET_INVALID; \ - (R) = lock_get((D)->dbenv->lk_info, (I)->dbc->locker, \ - 0, &(I)->dbc->lock_dbt, DB_LOCK_READ, &(I)->hlock); \ - (R) = (R) < 0 ? EAGAIN : (R); \ - } \ - if ((R) == 0 && \ - ((R) = __ham_get_page(D, 0, (PAGE **)&((I)->hdr))) != 0 && \ - (I)->hlock != LOCK_INVALID) { \ - (void)lock_put((D)->dbenv->lk_info, (I)->hlock); \ - (I)->hlock = LOCK_INVALID; \ - } \ -} - -#define RELEASE_META(D, I) { \ - if ((I)->hdr) \ - (void)__ham_put_page(D, (PAGE *)(I)->hdr, \ - F_ISSET(I, H_DIRTY) ? 1 : 0); \ - (I)->hdr = NULL; \ - if (!F_ISSET((I)->dbc, DBC_RECOVER) && \ - (I)->dbc->txn == NULL && (I)->hlock) \ - (void)lock_put((D)->dbenv->lk_info, (I)->hlock); \ - (I)->hlock = LOCK_INVALID; \ - F_CLR(I, H_DIRTY); \ -} - -#define DIRTY_META(D, I, R) { \ - if (F_ISSET(D, DB_AM_LOCKING) && \ - !F_ISSET((I)->dbc, DBC_RECOVER)) { \ - DB_LOCK _tmp; \ - (I)->dbc->lock.pgno = BUCKET_INVALID; \ - if (((R) = lock_get((D)->dbenv->lk_info, \ - (I)->dbc->locker, 0, &(I)->dbc->lock_dbt, \ - DB_LOCK_WRITE, &_tmp)) == 0) \ - (R) = lock_put((D)->dbenv->lk_info, (I)->hlock);\ - else if ((R) < 0) \ - (R) = EAGAIN; \ - (I)->hlock = _tmp; \ - } \ - F_SET((I), H_DIRTY); \ -} - -/* Test string. */ -#define CHARKEY "%$sniglet^&" - -/* Overflow management */ -/* - * Overflow page numbers are allocated per split point. At each doubling of - * the table, we can allocate extra pages. We keep track of how many pages - * we've allocated at each point to calculate bucket to page number mapping. - */ -#define BUCKET_TO_PAGE(I, B) \ - ((B) + 1 + ((B) ? (I)->hdr->spares[__db_log2((B)+1)-1] : 0)) - -#define PGNO_OF(I, S, O) (BUCKET_TO_PAGE((I), (1 << (S)) - 1) + (O)) - -/* Constraints about number of pages and how much data goes on a page. */ - -#define MAX_PAGES(H) UINT32_T_MAX -#define MINFILL 4 -#define ISBIG(I, N) (((N) > ((I)->hdr->pagesize / MINFILL)) ? 1 : 0) - -/* Shorthands for accessing structure */ -#define NDX_INVALID 0xFFFF -#define BUCKET_INVALID 0xFFFFFFFF - -/* On page duplicates are stored as a string of size-data-size triples. */ -#define DUP_SIZE(len) ((len) + 2 * sizeof(db_indx_t)) - -/* Log messages types (these are subtypes within a record type) */ -#define PAIR_KEYMASK 0x1 -#define PAIR_DATAMASK 0x2 -#define PAIR_ISKEYBIG(N) (N & PAIR_KEYMASK) -#define PAIR_ISDATABIG(N) (N & PAIR_DATAMASK) -#define OPCODE_OF(N) (N & ~(PAIR_KEYMASK | PAIR_DATAMASK)) - -#define PUTPAIR 0x20 -#define DELPAIR 0x30 -#define PUTOVFL 0x40 -#define DELOVFL 0x50 -#define ALLOCPGNO 0x60 -#define DELPGNO 0x70 -#define SPLITOLD 0x80 -#define SPLITNEW 0x90 - -#include "hash_auto.h" -#include "hash_ext.h" -#include "db_am.h" -#include "common_ext.h" diff --git a/db2/include/hash_auto.h b/db2/include/hash_auto.h deleted file mode 100644 index 2b8aea8..0000000 --- a/db2/include/hash_auto.h +++ /dev/null @@ -1,132 +0,0 @@ -/* Do not edit: automatically built by dist/db_gen.sh. */ -#ifndef ham_AUTO_H -#define ham_AUTO_H - -#define DB_ham_insdel (DB_ham_BEGIN + 1) - -typedef struct _ham_insdel_args { - u_int32_t type; - DB_TXN *txnid; - DB_LSN prev_lsn; - u_int32_t opcode; - u_int32_t fileid; - db_pgno_t pgno; - u_int32_t ndx; - DB_LSN pagelsn; - DBT key; - DBT data; -} __ham_insdel_args; - - -#define DB_ham_newpage (DB_ham_BEGIN + 2) - -typedef struct _ham_newpage_args { - u_int32_t type; - DB_TXN *txnid; - DB_LSN prev_lsn; - u_int32_t opcode; - u_int32_t fileid; - db_pgno_t prev_pgno; - DB_LSN prevlsn; - db_pgno_t new_pgno; - DB_LSN pagelsn; - db_pgno_t next_pgno; - DB_LSN nextlsn; -} __ham_newpage_args; - - -#define DB_ham_splitmeta (DB_ham_BEGIN + 3) - -typedef struct _ham_splitmeta_args { - u_int32_t type; - DB_TXN *txnid; - DB_LSN prev_lsn; - u_int32_t fileid; - u_int32_t bucket; - u_int32_t ovflpoint; - u_int32_t spares; - DB_LSN metalsn; -} __ham_splitmeta_args; - - -#define DB_ham_splitdata (DB_ham_BEGIN + 4) - -typedef struct _ham_splitdata_args { - u_int32_t type; - DB_TXN *txnid; - DB_LSN prev_lsn; - u_int32_t fileid; - u_int32_t opcode; - db_pgno_t pgno; - DBT pageimage; - DB_LSN pagelsn; -} __ham_splitdata_args; - - -#define DB_ham_replace (DB_ham_BEGIN + 5) - -typedef struct _ham_replace_args { - u_int32_t type; - DB_TXN *txnid; - DB_LSN prev_lsn; - u_int32_t fileid; - db_pgno_t pgno; - u_int32_t ndx; - DB_LSN pagelsn; - int32_t off; - DBT olditem; - DBT newitem; - u_int32_t makedup; -} __ham_replace_args; - - -#define DB_ham_newpgno (DB_ham_BEGIN + 6) - -typedef struct _ham_newpgno_args { - u_int32_t type; - DB_TXN *txnid; - DB_LSN prev_lsn; - u_int32_t opcode; - u_int32_t fileid; - db_pgno_t pgno; - db_pgno_t free_pgno; - u_int32_t old_type; - db_pgno_t old_pgno; - u_int32_t new_type; - DB_LSN pagelsn; - DB_LSN metalsn; -} __ham_newpgno_args; - - -#define DB_ham_ovfl (DB_ham_BEGIN + 7) - -typedef struct _ham_ovfl_args { - u_int32_t type; - DB_TXN *txnid; - DB_LSN prev_lsn; - u_int32_t fileid; - db_pgno_t start_pgno; - u_int32_t npages; - db_pgno_t free_pgno; - u_int32_t ovflpoint; - DB_LSN metalsn; -} __ham_ovfl_args; - - -#define DB_ham_copypage (DB_ham_BEGIN + 8) - -typedef struct _ham_copypage_args { - u_int32_t type; - DB_TXN *txnid; - DB_LSN prev_lsn; - u_int32_t fileid; - db_pgno_t pgno; - DB_LSN pagelsn; - db_pgno_t next_pgno; - DB_LSN nextlsn; - db_pgno_t nnext_pgno; - DB_LSN nnextlsn; - DBT page; -} __ham_copypage_args; - -#endif diff --git a/db2/include/hash_ext.h b/db2/include/hash_ext.h deleted file mode 100644 index fe17dc7..0000000 --- a/db2/include/hash_ext.h +++ /dev/null @@ -1,130 +0,0 @@ -/* DO NOT EDIT: automatically built by dist/distrib. */ -#ifndef _hash_ext_h_ -#define _hash_ext_h_ -int __ham_open __P((DB *, DB_INFO *)); -int __ham_close __P((DB *)); -int __ham_c_init __P((DBC *)); -u_int32_t __ham_call_hash __P((HASH_CURSOR *, u_int8_t *, int32_t)); -int __ham_init_dbt __P((DBT *, u_int32_t, void **, u_int32_t *)); -void __ham_c_update - __P((HASH_CURSOR *, db_pgno_t, u_int32_t, int, int)); -int __ham_insdel_log - __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - u_int32_t, u_int32_t, db_pgno_t, u_int32_t, - DB_LSN *, const DBT *, const DBT *)); -int __ham_insdel_print - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __ham_insdel_read __P((void *, __ham_insdel_args **)); -int __ham_newpage_log - __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - u_int32_t, u_int32_t, db_pgno_t, DB_LSN *, - db_pgno_t, DB_LSN *, db_pgno_t, DB_LSN *)); -int __ham_newpage_print - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __ham_newpage_read __P((void *, __ham_newpage_args **)); -int __ham_splitmeta_log - __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - u_int32_t, u_int32_t, u_int32_t, u_int32_t, - DB_LSN *)); -int __ham_splitmeta_print - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __ham_splitmeta_read __P((void *, __ham_splitmeta_args **)); -int __ham_splitdata_log - __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - u_int32_t, u_int32_t, db_pgno_t, const DBT *, - DB_LSN *)); -int __ham_splitdata_print - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __ham_splitdata_read __P((void *, __ham_splitdata_args **)); -int __ham_replace_log - __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - u_int32_t, db_pgno_t, u_int32_t, DB_LSN *, - int32_t, const DBT *, const DBT *, u_int32_t)); -int __ham_replace_print - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __ham_replace_read __P((void *, __ham_replace_args **)); -int __ham_newpgno_log - __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - u_int32_t, u_int32_t, db_pgno_t, db_pgno_t, - u_int32_t, db_pgno_t, u_int32_t, DB_LSN *, - DB_LSN *)); -int __ham_newpgno_print - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __ham_newpgno_read __P((void *, __ham_newpgno_args **)); -int __ham_ovfl_log - __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - u_int32_t, db_pgno_t, u_int32_t, db_pgno_t, - u_int32_t, DB_LSN *)); -int __ham_ovfl_print - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __ham_ovfl_read __P((void *, __ham_ovfl_args **)); -int __ham_copypage_log - __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - u_int32_t, db_pgno_t, DB_LSN *, db_pgno_t, - DB_LSN *, db_pgno_t, DB_LSN *, const DBT *)); -int __ham_copypage_print - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __ham_copypage_read __P((void *, __ham_copypage_args **)); -int __ham_init_print __P((DB_ENV *)); -int __ham_init_recover __P((DB_ENV *)); -int __ham_pgin __P((db_pgno_t, void *, DBT *)); -int __ham_pgout __P((db_pgno_t, void *, DBT *)); -int __ham_mswap __P((void *)); -int __ham_add_dup __P((DBC *, DBT *, u_int32_t)); -void __ham_move_offpage __P((DBC *, PAGE *, u_int32_t, db_pgno_t)); -void __ham_dsearch __P((DBC *, DBT *, u_int32_t *, int *)); -u_int32_t __ham_func2 __P((const void *, u_int32_t)); -u_int32_t __ham_func3 __P((const void *, u_int32_t)); -u_int32_t __ham_func4 __P((const void *, u_int32_t)); -u_int32_t __ham_func5 __P((const void *, u_int32_t)); -int __ham_item __P((DBC *, db_lockmode_t)); -int __ham_item_reset __P((DBC *)); -void __ham_item_init __P((HASH_CURSOR *)); -int __ham_item_done __P((DBC *, int)); -int __ham_item_last __P((DBC *, db_lockmode_t)); -int __ham_item_first __P((DBC *, db_lockmode_t)); -int __ham_item_prev __P((DBC *, db_lockmode_t)); -int __ham_item_next __P((DBC *, db_lockmode_t)); -void __ham_putitem __P((PAGE *p, const DBT *, int)); -void __ham_reputpair - __P((PAGE *p, u_int32_t, u_int32_t, const DBT *, const DBT *)); -int __ham_del_pair __P((DBC *, int)); -int __ham_replpair __P((DBC *, DBT *, u_int32_t)); -void __ham_onpage_replace __P((PAGE *, size_t, u_int32_t, int32_t, - int32_t, DBT *)); -int __ham_split_page __P((DBC *, u_int32_t, u_int32_t)); -int __ham_add_el __P((DBC *, const DBT *, const DBT *, int)); -void __ham_copy_item __P((size_t, PAGE *, u_int32_t, PAGE *)); -int __ham_add_ovflpage __P((DBC *, PAGE *, int, PAGE **)); -int __ham_new_page __P((DB *, u_int32_t, u_int32_t, PAGE **)); -int __ham_del_page __P((DBC *, PAGE *)); -int __ham_put_page __P((DB *, PAGE *, int32_t)); -int __ham_dirty_page __P((DB *, PAGE *)); -int __ham_get_page __P((DB *, db_pgno_t, PAGE **)); -int __ham_overflow_page - __P((DBC *, u_int32_t, PAGE **)); -#ifdef DEBUG -db_pgno_t __bucket_to_page __P((HASH_CURSOR *, db_pgno_t)); -#endif -void __ham_init_ovflpages __P((DBC *)); -int __ham_get_cpage __P((DBC *, db_lockmode_t)); -int __ham_next_cpage __P((DBC *, db_pgno_t, int, u_int32_t)); -void __ham_dpair __P((DB *, PAGE *, u_int32_t)); -int __ham_insdel_recover - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __ham_newpage_recover - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __ham_replace_recover - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __ham_newpgno_recover - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __ham_splitmeta_recover - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __ham_splitdata_recover - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __ham_ovfl_recover - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __ham_copypage_recover - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __ham_stat __P((DB *, void *, void *(*)(size_t), u_int32_t)); -#endif /* _hash_ext_h_ */ diff --git a/db2/include/lock.h b/db2/include/lock.h deleted file mode 100644 index 13364ca..0000000 --- a/db2/include/lock.h +++ /dev/null @@ -1,197 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - * - * @(#)lock.h 10.17 (Sleepycat) 1/3/99 - */ - -typedef struct __db_lockobj DB_LOCKOBJ; - -#define DB_DEFAULT_LOCK_FILE "__db_lock.share" - -#ifndef DB_LOCK_DEFAULT_N -#define DB_LOCK_DEFAULT_N 5000 /* Default # of locks in region. */ -#endif - -/* - * The locker id space is divided between the transaction manager and the lock - * manager. Lockid's start at 0 and go to DB_LOCK_MAXID. Txn Id's start at - * DB_LOCK_MAXID + 1 and go up to TXN_INVALID. - */ -#define DB_LOCK_MAXID 0x7fffffff - -/* Check for region catastrophic shutdown. */ -#define LOCK_PANIC_CHECK(lt) { \ - if ((lt)->region->hdr.panic) \ - return (DB_RUNRECOVERY); \ -} - -/* - * The lock region consists of: - * The DB_LOCKREGION structure (sizeof(DB_LOCKREGION)). - * The conflict matrix of nmodes * nmodes bytes (nmodes * nmodes). - * The hash table for object lookup (hashsize * sizeof(DB_OBJ *)). - * The locks themselves (maxlocks * sizeof(struct __db_lock). - * The objects being locked (maxlocks * sizeof(DB_OBJ)). - * String space to represent the DBTs that are the objects being locked. - */ -struct __db_lockregion { - RLAYOUT hdr; /* Shared region header. */ - u_int32_t magic; /* lock magic number */ - u_int32_t version; /* version number */ - u_int32_t id; /* unique id generator */ - u_int32_t need_dd; /* flag for deadlock detector */ - u_int32_t detect; /* run dd on every conflict */ - SH_TAILQ_HEAD(lock_header) free_locks; /* free lock header */ - SH_TAILQ_HEAD(obj_header) free_objs; /* free obj header */ - u_int32_t maxlocks; /* maximum number of locks in table */ - u_int32_t table_size; /* size of hash table */ - u_int32_t nmodes; /* number of lock modes */ - u_int32_t numobjs; /* number of objects */ - u_int32_t nlockers; /* number of lockers */ - size_t increment; /* how much to grow region */ - size_t hash_off; /* offset of hash table */ - size_t mem_off; /* offset of memory region */ - size_t mem_bytes; /* number of bytes in memory region */ - u_int32_t nconflicts; /* number of lock conflicts */ - u_int32_t nrequests; /* number of lock gets */ - u_int32_t nreleases; /* number of lock puts */ - u_int32_t ndeadlocks; /* number of deadlocks */ -}; - -/* Macros to lock/unlock the region. */ -#define LOCK_LOCKREGION(lt) \ - (void)__db_mutex_lock(&(lt)->region->hdr.lock, (lt)->reginfo.fd) -#define UNLOCK_LOCKREGION(lt) \ - (void)__db_mutex_unlock(&(lt)->region->hdr.lock, (lt)->reginfo.fd) - -/* - * Since we will be keeping DBTs in shared memory, we need the equivalent - * of a DBT that will work in shared memory. - */ -typedef struct __sh_dbt { - u_int32_t size; - ssize_t off; -} SH_DBT; - -#define SH_DBT_PTR(p) ((void *)(((u_int8_t *)(p)) + (p)->off)) - -struct __db_lockobj { - SH_DBT lockobj; /* Identifies object locked. */ - SH_TAILQ_ENTRY links; /* Links for free list. */ - union { - SH_TAILQ_HEAD(_wait) _waiters; /* List of waiting locks. */ - u_int32_t _dd_id; /* Deadlock detector id. */ - } wlinks; - union { - SH_LIST_HEAD(_held) _heldby; /* Locks held by this locker. */ - SH_TAILQ_HEAD(_hold) _holders; /* List of held locks. */ - } dlinks; -#define DB_LOCK_OBJTYPE 1 -#define DB_LOCK_LOCKER 2 - /* Allocate room in the object to - * hold typical DB lock structures - * so that we do not have to - * allocate them from shalloc. */ - u_int8_t objdata[sizeof(struct __db_ilock)]; - u_int8_t type; /* Real object or locker id. */ -}; - -#define dd_id wlinks._dd_id -#define waiters wlinks._waiters -#define holders dlinks._holders -#define heldby dlinks._heldby - -/* - * The lock table is the per-process cookie returned from a lock_open call. - */ -struct __db_locktab { - DB_ENV *dbenv; /* Environment. */ - REGINFO reginfo; /* Region information. */ - DB_LOCKREGION *region; /* Address of shared memory region. */ - DB_HASHTAB *hashtab; /* Beginning of hash table. */ - void *mem; /* Beginning of string space. */ - u_int8_t *conflicts; /* Pointer to conflict matrix. */ -}; - -/* Test for conflicts. */ -#define CONFLICTS(T, HELD, WANTED) \ - T->conflicts[HELD * T->region->nmodes + WANTED] - -/* - * Resources in the lock region. Used to indicate which resource - * is running low when we need to grow the region. - */ -typedef enum { - DB_LOCK_MEM, DB_LOCK_OBJ, DB_LOCK_LOCK -} db_resource_t; - -struct __db_lock { - /* - * Wait on mutex to wait on lock. You reference your own mutex with - * ID 0 and others reference your mutex with ID 1. - */ - db_mutex_t mutex; - - u_int32_t holder; /* Who holds this lock. */ - SH_TAILQ_ENTRY links; /* Free or holder/waiter list. */ - SH_LIST_ENTRY locker_links; /* List of locks held by a locker. */ - u_int32_t refcount; /* Reference count the lock. */ - db_lockmode_t mode; /* What sort of lock. */ - ssize_t obj; /* Relative offset of object struct. */ - size_t txnoff; /* Offset of holding transaction. */ - db_status_t status; /* Status of this lock. */ -}; - -/* - * This is a serious layering violation. To support nested transactions, we - * need to be able to tell that a lock is held by a transaction (as opposed to - * some other locker) and to be able to traverse the parent/descendent chain. - * In order to do this, each lock held by a transaction maintains a reference - * to the shared memory transaction structure so it can be accessed during lock - * promotion. As the structure is in shared memory, we cannot store a pointer - * to it, so we use the offset within the region. As nothing lives at region - * offset 0, we use that to indicate that there is no transaction associated - * with the current lock. - */ -#define TXN_IS_HOLDING(L) ((L)->txnoff != 0 /* INVALID_REG_OFFSET */) - -/* - * We cannot return pointers to the user (else we cannot easily grow regions), - * so we return offsets in the region. These must be converted to and from - * regular pointers. Always use the macros below. - */ -#define OFFSET_TO_LOCK(lt, off) \ - ((struct __db_lock *)((u_int8_t *)((lt)->region) + (off))) -#define LOCK_TO_OFFSET(lt, lock) \ - ((size_t)((u_int8_t *)(lock) - (u_int8_t *)lt->region)) -#define OFFSET_TO_OBJ(lt, off) \ - ((DB_LOCKOBJ *)((u_int8_t *)((lt)->region) + (off))) -#define OBJ_TO_OFFSET(lt, obj) \ - ((size_t)((u_int8_t *)(obj) - (u_int8_t *)lt->region)) - -/* - * The lock header contains the region structure and the conflict matrix. - * Aligned to a large boundary because we don't know what the underlying - * type of the hash table elements are. - */ -#define LOCK_HASH_ALIGN 8 -#define LOCK_HEADER_SIZE(M) \ - ((size_t)(sizeof(DB_LOCKREGION) + ALIGN((M * M), LOCK_HASH_ALIGN))) - -/* - * For the full region, we need to add the locks, the objects, the hash table - * and the string space (which is 16 bytes per lock). - */ -#define STRING_SIZE(N) (16 * N) - -#define LOCK_REGION_SIZE(M, N, H) \ - (ALIGN(LOCK_HEADER_SIZE(M) + \ - (H) * sizeof(DB_HASHTAB), MUTEX_ALIGNMENT) + \ - (N) * ALIGN(sizeof(struct __db_lock), MUTEX_ALIGNMENT) + \ - ALIGN((N) * sizeof(DB_LOCKOBJ), sizeof(size_t)) + \ - ALIGN(STRING_SIZE(N), sizeof(size_t))) - -#include "lock_ext.h" diff --git a/db2/include/lock_ext.h b/db2/include/lock_ext.h deleted file mode 100644 index ce79947..0000000 --- a/db2/include/lock_ext.h +++ /dev/null @@ -1,20 +0,0 @@ -/* DO NOT EDIT: automatically built by dist/distrib. */ -#ifndef _lock_ext_h_ -#define _lock_ext_h_ -int __lock_is_locked - __P((DB_LOCKTAB *, u_int32_t, DBT *, db_lockmode_t)); -void __lock_printlock __P((DB_LOCKTAB *, struct __db_lock *, int)); -int __lock_getobj __P((DB_LOCKTAB *, - u_int32_t, const DBT *, u_int32_t type, DB_LOCKOBJ **)); -int __lock_downgrade __P((DB_LOCKTAB *, - DB_LOCK, db_lockmode_t, u_int32_t)); -void __lock_panic __P((DB_ENV *)); -int __lock_validate_region __P((DB_LOCKTAB *)); -int __lock_grow_region __P((DB_LOCKTAB *, int, size_t)); -void __lock_dump_region __P((DB_LOCKTAB *, char *, FILE *)); -int __lock_cmp __P((const DBT *, DB_LOCKOBJ *)); -int __lock_locker_cmp __P((u_int32_t, DB_LOCKOBJ *)); -u_int32_t __lock_ohash __P((const DBT *)); -u_int32_t __lock_lhash __P((DB_LOCKOBJ *)); -u_int32_t __lock_locker_hash __P((u_int32_t)); -#endif /* _lock_ext_h_ */ diff --git a/db2/include/log.h b/db2/include/log.h deleted file mode 100644 index 5030908..0000000 --- a/db2/include/log.h +++ /dev/null @@ -1,204 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - * - * @(#)log.h 10.30 (Sleepycat) 10/11/98 - */ - -#ifndef _LOG_H_ -#define _LOG_H_ - -struct __fname; typedef struct __fname FNAME; -struct __hdr; typedef struct __hdr HDR; -struct __log; typedef struct __log LOG; -struct __log_persist; typedef struct __log_persist LOGP; - -#ifndef MAXLFNAME -#define LFPREFIX "log." /* Log file name prefix. */ -#define LFNAME "log.%010d" /* Log file name template. */ -#define LFNAME_V1 "log.%05d" /* Log file name template, rev 1. */ -#define MAXLFNAME 2000000000 /* Maximum log file name. */ -#endif - /* Default log name. */ -#define DB_DEFAULT_LOG_FILE "__db_log.share" - -#define DEFAULT_MAX (10 * MEGABYTE) /* 10 Mb. */ - -/* Macros to lock/unlock the region and threads. */ -#define LOCK_LOGTHREAD(dblp) \ - if (F_ISSET(dblp, DB_AM_THREAD)) \ - (void)__db_mutex_lock((dblp)->mutexp, -1) -#define UNLOCK_LOGTHREAD(dblp) \ - if (F_ISSET(dblp, DB_AM_THREAD)) \ - (void)__db_mutex_unlock((dblp)->mutexp, -1); -#define LOCK_LOGREGION(dblp) \ - (void)__db_mutex_lock(&((RLAYOUT *)(dblp)->lp)->lock, \ - (dblp)->reginfo.fd) -#define UNLOCK_LOGREGION(dblp) \ - (void)__db_mutex_unlock(&((RLAYOUT *)(dblp)->lp)->lock, \ - (dblp)->reginfo.fd) - -/* Check for region catastrophic shutdown. */ -#define LOG_PANIC_CHECK(dblp) { \ - if ((dblp)->lp->rlayout.panic) \ - return (DB_RUNRECOVERY); \ -} - -/* - * The per-process table that maps log file-id's to DB structures. - */ -typedef struct __db_entry { - DB *dbp; /* Associated DB structure. */ - u_int32_t refcount; /* Reference counted. */ - int deleted; /* File was not found during open. */ -} DB_ENTRY; - -/* - * DB_LOG - * Per-process log structure. - */ -struct __db_log { -/* These fields need to be protected for multi-threaded support. */ - db_mutex_t *mutexp; /* Mutex for thread protection. */ - - DB_ENTRY *dbentry; /* Recovery file-id mapping. */ -#define DB_GROW_SIZE 64 - u_int32_t dbentry_cnt; /* Entries. Grows by DB_GROW_SIZE. */ - -/* - * These fields are always accessed while the region lock is held, so they do - * not have to be protected by the thread lock as well OR, they are only used - * when threads are not being used, i.e. most cursor operations are disallowed - * on threaded logs. - */ - u_int32_t lfname; /* Log file "name". */ - int lfd; /* Log file descriptor. */ - - DB_LSN c_lsn; /* Cursor: current LSN. */ - DBT c_dbt; /* Cursor: return DBT structure. */ - int c_fd; /* Cursor: file descriptor. */ - u_int32_t c_off; /* Cursor: previous record offset. */ - u_int32_t c_len; /* Cursor: current record length. */ - -/* These fields are not protected. */ - LOG *lp; /* Address of the shared LOG. */ - - DB_ENV *dbenv; /* Reference to error information. */ - REGINFO reginfo; /* Region information. */ - - void *addr; /* Address of shalloc() region. */ - - char *dir; /* Directory argument. */ - -/* - * These fields are used by XA; since XA forbids threaded execution, these - * do not have to be protected. - */ - void *xa_info; /* Committed transaction list that - * has to be carried between calls - * to xa_recover. */ - DB_LSN xa_lsn; /* Position of an XA recovery scan. */ - DB_LSN xa_first; /* LSN to which we need to roll back - for this XA recovery scan. */ - - /* - * !!! - * Currently used to hold: - * DB_AM_THREAD (a DB flag) - * DBC_RECOVER (a DBC flag) - * If they are ever the same bits, we're in serious trouble. - */ -#if DB_AM_THREAD == DBC_RECOVER - DB_AM_THREAD, DBC_RECOVER, FLAG MISMATCH -#endif - u_int32_t flags; -}; - -/* - * HDR -- - * Log record header. - */ -struct __hdr { - u_int32_t prev; /* Previous offset. */ - u_int32_t cksum; /* Current checksum. */ - u_int32_t len; /* Current length. */ -}; - -struct __log_persist { - u_int32_t magic; /* DB_LOGMAGIC */ - u_int32_t version; /* DB_LOGVERSION */ - - u_int32_t lg_max; /* Maximum file size. */ - int mode; /* Log file mode. */ -}; - -/* - * LOG -- - * Shared log region. One of these is allocated in shared memory, - * and describes the log. - */ -struct __log { - RLAYOUT rlayout; /* General region information. */ - - LOGP persist; /* Persistent information. */ - - SH_TAILQ_HEAD(__fq) fq; /* List of file names. */ - - /* - * The lsn LSN is the file offset that we're about to write and which - * we will return to the user. - */ - DB_LSN lsn; /* LSN at current file offset. */ - - /* - * The s_lsn LSN is the last LSN that we know is on disk, not just - * written, but synced. - */ - DB_LSN s_lsn; /* LSN of the last sync. */ - - u_int32_t len; /* Length of the last record. */ - - u_int32_t w_off; /* Current write offset in the file. */ - - DB_LSN chkpt_lsn; /* LSN of the last checkpoint. */ - time_t chkpt; /* Time of the last checkpoint. */ - - DB_LOG_STAT stat; /* Log statistics. */ - - /* - * The f_lsn LSN is the LSN (returned to the user) that "owns" the - * first byte of the buffer. If the record associated with the LSN - * spans buffers, it may not reflect the physical file location of - * the first byte of the buffer. - */ - DB_LSN f_lsn; /* LSN of first byte in the buffer. */ - size_t b_off; /* Current offset in the buffer. */ - u_int8_t buf[4 * 1024]; /* Log buffer. */ -}; - -/* - * FNAME -- - * File name and id. - */ -struct __fname { - SH_TAILQ_ENTRY q; /* File name queue. */ - - u_int16_t ref; /* Reference count. */ - - u_int32_t id; /* Logging file id. */ - DBTYPE s_type; /* Saved DB type. */ - - size_t name_off; /* Name offset. */ - u_int8_t ufid[DB_FILE_ID_LEN]; /* Unique file id. */ -}; - -/* File open/close register log record opcodes. */ -#define LOG_CHECKPOINT 1 /* Checkpoint: file name/id dump. */ -#define LOG_CLOSE 2 /* File close. */ -#define LOG_OPEN 3 /* File open. */ - -#include "log_auto.h" -#include "log_ext.h" -#endif /* _LOG_H_ */ diff --git a/db2/include/log_auto.h b/db2/include/log_auto.h deleted file mode 100644 index 5717e14..0000000 --- a/db2/include/log_auto.h +++ /dev/null @@ -1,18 +0,0 @@ -/* Do not edit: automatically built by dist/db_gen.sh. */ -#ifndef log_AUTO_H -#define log_AUTO_H - -#define DB_log_register (DB_log_BEGIN + 1) - -typedef struct _log_register_args { - u_int32_t type; - DB_TXN *txnid; - DB_LSN prev_lsn; - u_int32_t opcode; - DBT name; - DBT uid; - u_int32_t id; - DBTYPE ftype; -} __log_register_args; - -#endif diff --git a/db2/include/log_ext.h b/db2/include/log_ext.h deleted file mode 100644 index 842a3f4..0000000 --- a/db2/include/log_ext.h +++ /dev/null @@ -1,26 +0,0 @@ -/* DO NOT EDIT: automatically built by dist/distrib. */ -#ifndef _log_ext_h_ -#define _log_ext_h_ -void __log_panic __P((DB_ENV *)); -int __log_find __P((DB_LOG *, int, int *)); -int __log_valid __P((DB_LOG *, u_int32_t, int)); -int __log_register_log - __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - u_int32_t, const DBT *, const DBT *, u_int32_t, - DBTYPE)); -int __log_register_print - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __log_register_read __P((void *, __log_register_args **)); -int __log_init_print __P((DB_ENV *)); -int __log_init_recover __P((DB_ENV *)); -int __log_findckp __P((DB_LOG *, DB_LSN *)); -int __log_get __P((DB_LOG *, DB_LSN *, DBT *, u_int32_t, int)); -int __log_put __P((DB_LOG *, DB_LSN *, const DBT *, u_int32_t)); -int __log_name __P((DB_LOG *, u_int32_t, char **, int *, u_int32_t)); -int __log_register_recover - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __log_add_logid __P((DB_LOG *, DB *, u_int32_t)); -int __db_fileid_to_db __P((DB_LOG *, DB **, u_int32_t)); -void __log_close_files __P((DB_LOG *)); -void __log_rem_logid __P((DB_LOG *, u_int32_t)); -#endif /* _log_ext_h_ */ diff --git a/db2/include/mp.h b/db2/include/mp.h deleted file mode 100644 index 904bccf..0000000 --- a/db2/include/mp.h +++ /dev/null @@ -1,299 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - * - * @(#)mp.h 10.37 (Sleepycat) 1/1/99 - */ - -struct __bh; typedef struct __bh BH; -struct __db_mpreg; typedef struct __db_mpreg DB_MPREG; -struct __mpool; typedef struct __mpool MPOOL; -struct __mpoolfile; typedef struct __mpoolfile MPOOLFILE; - - /* Default mpool name. */ -#define DB_DEFAULT_MPOOL_FILE "__db_mpool.share" - -/* - * We default to 256K (32 8K pages) if the user doesn't specify, and - * require a minimum of 20K. - */ -#ifndef DB_CACHESIZE_DEF -#define DB_CACHESIZE_DEF (256 * 1024) -#endif -#define DB_CACHESIZE_MIN ( 20 * 1024) - -#define INVALID 0 /* Invalid shared memory offset. */ - -/* - * There are three ways we do locking in the mpool code: - * - * Locking a handle mutex to provide concurrency for DB_THREAD operations. - * Locking the region mutex to provide mutual exclusion while reading and - * writing structures in the shared region. - * Locking buffer header mutexes during I/O. - * - * The first will not be further described here. We use the shared mpool - * region lock to provide mutual exclusion while reading/modifying all of - * the data structures, including the buffer headers. We use a per-buffer - * header lock to wait on buffer I/O. The order of locking is as follows: - * - * Searching for a buffer: - * Acquire the region lock. - * Find the buffer header. - * Increment the reference count (guarantee the buffer stays). - * While the BH_LOCKED flag is set (I/O is going on) { - * Release the region lock. - * Explicitly yield the processor if it's not the first pass - * through this loop, otherwise, we can simply spin because - * we'll be simply switching between the two locks. - * Request the buffer lock. - * The I/O will complete... - * Acquire the buffer lock. - * Release the buffer lock. - * Acquire the region lock. - * } - * Return the buffer. - * - * Reading/writing a buffer: - * Acquire the region lock. - * Find/create the buffer header. - * If reading, increment the reference count (guarantee the buffer stays). - * Set the BH_LOCKED flag. - * Acquire the buffer lock (guaranteed not to block). - * Release the region lock. - * Do the I/O and/or initialize the buffer contents. - * Release the buffer lock. - * At this point, the buffer lock is available, but the logical - * operation (flagged by BH_LOCKED) is not yet completed. For - * this reason, among others, threads checking the BH_LOCKED flag - * must loop around their test. - * Acquire the region lock. - * Clear the BH_LOCKED flag. - * Release the region lock. - * Return/discard the buffer. - * - * Pointers to DB_MPOOL, MPOOL, DB_MPOOLFILE and MPOOLFILE structures are not - * reacquired when a region lock is reacquired because they couldn't have been - * closed/discarded and because they never move in memory. - */ -#define LOCKINIT(dbmp, mutexp) \ - if (F_ISSET(dbmp, MP_LOCKHANDLE | MP_LOCKREGION)) \ - (void)__db_mutex_init(mutexp, \ - MUTEX_LOCK_OFFSET((dbmp)->reginfo.addr, mutexp)) - -#define LOCKHANDLE(dbmp, mutexp) \ - if (F_ISSET(dbmp, MP_LOCKHANDLE)) \ - (void)__db_mutex_lock(mutexp, (dbmp)->reginfo.fd) -#define UNLOCKHANDLE(dbmp, mutexp) \ - if (F_ISSET(dbmp, MP_LOCKHANDLE)) \ - (void)__db_mutex_unlock(mutexp, (dbmp)->reginfo.fd) - -#define LOCKREGION(dbmp) \ - if (F_ISSET(dbmp, MP_LOCKREGION)) \ - (void)__db_mutex_lock(&((RLAYOUT *)(dbmp)->mp)->lock, \ - (dbmp)->reginfo.fd) -#define UNLOCKREGION(dbmp) \ - if (F_ISSET(dbmp, MP_LOCKREGION)) \ - (void)__db_mutex_unlock(&((RLAYOUT *)(dbmp)->mp)->lock, \ - (dbmp)->reginfo.fd) - -#define LOCKBUFFER(dbmp, bhp) \ - if (F_ISSET(dbmp, MP_LOCKREGION)) \ - (void)__db_mutex_lock(&(bhp)->mutex, (dbmp)->reginfo.fd) -#define UNLOCKBUFFER(dbmp, bhp) \ - if (F_ISSET(dbmp, MP_LOCKREGION)) \ - (void)__db_mutex_unlock(&(bhp)->mutex, (dbmp)->reginfo.fd) - -/* Check for region catastrophic shutdown. */ -#define MP_PANIC_CHECK(dbmp) { \ - if ((dbmp)->mp->rlayout.panic) \ - return (DB_RUNRECOVERY); \ -} - -/* - * DB_MPOOL -- - * Per-process memory pool structure. - */ -struct __db_mpool { -/* These fields need to be protected for multi-threaded support. */ - db_mutex_t *mutexp; /* Structure lock. */ - - /* List of pgin/pgout routines. */ - LIST_HEAD(__db_mpregh, __db_mpreg) dbregq; - - /* List of DB_MPOOLFILE's. */ - TAILQ_HEAD(__db_mpoolfileh, __db_mpoolfile) dbmfq; - -/* These fields are not protected. */ - DB_ENV *dbenv; /* Reference to error information. */ - REGINFO reginfo; /* Region information. */ - - MPOOL *mp; /* Address of the shared MPOOL. */ - - void *addr; /* Address of shalloc() region. */ - - DB_HASHTAB *htab; /* Hash table of bucket headers. */ - -#define MP_LOCKHANDLE 0x01 /* Threaded, lock handles and region. */ -#define MP_LOCKREGION 0x02 /* Concurrent access, lock region. */ - u_int32_t flags; -}; - -/* - * DB_MPREG -- - * DB_MPOOL registry of pgin/pgout functions. - */ -struct __db_mpreg { - LIST_ENTRY(__db_mpreg) q; /* Linked list. */ - - int ftype; /* File type. */ - /* Pgin, pgout routines. */ - int (DB_CALLBACK *pgin) __P((db_pgno_t, void *, DBT *)); - int (DB_CALLBACK *pgout) __P((db_pgno_t, void *, DBT *)); -}; - -/* - * DB_MPOOLFILE -- - * Per-process DB_MPOOLFILE information. - */ -struct __db_mpoolfile { -/* These fields need to be protected for multi-threaded support. */ - db_mutex_t *mutexp; /* Structure lock. */ - - int fd; /* Underlying file descriptor. */ - - u_int32_t ref; /* Reference count. */ - - /* - * !!! - * This field is a special case -- it's protected by the region lock - * NOT the thread lock. The reason for this is that we always have - * the region lock immediately before or after we modify the field, - * and we don't want to use the structure lock to protect it because - * then I/O (which is done with the structure lock held because of - * the race between the seek and write of the file descriptor) will - * block any other put/get calls using this DB_MPOOLFILE structure. - */ - u_int32_t pinref; /* Pinned block reference count. */ - -/* These fields are not protected. */ - TAILQ_ENTRY(__db_mpoolfile) q; /* Linked list of DB_MPOOLFILE's. */ - - DB_MPOOL *dbmp; /* Overlying DB_MPOOL. */ - MPOOLFILE *mfp; /* Underlying MPOOLFILE. */ - - void *addr; /* Address of mmap'd region. */ - size_t len; /* Length of mmap'd region. */ - -/* These fields need to be protected for multi-threaded support. */ -#define MP_READONLY 0x01 /* File is readonly. */ -#define MP_UPGRADE 0x02 /* File descriptor is readwrite. */ -#define MP_UPGRADE_FAIL 0x04 /* Upgrade wasn't possible. */ - u_int32_t flags; -}; - -/* - * MPOOL -- - * Shared memory pool region. One of these is allocated in shared - * memory, and describes the pool. - */ -struct __mpool { - RLAYOUT rlayout; /* General region information. */ - - SH_TAILQ_HEAD(__bhq) bhq; /* LRU list of buckets. */ - SH_TAILQ_HEAD(__bhfq) bhfq; /* Free buckets. */ - SH_TAILQ_HEAD(__mpfq) mpfq; /* List of MPOOLFILEs. */ - - /* - * We make the assumption that the early pages of the file are far - * more likely to be retrieved than the later pages, which means - * that the top bits are more interesting for hashing since they're - * less likely to collide. On the other hand, since 512 4K pages - * represents a 2MB file, only the bottom 9 bits of the page number - * are likely to be set. We XOR in the offset in the MPOOL of the - * MPOOLFILE that backs this particular page, since that should also - * be unique for the page. - */ -#define BUCKET(mp, mf_offset, pgno) \ - (((pgno) ^ ((mf_offset) << 9)) % (mp)->htab_buckets) - - size_t htab; /* Hash table offset. */ - size_t htab_buckets; /* Number of hash table entries. */ - - DB_LSN lsn; /* Maximum checkpoint LSN. */ - u_int32_t lsn_cnt; /* Checkpoint buffers left to write. */ - - DB_MPOOL_STAT stat; /* Global mpool statistics. */ - -#define MP_LSN_RETRY 0x01 /* Retry all BH_WRITE buffers. */ - u_int32_t flags; -}; - -/* - * MPOOLFILE -- - * Shared DB_MPOOLFILE information. - */ -struct __mpoolfile { - SH_TAILQ_ENTRY q; /* List of MPOOLFILEs */ - - u_int32_t ref; /* Reference count. */ - - int ftype; /* File type. */ - - int32_t lsn_off; /* Page's LSN offset. */ - u_int32_t clear_len; /* Bytes to clear on page create. */ - - size_t path_off; /* File name location. */ - size_t fileid_off; /* File identification location. */ - - size_t pgcookie_len; /* Pgin/pgout cookie length. */ - size_t pgcookie_off; /* Pgin/pgout cookie location. */ - - u_int32_t lsn_cnt; /* Checkpoint buffers left to write. */ - - db_pgno_t last_pgno; /* Last page in the file. */ - db_pgno_t orig_last_pgno; /* Original last page in the file. */ - -#define MP_CAN_MMAP 0x01 /* If the file can be mmap'd. */ -#define MP_TEMP 0x02 /* Backing file is a temporary. */ - u_int32_t flags; - - DB_MPOOL_FSTAT stat; /* Per-file mpool statistics. */ -}; - -/* - * BH -- - * Buffer header. - */ -struct __bh { - db_mutex_t mutex; /* Structure lock. */ - - u_int16_t ref; /* Reference count. */ - -#define BH_CALLPGIN 0x001 /* Page needs to be reworked... */ -#define BH_DIRTY 0x002 /* Page was modified. */ -#define BH_DISCARD 0x004 /* Page is useless. */ -#define BH_LOCKED 0x008 /* Page is locked (I/O in progress). */ -#define BH_TRASH 0x010 /* Page is garbage. */ -#define BH_WRITE 0x020 /* Page scheduled for writing. */ - u_int16_t flags; - - SH_TAILQ_ENTRY q; /* LRU queue. */ - SH_TAILQ_ENTRY hq; /* MPOOL hash bucket queue. */ - - db_pgno_t pgno; /* Underlying MPOOLFILE page number. */ - size_t mf_offset; /* Associated MPOOLFILE offset. */ - - /* - * !!! - * This array must be size_t aligned -- the DB access methods put PAGE - * and other structures into it, and expect to be able to access them - * directly. (We guarantee size_t alignment in the db_mpool(3) manual - * page as well.) - */ - u_int8_t buf[1]; /* Variable length data. */ -}; - -#include "mp_ext.h" diff --git a/db2/include/mp_ext.h b/db2/include/mp_ext.h deleted file mode 100644 index 8b46334..0000000 --- a/db2/include/mp_ext.h +++ /dev/null @@ -1,21 +0,0 @@ -/* DO NOT EDIT: automatically built by dist/distrib. */ -#ifndef _mp_ext_h_ -#define _mp_ext_h_ -int __memp_bhwrite - __P((DB_MPOOL *, MPOOLFILE *, BH *, int *, int *)); -int __memp_pgread __P((DB_MPOOLFILE *, BH *, int)); -int __memp_pgwrite __P((DB_MPOOLFILE *, BH *, int *, int *)); -int __memp_pg __P((DB_MPOOLFILE *, BH *, int)); -void __memp_bhfree __P((DB_MPOOL *, MPOOLFILE *, BH *, int)); -int __memp_fopen __P((DB_MPOOL *, MPOOLFILE *, const char *, - u_int32_t, int, size_t, int, DB_MPOOL_FINFO *, DB_MPOOLFILE **)); -void __memp_panic __P((DB_ENV *)); -char * __memp_fn __P((DB_MPOOLFILE *)); -char * __memp_fns __P((DB_MPOOL *, MPOOLFILE *)); -void __memp_dump_region __P((DB_MPOOL *, char *, FILE *)); -int __memp_reg_alloc __P((DB_MPOOL *, size_t, size_t *, void *)); -int __memp_alloc __P((DB_MPOOL *, size_t, size_t *, void *)); -int __memp_ropen - __P((DB_MPOOL *, const char *, size_t, int, int, u_int32_t)); -int __mp_xxx_fd __P((DB_MPOOLFILE *, int *)); -#endif /* _mp_ext_h_ */ diff --git a/db2/include/mutex_ext.h b/db2/include/mutex_ext.h deleted file mode 100644 index b48da5d..0000000 --- a/db2/include/mutex_ext.h +++ /dev/null @@ -1,7 +0,0 @@ -/* DO NOT EDIT: automatically built by dist/distrib. */ -#ifndef _mutex_ext_h_ -#define _mutex_ext_h_ -int __db_mutex_init __P((db_mutex_t *, u_int32_t)); -int __db_mutex_lock __P((db_mutex_t *, int)); -int __db_mutex_unlock __P((db_mutex_t *, int)); -#endif /* _mutex_ext_h_ */ diff --git a/db2/include/os.h b/db2/include/os.h deleted file mode 100644 index f173d1f..0000000 --- a/db2/include/os.h +++ /dev/null @@ -1,24 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1997, 1998 - * Sleepycat Software. All rights reserved. - * - * @(#)os.h 10.11 (Sleepycat) 10/12/98 - */ - -/* - * We group seek/write calls into a single function so that we can use - * pread(2)/pwrite(2) where they're available. - */ -#define DB_IO_READ 1 -#define DB_IO_WRITE 2 -typedef struct __io { - int fd_io; /* I/O file descriptor. */ - int fd_lock; /* Locking file descriptor. */ - db_mutex_t *mutexp; /* Mutex to lock. */ - size_t pagesize; /* Page size. */ - db_pgno_t pgno; /* Page number. */ - u_int8_t *buf; /* Buffer. */ - size_t bytes; /* Bytes read/written. */ -} DB_IO; diff --git a/db2/include/os_ext.h b/db2/include/os_ext.h deleted file mode 100644 index 3462109..0000000 --- a/db2/include/os_ext.h +++ /dev/null @@ -1,40 +0,0 @@ -/* DO NOT EDIT: automatically built by dist/distrib. */ -#ifndef _os_ext_h_ -#define _os_ext_h_ -int __os_abspath __P((const char *)); -int __os_strdup __P((const char *, void *)); -int __os_calloc __P((size_t, size_t, void *)); -int __os_malloc __P((size_t, void *(*)(size_t), void *)); -int __os_realloc __P((void *, size_t)); -void __os_free __P((void *, size_t)); -void __os_freestr __P((void *)); -int __os_dirlist __P((const char *, char ***, int *)); -void __os_dirfree __P((char **, int)); -int __os_fileid __P((DB_ENV *, const char *, int, u_int8_t *)); -int __os_fsync __P((int)); -int __db_mapanon_ok __P((int)); -int __db_mapinit __P((void)); -int __db_mapregion __P((char *, REGINFO *)); -int __db_unmapregion __P((REGINFO *)); -int __db_unlinkregion __P((char *, REGINFO *)); -int __db_mapfile __P((char *, int, size_t, int, void **)); -int __db_unmapfile __P((void *, size_t)); -u_int32_t __db_oflags __P((int)); -int __db_omode __P((const char *)); -int __db_open __P((const char *, u_int32_t, u_int32_t, int, int *)); -int __os_open __P((const char *, int, int, int *)); -int __os_close __P((int)); -char *__db_rpath __P((const char *)); -int __os_io __P((DB_IO *, int, ssize_t *)); -int __os_read __P((int, void *, size_t, ssize_t *)); -int __os_write __P((int, const void *, size_t, ssize_t *)); -int __os_seek __P((int, size_t, db_pgno_t, u_int32_t, int, int)); -int __os_sleep __P((u_long, u_long)); -int __os_spin __P((void)); -void __os_yield __P((u_long)); -int __os_exists __P((const char *, int *)); -int __os_ioinfo - __P((const char *, int, u_int32_t *, u_int32_t *, u_int32_t *)); -int __os_tmpdir __P((DB_ENV *, u_int32_t)); -int __os_unlink __P((const char *)); -#endif /* _os_ext_h_ */ diff --git a/db2/include/os_jump.h b/db2/include/os_jump.h deleted file mode 100644 index e2d577f..0000000 --- a/db2/include/os_jump.h +++ /dev/null @@ -1,40 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1997, 1998 - * Sleepycat Software. All rights reserved. - * - * @(#)os_jump.h 10.1 (Sleepycat) 10/17/98 - */ - -/* Calls which can be replaced by the application. */ -struct __db_jumptab { - int (*j_close) __P((int)); /* DB_FUNC_CLOSE */ - void (*j_dirfree) __P((char **, int)); /* DB_FUNC_DIRFREE */ - int (*j_dirlist) /* DB_FUNC_DIRLIST */ - __P((const char *, char ***, int *)); - int (*j_exists) /* DB_FUNC_EXISTS */ - __P((const char *, int *)); - void (*j_free) __P((void *)); /* DB_FUNC_FREE */ - int (*j_fsync) __P((int)); /* DB_FUNC_FSYNC */ - int (*j_ioinfo) __P((const char *, /* DB_FUNC_IOINFO */ - int, u_int32_t *, u_int32_t *, u_int32_t *)); - void *(*j_malloc) __P((size_t)); /* DB_FUNC_MALLOC */ - int (*j_map) /* DB_FUNC_MAP */ - __P((char *, int, size_t, int, int, int, void **)); - int (*j_open) /* DB_FUNC_OPEN */ - __P((const char *, int, ...)); - ssize_t (*j_read) __P((int, void *, size_t)); /* DB_FUNC_READ */ - void *(*j_realloc) __P((void *, size_t)); /* DB_FUNC_REALLOC */ - int (*j_runlink) __P((char *)); /* DB_FUNC_RUNLINK */ - int (*j_seek) /* DB_FUNC_SEEK */ - __P((int, size_t, db_pgno_t, u_int32_t, int, int)); - int (*j_sleep) __P((u_long, u_long)); /* DB_FUNC_SLEEP */ - int (*j_unlink) __P((const char *)); /* DB_FUNC_UNLINK */ - int (*j_unmap) __P((void *, size_t)); /* DB_FUNC_UNMAP */ - ssize_t (*j_write) /* DB_FUNC_WRITE */ - __P((int, const void *, size_t)); - int (*j_yield) __P((void)); /* DB_FUNC_YIELD */ -}; - -extern struct __db_jumptab __db_jump; diff --git a/db2/include/queue.h b/db2/include/queue.h deleted file mode 100644 index f606eb0..0000000 --- a/db2/include/queue.h +++ /dev/null @@ -1,275 +0,0 @@ -/* BSDI $Id$ */ - -/* - * Copyright (c) 1991, 1993 - * The Regents of the University of California. 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. - * - * @(#)queue.h 8.5 (Berkeley) 8/20/94 - */ - -#ifndef _SYS_QUEUE_H_ -#define _SYS_QUEUE_H_ - -/* - * This file defines three types of data structures: lists, tail queues, - * and circular queues. - * - * A list is headed by a single forward pointer (or an array of forward - * pointers for a hash table header). The elements are doubly linked - * so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before - * or after an existing element or at the head of the list. A list - * may only be traversed in the forward direction. - * - * A tail queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or - * after an existing element, at the head of the list, or at the end of - * the list. A tail queue may only be traversed in the forward direction. - * - * A circle queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or after - * an existing element, at the head of the list, or at the end of the list. - * A circle queue may be traversed in either direction, but has a more - * complex end of list detection. - * - * For details on the use of these macros, see the queue(3) manual page. - */ - -/* - * List definitions. - */ -#define LIST_HEAD(name, type) \ -struct name { \ - struct type *lh_first; /* first element */ \ -} - -#define LIST_ENTRY(type) \ -struct { \ - struct type *le_next; /* next element */ \ - struct type **le_prev; /* address of previous next element */ \ -} - -#define LIST_FIRST(head) ((head)->lh_first) -#define LIST_NEXT(elm, field) ((elm)->field.le_next) -#define LIST_END(head) NULL - -/* - * List functions. - */ -#define LIST_INIT(head) { \ - (head)->lh_first = NULL; \ -} - -#define LIST_INSERT_AFTER(listelm, elm, field) do { \ - if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ - (listelm)->field.le_next->field.le_prev = \ - &(elm)->field.le_next; \ - (listelm)->field.le_next = (elm); \ - (elm)->field.le_prev = &(listelm)->field.le_next; \ -} while (0) - -#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ - (elm)->field.le_prev = (listelm)->field.le_prev; \ - (elm)->field.le_next = (listelm); \ - *(listelm)->field.le_prev = (elm); \ - (listelm)->field.le_prev = &(elm)->field.le_next; \ -} while (0) - -#define LIST_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.le_next = (head)->lh_first) != NULL) \ - (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ - (head)->lh_first = (elm); \ - (elm)->field.le_prev = &(head)->lh_first; \ -} while (0) - -#define LIST_REMOVE(elm, field) do { \ - if ((elm)->field.le_next != NULL) \ - (elm)->field.le_next->field.le_prev = \ - (elm)->field.le_prev; \ - *(elm)->field.le_prev = (elm)->field.le_next; \ -} while (0) - -/* - * Tail queue definitions. - */ -#define TAILQ_HEAD(name, type) \ -struct name { \ - struct type *tqh_first; /* first element */ \ - struct type **tqh_last; /* addr of last next element */ \ -} - -#define TAILQ_ENTRY(type) \ -struct { \ - struct type *tqe_next; /* next element */ \ - struct type **tqe_prev; /* address of previous next element */ \ -} - -#define TAILQ_FIRST(head) ((head)->tqh_first) -#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) -#define TAILQ_END(head) NULL - -/* - * Tail queue functions. - */ -#define TAILQ_INIT(head) do { \ - (head)->tqh_first = NULL; \ - (head)->tqh_last = &(head)->tqh_first; \ -} while (0) - -#define TAILQ_INSERT_HEAD(head, elm, field) do { \ - if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ - (head)->tqh_first->field.tqe_prev = \ - &(elm)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm)->field.tqe_next; \ - (head)->tqh_first = (elm); \ - (elm)->field.tqe_prev = &(head)->tqh_first; \ -} while (0) - -#define TAILQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.tqe_next = NULL; \ - (elm)->field.tqe_prev = (head)->tqh_last; \ - *(head)->tqh_last = (elm); \ - (head)->tqh_last = &(elm)->field.tqe_next; \ -} while (0) - -#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ - if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ - (elm)->field.tqe_next->field.tqe_prev = \ - &(elm)->field.tqe_next; \ - else \ - (head)->tqh_last = &(elm)->field.tqe_next; \ - (listelm)->field.tqe_next = (elm); \ - (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ -} while (0) - -#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ - (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ - (elm)->field.tqe_next = (listelm); \ - *(listelm)->field.tqe_prev = (elm); \ - (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ -} while (0) - -#define TAILQ_REMOVE(head, elm, field) do { \ - if (((elm)->field.tqe_next) != NULL) \ - (elm)->field.tqe_next->field.tqe_prev = \ - (elm)->field.tqe_prev; \ - else \ - (head)->tqh_last = (elm)->field.tqe_prev; \ - *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ -} while (0) - -/* - * Circular queue definitions. - */ -#define CIRCLEQ_HEAD(name, type) \ -struct name { \ - struct type *cqh_first; /* first element */ \ - struct type *cqh_last; /* last element */ \ -} - -#define CIRCLEQ_ENTRY(type) \ -struct { \ - struct type *cqe_next; /* next element */ \ - struct type *cqe_prev; /* previous element */ \ -} - -#define CIRCLEQ_FIRST(head) ((head)->cqh_first) -#define CIRCLEQ_LAST(head) ((head)->cqh_last) -#define CIRCLEQ_END(head) ((void *)(head)) -#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) -#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) - -/* - * Circular queue functions. - */ -#define CIRCLEQ_INIT(head) do { \ - (head)->cqh_first = (void *)(head); \ - (head)->cqh_last = (void *)(head); \ -} while (0) - -#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ - (elm)->field.cqe_next = (listelm)->field.cqe_next; \ - (elm)->field.cqe_prev = (listelm); \ - if ((listelm)->field.cqe_next == (void *)(head)) \ - (head)->cqh_last = (elm); \ - else \ - (listelm)->field.cqe_next->field.cqe_prev = (elm); \ - (listelm)->field.cqe_next = (elm); \ -} while (0) - -#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ - (elm)->field.cqe_next = (listelm); \ - (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ - if ((listelm)->field.cqe_prev == (void *)(head)) \ - (head)->cqh_first = (elm); \ - else \ - (listelm)->field.cqe_prev->field.cqe_next = (elm); \ - (listelm)->field.cqe_prev = (elm); \ -} while (0) - -#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ - (elm)->field.cqe_next = (head)->cqh_first; \ - (elm)->field.cqe_prev = (void *)(head); \ - if ((head)->cqh_last == (void *)(head)) \ - (head)->cqh_last = (elm); \ - else \ - (head)->cqh_first->field.cqe_prev = (elm); \ - (head)->cqh_first = (elm); \ -} while (0) - -#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.cqe_next = (void *)(head); \ - (elm)->field.cqe_prev = (head)->cqh_last; \ - if ((head)->cqh_first == (void *)(head)) \ - (head)->cqh_first = (elm); \ - else \ - (head)->cqh_last->field.cqe_next = (elm); \ - (head)->cqh_last = (elm); \ -} while (0) - -#define CIRCLEQ_REMOVE(head, elm, field) do { \ - if ((elm)->field.cqe_next == (void *)(head)) \ - (head)->cqh_last = (elm)->field.cqe_prev; \ - else \ - (elm)->field.cqe_next->field.cqe_prev = \ - (elm)->field.cqe_prev; \ - if ((elm)->field.cqe_prev == (void *)(head)) \ - (head)->cqh_first = (elm)->field.cqe_next; \ - else \ - (elm)->field.cqe_prev->field.cqe_next = \ - (elm)->field.cqe_next; \ -} while (0) -#endif /* !_SYS_QUEUE_H_ */ diff --git a/db2/include/shqueue.h b/db2/include/shqueue.h deleted file mode 100644 index 00e5d76..0000000 --- a/db2/include/shqueue.h +++ /dev/null @@ -1,334 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - * - * @(#)shqueue.h 8.13 (Sleepycat) 4/10/98 - */ -#ifndef _SYS_SHQUEUE_H_ -#define _SYS_SHQUEUE_H_ - -/* - * This file defines three types of data structures: lists, tail queues, and - * circular queues, similarly to the include file <sys/queue.h>. - * - * The difference is that this set of macros can be used for structures that - * reside in shared memory that may be mapped at different addresses in each - * process. In most cases, the macros for shared structures exactly mirror - * the normal macros, although the macro calls require an additional type - * parameter, only used by the HEAD and ENTRY macros of the standard macros. - * - * For details on the use of these macros, see the queue(3) manual page. - */ - -/* - * Shared list definitions. - */ -#define SH_LIST_HEAD(name) \ -struct name { \ - ssize_t slh_first; /* first element */ \ -} - -#define SH_LIST_ENTRY \ -struct { \ - ssize_t sle_next; /* relative offset next element */ \ - ssize_t sle_prev; /* relative offset of prev element */ \ -} - -/* - * Shared list functions. Since we use relative offsets for pointers, - * 0 is a valid offset. Therefore, we use -1 to indicate end of list. - * The macros ending in "P" return pointers without checking for end - * of list, the others check for end of list and evaluate to either a - * pointer or NULL. - */ - -#define SH_LIST_FIRSTP(head, type) \ - ((struct type *)(((u_int8_t *)(head)) + (head)->slh_first)) - -#define SH_LIST_FIRST(head, type) \ - ((head)->slh_first == -1 ? NULL : \ - ((struct type *)(((u_int8_t *)(head)) + (head)->slh_first))) - -#define SH_LIST_NEXTP(elm, field, type) \ - ((struct type *)(((u_int8_t *)(elm)) + (elm)->field.sle_next)) - -#define SH_LIST_NEXT(elm, field, type) \ - ((elm)->field.sle_next == -1 ? NULL : \ - ((struct type *)(((u_int8_t *)(elm)) + (elm)->field.sle_next))) - -#define SH_LIST_PREV(elm, field) \ - ((ssize_t *)(((u_int8_t *)(elm)) + (elm)->field.sle_prev)) - -#define SH_PTR_TO_OFF(src, dest) \ - ((ssize_t)(((u_int8_t *)(dest)) - ((u_int8_t *)(src)))) - -#define SH_LIST_END(head) NULL - -/* - * Take the element's next pointer and calculate what the corresponding - * Prev pointer should be -- basically it is the negation plus the offset - * of the next field in the structure. - */ -#define SH_LIST_NEXT_TO_PREV(elm, field) \ - (-(elm)->field.sle_next + SH_PTR_TO_OFF(elm, &(elm)->field.sle_next)) - -#define SH_LIST_INIT(head) (head)->slh_first = -1 - -#define SH_LIST_INSERT_AFTER(listelm, elm, field, type) do { \ - if ((listelm)->field.sle_next != -1) { \ - (elm)->field.sle_next = SH_PTR_TO_OFF(elm, \ - SH_LIST_NEXTP(listelm, field, type)); \ - SH_LIST_NEXTP(listelm, field, type)->field.sle_prev = \ - SH_LIST_NEXT_TO_PREV(elm, field); \ - } else \ - (elm)->field.sle_next = -1; \ - (listelm)->field.sle_next = SH_PTR_TO_OFF(listelm, elm); \ - (elm)->field.sle_prev = SH_LIST_NEXT_TO_PREV(listelm, field); \ -} while (0) - -#define SH_LIST_INSERT_HEAD(head, elm, field, type) do { \ - if ((head)->slh_first != -1) { \ - (elm)->field.sle_next = \ - (head)->slh_first - SH_PTR_TO_OFF(head, elm); \ - SH_LIST_FIRSTP(head, type)->field.sle_prev = \ - SH_LIST_NEXT_TO_PREV(elm, field); \ - } else \ - (elm)->field.sle_next = -1; \ - (head)->slh_first = SH_PTR_TO_OFF(head, elm); \ - (elm)->field.sle_prev = SH_PTR_TO_OFF(elm, &(head)->slh_first); \ -} while (0) - -#define SH_LIST_REMOVE(elm, field, type) do { \ - if ((elm)->field.sle_next != -1) { \ - SH_LIST_NEXTP(elm, field, type)->field.sle_prev = \ - (elm)->field.sle_prev - (elm)->field.sle_next; \ - *SH_LIST_PREV(elm, field) += (elm)->field.sle_next; \ - } else \ - *SH_LIST_PREV(elm, field) = -1; \ -} while (0) - -/* - * Shared tail queue definitions. - */ -#define SH_TAILQ_HEAD(name) \ -struct name { \ - ssize_t stqh_first; /* relative offset of first element */ \ - ssize_t stqh_last; /* relative offset of last's next */ \ -} - -#define SH_TAILQ_ENTRY \ -struct { \ - ssize_t stqe_next; /* relative offset of next element */ \ - ssize_t stqe_prev; /* relative offset of prev's next */ \ -} - -/* - * Shared tail queue functions. - */ -#define SH_TAILQ_FIRSTP(head, type) \ - ((struct type *)((u_int8_t *)(head) + (head)->stqh_first)) - -#define SH_TAILQ_FIRST(head, type) \ - ((head)->stqh_first == -1 ? NULL : SH_TAILQ_FIRSTP(head, type)) - -#define SH_TAILQ_NEXTP(elm, field, type) \ - ((struct type *)((u_int8_t *)(elm) + (elm)->field.stqe_next)) - -#define SH_TAILQ_NEXT(elm, field, type) \ - ((elm)->field.stqe_next == -1 ? NULL : SH_TAILQ_NEXTP(elm, field, type)) - -#define SH_TAILQ_PREVP(elm, field) \ - ((ssize_t *)((u_int8_t *)(elm) + (elm)->field.stqe_prev)) - -#define SH_TAILQ_LAST(head) \ - ((ssize_t *)(((u_int8_t *)(head)) + (head)->stqh_last)) - -#define SH_TAILQ_NEXT_TO_PREV(elm, field) \ - (-(elm)->field.stqe_next + SH_PTR_TO_OFF(elm, &(elm)->field.stqe_next)) - -#define SH_TAILQ_END(head) NULL - -#define SH_TAILQ_INIT(head) { \ - (head)->stqh_first = -1; \ - (head)->stqh_last = SH_PTR_TO_OFF(head, &(head)->stqh_first); \ -} - -#define SH_TAILQ_INSERT_HEAD(head, elm, field, type) do { \ - if ((head)->stqh_first != -1) { \ - (elm)->field.stqe_next = \ - (head)->stqh_first - SH_PTR_TO_OFF(head, elm); \ - SH_TAILQ_FIRSTP(head, type)->field.stqe_prev = \ - SH_TAILQ_NEXT_TO_PREV(elm, field); \ - } else { \ - (elm)->field.stqe_next = -1; \ - (head)->stqh_last = \ - SH_PTR_TO_OFF(head, &(elm)->field.stqe_next); \ - } \ - (head)->stqh_first = SH_PTR_TO_OFF(head, elm); \ - (elm)->field.stqe_prev = \ - SH_PTR_TO_OFF(elm, &(head)->stqh_first); \ -} while (0) - -#define SH_TAILQ_INSERT_TAIL(head, elm, field) do { \ - (elm)->field.stqe_next = -1; \ - (elm)->field.stqe_prev = \ - -SH_PTR_TO_OFF(head, elm) + (head)->stqh_last; \ - if ((head)->stqh_last == \ - SH_PTR_TO_OFF((head), &(head)->stqh_first)) \ - (head)->stqh_first = SH_PTR_TO_OFF(head, elm); \ - else \ - *SH_TAILQ_LAST(head) = -(head)->stqh_last + \ - SH_PTR_TO_OFF((elm), &(elm)->field.stqe_next) + \ - SH_PTR_TO_OFF(head, elm); \ - (head)->stqh_last = \ - SH_PTR_TO_OFF(head, &((elm)->field.stqe_next)); \ -} while (0) - -#define SH_TAILQ_INSERT_AFTER(head, listelm, elm, field, type) do { \ - if ((listelm)->field.stqe_next != -1) { \ - (elm)->field.stqe_next = (listelm)->field.stqe_next - \ - SH_PTR_TO_OFF(listelm, elm); \ - SH_TAILQ_NEXTP(listelm, field, type)->field.stqe_prev = \ - SH_TAILQ_NEXT_TO_PREV(elm, field); \ - } else { \ - (elm)->field.stqe_next = -1; \ - (head)->stqh_last = \ - SH_PTR_TO_OFF(head, &elm->field.stqe_next); \ - } \ - (listelm)->field.stqe_next = SH_PTR_TO_OFF(listelm, elm); \ - (elm)->field.stqe_prev = SH_TAILQ_NEXT_TO_PREV(listelm, field); \ -} while (0) - -#define SH_TAILQ_REMOVE(head, elm, field, type) do { \ - if ((elm)->field.stqe_next != -1) { \ - SH_TAILQ_NEXTP(elm, field, type)->field.stqe_prev = \ - (elm)->field.stqe_prev + \ - SH_PTR_TO_OFF(SH_TAILQ_NEXTP(elm, \ - field, type), elm); \ - *SH_TAILQ_PREVP(elm, field) += elm->field.stqe_next; \ - } else { \ - (head)->stqh_last = (elm)->field.stqe_prev + \ - SH_PTR_TO_OFF(head, elm); \ - *SH_TAILQ_PREVP(elm, field) = -1; \ - } \ -} while (0) - -/* - * Shared circular queue definitions. - */ -#define SH_CIRCLEQ_HEAD(name) \ -struct name { \ - ssize_t scqh_first; /* first element */ \ - ssize_t scqh_last; /* last element */ \ -} - -#define SH_CIRCLEQ_ENTRY \ -struct { \ - ssize_t scqe_next; /* next element */ \ - ssize_t scqe_prev; /* previous element */ \ -} - -/* - * Shared circular queue functions. - */ -#define SH_CIRCLEQ_FIRSTP(head, type) \ - ((struct type *)(((u_int8_t *)(head)) + (head)->scqh_first)) - -#define SH_CIRCLEQ_FIRST(head, type) \ - ((head)->scqh_first == -1 ? \ - (void *)head : SH_CIRCLEQ_FIRSTP(head, type)) - -#define SH_CIRCLEQ_LASTP(head, type) \ - ((struct type *)(((u_int8_t *)(head)) + (head)->scqh_last)) - -#define SH_CIRCLEQ_LAST(head, type) \ - ((head)->scqh_last == -1 ? (void *)head : SH_CIRCLEQ_LASTP(head, type)) - -#define SH_CIRCLEQ_NEXTP(elm, field, type) \ - ((struct type *)(((u_int8_t *)(elm)) + (elm)->field.scqe_next)) - -#define SH_CIRCLEQ_NEXT(head, elm, field, type) \ - ((elm)->field.scqe_next == SH_PTR_TO_OFF(elm, head) ? \ - (void *)head : SH_CIRCLEQ_NEXTP(elm, field, type)) - -#define SH_CIRCLEQ_PREVP(elm, field, type) \ - ((struct type *)(((u_int8_t *)(elm)) + (elm)->field.scqe_prev)) - -#define SH_CIRCLEQ_PREV(head, elm, field, type) \ - ((elm)->field.scqe_prev == SH_PTR_TO_OFF(elm, head) ? \ - (void *)head : SH_CIRCLEQ_PREVP(elm, field, type)) - -#define SH_CIRCLEQ_END(head) ((void *)(head)) - -#define SH_CIRCLEQ_INIT(head) { \ - (head)->scqh_first = 0; \ - (head)->scqh_last = 0; \ -} - -#define SH_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field, type) do { \ - (elm)->field.scqe_prev = SH_PTR_TO_OFF(elm, listelm); \ - (elm)->field.scqe_next = (listelm)->field.scqe_next + \ - (elm)->field.scqe_prev; \ - if (SH_CIRCLEQ_NEXTP(listelm, field, type) == (void *)head) \ - (head)->scqh_last = SH_PTR_TO_OFF(head, elm); \ - else \ - SH_CIRCLEQ_NEXTP(listelm, \ - field, type)->field.scqe_prev = \ - SH_PTR_TO_OFF(SH_CIRCLEQ_NEXTP(listelm, \ - field, type), elm); \ - (listelm)->field.scqe_next = -(elm)->field.scqe_prev; \ -} while (0) - -#define SH_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field, type) do { \ - (elm)->field.scqe_next = SH_PTR_TO_OFF(elm, listelm); \ - (elm)->field.scqe_prev = (elm)->field.scqe_next - \ - SH_CIRCLEQ_PREVP(listelm, field, type)->field.scqe_next;\ - if (SH_CIRCLEQ_PREVP(listelm, field, type) == (void *)(head)) \ - (head)->scqh_first = SH_PTR_TO_OFF(head, elm); \ - else \ - SH_CIRCLEQ_PREVP(listelm, \ - field, type)->field.scqe_next = \ - SH_PTR_TO_OFF(SH_CIRCLEQ_PREVP(listelm, \ - field, type), elm); \ - (listelm)->field.scqe_prev = -(elm)->field.scqe_next; \ -} while (0) - -#define SH_CIRCLEQ_INSERT_HEAD(head, elm, field, type) do { \ - (elm)->field.scqe_prev = SH_PTR_TO_OFF(elm, head); \ - (elm)->field.scqe_next = (head)->scqh_first + \ - (elm)->field.scqe_prev; \ - if ((head)->scqh_last == 0) \ - (head)->scqh_last = -(elm)->field.scqe_prev; \ - else \ - SH_CIRCLEQ_FIRSTP(head, type)->field.scqe_prev = \ - SH_PTR_TO_OFF(SH_CIRCLEQ_FIRSTP(head, type), elm); \ - (head)->scqh_first = -(elm)->field.scqe_prev; \ -} while (0) - -#define SH_CIRCLEQ_INSERT_TAIL(head, elm, field, type) do { \ - (elm)->field.scqe_next = SH_PTR_TO_OFF(elm, head); \ - (elm)->field.scqe_prev = (head)->scqh_last + \ - (elm)->field.scqe_next; \ - if ((head)->scqh_first == 0) \ - (head)->scqh_first = -(elm)->field.scqe_next; \ - else \ - SH_CIRCLEQ_LASTP(head, type)->field.scqe_next = \ - SH_PTR_TO_OFF(SH_CIRCLEQ_LASTP(head, type), elm); \ - (head)->scqh_last = -(elm)->field.scqe_next; \ -} while (0) - -#define SH_CIRCLEQ_REMOVE(head, elm, field, type) do { \ - if (SH_CIRCLEQ_NEXTP(elm, field, type) == (void *)(head)) \ - (head)->scqh_last += (elm)->field.scqe_prev; \ - else \ - SH_CIRCLEQ_NEXTP(elm, field, type)->field.scqe_prev += \ - (elm)->field.scqe_prev; \ - if (SH_CIRCLEQ_PREVP(elm, field, type) == (void *)(head)) \ - (head)->scqh_first += (elm)->field.scqe_next; \ - else \ - SH_CIRCLEQ_PREVP(elm, field, type)->field.scqe_next += \ - (elm)->field.scqe_next; \ -} while (0) -#endif /* !_SYS_SHQUEUE_H_ */ diff --git a/db2/include/txn.h b/db2/include/txn.h deleted file mode 100644 index a6fa4db..0000000 --- a/db2/include/txn.h +++ /dev/null @@ -1,148 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - * - * @(#)txn.h 10.18 (Sleepycat) 1/3/99 - */ -#ifndef _TXN_H_ -#define _TXN_H_ - -#include "xa.h" - -/* - * The name of the transaction shared memory region is DEFAULT_TXN_FILE and - * the region is always created group RW of the group owning the directory. - */ -#define DEFAULT_TXN_FILE "__db_txn.share" -/* TXN_MINIMUM = (DB_LOCK_MAXID + 1) but this makes compilers complain. */ -#define TXN_MINIMUM 0x80000000 -#define TXN_INVALID 0xffffffff /* Maximum number of txn ids. */ - -/* - * Transaction type declarations. - */ - -/* - * Internal data maintained in shared memory for each transaction. - */ -typedef char DB_XID[XIDDATASIZE]; - -typedef struct __txn_detail { - u_int32_t txnid; /* current transaction id - used to link free list also */ - DB_LSN last_lsn; /* last lsn written for this txn */ - DB_LSN begin_lsn; /* lsn of begin record */ - size_t last_lock; /* offset in lock region of last lock - for this transaction. */ - size_t parent; /* Offset of transaction's parent. */ -#define TXN_UNALLOC 0 -#define TXN_RUNNING 1 -#define TXN_ABORTED 2 -#define TXN_PREPARED 3 -#define TXN_COMMITTED 4 - u_int32_t status; /* status of the transaction */ - SH_TAILQ_ENTRY links; /* free/active list */ - -#define TXN_XA_ABORTED 1 -#define TXN_XA_DEADLOCKED 2 -#define TXN_XA_ENDED 3 -#define TXN_XA_PREPARED 4 -#define TXN_XA_STARTED 5 -#define TXN_XA_SUSPENDED 6 - u_int32_t xa_status; /* XA status */ - - /* - * XID (xid_t) structure: because these fields are logged, the - * sizes have to be explicit. - */ - DB_XID xid; /* XA global transaction id */ - u_int32_t bqual; /* bqual_length from XID */ - u_int32_t gtrid; /* gtrid_length from XID */ - int32_t format; /* XA format */ -} TXN_DETAIL; - -/* - * The transaction manager encapsulates the transaction system. It contains - * references to the log and lock managers as well as the state that keeps - * track of the shared memory region. - */ -struct __db_txnmgr { -/* These fields need to be protected for multi-threaded support. */ - db_mutex_t *mutexp; /* Synchronization. */ - /* list of active transactions */ - TAILQ_HEAD(_chain, __db_txn) txn_chain; - -/* These fields are not protected. */ - REGINFO reginfo; /* Region information. */ - DB_ENV *dbenv; /* Environment. */ - int (*recover) /* Recovery dispatch routine */ - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - u_int32_t flags; /* DB_TXN_NOSYNC, DB_THREAD */ - DB_TXNREGION *region; /* address of shared memory region */ - void *mem; /* address of the shalloc space */ -}; - -/* - * Layout of the shared memory region. - * The region consists of a DB_TXNREGION structure followed by a large - * pool of shalloc'd memory which is used to hold TXN_DETAIL structures - * and thread mutexes (which are dynamically allocated). - */ -struct __db_txnregion { - RLAYOUT hdr; /* Shared memory region header. */ - u_int32_t magic; /* transaction magic number */ - u_int32_t version; /* version number */ - u_int32_t maxtxns; /* maximum number of active txns */ - u_int32_t last_txnid; /* last transaction id given out */ - DB_LSN pending_ckp; /* last checkpoint did not finish */ - DB_LSN last_ckp; /* lsn of the last checkpoint */ - time_t time_ckp; /* time of last checkpoint */ - u_int32_t logtype; /* type of logging */ - u_int32_t locktype; /* lock type */ - u_int32_t naborts; /* number of aborted transactions */ - u_int32_t ncommits; /* number of committed transactions */ - u_int32_t nbegins; /* number of begun transactions */ - SH_TAILQ_HEAD(_active) active_txn; /* active transaction list */ -}; - -/* - * Make the region large enough to hold N transaction detail structures - * plus some space to hold thread handles and the beginning of the shalloc - * region. - */ -#define TXN_REGION_SIZE(N) \ - (sizeof(DB_TXNREGION) + N * sizeof(TXN_DETAIL) + 1000) - -/* Macros to lock/unlock the region and threads. */ -#define LOCK_TXNTHREAD(tmgrp) \ - if (F_ISSET(tmgrp, DB_THREAD)) \ - (void)__db_mutex_lock((tmgrp)->mutexp, -1) -#define UNLOCK_TXNTHREAD(tmgrp) \ - if (F_ISSET(tmgrp, DB_THREAD)) \ - (void)__db_mutex_unlock((tmgrp)->mutexp, -1) - -#define LOCK_TXNREGION(tmgrp) \ - (void)__db_mutex_lock(&(tmgrp)->region->hdr.lock, (tmgrp)->reginfo.fd) -#define UNLOCK_TXNREGION(tmgrp) \ - (void)__db_mutex_unlock(&(tmgrp)->region->hdr.lock, (tmgrp)->reginfo.fd) - -/* Check for region catastrophic shutdown. */ -#define TXN_PANIC_CHECK(tmgrp) { \ - if ((tmgrp)->region->hdr.panic) \ - return (DB_RUNRECOVERY); \ -} - -/* - * Log record types. - */ -#define TXN_COMMIT 1 -#define TXN_PREPARE 2 -#define TXN_CHECKPOINT 3 - -#include "txn_auto.h" -#include "txn_ext.h" - -#include "xa_ext.h" -#endif /* !_TXN_H_ */ diff --git a/db2/include/txn_auto.h b/db2/include/txn_auto.h deleted file mode 100644 index bb3de4e..0000000 --- a/db2/include/txn_auto.h +++ /dev/null @@ -1,51 +0,0 @@ -/* Do not edit: automatically built by dist/db_gen.sh. */ -#ifndef txn_AUTO_H -#define txn_AUTO_H - -#define DB_txn_regop (DB_txn_BEGIN + 1) - -typedef struct _txn_regop_args { - u_int32_t type; - DB_TXN *txnid; - DB_LSN prev_lsn; - u_int32_t opcode; -} __txn_regop_args; - - -#define DB_txn_ckp (DB_txn_BEGIN + 2) - -typedef struct _txn_ckp_args { - u_int32_t type; - DB_TXN *txnid; - DB_LSN prev_lsn; - DB_LSN ckp_lsn; - DB_LSN last_ckp; -} __txn_ckp_args; - - -#define DB_txn_xa_regop (DB_txn_BEGIN + 3) - -typedef struct _txn_xa_regop_args { - u_int32_t type; - DB_TXN *txnid; - DB_LSN prev_lsn; - u_int32_t opcode; - DBT xid; - int32_t formatID; - u_int32_t gtrid; - u_int32_t bqual; - DB_LSN begin_lsn; -} __txn_xa_regop_args; - - -#define DB_txn_child (DB_txn_BEGIN + 4) - -typedef struct _txn_child_args { - u_int32_t type; - DB_TXN *txnid; - DB_LSN prev_lsn; - u_int32_t opcode; - u_int32_t parent; -} __txn_child_args; - -#endif diff --git a/db2/include/txn_ext.h b/db2/include/txn_ext.h deleted file mode 100644 index e0d69c3..0000000 --- a/db2/include/txn_ext.h +++ /dev/null @@ -1,41 +0,0 @@ -/* DO NOT EDIT: automatically built by dist/distrib. */ -#ifndef _txn_ext_h_ -#define _txn_ext_h_ -void __txn_panic __P((DB_ENV *)); -int __txn_xa_begin __P((DB_ENV *, DB_TXN *)); -int __txn_is_ancestor __P((DB_TXNMGR *, size_t, size_t)); -int __txn_regop_log - __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - u_int32_t)); -int __txn_regop_print - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __txn_regop_read __P((void *, __txn_regop_args **)); -int __txn_ckp_log - __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - DB_LSN *, DB_LSN *)); -int __txn_ckp_print - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __txn_ckp_read __P((void *, __txn_ckp_args **)); -int __txn_xa_regop_log - __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - u_int32_t, const DBT *, int32_t, u_int32_t, - u_int32_t, DB_LSN *)); -int __txn_xa_regop_print - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __txn_xa_regop_read __P((void *, __txn_xa_regop_args **)); -int __txn_child_log - __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - u_int32_t, u_int32_t)); -int __txn_child_print - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __txn_child_read __P((void *, __txn_child_args **)); -int __txn_init_print __P((DB_ENV *)); -int __txn_init_recover __P((DB_ENV *)); -int __txn_regop_recover - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __txn_xa_regop_recover - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __txn_ckp_recover __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -int __txn_child_recover - __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); -#endif /* _txn_ext_h_ */ diff --git a/db2/include/xa.h b/db2/include/xa.h deleted file mode 100644 index ae822f3..0000000 --- a/db2/include/xa.h +++ /dev/null @@ -1,179 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1998 - * Sleepycat Software. All rights reserved. - * - * @(#)xa.h 10.1 (Sleepycat) 6/22/98 - */ -/* - * Start of xa.h header - * - * Define a symbol to prevent multiple inclusions of this header file - */ -#ifndef XA_H -#define XA_H - -/* - * Transaction branch identification: XID and NULLXID: - */ -#define XIDDATASIZE 128 /* size in bytes */ -#define MAXGTRIDSIZE 64 /* maximum size in bytes of gtrid */ -#define MAXBQUALSIZE 64 /* maximum size in bytes of bqual */ - -struct xid_t { - long formatID; /* format identifier */ - long gtrid_length; /* value from 1 through 64 */ - long bqual_length; /* value from 1 through 64 */ - char data[XIDDATASIZE]; -}; -typedef struct xid_t XID; -/* - * A value of -1 in formatID means that the XID is null. - */ - -/* - * Declarations of routines by which RMs call TMs: - */ -extern int ax_reg __P((int, XID *, long)); -extern int ax_unreg __P((int, long)); - -/* - * XA Switch Data Structure - */ -#define RMNAMESZ 32 /* length of resource manager name, */ - /* including the null terminator */ -#define MAXINFOSIZE 256 /* maximum size in bytes of xa_info */ - /* strings, including the null - terminator */ -struct xa_switch_t { - char name[RMNAMESZ]; /* name of resource manager */ - long flags; /* resource manager specific options */ - long version; /* must be 0 */ - int (*xa_open_entry) /* xa_open function pointer */ - __P((char *, int, long)); - int (*xa_close_entry) /* xa_close function pointer */ - __P((char *, int, long)); - int (*xa_start_entry) /* xa_start function pointer */ - __P((XID *, int, long)); - int (*xa_end_entry) /* xa_end function pointer */ - __P((XID *, int, long)); - int (*xa_rollback_entry) /* xa_rollback function pointer */ - __P((XID *, int, long)); - int (*xa_prepare_entry) /* xa_prepare function pointer */ - __P((XID *, int, long)); - int (*xa_commit_entry) /* xa_commit function pointer */ - __P((XID *, int, long)); - int (*xa_recover_entry) /* xa_recover function pointer */ - __P((XID *, long, int, long)); - int (*xa_forget_entry) /* xa_forget function pointer */ - __P((XID *, int, long)); - int (*xa_complete_entry) /* xa_complete function pointer */ - __P((int *, int *, int, long)); -}; - -/* - * Flag definitions for the RM switch - */ -#define TMNOFLAGS 0x00000000L /* no resource manager features - selected */ -#define TMREGISTER 0x00000001L /* resource manager dynamically - registers */ -#define TMNOMIGRATE 0x00000002L /* resource manager does not support - association migration */ -#define TMUSEASYNC 0x00000004L /* resource manager supports - asynchronous operations */ -/* - * Flag definitions for xa_ and ax_ routines - */ -/* use TMNOFLAGGS, defined above, when not specifying other flags */ -#define TMASYNC 0x80000000L /* perform routine asynchronously */ -#define TMONEPHASE 0x40000000L /* caller is using one-phase commit - optimisation */ -#define TMFAIL 0x20000000L /* dissociates caller and marks - transaction branch rollback-only */ -#define TMNOWAIT 0x10000000L /* return if blocking condition - exists */ -#define TMRESUME 0x08000000L /* caller is resuming association with - suspended transaction branch */ -#define TMSUCCESS 0x04000000L /* dissociate caller from transaction - branch */ -#define TMSUSPEND 0x02000000L /* caller is suspending, not ending, - association */ -#define TMSTARTRSCAN 0x01000000L /* start a recovery scan */ -#define TMENDRSCAN 0x00800000L /* end a recovery scan */ -#define TMMULTIPLE 0x00400000L /* wait for any asynchronous - operation */ -#define TMJOIN 0x00200000L /* caller is joining existing - transaction branch */ -#define TMMIGRATE 0x00100000L /* caller intends to perform - migration */ - -/* - * ax_() return codes (transaction manager reports to resource manager) - */ -#define TM_JOIN 2 /* caller is joining existing - transaction branch */ -#define TM_RESUME 1 /* caller is resuming association with - suspended transaction branch */ -#define TM_OK 0 /* normal execution */ -#define TMER_TMERR -1 /* an error occurred in the transaction - manager */ -#define TMER_INVAL -2 /* invalid arguments were given */ -#define TMER_PROTO -3 /* routine invoked in an improper - context */ - -/* - * xa_() return codes (resource manager reports to transaction manager) - */ -#define XA_RBBASE 100 /* The inclusive lower bound of the - rollback codes */ -#define XA_RBROLLBACK XA_RBBASE /* The rollback was caused by an - unspecified reason */ -#define XA_RBCOMMFAIL XA_RBBASE+1 /* The rollback was caused by a - communication failure */ -#define XA_RBDEADLOCK XA_RBBASE+2 /* A deadlock was detected */ -#define XA_RBINTEGRITY XA_RBBASE+3 /* A condition that violates the - integrity of the resources was - detected */ -#define XA_RBOTHER XA_RBBASE+4 /* The resource manager rolled back the - transaction branch for a reason not - on this list */ -#define XA_RBPROTO XA_RBBASE+5 /* A protocol error occurred in the - resource manager */ -#define XA_RBTIMEOUT XA_RBBASE+6 /* A transaction branch took too long */ -#define XA_RBTRANSIENT XA_RBBASE+7 /* May retry the transaction branch */ -#define XA_RBEND XA_RBTRANSIENT /* The inclusive upper bound of the - rollback codes */ -#define XA_NOMIGRATE 9 /* resumption must occur where - suspension occurred */ -#define XA_HEURHAZ 8 /* the transaction branch may have - been heuristically completed */ -#define XA_HEURCOM 7 /* the transaction branch has been - heuristically committed */ -#define XA_HEURRB 6 /* the transaction branch has been - heuristically rolled back */ -#define XA_HEURMIX 5 /* the transaction branch has been - heuristically committed and rolled - back */ -#define XA_RETRY 4 /* routine returned with no effect and - may be re-issued */ -#define XA_RDONLY 3 /* the transaction branch was read-only - and has been committed */ -#define XA_OK 0 /* normal execution */ -#define XAER_ASYNC -2 /* asynchronous operation already - outstanding */ -#define XAER_RMERR -3 /* a resource manager error occurred in - the transaction branch */ -#define XAER_NOTA -4 /* the XID is not valid */ -#define XAER_INVAL -5 /* invalid arguments were given */ -#define XAER_PROTO -6 /* routine invoked in an improper - context */ -#define XAER_RMFAIL -7 /* resource manager unavailable */ -#define XAER_DUPID -8 /* the XID already exists */ -#define XAER_OUTSIDE -9 /* resource manager doing work outside - transaction */ -#endif /* ifndef XA_H */ -/* - * End of xa.h header - */ diff --git a/db2/include/xa_ext.h b/db2/include/xa_ext.h deleted file mode 100644 index 00369cc..0000000 --- a/db2/include/xa_ext.h +++ /dev/null @@ -1,13 +0,0 @@ -/* DO NOT EDIT: automatically built by dist/distrib. */ -#ifndef _xa_ext_h_ -#define _xa_ext_h_ -int __db_rmid_to_env __P((int rmid, DB_ENV **envp, int open_ok)); -int __db_xid_to_txn __P((DB_ENV *, XID *, size_t *)); -int __db_map_rmid __P((int, DB_ENV *)); -int __db_unmap_rmid __P((int)); -int __db_map_xid __P((DB_ENV *, XID *, size_t)); -void __db_unmap_xid __P((DB_ENV *, XID *, size_t)); -int __db_map_rmid_name __P((int, char *)); -int __db_rmid_to_name __P((int, char **)); - void __db_unmap_rmid_name __P((int)); -#endif /* _xa_ext_h_ */ diff --git a/db2/lock/lock.c b/db2/lock/lock.c deleted file mode 100644 index 4cf1d9e..0000000 --- a/db2/lock/lock.c +++ /dev/null @@ -1,1034 +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[] = "@(#)lock.c 10.61 (Sleepycat) 1/3/99"; -#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 "db_page.h" -#include "db_shash.h" -#include "lock.h" -#include "db_am.h" -#include "txn_auto.h" -#include "txn_ext.h" -#include "common_ext.h" - -static void __lock_checklocker __P((DB_LOCKTAB *, struct __db_lock *, int)); -static void __lock_freeobj __P((DB_LOCKTAB *, DB_LOCKOBJ *)); -static int __lock_get_internal __P((DB_LOCKTAB *, u_int32_t, DB_TXN *, - u_int32_t, const DBT *, db_lockmode_t, struct __db_lock **)); -static int __lock_is_parent __P((u_int32_t, DB_TXN *)); -static int __lock_promote __P((DB_LOCKTAB *, DB_LOCKOBJ *)); -static int __lock_put_internal __P((DB_LOCKTAB *, struct __db_lock *, int)); -static void __lock_remove_waiter - __P((DB_LOCKTAB *, DB_LOCKOBJ *, struct __db_lock *, db_status_t)); -static int __lock_vec_internal __P((DB_LOCKTAB *, u_int32_t, DB_TXN *, - u_int32_t, DB_LOCKREQ *, int, DB_LOCKREQ **elistp)); - -int -lock_id(lt, idp) - DB_LOCKTAB *lt; - u_int32_t *idp; -{ - u_int32_t id; - - LOCK_PANIC_CHECK(lt); - - LOCK_LOCKREGION(lt); - if (lt->region->id >= DB_LOCK_MAXID) - lt->region->id = 0; - id = ++lt->region->id; - UNLOCK_LOCKREGION(lt); - - *idp = id; - return (0); -} - -int -lock_vec(lt, locker, flags, list, nlist, elistp) - DB_LOCKTAB *lt; - u_int32_t locker, flags; - int nlist; - DB_LOCKREQ *list, **elistp; -{ - return (__lock_vec_internal(lt, - locker, NULL, flags, list, nlist, elistp)); -} - -int -lock_tvec(lt, txn, flags, list, nlist, elistp) - DB_LOCKTAB *lt; - DB_TXN *txn; - u_int32_t flags; - int nlist; - DB_LOCKREQ *list, **elistp; -{ - return (__lock_vec_internal(lt, - txn->txnid, txn, flags, list, nlist, elistp)); -} - -static int -__lock_vec_internal(lt, locker, txn, flags, list, nlist, elistp) - DB_LOCKTAB *lt; - u_int32_t locker; - DB_TXN *txn; - u_int32_t flags; - int nlist; - DB_LOCKREQ *list, **elistp; -{ - struct __db_lock *lp; - DB_LOCKOBJ *sh_obj, *sh_locker, *sh_parent; - int i, ret, run_dd; - - LOCK_PANIC_CHECK(lt); - - /* Validate arguments. */ - if ((ret = - __db_fchk(lt->dbenv, "lock_vec", flags, DB_LOCK_NOWAIT)) != 0) - return (ret); - - LOCK_LOCKREGION(lt); - - if ((ret = __lock_validate_region(lt)) != 0) { - UNLOCK_LOCKREGION(lt); - return (ret); - } - - ret = 0; - for (i = 0; i < nlist && ret == 0; i++) { - switch (list[i].op) { - case DB_LOCK_GET: - ret = __lock_get_internal(lt, locker, txn, flags, - list[i].obj, list[i].mode, &lp); - if (ret == 0) { - list[i].lock = LOCK_TO_OFFSET(lt, lp); - lt->region->nrequests++; - } - break; - case DB_LOCK_INHERIT: - /* Find the locker. */ - if ((ret = __lock_getobj(lt, locker, - NULL, DB_LOCK_LOCKER, &sh_locker)) != 0) - break; - if (txn == NULL || txn->parent == NULL) { - ret = EINVAL; - break; - } - - if ((ret = __lock_getobj(lt, txn->parent->txnid, - NULL, DB_LOCK_LOCKER, &sh_parent)) != 0) - break; - - /* - * Traverse all the locks held by this locker. Remove - * the locks from the locker's list and put them on the - * parent's list. - */ - for (lp = SH_LIST_FIRST(&sh_locker->heldby, __db_lock); - lp != NULL; - lp = SH_LIST_FIRST(&sh_locker->heldby, __db_lock)) { - SH_LIST_REMOVE(lp, locker_links, __db_lock); - SH_LIST_INSERT_HEAD(&sh_parent->heldby, lp, - locker_links, __db_lock); - lp->holder = txn->parent->txnid; - } - __lock_freeobj(lt, sh_locker); - lt->region->nlockers--; - break; - case DB_LOCK_PUT: - lp = OFFSET_TO_LOCK(lt, list[i].lock); - if (lp->holder != locker) { - ret = DB_LOCK_NOTHELD; - break; - } - list[i].mode = lp->mode; - - ret = __lock_put_internal(lt, lp, 0); - __lock_checklocker(lt, lp, 0); - break; - case DB_LOCK_PUT_ALL: - /* Find the locker. */ - if ((ret = __lock_getobj(lt, locker, - NULL, DB_LOCK_LOCKER, &sh_locker)) != 0) - break; - - for (lp = SH_LIST_FIRST(&sh_locker->heldby, __db_lock); - lp != NULL; - lp = SH_LIST_FIRST(&sh_locker->heldby, __db_lock)) { - if ((ret = __lock_put_internal(lt, lp, 1)) != 0) - break; - } - __lock_freeobj(lt, sh_locker); - lt->region->nlockers--; - break; - case DB_LOCK_PUT_OBJ: - - /* Look up the object in the hash table. */ - HASHLOOKUP(lt->hashtab, __db_lockobj, links, - list[i].obj, sh_obj, lt->region->table_size, - __lock_ohash, __lock_cmp); - if (sh_obj == NULL) { - ret = EINVAL; - break; - } - /* - * Release waiters first, because they won't cause - * anyone else to be awakened. If we release the - * lockers first, all the waiters get awakened - * needlessly. - */ - for (lp = SH_TAILQ_FIRST(&sh_obj->waiters, __db_lock); - lp != NULL; - lp = SH_TAILQ_FIRST(&sh_obj->waiters, __db_lock)) { - lt->region->nreleases += lp->refcount; - __lock_remove_waiter(lt, sh_obj, lp, - DB_LSTAT_NOGRANT); - __lock_checklocker(lt, lp, 1); - } - - for (lp = SH_TAILQ_FIRST(&sh_obj->holders, __db_lock); - lp != NULL; - lp = SH_TAILQ_FIRST(&sh_obj->holders, __db_lock)) { - - lt->region->nreleases += lp->refcount; - SH_LIST_REMOVE(lp, locker_links, __db_lock); - SH_TAILQ_REMOVE(&sh_obj->holders, lp, links, - __db_lock); - lp->status = DB_LSTAT_FREE; - SH_TAILQ_INSERT_HEAD(<->region->free_locks, - lp, links, __db_lock); - } - - /* Now free the object. */ - __lock_freeobj(lt, sh_obj); - break; -#ifdef DEBUG - case DB_LOCK_DUMP: - /* Find the locker. */ - if ((ret = __lock_getobj(lt, locker, - NULL, DB_LOCK_LOCKER, &sh_locker)) != 0) - break; - - for (lp = SH_LIST_FIRST(&sh_locker->heldby, __db_lock); - lp != NULL; - lp = SH_LIST_NEXT(lp, locker_links, __db_lock)) { - __lock_printlock(lt, lp, 1); - ret = EINVAL; - } - if (ret == 0) { - __lock_freeobj(lt, sh_locker); - lt->region->nlockers--; - } - break; -#endif - default: - ret = EINVAL; - break; - } - } - - if (lt->region->need_dd && lt->region->detect != DB_LOCK_NORUN) { - run_dd = 1; - lt->region->need_dd = 0; - } else - run_dd = 0; - - UNLOCK_LOCKREGION(lt); - - if (ret == 0 && run_dd) - lock_detect(lt, 0, lt->region->detect); - - if (elistp && ret != 0) - *elistp = &list[i - 1]; - return (ret); -} - -int -lock_get(lt, locker, flags, obj, lock_mode, lock) - DB_LOCKTAB *lt; - u_int32_t locker, flags; - const DBT *obj; - db_lockmode_t lock_mode; - DB_LOCK *lock; -{ - struct __db_lock *lockp; - int ret; - - LOCK_PANIC_CHECK(lt); - - /* Validate arguments. */ - if ((ret = __db_fchk(lt->dbenv, - "lock_get", flags, DB_LOCK_NOWAIT | DB_LOCK_UPGRADE)) != 0) - return (ret); - - LOCK_LOCKREGION(lt); - - if ((ret = __lock_validate_region(lt)) == 0) { - if (LF_ISSET(DB_LOCK_UPGRADE)) - lockp = OFFSET_TO_LOCK(lt, *lock); - - if ((ret = __lock_get_internal(lt, - locker, NULL, flags, obj, lock_mode, &lockp)) == 0) { - if (!LF_ISSET(DB_LOCK_UPGRADE)) - *lock = LOCK_TO_OFFSET(lt, lockp); - lt->region->nrequests++; - } - } - - UNLOCK_LOCKREGION(lt); - return (ret); -} - -int -lock_tget(lt, txn, flags, obj, lock_mode, lock) - DB_LOCKTAB *lt; - DB_TXN *txn; - u_int32_t flags; - const DBT *obj; - db_lockmode_t lock_mode; - DB_LOCK *lock; -{ - struct __db_lock *lockp; - int ret; - - LOCK_PANIC_CHECK(lt); - - /* Validate arguments. */ - if ((ret = __db_fchk(lt->dbenv, - "lock_get", flags, DB_LOCK_NOWAIT | DB_LOCK_UPGRADE)) != 0) - return (ret); - - LOCK_LOCKREGION(lt); - - if ((ret = __lock_validate_region(lt)) == 0) { - if (LF_ISSET(DB_LOCK_UPGRADE)) - lockp = OFFSET_TO_LOCK(lt, *lock); - - if ((ret = __lock_get_internal(lt, - txn->txnid, txn, flags, obj, lock_mode, &lockp)) == 0) { - if (!LF_ISSET(DB_LOCK_UPGRADE)) - *lock = LOCK_TO_OFFSET(lt, lockp); - lt->region->nrequests++; - } - } - - UNLOCK_LOCKREGION(lt); - return (ret); -} -int -lock_put(lt, lock) - DB_LOCKTAB *lt; - DB_LOCK lock; -{ - struct __db_lock *lockp; - int ret, run_dd; - - LOCK_PANIC_CHECK(lt); - - LOCK_LOCKREGION(lt); - - if ((ret = __lock_validate_region(lt)) != 0) - return (ret); - else { - lockp = OFFSET_TO_LOCK(lt, lock); - ret = __lock_put_internal(lt, lockp, 0); - } - - __lock_checklocker(lt, lockp, 0); - - if (lt->region->need_dd && lt->region->detect != DB_LOCK_NORUN) { - run_dd = 1; - lt->region->need_dd = 0; - } else - run_dd = 0; - - UNLOCK_LOCKREGION(lt); - - if (ret == 0 && run_dd) - lock_detect(lt, 0, lt->region->detect); - - return (ret); -} - -static int -__lock_put_internal(lt, lockp, do_all) - DB_LOCKTAB *lt; - struct __db_lock *lockp; - int do_all; -{ - DB_LOCKOBJ *sh_obj; - int state_changed; - - if (lockp->refcount == 0 || (lockp->status != DB_LSTAT_HELD && - lockp->status != DB_LSTAT_WAITING) || lockp->obj == 0) { - __db_err(lt->dbenv, "lock_put: invalid lock %lu", - (u_long)((u_int8_t *)lockp - (u_int8_t *)lt->region)); - return (EINVAL); - } - - if (do_all) - lt->region->nreleases += lockp->refcount; - else - lt->region->nreleases++; - if (do_all == 0 && lockp->refcount > 1) { - lockp->refcount--; - return (0); - } - - /* Get the object associated with this lock. */ - sh_obj = (DB_LOCKOBJ *)((u_int8_t *)lockp + lockp->obj); - - /* Remove lock from locker list. */ - SH_LIST_REMOVE(lockp, locker_links, __db_lock); - - /* Remove this lock from its holders/waitlist. */ - if (lockp->status != DB_LSTAT_HELD) - __lock_remove_waiter(lt, sh_obj, lockp, DB_LSTAT_FREE); - else - SH_TAILQ_REMOVE(&sh_obj->holders, lockp, links, __db_lock); - - state_changed = __lock_promote(lt, sh_obj); - - /* Check if object should be reclaimed. */ - if (SH_TAILQ_FIRST(&sh_obj->holders, __db_lock) == NULL) { - HASHREMOVE_EL(lt->hashtab, __db_lockobj, - links, sh_obj, lt->region->table_size, __lock_lhash); - if (sh_obj->lockobj.size > sizeof(sh_obj->objdata)) - __db_shalloc_free(lt->mem, - SH_DBT_PTR(&sh_obj->lockobj)); - SH_TAILQ_INSERT_HEAD(<->region->free_objs, sh_obj, links, - __db_lockobj); - state_changed = 1; - } - - /* Free lock. */ - lockp->status = DB_LSTAT_FREE; - SH_TAILQ_INSERT_HEAD(<->region->free_locks, lockp, links, __db_lock); - - /* - * If we did not promote anyone; we need to run the deadlock - * detector again. - */ - if (state_changed == 0) - lt->region->need_dd = 1; - - return (0); -} - -static int -__lock_get_internal(lt, locker, txn, flags, obj, lock_mode, lockp) - DB_LOCKTAB *lt; - u_int32_t locker, flags; - DB_TXN *txn; - const DBT *obj; - db_lockmode_t lock_mode; - struct __db_lock **lockp; -{ - struct __db_lock *newl, *lp; - DB_LOCKOBJ *sh_obj, *sh_locker; - DB_LOCKREGION *lrp; - size_t newl_off; - int ihold, no_dd, ret; - - no_dd = ret = 0; - - /* - * Check that lock mode is valid. - */ - lrp = lt->region; - if ((u_int32_t)lock_mode >= lrp->nmodes) { - __db_err(lt->dbenv, - "lock_get: invalid lock mode %lu\n", (u_long)lock_mode); - return (EINVAL); - } - - /* Allocate a new lock. Optimize for the common case of a grant. */ - if ((newl = SH_TAILQ_FIRST(&lrp->free_locks, __db_lock)) == NULL) { - if ((ret = __lock_grow_region(lt, DB_LOCK_LOCK, 0)) != 0) - return (ret); - lrp = lt->region; - newl = SH_TAILQ_FIRST(&lrp->free_locks, __db_lock); - } - newl_off = LOCK_TO_OFFSET(lt, newl); - - /* Optimize for common case of granting a lock. */ - SH_TAILQ_REMOVE(&lrp->free_locks, newl, links, __db_lock); - - newl->mode = lock_mode; - newl->status = DB_LSTAT_HELD; - newl->holder = locker; - newl->refcount = 1; - - if ((ret = __lock_getobj(lt, 0, obj, DB_LOCK_OBJTYPE, &sh_obj)) != 0) - return (ret); - - lrp = lt->region; /* getobj might have grown */ - newl = OFFSET_TO_LOCK(lt, newl_off); - - /* Now make new lock point to object */ - newl->obj = SH_PTR_TO_OFF(newl, sh_obj); - - /* - * Now we have a lock and an object and we need to see if we should - * grant the lock. We use a FIFO ordering so we can only grant a - * new lock if it does not conflict with anyone on the holders list - * OR anyone on the waiters list. The reason that we don't grant if - * there's a conflict is that this can lead to starvation (a writer - * waiting on a popularly read item will never be granted). The - * downside of this is that a waiting reader can prevent an upgrade - * from reader to writer, which is not uncommon. - * - * There is one exception to the no-conflict rule. If a lock is held - * by the requesting locker AND the new lock does not conflict with - * any other holders, then we grant the lock. The most common place - * this happens is when the holder has a WRITE lock and a READ lock - * request comes in for the same locker. If we do not grant the read - * lock, then we guarantee deadlock. - * - * In case of conflict, we put the new lock on the end of the waiters - * list, unless we are upgrading in which case the locker goes on the - * front of the list. - */ - ihold = 0; - for (lp = SH_TAILQ_FIRST(&sh_obj->holders, __db_lock); - lp != NULL; - lp = SH_TAILQ_NEXT(lp, links, __db_lock)) { - if (locker == lp->holder || - __lock_is_parent(lp->holder, txn)) { - if (lp->mode == lock_mode && - lp->status == DB_LSTAT_HELD) { - if (LF_ISSET(DB_LOCK_UPGRADE)) - goto upgrade; - - /* - * Lock is held, so we can increment the - * reference count and return this lock. - */ - lp->refcount++; - *lockp = lp; - SH_TAILQ_INSERT_HEAD(&lrp->free_locks, - newl, links, __db_lock); - return (0); - } else - ihold = 1; - } else if (CONFLICTS(lt, lp->mode, lock_mode)) - break; - } - - /* - * If we are upgrading, then there are two scenarios. Either - * we had no conflicts, so we can do the upgrade. Or, there - * is a conflict and we should wait at the HEAD of the waiters - * list. - */ - if (LF_ISSET(DB_LOCK_UPGRADE)) { - if (lp == NULL) - goto upgrade; - - /* There was a conflict, wait. */ - SH_TAILQ_INSERT_HEAD(&sh_obj->waiters, newl, links, __db_lock); - goto wait; - } - - if (lp == NULL && !ihold) - for (lp = SH_TAILQ_FIRST(&sh_obj->waiters, __db_lock); - lp != NULL; - lp = SH_TAILQ_NEXT(lp, links, __db_lock)) { - if (CONFLICTS(lt, lp->mode, lock_mode) && - locker != lp->holder) - break; - } - if (lp == NULL) - SH_TAILQ_INSERT_TAIL(&sh_obj->holders, newl, links); - else if (!(flags & DB_LOCK_NOWAIT)) - SH_TAILQ_INSERT_TAIL(&sh_obj->waiters, newl, links); - else { - /* Free the lock and return an error. */ - newl->status = DB_LSTAT_FREE; - SH_TAILQ_INSERT_HEAD(&lrp->free_locks, newl, links, __db_lock); - return (DB_LOCK_NOTGRANTED); - } - - /* - * Now, insert the lock onto its locker's list. If the locker does - * not currently hold any locks, there's no reason to run a deadlock - * detector, save that information. - */ - if ((ret = - __lock_getobj(lt, locker, NULL, DB_LOCK_LOCKER, &sh_locker)) != 0) - return (ret); - no_dd = SH_LIST_FIRST(&sh_locker->heldby, __db_lock) == NULL; - - lrp = lt->region; - SH_LIST_INSERT_HEAD(&sh_locker->heldby, newl, locker_links, __db_lock); - - if (lp != NULL) { - /* - * This is really a blocker for the process, so initialize it - * set. That way the current process will block when it tries - * to get it and the waking process will release it. - */ -wait: (void)__db_mutex_init(&newl->mutex, - MUTEX_LOCK_OFFSET(lt->region, &newl->mutex)); - (void)__db_mutex_lock(&newl->mutex, lt->reginfo.fd); - - newl->status = DB_LSTAT_WAITING; - lrp->nconflicts++; - - /* - * We are about to wait; must release the region mutex. Then, - * when we wakeup, we need to reacquire the region mutex before - * continuing. - */ - if (lrp->detect == DB_LOCK_NORUN) - lt->region->need_dd = 1; - UNLOCK_LOCKREGION(lt); - - /* - * We are about to wait; before waiting, see if the deadlock - * detector should be run. - */ - if (lrp->detect != DB_LOCK_NORUN && !no_dd) - (void)lock_detect(lt, 0, lrp->detect); - - (void)__db_mutex_lock(&newl->mutex, lt->reginfo.fd); - - LOCK_LOCKREGION(lt); - if (newl->status != DB_LSTAT_PENDING) { - /* - * If this lock errored due to a deadlock, then - * we have waiters that require promotion. - */ - if (newl->status == DB_LSTAT_ABORTED) - (void)__lock_promote(lt, sh_obj); - /* Return to free list. */ - __lock_checklocker(lt, newl, 0); - SH_TAILQ_INSERT_HEAD(&lrp->free_locks, newl, links, - __db_lock); - switch (newl->status) { - case DB_LSTAT_ABORTED: - ret = DB_LOCK_DEADLOCK; - break; - case DB_LSTAT_NOGRANT: - ret = DB_LOCK_NOTGRANTED; - break; - default: - ret = EINVAL; - break; - } - newl->status = DB_LSTAT_FREE; - newl = NULL; - } else if (LF_ISSET(DB_LOCK_UPGRADE)) { - /* - * The lock that was just granted got put on the - * holders list. Since we're upgrading some other - * lock, we've got to remove it here. - */ - SH_TAILQ_REMOVE(&sh_obj->holders, - newl, links, __db_lock); - goto upgrade; - } else - newl->status = DB_LSTAT_HELD; - } - - *lockp = newl; - return (ret); - -upgrade: - /* - * This was an upgrade, so return the new lock to the free list and - * upgrade the mode. - */ - (*lockp)->mode = lock_mode; - newl->status = DB_LSTAT_FREE; - SH_TAILQ_INSERT_HEAD(&lrp->free_locks, newl, links, __db_lock); - return (0); -} - -/* - * __lock_is_locked -- - * - * PUBLIC: int __lock_is_locked - * PUBLIC: __P((DB_LOCKTAB *, u_int32_t, DBT *, db_lockmode_t)); - */ -int -__lock_is_locked(lt, locker, dbt, mode) - DB_LOCKTAB *lt; - u_int32_t locker; - DBT *dbt; - db_lockmode_t mode; -{ - struct __db_lock *lp; - DB_LOCKOBJ *sh_obj; - DB_LOCKREGION *lrp; - - lrp = lt->region; - - /* Look up the object in the hash table. */ - HASHLOOKUP(lt->hashtab, __db_lockobj, links, - dbt, sh_obj, lrp->table_size, __lock_ohash, __lock_cmp); - if (sh_obj == NULL) - return (0); - - for (lp = SH_TAILQ_FIRST(&sh_obj->holders, __db_lock); - lp != NULL; - lp = SH_TAILQ_FIRST(&sh_obj->holders, __db_lock)) { - if (lp->holder == locker && lp->mode == mode) - return (1); - } - - return (0); -} - -/* - * __lock_printlock -- - * - * PUBLIC: void __lock_printlock __P((DB_LOCKTAB *, struct __db_lock *, int)); - */ -void -__lock_printlock(lt, lp, ispgno) - DB_LOCKTAB *lt; - struct __db_lock *lp; - int ispgno; -{ - DB_LOCKOBJ *lockobj; - db_pgno_t pgno; - size_t obj; - u_int8_t *ptr; - const char *mode, *status; - - switch (lp->mode) { - case DB_LOCK_IREAD: - mode = "IREAD"; - break; - case DB_LOCK_IWR: - mode = "IWR"; - break; - case DB_LOCK_IWRITE: - mode = "IWRITE"; - break; - case DB_LOCK_NG: - mode = "NG"; - break; - case DB_LOCK_READ: - mode = "READ"; - break; - case DB_LOCK_WRITE: - mode = "WRITE"; - break; - default: - mode = "UNKNOWN"; - break; - } - switch (lp->status) { - case DB_LSTAT_ABORTED: - status = "ABORT"; - break; - case DB_LSTAT_ERR: - status = "ERROR"; - break; - case DB_LSTAT_FREE: - status = "FREE"; - break; - case DB_LSTAT_HELD: - status = "HELD"; - break; - case DB_LSTAT_NOGRANT: - status = "NONE"; - break; - case DB_LSTAT_WAITING: - status = "WAIT"; - break; - case DB_LSTAT_PENDING: - status = "PENDING"; - break; - default: - status = "UNKNOWN"; - break; - } - printf("\t%lx\t%s\t%lu\t%s\t", - (u_long)lp->holder, mode, (u_long)lp->refcount, status); - - lockobj = (DB_LOCKOBJ *)((u_int8_t *)lp + lp->obj); - ptr = SH_DBT_PTR(&lockobj->lockobj); - if (ispgno) { - /* Assume this is a DBT lock. */ - memcpy(&pgno, ptr, sizeof(db_pgno_t)); - printf("page %lu\n", (u_long)pgno); - } else { - obj = (u_int8_t *)lp + lp->obj - (u_int8_t *)lt->region; - printf("0x%lx ", (u_long)obj); - __db_pr(ptr, lockobj->lockobj.size); - printf("\n"); - } -} - -/* - * PUBLIC: int __lock_getobj __P((DB_LOCKTAB *, - * PUBLIC: u_int32_t, const DBT *, u_int32_t type, DB_LOCKOBJ **)); - */ -int -__lock_getobj(lt, locker, dbt, type, objp) - DB_LOCKTAB *lt; - u_int32_t locker, type; - const DBT *dbt; - DB_LOCKOBJ **objp; -{ - DB_LOCKREGION *lrp; - DB_LOCKOBJ *sh_obj; - u_int32_t obj_size; - int ret; - void *p, *src; - - lrp = lt->region; - - /* Look up the object in the hash table. */ - if (type == DB_LOCK_OBJTYPE) { - HASHLOOKUP(lt->hashtab, __db_lockobj, links, dbt, sh_obj, - lrp->table_size, __lock_ohash, __lock_cmp); - obj_size = dbt->size; - } else { - HASHLOOKUP(lt->hashtab, __db_lockobj, links, locker, - sh_obj, lrp->table_size, __lock_locker_hash, - __lock_locker_cmp); - obj_size = sizeof(locker); - } - - /* - * If we found the object, then we can just return it. If - * we didn't find the object, then we need to create it. - */ - if (sh_obj == NULL) { - /* Create new object and then insert it into hash table. */ - if ((sh_obj = - SH_TAILQ_FIRST(&lrp->free_objs, __db_lockobj)) == NULL) { - if ((ret = __lock_grow_region(lt, DB_LOCK_OBJ, 0)) != 0) - return (ret); - lrp = lt->region; - sh_obj = SH_TAILQ_FIRST(&lrp->free_objs, __db_lockobj); - } - - /* - * If we can fit this object in the structure, do so instead - * of shalloc-ing space for it. - */ - if (obj_size <= sizeof(sh_obj->objdata)) - p = sh_obj->objdata; - else - if ((ret = - __db_shalloc(lt->mem, obj_size, 0, &p)) != 0) { - if ((ret = __lock_grow_region(lt, - DB_LOCK_MEM, obj_size)) != 0) - return (ret); - lrp = lt->region; - /* Reacquire the head of the list. */ - sh_obj = SH_TAILQ_FIRST(&lrp->free_objs, - __db_lockobj); - (void)__db_shalloc(lt->mem, obj_size, 0, &p); - } - - src = type == DB_LOCK_OBJTYPE ? dbt->data : (void *)&locker; - memcpy(p, src, obj_size); - - sh_obj->type = type; - SH_TAILQ_REMOVE(&lrp->free_objs, sh_obj, links, __db_lockobj); - - SH_TAILQ_INIT(&sh_obj->waiters); - if (type == DB_LOCK_LOCKER) - SH_LIST_INIT(&sh_obj->heldby); - else - SH_TAILQ_INIT(&sh_obj->holders); - sh_obj->lockobj.size = obj_size; - sh_obj->lockobj.off = SH_PTR_TO_OFF(&sh_obj->lockobj, p); - - HASHINSERT(lt->hashtab, - __db_lockobj, links, sh_obj, lrp->table_size, __lock_lhash); - - if (type == DB_LOCK_LOCKER) - lrp->nlockers++; - } - - *objp = sh_obj; - return (0); -} - -/* - * Any lock on the waitlist has a process waiting for it. Therefore, we - * can't return the lock to the freelist immediately. Instead, we can - * remove the lock from the list of waiters, set the status field of the - * lock, and then let the process waking up return the lock to the - * free list. - */ -static void -__lock_remove_waiter(lt, sh_obj, lockp, status) - DB_LOCKTAB *lt; - DB_LOCKOBJ *sh_obj; - struct __db_lock *lockp; - db_status_t status; -{ - SH_TAILQ_REMOVE(&sh_obj->waiters, lockp, links, __db_lock); - lockp->status = status; - - /* Wake whoever is waiting on this lock. */ - (void)__db_mutex_unlock(&lockp->mutex, lt->reginfo.fd); -} - -static void -__lock_checklocker(lt, lockp, do_remove) - DB_LOCKTAB *lt; - struct __db_lock *lockp; - int do_remove; -{ - DB_LOCKOBJ *sh_locker; - - if (do_remove) - SH_LIST_REMOVE(lockp, locker_links, __db_lock); - - /* if the locker list is NULL, free up the object. */ - if (__lock_getobj(lt, lockp->holder, NULL, DB_LOCK_LOCKER, &sh_locker) - == 0 && SH_LIST_FIRST(&sh_locker->heldby, __db_lock) == NULL) { - __lock_freeobj(lt, sh_locker); - lt->region->nlockers--; - } -} - -static void -__lock_freeobj(lt, obj) - DB_LOCKTAB *lt; - DB_LOCKOBJ *obj; -{ - HASHREMOVE_EL(lt->hashtab, - __db_lockobj, links, obj, lt->region->table_size, __lock_lhash); - if (obj->lockobj.size > sizeof(obj->objdata)) - __db_shalloc_free(lt->mem, SH_DBT_PTR(&obj->lockobj)); - SH_TAILQ_INSERT_HEAD(<->region->free_objs, obj, links, __db_lockobj); -} - -/* - * __lock_downgrade -- - * Used by the concurrent access product to downgrade write locks - * back to iwrite locks. - * - * PUBLIC: int __lock_downgrade __P((DB_LOCKTAB *, - * PUBLIC: DB_LOCK, db_lockmode_t, u_int32_t)); - */ -int -__lock_downgrade(lt, lock, new_mode, flags) - DB_LOCKTAB *lt; - DB_LOCK lock; - db_lockmode_t new_mode; - u_int32_t flags; -{ - struct __db_lock *lockp; - DB_LOCKOBJ *obj; - int ret; - - COMPQUIET(flags, 0); - LOCK_PANIC_CHECK(lt); - LOCK_LOCKREGION(lt); - - if ((ret = __lock_validate_region(lt)) == 0) { - lockp = OFFSET_TO_LOCK(lt, lock); - lockp->mode = new_mode; - - /* Get the object associated with this lock. */ - obj = (DB_LOCKOBJ *)((u_int8_t *)lockp + lockp->obj); - (void)__lock_promote(lt, obj); - ++lt->region->nreleases; - } - - UNLOCK_LOCKREGION(lt); - - return (ret); -} - -/* - * __lock_promote -- - * - * Look through the waiters and holders lists and decide which (if any) - * locks can be promoted. Promote any that are eligible. - */ -static int -__lock_promote(lt, obj) - DB_LOCKTAB *lt; - DB_LOCKOBJ *obj; -{ - struct __db_lock *lp_w, *lp_h, *next_waiter; - int state_changed, waiter_is_txn; - - /* - * We need to do lock promotion. We also need to determine if - * we're going to need to run the deadlock detector again. If - * we release locks, and there are waiters, but no one gets promoted, - * then we haven't fundamentally changed the lockmgr state, so - * we may still have a deadlock and we have to run again. However, - * if there were no waiters, or we actually promoted someone, then - * we are OK and we don't have to run it immediately. - * - * During promotion, we look for state changes so we can return - * this information to the caller. - */ - for (lp_w = SH_TAILQ_FIRST(&obj->waiters, __db_lock), - state_changed = lp_w == NULL; - lp_w != NULL; - lp_w = next_waiter) { - waiter_is_txn = TXN_IS_HOLDING(lp_w); - next_waiter = SH_TAILQ_NEXT(lp_w, links, __db_lock); - for (lp_h = SH_TAILQ_FIRST(&obj->holders, __db_lock); - lp_h != NULL; - lp_h = SH_TAILQ_NEXT(lp_h, links, __db_lock)) { - if (CONFLICTS(lt, lp_h->mode, lp_w->mode) && - lp_h->holder != lp_w->holder && - !(waiter_is_txn && - TXN_IS_HOLDING(lp_h) && - __txn_is_ancestor(lt->dbenv->tx_info, - lp_h->txnoff, lp_w->txnoff))) - break; - } - if (lp_h != NULL) /* Found a conflict. */ - break; - - /* No conflict, promote the waiting lock. */ - SH_TAILQ_REMOVE(&obj->waiters, lp_w, links, __db_lock); - lp_w->status = DB_LSTAT_PENDING; - SH_TAILQ_INSERT_TAIL(&obj->holders, lp_w, links); - - /* Wake up waiter. */ - (void)__db_mutex_unlock(&lp_w->mutex, lt->reginfo.fd); - state_changed = 1; - } - - return (state_changed); -} - -static int -__lock_is_parent(locker, txn) - u_int32_t locker; - DB_TXN *txn; -{ - DB_TXN *t; - - if (txn == NULL) - return (0); - - for (t = txn->parent; t != NULL; t = t->parent) - if (t->txnid == locker) - return (1); - - return (0); -} diff --git a/db2/lock/lock_conflict.c b/db2/lock/lock_conflict.c deleted file mode 100644 index 4be858a..0000000 --- a/db2/lock/lock_conflict.c +++ /dev/null @@ -1,39 +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[] = "@(#)lock_conflict.c 10.4 (Sleepycat) 11/20/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> -#endif - -#include "db_int.h" - -/* - * The conflict arrays are set up such that the row is the lock you - * are holding and the column is the lock that is desired. - */ -const u_int8_t db_rw_conflicts[] = { - /* N R W */ - /* N */ 0, 0, 0, - /* R */ 0, 0, 1, - /* W */ 0, 1, 1 -}; - -const u_int8_t db_riw_conflicts[] = { - /* N S X IX IS SIX */ - /* N */ 0, 0, 0, 0, 0, 0, - /* S */ 0, 0, 1, 1, 0, 1, - /* X */ 1, 1, 1, 1, 1, 1, - /* IX */ 0, 1, 1, 0, 0, 0, - /* IS */ 0, 0, 1, 0, 0, 0, - /* SIX */ 0, 1, 1, 0, 0, 0 -}; diff --git a/db2/lock/lock_deadlock.c b/db2/lock/lock_deadlock.c deleted file mode 100644 index 8b2f91b..0000000 --- a/db2/lock/lock_deadlock.c +++ /dev/null @@ -1,502 +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[] = "@(#)lock_deadlock.c 10.37 (Sleepycat) 10/4/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 "db_shash.h" -#include "lock.h" -#include "common_ext.h" - -#define ISSET_MAP(M, N) (M[(N) / 32] & (1 << (N) % 32)) - -#define CLEAR_MAP(M, N) { \ - u_int32_t __i; \ - for (__i = 0; __i < (N); __i++) \ - M[__i] = 0; \ -} - -#define SET_MAP(M, B) (M[(B) / 32] |= (1 << ((B) % 32))) -#define CLR_MAP(M, B) (M[(B) / 32] &= ~(1 << ((B) % 32))) - -#define OR_MAP(D, S, N) { \ - u_int32_t __i; \ - for (__i = 0; __i < (N); __i++) \ - D[__i] |= S[__i]; \ -} -#define BAD_KILLID 0xffffffff - -typedef struct { - int valid; - u_int32_t id; - DB_LOCK last_lock; - db_pgno_t pgno; -} locker_info; - -static int __dd_abort __P((DB_ENV *, locker_info *)); -static int __dd_build - __P((DB_ENV *, u_int32_t **, u_int32_t *, locker_info **)); -static u_int32_t - *__dd_find __P((u_int32_t *, locker_info *, u_int32_t)); - -#ifdef DIAGNOSTIC -static void __dd_debug __P((DB_ENV *, locker_info *, u_int32_t *, u_int32_t)); -#endif - -int -lock_detect(lt, flags, atype) - DB_LOCKTAB *lt; - u_int32_t flags, atype; -{ - DB_ENV *dbenv; - locker_info *idmap; - u_int32_t *bitmap, *deadlock, i, killid, nentries, nlockers; - int do_pass, ret; - - LOCK_PANIC_CHECK(lt); - - /* Validate arguments. */ - if ((ret = - __db_fchk(lt->dbenv, "lock_detect", flags, DB_LOCK_CONFLICT)) != 0) - return (ret); - - /* Check if a detector run is necessary. */ - dbenv = lt->dbenv; - if (LF_ISSET(DB_LOCK_CONFLICT)) { - /* Make a pass every time a lock waits. */ - LOCK_LOCKREGION(lt); - do_pass = dbenv->lk_info->region->need_dd != 0; - UNLOCK_LOCKREGION(lt); - - if (!do_pass) - return (0); - } - - /* Build the waits-for bitmap. */ - if ((ret = __dd_build(dbenv, &bitmap, &nlockers, &idmap)) != 0) - return (ret); - - if (nlockers == 0) - return (0); -#ifdef DIAGNOSTIC - if (dbenv->db_verbose != 0) - __dd_debug(dbenv, idmap, bitmap, nlockers); -#endif - /* Find a deadlock. */ - deadlock = __dd_find(bitmap, idmap, nlockers); - nentries = ALIGN(nlockers, 32) / 32; - killid = BAD_KILLID; - if (deadlock != NULL) { - /* Kill someone. */ - switch (atype) { - case DB_LOCK_OLDEST: - /* - * Find the first bit set in the current - * array and then look for a lower tid in - * the array. - */ - for (i = 0; i < nlockers; i++) - if (ISSET_MAP(deadlock, i)) - killid = i; - - if (killid == BAD_KILLID) { - __db_err(dbenv, - "warning: could not find locker to abort"); - break; - } - - /* - * The oldest transaction has the lowest - * transaction id. - */ - for (i = killid + 1; i < nlockers; i++) - if (ISSET_MAP(deadlock, i) && - idmap[i].id < idmap[killid].id) - killid = i; - break; - case DB_LOCK_DEFAULT: - case DB_LOCK_RANDOM: - /* - * We are trying to calculate the id of the - * locker whose entry is indicated by deadlock. - */ - killid = (deadlock - bitmap) / nentries; - break; - case DB_LOCK_YOUNGEST: - /* - * Find the first bit set in the current - * array and then look for a lower tid in - * the array. - */ - for (i = 0; i < nlockers; i++) - if (ISSET_MAP(deadlock, i)) - killid = i; - - if (killid == BAD_KILLID) { - __db_err(dbenv, - "warning: could not find locker to abort"); - break; - } - /* - * The youngest transaction has the highest - * transaction id. - */ - for (i = killid + 1; i < nlockers; i++) - if (ISSET_MAP(deadlock, i) && - idmap[i].id > idmap[killid].id) - killid = i; - break; - default: - killid = BAD_KILLID; - ret = EINVAL; - } - - /* Kill the locker with lockid idmap[killid]. */ - if (dbenv->db_verbose != 0 && killid != BAD_KILLID) - __db_err(dbenv, "Aborting locker %lx", - (u_long)idmap[killid].id); - - if (killid != BAD_KILLID && - (ret = __dd_abort(dbenv, &idmap[killid])) != 0) - __db_err(dbenv, - "warning: unable to abort locker %lx", - (u_long)idmap[killid].id); - } - __os_free(bitmap, 0); - __os_free(idmap, 0); - - return (ret); -} - -/* - * ======================================================================== - * Utilities - */ -static int -__dd_build(dbenv, bmp, nlockers, idmap) - DB_ENV *dbenv; - u_int32_t **bmp, *nlockers; - locker_info **idmap; -{ - struct __db_lock *lp; - DB_LOCKTAB *lt; - DB_LOCKOBJ *op, *lo, *lockerp; - u_int8_t *pptr; - locker_info *id_array; - u_int32_t *bitmap, count, *entryp, i, id, nentries, *tmpmap; - int is_first, ret; - - lt = dbenv->lk_info; - - /* - * We'll check how many lockers there are, add a few more in for - * good measure and then allocate all the structures. Then we'll - * verify that we have enough room when we go back in and get the - * mutex the second time. - */ - LOCK_LOCKREGION(lt); -retry: count = lt->region->nlockers; - lt->region->need_dd = 0; - UNLOCK_LOCKREGION(lt); - - if (count == 0) { - *nlockers = 0; - return (0); - } - - if (dbenv->db_verbose) - __db_err(dbenv, "%lu lockers", (u_long)count); - - count += 10; - nentries = ALIGN(count, 32) / 32; - /* - * Allocate enough space for a count by count bitmap matrix. - * - * XXX - * We can probably save the malloc's between iterations just - * reallocing if necessary because count grew by too much. - */ - if ((ret = __os_calloc((size_t)count, - sizeof(u_int32_t) * nentries, &bitmap)) != 0) - return (ret); - - if ((ret = __os_calloc(sizeof(u_int32_t), nentries, &tmpmap)) != 0) { - __os_free(bitmap, sizeof(u_int32_t) * nentries); - return (ret); - } - - if ((ret = - __os_calloc((size_t)count, sizeof(locker_info), &id_array)) != 0) { - __os_free(bitmap, count * sizeof(u_int32_t) * nentries); - __os_free(tmpmap, sizeof(u_int32_t) * nentries); - return (ret); - } - - /* - * Now go back in and actually fill in the matrix. - */ - LOCK_LOCKREGION(lt); - if (lt->region->nlockers > count) { - __os_free(bitmap, count * sizeof(u_int32_t) * nentries); - __os_free(tmpmap, sizeof(u_int32_t) * nentries); - __os_free(id_array, count * sizeof(locker_info)); - goto retry; - } - - /* - * First we go through and assign each locker a deadlock detector id. - * Note that we fill in the idmap in the next loop since that's the - * only place where we conveniently have both the deadlock id and the - * actual locker. - */ - for (id = 0, i = 0; i < lt->region->table_size; i++) - for (op = SH_TAILQ_FIRST(<->hashtab[i], __db_lockobj); - op != NULL; op = SH_TAILQ_NEXT(op, links, __db_lockobj)) - if (op->type == DB_LOCK_LOCKER) - op->dd_id = id++; - /* - * We go through the hash table and find each object. For each object, - * we traverse the waiters list and add an entry in the waitsfor matrix - * for each waiter/holder combination. - */ - for (i = 0; i < lt->region->table_size; i++) { - for (op = SH_TAILQ_FIRST(<->hashtab[i], __db_lockobj); - op != NULL; op = SH_TAILQ_NEXT(op, links, __db_lockobj)) { - if (op->type != DB_LOCK_OBJTYPE) - continue; - CLEAR_MAP(tmpmap, nentries); - - /* - * First we go through and create a bit map that - * represents all the holders of this object. - */ - for (lp = SH_TAILQ_FIRST(&op->holders, __db_lock); - lp != NULL; - lp = SH_TAILQ_NEXT(lp, links, __db_lock)) { - if (__lock_getobj(lt, lp->holder, - NULL, DB_LOCK_LOCKER, &lockerp) != 0) { - __db_err(dbenv, - "warning unable to find object"); - continue; - } - id_array[lockerp->dd_id].id = lp->holder; - id_array[lockerp->dd_id].valid = 1; - - /* - * If the holder has already been aborted, then - * we should ignore it for now. - */ - if (lp->status == DB_LSTAT_HELD) - SET_MAP(tmpmap, lockerp->dd_id); - } - - /* - * Next, for each waiter, we set its row in the matrix - * equal to the map of holders we set up above. - */ - for (is_first = 1, - lp = SH_TAILQ_FIRST(&op->waiters, __db_lock); - lp != NULL; - is_first = 0, - lp = SH_TAILQ_NEXT(lp, links, __db_lock)) { - if (__lock_getobj(lt, lp->holder, - NULL, DB_LOCK_LOCKER, &lockerp) != 0) { - __db_err(dbenv, - "warning unable to find object"); - continue; - } - id_array[lockerp->dd_id].id = lp->holder; - id_array[lockerp->dd_id].valid = 1; - - /* - * If the transaction is pending abortion, then - * ignore it on this iteration. - */ - if (lp->status != DB_LSTAT_WAITING) - continue; - - entryp = bitmap + (nentries * lockerp->dd_id); - OR_MAP(entryp, tmpmap, nentries); - /* - * If this is the first waiter on the queue, - * then we remove the waitsfor relationship - * with oneself. However, if it's anywhere - * else on the queue, then we have to keep - * it and we have an automatic deadlock. - */ - if (is_first) - CLR_MAP(entryp, lockerp->dd_id); - } - } - } - - /* Now for each locker; record its last lock. */ - for (id = 0; id < count; id++) { - if (!id_array[id].valid) - continue; - if (__lock_getobj(lt, - id_array[id].id, NULL, DB_LOCK_LOCKER, &lockerp) != 0) { - __db_err(dbenv, - "No locks for locker %lu", (u_long)id_array[id].id); - continue; - } - lp = SH_LIST_FIRST(&lockerp->heldby, __db_lock); - if (lp != NULL) { - id_array[id].last_lock = LOCK_TO_OFFSET(lt, lp); - lo = (DB_LOCKOBJ *)((u_int8_t *)lp + lp->obj); - pptr = SH_DBT_PTR(&lo->lockobj); - if (lo->lockobj.size >= sizeof(db_pgno_t)) - memcpy(&id_array[id].pgno, pptr, - sizeof(db_pgno_t)); - else - id_array[id].pgno = 0; - } - } - - /* Pass complete, reset the deadlock detector bit. */ - lt->region->need_dd = 0; - UNLOCK_LOCKREGION(lt); - - /* - * Now we can release everything except the bitmap matrix that we - * created. - */ - *nlockers = id; - *idmap = id_array; - *bmp = bitmap; - __os_free(tmpmap, sizeof(u_int32_t) * nentries); - return (0); -} - -static u_int32_t * -__dd_find(bmp, idmap, nlockers) - u_int32_t *bmp, nlockers; - locker_info *idmap; -{ - u_int32_t i, j, nentries, *mymap, *tmpmap; - - /* - * For each locker, OR in the bits from the lockers on which that - * locker is waiting. - */ - nentries = ALIGN(nlockers, 32) / 32; - for (mymap = bmp, i = 0; i < nlockers; i++, mymap += nentries) { - if (!idmap[i].valid) - continue; - for (j = 0; j < nlockers; j++) { - if (ISSET_MAP(mymap, j)) { - /* Find the map for this bit. */ - tmpmap = bmp + (nentries * j); - OR_MAP(mymap, tmpmap, nentries); - if (ISSET_MAP(mymap, i)) - return (mymap); - } - } - } - return (NULL); -} - -static int -__dd_abort(dbenv, info) - DB_ENV *dbenv; - locker_info *info; -{ - struct __db_lock *lockp; - DB_LOCKTAB *lt; - DB_LOCKOBJ *lockerp, *sh_obj; - int ret; - - lt = dbenv->lk_info; - LOCK_LOCKREGION(lt); - - /* Find the locker's last lock. */ - if ((ret = - __lock_getobj(lt, info->id, NULL, DB_LOCK_LOCKER, &lockerp)) != 0) - goto out; - - lockp = SH_LIST_FIRST(&lockerp->heldby, __db_lock); - - /* - * It's possible that this locker was already aborted. - * If that's the case, make sure that we remove its - * locker from the hash table. - */ - if (lockp == NULL) { - HASHREMOVE_EL(lt->hashtab, __db_lockobj, - links, lockerp, lt->region->table_size, __lock_lhash); - SH_TAILQ_INSERT_HEAD(<->region->free_objs, - lockerp, links, __db_lockobj); - lt->region->nlockers--; - goto out; - } else if (LOCK_TO_OFFSET(lt, lockp) != info->last_lock || - lockp->status != DB_LSTAT_WAITING) - goto out; - - /* Abort lock, take it off list, and wake up this lock. */ - lockp->status = DB_LSTAT_ABORTED; - lt->region->ndeadlocks++; - SH_LIST_REMOVE(lockp, locker_links, __db_lock); - sh_obj = (DB_LOCKOBJ *)((u_int8_t *)lockp + lockp->obj); - SH_TAILQ_REMOVE(&sh_obj->waiters, lockp, links, __db_lock); - (void)__db_mutex_unlock(&lockp->mutex, lt->reginfo.fd); - - ret = 0; - -out: UNLOCK_LOCKREGION(lt); - return (ret); -} - -#ifdef DIAGNOSTIC -static void -__dd_debug(dbenv, idmap, bitmap, nlockers) - DB_ENV *dbenv; - locker_info *idmap; - u_int32_t *bitmap, nlockers; -{ - u_int32_t i, j, *mymap, nentries; - int ret; - char *msgbuf; - - __db_err(dbenv, "Waitsfor array"); - __db_err(dbenv, "waiter\twaiting on"); - - /* Allocate space to print 10 bytes per item waited on. */ -#undef MSGBUF_LEN -#define MSGBUF_LEN ((nlockers + 1) * 10 + 64) - if ((ret = __os_malloc(MSGBUF_LEN, NULL, &msgbuf)) != 0) - return; - - nentries = ALIGN(nlockers, 32) / 32; - for (mymap = bitmap, i = 0; i < nlockers; i++, mymap += nentries) { - if (!idmap[i].valid) - continue; - sprintf(msgbuf, /* Waiter. */ - "%lx/%lu:\t", (u_long)idmap[i].id, (u_long)idmap[i].pgno); - for (j = 0; j < nlockers; j++) - if (ISSET_MAP(mymap, j)) - sprintf(msgbuf, "%s %lx", msgbuf, - (u_long)idmap[j].id); - (void)sprintf(msgbuf, - "%s %lu", msgbuf, (u_long)idmap[i].last_lock); - __db_err(dbenv, msgbuf); - } - - __os_free(msgbuf, MSGBUF_LEN); -} -#endif diff --git a/db2/lock/lock_region.c b/db2/lock/lock_region.c deleted file mode 100644 index 613a6ce..0000000 --- a/db2/lock/lock_region.c +++ /dev/null @@ -1,743 +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[] = "@(#)lock_region.c 10.21 (Sleepycat) 10/19/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <ctype.h> -#include <errno.h> -#include <string.h> -#endif - -#include "db_int.h" -#include "shqueue.h" -#include "db_shash.h" -#include "lock.h" -#include "common_ext.h" - -static u_int32_t __lock_count_locks __P((DB_LOCKREGION *)); -static u_int32_t __lock_count_objs __P((DB_LOCKREGION *)); -static void __lock_dump_locker __P((DB_LOCKTAB *, DB_LOCKOBJ *, FILE *)); -static void __lock_dump_object __P((DB_LOCKTAB *, DB_LOCKOBJ *, FILE *)); -static const char * - __lock_dump_status __P((db_status_t)); -static void __lock_reset_region __P((DB_LOCKTAB *)); -static int __lock_tabinit __P((DB_ENV *, DB_LOCKREGION *)); - -int -lock_open(path, flags, mode, dbenv, ltp) - const char *path; - u_int32_t flags; - int mode; - DB_ENV *dbenv; - DB_LOCKTAB **ltp; -{ - DB_LOCKTAB *lt; - u_int32_t lock_modes, maxlocks, regflags; - int ret; - - /* Validate arguments. */ -#ifdef HAVE_SPINLOCKS -#define OKFLAGS (DB_CREATE | DB_THREAD) -#else -#define OKFLAGS (DB_CREATE) -#endif - if ((ret = __db_fchk(dbenv, "lock_open", flags, OKFLAGS)) != 0) - return (ret); - - /* Create the lock table structure. */ - if ((ret = __os_calloc(1, sizeof(DB_LOCKTAB), <)) != 0) - return (ret); - lt->dbenv = dbenv; - - /* Grab the values that we need to compute the region size. */ - lock_modes = DB_LOCK_RW_N; - maxlocks = DB_LOCK_DEFAULT_N; - regflags = REGION_SIZEDEF; - if (dbenv != NULL) { - if (dbenv->lk_modes != 0) { - lock_modes = dbenv->lk_modes; - regflags = 0; - } - if (dbenv->lk_max != 0) { - maxlocks = dbenv->lk_max; - regflags = 0; - } - } - - /* Join/create the lock region. */ - lt->reginfo.dbenv = dbenv; - lt->reginfo.appname = DB_APP_NONE; - if (path == NULL) - lt->reginfo.path = NULL; - else - if ((ret = __os_strdup(path, <->reginfo.path)) != 0) - goto err; - lt->reginfo.file = DB_DEFAULT_LOCK_FILE; - lt->reginfo.mode = mode; - lt->reginfo.size = - LOCK_REGION_SIZE(lock_modes, maxlocks, __db_tablesize(maxlocks)); - lt->reginfo.dbflags = flags; - lt->reginfo.addr = NULL; - lt->reginfo.fd = -1; - lt->reginfo.flags = regflags; - - if ((ret = __db_rattach(<->reginfo)) != 0) - goto err; - - /* Now set up the pointer to the region. */ - lt->region = lt->reginfo.addr; - - /* Initialize the region if we created it. */ - if (F_ISSET(<->reginfo, REGION_CREATED)) { - lt->region->maxlocks = maxlocks; - lt->region->nmodes = lock_modes; - if ((ret = __lock_tabinit(dbenv, lt->region)) != 0) - goto err; - } else { - /* Check for an unexpected region. */ - if (lt->region->magic != DB_LOCKMAGIC) { - __db_err(dbenv, - "lock_open: %s: bad magic number", path); - ret = EINVAL; - goto err; - } - } - - /* Check for automatic deadlock detection. */ - if (dbenv != NULL && dbenv->lk_detect != DB_LOCK_NORUN) { - if (lt->region->detect != DB_LOCK_NORUN && - dbenv->lk_detect != DB_LOCK_DEFAULT && - lt->region->detect != dbenv->lk_detect) { - __db_err(dbenv, - "lock_open: incompatible deadlock detector mode"); - ret = EINVAL; - goto err; - } - if (lt->region->detect == DB_LOCK_NORUN) - lt->region->detect = dbenv->lk_detect; - } - - /* Set up remaining pointers into region. */ - lt->conflicts = (u_int8_t *)lt->region + sizeof(DB_LOCKREGION); - lt->hashtab = - (DB_HASHTAB *)((u_int8_t *)lt->region + lt->region->hash_off); - lt->mem = (void *)((u_int8_t *)lt->region + lt->region->mem_off); - - UNLOCK_LOCKREGION(lt); - *ltp = lt; - return (0); - -err: if (lt->reginfo.addr != NULL) { - UNLOCK_LOCKREGION(lt); - (void)__db_rdetach(<->reginfo); - if (F_ISSET(<->reginfo, REGION_CREATED)) - (void)lock_unlink(path, 1, dbenv); - } - - if (lt->reginfo.path != NULL) - __os_freestr(lt->reginfo.path); - __os_free(lt, sizeof(*lt)); - return (ret); -} - -/* - * __lock_panic -- - * Panic a lock region. - * - * PUBLIC: void __lock_panic __P((DB_ENV *)); - */ -void -__lock_panic(dbenv) - DB_ENV *dbenv; -{ - if (dbenv->lk_info != NULL) - dbenv->lk_info->region->hdr.panic = 1; -} - - -/* - * __lock_tabinit -- - * Initialize the lock region. - */ -static int -__lock_tabinit(dbenv, lrp) - DB_ENV *dbenv; - DB_LOCKREGION *lrp; -{ - struct __db_lock *lp; - struct lock_header *tq_head; - struct obj_header *obj_head; - DB_LOCKOBJ *op; - u_int32_t i, nelements; - const u_int8_t *conflicts; - u_int8_t *curaddr; - - conflicts = dbenv == NULL || dbenv->lk_conflicts == NULL ? - db_rw_conflicts : dbenv->lk_conflicts; - - lrp->table_size = __db_tablesize(lrp->maxlocks); - lrp->magic = DB_LOCKMAGIC; - lrp->version = DB_LOCKVERSION; - lrp->id = 0; - /* - * These fields (lrp->maxlocks, lrp->nmodes) are initialized - * in the caller, since we had to grab those values to size - * the region. - */ - lrp->need_dd = 0; - lrp->detect = DB_LOCK_NORUN; - lrp->numobjs = lrp->maxlocks; - lrp->nlockers = 0; - lrp->mem_bytes = ALIGN(STRING_SIZE(lrp->maxlocks), sizeof(size_t)); - lrp->increment = lrp->hdr.size / 2; - lrp->nconflicts = 0; - lrp->nrequests = 0; - lrp->nreleases = 0; - lrp->ndeadlocks = 0; - - /* - * As we write the region, we've got to maintain the alignment - * for the structures that follow each chunk. This information - * ends up being encapsulated both in here as well as in the - * lock.h file for the XXX_SIZE macros. - */ - /* Initialize conflict matrix. */ - curaddr = (u_int8_t *)lrp + sizeof(DB_LOCKREGION); - memcpy(curaddr, conflicts, lrp->nmodes * lrp->nmodes); - curaddr += lrp->nmodes * lrp->nmodes; - - /* - * Initialize hash table. - */ - curaddr = (u_int8_t *)ALIGNP(curaddr, LOCK_HASH_ALIGN); - lrp->hash_off = curaddr - (u_int8_t *)lrp; - nelements = lrp->table_size; - __db_hashinit(curaddr, nelements); - curaddr += nelements * sizeof(DB_HASHTAB); - - /* - * Initialize locks onto a free list. Since locks contains mutexes, - * we need to make sure that each lock is aligned on a MUTEX_ALIGNMENT - * boundary. - */ - curaddr = (u_int8_t *)ALIGNP(curaddr, MUTEX_ALIGNMENT); - tq_head = &lrp->free_locks; - SH_TAILQ_INIT(tq_head); - - for (i = 0; i++ < lrp->maxlocks; - curaddr += ALIGN(sizeof(struct __db_lock), MUTEX_ALIGNMENT)) { - lp = (struct __db_lock *)curaddr; - lp->status = DB_LSTAT_FREE; - SH_TAILQ_INSERT_HEAD(tq_head, lp, links, __db_lock); - } - - /* Initialize objects onto a free list. */ - obj_head = &lrp->free_objs; - SH_TAILQ_INIT(obj_head); - - for (i = 0; i++ < lrp->maxlocks; curaddr += sizeof(DB_LOCKOBJ)) { - op = (DB_LOCKOBJ *)curaddr; - SH_TAILQ_INSERT_HEAD(obj_head, op, links, __db_lockobj); - } - - /* - * Initialize the string space; as for all shared memory allocation - * regions, this requires size_t alignment, since we store the - * lengths of malloc'd areas in the area. - */ - curaddr = (u_int8_t *)ALIGNP(curaddr, sizeof(size_t)); - lrp->mem_off = curaddr - (u_int8_t *)lrp; - __db_shalloc_init(curaddr, lrp->mem_bytes); - return (0); -} - -int -lock_close(lt) - DB_LOCKTAB *lt; -{ - int ret; - - LOCK_PANIC_CHECK(lt); - - if ((ret = __db_rdetach(<->reginfo)) != 0) - return (ret); - - if (lt->reginfo.path != NULL) - __os_freestr(lt->reginfo.path); - __os_free(lt, sizeof(*lt)); - - return (0); -} - -int -lock_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_NONE; - if (path != NULL && (ret = __os_strdup(path, ®info.path)) != 0) - return (ret); - reginfo.file = DB_DEFAULT_LOCK_FILE; - ret = __db_runlink(®info, force); - if (reginfo.path != NULL) - __os_freestr(reginfo.path); - return (ret); -} - -/* - * __lock_validate_region -- - * Called at every interface to verify if the region has changed size, - * and if so, to remap the region in and reset the process' pointers. - * - * PUBLIC: int __lock_validate_region __P((DB_LOCKTAB *)); - */ -int -__lock_validate_region(lt) - DB_LOCKTAB *lt; -{ - int ret; - - if (lt->reginfo.size == lt->region->hdr.size) - return (0); - - /* Detach/reattach the region. */ - if ((ret = __db_rreattach(<->reginfo, lt->region->hdr.size)) != 0) - return (ret); - - /* Reset region information. */ - lt->region = lt->reginfo.addr; - __lock_reset_region(lt); - - return (0); -} - -/* - * __lock_grow_region -- - * We have run out of space; time to grow the region. - * - * PUBLIC: int __lock_grow_region __P((DB_LOCKTAB *, int, size_t)); - */ -int -__lock_grow_region(lt, which, howmuch) - DB_LOCKTAB *lt; - int which; - size_t howmuch; -{ - struct __db_lock *newl; - struct lock_header *lock_head; - struct obj_header *obj_head; - DB_LOCKOBJ *op; - DB_LOCKREGION *lrp; - float lock_ratio, obj_ratio; - size_t incr, oldsize, used, usedmem; - u_int32_t i, newlocks, newmem, newobjs, usedlocks, usedobjs; - u_int8_t *curaddr; - int ret; - - lrp = lt->region; - oldsize = lrp->hdr.size; - incr = lrp->increment; - - /* Figure out how much of each sort of space we have. */ - usedmem = lrp->mem_bytes - __db_shalloc_count(lt->mem); - usedobjs = lrp->numobjs - __lock_count_objs(lrp); - usedlocks = lrp->maxlocks - __lock_count_locks(lrp); - - /* - * Figure out what fraction of the used space belongs to each - * different type of "thing" in the region. Then partition the - * new space up according to this ratio. - */ - used = usedmem + - usedlocks * ALIGN(sizeof(struct __db_lock), MUTEX_ALIGNMENT) + - usedobjs * sizeof(DB_LOCKOBJ); - - lock_ratio = usedlocks * - ALIGN(sizeof(struct __db_lock), MUTEX_ALIGNMENT) / (float)used; - obj_ratio = usedobjs * sizeof(DB_LOCKOBJ) / (float)used; - - newlocks = (u_int32_t)(lock_ratio * - incr / ALIGN(sizeof(struct __db_lock), MUTEX_ALIGNMENT)); - newobjs = (u_int32_t)(obj_ratio * incr / sizeof(DB_LOCKOBJ)); - newmem = incr - - (newobjs * sizeof(DB_LOCKOBJ) + - newlocks * ALIGN(sizeof(struct __db_lock), MUTEX_ALIGNMENT)); - - /* - * Make sure we allocate enough memory for the object being - * requested. - */ - switch (which) { - case DB_LOCK_LOCK: - if (newlocks == 0) { - newlocks = 10; - incr += newlocks * sizeof(struct __db_lock); - } - break; - case DB_LOCK_OBJ: - if (newobjs == 0) { - newobjs = 10; - incr += newobjs * sizeof(DB_LOCKOBJ); - } - break; - case DB_LOCK_MEM: - if (newmem < howmuch * 2) { - incr += howmuch * 2 - newmem; - newmem = howmuch * 2; - } - break; - } - - newmem += ALIGN(incr, sizeof(size_t)) - incr; - incr = ALIGN(incr, sizeof(size_t)); - - /* - * Since we are going to be allocating locks at the beginning of the - * new chunk, we need to make sure that the chunk is MUTEX_ALIGNMENT - * aligned. We did not guarantee this when we created the region, so - * we may need to pad the old region by extra bytes to ensure this - * alignment. - */ - incr += ALIGN(oldsize, MUTEX_ALIGNMENT) - oldsize; - - __db_err(lt->dbenv, - "Growing lock region: %lu locks %lu objs %lu bytes", - (u_long)newlocks, (u_long)newobjs, (u_long)newmem); - - if ((ret = __db_rgrow(<->reginfo, oldsize + incr)) != 0) - return (ret); - lt->region = lt->reginfo.addr; - __lock_reset_region(lt); - - /* Update region parameters. */ - lrp = lt->region; - lrp->increment = incr << 1; - lrp->maxlocks += newlocks; - lrp->numobjs += newobjs; - lrp->mem_bytes += newmem; - - curaddr = (u_int8_t *)lrp + oldsize; - curaddr = (u_int8_t *)ALIGNP(curaddr, MUTEX_ALIGNMENT); - - /* Put new locks onto the free list. */ - lock_head = &lrp->free_locks; - for (i = 0; i++ < newlocks; - curaddr += ALIGN(sizeof(struct __db_lock), MUTEX_ALIGNMENT)) { - newl = (struct __db_lock *)curaddr; - SH_TAILQ_INSERT_HEAD(lock_head, newl, links, __db_lock); - } - - /* Put new objects onto the free list. */ - obj_head = &lrp->free_objs; - for (i = 0; i++ < newobjs; curaddr += sizeof(DB_LOCKOBJ)) { - op = (DB_LOCKOBJ *)curaddr; - SH_TAILQ_INSERT_HEAD(obj_head, op, links, __db_lockobj); - } - - *((size_t *)curaddr) = newmem - sizeof(size_t); - curaddr += sizeof(size_t); - __db_shalloc_free(lt->mem, curaddr); - - return (0); -} - -static void -__lock_reset_region(lt) - DB_LOCKTAB *lt; -{ - lt->conflicts = (u_int8_t *)lt->region + sizeof(DB_LOCKREGION); - lt->hashtab = - (DB_HASHTAB *)((u_int8_t *)lt->region + lt->region->hash_off); - lt->mem = (void *)((u_int8_t *)lt->region + lt->region->mem_off); -} - -/* - * lock_stat -- - * Return LOCK statistics. - */ -int -lock_stat(lt, gspp, db_malloc) - DB_LOCKTAB *lt; - DB_LOCK_STAT **gspp; - void *(*db_malloc) __P((size_t)); -{ - DB_LOCKREGION *rp; - int ret; - - *gspp = NULL; - - LOCK_PANIC_CHECK(lt); - - if ((ret = __os_malloc(sizeof(**gspp), db_malloc, gspp)) != 0) - return (ret); - - /* Copy out the global statistics. */ - LOCK_LOCKREGION(lt); - - rp = lt->region; - (*gspp)->st_magic = rp->magic; - (*gspp)->st_version = rp->version; - (*gspp)->st_maxlocks = rp->maxlocks; - (*gspp)->st_nmodes = rp->nmodes; - (*gspp)->st_numobjs = rp->numobjs; - (*gspp)->st_nlockers = rp->nlockers; - (*gspp)->st_nconflicts = rp->nconflicts; - (*gspp)->st_nrequests = rp->nrequests; - (*gspp)->st_nreleases = rp->nreleases; - (*gspp)->st_ndeadlocks = rp->ndeadlocks; - (*gspp)->st_region_nowait = rp->hdr.lock.mutex_set_nowait; - (*gspp)->st_region_wait = rp->hdr.lock.mutex_set_wait; - (*gspp)->st_refcnt = rp->hdr.refcnt; - (*gspp)->st_regsize = rp->hdr.size; - - UNLOCK_LOCKREGION(lt); - - return (0); -} - -static u_int32_t -__lock_count_locks(lrp) - DB_LOCKREGION *lrp; -{ - struct __db_lock *newl; - u_int32_t count; - - count = 0; - for (newl = SH_TAILQ_FIRST(&lrp->free_locks, __db_lock); - newl != NULL; - newl = SH_TAILQ_NEXT(newl, links, __db_lock)) - count++; - - return (count); -} - -static u_int32_t -__lock_count_objs(lrp) - DB_LOCKREGION *lrp; -{ - DB_LOCKOBJ *obj; - u_int32_t count; - - count = 0; - for (obj = SH_TAILQ_FIRST(&lrp->free_objs, __db_lockobj); - obj != NULL; - obj = SH_TAILQ_NEXT(obj, links, __db_lockobj)) - count++; - - return (count); -} - -#define LOCK_DUMP_CONF 0x001 /* Conflict matrix. */ -#define LOCK_DUMP_FREE 0x002 /* Display lock free list. */ -#define LOCK_DUMP_LOCKERS 0x004 /* Display lockers. */ -#define LOCK_DUMP_MEM 0x008 /* Display region memory. */ -#define LOCK_DUMP_OBJECTS 0x010 /* Display objects. */ -#define LOCK_DUMP_ALL 0x01f /* Display all. */ - -/* - * __lock_dump_region -- - * - * PUBLIC: void __lock_dump_region __P((DB_LOCKTAB *, char *, FILE *)); - */ -void -__lock_dump_region(lt, area, fp) - DB_LOCKTAB *lt; - char *area; - FILE *fp; -{ - struct __db_lock *lp; - DB_LOCKOBJ *op; - DB_LOCKREGION *lrp; - u_int32_t flags, i, j; - int label; - - /* Make it easy to call from the debugger. */ - if (fp == NULL) - fp = stderr; - - for (flags = 0; *area != '\0'; ++area) - switch (*area) { - case 'A': - LF_SET(LOCK_DUMP_ALL); - break; - case 'c': - LF_SET(LOCK_DUMP_CONF); - break; - case 'f': - LF_SET(LOCK_DUMP_FREE); - break; - case 'l': - LF_SET(LOCK_DUMP_LOCKERS); - break; - case 'm': - LF_SET(LOCK_DUMP_MEM); - break; - case 'o': - LF_SET(LOCK_DUMP_OBJECTS); - break; - } - - lrp = lt->region; - - fprintf(fp, "%s\nLock region parameters\n", DB_LINE); - fprintf(fp, "%s: %lu, %s: %lu, %s: %lu, %s: %lu\n%s: %lu, %s: %lu\n", - "table size", (u_long)lrp->table_size, - "hash_off", (u_long)lrp->hash_off, - "increment", (u_long)lrp->increment, - "mem_off", (u_long)lrp->mem_off, - "mem_bytes", (u_long)lrp->mem_bytes, - "need_dd", (u_long)lrp->need_dd); - - if (LF_ISSET(LOCK_DUMP_CONF)) { - fprintf(fp, "\n%s\nConflict matrix\n", DB_LINE); - for (i = 0; i < lrp->nmodes; i++) { - for (j = 0; j < lrp->nmodes; j++) - fprintf(fp, "%lu\t", - (u_long)lt->conflicts[i * lrp->nmodes + j]); - fprintf(fp, "\n"); - } - } - - if (LF_ISSET(LOCK_DUMP_LOCKERS | LOCK_DUMP_OBJECTS)) { - fprintf(fp, "%s\nLock hash buckets\n", DB_LINE); - for (i = 0; i < lrp->table_size; i++) { - label = 1; - for (op = SH_TAILQ_FIRST(<->hashtab[i], __db_lockobj); - op != NULL; - op = SH_TAILQ_NEXT(op, links, __db_lockobj)) { - if (LF_ISSET(LOCK_DUMP_LOCKERS) && - op->type == DB_LOCK_LOCKER) { - if (label) { - fprintf(fp, - "Bucket %lu:\n", (u_long)i); - label = 0; - } - __lock_dump_locker(lt, op, fp); - } - if (LF_ISSET(LOCK_DUMP_OBJECTS) && - op->type == DB_LOCK_OBJTYPE) { - if (label) { - fprintf(fp, - "Bucket %lu:\n", (u_long)i); - label = 0; - } - __lock_dump_object(lt, op, fp); - } - } - } - } - - if (LF_ISSET(LOCK_DUMP_FREE)) { - fprintf(fp, "%s\nLock free list\n", DB_LINE); - for (lp = SH_TAILQ_FIRST(&lrp->free_locks, __db_lock); - lp != NULL; - lp = SH_TAILQ_NEXT(lp, links, __db_lock)) - fprintf(fp, "0x%lx: %lu\t%lu\t%s\t0x%lx\n", (u_long)lp, - (u_long)lp->holder, (u_long)lp->mode, - __lock_dump_status(lp->status), (u_long)lp->obj); - - fprintf(fp, "%s\nObject free list\n", DB_LINE); - for (op = SH_TAILQ_FIRST(&lrp->free_objs, __db_lockobj); - op != NULL; - op = SH_TAILQ_NEXT(op, links, __db_lockobj)) - fprintf(fp, "0x%lx\n", (u_long)op); - } - - if (LF_ISSET(LOCK_DUMP_MEM)) - __db_shalloc_dump(lt->mem, fp); -} - -static void -__lock_dump_locker(lt, op, fp) - DB_LOCKTAB *lt; - DB_LOCKOBJ *op; - FILE *fp; -{ - struct __db_lock *lp; - u_int32_t locker; - void *ptr; - - ptr = SH_DBT_PTR(&op->lockobj); - memcpy(&locker, ptr, sizeof(u_int32_t)); - fprintf(fp, "L %lx", (u_long)locker); - - lp = SH_LIST_FIRST(&op->heldby, __db_lock); - if (lp == NULL) { - fprintf(fp, "\n"); - return; - } - for (; lp != NULL; lp = SH_LIST_NEXT(lp, locker_links, __db_lock)) - __lock_printlock(lt, lp, 0); -} - -static void -__lock_dump_object(lt, op, fp) - DB_LOCKTAB *lt; - DB_LOCKOBJ *op; - FILE *fp; -{ - struct __db_lock *lp; - u_int32_t j; - u_int8_t *ptr; - u_int ch; - - ptr = SH_DBT_PTR(&op->lockobj); - for (j = 0; j < op->lockobj.size; ptr++, j++) { - ch = *ptr; - fprintf(fp, isprint(ch) ? "%c" : "\\%o", ch); - } - fprintf(fp, "\n"); - - fprintf(fp, "H:"); - for (lp = - SH_TAILQ_FIRST(&op->holders, __db_lock); - lp != NULL; - lp = SH_TAILQ_NEXT(lp, links, __db_lock)) - __lock_printlock(lt, lp, 0); - lp = SH_TAILQ_FIRST(&op->waiters, __db_lock); - if (lp != NULL) { - fprintf(fp, "\nW:"); - for (; lp != NULL; lp = SH_TAILQ_NEXT(lp, links, __db_lock)) - __lock_printlock(lt, lp, 0); - } -} - -static const char * -__lock_dump_status(status) - db_status_t status; -{ - switch (status) { - case DB_LSTAT_ABORTED: - return ("aborted"); - case DB_LSTAT_ERR: - return ("err"); - case DB_LSTAT_FREE: - return ("free"); - case DB_LSTAT_HELD: - return ("held"); - case DB_LSTAT_NOGRANT: - return ("nogrant"); - case DB_LSTAT_PENDING: - return ("pending"); - case DB_LSTAT_WAITING: - return ("waiting"); - } - return ("unknown status"); -} diff --git a/db2/lock/lock_util.c b/db2/lock/lock_util.c deleted file mode 100644 index 29da75b..0000000 --- a/db2/lock/lock_util.c +++ /dev/null @@ -1,152 +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[] = "@(#)lock_util.c 10.10 (Sleepycat) 9/20/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <string.h> -#endif - -#include "db_int.h" -#include "shqueue.h" -#include "db_page.h" -#include "db_shash.h" -#include "hash.h" -#include "lock.h" - -/* - * __lock_cmp -- - * This function is used to compare a DBT that is about to be entered - * into a hash table with an object already in the hash table. Note - * that it just returns true on equal and 0 on not-equal. Therefore - * this function cannot be used as a sort function; its purpose is to - * be used as a hash comparison function. - * - * PUBLIC: int __lock_cmp __P((const DBT *, DB_LOCKOBJ *)); - */ -int -__lock_cmp(dbt, lock_obj) - const DBT *dbt; - DB_LOCKOBJ *lock_obj; -{ - void *obj_data; - - if (lock_obj->type != DB_LOCK_OBJTYPE) - return (0); - - obj_data = SH_DBT_PTR(&lock_obj->lockobj); - return (dbt->size == lock_obj->lockobj.size && - memcmp(dbt->data, obj_data, dbt->size) == 0); -} - -/* - * PUBLIC: int __lock_locker_cmp __P((u_int32_t, DB_LOCKOBJ *)); - */ -int -__lock_locker_cmp(locker, lock_obj) - u_int32_t locker; - DB_LOCKOBJ *lock_obj; -{ - void *obj_data; - - if (lock_obj->type != DB_LOCK_LOCKER) - return (0); - - obj_data = SH_DBT_PTR(&lock_obj->lockobj); - return (memcmp(&locker, obj_data, sizeof(u_int32_t)) == 0); -} - -/* - * The next two functions are the hash functions used to store objects in the - * lock hash table. They are hashing the same items, but one (__lock_ohash) - * takes a DBT (used for hashing a parameter passed from the user) and the - * other (__lock_lhash) takes a DB_LOCKOBJ (used for hashing something that is - * already in the lock manager). In both cases, we have a special check to - * fast path the case where we think we are doing a hash on a DB page/fileid - * pair. If the size is right, then we do the fast hash. - * - * We know that DB uses DB_LOCK_ILOCK types for its lock objects. The first - * four bytes are the 4-byte page number and the next DB_FILE_ID_LEN bytes - * are a unique file id, where the first 4 bytes on UNIX systems are the file - * inode number, and the first 4 bytes on Windows systems are the FileIndexLow - * bytes. So, we use the XOR of the page number and the first four bytes of - * the file id to produce a 32-bit hash value. - * - * We have no particular reason to believe that this algorithm will produce - * a good hash, but we want a fast hash more than we want a good one, when - * we're coming through this code path. - */ -#define FAST_HASH(P) { \ - u_int32_t __h; \ - u_int8_t *__cp, *__hp; \ - __hp = (u_int8_t *)&__h; \ - __cp = (u_int8_t *)(P); \ - __hp[0] = __cp[0] ^ __cp[4]; \ - __hp[1] = __cp[1] ^ __cp[5]; \ - __hp[2] = __cp[2] ^ __cp[6]; \ - __hp[3] = __cp[3] ^ __cp[7]; \ - return (__h); \ -} - -/* - * __lock_ohash -- - * - * PUBLIC: u_int32_t __lock_ohash __P((const DBT *)); - */ -u_int32_t -__lock_ohash(dbt) - const DBT *dbt; -{ - if (dbt->size == sizeof(DB_LOCK_ILOCK)) - FAST_HASH(dbt->data); - - return (__ham_func5(dbt->data, dbt->size)); -} - -/* - * __lock_lhash -- - * - * PUBLIC: u_int32_t __lock_lhash __P((DB_LOCKOBJ *)); - */ -u_int32_t -__lock_lhash(lock_obj) - DB_LOCKOBJ *lock_obj; -{ - u_int32_t tmp; - void *obj_data; - - obj_data = SH_DBT_PTR(&lock_obj->lockobj); - if (lock_obj->type == DB_LOCK_LOCKER) { - memcpy(&tmp, obj_data, sizeof(u_int32_t)); - return (tmp); - } - - if (lock_obj->lockobj.size == sizeof(DB_LOCK_ILOCK)) - FAST_HASH(obj_data); - - return (__ham_func5(obj_data, lock_obj->lockobj.size)); -} - -/* - * __lock_locker_hash -- - * Hash function for entering lockers into the hash table. Since these - * are simply 32-bit unsigned integers, just return the locker value. - * - * PUBLIC: u_int32_t __lock_locker_hash __P((u_int32_t)); - */ -u_int32_t -__lock_locker_hash(locker) - u_int32_t locker; -{ - return (locker); -} 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); -} diff --git a/db2/makedb.c b/db2/makedb.c deleted file mode 100644 index edc2c5f..0000000 --- a/db2/makedb.c +++ /dev/null @@ -1,387 +0,0 @@ -/* Create simple DB database from textual input. - Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include <argp.h> -#include <ctype.h> -#include <db.h> -#include <errno.h> -#include <error.h> -#include <fcntl.h> -#include <libintl.h> -#include <locale.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> - -/* Get libc version number. */ -#include "../version.h" - -#define PACKAGE _libc_intl_domainname - -/* If non-zero convert key to lower case. */ -static int to_lowercase; - -/* If non-zero print content of input file, one entry per line. */ -static int do_undo; - -/* If non-zero do not print informational messages. */ -static int be_quiet; - -/* Name of output file. */ -static const char *output_name; - -/* Name and version of program. */ -static void print_version (FILE *stream, struct argp_state *state); -void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version; - -/* Definitions of arguments for argp functions. */ -static const struct argp_option options[] = -{ - { "fold-case", 'f', NULL, 0, N_("Convert key to lower case") }, - { "output", 'o', N_("NAME"), 0, N_("Write output to file NAME") }, - { "quiet", 'q', NULL, 0, - N_("Do not print messages while building database") }, - { "undo", 'u', NULL, 0, - N_("Print content of database file, one entry a line") }, - { NULL, 0, NULL, 0, NULL } -}; - -/* Short description of program. */ -static const char doc[] = N_("Create simple DB database from textual input."); - -/* Strings for arguments in help texts. */ -static const char args_doc[] = N_("\ -INPUT-FILE OUTPUT-FILE\n-o OUTPUT-FILE INPUT-FILE\n-u INPUT-FILE"); - -/* Prototype for option handler. */ -static error_t parse_opt __P ((int key, char *arg, struct argp_state *state)); - -/* Function to print some extra text in the help message. */ -static char *more_help __P ((int key, const char *text, void *input)); - -/* Data structure to communicate with argp functions. */ -static struct argp argp = -{ - options, parse_opt, args_doc, doc, NULL, more_help -}; - - -/* Prototypes for local functions. */ -static int process_input __P ((FILE *input, const char *inname, DB *output, - int to_lowercase, int be_quiet)); -static int print_database __P ((DB *db)); -int main __P ((int argc, char *argv[])); - - -int -main (argc, argv) - int argc; - char *argv[]; -{ - const char *input_name; - FILE *input_file; - DB *db_file; - int status; - int remaining; - int mode = 0666; - - /* Set locale via LC_ALL. */ - setlocale (LC_ALL, ""); - - /* Set the text message domain. */ - textdomain (_libc_intl_domainname); - - /* Initialize local variables. */ - input_name = NULL; - - /* Parse and process arguments. */ - argp_parse (&argp, argc, argv, 0, &remaining, NULL); - - /* Determine file names. */ - if (do_undo || output_name != NULL) - { - if (remaining + 1 != argc) - { - wrong_arguments: - error (0, 0, gettext ("wrong number of arguments")); - argp_help (&argp, stdout, ARGP_HELP_SEE, - program_invocation_short_name); - exit (1); - } - input_name = argv[remaining]; - } - else - { - if (remaining + 2 != argc) - goto wrong_arguments; - - input_name = argv[remaining++]; - output_name = argv[remaining]; - } - - /* Special handling if we are asked to print the database. */ - if (do_undo) - { - status = db_open (input_name, DB_BTREE, DB_RDONLY, 0666, NULL, NULL, - &db_file); - if (status != 0) - error (EXIT_FAILURE, 0, gettext ("cannot open database file `%s': %s"), - input_name, - (status == EINVAL ? gettext ("incorrectly formatted file") - : strerror (status))); - - status = print_database (db_file); - - db_file->close (db_file, 0); - - return status; - } - - /* Open input file. */ - if (strcmp (input_name, "-") == 0 || strcmp (input_name, "/dev/stdin") == 0) - input_file = stdin; - else - { - struct stat st; - - input_file = fopen (input_name, "r"); - if (input_file == NULL) - error (EXIT_FAILURE, errno, gettext ("cannot open input file `%s'"), - input_name); - - /* Get the access rights from the source file. The output file should - have the same. */ - if (fstat (fileno (input_file), &st) >= 0) - mode = st.st_mode & ACCESSPERMS; - } - - /* Open output file. This must not be standard output so we don't - handle "-" and "/dev/stdout" special. */ - status = db_open (output_name, DB_BTREE, DB_CREATE | DB_TRUNCATE, mode, - NULL, NULL, &db_file); - if (status != 0) - error (EXIT_FAILURE, status, gettext ("cannot open output file `%s'"), - output_name); - - /* Start the real work. */ - status = process_input (input_file, input_name, db_file, to_lowercase, - be_quiet); - - /* Close files. */ - if (input_file != stdin) - fclose (input_file); - db_file->close (db_file, 0); - - return status; -} - - -/* Handle program arguments. */ -static error_t -parse_opt (int key, char *arg, struct argp_state *state) -{ - switch (key) - { - case 'f': - to_lowercase = 1; - break; - case 'o': - output_name = arg; - break; - case 'q': - be_quiet = 1; - break; - case 'u': - do_undo = 1; - break; - default: - return ARGP_ERR_UNKNOWN; - } - return 0; -} - - -static char * -more_help (int key, const char *text, void *input) -{ - switch (key) - { - case ARGP_KEY_HELP_EXTRA: - /* We print some extra information. */ - return strdup (gettext ("\ -Report bugs using the `glibcbug' script to <bugs@gnu.org>.\n")); - default: - break; - } - return (char *) text; -} - -/* Print the version information. */ -static void -print_version (FILE *stream, struct argp_state *state) -{ - fprintf (stream, "makedb (GNU %s) %s\n", PACKAGE, VERSION); - fprintf (stream, gettext ("\ -Copyright (C) %s Free Software Foundation, Inc.\n\ -This is free software; see the source for copying conditions. There is NO\n\ -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ -"), "1999"); - fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper"); -} - - -static int -process_input (input, inname, output, to_lowercase, be_quiet) - FILE *input; - const char *inname; - DB *output; - int to_lowercase; - int be_quiet; -{ - char *line; - size_t linelen; - int status; - size_t linenr; - - line = NULL; - linelen = 0; - status = EXIT_SUCCESS; - linenr = 0; - - while (!feof (input)) - { - DBT key; - DBT val; - char *cp; - int n; - - n = getline (&line, &linelen, input); - if (n < 0) - /* This means end of file or some bug. */ - break; - if (n == 0) - /* Short read. Probably interrupted system call. */ - continue; - - ++linenr; - - if (line[n - 1] == '\n') - /* Remove trailing newline. */ - line[--n] = '\0'; - - cp = line; - while (isspace (*cp)) - ++cp; - - if (*cp == '#') - /* First non-space character in line '#': it's a comment. */ - continue; - - key.data = cp; - while (*cp != '\0' && !isspace (*cp)) - { - if (to_lowercase) - *cp = tolower (*cp); - ++cp; - } - - if (key.data == cp) - /* It's an empty line. */ - continue; - - key.size = cp - (char *) key.data; - key.flags = 0; - - while (isspace (*cp)) - ++cp; - - val.data = cp; - val.size = (&line[n] - cp) + 1; - val.flags = 0; - - /* Store the value. */ - status = output->put (output, NULL, &key, &val, DB_NOOVERWRITE); - if (status != 0) - { - if (status == DB_KEYEXIST) - { - if (!be_quiet) - error_at_line (0, 0, inname, linenr, - gettext ("duplicate key")); - /* This is no real error. Just give a warning. */ - status = 0; - continue; - } - else - error (0, status, gettext ("while writing database file")); - - status = EXIT_FAILURE; - - clearerr (input); - break; - } - } - - if (ferror (input)) - { - error (0, 0, gettext ("problems while reading `%s'"), inname); - status = EXIT_FAILURE; - } - - return status; -} - - -static int -print_database (db) - DB *db; -{ - DBT key; - DBT val; - DBC *cursor; - int status; - - status = db->cursor (db, NULL, &cursor, 0); - if (status != 0) - { - error (0, status, gettext ("while reading database")); - return EXIT_FAILURE; - } - - key.flags = 0; - val.flags = 0; - status = cursor->c_get (cursor, &key, &val, DB_FIRST); - while (status == 0) - { - printf ("%.*s %s\n", (int) key.size, (char *) key.data, - (char *) val.data); - - status = cursor->c_get (cursor, &key, &val, DB_NEXT); - } - - if (status != DB_NOTFOUND) - { - error (0, status, gettext ("while reading database")); - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} diff --git a/db2/mp/mp_bh.c b/db2/mp/mp_bh.c deleted file mode 100644 index 12c5341..0000000 --- a/db2/mp/mp_bh.c +++ /dev/null @@ -1,592 +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[] = "@(#)mp_bh.c 10.45 (Sleepycat) 11/25/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_shash.h" -#include "mp.h" -#include "common_ext.h" - -static int __memp_upgrade __P((DB_MPOOL *, DB_MPOOLFILE *, MPOOLFILE *)); - -/* - * __memp_bhwrite -- - * Write the page associated with a given bucket header. - * - * PUBLIC: int __memp_bhwrite - * PUBLIC: __P((DB_MPOOL *, MPOOLFILE *, BH *, int *, int *)); - */ -int -__memp_bhwrite(dbmp, mfp, bhp, restartp, wrotep) - DB_MPOOL *dbmp; - MPOOLFILE *mfp; - BH *bhp; - int *restartp, *wrotep; -{ - DB_MPOOLFILE *dbmfp; - DB_MPREG *mpreg; - int incremented, ret; - - if (restartp != NULL) - *restartp = 0; - if (wrotep != NULL) - *wrotep = 0; - incremented = 0; - - /* - * Walk the process' DB_MPOOLFILE list and find a file descriptor for - * the file. We also check that the descriptor is open for writing. - * If we find a descriptor on the file that's not open for writing, we - * try and upgrade it to make it writeable. If that fails, we're done. - */ - LOCKHANDLE(dbmp, dbmp->mutexp); - for (dbmfp = TAILQ_FIRST(&dbmp->dbmfq); - dbmfp != NULL; dbmfp = TAILQ_NEXT(dbmfp, q)) - if (dbmfp->mfp == mfp) { - if (F_ISSET(dbmfp, MP_READONLY) && - __memp_upgrade(dbmp, dbmfp, mfp)) { - UNLOCKHANDLE(dbmp, dbmp->mutexp); - return (0); - } - - /* - * Increment the reference count -- see the comment in - * memp_fclose(). - */ - ++dbmfp->ref; - incremented = 1; - break; - } - UNLOCKHANDLE(dbmp, dbmp->mutexp); - if (dbmfp != NULL) - goto found; - - /* - * It's not a page from a file we've opened. If the file requires - * input/output processing, see if this process has ever registered - * information as to how to write this type of file. If not, there's - * nothing we can do. - */ - if (mfp->ftype != 0) { - LOCKHANDLE(dbmp, dbmp->mutexp); - for (mpreg = LIST_FIRST(&dbmp->dbregq); - mpreg != NULL; mpreg = LIST_NEXT(mpreg, q)) - if (mpreg->ftype == mfp->ftype) - break; - UNLOCKHANDLE(dbmp, dbmp->mutexp); - if (mpreg == NULL) - return (0); - } - - /* - * Try and open the file, attaching to the underlying shared area. - * - * XXX - * Don't try to attach to temporary files. There are two problems in - * trying to do that. First, if we have different privileges than the - * process that "owns" the temporary file, we might create the backing - * disk file such that the owning process couldn't read/write its own - * buffers, e.g., memp_trickle() running as root creating a file owned - * as root, mode 600. Second, if the temporary file has already been - * created, we don't have any way of finding out what its real name is, - * and, even if we did, it was already unlinked (so that it won't be - * left if the process dies horribly). This decision causes a problem, - * however: if the temporary file consumes the entire buffer cache, - * and the owner doesn't flush the buffers to disk, we could end up - * with resource starvation, and the memp_trickle() thread couldn't do - * anything about it. That's a pretty unlikely scenario, though. - * - * XXX - * There's no negative cache, so we may repeatedly try and open files - * that we have previously tried (and failed) to open. - * - * Ignore any error, assume it's a permissions problem. - */ - if (F_ISSET(mfp, MP_TEMP)) - return (0); - - if (__memp_fopen(dbmp, mfp, R_ADDR(dbmp, mfp->path_off), - 0, 0, mfp->stat.st_pagesize, 0, NULL, &dbmfp) != 0) - return (0); - -found: ret = __memp_pgwrite(dbmfp, bhp, restartp, wrotep); - - if (incremented) { - LOCKHANDLE(dbmp, dbmp->mutexp); - --dbmfp->ref; - UNLOCKHANDLE(dbmp, dbmp->mutexp); - } - - return (ret); -} - -/* - * __memp_pgread -- - * Read a page from a file. - * - * PUBLIC: int __memp_pgread __P((DB_MPOOLFILE *, BH *, int)); - */ -int -__memp_pgread(dbmfp, bhp, can_create) - DB_MPOOLFILE *dbmfp; - BH *bhp; - int can_create; -{ - DB_IO db_io; - DB_MPOOL *dbmp; - MPOOLFILE *mfp; - size_t len, pagesize; - ssize_t nr; - int created, ret; - - dbmp = dbmfp->dbmp; - mfp = dbmfp->mfp; - pagesize = mfp->stat.st_pagesize; - - F_SET(bhp, BH_LOCKED | BH_TRASH); - LOCKBUFFER(dbmp, bhp); - UNLOCKREGION(dbmp); - - /* - * Temporary files may not yet have been created. We don't create - * them now, we create them when the pages have to be flushed. - */ - nr = 0; - if (dbmfp->fd == -1) - ret = 0; - else { - /* - * Ignore read errors if we have permission to create the page. - * Assume that the page doesn't exist, and that we'll create it - * when we write it out. - */ - db_io.fd_io = dbmfp->fd; - db_io.fd_lock = dbmp->reginfo.fd; - db_io.mutexp = - F_ISSET(dbmp, MP_LOCKHANDLE) ? dbmfp->mutexp : NULL; - db_io.pagesize = db_io.bytes = pagesize; - db_io.pgno = bhp->pgno; - db_io.buf = bhp->buf; - - ret = __os_io(&db_io, DB_IO_READ, &nr); - } - - created = 0; - if (nr < (ssize_t)pagesize) { - if (can_create) - created = 1; - else { - /* If we had a short read, ret may be 0. */ - if (ret == 0) - ret = EIO; - __db_err(dbmp->dbenv, - "%s: page %lu doesn't exist, create flag not set", - __memp_fn(dbmfp), (u_long)bhp->pgno); - goto err; - } - } - - /* - * Clear any bytes we didn't read that need to be cleared. If we're - * running in diagnostic mode, smash any bytes on the page that are - * unknown quantities for the caller. - */ - if (nr != (ssize_t)pagesize) { - len = mfp->clear_len == 0 ? pagesize : mfp->clear_len; - if (nr < (ssize_t)len) - memset(bhp->buf + nr, 0, len - nr); -#ifdef DIAGNOSTIC - if (nr > (ssize_t)len) - len = nr; - if (len < pagesize) - memset(bhp->buf + len, 0xdb, pagesize - len); -#endif - } - - /* Call any pgin function. */ - ret = mfp->ftype == 0 ? 0 : __memp_pg(dbmfp, bhp, 1); - - /* Unlock the buffer and reacquire the region lock. */ -err: UNLOCKBUFFER(dbmp, bhp); - LOCKREGION(dbmp); - - /* - * If no errors occurred, the data is now valid, clear the BH_TRASH - * flag; regardless, clear the lock bit and let other threads proceed. - */ - F_CLR(bhp, BH_LOCKED); - if (ret == 0) { - F_CLR(bhp, BH_TRASH); - - /* Update the statistics. */ - if (created) { - ++dbmp->mp->stat.st_page_create; - ++mfp->stat.st_page_create; - } else { - ++dbmp->mp->stat.st_page_in; - ++mfp->stat.st_page_in; - } - } - - return (ret); -} - -/* - * __memp_pgwrite -- - * Write a page to a file. - * - * PUBLIC: int __memp_pgwrite __P((DB_MPOOLFILE *, BH *, int *, int *)); - */ -int -__memp_pgwrite(dbmfp, bhp, restartp, wrotep) - DB_MPOOLFILE *dbmfp; - BH *bhp; - int *restartp, *wrotep; -{ - DB_ENV *dbenv; - DB_IO db_io; - DB_LOG *lg_info; - DB_LSN lsn; - DB_MPOOL *dbmp; - MPOOL *mp; - MPOOLFILE *mfp; - ssize_t nw; - int callpgin, ret, syncfail; - const char *fail; - - dbmp = dbmfp->dbmp; - dbenv = dbmp->dbenv; - mp = dbmp->mp; - mfp = dbmfp->mfp; - - if (restartp != NULL) - *restartp = 0; - if (wrotep != NULL) - *wrotep = 0; - callpgin = 0; - - /* - * Check the dirty bit -- this buffer may have been written since we - * decided to write it. - */ - if (!F_ISSET(bhp, BH_DIRTY)) { - if (wrotep != NULL) - *wrotep = 1; - return (0); - } - - LOCKBUFFER(dbmp, bhp); - - /* - * If there were two writers, we may have just been waiting while the - * other writer completed I/O on this buffer. Check the dirty bit one - * more time. - */ - if (!F_ISSET(bhp, BH_DIRTY)) { - UNLOCKBUFFER(dbmp, bhp); - - if (wrotep != NULL) - *wrotep = 1; - return (0); - } - - F_SET(bhp, BH_LOCKED); - UNLOCKREGION(dbmp); - - if (restartp != NULL) - *restartp = 1; - - /* Copy the LSN off the page if we're going to need it. */ - lg_info = dbenv->lg_info; - if (lg_info != NULL || F_ISSET(bhp, BH_WRITE)) - memcpy(&lsn, bhp->buf + mfp->lsn_off, sizeof(DB_LSN)); - - /* Ensure the appropriate log records are on disk. */ - if (lg_info != NULL && (ret = log_flush(lg_info, &lsn)) != 0) - goto err; - - /* - * Call any pgout function. We set the callpgin flag so that we flag - * that the contents of the buffer will need to be passed through pgin - * before they are reused. - */ - if (mfp->ftype == 0) - ret = 0; - else { - callpgin = 1; - if ((ret = __memp_pg(dbmfp, bhp, 0)) != 0) - goto err; - } - - /* Temporary files may not yet have been created. */ - if (dbmfp->fd == -1) { - LOCKHANDLE(dbmp, dbmfp->mutexp); - if (dbmfp->fd == -1 && ((ret = __db_appname(dbenv, - DB_APP_TMP, NULL, NULL, DB_CREATE | DB_EXCL | DB_TEMPORARY, - &dbmfp->fd, NULL)) != 0 || dbmfp->fd == -1)) { - UNLOCKHANDLE(dbmp, dbmfp->mutexp); - __db_err(dbenv, - "unable to create temporary backing file"); - goto err; - } - UNLOCKHANDLE(dbmp, dbmfp->mutexp); - } - - /* Write the page. */ - db_io.fd_io = dbmfp->fd; - db_io.fd_lock = dbmp->reginfo.fd; - db_io.mutexp = F_ISSET(dbmp, MP_LOCKHANDLE) ? dbmfp->mutexp : NULL; - db_io.pagesize = db_io.bytes = mfp->stat.st_pagesize; - db_io.pgno = bhp->pgno; - db_io.buf = bhp->buf; - if ((ret = __os_io(&db_io, DB_IO_WRITE, &nw)) != 0) { - __db_panic(dbenv, ret); - fail = "write"; - goto syserr; - } - if (nw != (ssize_t)mfp->stat.st_pagesize) { - ret = EIO; - fail = "write"; - goto syserr; - } - - if (wrotep != NULL) - *wrotep = 1; - - /* Unlock the buffer and reacquire the region lock. */ - UNLOCKBUFFER(dbmp, bhp); - LOCKREGION(dbmp); - - /* - * Clean up the flags based on a successful write. - * - * If we rewrote the page, it will need processing by the pgin - * routine before reuse. - */ - if (callpgin) - F_SET(bhp, BH_CALLPGIN); - F_CLR(bhp, BH_DIRTY | BH_LOCKED); - - /* - * If we write a buffer for which a checkpoint is waiting, update - * the count of pending buffers (both in the mpool as a whole and - * for this file). If the count for this file goes to zero, flush - * the writes. - * - * XXX: - * Don't lock the region around the sync, fsync(2) has no atomicity - * issues. - * - * XXX: - * We ignore errors from the sync -- it makes no sense to return an - * error to the calling process, so set a flag causing the checkpoint - * to be retried later. - */ - if (F_ISSET(bhp, BH_WRITE)) { - if (mfp->lsn_cnt == 1) { - UNLOCKREGION(dbmp); - syncfail = __os_fsync(dbmfp->fd) != 0; - LOCKREGION(dbmp); - if (syncfail) - F_SET(mp, MP_LSN_RETRY); - - } - - F_CLR(bhp, BH_WRITE); - - /* - * If the buffer just written has a larger LSN than the current - * max LSN written for this checkpoint, update the saved value. - */ - if (log_compare(&lsn, &mp->lsn) > 0) - mp->lsn = lsn; - - --mp->lsn_cnt; - --mfp->lsn_cnt; - } - - /* Update the page clean/dirty statistics. */ - ++mp->stat.st_page_clean; - --mp->stat.st_page_dirty; - - /* Update I/O statistics. */ - ++mp->stat.st_page_out; - ++mfp->stat.st_page_out; - - return (0); - -syserr: __db_err(dbenv, "%s: %s failed for page %lu", - __memp_fn(dbmfp), fail, (u_long)bhp->pgno); - -err: /* Unlock the buffer and reacquire the region lock. */ - UNLOCKBUFFER(dbmp, bhp); - LOCKREGION(dbmp); - - /* - * Clean up the flags based on a failure. - * - * The page remains dirty but we remove our lock. If we rewrote the - * page, it will need processing by the pgin routine before reuse. - */ - if (callpgin) - F_SET(bhp, BH_CALLPGIN); - F_CLR(bhp, BH_LOCKED); - - return (ret); -} - -/* - * __memp_pg -- - * Call the pgin/pgout routine. - * - * PUBLIC: int __memp_pg __P((DB_MPOOLFILE *, BH *, int)); - */ -int -__memp_pg(dbmfp, bhp, is_pgin) - DB_MPOOLFILE *dbmfp; - BH *bhp; - int is_pgin; -{ - DBT dbt, *dbtp; - DB_MPOOL *dbmp; - DB_MPREG *mpreg; - MPOOLFILE *mfp; - int ftype, ret; - - dbmp = dbmfp->dbmp; - mfp = dbmfp->mfp; - - LOCKHANDLE(dbmp, dbmp->mutexp); - - ftype = mfp->ftype; - for (mpreg = LIST_FIRST(&dbmp->dbregq); - mpreg != NULL; mpreg = LIST_NEXT(mpreg, q)) { - if (ftype != mpreg->ftype) - continue; - if (mfp->pgcookie_len == 0) - dbtp = NULL; - else { - dbt.size = mfp->pgcookie_len; - dbt.data = R_ADDR(dbmp, mfp->pgcookie_off); - dbtp = &dbt; - } - UNLOCKHANDLE(dbmp, dbmp->mutexp); - - if (is_pgin) { - if (mpreg->pgin != NULL && (ret = - mpreg->pgin(bhp->pgno, bhp->buf, dbtp)) != 0) - goto err; - } else - if (mpreg->pgout != NULL && (ret = - mpreg->pgout(bhp->pgno, bhp->buf, dbtp)) != 0) - goto err; - break; - } - - if (mpreg == NULL) - UNLOCKHANDLE(dbmp, dbmp->mutexp); - - return (0); - -err: UNLOCKHANDLE(dbmp, dbmp->mutexp); - __db_err(dbmp->dbenv, "%s: %s failed for page %lu", - __memp_fn(dbmfp), is_pgin ? "pgin" : "pgout", (u_long)bhp->pgno); - return (ret); -} - -/* - * __memp_bhfree -- - * Free a bucket header and its referenced data. - * - * PUBLIC: void __memp_bhfree __P((DB_MPOOL *, MPOOLFILE *, BH *, int)); - */ -void -__memp_bhfree(dbmp, mfp, bhp, free_mem) - DB_MPOOL *dbmp; - MPOOLFILE *mfp; - BH *bhp; - int free_mem; -{ - size_t off; - - /* Delete the buffer header from the hash bucket queue. */ - off = BUCKET(dbmp->mp, R_OFFSET(dbmp, mfp), bhp->pgno); - SH_TAILQ_REMOVE(&dbmp->htab[off], bhp, hq, __bh); - - /* Delete the buffer header from the LRU queue. */ - SH_TAILQ_REMOVE(&dbmp->mp->bhq, bhp, q, __bh); - - /* - * If we're not reusing it immediately, free the buffer header - * and data for real. - */ - if (free_mem) { - __db_shalloc_free(dbmp->addr, bhp); - --dbmp->mp->stat.st_page_clean; - } -} - -/* - * __memp_upgrade -- - * Upgrade a file descriptor from readonly to readwrite. - */ -static int -__memp_upgrade(dbmp, dbmfp, mfp) - DB_MPOOL *dbmp; - DB_MPOOLFILE *dbmfp; - MPOOLFILE *mfp; -{ - int fd, ret; - char *rpath; - - /* - * !!! - * We expect the handle to already be locked. - */ - - /* Check to see if we've already upgraded. */ - if (F_ISSET(dbmfp, MP_UPGRADE)) - return (0); - - /* Check to see if we've already failed. */ - if (F_ISSET(dbmfp, MP_UPGRADE_FAIL)) - return (1); - - /* - * Calculate the real name for this file and try to open it read/write. - * We know we have a valid pathname for the file because it's the only - * way we could have gotten a file descriptor of any kind. - */ - if ((ret = __db_appname(dbmp->dbenv, DB_APP_DATA, - NULL, R_ADDR(dbmp, mfp->path_off), 0, NULL, &rpath)) != 0) - return (ret); - if (__db_open(rpath, 0, 0, 0, &fd) != 0) { - F_SET(dbmfp, MP_UPGRADE_FAIL); - ret = 1; - } else { - /* Swap the descriptors and set the upgrade flag. */ - (void)__os_close(dbmfp->fd); - dbmfp->fd = fd; - F_SET(dbmfp, MP_UPGRADE); - ret = 0; - } - __os_freestr(rpath); - return (ret); -} diff --git a/db2/mp/mp_fget.c b/db2/mp/mp_fget.c deleted file mode 100644 index f159dc2..0000000 --- a/db2/mp/mp_fget.c +++ /dev/null @@ -1,352 +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[] = "@(#)mp_fget.c 10.53 (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 "db_shash.h" -#include "mp.h" -#include "common_ext.h" - -/* - * memp_fget -- - * Get a page from the file. - */ -int -memp_fget(dbmfp, pgnoaddr, flags, addrp) - DB_MPOOLFILE *dbmfp; - db_pgno_t *pgnoaddr; - u_int32_t flags; - void *addrp; -{ - BH *bhp; - DB_MPOOL *dbmp; - MPOOL *mp; - MPOOLFILE *mfp; - size_t bucket, mf_offset; - u_int32_t st_hsearch; - int b_incr, first, ret; - - dbmp = dbmfp->dbmp; - mp = dbmp->mp; - mfp = dbmfp->mfp; - - MP_PANIC_CHECK(dbmp); - - /* - * Validate arguments. - * - * !!! - * Don't test for DB_MPOOL_CREATE and DB_MPOOL_NEW flags for readonly - * files here, and create non-existent pages in readonly files if the - * flags are set, later. The reason is that the hash access method - * wants to get empty pages that don't really exist in readonly files. - * The only alternative is for hash to write the last "bucket" all the - * time, which we don't want to do because one of our big goals in life - * is to keep database files small. It's sleazy as hell, but we catch - * any attempt to actually write the file in memp_fput(). - */ -#define OKFLAGS (DB_MPOOL_CREATE | DB_MPOOL_LAST | DB_MPOOL_NEW) - if (flags != 0) { - if ((ret = - __db_fchk(dbmp->dbenv, "memp_fget", flags, OKFLAGS)) != 0) - return (ret); - - switch (flags) { - case DB_MPOOL_CREATE: - case DB_MPOOL_LAST: - case DB_MPOOL_NEW: - case 0: - break; - default: - return (__db_ferr(dbmp->dbenv, "memp_fget", 1)); - } - } - -#ifdef DIAGNOSTIC - /* - * XXX - * We want to switch threads as often as possible. Yield every time - * we get a new page to ensure contention. - */ - if (DB_GLOBAL(db_pageyield)) - __os_yield(1); -#endif - - /* Initialize remaining local variables. */ - mf_offset = R_OFFSET(dbmp, mfp); - bhp = NULL; - st_hsearch = 0; - b_incr = ret = 0; - - /* Determine the hash bucket where this page will live. */ - bucket = BUCKET(mp, mf_offset, *pgnoaddr); - - LOCKREGION(dbmp); - - /* - * Check for the last or last + 1 page requests. - * - * Examine and update the file's last_pgno value. We don't care if - * the last_pgno value immediately changes due to another thread -- - * at this instant in time, the value is correct. We do increment the - * current last_pgno value if the thread is asking for a new page, - * however, to ensure that two threads creating pages don't get the - * same one. - */ - if (LF_ISSET(DB_MPOOL_LAST | DB_MPOOL_NEW)) { - if (LF_ISSET(DB_MPOOL_NEW)) - ++mfp->last_pgno; - *pgnoaddr = mfp->last_pgno; - bucket = BUCKET(mp, mf_offset, mfp->last_pgno); - - if (LF_ISSET(DB_MPOOL_NEW)) - goto alloc; - } - - /* - * If mmap'ing the file and the page is not past the end of the file, - * just return a pointer. - * - * The page may be past the end of the file, so check the page number - * argument against the original length of the file. If we previously - * returned pages past the original end of the file, last_pgno will - * have been updated to match the "new" end of the file, and checking - * against it would return pointers past the end of the mmap'd region. - * - * If another process has opened the file for writing since we mmap'd - * it, we will start playing the game by their rules, i.e. everything - * goes through the cache. All pages previously returned will be safe, - * as long as the correct locking protocol was observed. - * - * XXX - * We don't discard the map because we don't know when all of the - * pages will have been discarded from the process' address space. - * It would be possible to do so by reference counting the open - * pages from the mmap, but it's unclear to me that it's worth it. - */ - if (dbmfp->addr != NULL && F_ISSET(mfp, MP_CAN_MMAP)) { - if (*pgnoaddr > mfp->orig_last_pgno) { - /* - * !!! - * See the comment above about non-existent pages and - * the hash access method. - */ - if (!LF_ISSET(DB_MPOOL_CREATE)) { - __db_err(dbmp->dbenv, - "%s: page %lu doesn't exist", - __memp_fn(dbmfp), (u_long)*pgnoaddr); - ret = EINVAL; - goto err; - } - } else { - *(void **)addrp = - R_ADDR(dbmfp, *pgnoaddr * mfp->stat.st_pagesize); - ++mp->stat.st_map; - ++mfp->stat.st_map; - goto done; - } - } - - /* Search the hash chain for the page. */ - for (bhp = SH_TAILQ_FIRST(&dbmp->htab[bucket], __bh); - bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, hq, __bh)) { - ++st_hsearch; - if (bhp->pgno != *pgnoaddr || bhp->mf_offset != mf_offset) - continue; - - /* Increment the reference count. */ - if (bhp->ref == UINT16_T_MAX) { - __db_err(dbmp->dbenv, - "%s: page %lu: reference count overflow", - __memp_fn(dbmfp), (u_long)bhp->pgno); - ret = EINVAL; - goto err; - } - - /* - * Increment the reference count. We may discard the region - * lock as we evaluate and/or read the buffer, so we need to - * ensure that it doesn't move and that its contents remain - * unchanged. - */ - ++bhp->ref; - b_incr = 1; - - /* - * Any buffer we find might be trouble. - * - * BH_LOCKED -- - * I/O is in progress. Because we've incremented the buffer - * reference count, we know the buffer can't move. Unlock - * the region lock, wait for the I/O to complete, and reacquire - * the region. - */ - for (first = 1; F_ISSET(bhp, BH_LOCKED); first = 0) { - UNLOCKREGION(dbmp); - - /* - * Explicitly yield the processor if it's not the first - * pass through this loop -- if we don't, we might end - * up running to the end of our CPU quantum as we will - * simply be swapping between the two locks. - */ - if (!first) - __os_yield(1); - - LOCKBUFFER(dbmp, bhp); - /* Wait for I/O to finish... */ - UNLOCKBUFFER(dbmp, bhp); - LOCKREGION(dbmp); - } - - /* - * BH_TRASH -- - * The contents of the buffer are garbage. Shouldn't happen, - * and this read is likely to fail, but might as well try. - */ - if (F_ISSET(bhp, BH_TRASH)) - goto reread; - - /* - * BH_CALLPGIN -- - * The buffer was converted so it could be written, and the - * contents need to be converted again. - */ - if (F_ISSET(bhp, BH_CALLPGIN)) { - if ((ret = __memp_pg(dbmfp, bhp, 1)) != 0) - goto err; - F_CLR(bhp, BH_CALLPGIN); - } - - ++mp->stat.st_cache_hit; - ++mfp->stat.st_cache_hit; - *(void **)addrp = bhp->buf; - goto done; - } - -alloc: /* Allocate new buffer header and data space. */ - if ((ret = __memp_alloc(dbmp, sizeof(BH) - - sizeof(u_int8_t) + mfp->stat.st_pagesize, NULL, &bhp)) != 0) - goto err; - -#ifdef DIAGNOSTIC - if ((ALIGNTYPE)bhp->buf & (sizeof(size_t) - 1)) { - __db_err(dbmp->dbenv, - "Internal error: BH data NOT size_t aligned."); - ret = EINVAL; - goto err; - } -#endif - /* Initialize the BH fields. */ - memset(bhp, 0, sizeof(BH)); - LOCKINIT(dbmp, &bhp->mutex); - bhp->ref = 1; - bhp->pgno = *pgnoaddr; - bhp->mf_offset = mf_offset; - - /* - * Prepend the bucket header to the head of the appropriate MPOOL - * bucket hash list. Append the bucket header to the tail of the - * MPOOL LRU chain. - */ - SH_TAILQ_INSERT_HEAD(&dbmp->htab[bucket], bhp, hq, __bh); - SH_TAILQ_INSERT_TAIL(&mp->bhq, bhp, q); - - /* - * If we created the page, zero it out and continue. - * - * !!! - * Note: DB_MPOOL_NEW specifically doesn't call the pgin function. - * If DB_MPOOL_CREATE is used, then the application's pgin function - * has to be able to handle pages of 0's -- if it uses DB_MPOOL_NEW, - * it can detect all of its page creates, and not bother. - * - * Otherwise, read the page into memory, optionally creating it if - * DB_MPOOL_CREATE is set. - */ - if (LF_ISSET(DB_MPOOL_NEW)) { - if (mfp->clear_len == 0) - memset(bhp->buf, 0, mfp->stat.st_pagesize); - else { - memset(bhp->buf, 0, mfp->clear_len); -#ifdef DIAGNOSTIC - memset(bhp->buf + mfp->clear_len, 0xdb, - mfp->stat.st_pagesize - mfp->clear_len); -#endif - } - - ++mp->stat.st_page_create; - ++mfp->stat.st_page_create; - } else { - /* - * It's possible for the read function to fail, which means - * that we fail as well. Note, the __memp_pgread() function - * discards the region lock, so the buffer must be pinned - * down so that it cannot move and its contents are unchanged. - */ -reread: if ((ret = __memp_pgread(dbmfp, - bhp, LF_ISSET(DB_MPOOL_CREATE))) != 0) { - /* - * !!! - * Discard the buffer unless another thread is waiting - * on our I/O to complete. Regardless, the header has - * the BH_TRASH flag set. - */ - if (bhp->ref == 1) - __memp_bhfree(dbmp, mfp, bhp, 1); - goto err; - } - - ++mp->stat.st_cache_miss; - ++mfp->stat.st_cache_miss; - } - - /* - * If we're returning a page after our current notion of the last-page, - * update our information. Note, there's no way to un-instantiate this - * page, it's going to exist whether it's returned to us dirty or not. - */ - if (bhp->pgno > mfp->last_pgno) - mfp->last_pgno = bhp->pgno; - - ++mp->stat.st_page_clean; - *(void **)addrp = bhp->buf; - -done: /* Update the chain search statistics. */ - if (st_hsearch) { - ++mp->stat.st_hash_searches; - if (st_hsearch > mp->stat.st_hash_longest) - mp->stat.st_hash_longest = st_hsearch; - mp->stat.st_hash_examined += st_hsearch; - } - - ++dbmfp->pinref; - - UNLOCKREGION(dbmp); - - return (0); - -err: /* Discard our reference. */ - if (b_incr) - --bhp->ref; - UNLOCKREGION(dbmp); - - *(void **)addrp = NULL; - return (ret); -} diff --git a/db2/mp/mp_fopen.c b/db2/mp/mp_fopen.c deleted file mode 100644 index dd02662..0000000 --- a/db2/mp/mp_fopen.c +++ /dev/null @@ -1,560 +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[] = "@(#)mp_fopen.c 10.60 (Sleepycat) 1/1/99"; -#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 "db_shash.h" -#include "mp.h" -#include "common_ext.h" - -static int __memp_mf_close __P((DB_MPOOL *, DB_MPOOLFILE *)); -static int __memp_mf_open __P((DB_MPOOL *, - const char *, size_t, db_pgno_t, DB_MPOOL_FINFO *, MPOOLFILE **)); - -/* - * memp_fopen -- - * Open a backing file for the memory pool. - */ -int -memp_fopen(dbmp, path, flags, mode, pagesize, finfop, retp) - DB_MPOOL *dbmp; - const char *path; - u_int32_t flags; - int mode; - size_t pagesize; - DB_MPOOL_FINFO *finfop; - DB_MPOOLFILE **retp; -{ - int ret; - - MP_PANIC_CHECK(dbmp); - - /* Validate arguments. */ - if ((ret = __db_fchk(dbmp->dbenv, - "memp_fopen", flags, DB_CREATE | DB_NOMMAP | DB_RDONLY)) != 0) - return (ret); - - /* Require a non-zero pagesize. */ - if (pagesize == 0) { - __db_err(dbmp->dbenv, "memp_fopen: pagesize not specified"); - return (EINVAL); - } - if (finfop != NULL && finfop->clear_len > pagesize) - return (EINVAL); - - return (__memp_fopen(dbmp, - NULL, path, flags, mode, pagesize, 1, finfop, retp)); -} - -/* - * __memp_fopen -- - * Open a backing file for the memory pool; internal version. - * - * PUBLIC: int __memp_fopen __P((DB_MPOOL *, MPOOLFILE *, const char *, - * PUBLIC: u_int32_t, int, size_t, int, DB_MPOOL_FINFO *, DB_MPOOLFILE **)); - */ -int -__memp_fopen(dbmp, mfp, path, flags, mode, pagesize, needlock, finfop, retp) - DB_MPOOL *dbmp; - MPOOLFILE *mfp; - const char *path; - u_int32_t flags; - int mode, needlock; - size_t pagesize; - DB_MPOOL_FINFO *finfop; - DB_MPOOLFILE **retp; -{ - DB_ENV *dbenv; - DB_MPOOLFILE *dbmfp; - DB_MPOOL_FINFO finfo; - db_pgno_t last_pgno; - size_t maxmap; - u_int32_t mbytes, bytes; - int ret; - u_int8_t idbuf[DB_FILE_ID_LEN]; - char *rpath; - - dbenv = dbmp->dbenv; - ret = 0; - rpath = NULL; - - /* - * If mfp is provided, we take the DB_MPOOL_FINFO information from - * the mfp. We don't bother initializing everything, because some - * of them are expensive to acquire. If no mfp is provided and the - * finfop argument is NULL, we default the values. - */ - if (finfop == NULL) { - memset(&finfo, 0, sizeof(finfo)); - if (mfp != NULL) { - finfo.ftype = mfp->ftype; - finfo.pgcookie = NULL; - finfo.fileid = NULL; - finfo.lsn_offset = mfp->lsn_off; - finfo.clear_len = mfp->clear_len; - } else { - finfo.ftype = 0; - finfo.pgcookie = NULL; - finfo.fileid = NULL; - finfo.lsn_offset = -1; - finfo.clear_len = 0; - } - finfop = &finfo; - } - - /* Allocate and initialize the per-process structure. */ - if ((ret = __os_calloc(1, sizeof(DB_MPOOLFILE), &dbmfp)) != 0) - return (ret); - dbmfp->dbmp = dbmp; - dbmfp->fd = -1; - dbmfp->ref = 1; - if (LF_ISSET(DB_RDONLY)) - F_SET(dbmfp, MP_READONLY); - - if (path == NULL) { - if (LF_ISSET(DB_RDONLY)) { - __db_err(dbenv, - "memp_fopen: temporary files can't be readonly"); - ret = EINVAL; - goto err; - } - last_pgno = 0; - } else { - /* Get the real name for this file and open it. */ - if ((ret = __db_appname(dbenv, - DB_APP_DATA, NULL, path, 0, NULL, &rpath)) != 0) - goto err; - if ((ret = __db_open(rpath, - LF_ISSET(DB_CREATE | DB_RDONLY), - DB_CREATE | DB_RDONLY, mode, &dbmfp->fd)) != 0) { - __db_err(dbenv, "%s: %s", rpath, strerror(ret)); - goto err; - } - - /* - * Don't permit files that aren't a multiple of the pagesize, - * and find the number of the last page in the file, all the - * time being careful not to overflow 32 bits. - * - * !!! - * We can't use off_t's here, or in any code in the mainline - * library for that matter. (We have to use them in the os - * stubs, of course, as there are system calls that take them - * as arguments.) The reason is that some customers build in - * environments where an off_t is 32-bits, but still run where - * offsets are 64-bits, and they pay us a lot of money. - */ - if ((ret = __os_ioinfo(rpath, - dbmfp->fd, &mbytes, &bytes, NULL)) != 0) { - __db_err(dbenv, "%s: %s", rpath, strerror(ret)); - goto err; - } - - /* Page sizes have to be a power-of-two, ignore mbytes. */ - if (bytes % pagesize != 0) { - __db_err(dbenv, - "%s: file size not a multiple of the pagesize", - rpath); - ret = EINVAL; - goto err; - } - - last_pgno = mbytes * (MEGABYTE / pagesize); - last_pgno += bytes / pagesize; - - /* Correction: page numbers are zero-based, not 1-based. */ - if (last_pgno != 0) - --last_pgno; - - /* - * Get the file id if we weren't given one. Generated file id's - * don't use timestamps, otherwise there'd be no chance of any - * other process joining the party. - */ - if (finfop->fileid == NULL) { - if ((ret = __os_fileid(dbenv, rpath, 0, idbuf)) != 0) - goto err; - finfop->fileid = idbuf; - } - } - - /* - * If we weren't provided an underlying shared object to join with, - * find/allocate the shared file objects. Also allocate space for - * for the per-process thread lock. - */ - if (needlock) - LOCKREGION(dbmp); - - if (mfp == NULL) - ret = __memp_mf_open(dbmp, - path, pagesize, last_pgno, finfop, &mfp); - else { - ++mfp->ref; - ret = 0; - } - if (ret == 0 && - F_ISSET(dbmp, MP_LOCKHANDLE) && (ret = - __memp_alloc(dbmp, sizeof(db_mutex_t), NULL, &dbmfp->mutexp)) == 0) - LOCKINIT(dbmp, dbmfp->mutexp); - - if (needlock) - UNLOCKREGION(dbmp); - if (ret != 0) - goto err; - - dbmfp->mfp = mfp; - - /* - * If a file: - * + is read-only - * + isn't temporary - * + doesn't require any pgin/pgout support - * + the DB_NOMMAP flag wasn't set - * + and is less than mp_mmapsize bytes in size - * - * we can mmap it instead of reading/writing buffers. Don't do error - * checking based on the mmap call failure. We want to do normal I/O - * on the file if the reason we failed was because the file was on an - * NFS mounted partition, and we can fail in buffer I/O just as easily - * as here. - * - * XXX - * We'd like to test to see if the file is too big to mmap. Since we - * don't know what size or type off_t's or size_t's are, or the largest - * unsigned integral type is, or what random insanity the local C - * compiler will perpetrate, doing the comparison in a portable way is - * flatly impossible. Hope that mmap fails if the file is too large. - */ -#define DB_MAXMMAPSIZE (10 * 1024 * 1024) /* 10 Mb. */ - if (F_ISSET(mfp, MP_CAN_MMAP)) { - if (!F_ISSET(dbmfp, MP_READONLY)) - F_CLR(mfp, MP_CAN_MMAP); - if (path == NULL) - F_CLR(mfp, MP_CAN_MMAP); - if (finfop->ftype != 0) - F_CLR(mfp, MP_CAN_MMAP); - if (LF_ISSET(DB_NOMMAP)) - F_CLR(mfp, MP_CAN_MMAP); - maxmap = dbenv == NULL || dbenv->mp_mmapsize == 0 ? - DB_MAXMMAPSIZE : dbenv->mp_mmapsize; - if (mbytes > maxmap / MEGABYTE || - (mbytes == maxmap / MEGABYTE && bytes >= maxmap % MEGABYTE)) - F_CLR(mfp, MP_CAN_MMAP); - } - dbmfp->addr = NULL; - if (F_ISSET(mfp, MP_CAN_MMAP)) { - dbmfp->len = (size_t)mbytes * MEGABYTE + bytes; - if (__db_mapfile(rpath, - dbmfp->fd, dbmfp->len, 1, &dbmfp->addr) != 0) { - dbmfp->addr = NULL; - F_CLR(mfp, MP_CAN_MMAP); - } - } - if (rpath != NULL) - __os_freestr(rpath); - - LOCKHANDLE(dbmp, dbmp->mutexp); - TAILQ_INSERT_TAIL(&dbmp->dbmfq, dbmfp, q); - UNLOCKHANDLE(dbmp, dbmp->mutexp); - - *retp = dbmfp; - return (0); - -err: /* - * Note that we do not have to free the thread mutex, because we - * never get to here after we have successfully allocated it. - */ - if (rpath != NULL) - __os_freestr(rpath); - if (dbmfp->fd != -1) - (void)__os_close(dbmfp->fd); - if (dbmfp != NULL) - __os_free(dbmfp, sizeof(DB_MPOOLFILE)); - return (ret); -} - -/* - * __memp_mf_open -- - * Open an MPOOLFILE. - */ -static int -__memp_mf_open(dbmp, path, pagesize, last_pgno, finfop, retp) - DB_MPOOL *dbmp; - const char *path; - size_t pagesize; - db_pgno_t last_pgno; - DB_MPOOL_FINFO *finfop; - MPOOLFILE **retp; -{ - MPOOLFILE *mfp; - int ret; - void *p; - -#define ISTEMPORARY (path == NULL) - - /* - * Walk the list of MPOOLFILE's, looking for a matching file. - * Temporary files can't match previous files. - */ - if (!ISTEMPORARY) - for (mfp = SH_TAILQ_FIRST(&dbmp->mp->mpfq, __mpoolfile); - mfp != NULL; mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile)) { - if (F_ISSET(mfp, MP_TEMP)) - continue; - if (!memcmp(finfop->fileid, - R_ADDR(dbmp, mfp->fileid_off), DB_FILE_ID_LEN)) { - if (finfop->clear_len != mfp->clear_len || - finfop->ftype != mfp->ftype || - pagesize != mfp->stat.st_pagesize) { - __db_err(dbmp->dbenv, - "%s: ftype, clear length or pagesize changed", - path); - return (EINVAL); - } - - /* Found it: increment the reference count. */ - ++mfp->ref; - *retp = mfp; - return (0); - } - } - - /* Allocate a new MPOOLFILE. */ - if ((ret = __memp_alloc(dbmp, sizeof(MPOOLFILE), NULL, &mfp)) != 0) - return (ret); - *retp = mfp; - - /* Initialize the structure. */ - memset(mfp, 0, sizeof(MPOOLFILE)); - mfp->ref = 1; - mfp->ftype = finfop->ftype; - mfp->lsn_off = finfop->lsn_offset; - mfp->clear_len = finfop->clear_len; - - /* - * If the user specifies DB_MPOOL_LAST or DB_MPOOL_NEW on a memp_fget, - * we have to know the last page in the file. Figure it out and save - * it away. - */ - mfp->stat.st_pagesize = pagesize; - mfp->orig_last_pgno = mfp->last_pgno = last_pgno; - - if (ISTEMPORARY) - F_SET(mfp, MP_TEMP); - else { - /* Copy the file path into shared memory. */ - if ((ret = __memp_alloc(dbmp, - strlen(path) + 1, &mfp->path_off, &p)) != 0) - goto err; - memcpy(p, path, strlen(path) + 1); - - /* Copy the file identification string into shared memory. */ - if ((ret = __memp_alloc(dbmp, - DB_FILE_ID_LEN, &mfp->fileid_off, &p)) != 0) - goto err; - memcpy(p, finfop->fileid, DB_FILE_ID_LEN); - - F_SET(mfp, MP_CAN_MMAP); - } - - /* Copy the page cookie into shared memory. */ - if (finfop->pgcookie == NULL || finfop->pgcookie->size == 0) { - mfp->pgcookie_len = 0; - mfp->pgcookie_off = 0; - } else { - if ((ret = __memp_alloc(dbmp, - finfop->pgcookie->size, &mfp->pgcookie_off, &p)) != 0) - goto err; - memcpy(p, finfop->pgcookie->data, finfop->pgcookie->size); - mfp->pgcookie_len = finfop->pgcookie->size; - } - - /* Prepend the MPOOLFILE to the list of MPOOLFILE's. */ - SH_TAILQ_INSERT_HEAD(&dbmp->mp->mpfq, mfp, q, __mpoolfile); - - if (0) { -err: if (mfp->path_off != 0) - __db_shalloc_free(dbmp->addr, - R_ADDR(dbmp, mfp->path_off)); - if (mfp->fileid_off != 0) - __db_shalloc_free(dbmp->addr, - R_ADDR(dbmp, mfp->fileid_off)); - if (mfp != NULL) - __db_shalloc_free(dbmp->addr, mfp); - mfp = NULL; - } - return (0); -} - -/* - * memp_fclose -- - * Close a backing file for the memory pool. - */ -int -memp_fclose(dbmfp) - DB_MPOOLFILE *dbmfp; -{ - DB_MPOOL *dbmp; - int ret, t_ret; - - dbmp = dbmfp->dbmp; - ret = 0; - - MP_PANIC_CHECK(dbmp); - - for (;;) { - LOCKHANDLE(dbmp, dbmp->mutexp); - - /* - * We have to reference count DB_MPOOLFILE structures as other - * threads may be using them. The problem only happens if the - * application makes a bad design choice. Here's the path: - * - * Thread A opens a database. - * Thread B uses thread A's DB_MPOOLFILE to write a buffer - * in order to free up memory in the mpool cache. - * Thread A closes the database while thread B is using the - * DB_MPOOLFILE structure. - * - * By opening all databases before creating the threads, and - * closing them after the threads have exited, applications - * get better performance and avoid the problem path entirely. - * - * Regardless, holding the DB_MPOOLFILE to flush a dirty buffer - * is a short-term lock, even in worst case, since we better be - * the only thread of control using the DB_MPOOLFILE structure - * to read pages *into* the cache. Wait until we're the only - * reference holder and remove the DB_MPOOLFILE structure from - * the list, so nobody else can even find it. - */ - if (dbmfp->ref == 1) { - TAILQ_REMOVE(&dbmp->dbmfq, dbmfp, q); - break; - } - UNLOCKHANDLE(dbmp, dbmp->mutexp); - - (void)__os_sleep(1, 0); - } - UNLOCKHANDLE(dbmp, dbmp->mutexp); - - /* Complain if pinned blocks never returned. */ - if (dbmfp->pinref != 0) - __db_err(dbmp->dbenv, "%s: close: %lu blocks left pinned", - __memp_fn(dbmfp), (u_long)dbmfp->pinref); - - /* Close the underlying MPOOLFILE. */ - (void)__memp_mf_close(dbmp, dbmfp); - - /* Discard any mmap information. */ - if (dbmfp->addr != NULL && - (ret = __db_unmapfile(dbmfp->addr, dbmfp->len)) != 0) - __db_err(dbmp->dbenv, - "%s: %s", __memp_fn(dbmfp), strerror(ret)); - - /* Close the file; temporary files may not yet have been created. */ - if (dbmfp->fd != -1 && (t_ret = __os_close(dbmfp->fd)) != 0) { - __db_err(dbmp->dbenv, - "%s: %s", __memp_fn(dbmfp), strerror(t_ret)); - if (ret != 0) - t_ret = ret; - } - - /* Free memory. */ - if (dbmfp->mutexp != NULL) { - LOCKREGION(dbmp); - __db_shalloc_free(dbmp->addr, dbmfp->mutexp); - UNLOCKREGION(dbmp); - } - - /* Discard the DB_MPOOLFILE structure. */ - __os_free(dbmfp, sizeof(DB_MPOOLFILE)); - - return (ret); -} - -/* - * __memp_mf_close -- - * Close down an MPOOLFILE. - */ -static int -__memp_mf_close(dbmp, dbmfp) - DB_MPOOL *dbmp; - DB_MPOOLFILE *dbmfp; -{ - BH *bhp, *nbhp; - MPOOL *mp; - MPOOLFILE *mfp; - size_t mf_offset; - - mp = dbmp->mp; - mfp = dbmfp->mfp; - - LOCKREGION(dbmp); - - /* If more than a single reference, simply decrement. */ - if (mfp->ref > 1) { - --mfp->ref; - goto ret1; - } - - /* - * Move any BH's held by the file to the free list. We don't free the - * memory itself because we may be discarding the memory pool, and it's - * fairly expensive to reintegrate the buffers back into the region for - * no purpose. - */ - mf_offset = R_OFFSET(dbmp, mfp); - for (bhp = SH_TAILQ_FIRST(&mp->bhq, __bh); bhp != NULL; bhp = nbhp) { - nbhp = SH_TAILQ_NEXT(bhp, q, __bh); - -#ifdef DEBUG_NO_DIRTY - /* Complain if we find any blocks that were left dirty. */ - if (F_ISSET(bhp, BH_DIRTY)) - __db_err(dbmp->dbenv, - "%s: close: pgno %lu left dirty; ref %lu", - __memp_fn(dbmfp), - (u_long)bhp->pgno, (u_long)bhp->ref); -#endif - - if (bhp->mf_offset == mf_offset) { - if (F_ISSET(bhp, BH_DIRTY)) { - ++mp->stat.st_page_clean; - --mp->stat.st_page_dirty; - } - __memp_bhfree(dbmp, mfp, bhp, 0); - SH_TAILQ_INSERT_HEAD(&mp->bhfq, bhp, q, __bh); - } - } - - /* Delete from the list of MPOOLFILEs. */ - SH_TAILQ_REMOVE(&mp->mpfq, mfp, q, __mpoolfile); - - /* Free the space. */ - if (mfp->path_off != 0) - __db_shalloc_free(dbmp->addr, R_ADDR(dbmp, mfp->path_off)); - if (mfp->fileid_off != 0) - __db_shalloc_free(dbmp->addr, R_ADDR(dbmp, mfp->fileid_off)); - if (mfp->pgcookie_off != 0) - __db_shalloc_free(dbmp->addr, R_ADDR(dbmp, mfp->pgcookie_off)); - __db_shalloc_free(dbmp->addr, mfp); - -ret1: UNLOCKREGION(dbmp); - return (0); -} diff --git a/db2/mp/mp_fput.c b/db2/mp/mp_fput.c deleted file mode 100644 index c551f97..0000000 --- a/db2/mp/mp_fput.c +++ /dev/null @@ -1,153 +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[] = "@(#)mp_fput.c 10.24 (Sleepycat) 9/27/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#endif - -#include "db_int.h" -#include "shqueue.h" -#include "db_shash.h" -#include "mp.h" -#include "common_ext.h" - -/* - * memp_fput -- - * Mpool file put function. - */ -int -memp_fput(dbmfp, pgaddr, flags) - DB_MPOOLFILE *dbmfp; - void *pgaddr; - u_int32_t flags; -{ - BH *bhp; - DB_MPOOL *dbmp; - MPOOL *mp; - int wrote, ret; - - dbmp = dbmfp->dbmp; - mp = dbmp->mp; - - MP_PANIC_CHECK(dbmp); - - /* Validate arguments. */ - if (flags) { - if ((ret = __db_fchk(dbmp->dbenv, "memp_fput", flags, - DB_MPOOL_CLEAN | DB_MPOOL_DIRTY | DB_MPOOL_DISCARD)) != 0) - return (ret); - if ((ret = __db_fcchk(dbmp->dbenv, "memp_fput", - flags, DB_MPOOL_CLEAN, DB_MPOOL_DIRTY)) != 0) - return (ret); - - if (LF_ISSET(DB_MPOOL_DIRTY) && F_ISSET(dbmfp, MP_READONLY)) { - __db_err(dbmp->dbenv, - "%s: dirty flag set for readonly file page", - __memp_fn(dbmfp)); - return (EACCES); - } - } - - LOCKREGION(dbmp); - - /* Decrement the pinned reference count. */ - if (dbmfp->pinref == 0) - __db_err(dbmp->dbenv, - "%s: put: more blocks returned than retrieved", - __memp_fn(dbmfp)); - else - --dbmfp->pinref; - - /* - * If we're mapping the file, there's nothing to do. Because we can - * stop mapping the file at any time, we have to check on each buffer - * to see if the address we gave the application was part of the map - * region. - */ - if (dbmfp->addr != NULL && pgaddr >= dbmfp->addr && - (u_int8_t *)pgaddr <= (u_int8_t *)dbmfp->addr + dbmfp->len) { - UNLOCKREGION(dbmp); - return (0); - } - - /* Convert the page address to a buffer header. */ - bhp = (BH *)((u_int8_t *)pgaddr - SSZA(BH, buf)); - - /* Set/clear the page bits. */ - if (LF_ISSET(DB_MPOOL_CLEAN) && F_ISSET(bhp, BH_DIRTY)) { - ++mp->stat.st_page_clean; - --mp->stat.st_page_dirty; - F_CLR(bhp, BH_DIRTY); - } - if (LF_ISSET(DB_MPOOL_DIRTY) && !F_ISSET(bhp, BH_DIRTY)) { - --mp->stat.st_page_clean; - ++mp->stat.st_page_dirty; - F_SET(bhp, BH_DIRTY); - } - if (LF_ISSET(DB_MPOOL_DISCARD)) - F_SET(bhp, BH_DISCARD); - - /* - * Check for a reference count going to zero. This can happen if the - * application returns a page twice. - */ - if (bhp->ref == 0) { - __db_err(dbmp->dbenv, "%s: page %lu: unpinned page returned", - __memp_fn(dbmfp), (u_long)bhp->pgno); - UNLOCKREGION(dbmp); - return (EINVAL); - } - - /* - * If more than one reference to the page, we're done. Ignore the - * discard flags (for now) and leave it at its position in the LRU - * chain. The rest gets done at last reference close. - */ - if (--bhp->ref > 0) { - UNLOCKREGION(dbmp); - return (0); - } - - /* - * If this buffer is scheduled for writing because of a checkpoint, we - * need to write it (if we marked it dirty), or update the checkpoint - * counters (if we didn't mark it dirty). If we try to write it and - * can't, that's not necessarily an error, but set a flag so that the - * next time the memp_sync function runs we try writing it there, as - * the checkpoint application better be able to write all of the files. - */ - if (F_ISSET(bhp, BH_WRITE)) { - if (F_ISSET(bhp, BH_DIRTY)) { - if (__memp_bhwrite(dbmp, - dbmfp->mfp, bhp, NULL, &wrote) != 0 || !wrote) - F_SET(mp, MP_LSN_RETRY); - } else { - F_CLR(bhp, BH_WRITE); - - --dbmfp->mfp->lsn_cnt; - --mp->lsn_cnt; - } - } - - /* Move the buffer to the head/tail of the LRU chain. */ - SH_TAILQ_REMOVE(&mp->bhq, bhp, q, __bh); - if (F_ISSET(bhp, BH_DISCARD)) - SH_TAILQ_INSERT_HEAD(&mp->bhq, bhp, q, __bh); - else - SH_TAILQ_INSERT_TAIL(&mp->bhq, bhp, q); - - - UNLOCKREGION(dbmp); - return (0); -} diff --git a/db2/mp/mp_fset.c b/db2/mp/mp_fset.c deleted file mode 100644 index 1940d3b..0000000 --- a/db2/mp/mp_fset.c +++ /dev/null @@ -1,83 +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[] = "@(#)mp_fset.c 10.16 (Sleepycat) 9/27/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#endif - -#include "db_int.h" -#include "shqueue.h" -#include "db_shash.h" -#include "mp.h" -#include "common_ext.h" - -/* - * memp_fset -- - * Mpool page set-flag routine. - */ -int -memp_fset(dbmfp, pgaddr, flags) - DB_MPOOLFILE *dbmfp; - void *pgaddr; - u_int32_t flags; -{ - BH *bhp; - DB_MPOOL *dbmp; - MPOOL *mp; - int ret; - - dbmp = dbmfp->dbmp; - mp = dbmp->mp; - - MP_PANIC_CHECK(dbmp); - - /* Validate arguments. */ - if (flags == 0) - return (__db_ferr(dbmp->dbenv, "memp_fset", 1)); - - if ((ret = __db_fchk(dbmp->dbenv, "memp_fset", flags, - DB_MPOOL_DIRTY | DB_MPOOL_CLEAN | DB_MPOOL_DISCARD)) != 0) - return (ret); - if ((ret = __db_fcchk(dbmp->dbenv, "memp_fset", - flags, DB_MPOOL_CLEAN, DB_MPOOL_DIRTY)) != 0) - return (ret); - - if (LF_ISSET(DB_MPOOL_DIRTY) && F_ISSET(dbmfp, MP_READONLY)) { - __db_err(dbmp->dbenv, - "%s: dirty flag set for readonly file page", - __memp_fn(dbmfp)); - return (EACCES); - } - - /* Convert the page address to a buffer header. */ - bhp = (BH *)((u_int8_t *)pgaddr - SSZA(BH, buf)); - - LOCKREGION(dbmp); - - if (LF_ISSET(DB_MPOOL_CLEAN) && F_ISSET(bhp, BH_DIRTY)) { - ++mp->stat.st_page_clean; - --mp->stat.st_page_dirty; - F_CLR(bhp, BH_DIRTY); - } - if (LF_ISSET(DB_MPOOL_DIRTY) && !F_ISSET(bhp, BH_DIRTY)) { - --mp->stat.st_page_clean; - ++mp->stat.st_page_dirty; - F_SET(bhp, BH_DIRTY); - } - if (LF_ISSET(DB_MPOOL_DISCARD)) - F_SET(bhp, BH_DISCARD); - - UNLOCKREGION(dbmp); - return (0); -} diff --git a/db2/mp/mp_open.c b/db2/mp/mp_open.c deleted file mode 100644 index 4c90fc4..0000000 --- a/db2/mp/mp_open.c +++ /dev/null @@ -1,221 +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[] = "@(#)mp_open.c 10.27 (Sleepycat) 10/1/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 "db_shash.h" -#include "mp.h" -#include "common_ext.h" - -/* - * memp_open -- - * Initialize and/or join a memory pool. - */ -int -memp_open(path, flags, mode, dbenv, retp) - const char *path; - u_int32_t flags; - int mode; - DB_ENV *dbenv; - DB_MPOOL **retp; -{ - DB_MPOOL *dbmp; - size_t cachesize; - int is_private, ret; - - /* Validate arguments. */ -#ifdef HAVE_SPINLOCKS -#define OKFLAGS (DB_CREATE | DB_MPOOL_PRIVATE | DB_NOMMAP | DB_THREAD) -#else -#define OKFLAGS (DB_CREATE | DB_MPOOL_PRIVATE | DB_NOMMAP) -#endif - if ((ret = __db_fchk(dbenv, "memp_open", flags, OKFLAGS)) != 0) - return (ret); - - /* Extract fields from DB_ENV structure. */ - cachesize = dbenv == NULL ? 0 : dbenv->mp_size; - - /* Create and initialize the DB_MPOOL structure. */ - if ((ret = __os_calloc(1, sizeof(DB_MPOOL), &dbmp)) != 0) - return (ret); - LIST_INIT(&dbmp->dbregq); - TAILQ_INIT(&dbmp->dbmfq); - - dbmp->dbenv = dbenv; - - /* Decide if it's possible for anyone else to access the pool. */ - is_private = - (dbenv == NULL && path == NULL) || LF_ISSET(DB_MPOOL_PRIVATE); - - /* - * Map in the region. We do locking regardless, as portions of it are - * implemented in common code (if we put the region in a file, that is). - */ - F_SET(dbmp, MP_LOCKREGION); - if ((ret = __memp_ropen(dbmp, - path, cachesize, mode, is_private, LF_ISSET(DB_CREATE))) != 0) - goto err; - F_CLR(dbmp, MP_LOCKREGION); - - /* - * If there's concurrent access, then we have to lock the region. - * If it's threaded, then we have to lock both the handles and the - * region, and we need to allocate a mutex for that purpose. - */ - if (!is_private) - F_SET(dbmp, MP_LOCKREGION); - if (LF_ISSET(DB_THREAD)) { - F_SET(dbmp, MP_LOCKHANDLE | MP_LOCKREGION); - LOCKREGION(dbmp); - ret = __memp_alloc(dbmp, - sizeof(db_mutex_t), NULL, &dbmp->mutexp); - UNLOCKREGION(dbmp); - if (ret != 0) { - (void)memp_close(dbmp); - goto err; - } - LOCKINIT(dbmp, dbmp->mutexp); - } - - *retp = dbmp; - return (0); - -err: if (dbmp != NULL) - __os_free(dbmp, sizeof(DB_MPOOL)); - return (ret); -} - -/* - * memp_close -- - * Close a memory pool. - */ -int -memp_close(dbmp) - DB_MPOOL *dbmp; -{ - DB_MPOOLFILE *dbmfp; - DB_MPREG *mpreg; - int ret, t_ret; - - ret = 0; - - MP_PANIC_CHECK(dbmp); - - /* Discard DB_MPREGs. */ - while ((mpreg = LIST_FIRST(&dbmp->dbregq)) != NULL) { - LIST_REMOVE(mpreg, q); - __os_free(mpreg, sizeof(DB_MPREG)); - } - - /* Discard DB_MPOOLFILEs. */ - while ((dbmfp = TAILQ_FIRST(&dbmp->dbmfq)) != NULL) - if ((t_ret = memp_fclose(dbmfp)) != 0 && ret == 0) - ret = t_ret; - - /* Discard thread mutex. */ - if (F_ISSET(dbmp, MP_LOCKHANDLE)) { - LOCKREGION(dbmp); - __db_shalloc_free(dbmp->addr, dbmp->mutexp); - UNLOCKREGION(dbmp); - } - - /* Close the region. */ - if ((t_ret = __db_rdetach(&dbmp->reginfo)) != 0 && ret == 0) - ret = t_ret; - - if (dbmp->reginfo.path != NULL) - __os_freestr(dbmp->reginfo.path); - __os_free(dbmp, sizeof(DB_MPOOL)); - - return (ret); -} - -/* - * __memp_panic -- - * Panic a memory pool. - * - * PUBLIC: void __memp_panic __P((DB_ENV *)); - */ -void -__memp_panic(dbenv) - DB_ENV *dbenv; -{ - if (dbenv->mp_info != NULL) - dbenv->mp_info->mp->rlayout.panic = 1; -} - -/* - * memp_unlink -- - * Exit a memory pool. - */ -int -memp_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_NONE; - if (path != NULL && (ret = __os_strdup(path, ®info.path)) != 0) - return (ret); - reginfo.file = DB_DEFAULT_MPOOL_FILE; - ret = __db_runlink(®info, force); - if (reginfo.path != NULL) - __os_freestr(reginfo.path); - return (ret); -} - -/* - * memp_register -- - * Register a file type's pgin, pgout routines. - */ -int -memp_register(dbmp, ftype, pgin, pgout) - DB_MPOOL *dbmp; - int ftype; - int (*pgin) __P((db_pgno_t, void *, DBT *)); - int (*pgout) __P((db_pgno_t, void *, DBT *)); -{ - DB_MPREG *mpr; - int ret; - - MP_PANIC_CHECK(dbmp); - - if ((ret = __os_malloc(sizeof(DB_MPREG), NULL, &mpr)) != 0) - return (ret); - - mpr->ftype = ftype; - mpr->pgin = pgin; - mpr->pgout = pgout; - - /* - * Insert at the head. Because we do a linear walk, we'll find - * the most recent registry in the case of multiple entries, so - * we don't have to check for multiple registries. - */ - LOCKHANDLE(dbmp, dbmp->mutexp); - LIST_INSERT_HEAD(&dbmp->dbregq, mpr, q); - UNLOCKHANDLE(dbmp, dbmp->mutexp); - - return (0); -} diff --git a/db2/mp/mp_pr.c b/db2/mp/mp_pr.c deleted file mode 100644 index 84c782e..0000000 --- a/db2/mp/mp_pr.c +++ /dev/null @@ -1,304 +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[] = "@(#)mp_pr.c 10.30 (Sleepycat) 10/1/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#endif - -#include "db_int.h" -#include "db_page.h" -#include "shqueue.h" -#include "db_shash.h" -#include "mp.h" -#include "db_auto.h" -#include "db_ext.h" -#include "common_ext.h" - -static void __memp_pbh __P((DB_MPOOL *, BH *, size_t *, FILE *)); - -/* - * memp_stat -- - * Display MPOOL statistics. - */ -int -memp_stat(dbmp, gspp, fspp, db_malloc) - DB_MPOOL *dbmp; - DB_MPOOL_STAT **gspp; - DB_MPOOL_FSTAT ***fspp; - void *(*db_malloc) __P((size_t)); -{ - DB_MPOOL_FSTAT **tfsp; - MPOOLFILE *mfp; - size_t len, nlen; - int ret; - char *name; - - MP_PANIC_CHECK(dbmp); - - /* Allocate space for the global statistics. */ - if (gspp != NULL) { - *gspp = NULL; - - if ((ret = __os_malloc(sizeof(**gspp), db_malloc, gspp)) != 0) - return (ret); - - LOCKREGION(dbmp); - - /* Copy out the global statistics. */ - **gspp = dbmp->mp->stat; - (*gspp)->st_hash_buckets = dbmp->mp->htab_buckets; - (*gspp)->st_region_wait = - dbmp->mp->rlayout.lock.mutex_set_wait; - (*gspp)->st_region_nowait = - dbmp->mp->rlayout.lock.mutex_set_nowait; - (*gspp)->st_refcnt = dbmp->mp->rlayout.refcnt; - (*gspp)->st_regsize = dbmp->mp->rlayout.size; - - UNLOCKREGION(dbmp); - } - - if (fspp != NULL) { - *fspp = NULL; - - LOCKREGION(dbmp); - - /* Count the MPOOLFILE structures. */ - for (len = 0, - mfp = SH_TAILQ_FIRST(&dbmp->mp->mpfq, __mpoolfile); - mfp != NULL; - ++len, mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile)) - ; - - UNLOCKREGION(dbmp); - - if (len == 0) - return (0); - - /* Allocate space for the pointers. */ - len = (len + 1) * sizeof(DB_MPOOL_FSTAT *); - if ((ret = __os_malloc(len, db_malloc, fspp)) != 0) - return (ret); - - LOCKREGION(dbmp); - - /* Build each individual entry. */ - for (tfsp = *fspp, - mfp = SH_TAILQ_FIRST(&dbmp->mp->mpfq, __mpoolfile); - mfp != NULL; - ++tfsp, mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile)) { - name = __memp_fns(dbmp, mfp); - nlen = strlen(name); - len = sizeof(DB_MPOOL_FSTAT) + nlen + 1; - if ((ret = __os_malloc(len, db_malloc, tfsp)) != 0) - return (ret); - **tfsp = mfp->stat; - (*tfsp)->file_name = (char *) - (u_int8_t *)*tfsp + sizeof(DB_MPOOL_FSTAT); - memcpy((*tfsp)->file_name, name, nlen + 1); - } - *tfsp = NULL; - - UNLOCKREGION(dbmp); - } - return (0); -} - -/* - * __memp_fn -- - * On errors we print whatever is available as the file name. - * - * PUBLIC: char * __memp_fn __P((DB_MPOOLFILE *)); - */ -char * -__memp_fn(dbmfp) - DB_MPOOLFILE *dbmfp; -{ - return (__memp_fns(dbmfp->dbmp, dbmfp->mfp)); -} - -/* - * __memp_fns -- - * On errors we print whatever is available as the file name. - * - * PUBLIC: char * __memp_fns __P((DB_MPOOL *, MPOOLFILE *)); - * - */ -char * -__memp_fns(dbmp, mfp) - DB_MPOOL *dbmp; - MPOOLFILE *mfp; -{ - if (mfp->path_off == 0) - return ((char *)"temporary"); - - return ((char *)R_ADDR(dbmp, mfp->path_off)); -} - -#define FMAP_ENTRIES 200 /* Files we map. */ - -#define MPOOL_DUMP_HASH 0x01 /* Debug hash chains. */ -#define MPOOL_DUMP_LRU 0x02 /* Debug LRU chains. */ -#define MPOOL_DUMP_MEM 0x04 /* Debug region memory. */ -#define MPOOL_DUMP_ALL 0x07 /* Debug all. */ - - -/* - * __memp_dump_region -- - * Display MPOOL structures. - * - * PUBLIC: void __memp_dump_region __P((DB_MPOOL *, char *, FILE *)); - */ -void -__memp_dump_region(dbmp, area, fp) - DB_MPOOL *dbmp; - char *area; - FILE *fp; -{ - BH *bhp; - DB_HASHTAB *htabp; - DB_MPOOLFILE *dbmfp; - MPOOL *mp; - MPOOLFILE *mfp; - size_t bucket, fmap[FMAP_ENTRIES + 1]; - u_int32_t flags; - int cnt; - - /* Make it easy to call from the debugger. */ - if (fp == NULL) - fp = stderr; - - for (flags = 0; *area != '\0'; ++area) - switch (*area) { - case 'A': - LF_SET(MPOOL_DUMP_ALL); - break; - case 'h': - LF_SET(MPOOL_DUMP_HASH); - break; - case 'l': - LF_SET(MPOOL_DUMP_LRU); - break; - case 'm': - LF_SET(MPOOL_DUMP_MEM); - break; - } - - LOCKREGION(dbmp); - - mp = dbmp->mp; - - /* Display MPOOL structures. */ - (void)fprintf(fp, "%s\nPool (region addr 0x%lx, alloc addr 0x%lx)\n", - DB_LINE, (u_long)dbmp->reginfo.addr, (u_long)dbmp->addr); - - /* Display the MPOOLFILE structures. */ - cnt = 0; - for (mfp = SH_TAILQ_FIRST(&dbmp->mp->mpfq, __mpoolfile); - mfp != NULL; mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile), ++cnt) { - (void)fprintf(fp, "file #%d: %s: refs %lu, type %ld, %s\n", - cnt + 1, __memp_fns(dbmp, mfp), (u_long)mfp->ref, - (long)mfp->ftype, - F_ISSET(mfp, MP_CAN_MMAP) ? "mmap" : "read/write"); - if (cnt < FMAP_ENTRIES) - fmap[cnt] = R_OFFSET(dbmp, mfp); - } - - for (dbmfp = TAILQ_FIRST(&dbmp->dbmfq); - dbmfp != NULL; dbmfp = TAILQ_NEXT(dbmfp, q), ++cnt) { - (void)fprintf(fp, "file #%d: %s: fd: %d: per-process, %s\n", - cnt + 1, __memp_fn(dbmfp), dbmfp->fd, - F_ISSET(dbmfp, MP_READONLY) ? "readonly" : "read/write"); - if (cnt < FMAP_ENTRIES) - fmap[cnt] = R_OFFSET(dbmp, mfp); - } - if (cnt < FMAP_ENTRIES) - fmap[cnt] = INVALID; - else - fmap[FMAP_ENTRIES] = INVALID; - - /* Display the hash table list of BH's. */ - if (LF_ISSET(MPOOL_DUMP_HASH)) { - (void)fprintf(fp, - "%s\nBH hash table (%lu hash slots)\npageno, file, ref, address\n", - DB_LINE, (u_long)mp->htab_buckets); - for (htabp = dbmp->htab, - bucket = 0; bucket < mp->htab_buckets; ++htabp, ++bucket) { - if (SH_TAILQ_FIRST(&dbmp->htab[bucket], __bh) != NULL) - (void)fprintf(fp, "%lu:\n", (u_long)bucket); - for (bhp = SH_TAILQ_FIRST(&dbmp->htab[bucket], __bh); - bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, hq, __bh)) - __memp_pbh(dbmp, bhp, fmap, fp); - } - } - - /* Display the LRU list of BH's. */ - if (LF_ISSET(MPOOL_DUMP_LRU)) { - (void)fprintf(fp, "%s\nBH LRU list\n", DB_LINE); - (void)fprintf(fp, "pageno, file, ref, address\n"); - for (bhp = SH_TAILQ_FIRST(&dbmp->mp->bhq, __bh); - bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, q, __bh)) - __memp_pbh(dbmp, bhp, fmap, fp); - } - - if (LF_ISSET(MPOOL_DUMP_MEM)) - __db_shalloc_dump(dbmp->addr, fp); - - UNLOCKREGION(dbmp); - - /* Flush in case we're debugging. */ - (void)fflush(fp); -} - -/* - * __memp_pbh -- - * Display a BH structure. - */ -static void -__memp_pbh(dbmp, bhp, fmap, fp) - DB_MPOOL *dbmp; - BH *bhp; - size_t *fmap; - FILE *fp; -{ - static const FN fn[] = { - { BH_CALLPGIN, "callpgin" }, - { BH_DIRTY, "dirty" }, - { BH_DISCARD, "discard" }, - { BH_LOCKED, "locked" }, - { BH_TRASH, "trash" }, - { BH_WRITE, "write" }, - { 0 }, - }; - int i; - - for (i = 0; i < FMAP_ENTRIES; ++i) - if (fmap[i] == INVALID || fmap[i] == bhp->mf_offset) - break; - - if (fmap[i] == INVALID) - (void)fprintf(fp, " %4lu, %lu, %2lu, %lu", - (u_long)bhp->pgno, (u_long)bhp->mf_offset, - (u_long)bhp->ref, (u_long)R_OFFSET(dbmp, bhp)); - else - (void)fprintf(fp, " %4lu, #%d, %2lu, %lu", - (u_long)bhp->pgno, i + 1, - (u_long)bhp->ref, (u_long)R_OFFSET(dbmp, bhp)); - - __db_prflags(bhp->flags, fn, fp); - - (void)fprintf(fp, "\n"); -} diff --git a/db2/mp/mp_region.c b/db2/mp/mp_region.c deleted file mode 100644 index b9c92f2..0000000 --- a/db2/mp/mp_region.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[] = "@(#)mp_region.c 10.35 (Sleepycat) 12/11/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 "db_shash.h" -#include "mp.h" -#include "common_ext.h" - -/* - * __memp_reg_alloc -- - * Allocate some space in the mpool region, with locking. - * - * PUBLIC: int __memp_reg_alloc __P((DB_MPOOL *, size_t, size_t *, void *)); - */ -int -__memp_reg_alloc(dbmp, len, offsetp, retp) - DB_MPOOL *dbmp; - size_t len, *offsetp; - void *retp; -{ - int ret; - - LOCKREGION(dbmp); - ret = __memp_alloc(dbmp, len, offsetp, retp); - UNLOCKREGION(dbmp); - return (ret); -} - -/* - * __memp_alloc -- - * Allocate some space in the mpool region. - * - * PUBLIC: int __memp_alloc __P((DB_MPOOL *, size_t, size_t *, void *)); - */ -int -__memp_alloc(dbmp, len, offsetp, retp) - DB_MPOOL *dbmp; - size_t len, *offsetp; - void *retp; -{ - BH *bhp, *nbhp; - MPOOL *mp; - MPOOLFILE *mfp; - size_t fsize, total; - int nomore, restart, ret, wrote; - void *p; - - mp = dbmp->mp; - - nomore = 0; -alloc: if ((ret = __db_shalloc(dbmp->addr, len, MUTEX_ALIGNMENT, &p)) == 0) { - if (offsetp != NULL) - *offsetp = R_OFFSET(dbmp, p); - *(void **)retp = p; - return (0); - } - if (nomore) { - __db_err(dbmp->dbenv, - "Unable to allocate %lu bytes from mpool shared region: %s\n", - (u_long)len, strerror(ret)); - return (ret); - } - - /* Look for a buffer on the free list that's the right size. */ - for (bhp = - SH_TAILQ_FIRST(&mp->bhfq, __bh); bhp != NULL; bhp = nbhp) { - nbhp = SH_TAILQ_NEXT(bhp, q, __bh); - - if (__db_shsizeof(bhp) == len) { - SH_TAILQ_REMOVE(&mp->bhfq, bhp, q, __bh); - if (offsetp != NULL) - *offsetp = R_OFFSET(dbmp, bhp); - *(void **)retp = bhp; - return (0); - } - } - - /* Discard from the free list until we've freed enough memory. */ - total = 0; - for (bhp = - SH_TAILQ_FIRST(&mp->bhfq, __bh); bhp != NULL; bhp = nbhp) { - nbhp = SH_TAILQ_NEXT(bhp, q, __bh); - - SH_TAILQ_REMOVE(&mp->bhfq, bhp, q, __bh); - __db_shalloc_free(dbmp->addr, bhp); - --mp->stat.st_page_clean; - - /* - * Retry as soon as we've freed up sufficient space. If we - * will have to coalesce memory to satisfy the request, don't - * try until it's likely (possible?) that we'll succeed. - */ - total += fsize = __db_shsizeof(bhp); - if (fsize >= len || total >= 3 * len) - goto alloc; - } - -retry: /* Find a buffer we can flush; pure LRU. */ - restart = total = 0; - for (bhp = - SH_TAILQ_FIRST(&mp->bhq, __bh); bhp != NULL; bhp = nbhp) { - nbhp = SH_TAILQ_NEXT(bhp, q, __bh); - - /* Ignore pinned or locked (I/O in progress) buffers. */ - if (bhp->ref != 0 || F_ISSET(bhp, BH_LOCKED)) - continue; - - /* Find the associated MPOOLFILE. */ - mfp = R_ADDR(dbmp, bhp->mf_offset); - - /* - * Write the page if it's dirty. - * - * If we wrote the page, fall through and free the buffer. We - * don't have to rewalk the list to acquire the buffer because - * it was never available for any other process to modify it. - * If we didn't write the page, but we discarded and reacquired - * the region lock, restart the buffer list walk. If we neither - * wrote the buffer nor discarded the region lock, continue down - * the buffer list. - */ - if (F_ISSET(bhp, BH_DIRTY)) { - if ((ret = __memp_bhwrite(dbmp, - mfp, bhp, &restart, &wrote)) != 0) - return (ret); - - /* - * It's possible that another process wants this buffer - * and incremented the ref count while we were writing - * it. - */ - if (bhp->ref != 0) - goto retry; - - if (wrote) - ++mp->stat.st_rw_evict; - else { - if (restart) - goto retry; - continue; - } - } else - ++mp->stat.st_ro_evict; - - /* - * Check to see if the buffer is the size we're looking for. - * If it is, simply reuse it. - */ - total += fsize = __db_shsizeof(bhp); - if (fsize == len) { - __memp_bhfree(dbmp, mfp, bhp, 0); - - if (offsetp != NULL) - *offsetp = R_OFFSET(dbmp, bhp); - *(void **)retp = bhp; - return (0); - } - - /* Free the buffer. */ - __memp_bhfree(dbmp, mfp, bhp, 1); - - /* - * Retry as soon as we've freed up sufficient space. If we - * have to coalesce of memory to satisfy the request, don't - * try until it's likely (possible?) that we'll succeed. - */ - if (fsize >= len || total >= 3 * len) - goto alloc; - - /* Restart the walk if we discarded the region lock. */ - if (restart) - goto retry; - } - nomore = 1; - goto alloc; -} - -/* - * __memp_ropen -- - * Attach to, and optionally create, the mpool region. - * - * PUBLIC: int __memp_ropen - * PUBLIC: __P((DB_MPOOL *, const char *, size_t, int, int, u_int32_t)); - */ -int -__memp_ropen(dbmp, path, cachesize, mode, is_private, flags) - DB_MPOOL *dbmp; - const char *path; - size_t cachesize; - int mode, is_private; - u_int32_t flags; -{ - MPOOL *mp; - size_t rlen; - int defcache, ret; - - /* - * Unlike other DB subsystems, mpool can't simply grow the region - * because it returns pointers into the region to its clients. To - * "grow" the region, we'd have to allocate a new region and then - * store a region number in the structures that reference regional - * objects. It's reasonable that we fail regardless, as clients - * shouldn't have every page in the region pinned, so the only - * "failure" mode should be a performance penalty because we don't - * find a page in the cache that we'd like to have found. - * - * Up the user's cachesize by 25% to account for our overhead. - */ - defcache = 0; - if (cachesize < DB_CACHESIZE_MIN) { - if (cachesize == 0) { - defcache = 1; - cachesize = DB_CACHESIZE_DEF; - } else - cachesize = DB_CACHESIZE_MIN; - } - rlen = cachesize + cachesize / 4; - - /* - * Map in the region. - * - * If it's a private mpool, use malloc, it's a lot faster than - * instantiating a region. - */ - dbmp->reginfo.dbenv = dbmp->dbenv; - dbmp->reginfo.appname = DB_APP_NONE; - if (path == NULL) - dbmp->reginfo.path = NULL; - else - if ((ret = __os_strdup(path, &dbmp->reginfo.path)) != 0) - return (ret); - dbmp->reginfo.file = DB_DEFAULT_MPOOL_FILE; - dbmp->reginfo.mode = mode; - dbmp->reginfo.size = rlen; - dbmp->reginfo.dbflags = flags; - dbmp->reginfo.flags = 0; - if (defcache) - F_SET(&dbmp->reginfo, REGION_SIZEDEF); - - /* - * If we're creating a temporary region, don't use any standard - * naming. - */ - if (is_private) { - dbmp->reginfo.appname = DB_APP_TMP; - dbmp->reginfo.file = NULL; - F_SET(&dbmp->reginfo, REGION_PRIVATE); - } - - if ((ret = __db_rattach(&dbmp->reginfo)) != 0) { - if (dbmp->reginfo.path != NULL) - __os_freestr(dbmp->reginfo.path); - return (ret); - } - - /* - * The MPOOL structure is first in the region, the rest of the region - * is free space. - */ - dbmp->mp = dbmp->reginfo.addr; - dbmp->addr = (u_int8_t *)dbmp->mp + sizeof(MPOOL); - - /* Initialize a created region. */ - if (F_ISSET(&dbmp->reginfo, REGION_CREATED)) { - mp = dbmp->mp; - SH_TAILQ_INIT(&mp->bhq); - SH_TAILQ_INIT(&mp->bhfq); - SH_TAILQ_INIT(&mp->mpfq); - - __db_shalloc_init(dbmp->addr, rlen - sizeof(MPOOL)); - - /* - * Assume we want to keep the hash chains with under 10 pages - * on each chain. We don't know the pagesize in advance, and - * it may differ for different files. Use a pagesize of 1K for - * the calculation -- we walk these chains a lot, they should - * be short. - */ - mp->htab_buckets = - __db_tablesize((cachesize / (1 * 1024)) / 10); - - /* Allocate hash table space and initialize it. */ - if ((ret = __db_shalloc(dbmp->addr, - mp->htab_buckets * sizeof(DB_HASHTAB), - 0, &dbmp->htab)) != 0) - goto err; - __db_hashinit(dbmp->htab, mp->htab_buckets); - mp->htab = R_OFFSET(dbmp, dbmp->htab); - - ZERO_LSN(mp->lsn); - mp->lsn_cnt = 0; - - memset(&mp->stat, 0, sizeof(mp->stat)); - mp->stat.st_cachesize = cachesize; - - mp->flags = 0; - } - - /* Get the local hash table address. */ - dbmp->htab = R_ADDR(dbmp, dbmp->mp->htab); - - UNLOCKREGION(dbmp); - return (0); - -err: UNLOCKREGION(dbmp); - (void)__db_rdetach(&dbmp->reginfo); - if (F_ISSET(&dbmp->reginfo, REGION_CREATED)) - (void)memp_unlink(path, 1, dbmp->dbenv); - - if (dbmp->reginfo.path != NULL) - __os_freestr(dbmp->reginfo.path); - return (ret); -} diff --git a/db2/mp/mp_sync.c b/db2/mp/mp_sync.c deleted file mode 100644 index 5353485..0000000 --- a/db2/mp/mp_sync.c +++ /dev/null @@ -1,549 +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[] = "@(#)mp_sync.c 10.31 (Sleepycat) 12/11/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <stdlib.h> -#endif - -#include "db_int.h" -#include "shqueue.h" -#include "db_shash.h" -#include "mp.h" -#include "common_ext.h" - -static int __bhcmp __P((const void *, const void *)); -static int __memp_fsync __P((DB_MPOOLFILE *)); - -/* - * memp_sync -- - * Mpool sync function. - */ -int -memp_sync(dbmp, lsnp) - DB_MPOOL *dbmp; - DB_LSN *lsnp; -{ - BH *bhp, **bharray; - DB_ENV *dbenv; - MPOOL *mp; - MPOOLFILE *mfp; - int ar_cnt, nalloc, next, maxpin, ret, wrote; - - MP_PANIC_CHECK(dbmp); - - dbenv = dbmp->dbenv; - mp = dbmp->mp; - - if (dbenv->lg_info == NULL) { - __db_err(dbenv, "memp_sync: requires logging"); - return (EINVAL); - } - - /* - * We try and write the buffers in page order: it should reduce seeks - * by the underlying filesystem and possibly reduce the actual number - * of writes. We don't want to hold the region lock while we write - * the buffers, so only hold it lock while we create a list. Get a - * good-size block of memory to hold buffer pointers, we don't want - * to run out. - */ - LOCKREGION(dbmp); - nalloc = mp->stat.st_page_dirty + mp->stat.st_page_dirty / 2 + 10; - UNLOCKREGION(dbmp); - - if ((ret = __os_malloc(nalloc * sizeof(BH *), NULL, &bharray)) != 0) - return (ret); - - LOCKREGION(dbmp); - - /* - * If the application is asking about a previous call to memp_sync(), - * and we haven't found any buffers that the application holding the - * pin couldn't write, return yes or no based on the current count. - * Note, if the application is asking about a LSN *smaller* than one - * we've already handled or are currently handling, then we return a - * result based on the count for the larger LSN. - */ - if (!F_ISSET(mp, MP_LSN_RETRY) && log_compare(lsnp, &mp->lsn) <= 0) { - if (mp->lsn_cnt == 0) { - *lsnp = mp->lsn; - ret = 0; - } else - ret = DB_INCOMPLETE; - goto done; - } - - /* Else, it's a new checkpoint. */ - F_CLR(mp, MP_LSN_RETRY); - - /* - * Save the LSN. We know that it's a new LSN or larger than the one - * for which we were already doing a checkpoint. (BTW, I don't expect - * to see multiple LSN's from the same or multiple processes, but You - * Just Never Know. Responding as if they all called with the largest - * of the LSNs specified makes everything work.) - * - * We don't currently use the LSN we save. We could potentially save - * the last-written LSN in each buffer header and use it to determine - * what buffers need to be written. The problem with this is that it's - * sizeof(LSN) more bytes of buffer header. We currently write all the - * dirty buffers instead. - * - * Walk the list of shared memory segments clearing the count of - * buffers waiting to be written. - */ - mp->lsn = *lsnp; - mp->lsn_cnt = 0; - for (mfp = SH_TAILQ_FIRST(&dbmp->mp->mpfq, __mpoolfile); - mfp != NULL; mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile)) - mfp->lsn_cnt = 0; - - /* - * Walk the list of buffers and mark all dirty buffers to be written - * and all pinned buffers to be potentially written (we can't know if - * we'll need to write them until the holding process returns them to - * the cache). We do this in one pass while holding the region locked - * so that processes can't make new buffers dirty, causing us to never - * finish. Since the application may have restarted the sync, clear - * any BH_WRITE flags that appear to be left over from previous calls. - * - * We don't want to pin down the entire buffer cache, otherwise we'll - * starve threads needing new pages. Don't pin down more than 80% of - * the cache. - * - * Keep a count of the total number of buffers we need to write in - * MPOOL->lsn_cnt, and for each file, in MPOOLFILE->lsn_count. - */ - ar_cnt = 0; - maxpin = ((mp->stat.st_page_dirty + mp->stat.st_page_clean) * 8) / 10; - for (bhp = SH_TAILQ_FIRST(&mp->bhq, __bh); - bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, q, __bh)) - if (F_ISSET(bhp, BH_DIRTY) || bhp->ref != 0) { - F_SET(bhp, BH_WRITE); - - ++mp->lsn_cnt; - - mfp = R_ADDR(dbmp, bhp->mf_offset); - ++mfp->lsn_cnt; - - /* - * If the buffer isn't in use, we should be able to - * write it immediately, so increment the reference - * count to lock it and its contents down, and then - * save a reference to it. - * - * If we've run out space to store buffer references, - * we're screwed. We don't want to realloc the array - * while holding a region lock, so we set the flag to - * force the checkpoint to be done again, from scratch, - * later. - * - * If we've pinned down too much of the cache stop, and - * set a flag to force the checkpoint to be tried again - * later. - */ - if (bhp->ref == 0) { - ++bhp->ref; - bharray[ar_cnt] = bhp; - if (++ar_cnt >= nalloc || ar_cnt >= maxpin) { - F_SET(mp, MP_LSN_RETRY); - break; - } - } - } else - if (F_ISSET(bhp, BH_WRITE)) - F_CLR(bhp, BH_WRITE); - - /* If there no buffers we can write immediately, we're done. */ - if (ar_cnt == 0) { - ret = mp->lsn_cnt ? DB_INCOMPLETE : 0; - goto done; - } - - UNLOCKREGION(dbmp); - - /* Sort the buffers we're going to write. */ - qsort(bharray, ar_cnt, sizeof(BH *), __bhcmp); - - LOCKREGION(dbmp); - - /* Walk the array, writing buffers. */ - for (next = 0; next < ar_cnt; ++next) { - /* - * It's possible for a thread to have gotten the buffer since - * we listed it for writing. If the reference count is still - * 1, we're the only ones using the buffer, go ahead and write. - * If it's >1, then skip the buffer and assume that it will be - * written when it's returned to the cache. - */ - if (bharray[next]->ref > 1) { - --bharray[next]->ref; - continue; - } - - /* Write the buffer. */ - mfp = R_ADDR(dbmp, bharray[next]->mf_offset); - ret = __memp_bhwrite(dbmp, mfp, bharray[next], NULL, &wrote); - - /* Release the buffer. */ - --bharray[next]->ref; - - /* If there's an error, release the rest of the buffers. */ - if (ret != 0 || !wrote) { - /* - * Any process syncing the shared memory buffer pool - * had better be able to write to any underlying file. - * Be understanding, but firm, on this point. - */ - if (ret == 0) { - __db_err(dbenv, "%s: unable to flush page: %lu", - __memp_fns(dbmp, mfp), - (u_long)bharray[next]->pgno); - ret = EPERM; - } - - while (++next < ar_cnt) - --bharray[next]->ref; - goto err; - } - } - ret = mp->lsn_cnt != 0 || - F_ISSET(mp, MP_LSN_RETRY) ? DB_INCOMPLETE : 0; - -done: - if (0) { -err: /* - * On error, clear: - * MPOOL->lsn_cnt (the total sync count) - * MPOOLFILE->lsn_cnt (the per-file sync count) - * BH_WRITE flag (the scheduled for writing flag) - */ - mp->lsn_cnt = 0; - for (mfp = SH_TAILQ_FIRST(&dbmp->mp->mpfq, __mpoolfile); - mfp != NULL; mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile)) - mfp->lsn_cnt = 0; - for (bhp = SH_TAILQ_FIRST(&mp->bhq, __bh); - bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, q, __bh)) - F_CLR(bhp, BH_WRITE); - } - UNLOCKREGION(dbmp); - __os_free(bharray, nalloc * sizeof(BH *)); - return (ret); -} - -/* - * memp_fsync -- - * Mpool file sync function. - */ -int -memp_fsync(dbmfp) - DB_MPOOLFILE *dbmfp; -{ - DB_MPOOL *dbmp; - int is_tmp; - - dbmp = dbmfp->dbmp; - - MP_PANIC_CHECK(dbmp); - - /* - * If this handle doesn't have a file descriptor that's open for - * writing, or if the file is a temporary, there's no reason to - * proceed further. - */ - if (F_ISSET(dbmfp, MP_READONLY)) - return (0); - - LOCKREGION(dbmp); - is_tmp = F_ISSET(dbmfp->mfp, MP_TEMP); - UNLOCKREGION(dbmp); - if (is_tmp) - return (0); - - return (__memp_fsync(dbmfp)); -} - -/* - * __mp_xxx_fd -- - * Return a file descriptor for DB 1.85 compatibility locking. - * - * PUBLIC: int __mp_xxx_fd __P((DB_MPOOLFILE *, int *)); - */ -int -__mp_xxx_fd(dbmfp, fdp) - DB_MPOOLFILE *dbmfp; - int *fdp; -{ - int ret; - - /* - * This is a truly spectacular layering violation, intended ONLY to - * support compatibility for the DB 1.85 DB->fd call. - * - * Sync the database file to disk, creating the file as necessary. - * - * We skip the MP_READONLY and MP_TEMP tests done by memp_fsync(3). - * The MP_READONLY test isn't interesting because we will either - * already have a file descriptor (we opened the database file for - * reading) or we aren't readonly (we created the database which - * requires write privileges). The MP_TEMP test isn't interesting - * because we want to write to the backing file regardless so that - * we get a file descriptor to return. - */ - ret = dbmfp->fd == -1 ? __memp_fsync(dbmfp) : 0; - - return ((*fdp = dbmfp->fd) == -1 ? ENOENT : ret); -} - -/* - * __memp_fsync -- - * Mpool file internal sync function. - */ -static int -__memp_fsync(dbmfp) - DB_MPOOLFILE *dbmfp; -{ - BH *bhp, **bharray; - DB_MPOOL *dbmp; - MPOOL *mp; - size_t mf_offset; - int ar_cnt, incomplete, nalloc, next, ret, wrote; - - ret = 0; - dbmp = dbmfp->dbmp; - mp = dbmp->mp; - mf_offset = R_OFFSET(dbmp, dbmfp->mfp); - - /* - * We try and write the buffers in page order: it should reduce seeks - * by the underlying filesystem and possibly reduce the actual number - * of writes. We don't want to hold the region lock while we write - * the buffers, so only hold it lock while we create a list. Get a - * good-size block of memory to hold buffer pointers, we don't want - * to run out. - */ - LOCKREGION(dbmp); - nalloc = mp->stat.st_page_dirty + mp->stat.st_page_dirty / 2 + 10; - UNLOCKREGION(dbmp); - - if ((ret = __os_malloc(nalloc * sizeof(BH *), NULL, &bharray)) != 0) - return (ret); - - LOCKREGION(dbmp); - - /* - * Walk the LRU list of buffer headers, and get a list of buffers to - * write for this MPOOLFILE. - */ - ar_cnt = incomplete = 0; - for (bhp = SH_TAILQ_FIRST(&mp->bhq, __bh); - bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, q, __bh)) { - if (!F_ISSET(bhp, BH_DIRTY) || bhp->mf_offset != mf_offset) - continue; - if (bhp->ref != 0 || F_ISSET(bhp, BH_LOCKED)) { - incomplete = 1; - continue; - } - - ++bhp->ref; - bharray[ar_cnt] = bhp; - - /* - * If we've run out space to store buffer references, we're - * screwed, as we don't want to realloc the array holding a - * region lock. Set the incomplete flag -- the only way we - * can get here is if the file is active in the buffer cache, - * which is the same thing as finding pinned buffers. - */ - if (++ar_cnt >= nalloc) { - incomplete = 1; - break; - } - } - - UNLOCKREGION(dbmp); - - /* Sort the buffers we're going to write. */ - if (ar_cnt != 0) - qsort(bharray, ar_cnt, sizeof(BH *), __bhcmp); - - LOCKREGION(dbmp); - - /* Walk the array, writing buffers. */ - for (next = 0; next < ar_cnt; ++next) { - /* - * It's possible for a thread to have gotten the buffer since - * we listed it for writing. If the reference count is still - * 1, we're the only ones using the buffer, go ahead and write. - * If it's >1, then skip the buffer. - */ - if (bharray[next]->ref > 1) { - incomplete = 1; - - --bharray[next]->ref; - continue; - } - - /* Write the buffer. */ - ret = __memp_pgwrite(dbmfp, bharray[next], NULL, &wrote); - - /* Release the buffer. */ - --bharray[next]->ref; - - /* If there's an error, release the rest of the buffers. */ - if (ret != 0) { - while (++next < ar_cnt) - --bharray[next]->ref; - goto err; - } - - /* - * If we didn't write the buffer for some reason, don't return - * success. - */ - if (!wrote) - incomplete = 1; - } - -err: UNLOCKREGION(dbmp); - - __os_free(bharray, nalloc * sizeof(BH *)); - - /* - * Sync the underlying file as the last thing we do, so that the OS - * has maximal opportunity to flush buffers before we request it. - * - * XXX: - * Don't lock the region around the sync, fsync(2) has no atomicity - * issues. - */ - if (ret == 0) - return (incomplete ? DB_INCOMPLETE : __os_fsync(dbmfp->fd)); - return (ret); -} - -/* - * memp_trickle -- - * Keep a specified percentage of the buffers clean. - */ -int -memp_trickle(dbmp, pct, nwrotep) - DB_MPOOL *dbmp; - int pct, *nwrotep; -{ - BH *bhp; - MPOOL *mp; - MPOOLFILE *mfp; - u_long total; - int ret, wrote; - - MP_PANIC_CHECK(dbmp); - - mp = dbmp->mp; - if (nwrotep != NULL) - *nwrotep = 0; - - if (pct < 1 || pct > 100) - return (EINVAL); - - LOCKREGION(dbmp); - - /* - * If there are sufficient clean buffers, or no buffers or no dirty - * buffers, we're done. - * - * XXX - * Using st_page_clean and st_page_dirty is our only choice at the - * moment, but it's not as correct as we might like in the presence - * of pools with more than one buffer size, as a free 512-byte buffer - * isn't the same as a free 8K buffer. - */ -loop: total = mp->stat.st_page_clean + mp->stat.st_page_dirty; - if (total == 0 || mp->stat.st_page_dirty == 0 || - (mp->stat.st_page_clean * 100) / total >= (u_long)pct) { - UNLOCKREGION(dbmp); - return (0); - } - - /* Loop until we write a buffer. */ - for (bhp = SH_TAILQ_FIRST(&mp->bhq, __bh); - bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, q, __bh)) { - if (bhp->ref != 0 || - !F_ISSET(bhp, BH_DIRTY) || F_ISSET(bhp, BH_LOCKED)) - continue; - - mfp = R_ADDR(dbmp, bhp->mf_offset); - - /* - * We can't write to temporary files -- see the comment in - * mp_bh.c:__memp_bhwrite(). - */ - if (F_ISSET(mfp, MP_TEMP)) - continue; - - if ((ret = __memp_bhwrite(dbmp, mfp, bhp, NULL, &wrote)) != 0) - goto err; - - /* - * Any process syncing the shared memory buffer pool had better - * be able to write to any underlying file. Be understanding, - * but firm, on this point. - */ - if (!wrote) { - __db_err(dbmp->dbenv, "%s: unable to flush page: %lu", - __memp_fns(dbmp, mfp), (u_long)bhp->pgno); - ret = EPERM; - goto err; - } - - ++mp->stat.st_page_trickle; - if (nwrotep != NULL) - ++*nwrotep; - goto loop; - } - - /* No more buffers to write. */ - ret = 0; - -err: UNLOCKREGION(dbmp); - return (ret); -} - -static int -__bhcmp(p1, p2) - const void *p1, *p2; -{ - BH *bhp1, *bhp2; - - bhp1 = *(BH * const *)p1; - bhp2 = *(BH * const *)p2; - - /* Sort by file (shared memory pool offset). */ - if (bhp1->mf_offset < bhp2->mf_offset) - return (-1); - if (bhp1->mf_offset > bhp2->mf_offset) - return (1); - - /* - * !!! - * Defend against badly written quicksort code calling the comparison - * function with two identical pointers (e.g., WATCOM C++ (Power++)). - */ - if (bhp1->pgno < bhp2->pgno) - return (-1); - if (bhp1->pgno > bhp2->pgno) - return (1); - return (0); -} diff --git a/db2/mutex/68020.gcc b/db2/mutex/68020.gcc deleted file mode 100644 index 21410e6..0000000 --- a/db2/mutex/68020.gcc +++ /dev/null @@ -1,18 +0,0 @@ -/* - * @(#)68020.gcc 10.2 (Sleepycat) 2/15/98 - * - * For gcc/68K, 0 is clear, 1 is set. - */ -#define TSL_SET(tsl) ({ \ - register tsl_t *__l = (tsl); \ - int __r; \ - asm volatile("tas %1; \n \ - seq %0" \ - : "=dm" (__r), "=m" (*__l) \ - : "1" (*__l) \ - ); \ - __r & 1; \ -}) - -#define TSL_UNSET(tsl) (*(tsl) = 0) -#define TSL_INIT(tsl) TSL_UNSET(tsl) diff --git a/db2/mutex/README b/db2/mutex/README deleted file mode 100644 index fceeef7..0000000 --- a/db2/mutex/README +++ /dev/null @@ -1,105 +0,0 @@ -# @(#)README 10.2 (Sleepycat) 11/25/97 - -Resource locking routines: lock based on a db_mutex_t. All this gunk -(including trying to make assembly code portable), is necessary because -System V semaphores require system calls for uncontested locks and we -don't want to make two system calls per resource lock. - -First, this is how it works. The db_mutex_t structure contains a resource -test-and-set lock (tsl), a file offset, a pid for debugging and statistics -information. - -If HAVE_SPINLOCKS is defined (i.e. we know how to do test-and-sets for -this compiler/architecture combination), we try and lock the resource tsl -__db_tsl_spins times. If we can't acquire the lock that way, we use a -system call to sleep for 10ms, 20ms, 40ms, etc. (The time is bounded at -1 second, just in case.) Using the timer backoff means that there are -two assumptions: that locks are held for brief periods (never over system -calls or I/O) and that locks are not hotly contested. - -If HAVE_SPINLOCKS is not defined, i.e. we can't do test-and-sets, we use -a file descriptor to do byte locking on a file at a specified offset. In -this case, ALL of the locking is done in the kernel. Because file -descriptors are allocated per process, we have to provide the file -descriptor as part of the lock/unlock call. We still have to do timer -backoff because we need to be able to block ourselves, i.e. the lock -manager causes processes to wait by having the process acquire a mutex -and then attempting to re-acquire the mutex. There's no way to use kernel -locking to block yourself, i.e. if you hold a lock and attempt to -re-acquire it, the attempt will succeed. - -Next, let's talk about why it doesn't work the way a reasonable person -would think it should work. - -Ideally, we'd have the ability to try to lock the resource tsl, and if -that fails, increment a counter of waiting processes, then block in the -kernel until the tsl is released. The process holding the resource tsl -would see the wait counter when it went to release the resource tsl, and -would wake any waiting processes up after releasing the lock. This would -actually require both another tsl (call it the mutex tsl) and -synchronization between the call that blocks in the kernel and the actual -resource tsl. The mutex tsl would be used to protect accesses to the -db_mutex_t itself. Locking the mutex tsl would be done by a busy loop, -which is safe because processes would never block holding that tsl (all -they would do is try to obtain the resource tsl and set/check the wait -count). The problem in this model is that the blocking call into the -kernel requires a blocking semaphore, i.e. one whose normal state is -locked. - -The only portable forms of locking under UNIX are fcntl(2) on a file -descriptor/offset, and System V semaphores. Neither of these locking -methods are sufficient to solve the problem. - -The problem with fcntl locking is that only the process that obtained the -lock can release it. Remember, we want the normal state of the kernel -semaphore to be locked. So, if the creator of the db_mutex_t were to -initialize the lock to "locked", then a second process locks the resource -tsl, and then a third process needs to block, waiting for the resource -tsl, when the second process wants to wake up the third process, it can't -because it's not the holder of the lock! For the second process to be -the holder of the lock, we would have to make a system call per -uncontested lock, which is what we were trying to get away from in the -first place. - -There are some hybrid schemes, such as signaling the holder of the lock, -or using a different blocking offset depending on which process is -holding the lock, but it gets complicated fairly quickly. I'm open to -suggestions, but I'm not holding my breath. - -Regardless, we use this form of locking when HAVE_SPINLOCKS is not -defined, (i.e. we're locking in the kernel) because it doesn't have the -limitations found in System V semaphores, and because the normal state of -the kernel object in that case is unlocked, so the process releasing the -lock is also the holder of the lock. - -The System V semaphore design has a number of other limitations that make -it inappropriate for this task. Namely: - -First, the semaphore key name space is separate from the file system name -space (although there exist methods for using file names to create -semaphore keys). If we use a well-known key, there's no reason to believe -that any particular key will not already be in use, either by another -instance of the DB application or some other application, in which case -the DB application will fail. If we create a key, then we have to use a -file system name to rendezvous and pass around the key. - -Second, System V semaphores traditionally have compile-time, system-wide -limits on the number of semaphore keys that you can have. Typically, that -number is far too low for any practical purpose. Since the semaphores -permit more than a single slot per semaphore key, we could try and get -around that limit by using multiple slots, but that means that the file -that we're using for rendezvous is going to have to contain slot -information as well as semaphore key information, and we're going to be -reading/writing it on every db_mutex_t init or destroy operation. Anyhow, -similar compile-time, system-wide limits on the numbers of slots per -semaphore key kick in, and you're right back where you started. - -My fantasy is that once POSIX.1 standard mutexes are in wide-spread use, -we can switch to them. My guess is that it won't happen, because the -POSIX semaphores are only required to work for threads within a process, -and not independent processes. - -Note: there are races in the statistics code, but since it's just that, -I didn't bother fixing them. (The fix requires a mutex tsl, so, when/if -this code is fixed to do rational locking (see above), then change the -statistics update code to acquire/release the mutex tsl. diff --git a/db2/mutex/alpha.h b/db2/mutex/alpha.h deleted file mode 100644 index ad3afc4..0000000 --- a/db2/mutex/alpha.h +++ /dev/null @@ -1,26 +0,0 @@ -/* For alpha, 0 is clear, 1 is set. */ - -#ifdef __GNUC__ -#define TSL_SET(tsl) ({ \ - register tsl_t *__l = (tsl); \ - int __r; \ - asm volatile( \ - "1: ldl_l %0,%1\n" \ - " blbs %0,2f\n" \ - " mov 1,%0\n" \ - " stl_c %0,%1\n" \ - " bne %0,1b\n" \ - " mb\n" \ - "2:" \ - : "=&r"(__r), "=m"(*__l) : "m"(*__l) : "memory"); \ - __r; \ -}) -#endif - -#ifdef __DECC -#include <alpha/builtins.h> -#define TSL_SET(tsl) (__LOCK_LONG_RETRY((tsl), 1) != 0) -#endif - -#define TSL_UNSET(tsl) (*(tsl) = 0) -#define TSL_INIT(tsl) TSL_UNSET(tsl) diff --git a/db2/mutex/mutex.c b/db2/mutex/mutex.c deleted file mode 100644 index 2fac14c..0000000 --- a/db2/mutex/mutex.c +++ /dev/null @@ -1,318 +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[] = "@(#)mutex.c 10.52 (Sleepycat) 11/8/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <fcntl.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#endif - -#include "db_int.h" - -#ifdef HAVE_SPINLOCKS - -#ifdef HAVE_FUNC_AIX -#define TSL_INIT(x) -#define TSL_SET(x) (!_check_lock(x, 0, 1)) -#define TSL_UNSET(x) _clear_lock(x, 0) -#endif - -#ifdef HAVE_ASSEM_MC68020_GCC -#include "68020.gcc" -#endif - -#if defined(HAVE_FUNC_MSEM) -/* - * !!! - * Do not remove the MSEM_IF_NOWAIT flag. The problem is that if a single - * process makes two msem_lock() calls in a row, the second one returns an - * error. We depend on the fact that we can lock against ourselves in the - * locking subsystem, where we set up a mutex so that we can block ourselves. - * Tested on OSF1 v4.0. - */ -#define TSL_INIT(x) (msem_init(x, MSEM_UNLOCKED) == NULL) -#define TSL_INIT_ERROR 1 -#define TSL_SET(x) (!msem_lock(x, MSEM_IF_NOWAIT)) -#define TSL_UNSET(x) msem_unlock(x, 0) -#endif - -#ifdef HAVE_FUNC_RELIANT -#define TSL_INIT(x) initspin(x, 1) -#define TSL_SET(x) (cspinlock(x) == 0) -#define TSL_UNSET(x) spinunlock(x) -#endif - -#ifdef HAVE_FUNC_SGI -#define TSL_INIT(x) (init_lock(x) != 0) -#define TSL_INIT_ERROR 1 -#define TSL_SET(x) (!acquire_lock(x)) -#define TSL_UNSET(x) release_lock(x) -#endif - -#ifdef HAVE_FUNC_SOLARIS -/* - * Semaphore calls don't work on Solaris 5.5. - * - * #define TSL_INIT(x) (sema_init(x, 1, USYNC_PROCESS, NULL) != 0) - * #define TSL_INIT_ERROR 1 - * #define TSL_SET(x) (sema_wait(x) == 0) - * #define TSL_UNSET(x) sema_post(x) - */ -#define TSL_INIT(x) -#define TSL_SET(x) (_lock_try(x)) -#define TSL_UNSET(x) _lock_clear(x) -#endif - -#ifdef HAVE_FUNC_VMS -#include <builtins.h> -#ifdef __ALPHA -#define TSL_SET(tsl) (!__TESTBITSSI(tsl, 0)) -#else /* __VAX */ -#define TSL_SET(tsl) (!(int)_BBSSI(0, tsl)) -#endif -#define TSL_UNSET(tsl) (*(tsl) = 0) -#define TSL_INIT(tsl) TSL_UNSET(tsl) -#endif - -#ifdef HAVE_ASSEM_PARISC_GCC -#include "parisc.gcc" -#endif - -#ifdef HAVE_ASSEM_SCO_CC -#include "sco.cc" -#endif - -#ifdef HAVE_ASSEM_SPARC_GCC -#include "sparc.gcc" -#endif - -#ifdef HAVE_ASSEM_UTS4_CC -#define TSL_INIT(x) -#define TSL_SET(x) (!uts_lock(x, 1)) -#define TSL_UNSET(x) (*(x) = 0) -#endif - -#ifdef HAVE_ASSEM_X86_GCC -#include "x86.gcc" -#endif - -#ifdef HAVE_ASSEM_ALPHA -#include "alpha.h" -#endif - -#ifdef WIN16 -/* Win16 spinlocks are simple because we cannot possibly be preempted. */ -#define TSL_INIT(tsl) -#define TSL_SET(tsl) (*(tsl) = 1) -#define TSL_UNSET(tsl) (*(tsl) = 0) -#endif - -#if defined(_WIN32) -/* - * XXX - * DBDB this needs to be byte-aligned!! - */ -#define TSL_INIT(tsl) -#define TSL_SET(tsl) (!InterlockedExchange((PLONG)tsl, 1)) -#define TSL_UNSET(tsl) (*(tsl) = 0) -#endif - -#endif /* HAVE_SPINLOCKS */ - -/* - * __db_mutex_init -- - * Initialize a DB mutex structure. - * - * PUBLIC: int __db_mutex_init __P((db_mutex_t *, u_int32_t)); - */ -int -__db_mutex_init(mp, off) - db_mutex_t *mp; - u_int32_t off; -{ -#ifdef DIAGNOSTIC - if ((ALIGNTYPE)mp & (MUTEX_ALIGNMENT - 1)) { - (void)fprintf(stderr, - "MUTEX ERROR: mutex NOT %d-byte aligned!\n", - MUTEX_ALIGNMENT); - abort(); - } -#endif - memset(mp, 0, sizeof(db_mutex_t)); - -#ifdef HAVE_SPINLOCKS - COMPQUIET(off, 0); - -#ifdef TSL_INIT_ERROR - if (TSL_INIT(&mp->tsl_resource)) - return (errno); -#else - TSL_INIT(&mp->tsl_resource); -#endif - mp->spins = __os_spin(); -#else - mp->off = off; -#endif - return (0); -} - -#define MS(n) ((n) * 1000) /* Milliseconds to micro-seconds. */ -#define SECOND (MS(1000)) /* A second's worth of micro-seconds. */ - -/* - * __db_mutex_lock - * Lock on a mutex, logically blocking if necessary. - * - * PUBLIC: int __db_mutex_lock __P((db_mutex_t *, int)); - */ -int -__db_mutex_lock(mp, fd) - db_mutex_t *mp; - int fd; -{ - u_long usecs; -#ifdef HAVE_SPINLOCKS - int nspins; -#else - struct flock k_lock; - pid_t mypid; - int locked; -#endif - - if (!DB_GLOBAL(db_mutexlocks)) - return (0); - -#ifdef HAVE_SPINLOCKS - COMPQUIET(fd, 0); - - for (usecs = MS(1);;) { - /* Try and acquire the uncontested resource lock for N spins. */ - for (nspins = mp->spins; nspins > 0; --nspins) - if (TSL_SET(&mp->tsl_resource)) { -#ifdef DIAGNOSTIC - if (mp->pid != 0) { - (void)fprintf(stderr, - "MUTEX ERROR: __db_mutex_lock: lock currently locked\n"); - abort(); - } - mp->pid = getpid(); -#endif - if (usecs == MS(1)) - ++mp->mutex_set_nowait; - else - ++mp->mutex_set_wait; - return (0); - } - - /* Yield the processor; wait 1ms initially, up to 1 second. */ - __os_yield(usecs); - if ((usecs <<= 1) > SECOND) - usecs = SECOND; - } - /* NOTREACHED */ - -#else /* !HAVE_SPINLOCKS */ - - /* Initialize the lock. */ - k_lock.l_whence = SEEK_SET; - k_lock.l_start = mp->off; - k_lock.l_len = 1; - - for (locked = 0, mypid = getpid();;) { - /* - * Wait for the lock to become available; wait 1ms initially, - * up to 1 second. - */ - for (usecs = MS(1); mp->pid != 0;) { - __os_yield(usecs); - if ((usecs <<= 1) > SECOND) - usecs = SECOND; - } - - /* Acquire an exclusive kernel lock. */ - k_lock.l_type = F_WRLCK; - if (fcntl(fd, F_SETLKW, &k_lock)) - return (errno); - - /* If the resource tsl is still available, it's ours. */ - if (mp->pid == 0) { - locked = 1; - mp->pid = mypid; - } - - /* Release the kernel lock. */ - k_lock.l_type = F_UNLCK; - if (fcntl(fd, F_SETLK, &k_lock)) - return (errno); - - /* - * If we got the resource tsl we're done. - * - * !!! - * We can't check to see if the lock is ours, because we may - * be trying to block ourselves in the lock manager, and so - * the holder of the lock that's preventing us from getting - * the lock may be us! (Seriously.) - */ - if (locked) - break; - } - return (0); -#endif /* !HAVE_SPINLOCKS */ -} - -/* - * __db_mutex_unlock -- - * Release a lock. - * - * PUBLIC: int __db_mutex_unlock __P((db_mutex_t *, int)); - */ -int -__db_mutex_unlock(mp, fd) - db_mutex_t *mp; - int fd; -{ - if (!DB_GLOBAL(db_mutexlocks)) - return (0); - -#ifdef DIAGNOSTIC - if (mp->pid == 0) { - (void)fprintf(stderr, - "MUTEX ERROR: __db_mutex_unlock: lock already unlocked\n"); - abort(); - } -#endif - -#ifdef HAVE_SPINLOCKS - COMPQUIET(fd, 0); - -#ifdef DIAGNOSTIC - mp->pid = 0; -#endif - - /* Release the resource tsl. */ - TSL_UNSET(&mp->tsl_resource); -#else - /* - * Release the resource tsl. We don't have to acquire any locks - * because processes trying to acquire the lock are checking for - * a pid of 0, not a specific value. - */ - mp->pid = 0; -#endif - return (0); -} diff --git a/db2/mutex/parisc.gcc b/db2/mutex/parisc.gcc deleted file mode 100644 index 2e4540f..0000000 --- a/db2/mutex/parisc.gcc +++ /dev/null @@ -1,36 +0,0 @@ -/* - * @(#)parisc.gcc 8.8 (Sleepycat) 6/2/98 - * - * Copyright (c) 1996-1997, The University of Utah and the Computer Systems - * Laboratory at the University of Utah (CSL). All rights reserved. - * - * Permission to use, copy, modify and distribute this software is hereby - * granted provided that (1) source code retains these copyright, permission, - * and disclaimer notices, and (2) redistributions including binaries - * reproduce the notices in supporting documentation, and (3) all advertising - * materials mentioning features or use of this software display the following - * acknowledgement: ``This product includes software developed by the Computer - * Systems Laboratory at the University of Utah.'' - * - * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS - * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF - * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * CSL requests users of this software to return to csl-dist@cs.utah.edu any - * improvements that they make and grant CSL redistribution rights. - */ - -/* - * The PA-RISC has a "load and clear" instead of a "test and set" instruction. - * The 32-bit word used by that instruction must be 16-byte aligned. We could - * use the "aligned" attribute in GCC but that doesn't work for stack variables. - */ -#define TSL_SET(tsl) ({ \ - register tsl_t *__l = (tsl); \ - int __r; \ - asm volatile("ldcws 0(%1),%0" : "=r" (__r) : "r" (__l)); \ - __r & 1; \ -}) - -#define TSL_UNSET(tsl) (*(tsl) = -1) -#define TSL_INIT(tsl) TSL_UNSET(tsl) diff --git a/db2/mutex/sco.cc b/db2/mutex/sco.cc deleted file mode 100644 index 7c165a2..0000000 --- a/db2/mutex/sco.cc +++ /dev/null @@ -1,24 +0,0 @@ -/* - * @(#)x86.uslc - * - * UnixWare has threads in libthread, but OpenServer doesn't (yet). - * - * For cc/x86, 0 is clear, 1 is set. - */ - -#if defined(__USLC__) -asm int -_tsl_set(void *tsl) -{ -%mem tsl - movl tsl, %ecx - movl $1, %eax - lock - xchgb (%ecx),%al - xorl $1,%eax -} -#endif - -#define TSL_SET(tsl) _tsl_set(tsl) -#define TSL_UNSET(tsl) (*(tsl) = 0) -#define TSL_INIT(tsl) TSL_UNSET(tsl) diff --git a/db2/mutex/sparc.gcc b/db2/mutex/sparc.gcc deleted file mode 100644 index 5eff176..0000000 --- a/db2/mutex/sparc.gcc +++ /dev/null @@ -1,31 +0,0 @@ -/* - * @(#)sparc.gcc 10.1 (Sleepycat) 4/12/97 - * - * The ldstub instruction takes the location specified by its first argument - * (a register containing a memory address) and loads its contents into its - * second argument (a register) and atomically sets the contents the location - * specified by its first argument to a byte of 1s. (The value in the second - * argument is never read, but only overwritten.) - * - * The membar instructions are needed to ensure that writes to the lock are - * correctly ordered with writes that occur later in the instruction stream. - * - * For gcc/sparc, 0 is clear, 1 is set. - */ - -/* The stbar is needed for v8, and is implemented as membar #sync on v9, - so is functional there as well. For v7, stbar may generate an illegal - instruction and we have no way to tell what we're running on. Some - operating systems notice and skip this instruction in the fault handler. */ - -#define TSL_SET(tsl) ({ \ - register tsl_t *__l = (tsl); \ - register tsl_t __r; \ - __asm__ volatile \ - ("ldstub [%1],%0; stbar" \ - : "=r"( __r) : "r" (__l)); \ - !__r; \ -}) - -#define TSL_UNSET(tsl) (*(tsl) = 0) -#define TSL_INIT(tsl) TSL_UNSET(tsl) diff --git a/db2/mutex/tsl_parisc.s b/db2/mutex/tsl_parisc.s deleted file mode 100644 index e605494..0000000 --- a/db2/mutex/tsl_parisc.s +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 1996-1997 The University of Utah and the Computer Systems - * Laboratory at the University of Utah (CSL). All rights reserved. - * - * Permission to use, copy, modify and distribute this software is hereby - * granted provided that (1) source code retains these copyright, permission, - * and disclaimer notices, and (2) redistributions including binaries - * reproduce the notices in supporting documentation, and (3) all advertising - * materials mentioning features or use of this software display the following - * acknowledgement: ``This product includes software developed by the Computer - * Systems Laboratory at the University of Utah.'' - * - * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS - * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF - * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * CSL requests users of this software to return to csl-dist@cs.utah.edu any - * improvements that they make and grant CSL redistribution rights. - * - * @(#)tsl_parisc.s 8.4 (Sleepycat) 1/18/97 - */ - -/* - * Spin locks for the PA-RISC. Based on Bob Wheeler's Mach implementation. - */ - .SPACE $TEXT$ - .SUBSPA $CODE$ - -/* - * int tsl_set(tsl_t *tsl) - * - * Try to acquire a lock, return 1 if successful, 0 if not. - */ - .EXPORT tsl_set,ENTRY -tsl_set - .PROC - .CALLINFO FRAME=0,NO_CALLS - .ENTRY - ldo 15(%r26),%r26 - depi 0,31,4,%r26 - ldcws 0(%r26),%r28 - subi,= 0,%r28,%r0 - ldi 1,%r28 - bv,n 0(%r2) - .EXIT - .PROCEND - - -/* - * void tsl_unset(tsl_t *tsl) - * - * Release a lock. - */ - .EXPORT tsl_unset,ENTRY -tsl_unset - .PROC - .CALLINFO FRAME=0,NO_CALLS - .ENTRY - ldo 15(%r26),%r26 - ldi -1,%r19 - depi 0,31,4,%r26 - bv 0(%r2) - stw %r19,0(%r26) - .EXIT - .PROCEND diff --git a/db2/mutex/uts4_cc.s b/db2/mutex/uts4_cc.s deleted file mode 100644 index ee5f414..0000000 --- a/db2/mutex/uts4_cc.s +++ /dev/null @@ -1,21 +0,0 @@ - / - / int uts_lock ( int *p, int i ); - / Update the lock word pointed to by p with the - / value i, using compare-and-swap. - / Returns 0 if update was successful. - / Returns 1 if update failed. - / - entry uts_lock - uts_lock: - using .,r15 - st r2,8(sp) / Save R2 - l r2,64+0(sp) / R2 -> word to update - slr r0, r0 / R0 = current lock value must be 0 - l r1,64+4(sp) / R1 = new lock value - cs r0,r1,0(r2) / Try the update ... - be x / ... Success. Return 0 - la r0,1 / ... Failure. Return 1 - x: / - l r2,8(sp) / Restore R2 - b 2(,r14) / Return to caller - drop r15 diff --git a/db2/mutex/x86.gcc b/db2/mutex/x86.gcc deleted file mode 100644 index 566b9c4..0000000 --- a/db2/mutex/x86.gcc +++ /dev/null @@ -1,17 +0,0 @@ -/* - * @(#)x86.gcc 10.3 (Sleepycat) 8/27/97 - * - * For gcc/x86, 0 is clear, 1 is set. - */ -#define TSL_SET(tsl) ({ \ - register tsl_t *__l = (tsl); \ - int __r; \ - asm volatile("movl $1,%%eax; lock; xchgb %1,%%al; xorl $1,%%eax"\ - : "=&a" (__r), "=m" (*__l) \ - : "1" (*__l) \ - ); \ - __r & 1; \ -}) - -#define TSL_UNSET(tsl) (*(tsl) = 0) -#define TSL_INIT(tsl) TSL_UNSET(tsl) diff --git a/db2/os/os_abs.c b/db2/os/os_abs.c deleted file mode 100644 index 547a680..0000000 --- a/db2/os/os_abs.c +++ /dev/null @@ -1,31 +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[] = "@(#)os_abs.c 10.9 (Sleepycat) 7/21/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> -#endif - -#include "db_int.h" - -/* - * __os_abspath -- - * Return if a path is an absolute path. - * - * PUBLIC: int __os_abspath __P((const char *)); - */ -int -__os_abspath(path) - const char *path; -{ - return (path[0] == '/'); -} diff --git a/db2/os/os_alloc.c b/db2/os/os_alloc.c deleted file mode 100644 index 0090eb1..0000000 --- a/db2/os/os_alloc.c +++ /dev/null @@ -1,219 +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[] = "@(#)os_alloc.c 10.10 (Sleepycat) 10/12/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <string.h> -#include <stdlib.h> -#endif - -#include "db_int.h" -#include "os_jump.h" - -/* - * !!! - * Correct for systems that return NULL when you allocate 0 bytes of memory. - * There are several places in DB where we allocate the number of bytes held - * by the key/data item, and it can be 0. Correct here so that malloc never - * returns a NULL for that reason (which behavior is permitted by ANSI). We - * could make these calls macros on non-Alpha architectures (that's where we - * saw the problem), but it's probably not worth the autoconf complexity. - * - * !!! - * Correct for systems that don't set errno when malloc and friends fail. - * - * Out of memory. - * We wish to hold the whole sky, - * But we never will. - */ - -/* - * __os_strdup -- - * The strdup(3) function for DB. - * - * PUBLIC: int __os_strdup __P((const char *, void *)); - */ -int -__os_strdup(str, storep) - const char *str; - void *storep; -{ - size_t size; - int ret; - void *p; - - *(void **)storep = NULL; - - size = strlen(str) + 1; - if ((ret = __os_malloc(size, NULL, &p)) != 0) - return (ret); - - memcpy(p, str, size); - - *(void **)storep = p; - return (0); -} - -/* - * __os_calloc -- - * The calloc(3) function for DB. - * - * PUBLIC: int __os_calloc __P((size_t, size_t, void *)); - */ -int -__os_calloc(num, size, storep) - size_t num, size; - void *storep; -{ - void *p; - int ret; - - size *= num; - if ((ret = __os_malloc(size, NULL, &p)) != 0) - return (ret); - - memset(p, 0, size); - *(void **)storep = p; - - return (0); -} - -/* - * __os_malloc -- - * The malloc(3) function for DB. - * - * PUBLIC: int __os_malloc __P((size_t, void *(*)(size_t), void *)); - */ -int -__os_malloc(size, db_malloc, storep) - size_t size; - void *(*db_malloc) __P((size_t)), *storep; -{ - void *p; - - *(void **)storep = NULL; - - /* Never allocate 0 bytes -- some C libraries don't like it. */ - if (size == 0) - ++size; - - /* Some C libraries don't correctly set errno when malloc(3) fails. */ - errno = 0; - if (db_malloc != NULL) - p = db_malloc(size); - else if (__db_jump.j_malloc != NULL) - p = __db_jump.j_malloc(size); - else - p = malloc(size); - if (p == NULL) { - if (errno == 0) - errno = ENOMEM; - return (errno); - } - -#ifdef DIAGNOSTIC - memset(p, 0xdb, size); -#endif - *(void **)storep = p; - - return (0); -} - -/* - * __os_realloc -- - * The realloc(3) function for DB. - * - * PUBLIC: int __os_realloc __P((void *, size_t)); - */ -int -__os_realloc(storep, size) - void *storep; - size_t size; -{ - void *p, *ptr; - - ptr = *(void **)storep; - - /* If we haven't yet allocated anything yet, simply call malloc. */ - if (ptr == NULL) - return (__os_malloc(size, NULL, storep)); - - /* Never allocate 0 bytes -- some C libraries don't like it. */ - if (size == 0) - ++size; - - /* - * Some C libraries don't correctly set errno when realloc(3) fails. - * - * Don't overwrite the original pointer, there are places in DB we - * try to continue after realloc fails. - */ - errno = 0; - if (__db_jump.j_realloc != NULL) - p = __db_jump.j_realloc(ptr, size); - else - p = realloc(ptr, size); - if (p == NULL) { - if (errno == 0) - errno = ENOMEM; - return (errno); - } - - *(void **)storep = p; - - return (0); -} - -/* - * __os_free -- - * The free(3) function for DB. - * - * PUBLIC: void __os_free __P((void *, size_t)); - */ -void -__os_free(ptr, size) - void *ptr; - size_t size; -{ -#ifdef DIAGNOSTIC - if (size != 0) - memset(ptr, 0xdb, size); -#endif - - if (__db_jump.j_free != NULL) - __db_jump.j_free(ptr); - else - free(ptr); -} - -/* - * __os_freestr -- - * The free(3) function for DB, freeing a string. - * - * PUBLIC: void __os_freestr __P((void *)); - */ -void -__os_freestr(ptr) - void *ptr; -{ -#ifdef DIAGNOSTIC - memset(ptr, 0xdb, strlen(ptr) + 1); -#endif - - if (__db_jump.j_free != NULL) - __db_jump.j_free(ptr); - else - free(ptr); -} diff --git a/db2/os/os_config.c b/db2/os/os_config.c deleted file mode 100644 index 71d379a..0000000 --- a/db2/os/os_config.c +++ /dev/null @@ -1,153 +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[] = "@(#)os_config.c 10.30 (Sleepycat) 10/12/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#endif - -#include "db_int.h" -#include "os_jump.h" - -struct __db_jumptab __db_jump; - -DB_GLOBALS __db_global_values = { - 1, /* DB_MUTEXLOCKS */ - 0, /* DB_PAGEYIELD */ - 0, /* DB_REGION_ANON, DB_REGION_NAME */ - 0, /* DB_REGION_INIT */ - 0, /* DB_TSL_SPINS */ - {NULL, &__db_global_values.db_envq.tqh_first}, /* Environemnt queue */ - {NULL, &__db_global_values.db_nameq.tqh_first} /* Name queue */ -}; - -/* - * db_jump_set -- - * Replace functions for the DB package. - */ -int -db_jump_set(func, which) - void *func; - int which; -{ - switch (which) { - case DB_FUNC_CLOSE: - __db_jump.j_close = (int (*) __P((int)))func; - break; - case DB_FUNC_DIRFREE: - __db_jump.j_dirfree = (void (*) __P((char **, int)))func; - break; - case DB_FUNC_DIRLIST: - __db_jump.j_dirlist = - (int (*) __P((const char *, char ***, int *)))func; - break; - case DB_FUNC_EXISTS: - __db_jump.j_exists = (int (*) __P((const char *, int *)))func; - break; - case DB_FUNC_FREE: - __db_jump.j_free = (void (*) __P((void *)))func; - break; - case DB_FUNC_FSYNC: - __db_jump.j_fsync = (int (*) __P((int)))func; - break; - case DB_FUNC_IOINFO: - __db_jump.j_ioinfo = (int (*) __P((const char *, - int, u_int32_t *, u_int32_t *, u_int32_t *)))func; - break; - case DB_FUNC_MALLOC: - __db_jump.j_malloc = (void *(*) __P((size_t)))func; - break; - case DB_FUNC_MAP: - __db_jump.j_map = (int (*) - __P((char *, int, size_t, int, int, int, void **)))func; - break; - case DB_FUNC_OPEN: - __db_jump.j_open = (int (*) __P((const char *, int, ...)))func; - break; - case DB_FUNC_READ: - __db_jump.j_read = - (ssize_t (*) __P((int, void *, size_t)))func; - break; - case DB_FUNC_REALLOC: - __db_jump.j_realloc = (void *(*) __P((void *, size_t)))func; - break; - case DB_FUNC_RUNLINK: - __db_jump.j_runlink = (int (*) __P((char *)))func; - break; - case DB_FUNC_SEEK: - __db_jump.j_seek = (int (*) - __P((int, size_t, db_pgno_t, u_int32_t, int, int)))func; - break; - case DB_FUNC_SLEEP: - __db_jump.j_sleep = (int (*) __P((u_long, u_long)))func; - break; - case DB_FUNC_UNLINK: - __db_jump.j_unlink = (int (*) __P((const char *)))func; - break; - case DB_FUNC_UNMAP: - __db_jump.j_unmap = (int (*) __P((void *, size_t)))func; - break; - case DB_FUNC_WRITE: - __db_jump.j_write = - (ssize_t (*) __P((int, const void *, size_t)))func; - break; - case DB_FUNC_YIELD: - __db_jump.j_yield = (int (*) __P((void)))func; - break; - default: - return (EINVAL); - } - return (0); -} - -/* - * db_value_set -- - * Replace values for the DB package. - */ -int -db_value_set(value, which) - int value, which; -{ - int ret; - - switch (which) { - case DB_MUTEXLOCKS: - DB_GLOBAL(db_mutexlocks) = value; - break; - case DB_PAGEYIELD: - DB_GLOBAL(db_pageyield) = value; - break; - case DB_REGION_ANON: - if (value != 0 && (ret = __db_mapanon_ok(0)) != 0) - return (ret); - DB_GLOBAL(db_region_anon) = value; - break; - case DB_REGION_INIT: - DB_GLOBAL(db_region_init) = value; - break; - case DB_REGION_NAME: - if (value != 0 && (ret = __db_mapanon_ok(1)) != 0) - return (ret); - DB_GLOBAL(db_region_anon) = value; - break; - case DB_TSL_SPINS: - if (value <= 0) - return (EINVAL); - DB_GLOBAL(db_tsl_spins) = value; - break; - default: - return (EINVAL); - } - return (0); -} diff --git a/db2/os/os_dir.c b/db2/os/os_dir.c deleted file mode 100644 index f2ee128..0000000 --- a/db2/os/os_dir.c +++ /dev/null @@ -1,101 +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[] = "@(#)os_dir.c 10.19 (Sleepycat) 10/12/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#if HAVE_DIRENT_H -# include <dirent.h> -# define NAMLEN(dirent) strlen((dirent)->d_name) -#else -# define dirent direct -# define NAMLEN(dirent) (dirent)->d_namlen -# if HAVE_SYS_NDIR_H -# include <sys/ndir.h> -# endif -# if HAVE_SYS_DIR_H -# include <sys/dir.h> -# endif -# if HAVE_NDIR_H -# include <ndir.h> -# endif -#endif - -#include <errno.h> -#endif - -#include "db_int.h" -#include "os_jump.h" - -/* - * __os_dirlist -- - * Return a list of the files in a directory. - * - * PUBLIC: int __os_dirlist __P((const char *, char ***, int *)); - */ -int -__os_dirlist(dir, namesp, cntp) - const char *dir; - char ***namesp; - int *cntp; -{ - struct dirent *dp; - DIR *dirp; - int arraysz, cnt, ret; - char **names; - - if (__db_jump.j_dirlist != NULL) - return (__db_jump.j_dirlist(dir, namesp, cntp)); - - if ((dirp = opendir(dir)) == NULL) - return (errno); - names = NULL; - for (arraysz = cnt = 0; (dp = readdir(dirp)) != NULL; ++cnt) { - if (cnt >= arraysz) { - arraysz += 100; - if ((ret = __os_realloc(&names, - arraysz * sizeof(names[0]))) != 0) - goto nomem; - } - if ((ret = __os_strdup(dp->d_name, &names[cnt])) != 0) - goto nomem; - } - (void)closedir(dirp); - - *namesp = names; - *cntp = cnt; - return (0); - -nomem: if (names != NULL) - __os_dirfree(names, cnt); - return (ret); -} - -/* - * __os_dirfree -- - * Free the list of files. - * - * PUBLIC: void __os_dirfree __P((char **, int)); - */ -void -__os_dirfree(names, cnt) - char **names; - int cnt; -{ - if (__db_jump.j_dirfree != NULL) - __db_jump.j_dirfree(names, cnt); - - while (cnt > 0) - __os_free(names[--cnt], 0); - __os_free(names, 0); -} diff --git a/db2/os/os_fid.c b/db2/os/os_fid.c deleted file mode 100644 index 62da590..0000000 --- a/db2/os/os_fid.c +++ /dev/null @@ -1,76 +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[] = "@(#)os_fid.c 10.12 (Sleepycat) 7/21/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> -#include <sys/stat.h> - -#include <errno.h> -#include <string.h> -#include <time.h> -#endif - -#include "db_int.h" -#include "common_ext.h" - -/* - * __os_fileid -- - * Return a unique identifier for a file. - * - * PUBLIC: int __os_fileid __P((DB_ENV *, const char *, int, u_int8_t *)); - */ -int -__os_fileid(dbenv, fname, timestamp, fidp) - DB_ENV *dbenv; - const char *fname; - int timestamp; - u_int8_t *fidp; -{ - struct stat sb; - size_t i; - time_t now; - u_int8_t *p; - - /* Clear the buffer. */ - memset(fidp, 0, DB_FILE_ID_LEN); - - /* Check for the unthinkable. */ - if (sizeof(sb.st_ino) + - sizeof(sb.st_dev) + sizeof(time_t) > DB_FILE_ID_LEN) - return (EINVAL); - - /* On UNIX, use a dev/inode pair. */ - if (stat(fname, &sb)) { - __db_err(dbenv, "%s: %s", fname, strerror(errno)); - return (errno); - } - - /* - * Use the inode first and in reverse order, hopefully putting the - * distinguishing information early in the string. - */ - for (p = (u_int8_t *)&sb.st_ino + - sizeof(sb.st_ino), i = 0; i < sizeof(sb.st_ino); ++i) - *fidp++ = *--p; - for (p = (u_int8_t *)&sb.st_dev + - sizeof(sb.st_dev), i = 0; i < sizeof(sb.st_dev); ++i) - *fidp++ = *--p; - - if (timestamp) { - (void)time(&now); - for (p = (u_int8_t *)&now + - sizeof(now), i = 0; i < sizeof(now); ++i) - *fidp++ = *--p; - } - return (0); -} diff --git a/db2/os/os_fsync.c b/db2/os/os_fsync.c deleted file mode 100644 index 61a504f..0000000 --- a/db2/os/os_fsync.c +++ /dev/null @@ -1,59 +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[] = "@(#)os_fsync.c 10.7 (Sleepycat) 10/12/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <fcntl.h> /* XXX: Required by __hp3000s900 */ -#include <unistd.h> -#endif - -#include "db_int.h" -#include "os_jump.h" - -#ifdef __hp3000s900 -int -__mpe_fsync(fd) - int fd; -{ - extern FCONTROL(short, short, void *); - - FCONTROL(_MPE_FILENO(fd), 2, NULL); /* Flush the buffers */ - FCONTROL(_MPE_FILENO(fd), 6, NULL); /* Write the EOF */ - return (0); -} -#endif - -#ifdef __hp3000s900 -#define fsync(fd) __mpe_fsync(fd); -#endif -#ifdef _WIN32 -#define fsync(fd) _commit(fd); -#endif - -/* - * __os_fsync -- - * Flush a file descriptor. - * - * PUBLIC: int __os_fsync __P((int)); - */ -int -__os_fsync(fd) - int fd; -{ - int ret; - - ret = __db_jump.j_fsync != NULL ? __db_jump.j_fsync(fd) : fsync(fd); - return (ret == 0 ? 0 : errno); -} diff --git a/db2/os/os_map.c b/db2/os/os_map.c deleted file mode 100644 index 5664a2e..0000000 --- a/db2/os/os_map.c +++ /dev/null @@ -1,447 +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[] = "@(#)os_map.c 10.24 (Sleepycat) 10/12/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> -#ifdef HAVE_MMAP -#include <sys/mman.h> -#endif - -#ifdef HAVE_SHMGET -#include <sys/ipc.h> -#include <sys/shm.h> -#endif - -#include <errno.h> -#include <string.h> -#endif - -#include "db_int.h" -#include "os_jump.h" -#include "common_ext.h" - -#ifdef HAVE_MMAP -static int __os_map __P((char *, int, size_t, int, int, int, void **)); -#endif -#ifdef HAVE_SHMGET -static int __os_shmget __P((REGINFO *)); -#endif - -/* - * __db_mapanon_ok -- - * Return if this OS can support anonymous memory regions. - * - * PUBLIC: int __db_mapanon_ok __P((int)); - */ -int -__db_mapanon_ok(need_names) - int need_names; -{ - int ret; - - ret = EINVAL; - - /* - * If we don't have spinlocks, we have to have a file descriptor - * for fcntl(2) locking, which implies using mmap(2) to map in a - * regular file. Theoretically, we could probably find ways to - * get a file descriptor to lock other types of shared regions, - * but I don't see any reason to do so. - * - * If need_names is set, the application wants to share anonymous - * memory among multiple processes, so we have to have a way to - * name it. This requires shmget(2), on UNIX systems. - */ -#ifdef HAVE_SPINLOCKS -#ifdef HAVE_SHMGET - ret = 0; -#endif -#ifdef HAVE_MMAP -#ifdef MAP_ANON - if (!need_names) - ret = 0; -#endif -#ifdef MAP_ANONYMOUS - if (!need_names) - ret = 0; -#endif -#else - COMPQUIET(need_names, 0); -#endif /* HAVE_MMAP */ -#endif /* HAVE_SPINLOCKS */ - - return (ret); -} - -/* - * __db_mapinit -- - * Return if shared regions need to be initialized. - * - * PUBLIC: int __db_mapinit __P((void)); - */ -int -__db_mapinit() -{ - /* - * Historically, some systems required that all of the bytes of the - * region be written before it could be mmapped and accessed randomly. - * We have the option of setting REGION_INIT_NEEDED at configuration - * time if we're running on one of those systems. - */ -#ifdef REGION_INIT_NEEDED - return (1); -#else - return (0); -#endif -} - -/* - * __db_mapregion -- - * Attach to a shared memory region. - * - * PUBLIC: int __db_mapregion __P((char *, REGINFO *)); - */ -int -__db_mapregion(path, infop) - char *path; - REGINFO *infop; -{ - int called, ret; - - called = 0; - ret = EINVAL; - - /* If the user replaces the map call, call through their interface. */ - if (__db_jump.j_map != NULL) { - F_SET(infop, REGION_HOLDINGSYS); - return (__db_jump.j_map(path, infop->fd, infop->size, - 1, F_ISSET(infop, REGION_ANONYMOUS), 0, &infop->addr)); - } - - if (F_ISSET(infop, REGION_ANONYMOUS)) { - /* - * !!! - * If we're creating anonymous regions: - * - * If it's private, we use mmap(2). The problem with using - * shmget(2) is that we may be creating a region of which the - * application isn't aware, and if the application crashes - * we'll have no way to remove the system resources for the - * region. - * - * If it's not private, we use the shmget(2) interface if it's - * available, because it allows us to name anonymous memory. - * If shmget(2) isn't available, use the mmap(2) calls. - * - * In the case of anonymous memory, using mmap(2) means the - * memory isn't named and only the single process and its - * threads can access the region. - */ -#ifdef HAVE_MMAP -#ifdef MAP_ANON -#define HAVE_MMAP_ANONYMOUS 1 -#else -#ifdef MAP_ANONYMOUS -#define HAVE_MMAP_ANONYMOUS 1 -#endif -#endif -#endif -#ifdef HAVE_MMAP_ANONYMOUS - if (!called && F_ISSET(infop, REGION_PRIVATE)) { - called = 1; - ret = __os_map(path, - infop->fd, infop->size, 1, 1, 0, &infop->addr); - } -#endif -#ifdef HAVE_SHMGET - if (!called) { - called = 1; - ret = __os_shmget(infop); - } -#endif -#ifdef HAVE_MMAP - /* - * If we're trying to join an unnamed anonymous region, fail -- - * that's not possible. - */ - if (!called) { - called = 1; - - if (!F_ISSET(infop, REGION_CREATED)) { - __db_err(infop->dbenv, - "cannot join region in unnamed anonymous memory"); - return (EINVAL); - } - - ret = __os_map(path, - infop->fd, infop->size, 1, 1, 0, &infop->addr); - } -#endif - } else { - /* - * !!! - * If we're creating normal regions, we use the mmap(2) - * interface if it's available because it's POSIX 1003.1 - * standard and we trust it more than we do shmget(2). - */ -#ifdef HAVE_MMAP - if (!called) { - called = 1; - - /* Mmap(2) regions that aren't anonymous can grow. */ - F_SET(infop, REGION_CANGROW); - - ret = __os_map(path, - infop->fd, infop->size, 1, 0, 0, &infop->addr); - } -#endif -#ifdef HAVE_SHMGET - if (!called) { - called = 1; - ret = __os_shmget(infop); - } -#endif - } - return (ret); -} - -/* - * __db_unmapregion -- - * Detach from the shared memory region. - * - * PUBLIC: int __db_unmapregion __P((REGINFO *)); - */ -int -__db_unmapregion(infop) - REGINFO *infop; -{ - int called, ret; - - called = 0; - ret = EINVAL; - - if (__db_jump.j_unmap != NULL) - return (__db_jump.j_unmap(infop->addr, infop->size)); - -#ifdef HAVE_SHMGET - if (infop->segid != INVALID_SEGID) { - called = 1; - ret = shmdt(infop->addr) ? errno : 0; - } -#endif -#ifdef HAVE_MMAP - if (!called) { - called = 1; - ret = munmap(infop->addr, infop->size) ? errno : 0; - } -#endif - return (ret); -} - -/* - * __db_unlinkregion -- - * Remove the shared memory region. - * - * PUBLIC: int __db_unlinkregion __P((char *, REGINFO *)); - */ -int -__db_unlinkregion(name, infop) - char *name; - REGINFO *infop; -{ - int called, ret; - - called = 0; - ret = EINVAL; - - if (__db_jump.j_runlink != NULL) - return (__db_jump.j_runlink(name)); - -#ifdef HAVE_SHMGET - if (infop->segid != INVALID_SEGID) { - called = 1; - ret = shmctl(infop->segid, IPC_RMID, NULL) ? errno : 0; - } -#endif -#ifdef HAVE_MMAP - COMPQUIET(infop, NULL); - if (!called) { - called = 1; - ret = 0; - } -#endif - return (ret); -} - -/* - * __db_mapfile -- - * Map in a shared memory file. - * - * PUBLIC: int __db_mapfile __P((char *, int, size_t, int, void **)); - */ -int -__db_mapfile(path, fd, len, is_rdonly, addr) - char *path; - int fd, is_rdonly; - size_t len; - void **addr; -{ - if (__db_jump.j_map != NULL) - return (__db_jump.j_map(path, fd, len, 0, 0, is_rdonly, addr)); - -#ifdef HAVE_MMAP - return (__os_map(path, fd, len, 0, 0, is_rdonly, addr)); -#else - return (EINVAL); -#endif -} - -/* - * __db_unmapfile -- - * Unmap the shared memory file. - * - * PUBLIC: int __db_unmapfile __P((void *, size_t)); - */ -int -__db_unmapfile(addr, len) - void *addr; - size_t len; -{ - if (__db_jump.j_unmap != NULL) - return (__db_jump.j_unmap(addr, len)); - -#ifdef HAVE_MMAP - return (munmap(addr, len) ? errno : 0); -#else - return (EINVAL); -#endif -} - -#ifdef HAVE_MMAP -/* - * __os_map -- - * Call the mmap(2) function. - */ -static int -__os_map(path, fd, len, is_region, is_anonymous, is_rdonly, addr) - char *path; - int fd, is_region, is_anonymous, is_rdonly; - size_t len; - void **addr; -{ - void *p; - int flags, prot; - - COMPQUIET(path, NULL); - - /* - * If it's read-only, it's private, and if it's not, it's shared. - * Don't bother with an additional parameter. - */ - flags = is_rdonly ? MAP_PRIVATE : MAP_SHARED; - - if (is_region && is_anonymous) { - /* - * BSD derived systems use MAP_ANON; Digital Unix and HP/UX - * use MAP_ANONYMOUS. - */ -#ifdef MAP_ANON - flags |= MAP_ANON; -#endif -#ifdef MAP_ANONYMOUS - flags |= MAP_ANONYMOUS; -#endif - fd = -1; - } -#ifdef MAP_FILE - if (!is_region || !is_anonymous) { - /* - * Historically, MAP_FILE was required for mapping regular - * files, even though it was the default. Some systems have - * it, some don't, some that have it set it to 0. - */ - flags |= MAP_FILE; - } -#endif - - /* - * I know of no systems that implement the flag to tell the system - * that the region contains semaphores, but it's not an unreasonable - * thing to do, and has been part of the design since forever. I - * don't think anyone will object, but don't set it for read-only - * files, it doesn't make sense. - */ -#ifdef MAP_HASSEMAPHORE - if (!is_rdonly) - flags |= MAP_HASSEMAPHORE; -#endif - - prot = PROT_READ | (is_rdonly ? 0 : PROT_WRITE); - -/* - * XXX - * Work around a bug in the VMS V7.1 mmap() implementation. To map a file - * into memory on VMS it needs to be opened in a certain way, originally. - * To get the file opened in that certain way, the VMS mmap() closes the - * file and re-opens it. When it does this, it doesn't flush any caches - * out to disk before closing. The problem this causes us is that when the - * memory cache doesn't get written out, the file isn't big enough to match - * the memory chunk and the mmap() call fails. This call to fsync() fixes - * the problem. DEC thinks this isn't a bug because of language in XPG5 - * discussing user responsibility for on-disk and in-memory synchronization. - */ -#ifdef VMS - if (__os_fsync(fd) == -1) - return(errno); -#endif - - /* MAP_FAILED was not defined in early mmap implementations. */ -#ifndef MAP_FAILED -#define MAP_FAILED -1 -#endif - if ((p = - mmap(NULL, len, prot, flags, fd, (off_t)0)) == (void *)MAP_FAILED) - return (errno); - - *addr = p; - return (0); -} -#endif - -#ifdef HAVE_SHMGET -/* - * __os_shmget -- - * Call the shmget(2) family of functions. - */ -static int -__os_shmget(infop) - REGINFO *infop; -{ - if (F_ISSET(infop, REGION_CREATED) && - (infop->segid = shmget(0, infop->size, IPC_PRIVATE | 0600)) == -1) - return (errno); - - if ((infop->addr = shmat(infop->segid, NULL, 0)) == (void *)-1) { - /* - * If we're trying to join the region and failing, assume - * that there was a reboot and the region no longer exists. - */ - if (!F_ISSET(infop, REGION_CREATED)) - errno = EAGAIN; - return (errno); - } - - F_SET(infop, REGION_HOLDINGSYS); - return (0); -} -#endif diff --git a/db2/os/os_oflags.c b/db2/os/os_oflags.c deleted file mode 100644 index a4003dd..0000000 --- a/db2/os/os_oflags.c +++ /dev/null @@ -1,99 +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[] = "@(#)os_oflags.c 10.6 (Sleepycat) 4/19/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> -#include <sys/stat.h> - -#include <fcntl.h> -#endif - -#include "db_int.h" - -/* - * __db_oflags -- - * Convert open(2) flags to DB flags. - * - * PUBLIC: u_int32_t __db_oflags __P((int)); - */ -u_int32_t -__db_oflags(oflags) - int oflags; -{ - u_int32_t dbflags; - - /* - * Convert POSIX 1003.1 open(2) flags to DB flags. - */ - dbflags = 0; - switch (oflags & O_ACCMODE) { - case O_RDONLY: - dbflags |= DB_RDONLY; - break; - case O_WRONLY: - case O_RDWR: - break; - default: /* Bogus flags value from user. */ - /* XXX no way to return error from here */ - } - if (oflags & O_CREAT) - dbflags |= DB_CREATE; - if (oflags & O_TRUNC) - dbflags |= DB_TRUNCATE; - return (dbflags); -} - -/* - * __db_omode -- - * Convert a permission string to the correct open(2) flags. - * - * PUBLIC: int __db_omode __P((const char *)); - */ -int -__db_omode(perm) - const char *perm; -{ - int mode; - -#ifndef S_IRUSR -#if defined(_WIN32) || defined(WIN16) -#define S_IRUSR S_IREAD /* R for owner */ -#define S_IWUSR S_IWRITE /* W for owner */ -#define S_IRGRP 0 /* R for group */ -#define S_IWGRP 0 /* W for group */ -#define S_IROTH 0 /* R for other */ -#define S_IWOTH 0 /* W for other */ -#else -#define S_IRUSR 0000400 /* R for owner */ -#define S_IWUSR 0000200 /* W for owner */ -#define S_IRGRP 0000040 /* R for group */ -#define S_IWGRP 0000020 /* W for group */ -#define S_IROTH 0000004 /* R for other */ -#define S_IWOTH 0000002 /* W for other */ -#endif /* _WIN32 || WIN16 */ -#endif - mode = 0; - if (perm[0] == 'r') - mode |= S_IRUSR; - if (perm[1] == 'w') - mode |= S_IWUSR; - if (perm[2] == 'r') - mode |= S_IRGRP; - if (perm[3] == 'w') - mode |= S_IWGRP; - if (perm[4] == 'r') - mode |= S_IROTH; - if (perm[5] == 'w') - mode |= S_IWOTH; - return (mode); -} diff --git a/db2/os/os_open.c b/db2/os/os_open.c deleted file mode 100644 index c54fd73..0000000 --- a/db2/os/os_open.c +++ /dev/null @@ -1,152 +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[] = "@(#)os_open.c 10.33 (Sleepycat) 10/12/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <fcntl.h> -#include <signal.h> -#include <unistd.h> -#endif - -#include "db_int.h" -#include "os_jump.h" - -/* - * __db_open -- - * Open a file descriptor. - * - * PUBLIC: int __db_open __P((const char *, u_int32_t, u_int32_t, int, int *)); - */ -int -__db_open(name, arg_flags, ok_flags, mode, fdp) - const char *name; - u_int32_t arg_flags, ok_flags; - int mode, *fdp; -{ -#if !defined(_WIN32) && defined(HAVE_SIGFILLSET) - sigset_t set, oset; -#endif - int flags, ret; - - if (arg_flags & ~ok_flags) - return (EINVAL); - - flags = 0; - - /* - * DB requires the semantic that two files opened at the same time - * with O_CREAT and O_EXCL set will return failure in at least one. - */ - if (arg_flags & DB_CREATE) - flags |= O_CREAT; - - if (arg_flags & DB_EXCL) - flags |= O_EXCL; - - if (arg_flags & DB_RDONLY) - flags |= O_RDONLY; - else - flags |= O_RDWR; - -#if defined(_WIN32) || defined(WIN16) -#ifdef _MSC_VER - if (arg_flags & DB_SEQUENTIAL) - flags |= _O_SEQUENTIAL; - else - flags |= _O_RANDOM; - - if (arg_flags & DB_TEMPORARY) - flags |= _O_TEMPORARY; -#endif - flags |= O_BINARY | O_NOINHERIT; -#endif - - if (arg_flags & DB_TRUNCATE) - flags |= O_TRUNC; - -#if !defined(_WIN32) && defined(HAVE_SIGFILLSET) - /* - * We block every signal we can get our hands on so that the temporary - * file isn't left around if we're interrupted at the wrong time. Of - * course, if we drop core in-between the calls we'll hang forever, but - * that's probably okay. ;-) - */ - if (arg_flags & DB_TEMPORARY) { - (void)sigfillset(&set); - (void)sigprocmask(SIG_BLOCK, &set, &oset); - } -#endif - - /* Open the file. */ - if ((ret = __os_open(name, flags, mode, fdp)) != 0) - return (ret); - -#if !defined(_WIN32) - /* Delete any temporary file; done for Win32 by _O_TEMPORARY. */ - if (arg_flags & DB_TEMPORARY) { - (void)__os_unlink(name); -#if defined(HAVE_SIGFILLSET) - (void)sigprocmask(SIG_SETMASK, &oset, NULL); -#endif - } -#endif - -#if !defined(_WIN32) && !defined(WIN16) && !defined(VMS) - /* - * Deny access to any child process. - * VMS: does not have fd inheritance. - * Win32: done by O_NOINHERIT. - */ - if (fcntl(*fdp, F_SETFD, 1) == -1) { - ret = errno; - - (void)__os_close(*fdp); - return (ret); - } -#endif - return (0); -} - -/* - * __os_open -- - * Open a file. - * - * PUBLIC: int __os_open __P((const char *, int, int, int *)); - */ -int -__os_open(name, flags, mode, fdp) - const char *name; - int flags, mode, *fdp; -{ - *fdp = __db_jump.j_open != NULL ? - __db_jump.j_open(name, flags, mode) : open(name, flags, mode); - return (*fdp == -1 ? errno : 0); -} - -/* - * __os_close -- - * Close a file descriptor. - * - * PUBLIC: int __os_close __P((int)); - */ -int -__os_close(fd) - int fd; -{ - int ret; - - ret = __db_jump.j_close != NULL ? __db_jump.j_close(fd) : close(fd); - return (ret == 0 ? 0 : errno); -} diff --git a/db2/os/os_rpath.c b/db2/os/os_rpath.c deleted file mode 100644 index 23867b3..0000000 --- a/db2/os/os_rpath.c +++ /dev/null @@ -1,42 +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[] = "@(#)os_rpath.c 10.3 (Sleepycat) 4/10/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <string.h> -#endif - -#include "db_int.h" - -/* - * __db_rpath -- - * Return the last path separator in the path or NULL if none found. - * - * PUBLIC: char *__db_rpath __P((const char *)); - */ -char * -__db_rpath(path) - const char *path; -{ - const char *s, *last; - - last = NULL; - if (PATH_SEPARATOR[1] != '\0') { - for (s = path; s[0] != '\0'; ++s) - if (strchr(PATH_SEPARATOR, s[0]) != NULL) - last = s; - } else - for (s = path; s[0] != '\0'; ++s) - if (s[0] == PATH_SEPARATOR[0]) - last = s; - return ((char *)last); -} diff --git a/db2/os/os_rw.c b/db2/os/os_rw.c deleted file mode 100644 index e0a8163..0000000 --- a/db2/os/os_rw.c +++ /dev/null @@ -1,136 +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[] = "@(#)os_rw.c 10.11 (Sleepycat) 10/12/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <unistd.h> -#endif - -#include "db_int.h" -#include "os_jump.h" - -/* - * __os_io -- - * Do an I/O. - * - * PUBLIC: int __os_io __P((DB_IO *, int, ssize_t *)); - */ -int -__os_io(db_iop, op, niop) - DB_IO *db_iop; - int op; - ssize_t *niop; -{ - int ret; - -#ifdef HAVE_PREAD - switch (op) { - case DB_IO_READ: - if (__db_jump.j_read != NULL) - goto slow; - *niop = pread(db_iop->fd_io, db_iop->buf, - db_iop->bytes, (off_t)db_iop->pgno * db_iop->pagesize); - break; - case DB_IO_WRITE: - if (__db_jump.j_write != NULL) - goto slow; - *niop = pwrite(db_iop->fd_io, db_iop->buf, - db_iop->bytes, (off_t)db_iop->pgno * db_iop->pagesize); - break; - } - if (*niop == db_iop->bytes) - return (0); -slow: -#endif - if (db_iop->mutexp != NULL) - (void)__db_mutex_lock(db_iop->mutexp, db_iop->fd_lock); - - if ((ret = __os_seek(db_iop->fd_io, - db_iop->pagesize, db_iop->pgno, 0, 0, SEEK_SET)) != 0) - goto err; - switch (op) { - case DB_IO_READ: - ret = - __os_read(db_iop->fd_io, db_iop->buf, db_iop->bytes, niop); - break; - case DB_IO_WRITE: - ret = - __os_write(db_iop->fd_io, db_iop->buf, db_iop->bytes, niop); - break; - } - -err: if (db_iop->mutexp != NULL) - (void)__db_mutex_unlock(db_iop->mutexp, db_iop->fd_lock); - - return (ret); - -} - -/* - * __os_read -- - * Read from a file handle. - * - * PUBLIC: int __os_read __P((int, void *, size_t, ssize_t *)); - */ -int -__os_read(fd, addr, len, nrp) - int fd; - void *addr; - size_t len; - ssize_t *nrp; -{ - size_t offset; - ssize_t nr; - u_int8_t *taddr; - - for (taddr = addr, - offset = 0; offset < len; taddr += nr, offset += nr) { - if ((nr = __db_jump.j_read != NULL ? - __db_jump.j_read(fd, taddr, len - offset) : - read(fd, taddr, len - offset)) < 0) - return (errno); - if (nr == 0) - break; - } - *nrp = taddr - (u_int8_t *)addr; - return (0); -} - -/* - * __os_write -- - * Write to a file handle. - * - * PUBLIC: int __os_write __P((int, void *, size_t, ssize_t *)); - */ -int -__os_write(fd, addr, len, nwp) - int fd; - const void *addr; - size_t len; - ssize_t *nwp; -{ - size_t offset; - ssize_t nw; - const u_int8_t *taddr; - - for (taddr = addr, - offset = 0; offset < len; taddr += nw, offset += nw) - if ((nw = __db_jump.j_write != NULL ? - __db_jump.j_write(fd, taddr, len - offset) : - write(fd, taddr, len - offset)) < 0) - return (errno); - *nwp = len; - return (0); -} diff --git a/db2/os/os_seek.c b/db2/os/os_seek.c deleted file mode 100644 index ae5272b..0000000 --- a/db2/os/os_seek.c +++ /dev/null @@ -1,52 +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[] = "@(#)os_seek.c 10.11 (Sleepycat) 10/12/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <unistd.h> -#endif - -#include "db_int.h" -#include "os_jump.h" - -/* - * __os_seek -- - * Seek to a page/byte offset in the file. - * - * PUBLIC: int __os_seek __P((int, size_t, db_pgno_t, u_int32_t, int, int)); - */ -int -__os_seek(fd, pgsize, pageno, relative, isrewind, whence) - int fd; - size_t pgsize; - db_pgno_t pageno; - u_int32_t relative; - int isrewind, whence; -{ - off_t offset; - int ret; - - if (__db_jump.j_seek != NULL) - ret = __db_jump.j_seek(fd, - pgsize, pageno, relative, isrewind, whence); - else { - offset = (off_t)pgsize * pageno + relative; - if (isrewind) - offset = -offset; - - ret = lseek(fd, offset, whence); - } - return (ret == -1 ? errno : 0); -} diff --git a/db2/os/os_sleep.c b/db2/os/os_sleep.c deleted file mode 100644 index 5aa4763..0000000 --- a/db2/os/os_sleep.c +++ /dev/null @@ -1,59 +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[] = "@(#)os_sleep.c 10.12 (Sleepycat) 10/12/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> -#ifdef HAVE_SYS_TIME_H -#include <sys/time.h> -#endif -#ifdef HAVE_SYS_SELECT_H -#include <sys/select.h> -#endif - -#include <errno.h> -#ifndef HAVE_SYS_TIME_H -#include <time.h> -#endif -#include <unistd.h> -#endif - -#include "db_int.h" -#include "os_jump.h" - -/* - * __os_sleep -- - * Yield the processor for a period of time. - * - * PUBLIC: int __os_sleep __P((u_long, u_long)); - */ -int -__os_sleep(secs, usecs) - u_long secs, usecs; /* Seconds and microseconds. */ -{ - struct timeval t; - - /* Don't require that the values be normalized. */ - for (; usecs >= 1000000; ++secs, usecs -= 1000000) - ; - - if (__db_jump.j_sleep != NULL) - return (__db_jump.j_sleep(secs, usecs)); - - /* - * It's important that we yield the processor here so that other - * processes or threads are permitted to run. - */ - t.tv_sec = secs; - t.tv_usec = usecs; - return (select(0, NULL, NULL, NULL, &t) == -1 ? errno : 0); -} diff --git a/db2/os/os_spin.c b/db2/os/os_spin.c deleted file mode 100644 index cbde588..0000000 --- a/db2/os/os_spin.c +++ /dev/null @@ -1,107 +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[] = "@(#)os_spin.c 10.10 (Sleepycat) 10/12/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> -#if defined(HAVE_PSTAT_GETDYNAMIC) -#include <sys/pstat.h> -#endif - -#include <limits.h> -#include <unistd.h> -#endif - -#include "db_int.h" -#include "os_jump.h" - -#if defined(HAVE_PSTAT_GETDYNAMIC) -/* - * __os_pstat_getdynamic -- - * HP/UX. - */ -static int -__os_pstat_getdynamic() -{ - struct pst_dynamic psd; - - return (pstat_getdynamic(&psd, - sizeof(psd), (size_t)1, 0) == -1 ? 1 : psd.psd_proc_cnt); -} -#endif - -#if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN) -/* - * __os_sysconf -- - * Solaris, Linux. - */ -static int -__os_sysconf(void) -{ - int nproc; - - return ((nproc = sysconf(_SC_NPROCESSORS_ONLN)) > 1 ? nproc : 1); -} -#endif - -/* - * __os_spin -- - * Return the number of default spins before blocking. - * - * PUBLIC: int __os_spin __P((void)); - */ -int -__os_spin() -{ - /* - * If the application specified a value or we've already figured it - * out, return it. - * - * XXX - * We don't want to repeatedly call the underlying function because - * it can be expensive (e.g., requiring multiple filesystem accesses - * under Debian Linux). - */ - if (DB_GLOBAL(db_tsl_spins) != 0) - return (DB_GLOBAL(db_tsl_spins)); - - DB_GLOBAL(db_tsl_spins) = 1; -#if defined(HAVE_PSTAT_GETDYNAMIC) - DB_GLOBAL(db_tsl_spins) = __os_pstat_getdynamic(); -#endif -#if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN) - DB_GLOBAL(db_tsl_spins) = __os_sysconf(); -#endif - - /* - * Spin 50 times per processor, we have anecdotal evidence that this - * is a reasonable value. - */ - DB_GLOBAL(db_tsl_spins) *= 50; - - return (DB_GLOBAL(db_tsl_spins)); -} - -/* - * __os_yield -- - * Yield the processor. - * - * PUBLIC: void __os_yield __P((u_long)); - */ -void -__os_yield(usecs) - u_long usecs; -{ - if (__db_jump.j_yield != NULL && __db_jump.j_yield() == 0) - return; - __os_sleep(0, usecs); -} diff --git a/db2/os/os_stat.c b/db2/os/os_stat.c deleted file mode 100644 index 65cba82..0000000 --- a/db2/os/os_stat.c +++ /dev/null @@ -1,99 +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[] = "@(#)os_stat.c 10.18 (Sleepycat) 10/12/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> -#include <sys/stat.h> - -#include <errno.h> -#endif - -#include "db_int.h" -#include "os_jump.h" - -/* - * __os_exists -- - * Return if the file exists. - * - * PUBLIC: int __os_exists __P((const char *, int *)); - */ -int -__os_exists(path, isdirp) - const char *path; - int *isdirp; -{ - struct stat sb; - - if (__db_jump.j_exists != NULL) - return (__db_jump.j_exists(path, isdirp)); - - if (stat(path, &sb) != 0) - return (errno); - -#if !defined(S_ISDIR) || defined(STAT_MACROS_BROKEN) -#if defined(_WIN32) || defined(WIN16) -#define S_ISDIR(m) (_S_IFDIR & (m)) -#else -#define S_ISDIR(m) (((m) & 0170000) == 0040000) -#endif -#endif - if (isdirp != NULL) - *isdirp = S_ISDIR(sb.st_mode); - - return (0); -} - -/* - * __os_ioinfo -- - * Return file size and I/O size; abstracted to make it easier - * to replace. - * - * PUBLIC: int __os_ioinfo - * PUBLIC: __P((const char *, int, u_int32_t *, u_int32_t *, u_int32_t *)); - */ -int -__os_ioinfo(path, fd, mbytesp, bytesp, iosizep) - const char *path; - int fd; - u_int32_t *mbytesp, *bytesp, *iosizep; -{ - struct stat sb; - - if (__db_jump.j_ioinfo != NULL) - return (__db_jump.j_ioinfo(path, fd, mbytesp, bytesp, iosizep)); - - if (fstat(fd, &sb) == -1) - return (errno); - - /* Return the size of the file. */ - if (mbytesp != NULL) - *mbytesp = sb.st_size / MEGABYTE; - if (bytesp != NULL) - *bytesp = sb.st_size % MEGABYTE; - - /* - * Return the underlying filesystem blocksize, if available. - * - * XXX - * Check for a 0 size -- the HP MPE/iX architecture has st_blksize, - * but it's always 0. - */ -#ifdef HAVE_ST_BLKSIZE - if (iosizep != NULL && (*iosizep = sb.st_blksize) == 0) - *iosizep = DB_DEF_IOSIZE; -#else - if (iosizep != NULL) - *iosizep = DB_DEF_IOSIZE; -#endif - return (0); -} diff --git a/db2/os/os_tmpdir.c b/db2/os/os_tmpdir.c deleted file mode 100644 index 0b0bbc7..0000000 --- a/db2/os/os_tmpdir.c +++ /dev/null @@ -1,113 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1998 - * Sleepycat Software. All rights reserved. - */ - -#include "config.h" - -#ifndef lint -static const char sccsid[] = "@(#)os_tmpdir.c 10.3 (Sleepycat) 10/13/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <stdlib.h> -#endif - -#include "db_int.h" -#include "common_ext.h" - -#ifdef macintosh -#include <TFileSpec.h> -#endif - -/* - * __os_tmpdir -- - * Set the temporary directory path. - * - * The order of items in the list structure and the order of checks in - * the environment are documented. - * - * PUBLIC: int __os_tmpdir __P((DB_ENV *, u_int32_t)); - */ -int -__os_tmpdir(dbenv, flags) - DB_ENV *dbenv; - u_int32_t flags; -{ - /* - * !!! - * Don't change this to: - * - * static const char * const list[] - * - * because it creates a text relocation in position independent code. - */ - static const char * list[] = { - "/var/tmp", - "/usr/tmp", - "/temp", /* Windows. */ - "/tmp", - "C:/temp", /* Windows. */ - "C:/tmp", /* Windows. */ - NULL - }; - const char * const *lp, *p; - - /* Use the environment if it's permitted and initialized. */ - p = NULL; -#ifdef HAVE_GETEUID - 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("TMPDIR")) != NULL && p[0] == '\0') { - __db_err(dbenv, "illegal TMPDIR environment variable"); - return (EINVAL); - } - /* Windows */ - if (p == NULL && (p = getenv("TEMP")) != NULL && p[0] == '\0') { - __db_err(dbenv, "illegal TEMP environment variable"); - return (EINVAL); - } - /* Windows */ - if (p == NULL && (p = getenv("TMP")) != NULL && p[0] == '\0') { - __db_err(dbenv, "illegal TMP environment variable"); - return (EINVAL); - } - /* Macintosh */ - if (p == NULL && - (p = getenv("TempFolder")) != NULL && p[0] == '\0') { - __db_err(dbenv, - "illegal TempFolder environment variable"); - return (EINVAL); - } - } - -#ifdef macintosh - /* Get the path to the temporary folder. */ - if (p == NULL) { - FSSpec spec; - - if (!Special2FSSpec(kTemporaryFolderType, - kOnSystemDisk, 0, &spec)) - (void)__os_strdup(FSp2FullPath(&spec), &p); - } -#endif - - /* Step through the list looking for a possibility. */ - if (p == NULL) - for (lp = list; *lp != NULL; ++lp) - if (__os_exists(p = *lp, NULL) == 0) - break; - if (p == NULL) - return (0); - - return (__os_strdup(p, &dbenv->db_tmp_dir)); -} diff --git a/db2/os/os_unlink.c b/db2/os/os_unlink.c deleted file mode 100644 index aa484de..0000000 --- a/db2/os/os_unlink.c +++ /dev/null @@ -1,39 +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[] = "@(#)os_unlink.c 10.7 (Sleepycat) 10/12/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <unistd.h> -#endif - -#include "db_int.h" -#include "os_jump.h" - -/* - * __os_unlink -- - * Remove a file. - * - * PUBLIC: int __os_unlink __P((const char *)); - */ -int -__os_unlink(path) - const char *path; -{ - int ret; - - ret = __db_jump.j_unlink != NULL ? - __db_jump.j_unlink(path) : unlink(path); - return (ret == -1 ? errno : 0); -} diff --git a/db2/progs/db_archive/db_archive.c b/db2/progs/db_archive/db_archive.c deleted file mode 100644 index ca48995..0000000 --- a/db2/progs/db_archive/db_archive.c +++ /dev/null @@ -1,156 +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_archive.c 10.20 (Sleepycat) 10/3/98"; -#endif - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <signal.h> -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#include <unistd.h> -#endif - -#include "db_int.h" -#include "shqueue.h" -#include "log.h" -#include "db_dispatch.h" -#include "clib_ext.h" -#include "common_ext.h" - -DB_ENV *db_init __P((char *, int)); -int main __P((int, char *[])); -void nosig __P((void)); -void usage __P((void)); - -const char - *progname = "db_archive"; /* Program name. */ - -int -main(argc, argv) - int argc; - char *argv[]; -{ - extern char *optarg; - extern int optind; - DB_ENV *dbenv; - u_int32_t flags; - int ch, verbose; - char *home, **list; - - flags = verbose = 0; - home = NULL; - while ((ch = getopt(argc, argv, "ah:lsv")) != EOF) - switch (ch) { - case 'a': - flags |= DB_ARCH_ABS; - break; - case 'h': - home = optarg; - break; - case 'l': - flags |= DB_ARCH_LOG; - break; - case 's': - flags |= DB_ARCH_DATA; - break; - case 'v': - verbose = 1; - break; - case '?': - default: - usage(); - } - argc -= optind; - argv += optind; - - if (argc != 0) - usage(); - - /* - * Ignore signals -- we don't want to be interrupted because we're - * spending all of our time in the DB library. - */ - nosig(); - dbenv = db_init(home, verbose); - - /* Get the list of names. */ - if ((errno = log_archive(dbenv->lg_info, &list, flags, NULL)) != 0) { - warn(NULL); - (void)db_appexit(dbenv); - return (1); - } - - /* Print the names. */ - if (list != NULL) - for (; *list != NULL; ++list) - printf("%s\n", *list); - - if ((errno = db_appexit(dbenv)) != 0) { - warn(NULL); - return (1); - } - - return (0); -} - -/* - * db_init -- - * Initialize the environment. - */ -DB_ENV * -db_init(home, verbose) - char *home; - int verbose; -{ - DB_ENV *dbenv; - - if ((dbenv = (DB_ENV *)calloc(sizeof(DB_ENV), 1)) == NULL) { - errno = ENOMEM; - err(1, NULL); - } - dbenv->db_errfile = stderr; - dbenv->db_errpfx = progname; - dbenv->db_verbose = verbose; - - if ((errno = db_appinit(home, NULL, dbenv, - DB_CREATE | DB_INIT_LOG | DB_INIT_TXN | DB_USE_ENVIRON)) != 0) - err(1, "db_appinit"); - - return (dbenv); -} - -/* - * nosig -- - * We don't want to be interrupted. - */ -void -nosig() -{ -#ifdef SIGHUP - (void)signal(SIGHUP, SIG_IGN); -#endif - (void)signal(SIGINT, SIG_IGN); - (void)signal(SIGTERM, SIG_IGN); -} - -void -usage() -{ - (void)fprintf(stderr, "usage: db_archive [-alsv] [-h home]\n"); - exit(1); -} diff --git a/db2/progs/db_checkpoint/db_checkpoint.c b/db2/progs/db_checkpoint/db_checkpoint.c deleted file mode 100644 index f0fe48a..0000000 --- a/db2/progs/db_checkpoint/db_checkpoint.c +++ /dev/null @@ -1,263 +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_checkpoint.c 10.21 (Sleepycat) 10/4/98"; -#endif - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <limits.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.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 "btree.h" -#include "hash.h" -#include "clib_ext.h" -#include "common_ext.h" - -char *check __P((DB_ENV *, long, long)); -DB_ENV *db_init __P((char *)); -int logpid __P((char *, int)); -int main __P((int, char *[])); -void onint __P((int)); -void siginit __P((void)); -void usage __P((void)); - -int interrupted; -const char - *progname = "db_checkpoint"; /* Program name. */ - -int -main(argc, argv) - int argc; - char *argv[]; -{ - extern char *optarg; - extern int optind; - DB_ENV *dbenv; - time_t now; - long argval; - u_int32_t kbytes, minutes, seconds; - int ch, once, ret, verbose; - char *home, *logfile; - - /* - * XXX - * Don't allow a fully unsigned 32-bit number, some compilers get - * upset and require it to be specified in hexadecimal and so on. - */ -#define MAX_UINT32_T 2147483647 - - kbytes = minutes = 0; - once = ret = verbose = 0; - home = logfile = NULL; - while ((ch = getopt(argc, argv, "1h:k:L:p:v")) != EOF) - switch (ch) { - case '1': - once = 1; - break; - case 'h': - home = optarg; - break; - case 'k': - get_long(optarg, 1, (long)MAX_UINT32_T, &argval); - kbytes = argval; - break; - case 'L': - logfile = optarg; - break; - case 'p': - get_long(optarg, 1, (long)MAX_UINT32_T, &argval); - minutes = argval; - break; - case 'v': - verbose = 1; - break; - case '?': - default: - usage(); - } - argc -= optind; - argv += optind; - - if (argc != 0) - usage(); - - if (once == 0 && kbytes == 0 && minutes == 0) { - warnx("at least one of -1, -k and -p must be specified"); - usage(); - } - - /* Initialize the environment. */ - siginit(); - dbenv = db_init(home); - - if (logfile != NULL && logpid(logfile, 1)) { - (void)db_appexit(dbenv); - return (1); - } - - /* - * If we have only a time delay, then we'll sleep the right amount - * to wake up when a checkpoint is necessary. If we have a "kbytes" - * field set, then we'll check every 30 seconds. - */ - seconds = kbytes != 0 ? 30 : minutes * 60; - while (!interrupted) { - if (verbose) { - (void)time(&now); - warnx("checkpoint: %s", ctime(&now)); - } - - errno = txn_checkpoint(dbenv->tx_info, kbytes, minutes); - while (errno == DB_INCOMPLETE) { - if (verbose) - warnx("checkpoint did not finish, retrying\n"); - (void)sleep(2); - errno = txn_checkpoint(dbenv->tx_info, 0, 0); - } - - if (errno != 0) { - ret = 1; - warn(NULL); - break; - } - - if (once) - break; - - (void)sleep(seconds); - } - - if (logfile != NULL && logpid(logfile, 0)) - ret = 1; - - if ((errno = db_appexit(dbenv)) != 0) { - ret = 1; - warn(NULL); - } - - if (interrupted) { - (void)signal(interrupted, SIG_DFL); - (void)raise(interrupted); - /* NOTREACHED */ - } - - return (ret); -} - -/* - * db_init -- - * Initialize the environment. - */ -DB_ENV * -db_init(home) - char *home; -{ - DB_ENV *dbenv; - - if ((dbenv = (DB_ENV *)calloc(sizeof(DB_ENV), 1)) == NULL) { - errno = ENOMEM; - err(1, NULL); - } - dbenv->db_errfile = stderr; - dbenv->db_errpfx = progname; - - if ((errno = db_appinit(home, NULL, dbenv, - DB_INIT_LOG | DB_INIT_TXN | DB_INIT_MPOOL | DB_USE_ENVIRON)) != 0) - err(1, "db_appinit"); - - if (memp_register(dbenv->mp_info, - DB_FTYPE_BTREE, __bam_pgin, __bam_pgout) || - memp_register(dbenv->mp_info, - DB_FTYPE_HASH, __ham_pgin, __ham_pgout)) { - (void)db_appexit(dbenv); - errx(1, - "db_appinit: failed to register access method functions"); - } - - return (dbenv); -} - -/* - * logpid -- - * Log that we're running. - */ -int -logpid(fname, is_open) - char *fname; - int is_open; -{ - FILE *fp; - time_t now; - - if (is_open) { - if ((fp = fopen(fname, "w")) == NULL) { - warn("%s", fname); - return (1); - } - (void)time(&now); - fprintf(fp, - "%.24s: %lu %s", progname, (u_long)getpid(), ctime(&now)); - fclose(fp); - } else - (void)remove(fname); - return (0); -} - -/* - * siginit -- - * Initialize the set of signals for which we want to clean up. - * Generally, we try not to leave the shared regions locked if - * we can. - */ -void -siginit() -{ -#ifdef SIGHUP - (void)signal(SIGHUP, onint); -#endif - (void)signal(SIGINT, onint); - (void)signal(SIGTERM, onint); -} - -/* - * onint -- - * Interrupt signal handler. - */ -void -onint(signo) - int signo; -{ - if ((interrupted = signo) == 0) - interrupted = SIGINT; -} - -void -usage() -{ - (void)fprintf(stderr, - "usage: db_checkpoint [-1v] [-h home] [-k kbytes] [-L file] [-p min]\n"); - exit(1); -} diff --git a/db2/progs/db_deadlock/db_deadlock.c b/db2/progs/db_deadlock/db_deadlock.c deleted file mode 100644 index bc5039e..0000000 --- a/db2/progs/db_deadlock/db_deadlock.c +++ /dev/null @@ -1,245 +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_deadlock.c 10.23 (Sleepycat) 10/4/98"; -#endif - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <limits.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <time.h> -#include <unistd.h> -#endif - -#include "db_int.h" -#include "clib_ext.h" -#include "common_ext.h" - -#define BAD_KILLID 0xffffffff - -DB_ENV *db_init __P((char *, int)); -int logpid __P((char *, int)); -int main __P((int, char *[])); -void onint __P((int)); -void siginit __P((void)); -void usage __P((void)); - -int interrupted; -const char - *progname = "db_deadlock"; /* Program name. */ - -int -main(argc, argv) - int argc; - char *argv[]; -{ - extern char *optarg; - extern int optind; - DB_ENV *dbenv; - u_int32_t atype; - time_t now; - long usecs; - u_int32_t flags; - int ch, ret, verbose; - char *home, *logfile; - - atype = DB_LOCK_DEFAULT; - home = logfile = NULL; - usecs = 0; - flags = 0; - ret = verbose = 0; - while ((ch = getopt(argc, argv, "a:h:L:t:vw")) != EOF) - switch (ch) { - case 'a': - switch (optarg[0]) { - case 'o': - atype = DB_LOCK_OLDEST; - break; - case 'y': - atype = DB_LOCK_YOUNGEST; - break; - default: - usage(); - /* NOTREACHED */ - } - if (optarg[1] != '\0') - usage(); - break; - case 'h': - home = optarg; - break; - case 'L': - logfile = optarg; - break; - case 't': - get_long(optarg, 1, LONG_MAX, &usecs); - usecs *= 1000000; - break; - case 'v': - verbose = 1; - break; - case 'w': - LF_SET(DB_LOCK_CONFLICT); - break; - case '?': - default: - usage(); - } - argc -= optind; - argv += optind; - - if (argc != 0) - usage(); - - if (usecs == 0 && !LF_ISSET(DB_LOCK_CONFLICT)) { - warnx("at least one of -t and -w must be specified"); - usage(); - } - - /* - * We detect every 100ms (100000 us) when we're running in - * DB_LOCK_CONFLICT mode. - */ - if (usecs == 0) - usecs = 100000; - - /* Initialize the deadlock detector by opening the lock manager. */ - siginit(); - dbenv = db_init(home, verbose); - - if (logfile != NULL && logpid(logfile, 1)) { - (void)db_appexit(dbenv); - return (1); - } - - while (!interrupted) { - if (dbenv->db_verbose != 0) { - time(&now); - warnx("Running at %.24s", ctime(&now)); - } - - if ((errno = lock_detect(dbenv->lk_info, flags, atype)) != 0) { - ret = 1; - warnx(NULL); - break; - } - - /* Make a pass every "usecs" usecs. */ - (void)usleep(usecs); - } - - if (logfile != NULL && logpid(logfile, 0)) - ret = 1; - - if ((errno = db_appexit(dbenv)) != 0) { - ret = 1; - warn(NULL); - } - - if (interrupted) { - (void)signal(interrupted, SIG_DFL); - (void)raise(interrupted); - /* NOTREACHED */ - } - - return (ret); -} - -DB_ENV * -db_init(home, verbose) - char *home; - int verbose; -{ - DB_ENV *dbenv; - - if ((dbenv = (DB_ENV *)calloc(sizeof(DB_ENV), 1)) == NULL) { - errno = ENOMEM; - err(1, NULL); - } - dbenv->db_errfile = stderr; - dbenv->db_errpfx = progname; - dbenv->db_verbose = verbose; - - if ((errno = db_appinit(home, - NULL, dbenv, DB_INIT_LOCK | DB_USE_ENVIRON)) != 0) - err(1, "db_appinit"); - - return (dbenv); -} - -/* - * logpid -- - * Log that we're running. - */ -int -logpid(fname, is_open) - char *fname; - int is_open; -{ - FILE *fp; - time_t now; - - if (is_open) { - if ((fp = fopen(fname, "w")) == NULL) { - warn("%s", fname); - return (1); - } - (void)time(&now); - fprintf(fp, - "%.24s: %lu %s", progname, (u_long)getpid(), ctime(&now)); - fclose(fp); - } else - (void)remove(fname); - return (0); -} - -/* - * siginit -- - * Initialize the set of signals for which we want to clean up. - * Generally, we try not to leave the shared regions locked if - * we can. - */ -void -siginit() -{ -#ifdef SIGHUP - (void)signal(SIGHUP, onint); -#endif - (void)signal(SIGINT, onint); - (void)signal(SIGTERM, onint); -} - -/* - * onint -- - * Interrupt signal handler. - */ -void -onint(signo) - int signo; -{ - if ((interrupted = signo) == 0) - interrupted = SIGINT; -} - -void -usage() -{ - (void)fprintf(stderr, - "usage: db_deadlock [-vw] [-a m | o | y] [-h home] [-L file] [-t sec]\n"); - exit(1); -} diff --git a/db2/progs/db_dump/db_dump.c b/db2/progs/db_dump/db_dump.c deleted file mode 100644 index 0f34ddc..0000000 --- a/db2/progs/db_dump/db_dump.c +++ /dev/null @@ -1,260 +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_dump.c 10.24 (Sleepycat) 11/22/98"; -#endif - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <ctype.h> -#include <errno.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#endif - -#undef stat - -#include "db_int.h" -#include "db_page.h" -#include "btree.h" -#include "hash.h" -#include "clib_ext.h" - -void configure __P((char *)); -DB_ENV *db_init __P((char *)); -int main __P((int, char *[])); -void pheader __P((DB *, int)); -void usage __P((void)); - -const char - *progname = "db_dump"; /* Program name. */ - -int -main(argc, argv) - int argc; - char *argv[]; -{ - extern char *optarg; - extern int optind; - DB *dbp; - DBC *dbcp; - DBT key, data; - DB_ENV *dbenv; - int ch, checkprint, dflag; - char *home; - - home = NULL; - checkprint = dflag = 0; - while ((ch = getopt(argc, argv, "df:h:Np")) != EOF) - switch (ch) { - case 'd': - dflag = 1; - break; - case 'f': - if (freopen(optarg, "w", stdout) == NULL) - err(1, "%s", optarg); - break; - case 'h': - home = optarg; - break; - case 'N': - (void)db_value_set(0, DB_MUTEXLOCKS); - break; - case 'p': - checkprint = 1; - break; - case '?': - default: - usage(); - } - argc -= optind; - argv += optind; - - if (argc != 1) - usage(); - - if (dflag && checkprint) - errx(1, "the -d and -p options may not both be specified"); - - /* Initialize the environment. */ - dbenv = db_init(home); - - /* Open the DB file. */ - if ((errno = - db_open(argv[0], DB_UNKNOWN, DB_RDONLY, 0, dbenv, NULL, &dbp)) != 0) - err(1, "%s", argv[0]); - - /* DB dump. */ - if (dflag) { - (void)__db_dump(dbp, NULL, 1); - if ((errno = dbp->close(dbp, 0)) != 0) - err(1, "close"); - exit (0); - } - - /* Get a cursor and step through the database. */ - if ((errno = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) { - (void)dbp->close(dbp, 0); - err(1, "cursor"); - } - - /* Print out the header. */ - pheader(dbp, checkprint); - - /* Print out the key/data pairs. */ - memset(&key, 0, sizeof(key)); - memset(&data, 0, sizeof(data)); - while ((errno = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0) { - if (dbp->type != DB_RECNO && - (errno = __db_prdbt(&key, checkprint, stdout)) != 0) - break; - if ((errno = __db_prdbt(&data, checkprint, stdout)) != 0) - break; - } - - if (errno != DB_NOTFOUND) - err(1, "cursor get"); - - if ((errno = dbp->close(dbp, 0)) != 0) - err(1, "close"); - return (0); -} - -/* - * db_init -- - * Initialize the environment. - */ -DB_ENV * -db_init(home) - char *home; -{ - DB_ENV *dbenv; - - if ((dbenv = (DB_ENV *)calloc(1, sizeof(DB_ENV))) == NULL) { - errno = ENOMEM; - err(1, NULL); - } - - /* - * Try and use the shared mpool region so that we get pages that - * haven't been flushed to disk (mostly useful for debugging). - * If that fails, try again, without the DB_INIT_MPOOL flag. - * - * If it works, set the error output options so that future errors - * are correctly reported. - */ - if ((errno = db_appinit(home, - NULL, dbenv, DB_USE_ENVIRON | DB_INIT_MPOOL)) == 0) { - dbenv->db_errfile = stderr; - dbenv->db_errpfx = progname; - return (dbenv); - } - - /* Set the error output options -- this time we want a message. */ - memset(dbenv, 0, sizeof(*dbenv)); - dbenv->db_errfile = stderr; - dbenv->db_errpfx = progname; - - /* Try again, and it's fatal if we fail. */ - if ((errno = db_appinit(home, NULL, dbenv, DB_USE_ENVIRON)) != 0) - err(1, "db_appinit"); - - return (dbenv); -} - -/* - * pheader -- - * Write out the header information. - */ -void -pheader(dbp, pflag) - DB *dbp; - int pflag; -{ - DBC *dbc; - DB_BTREE_STAT *btsp; - HASH_CURSOR *hcp; - int ret; - - printf("format=%s\n", pflag ? "print" : "bytevalue"); - switch (dbp->type) { - case DB_BTREE: - printf("type=btree\n"); - if ((errno = dbp->stat(dbp, &btsp, NULL, 0)) != 0) - err(1, "dbp->stat"); - if (F_ISSET(dbp, DB_BT_RECNUM)) - printf("recnum=1\n"); - if (btsp->bt_maxkey != 0) - printf("bt_maxkey=%lu\n", (u_long)btsp->bt_maxkey); - if (btsp->bt_minkey != 0) - printf("bt_minkey=%lu\n", (u_long)btsp->bt_minkey); - break; - case DB_HASH: - printf("type=hash\n"); - if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0) - break; - hcp = (HASH_CURSOR *)dbc->internal; - GET_META(dbp, hcp, ret); - if (ret == 0) { - if (hcp->hdr->ffactor != 0) - printf("h_ffactor=%lu\n", - (u_long)hcp->hdr->ffactor); - if (hcp->hdr->nelem != 0) - printf("h_nelem=%lu\n", - (u_long)hcp->hdr->nelem); - RELEASE_META(dbp, hcp); - } - (void)dbc->c_close(dbc); - break; - case DB_RECNO: - printf("type=recno\n"); - if ((errno = dbp->stat(dbp, &btsp, NULL, 0)) != 0) - err(1, "dbp->stat"); - if (F_ISSET(dbp, DB_RE_RENUMBER)) - printf("renumber=1\n"); - if (F_ISSET(dbp, DB_RE_FIXEDLEN)) - printf("re_len=%lu\n", (u_long)btsp->bt_re_len); - if (F_ISSET(dbp, DB_RE_PAD)) - printf("re_pad=%#x\n", btsp->bt_re_pad); - break; - case DB_UNKNOWN: - abort(); - /* NOTREACHED */ - } - - if (F_ISSET(dbp, DB_AM_DUP)) - printf("duplicates=1\n"); - - if (dbp->dbenv->db_lorder != 0) - printf("db_lorder=%lu\n", (u_long)dbp->dbenv->db_lorder); - - if (!F_ISSET(dbp, DB_AM_PGDEF)) - printf("db_pagesize=%lu\n", (u_long)dbp->pgsize); - - printf("HEADER=END\n"); -} - -/* - * usage -- - * Display the usage message. - */ -void -usage() -{ - (void)fprintf(stderr, - "usage: db_dump [-dNp] [-f file] [-h home] db_file\n"); - exit(1); -} diff --git a/db2/progs/db_dump185/db_dump185.c b/db2/progs/db_dump185/db_dump185.c deleted file mode 100644 index 1745110..0000000 --- a/db2/progs/db_dump185/db_dump185.c +++ /dev/null @@ -1,353 +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_dump185.c 10.10 (Sleepycat) 4/10/98"; -#endif - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <ctype.h> -#include <errno.h> -#include <fcntl.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#endif - -#include "db_185.h" -#include "clib_ext.h" - -/* Hash Table Information */ -typedef struct hashhdr185 { /* Disk resident portion */ - int magic; /* Magic NO for hash tables */ - int version; /* Version ID */ - u_int32_t lorder; /* Byte Order */ - int bsize; /* Bucket/Page Size */ - int bshift; /* Bucket shift */ - int dsize; /* Directory Size */ - int ssize; /* Segment Size */ - int sshift; /* Segment shift */ - int ovfl_point; /* Where overflow pages are being - * allocated */ - int last_freed; /* Last overflow page freed */ - int max_bucket; /* ID of Maximum bucket in use */ - int high_mask; /* Mask to modulo into entire table */ - int low_mask; /* Mask to modulo into lower half of - * table */ - int ffactor; /* Fill factor */ - int nkeys; /* Number of keys in hash table */ -} HASHHDR185; -typedef struct htab185 { /* Memory resident data structure */ - HASHHDR185 hdr; /* Header */ -} HTAB185; - -/* Hash Table Information */ -typedef struct hashhdr186 { /* Disk resident portion */ - int32_t magic; /* Magic NO for hash tables */ - int32_t version; /* Version ID */ - int32_t lorder; /* Byte Order */ - int32_t bsize; /* Bucket/Page Size */ - int32_t bshift; /* Bucket shift */ - int32_t ovfl_point; /* Where overflow pages are being allocated */ - int32_t last_freed; /* Last overflow page freed */ - int32_t max_bucket; /* ID of Maximum bucket in use */ - int32_t high_mask; /* Mask to modulo into entire table */ - int32_t low_mask; /* Mask to modulo into lower half of table */ - int32_t ffactor; /* Fill factor */ - int32_t nkeys; /* Number of keys in hash table */ - int32_t hdrpages; /* Size of table header */ - int32_t h_charkey; /* value of hash(CHARKEY) */ -#define NCACHED 32 /* number of bit maps and spare points */ - int32_t spares[NCACHED];/* spare pages for overflow */ - u_int16_t bitmaps[NCACHED]; /* address of overflow page bitmaps */ -} HASHHDR186; -typedef struct htab186 { /* Memory resident data structure */ - HASHHDR186 hdr; /* Header */ -} HTAB186; - -typedef struct _epgno { - u_int32_t pgno; /* the page number */ - u_int16_t index; /* the index on the page */ -} EPGNO; - -typedef struct _epg { - void *page; /* the (pinned) page */ - u_int16_t index; /* the index on the page */ -} EPG; - -typedef struct _cursor { - EPGNO pg; /* B: Saved tree reference. */ - DBT key; /* B: Saved key, or key.data == NULL. */ - u_int32_t rcursor; /* R: recno cursor (1-based) */ - -#define CURS_ACQUIRE 0x01 /* B: Cursor needs to be reacquired. */ -#define CURS_AFTER 0x02 /* B: Unreturned cursor after key. */ -#define CURS_BEFORE 0x04 /* B: Unreturned cursor before key. */ -#define CURS_INIT 0x08 /* RB: Cursor initialized. */ - u_int8_t flags; -} CURSOR; - -/* The in-memory btree/recno data structure. */ -typedef struct _btree { - void *bt_mp; /* memory pool cookie */ - - void *bt_dbp; /* pointer to enclosing DB */ - - EPG bt_cur; /* current (pinned) page */ - void *bt_pinned; /* page pinned across calls */ - - CURSOR bt_cursor; /* cursor */ - - EPGNO bt_stack[50]; /* stack of parent pages */ - EPGNO *bt_sp; /* current stack pointer */ - - DBT bt_rkey; /* returned key */ - DBT bt_rdata; /* returned data */ - - int bt_fd; /* tree file descriptor */ - - u_int32_t bt_free; /* next free page */ - u_int32_t bt_psize; /* page size */ - u_int16_t bt_ovflsize; /* cut-off for key/data overflow */ - int bt_lorder; /* byte order */ - /* sorted order */ - enum { NOT, BACK, FORWARD } bt_order; - EPGNO bt_last; /* last insert */ - - /* B: key comparison function */ - int (*bt_cmp) __P((const DBT *, const DBT *)); - /* B: prefix comparison function */ - size_t (*bt_pfx) __P((const DBT *, const DBT *)); - /* R: recno input function */ - int (*bt_irec) __P((struct _btree *, u_int32_t)); - - FILE *bt_rfp; /* R: record FILE pointer */ - int bt_rfd; /* R: record file descriptor */ - - void *bt_cmap; /* R: current point in mapped space */ - void *bt_smap; /* R: start of mapped space */ - void *bt_emap; /* R: end of mapped space */ - size_t bt_msize; /* R: size of mapped region. */ - - u_int32_t bt_nrecs; /* R: number of records */ - size_t bt_reclen; /* R: fixed record length */ - u_char bt_bval; /* R: delimiting byte/pad character */ - -/* - * NB: - * B_NODUPS and R_RECNO are stored on disk, and may not be changed. - */ -#define B_INMEM 0x00001 /* in-memory tree */ -#define B_METADIRTY 0x00002 /* need to write metadata */ -#define B_MODIFIED 0x00004 /* tree modified */ -#define B_NEEDSWAP 0x00008 /* if byte order requires swapping */ -#define B_RDONLY 0x00010 /* read-only tree */ - -#define B_NODUPS 0x00020 /* no duplicate keys permitted */ -#define R_RECNO 0x00080 /* record oriented tree */ - -#define R_CLOSEFP 0x00040 /* opened a file pointer */ -#define R_EOF 0x00100 /* end of input file reached. */ -#define R_FIXLEN 0x00200 /* fixed length records */ -#define R_MEMMAPPED 0x00400 /* memory mapped file. */ -#define R_INMEM 0x00800 /* in-memory file */ -#define R_MODIFIED 0x01000 /* modified file */ -#define R_RDONLY 0x02000 /* read-only file */ - -#define B_DB_LOCK 0x04000 /* DB_LOCK specified. */ -#define B_DB_SHMEM 0x08000 /* DB_SHMEM specified. */ -#define B_DB_TXN 0x10000 /* DB_TXN specified. */ - u_int32_t flags; -} BTREE; - -void db_btree __P((DB *, int)); -void db_hash __P((DB *, int)); -void dbt_dump __P((DBT *)); -void dbt_print __P((DBT *)); -int main __P((int, char *[])); -void usage __P((void)); - -const char - *progname = "db_dump185"; /* Program name. */ - -int -main(argc, argv) - int argc; - char *argv[]; -{ - extern char *optarg; - extern int optind; - DB *dbp; - DBT key, data; - int ch, pflag, rval; - - pflag = 0; - while ((ch = getopt(argc, argv, "f:p")) != EOF) - switch (ch) { - case 'f': - if (freopen(optarg, "w", stdout) == NULL) - err(1, "%s", optarg); - break; - case 'p': - pflag = 1; - break; - case '?': - default: - usage(); - } - argc -= optind; - argv += optind; - - if (argc != 1) - usage(); - - if ((dbp = dbopen(argv[0], O_RDONLY, 0, DB_BTREE, NULL)) == NULL) { - if ((dbp = dbopen(argv[0], O_RDONLY, 0, DB_HASH, NULL)) == NULL) - err(1, "%s", argv[0]); - db_hash(dbp, pflag); - } else - db_btree(dbp, pflag); - - /* - * !!! - * DB 1.85 DBTs are a subset of DB 2.0 DBTs, so we just use the - * new dump/print routines. - */ - if (pflag) - while (!(rval = dbp->seq(dbp, &key, &data, R_NEXT))) { - dbt_print(&key); - dbt_print(&data); - } - else - while (!(rval = dbp->seq(dbp, &key, &data, R_NEXT))) { - dbt_dump(&key); - dbt_dump(&data); - } - - if (rval == -1) - err(1, "seq"); - return (0); -} - -/* - * db_hash -- - * Dump out hash header information. - */ -void -db_hash(dbp, pflag) - DB *dbp; - int pflag; -{ - HTAB185 *hash185p; - HTAB186 *hash186p; - - printf("format=%s\n", pflag ? "print" : "bytevalue"); - printf("type=hash\n"); - - /* DB 1.85 was version 2, DB 1.86 was version 3. */ - hash185p = dbp->internal; - if (hash185p->hdr.version > 2) { - hash186p = dbp->internal; - printf("h_ffactor=%lu\n", (u_long)hash186p->hdr.ffactor); - if (hash186p->hdr.lorder != 0) - printf("db_lorder=%lu\n", (u_long)hash186p->hdr.lorder); - printf("db_pagesize=%lu\n", (u_long)hash186p->hdr.bsize); - } else { - printf("h_ffactor=%lu\n", (u_long)hash185p->hdr.ffactor); - if (hash185p->hdr.lorder != 0) - printf("db_lorder=%lu\n", (u_long)hash185p->hdr.lorder); - printf("db_pagesize=%lu\n", (u_long)hash185p->hdr.bsize); - } - printf("HEADER=END\n"); -} - -/* - * db_btree -- - * Dump out btree header information. - */ -void -db_btree(dbp, pflag) - DB *dbp; - int pflag; -{ - BTREE *btp; - - btp = dbp->internal; - - printf("format=%s\n", pflag ? "print" : "bytevalue"); - printf("type=btree\n"); -#ifdef NOT_AVAILABLE_IN_185 - printf("bt_minkey=%lu\n", (u_long)XXX); - printf("bt_maxkey=%lu\n", (u_long)XXX); -#endif - if (btp->bt_lorder != 0) - printf("db_lorder=%lu\n", (u_long)btp->bt_lorder); - printf("db_pagesize=%lu\n", (u_long)btp->bt_psize); - if (!(btp->flags & B_NODUPS)) - printf("duplicates=1\n"); - printf("HEADER=END\n"); -} - -static char hex[] = "0123456789abcdef"; - -/* - * dbt_dump -- - * Write out a key or data item using byte values. - */ -void -dbt_dump(dbtp) - DBT *dbtp; -{ - size_t len; - u_int8_t *p; - - for (len = dbtp->size, p = dbtp->data; len--; ++p) - (void)printf("%c%c", - hex[(*p & 0xf0) >> 4], hex[*p & 0x0f]); - printf("\n"); -} - -/* - * dbt_print -- - * Write out a key or data item using printable characters. - */ -void -dbt_print(dbtp) - DBT *dbtp; -{ - size_t len; - u_int8_t *p; - - for (len = dbtp->size, p = dbtp->data; len--; ++p) - if (isprint(*p)) { - if (*p == '\\') - (void)printf("\\"); - (void)printf("%c", *p); - } else - (void)printf("\\%c%c", - hex[(*p & 0xf0) >> 4], hex[*p & 0x0f]); - printf("\n"); -} - -/* - * usage -- - * Display the usage message. - */ -void -usage() -{ - (void)fprintf(stderr, "usage: db_dump [-p] [-f file] db_file\n"); - exit(1); -} diff --git a/db2/progs/db_load/db_load.c b/db2/progs/db_load/db_load.c deleted file mode 100644 index a242602..0000000 --- a/db2/progs/db_load/db_load.c +++ /dev/null @@ -1,571 +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_load.c 10.23 (Sleepycat) 10/4/98"; -#endif - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <limits.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#endif - -#include "db_int.h" -#include "db_page.h" -#include "db_am.h" -#include "clib_ext.h" - -void badnum __P((void)); -void configure __P((DB_INFO *, char **)); -DB_ENV *db_init __P((char *)); -int dbt_rdump __P((DBT *)); -int dbt_rprint __P((DBT *)); -int digitize __P((int)); -int main __P((int, char *[])); -void onint __P((int)); -void rheader __P((DBTYPE *, int *, DB_INFO *)); -void siginit __P((void)); -void usage __P((void)); - -int interrupted; -const char - *progname = "db_load"; /* Program name. */ - -int -main(argc, argv) - int argc; - char *argv[]; -{ - extern char *optarg; - extern int optind; - DB *dbp; - DBT key, data; - DBTYPE argtype, dbtype; - DB_ENV *dbenv; - DB_INFO dbinfo; - db_recno_t recno; - u_int32_t db_nooverwrite; - int ch, checkprint, existed, no_header, ret; - char **clist, **clp, *home; - - /* Allocate enough room for configuration arguments. */ - if ((clp = clist = (char **)calloc(argc + 1, sizeof(char *))) == NULL) - err(1, NULL); - - dbp = NULL; - home = NULL; - db_nooverwrite = 0; - checkprint = existed = no_header = ret = 0; - argtype = dbtype = DB_UNKNOWN; - while ((ch = getopt(argc, argv, "c:f:h:nTt:")) != EOF) - switch (ch) { - case 'c': - *clp++ = optarg; - break; - case 'f': - if (freopen(optarg, "r", stdin) == NULL) - err(1, "%s", optarg); - break; - case 'h': - home = optarg; - break; - case 'n': - db_nooverwrite = DB_NOOVERWRITE; - break; - case 'T': - no_header = checkprint = 1; - break; - case 't': - if (strcmp(optarg, "btree") == 0) { - argtype = DB_BTREE; - break; - } - if (strcmp(optarg, "hash") == 0) { - argtype = DB_HASH; - break; - } - if (strcmp(optarg, "recno") == 0) { - argtype = DB_RECNO; - break; - } - usage(); - /* NOTREACHED */ - case '?': - default: - usage(); - } - argc -= optind; - argv += optind; - - if (argc != 1) - usage(); - - /* - * Read the header. If there isn't any header, we're expecting flat - * text, set the checkprint flag appropriately. - */ - memset(&dbinfo, 0, sizeof(DB_INFO)); - if (no_header) - dbtype = argtype; - else { - rheader(&dbtype, &checkprint, &dbinfo); - if (argtype != DB_UNKNOWN) { - /* Conversion to/from recno is prohibited. */ - if ((dbtype == DB_RECNO && argtype != DB_RECNO) || - (argtype == DB_RECNO && dbtype != DB_RECNO)) - errx(1, - "databases of type recno may not be converted"); - dbtype = argtype; - } - } - - if (dbtype == DB_UNKNOWN) - errx(1, "no database type specified"); - - /* Apply command-line configuration changes. */ - configure(&dbinfo, clist); - - /* Initialize the key/data pair. */ - memset(&key, 0, sizeof(DBT)); - if (dbtype == DB_RECNO) { - key.data = &recno; - key.size = sizeof(recno); - } else - if ((key.data = (void *)malloc(key.ulen = 1024)) == NULL) { - errno = ENOMEM; - err(1, NULL); - } - memset(&data, 0, sizeof(DBT)); - if ((data.data = (void *)malloc(data.ulen = 1024)) == NULL) { - errno = ENOMEM; - err(1, NULL); - } - - /* Initialize the environment if the user specified one. */ - siginit(); - dbenv = home == NULL ? NULL : db_init(home); - - /* Open the DB file. */ - if ((errno = db_open(argv[0], dbtype, DB_CREATE, - __db_omode("rwrwrw"), dbenv, &dbinfo, &dbp)) != 0) { - warn("%s", argv[0]); - goto err; - } - - /* Get each key/data pair and add them to the database. */ - for (recno = 1; !interrupted; ++recno) { - if (dbtype == DB_RECNO) { - if (checkprint) { - if (dbt_rprint(&data)) - break; - } else { - if (dbt_rdump(&data)) - break; - } - } else { - if (checkprint) { - if (dbt_rprint(&key)) - break; - if (dbt_rprint(&data)) - goto fmt; - } else { - if (dbt_rdump(&key)) - break; - if (dbt_rdump(&data)) { -fmt: warnx("odd number of key/data pairs"); - goto err; - } - } - } - switch (errno = - dbp->put(dbp, NULL, &key, &data, db_nooverwrite)) { - case 0: - break; - case DB_KEYEXIST: - existed = 1; - warnx("%s: line %d: key already exists, not loaded:", - argv[0], - dbtype == DB_RECNO ? recno : recno * 2 - 1); - - (void)__db_prdbt(&key, checkprint, stderr); - break; - default: - warn(NULL); - goto err; - } - } - - if (0) { -err: ret = 1; - } - if (dbp != NULL && (errno = dbp->close(dbp, 0)) != 0) { - ret = 1; - warn(NULL); - } - - if (dbenv != NULL && (errno = db_appexit(dbenv)) != 0) { - ret = 1; - warn(NULL); - } - - if (interrupted) { - (void)signal(interrupted, SIG_DFL); - (void)raise(interrupted); - /* NOTREACHED */ - } - - /* Return 0 on success, 1 if keys existed already, and 2 on failure. */ - return (ret == 0 ? (existed == 0 ? 0 : 1) : 2); -} - -/* - * db_init -- - * Initialize the environment. - */ -DB_ENV * -db_init(home) - char *home; -{ - DB_ENV *dbenv; - - if ((dbenv = (DB_ENV *)calloc(sizeof(DB_ENV), 1)) == NULL) { - errno = ENOMEM; - err(1, NULL); - } - - /* - * The database may be live, try and use the shared regions. - * - * If it works, we're done. Set the error output options so that - * future errors are correctly reported. - */ - if ((errno = db_appinit(home, NULL, dbenv, DB_INIT_LOCK | - DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN | DB_USE_ENVIRON)) == 0) { - dbenv->db_errfile = stderr; - dbenv->db_errpfx = progname; - return (dbenv); - } - - /* - * If the db_appinit fails, assume the database isn't live, and don't - * bother with an environment. - */ - free(dbenv); - return (NULL); -} - -#define FLAG(name, value, keyword, flag) \ - if (strcmp(name, keyword) == 0) { \ - switch (*value) { \ - case '1': \ - dbinfop->flags |= (flag); \ - break; \ - case '0': \ - dbinfop->flags &= ~(flag); \ - break; \ - default: \ - badnum(); \ - /* NOTREACHED */ \ - } \ - continue; \ - } -#define NUMBER(name, value, keyword, field, flag) \ - if (strcmp(name, keyword) == 0) { \ - get_long(value, 1, LONG_MAX, &val); \ - dbinfop->field = val; \ - if (flag != 0) \ - dbinfop->flags |= (flag); \ - continue; \ - } -#define STRING(name, value, keyword, field, flag) \ - if (strcmp(name, keyword) == 0) { \ - dbinfop->field = value[0]; \ - if (flag != 0) \ - dbinfop->flags |= (flag); \ - continue; \ - } - -/* - * configure -- - * Handle command-line configuration options. - */ -void -configure(dbinfop, clp) - DB_INFO *dbinfop; - char **clp; -{ - long val; - char *name, *value; - - for (; (name = *clp) != NULL; ++clp) { - if ((value = strchr(name, '=')) == NULL) - errx(1, - "command-line configuration uses name=value format"); - *value++ = '\0'; - - NUMBER(name, value, "bt_maxkey", bt_maxkey, 0); - NUMBER(name, value, "bt_minkey", bt_minkey, 0); - NUMBER(name, value, "db_lorder", db_lorder, 0); - NUMBER(name, value, "db_pagesize", db_pagesize, 0); - FLAG(name, value, "duplicates", DB_DUP); - NUMBER(name, value, "h_ffactor", h_ffactor, 0); - NUMBER(name, value, "h_nelem", h_nelem, 0); - NUMBER(name, value, "re_len", re_len, DB_FIXEDLEN); - STRING(name, value, "re_pad", re_pad, DB_PAD); - FLAG(name, value, "recnum", DB_RECNUM); - FLAG(name, value, "renumber", DB_RENUMBER); - - errx(1, "unknown command-line configuration keyword"); - } -} - -/* - * rheader -- - * Read the header message. - */ -void -rheader(dbtypep, checkprintp, dbinfop) - DBTYPE *dbtypep; - int *checkprintp; - DB_INFO *dbinfop; -{ - long lineno, val; - char name[256], value[256]; - - *dbtypep = DB_UNKNOWN; - *checkprintp = 0; - - for (lineno = 1;; ++lineno) { - /* If we don't see the expected information, it's an error. */ - if (fscanf(stdin, "%[^=]=%s\n", name, value) != 2) - errx(1, "line %lu: unexpected format", lineno); - - /* Check for the end of the header lines. */ - if (strcmp(name, "HEADER") == 0) - break; - - if (strcmp(name, "format") == 0) { - if (strcmp(value, "bytevalue") == 0) { - *checkprintp = 0; - continue; - } - if (strcmp(value, "print") == 0) { - *checkprintp = 1; - continue; - } - errx(1, "line %d: unknown format", lineno); - } - if (strcmp(name, "type") == 0) { - if (strcmp(value, "btree") == 0) { - *dbtypep = DB_BTREE; - continue; - } - if (strcmp(value, "hash") == 0) { - *dbtypep = DB_HASH; - continue; - } - if (strcmp(value, "recno") == 0) { - *dbtypep = DB_RECNO; - continue; - } - errx(1, "line %d: unknown type", lineno); - } - NUMBER(name, value, "bt_maxkey", bt_maxkey, 0); - NUMBER(name, value, "bt_minkey", bt_minkey, 0); - NUMBER(name, value, "db_lorder", db_lorder, 0); - NUMBER(name, value, "db_pagesize", db_pagesize, 0); - FLAG(name, value, "duplicates", DB_DUP); - NUMBER(name, value, "h_ffactor", h_ffactor, 0); - NUMBER(name, value, "h_nelem", h_nelem, 0); - NUMBER(name, value, "re_len", re_len, DB_FIXEDLEN); - STRING(name, value, "re_pad", re_pad, DB_PAD); - FLAG(name, value, "recnum", DB_RECNUM); - FLAG(name, value, "renumber", DB_RENUMBER); - - errx(1, "unknown input-file header configuration keyword"); - } -} - -/* - * dbt_rprint -- - * Read a printable line into a DBT structure. - */ -int -dbt_rprint(dbtp) - DBT *dbtp; -{ - u_int32_t len; - u_int8_t *p; - int c1, c2, escape; - - escape = 0; - for (p = dbtp->data, len = 0; (c1 = getchar()) != '\n';) { - if (c1 == EOF) { - if (len == 0) - return (1); - err(1, "unexpected end of key/data pair"); - } - if (escape) { - if (c1 != '\\') { - if ((c2 = getchar()) == EOF) - err(1, - "unexpected end of key/data pair"); - c1 = digitize(c1) << 4 | digitize(c2); - } - escape = 0; - } else - if (c1 == '\\') { - escape = 1; - continue; - } - if (len >= dbtp->ulen - 10) { - dbtp->ulen *= 2; - if ((dbtp->data = - (void *)realloc(dbtp->data, dbtp->ulen)) == NULL) { - errno = ENOMEM; - err(1, NULL); - } - p = (u_int8_t *)dbtp->data + len; - } - ++len; - *p++ = c1; - } - dbtp->size = len; - return (0); -} - -/* - * dbt_rdump -- - * Read a byte dump line into a DBT structure. - */ -int -dbt_rdump(dbtp) - DBT *dbtp; -{ - u_int32_t len; - u_int8_t *p; - int c1, c2; - - for (p = dbtp->data, len = 0; (c1 = getchar()) != '\n';) { - if (c1 == EOF) { - if (len == 0) - return (1); - err(1, "unexpected end of key/data pair"); - } - if ((c2 = getchar()) == EOF) - err(1, "unexpected end of key/data pair"); - if (len >= dbtp->ulen - 10) { - dbtp->ulen *= 2; - if ((dbtp->data = - (void *)realloc(dbtp->data, dbtp->ulen)) == NULL) { - errno = ENOMEM; - err(1, NULL); - } - p = (u_int8_t *)dbtp->data + len; - } - ++len; - *p++ = digitize(c1) << 4 | digitize(c2); - } - dbtp->size = len; - return (0); -} - -/* - * digitize -- - * Convert a character to an integer. - */ -int -digitize(c) - int c; -{ - switch (c) { /* Don't depend on ASCII ordering. */ - case '0': return (0); - case '1': return (1); - case '2': return (2); - case '3': return (3); - case '4': return (4); - case '5': return (5); - case '6': return (6); - case '7': return (7); - case '8': return (8); - case '9': return (9); - case 'a': return (10); - case 'b': return (11); - case 'c': return (12); - case 'd': return (13); - case 'e': return (14); - case 'f': return (15); - } - - err(1, "unexpected hexadecimal value"); - /* NOTREACHED */ - - return (0); -} - -/* - * badnum -- - * Display the bad number message. - */ -void -badnum() -{ - err(1, "boolean name=value pairs require a value of 0 or 1"); -} - -/* - * siginit -- - * Initialize the set of signals for which we want to clean up. - * Generally, we try not to leave the shared regions locked if - * we can. - */ -void -siginit() -{ -#ifdef SIGHUP - (void)signal(SIGHUP, onint); -#endif - (void)signal(SIGINT, onint); - (void)signal(SIGTERM, onint); -} - -/* - * onint -- - * Interrupt signal handler. - */ -void -onint(signo) - int signo; -{ - if ((interrupted = signo) == 0) - interrupted = SIGINT; -} - -/* - * usage -- - * Display the usage message. - */ -void -usage() -{ - (void)fprintf(stderr, "%s\n\t%s\n", - "usage: db_load [-nT]", - "[-c name=value] [-f file] [-h home] [-t btree | hash | recno] db_file"); - exit(1); -} diff --git a/db2/progs/db_printlog/README b/db2/progs/db_printlog/README deleted file mode 100644 index 05051f3..0000000 --- a/db2/progs/db_printlog/README +++ /dev/null @@ -1,22 +0,0 @@ -# @(#)README 10.3 (Sleepycat) 11/1/98 - -Berkeley DB log dump utility. This utility dumps out a DB log in human -readable form, a record at a time, to assist in recovery and transaction -abort debugging. - -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -commit.awk Output transaction ID of committed transactions. - -count.awk Print out the number of log records for transactions - that we encountered. - -pgno.awk Take a comma-separated list of page numbers and spit - out all the log records that affect those page numbers. - -range.awk Print out a range of the log. - -status.awk Read through db_printlog output and list the transactions - encountered, and whether they commited or aborted. - -txn.awk Print out all the records for a comma-separated list of - transaction IDs. diff --git a/db2/progs/db_printlog/commit.awk b/db2/progs/db_printlog/commit.awk deleted file mode 100644 index 711064b..0000000 --- a/db2/progs/db_printlog/commit.awk +++ /dev/null @@ -1,7 +0,0 @@ -# @(#)commit.awk 10.1 (Sleepycat) 11/1/98 -# -# Output tid of committed transactions. - -/txn_regop/ { - print $5 -} diff --git a/db2/progs/db_printlog/count.awk b/db2/progs/db_printlog/count.awk deleted file mode 100644 index a0b214a..0000000 --- a/db2/progs/db_printlog/count.awk +++ /dev/null @@ -1,9 +0,0 @@ -# @(#)count.awk 10.1 (Sleepycat) 11/1/98 -# -# Print out the number of log records for transactions that we -# encountered. - -/^\[/{ - if ($5 != 0) - print $5 -} diff --git a/db2/progs/db_printlog/db_printlog.c b/db2/progs/db_printlog/db_printlog.c deleted file mode 100644 index 5a0c2eb..0000000 --- a/db2/progs/db_printlog/db_printlog.c +++ /dev/null @@ -1,192 +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_printlog.c 10.17 (Sleepycat) 11/1/98"; -#endif - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <signal.h> -#include <stdio.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 "db_am.h" -#include "clib_ext.h" - -DB_ENV *db_init __P((char *)); -int main __P((int, char *[])); -void onint __P((int)); -void siginit __P((void)); -void usage __P((void)); - -int interrupted; -const char - *progname = "db_printlog"; /* Program name. */ - -int -main(argc, argv) - int argc; - char *argv[]; -{ - extern char *optarg; - extern int optind; - DB_ENV *dbenv; - DBT data; - DB_LSN key; - int ch, ret; - char *home; - - ret = 0; - home = NULL; - while ((ch = getopt(argc, argv, "h:N")) != EOF) - switch (ch) { - case 'h': - home = optarg; - break; - case 'N': - (void)db_value_set(0, DB_MUTEXLOCKS); - break; - case '?': - default: - usage(); - } - argc -= optind; - argv += optind; - - if (argc > 0) - usage(); - - /* Initialize the environment. */ - siginit(); - dbenv = db_init(home); - - if ((errno = __bam_init_print(dbenv)) != 0 || - (errno = __db_init_print(dbenv)) != 0 || - (errno = __ham_init_print(dbenv)) != 0 || - (errno = __log_init_print(dbenv)) != 0 || - (errno = __txn_init_print(dbenv)) != 0) { - warn("initialization"); - (void)db_appexit(dbenv); - return (1); - } - - memset(&data, 0, sizeof(data)); - while (!interrupted) { - if ((errno = - log_get(dbenv->lg_info, &key, &data, DB_NEXT)) != 0) { - if (errno == DB_NOTFOUND) - break; - warn("log_get"); - goto err; - } - if (dbenv->tx_recover != NULL) - errno = dbenv->tx_recover(dbenv->lg_info, - &data, &key, 0, NULL); - else - errno = __db_dispatch(dbenv->lg_info, - &data, &key, 0, NULL); - - fflush(stdout); - if (errno != 0) { - warn("dispatch"); - goto err; - } - } - - if (0) { -err: ret = 1; - } - - if (dbenv != NULL && (errno = db_appexit(dbenv)) != 0) { - ret = 1; - warn(NULL); - } - - if (interrupted) { - (void)signal(interrupted, SIG_DFL); - (void)raise(interrupted); - /* NOTREACHED */ - } - - return (ret); -} - -/* - * db_init -- - * Initialize the environment. - */ -DB_ENV * -db_init(home) - char *home; -{ - DB_ENV *dbenv; - - if ((dbenv = (DB_ENV *)calloc(sizeof(DB_ENV), 1)) == NULL) { - errno = ENOMEM; - err(1, NULL); - } - dbenv->db_errfile = stderr; - dbenv->db_errpfx = progname; - - if ((errno = - db_appinit(home, NULL, dbenv, DB_CREATE | DB_INIT_LOG)) != 0) - err(1, "db_appinit"); - return (dbenv); -} - -/* - * siginit -- - * Initialize the set of signals for which we want to clean up. - * Generally, we try not to leave the shared regions locked if - * we can. - */ -void -siginit() -{ -#ifdef SIGHUP - (void)signal(SIGHUP, onint); -#endif - (void)signal(SIGINT, onint); - (void)signal(SIGTERM, onint); -} - -/* - * onint -- - * Interrupt signal handler. - */ -void -onint(signo) - int signo; -{ - if ((interrupted = signo) == 0) - interrupted = SIGINT; -} - -void -usage() -{ - fprintf(stderr, "usage: db_printlog [-N] [-h home]\n"); - exit (1); -} diff --git a/db2/progs/db_printlog/pgno.awk b/db2/progs/db_printlog/pgno.awk deleted file mode 100644 index 99aa38f..0000000 --- a/db2/progs/db_printlog/pgno.awk +++ /dev/null @@ -1,43 +0,0 @@ -# @(#)pgno.awk 10.1 (Sleepycat) 11/1/98 -# -# Take a comma-separated list of page numbers and spit out all the -# log records that affect those page numbers. - -{ - if (NR == 1) { - npages = 0 - while ((ndx = index(PGNO, ",")) != 0) { - pgno[npages] = substr(PGNO, 1, ndx - 1); - PGNO = substr(PGNO, ndx + 1, length(PGNO) - ndx); - npages++ - } - pgno[npages] = PGNO; - } -} -/^\[/{ - if (printme == 1) { - printf("%s\n", rec); - printme = 0 - } - rec = ""; - - rec = $0 -} -/^ /{ - rec = sprintf("%s\n%s", rec, $0); -} -/pgno/{ - for (i = 0; i <= npages; i++) - if ($2 == pgno[i]) - printme = 1 -} -/right/{ - for (i = 0; i <= npages; i++) - if ($2 == pgno[i]) - printme = 1 -} -/left/{ - for (i = 0; i <= npages; i++) - if ($2 == pgno[i]) - printme = 1 -} diff --git a/db2/progs/db_printlog/range.awk b/db2/progs/db_printlog/range.awk deleted file mode 100644 index 89c56ea..0000000 --- a/db2/progs/db_printlog/range.awk +++ /dev/null @@ -1,27 +0,0 @@ -# @(#)range.awk 10.1 (Sleepycat) 11/1/98 -# -# Print out a range of the log - -/^\[/{ - l = length($1) - 1; - i = index($1, "]"); - file = substr($1, 2, i - 2); - file += 0; - start = i + 2; - offset = substr($1, start, l - start + 1); - i = index(offset, "]"); - offset = substr($1, start, i - 1); - offset += 0; - - if ((file == START_FILE && offset >= START_OFFSET || file > START_FILE)\ - && (file < END_FILE || (file == END_FILE && offset < END_OFFSET))) - printme = 1 - else if (file == END_FILE && offset > END_OFFSET || file > END_FILE) - exit - else - printme = 0 -} -{ - if (printme == 1) - print $0 -} diff --git a/db2/progs/db_printlog/status.awk b/db2/progs/db_printlog/status.awk deleted file mode 100644 index d97e935..0000000 --- a/db2/progs/db_printlog/status.awk +++ /dev/null @@ -1,26 +0,0 @@ -# @(#)status.awk 10.1 (Sleepycat) 11/1/98 -# -# Read through db_printlog output and list all the transactions encountered -# and whether they commited or aborted. -# -# 1 = started -# 2 = commited -BEGIN { - cur_txn = 0 -} -/^\[/{ - if (status[$5] == 0) { - status[$5] = 1; - txns[cur_txn] = $5; - cur_txn++; - } -} -/txn_regop/ { - status[$5] = 2 -} -END { - for (i = 0; i < cur_txn; i++) { - printf("%s\t%s\n", - txns[i], status[txns[i]] == 1 ? "ABORT" : "COMMIT"); - } -} diff --git a/db2/progs/db_printlog/txn.awk b/db2/progs/db_printlog/txn.awk deleted file mode 100644 index c8d3bd3..0000000 --- a/db2/progs/db_printlog/txn.awk +++ /dev/null @@ -1,30 +0,0 @@ -# @(#)txn.awk 10.1 (Sleepycat) 11/1/98 -# -# Print out all the records for a comma-separated list of transaction ids. -{ - if (NR == 1) { - ntxns = 0 - while ((ndx = index(TXN, ",")) != 0) { - txn[ntxns] = substr(TXN, 1, ndx - 1); - TXN = substr(TXN, ndx + 1, length(TXN) - ndx); - ntxns++ - } - txn[ntxns] = TXN; - } -} -/^\[/{ - if (printme == 1) { - printf("%s\n", rec); - printme = 0 - } - rec = ""; - - for (i = 0; i <= ntxns; i++) - if (txn[i] == $5) { - rec = $0 - printme = 1 - } -} -/^ /{ - rec = sprintf("%s\n%s", rec, $0); -} diff --git a/db2/progs/db_recover/db_recover.c b/db2/progs/db_recover/db_recover.c deleted file mode 100644 index d946ca1..0000000 --- a/db2/progs/db_recover/db_recover.c +++ /dev/null @@ -1,147 +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_recover.c 10.23 (Sleepycat) 10/5/98"; -#endif - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <signal.h> -#include <stdlib.h> -#include <time.h> -#include <unistd.h> -#endif - -#include "db_int.h" -#include "shqueue.h" -#include "txn.h" -#include "common_ext.h" -#include "clib_ext.h" - -DB_ENV *db_init __P((char *, u_int32_t, int)); -int main __P((int, char *[])); -void nosig __P((void)); -void usage __P((void)); - -const char - *progname = "db_recover"; /* Program name. */ - -int -main(argc, argv) - int argc; - char *argv[]; -{ - extern char *optarg; - extern int optind; - DB_ENV *dbenv; - time_t now; - u_int32_t flags; - int ch, verbose; - char *home; - - home = NULL; - flags = verbose = 0; - while ((ch = getopt(argc, argv, "ch:v")) != EOF) - switch (ch) { - case 'c': - LF_SET(DB_RECOVER_FATAL); - break; - case 'h': - home = optarg; - break; - case 'v': - verbose = 1; - break; - case '?': - default: - usage(); - } - argc -= optind; - argv += optind; - - if (argc != 0) - usage(); - - /* - * Ignore signals -- we don't want to be interrupted because we're - * spending all of our time in the DB library. - */ - nosig(); - dbenv = db_init(home, flags, verbose); - if (verbose) { - __db_err(dbenv, "Recovery complete at %.24s", ctime(&now)); - __db_err(dbenv, "%s %lx %s [%lu][%lu]", - "Maximum transaction id", - (u_long)dbenv->tx_info->region->last_txnid, - "Recovery checkpoint", - (u_long)dbenv->tx_info->region->last_ckp.file, - (u_long)dbenv->tx_info->region->last_ckp.offset); - } - - return (db_appexit(dbenv)); -} - -DB_ENV * -db_init(home, flags, verbose) - char *home; - u_int32_t flags; - int verbose; -{ - DB_ENV *dbenv; - u_int32_t local_flags; - - if ((dbenv = (DB_ENV *)calloc(sizeof(DB_ENV), 1)) == NULL) { - errno = ENOMEM; - err(1, NULL); - } - dbenv->db_errfile = stderr; - dbenv->db_errpfx = "db_recover"; - dbenv->db_verbose = verbose; - - /* Initialize environment for pathnames only. */ - local_flags = DB_CREATE | DB_INIT_LOG | - DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_TXN | DB_USE_ENVIRON; - - if (LF_ISSET(DB_RECOVER_FATAL)) - local_flags |= DB_RECOVER_FATAL; - else - local_flags |= DB_RECOVER; - - if ((errno = db_appinit(home, NULL, dbenv, local_flags)) != 0) - err(1, "appinit failed"); - - return (dbenv); -} - -/* - * nosig -- - * We don't want to be interrupted. - */ -void -nosig() -{ -#ifdef SIGHUP - (void)signal(SIGHUP, SIG_IGN); -#endif - (void)signal(SIGINT, SIG_IGN); - (void)signal(SIGTERM, SIG_IGN); -} - -void -usage() -{ - (void)fprintf(stderr, "usage: db_recover [-cv] [-h home]\n"); - exit(1); -} diff --git a/db2/progs/db_stat/db_stat.c b/db2/progs/db_stat/db_stat.c deleted file mode 100644 index cef645d..0000000 --- a/db2/progs/db_stat/db_stat.c +++ /dev/null @@ -1,621 +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_stat.c 8.41 (Sleepycat) 10/3/98"; -#endif - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <ctype.h> -#include <errno.h> -#include <signal.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> -#endif - -#undef stat - -#include "db_int.h" -#include "shqueue.h" -#include "db_shash.h" -#include "lock.h" -#include "mp.h" -#include "clib_ext.h" - -typedef enum { T_NOTSET, T_DB, T_LOCK, T_LOG, T_MPOOL, T_TXN } test_t; - -int argcheck __P((char *, const char *)); -void btree_stats __P((DB *)); -DB_ENV *db_init __P((char *, test_t)); -void dl __P((const char *, u_long)); -void hash_stats __P((DB *)); -int lock_ok __P((char *)); -void lock_stats __P((DB_ENV *)); -void log_stats __P((DB_ENV *)); -int main __P((int, char *[])); -int mpool_ok __P((char *)); -void mpool_stats __P((DB_ENV *)); -void nosig __P((void)); -void prflags __P((u_int32_t, const FN *)); -int txn_compare __P((const void *, const void *)); -void txn_stats __P((DB_ENV *)); -void usage __P((void)); - -char *internal; -const char - *progname = "db_stat"; /* Program name. */ - -int -main(argc, argv) - int argc; - char *argv[]; -{ - extern char *optarg; - extern int optind; - DB *dbp; - DB_ENV *dbenv; - test_t ttype; - int ch; - char *db, *home; - - ttype = T_NOTSET; - db = home = NULL; - while ((ch = getopt(argc, argv, "C:cd:h:lM:mNt")) != EOF) - switch (ch) { - case 'C': - ttype = T_LOCK; - if (!argcheck(internal = optarg, "Acflmo")) - usage(); - break; - case 'c': - ttype = T_LOCK; - break; - case 'd': - db = optarg; - ttype = T_DB; - break; - case 'h': - home = optarg; - break; - case 'l': - ttype = T_LOG; - break; - case 'M': - ttype = T_MPOOL; - if (!argcheck(internal = optarg, "Ahlm")) - usage(); - break; - case 'm': - ttype = T_MPOOL; - break; - case 'N': - (void)db_value_set(0, DB_MUTEXLOCKS); - break; - case 't': - ttype = T_TXN; - break; - case '?': - default: - usage(); - } - argc -= optind; - argv += optind; - - if (argc != 0 || ttype == T_NOTSET) - usage(); - - /* - * Ignore signals -- we don't want to be interrupted because we're - * spending all of our time in the DB library. - */ - nosig(); - dbenv = db_init(home, ttype); - - switch (ttype) { - case T_DB: - if ((errno = db_open(db, DB_UNKNOWN, - DB_RDONLY, 0, dbenv, NULL, &dbp)) != 0) { - warn("%s", db); - return (1); - } - switch (dbp->type) { - case DB_BTREE: - case DB_RECNO: - btree_stats(dbp); - break; - case DB_HASH: - hash_stats(dbp); - break; - case DB_UNKNOWN: - abort(); /* Impossible. */ - /* NOTREACHED */ - } - (void)dbp->close(dbp, 0); - break; - case T_LOCK: - lock_stats(dbenv); - break; - case T_LOG: - log_stats(dbenv); - break; - case T_MPOOL: - mpool_stats(dbenv); - break; - case T_TXN: - txn_stats(dbenv); - break; - case T_NOTSET: - abort(); /* Impossible. */ - /* NOTREACHED */ - } - - if ((errno = db_appexit(dbenv)) != 0) { - warn(NULL); - return (1); - } - return (0); -} - -/* - * btree_stats -- - * Display btree/recno statistics. - */ -void -btree_stats(dbp) - DB *dbp; -{ - static const FN fn[] = { - { DB_DUP, "DB_DUP" }, - { DB_FIXEDLEN, "DB_FIXEDLEN" }, - { DB_RECNUM, "DB_RECNUM" }, - { DB_RENUMBER, "DB_RENUMBER" }, - { 0 } - }; - DB_BTREE_STAT *sp; - - if (dbp->stat(dbp, &sp, NULL, 0)) - err(1, "dbp->stat"); - -#define PCT(f, t) \ - (t == 0 ? 0 : \ - (((double)((t * sp->bt_pagesize) - f) / (t * sp->bt_pagesize)) * 100)) - - printf("%#lx\tBtree magic number.\n", (u_long)sp->bt_magic); - printf("%lu\tBtree version number.\n", (u_long)sp->bt_version); - prflags(sp->bt_flags, fn); - if (dbp->type == DB_BTREE) { -#ifdef NOT_IMPLEMENTED - dl("Maximum keys per-page.\n", (u_long)sp->bt_maxkey); -#endif - dl("Minimum keys per-page.\n", (u_long)sp->bt_minkey); - } - if (dbp->type == DB_RECNO) { - dl("Fixed-length record size.\n", (u_long)sp->bt_re_len); - if (isprint(sp->bt_re_pad)) - printf("%c\tFixed-length record pad.\n", - (int)sp->bt_re_pad); - else - printf("0x%x\tFixed-length record pad.\n", - (int)sp->bt_re_pad); - } - dl("Underlying tree page size.\n", (u_long)sp->bt_pagesize); - dl("Number of levels in the tree.\n", (u_long)sp->bt_levels); - dl("Number of keys in the tree.\n", (u_long)sp->bt_nrecs); - dl("Number of tree internal pages.\n", (u_long)sp->bt_int_pg); - dl("Number of tree leaf pages.\n", (u_long)sp->bt_leaf_pg); - dl("Number of tree duplicate pages.\n", (u_long)sp->bt_dup_pg); - dl("Number of tree overflow pages.\n", (u_long)sp->bt_over_pg); - dl("Number of pages on the free list.\n", (u_long)sp->bt_free); - dl("Number of bytes free in tree internal pages", - (u_long)sp->bt_int_pgfree); - printf(" (%.0f%% ff).\n", PCT(sp->bt_int_pgfree, sp->bt_int_pg)); - dl("Number of bytes free in tree leaf pages", - (u_long)sp->bt_leaf_pgfree); - printf(" (%.0f%% ff).\n", PCT(sp->bt_leaf_pgfree, sp->bt_leaf_pg)); - dl("Number of bytes free in tree duplicate pages", - (u_long)sp->bt_dup_pgfree); - printf(" (%.0f%% ff).\n", PCT(sp->bt_dup_pgfree, sp->bt_dup_pg)); - dl("Number of bytes free in tree overflow pages", - (u_long)sp->bt_over_pgfree); - printf(" (%.0f%% ff).\n", PCT(sp->bt_over_pgfree, sp->bt_over_pg)); -} - -/* - * hash_stats -- - * Display hash statistics. - */ -void -hash_stats(dbp) - DB *dbp; -{ - COMPQUIET(dbp, NULL); - - printf("Hash statistics not currently available.\n"); - return; -} - -/* - * lock_stats -- - * Display lock statistics. - */ -void -lock_stats(dbenv) - DB_ENV *dbenv; -{ - DB_LOCK_STAT *sp; - - if (internal != NULL) { - __lock_dump_region(dbenv->lk_info, internal, stdout); - return; - } - - if (lock_stat(dbenv->lk_info, &sp, NULL)) - err(1, NULL); - - printf("%#lx\tLock magic number.\n", (u_long)sp->st_magic); - printf("%lu\tLock version number.\n", (u_long)sp->st_version); - dl("Lock region reference count.\n", (u_long)sp->st_refcnt); - dl("Lock region size.\n", (u_long)sp->st_regsize); - dl("Maximum number of locks.\n", (u_long)sp->st_maxlocks); - dl("Number of lock modes.\n", (u_long)sp->st_nmodes); - dl("Number of lock objects.\n", (u_long)sp->st_numobjs); - dl("Number of lockers.\n", (u_long)sp->st_nlockers); - dl("Number of lock conflicts.\n", (u_long)sp->st_nconflicts); - dl("Number of lock requests.\n", (u_long)sp->st_nrequests); - dl("Number of lock releases.\n", (u_long)sp->st_nreleases); - dl("Number of deadlocks.\n", (u_long)sp->st_ndeadlocks); - dl("The number of region locks granted without waiting.\n", - (u_long)sp->st_region_nowait); - dl("The number of region locks granted after waiting.\n", - (u_long)sp->st_region_wait); -} - -/* - * log_stats -- - * Display log statistics. - */ -void -log_stats(dbenv) - DB_ENV *dbenv; -{ - DB_LOG_STAT *sp; - - if (log_stat(dbenv->lg_info, &sp, NULL)) - err(1, NULL); - - printf("%#lx\tLog magic number.\n", (u_long)sp->st_magic); - printf("%lu\tLog version number.\n", (u_long)sp->st_version); - dl("Log region reference count.\n", (u_long)sp->st_refcnt); - dl("Log region size.\n", (u_long)sp->st_regsize); - printf("%#o\tLog file mode.\n", sp->st_mode); - if (sp->st_lg_max % MEGABYTE == 0) - printf("%luMb\tLog file size.\n", - (u_long)sp->st_lg_max / MEGABYTE); - else if (sp->st_lg_max % 1024 == 0) - printf("%luKb\tLog file size.\n", (u_long)sp->st_lg_max / 1024); - else - printf("%lu\tLog file size.\n", (u_long)sp->st_lg_max); - printf("%luMb\tLog bytes written (+%lu bytes).\n", - (u_long)sp->st_w_mbytes, (u_long)sp->st_w_bytes); - printf("%luMb\tLog bytes written since last checkpoint (+%lu bytes).\n", - (u_long)sp->st_wc_mbytes, (u_long)sp->st_wc_bytes); - dl("Total log file writes.\n", (u_long)sp->st_wcount); - dl("Total log file flushes.\n", (u_long)sp->st_scount); - printf("%lu\tCurrent log file number.\n", (u_long)sp->st_cur_file); - printf("%lu\tCurrent log file offset.\n", (u_long)sp->st_cur_offset); - dl("The number of region locks granted without waiting.\n", - (u_long)sp->st_region_nowait); - dl("The number of region locks granted after waiting.\n", - (u_long)sp->st_region_wait); -} - -/* - * mpool_stats -- - * Display mpool statistics. - */ -void -mpool_stats(dbenv) - DB_ENV *dbenv; -{ - DB_MPOOL_FSTAT **fsp; - DB_MPOOL_STAT *gsp; - - if (internal != NULL) { - __memp_dump_region(dbenv->mp_info, internal, stdout); - return; - } - - if (memp_stat(dbenv->mp_info, &gsp, &fsp, NULL)) - err(1, NULL); - - dl("Pool region reference count.\n", (u_long)gsp->st_refcnt); - dl("Pool region size.\n", (u_long)gsp->st_regsize); - dl("Cache size", (u_long)gsp->st_cachesize); - printf(" (%luK).\n", (u_long)gsp->st_cachesize / 1024); - dl("Requested pages found in the cache", (u_long)gsp->st_cache_hit); - if (gsp->st_cache_hit + gsp->st_cache_miss != 0) - printf(" (%.0f%%)", ((double)gsp->st_cache_hit / - (gsp->st_cache_hit + gsp->st_cache_miss)) * 100); - printf(".\n"); - dl("Requested pages mapped into the process' address space.\n", - (u_long)gsp->st_map); - dl("Requested pages not found in the cache.\n", - (u_long)gsp->st_cache_miss); - dl("Pages created in the cache.\n", (u_long)gsp->st_page_create); - dl("Pages read into the cache.\n", (u_long)gsp->st_page_in); - dl("Pages written from the cache to the backing file.\n", - (u_long)gsp->st_page_out); - dl("Clean pages forced from the cache.\n", - (u_long)gsp->st_ro_evict); - dl("Dirty pages forced from the cache.\n", - (u_long)gsp->st_rw_evict); - dl("Dirty buffers written by trickle-sync thread.\n", - (u_long)gsp->st_page_trickle); - dl("Current clean buffer count.\n", - (u_long)gsp->st_page_clean); - dl("Current dirty buffer count.\n", - (u_long)gsp->st_page_dirty); - dl("Number of hash buckets used for page location.\n", - (u_long)gsp->st_hash_buckets); - dl("Total number of times hash chains searched for a page.\n", - (u_long)gsp->st_hash_searches); - dl("The longest hash chain searched for a page.\n", - (u_long)gsp->st_hash_longest); - dl("Total number of hash buckets examined for page location.\n", - (u_long)gsp->st_hash_examined); - dl("The number of region locks granted without waiting.\n", - (u_long)gsp->st_region_nowait); - dl("The number of region locks granted after waiting.\n", - (u_long)gsp->st_region_wait); - - for (; fsp != NULL && *fsp != NULL; ++fsp) { - printf("%s\n", DB_LINE); - printf("%s\n", (*fsp)->file_name); - dl("Page size.\n", (u_long)(*fsp)->st_pagesize); - dl("Requested pages found in the cache", - (u_long)(*fsp)->st_cache_hit); - if ((*fsp)->st_cache_hit + (*fsp)->st_cache_miss != 0) - printf(" (%.0f%%)", ((double)(*fsp)->st_cache_hit / - ((*fsp)->st_cache_hit + (*fsp)->st_cache_miss)) * - 100); - printf(".\n"); - dl("Requested pages mapped into the process' address space.\n", - (u_long)(*fsp)->st_map); - dl("Requested pages not found in the cache.\n", - (u_long)(*fsp)->st_cache_miss); - dl("Pages created in the cache.\n", - (u_long)(*fsp)->st_page_create); - dl("Pages read into the cache.\n", - (u_long)(*fsp)->st_page_in); - dl("Pages written from the cache to the backing file.\n", - (u_long)(*fsp)->st_page_out); - } -} - -/* - * txn_stats -- - * Display transaction statistics. - */ -void -txn_stats(dbenv) - DB_ENV *dbenv; -{ - DB_TXN_STAT *sp; - u_int32_t i; - const char *p; - - if (txn_stat(dbenv->tx_info, &sp, NULL)) - err(1, NULL); - - dl("Txn region reference count.\n", (u_long)sp->st_refcnt); - dl("Txn region size.\n", (u_long)sp->st_regsize); - p = sp->st_last_ckp.file == 0 ? - "No checkpoint LSN." : "File/offset for last checkpoint LSN."; - printf("%lu/%lu\t%s\n", - (u_long)sp->st_last_ckp.file, (u_long)sp->st_last_ckp.offset, p); - p = sp->st_pending_ckp.file == 0 ? - "No pending checkpoint LSN." : - "File/offset for last pending checkpoint LSN."; - printf("%lu/%lu\t%s\n", - (u_long)sp->st_pending_ckp.file, - (u_long)sp->st_pending_ckp.offset, p); - if (sp->st_time_ckp == 0) - printf("0\tNo checkpoint timestamp.\n"); - else - printf("%.24s\tCheckpoint timestamp.\n", - ctime(&sp->st_time_ckp)); - printf("%lx\tLast transaction ID allocated.\n", - (u_long)sp->st_last_txnid); - dl("Maximum number of active transactions.\n", (u_long)sp->st_maxtxns); - dl("Number of transactions begun.\n", (u_long)sp->st_nbegins); - dl("Number of transactions aborted.\n", (u_long)sp->st_naborts); - dl("Number of transactions committed.\n", (u_long)sp->st_ncommits); - dl("The number of region locks granted without waiting.\n", - (u_long)sp->st_region_nowait); - dl("The number of region locks granted after waiting.\n", - (u_long)sp->st_region_wait); - dl("Active transactions.\n", (u_long)sp->st_nactive); - qsort(sp->st_txnarray, - sp->st_nactive, sizeof(sp->st_txnarray[0]), txn_compare); - for (i = 0; i < sp->st_nactive; ++i) - printf("\tid: %lx; initial LSN file/offest %lu/%lu\n", - (u_long)sp->st_txnarray[i].txnid, - (u_long)sp->st_txnarray[i].lsn.file, - (u_long)sp->st_txnarray[i].lsn.offset); -} - -int -txn_compare(a1, b1) - const void *a1, *b1; -{ - const DB_TXN_ACTIVE *a, *b; - - a = a1; - b = b1; - - if (a->txnid > b->txnid) - return (1); - if (a->txnid < b->txnid) - return (-1); - return (0); -} - -/* - * dl -- - * Display a big value. - */ -void -dl(msg, value) - const char *msg; - u_long value; -{ - /* - * Two formats: if less than 10 million, display as the number, if - * greater than 10 million display as ###M. - */ - if (value < 10000000) - printf("%lu\t%s", value, msg); - else - printf("%luM\t%s", value / 1000000, msg); -} - -/* - * prflags -- - * Print out flag values. - */ -void -prflags(flags, fnp) - u_int32_t flags; - const FN *fnp; -{ - const char *sep; - - sep = " "; - printf("Flags:"); - for (; fnp->mask != 0; ++fnp) - if (fnp->mask & flags) { - printf("%s%s", sep, fnp->name); - sep = ", "; - } - printf("\n"); -} - -/* - * db_init -- - * Initialize the environment. - */ -DB_ENV * -db_init(home, ttype) - char *home; - test_t ttype; -{ - DB_ENV *dbenv; - u_int32_t flags; - - if ((dbenv = (DB_ENV *)malloc(sizeof(DB_ENV))) == NULL) { - errno = ENOMEM; - err(1, NULL); - } - - /* - * Try and use the shared regions when reporting statistics on the - * DB databases, so our information is as up-to-date as possible, - * even if the mpool cache hasn't been flushed. If that fails, we - * turn off the DB_INIT_MPOOL flag and try again. - */ - flags = DB_USE_ENVIRON; - switch (ttype) { - case T_DB: - case T_MPOOL: - LF_SET(DB_INIT_MPOOL); - break; - case T_LOCK: - LF_SET(DB_INIT_LOCK); - break; - case T_LOG: - LF_SET(DB_INIT_LOG); - break; - case T_TXN: - LF_SET(DB_INIT_TXN); - break; - case T_NOTSET: - abort(); - /* NOTREACHED */ - } - - /* - * If it works, we're done. Set the error output options so that - * future errors are correctly reported. - */ - memset(dbenv, 0, sizeof(*dbenv)); - if ((errno = db_appinit(home, NULL, dbenv, flags)) == 0) { - dbenv->db_errfile = stderr; - dbenv->db_errpfx = progname; - return (dbenv); - } - - /* Turn off the DB_INIT_MPOOL flag if it's a database. */ - if (ttype == T_DB) - LF_CLR(DB_INIT_MPOOL); - - /* Set the error output options -- this time we want a message. */ - memset(dbenv, 0, sizeof(*dbenv)); - dbenv->db_errfile = stderr; - dbenv->db_errpfx = progname; - - /* Try again, and it's fatal if we fail. */ - if ((errno = db_appinit(home, NULL, dbenv, flags)) != 0) - err(1, "db_appinit"); - - return (dbenv); -} - -/* - * argcheck -- - * Return if argument flags are okay. - */ -int -argcheck(arg, ok_args) - char *arg; - const char *ok_args; -{ - for (; *arg != '\0'; ++arg) - if (strchr(ok_args, *arg) == NULL) - return (0); - return (1); -} - -/* - * nosig -- - * We don't want to be interrupted. - */ -void -nosig() -{ -#ifdef SIGHUP - (void)signal(SIGHUP, SIG_IGN); -#endif - (void)signal(SIGINT, SIG_IGN); - (void)signal(SIGTERM, SIG_IGN); -} - -void -usage() -{ - fprintf(stderr, - "usage: db_stat [-clmNt] [-C Acflmo] [-d file] [-h home] [-M Ahlm]\n"); - exit (1); -} diff --git a/db2/txn/txn.c b/db2/txn/txn.c deleted file mode 100644 index aa0b365..0000000 --- a/db2/txn/txn.c +++ /dev/null @@ -1,1046 +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. - * - * 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[] = "@(#)txn.c 10.66 (Sleepycat) 1/3/99"; -#endif /* not lint */ - - -#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_shash.h" -#include "txn.h" -#include "db_dispatch.h" -#include "lock.h" -#include "log.h" -#include "db_am.h" -#include "common_ext.h" - -static int __txn_begin __P((DB_TXN *)); -static int __txn_check_running __P((const DB_TXN *, TXN_DETAIL **)); -static int __txn_end __P((DB_TXN *, int)); -static void __txn_freekids __P((DB_TXN *)); -static int __txn_grow_region __P((DB_TXNMGR *)); -static int __txn_init __P((DB_TXNREGION *)); -static int __txn_undo __P((DB_TXN *)); -static int __txn_validate_region __P((DB_TXNMGR *)); - -/* - * This file contains the top level routines of the transaction library. - * It assumes that a lock manager and log manager that conform to the db_log(3) - * and db_lock(3) interfaces exist. - * - * Initialize a transaction region in shared memory. - * Return 0 on success, errno on failure. - */ -static int -__txn_init(txn_region) - DB_TXNREGION *txn_region; -{ - time_t now; - - (void)time(&now); - - /* maxtxns is already initialized. */ - txn_region->magic = DB_TXNMAGIC; - txn_region->version = DB_TXNVERSION; - txn_region->last_txnid = TXN_MINIMUM; - /* - * XXX - * If we ever do more types of locking and logging, this changes. - */ - txn_region->logtype = 0; - txn_region->locktype = 0; - txn_region->time_ckp = now; - ZERO_LSN(txn_region->last_ckp); - ZERO_LSN(txn_region->pending_ckp); - SH_TAILQ_INIT(&txn_region->active_txn); - __db_shalloc_init((void *)&txn_region[1], - TXN_REGION_SIZE(txn_region->maxtxns) - sizeof(DB_TXNREGION)); - - return (0); -} - -int -txn_open(path, flags, mode, dbenv, mgrpp) - const char *path; - u_int32_t flags; - int mode; - DB_ENV *dbenv; - DB_TXNMGR **mgrpp; -{ - DB_TXNMGR *tmgrp; - u_int32_t maxtxns; - int ret; - - /* Validate arguments. */ - if (dbenv == NULL) - return (EINVAL); -#ifdef HAVE_SPINLOCKS -#define OKFLAGS (DB_CREATE | DB_THREAD | DB_TXN_NOSYNC) -#else -#define OKFLAGS (DB_CREATE | DB_TXN_NOSYNC) -#endif - if ((ret = __db_fchk(dbenv, "txn_open", flags, OKFLAGS)) != 0) - return (ret); - - maxtxns = dbenv->tx_max != 0 ? dbenv->tx_max : 20; - - /* Now, create the transaction manager structure and set its fields. */ - if ((ret = __os_calloc(1, sizeof(DB_TXNMGR), &tmgrp)) != 0) - return (ret); - - /* Initialize the transaction manager structure. */ - tmgrp->mutexp = NULL; - tmgrp->dbenv = dbenv; - tmgrp->recover = - dbenv->tx_recover == NULL ? __db_dispatch : dbenv->tx_recover; - tmgrp->flags = LF_ISSET(DB_TXN_NOSYNC | DB_THREAD); - TAILQ_INIT(&tmgrp->txn_chain); - - /* Join/create the txn region. */ - tmgrp->reginfo.dbenv = dbenv; - tmgrp->reginfo.appname = DB_APP_NONE; - if (path == NULL) - tmgrp->reginfo.path = NULL; - else - if ((ret = __os_strdup(path, &tmgrp->reginfo.path)) != 0) - goto err; - tmgrp->reginfo.file = DEFAULT_TXN_FILE; - tmgrp->reginfo.mode = mode; - tmgrp->reginfo.size = TXN_REGION_SIZE(maxtxns); - tmgrp->reginfo.dbflags = flags; - tmgrp->reginfo.addr = NULL; - tmgrp->reginfo.fd = -1; - tmgrp->reginfo.flags = dbenv->tx_max == 0 ? REGION_SIZEDEF : 0; - if ((ret = __db_rattach(&tmgrp->reginfo)) != 0) - goto err; - - /* Fill in region-related fields. */ - tmgrp->region = tmgrp->reginfo.addr; - tmgrp->mem = &tmgrp->region[1]; - - if (F_ISSET(&tmgrp->reginfo, REGION_CREATED)) { - tmgrp->region->maxtxns = maxtxns; - if ((ret = __txn_init(tmgrp->region)) != 0) - goto err; - - } else if (tmgrp->region->magic != DB_TXNMAGIC) { - /* Check if valid region. */ - __db_err(dbenv, "txn_open: Bad magic number"); - ret = EINVAL; - goto err; - } - - if (LF_ISSET(DB_THREAD)) { - if ((ret = __db_shalloc(tmgrp->mem, sizeof(db_mutex_t), - MUTEX_ALIGNMENT, &tmgrp->mutexp)) == 0) - /* - * Since we only get here if threading is turned on, we - * know that we have spinlocks, so the offset is going - * to be ignored. We put 0 here as a valid placeholder. - */ - __db_mutex_init(tmgrp->mutexp, 0); - if (ret != 0) - goto err; - } - - UNLOCK_TXNREGION(tmgrp); - *mgrpp = tmgrp; - return (0); - -err: if (tmgrp->reginfo.addr != NULL) { - if (tmgrp->mutexp != NULL) - __db_shalloc_free(tmgrp->mem, tmgrp->mutexp); - - UNLOCK_TXNREGION(tmgrp); - (void)__db_rdetach(&tmgrp->reginfo); - if (F_ISSET(&tmgrp->reginfo, REGION_CREATED)) - (void)txn_unlink(path, 1, dbenv); - } - - if (tmgrp->reginfo.path != NULL) - __os_freestr(tmgrp->reginfo.path); - __os_free(tmgrp, sizeof(*tmgrp)); - return (ret); -} - -/* - * __txn_panic -- - * Panic a transaction region. - * - * PUBLIC: void __txn_panic __P((DB_ENV *)); - */ -void -__txn_panic(dbenv) - DB_ENV *dbenv; -{ - if (dbenv->tx_info != NULL) - dbenv->tx_info->region->hdr.panic = 1; -} - -/* - * txn_begin -- - * This is a wrapper to the actual begin process. Normal txn_begin() - * allocates a DB_TXN structure for the caller, while txn_xa_begin() does - * not. Other than that, both call into the common __txn_begin code(). - * - * Internally, we use TXN_DETAIL structures, but the DB_TXN structure - * provides access to the transaction ID and the offset in the transaction - * region of the TXN_DETAIL structure. - */ -int -txn_begin(tmgrp, parent, txnpp) - DB_TXNMGR *tmgrp; - DB_TXN *parent, **txnpp; -{ - DB_TXN *txn; - int ret; - - TXN_PANIC_CHECK(tmgrp); - - if ((ret = __os_calloc(1, sizeof(DB_TXN), &txn)) != 0) - return (ret); - - txn->parent = parent; - TAILQ_INIT(&txn->kids); - txn->mgrp = tmgrp; - txn->flags = TXN_MALLOC; - if ((ret = __txn_begin(txn)) != 0) { - __os_free(txn, sizeof(DB_TXN)); - txn = NULL; - } - if (txn != NULL && parent != NULL) - TAILQ_INSERT_HEAD(&parent->kids, txn, klinks); - *txnpp = txn; - return (ret); -} - -/* - * __txn_xa_begin -- - * XA version of txn_begin. - * - * PUBLIC: int __txn_xa_begin __P((DB_ENV *, DB_TXN *)); - */ -int -__txn_xa_begin(dbenv, txn) - DB_ENV *dbenv; - DB_TXN *txn; -{ - TXN_PANIC_CHECK(dbenv->tx_info); - - memset(txn, 0, sizeof(DB_TXN)); - - txn->mgrp = dbenv->tx_info; - - return (__txn_begin(txn)); -} - -/* - * __txn_begin -- - * Normal DB version of txn_begin. - */ -static int -__txn_begin(txn) - DB_TXN *txn; -{ - DB_LSN begin_lsn; - DB_TXNMGR *mgr; - TXN_DETAIL *td; - size_t off; - u_int32_t id; - int ret; - - /* - * We do not have to write begin records (and if we do not, then we - * need never write records for read-only transactions). However, - * we do need to find the current LSN so that we can store it in the - * transaction structure, so we can know where to take checkpoints. - */ - mgr = txn->mgrp; - if (mgr->dbenv->lg_info != NULL && (ret = - log_put(mgr->dbenv->lg_info, &begin_lsn, NULL, DB_CURLSN)) != 0) - goto err2; - - LOCK_TXNREGION(mgr); - - /* Make sure that last_txnid is not going to wrap around. */ - if (mgr->region->last_txnid == TXN_INVALID) { - __db_err(mgr->dbenv, "txn_begin: %s %s", - "Transaction ID wrapping.", - "Snapshot your database and start a new log."); - ret = EINVAL; - goto err1; - } - - if ((ret = __txn_validate_region(mgr)) != 0) - goto err1; - - /* Allocate a new transaction detail structure. */ - if ((ret = __db_shalloc(mgr->mem, sizeof(TXN_DETAIL), 0, &td)) != 0 - && ret == ENOMEM && (ret = __txn_grow_region(mgr)) == 0) - ret = __db_shalloc(mgr->mem, sizeof(TXN_DETAIL), 0, &td); - if (ret != 0) - goto err1; - - /* Place transaction on active transaction list. */ - SH_TAILQ_INSERT_HEAD(&mgr->region->active_txn, td, links, __txn_detail); - - id = ++mgr->region->last_txnid; - ++mgr->region->nbegins; - - td->txnid = id; - td->begin_lsn = begin_lsn; - ZERO_LSN(td->last_lsn); - td->last_lock = 0; - td->status = TXN_RUNNING; - if (txn->parent != NULL) - td->parent = txn->parent->off; - else - td->parent = 0; - - off = (u_int8_t *)td - (u_int8_t *)mgr->region; - UNLOCK_TXNREGION(mgr); - - ZERO_LSN(txn->last_lsn); - txn->txnid = id; - txn->off = off; - - if (F_ISSET(txn, TXN_MALLOC)) { - LOCK_TXNTHREAD(mgr); - TAILQ_INSERT_TAIL(&mgr->txn_chain, txn, links); - UNLOCK_TXNTHREAD(mgr); - } - - return (0); - -err1: UNLOCK_TXNREGION(mgr); - -err2: return (ret); -} -/* - * txn_commit -- - * Commit a transaction. - */ -int -txn_commit(txnp) - DB_TXN *txnp; -{ - DB_LOG *logp; - DB_TXNMGR *mgr; - int ret; - - mgr = txnp->mgrp; - - TXN_PANIC_CHECK(mgr); - if ((ret = __txn_check_running(txnp, NULL)) != 0) - return (ret); - - /* - * If there are any log records, write a log record and sync - * the log, else do no log writes. If the commit is for a child - * transaction, we do not need to commit the child synchronously - * since if its parent aborts, it will abort too and its parent - * (or ultimate ancestor) will write synchronously. - */ - if ((logp = mgr->dbenv->lg_info) != NULL && - !IS_ZERO_LSN(txnp->last_lsn)) { - if (txnp->parent == NULL) - ret = __txn_regop_log(logp, txnp, &txnp->last_lsn, - F_ISSET(mgr, DB_TXN_NOSYNC) ? 0 : DB_FLUSH, - TXN_COMMIT); - else - ret = __txn_child_log(logp, txnp, &txnp->last_lsn, 0, - TXN_COMMIT, txnp->parent->txnid); - if (ret != 0) - return (ret); - } - - /* - * If this is the senior ancestor (i.e., it has no children), then we - * can release all the child transactions since everyone is committing. - * Then we can release this transaction. If this is not the ultimate - * ancestor, then we can neither free it or its children. - */ - if (txnp->parent == NULL) - __txn_freekids(txnp); - - return (__txn_end(txnp, 1)); -} - -/* - * txn_abort -- - * Abort a transcation. - */ -int -txn_abort(txnp) - DB_TXN *txnp; -{ - int ret; - DB_TXN *kids; - - TXN_PANIC_CHECK(txnp->mgrp); - if ((ret = __txn_check_running(txnp, NULL)) != 0) - return (ret); - - for (kids = TAILQ_FIRST(&txnp->kids); - kids != NULL; - kids = TAILQ_FIRST(&txnp->kids)) - txn_abort(kids); - - if ((ret = __txn_undo(txnp)) != 0) { - __db_err(txnp->mgrp->dbenv, - "txn_abort: Log undo failed %s", strerror(ret)); - return (ret); - } - return (__txn_end(txnp, 0)); -} - -/* - * txn_prepare -- - * Flush the log so a future commit is guaranteed to succeed. - */ -int -txn_prepare(txnp) - DB_TXN *txnp; -{ - DBT xid; - DB_ENV *dbenv; - TXN_DETAIL *td; - int ret; - - if ((ret = __txn_check_running(txnp, &td)) != 0) - return (ret); - - dbenv = txnp->mgrp->dbenv; - memset(&xid, 0, sizeof(xid)); - xid.data = td->xid; - /* - * We indicate that a transaction is an XA transaction by putting - * a valid size in the xid.size fiels. XA requires that the transaction - * be either ENDED or SUSPENDED when prepare is called, so we know - * that if the xa_status isn't in one of those states, but we are - * calling prepare that we are not an XA transaction. - */ - xid.size = - td->xa_status != TXN_XA_ENDED && td->xa_status != TXN_XA_SUSPENDED ? - 0 : sizeof(td->xid); - if (dbenv->lg_info != NULL && - (ret = __txn_xa_regop_log(dbenv->lg_info, txnp, &txnp->last_lsn, - F_ISSET(txnp->mgrp, DB_TXN_NOSYNC) ? 0 : DB_FLUSH, TXN_PREPARE, - &xid, td->format, td->gtrid, td->bqual, &td->begin_lsn)) != 0) { - __db_err(dbenv, - "txn_prepare: log_write failed %s\n", strerror(ret)); - return (ret); - } - - LOCK_TXNTHREAD(txnp->mgrp); - td->status = TXN_PREPARED; - UNLOCK_TXNTHREAD(txnp->mgrp); - return (ret); -} - -/* - * Return the transaction ID associated with a particular transaction - */ -u_int32_t -txn_id(txnp) - DB_TXN *txnp; -{ - return (txnp->txnid); -} - -/* - * txn_close -- - * Close the transaction region, does not imply a checkpoint. - */ -int -txn_close(tmgrp) - DB_TXNMGR *tmgrp; -{ - DB_TXN *txnp; - int ret, t_ret; - - TXN_PANIC_CHECK(tmgrp); - - ret = 0; - - /* - * This function had better only be called once per process - * (i.e., not per thread), so there should be no synchronization - * required. - */ - while ((txnp = - TAILQ_FIRST(&tmgrp->txn_chain)) != TAILQ_END(&tmgrp->txn_chain)) - if ((t_ret = txn_abort(txnp)) != 0) { - __txn_end(txnp, 0); - if (ret == 0) - ret = t_ret; - } - - if (tmgrp->dbenv->lg_info && - (t_ret = log_flush(tmgrp->dbenv->lg_info, NULL)) != 0 && ret == 0) - ret = t_ret; - - if (tmgrp->mutexp != NULL) { - LOCK_TXNREGION(tmgrp); - __db_shalloc_free(tmgrp->mem, tmgrp->mutexp); - UNLOCK_TXNREGION(tmgrp); - } - - if ((t_ret = __db_rdetach(&tmgrp->reginfo)) != 0 && ret == 0) - ret = t_ret; - - if (tmgrp->reginfo.path != NULL) - __os_freestr(tmgrp->reginfo.path); - __os_free(tmgrp, sizeof(*tmgrp)); - - return (ret); -} - -/* - * txn_unlink -- - * Remove the transaction region. - */ -int -txn_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_NONE; - if (path != NULL && (ret = __os_strdup(path, ®info.path)) != 0) - return (ret); - reginfo.file = DEFAULT_TXN_FILE; - ret = __db_runlink(®info, force); - if (reginfo.path != NULL) - __os_freestr(reginfo.path); - return (ret); -} - -/* Internal routines. */ - -/* - * Return 0 if the txnp is reasonable, otherwise returns EINVAL. - */ -static int -__txn_check_running(txnp, tdp) - const DB_TXN *txnp; - TXN_DETAIL **tdp; -{ - TXN_DETAIL *tp; - - tp = NULL; - if (txnp != NULL && txnp->mgrp != NULL && txnp->mgrp->region != NULL) { - tp = (TXN_DETAIL *)((u_int8_t *)txnp->mgrp->region + txnp->off); - /* - * Child transactions could be marked committed which is OK. - */ - if (tp->status != TXN_RUNNING && - tp->status != TXN_PREPARED && tp->status != TXN_COMMITTED) - tp = NULL; - if (tdp != NULL) - *tdp = tp; - } - - return (tp == NULL ? EINVAL : 0); -} - -static int -__txn_end(txnp, is_commit) - DB_TXN *txnp; - int is_commit; -{ - DB_LOCKREQ request; - DB_TXNMGR *mgr; - TXN_DETAIL *tp; - u_int32_t locker; - int ret; - - mgr = txnp->mgrp; - - /* Release the locks. */ - locker = txnp->txnid; - request.op = txnp->parent == NULL || - is_commit == 0 ? DB_LOCK_PUT_ALL : DB_LOCK_INHERIT; - - if (mgr->dbenv->lk_info) { - ret = - lock_tvec(mgr->dbenv->lk_info, txnp, 0, &request, 1, NULL); - if (ret != 0 && (ret != DB_LOCK_DEADLOCK || is_commit)) { - __db_err(mgr->dbenv, "%s: release locks failed %s", - is_commit ? "txn_commit" : "txn_abort", - strerror(ret)); - return (ret); - } - } - - /* End the transaction. */ - LOCK_TXNREGION(mgr); - - /* - * Child transactions that are committing cannot be released until - * the parent commits, since the parent may abort, causing the child - * to abort as well. - */ - tp = (TXN_DETAIL *)((u_int8_t *)mgr->region + txnp->off); - if (txnp->parent == NULL || !is_commit) { - SH_TAILQ_REMOVE(&mgr->region->active_txn, - tp, links, __txn_detail); - - __db_shalloc_free(mgr->mem, tp); - } else - tp->status = is_commit ? TXN_COMMITTED : TXN_ABORTED; - - if (is_commit) - mgr->region->ncommits++; - else - mgr->region->naborts++; - - UNLOCK_TXNREGION(mgr); - - /* - * If the transaction aborted, we can remove it from its parent links. - * If it committed, then we need to leave it on, since the parent can - * still abort. - */ - if (txnp->parent != NULL && !is_commit) - TAILQ_REMOVE(&txnp->parent->kids, txnp, klinks); - - /* Free the space. */ - if (F_ISSET(txnp, TXN_MALLOC) && (txnp->parent == NULL || !is_commit)) { - LOCK_TXNTHREAD(mgr); - TAILQ_REMOVE(&mgr->txn_chain, txnp, links); - UNLOCK_TXNTHREAD(mgr); - - __os_free(txnp, sizeof(*txnp)); - } - - return (0); -} - - -/* - * __txn_undo -- - * Undo the transaction with id txnid. Returns 0 on success and - * errno on failure. - */ -static int -__txn_undo(txnp) - DB_TXN *txnp; -{ - DBT rdbt; - DB_LOG *logp; - DB_LSN key_lsn; - DB_TXNMGR *mgr; - int ret; - - mgr = txnp->mgrp; - logp = mgr->dbenv->lg_info; - if (logp == NULL) - return (0); - - /* - * This is the simplest way to code this, but if the mallocs during - * recovery turn out to be a performance issue, we can do the - * allocation here and use DB_DBT_USERMEM. - */ - memset(&rdbt, 0, sizeof(rdbt)); - if (F_ISSET(logp, DB_AM_THREAD)) - F_SET(&rdbt, DB_DBT_MALLOC); - - key_lsn = txnp->last_lsn; /* structure assignment */ - for (ret = 0; ret == 0 && !IS_ZERO_LSN(key_lsn);) { - /* - * The dispatch routine returns the lsn of the record - * before the current one in the key_lsn argument. - */ - if ((ret = log_get(logp, &key_lsn, &rdbt, DB_SET)) == 0) { - ret = - mgr->recover(logp, &rdbt, &key_lsn, TXN_UNDO, NULL); - if (F_ISSET(logp, DB_AM_THREAD) && rdbt.data != NULL) { - __os_free(rdbt.data, rdbt.size); - rdbt.data = NULL; - } - } - if (ret != 0) - return (ret); - } - - return (ret); -} - -/* - * Transaction checkpoint. - * If either kbytes or minutes is non-zero, then we only take the checkpoint - * more than "minutes" minutes have passed since the last checkpoint or if - * more than "kbytes" of log data have been written since the last checkpoint. - * When taking a checkpoint, find the oldest active transaction and figure out - * its first LSN. This is the lowest LSN we can checkpoint, since any record - * written after since that point may be involved in a transaction and may - * therefore need to be undone in the case of an abort. - */ -int -txn_checkpoint(mgr, kbytes, minutes) - const DB_TXNMGR *mgr; - u_int32_t kbytes, minutes; -{ - DB_LOG *dblp; - DB_LSN ckp_lsn, sync_lsn, last_ckp; - TXN_DETAIL *txnp; - time_t last_ckp_time, now; - u_int32_t kbytes_written; - int ret; - - TXN_PANIC_CHECK(mgr); - - /* - * Check if we need to run recovery. - */ - ZERO_LSN(ckp_lsn); - if (minutes != 0) { - (void)time(&now); - - LOCK_TXNREGION(mgr); - last_ckp_time = mgr->region->time_ckp; - UNLOCK_TXNREGION(mgr); - - if (now - last_ckp_time >= (time_t)(minutes * 60)) - goto do_ckp; - } - - if (kbytes != 0) { - dblp = mgr->dbenv->lg_info; - LOCK_LOGREGION(dblp); - kbytes_written = - dblp->lp->stat.st_wc_mbytes * 1024 + - dblp->lp->stat.st_wc_bytes / 1024; - ckp_lsn = dblp->lp->lsn; - UNLOCK_LOGREGION(dblp); - if (kbytes_written >= (u_int32_t)kbytes) - goto do_ckp; - } - - /* - * If we checked time and data and didn't go to checkpoint, - * we're done. - */ - if (minutes != 0 || kbytes != 0) - return (0); - -do_ckp: - if (IS_ZERO_LSN(ckp_lsn)) { - dblp = mgr->dbenv->lg_info; - LOCK_LOGREGION(dblp); - ckp_lsn = dblp->lp->lsn; - UNLOCK_LOGREGION(dblp); - } - - /* - * We have to find an LSN such that all transactions begun - * before that LSN are complete. - */ - LOCK_TXNREGION(mgr); - - if (!IS_ZERO_LSN(mgr->region->pending_ckp)) - ckp_lsn = mgr->region->pending_ckp; - else - for (txnp = - SH_TAILQ_FIRST(&mgr->region->active_txn, __txn_detail); - txnp != NULL; - txnp = SH_TAILQ_NEXT(txnp, links, __txn_detail)) { - - /* - * Look through the active transactions for the - * lowest begin lsn. - */ - if (!IS_ZERO_LSN(txnp->begin_lsn) && - log_compare(&txnp->begin_lsn, &ckp_lsn) < 0) - ckp_lsn = txnp->begin_lsn; - } - - mgr->region->pending_ckp = ckp_lsn; - UNLOCK_TXNREGION(mgr); - - /* - * memp_sync may change the lsn you pass it, so don't pass it - * the actual ckp_lsn, pass it a temp instead. - */ - sync_lsn = ckp_lsn; - if (mgr->dbenv->mp_info != NULL && - (ret = memp_sync(mgr->dbenv->mp_info, &sync_lsn)) != 0) { - /* - * ret == DB_INCOMPLETE means that there are still buffers to - * flush, the checkpoint is not complete. Wait and try again. - */ - if (ret > 0) - __db_err(mgr->dbenv, - "txn_checkpoint: system failure in memp_sync %s\n", - strerror(ret)); - return (ret); - } - if (mgr->dbenv->lg_info != NULL) { - LOCK_TXNREGION(mgr); - last_ckp = mgr->region->last_ckp; - ZERO_LSN(mgr->region->pending_ckp); - UNLOCK_TXNREGION(mgr); - - if ((ret = __txn_ckp_log(mgr->dbenv->lg_info, - NULL, &ckp_lsn, DB_CHECKPOINT, &ckp_lsn, &last_ckp)) != 0) { - __db_err(mgr->dbenv, - "txn_checkpoint: log failed at LSN [%ld %ld] %s\n", - (long)ckp_lsn.file, (long)ckp_lsn.offset, - strerror(ret)); - return (ret); - } - - LOCK_TXNREGION(mgr); - mgr->region->last_ckp = ckp_lsn; - (void)time(&mgr->region->time_ckp); - UNLOCK_TXNREGION(mgr); - } - return (0); -} - -/* - * __txn_validate_region -- - * Called at every interface to verify if the region has changed size, - * and if so, to remap the region in and reset the process' pointers. - */ -static int -__txn_validate_region(tp) - DB_TXNMGR *tp; -{ - int ret; - - if (tp->reginfo.size == tp->region->hdr.size) - return (0); - - /* Detach/reattach the region. */ - if ((ret = __db_rreattach(&tp->reginfo, tp->region->hdr.size)) != 0) - return (ret); - - /* Reset region information. */ - tp->region = tp->reginfo.addr; - tp->mem = &tp->region[1]; - - return (0); -} - -static int -__txn_grow_region(tp) - DB_TXNMGR *tp; -{ - size_t incr, oldsize; - u_int32_t mutex_offset, oldmax; - u_int8_t *curaddr; - int ret; - - oldmax = tp->region->maxtxns; - incr = oldmax * sizeof(DB_TXN); - mutex_offset = tp->mutexp != NULL ? - (u_int8_t *)tp->mutexp - (u_int8_t *)tp->region : 0; - - oldsize = tp->reginfo.size; - if ((ret = __db_rgrow(&tp->reginfo, oldsize + incr)) != 0) - return (ret); - tp->region = tp->reginfo.addr; - - /* Throw the new space on the free list. */ - curaddr = (u_int8_t *)tp->region + oldsize; - tp->mem = &tp->region[1]; - tp->mutexp = mutex_offset != 0 ? - (db_mutex_t *)((u_int8_t *)tp->region + mutex_offset) : NULL; - - *((size_t *)curaddr) = incr - sizeof(size_t); - curaddr += sizeof(size_t); - __db_shalloc_free(tp->mem, curaddr); - - tp->region->maxtxns = 2 * oldmax; - - return (0); -} - -int -txn_stat(mgr, statp, db_malloc) - DB_TXNMGR *mgr; - DB_TXN_STAT **statp; - void *(*db_malloc) __P((size_t)); -{ - DB_TXN_STAT *stats; - TXN_DETAIL *txnp; - size_t nbytes; - u_int32_t nactive, ndx; - int ret; - - TXN_PANIC_CHECK(mgr); - - LOCK_TXNREGION(mgr); - nactive = mgr->region->nbegins - - mgr->region->naborts - mgr->region->ncommits; - UNLOCK_TXNREGION(mgr); - - /* - * Allocate a bunch of extra active structures to handle any - * that have been created since we unlocked the region. - */ - nbytes = sizeof(DB_TXN_STAT) + sizeof(DB_TXN_ACTIVE) * (nactive + 200); - if ((ret = __os_malloc(nbytes, db_malloc, &stats)) != 0) - return (ret); - - LOCK_TXNREGION(mgr); - stats->st_last_txnid = mgr->region->last_txnid; - stats->st_last_ckp = mgr->region->last_ckp; - stats->st_maxtxns = mgr->region->maxtxns; - stats->st_naborts = mgr->region->naborts; - stats->st_nbegins = mgr->region->nbegins; - stats->st_ncommits = mgr->region->ncommits; - stats->st_pending_ckp = mgr->region->pending_ckp; - stats->st_time_ckp = mgr->region->time_ckp; - stats->st_nactive = stats->st_nbegins - - stats->st_naborts - stats->st_ncommits; - if (stats->st_nactive > nactive + 200) - stats->st_nactive = nactive + 200; - stats->st_txnarray = (DB_TXN_ACTIVE *)&stats[1]; - - ndx = 0; - for (txnp = SH_TAILQ_FIRST(&mgr->region->active_txn, __txn_detail); - txnp != NULL; - txnp = SH_TAILQ_NEXT(txnp, links, __txn_detail)) { - stats->st_txnarray[ndx].txnid = txnp->txnid; - stats->st_txnarray[ndx].lsn = txnp->begin_lsn; - ndx++; - - if (ndx >= stats->st_nactive) - break; - } - - stats->st_region_wait = mgr->region->hdr.lock.mutex_set_wait; - stats->st_region_nowait = mgr->region->hdr.lock.mutex_set_nowait; - stats->st_refcnt = mgr->region->hdr.refcnt; - stats->st_regsize = mgr->region->hdr.size; - - UNLOCK_TXNREGION(mgr); - *statp = stats; - return (0); -} - -static void -__txn_freekids(txnp) - DB_TXN *txnp; -{ - DB_TXNMGR *mgr; - TXN_DETAIL *tp; - DB_TXN *kids; - - mgr = txnp->mgrp; - - for (kids = TAILQ_FIRST(&txnp->kids); - kids != NULL; - kids = TAILQ_FIRST(&txnp->kids)) { - /* Free any children of this transaction. */ - __txn_freekids(kids); - - /* Free the transaction detail in the region. */ - LOCK_TXNREGION(mgr); - tp = (TXN_DETAIL *)((u_int8_t *)mgr->region + kids->off); - SH_TAILQ_REMOVE(&mgr->region->active_txn, - tp, links, __txn_detail); - - __db_shalloc_free(mgr->mem, tp); - UNLOCK_TXNREGION(mgr); - - /* Now remove from its parent. */ - TAILQ_REMOVE(&txnp->kids, kids, klinks); - if (F_ISSET(txnp, TXN_MALLOC)) { - LOCK_TXNTHREAD(mgr); - TAILQ_REMOVE(&mgr->txn_chain, kids, links); - UNLOCK_TXNTHREAD(mgr); - __os_free(kids, sizeof(*kids)); - } - } -} - -/* - * __txn_is_ancestor -- - * Determine if a transaction is an ancestor of another transaction. - * This is used during lock promotion when we do not have the per-process - * data structures that link parents together. Instead, we'll have to - * follow the links in the transaction region. - * - * PUBLIC: int __txn_is_ancestor __P((DB_TXNMGR *, size_t, size_t)); - */ -int -__txn_is_ancestor(mgr, hold_off, req_off) - DB_TXNMGR *mgr; - size_t hold_off, req_off; -{ - TXN_DETAIL *hold_tp, *req_tp; - - hold_tp = (TXN_DETAIL *)((u_int8_t *)mgr->region + hold_off); - req_tp = (TXN_DETAIL *)((u_int8_t *)mgr->region + req_off); - - while (req_tp->parent != 0) { - req_tp = - (TXN_DETAIL *)((u_int8_t *)mgr->region + req_tp->parent); - if (req_tp->txnid == hold_tp->txnid) - return (1); - } - - return (0); -} diff --git a/db2/txn/txn.src b/db2/txn/txn.src deleted file mode 100644 index c9614f6..0000000 --- a/db2/txn/txn.src +++ /dev/null @@ -1,55 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - * - * @(#)txn.src 10.6 (Sleepycat) 1/3/99 - */ - -PREFIX txn - -/* - * This is the standard log operation for commit. - */ -BEGIN regop -ARG opcode u_int32_t lu -END - -/* - * This is the checkpoint record. It contains the lsn that the checkpoint - * guarantees and a pointer to the last checkpoint so we can walk backwards - * by checkpoint. - * - * ckp_lsn: - * The lsn in the log of the most recent point at which all begun - * transactions have been aborted. This is the point for which - * the checkpoint is relevant. - * last_ckp: - * The previous checkpoint. - */ -BEGIN ckp -POINTER ckp_lsn DB_LSN * lu -POINTER last_ckp DB_LSN * lu -END - -/* - * This is the standard log operation for prepare (since right now - * we only use prepare in an XA environment). - */ -BEGIN xa_regop -ARG opcode u_int32_t lu -DBT xid DBT s -ARG formatID int32_t ld -ARG gtrid u_int32_t u -ARG bqual u_int32_t u -POINTER begin_lsn DB_LSN * lu -END - -/* - * This is the log operation for a child commit. - */ -BEGIN child -ARG opcode u_int32_t lu -ARG parent u_int32_t lu -END diff --git a/db2/txn/txn_auto.c b/db2/txn/txn_auto.c deleted file mode 100644 index e6d431f..0000000 --- a/db2/txn/txn_auto.c +++ /dev/null @@ -1,621 +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 "txn.h" -#include "db_am.h" -/* - * PUBLIC: int __txn_regop_log - * PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - * PUBLIC: u_int32_t)); - */ -int __txn_regop_log(logp, txnid, ret_lsnp, flags, - opcode) - DB_LOG *logp; - DB_TXN *txnid; - DB_LSN *ret_lsnp; - u_int32_t flags; - u_int32_t opcode; -{ - DBT logrec; - DB_LSN *lsnp, null_lsn; - u_int32_t rectype, txn_num; - int ret; - u_int8_t *bp; - - rectype = DB_txn_regop; - 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); - 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); -#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 __txn_regop_print - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__txn_regop_print(notused1, dbtp, lsnp, notused2, notused3) - DB_LOG *notused1; - DBT *dbtp; - DB_LSN *lsnp; - int notused2; - void *notused3; -{ - __txn_regop_args *argp; - u_int32_t i; - u_int ch; - int ret; - - i = 0; - ch = 0; - notused1 = NULL; - notused2 = 0; - notused3 = NULL; - - if ((ret = __txn_regop_read(dbtp->data, &argp)) != 0) - return (ret); - printf("[%lu][%lu]txn_regop: 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("\n"); - __os_free(argp, 0); - return (0); -} - -/* - * PUBLIC: int __txn_regop_read __P((void *, __txn_regop_args **)); - */ -int -__txn_regop_read(recbuf, argpp) - void *recbuf; - __txn_regop_args **argpp; -{ - __txn_regop_args *argp; - u_int8_t *bp; - int ret; - - ret = __os_malloc(sizeof(__txn_regop_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); - *argpp = argp; - return (0); -} - -/* - * PUBLIC: int __txn_ckp_log - * PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - * PUBLIC: DB_LSN *, DB_LSN *)); - */ -int __txn_ckp_log(logp, txnid, ret_lsnp, flags, - ckp_lsn, last_ckp) - DB_LOG *logp; - DB_TXN *txnid; - DB_LSN *ret_lsnp; - u_int32_t flags; - DB_LSN * ckp_lsn; - DB_LSN * last_ckp; -{ - DBT logrec; - DB_LSN *lsnp, null_lsn; - u_int32_t rectype, txn_num; - int ret; - u_int8_t *bp; - - rectype = DB_txn_ckp; - 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(*ckp_lsn) - + sizeof(*last_ckp); - 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); - if (ckp_lsn != NULL) - memcpy(bp, ckp_lsn, sizeof(*ckp_lsn)); - else - memset(bp, 0, sizeof(*ckp_lsn)); - bp += sizeof(*ckp_lsn); - if (last_ckp != NULL) - memcpy(bp, last_ckp, sizeof(*last_ckp)); - else - memset(bp, 0, sizeof(*last_ckp)); - bp += sizeof(*last_ckp); -#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 __txn_ckp_print - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__txn_ckp_print(notused1, dbtp, lsnp, notused2, notused3) - DB_LOG *notused1; - DBT *dbtp; - DB_LSN *lsnp; - int notused2; - void *notused3; -{ - __txn_ckp_args *argp; - u_int32_t i; - u_int ch; - int ret; - - i = 0; - ch = 0; - notused1 = NULL; - notused2 = 0; - notused3 = NULL; - - if ((ret = __txn_ckp_read(dbtp->data, &argp)) != 0) - return (ret); - printf("[%lu][%lu]txn_ckp: 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("\tckp_lsn: [%lu][%lu]\n", - (u_long)argp->ckp_lsn.file, (u_long)argp->ckp_lsn.offset); - printf("\tlast_ckp: [%lu][%lu]\n", - (u_long)argp->last_ckp.file, (u_long)argp->last_ckp.offset); - printf("\n"); - __os_free(argp, 0); - return (0); -} - -/* - * PUBLIC: int __txn_ckp_read __P((void *, __txn_ckp_args **)); - */ -int -__txn_ckp_read(recbuf, argpp) - void *recbuf; - __txn_ckp_args **argpp; -{ - __txn_ckp_args *argp; - u_int8_t *bp; - int ret; - - ret = __os_malloc(sizeof(__txn_ckp_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->ckp_lsn, bp, sizeof(argp->ckp_lsn)); - bp += sizeof(argp->ckp_lsn); - memcpy(&argp->last_ckp, bp, sizeof(argp->last_ckp)); - bp += sizeof(argp->last_ckp); - *argpp = argp; - return (0); -} - -/* - * PUBLIC: int __txn_xa_regop_log - * PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - * PUBLIC: u_int32_t, const DBT *, int32_t, u_int32_t, - * PUBLIC: u_int32_t, DB_LSN *)); - */ -int __txn_xa_regop_log(logp, txnid, ret_lsnp, flags, - opcode, xid, formatID, gtrid, bqual, begin_lsn) - DB_LOG *logp; - DB_TXN *txnid; - DB_LSN *ret_lsnp; - u_int32_t flags; - u_int32_t opcode; - const DBT *xid; - int32_t formatID; - u_int32_t gtrid; - u_int32_t bqual; - DB_LSN * begin_lsn; -{ - 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_txn_xa_regop; - 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) + (xid == NULL ? 0 : xid->size) - + sizeof(formatID) - + sizeof(gtrid) - + sizeof(bqual) - + sizeof(*begin_lsn); - 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 (xid == NULL) { - zero = 0; - memcpy(bp, &zero, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - } else { - memcpy(bp, &xid->size, sizeof(xid->size)); - bp += sizeof(xid->size); - memcpy(bp, xid->data, xid->size); - bp += xid->size; - } - memcpy(bp, &formatID, sizeof(formatID)); - bp += sizeof(formatID); - memcpy(bp, >rid, sizeof(gtrid)); - bp += sizeof(gtrid); - memcpy(bp, &bqual, sizeof(bqual)); - bp += sizeof(bqual); - if (begin_lsn != NULL) - memcpy(bp, begin_lsn, sizeof(*begin_lsn)); - else - memset(bp, 0, sizeof(*begin_lsn)); - bp += sizeof(*begin_lsn); -#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 __txn_xa_regop_print - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__txn_xa_regop_print(notused1, dbtp, lsnp, notused2, notused3) - DB_LOG *notused1; - DBT *dbtp; - DB_LSN *lsnp; - int notused2; - void *notused3; -{ - __txn_xa_regop_args *argp; - u_int32_t i; - u_int ch; - int ret; - - i = 0; - ch = 0; - notused1 = NULL; - notused2 = 0; - notused3 = NULL; - - if ((ret = __txn_xa_regop_read(dbtp->data, &argp)) != 0) - return (ret); - printf("[%lu][%lu]txn_xa_regop: 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("\txid: "); - for (i = 0; i < argp->xid.size; i++) { - ch = ((u_int8_t *)argp->xid.data)[i]; - if (isprint(ch) || ch == 0xa) - putchar(ch); - else - printf("%#x ", ch); - } - printf("\n"); - printf("\tformatID: %ld\n", (long)argp->formatID); - printf("\tgtrid: %u\n", argp->gtrid); - printf("\tbqual: %u\n", argp->bqual); - printf("\tbegin_lsn: [%lu][%lu]\n", - (u_long)argp->begin_lsn.file, (u_long)argp->begin_lsn.offset); - printf("\n"); - __os_free(argp, 0); - return (0); -} - -/* - * PUBLIC: int __txn_xa_regop_read __P((void *, __txn_xa_regop_args **)); - */ -int -__txn_xa_regop_read(recbuf, argpp) - void *recbuf; - __txn_xa_regop_args **argpp; -{ - __txn_xa_regop_args *argp; - u_int8_t *bp; - int ret; - - ret = __os_malloc(sizeof(__txn_xa_regop_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->xid.size, bp, sizeof(u_int32_t)); - bp += sizeof(u_int32_t); - argp->xid.data = bp; - bp += argp->xid.size; - memcpy(&argp->formatID, bp, sizeof(argp->formatID)); - bp += sizeof(argp->formatID); - memcpy(&argp->gtrid, bp, sizeof(argp->gtrid)); - bp += sizeof(argp->gtrid); - memcpy(&argp->bqual, bp, sizeof(argp->bqual)); - bp += sizeof(argp->bqual); - memcpy(&argp->begin_lsn, bp, sizeof(argp->begin_lsn)); - bp += sizeof(argp->begin_lsn); - *argpp = argp; - return (0); -} - -/* - * PUBLIC: int __txn_child_log - * PUBLIC: __P((DB_LOG *, DB_TXN *, DB_LSN *, u_int32_t, - * PUBLIC: u_int32_t, u_int32_t)); - */ -int __txn_child_log(logp, txnid, ret_lsnp, flags, - opcode, parent) - DB_LOG *logp; - DB_TXN *txnid; - DB_LSN *ret_lsnp; - u_int32_t flags; - u_int32_t opcode; - u_int32_t parent; -{ - DBT logrec; - DB_LSN *lsnp, null_lsn; - u_int32_t rectype, txn_num; - int ret; - u_int8_t *bp; - - rectype = DB_txn_child; - 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(parent); - 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); - memcpy(bp, &parent, sizeof(parent)); - bp += sizeof(parent); -#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 __txn_child_print - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__txn_child_print(notused1, dbtp, lsnp, notused2, notused3) - DB_LOG *notused1; - DBT *dbtp; - DB_LSN *lsnp; - int notused2; - void *notused3; -{ - __txn_child_args *argp; - u_int32_t i; - u_int ch; - int ret; - - i = 0; - ch = 0; - notused1 = NULL; - notused2 = 0; - notused3 = NULL; - - if ((ret = __txn_child_read(dbtp->data, &argp)) != 0) - return (ret); - printf("[%lu][%lu]txn_child: 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("\tparent: %lu\n", (u_long)argp->parent); - printf("\n"); - __os_free(argp, 0); - return (0); -} - -/* - * PUBLIC: int __txn_child_read __P((void *, __txn_child_args **)); - */ -int -__txn_child_read(recbuf, argpp) - void *recbuf; - __txn_child_args **argpp; -{ - __txn_child_args *argp; - u_int8_t *bp; - int ret; - - ret = __os_malloc(sizeof(__txn_child_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->parent, bp, sizeof(argp->parent)); - bp += sizeof(argp->parent); - *argpp = argp; - return (0); -} - -/* - * PUBLIC: int __txn_init_print __P((DB_ENV *)); - */ -int -__txn_init_print(dbenv) - DB_ENV *dbenv; -{ - int ret; - - if ((ret = __db_add_recovery(dbenv, - __txn_regop_print, DB_txn_regop)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __txn_ckp_print, DB_txn_ckp)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __txn_xa_regop_print, DB_txn_xa_regop)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __txn_child_print, DB_txn_child)) != 0) - return (ret); - return (0); -} - -/* - * PUBLIC: int __txn_init_recover __P((DB_ENV *)); - */ -int -__txn_init_recover(dbenv) - DB_ENV *dbenv; -{ - int ret; - - if ((ret = __db_add_recovery(dbenv, - __txn_regop_recover, DB_txn_regop)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __txn_ckp_recover, DB_txn_ckp)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __txn_xa_regop_recover, DB_txn_xa_regop)) != 0) - return (ret); - if ((ret = __db_add_recovery(dbenv, - __txn_child_recover, DB_txn_child)) != 0) - return (ret); - return (0); -} - diff --git a/db2/txn/txn_rec.c b/db2/txn/txn_rec.c deleted file mode 100644 index f21a0f9..0000000 --- a/db2/txn/txn_rec.c +++ /dev/null @@ -1,296 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * Sleepycat Software. All rights reserved. - */ -/* - * Copyright (c) 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[] = "@(#)txn_rec.c 10.15 (Sleepycat) 1/3/99"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#endif - -#include "db_int.h" -#include "db_page.h" -#include "shqueue.h" -#include "txn.h" -#include "db_am.h" -#include "log.h" -#include "common_ext.h" - -static int __txn_restore_txn __P((DB_ENV *, DB_LSN *, __txn_xa_regop_args *)); - -#define IS_XA_TXN(R) (R->xid.size != 0) - -/* - * PUBLIC: int __txn_regop_recover - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - * - * These records are only ever written for commits. - */ -int -__txn_regop_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __txn_regop_args *argp; - int ret; - -#ifdef DEBUG_RECOVER - (void)__txn_regop_print(logp, dbtp, lsnp, redo, info); -#endif - COMPQUIET(redo, 0); - COMPQUIET(logp, NULL); - - if ((ret = __txn_regop_read(dbtp->data, &argp)) != 0) - return (ret); - - if (argp->opcode != TXN_COMMIT) - ret = EINVAL; - else - if (__db_txnlist_find(info, argp->txnid->txnid) == DB_NOTFOUND) - ret = __db_txnlist_add(info, argp->txnid->txnid); - - if (ret == 0) - *lsnp = argp->prev_lsn; - __os_free(argp, 0); - - return (ret); -} - -/* - * PUBLIC: int __txn_xa_regop_recover - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - * - * These records are only ever written for prepares. - */ -int -__txn_xa_regop_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __txn_xa_regop_args *argp; - int ret; - -#ifdef DEBUG_RECOVER - (void)__txn_xa_regop_print(logp, dbtp, lsnp, redo, info); -#endif - COMPQUIET(redo, 0); - COMPQUIET(logp, NULL); - - if ((ret = __txn_xa_regop_read(dbtp->data, &argp)) != 0) - return (ret); - - if (argp->opcode != TXN_PREPARE) - ret = EINVAL; - else { - /* - * Whether we are in XA or not, we need to call - * __db_txnlist_find so that we update the maxid. - * If this is an XA transaction, then we treat - * prepares like commits so that we roll forward to - * a point where we can handle commit/abort calls - * from the TMS. If this isn't XA, then a prepare - * is treated like a No-op; we only care about the - * commit. - */ - ret = __db_txnlist_find(info, argp->txnid->txnid); - if (IS_XA_TXN(argp) && ret == DB_NOTFOUND) { - /* - * This is an XA prepared, but not yet committed - * transaction. We need to add it to the - * transaction list, so that it gets rolled - * forward. We also have to add it to the region's - * internal state so it can be properly aborted - * or recovered. - */ - ret = __db_txnlist_add(info, argp->txnid->txnid); - if (ret == 0) - ret = __txn_restore_txn(logp->dbenv, - lsnp, argp); - } - } - - if (ret == 0) - *lsnp = argp->prev_lsn; - __os_free(argp, 0); - - return (ret); -} - -/* - * PUBLIC: int __txn_ckp_recover __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__txn_ckp_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __txn_ckp_args *argp; - int ret; - -#ifdef DEBUG_RECOVER - __txn_ckp_print(logp, dbtp, lsnp, redo, info); -#endif - COMPQUIET(logp, NULL); - - if ((ret = __txn_ckp_read(dbtp->data, &argp)) != 0) - return (ret); - - /* - * Check for 'restart' checkpoint record. This occurs when the - * checkpoint lsn is equal to the lsn of the checkpoint record - * and means that we could set the transaction ID back to 1, so - * that we don't exhaust the transaction ID name space. - */ - if (argp->ckp_lsn.file == lsnp->file && - argp->ckp_lsn.offset == lsnp->offset) - __db_txnlist_gen(info, redo ? -1 : 1); - - *lsnp = argp->last_ckp; - __os_free(argp, 0); - return (DB_TXN_CKP); -} - -/* - * __txn_child_recover - * Recover a commit record for a child transaction. - * - * PUBLIC: int __txn_child_recover - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__txn_child_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __txn_child_args *argp; - int ret; - -#ifdef DEBUG_RECOVER - (void)__txn_child_print(logp, dbtp, lsnp, redo, info); -#endif - COMPQUIET(redo, 0); - COMPQUIET(logp, NULL); - - if ((ret = __txn_child_read(dbtp->data, &argp)) != 0) - return (ret); - - /* - * We count the child as committed only if its parent committed. - * So, if we are not yet in the transaction list, but our parent - * is, then we should go ahead and commit. - */ - if (argp->opcode != TXN_COMMIT) - ret = EINVAL; - else - if (__db_txnlist_find(info, argp->parent) == 0 && - __db_txnlist_find(info, argp->txnid->txnid) == DB_NOTFOUND) - ret = __db_txnlist_add(info, argp->txnid->txnid); - - if (ret == 0) - *lsnp = argp->prev_lsn; - __os_free(argp, 0); - - return (ret); -} - -/* - * __txn_restore_txn -- - * Using only during XA recovery. If we find any transactions that are - * prepared, but not yet committed, then we need to restore the transaction's - * state into the shared region, because the TM is going to issue a txn_abort - * or txn_commit and we need to respond correctly. - * - * lsnp is the LSN of the returned LSN - * argp is the perpare record (in an appropriate structure) - */ -static int -__txn_restore_txn(dbenv, lsnp, argp) - DB_ENV *dbenv; - DB_LSN *lsnp; - __txn_xa_regop_args *argp; -{ - DB_TXNMGR *mgr; - TXN_DETAIL *td; - int ret; - - if (argp->xid.size == 0) - return(0); - - mgr = dbenv->tx_info; - LOCK_TXNREGION(mgr); - - /* Allocate a new transaction detail structure. */ - if ((ret = __db_shalloc(mgr->mem, sizeof(TXN_DETAIL), 0, &td)) != 0) - return (ret); - - /* Place transaction on active transaction list. */ - SH_TAILQ_INSERT_HEAD(&mgr->region->active_txn, td, links, __txn_detail); - - td->txnid = argp->txnid->txnid; - td->begin_lsn = argp->begin_lsn; - td->last_lsn = *lsnp; - td->last_lock = 0; - td->parent = 0; - td->status = TXN_PREPARED; - td->xa_status = TXN_XA_PREPARED; - memcpy(td->xid, argp->xid.data, argp->xid.size); - td->bqual = argp->bqual; - td->gtrid = argp->gtrid; - td->format = argp->formatID; - - UNLOCK_TXNREGION(mgr); - return (0); -} diff --git a/db2/xa/xa.c b/db2/xa/xa.c deleted file mode 100644 index 94a96e7..0000000 --- a/db2/xa/xa.c +++ /dev/null @@ -1,682 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1998 - * Sleepycat Software. All rights reserved. - */ - -/* XXX Remove the global transaction and hang it off the environment. */ -#include "config.h" - -#ifndef lint -static const char sccsid[] = "@(#)xa.c 10.4 (Sleepycat) 10/11/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#endif - -#include "db_int.h" -#include "db_page.h" -#include "shqueue.h" -#include "log.h" -#include "txn.h" -#include "db_auto.h" -#include "db_ext.h" -#include "db_dispatch.h" - -static int __db_xa_close __P((char *, int, long)); -static int __db_xa_commit __P((XID *, int, long)); -static int __db_xa_complete __P((int *, int *, int, long)); -static int __db_xa_end __P((XID *, int, long)); -static int __db_xa_forget __P((XID *, int, long)); -static int __db_xa_open __P((char *, int, long)); -static int __db_xa_prepare __P((XID *, int, long)); -static int __db_xa_recover __P((XID *, long, int, long)); -static int __db_xa_rollback __P((XID *, int, long)); -static int __db_xa_start __P((XID *, int, long)); -static void __xa_txn_end __P((DB_ENV *)); -static void __xa_txn_init __P((DB_ENV *, TXN_DETAIL *, size_t)); - -/* - * Possible flag values: - * Dynamic registration 0 => no dynamic registration - * TMREGISTER => dynamic registration - * Asynchronous operation 0 => no support for asynchrony - * TMUSEASYNC => async support - * Migration support 0 => migration of transactions across - * threads is possible - * TMNOMIGRATE => no migration across threads - */ -const struct xa_switch_t db_xa_switch = { - "Berkeley DB", /* name[RMNAMESZ] */ - TMNOMIGRATE, /* flags */ - 0, /* version */ - __db_xa_open, /* xa_open_entry */ - __db_xa_close, /* xa_close_entry */ - __db_xa_start, /* xa_start_entry */ - __db_xa_end, /* xa_end_entry */ - __db_xa_rollback, /* xa_rollback_entry */ - __db_xa_prepare, /* xa_prepare_entry */ - __db_xa_commit, /* xa_commit_entry */ - __db_xa_recover, /* xa_recover_entry */ - __db_xa_forget, /* xa_forget_entry */ - __db_xa_complete /* xa_complete_entry */ -}; - -/* - * __db_xa_open -- - * The open call in the XA protocol. The rmid field is an id number - * that the TM assigned us and will pass us on every xa call. We need to - * map that rmid number into a dbenv structure that we create during - * initialization. Since this id number is thread specific, we do not - * need to store it in shared memory. The file xa_map.c implements all - * such xa->db mappings. - * The xa_info field is instance specific information. We require - * that the value of DB_HOME be passed in xa_info. Since xa_info is the - * only thing that we get to pass to db_appinit, any config information - * will have to be done via a config file instead of via the db_appinit - * call. - */ -static int -__db_xa_open(xa_info, rmid, flags) - char *xa_info; - int rmid; - long flags; -{ - DB_ENV *env; - - if (LF_ISSET(TMASYNC)) - return (XAER_ASYNC); - if (flags != TMNOFLAGS) - return (XAER_INVAL); - - /* Verify if we already have this environment open. */ - if (__db_rmid_to_env(rmid, &env, 0) == 0) - return (XA_OK); - - /* - * Since we cannot tell whether the environment is OK or not, - * we can't actually do the db_appinit in xa_open. Instead, - * we save the mapping between the rmid and the xa_info. If - * we next get a call to __xa_recover, we do the db_appinit - * with DB_RECOVER set. If we get any other call, then we - * do the db_appinit. - */ - return (__db_map_rmid_name(rmid, xa_info)); -} - -/* - * __db_xa_close -- - * The close call of the XA protocol. The only trickiness here - * is that if there are any active transactions, we must fail. It is - * *not* an error to call close on an environment that has already been - * closed (I am interpreting that to mean it's OK to call close on an - * environment that has never been opened). - */ -static int -__db_xa_close(xa_info, rmid, flags) - char *xa_info; - int rmid; - long flags; -{ - DB_ENV *env; - int ret, t_ret; - - COMPQUIET(xa_info, NULL); - - if (LF_ISSET(TMASYNC)) - return (XAER_ASYNC); - if (flags != TMNOFLAGS) - return (XAER_INVAL); - - /* If the environment is closed, then we're done. */ - if (__db_rmid_to_env(rmid, &env, 0) != 0) - return (XA_OK); - - /* Check if there are any pending transactions. */ - if (env->xa_txn != NULL && env->xa_txn->txnid != TXN_INVALID) - return (XAER_PROTO); - - /* Now, destroy the mapping and close the environment. */ - ret = __db_unmap_rmid(rmid); - if ((t_ret = db_appexit(env)) != 0 && ret == 0) - ret = t_ret; - - __os_free(env, sizeof(DB_ENV)); - - return (ret == 0 ? XA_OK : XAER_RMERR); -} - -/* - * __db_xa_start -- - * Begin a transaction for the current resource manager. - */ -static int -__db_xa_start(xid, rmid, flags) - XID *xid; - int rmid; - long flags; -{ - DB_ENV *env; - TXN_DETAIL *td; - size_t off; - int is_known; - -#define OK_FLAGS (TMJOIN | TMRESUME | TMNOWAIT | TMASYNC | TMNOFLAGS) - if (LF_ISSET(~OK_FLAGS)) - return (XAER_INVAL); - - if (LF_ISSET(TMJOIN) && LF_ISSET(TMRESUME)) - return (XAER_INVAL); - - if (LF_ISSET(TMASYNC)) - return (XAER_ASYNC); - - if (__db_rmid_to_env(rmid, &env, 1) != 0) - return (XAER_PROTO); - - is_known = __db_xid_to_txn(env, xid, &off) == 0; - - if (is_known && !LF_ISSET(TMRESUME) && !LF_ISSET(TMJOIN)) - return (XAER_DUPID); - - if (!is_known && LF_ISSET(TMRESUME | TMJOIN)) - return (XAER_NOTA); - - /* - * This can't block, so we can ignore TMNOWAIT. - * - * Other error conditions: RMERR, RMFAIL, OUTSIDE, PROTO, RB* - */ - if (is_known) { - td = (TXN_DETAIL *)((u_int8_t *)env->tx_info->region + off); - if (td->xa_status == TXN_XA_SUSPENDED && !LF_SET(TMRESUME)) - return (XAER_PROTO); - if (td->xa_status == TXN_XA_DEADLOCKED) - return (XA_RBDEADLOCK); - if (td->xa_status == TXN_XA_ABORTED) - return (XA_RBOTHER); - - /* Now, fill in the global transaction structure. */ - __xa_txn_init(env, td, off); - td->xa_status = TXN_XA_STARTED; - } else { - if (__txn_xa_begin(env, env->xa_txn) != 0) - return (XAER_RMERR); - (void)__db_map_xid(env, xid, env->xa_txn->off); - td = (TXN_DETAIL *) - ((u_int8_t *)env->tx_info->region + env->xa_txn->off); - td->xa_status = TXN_XA_STARTED; - } - return (XA_OK); -} - -/* - * __db_xa_end -- - * Disassociate the current transaction from the current process. - */ -static int -__db_xa_end(xid, rmid, flags) - XID *xid; - int rmid; - long flags; -{ - DB_ENV *env; - DB_TXN *txn; - TXN_DETAIL *td; - size_t off; - - if (flags != TMNOFLAGS && !LF_ISSET(TMSUSPEND | TMSUCCESS | TMFAIL)) - return (XAER_INVAL); - - if (__db_rmid_to_env(rmid, &env, 0) != 0) - return (XAER_PROTO); - - if (__db_xid_to_txn(env, xid, &off) != 0) - return (XAER_NOTA); - - txn = env->xa_txn; - if (off != txn->off) - return (XAER_PROTO); - - td = (TXN_DETAIL *)((u_int8_t *)env->tx_info->region + off); - if (td->xa_status == TXN_XA_DEADLOCKED) - return (XA_RBDEADLOCK); - - if (td->status == TXN_ABORTED) - return (XA_RBOTHER); - - if (td->xa_status != TXN_XA_STARTED) - return (XAER_PROTO); - - /* Update the shared memory last_lsn field */ - td->last_lsn = txn->last_lsn; - - /* - * If we ever support XA migration, we cannot keep SUSPEND/END - * status in the shared region; it would have to be process local. - */ - if (LF_ISSET(TMSUSPEND)) - td->xa_status = TXN_XA_SUSPENDED; - else - td->xa_status = TXN_XA_ENDED; - - txn->txnid = TXN_INVALID; - return (XA_OK); -} - -/* - * __db_xa_prepare -- - * Sync the log to disk so we can guarantee recoverability. - */ -static int -__db_xa_prepare(xid, rmid, flags) - XID *xid; - int rmid; - long flags; -{ - DB_ENV *env; - TXN_DETAIL *td; - size_t off; - - if (LF_ISSET(TMASYNC)) - return (XAER_ASYNC); - if (flags != TMNOFLAGS) - return (XAER_INVAL); - - /* - * We need to know if we've ever called prepare on this. - * As part of the prepare, we set the xa_status field to - * reflect that fact that prepare has been called, and if - * it's ever called again, it's an error. - */ - if (__db_rmid_to_env(rmid, &env, 1) != 0) - return (XAER_PROTO); - - if (__db_xid_to_txn(env, xid, &off) != 0) - return (XAER_NOTA); - - td = (TXN_DETAIL *)((u_int8_t *)env->tx_info->region + off); - - if (td->xa_status == TXN_XA_DEADLOCKED) - return (XA_RBDEADLOCK); - - if (td->xa_status != TXN_XA_ENDED && td->xa_status != TXN_XA_SUSPENDED) - return (XAER_PROTO); - - /* Now, fill in the global transaction structure. */ - __xa_txn_init(env, td, off); - - if (txn_prepare(env->xa_txn) != 0) - return (XAER_RMERR); - - td->xa_status = TXN_XA_PREPARED; - - /* No fatal value that would require an XAER_RMFAIL. */ - __xa_txn_end(env); - return (XA_OK); -} - -/* - * __db_xa_commit -- - * Commit the transaction - */ -static int -__db_xa_commit(xid, rmid, flags) - XID *xid; - int rmid; - long flags; -{ - DB_ENV *env; - TXN_DETAIL *td; - size_t off; - - if (LF_ISSET(TMASYNC)) - return (XAER_ASYNC); -#undef OK_FLAGS -#define OK_FLAGS (TMNOFLAGS | TMNOWAIT | TMONEPHASE) - if (LF_ISSET(~OK_FLAGS)) - return (XAER_INVAL); - - /* - * We need to know if we've ever called prepare on this. - * We can verify this by examining the xa_status field. - */ - if (__db_rmid_to_env(rmid, &env, 1) != 0) - return (XAER_PROTO); - - if (__db_xid_to_txn(env, xid, &off) != 0) - return (XAER_NOTA); - - td = (TXN_DETAIL *)((u_int8_t *)env->tx_info->region + off); - - if (td->xa_status == TXN_XA_DEADLOCKED) - return (XA_RBDEADLOCK); - - if (td->xa_status == TXN_XA_ABORTED) - return (XA_RBOTHER); - - if (LF_SET(TMONEPHASE) && - td->xa_status != TXN_XA_ENDED && td->xa_status != TXN_XA_SUSPENDED) - return (XAER_PROTO); - - if (!LF_SET(TMONEPHASE) && td->xa_status != TXN_XA_PREPARED) - return (XAER_PROTO); - - /* Now, fill in the global transaction structure. */ - __xa_txn_init(env, td, off); - - if (txn_commit(env->xa_txn) != 0) - return (XAER_RMERR); - - /* No fatal value that would require an XAER_RMFAIL. */ - __xa_txn_end(env); - return (XA_OK); -} - -/* - * __db_xa_recover -- - * Returns a list of prepared and heuristically completed transactions. - * - * The return value is the number of xids placed into the xid array (less - * than or equal to the count parameter). The flags are going to indicate - * whether we are starting a scan or continuing one. - */ -static int -__db_xa_recover(xids, count, rmid, flags) - XID *xids; - long count, flags; - int rmid; -{ - __txn_xa_regop_args *argp; - DBT data; - DB_ENV *env; - DB_LOG *log; - XID *xidp; - char *dbhome; - int err, ret; - u_int32_t rectype, txnid; - - ret = 0; - xidp = xids; - - - /* - * If we are starting a scan, then we need to open the environment - * and run recovery. This recovery puts us in a state where we can - * either commit or abort any transactions that were prepared but not - * yet committed. Once we've done that, we need to figure out where - * to begin checking for such transactions. If we are not starting - * a scan, then the environment had better have already been recovered - * and we'll start from * wherever the log cursor is. Since XA apps - * cannot be threaded, we don't have to worry about someone else - * having moved it. - */ - if (LF_ISSET(TMSTARTRSCAN)) { - /* If the environment is open, we have a problem. */ - if (__db_rmid_to_env(rmid, &env, 0) == XA_OK) - return (XAER_PROTO); - - if ((ret = __os_calloc(1, sizeof(DB_ENV), &env)) != 0) - return (XAER_RMERR); - - if (__db_rmid_to_name(rmid, &dbhome) != 0) - goto err1; - -#undef XA_FLAGS -#define XA_FLAGS DB_RECOVER | \ - DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN - if ((ret = db_appinit(dbhome, NULL, env, XA_FLAGS)) != 0) - goto err1; - - if (__db_map_rmid(rmid, env) != 0) - goto err2; - - /* Now figure out from where to begin scan. */ - log = env->lg_info; - if ((err = __log_findckp(log, &log->xa_first)) == DB_NOTFOUND) { - /* - * If there were no log files, then we have no - * transactions to return, so we simply return 0. - */ - return (0); - } - if ((err = __db_txnlist_init(&log->xa_info)) != 0) - goto err3; - } else { - /* We had better already know about this rmid. */ - if (__db_rmid_to_env(rmid, &env, 0) != 0) - return (XAER_PROTO); - /* - * If we are not starting a scan, the log cursor had - * better be set. - */ - log = env->lg_info; - if (IS_ZERO_LSN(log->xa_lsn)) - return (XAER_PROTO); - } - - /* - * At this point log->xa_first contains the point in the log - * to which we need to roll back. If we are starting a scan, - * we'll start at the last record; if we're continuing a scan, - * we'll have to start at log->xa_lsn. - */ - - memset(&data, 0, sizeof(data)); - for (err = log_get(log, &log->xa_lsn, &data, - LF_ISSET(TMSTARTRSCAN) ? DB_LAST : DB_SET); - err == 0 && log_compare(&log->xa_lsn, &log->xa_first) > 0; - err = log_get(log, &log->xa_lsn, &data, DB_PREV)) { - memcpy(&rectype, data.data, sizeof(rectype)); - - /* - * The only record type we care about is an DB_txn_xa_regop. - * If it's a commit, we have to add it to a txnlist. If it's - * a prepare, and we don't have a commit, then we return it. - * We are redoing some of what's in the xa_regop_recovery - * code, but we have to do it here so we can get at the xid - * in the record. - */ - if (rectype != DB_txn_xa_regop && rectype != DB_txn_regop) - continue; - - memcpy(&txnid, (u_int8_t *)data.data + sizeof(rectype), - sizeof(txnid)); - err = __db_txnlist_find(log->xa_info, txnid); - switch (rectype) { - case DB_txn_regop: - if (err == DB_NOTFOUND) - __db_txnlist_add(log->xa_info, txnid); - err = 0; - break; - case DB_txn_xa_regop: - /* - * This transaction is commited, so we needn't read - * the record and do anything. - */ - if (err == 0) - break; - if ((err = - __txn_xa_regop_read(data.data, &argp)) != 0) { - ret = XAER_RMERR; - goto out; - } - - xidp->formatID = argp->formatID; - xidp->gtrid_length = argp->gtrid; - xidp->bqual_length = argp->bqual; - memcpy(xidp->data, argp->xid.data, argp->xid.size); - ret++; - xidp++; - __os_free(argp, sizeof(*argp)); - if (ret == count) - goto done; - break; - } - } - - if (err != 0 && err != DB_NOTFOUND) - goto out; - -done: if (LF_ISSET(TMENDRSCAN)) { - ZERO_LSN(log->xa_lsn); - ZERO_LSN(log->xa_first); - -out: __db_txnlist_end(log->xa_info); - log->xa_info = NULL; - } - return (ret); - -err3: (void)__db_unmap_rmid(rmid); -err2: (void)db_appexit(env); -err1: __os_free(env, sizeof(DB_ENV)); - return (XAER_RMERR); -} - -/* - * __db_xa_rollback - * Abort an XA transaction. - */ -static int -__db_xa_rollback(xid, rmid, flags) - XID *xid; - int rmid; - long flags; -{ - DB_ENV *env; - TXN_DETAIL *td; - size_t off; - - if (LF_ISSET(TMASYNC)) - return (XAER_ASYNC); - if (flags != TMNOFLAGS) - return (XAER_INVAL); - - if (__db_rmid_to_env(rmid, &env, 1) != 0) - return (XAER_PROTO); - - if (__db_xid_to_txn(env, xid, &off) != 0) - return (XAER_NOTA); - - td = (TXN_DETAIL *)((u_int8_t *)env->tx_info->region + off); - - if (td->xa_status == TXN_XA_DEADLOCKED) - return (XA_RBDEADLOCK); - - if (td->xa_status == TXN_XA_ABORTED) - return (XA_RBOTHER); - - if (LF_SET(TMONEPHASE) && - td->xa_status != TXN_XA_ENDED && td->xa_status != TXN_XA_SUSPENDED) - return (XAER_PROTO); - - if (!LF_SET(TMONEPHASE) && td->xa_status != TXN_XA_PREPARED) - return (XAER_PROTO); - - /* Now, fill in the global transaction structure. */ - __xa_txn_init(env, td, off); - if (txn_abort(env->xa_txn) != 0) - return (XAER_RMERR); - - /* No fatal value that would require an XAER_RMFAIL. */ - __xa_txn_end(env); - return (XA_OK); -} - -/* - * __db_xa_forget -- - * Forget about an XID for a transaction that was heuristically - * completed. Since we do not heuristically complete anything, I - * don't think we have to do anything here, but we should make sure - * that we reclaim the slots in the txnid table. - */ -static int -__db_xa_forget(xid, rmid, flags) - XID *xid; - int rmid; - long flags; -{ - DB_ENV *env; - size_t off; - - if (LF_ISSET(TMASYNC)) - return (XAER_ASYNC); - if (flags != TMNOFLAGS) - return (XAER_INVAL); - - if (__db_rmid_to_env(rmid, &env, 1) != 0) - return (XAER_PROTO); - - /* - * If mapping is gone, then we're done. - */ - if (__db_xid_to_txn(env, xid, &off) != 0) - return (XA_OK); - - __db_unmap_xid(env, xid, off); - - /* No fatal value that would require an XAER_RMFAIL. */ - return (XA_OK); -} - -/* - * __db_xa_complete -- - * Used to wait for asynchronous operations to complete. Since we're - * not doing asynch, this is an invalid operation. - */ -static int -__db_xa_complete(handle, retval, rmid, flags) - int *handle, *retval, rmid; - long flags; -{ - COMPQUIET(handle, NULL); - COMPQUIET(retval, NULL); - COMPQUIET(rmid, 0); - COMPQUIET(flags, 0); - - return (XAER_INVAL); -} - -/* - * __xa_txn_init -- - * Fill in the fields of the local transaction structure given - * the detail transaction structure. - */ -static void -__xa_txn_init(env, td, off) - DB_ENV *env; - TXN_DETAIL *td; - size_t off; -{ - DB_TXN *txn; - - txn = env->xa_txn; - txn->mgrp = env->tx_info; - txn->parent = NULL; - txn->last_lsn = td->last_lsn; - txn->txnid = td->txnid; - txn->off = off; - txn->flags = 0; -} - -/* - * __xa_txn_end -- - * Invalidate a transaction structure that was generated by xa_txn_init. - */ -static void -__xa_txn_end(env) - DB_ENV *env; -{ - DB_TXN *txn; - - txn = env->xa_txn; - if (txn != NULL) - txn->txnid = TXN_INVALID; -} - diff --git a/db2/xa/xa_db.c b/db2/xa/xa_db.c deleted file mode 100644 index 4aaaeff..0000000 --- a/db2/xa/xa_db.c +++ /dev/null @@ -1,308 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1998 - * Sleepycat Software. All rights reserved. - */ - -#include "config.h" - -#ifndef lint -static const char sccsid[] = "@(#)xa_db.c 10.6 (Sleepycat) 12/19/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <stdio.h> -#include <string.h> -#endif - -#undef stat - -#include "db_int.h" -#include "db_page.h" -#include "xa.h" -#include "xa_ext.h" -#include "db_am.h" -#include "db_ext.h" -#include "common_ext.h" - -static int __xa_c_close __P((DBC *)); -static int __xa_c_del __P((DBC *, u_int32_t)); -static int __xa_c_get __P((DBC *, DBT *, DBT *, u_int32_t)); -static int __xa_c_put __P((DBC *, DBT *, DBT *, u_int32_t)); -static int __xa_close __P((DB *, u_int32_t)); -static int __xa_cursor __P((DB *, DB_TXN *, DBC **, u_int32_t)); -static int __xa_del __P((DB *, DB_TXN *, DBT *, u_int32_t)); -static int __xa_fd __P((DB *, int *)); -static int __xa_get __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t)); -static int __xa_put __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t)); -static int __xa_stat __P((DB *, void *, void *(*)(size_t), u_int32_t)); -static int __xa_sync __P((DB *, u_int32_t)); - -int -db_xa_open(fname, type, flags, mode, dbinfo, dbpp) - const char *fname; - DBTYPE type; - u_int32_t flags; - int mode; - DB_INFO *dbinfo; - DB **dbpp; -{ - DB *dbp, *real_dbp; - DB_ENV *dbenv; - struct __rmname *rp; - int ret; - - /* - * First try to open up the underlying DB. - * - * !!! - * The dbenv argument is taken from the global list of environments. - * When the transaction manager called xa_start() (__db_xa_start()), - * the "current" DB environment was moved to the start of the list. - * However, if we were called in a tpsvrinit function (which is - * entirely plausible), then it's possible that xa_open was called - * (which simply recorded the name of the environment to open) and - * this is the next call into DB. In that case, we still have to - * open the environment. - * - * The way that we know that xa_open and nothing else was called - * is because the nameq is not NULL. - */ - if ((rp = TAILQ_FIRST(&DB_GLOBAL(db_nameq))) != NULL && - (ret = __db_rmid_to_env(rp->rmid, &dbenv, 1)) != 0) - return (ret); - - dbenv = TAILQ_FIRST(&DB_GLOBAL(db_envq)); - if ((ret = db_open(fname, - type, flags, mode, dbenv, dbinfo, &real_dbp)) != 0) - return (ret); - - /* - * Allocate our own DB handle, and copy the exported fields and - * function pointers into it. The internal pointer references - * the real underlying DB handle. - */ - if ((ret = __os_calloc(1, sizeof(DB), &dbp)) != 0) { - (void)real_dbp->close(real_dbp, 0); - return (ret); - } - dbp->type = real_dbp->type; - dbp->byteswapped = real_dbp->byteswapped; - dbp->dbenv = dbenv; - dbp->internal = real_dbp; - TAILQ_INIT(&dbp->active_queue); - TAILQ_INIT(&dbp->free_queue); - dbp->close = __xa_close; - dbp->cursor = __xa_cursor; - dbp->del = __xa_del; - dbp->fd = __xa_fd; - dbp->get = __xa_get; - dbp->join = real_dbp->join; - dbp->put = __xa_put; - dbp->stat = __xa_stat; - dbp->sync = __xa_sync; - - *dbpp = dbp; - return (0); -} - -static int -__xa_close(dbp, flags) - DB *dbp; - u_int32_t flags; -{ - DB *real_dbp; - DBC *dbc; - int ret; - - /* Close any associated cursors. */ - while ((dbc = TAILQ_FIRST(&dbp->active_queue)) != NULL) - (void)dbc->c_close(dbc); - - /* Close the DB handle. */ - real_dbp = (DB *)dbp->internal; - ret = real_dbp->close(real_dbp, flags); - - __os_free(dbp, sizeof(DB)); - return (ret); -} - -static int -__xa_cursor(dbp, txn, dbcp, flags) - DB *dbp; - DB_TXN *txn; - DBC **dbcp; - u_int32_t flags; -{ - DB *real_dbp; - DBC *real_dbc, *dbc; - int ret; - - real_dbp = (DB *)dbp->internal; - txn = dbp->dbenv->xa_txn; - - if ((ret = real_dbp->cursor(real_dbp, txn, &real_dbc, flags)) != 0) - return (ret); - - /* - * Allocate our own DBC handle, and copy the exported fields and - * function pointers into it. The internal pointer references - * the real underlying DBC handle. - */ - if ((ret = __os_calloc(1, sizeof(DBC), &dbc)) != 0) { - (void)real_dbc->c_close(real_dbc); - return (ret); - } - dbc->dbp = dbp; - dbc->c_close = __xa_c_close; - dbc->c_del = __xa_c_del; - dbc->c_get = __xa_c_get; - dbc->c_put = __xa_c_put; - dbc->internal = real_dbc; - TAILQ_INSERT_TAIL(&dbp->active_queue, dbc, links); - - *dbcp = dbc; - return (0); -} - -static int -__xa_fd(dbp, fdp) - DB *dbp; - int *fdp; -{ - DB *real_dbp; - - COMPQUIET(fdp, NULL); - - real_dbp = (DB *)dbp->internal; - return (__db_eopnotsup(real_dbp->dbenv)); -} - -static int -__xa_del(dbp, txn, key, flags) - DB *dbp; - DB_TXN *txn; - DBT *key; - u_int32_t flags; -{ - DB *real_dbp; - - real_dbp = (DB *)dbp->internal; - txn = dbp->dbenv->xa_txn; - - return (real_dbp->del(real_dbp, txn, key, flags)); -} - -static int -__xa_get(dbp, txn, key, data, flags) - DB *dbp; - DB_TXN *txn; - DBT *key; - DBT *data; - u_int32_t flags; -{ - DB *real_dbp; - - real_dbp = (DB *)dbp->internal; - txn = dbp->dbenv->xa_txn; - - return (real_dbp->get(real_dbp, txn, key, data, flags)); -} - -static int -__xa_put(dbp, txn, key, data, flags) - DB *dbp; - DB_TXN *txn; - DBT *key; - DBT *data; - u_int32_t flags; -{ - DB *real_dbp; - - real_dbp = (DB *)dbp->internal; - txn = dbp->dbenv->xa_txn; - - return (real_dbp->put(real_dbp, txn, key, data, flags)); -} - -static int -__xa_stat(dbp, spp, db_malloc, flags) - DB *dbp; - void *spp; - void *(*db_malloc) __P((size_t)); - u_int32_t flags; -{ - DB *real_dbp; - - real_dbp = (DB *)dbp->internal; - return (real_dbp->stat(real_dbp, spp, db_malloc, flags)); -} - -static int -__xa_sync(dbp, flags) - DB *dbp; - u_int32_t flags; -{ - DB *real_dbp; - - real_dbp = (DB *)dbp->internal; - return (real_dbp->sync(real_dbp, flags)); -} - -static int -__xa_c_close(dbc) - DBC *dbc; -{ - DBC *real_dbc; - int ret; - - real_dbc = (DBC *)dbc->internal; - - ret = real_dbc->c_close(real_dbc); - - TAILQ_REMOVE(&dbc->dbp->active_queue, dbc, links); - __os_free(dbc, sizeof(DBC)); - - return (ret); -} - -static int -__xa_c_del(dbc, flags) - DBC *dbc; - u_int32_t flags; -{ - DBC *real_dbc; - - real_dbc = (DBC *)dbc->internal; - return (real_dbc->c_del(real_dbc, flags)); -} - -static int -__xa_c_get(dbc, key, data, flags) - DBC *dbc; - DBT *key; - DBT *data; - u_int32_t flags; -{ - DBC *real_dbc; - - real_dbc = (DBC *)dbc->internal; - return (real_dbc->c_get(real_dbc, key, data, flags)); -} - -static int -__xa_c_put(dbc, key, data, flags) - DBC *dbc; - DBT *key; - DBT *data; - u_int32_t flags; -{ - DBC *real_dbc; - - real_dbc = (DBC *)dbc->internal; - return (real_dbc->c_put(real_dbc, key, data, flags)); -} diff --git a/db2/xa/xa_map.c b/db2/xa/xa_map.c deleted file mode 100644 index d4ebbae..0000000 --- a/db2/xa/xa_map.c +++ /dev/null @@ -1,305 +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[] = "@(#)xa_map.c 10.4 (Sleepycat) 10/20/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <stdio.h> -#include <string.h> -#endif - -#include "db_int.h" -#include "shqueue.h" -#include "txn.h" - -/* - * This file contains all the mapping information that we need to support - * the DB/XA interface. - */ - -/* - * __db_rmid_to_env - * Return the environment associated with a given XA rmid. - * - * PUBLIC: int __db_rmid_to_env __P((int rmid, DB_ENV **envp, int open_ok)); - */ -int -__db_rmid_to_env(rmid, envp, open_ok) - int rmid; - DB_ENV **envp; - int open_ok; -{ - DB_ENV *env; - char *dbhome; - - env = TAILQ_FIRST(&DB_GLOBAL(db_envq)); - if (env != NULL && env->xa_rmid == rmid) { - *envp = env; - return (0); - } - - /* - * When we map an rmid, move that environment to be the first one in - * the list of environments, so we pass the correct environment from - * the upcoming db_xa_open() call into db_open(). - */ - for (; env != NULL; env = TAILQ_NEXT(env, links)) - if (env->xa_rmid == rmid) { - TAILQ_REMOVE(&DB_GLOBAL(db_envq), env, links); - TAILQ_INSERT_HEAD(&DB_GLOBAL(db_envq), env, links); - *envp = env; - return (0); - } - - /* - * We have not found the rmid on the environment list. If we - * are allowed to do an open, search for the rmid on the name - * list and, if we find it, then open it. - */ - if (!open_ok) - return (1); - - if (__db_rmid_to_name(rmid, &dbhome) != 0) - return (1); -#undef XA_FLAGS -#define XA_FLAGS \ - DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN - - if (__os_calloc(1, sizeof(DB_ENV), &env) != 0) - return (1); - - if (db_appinit(dbhome, NULL, env, XA_FLAGS) != 0) - goto err; - - if (__db_map_rmid(rmid, env) != 0) - goto err1; - - __db_unmap_rmid_name(rmid); - - *envp = env; - return (0); - -err1: (void)db_appexit(env); -err: __os_free(env, sizeof(DB_ENV)); - return (1); -} - -/* - * __db_xid_to_txn - * Return the txn that corresponds to this XID. - * - * PUBLIC: int __db_xid_to_txn __P((DB_ENV *, XID *, size_t *)); - */ -int -__db_xid_to_txn(dbenv, xid, offp) - DB_ENV *dbenv; - XID *xid; - size_t *offp; -{ - DB_TXNREGION *tmr; - struct __txn_detail *td; - - /* - * Search the internal active transaction table to find the - * matching xid. If this is a performance hit, then we - * can create a hash table, but I doubt it's worth it. - */ - tmr = dbenv->tx_info->region; - - LOCK_TXNREGION(dbenv->tx_info); - for (td = SH_TAILQ_FIRST(&tmr->active_txn, __txn_detail); - td != NULL; - td = SH_TAILQ_NEXT(td, links, __txn_detail)) - if (memcmp(xid->data, td->xid, XIDDATASIZE) == 0) - break; - UNLOCK_TXNREGION(dbenv->tx_info); - - if (td == NULL) - return (EINVAL); - - *offp = (u_int8_t *)td - (u_int8_t *)tmr; - return (0); -} - -/* - * __db_map_rmid - * Create a mapping between the specified rmid and environment. - * - * PUBLIC: int __db_map_rmid __P((int, DB_ENV *)); - */ -int -__db_map_rmid(rmid, env) - int rmid; - DB_ENV *env; -{ - if (__os_calloc(1, sizeof(DB_TXN), &env->xa_txn) != 0) - return (XAER_RMERR); - env->xa_txn->txnid = TXN_INVALID; - env->xa_rmid = rmid; - TAILQ_INSERT_HEAD(&DB_GLOBAL(db_envq), env, links); - return (XA_OK); -} - -/* - * __db_unmap_rmid - * Destroy the mapping for the given rmid. - * - * PUBLIC: int __db_unmap_rmid __P((int)); - */ -int -__db_unmap_rmid(rmid) - int rmid; -{ - DB_ENV *e; - - for (e = TAILQ_FIRST(&DB_GLOBAL(db_envq)); - e->xa_rmid != rmid; - e = TAILQ_NEXT(e, links)); - - if (e == NULL) - return (EINVAL); - - TAILQ_REMOVE(&DB_GLOBAL(db_envq), e, links); - if (e->xa_txn != NULL) - __os_free(e->xa_txn, sizeof(DB_TXN)); - return (0); -} - -/* - * __db_map_xid - * Create a mapping between this XID and the transaction at - * "off" in the shared region. - * - * PUBLIC: int __db_map_xid __P((DB_ENV *, XID *, size_t)); - */ -int -__db_map_xid(env, xid, off) - DB_ENV *env; - XID *xid; - size_t off; -{ - DB_TXNMGR *tm; - TXN_DETAIL *td; - - tm = env->tx_info; - td = (TXN_DETAIL *)((u_int8_t *)tm->region + off); - - LOCK_TXNREGION(tm); - memcpy(td->xid, xid->data, XIDDATASIZE); - UNLOCK_TXNREGION(tm); - - return (0); -} - -/* - * __db_unmap_xid - * Destroy the mapping for the specified XID. - * - * PUBLIC: void __db_unmap_xid __P((DB_ENV *, XID *, size_t)); - */ - -void -__db_unmap_xid(env, xid, off) - DB_ENV *env; - XID *xid; - size_t off; -{ - TXN_DETAIL *td; - - COMPQUIET(xid, NULL); - - td = (TXN_DETAIL *)((u_int8_t *)env->tx_info->region + off); - memset(td->xid, 0, sizeof(td->xid)); -} - -/* - * __db_map_rmid_name -- - * Create a mapping from an rmid to a name (the xa_info argument). - * We use this during create and then at some later point when we are - * trying to map an rmid, we might indicate that it's OK to do an open - * in which case, we'll get the xa_info parameter from here and then - * free it up. - * - * PUBLIC: int __db_map_rmid_name __P((int, char *)); - */ - -int -__db_map_rmid_name(rmid, dbhome) - int rmid; - char *dbhome; -{ - struct __rmname *entry; - int ret; - - if ((ret = __os_malloc(sizeof(struct __rmname), NULL, &entry)) != 0) - return (ret); - - if ((ret = __os_strdup(dbhome, &entry->dbhome)) != 0) { - __os_free(entry, sizeof(struct __rmname)); - return (ret); - } - - entry->rmid = rmid; - - TAILQ_INSERT_HEAD(&DB_GLOBAL(db_nameq), entry, links); - return (0); -} - -/* - * __db_rmid_to_name -- - * Given an rmid, return the name of the home directory for that - * rmid. - * - * PUBLIC: int __db_rmid_to_name __P((int, char **)); - */ -int -__db_rmid_to_name(rmid, dbhomep) - int rmid; - char **dbhomep; -{ - struct __rmname *np; - - for (np = TAILQ_FIRST(&DB_GLOBAL(db_nameq)); np != NULL; - np = TAILQ_NEXT(np, links)) { - if (np->rmid == rmid) { - *dbhomep = np->dbhome; - return (0); - } - } - return (1); -} - -/* - * __db_unmap_rmid_name -- - * Given an rmid, remove its entry from the name list. - * - * PUBLIC: void __db_unmap_rmid_name __P((int)); - */ -void -__db_unmap_rmid_name(rmid) - int rmid; -{ - struct __rmname *np, *next; - - for (np = TAILQ_FIRST(&DB_GLOBAL(db_nameq)); np != NULL; np = next) { - next = TAILQ_NEXT(np, links); - if (np->rmid == rmid) { - TAILQ_REMOVE(&DB_GLOBAL(db_nameq), np, links); - __os_freestr(np->dbhome); - __os_free(np, sizeof(struct __rmname)); - return; - } - } - return; -} |