diff options
Diffstat (limited to 'src/util/db2')
-rw-r--r-- | src/util/db2/ChangeLog | 47 | ||||
-rw-r--r-- | src/util/db2/btree/bt_close.c | 3 | ||||
-rw-r--r-- | src/util/db2/btree/bt_debug.c | 21 | ||||
-rw-r--r-- | src/util/db2/btree/bt_page.c | 2 | ||||
-rw-r--r-- | src/util/db2/btree/bt_seq.c | 410 | ||||
-rw-r--r-- | src/util/db2/btree/bt_split.c | 5 | ||||
-rw-r--r-- | src/util/db2/btree/extern.h | 13 | ||||
-rw-r--r-- | src/util/db2/hash/dbm.c | 5 | ||||
-rw-r--r-- | src/util/db2/hash/hash_debug.c | 1 | ||||
-rw-r--r-- | src/util/db2/include/ChangeLog | 6 | ||||
-rw-r--r-- | src/util/db2/include/db.h | 2 | ||||
-rw-r--r-- | src/util/db2/test/ChangeLog | 14 | ||||
-rw-r--r-- | src/util/db2/test/btree.tests/ChangeLog | 14 | ||||
-rw-r--r-- | src/util/db2/test/btree.tests/main.c | 83 | ||||
-rw-r--r-- | src/util/db2/test/dbtest.c | 14 | ||||
-rw-r--r-- | src/util/db2/test/run.test | 19 |
16 files changed, 625 insertions, 34 deletions
diff --git a/src/util/db2/ChangeLog b/src/util/db2/ChangeLog index 7972728..9c9768c 100644 --- a/src/util/db2/ChangeLog +++ b/src/util/db2/ChangeLog @@ -1,3 +1,50 @@ +2002-08-28 Tom Yu <tlyu@mit.edu> + + * btree/bt_split.c (bt_psplit): Correctly account for + sizeof(indx_t) when computing space used in a page by an item. + [patch from www.sleepycat.com] + [pullup from trunk] + +2002-08-26 Tom Yu <tlyu@mit.edu> + + * Makefile.in (LIBMINOR): Bump due to addition of bt_rseq(). + + * hash/hash_debug.c: Remove inclusion of compat.h, as we don't + have it in our build system. + + * btree/extern.h: Add missing prototypes/renames for + __bt_dmpage(). Add renames for bt_rseq() support functions. + + * btree/bt_seq.c (bt_rseq): New function; like __bt_seq() but does + recursive descent rather than using the prev/next pointers. This + will catch some pages that might be missed if the database is + inconsistent. Added support functions for bt_rseq() as well. + + * btree/bt_page.c (__bt_free): Set B_METADIRTY when updating free + list. + (__bt_new): Set B_METADIRTY when updating free list. + [patch from www.sleepycat.com] + + * btree/bt_debug.c (__bt_dump): Bound loop by number of pages + actually in file to avoid getting a nigh-infinite number of + all-zeroes pages. + (__bt_dmpage): Print a newline after dumping the meta page. + (__bt_dpage): Add DB* parameter; use this to get pagesize in order + to limit dumping of page contents, in case NEXTINDEX(h) happens to + be bogus. + (__bt_stat): Bound loop by number of pages actually in file so as + to stop counting pages after the actual end of file. + + * btree/bt_close.c (__bt_sync): Apply a Kerbnet fix from long ago; + don't return prematurely when B_METADIRTY is set but B_MODIFIED is + clear. + + [pullups from trunk] + +2000-05-01 Nalin Dahyabhai <nalin@redhat.com> + + * hash/dbm.c (kdb2_dbm_open): Don't overflow buffer "path". + 1999-08-15 Tom Yu <tlyu@mit.edu> * README.NOT.SLEEPYCAT.DB: New file; pointer to README to diff --git a/src/util/db2/btree/bt_close.c b/src/util/db2/btree/bt_close.c index b731dcb..11be134 100644 --- a/src/util/db2/btree/bt_close.c +++ b/src/util/db2/btree/bt_close.c @@ -137,7 +137,8 @@ __bt_sync(dbp, flags) return (RET_ERROR); } - if (F_ISSET(t, B_INMEM | B_RDONLY) || !F_ISSET(t, B_MODIFIED)) + if (F_ISSET(t, B_INMEM | B_RDONLY) + || !F_ISSET(t, B_MODIFIED | B_METADIRTY)) return (RET_SUCCESS); if (F_ISSET(t, B_METADIRTY) && bt_meta(t) == RET_ERROR) diff --git a/src/util/db2/btree/bt_debug.c b/src/util/db2/btree/bt_debug.c index 8cf1cda..d36256b 100644 --- a/src/util/db2/btree/bt_debug.c +++ b/src/util/db2/btree/bt_debug.c @@ -114,10 +114,9 @@ __bt_dump(dbp) (void)fprintf(tracefp, ")\n"); } #undef X - - for (i = P_ROOT; + for (i = P_ROOT; i < t->bt_mp->npages && (h = mpool_get(t->bt_mp, i, MPOOL_IGNOREPIN)) != NULL; ++i) - __bt_dpage(h); + __bt_dpage(dbp, h); (void)fflush(tracefp); return (0); } @@ -156,6 +155,7 @@ __bt_dmpage(h) X(R_RECNO, "RECNO"); (void)fprintf(tracefp, ")"); } + (void)fprintf(tracefp, "\n"); (void)fflush(tracefp); return (0); } @@ -178,7 +178,7 @@ __bt_dnpage(dbp, pgno) t = dbp->internal; if ((h = mpool_get(t->bt_mp, pgno, MPOOL_IGNOREPIN)) != NULL) - __bt_dpage(h); + __bt_dpage(dbp, h); (void)fflush(tracefp); return (0); } @@ -190,14 +190,16 @@ __bt_dnpage(dbp, pgno) * h: pointer to the PAGE */ int -__bt_dpage(h) +__bt_dpage(dbp, h) + DB *dbp; PAGE *h; { BINTERNAL *bi; BLEAF *bl; RINTERNAL *ri; RLEAF *rl; - indx_t cur, top; + u_long pgsize; + indx_t cur, top, lim; char *sep; __bt_dinit(); @@ -223,10 +225,13 @@ __bt_dpage(h) if (h->flags & P_OVERFLOW) return; + pgsize = ((BTREE *)dbp->internal)->bt_mp->pagesize; + lim = (pgsize - BTDATAOFF) / sizeof(indx_t); top = NEXTINDEX(h); + lim = top > lim ? lim : top; (void)fprintf(tracefp, " lower %3d upper %3d nextind %d\n", h->lower, h->upper, top); - for (cur = 0; cur < top; cur++) { + for (cur = 0; cur < lim; cur++) { (void)fprintf(tracefp, "\t[%03d] %4d ", cur, h->linp[cur]); switch (h->flags & P_TYPE) { case P_BINTERNAL: @@ -307,7 +312,7 @@ __bt_stat(dbp) t = dbp->internal; pcont = pinternal = pleaf = 0; nkeys = ifree = lfree = 0; - for (i = P_ROOT; + for (i = P_ROOT; i < t->bt_mp->npages && (h = mpool_get(t->bt_mp, i, MPOOL_IGNOREPIN)) != NULL; ++i) switch (h->flags & P_TYPE) { case P_BINTERNAL: diff --git a/src/util/db2/btree/bt_page.c b/src/util/db2/btree/bt_page.c index cb65040..3663cf7 100644 --- a/src/util/db2/btree/bt_page.c +++ b/src/util/db2/btree/bt_page.c @@ -65,6 +65,7 @@ __bt_free(t, h) h->prevpg = P_INVALID; h->nextpg = t->bt_free; t->bt_free = h->pgno; + F_SET(t, B_METADIRTY); /* Make sure the page gets written back. */ return (mpool_put(t->bt_mp, h, MPOOL_DIRTY)); @@ -92,6 +93,7 @@ __bt_new(t, npg) (h = mpool_get(t->bt_mp, t->bt_free, 0)) != NULL) { *npg = t->bt_free; t->bt_free = h->nextpg; + F_SET(t, B_METADIRTY); return (h); } return (mpool_new(t->bt_mp, npg, MPOOL_PAGE_NEXT)); diff --git a/src/util/db2/btree/bt_seq.c b/src/util/db2/btree/bt_seq.c index 3e68c66..c16d4a2 100644 --- a/src/util/db2/btree/bt_seq.c +++ b/src/util/db2/btree/bt_seq.c @@ -1,3 +1,27 @@ +/* + * Copyright (C) 2002 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + /*- * Copyright (c) 1990, 1993, 1994 * The Regents of the University of California. All rights reserved. @@ -488,3 +512,389 @@ __bt_setcur(t, pgno, index) t->bt_cursor.pg.index = index; F_SET(&t->bt_cursor, CURS_INIT); } + +/* Recursive descent cursor. */ +typedef struct rcursor_ { + CURSOR cursor; + size_t ssize; + EPGNO *stack; + EPGNO *sp; +} RCURSOR; +#define RCURSOR_MINSS 64 + +static int bt_rcinit(void **); +static void bt_rcdestroy(void **); +static int bt_rcpush(RCURSOR *, db_pgno_t, u_int); +static EPGNO *bt_rcpop(RCURSOR *); +static void bt_rcclr(RCURSOR *); +static int bt_rcgrowstk(RCURSOR *); +static int bt_rseqset(BTREE *, EPG *, DBT *, RCURSOR *, int); +static int bt_rseqadv(BTREE *, EPG *, RCURSOR *, int); + +static int +bt_rcinit(curs) + void **curs; +{ + RCURSOR *rc; + + rc = *curs = malloc(sizeof(RCURSOR)); + if (rc == NULL) { + errno = ENOMEM; + return RET_ERROR; + } + memset(rc, 0, sizeof(*rc)); + + rc->ssize = RCURSOR_MINSS; + rc->stack = malloc(rc->ssize * sizeof(EPGNO)); + if (rc->stack == NULL) { + free(rc); + errno = ENOMEM; + return RET_ERROR; + } + bt_rcclr(rc); + return RET_SUCCESS; +} + +static void +bt_rcdestroy(curs) + void **curs; +{ + RCURSOR *rc; + + rc = *curs; + free(rc->stack); + free(rc); + *curs = NULL; +} + +static int +bt_rcpush(rc, p, i) + RCURSOR *rc; + db_pgno_t p; + u_int i; +{ + int status; + + rc->sp->pgno = p; + rc->sp->index = i; + if (++rc->sp > rc->stack + rc->ssize) { + status = bt_rcgrowstk(rc); + if (status != RET_SUCCESS) + return status; + } + return RET_SUCCESS; +} + +static EPGNO * +bt_rcpop(rc) + RCURSOR *rc; +{ + return (rc->sp == rc->stack) ? NULL : --rc->sp; +} + +static void +bt_rcclr(rc) + RCURSOR *rc; +{ + rc->sp = rc->stack; +} + +static int +bt_rcgrowstk(rc) + RCURSOR *rc; +{ + size_t osize; + EPGNO *e; + + osize = rc->ssize; + rc->ssize *= 2; + e = realloc(rc->stack, rc->ssize * sizeof(EPGNO)); + if (e == NULL) { + rc->ssize = osize; + errno = ENOMEM; + return RET_ERROR; + } + rc->stack = e; + return RET_SUCCESS; +} + +/* + * bt_rseq -- + * Like __bt_seq but does recursive descent tree traversal + * instead of using the prev/next pointers. + */ +int +bt_rseq(dbp, key, data, curs, flags) + const DB *dbp; + DBT *key, *data; + void **curs; + u_int flags; +{ + RCURSOR *rc; + BTREE *t; + EPG e; + int status; + + t = dbp->internal; + + /* Toss any page pinned across calls. */ + if (t->bt_pinned != NULL) { + mpool_put(t->bt_mp, t->bt_pinned, 0); + t->bt_pinned = NULL; + } + + if (curs == NULL) { + errno = EINVAL; + return RET_ERROR; + } + if (*curs == NULL) { + status = bt_rcinit(curs); + if (status != RET_SUCCESS) + return RET_ERROR; + } + rc = *curs; + + /* + * If scan unitialized as yet, or starting at a specific record, set + * the scan to a specific key. Both bt_rseqset and bt_rseqadv pin + * the page the cursor references if they're successful. + */ + switch (flags) { + case R_NEXT: + case R_PREV: + if (F_ISSET(&rc->cursor, CURS_INIT)) { + status = bt_rseqadv(t, &e, rc, flags); + break; + } + /* FALLTHROUGH */ + case R_FIRST: + case R_LAST: + case R_CURSOR: + status = bt_rseqset(t, &e, key, rc, flags); + break; + default: + errno = EINVAL; + return (RET_ERROR); + } + + if (status == RET_SUCCESS) { + status = + __bt_ret(t, &e, key, &t->bt_rkey, data, &t->bt_rdata, 0); + + /* + * If the user is doing concurrent access, we copied the + * key/data, toss the page. + */ + if (F_ISSET(t, B_DB_LOCK)) + mpool_put(t->bt_mp, e.page, 0); + else + t->bt_pinned = e.page; + } else if (status == RET_SPECIAL) + bt_rcdestroy(curs); + return (status); +} + +/* + * bt_rseqset -- + * Set the sequential scan to a specific key. + * + * Parameters: + * t: tree + * ep: storage for returned key + * key: key for initial scan position + * rc: recursion cursor + * flags: R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV + * + * Side effects: + * Pins the page the cursor references. + * Updates rc's stack and cursor. + * + * Returns: + * RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key. + */ +static int +bt_rseqset(t, ep, key, rc, flags) + BTREE *t; + EPG *ep; + DBT *key; + RCURSOR *rc; + int flags; +{ + PAGE *h; + db_pgno_t pg; + int status; + + /* + * Find the first, last or specific key in the tree and point the + * cursor at it. The cursor may not be moved until a new key has + * been found. + */ + switch (flags) { + case R_CURSOR: /* Not implemented. */ + errno = EINVAL; + return RET_ERROR; + case R_FIRST: /* First record. */ + case R_NEXT: + bt_rcclr(rc); + /* 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; + status = bt_rcpush(rc, h->pgno, 0); + mpool_put(t->bt_mp, h, 0); + if (status != RET_SUCCESS) + return status; + } + ep->page = h; + ep->index = 0; + break; + case R_LAST: /* Last record. */ + case R_PREV: + bt_rcclr(rc); + /* Walk down the right-hand side of the tree. */ + for (pg = P_ROOT;;) { + if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) + return (RET_ERROR); + + /* Check for an empty tree. */ + if (NEXTINDEX(h) == 0) { + mpool_put(t->bt_mp, h, 0); + return (RET_SPECIAL); + } + + if (h->flags & (P_BLEAF | P_RLEAF)) + break; + pg = GETBINTERNAL(h, NEXTINDEX(h) - 1)->pgno; + status = bt_rcpush(rc, h->pgno, NEXTINDEX(h) - 1); + mpool_put(t->bt_mp, h, 0); + if (status != RET_SUCCESS) + return status; + } + ep->page = h; + ep->index = NEXTINDEX(h) - 1; + break; + } + rc->cursor.pg.pgno = ep->page->pgno; + rc->cursor.pg.index = ep->index; + F_CLR(&rc->cursor, CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE); + F_SET(&rc->cursor, CURS_INIT); + return (RET_SUCCESS); +} + +/* + * bt_rseqadvance -- + * Advance the sequential scan. + * + * Parameters: + * t: tree + * ep: return page + * rc: recursion cursor + * flags: R_NEXT, R_PREV + * + * Side effects: + * Pins the page the new key/data record is on. + * Updates rc's stack and cursor. + * + * Returns: + * RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key. + */ +static int +bt_rseqadv(t, ep, rc, flags) + BTREE *t; + EPG *ep; + RCURSOR *rc; + int flags; +{ + CURSOR *c; + PAGE *h; + indx_t idx; + db_pgno_t pg; + int status; + EPGNO *e; + + /* + * 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 = &rc->cursor; + + /* Get the page referenced by the cursor. */ + if ((h = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL) + return (RET_ERROR); + + /* + * Find the next/previous record in the tree and point the cursor at + * it. The cursor may not be moved until a new key has been found. + */ + switch (flags) { + case R_NEXT: /* Next record. */ + idx = c->pg.index; + while (++idx == NEXTINDEX(h)) { + /* Crawl up if we hit the right edge. */ + e = bt_rcpop(rc); + mpool_put(t->bt_mp, h, 0); + if (e == NULL) /* Hit the right edge of root. */ + return RET_SPECIAL; + idx = e->index; + pg = e->pgno; + if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) + return (RET_ERROR); + } + while (!(h->flags & (P_BLEAF | P_RLEAF))) { + /* Crawl down the left until we hit a leaf. */ + status = bt_rcpush(rc, h->pgno, idx); + pg = GETBINTERNAL(h, idx)->pgno; + mpool_put(t->bt_mp, h, 0); + if (status != RET_SUCCESS) + return status; + if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) + return (RET_ERROR); + idx = 0; + } + break; + case R_PREV: /* Previous record. */ + idx = c->pg.index; + while (!idx) { + /* Crawl up if we hit the left edge. */ + e = bt_rcpop(rc); + mpool_put(t->bt_mp, h, 0); + if (e == NULL) /* Hit the left edge of root. */ + return RET_SPECIAL; + idx = e->index; + pg = e->pgno; + if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) + return (RET_ERROR); + } + idx--; + while (!(h->flags & (P_BLEAF | P_RLEAF))) { + /* Crawl down the right until we hit a leaf. */ + status = bt_rcpush(rc, h->pgno, idx); + pg = GETBINTERNAL(h, idx)->pgno; + mpool_put(t->bt_mp, h, 0); + if (status != RET_SUCCESS) + return status; + if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) + return (RET_ERROR); + idx = NEXTINDEX(h) - 1; + } + break; + } + + ep->page = h; + ep->index = idx; + c->pg.pgno = h->pgno; + c->pg.index = idx; + F_CLR(c, CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE); + F_SET(c, CURS_INIT); + return (RET_SUCCESS); +} diff --git a/src/util/db2/btree/bt_split.c b/src/util/db2/btree/bt_split.c index 0fc95ba..0cc6cf0 100644 --- a/src/util/db2/btree/bt_split.c +++ b/src/util/db2/btree/bt_split.c @@ -673,7 +673,8 @@ bt_psplit(t, h, l, r, pskip, ilen) * where we decide to try and copy too much onto the left page. * Make sure that doesn't happen. */ - if (skip <= off && used + nbytes >= full || nxt == top - 1) { + if ((skip <= off && used + nbytes + sizeof(indx_t) >= full) + || nxt == top - 1) { --off; break; } @@ -686,7 +687,7 @@ bt_psplit(t, h, l, r, pskip, ilen) memmove((char *)l + l->upper, src, nbytes); } - used += nbytes; + used += nbytes + sizeof(indx_t); if (used >= half) { if (!isbigkey || bigkeycnt == 3) break; diff --git a/src/util/db2/btree/extern.h b/src/util/db2/btree/extern.h index 70a8807..3aa8841 100644 --- a/src/util/db2/btree/extern.h +++ b/src/util/db2/btree/extern.h @@ -58,10 +58,20 @@ #define __ovfl_get __kdb2_ovfl_get #define __ovfl_put __kdb2_ovfl_put #define __bt_dnpage __kdb2_bt_dnpage +#define __bt_dmpage __kdb2_bt_dmpage #define __bt_dpage __kdb2_bt_dpage #define __bt_dump __kdb2_bt_dump #define __bt_stat __kdb2_bt_stat +#define bt_rcinit kdb2_bt_rcinit +#define bt_rcdestroy kdb2_bt_rcdestroy +#define bt_rcpush kdb2_bt_rcpush +#define bt_rcpop kdb2_bt_rcpop +#define bt_rcclr kdb2_bt_rcclr +#define bt_rcgrowstk kdb2_bt_rcgrowstk +#define bt_rseqset kdb2_bt_rseqset +#define bt_rseqadv kdb2_bt_rseqadv + int __bt_close __P((DB *)); int __bt_cmp __P((BTREE *, const DBT *, EPG *)); int __bt_crsrdel __P((BTREE *, EPGNO *)); @@ -91,7 +101,8 @@ int __ovfl_put __P((BTREE *, const DBT *, db_pgno_t *)); #ifdef DEBUG int __bt_dnpage __P((DB *, db_pgno_t)); -int __bt_dpage __P((PAGE *)); +int __bt_dpage __P((DB *, PAGE *)); +int __bt_dmpage __P((PAGE *)); int __bt_dump __P((DB *)); #endif #ifdef STATISTICS diff --git a/src/util/db2/hash/dbm.c b/src/util/db2/hash/dbm.c index 50921de..aa96766 100644 --- a/src/util/db2/hash/dbm.c +++ b/src/util/db2/hash/dbm.c @@ -168,8 +168,9 @@ kdb2_dbm_open(file, flags, mode) info.cachesize = 0; info.hash = NULL; info.lorder = 0; - (void)strcpy(path, file); - (void)strcat(path, DBM_SUFFIX); + (void)strncpy(path, file, sizeof(path) - 1); + path[sizeof(path) - 1] = '\0'; + (void)strncat(path, DBM_SUFFIX, sizeof(path) - 1 - strlen(path)); return ((DBM *)__hash_open(path, flags, mode, &info, 0)); } diff --git a/src/util/db2/hash/hash_debug.c b/src/util/db2/hash/hash_debug.c index ed99c69..69229fc 100644 --- a/src/util/db2/hash/hash_debug.c +++ b/src/util/db2/hash/hash_debug.c @@ -56,7 +56,6 @@ static char sccsid[] = "@(#)hash_debug.c 8.4 (Berkeley) 11/7/95"; #include "hash.h" #include "page.h" #include "extern.h" -#include "compat.h" void __dump_bucket(hashp, bucket) diff --git a/src/util/db2/include/ChangeLog b/src/util/db2/include/ChangeLog index 4d3d16d..7b25e55 100644 --- a/src/util/db2/include/ChangeLog +++ b/src/util/db2/include/ChangeLog @@ -1,3 +1,9 @@ +2002-08-26 Tom Yu <tlyu@mit.edu> + + * db.h: Add rename and prototype for bt_rseq(); this is a kludge + to avoid stuffing more things into the DB handle. + [pullup from trunk] + Fri Feb 13 14:39:25 1998 Tom Yu <tlyu@mit.edu> * db-int.h: Additional renaming. diff --git a/src/util/db2/include/db.h b/src/util/db2/include/db.h index 2eaf0bc..980145a 100644 --- a/src/util/db2/include/db.h +++ b/src/util/db2/include/db.h @@ -166,8 +166,10 @@ typedef struct { #endif #define dbopen kdb2_dbopen +#define bt_rseq kdb2_bt_rseq /* XXX kludge */ __BEGIN_DECLS DB *dbopen __P((const char *, int, int, DBTYPE, const void *)); +int bt_rseq(const DB*, DBT *, DBT *, void **, u_int); /* XXX kludge */ __END_DECLS #endif /* !_DB_H_ */ diff --git a/src/util/db2/test/ChangeLog b/src/util/db2/test/ChangeLog index 4e147d7..fc2f691 100644 --- a/src/util/db2/test/ChangeLog +++ b/src/util/db2/test/ChangeLog @@ -1,3 +1,17 @@ +2002-08-26 Tom Yu <tlyu@mit.edu> + + * dbtest.c: Include btree.h if we're compiled with -DSTATISTICS. + [pullup from trunk] + +2001-12-21 Ken Raeburn <raeburn@mit.edu> + + * dbtest.c (compare): Make comparison failures fatal. + (get): Make no-such-key errors fatal. + + * run.test (main, test3, test8): Use "/bin/." instead of "/bin" in + find commands, in case /bin itself is a symlink. + (test8): Do check exit status of program. + 1998-05-06 Theodore Ts'o <tytso@rsts-11.mit.edu> * dbtest.c (main): POSIX states that getopt returns -1 diff --git a/src/util/db2/test/btree.tests/ChangeLog b/src/util/db2/test/btree.tests/ChangeLog index cfd0b18..b70f64e 100644 --- a/src/util/db2/test/btree.tests/ChangeLog +++ b/src/util/db2/test/btree.tests/ChangeLog @@ -1,3 +1,17 @@ +2002-08-26 Tom Yu <tlyu@mit.edu> + + * main.c: Disable append(); we don't have R_APPEND in this release + of DB for some reason. Disable load() due to lack of fgetline(). + Conditionalize lots of things on -DSTATISTICS or -DDEBUG as + appropriate. + (rlist): New function; does recursive listing of principals. + (main): Fix up naming of *_ENDIAN macros. Default to read-only + open, with new "-w" option for opening read/write. Actually call + db->sync with the correct number of arguments. + (show): Update call to __bt_dpage(). + (usage): Update. + [pullup from trunk] + 1998-05-06 Theodore Ts'o <tytso@rsts-11.mit.edu> * main.c (main): POSIX states that getopt returns -1 diff --git a/src/util/db2/test/btree.tests/main.c b/src/util/db2/test/btree.tests/main.c index bbf1fcf..06f02b3 100644 --- a/src/util/db2/test/btree.tests/main.c +++ b/src/util/db2/test/btree.tests/main.c @@ -59,12 +59,18 @@ typedef struct cmd_table { int stopstop; DB *globaldb; +#if 0 void append __P((DB *, char **)); +#endif +#ifdef STATISTICS void bstat __P((DB *, char **)); +#endif void cursor __P((DB *, char **)); void delcur __P((DB *, char **)); void delete __P((DB *, char **)); +#ifdef DEBUG void dump __P((DB *, char **)); +#endif void first __P((DB *, char **)); void get __P((DB *, char **)); void help __P((DB *, char **)); @@ -75,23 +81,36 @@ void insert __P((DB *, char **)); void keydata __P((DBT *, DBT *)); void last __P((DB *, char **)); void list __P((DB *, char **)); +#if 0 void load __P((DB *, char **)); +#endif +#ifdef STATISTICS void mstat __P((DB *, char **)); +#endif void next __P((DB *, char **)); int parse __P((char *, char **, int)); void previous __P((DB *, char **)); +#ifdef DEBUG void show __P((DB *, char **)); +#endif +void rlist __P((DB *, char **)); void usage __P((void)); void user __P((DB *)); cmd_table commands[] = { "?", 0, 0, help, "help", NULL, +#if 0 "a", 2, 1, append, "append key def", "append key with data def", +#endif +#ifdef STATISTICS "b", 0, 0, bstat, "bstat", "stat btree", +#endif "c", 1, 1, cursor, "cursor word", "move cursor to word", "delc", 0, 0, delcur, "delcur", "delete key the cursor references", "dele", 1, 1, delete, "delete word", "delete word", +#ifdef DEBUG "d", 0, 0, dump, "dump", "dump database", +#endif "f", 0, 0, first, "first", "move cursor to first record", "g", 1, 1, get, "get key", "locate key", "h", 0, 0, help, "help", "print command summary", @@ -101,13 +120,20 @@ cmd_table commands[] = { "in", 2, 1, insert, "insert key def", "insert key with data def", "la", 0, 0, last, "last", "move cursor to last record", "li", 1, 1, list, "list file", "list to a file", +#if 0 "loa", 1, 0, load, "load file", NULL, +#endif "loc", 1, 1, get, "get key", NULL, +#ifdef STATISTICS "m", 0, 0, mstat, "mstat", "stat memory pool", +#endif "n", 0, 0, next, "next", "move cursor forward one record", "p", 0, 0, previous, "previous", "move cursor back one record", "q", 0, 0, NULL, "quit", "quit", + "rli", 1, 1, rlist, "rlist file", "list to a file (recursive)", +#ifdef DEBUG "sh", 1, 0, show, "show page", "dump a page", +#endif { NULL }, }; @@ -121,11 +147,13 @@ main(argc, argv) char **argv; { int c; + int omode; DB *db; BTREEINFO b; progname = *argv; + omode = O_RDONLY; b.flags = 0; b.cachesize = 0; b.maxkeypage = 0; @@ -135,10 +163,10 @@ main(argc, argv) b.prefix = NULL; b.lorder = 0; - while ((c = getopt(argc, argv, "bc:di:lp:ru")) != -1) { + while ((c = getopt(argc, argv, "bc:di:lp:ruw")) != -1) { switch (c) { case 'b': - b.lorder = BIG_ENDIAN; + b.lorder = DB_BIG_ENDIAN; break; case 'c': b.cachesize = atoi(optarg); @@ -150,7 +178,7 @@ main(argc, argv) dict = optarg; break; case 'l': - b.lorder = LITTLE_ENDIAN; + b.lorder = DB_LITTLE_ENDIAN; break; case 'p': b.psize = atoi(optarg); @@ -161,6 +189,9 @@ main(argc, argv) case 'u': b.flags = 0; break; + case 'w': + omode = O_RDWR; + break; default: usage(); } @@ -169,10 +200,10 @@ main(argc, argv) argv += optind; if (recno) - db = dbopen(*argv == NULL ? NULL : *argv, O_RDWR|O_BINARY, + db = dbopen(*argv == NULL ? NULL : *argv, omode|O_BINARY, 0, DB_RECNO, NULL); else - db = dbopen(*argv == NULL ? NULL : *argv, O_CREAT|O_RDWR|O_BINARY, + db = dbopen(*argv == NULL ? NULL : *argv, O_CREAT|omode|O_BINARY, 0600, DB_BTREE, &b); if (db == NULL) { @@ -240,7 +271,7 @@ user(db) uselast: last = i; (*commands[i].func)(db, argv); } - if ((db->sync)(db) == RET_ERROR) + if ((db->sync)(db, 0) == RET_ERROR) perror("dbsync"); else if ((db->close)(db) == RET_ERROR) perror("dbclose"); @@ -269,6 +300,7 @@ parse(lbuf, argv, maxargc) return (argc); } +#if 0 void append(db, argv) DB *db; @@ -298,6 +330,7 @@ append(db, argv) break; } } +#endif void cursor(db, argv) @@ -366,6 +399,7 @@ delete(db, argv) } } +#ifdef DEBUG void dump(db, argv) DB *db; @@ -373,6 +407,7 @@ dump(db, argv) { __bt_dump(db); } +#endif void first(db, argv) @@ -598,10 +633,37 @@ list(db, argv) (void)fprintf(fp, "%s\n", key.data); status = (*db->seq)(db, &key, &data, R_NEXT); } + (void)fclose(fp); + if (status == RET_ERROR) + perror("list/seq"); +} + +void +rlist(db, argv) + DB *db; + char **argv; +{ + DBT data, key; + FILE *fp; + int status; + void *cookie; + + cookie = NULL; + if ((fp = fopen(argv[1], "w")) == NULL) { + (void)fprintf(stderr, "%s: %s\n", argv[1], strerror(errno)); + return; + } + status = bt_rseq(db, &key, &data, &cookie, R_FIRST); + while (status == RET_SUCCESS) { + (void)fprintf(fp, "%s\n", key.data); + status = bt_rseq(db, &key, &data, &cookie, R_NEXT); + } + (void)fclose(fp); if (status == RET_ERROR) perror("list/seq"); } +#if 0 DB *BUGdb; void load(db, argv) @@ -657,6 +719,7 @@ load(db, argv) } (void)fclose(fp); } +#endif void next(db, argv) @@ -704,6 +767,7 @@ previous(db, argv) } } +#ifdef DEBUG void show(db, argv) DB *db; @@ -722,10 +786,12 @@ show(db, argv) if (pg == 0) __bt_dmpage(h); else - __bt_dpage(h); + __bt_dpage(db, h); mpool_put(t->bt_mp, h, 0); } +#endif +#ifdef STATISTICS void bstat(db, argv) DB *db; @@ -743,6 +809,7 @@ mstat(db, argv) (void)printf("MPOOL\n"); mpool_stat(((BTREE *)db->internal)->bt_mp); } +#endif void keydata(key, data) @@ -759,7 +826,7 @@ void usage() { (void)fprintf(stderr, - "usage: %s [-bdlu] [-c cache] [-i file] [-p page] [file]\n", + "usage: %s [-bdluw] [-c cache] [-i file] [-p page] [file]\n", progname); exit (1); } diff --git a/src/util/db2/test/dbtest.c b/src/util/db2/test/dbtest.c index f499047..315b13c 100644 --- a/src/util/db2/test/dbtest.c +++ b/src/util/db2/test/dbtest.c @@ -54,6 +54,9 @@ static char sccsid[] = "@(#)dbtest.c 8.17 (Berkeley) 9/1/94"; #include <unistd.h> #include "db-int.h" +#ifdef STATISTICS +#include "btree.h" +#endif enum S { COMMAND, COMPARE, GET, PUT, REMOVE, SEQ, SEQFLAG, KEY, DATA }; @@ -344,13 +347,13 @@ compare(db1, db2) register u_char *p1, *p2; if (db1->size != db2->size) - printf("compare failed: key->data len %lu != data len %lu\n", + err("compare failed: key->data len %lu != data len %lu\n", db1->size, db2->size); len = MIN(db1->size, db2->size); for (p1 = db1->data, p2 = db2->data; len--;) if (*p1++ != *p2++) { - printf("compare failed at offset %d\n", + err("compare failed at offset %d\n", p1 - (u_char *)db1->data); break; } @@ -374,10 +377,11 @@ get(dbp, kp) /* NOTREACHED */ case 1: #define NOSUCHKEY "get failed, no such key\n" - if (ofd != STDOUT_FILENO) + if (ofd != STDOUT_FILENO) { (void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1); - else - (void)fprintf(stderr, "%d: %.*s: %s", + exit (1); + } else + err(stderr, "%d: %.*s: %s", lineno, MIN(kp->size, 20), kp->data, NOSUCHKEY); #undef NOSUCHKEY break; diff --git a/src/util/db2/test/run.test b/src/util/db2/test/run.test index 462a9c2..c3922c8 100644 --- a/src/util/db2/test/run.test +++ b/src/util/db2/test/run.test @@ -31,6 +31,8 @@ main() dictsize=`wc -l < $DICT` + bindir=/bin/. + if [ $# -eq 0 ]; then for t in 1 2 3 4 5 6 7 8 9 10 11 12 13 20; do test$t @@ -141,15 +143,15 @@ test2() fi } -# Insert the programs in /bin with their paths as their keys. +# Insert the programs in $bindir with their paths as their keys. test3() { echo "Test 3: hash: small key, big data pairs" rm -f $TMP1 - (find /bin -type f -exec test -r {} \; -print | xargs cat) > $TMP1 + (find $bindir -type f -exec test -r {} \; -print | xargs cat) > $TMP1 for type in hash; do rm -f $TMP2 $TMP3 - for i in `find /bin -type f -exec test -r {} \; -print`; do + for i in `find $bindir -type f -exec test -r {} \; -print`; do echo p echo k$i echo D$i @@ -168,7 +170,7 @@ test3() echo " page size $psize" for type in btree; do rm -f $TMP2 $TMP3 - for i in `find /bin -type f -exec test -r {} \; -print`; do + for i in `find $bindir -type f -exec test -r {} \; -print`; do echo p echo k$i echo D$i @@ -185,7 +187,7 @@ test3() done echo "Test 3: recno: big data pairs" rm -f $TMP2 $TMP3 - find /bin -type f -exec test -r {} \; -print | + find $bindir -type f -exec test -r {} \; -print | awk '{ ++i; printf("p\nk%d\nD%s\ng\nk%d\n", i, $0, i); @@ -415,7 +417,12 @@ test8() printf("r\nkkey1\nr\nkkey2\n"); } }' > $TMP1 - $PROG btree $TMP1 + if $PROG btree $TMP1 ; then + true + else + echo "test8: btree tests failed" + exit 1 + fi # $PROG hash $TMP1 # No explicit test for success. } |