summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1996-05-07 09:02:24 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1996-05-07 09:02:24 +0000
commit30981883e827aa69632bca87e2764ef1ab152fa8 (patch)
treee1095f47308154adb4c7d01f0b14a4f737d2da8e
parent6a0d2fe1f44c1b101f0a8a97b06b5e847918cf81 (diff)
db release 1.85
-rw-r--r--include/mpool.h112
-rw-r--r--lib/libc/db/README43
-rw-r--r--lib/libc/db/VERSION113
-rw-r--r--lib/libc/db/btree/Makefile.inc6
-rw-r--r--lib/libc/db/btree/bt_close.c86
-rw-r--r--lib/libc/db/btree/bt_conv.c22
-rw-r--r--lib/libc/db/btree/bt_debug.c40
-rw-r--r--lib/libc/db/btree/bt_delete.c667
-rw-r--r--lib/libc/db/btree/bt_get.c145
-rw-r--r--lib/libc/db/btree/bt_open.c70
-rw-r--r--lib/libc/db/btree/bt_overflow.c8
-rw-r--r--lib/libc/db/btree/bt_page.c25
-rw-r--r--lib/libc/db/btree/bt_put.c100
-rw-r--r--lib/libc/db/btree/bt_search.c134
-rw-r--r--lib/libc/db/btree/bt_seq.c384
-rw-r--r--lib/libc/db/btree/bt_split.c42
-rw-r--r--lib/libc/db/btree/bt_stack.c102
-rw-r--r--lib/libc/db/btree/bt_utils.c104
-rw-r--r--lib/libc/db/btree/btree.h202
-rw-r--r--lib/libc/db/btree/extern.h14
-rw-r--r--lib/libc/db/changelog105
-rw-r--r--lib/libc/db/db2netbsd31
-rw-r--r--lib/libc/db/hash/Makefile.inc2
-rw-r--r--lib/libc/db/hash/README2
-rw-r--r--lib/libc/db/hash/extern.h2
-rw-r--r--lib/libc/db/hash/hash.c4
-rw-r--r--lib/libc/db/hash/hash.h2
-rw-r--r--lib/libc/db/hash/hash_bigkey.c4
-rw-r--r--lib/libc/db/hash/hash_buf.c12
-rw-r--r--lib/libc/db/hash/hash_func.c4
-rw-r--r--lib/libc/db/hash/hash_log2.c4
-rw-r--r--lib/libc/db/hash/hash_page.c22
-rw-r--r--lib/libc/db/hash/hsearch.c8
-rw-r--r--lib/libc/db/hash/ndbm.c59
-rw-r--r--lib/libc/db/hash/page.h2
-rw-r--r--lib/libc/db/hash/search.h2
-rw-r--r--lib/libc/db/man/btree.313
-rw-r--r--lib/libc/db/man/hash.313
-rw-r--r--lib/libc/db/man/recno.326
-rw-r--r--lib/libc/db/mpool/mpool.c431
-rw-r--r--lib/libc/db/mpool/mpool.libtp746
-rw-r--r--lib/libc/db/recno/Makefile.inc2
-rw-r--r--lib/libc/db/recno/extern.h2
-rw-r--r--lib/libc/db/recno/rec_close.c63
-rw-r--r--lib/libc/db/recno/rec_delete.c14
-rw-r--r--lib/libc/db/recno/rec_get.c109
-rw-r--r--lib/libc/db/recno/rec_open.c47
-rw-r--r--lib/libc/db/recno/rec_put.c53
-rw-r--r--lib/libc/db/recno/rec_search.c9
-rw-r--r--lib/libc/db/recno/rec_seq.c26
-rw-r--r--lib/libc/db/recno/rec_utils.c79
-rw-r--r--lib/libc/db/recno/recno.h2
-rw-r--r--regress/lib/libc/db/README36
-rw-r--r--regress/lib/libc/db/dbtest.c213
-rw-r--r--regress/lib/libc/db/run.test35
55 files changed, 2862 insertions, 1741 deletions
diff --git a/include/mpool.h b/include/mpool.h
index 849729759b3..622d2c9a377 100644
--- a/include/mpool.h
+++ b/include/mpool.h
@@ -1,7 +1,7 @@
-/* $NetBSD: mpool.h,v 1.6 1994/10/26 00:56:07 cgd Exp $ */
+/* $NetBSD: mpool.h,v 1.7 1996/05/03 21:13:41 cgd Exp $ */
/*-
- * Copyright (c) 1991, 1993
+ * 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
@@ -32,98 +32,62 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)mpool.h 8.1 (Berkeley) 6/2/93
+ * @(#)mpool.h 8.2 (Berkeley) 7/14/94
*/
+#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 three ways. All active pages are threaded
- * on a hash chain (hashed by the page number) and an lru chain. Inactive
- * pages are threaded on a free chain. Each reference to a memory pool is
- * handed an MPOOL which is the opaque cookie passed to all of the memory
- * routines.
+ * 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 lists. */
-typedef struct BKT {
- struct BKT *hnext; /* next hash bucket */
- struct BKT *hprev; /* previous hash bucket */
- struct BKT *cnext; /* next free/lru bucket */
- struct BKT *cprev; /* previous free/lru bucket */
- void *page; /* page */
- pgno_t pgno; /* page number */
+/* 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 */
- unsigned long flags; /* flags */
+ u_int8_t flags; /* flags */
} BKT;
-/* The BKTHDR structures are the heads of the lists. */
-typedef struct BKTHDR {
- struct BKT *hnext; /* next hash bucket */
- struct BKT *hprev; /* previous hash bucket */
- struct BKT *cnext; /* next free/lru bucket */
- struct BKT *cprev; /* previous free/lru bucket */
-} BKTHDR;
-
typedef struct MPOOL {
- BKTHDR free; /* The free list. */
- BKTHDR lru; /* The LRU list. */
- BKTHDR hashtable[HASHSIZE]; /* Hashed list by page number. */
- 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. */
+ 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) __P((void *, pgno_t, void *));
- /* Page out conversion routine. */
+ /* page out conversion routine */
void (*pgout) __P((void *, pgno_t, void *));
- void *pgcookie; /* Cookie for page in/out routines. */
+ void *pgcookie; /* cookie for page in/out routines */
#ifdef STATISTICS
- unsigned long cachehit;
- unsigned long cachemiss;
- unsigned long pagealloc;
- unsigned long pageflush;
- unsigned long pageget;
- unsigned long pagenew;
- unsigned long pageput;
- unsigned long pageread;
- unsigned long pagewrite;
+ 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;
-#ifdef __MPOOLINTERFACE_PRIVATE
-/* Macros to insert/delete into/from hash chain. */
-#define rmhash(bp) { \
- (bp)->hprev->hnext = (bp)->hnext; \
- (bp)->hnext->hprev = (bp)->hprev; \
-}
-#define inshash(bp, pg) { \
- hp = &mp->hashtable[HASHKEY(pg)]; \
- (bp)->hnext = hp->hnext; \
- (bp)->hprev = (struct BKT *)hp; \
- hp->hnext->hprev = (bp); \
- hp->hnext = (bp); \
-}
-
-/* Macros to insert/delete into/from lru and free chains. */
-#define rmchain(bp) { \
- (bp)->cprev->cnext = (bp)->cnext; \
- (bp)->cnext->cprev = (bp)->cprev; \
-}
-#define inschain(bp, dp) { \
- (bp)->cnext = (dp)->cnext; \
- (bp)->cprev = (struct BKT *)(dp); \
- (dp)->cnext->cprev = (bp); \
- (dp)->cnext = (bp); \
-}
-#endif
-
__BEGIN_DECLS
-MPOOL *mpool_open __P((DBT *, 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_new __P((MPOOL *, pgno_t *));
diff --git a/lib/libc/db/README b/lib/libc/db/README
index df1be282063..d06cdf14fc7 100644
--- a/lib/libc/db/README
+++ b/lib/libc/db/README
@@ -1,2 +1,41 @@
-$NetBSD: README,v 1.2 1995/02/27 13:19:30 cgd Exp $
-(was symlink to VERSION. -- cgd)
+# $NetBSD: README,v 1.3 1996/05/03 21:17:07 cgd Exp $
+# @(#)README 8.27 (Berkeley) 9/1/94
+
+This is version 1.85 of the Berkeley DB code.
+
+For information on compiling and installing this software, see the file
+PORT/README.
+
+Newer versions of this software will periodically be made available by
+anonymous ftp from ftp.cs.berkeley.edu. An archive in compressed format
+is in ucb/4bsd/db.tar.Z, or in gzip format in ucb/4bsd/db.tar.gz. If
+you'd like to receive announcements of future releases of this software,
+send email to the contact address below.
+
+Email questions may be addressed to Keith Bostic at bostic@cs.berkeley.edu.
+
+============================================
+Distribution contents:
+
+Makefile.inc Ignore this, it's the 4.4BSD subsystem Makefile.
+PORT The per OS/architecture directories to use to build
+ libdb.a, if you're not running 4.4BSD. See the file
+ PORT/README for more information.
+README This file.
+btree The B+tree routines.
+changelog List of changes, per version.
+db The dbopen(3) interface routine.
+docs Various USENIX papers, and the formatted manual pages.
+hash The extended linear hashing routines.
+man The unformatted manual pages.
+mpool The memory pool routines.
+recno The fixed/variable length record routines.
+test Test package.
+
+============================================
+Debugging:
+
+If you're running a memory checker (e.g. Purify) on DB, make sure that
+you recompile it with "-DPURIFY" in the CFLAGS, first. By default,
+allocated pages are not initialized by the DB code, and they will show
+up as reads of uninitialized memory in the buffer write routines.
diff --git a/lib/libc/db/VERSION b/lib/libc/db/VERSION
index 440b71bad09..e69de29bb2d 100644
--- a/lib/libc/db/VERSION
+++ b/lib/libc/db/VERSION
@@ -1,113 +0,0 @@
-# $NetBSD: VERSION,v 1.7 1995/02/27 13:19:33 cgd Exp $
-# @(#)VERSION 8.17 (Berkeley) 6/20/94
-
-This is version 1.79 of the Berkeley DB code.
-
-For information on compiling and installing this software, see the file
-PORT/README.
-
-If your version of the DB code doesn't have a copy of this version file,
-it's really old, please update it!
-
-Newer versions of this software will periodically be made available by
-anonymous ftp from ftp.cs.berkeley.edu. An archive in compressed format
-is in ucb/4bsd/db.tar.Z, or in gzip format in ucb/4bsd/db.tar.gz. If
-you'd like to receive announcements of future releases of this software,
-send email to the contact address below.
-
-Email questions may be addressed to Keith Bostic at bostic@cs.berkeley.edu.
-
-============================================
-Distribution contents:
-
-Makefile.inc Ignore this, it's the 4.4BSD subsystem Makefile.
-PORT The per OS/architecture directories to use to build
- libdb.a, if you're not running 4.4BSD. See the file
- PORT/README for more information.
-README This file.
-VERSION This file.
-btree B+tree routines.
-db Dbopen(3) interface routine.
-doc USENIX papers, formatted manual pages.
-hash Extended linear hashing routines.
-man Unformatted manual pages.
-mpool Memory pool routines.
-recno Fixed/variable length record routines.
-test Test package.
-
-============================================
-1.78 -> 1.79 Mon Jun 20 17:36:47 EDT 1994
- all: Minor cleanups of 1.78 for porting reasons; only
- major change was inlining check of NULL pointer
- so that __fix_realloc goes away.
-
-1.77 -> 1.78 Thu Jun 16 19:06:43 EDT 1994
- all: Move "standard" size typedef's into db.h.
-
-1.76 -> 1.77 Thu Jun 16 16:48:38 EDT 1994
- hash: Delete __init_ routine, has special meaning to OSF 2.0.
-
-1.74 -> 1.76
- all: Finish up the port to the Alpha.
-
-1.73 -> 1.74
- recno: Don't put the record if rec_search fails, in rec_rdelete.
- Create fixed-length intermediate records past "end" of DB
- correctly.
- Realloc bug when reading in fixed records.
- all: First cut at port to Alpha (64-bit architecture) using
- 4.4BSD basic integral types typedef's.
- Cast allocation pointers to shut up old compilers.
- Rework PORT directory into OS/machine directories.
-
-1.72 -> 1.73
- btree: If enough duplicate records were inserted and then deleted
- that internal pages had references to empty pages of the
- duplicate keys, the search function ended up on the wrong
- page.
-
-1.7 -> 1.72 12 Oct 1993
- hash: Support NET/2 hash formats.
-
-1.7 -> 1.71 16 Sep 1993
- btree/recno:
- Fix bug in internal search routines that caused
- return of invalid pointers.
-
-1.6 -> 1.7 07 Sep 1993
- hash: Fixed big key overflow bugs.
- test: Portability hacks, rewrite test script, Makefile.
- btree/recno:
- Stop copying non-overflow key/data pairs.
- PORT: Break PORT directory up into per architecture/OS
- subdirectories.
-
-1.5 -> 1.6 06 Jun 1993
- hash: In PAIRFITS, the first comparison should look at (P)[2].
- The hash_realloc function was walking off the end of memory.
- The overflow page number was wrong when bumping splitpoint.
-
-1.4 -> 1.5 23 May 1993
- hash: Set hash default fill factor dynamically.
- recno: Fixed bug in sorted page splits.
- Add page size parameter support.
- Allow recno to specify the name of the underlying btree;
- used for vi recovery.
- btree/recno:
- Support 64K pages.
- btree/hash/recno:
- Provide access to an underlying file descriptor.
- Change sync routines to take a flag argument, recno
- uses this to sync out the underlying btree.
-
-1.3 -> 1.4 10 May 1993
- recno: Delete the R_CURSORLOG flag from the recno interface.
- Zero-length record fix for non-mmap reads.
- Try and make SIZE_T_MAX test in open portable.
-
-1.2 -> 1.3 01 May 1993
- btree: Ignore user byte-order setting when reading already
- existing database. Fixes to byte-order conversions.
-
-1.1 -> 1.2 15 Apr 1993
- No bug fixes, only compatibility hacks.
diff --git a/lib/libc/db/btree/Makefile.inc b/lib/libc/db/btree/Makefile.inc
index d187103e2d3..46fbb029e39 100644
--- a/lib/libc/db/btree/Makefile.inc
+++ b/lib/libc/db/btree/Makefile.inc
@@ -1,8 +1,8 @@
-# $NetBSD: Makefile.inc,v 1.5 1995/02/27 13:19:53 cgd Exp $
-# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $NetBSD: Makefile.inc,v 1.6 1996/05/03 21:50:36 cgd Exp $
+# @(#)Makefile.inc 8.2 (Berkeley) 7/14/94
.PATH: ${.CURDIR}/db/btree
SRCS+= bt_close.c bt_conv.c bt_debug.c bt_delete.c bt_get.c bt_open.c \
bt_overflow.c bt_page.c bt_put.c bt_search.c bt_seq.c bt_split.c \
- bt_stack.c bt_utils.c
+ bt_utils.c
diff --git a/lib/libc/db/btree/bt_close.c b/lib/libc/db/btree/bt_close.c
index 2b27327f7ed..b18c278602e 100644
--- a/lib/libc/db/btree/bt_close.c
+++ b/lib/libc/db/btree/bt_close.c
@@ -1,7 +1,7 @@
-/* $NetBSD: bt_close.c,v 1.6 1995/02/27 13:19:59 cgd Exp $ */
+/* $NetBSD: bt_close.c,v 1.7 1996/05/03 21:50:38 cgd Exp $ */
/*-
- * Copyright (c) 1990, 1993
+ * 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
@@ -38,9 +38,9 @@
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
-static char sccsid[] = "@(#)bt_close.c 8.3 (Berkeley) 2/21/94";
+static char sccsid[] = "@(#)bt_close.c 8.7 (Berkeley) 8/17/94";
#else
-static char rcsid[] = "$NetBSD: bt_close.c,v 1.6 1995/02/27 13:19:59 cgd Exp $";
+static char rcsid[] = "$NetBSD: bt_close.c,v 1.7 1996/05/03 21:50:38 cgd Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
@@ -81,25 +81,30 @@ __bt_close(dbp)
t->bt_pinned = NULL;
}
- /*
- * Delete any already deleted record that we've been saving
- * because the cursor pointed to it.
- */
- if (ISSET(t, B_DELCRSR) && __bt_crsrdel(t, &t->bt_bcursor))
- return (RET_ERROR);
-
+ /* 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);
- if (t->bt_stack)
- free(t->bt_stack);
- if (t->bt_kbuf)
- free(t->bt_kbuf);
- if (t->bt_dbuf)
- free(t->bt_dbuf);
+ /* 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);
@@ -123,8 +128,6 @@ __bt_sync(dbp, flags)
{
BTREE *t;
int status;
- PAGE *h;
- void *p;
t = dbp->internal;
@@ -140,40 +143,15 @@ __bt_sync(dbp, flags)
return (RET_ERROR);
}
- if (ISSET(t, B_INMEM | B_RDONLY) || !ISSET(t, B_MODIFIED))
+ if (F_ISSET(t, B_INMEM | B_RDONLY) || !F_ISSET(t, B_MODIFIED))
return (RET_SUCCESS);
- if (ISSET(t, B_METADIRTY) && bt_meta(t) == RET_ERROR)
+ if (F_ISSET(t, B_METADIRTY) && bt_meta(t) == RET_ERROR)
return (RET_ERROR);
- /*
- * Nastiness. If the cursor has been marked for deletion, but not
- * actually deleted, we have to make a copy of the page, delete the
- * key/data item, sync the file, and then restore the original page
- * contents.
- */
- if (ISSET(t, B_DELCRSR)) {
- if ((p = (void *)malloc(t->bt_psize)) == NULL)
- return (RET_ERROR);
- if ((h = mpool_get(t->bt_mp, t->bt_bcursor.pgno, 0)) == NULL)
- return (RET_ERROR);
- memmove(p, h, t->bt_psize);
- if ((status =
- __bt_dleaf(t, h, t->bt_bcursor.index)) == RET_ERROR)
- goto ecrsr;
- mpool_put(t->bt_mp, h, MPOOL_DIRTY);
- }
-
if ((status = mpool_sync(t->bt_mp)) == RET_SUCCESS)
- CLR(t, B_MODIFIED);
-
-ecrsr: if (ISSET(t, B_DELCRSR)) {
- if ((h = mpool_get(t->bt_mp, t->bt_bcursor.pgno, 0)) == NULL)
- return (RET_ERROR);
- memmove(h, p, t->bt_psize);
- free(p);
- mpool_put(t->bt_mp, h, MPOOL_DIRTY);
- }
+ F_CLR(t, B_MODIFIED);
+
return (status);
}
@@ -197,12 +175,12 @@ bt_meta(t)
return (RET_ERROR);
/* Fill in metadata. */
- m.m_magic = BTREEMAGIC;
- m.m_version = BTREEVERSION;
- m.m_psize = t->bt_psize;
- m.m_free = t->bt_free;
- m.m_nrecs = t->bt_nrecs;
- m.m_flags = t->bt_flags & SAVEMETA;
+ 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);
diff --git a/lib/libc/db/btree/bt_conv.c b/lib/libc/db/btree/bt_conv.c
index 1d513865455..27ab66c0752 100644
--- a/lib/libc/db/btree/bt_conv.c
+++ b/lib/libc/db/btree/bt_conv.c
@@ -1,4 +1,4 @@
-/* $NetBSD: bt_conv.c,v 1.5 1995/02/27 13:20:04 cgd Exp $ */
+/* $NetBSD: bt_conv.c,v 1.6 1996/05/03 21:50:39 cgd Exp $ */
/*-
* Copyright (c) 1990, 1993, 1994
@@ -38,9 +38,9 @@
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
-static char sccsid[] = "@(#)bt_conv.c 8.3 (Berkeley) 5/31/94";
+static char sccsid[] = "@(#)bt_conv.c 8.5 (Berkeley) 8/17/94";
#else
-static char rcsid[] = "$NetBSD: bt_conv.c,v 1.5 1995/02/27 13:20:04 cgd Exp $";
+static char rcsid[] = "$NetBSD: bt_conv.c,v 1.6 1996/05/03 21:50:39 cgd Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
@@ -74,7 +74,7 @@ __bt_pgin(t, pg, pp)
u_char flags;
char *p;
- if (!ISSET(((BTREE *)t), B_NEEDSWAP))
+ if (!F_ISSET(((BTREE *)t), B_NEEDSWAP))
return;
if (pg == P_META) {
mswap(pp);
@@ -142,7 +142,7 @@ __bt_pgout(t, pg, pp)
u_char flags;
char *p;
- if (!ISSET(((BTREE *)t), B_NEEDSWAP))
+ if (!F_ISSET(((BTREE *)t), B_NEEDSWAP))
return;
if (pg == P_META) {
mswap(pp);
@@ -212,16 +212,16 @@ mswap(pg)
char *p;
p = (char *)pg;
- P_32_SWAP(p); /* m_magic */
+ P_32_SWAP(p); /* magic */
p += sizeof(u_int32_t);
- P_32_SWAP(p); /* m_version */
+ P_32_SWAP(p); /* version */
p += sizeof(u_int32_t);
- P_32_SWAP(p); /* m_psize */
+ P_32_SWAP(p); /* psize */
p += sizeof(u_int32_t);
- P_32_SWAP(p); /* m_free */
+ P_32_SWAP(p); /* free */
p += sizeof(u_int32_t);
- P_32_SWAP(p); /* m_nrecs */
+ P_32_SWAP(p); /* nrecs */
p += sizeof(u_int32_t);
- P_32_SWAP(p); /* m_flags */
+ P_32_SWAP(p); /* flags */
p += sizeof(u_int32_t);
}
diff --git a/lib/libc/db/btree/bt_debug.c b/lib/libc/db/btree/bt_debug.c
index fb967122aaa..7b80328b952 100644
--- a/lib/libc/db/btree/bt_debug.c
+++ b/lib/libc/db/btree/bt_debug.c
@@ -1,4 +1,4 @@
-/* $NetBSD: bt_debug.c,v 1.5 1995/02/27 13:20:12 cgd Exp $ */
+/* $NetBSD: bt_debug.c,v 1.6 1996/05/03 21:50:41 cgd Exp $ */
/*-
* Copyright (c) 1990, 1993, 1994
@@ -38,9 +38,9 @@
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
-static char sccsid[] = "@(#)bt_debug.c 8.3 (Berkeley) 5/31/94";
+static char sccsid[] = "@(#)bt_debug.c 8.5 (Berkeley) 8/17/94";
#else
-static char rcsid[] = "$NetBSD: bt_debug.c,v 1.5 1995/02/27 13:20:12 cgd Exp $";
+static char rcsid[] = "$NetBSD: bt_debug.c,v 1.6 1996/05/03 21:50:41 cgd Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
@@ -71,24 +71,22 @@ __bt_dump(dbp)
t = dbp->internal;
(void)fprintf(stderr, "%s: pgsz %d",
- ISSET(t, B_INMEM) ? "memory" : "disk", t->bt_psize);
- if (ISSET(t, R_RECNO))
+ 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 (ISSET(t, flag)) { \
+ if (F_ISSET(t, flag)) { \
(void)fprintf(stderr, "%s%s", sep, name); \
sep = ", "; \
}
- if (t->bt_flags) {
+ if (t->flags != 0) {
sep = " flags (";
- X(B_DELCRSR, "DELCRSR");
X(R_FIXLEN, "FIXLEN");
X(B_INMEM, "INMEM");
X(B_NODUPS, "NODUPS");
X(B_RDONLY, "RDONLY");
X(R_RECNO, "RECNO");
- X(B_SEQINIT, "SEQINIT");
X(B_METADIRTY,"METADIRTY");
(void)fprintf(stderr, ")\n");
}
@@ -114,19 +112,19 @@ __bt_dmpage(h)
char *sep;
m = (BTMETA *)h;
- (void)fprintf(stderr, "magic %lx\n", m->m_magic);
- (void)fprintf(stderr, "version %lu\n", m->m_version);
- (void)fprintf(stderr, "psize %lu\n", m->m_psize);
- (void)fprintf(stderr, "free %lu\n", m->m_free);
- (void)fprintf(stderr, "nrecs %lu\n", m->m_nrecs);
- (void)fprintf(stderr, "flags %lu", m->m_flags);
+ (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->m_flags & flag) { \
+ if (m->flags & flag) { \
(void)fprintf(stderr, "%s%s", sep, name); \
sep = ", "; \
}
- if (m->m_flags) {
+ if (m->flags) {
sep = " (";
X(B_NODUPS, "NODUPS");
X(R_RECNO, "RECNO");
@@ -198,7 +196,7 @@ __bt_dpage(h)
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) {
+ switch (h->flags & P_TYPE) {
case P_BINTERNAL:
bi = GETBINTERNAL(h, cur);
(void)fprintf(stderr,
@@ -273,7 +271,7 @@ __bt_stat(dbp)
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) {
+ switch (h->flags & P_TYPE) {
case P_BINTERNAL:
case P_RINTERNAL:
++pinternal;
@@ -301,7 +299,7 @@ __bt_stat(dbp)
(void)mpool_put(t->bt_mp, h, 0);
break;
}
- i = ISSET(t, R_RECNO) ?
+ i = F_ISSET(t, R_RECNO) ?
GETRINTERNAL(h, 0)->pgno :
GETBINTERNAL(h, 0)->pgno;
(void)mpool_put(t->bt_mp, h, 0);
@@ -309,7 +307,7 @@ __bt_stat(dbp)
(void)fprintf(stderr, "%d level%s with %ld keys",
levels, levels == 1 ? "" : "s", nkeys);
- if (ISSET(t, R_RECNO))
+ 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",
diff --git a/lib/libc/db/btree/bt_delete.c b/lib/libc/db/btree/bt_delete.c
index e5ced2bc5c9..32efd2529fb 100644
--- a/lib/libc/db/btree/bt_delete.c
+++ b/lib/libc/db/btree/bt_delete.c
@@ -1,4 +1,4 @@
-/* $NetBSD: bt_delete.c,v 1.6 1995/02/27 13:20:16 cgd Exp $ */
+/* $NetBSD: bt_delete.c,v 1.7 1996/05/03 21:50:44 cgd Exp $ */
/*-
* Copyright (c) 1990, 1993, 1994
@@ -38,9 +38,9 @@
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
-static char sccsid[] = "@(#)bt_delete.c 8.4 (Berkeley) 5/31/94";
+static char sccsid[] = "@(#)bt_delete.c 8.13 (Berkeley) 7/28/94";
#else
-static char rcsid[] = "$NetBSD: bt_delete.c,v 1.6 1995/02/27 13:20:16 cgd Exp $";
+static char rcsid[] = "$NetBSD: bt_delete.c,v 1.7 1996/05/03 21:50:44 cgd Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
@@ -53,18 +53,17 @@ static char rcsid[] = "$NetBSD: bt_delete.c,v 1.6 1995/02/27 13:20:16 cgd Exp $"
#include <db.h>
#include "btree.h"
-static int bt_bdelete __P((BTREE *, const DBT *));
+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.
+ * __bt_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.
+ * Return RET_SPECIAL if the key is not found.
*/
int
__bt_delete(dbp, key, flags)
@@ -73,6 +72,8 @@ __bt_delete(dbp, key, flags)
u_int flags;
{
BTREE *t;
+ CURSOR *c;
+ PAGE *h;
int status;
t = dbp->internal;
@@ -83,242 +84,433 @@ __bt_delete(dbp, key, flags)
t->bt_pinned = NULL;
}
- if (ISSET(t, B_RDONLY)) {
+ /* Check for change to a read-only tree. */
+ if (F_ISSET(t, B_RDONLY)) {
errno = EPERM;
return (RET_ERROR);
}
- switch(flags) {
+ switch (flags) {
case 0:
- status = bt_bdelete(t, key);
+ 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 the record. For
- * the delete cursor bit to have been set requires that the
- * scan be initialized, so no reason to check.
+ * If flags is R_CURSOR, delete the cursor. Must already
+ * have started a scan and not have already deleted it.
*/
- if (!ISSET(t, B_SEQINIT))
- goto einval;
- status = ISSET(t, B_DELCRSR) ?
- RET_SPECIAL : __bt_crsrdel(t, &t->bt_bcursor);
- break;
+ 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:
-einval: errno = EINVAL;
+ errno = EINVAL;
return (RET_ERROR);
}
if (status == RET_SUCCESS)
- SET(t, B_MODIFIED);
+ F_SET(t, B_MODIFIED);
return (status);
}
/*
- * BT_BDELETE -- Delete all key/data pairs matching the specified key.
+ * __bt_stkacq --
+ * Acquire a stack so we can delete a cursor entry.
*
* Parameters:
- * tree: tree
+ * 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)
+__bt_bdelete(t, key)
BTREE *t;
const DBT *key;
{
- EPG *e, save;
+ EPG *e;
PAGE *h;
- pgno_t cpgno, pg;
- indx_t cindex;
- int deleted, dirty1, dirty2, exact;
+ int deleted, exact, redo;
+
+ deleted = 0;
/* Find any matching record; __bt_search pins the page. */
- if ((e = __bt_search(t, key, &exact)) == NULL)
- return (RET_ERROR);
+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 (RET_SPECIAL);
+ return (deleted ? RET_SUCCESS : RET_SPECIAL);
}
/*
- * Delete forward, then delete backward, from the found key. The
- * ordering is so that the deletions don't mess up the page refs.
- * The first loop deletes the key from the original page, the second
- * unpins the original page. In the first loop, dirty1 is set if
- * the original page is modified, and dirty2 is set if any subsequent
- * pages are modified. In the second loop, dirty1 starts off set if
- * the original page has been modified, and is set if any subsequent
- * pages are modified.
- *
- * If find the key referenced by the cursor, don't delete it, just
- * flag it for future deletion. The cursor page number is P_INVALID
- * unless the sequential scan is initialized, so no reason to check.
- * A special case is when the already deleted cursor record was the
- * only record found. If so, then the delete opertion fails as no
- * records were deleted.
- *
- * Cycle in place in the current page until the current record doesn't
- * match the key or the page is empty. If the latter, walk forward,
- * skipping empty pages and repeating until a record doesn't match
- * the key or the end of the tree is reached.
+ * 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.
*/
- cpgno = t->bt_bcursor.pgno;
- cindex = t->bt_bcursor.index;
- save = *e;
- dirty1 = 0;
- for (h = e->page, deleted = 0;;) {
- dirty2 = 0;
- do {
- if (h->pgno == cpgno && e->index == cindex) {
- if (!ISSET(t, B_DELCRSR)) {
- SET(t, B_DELCRSR);
- deleted = 1;
- }
- ++e->index;
- } else {
- if (__bt_dleaf(t, h, e->index)) {
- if (h->pgno != save.page->pgno)
- mpool_put(t->bt_mp, h, dirty2);
- mpool_put(t->bt_mp, save.page, dirty1);
+ 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);
- }
- if (h->pgno == save.page->pgno)
- dirty1 = MPOOL_DIRTY;
- else
- dirty2 = MPOOL_DIRTY;
- deleted = 1;
- }
- } while (e->index < NEXTINDEX(h) && __bt_cmp(t, key, e) == 0);
-
- /*
- * Quit if didn't find a match, no next page, or first key on
- * the next page doesn't match. Don't unpin the original page
- * unless an error occurs.
- */
- if (e->index < NEXTINDEX(h))
- break;
- for (;;) {
- if ((pg = h->nextpg) == P_INVALID)
- goto done1;
- if (h->pgno != save.page->pgno)
- mpool_put(t->bt_mp, h, dirty2);
- if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) {
- mpool_put(t->bt_mp, save.page, dirty1);
- return (RET_ERROR);
- }
- if (NEXTINDEX(h) != 0) {
- e->page = h;
- e->index = 0;
- break;
- }
+ } 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;
}
- /*
- * Reach here with the original page and the last page referenced
- * pinned (they may be the same). Release it if not the original.
- */
-done1: if (h->pgno != save.page->pgno)
- mpool_put(t->bt_mp, h, dirty2);
+ /* 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 backwards from the record previous to the record returned by
- * __bt_search, skipping empty pages, until a record doesn't match
- * the key or reach the beginning of the tree.
+ * 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.
*/
- *e = save;
- for (;;) {
- if (e->index)
- --e->index;
- for (h = e->page; e->index; --e->index) {
- if (__bt_cmp(t, key, e) != 0)
- goto done2;
- if (h->pgno == cpgno && e->index == cindex) {
- if (!ISSET(t, B_DELCRSR)) {
- SET(t, B_DELCRSR);
- deleted = 1;
- }
+ 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_dleaf(t, h, e->index) == RET_ERROR) {
- mpool_put(t->bt_mp, h, dirty1);
+ if (__bt_relink(t, pg) || __bt_free(t, pg))
return (RET_ERROR);
- }
- if (h->pgno == save.page->pgno)
- dirty1 = MPOOL_DIRTY;
- deleted = 1;
+ 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);
}
- if ((pg = h->prevpg) == P_INVALID)
- goto done2;
- mpool_put(t->bt_mp, h, dirty1);
- dirty1 = 0;
- if ((e->page = mpool_get(t->bt_mp, pg, 0)) == NULL)
- return (RET_ERROR);
- e->index = NEXTINDEX(e->page);
+ mpool_put(t->bt_mp, pg, MPOOL_DIRTY);
+ break;
}
- /*
- * Reach here with the last page that was looked at pinned. Release
- * it.
- */
-done2: mpool_put(t->bt_mp, h, dirty1);
- return (deleted ? RET_SUCCESS : RET_SPECIAL);
+ /* 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.
+ * __bt_dleaf --
+ * Delete a single record from a leaf page.
*
* Parameters:
* t: tree
- * index: index on current page to delete
+ * key: referenced key
+ * h: page
+ * index: index on page to delete
*
* Returns:
* RET_SUCCESS, RET_ERROR.
*/
int
-__bt_dleaf(t, h, index)
+__bt_dleaf(t, key, h, index)
BTREE *t;
+ const DBT *key;
PAGE *h;
- indx_t index;
+ u_int index;
{
- register BLEAF *bl;
- register indx_t cnt, *ip, offset;
- register u_int32_t nbytes;
- char *from;
+ BLEAF *bl;
+ indx_t cnt, *ip, offset;
+ u_int32_t nbytes;
void *to;
+ char *from;
- /*
- * Delete a record from a btree 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.
- */
+ /* 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);
- nbytes = NBLEAF(bl);
- /*
- * Compress the key/data pairs. Compress and adjust the [BR]LEAF
- * offsets. Reset the headers.
- */
+ /* 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)
@@ -326,5 +518,146 @@ __bt_dleaf(t, h, index)
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/lib/libc/db/btree/bt_get.c b/lib/libc/db/btree/bt_get.c
index 2adc73feb7a..18e3a37b6c0 100644
--- a/lib/libc/db/btree/bt_get.c
+++ b/lib/libc/db/btree/bt_get.c
@@ -1,7 +1,7 @@
-/* $NetBSD: bt_get.c,v 1.6 1995/02/27 13:20:22 cgd Exp $ */
+/* $NetBSD: bt_get.c,v 1.7 1996/05/03 21:50:45 cgd Exp $ */
/*-
- * Copyright (c) 1990, 1993
+ * 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
@@ -38,9 +38,9 @@
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
-static char sccsid[] = "@(#)bt_get.c 8.2 (Berkeley) 9/7/93";
+static char sccsid[] = "@(#)bt_get.c 8.6 (Berkeley) 7/20/94";
#else
-static char rcsid[] = "$NetBSD: bt_get.c,v 1.6 1995/02/27 13:20:22 cgd Exp $";
+static char rcsid[] = "$NetBSD: bt_get.c,v 1.7 1996/05/03 21:50:45 cgd Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
@@ -97,148 +97,15 @@ __bt_get(dbp, key, data, flags)
return (RET_SPECIAL);
}
- /*
- * A special case is if we found the record but it's flagged for
- * deletion. In this case, we want to find another record with the
- * same key, if it exists. Rather than look around the tree we call
- * __bt_first and have it redo the search, as __bt_first will not
- * return keys marked for deletion. Slow, but should never happen.
- */
- if (ISSET(t, B_DELCRSR) && e->page->pgno == t->bt_bcursor.pgno &&
- e->index == t->bt_bcursor.index) {
- mpool_put(t->bt_mp, e->page, 0);
- if ((e = __bt_first(t, key, &exact)) == NULL)
- return (RET_ERROR);
- if (!exact)
- return (RET_SPECIAL);
- }
+ status = __bt_ret(t, e, NULL, NULL, data, &t->bt_rdata, 0);
- status = __bt_ret(t, e, NULL, data);
/*
* If the user is doing concurrent access, we copied the
* key/data, toss the page.
*/
- if (ISSET(t, B_DB_LOCK))
+ if (F_ISSET(t, B_DB_LOCK))
mpool_put(t->bt_mp, e->page, 0);
else
t->bt_pinned = e->page;
return (status);
}
-
-/*
- * __BT_FIRST -- Find the first entry.
- *
- * Parameters:
- * t: the tree
- * key: the key
- *
- * Returns:
- * The first entry in the tree greater than or equal to key.
- */
-EPG *
-__bt_first(t, key, exactp)
- BTREE *t;
- const DBT *key;
- int *exactp;
-{
- register PAGE *h;
- register EPG *e;
- EPG save;
- pgno_t cpgno, pg;
- indx_t cindex;
- int found;
-
- /*
- * Find any matching record; __bt_search pins the page. Only exact
- * matches are tricky, otherwise just return the location of the key
- * if it were to be inserted into the tree.
- */
- if ((e = __bt_search(t, key, exactp)) == NULL)
- return (NULL);
- if (!*exactp)
- return (e);
-
- if (ISSET(t, B_DELCRSR)) {
- cpgno = t->bt_bcursor.pgno;
- cindex = t->bt_bcursor.index;
- } else {
- cpgno = P_INVALID;
- cindex = 0; /* GCC thinks it's uninitialized. */
- }
-
- /*
- * Walk backwards, skipping empty pages, 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. A special case is that we don't return a match
- * on records that the cursor references that have already been flagged
- * for deletion.
- */
- save = *e;
- h = e->page;
- found = 0;
- do {
- if (cpgno != h->pgno || cindex != e->index) {
- if (save.page->pgno != e->page->pgno) {
- mpool_put(t->bt_mp, save.page, 0);
- save = *e;
- } else
- save.index = e->index;
- found = 1;
- }
- /*
- * Make a special effort not to unpin the page the last (or
- * original) match was on, but also make sure it's unpinned
- * if an error occurs.
- */
- while (e->index == 0) {
- if (h->prevpg == P_INVALID)
- goto done1;
- 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 (NULL);
- }
- e->page = h;
- e->index = NEXTINDEX(h);
- }
- --e->index;
- } while (__bt_cmp(t, key, e) == 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.
- */
-done1: if (h->pgno != save.page->pgno)
- mpool_put(t->bt_mp, h, 0);
-
- /*
- * If still haven't found a record, the only possibility left is the
- * next one. Move forward one slot, skipping empty pages and check.
- */
- if (!found) {
- h = save.page;
- if (++save.index == NEXTINDEX(h)) {
- do {
- pg = h->nextpg;
- mpool_put(t->bt_mp, h, 0);
- if (pg == P_INVALID) {
- *exactp = 0;
- return (e);
- }
- if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
- return (NULL);
- } while ((save.index = NEXTINDEX(h)) == 0);
- save.page = h;
- }
- if (__bt_cmp(t, key, &save) != 0) {
- *exactp = 0;
- return (e);
- }
- }
- *e = save;
- *exactp = 1;
- return (e);
-}
diff --git a/lib/libc/db/btree/bt_open.c b/lib/libc/db/btree/bt_open.c
index 63162702051..8339edea618 100644
--- a/lib/libc/db/btree/bt_open.c
+++ b/lib/libc/db/btree/bt_open.c
@@ -1,4 +1,4 @@
-/* $NetBSD: bt_open.c,v 1.7 1995/02/27 13:20:27 cgd Exp $ */
+/* $NetBSD: bt_open.c,v 1.8 1996/05/03 21:50:46 cgd Exp $ */
/*-
* Copyright (c) 1990, 1993, 1994
@@ -38,9 +38,9 @@
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
-static char sccsid[] = "@(#)bt_open.c 8.7 (Berkeley) 6/16/94";
+static char sccsid[] = "@(#)bt_open.c 8.10 (Berkeley) 8/17/94";
#else
-static char rcsid[] = "$NetBSD: bt_open.c,v 1.7 1995/02/27 13:20:27 cgd Exp $";
+static char rcsid[] = "$NetBSD: bt_open.c,v 1.8 1996/05/03 21:50:46 cgd Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
@@ -67,6 +67,11 @@ static char rcsid[] = "$NetBSD: bt_open.c,v 1.7 1995/02/27 13:20:27 cgd Exp $";
#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));
@@ -163,7 +168,6 @@ __bt_open(fname, flags, mode, openinfo, dflags)
if ((t = (BTREE *)malloc(sizeof(BTREE))) == NULL)
goto err;
memset(t, 0, sizeof(BTREE));
- t->bt_bcursor.pgno = P_INVALID;
t->bt_fd = -1; /* Don't close unopened fd on error. */
t->bt_lorder = b.lorder;
t->bt_order = NOT;
@@ -173,9 +177,9 @@ __bt_open(fname, flags, mode, openinfo, dflags)
if ((t->bt_dbp = dbp = (DB *)malloc(sizeof(DB))) == NULL)
goto err;
- t->bt_flags = 0;
+ memset(t->bt_dbp, 0, sizeof(DB));
if (t->bt_lorder != machine_lorder)
- SET(t, B_NEEDSWAP);
+ F_SET(t, B_NEEDSWAP);
dbp->type = DB_BTREE;
dbp->internal = t;
@@ -192,9 +196,9 @@ __bt_open(fname, flags, mode, openinfo, dflags)
* open a backing temporary file. Otherwise, it's a disk-based tree.
*/
if (fname) {
- switch(flags & O_ACCMODE) {
+ switch (flags & O_ACCMODE) {
case O_RDONLY:
- SET(t, B_RDONLY);
+ F_SET(t, B_RDONLY);
break;
case O_RDWR:
break;
@@ -211,7 +215,7 @@ __bt_open(fname, flags, mode, openinfo, dflags)
goto einval;
if ((t->bt_fd = tmp()) == -1)
goto err;
- SET(t, B_INMEM);
+ F_SET(t, B_INMEM);
}
if (fcntl(t->bt_fd, F_SETFD, 1) == -1)
@@ -233,28 +237,28 @@ __bt_open(fname, flags, mode, openinfo, dflags)
* don't bother to return an error, we just clear the NEEDSWAP
* bit.
*/
- if (m.m_magic == BTREEMAGIC)
- CLR(t, B_NEEDSWAP);
+ if (m.magic == BTREEMAGIC)
+ F_CLR(t, B_NEEDSWAP);
else {
- SET(t, B_NEEDSWAP);
- M_32_SWAP(m.m_magic);
- M_32_SWAP(m.m_version);
- M_32_SWAP(m.m_psize);
- M_32_SWAP(m.m_free);
- M_32_SWAP(m.m_nrecs);
- M_32_SWAP(m.m_flags);
+ 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.m_magic != BTREEMAGIC || m.m_version != BTREEVERSION)
+ if (m.magic != BTREEMAGIC || m.version != BTREEVERSION)
goto eftype;
- if (m.m_psize < MINPSIZE || m.m_psize > MAX_PAGE_OFFSET + 1 ||
- m.m_psize & sizeof(indx_t) - 1)
+ if (m.psize < MINPSIZE || m.psize > MAX_PAGE_OFFSET + 1 ||
+ m.psize & sizeof(indx_t) - 1)
goto eftype;
- if (m.m_flags & ~SAVEMETA)
+ if (m.flags & ~SAVEMETA)
goto eftype;
- b.psize = m.m_psize;
- t->bt_flags |= m.m_flags;
- t->bt_free = m.m_free;
- t->bt_nrecs = m.m_nrecs;
+ 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.
@@ -270,11 +274,11 @@ __bt_open(fname, flags, mode, openinfo, dflags)
/* Set flag if duplicates permitted. */
if (!(b.flags & R_DUP))
- SET(t, B_NODUPS);
+ F_SET(t, B_NODUPS);
t->bt_free = P_INVALID;
t->bt_nrecs = 0;
- SET(t, B_METADIRTY);
+ F_SET(t, B_METADIRTY);
}
t->bt_psize = b.psize;
@@ -309,7 +313,7 @@ __bt_open(fname, flags, mode, openinfo, dflags)
if ((t->bt_mp =
mpool_open(NULL, t->bt_fd, t->bt_psize, ncache)) == NULL)
goto err;
- if (!ISSET(t, B_INMEM))
+ if (!F_ISSET(t, B_INMEM))
mpool_filter(t->bt_mp, __bt_pgin, __bt_pgout, t);
/* Create a root page if new tree. */
@@ -318,11 +322,11 @@ __bt_open(fname, flags, mode, openinfo, dflags)
/* Global flags. */
if (dflags & DB_LOCK)
- SET(t, B_DB_LOCK);
+ F_SET(t, B_DB_LOCK);
if (dflags & DB_SHMEM)
- SET(t, B_DB_SHMEM);
+ F_SET(t, B_DB_SHMEM);
if (dflags & DB_TXN)
- SET(t, B_DB_TXN);
+ F_SET(t, B_DB_TXN);
return (dbp);
@@ -438,7 +442,7 @@ __bt_fd(dbp)
}
/* In-memory database can't have a file descriptor. */
- if (ISSET(t, B_INMEM)) {
+ if (F_ISSET(t, B_INMEM)) {
errno = ENOENT;
return (-1);
}
diff --git a/lib/libc/db/btree/bt_overflow.c b/lib/libc/db/btree/bt_overflow.c
index b5c43c60435..fcae9ef013b 100644
--- a/lib/libc/db/btree/bt_overflow.c
+++ b/lib/libc/db/btree/bt_overflow.c
@@ -1,4 +1,4 @@
-/* $NetBSD: bt_overflow.c,v 1.5 1995/02/27 13:20:33 cgd Exp $ */
+/* $NetBSD: bt_overflow.c,v 1.6 1996/05/03 21:50:48 cgd Exp $ */
/*-
* Copyright (c) 1990, 1993, 1994
@@ -38,9 +38,9 @@
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
-static char sccsid[] = "@(#)bt_overflow.c 8.4 (Berkeley) 6/20/94";
+static char sccsid[] = "@(#)bt_overflow.c 8.5 (Berkeley) 7/16/94";
#else
-static char rcsid[] = "$NetBSD: bt_overflow.c,v 1.5 1995/02/27 13:20:33 cgd Exp $";
+static char rcsid[] = "$NetBSD: bt_overflow.c,v 1.6 1996/05/03 21:50:48 cgd Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
@@ -87,7 +87,7 @@ __ovfl_get(t, p, ssz, buf, bufsz)
BTREE *t;
void *p;
size_t *ssz;
- char **buf;
+ void **buf;
size_t *bufsz;
{
PAGE *h;
diff --git a/lib/libc/db/btree/bt_page.c b/lib/libc/db/btree/bt_page.c
index d6a44941854..7b977bd0d36 100644
--- a/lib/libc/db/btree/bt_page.c
+++ b/lib/libc/db/btree/bt_page.c
@@ -1,7 +1,7 @@
-/* $NetBSD: bt_page.c,v 1.5 1995/02/27 13:20:36 cgd Exp $ */
+/* $NetBSD: bt_page.c,v 1.6 1996/05/03 21:50:49 cgd Exp $ */
/*-
- * Copyright (c) 1990, 1993
+ * 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
@@ -35,9 +35,9 @@
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
-static char sccsid[] = "@(#)bt_page.c 8.2 (Berkeley) 2/21/94";
+static char sccsid[] = "@(#)bt_page.c 8.3 (Berkeley) 7/14/94";
#else
-static char rcsid[] = "$NetBSD: bt_page.c,v 1.5 1995/02/27 13:20:36 cgd Exp $";
+static char rcsid[] = "$NetBSD: bt_page.c,v 1.6 1996/05/03 21:50:49 cgd Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
@@ -49,7 +49,8 @@ static char rcsid[] = "$NetBSD: bt_page.c,v 1.5 1995/02/27 13:20:36 cgd Exp $";
#include "btree.h"
/*
- * __BT_FREE -- Put a page on the freelist.
+ * __bt_free --
+ * Put a page on the freelist.
*
* Parameters:
* t: tree
@@ -57,13 +58,16 @@ static char rcsid[] = "$NetBSD: bt_page.c,v 1.5 1995/02/27 13:20:36 cgd Exp $";
*
* 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 start of the free list. */
+ /* Insert the page at the head of the free list. */
h->prevpg = P_INVALID;
h->nextpg = t->bt_free;
t->bt_free = h->pgno;
@@ -73,7 +77,8 @@ __bt_free(t, h)
}
/*
- * __BT_NEW -- Get a new page, preferably from the freelist.
+ * __bt_new --
+ * Get a new page, preferably from the freelist.
*
* Parameters:
* t: tree
@@ -91,9 +96,9 @@ __bt_new(t, npg)
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;
- return (h);
+ *npg = t->bt_free;
+ t->bt_free = h->nextpg;
+ return (h);
}
return (mpool_new(t->bt_mp, npg));
}
diff --git a/lib/libc/db/btree/bt_put.c b/lib/libc/db/btree/bt_put.c
index 9ddc98d8ec1..5d13b062648 100644
--- a/lib/libc/db/btree/bt_put.c
+++ b/lib/libc/db/btree/bt_put.c
@@ -1,4 +1,4 @@
-/* $NetBSD: bt_put.c,v 1.7 1995/02/27 13:20:40 cgd Exp $ */
+/* $NetBSD: bt_put.c,v 1.8 1996/05/03 21:50:51 cgd Exp $ */
/*-
* Copyright (c) 1990, 1993, 1994
@@ -38,9 +38,9 @@
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
-static char sccsid[] = "@(#)bt_put.c 8.4 (Berkeley) 5/31/94";
+static char sccsid[] = "@(#)bt_put.c 8.8 (Berkeley) 7/26/94";
#else
-static char rcsid[] = "$NetBSD: bt_put.c,v 1.7 1995/02/27 13:20:40 cgd Exp $";
+static char rcsid[] = "$NetBSD: bt_put.c,v 1.8 1996/05/03 21:50:51 cgd Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
@@ -94,33 +94,38 @@ __bt_put(dbp, key, data, flags)
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 R_CURSOR:
- if (!ISSET(t, B_SEQINIT))
- goto einval;
- if (ISSET(t, B_DELCRSR))
- goto einval;
- break;
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:
-einval: errno = EINVAL;
- return (RET_ERROR);
- }
-
- if (ISSET(t, B_RDONLY)) {
- errno = EPERM;
+ errno = EINVAL;
return (RET_ERROR);
}
/*
- * If the key/data won't fit on a page, store it on indirect pages.
- * Only store the key on the overflow page if it's too big after the
- * data is on an overflow page.
+ * 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, these pages aren't recovered.
+ * If the insert fails later on, the overflow pages aren't recovered.
*/
dflags = 0;
if (key->size + data->size > t->bt_ovflsize) {
@@ -152,15 +157,15 @@ storekey: if (__ovfl_put(t, key, &pg) == RET_ERROR)
/* Replace the cursor. */
if (flags == R_CURSOR) {
- if ((h = mpool_get(t->bt_mp, t->bt_bcursor.pgno, 0)) == NULL)
+ if ((h = mpool_get(t->bt_mp, t->bt_cursor.pg.pgno, 0)) == NULL)
return (RET_ERROR);
- index = t->bt_bcursor.index;
+ 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 pin the returned page.
+ * 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)
@@ -169,34 +174,26 @@ storekey: if (__ovfl_put(t, key, &pg) == RET_ERROR)
index = e->index;
/*
- * Add the specified 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.
- *
- * Pages are split as required.
+ * 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;
- /*
- * One special case is if the cursor references the record and
- * it's been flagged for deletion. Then, we delete the record,
- * leaving the cursor there -- this means that the inserted
- * record will not be seen in a cursor scan.
- */
- if (ISSET(t, B_DELCRSR) && t->bt_bcursor.pgno == h->pgno &&
- t->bt_bcursor.index == index) {
- CLR(t, B_DELCRSR);
- goto delete;
- }
mpool_put(t->bt_mp, h, 0);
return (RET_SPECIAL);
default:
- if (!exact || !ISSET(t, B_NODUPS))
+ if (!exact || !F_ISSET(t, B_NODUPS))
break;
-delete: if (__bt_dleaf(t, h, index) == RET_ERROR) {
+ /*
+ * !!!
+ * 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);
}
@@ -226,6 +223,12 @@ delete: if (__bt_dleaf(t, h, index) == RET_ERROR) {
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) {
@@ -244,11 +247,10 @@ delete: if (__bt_dleaf(t, h, index) == RET_ERROR) {
mpool_put(t->bt_mp, h, MPOOL_DIRTY);
success:
- if (flags == R_SETCURSOR) {
- t->bt_bcursor.pgno = e->page->pgno;
- t->bt_bcursor.index = e->index;
- }
- SET(t, B_MODIFIED);
+ if (flags == R_SETCURSOR)
+ __bt_setcur(t, e->page->pgno, e->index);
+
+ F_SET(t, B_MODIFIED);
return (RET_SUCCESS);
}
@@ -284,8 +286,8 @@ bt_fast(t, key, data, exactp)
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.
+ * 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 (h->upper - h->lower < nbytes + sizeof(indx_t))
diff --git a/lib/libc/db/btree/bt_search.c b/lib/libc/db/btree/bt_search.c
index c98fe7346ea..d0832b9d383 100644
--- a/lib/libc/db/btree/bt_search.c
+++ b/lib/libc/db/btree/bt_search.c
@@ -1,7 +1,7 @@
-/* $NetBSD: bt_search.c,v 1.7 1995/02/27 13:20:44 cgd Exp $ */
+/* $NetBSD: bt_search.c,v 1.8 1996/05/03 21:50:52 cgd Exp $ */
/*-
- * Copyright (c) 1990, 1993
+ * 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
@@ -38,9 +38,9 @@
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
-static char sccsid[] = "@(#)bt_search.c 8.6 (Berkeley) 3/15/94";
+static char sccsid[] = "@(#)bt_search.c 8.8 (Berkeley) 7/31/94";
#else
-static char rcsid[] = "$NetBSD: bt_search.c,v 1.7 1995/02/27 13:20:44 cgd Exp $";
+static char rcsid[] = "$NetBSD: bt_search.c,v 1.8 1996/05/03 21:50:52 cgd Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
@@ -51,11 +51,12 @@ static char rcsid[] = "$NetBSD: bt_search.c,v 1.7 1995/02/27 13:20:44 cgd Exp $"
#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 *));
+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.
+ * __bt_search --
+ * Search a btree for a key.
*
* Parameters:
* t: tree to search
@@ -101,24 +102,26 @@ __bt_search(t, key, exactp)
}
/*
- * If it's a leaf page, and duplicates aren't allowed, we're
- * done. If duplicates are allowed, it's possible that there
- * were duplicate keys on duplicate pages, and they were later
- * deleted, so we could be on a page with no matches while
- * there are matches on other pages. If we're at the start or
- * end of a page, check on both sides.
+ * 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) {
- t->bt_cur.index = base;
- *exactp = 0;
- if (!ISSET(t, B_NODUPS)) {
+ if (!F_ISSET(t, B_NODUPS)) {
if (base == 0 &&
- bt_sprev(t, h, key, exactp))
+ h->prevpg != P_INVALID &&
+ __bt_sprev(t, h, key, exactp))
return (&t->bt_cur);
if (base == NEXTINDEX(h) &&
- bt_snext(t, h, key, exactp))
+ 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);
}
@@ -131,111 +134,86 @@ __bt_search(t, key, exactp)
*/
index = base ? base - 1 : base;
-next: if (__bt_push(t, h->pgno, index) == RET_ERROR)
- return (NULL);
+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.
+ * __bt_snext --
+ * Check for an exact match after the key.
*
* Parameters:
- * t: tree to search
- * h: current page.
- * key: key to find
+ * 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)
+__bt_snext(t, h, key, exactp)
BTREE *t;
PAGE *h;
const DBT *key;
int *exactp;
{
EPG e;
- PAGE *tp;
- pgno_t pg;
- /* Skip until reach the end of the tree or a key. */
- for (pg = h->nextpg; pg != P_INVALID;) {
- if ((tp = mpool_get(t->bt_mp, pg, 0)) == NULL) {
- mpool_put(t->bt_mp, h, 0);
- return (NULL);
- }
- if (NEXTINDEX(tp) != 0)
- break;
- pg = tp->prevpg;
- mpool_put(t->bt_mp, tp, 0);
- }
/*
- * The key is either an exact match, or not as good as
- * the one we already have.
+ * Get the next page. The key is either an exact
+ * match, or not as good as the one we already have.
*/
- if (pg != P_INVALID) {
- e.page = tp;
- e.index = NEXTINDEX(tp) - 1;
- if (__bt_cmp(t, key, &e) == 0) {
- mpool_put(t->bt_mp, h, 0);
- t->bt_cur = e;
- *exactp = 1;
- return (1);
- }
+ 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.
+ * __bt_sprev --
+ * Check for an exact match before the key.
*
* Parameters:
- * t: tree to search
- * h: current page.
- * key: key to find
+ * 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)
+__bt_sprev(t, h, key, exactp)
BTREE *t;
PAGE *h;
const DBT *key;
int *exactp;
{
EPG e;
- PAGE *tp;
- pgno_t pg;
- /* Skip until reach the beginning of the tree or a key. */
- for (pg = h->prevpg; pg != P_INVALID;) {
- if ((tp = mpool_get(t->bt_mp, pg, 0)) == NULL) {
- mpool_put(t->bt_mp, h, 0);
- return (NULL);
- }
- if (NEXTINDEX(tp) != 0)
- break;
- pg = tp->prevpg;
- mpool_put(t->bt_mp, tp, 0);
- }
/*
- * The key is either an exact match, or not as good as
- * the one we already have.
+ * Get the previous page. The key is either an exact
+ * match, or not as good as the one we already have.
*/
- if (pg != P_INVALID) {
- e.page = tp;
- e.index = NEXTINDEX(tp) - 1;
- if (__bt_cmp(t, key, &e) == 0) {
- mpool_put(t->bt_mp, h, 0);
- t->bt_cur = e;
- *exactp = 1;
- return (1);
- }
+ 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/lib/libc/db/btree/bt_seq.c b/lib/libc/db/btree/bt_seq.c
index f029cc3e174..7717593a589 100644
--- a/lib/libc/db/btree/bt_seq.c
+++ b/lib/libc/db/btree/bt_seq.c
@@ -1,7 +1,7 @@
-/* $NetBSD: bt_seq.c,v 1.6 1995/02/27 13:20:51 cgd Exp $ */
+/* $NetBSD: bt_seq.c,v 1.7 1996/05/03 21:50:54 cgd Exp $ */
/*-
- * Copyright (c) 1990, 1993
+ * 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
@@ -38,9 +38,9 @@
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
-static char sccsid[] = "@(#)bt_seq.c 8.2 (Berkeley) 9/7/93";
+static char sccsid[] = "@(#)bt_seq.c 8.7 (Berkeley) 7/20/94";
#else
-static char rcsid[] = "$NetBSD: bt_seq.c,v 1.6 1995/02/27 13:20:51 cgd Exp $";
+static char rcsid[] = "$NetBSD: bt_seq.c,v 1.7 1996/05/03 21:50:54 cgd Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
@@ -54,24 +54,21 @@ static char rcsid[] = "$NetBSD: bt_seq.c,v 1.6 1995/02/27 13:20:51 cgd Exp $";
#include <db.h>
#include "btree.h"
-static int bt_seqadv __P((BTREE *, EPG *, int));
-static int bt_seqset __P((BTREE *, EPG *, DBT *, int));
+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.
- *
- * Each tree has an EPGNO which has the current position of the cursor. The
- * cursor has to survive deletions/insertions in the tree without losing its
- * position. This is done by noting deletions without doing them, and then
- * doing them when the cursor moves (or the tree is closed).
+ * 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.
+ * __bt_seq --
+ * Btree sequential scan interface.
*
* Parameters:
* dbp: pointer to access method
@@ -102,21 +99,21 @@ __bt_seq(dbp, key, data, flags)
/*
* If scan unitialized 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.
+ * the scan to a specific key. Both __bt_seqset and __bt_seqadv pin
+ * the page the cursor references if they're successful.
*/
- switch(flags) {
+ switch (flags) {
case R_NEXT:
case R_PREV:
- if (ISSET(t, B_SEQINIT)) {
- status = bt_seqadv(t, &e, flags);
+ if (F_ISSET(&t->bt_cursor, CURS_INIT)) {
+ status = __bt_seqadv(t, &e, flags);
break;
}
/* FALLTHROUGH */
- case R_CURSOR:
case R_FIRST:
case R_LAST:
- status = bt_seqset(t, &e, key, flags);
+ case R_CURSOR:
+ status = __bt_seqset(t, &e, key, flags);
break;
default:
errno = EINVAL;
@@ -124,27 +121,26 @@ __bt_seq(dbp, key, data, flags)
}
if (status == RET_SUCCESS) {
- status = __bt_ret(t, &e, key, data);
+ __bt_setcur(t, e.page->pgno, e.index);
- /* Update the actual cursor. */
- t->bt_bcursor.pgno = e.page->pgno;
- t->bt_bcursor.index = 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 (ISSET(t, B_DB_LOCK))
+ if (F_ISSET(t, B_DB_LOCK))
mpool_put(t->bt_mp, e.page, 0);
else
t->bt_pinned = e.page;
- SET(t, B_SEQINIT);
}
return (status);
}
/*
- * BT_SEQSET -- Set the sequential scan to a specific key.
+ * __bt_seqset --
+ * Set the sequential scan to a specific key.
*
* Parameters:
* t: tree
@@ -159,87 +155,50 @@ __bt_seq(dbp, key, data, flags)
* RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
*/
static int
-bt_seqset(t, ep, key, flags)
+__bt_seqset(t, ep, key, flags)
BTREE *t;
EPG *ep;
DBT *key;
int flags;
{
- EPG *e;
PAGE *h;
pgno_t pg;
int exact;
/*
- * Delete any already deleted record that we've been saving because
- * the cursor pointed to it. Since going to a specific key, should
- * delete any logically deleted records so they aren't found.
- */
- if (ISSET(t, B_DELCRSR) && __bt_crsrdel(t, &t->bt_bcursor))
- return (RET_ERROR);
-
- /*
- * 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.
+ * 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) {
+ 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 run out
- * of keys, return RET_SPECIAL.
+ * 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);
}
- e = __bt_first(t, key, &exact); /* Returns pinned page. */
- if (e == NULL)
- return (RET_ERROR);
- /*
- * If at the end of a page, skip any empty pages and find the
- * next entry.
- */
- if (e->index == NEXTINDEX(e->page)) {
- h = e->page;
- do {
- 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);
- } while (NEXTINDEX(h) == 0);
- e->index = 0;
- e->page = h;
- }
- *ep = *e;
- break;
+ 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);
}
-
- /* Skip any empty pages. */
- while (NEXTINDEX(h) == 0 && h->nextpg != P_INVALID) {
- pg = h->nextpg;
- mpool_put(t->bt_mp, h, 0);
- if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
- return (RET_ERROR);
- }
-
- if (NEXTINDEX(h) == 0) {
- mpool_put(t->bt_mp, h, 0);
- return (RET_SPECIAL);
- }
-
ep->page = h;
ep->index = 0;
break;
@@ -249,25 +208,19 @@ bt_seqset(t, ep, key, flags)
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);
}
- /* Skip any empty pages. */
- while (NEXTINDEX(h) == 0 && h->prevpg != P_INVALID) {
- pg = h->prevpg;
- mpool_put(t->bt_mp, h, 0);
- if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
- return (RET_ERROR);
- }
-
- if (NEXTINDEX(h) == 0) {
- mpool_put(t->bt_mp, h, 0);
- return (RET_SPECIAL);
- }
-
ep->page = h;
ep->index = NEXTINDEX(h) - 1;
break;
@@ -276,7 +229,8 @@ bt_seqset(t, ep, key, flags)
}
/*
- * BT_SEQADVANCE -- Advance the sequential scan.
+ * __bt_seqadvance --
+ * Advance the sequential scan.
*
* Parameters:
* t: tree
@@ -289,98 +243,224 @@ bt_seqset(t, ep, key, flags)
* RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
*/
static int
-bt_seqadv(t, e, flags)
+__bt_seqadv(t, ep, flags)
BTREE *t;
- EPG *e;
+ EPG *ep;
int flags;
{
- EPGNO *c, delc;
+ CURSOR *c;
PAGE *h;
indx_t index;
pgno_t pg;
+ int exact;
- /* Save the current cursor if going to delete it. */
- c = &t->bt_bcursor;
- if (ISSET(t, B_DELCRSR))
- delc = *c;
+ /*
+ * 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;
- if ((h = mpool_get(t->bt_mp, c->pgno, 0)) == NULL)
+ /*
+ * 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.
+ * 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.
*/
- index = c->index;
- switch(flags) {
+ 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)) {
- do {
- 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);
- } while (NEXTINDEX(h) == 0);
+ 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. */
- if (index-- == 0) {
- do {
- 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);
- } while (NEXTINDEX(h) == 0);
- index = NEXTINDEX(h) - 1;
+ /*
+ * 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;
}
- e->page = h;
- e->index = index;
+ 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;
/*
- * Delete any already deleted record that we've been saving because the
- * cursor pointed to it. This could cause the new index to be shifted
- * down by one if the record we're deleting is on the same page and has
- * a larger index.
+ * 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 (ISSET(t, B_DELCRSR)) {
- CLR(t, B_DELCRSR); /* Don't try twice. */
- if (c->pgno == delc.pgno && c->index > delc.index)
- --c->index;
- if (__bt_crsrdel(t, &delc))
+ if ((ep = __bt_search(t, key, exactp)) == NULL)
+ return (NULL);
+ 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_CRSRDEL -- Delete the record referenced by the cursor.
+ * __bt_setcur --
+ * Set the cursor to an entry in the tree.
*
* Parameters:
- * t: tree
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS
+ * t: the tree
+ * pgno: page number
+ * index: page index
*/
-int
-__bt_crsrdel(t, c)
+void
+__bt_setcur(t, pgno, index)
BTREE *t;
- EPGNO *c;
+ pgno_t pgno;
+ u_int index;
{
- PAGE *h;
- int status;
+ /* 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);
- CLR(t, B_DELCRSR); /* Don't try twice. */
- if ((h = mpool_get(t->bt_mp, c->pgno, 0)) == NULL)
- return (RET_ERROR);
- status = __bt_dleaf(t, h, c->index);
- mpool_put(t->bt_mp, h, MPOOL_DIRTY);
- return (status);
+ /* 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/lib/libc/db/btree/bt_split.c b/lib/libc/db/btree/bt_split.c
index 22334c1e430..110e3f9dd1d 100644
--- a/lib/libc/db/btree/bt_split.c
+++ b/lib/libc/db/btree/bt_split.c
@@ -1,4 +1,4 @@
-/* $NetBSD: bt_split.c,v 1.5 1995/02/27 13:20:55 cgd Exp $ */
+/* $NetBSD: bt_split.c,v 1.6 1996/05/03 21:50:56 cgd Exp $ */
/*-
* Copyright (c) 1990, 1993, 1994
@@ -38,9 +38,9 @@
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
-static char sccsid[] = "@(#)bt_split.c 8.6 (Berkeley) 6/16/94";
+static char sccsid[] = "@(#)bt_split.c 8.9 (Berkeley) 7/26/94";
#else
-static char rcsid[] = "$NetBSD: bt_split.c,v 1.5 1995/02/27 13:20:55 cgd Exp $";
+static char rcsid[] = "$NetBSD: bt_split.c,v 1.6 1996/05/03 21:50:56 cgd Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
@@ -123,14 +123,14 @@ __bt_split(t, sp, key, data, flags, ilen, argskip)
*/
h->linp[skip] = h->upper -= ilen;
dest = (char *)h + h->upper;
- if (ISSET(t, R_RECNO))
+ 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 &&
- (ISSET(t, R_RECNO) ?
+ (F_ISSET(t, R_RECNO) ?
bt_rroot(t, sp, l, r) : bt_broot(t, sp, l, r)) == RET_ERROR)
goto err2;
@@ -238,7 +238,7 @@ __bt_split(t, sp, key, data, flags, ilen, argskip)
}
/* Insert the key into the parent page. */
- switch(rchild->flags & P_TYPE) {
+ switch (rchild->flags & P_TYPE) {
case P_BINTERNAL:
h->linp[skip] = h->upper -= nbytes;
dest = (char *)h + h->linp[skip];
@@ -303,7 +303,7 @@ __bt_split(t, sp, key, data, flags, ilen, argskip)
/* If the root page was split, make it look right. */
if (sp->pgno == P_ROOT &&
- (ISSET(t, R_RECNO) ?
+ (F_ISSET(t, R_RECNO) ?
bt_rroot(t, sp, l, r) : bt_broot(t, sp, l, r)) == RET_ERROR)
goto err1;
@@ -396,6 +396,9 @@ bt_page(t, h, lp, rp, skip, ilen)
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;
@@ -411,7 +414,7 @@ bt_page(t, h, lp, rp, skip, ilen)
return (NULL);
}
tp->prevpg = r->pgno;
- mpool_put(t->bt_mp, tp, 0);
+ mpool_put(t->bt_mp, tp, MPOOL_DIRTY);
}
/*
@@ -558,7 +561,7 @@ bt_broot(t, h, l, r)
dest = (char *)h + h->upper;
WR_BINTERNAL(dest, 0, l->pgno, 0);
- switch(h->flags & P_TYPE) {
+ switch (h->flags & P_TYPE) {
case P_BLEAF:
bl = GETBLEAF(r, 0);
nbytes = NBINTERNAL(bl->ksize);
@@ -621,8 +624,8 @@ bt_psplit(t, h, l, r, pskip, ilen)
{
BINTERNAL *bi;
BLEAF *bl;
+ CURSOR *c;
RLEAF *rl;
- EPGNO *c;
PAGE *rval;
void *src;
indx_t full, half, nxt, off, skip, top, used;
@@ -710,19 +713,16 @@ bt_psplit(t, h, l, r, pskip, ilen)
* 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.
- *
- * Don't bother checking for the B_SEQINIT flag, the page number will
- * be P_INVALID.
*/
- c = &t->bt_bcursor;
- if (c->pgno == h->pgno) {
- if (c->index >= skip)
- ++c->index;
- if (c->index < nxt) /* Left page. */
- c->pgno = l->pgno;
+ 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->pgno = r->pgno;
- c->index -= nxt;
+ c->pg.pgno = r->pgno;
+ c->pg.index -= nxt;
}
}
diff --git a/lib/libc/db/btree/bt_stack.c b/lib/libc/db/btree/bt_stack.c
index 7199ae9b090..e69de29bb2d 100644
--- a/lib/libc/db/btree/bt_stack.c
+++ b/lib/libc/db/btree/bt_stack.c
@@ -1,102 +0,0 @@
-/* $NetBSD: bt_stack.c,v 1.5 1995/02/27 13:21:01 cgd Exp $ */
-
-/*-
- * 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)
-#if 0
-static char sccsid[] = "@(#)bt_stack.c 8.4 (Berkeley) 6/20/94";
-#else
-static char rcsid[] = "$NetBSD: bt_stack.c,v 1.5 1995/02/27 13:21:01 cgd Exp $";
-#endif
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/types.h>
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <db.h>
-#include "btree.h"
-
-/*
- * When a page splits, a new record has to be inserted into its parent page.
- * This page may have to split as well, all the way up to the root. Since
- * parent pointers in each page would be expensive, we maintain a stack of
- * parent pages as we descend the tree.
- *
- * XXX
- * This is a concurrency problem -- if user a builds a stack, then user b
- * splits the tree, then user a tries to split the tree, there's a new level
- * in the tree that user a doesn't know about.
- */
-
-/*
- * __BT_PUSH -- Push parent page info onto the stack (LIFO).
- *
- * Parameters:
- * t: tree
- * pgno: page
- * index: page index
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS
- */
-int
-__bt_push(t, pgno, index)
- BTREE *t;
- pgno_t pgno;
- indx_t index;
-{
- size_t sz;
-
- if (t->bt_sp == t->bt_maxstack) {
- t->bt_maxstack += 50;
- sz = t->bt_maxstack * sizeof(EPGNO);
- t->bt_stack = (EPGNO *)(t->bt_stack == NULL ?
- malloc(sz) : realloc(t->bt_stack, sz));
- if (t->bt_stack == NULL) {
- t->bt_maxstack -= 50;
- return (RET_ERROR);
- }
- }
-
- t->bt_stack[t->bt_sp].pgno = pgno;
- t->bt_stack[t->bt_sp].index = index;
- ++t->bt_sp;
- return (RET_SUCCESS);
-}
diff --git a/lib/libc/db/btree/bt_utils.c b/lib/libc/db/btree/bt_utils.c
index f9acf0ab8a1..2637f719a18 100644
--- a/lib/libc/db/btree/bt_utils.c
+++ b/lib/libc/db/btree/bt_utils.c
@@ -1,4 +1,4 @@
-/* $NetBSD: bt_utils.c,v 1.6 1995/02/27 13:21:04 cgd Exp $ */
+/* $NetBSD: bt_utils.c,v 1.7 1996/05/03 21:50:58 cgd Exp $ */
/*-
* Copyright (c) 1990, 1993, 1994
@@ -38,9 +38,9 @@
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
-static char sccsid[] = "@(#)bt_utils.c 8.5 (Berkeley) 6/20/94";
+static char sccsid[] = "@(#)bt_utils.c 8.8 (Berkeley) 7/20/94";
#else
-static char rcsid[] = "$NetBSD: bt_utils.c,v 1.6 1995/02/27 13:21:04 cgd Exp $";
+static char rcsid[] = "$NetBSD: bt_utils.c,v 1.7 1996/05/03 21:50:58 cgd Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
@@ -54,81 +54,91 @@ static char rcsid[] = "$NetBSD: bt_utils.c,v 1.6 1995/02/27 13:21:04 cgd Exp $";
#include "btree.h"
/*
- * __BT_RET -- Build return key/data pair as a result of search or scan.
+ * __bt_ret --
+ * Build return key/data pair.
*
* Parameters:
* t: tree
- * d: LEAF to be returned to the user.
+ * e: key/data pair to be returned
* key: user's key structure (NULL if not to be filled in)
- * data: user's data structure
+ * 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, data)
+__bt_ret(t, e, key, rkey, data, rdata, copy)
BTREE *t;
EPG *e;
- DBT *key, *data;
+ DBT *key, *rkey, *data, *rdata;
+ int copy;
{
- register BLEAF *bl;
- register void *p;
+ BLEAF *bl;
+ void *p;
bl = GETBLEAF(e->page, e->index);
/*
- * We always copy big keys/data to make them contigous. Otherwise,
- * we leave the page pinned and don't copy unless the user specified
+ * We must copy big keys/data to make them contigous. Otherwise,
+ * leave the page pinned and don't copy unless the user specified
* concurrent access.
*/
- if (bl->flags & P_BIGDATA) {
- if (__ovfl_get(t, bl->bytes + bl->ksize,
- &data->size, &t->bt_dbuf, &t->bt_dbufsz))
+ 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);
- data->data = t->bt_dbuf;
- } else if (ISSET(t, B_DB_LOCK)) {
- /* Use +1 in case the first record retrieved is 0 length. */
- if (bl->dsize + 1 > t->bt_dbufsz) {
- p = (void *)(t->bt_dbuf == NULL ?
- malloc(bl->dsize + 1) :
- realloc(t->bt_dbuf, bl->dsize + 1));
+ 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);
- t->bt_dbuf = p;
- t->bt_dbufsz = bl->dsize + 1;
+ rkey->data = p;
+ rkey->size = bl->ksize;
}
- memmove(t->bt_dbuf, bl->bytes + bl->ksize, bl->dsize);
- data->size = bl->dsize;
- data->data = t->bt_dbuf;
+ memmove(rkey->data, bl->bytes, bl->ksize);
+ key->size = bl->ksize;
+ key->data = rkey->data;
} else {
- data->size = bl->dsize;
- data->data = bl->bytes + bl->ksize;
+ key->size = bl->ksize;
+ key->data = bl->bytes;
}
- if (key == NULL)
+dataonly:
+ if (data == NULL)
return (RET_SUCCESS);
- if (bl->flags & P_BIGKEY) {
- if (__ovfl_get(t, bl->bytes,
- &key->size, &t->bt_kbuf, &t->bt_kbufsz))
+ if (bl->flags & P_BIGDATA) {
+ if (__ovfl_get(t, bl->bytes + bl->ksize,
+ &data->size, &rdata->data, &rdata->size))
return (RET_ERROR);
- key->data = t->bt_kbuf;
- } else if (ISSET(t, B_DB_LOCK)) {
- if (bl->ksize > t->bt_kbufsz) {
- p = (void *)(t->bt_kbuf == NULL ?
- malloc(bl->ksize) : realloc(t->bt_kbuf, bl->ksize));
+ 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);
- t->bt_kbuf = p;
- t->bt_kbufsz = bl->ksize;
+ rdata->data = p;
+ rdata->size = bl->dsize + 1;
}
- memmove(t->bt_kbuf, bl->bytes, bl->ksize);
- key->size = bl->ksize;
- key->data = t->bt_kbuf;
+ memmove(rdata->data, bl->bytes + bl->ksize, bl->dsize);
+ data->size = bl->dsize;
+ data->data = rdata->data;
} else {
- key->size = bl->ksize;
- key->data = bl->bytes;
+ data->size = bl->dsize;
+ data->data = bl->bytes + bl->ksize;
}
+
return (RET_SUCCESS);
}
@@ -189,9 +199,9 @@ __bt_cmp(t, k1, e)
if (bigkey) {
if (__ovfl_get(t, bigkey,
- &k2.size, &t->bt_dbuf, &t->bt_dbufsz))
+ &k2.size, &t->bt_rdata.data, &t->bt_rdata.size))
return (RET_ERROR);
- k2.data = t->bt_dbuf;
+ k2.data = t->bt_rdata.data;
}
return ((*t->bt_cmp)(k1, &k2));
}
diff --git a/lib/libc/db/btree/btree.h b/lib/libc/db/btree/btree.h
index 747ed93638e..d2bb945a1c3 100644
--- a/lib/libc/db/btree/btree.h
+++ b/lib/libc/db/btree/btree.h
@@ -1,4 +1,4 @@
-/* $NetBSD: btree.h,v 1.8 1995/02/27 13:21:08 cgd Exp $ */
+/* $NetBSD: btree.h,v 1.9 1996/05/03 21:51:00 cgd Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
@@ -35,9 +35,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)btree.h 8.6 (Berkeley) 5/31/94
+ * @(#)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>
#define DEFMINKEYPAGE (2) /* Minimum keys per page */
@@ -81,8 +86,9 @@ typedef struct _page {
} 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 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))
/*
@@ -101,8 +107,7 @@ typedef struct _page {
* 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 LALIGN(n) (((n) + sizeof(pgno_t) - 1) & ~(sizeof(pgno_t) - 1))
#define NOVFLSIZE (sizeof(pgno_t) + sizeof(u_int32_t))
/*
@@ -124,11 +129,11 @@ typedef struct _binternal {
} BINTERNAL;
/* Get the page's BINTERNAL structure at index indx. */
-#define GETBINTERNAL(pg, indx) \
+#define GETBINTERNAL(pg, indx) \
((BINTERNAL *)((char *)(pg) + (pg)->linp[indx]))
/* Get the number of bytes in the entry. */
-#define NBINTERNAL(len) \
+#define NBINTERNAL(len) \
LALIGN(sizeof(u_int32_t) + sizeof(pgno_t) + sizeof(u_char) + (len))
/* Copy a BINTERNAL entry to the page. */
@@ -151,18 +156,18 @@ typedef struct _rinternal {
} RINTERNAL;
/* Get the page's RINTERNAL structure at index indx. */
-#define GETRINTERNAL(pg, indx) \
+#define GETRINTERNAL(pg, indx) \
((RINTERNAL *)((char *)(pg) + (pg)->linp[indx]))
/* Get the number of bytes in the entry. */
-#define NRINTERNAL \
+#define NRINTERNAL \
LALIGN(sizeof(recno_t) + sizeof(pgno_t))
/* Copy a RINTERAL entry to the page. */
-#define WR_RINTERNAL(p, nrecs, pgno) { \
- *(recno_t *)p = nrecs; \
- p += sizeof(recno_t); \
- *(pgno_t *)p = pgno; \
+#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. */
@@ -174,15 +179,15 @@ typedef struct _bleaf {
} BLEAF;
/* Get the page's BLEAF structure at index indx. */
-#define GETBLEAF(pg, 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) + \
+#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. */
@@ -206,14 +211,14 @@ typedef struct _rleaf {
} RLEAF;
/* Get the page's RLEAF structure at index indx. */
-#define GETRLEAF(pg, 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) \
+#define NRLEAFDBT(dsize) \
LALIGN(sizeof(u_int32_t) + sizeof(u_char) + (dsize))
/* Copy a RLEAF entry to the page. */
@@ -234,12 +239,6 @@ typedef struct _rleaf {
* 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.
- *
- * One comment about cursors. The cursor key is never removed from the tree,
- * even if deleted. This is because it is quite difficult to decide where the
- * cursor should be when other keys have been inserted/deleted in the tree;
- * duplicate keys make it impossible. This scheme does require extra work
- * though, to make sure that we don't perform an operation on a deleted key.
*/
typedef struct _epgno {
pgno_t pgno; /* the page number */
@@ -252,53 +251,90 @@ typedef struct _epg {
} EPG;
/*
- * The metadata of the tree. The m_nrecs field is used only by the RECNO code.
+ * 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 m_magic; /* magic number */
- u_int32_t m_version; /* version */
- u_int32_t m_psize; /* page size */
- u_int32_t m_free; /* page number of first free page */
- u_int32_t m_nrecs; /* R: number of records */
+ 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 m_flags; /* bt_flags & SAVEMETA */
- u_int32_t m_unused; /* unused */
+ u_int32_t flags; /* bt_flags & SAVEMETA */
} BTMETA;
/* The in-memory btree/recno data structure. */
typedef struct _btree {
- MPOOL *bt_mp; /* memory pool cookie */
+ MPOOL *bt_mp; /* memory pool cookie */
- DB *bt_dbp; /* pointer to enclosing DB */
+ DB *bt_dbp; /* pointer to enclosing DB */
- EPG bt_cur; /* current (pinned) page */
- PAGE *bt_pinned; /* page pinned across calls */
+ EPG bt_cur; /* current (pinned) page */
+ PAGE *bt_pinned; /* page pinned across calls */
- EPGNO bt_bcursor; /* B: btree cursor */
- recno_t bt_rcursor; /* R: recno cursor (1-based) */
+ CURSOR bt_cursor; /* cursor */
-#define BT_POP(t) (t->bt_sp ? t->bt_stack + --t->bt_sp : NULL)
-#define BT_CLR(t) (t->bt_sp = 0)
- EPGNO *bt_stack; /* stack of parent pages */
- u_int bt_sp; /* current stack pointer */
- u_int bt_maxstack; /* largest stack */
+#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 */
- char *bt_kbuf; /* key buffer */
- size_t bt_kbufsz; /* key buffer size */
- char *bt_dbuf; /* data buffer */
- size_t bt_dbufsz; /* data buffer size */
+ DBT bt_rkey; /* returned key */
+ DBT bt_rdata; /* returned data */
- int bt_fd; /* tree file descriptor */
+ int bt_fd; /* tree file descriptor */
- pgno_t bt_free; /* next free page */
+ 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 */
+ 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 */
+ EPGNO bt_last; /* last insert */
/* B: key comparison function */
int (*bt_cmp) __P((const DBT *, const DBT *));
@@ -307,49 +343,43 @@ typedef struct _btree {
/* 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 */
+ 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. */
+ 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 */
+ 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_DELCRSR 0x00001 /* cursor has been deleted */
-#define B_INMEM 0x00002 /* in-memory tree */
-#define B_METADIRTY 0x00004 /* need to write metadata */
-#define B_MODIFIED 0x00008 /* tree modified */
-#define B_NEEDSWAP 0x00010 /* if byte order requires swapping */
+#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 B_RDONLY 0x00040 /* read-only tree */
#define R_RECNO 0x00080 /* record oriented tree */
-#define B_SEQINIT 0x00100 /* sequential scan initialized */
-
-#define R_CLOSEFP 0x00200 /* opened a file pointer */
-#define R_EOF 0x00400 /* end of input file reached. */
-#define R_FIXLEN 0x00800 /* fixed length records */
-#define R_MEMMAPPED 0x01000 /* memory mapped file. */
-#define R_INMEM 0x02000 /* in-memory file */
-#define R_MODIFIED 0x04000 /* modified file */
-#define R_RDONLY 0x08000 /* read-only file */
-#define B_DB_LOCK 0x10000 /* DB_LOCK specified. */
-#define B_DB_SHMEM 0x20000 /* DB_SHMEM specified. */
-#define B_DB_TXN 0x40000 /* DB_TXN specified. */
-
- u_int32_t bt_flags; /* btree state */
+#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;
-#define SET(t, f) ((t)->bt_flags |= (f))
-#define CLR(t, f) ((t)->bt_flags &= ~(f))
-#define ISSET(t, f) ((t)->bt_flags & (f))
-
#include "extern.h"
diff --git a/lib/libc/db/btree/extern.h b/lib/libc/db/btree/extern.h
index 6d09c2eb204..6a4fddf61c4 100644
--- a/lib/libc/db/btree/extern.h
+++ b/lib/libc/db/btree/extern.h
@@ -1,7 +1,7 @@
-/* $NetBSD: extern.h,v 1.5 1995/02/27 13:21:12 cgd Exp $ */
+/* $NetBSD: extern.h,v 1.6 1996/05/03 21:51:01 cgd Exp $ */
/*-
- * Copyright (c) 1991, 1993
+ * 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
@@ -32,7 +32,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)extern.h 8.4 (Berkeley) 6/4/94
+ * @(#)extern.h 8.10 (Berkeley) 7/20/94
*/
int __bt_close __P((DB *));
@@ -41,9 +41,8 @@ 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 *, PAGE *, int));
+int __bt_dleaf __P((BTREE *, const DBT *, PAGE *, u_int));
int __bt_fd __P((const DB *));
-EPG *__bt_first __P((BTREE *, const DBT *, int *));
int __bt_free __P((BTREE *, PAGE *));
int __bt_get __P((const DB *, const DBT *, DBT *, u_int));
PAGE *__bt_new __P((BTREE *, pgno_t *));
@@ -51,15 +50,16 @@ 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 *));
+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 *, char **, size_t *));
+int __ovfl_get __P((BTREE *, void *, size_t *, void **, size_t *));
int __ovfl_put __P((BTREE *, const DBT *, pgno_t *));
#ifdef DEBUG
diff --git a/lib/libc/db/changelog b/lib/libc/db/changelog
new file mode 100644
index 00000000000..f820e56b588
--- /dev/null
+++ b/lib/libc/db/changelog
@@ -0,0 +1,105 @@
+# $NetBSD: changelog,v 1.2 1996/05/03 21:20:56 cgd Exp $
+
+1.84 -> 1.85
+ recno: #ifdef out use of mmap, it's not portable enough.
+
+1.83 -> 1.84 Thu Aug 18 15:46:07 EDT 1994
+ recno: Rework fixed-length records so that closing and reopening
+ the file now works. Pad short records on input. Never do
+ signed comparison in recno input reading functions.
+
+1.82 -> 1.83 Tue Jul 26 15:33:44 EDT 1994
+ btree: Rework cursor deletion code yet again; bugs with
+ deleting empty pages that only contained the cursor
+ record.
+
+1.81 -> 1.82 Sat Jul 16 11:01:50 EDT 1994
+ btree: Fix bugs introduced by new cursor/deletion code.
+ Replace return kbuf/dbuf with real DBT's.
+
+1.80 -> 1.81
+ btree: Fix bugs introduced by new cursor/deletion code.
+ all: Add #defines for Purify.
+
+1.79 -> 1.80 Wed Jul 13 22:41:54 EDT 1994
+ btree Change deletion to coalesce empty pages. This is a major
+ change, cursors and duplicate pages all had to be reworked.
+ Return to a fixed stack.
+ recno: Affected by cursor changes. New cursor structures should
+ permit multiple cursors in the future.
+
+1.78 -> 1.79 Mon Jun 20 17:36:47 EDT 1994
+ all: Minor cleanups of 1.78 for porting reasons; only
+ major change was inlining check of NULL pointer
+ so that __fix_realloc goes away.
+
+1.77 -> 1.78 Thu Jun 16 19:06:43 EDT 1994
+ all: Move "standard" size typedef's into db.h.
+
+1.76 -> 1.77 Thu Jun 16 16:48:38 EDT 1994
+ hash: Delete __init_ routine, has special meaning to OSF 2.0.
+
+1.74 -> 1.76
+ all: Finish up the port to the Alpha.
+
+1.73 -> 1.74
+ recno: Don't put the record if rec_search fails, in rec_rdelete.
+ Create fixed-length intermediate records past "end" of DB
+ correctly.
+ Realloc bug when reading in fixed records.
+ all: First cut at port to Alpha (64-bit architecture) using
+ 4.4BSD basic integral types typedef's.
+ Cast allocation pointers to shut up old compilers.
+ Rework PORT directory into OS/machine directories.
+
+1.72 -> 1.73
+ btree: If enough duplicate records were inserted and then deleted
+ that internal pages had references to empty pages of the
+ duplicate keys, the search function ended up on the wrong
+ page.
+
+1.7 -> 1.72 12 Oct 1993
+ hash: Support NET/2 hash formats.
+
+1.7 -> 1.71 16 Sep 1993
+ btree/recno:
+ Fix bug in internal search routines that caused
+ return of invalid pointers.
+
+1.6 -> 1.7 07 Sep 1993
+ hash: Fixed big key overflow bugs.
+ test: Portability hacks, rewrite test script, Makefile.
+ btree/recno:
+ Stop copying non-overflow key/data pairs.
+ PORT: Break PORT directory up into per architecture/OS
+ subdirectories.
+
+1.5 -> 1.6 06 Jun 1993
+ hash: In PAIRFITS, the first comparison should look at (P)[2].
+ The hash_realloc function was walking off the end of memory.
+ The overflow page number was wrong when bumping splitpoint.
+
+1.4 -> 1.5 23 May 1993
+ hash: Set hash default fill factor dynamically.
+ recno: Fixed bug in sorted page splits.
+ Add page size parameter support.
+ Allow recno to specify the name of the underlying btree;
+ used for vi recovery.
+ btree/recno:
+ Support 64K pages.
+ btree/hash/recno:
+ Provide access to an underlying file descriptor.
+ Change sync routines to take a flag argument, recno
+ uses this to sync out the underlying btree.
+
+1.3 -> 1.4 10 May 1993
+ recno: Delete the R_CURSORLOG flag from the recno interface.
+ Zero-length record fix for non-mmap reads.
+ Try and make SIZE_T_MAX test in open portable.
+
+1.2 -> 1.3 01 May 1993
+ btree: Ignore user byte-order setting when reading already
+ existing database. Fixes to byte-order conversions.
+
+1.1 -> 1.2 15 Apr 1993
+ No bug fixes, only compatibility hacks.
diff --git a/lib/libc/db/db2netbsd b/lib/libc/db/db2netbsd
new file mode 100644
index 00000000000..e29c97593bc
--- /dev/null
+++ b/lib/libc/db/db2netbsd
@@ -0,0 +1,31 @@
+#!/bin/sh
+# $NetBSD: db2netbsd,v 1.1 1996/05/03 22:43:02 cgd Exp $
+
+# This version transforms a Berkeley DB distribution into something
+# which can be 'cvs import'ed into the NetBSD source repository.
+# It is to be run in the untarred Berkeley DB distribution directory
+# (e.g. the "db.1.85" directory created by tar xvf), and sets up
+# the destination tree in place.
+
+version=`basename $PWD | sed -e 's/db\.//'`
+releasetag=`basename $PWD | sed -e 's/\./-/g'`
+
+CLEANFILES="PORT docs test/btree.tests test/hash.tests"
+
+# clean up pieces that we never import
+/bin/rm -rf $CLEANFILES
+find . -type l -o -name tags | xargs /bin/rm -f
+
+# The include files are already in place
+
+# Put the regression tests in the right place
+mkdir -p regress/lib/libc
+mv test regress/lib/libc/db
+
+# Put the libc pieces in the right place.
+mkdir -p lib/libc/db
+mv Makefile.inc README btree changelog db hash man mpool recno lib/libc/db
+
+echo "import with:"
+echo "cvs import -m \"Import of Berkeley DB version $version\" \
+src CSRG $releasetag"
diff --git a/lib/libc/db/hash/Makefile.inc b/lib/libc/db/hash/Makefile.inc
index 00f339ac2ed..79fddf587d9 100644
--- a/lib/libc/db/hash/Makefile.inc
+++ b/lib/libc/db/hash/Makefile.inc
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile.inc,v 1.5 1995/02/27 13:21:44 cgd Exp $
+# $NetBSD: Makefile.inc,v 1.6 1996/05/03 21:43:43 cgd Exp $
# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
.PATH: ${.CURDIR}/db/hash
diff --git a/lib/libc/db/hash/README b/lib/libc/db/hash/README
index fd1fc653a92..444bcb90414 100644
--- a/lib/libc/db/hash/README
+++ b/lib/libc/db/hash/README
@@ -1,4 +1,4 @@
-# $NetBSD: README,v 1.3 1995/02/27 13:21:52 cgd Exp $
+# $NetBSD: README,v 1.4 1996/05/03 21:43:44 cgd Exp $
# @(#)README 8.1 (Berkeley) 6/4/93
This package implements a superset of the hsearch and dbm/ndbm libraries.
diff --git a/lib/libc/db/hash/extern.h b/lib/libc/db/hash/extern.h
index af98921ef19..6b87ce4496d 100644
--- a/lib/libc/db/hash/extern.h
+++ b/lib/libc/db/hash/extern.h
@@ -1,4 +1,4 @@
-/* $NetBSD: extern.h,v 1.4 1995/02/27 13:21:55 cgd Exp $ */
+/* $NetBSD: extern.h,v 1.5 1996/05/03 21:43:45 cgd Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
diff --git a/lib/libc/db/hash/hash.c b/lib/libc/db/hash/hash.c
index 2fc3281cb9f..7ee731e500b 100644
--- a/lib/libc/db/hash/hash.c
+++ b/lib/libc/db/hash/hash.c
@@ -1,4 +1,4 @@
-/* $NetBSD: hash.c,v 1.8 1995/02/27 13:21:59 cgd Exp $ */
+/* $NetBSD: hash.c,v 1.9 1996/05/03 21:43:47 cgd Exp $ */
/*-
* Copyright (c) 1990, 1993, 1994
@@ -40,7 +40,7 @@
#if 0
static char sccsid[] = "@(#)hash.c 8.9 (Berkeley) 6/16/94";
#else
-static char rcsid[] = "$NetBSD: hash.c,v 1.8 1995/02/27 13:21:59 cgd Exp $";
+static char rcsid[] = "$NetBSD: hash.c,v 1.9 1996/05/03 21:43:47 cgd Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
diff --git a/lib/libc/db/hash/hash.h b/lib/libc/db/hash/hash.h
index 1ad93b74d9f..8ed5c6f6130 100644
--- a/lib/libc/db/hash/hash.h
+++ b/lib/libc/db/hash/hash.h
@@ -1,4 +1,4 @@
-/* $NetBSD: hash.h,v 1.5 1995/02/27 13:22:08 cgd Exp $ */
+/* $NetBSD: hash.h,v 1.6 1996/05/03 21:43:48 cgd Exp $ */
/*-
* Copyright (c) 1990, 1993, 1994
diff --git a/lib/libc/db/hash/hash_bigkey.c b/lib/libc/db/hash/hash_bigkey.c
index 993839d9f79..0db652b8645 100644
--- a/lib/libc/db/hash/hash_bigkey.c
+++ b/lib/libc/db/hash/hash_bigkey.c
@@ -1,4 +1,4 @@
-/* $NetBSD: hash_bigkey.c,v 1.5 1995/02/27 13:22:16 cgd Exp $ */
+/* $NetBSD: hash_bigkey.c,v 1.6 1996/05/03 21:43:49 cgd Exp $ */
/*-
* Copyright (c) 1990, 1993, 1994
@@ -40,7 +40,7 @@
#if 0
static char sccsid[] = "@(#)hash_bigkey.c 8.3 (Berkeley) 5/31/94";
#else
-static char rcsid[] = "$NetBSD: hash_bigkey.c,v 1.5 1995/02/27 13:22:16 cgd Exp $";
+static char rcsid[] = "$NetBSD: hash_bigkey.c,v 1.6 1996/05/03 21:43:49 cgd Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
diff --git a/lib/libc/db/hash/hash_buf.c b/lib/libc/db/hash/hash_buf.c
index 7747331688a..81aca2a1dc3 100644
--- a/lib/libc/db/hash/hash_buf.c
+++ b/lib/libc/db/hash/hash_buf.c
@@ -1,4 +1,4 @@
-/* $NetBSD: hash_buf.c,v 1.5 1995/02/27 13:22:23 cgd Exp $ */
+/* $NetBSD: hash_buf.c,v 1.6 1996/05/03 21:43:51 cgd Exp $ */
/*-
* Copyright (c) 1990, 1993, 1994
@@ -38,9 +38,9 @@
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
-static char sccsid[] = "@(#)hash_buf.c 8.4 (Berkeley) 6/4/94";
+static char sccsid[] = "@(#)hash_buf.c 8.5 (Berkeley) 7/15/94";
#else
-static char rcsid[] = "$NetBSD: hash_buf.c,v 1.5 1995/02/27 13:22:23 cgd Exp $";
+static char rcsid[] = "$NetBSD: hash_buf.c,v 1.6 1996/05/03 21:43:51 cgd Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
@@ -185,10 +185,16 @@ newbuf(hashp, addr, prev_bp)
/* 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 {
diff --git a/lib/libc/db/hash/hash_func.c b/lib/libc/db/hash/hash_func.c
index a978b99d2fa..09cf72e77f6 100644
--- a/lib/libc/db/hash/hash_func.c
+++ b/lib/libc/db/hash/hash_func.c
@@ -1,4 +1,4 @@
-/* $NetBSD: hash_func.c,v 1.5 1995/02/27 13:22:27 cgd Exp $ */
+/* $NetBSD: hash_func.c,v 1.6 1996/05/03 21:43:52 cgd Exp $ */
/*-
* Copyright (c) 1990, 1993
@@ -40,7 +40,7 @@
#if 0
static char sccsid[] = "@(#)hash_func.c 8.2 (Berkeley) 2/21/94";
#else
-static char rcsid[] = "$NetBSD: hash_func.c,v 1.5 1995/02/27 13:22:27 cgd Exp $";
+static char rcsid[] = "$NetBSD: hash_func.c,v 1.6 1996/05/03 21:43:52 cgd Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
diff --git a/lib/libc/db/hash/hash_log2.c b/lib/libc/db/hash/hash_log2.c
index 9332cbac887..6ac2ab1ec2d 100644
--- a/lib/libc/db/hash/hash_log2.c
+++ b/lib/libc/db/hash/hash_log2.c
@@ -1,4 +1,4 @@
-/* $NetBSD: hash_log2.c,v 1.5 1995/02/27 13:22:30 cgd Exp $ */
+/* $NetBSD: hash_log2.c,v 1.6 1996/05/03 21:43:54 cgd Exp $ */
/*-
* Copyright (c) 1990, 1993, 1994
@@ -40,7 +40,7 @@
#if 0
static char sccsid[] = "@(#)hash_log2.c 8.2 (Berkeley) 5/31/94";
#else
-static char rcsid[] = "$NetBSD: hash_log2.c,v 1.5 1995/02/27 13:22:30 cgd Exp $";
+static char rcsid[] = "$NetBSD: hash_log2.c,v 1.6 1996/05/03 21:43:54 cgd Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
diff --git a/lib/libc/db/hash/hash_page.c b/lib/libc/db/hash/hash_page.c
index 49ee8904a14..c81d46ba60f 100644
--- a/lib/libc/db/hash/hash_page.c
+++ b/lib/libc/db/hash/hash_page.c
@@ -1,4 +1,4 @@
-/* $NetBSD: hash_page.c,v 1.7 1995/02/27 13:22:34 cgd Exp $ */
+/* $NetBSD: hash_page.c,v 1.8 1996/05/03 21:43:55 cgd Exp $ */
/*-
* Copyright (c) 1990, 1993, 1994
@@ -38,9 +38,9 @@
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
-static char sccsid[] = "@(#)hash_page.c 8.6 (Berkeley) 6/16/94";
+static char sccsid[] = "@(#)hash_page.c 8.7 (Berkeley) 8/16/94";
#else
-static char rcsid[] = "$NetBSD: hash_page.c,v 1.7 1995/02/27 13:22:34 cgd Exp $";
+static char rcsid[] = "$NetBSD: hash_page.c,v 1.8 1996/05/03 21:43:55 cgd Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
@@ -689,7 +689,7 @@ overflow_page(hashp)
for ( i = first_page; i <= free_page; i++ ) {
if (!(freep = (u_int32_t *)hashp->mapp[i]) &&
!(freep = fetch_bitmap(hashp, i)))
- return (NULL);
+ return (0);
if (i == free_page)
in_use_bits = free_bit;
else
@@ -719,7 +719,7 @@ overflow_page(hashp)
if (offset > SPLITMASK) {
if (++splitnum >= NCACHED) {
(void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
- return (NULL);
+ return (0);
}
hashp->OVFL_POINT = splitnum;
hashp->SPARES[splitnum] = hashp->SPARES[splitnum-1];
@@ -732,7 +732,7 @@ overflow_page(hashp)
free_page++;
if (free_page >= NCACHED) {
(void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
- return (NULL);
+ return (0);
}
/*
* This is tricky. The 1 indicates that you want the new page
@@ -745,9 +745,9 @@ overflow_page(hashp)
* 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 (NULL);
+ if (__ibitmap(hashp,
+ (int)OADDR_OF(splitnum, offset), 1, free_page))
+ return (0);
hashp->SPARES[splitnum]++;
#ifdef DEBUG2
free_bit = 2;
@@ -757,7 +757,7 @@ overflow_page(hashp)
if (++splitnum >= NCACHED) {
(void)write(STDERR_FILENO, OVMSG,
sizeof(OVMSG) - 1);
- return (NULL);
+ return (0);
}
hashp->OVFL_POINT = splitnum;
hashp->SPARES[splitnum] = hashp->SPARES[splitnum-1];
@@ -801,7 +801,7 @@ found:
for (i = 0; (i < splitnum) && (bit > hashp->SPARES[i]); i++);
offset = (i ? bit - hashp->SPARES[i - 1] : bit);
if (offset >= SPLITMASK)
- return (NULL); /* Out of overflow pages */
+ 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",
diff --git a/lib/libc/db/hash/hsearch.c b/lib/libc/db/hash/hsearch.c
index ef825ab7182..409182c0c64 100644
--- a/lib/libc/db/hash/hsearch.c
+++ b/lib/libc/db/hash/hsearch.c
@@ -1,4 +1,4 @@
-/* $NetBSD: hsearch.c,v 1.8 1995/02/27 13:22:38 cgd Exp $ */
+/* $NetBSD: hsearch.c,v 1.10 1996/05/03 22:16:32 cgd Exp $ */
/*-
* Copyright (c) 1990, 1993
@@ -38,9 +38,9 @@
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
-static char sccsid[] = "@(#)hsearch.c 8.3 (Berkeley) 2/21/94";
+static char sccsid[] = "@(#)hsearch.c 8.4 (Berkeley) 7/21/94";
#else
-static char rcsid[] = "$NetBSD: hsearch.c,v 1.8 1995/02/27 13:22:38 cgd Exp $";
+static char rcsid[] = "$NetBSD: hsearch.c,v 1.10 1996/05/03 22:16:32 cgd Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
@@ -64,7 +64,7 @@ hcreate(nel)
info.nelem = nel;
info.bsize = 256;
info.ffactor = 8;
- info.cachesize = NULL;
+ info.cachesize = 0;
info.hash = NULL;
info.lorder = 0;
dbp = (DB *)__hash_open(NULL, O_CREAT | O_RDWR, 0600, &info, 0);
diff --git a/lib/libc/db/hash/ndbm.c b/lib/libc/db/hash/ndbm.c
index 875b0494e59..dd519a4a8ce 100644
--- a/lib/libc/db/hash/ndbm.c
+++ b/lib/libc/db/hash/ndbm.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ndbm.c,v 1.7 1995/02/27 13:22:44 cgd Exp $ */
+/* $NetBSD: ndbm.c,v 1.9 1996/05/04 00:38:58 cgd Exp $ */
/*-
* Copyright (c) 1990, 1993
@@ -38,9 +38,9 @@
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
-static char sccsid[] = "@(#)ndbm.c 8.3 (Berkeley) 5/30/94";
+static char sccsid[] = "@(#)ndbm.c 8.4 (Berkeley) 7/21/94";
#else
-static char rcsid[] = "$NetBSD: ndbm.c,v 1.7 1995/02/27 13:22:44 cgd Exp $";
+static char rcsid[] = "$NetBSD: ndbm.c,v 1.9 1996/05/04 00:38:58 cgd Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
@@ -73,7 +73,7 @@ dbm_open(file, flags, mode)
info.bsize = 4096;
info.ffactor = 40;
info.nelem = 1;
- info.cachesize = NULL;
+ info.cachesize = 0;
info.hash = NULL;
info.lorder = 0;
(void)strcpy(path, file);
@@ -98,15 +98,20 @@ dbm_fetch(db, key)
DBM *db;
datum key;
{
- datum retval;
+ datum retdata;
int status;
+ DBT dbtkey, dbtretdata;
- status = (db->get)(db, (DBT *)&key, (DBT *)&retval, 0);
+ dbtkey.data = key.dptr;
+ dbtkey.size = key.dsize;
+ status = (db->get)(db, &dbtkey, &dbtretdata, 0);
if (status) {
- retval.dptr = NULL;
- retval.dsize = 0;
+ dbtretdata.data = NULL;
+ dbtretdata.size = 0;
}
- return (retval);
+ retdata.dptr = dbtretdata.data;
+ retdata.dsize = dbtretdata.size;
+ return (retdata);
}
/*
@@ -119,11 +124,14 @@ dbm_firstkey(db)
DBM *db;
{
int status;
- datum retdata, retkey;
+ datum retkey;
+ DBT dbtretkey, dbtretdata;
- status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_FIRST);
+ status = (db->seq)(db, &dbtretkey, &dbtretdata, R_FIRST);
if (status)
- retkey.dptr = NULL;
+ dbtretkey.data = NULL;
+ retkey.dptr = dbtretkey.data;
+ retkey.dsize = dbtretkey.size;
return (retkey);
}
@@ -137,13 +145,17 @@ dbm_nextkey(db)
DBM *db;
{
int status;
- datum retdata, retkey;
+ datum retkey;
+ DBT dbtretkey, dbtretdata;
- status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_NEXT);
+ status = (db->seq)(db, &dbtretkey, &dbtretdata, R_NEXT);
if (status)
- retkey.dptr = NULL;
+ dbtretkey.data = NULL;
+ retkey.dptr = dbtretkey.data;
+ retkey.dsize = dbtretkey.size;
return (retkey);
}
+
/*
* Returns:
* 0 on success
@@ -155,8 +167,11 @@ dbm_delete(db, key)
datum key;
{
int status;
+ DBT dbtkey;
- status = (db->del)(db, (DBT *)&key, 0);
+ dbtkey.data = key.dptr;
+ dbtkey.size = key.dsize;
+ status = (db->del)(db, &dbtkey, 0);
if (status)
return (-1);
else
@@ -170,12 +185,18 @@ dbm_delete(db, key)
* 1 if DBM_INSERT and entry exists
*/
extern int
-dbm_store(db, key, content, flags)
+dbm_store(db, key, data, flags)
DBM *db;
- datum key, content;
+ datum key, data;
int flags;
{
- return ((db->put)(db, (DBT *)&key, (DBT *)&content,
+ DBT dbtkey, dbtdata;
+
+ dbtkey.data = key.dptr;
+ dbtkey.size = key.dsize;
+ dbtdata.data = data.dptr;
+ dbtdata.size = data.dsize;
+ return ((db->put)(db, &dbtkey, &dbtdata,
(flags == DBM_INSERT) ? R_NOOVERWRITE : 0));
}
diff --git a/lib/libc/db/hash/page.h b/lib/libc/db/hash/page.h
index ed62d595dc1..0ea00b7aea6 100644
--- a/lib/libc/db/hash/page.h
+++ b/lib/libc/db/hash/page.h
@@ -1,4 +1,4 @@
-/* $NetBSD: page.h,v 1.5 1995/02/27 13:22:52 cgd Exp $ */
+/* $NetBSD: page.h,v 1.6 1996/05/03 21:43:59 cgd Exp $ */
/*-
* Copyright (c) 1990, 1993, 1994
diff --git a/lib/libc/db/hash/search.h b/lib/libc/db/hash/search.h
index d11ac14eefb..b9f73132d8d 100644
--- a/lib/libc/db/hash/search.h
+++ b/lib/libc/db/hash/search.h
@@ -1,4 +1,4 @@
-/* $NetBSD: search.h,v 1.5 1995/02/27 13:22:58 cgd Exp $ */
+/* $NetBSD: search.h,v 1.6 1996/05/03 21:44:01 cgd Exp $ */
/*-
* Copyright (c) 1990, 1993
diff --git a/lib/libc/db/man/btree.3 b/lib/libc/db/man/btree.3
index f0cd4eba8d6..7c74828975a 100644
--- a/lib/libc/db/man/btree.3
+++ b/lib/libc/db/man/btree.3
@@ -1,4 +1,4 @@
-.\" $NetBSD: btree.3,v 1.5 1995/02/27 13:23:18 cgd Exp $
+.\" $NetBSD: btree.3,v 1.6 1996/05/03 21:26:48 cgd Exp $
.\"
.\" Copyright (c) 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -31,9 +31,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)btree.3 8.3 (Berkeley) 2/21/94
+.\" @(#)btree.3 8.4 (Berkeley) 8/18/94
.\"
-.TH BTREE 3 "February 21, 1994"
+.TH BTREE 3 "August 18, 1994"
.\".UC 7
.SH NAME
btree \- btree database access method
@@ -209,6 +209,13 @@ O lg base N where base is the average fill factor.
Often, inserting ordered data into btrees results in a low fill factor.
This implementation has been modified to make ordered insertion the best
case, resulting in a much better than normal page fill factor.
+.SH ERRORS
+The
+.I btree
+access method routines may fail and set
+.I errno
+for any of the errors specified for the library routine
+.IR dbopen (3).
.SH "SEE ALSO"
.IR dbopen (3),
.IR hash (3),
diff --git a/lib/libc/db/man/hash.3 b/lib/libc/db/man/hash.3
index 6d296a8f6d1..fcdb1f3af12 100644
--- a/lib/libc/db/man/hash.3
+++ b/lib/libc/db/man/hash.3
@@ -1,4 +1,4 @@
-.\" $NetBSD: hash.3,v 1.5 1995/02/27 13:23:31 cgd Exp $
+.\" $NetBSD: hash.3,v 1.6 1996/05/03 21:26:50 cgd Exp $
.\"
.\" Copyright (c) 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -31,9 +31,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)hash.3 8.5 (Berkeley) 2/21/94
+.\" @(#)hash.3 8.6 (Berkeley) 8/18/94
.\"
-.TH HASH 3 "February 21, 1994"
+.TH HASH 3 "August 18, 1994"
.UC 7
.SH NAME
hash \- hash database access method
@@ -139,6 +139,13 @@ and
.IR ndbm (3)
are provided, however these interfaces are not compatible with
previous file formats.
+.SH ERRORS
+The
+.I hash
+access method routines may fail and set
+.I errno
+for any of the errors specified for the library routine
+.IR dbopen (3).
.SH "SEE ALSO"
.IR btree (3),
.IR dbopen (3),
diff --git a/lib/libc/db/man/recno.3 b/lib/libc/db/man/recno.3
index 63a366b645f..1fd42078053 100644
--- a/lib/libc/db/man/recno.3
+++ b/lib/libc/db/man/recno.3
@@ -1,4 +1,4 @@
-.\" $NetBSD: recno.3,v 1.5 1995/06/13 00:53:40 jtc Exp $
+.\" $NetBSD: recno.3,v 1.6 1996/05/03 21:26:51 cgd Exp $
.\"
.\" Copyright (c) 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -31,9 +31,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)recno.3 8.3 (Berkeley) 2/21/94
+.\" @(#)recno.3 8.5 (Berkeley) 8/18/94
.\"
-.TH RECNO 3 "February 21, 1994"
+.TH RECNO 3 "August 18, 1994"
.UC 7
.SH NAME
recno \- record number database access method
@@ -99,6 +99,9 @@ The structure element
specifies the length of the record, and the structure element
.I bval
is used as the pad character.
+Any records, inserted into the database, that are less than
+.I reclen
+bytes long are automatically padded.
.TP
R_NOKEY
In the interface specified by
@@ -178,6 +181,11 @@ The
.I size
field of the key should be the size of that type.
.PP
+Because there can be no meta-data associated with the underlying
+recno access method files, any changes made to the default values
+(e.g. fixed record length or byte separator value) must be explicitly
+specified each time the file is opened.
+.PP
In the interface specified by
.IR dbopen ,
using the
@@ -185,6 +193,18 @@ using the
interface to create a new record will cause the creation of multiple,
empty records if the record number is more than one greater than the
largest record currently in the database.
+.SH ERRORS
+The
+.I recno
+access method routines may fail and set
+.I errno
+for any of the errors specified for the library routine
+.IR dbopen (3)
+or the following:
+.TP
+[EINVAL]
+An attempt was made to add a record to a fixed-length database that
+was too large to fit.
.SH "SEE ALSO"
.IR btree (3),
.IR dbopen (3),
diff --git a/lib/libc/db/mpool/mpool.c b/lib/libc/db/mpool/mpool.c
index 6417c29d453..be04f45e56c 100644
--- a/lib/libc/db/mpool/mpool.c
+++ b/lib/libc/db/mpool/mpool.c
@@ -1,7 +1,7 @@
-/* $NetBSD: mpool.c,v 1.5 1995/02/27 13:24:05 cgd Exp $ */
+/* $NetBSD: mpool.c,v 1.6 1996/05/03 21:29:48 cgd Exp $ */
/*-
- * Copyright (c) 1990, 1993
+ * 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
@@ -35,13 +35,14 @@
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
-static char sccsid[] = "@(#)mpool.c 8.2 (Berkeley) 2/21/94";
+static char sccsid[] = "@(#)mpool.c 8.5 (Berkeley) 7/26/94";
#else
-static char rcsid[] = "$NetBSD: mpool.c,v 1.5 1995/02/27 13:24:05 cgd Exp $";
+static char rcsid[] = "$NetBSD: mpool.c,v 1.6 1996/05/03 21:29:48 cgd Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
#include <sys/param.h>
+#include <sys/queue.h>
#include <sys/stat.h>
#include <errno.h>
@@ -51,31 +52,21 @@ static char rcsid[] = "$NetBSD: mpool.c,v 1.5 1995/02/27 13:24:05 cgd Exp $";
#include <unistd.h>
#include <db.h>
+
#define __MPOOLINTERFACE_PRIVATE
-#include "mpool.h"
+#include <mpool.h>
static BKT *mpool_bkt __P((MPOOL *));
static BKT *mpool_look __P((MPOOL *, pgno_t));
static int mpool_write __P((MPOOL *, BKT *));
-#ifdef DEBUG
-static void __mpoolerr __P((const char *fmt, ...));
-#endif
/*
- * MPOOL_OPEN -- initialize a memory pool.
- *
- * Parameters:
- * key: Shared buffer key.
- * fd: File descriptor.
- * pagesize: File page size.
- * maxcache: Max number of cached pages.
- *
- * Returns:
- * MPOOL pointer, NULL on error.
+ * mpool_open --
+ * Initialize a memory pool.
*/
MPOOL *
mpool_open(key, fd, pagesize, maxcache)
- DBT *key;
+ void *key;
int fd;
pgno_t pagesize, maxcache;
{
@@ -83,49 +74,35 @@ mpool_open(key, fd, pagesize, maxcache)
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);
- /* XXX
- * We should only set st_size to 0 for pipes -- 4.4BSD has the fix so
- * that stat(2) returns true for ISSOCK on pipes. Until then, this is
- * fairly close.
- */
if (!S_ISREG(sb.st_mode)) {
errno = ESPIPE;
return (NULL);
}
- if ((mp = (MPOOL *)malloc(sizeof(MPOOL))) == NULL)
+ /* Allocate and initialize the MPOOL cookie. */
+ if ((mp = (MPOOL *)calloc(1, sizeof(MPOOL))) == NULL)
return (NULL);
- mp->free.cnext = mp->free.cprev = (BKT *)&mp->free;
- mp->lru.cnext = mp->lru.cprev = (BKT *)&mp->lru;
+ CIRCLEQ_INIT(&mp->lqh);
for (entry = 0; entry < HASHSIZE; ++entry)
- mp->hashtable[entry].hnext = mp->hashtable[entry].hprev =
- mp->hashtable[entry].cnext = mp->hashtable[entry].cprev =
- (BKT *)&mp->hashtable[entry];
- mp->curcache = 0;
+ CIRCLEQ_INIT(&mp->hqh[entry]);
mp->maxcache = maxcache;
- mp->pagesize = pagesize;
mp->npages = sb.st_size / pagesize;
+ mp->pagesize = pagesize;
mp->fd = fd;
- mp->pgcookie = NULL;
- mp->pgin = mp->pgout = NULL;
-
-#ifdef STATISTICS
- mp->cachehit = mp->cachemiss = mp->pagealloc = mp->pageflush =
- mp->pageget = mp->pagenew = mp->pageput = mp->pageread =
- mp->pagewrite = 0;
-#endif
return (mp);
}
/*
- * MPOOL_FILTER -- initialize input/output filters.
- *
- * Parameters:
- * pgin: Page in conversion routine.
- * pgout: Page out conversion routine.
- * pgcookie: Cookie for page in/out routines.
+ * mpool_filter --
+ * Initialize input/output filters.
*/
void
mpool_filter(mp, pgin, pgout, pgcookie)
@@ -140,124 +117,128 @@ mpool_filter(mp, pgin, pgout, pgcookie)
}
/*
- * MPOOL_NEW -- get a new page
- *
- * Parameters:
- * mp: mpool cookie
- * pgnoadddr: place to store new page number
- * Returns:
- * RET_ERROR, RET_SUCCESS
+ * mpool_new --
+ * Get a new page of memory.
*/
void *
mpool_new(mp, pgnoaddr)
MPOOL *mp;
pgno_t *pgnoaddr;
{
- BKT *b;
- BKTHDR *hp;
+ 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 hash and lru chains and return.
+ * 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 ((b = mpool_bkt(mp)) == NULL)
+ if ((bp = mpool_bkt(mp)) == NULL)
return (NULL);
- *pgnoaddr = b->pgno = mp->npages++;
- b->flags = MPOOL_PINNED;
- inshash(b, b->pgno);
- inschain(b, &mp->lru);
- return (b->page);
+ *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 from the pool
- *
- * Parameters:
- * mp: mpool cookie
- * pgno: page number
- * flags: not used
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS
+ * mpool_get
+ * Get a page.
*/
void *
mpool_get(mp, pgno, flags)
MPOOL *mp;
pgno_t pgno;
- u_int flags; /* XXX not used? */
+ u_int flags; /* XXX not used? */
{
- BKT *b;
- BKTHDR *hp;
+ struct _hqh *head;
+ BKT *bp;
off_t off;
int nr;
- /*
- * If asking for a specific page that is already in the cache, find
- * it and return it.
- */
- if (b = mpool_look(mp, pgno)) {
+ /* Check for attempt to retrieve a non-existent page. */
+ if (pgno >= mp->npages) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
#ifdef STATISTICS
- ++mp->pageget;
+ ++mp->pageget;
#endif
+
+ /* Check for a page that is cached. */
+ if ((bp = mpool_look(mp, pgno)) != NULL) {
#ifdef DEBUG
- if (b->flags & MPOOL_PINNED)
- __mpoolerr("mpool_get: page %d already pinned",
- b->pgno);
+ if (bp->flags & MPOOL_PINNED) {
+ (void)fprintf(stderr,
+ "mpool_get: page %d already pinned\n", bp->pgno);
+ abort();
+ }
#endif
- rmchain(b);
- inschain(b, &mp->lru);
- b->flags |= MPOOL_PINNED;
- return (b->page);
- }
-
- /* Not allowed to retrieve a non-existent page. */
- if (pgno >= mp->npages) {
- errno = EINVAL;
- return (NULL);
+ /*
+ * 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 ((b = mpool_bkt(mp)) == NULL)
+ if ((bp = mpool_bkt(mp)) == NULL)
return (NULL);
- b->pgno = pgno;
- b->flags = MPOOL_PINNED;
+ /* Read in the contents. */
#ifdef STATISTICS
++mp->pageread;
#endif
- /* Read in the contents. */
off = mp->pagesize * pgno;
if (lseek(mp->fd, off, SEEK_SET) != off)
return (NULL);
- if ((nr = read(mp->fd, b->page, mp->pagesize)) != mp->pagesize) {
+ if ((nr = read(mp->fd, bp->page, mp->pagesize)) != mp->pagesize) {
if (nr >= 0)
errno = EFTYPE;
return (NULL);
}
- if (mp->pgin)
- (mp->pgin)(mp->pgcookie, b->pgno, b->page);
- inshash(b, b->pgno);
- inschain(b, &mp->lru);
-#ifdef STATISTICS
- ++mp->pageget;
-#endif
- return (b->page);
+ /* 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 to the pool
- *
- * Parameters:
- * mp: mpool cookie
- * page: page pointer
- * pgno: page number
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS
+ * mpool_put
+ * Return a page.
*/
int
mpool_put(mp, page, flags)
@@ -265,193 +246,172 @@ mpool_put(mp, page, flags)
void *page;
u_int flags;
{
- BKT *baddr;
-#ifdef DEBUG
- BKT *b;
-#endif
+ BKT *bp;
#ifdef STATISTICS
++mp->pageput;
#endif
- baddr = (BKT *)((char *)page - sizeof(BKT));
+ bp = (BKT *)((char *)page - sizeof(BKT));
#ifdef DEBUG
- if (!(baddr->flags & MPOOL_PINNED))
- __mpoolerr("mpool_put: page %d not pinned", b->pgno);
- for (b = mp->lru.cnext; b != (BKT *)&mp->lru; b = b->cnext) {
- if (b == (BKT *)&mp->lru)
- __mpoolerr("mpool_put: %0x: bad address", baddr);
- if (b == baddr)
- break;
+ if (!(bp->flags & MPOOL_PINNED)) {
+ (void)fprintf(stderr,
+ "mpool_put: page %d not pinned\n", bp->pgno);
+ abort();
}
#endif
- baddr->flags &= ~MPOOL_PINNED;
- baddr->flags |= flags & MPOOL_DIRTY;
+ bp->flags &= ~MPOOL_PINNED;
+ bp->flags |= flags & MPOOL_DIRTY;
return (RET_SUCCESS);
}
/*
- * MPOOL_CLOSE -- close the buffer pool
- *
- * Parameters:
- * mp: mpool cookie
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS
+ * mpool_close
+ * Close the buffer pool.
*/
int
mpool_close(mp)
MPOOL *mp;
{
- BKT *b, *next;
+ BKT *bp;
/* Free up any space allocated to the lru pages. */
- for (b = mp->lru.cprev; b != (BKT *)&mp->lru; b = next) {
- next = b->cprev;
- free(b);
+ 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 file to disk.
- *
- * Parameters:
- * mp: mpool cookie
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS
+ * mpool_sync
+ * Sync the pool to disk.
*/
int
mpool_sync(mp)
MPOOL *mp;
{
- BKT *b;
+ BKT *bp;
- for (b = mp->lru.cprev; b != (BKT *)&mp->lru; b = b->cprev)
- if (b->flags & MPOOL_DIRTY && mpool_write(mp, b) == RET_ERROR)
+ /* 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);
}
/*
- * MPOOL_BKT -- get/create a BKT from the cache
- *
- * Parameters:
- * mp: mpool cookie
- *
- * Returns:
- * NULL on failure and a pointer to the BKT on success
+ * mpool_bkt
+ * Get a page from the cache (or create one).
*/
static BKT *
mpool_bkt(mp)
MPOOL *mp;
{
- BKT *b;
+ 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 maxxed out, search 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.
+ * 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 (b = mp->lru.cprev; b != (BKT *)&mp->lru; b = b->cprev)
- if (!(b->flags & MPOOL_PINNED)) {
- if (b->flags & MPOOL_DIRTY &&
- mpool_write(mp, b) == RET_ERROR)
+ 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);
- rmhash(b);
- rmchain(b);
#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 = b->page;
- memset(b, 0xff, sizeof(BKT) + mp->pagesize);
- b->page = spage;
+ { void *spage;
+ spage = bp->page;
+ memset(bp, 0xff, sizeof(BKT) + mp->pagesize);
+ bp->page = spage;
}
#endif
- return (b);
+ return (bp);
}
-new: if ((b = (BKT *)malloc(sizeof(BKT) + mp->pagesize)) == NULL)
+new: if ((bp = (BKT *)malloc(sizeof(BKT) + mp->pagesize)) == NULL)
return (NULL);
#ifdef STATISTICS
++mp->pagealloc;
#endif
-#ifdef DEBUG
- memset(b, 0xff, sizeof(BKT) + mp->pagesize);
+#if defined(DEBUG) || defined(PURIFY)
+ memset(bp, 0xff, sizeof(BKT) + mp->pagesize);
#endif
- b->page = (char *)b + sizeof(BKT);
+ bp->page = (char *)bp + sizeof(BKT);
++mp->curcache;
- return (b);
+ return (bp);
}
/*
- * MPOOL_WRITE -- sync a page to disk
- *
- * Parameters:
- * mp: mpool cookie
- *
- * Returns:
- * RET_ERROR, RET_SUCCESS
+ * mpool_write
+ * Write a page to disk.
*/
static int
-mpool_write(mp, b)
+mpool_write(mp, bp)
MPOOL *mp;
- BKT *b;
+ BKT *bp;
{
off_t off;
- if (mp->pgout)
- (mp->pgout)(mp->pgcookie, b->pgno, b->page);
-
#ifdef STATISTICS
++mp->pagewrite;
#endif
- off = mp->pagesize * b->pgno;
+
+ /* 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 (write(mp->fd, b->page, mp->pagesize) != mp->pagesize)
+ if (write(mp->fd, bp->page, mp->pagesize) != mp->pagesize)
return (RET_ERROR);
- b->flags &= ~MPOOL_DIRTY;
+
+ bp->flags &= ~MPOOL_DIRTY;
return (RET_SUCCESS);
}
/*
- * MPOOL_LOOK -- lookup a page
- *
- * Parameters:
- * mp: mpool cookie
- * pgno: page number
- *
- * Returns:
- * NULL on failure and a pointer to the BKT on success
+ * mpool_look
+ * Lookup a page in the cache.
*/
static BKT *
mpool_look(mp, pgno)
MPOOL *mp;
pgno_t pgno;
{
- register BKT *b;
- register BKTHDR *tb;
+ struct _hqh *head;
+ BKT *bp;
- /* XXX
- * If find the buffer, put it first on the hash chain so can
- * find it again quickly.
- */
- tb = &mp->hashtable[HASHKEY(pgno)];
- for (b = tb->hnext; b != (BKT *)tb; b = b->hnext)
- if (b->pgno == pgno) {
+ 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 (b);
+ return (bp);
}
#ifdef STATISTICS
++mp->cachemiss;
@@ -461,16 +421,14 @@ mpool_look(mp, pgno)
#ifdef STATISTICS
/*
- * MPOOL_STAT -- cache statistics
- *
- * Parameters:
- * mp: mpool cookie
+ * mpool_stat
+ * Print out cache statistics.
*/
void
mpool_stat(mp)
MPOOL *mp;
{
- BKT *b;
+ BKT *bp;
int cnt;
char *sep;
@@ -492,11 +450,12 @@ mpool_stat(mp)
sep = "";
cnt = 0;
- for (b = mp->lru.cnext; b != (BKT *)&mp->lru; b = b->cnext) {
- (void)fprintf(stderr, "%s%d", sep, b->pgno);
- if (b->flags & MPOOL_DIRTY)
+ 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 (b->flags & MPOOL_PINNED)
+ if (bp->flags & MPOOL_PINNED)
(void)fprintf(stderr, "P");
if (++cnt == 10) {
sep = "\n";
@@ -508,33 +467,3 @@ mpool_stat(mp)
(void)fprintf(stderr, "\n");
}
#endif
-
-#ifdef DEBUG
-#if __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
-
-static void
-#if __STDC__
-__mpoolerr(const char *fmt, ...)
-#else
-__mpoolerr(fmt, va_alist)
- char *fmt;
- va_dcl
-#endif
-{
- va_list ap;
-#if __STDC__
- va_start(ap, fmt);
-#else
- va_start(ap);
-#endif
- (void)vfprintf(stderr, fmt, ap);
- va_end(ap);
- (void)fprintf(stderr, "\n");
- abort();
- /* NOTREACHED */
-}
-#endif
diff --git a/lib/libc/db/mpool/mpool.libtp b/lib/libc/db/mpool/mpool.libtp
new file mode 100644
index 00000000000..3ab0c8f835c
--- /dev/null
+++ b/lib/libc/db/mpool/mpool.libtp
@@ -0,0 +1,746 @@
+/******************************************************************************
+
+VERSION $Id: mpool.libtp,v 1.1 1996/05/07 09:02:01 deraadt Exp $
+PACKAGE: User Level Shared Memory Manager
+
+DESCRIPTION:
+ This package provides a buffer pool interface implemented as
+ a collection of file pages mapped into shared memory.
+
+ Based on Mark's buffer manager
+
+ROUTINES:
+ External
+ buf_alloc
+ buf_flags
+ buf_get
+ buf_init
+ buf_last
+ buf_open
+ buf_pin
+ buf_sync
+ buf_unpin
+ Internal
+ bf_assign_buf
+ bf_fid_to_fd
+ bf_newbuf
+ bf_put_page
+
+
+******************************************************************************/
+#include <sys/types.h>
+#include <assert.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <errno.h>
+#include "list.h"
+#include "user.h"
+#include "txn_sys.h"
+#include "buf.h"
+#include "semkeys.h"
+#include "error.h"
+
+/*
+ we need to translate between some type of file id that the user
+ process passes and a file descriptor. For now, it's a nop.
+*/
+#define GET_MASTER get_sem ( buf_spinlock )
+#define RELEASE_MASTER release_sem ( buf_spinlock )
+
+#define LRUID *buf_lru
+#define LRUP (bufhdr_table+*buf_lru)
+#define MRU bufhdr_table[*buf_lru].lru.prev
+
+/* Global indicator that you have started reusing buffers */
+int do_statistics = 0;
+/*
+ Process Statics (pointers into shared memory)
+*/
+static BUF_T *buf_table = 0;
+static BUFHDR_T *bufhdr_table;
+static int *buf_hash_table;
+static int *buf_lru; /* LRU is the free list */
+static int buf_spinlock;
+static FINFO_T *buf_fids;
+static int *buf_sp; /* Pointer to string free space */
+static char *buf_strings;
+
+/* Process Local FID->FD table */
+static int fds[NUM_FILE_ENTRIES];
+
+/* Static routines */
+static BUFHDR_T *bf_assign_buf();
+static int bf_fid_to_fd();
+static BUFHDR_T *bf_newbuf();
+static int bf_put_page();
+
+/*
+ Return 0 on success
+ 1 on failure
+*/
+extern int
+buf_init ( )
+{
+ ADDR_T buf_region;
+ BUFHDR_T *bhp;
+ int i;
+ int ref_count;
+ int *spinlockp;
+
+ /*
+ Initialize Process local structures
+ */
+ for ( i = 0; i < NUM_FILE_ENTRIES; i++ ) {
+ fds[i] = -1;
+ }
+
+ buf_region = attach_region ( BUF_REGION_NAME, BUF_REGION_NUM,
+ BUF_REGION_SIZE, &ref_count );
+ if ( !buf_region ) {
+ return (1);
+ }
+ error_log3 ( "Buf Region: ADDR: %d ID: %d SIZE: %d\n", buf_region,
+ BUF_REGION_NUM, BUF_REGION_SIZE );
+
+ buf_table = (BUF_T *)buf_region;
+ bufhdr_table = (BUFHDR_T *)(buf_table + NUM_BUFS);
+ buf_hash_table = (int *)(bufhdr_table + NUM_BUFS);
+ buf_lru = buf_hash_table + NUMTABLE_ENTRIES;
+ spinlockp = buf_lru + 1;
+ buf_fids = (FINFO_T *)(spinlockp+1);
+ buf_sp = (int *)(buf_fids + NUM_FILE_ENTRIES);
+ buf_strings = (char *)(buf_sp + 1);
+
+ /* Create locking spinlock (gets creating holding the lock) */
+ buf_spinlock = create_sem ( BUF_SPIN_NAME, BUF_SPIN_NUM, ref_count <= 1 );
+ if ( buf_spinlock < 0 ) {
+ return(1);
+ }
+ if ( ref_count <= 1 ) {
+ *spinlockp = buf_spinlock;
+
+ /* Now initialize the buffer manager */
+
+ /* 1. Free list */
+ *buf_lru = 0;
+
+ /* 2. Buffer headers */
+ for ( i = 0, bhp = bufhdr_table; i < NUM_BUFS; bhp++, i++ ) {
+ bhp->lru.next = i+1;
+ bhp->lru.prev = i-1;
+ bhp->flags = 0; /* All Flags off */
+ bhp->refcount = 0;
+ bhp->wait_proc = -1; /* No sleepers */
+ LISTPE_INIT ( hash, bhp, i ); /* Hash chains */
+ }
+ bufhdr_table[0].lru.prev = NUM_BUFS-1;
+ bufhdr_table[NUM_BUFS-1].lru.next = 0;
+
+ /* 3. Hash Table */
+ for ( i = 0; i < NUMTABLE_ENTRIES; i++ ) {
+ buf_hash_table[i] = NUM_BUFS;
+ }
+
+ /* 4. File ID Table */
+ for ( i = 0; i < NUM_FILE_ENTRIES; i++ ) {
+ buf_fids[i].offset = -1;
+ buf_fids[i].npages = -1;
+ buf_fids[i].refcount = 0;
+ }
+
+ /* 5. Free String Pointer */
+ *buf_sp = (FILE_NAME_LEN*NUM_FILE_ENTRIES);
+ if (RELEASE_MASTER) {
+ return(1);
+ }
+ error_log0 ( "Initialized buffer region\n" );
+ }
+ return (0);
+}
+
+extern void
+buf_exit()
+{
+ int ref;
+ int i;
+
+ /* Flush Buffer Pool on Exit */
+ for ( i = 0; i < NUM_FILE_ENTRIES; i++ ) {
+ if ( fds[i] != -1 ) {
+ close ( fds[i] );
+ }
+ }
+ if ( buf_table ) {
+ detach_region ( buf_table, BUF_REGION_NUM, BUF_REGION_SIZE, &ref );
+ }
+ return;
+}
+
+/*
+ We need an empty buffer. Find the LRU unpinned NON-Dirty page.
+*/
+static BUFHDR_T *
+bf_newbuf()
+{
+ int fd;
+ int lruid;
+ int nbytes;
+ int ndx;
+ BUFHDR_T *bhp;
+
+ lruid = LRUID;
+ for ( bhp = LRUP;
+ bhp->flags & (BUF_PINNED|BUF_IO_IN_PROGRESS);
+ bhp = LISTP_NEXTP (bufhdr_table, lru, bhp ) ) {
+
+ if ( bhp->lru.next == lruid ) {
+ /* OUT OF BUFFERS */
+ error_log1 ( "All buffers are pinned. %s\n",
+ "Unable to grant buffer request" );
+ return(NULL);
+ }
+ }
+ /* BHP can be used */
+ if ( bhp->flags & BUF_DIRTY ) {
+ do_statistics = 1;
+ /*
+ MIS Check for log flushed appropriately
+ */
+ fd = bf_fid_to_fd(bhp->id.file_id);
+ if ( fd == -1 ) {
+ error_log1 ("Invalid fid %d\n", bhp->id.file_id);
+ return(NULL);
+ }
+ if ( bf_put_page(fd, bhp) < 0 ) {
+ return(NULL);
+ }
+ }
+ /* Update Hash Pointers */
+ ndx = BUF_HASH ( bhp->id.file_id, bhp->id.obj_id );
+ LISTP_REMOVE(bufhdr_table, hash, bhp);
+ if ( buf_hash_table[ndx] == (bhp-bufhdr_table) ) {
+ if ( bhp->hash.next != (bhp-bufhdr_table) ) {
+ buf_hash_table[ndx] = bhp->hash.next;
+ } else {
+ buf_hash_table[ndx] = NUM_BUFS;
+ }
+ }
+ INIT_BUF(bhp);
+
+ return(bhp);
+}
+/*
+ buf_alloc
+
+ Add a page to a file and return a buffer for it.
+
+*/
+ADDR_T
+buf_alloc ( fid, new_pageno )
+int fid;
+int *new_pageno;
+{
+ BUFHDR_T *bhp;
+ int fd;
+ int len;
+ int ndx;
+ OBJ_T fobj;
+
+ if (GET_MASTER) {
+ return(NULL);
+ }
+ if ( buf_fids[fid].npages == -1 ) {
+ /* initialize npages field */
+ fd = bf_fid_to_fd ( fid );
+ }
+ assert (fid < NUM_FILE_ENTRIES);
+
+ *new_pageno = buf_fids[fid].npages;
+ if ( *new_pageno == -1 ) {
+ RELEASE_MASTER;
+ return ( NULL );
+ }
+ buf_fids[fid].npages++;
+ ndx = BUF_HASH ( fid, *new_pageno );
+ fobj.file_id = fid;
+ fobj.obj_id = *new_pageno;
+ bhp = bf_assign_buf ( ndx, &fobj, BF_PIN|BF_DIRTY|BF_EMPTY, &len );
+ if ( RELEASE_MASTER ) {
+ /* Memory leak */
+ return(NULL);
+ }
+ if ( bhp ) {
+ return ((ADDR_T)(buf_table+(bhp-bufhdr_table)));
+ } else {
+ return ( NULL );
+ }
+}
+
+
+/*
+ Buffer Flags
+ BF_DIRTY Mark page as dirty
+ BF_EMPTY Don't initialize page, just get buffer
+ BF_PIN Retrieve with pin
+
+MIS
+Might want to add a flag that sets an LSN for this buffer is the
+DIRTY flag is set
+
+Eventually, you may want a flag that indicates the I/O and lock
+request should be shipped off together, but not for now.
+*/
+extern ADDR_T
+buf_get ( file_id, page_id, flags, len )
+int file_id;
+int page_id;
+u_long flags;
+int *len; /* Number of bytes read into buffer */
+{
+ BUFHDR_T *bhp;
+ int bufid;
+ int fd;
+ int ndx;
+ int next_bufid;
+ int stat;
+ OBJ_T fobj;
+
+ ndx = BUF_HASH ( file_id, page_id );
+ fobj.file_id = (long) file_id;
+ fobj.obj_id = (long) page_id;
+ if ( GET_MASTER ) {
+ return(NULL);
+ }
+ /*
+ This could be a for loop, but we lose speed
+ by making all the cases general purpose so we
+ optimize for the no-collision case.
+ */
+ bufid = buf_hash_table[ndx];
+ if ( bufid < NUM_BUFS ) {
+ for ( bhp = bufhdr_table+bufid;
+ !OBJ_EQ (bhp->id, fobj) || !(bhp->flags & BUF_VALID);
+ bhp = LISTP_NEXTP ( bufhdr_table, hash, bhp ) ) {
+
+ if ( bhp->hash.next == bufid ) {
+ goto not_found;
+ }
+ }
+/* found */
+ if ( flags & BF_PIN ) {
+ bhp->flags |= BUF_PINNED;
+ bhp->refcount++;
+#ifdef PIN_DEBUG
+ fprintf(stderr, "buf_get: %X PINNED (%d)\n",
+ buf_table + (bhp-bufhdr_table), bhp->refcount);
+#endif
+ }
+ if ( flags & BF_DIRTY ) {
+ bhp->flags |= BUF_DIRTY;
+ }
+
+ while ( bhp->flags & BUF_IO_IN_PROGRESS ) {
+ /* MIS -- eventually err check here */
+#ifdef DEBUG
+ printf("About to sleep on %d (me: %d\n)\n", bhp->wait_proc,
+ my_txnp - txn_table);
+#endif
+#ifdef WAIT_STATS
+ buf_waits++;
+#endif
+ stat = proc_sleep_on ( &(bhp->wait_proc), buf_spinlock );
+ if ( stat ) {
+ /* Memory leak */
+ return(NULL);
+ }
+ if (!( bhp->flags & BUF_IO_IN_PROGRESS) &&
+ (!OBJ_EQ (bhp->id, fobj) || !(bhp->flags & BUF_VALID))) {
+ if (RELEASE_MASTER)
+ return(NULL);
+ return(buf_get ( file_id, page_id, flags, len ));
+ }
+ }
+ MAKE_MRU( bhp );
+ *len = BUFSIZE;
+ } else {
+not_found:
+ /* If you get here, the page isn't in the hash table */
+ bhp = bf_assign_buf ( ndx, &fobj, flags, len );
+ }
+ /* Common code between found and not found */
+
+ if ( bhp && bhp->flags & BUF_NEWPAGE ) {
+ *len = 0;
+ }
+ if (RELEASE_MASTER){
+ /* Memory leak */
+ return(NULL);
+ }
+ if ( bhp ) {
+ return ((ADDR_T)(buf_table+(bhp-bufhdr_table)));
+ } else {
+ return ( NULL );
+ }
+}
+
+/*
+ MIS - do I want to add file links to buffer pool?
+*/
+extern int
+buf_sync ( fid, close )
+int fid;
+int close; /* should we dec refcount and possibly
+ invalidate all the buffers */
+{
+ int i;
+ int fd;
+ int invalidate;
+ BUFHDR_T *bhp;
+
+ if ( (fd = bf_fid_to_fd ( fid )) < 0 ) {
+ return(1);
+ }
+ if (GET_MASTER) {
+ return(1);
+ }
+ invalidate = (buf_fids[fid].refcount == 1 && close);
+ if ( invalidate )
+ for ( bhp = bufhdr_table, i = 0; i < NUM_BUFS; bhp++, i++ ) {
+ if (bhp->id.file_id == fid) {
+ if ((bhp->flags & BF_DIRTY) && (bf_put_page( fd, bhp ) < 0)) {
+ return(1);
+ }
+ bhp->id.file_id = -1;
+ }
+ }
+ if (invalidate || close)
+ buf_fids[fid].refcount--;
+
+ if (RELEASE_MASTER) {
+ return(1);
+ }
+ return(0);
+
+
+}
+
+extern int
+buf_flags ( addr, set_flags, unset_flags )
+ADDR_T addr;
+u_long set_flags;
+u_long unset_flags;
+{
+ int bufid;
+ BUFHDR_T *bhp;
+
+#ifdef PIN_DEBUG
+ fprintf(stderr, "buf_flags: %X setting %s%s%s%s%s releasing %s%s%s%s%s\n",
+ addr,
+ set_flags&BUF_DIRTY ? "DIRTY " : "",
+ set_flags&BUF_VALID ? "VALID " : "",
+ set_flags&BUF_PINNED ? "PINNED " : "",
+ set_flags&BUF_IO_ERROR ? "IO_ERROR " : "",
+ set_flags&BUF_IO_IN_PROGRESS ? "IO_IN_PROG " : "",
+ set_flags&BUF_NEWPAGE ? "NEWPAGE " : "",
+ unset_flags&BUF_DIRTY ? "DIRTY " : "",
+ unset_flags&BUF_VALID ? "VALID " : "",
+ unset_flags&BUF_PINNED ? "PINNED " : "",
+ unset_flags&BUF_IO_ERROR ? "IO_ERROR " : "",
+ unset_flags&BUF_IO_IN_PROGRESS ? "IO_IN_PROG " : "",
+ unset_flags&BUF_NEWPAGE ? "NEWPAGE " : "" );
+#endif
+ if (!ADDR_OK(addr)) {
+ error_log1 ( "buf_pin: Invalid Buffer Address %x\n", addr );
+ return(1);
+ }
+ bufid = ((BUF_T *)addr) - buf_table;
+ assert ( bufid < NUM_BUFS);
+ bhp = &bufhdr_table[bufid];
+ if (GET_MASTER) {
+ return(1);
+ }
+ bhp->flags |= set_flags;
+ if ( set_flags & BUF_PINNED ) {
+ bhp->refcount++;
+ }
+ if ( set_flags & BUF_DIRTY ) {
+ unset_flags |= BUF_NEWPAGE;
+ }
+
+ if ( unset_flags & BUF_PINNED ) {
+ bhp->refcount--;
+ if ( bhp->refcount ) {
+ /* Turn off pin bit so it doesn't get unset */
+ unset_flags &= ~BUF_PINNED;
+ }
+ }
+ bhp->flags &= ~unset_flags;
+ MAKE_MRU(bhp);
+ if (RELEASE_MASTER) {
+ return(1);
+ }
+ return(0);
+}
+
+/*
+ Take a string name and produce an fid.
+
+ returns -1 on error
+
+ MIS -- this is a potential problem -- you keep actual names
+ here -- what if people run from different directories?
+*/
+extern int
+buf_name_lookup ( fname )
+char *fname;
+{
+ int i;
+ int fid;
+ int ndx;
+
+ fid = -1;
+ if (GET_MASTER) {
+ return(-1);
+ }
+ for ( i = 0; i < NUM_FILE_ENTRIES; i++ ) {
+ if ( buf_fids[i].offset == -1 ) {
+ fid = i;
+ } else {
+ if (!strcmp (fname, buf_strings+buf_fids[i].offset)) {
+ if (RELEASE_MASTER) {
+ return(-1);
+ }
+ buf_fids[i].refcount++;
+ return(i);
+ }
+ }
+ }
+ if ( fid == -1 ) {
+ error_log0 ( "No more file ID's\n" );
+ } else {
+ ndx = *buf_sp - strlen(fname) - 1;
+ if ( ndx < 0 ) {
+ error_log0 ( "Out of string space\n" );
+ fid = -1;
+ } else {
+ *buf_sp = ndx;
+ strcpy ( buf_strings+ndx, fname );
+ buf_fids[fid].offset = ndx;
+ }
+ buf_fids[fid].refcount = 1;
+ }
+ if (RELEASE_MASTER) {
+ return(-1);
+ }
+ return(fid);
+}
+
+static int
+bf_fid_to_fd ( fid )
+int fid;
+{
+ struct stat sbuf;
+
+ assert ( (fid < NUM_FILE_ENTRIES) && (buf_fids[fid].offset != -1) );
+ if ( fds[fid] != -1 ) {
+ return(fds[fid]);
+
+ }
+ fds[fid] = open ( buf_strings+buf_fids[fid].offset, O_RDWR|O_CREAT,
+ 0666 );
+ if ( fds[fid] < 0 ) {
+ error_log3 ( "Error Opening File %s FID: %d FD: %d. Errno = %d\n",
+ buf_strings+buf_fids[fid].offset, fid, fds[fid],
+ errno );
+ return(-1);
+ }
+ error_log3 ( "Opening File %s FID: %d FD: %d\n",
+ buf_strings+buf_fids[fid].offset, fid, fds[fid] );
+ if ( buf_fids[fid].npages == -1 ) {
+ /* Initialize the npages field */
+ if ( fstat ( fds[fid], &sbuf ) ) {
+ error_log3 ( "Error Fstating %s FID: %d. Errno = %d\n",
+ buf_strings+buf_fids[fid].offset, fid, errno );
+ } else {
+ buf_fids[fid].npages = ( sbuf.st_size / BUFSIZE );
+ }
+ }
+
+ return ( fds[fid] );
+}
+
+static int
+bf_put_page ( fd, bhp )
+int fd;
+BUFHDR_T *bhp;
+{
+ int nbytes;
+
+ assert ( (bhp-bufhdr_table) < NUM_BUFS );
+ if ( lseek ( fd, bhp->id.obj_id << BUFSHIFT, L_SET ) < 0 ) {
+ return(-1);
+ }
+ bhp->flags |= BUF_IO_IN_PROGRESS;
+ if (RELEASE_MASTER) {
+ return(-1);
+ }
+ nbytes = write(fd, buf_table[bhp-bufhdr_table], BUFSIZE);
+ if (GET_MASTER) {
+ return(-2);
+ }
+ if ( nbytes < 0 ) {
+ error_log1 ("Write failed with error code %d\n", errno);
+ return(-1);
+ } else if ( nbytes != BUFSIZE ) {
+ error_log1 ("Short write: %d bytes of %d\n", nbytes, BUFSIZE );
+ }
+ bhp->flags &= ~(BUF_DIRTY|BUF_IO_IN_PROGRESS);
+ return (0);
+}
+
+static BUFHDR_T *
+bf_assign_buf ( ndx, obj, flags, len )
+int ndx;
+OBJ_T *obj;
+u_long flags;
+int *len; /* Number of bytes read */
+{
+ BUFHDR_T *bhp;
+ int fd;
+
+ assert ( obj->file_id < NUM_FILE_ENTRIES );
+ bhp = bf_newbuf();
+ if ( !bhp ) {
+ return(NULL);
+ }
+ OBJ_ASSIGN ( (*obj), bhp->id );
+ if ( buf_hash_table[ndx] >= NUM_BUFS ) {
+ buf_hash_table[ndx] = bhp-bufhdr_table;
+ } else {
+ LISTPE_INSERT ( bufhdr_table, hash, bhp, buf_hash_table[ndx] );
+ }
+
+ bhp->flags |= BUF_VALID;
+ if ( flags & BF_PIN ) {
+ bhp->flags |= BUF_PINNED;
+ bhp->refcount++;
+#ifdef PIN_DEBUG
+ fprintf(stderr, "bf_assign_buf: %X PINNED (%d)\n",
+ buf_table + (bhp-bufhdr_table), bhp->refcount);
+#endif
+ }
+ fd = bf_fid_to_fd(obj->file_id);
+ if ( fd == -1 ) {
+ error_log1 ("Invalid fid %d\n", obj->file_id);
+ bhp->flags |= ~BUF_IO_ERROR;
+ return(NULL);
+ }
+ if ( obj->obj_id >= buf_fids[obj->file_id].npages) {
+ buf_fids[obj->file_id].npages = obj->obj_id+1;
+ *len = 0;
+ } else if ( flags & BF_EMPTY ) {
+ *len = 0;
+ } else {
+ bhp->flags |= BUF_IO_IN_PROGRESS;
+ if (RELEASE_MASTER) {
+ return(NULL);
+ }
+ if ( lseek ( fd, obj->obj_id << BUFSHIFT, L_SET ) < -1 ) {
+ error_log2 ("Unable to perform seek on file: %d to page %d",
+ obj->file_id, obj->obj_id );
+ bhp->flags &= ~BUF_IO_IN_PROGRESS;
+ bhp->flags |= ~BUF_IO_ERROR;
+ return(NULL);
+ }
+ *len = read(fd, buf_table[bhp-bufhdr_table], BUFSIZE);
+ if ( *len < 0 ) {
+ error_log2 ("Unable to perform read on file: %d to page %d",
+ obj->file_id, obj->obj_id );
+ bhp->flags &= ~BUF_IO_IN_PROGRESS;
+ bhp->flags |= ~BUF_IO_ERROR;
+ return(NULL);
+ }
+ if (GET_MASTER) {
+ return(NULL);
+ }
+ bhp->flags &= ~BUF_IO_IN_PROGRESS;
+ if ( bhp->wait_proc != -1 ) {
+ /* wake up waiter and anyone waiting on it */
+#ifdef DEBUG
+ printf("Waking transaction %d due to completed I/O\n",
+ bhp->wait_proc);
+#endif
+ proc_wake_id ( bhp->wait_proc );
+ bhp->wait_proc = -1;
+ }
+ MAKE_MRU(bhp);
+ }
+
+ if ( flags & BF_DIRTY ) {
+ bhp->flags |= BUF_DIRTY;
+ } else if ( *len < BUFSIZE ) {
+ bhp->flags |= BUF_NEWPAGE;
+ }
+ return ( bhp );
+}
+
+int
+buf_last ( fid )
+int fid;
+{
+ int val;
+
+ if (GET_MASTER) {
+ return(-1);
+ }
+ assert ( fid < NUM_FILE_ENTRIES );
+ if ( buf_fids[fid].npages == -1 ) {
+ /* initialize npages field */
+ (void) bf_fid_to_fd ( fid );
+ }
+ val = buf_fids[fid].npages;
+ if ( val ) {
+ val--; /* Convert to page number */
+ }
+ if (RELEASE_MASTER) {
+ return(-1);
+ }
+ return(val);
+}
+
+#ifdef DEBUG
+extern void
+buf_dump ( id, all )
+int id;
+int all;
+{
+ int i;
+ BUFHDR_T *bhp;
+
+ printf ( "LRU + %d\n", *buf_lru );
+ if ( all ) {
+ printf("ID\tFID\tPID\tLNEXT\tLPREV\tHNEXT\tHPREV\tSLEEP\tFLAG\tREFS\n");
+ for ( bhp = bufhdr_table, i = 0; i < NUM_BUFS; bhp++, i++ ) {
+ printf ( "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%x\t%d\n", i,
+ bhp->id.file_id, bhp->id.obj_id,
+ bhp->lru.next, bhp->lru.prev,
+ bhp->hash.next, bhp->hash.prev,
+ bhp->wait_proc, bhp->flags, bhp->refcount );
+ }
+ } else {
+ if ( id >= NUM_BUFS ) {
+ printf ( "Buffer ID (%d) too high\n", id );
+ return;
+ }
+ bhp = bufhdr_table+id;
+ printf ( "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%x\t%d\n", i,
+ bhp->id.file_id, bhp->id.obj_id,
+ bhp->lru.next, bhp->lru.prev,
+ bhp->hash.next, bhp->hash.prev,
+ bhp->wait_proc, bhp->flags, bhp->refcount );
+ }
+ return;
+}
+#endif
+
diff --git a/lib/libc/db/recno/Makefile.inc b/lib/libc/db/recno/Makefile.inc
index c0fd31125a1..e7f78f4ce76 100644
--- a/lib/libc/db/recno/Makefile.inc
+++ b/lib/libc/db/recno/Makefile.inc
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile.inc,v 1.4 1995/02/27 13:24:22 cgd Exp $
+# $NetBSD: Makefile.inc,v 1.5 1996/05/03 21:38:43 cgd Exp $
# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
.PATH: ${.CURDIR}/db/recno
diff --git a/lib/libc/db/recno/extern.h b/lib/libc/db/recno/extern.h
index 5ec5d2f220c..39d8d6379ab 100644
--- a/lib/libc/db/recno/extern.h
+++ b/lib/libc/db/recno/extern.h
@@ -1,4 +1,4 @@
-/* $NetBSD: extern.h,v 1.4 1995/02/27 13:24:30 cgd Exp $ */
+/* $NetBSD: extern.h,v 1.5 1996/05/03 21:38:44 cgd Exp $ */
/*-
* Copyright (c) 1991, 1993
diff --git a/lib/libc/db/recno/rec_close.c b/lib/libc/db/recno/rec_close.c
index 7c4dc283525..b8894afd732 100644
--- a/lib/libc/db/recno/rec_close.c
+++ b/lib/libc/db/recno/rec_close.c
@@ -1,7 +1,7 @@
-/* $NetBSD: rec_close.c,v 1.6 1995/02/27 13:24:37 cgd Exp $ */
+/* $NetBSD: rec_close.c,v 1.7 1996/05/03 21:38:45 cgd Exp $ */
/*-
- * Copyright (c) 1990, 1993
+ * 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
@@ -35,9 +35,9 @@
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
-static char sccsid[] = "@(#)rec_close.c 8.3 (Berkeley) 2/21/94";
+static char sccsid[] = "@(#)rec_close.c 8.6 (Berkeley) 8/18/94";
#else
-static char rcsid[] = "$NetBSD: rec_close.c,v 1.6 1995/02/27 13:24:37 cgd Exp $";
+static char rcsid[] = "$NetBSD: rec_close.c,v 1.7 1996/05/03 21:38:45 cgd Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
@@ -82,11 +82,11 @@ __rec_close(dbp)
/* Committed to closing. */
status = RET_SUCCESS;
- if (ISSET(t, R_MEMMAPPED) && munmap(t->bt_smap, t->bt_msize))
+ if (F_ISSET(t, R_MEMMAPPED) && munmap(t->bt_smap, t->bt_msize))
status = RET_ERROR;
- if (!ISSET(t, R_INMEM))
- if (ISSET(t, R_CLOSEFP)) {
+ if (!F_ISSET(t, R_INMEM))
+ if (F_ISSET(t, R_CLOSEFP)) {
if (fclose(t->bt_rfp))
status = RET_ERROR;
} else
@@ -131,39 +131,58 @@ __rec_sync(dbp, flags)
if (flags == R_RECNOSYNC)
return (__bt_sync(dbp, 0));
- if (ISSET(t, R_RDONLY | R_INMEM) || !ISSET(t, R_MODIFIED))
+ if (F_ISSET(t, R_RDONLY | R_INMEM) || !F_ISSET(t, R_MODIFIED))
return (RET_SUCCESS);
/* Read any remaining records into the tree. */
- if (!ISSET(t, R_EOF) && t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
+ 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);
- iov[1].iov_base = "\n";
- iov[1].iov_len = 1;
- scursor = t->bt_rcursor;
+ /* Save the cursor. */
+ scursor = t->bt_cursor.rcursor;
key.size = sizeof(recno_t);
key.data = &trec;
- 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 (writev(t->bt_rfd, iov, 2) != data.size + 1)
- return (RET_ERROR);
- status = (dbp->seq)(dbp, &key, &data, R_NEXT);
- }
- t->bt_rcursor = scursor;
+ 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 (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 (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);
- CLR(t, R_MODIFIED);
+ F_CLR(t, R_MODIFIED);
return (RET_SUCCESS);
}
diff --git a/lib/libc/db/recno/rec_delete.c b/lib/libc/db/recno/rec_delete.c
index 6f438a35cd9..3c6d48e698f 100644
--- a/lib/libc/db/recno/rec_delete.c
+++ b/lib/libc/db/recno/rec_delete.c
@@ -1,4 +1,4 @@
-/* $NetBSD: rec_delete.c,v 1.7 1995/02/27 13:24:48 cgd Exp $ */
+/* $NetBSD: rec_delete.c,v 1.8 1996/05/03 21:38:46 cgd Exp $ */
/*-
* Copyright (c) 1990, 1993, 1994
@@ -38,9 +38,9 @@
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
-static char sccsid[] = "@(#)rec_delete.c 8.6 (Berkeley) 6/4/94";
+static char sccsid[] = "@(#)rec_delete.c 8.7 (Berkeley) 7/14/94";
#else
-static char rcsid[] = "$NetBSD: rec_delete.c,v 1.7 1995/02/27 13:24:48 cgd Exp $";
+static char rcsid[] = "$NetBSD: rec_delete.c,v 1.8 1996/05/03 21:38:46 cgd Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
@@ -94,13 +94,13 @@ __rec_delete(dbp, key, flags)
status = rec_rdelete(t, nrec);
break;
case R_CURSOR:
- if (!ISSET(t, B_SEQINIT))
+ if (!F_ISSET(&t->bt_cursor, CURS_INIT))
goto einval;
if (t->bt_nrecs == 0)
return (RET_SPECIAL);
- status = rec_rdelete(t, t->bt_rcursor - 1);
+ status = rec_rdelete(t, t->bt_cursor.rcursor - 1);
if (status == RET_SUCCESS)
- --t->bt_rcursor;
+ --t->bt_cursor.rcursor;
break;
default:
einval: errno = EINVAL;
@@ -108,7 +108,7 @@ einval: errno = EINVAL;
}
if (status == RET_SUCCESS)
- SET(t, B_MODIFIED | R_MODIFIED);
+ F_SET(t, B_MODIFIED | R_MODIFIED);
return (status);
}
diff --git a/lib/libc/db/recno/rec_get.c b/lib/libc/db/recno/rec_get.c
index bc25104e552..a08e16f8089 100644
--- a/lib/libc/db/recno/rec_get.c
+++ b/lib/libc/db/recno/rec_get.c
@@ -1,4 +1,4 @@
-/* $NetBSD: rec_get.c,v 1.7 1995/02/27 13:24:57 cgd Exp $ */
+/* $NetBSD: rec_get.c,v 1.8 1996/05/03 21:38:48 cgd Exp $ */
/*-
* Copyright (c) 1990, 1993, 1994
@@ -35,9 +35,9 @@
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
-static char sccsid[] = "@(#)rec_get.c 8.5 (Berkeley) 6/20/94";
+static char sccsid[] = "@(#)rec_get.c 8.9 (Berkeley) 8/18/94";
#else
-static char rcsid[] = "$NetBSD: rec_get.c,v 1.7 1995/02/27 13:24:57 cgd Exp $";
+static char rcsid[] = "$NetBSD: rec_get.c,v 1.8 1996/05/03 21:38:48 cgd Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
@@ -96,7 +96,7 @@ __rec_get(dbp, key, data, flags)
* original file.
*/
if (nrec > t->bt_nrecs) {
- if (ISSET(t, R_EOF | R_INMEM))
+ if (F_ISSET(t, R_EOF | R_INMEM))
return (RET_SPECIAL);
if ((status = t->bt_irec(t, nrec)) != RET_SUCCESS)
return (status);
@@ -107,7 +107,7 @@ __rec_get(dbp, key, data, flags)
return (RET_ERROR);
status = __rec_ret(t, e, 0, NULL, data);
- if (ISSET(t, B_DB_LOCK))
+ if (F_ISSET(t, B_DB_LOCK))
mpool_put(t->bt_mp, e->page, 0);
else
t->bt_pinned = e->page;
@@ -133,32 +133,38 @@ __rec_fpipe(t, top)
recno_t nrec;
size_t len;
int ch;
- char *p;
+ u_char *p;
- if (t->bt_dbufsz < t->bt_reclen) {
- t->bt_dbuf = (char *)(t->bt_dbuf == NULL ?
- malloc(t->bt_reclen) : realloc(t->bt_dbuf, t->bt_reclen));
- if (t->bt_dbuf == NULL)
+ 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_dbufsz = t->bt_reclen;
+ t->bt_rdata.size = t->bt_reclen;
}
- data.data = t->bt_dbuf;
+ data.data = t->bt_rdata.data;
data.size = t->bt_reclen;
- for (nrec = t->bt_nrecs; nrec < top; ++nrec) {
+ for (nrec = t->bt_nrecs; nrec < top;) {
len = t->bt_reclen;
- for (p = t->bt_dbuf;; *p++ = ch)
- if ((ch = getc(t->bt_rfp)) == EOF || !len--) {
- if (__rec_iput(t, nrec, &data, 0)
- != RET_SUCCESS)
+ 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) {
- SET(t, R_EOF);
+ F_SET(t, R_EOF);
return (RET_SPECIAL);
}
return (RET_SUCCESS);
@@ -184,14 +190,15 @@ __rec_vpipe(t, top)
indx_t len;
size_t sz;
int bval, ch;
- char *p;
+ u_char *p;
bval = t->bt_bval;
for (nrec = t->bt_nrecs; nrec < top; ++nrec) {
- for (p = t->bt_dbuf, sz = t->bt_dbufsz;; *p++ = ch, --sz) {
+ 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_dbuf;
- data.size = p - t->bt_dbuf;
+ 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)
@@ -200,21 +207,21 @@ __rec_vpipe(t, top)
break;
}
if (sz == 0) {
- len = p - t->bt_dbuf;
- t->bt_dbufsz += (sz = 256);
- t->bt_dbuf = (char *)(t->bt_dbuf == NULL ?
- malloc(t->bt_dbufsz) :
- realloc(t->bt_dbuf, t->bt_dbufsz));
- if (t->bt_dbuf == NULL)
+ 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 = t->bt_dbuf + len;
+ p = (u_char *)t->bt_rdata.data + len;
}
}
if (ch == EOF)
break;
}
if (nrec < top) {
- SET(t, R_EOF);
+ F_SET(t, R_EOF);
return (RET_SPECIAL);
}
return (RET_SUCCESS);
@@ -237,34 +244,36 @@ __rec_fmap(t, top)
{
DBT data;
recno_t nrec;
- caddr_t sp, ep;
+ u_char *sp, *ep, *p;
size_t len;
- char *p;
- if (t->bt_dbufsz < t->bt_reclen) {
- t->bt_dbuf = (char *)(t->bt_dbuf == NULL ?
- malloc(t->bt_reclen) : realloc(t->bt_dbuf, t->bt_reclen));
- if (t->bt_dbuf == NULL)
+ 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_dbufsz = t->bt_reclen;
+ t->bt_rdata.size = t->bt_reclen;
}
- data.data = t->bt_dbuf;
+ data.data = t->bt_rdata.data;
data.size = t->bt_reclen;
- sp = t->bt_cmap;
- ep = t->bt_emap;
+ sp = (u_char *)t->bt_cmap;
+ ep = (u_char *)t->bt_emap;
for (nrec = t->bt_nrecs; nrec < top; ++nrec) {
if (sp >= ep) {
- SET(t, R_EOF);
+ F_SET(t, R_EOF);
return (RET_SPECIAL);
}
len = t->bt_reclen;
- for (p = t->bt_dbuf; sp < ep && len--; *p++ = *sp++);
- memset(p, t->bt_bval, len);
+ 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 = sp;
+ t->bt_cmap = (caddr_t)sp;
return (RET_SUCCESS);
}
@@ -284,25 +293,25 @@ __rec_vmap(t, top)
recno_t top;
{
DBT data;
- caddr_t sp, ep;
+ u_char *sp, *ep;
recno_t nrec;
int bval;
- sp = t->bt_cmap;
- ep = t->bt_emap;
+ 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) {
- SET(t, R_EOF);
+ F_SET(t, R_EOF);
return (RET_SPECIAL);
}
for (data.data = sp; sp < ep && *sp != bval; ++sp);
- data.size = sp - (caddr_t)data.data;
+ data.size = sp - (u_char *)data.data;
if (__rec_iput(t, nrec, &data, 0) != RET_SUCCESS)
return (RET_ERROR);
++sp;
}
- t->bt_cmap = sp;
+ t->bt_cmap = (caddr_t)sp;
return (RET_SUCCESS);
}
diff --git a/lib/libc/db/recno/rec_open.c b/lib/libc/db/recno/rec_open.c
index e67a7b6f000..d2c9369b730 100644
--- a/lib/libc/db/recno/rec_open.c
+++ b/lib/libc/db/recno/rec_open.c
@@ -1,7 +1,7 @@
-/* $NetBSD: rec_open.c,v 1.6 1995/02/27 13:25:05 cgd Exp $ */
+/* $NetBSD: rec_open.c,v 1.7 1996/05/03 21:38:49 cgd Exp $ */
/*-
- * Copyright (c) 1990, 1993
+ * 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
@@ -38,9 +38,9 @@
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
-static char sccsid[] = "@(#)rec_open.c 8.6 (Berkeley) 2/22/94";
+static char sccsid[] = "@(#)rec_open.c 8.10 (Berkeley) 9/1/94";
#else
-static char rcsid[] = "$NetBSD: rec_open.c,v 1.6 1995/02/27 13:25:05 cgd Exp $";
+static char rcsid[] = "$NetBSD: rec_open.c,v 1.7 1996/05/03 21:38:49 cgd Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
@@ -104,7 +104,7 @@ __rec_open(fname, flags, mode, openinfo, dflags)
t = dbp->internal;
if (openinfo) {
if (openinfo->flags & R_FIXEDLEN) {
- SET(t, R_FIXLEN);
+ F_SET(t, R_FIXLEN);
t->bt_reclen = openinfo->reclen;
if (t->bt_reclen == 0)
goto einval;
@@ -113,12 +113,11 @@ __rec_open(fname, flags, mode, openinfo, dflags)
} else
t->bt_bval = '\n';
- SET(t, R_RECNO);
+ F_SET(t, R_RECNO);
if (fname == NULL)
- SET(t, R_EOF | R_INMEM);
+ F_SET(t, R_EOF | R_INMEM);
else
t->bt_rfd = rfd;
- t->bt_rcursor = 0;
if (fname != NULL) {
/*
@@ -130,20 +129,20 @@ __rec_open(fname, flags, mode, openinfo, dflags)
if (lseek(rfd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE) {
switch (flags & O_ACCMODE) {
case O_RDONLY:
- SET(t, R_RDONLY);
+ F_SET(t, R_RDONLY);
break;
default:
goto einval;
}
slow: if ((t->bt_rfp = fdopen(rfd, "r")) == NULL)
goto err;
- SET(t, R_CLOSEFP);
+ F_SET(t, R_CLOSEFP);
t->bt_irec =
- ISSET(t, R_FIXLEN) ? __rec_fpipe : __rec_vpipe;
+ F_ISSET(t, R_FIXLEN) ? __rec_fpipe : __rec_vpipe;
} else {
switch (flags & O_ACCMODE) {
case O_RDONLY:
- SET(t, R_RDONLY);
+ F_SET(t, R_RDONLY);
break;
case O_RDWR:
break;
@@ -163,8 +162,16 @@ slow: if ((t->bt_rfp = fdopen(rfd, "r")) == NULL)
* fails if the file is too large.
*/
if (sb.st_size == 0)
- SET(t, R_EOF);
+ 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,
@@ -172,9 +179,12 @@ slow: if ((t->bt_rfp = fdopen(rfd, "r")) == NULL)
goto slow;
t->bt_cmap = t->bt_smap;
t->bt_emap = t->bt_smap + sb.st_size;
- t->bt_irec = ISSET(t, R_FIXLEN) ?
+ t->bt_irec = F_ISSET(t, R_FIXLEN) ?
__rec_fmap : __rec_vmap;
- SET(t, R_MEMMAPPED);
+ F_SET(t, R_MEMMAPPED);
+#else
+ goto slow;
+#endif
}
}
}
@@ -192,13 +202,14 @@ slow: if ((t->bt_rfp = fdopen(rfd, "r")) == NULL)
if ((h = mpool_get(t->bt_mp, P_ROOT, 0)) == NULL)
goto err;
if ((h->flags & P_TYPE) == P_BLEAF) {
- h->flags = h->flags & ~P_TYPE | P_RLEAF;
+ 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 &&
- !ISSET(t, R_EOF | R_INMEM) &&
+ !F_ISSET(t, R_EOF | R_INMEM) &&
t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
goto err;
return (dbp);
@@ -228,7 +239,7 @@ __rec_fd(dbp)
}
/* In-memory database can't have a file descriptor. */
- if (ISSET(t, R_INMEM)) {
+ if (F_ISSET(t, R_INMEM)) {
errno = ENOENT;
return (-1);
}
diff --git a/lib/libc/db/recno/rec_put.c b/lib/libc/db/recno/rec_put.c
index 77d7079fb73..107d645a649 100644
--- a/lib/libc/db/recno/rec_put.c
+++ b/lib/libc/db/recno/rec_put.c
@@ -1,4 +1,4 @@
-/* $NetBSD: rec_put.c,v 1.7 1995/02/27 13:25:13 cgd Exp $ */
+/* $NetBSD: rec_put.c,v 1.8 1996/05/03 21:38:50 cgd Exp $ */
/*-
* Copyright (c) 1990, 1993, 1994
@@ -35,9 +35,9 @@
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
-static char sccsid[] = "@(#)rec_put.c 8.4 (Berkeley) 5/31/94";
+static char sccsid[] = "@(#)rec_put.c 8.7 (Berkeley) 8/18/94";
#else
-static char rcsid[] = "$NetBSD: rec_put.c,v 1.7 1995/02/27 13:25:13 cgd Exp $";
+static char rcsid[] = "$NetBSD: rec_put.c,v 1.8 1996/05/03 21:38:50 cgd Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
@@ -72,7 +72,7 @@ __rec_put(dbp, key, data, flags)
u_int flags;
{
BTREE *t;
- DBT tdata;
+ DBT fdata, tdata;
recno_t nrec;
int status;
@@ -84,11 +84,38 @@ __rec_put(dbp, key, data, flags)
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 (!ISSET(t, B_SEQINIT))
+ if (!F_ISSET(&t->bt_cursor, CURS_INIT))
goto einval;
- nrec = t->bt_rcursor;
+ nrec = t->bt_cursor.rcursor;
break;
case R_SETCURSOR:
if ((nrec = *(recno_t *)key->data) == 0)
@@ -121,11 +148,11 @@ einval: errno = EINVAL;
* already in the database. If skipping records, create empty ones.
*/
if (nrec > t->bt_nrecs) {
- if (!ISSET(t, R_EOF | R_INMEM) &&
+ 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 (ISSET(t, R_FIXLEN)) {
+ if (F_ISSET(t, R_FIXLEN)) {
if ((tdata.data =
(void *)malloc(t->bt_reclen)) == NULL)
return (RET_ERROR);
@@ -139,18 +166,18 @@ einval: errno = EINVAL;
if (__rec_iput(t,
t->bt_nrecs, &tdata, 0) != RET_SUCCESS)
return (RET_ERROR);
- if (ISSET(t, R_FIXLEN))
+ if (F_ISSET(t, R_FIXLEN))
free(tdata.data);
}
}
- if ((status = __rec_iput(t, nrec - 1, data, flags)) != RET_SUCCESS)
+ if ((status = __rec_iput(t, nrec - 1, &fdata, flags)) != RET_SUCCESS)
return (status);
if (flags == R_SETCURSOR)
- t->bt_rcursor = nrec;
+ t->bt_cursor.rcursor = nrec;
- SET(t, R_MODIFIED);
+ F_SET(t, R_MODIFIED);
return (__rec_ret(t, NULL, nrec, key, NULL));
}
@@ -252,7 +279,7 @@ __rec_iput(t, nrec, data, flags)
WR_RLEAF(dest, data, dflags);
++t->bt_nrecs;
- SET(t, B_MODIFIED);
+ F_SET(t, B_MODIFIED);
mpool_put(t->bt_mp, h, MPOOL_DIRTY);
return (RET_SUCCESS);
diff --git a/lib/libc/db/recno/rec_search.c b/lib/libc/db/recno/rec_search.c
index 208328d9ddd..beb714b5146 100644
--- a/lib/libc/db/recno/rec_search.c
+++ b/lib/libc/db/recno/rec_search.c
@@ -1,4 +1,4 @@
-/* $NetBSD: rec_search.c,v 1.6 1995/02/27 13:25:17 cgd Exp $ */
+/* $NetBSD: rec_search.c,v 1.7 1996/05/03 21:38:52 cgd Exp $ */
/*-
* Copyright (c) 1990, 1993
@@ -35,9 +35,9 @@
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
-static char sccsid[] = "@(#)rec_search.c 8.3 (Berkeley) 2/21/94";
+static char sccsid[] = "@(#)rec_search.c 8.4 (Berkeley) 7/14/94";
#else
-static char rcsid[] = "$NetBSD: rec_search.c,v 1.6 1995/02/27 13:25:17 cgd Exp $";
+static char rcsid[] = "$NetBSD: rec_search.c,v 1.7 1996/05/03 21:38:52 cgd Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
@@ -97,8 +97,7 @@ __rec_search(t, recno, op)
total += r->nrecs;
}
- if (__bt_push(t, pg, index - 1) == RET_ERROR)
- return (NULL);
+ BT_PUSH(t, pg, index - 1);
pg = r->pgno;
switch (op) {
diff --git a/lib/libc/db/recno/rec_seq.c b/lib/libc/db/recno/rec_seq.c
index b91f3a27bf6..3b5c534dda6 100644
--- a/lib/libc/db/recno/rec_seq.c
+++ b/lib/libc/db/recno/rec_seq.c
@@ -1,7 +1,7 @@
-/* $NetBSD: rec_seq.c,v 1.6 1995/02/27 13:25:24 cgd Exp $ */
+/* $NetBSD: rec_seq.c,v 1.7 1996/05/03 21:38:53 cgd Exp $ */
/*-
- * Copyright (c) 1991, 1993
+ * 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
@@ -35,9 +35,9 @@
#ifndef lint
#if 0
-static char sccsid[] = "@(#)rec_seq.c 8.2 (Berkeley) 9/7/93";
+static char sccsid[] = "@(#)rec_seq.c 8.3 (Berkeley) 7/14/94";
#else
-static char rcsid[] = "$NetBSD: rec_seq.c,v 1.6 1995/02/27 13:25:24 cgd Exp $";
+static char rcsid[] = "$NetBSD: rec_seq.c,v 1.7 1996/05/03 21:38:53 cgd Exp $";
#endif
#endif /* not lint */
@@ -88,8 +88,8 @@ __rec_seq(dbp, key, data, flags)
goto einval;
break;
case R_NEXT:
- if (ISSET(t, B_SEQINIT)) {
- nrec = t->bt_rcursor + 1;
+ if (F_ISSET(&t->bt_cursor, CURS_INIT)) {
+ nrec = t->bt_cursor.rcursor + 1;
break;
}
/* FALLTHROUGH */
@@ -97,14 +97,14 @@ __rec_seq(dbp, key, data, flags)
nrec = 1;
break;
case R_PREV:
- if (ISSET(t, B_SEQINIT)) {
- if ((nrec = t->bt_rcursor - 1) == 0)
+ 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 (!ISSET(t, R_EOF | R_INMEM) &&
+ if (!F_ISSET(t, R_EOF | R_INMEM) &&
t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
return (RET_ERROR);
nrec = t->bt_nrecs;
@@ -115,7 +115,7 @@ einval: errno = EINVAL;
}
if (t->bt_nrecs == 0 || nrec > t->bt_nrecs) {
- if (!ISSET(t, R_EOF | R_INMEM) &&
+ 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)
@@ -125,11 +125,11 @@ einval: errno = EINVAL;
if ((e = __rec_search(t, nrec - 1, SEARCH)) == NULL)
return (RET_ERROR);
- SET(t, B_SEQINIT);
- t->bt_rcursor = nrec;
+ F_SET(&t->bt_cursor, CURS_INIT);
+ t->bt_cursor.rcursor = nrec;
status = __rec_ret(t, e, nrec, key, data);
- if (ISSET(t, B_DB_LOCK))
+ if (F_ISSET(t, B_DB_LOCK))
mpool_put(t->bt_mp, e->page, 0);
else
t->bt_pinned = e->page;
diff --git a/lib/libc/db/recno/rec_utils.c b/lib/libc/db/recno/rec_utils.c
index 7aab4ac3a91..e411dae7db4 100644
--- a/lib/libc/db/recno/rec_utils.c
+++ b/lib/libc/db/recno/rec_utils.c
@@ -1,4 +1,4 @@
-/* $NetBSD: rec_utils.c,v 1.6 1995/02/27 13:25:29 cgd Exp $ */
+/* $NetBSD: rec_utils.c,v 1.7 1996/05/03 21:38:54 cgd Exp $ */
/*-
* Copyright (c) 1990, 1993, 1994
@@ -35,9 +35,9 @@
#if defined(LIBC_SCCS) && !defined(lint)
#if 0
-static char sccsid[] = "@(#)rec_utils.c 8.4 (Berkeley) 6/20/94";
+static char sccsid[] = "@(#)rec_utils.c 8.6 (Berkeley) 7/16/94";
#else
-static char rcsid[] = "$NetBSD: rec_utils.c,v 1.6 1995/02/27 13:25:29 cgd Exp $";
+static char rcsid[] = "$NetBSD: rec_utils.c,v 1.7 1996/05/03 21:38:54 cgd Exp $";
#endif
#endif /* LIBC_SCCS and not lint */
@@ -51,11 +51,14 @@ static char rcsid[] = "$NetBSD: rec_utils.c,v 1.6 1995/02/27 13:25:29 cgd Exp $"
#include "recno.h"
/*
- * __REC_RET -- Build return data as a result of search or scan.
+ * __rec_ret --
+ * Build return data.
*
* Parameters:
* t: tree
- * d: LEAF to be returned to the user.
+ * e: key/data pair to be returned
+ * nrec: record number
+ * key: user's key structure
* data: user's data structure
*
* Returns:
@@ -68,58 +71,58 @@ __rec_ret(t, e, nrec, key, data)
recno_t nrec;
DBT *key, *data;
{
- register RLEAF *rl;
- register void *p;
+ RLEAF *rl;
+ void *p;
- if (data == NULL)
- goto retkey;
+ if (key == NULL)
+ goto dataonly;
- rl = GETRLEAF(e->page, e->index);
+ /* 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 always copy big data to make it contigous. Otherwise, we
+ * We must copy big keys/data to make them contigous. 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_dbuf, &t->bt_dbufsz))
+ &data->size, &t->bt_rdata.data, &t->bt_rdata.size))
return (RET_ERROR);
- data->data = t->bt_dbuf;
- } else if (ISSET(t, B_DB_LOCK)) {
+ 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_dbufsz) {
- p = (void *)(t->bt_dbuf == NULL ?
+ if (rl->dsize + 1 > t->bt_rdata.size) {
+ p = (void *)(t->bt_rdata.data == NULL ?
malloc(rl->dsize + 1) :
- realloc(t->bt_dbuf, rl->dsize + 1));
+ realloc(t->bt_rdata.data, rl->dsize + 1));
if (p == NULL)
return (RET_ERROR);
- t->bt_dbuf = p;
- t->bt_dbufsz = rl->dsize + 1;
+ t->bt_rdata.data = p;
+ t->bt_rdata.size = rl->dsize + 1;
}
- memmove(t->bt_dbuf, rl->bytes, rl->dsize);
+ memmove(t->bt_rdata.data, rl->bytes, rl->dsize);
data->size = rl->dsize;
- data->data = t->bt_dbuf;
+ data->data = t->bt_rdata.data;
} else {
data->size = rl->dsize;
data->data = rl->bytes;
}
-
-retkey: if (key == NULL)
- return (RET_SUCCESS);
-
- /* We have to copy the key, it's not on the page. */
- if (sizeof(recno_t) > t->bt_kbufsz) {
- p = (void *)(t->bt_kbuf == NULL ?
- malloc(sizeof(recno_t)) :
- realloc(t->bt_kbuf, sizeof(recno_t)));
- if (p == NULL)
- return (RET_ERROR);
- t->bt_kbuf = p;
- t->bt_kbufsz = sizeof(recno_t);
- }
- memmove(t->bt_kbuf, &nrec, sizeof(recno_t));
- key->size = sizeof(recno_t);
- key->data = t->bt_kbuf;
return (RET_SUCCESS);
}
diff --git a/lib/libc/db/recno/recno.h b/lib/libc/db/recno/recno.h
index 5c1c716ace3..747c7bd9ee7 100644
--- a/lib/libc/db/recno/recno.h
+++ b/lib/libc/db/recno/recno.h
@@ -1,4 +1,4 @@
-/* $NetBSD: recno.h,v 1.4 1995/02/27 13:25:35 cgd Exp $ */
+/* $NetBSD: recno.h,v 1.5 1996/05/03 21:38:55 cgd Exp $ */
/*-
* Copyright (c) 1991, 1993
diff --git a/regress/lib/libc/db/README b/regress/lib/libc/db/README
index 3b290b09d81..fddf5c3d5a0 100644
--- a/regress/lib/libc/db/README
+++ b/regress/lib/libc/db/README
@@ -1,5 +1,5 @@
-# $NetBSD: README,v 1.4 1995/04/20 22:39:18 cgd Exp $
-# @(#)README 8.4 (Berkeley) 6/20/94
+# $NetBSD: README,v 1.5 1996/05/03 21:54:19 cgd Exp $
+# @(#)README 8.8 (Berkeley) 7/31/94
To run the tests, enter "make regress".
@@ -9,8 +9,11 @@ the test runs, and even larger files (the database files) are created in
variable TMPDIR to a directory where the files can be built.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-The script file consists of lines with a initial character which is
-the "command" for that line. Legal characters are as follows:
+The script file consists of lines with an initial character which is
+the command for that line, or an initial character indicating a key
+or data entry for a previous command.
+
+Legal command characters are as follows:
c: compare a record
+ must be followed by [kK][dD]; the data value in the database
@@ -19,17 +22,24 @@ c: compare a record
e: echo a string
+ writes out the rest of the line into the output file; if the
last character is not a carriage-return, a newline is appended.
+f: set the flags for the next command
+ + no value zero's the flags
g: do a get command
+ must be followed by [kK]
+ writes out the retrieved data DBT.
+o [r]: dump [reverse]
+ + dump the database out, if 'r' is set, in reverse order.
p: do a put command
+ must be followed by [kK][dD]
r: do a del command
- + must be followed by [kK]
+ + must be followed by [kK] unless R_CURSOR flag set.
+S: sync the database
s: do a seq command
+ + must be followed by [kK] if R_CURSOR flag set.
+ writes out the retrieved data DBT.
-f: set the flags for the next command
- + no value zero's the flags
+
+Legal key/data characters are as follows:
+
D [file]: data file
+ set the current data value to the contents of the file
d [data]:
@@ -38,17 +48,21 @@ K [file]: key file
+ set the current key value to the contents of the file
k [data]:
+ set the current key value to the contents of the line.
-o [r]: dump [reverse]
- + dump the database out, if 'r' is set, in reverse order.
+
+Blank lines, lines with leading white space, and lines with leading
+hash marks (#) are ignored.
Options to dbtest are as follows:
+ -d: Set the DB_LOCK flag.
-f: Use the file argument as the database file.
-i: Use the rest of the argument to set elements in the info
structure. If the type is btree, then "-i cachesize=10240"
will set BTREEINFO.cachesize to 10240.
-o: The rest of the argument is the output file instead of
using stdout.
+ -s: Don't delete the database file before opening it, i.e.
+ use the database file from a previous run.
-Dbtest requires two arguments, the type of access "hash", "recno" or
-"btree", and the script name.
+Dbtest requires two arguments, the type of access "hash", "recno"
+or "btree", and the script name or "-" to indicate stdin.
diff --git a/regress/lib/libc/db/dbtest.c b/regress/lib/libc/db/dbtest.c
index 1fcf09af97f..65587a6fcb2 100644
--- a/regress/lib/libc/db/dbtest.c
+++ b/regress/lib/libc/db/dbtest.c
@@ -1,7 +1,7 @@
-/* $NetBSD: dbtest.c,v 1.7 1995/04/20 22:39:22 cgd Exp $ */
+/* $NetBSD: dbtest.c,v 1.8 1996/05/03 21:57:48 cgd Exp $ */
/*-
- * Copyright (c) 1992, 1993
+ * Copyright (c) 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,15 +35,15 @@
#ifndef lint
static char copyright[] =
-"@(#) Copyright (c) 1992, 1993\n\
+"@(#) Copyright (c) 1992, 1993, 1994\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
#if 0
-static char sccsid[] = "@(#)dbtest.c 8.8 (Berkeley) 2/21/94";
+static char sccsid[] = "@(#)dbtest.c 8.17 (Berkeley) 9/1/94";
#else
-static char rcsid[] = "$NetBSD: dbtest.c,v 1.7 1995/04/20 22:39:22 cgd Exp $";
+static char rcsid[] = "$NetBSD: dbtest.c,v 1.8 1996/05/03 21:57:48 cgd Exp $";
#endif
#endif /* not lint */
@@ -71,6 +71,8 @@ void get __P((DB *, DBT *));
void getdata __P((DB *, DBT *, DBT *));
void put __P((DB *, DBT *, DBT *));
void rem __P((DB *, DBT *));
+char *sflags __P((int));
+void synk __P((DB *));
void *rfile __P((char *, size_t *));
void seq __P((DB *, DBT *));
u_int setflags __P((char *));
@@ -78,13 +80,14 @@ void *setinfo __P((DBTYPE, char *));
void usage __P((void));
void *xmalloc __P((char *, size_t));
-DBTYPE type;
-void *infop;
-u_long lineno;
-u_int flags;
-int ofd = STDOUT_FILENO;
+DBTYPE type; /* Database type. */
+void *infop; /* Iflags. */
+u_long lineno; /* Current line in test script. */
+u_int flags; /* Current DB flags. */
+int ofd = STDOUT_FILENO; /* Standard output fd. */
DB *XXdbp; /* Global for gdb. */
+int XXlineno; /* Fast breakpoint for gdb. */
int
main(argc, argv)
@@ -97,14 +100,15 @@ main(argc, argv)
DB *dbp;
DBT data, key, keydata;
size_t len;
- int ch, oflags;
- char *fname, *infoarg, *p, buf[8 * 1024];
+ int ch, oflags, sflag;
+ char *fname, *infoarg, *p, *t, buf[8 * 1024];
infoarg = NULL;
fname = NULL;
oflags = O_CREAT | O_RDWR;
- while ((ch = getopt(argc, argv, "f:i:lo:")) != EOF)
- switch(ch) {
+ sflag = 0;
+ while ((ch = getopt(argc, argv, "f:i:lo:s")) != EOF)
+ switch (ch) {
case 'f':
fname = optarg;
break;
@@ -119,6 +123,9 @@ main(argc, argv)
O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
err("%s: %s", optarg, strerror(errno));
break;
+ case 's':
+ sflag = 1;
+ break;
case '?':
default:
usage();
@@ -133,8 +140,8 @@ main(argc, argv)
type = dbtype(*argv++);
/* Open the descriptor file. */
- if (freopen(*argv, "r", stdin) == NULL)
- err("%s: %s", *argv, strerror(errno));
+ if (strcmp(*argv, "-") && freopen(*argv, "r", stdin) == NULL)
+ err("%s: %s", *argv, strerror(errno));
/* Set up the db structure as necessary. */
if (infoarg == NULL)
@@ -145,7 +152,10 @@ main(argc, argv)
if (*p != '\0')
infop = setinfo(type, p);
- /* Open the DB. */
+ /*
+ * Open the DB. Delete any preexisting copy, you almost never
+ * want it around, and it often screws up tests.
+ */
if (fname == NULL) {
p = getenv("TMPDIR");
if (p == NULL)
@@ -153,7 +163,9 @@ main(argc, argv)
(void)sprintf(buf, "%s/__dbtest", p);
fname = buf;
(void)unlink(buf);
- }
+ } else if (!sflag)
+ (void)unlink(fname);
+
if ((dbp = dbopen(fname,
oflags, S_IRUSR | S_IWUSR, type, infop)) == NULL)
err("dbopen: %s", strerror(errno));
@@ -162,8 +174,16 @@ main(argc, argv)
state = COMMAND;
for (lineno = 1;
(p = fgets(buf, sizeof(buf), stdin)) != NULL; ++lineno) {
- len = strlen(buf);
- switch(*p) {
+ /* Delete the newline, displaying the key/data is easier. */
+ if (ofd == STDOUT_FILENO && (t = strchr(p, '\n')) != NULL)
+ *t = '\0';
+ if ((len = strlen(buf)) == 0 || isspace(*p) || *p == '#')
+ continue;
+
+ /* Convenient gdb break point. */
+ if (XXlineno == lineno)
+ XXlineno = 1;
+ switch (*p) {
case 'c': /* compare */
if (state != COMMAND)
err("line %lu: not expecting command", lineno);
@@ -176,7 +196,8 @@ main(argc, argv)
/* Don't display the newline, if CR at EOL. */
if (p[len - 2] == '\r')
--len;
- if (write(ofd, p + 1, len - 1) != len - 1)
+ if (write(ofd, p + 1, len - 1) != len - 1 ||
+ write(ofd, "\n", 1) != 1)
err("write: %s", strerror(errno));
break;
case 'g': /* get */
@@ -194,8 +215,19 @@ main(argc, argv)
case 'r': /* remove */
if (state != COMMAND)
err("line %lu: not expecting command", lineno);
- state = KEY;
- command = REMOVE;
+ if (flags == R_CURSOR) {
+ rem(dbp, &key);
+ state = COMMAND;
+ } else {
+ state = KEY;
+ command = REMOVE;
+ }
+ break;
+ case 'S': /* sync */
+ if (state != COMMAND)
+ err("line %lu: not expecting command", lineno);
+ synk(dbp);
+ state = COMMAND;
break;
case 's': /* seq */
if (state != COMMAND)
@@ -219,7 +251,7 @@ main(argc, argv)
err("line %lu: not expecting data", lineno);
data.data = xmalloc(p + 1, len - 1);
data.size = len - 1;
-ldata: switch(command) {
+ldata: switch (command) {
case COMPARE:
compare(&keydata, &data);
break;
@@ -255,7 +287,7 @@ ldata: switch(command) {
key.data = xmalloc(p + 1, len - 1);
key.size = len - 1;
}
-lkey: switch(command) {
+lkey: switch (command) {
case COMPARE:
getdata(dbp, &key, &keydata);
state = DATA;
@@ -271,13 +303,13 @@ lkey: switch(command) {
break;
case REMOVE:
rem(dbp, &key);
- if (type != DB_RECNO)
+ if ((type != DB_RECNO) && (flags != R_CURSOR))
free(key.data);
state = COMMAND;
break;
case SEQ:
seq(dbp, &key);
- if (type != DB_RECNO)
+ if ((type != DB_RECNO) && (flags != R_CURSOR))
free(key.data);
state = COMMAND;
break;
@@ -291,11 +323,15 @@ lkey: switch(command) {
break;
default:
err("line %lu: %s: unknown command character",
- p, lineno);
+ lineno, p);
}
}
#ifdef STATISTICS
- if (type == DB_BTREE)
+ /*
+ * -l must be used (DB_LOCK must be set) for this to be
+ * used, otherwise a page will be locked and it will fail.
+ */
+ if (type == DB_BTREE && oflags & DB_LOCK)
__bt_stat(dbp);
#endif
if (dbp->close(dbp))
@@ -305,7 +341,6 @@ lkey: switch(command) {
}
#define NOOVERWRITE "put failed, would overwrite key\n"
-#define NOSUCHKEY "get failed, no such key\n"
void
compare(db1, db2)
@@ -334,17 +369,23 @@ get(dbp, kp)
{
DBT data;
- switch(dbp->get(dbp, kp, &data, flags)) {
+ switch (dbp->get(dbp, kp, &data, flags)) {
case 0:
(void)write(ofd, data.data, data.size);
+ if (ofd == STDOUT_FILENO)
+ (void)write(ofd, "\n", 1);
break;
case -1:
err("line %lu: get: %s", lineno, strerror(errno));
/* NOTREACHED */
case 1:
- (void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1);
- (void)fprintf(stderr, "%d: %.*s: %s\n",
- lineno, kp->size, kp->data, NOSUCHKEY);
+#define NOSUCHKEY "get failed, no such key\n"
+ if (ofd != STDOUT_FILENO)
+ (void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1);
+ else
+ (void)fprintf(stderr, "%d: %.*s: %s",
+ lineno, MIN(kp->size, 20), kp->data, NOSUCHKEY);
+#undef NOSUCHKEY
break;
}
}
@@ -354,14 +395,14 @@ getdata(dbp, kp, dp)
DB *dbp;
DBT *kp, *dp;
{
- switch(dbp->get(dbp, kp, dp, flags)) {
+ switch (dbp->get(dbp, kp, dp, flags)) {
case 0:
return;
case -1:
err("line %lu: getdata: %s", lineno, strerror(errno));
/* NOTREACHED */
case 1:
- err("line %lu: get failed, no such key", lineno);
+ err("line %lu: getdata failed, no such key", lineno);
/* NOTREACHED */
}
}
@@ -371,7 +412,7 @@ put(dbp, kp, dp)
DB *dbp;
DBT *kp, *dp;
{
- switch(dbp->put(dbp, kp, dp, flags)) {
+ switch (dbp->put(dbp, kp, dp, flags)) {
case 0:
break;
case -1:
@@ -388,34 +429,67 @@ rem(dbp, kp)
DB *dbp;
DBT *kp;
{
- switch(dbp->del(dbp, kp, flags)) {
+ switch (dbp->del(dbp, kp, flags)) {
case 0:
break;
case -1:
- err("line %lu: get: %s", lineno, strerror(errno));
+ err("line %lu: rem: %s", lineno, strerror(errno));
/* NOTREACHED */
case 1:
- (void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1);
+#define NOSUCHKEY "rem failed, no such key\n"
+ if (ofd != STDOUT_FILENO)
+ (void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1);
+ else if (flags != R_CURSOR)
+ (void)fprintf(stderr, "%d: %.*s: %s",
+ lineno, MIN(kp->size, 20), kp->data, NOSUCHKEY);
+ else
+ (void)fprintf(stderr,
+ "%d: rem of cursor failed\n", lineno);
+#undef NOSUCHKEY
break;
}
}
void
+synk(dbp)
+ DB *dbp;
+{
+ switch (dbp->sync(dbp, flags)) {
+ case 0:
+ break;
+ case -1:
+ err("line %lu: synk: %s", lineno, strerror(errno));
+ /* NOTREACHED */
+ }
+}
+
+void
seq(dbp, kp)
DB *dbp;
DBT *kp;
{
DBT data;
- switch(dbp->seq(dbp, kp, &data, flags)) {
+ switch (dbp->seq(dbp, kp, &data, flags)) {
case 0:
(void)write(ofd, data.data, data.size);
+ if (ofd == STDOUT_FILENO)
+ (void)write(ofd, "\n", 1);
break;
case -1:
err("line %lu: seq: %s", lineno, strerror(errno));
/* NOTREACHED */
case 1:
- (void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1);
+#define NOSUCHKEY "seq failed, no such key\n"
+ if (ofd != STDOUT_FILENO)
+ (void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1);
+ else if (flags == R_CURSOR)
+ (void)fprintf(stderr, "%d: %.*s: %s",
+ lineno, MIN(kp->size, 20), kp->data, NOSUCHKEY);
+ else
+ (void)fprintf(stderr,
+ "%d: seq (%s) failed\n", lineno, sflags(flags));
+#undef NOSUCHKEY
break;
}
}
@@ -436,9 +510,11 @@ dump(dbp, rev)
nflags = R_NEXT;
}
for (;; flags = nflags)
- switch(dbp->seq(dbp, &key, &data, flags)) {
+ switch (dbp->seq(dbp, &key, &data, flags)) {
case 0:
(void)write(ofd, data.data, data.size);
+ if (ofd == STDOUT_FILENO)
+ (void)write(ofd, "\n", 1);
break;
case 1:
goto done;
@@ -457,31 +533,42 @@ setflags(s)
char *p, *index();
for (; isspace(*s); ++s);
- if (*s == '\n')
+ if (*s == '\n' || *s == '\0')
return (0);
if ((p = index(s, '\n')) != NULL)
*p = '\0';
- if (!strcmp(s, "R_CURSOR"))
- return (R_CURSOR);
- if (!strcmp(s, "R_FIRST"))
- return (R_FIRST);
- if (!strcmp(s, "R_IAFTER"))
- return (R_IAFTER);
- if (!strcmp(s, "R_IBEFORE"))
- return (R_IBEFORE);
- if (!strcmp(s, "R_LAST"))
- return (R_LAST);
- if (!strcmp(s, "R_NEXT"))
- return (R_NEXT);
- if (!strcmp(s, "R_NOOVERWRITE"))
- return (R_NOOVERWRITE);
- if (!strcmp(s, "R_PREV"))
- return (R_PREV);
- if (!strcmp(s, "R_SETCURSOR"))
- return (R_SETCURSOR);
+ if (!strcmp(s, "R_CURSOR")) return (R_CURSOR);
+ if (!strcmp(s, "R_FIRST")) return (R_FIRST);
+ if (!strcmp(s, "R_IAFTER")) return (R_IAFTER);
+ if (!strcmp(s, "R_IBEFORE")) return (R_IBEFORE);
+ if (!strcmp(s, "R_LAST")) return (R_LAST);
+ if (!strcmp(s, "R_NEXT")) return (R_NEXT);
+ if (!strcmp(s, "R_NOOVERWRITE")) return (R_NOOVERWRITE);
+ if (!strcmp(s, "R_PREV")) return (R_PREV);
+ if (!strcmp(s, "R_SETCURSOR")) return (R_SETCURSOR);
+
err("line %lu: %s: unknown flag", lineno, s);
/* NOTREACHED */
}
+
+char *
+sflags(flags)
+ int flags;
+{
+ switch (flags) {
+ case R_CURSOR: return ("R_CURSOR");
+ case R_FIRST: return ("R_FIRST");
+ case R_IAFTER: return ("R_IAFTER");
+ case R_IBEFORE: return ("R_IBEFORE");
+ case R_LAST: return ("R_LAST");
+ case R_NEXT: return ("R_NEXT");
+ case R_NOOVERWRITE: return ("R_NOOVERWRITE");
+ case R_PREV: return ("R_PREV");
+ case R_SETCURSOR: return ("R_SETCURSOR");
+ }
+
+ return ("UNKNOWN!");
+}
DBTYPE
dbtype(s)
@@ -513,7 +600,7 @@ setinfo(type, s)
if (!isdigit(*eq))
err("%s: structure set statement must be a number", s);
- switch(type) {
+ switch (type) {
case DB_BTREE:
if (!strcmp("flags", s)) {
ib.flags = atoi(eq);
diff --git a/regress/lib/libc/db/run.test b/regress/lib/libc/db/run.test
index 4073310a311..acbd3f49e17 100644
--- a/regress/lib/libc/db/run.test
+++ b/regress/lib/libc/db/run.test
@@ -1,19 +1,27 @@
#!/bin/sh -
-# $NetBSD: run.test,v 1.7 1995/04/20 22:39:27 cgd Exp $
#
-# @(#)run.test 8.8 (Berkeley) 6/16/94
+# $NetBSD: run.test,v 1.8 1996/05/03 21:57:51 cgd Exp $
+# @(#)run.test 8.10 (Berkeley) 7/26/94
#
# db regression tests
main()
{
-DICT=/usr/share/dict/web2
-PROG=./dbtest
-TMP1=t1
-TMP2=t2
-TMP3=t3
+ PROG=./dbtest
+ TMP1=t1
+ TMP2=t2
+ TMP3=t3
+ if [ -f /usr/share/dict/words ]; then
+ DICT=/usr/share/dict/words
+ elif [ -f /usr/dict/words ]; then
+ DICT=/usr/dict/words
+ else
+ echo 'run.test: no dictionary'
+ exit 1
+ fi
+
if [ $# -eq 0 ]; then
for t in 1 2 3 4 5 6 7 8 9 10 11 12 13 20; do
test$t
@@ -345,7 +353,7 @@ test7()
for (i = 1; i <= 120; ++i)
printf("%05d: input key %d: %s\n", i, i, $0);
printf("%05d: input key %d: %s\n", 120, 120, $0);
- printf("get failed, no such key\n");
+ printf("seq failed, no such key\n");
printf("%05d: input key %d: %s\n", 1, 1, $0);
printf("%05d: input key %d: %s\n", 2, 2, $0);
exit;
@@ -364,10 +372,10 @@ test7()
for (i = 1; i <= 120; ++i)
printf("s\n");
printf("fR_CURSOR\ns\nk120\n");
- printf("r\nk120\n");
+ printf("r\n");
printf("fR_NEXT\ns\n");
printf("fR_CURSOR\ns\nk1\n");
- printf("r\nk1\n");
+ printf("r\n");
printf("fR_FIRST\ns\n");
}' > $TMP2
$PROG -o $TMP3 recno $TMP2
@@ -397,8 +405,6 @@ test8()
printf("e\t%d of 10 \n", i);
printf("r\nkkey1\nr\nkkey2\n");
}
- printf("e\n");
- printf("eend of test8 run\n");
}' > $TMP1
$PROG btree $TMP1
# $PROG hash $TMP1
@@ -459,7 +465,7 @@ test10()
printf("p\nk%d\nd%s\n", ++i, $0);
}
END {
- printf("fR_CURSOR\nr\nk1\n");
+ printf("fR_CURSOR\nr\n");
printf("eR_CURSOR SHOULD HAVE FAILED\n");
}' > $TMP2
$PROG -o $TMP3 $type $TMP2 > /dev/null 2>&1
@@ -573,7 +579,8 @@ test13()
echo g
echo k$i
done > $TMP2
- $PROG -ilorder=$order -f byte.file -o $TMP3 $type $TMP2
+ $PROG -s \
+ -ilorder=$order -f byte.file -o $TMP3 $type $TMP2
if (cmp -s $TMP1 $TMP3) ; then :
else
echo "test13: $type/$order get failed"