diff --git a/lib/libc/db/btree/bt_close.c b/lib/libc/db/btree/bt_close.c index ae2fb91bb799..085fa7c0ef5f 100644 --- a/lib/libc/db/btree/bt_close.c +++ b/lib/libc/db/btree/bt_close.c @@ -1,4 +1,4 @@ -/* $NetBSD: bt_close.c,v 1.15 2016/08/31 06:23:51 christos Exp $ */ +/* $NetBSD: bt_close.c,v 1.16 2016/09/24 20:11:12 christos Exp $ */ /*- * Copyright (c) 1990, 1993, 1994 @@ -37,7 +37,7 @@ #endif #include -__RCSID("$NetBSD: bt_close.c,v 1.15 2016/08/31 06:23:51 christos Exp $"); +__RCSID("$NetBSD: bt_close.c,v 1.16 2016/09/24 20:11:12 christos Exp $"); #include "namespace.h" @@ -164,7 +164,7 @@ bt_meta(BTREE *t) BTMETA m; void *p; - if ((p = mpool_get(t->bt_mp, P_META, 0)) == NULL) + if ((p = mpool_getf(t->bt_mp, P_META, 0)) == NULL) return (RET_ERROR); /* Fill in metadata. */ diff --git a/lib/libc/db/btree/bt_conv.c b/lib/libc/db/btree/bt_conv.c index 2c5217a39102..fe658aac39de 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.14 2008/09/10 17:52:35 joerg Exp $ */ +/* $NetBSD: bt_conv.c,v 1.15 2016/09/24 20:11:12 christos Exp $ */ /*- * Copyright (c) 1990, 1993, 1994 @@ -37,10 +37,11 @@ #endif #include -__RCSID("$NetBSD: bt_conv.c,v 1.14 2008/09/10 17:52:35 joerg Exp $"); +__RCSID("$NetBSD: bt_conv.c,v 1.15 2016/09/24 20:11:12 christos Exp $"); #include #include +#include #include #include "btree.h" @@ -64,6 +65,7 @@ __bt_pgin(void *t, pgno_t pg, void *pp) indx_t i, top; uint8_t flags; char *p; + uint32_t ksize; if (!F_ISSET(((BTREE *)t), B_NEEDSWAP)) return; @@ -101,6 +103,7 @@ __bt_pgin(void *t, pgno_t pg, void *pp) M_16_SWAP(h->linp[i]); p = (char *)(void *)GETBLEAF(h, i); P_32_SWAP(p); + memcpy(&ksize, p, sizeof(ksize)); p += sizeof(uint32_t); P_32_SWAP(p); p += sizeof(uint32_t); @@ -113,7 +116,7 @@ __bt_pgin(void *t, pgno_t pg, void *pp) P_32_SWAP(p); } if (flags & P_BIGDATA) { - p += sizeof(uint32_t); + p += ksize; P_32_SWAP(p); p += sizeof(pgno_t); P_32_SWAP(p); @@ -129,6 +132,7 @@ __bt_pgout(void *t, pgno_t pg, void *pp) indx_t i, top; uint8_t flags; char *p; + uint32_t ksize; if (!F_ISSET(((BTREE *)t), B_NEEDSWAP)) return; @@ -157,6 +161,7 @@ __bt_pgout(void *t, pgno_t pg, void *pp) else if ((h->flags & P_TYPE) == P_BLEAF) for (i = 0; i < top; i++) { p = (char *)(void *)GETBLEAF(h, i); + ksize = GETBLEAF(h, i)->ksize; P_32_SWAP(p); p += sizeof(uint32_t); P_32_SWAP(p); @@ -170,7 +175,7 @@ __bt_pgout(void *t, pgno_t pg, void *pp) P_32_SWAP(p); } if (flags & P_BIGDATA) { - p += sizeof(uint32_t); + p += ksize; P_32_SWAP(p); p += sizeof(pgno_t); P_32_SWAP(p); diff --git a/lib/libc/db/btree/bt_debug.c b/lib/libc/db/btree/bt_debug.c index 5b5f2cd814fa..69dad4a61dc2 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.16 2011/07/17 20:47:39 christos Exp $ */ +/* $NetBSD: bt_debug.c,v 1.17 2016/09/24 20:11:12 christos Exp $ */ /*- * Copyright (c) 1990, 1993, 1994 @@ -37,7 +37,7 @@ #endif #include -__RCSID("$NetBSD: bt_debug.c,v 1.16 2011/07/17 20:47:39 christos Exp $"); +__RCSID("$NetBSD: bt_debug.c,v 1.17 2016/09/24 20:11:12 christos Exp $"); #include #include @@ -47,6 +47,29 @@ __RCSID("$NetBSD: bt_debug.c,v 1.16 2011/07/17 20:47:39 christos Exp $"); #include #include "btree.h" +#if defined(DEBUG) || defined(STATISTICS) + +static FILE *tracefp; + +/* + * __bt_dinit -- + * initialize debugging. + */ +static void +__bt_dinit(void) +{ + if (tracefp != NULL) + return; + +#ifndef TRACE_TO_STDERR + if ((tracefp = fopen("/tmp/__bt_debug", "w")) != NULL) + return; +#endif + tracefp = stderr; +} +#endif + + #ifdef DEBUG /* * BT_DUMP -- Dump the tree @@ -62,15 +85,17 @@ __bt_dump(DB *dbp) pgno_t i; const char *sep; + __bt_dinit(); + t = dbp->internal; - (void)fprintf(stderr, "%s: pgsz %d", + (void)fprintf(tracefp, "%s: pgsz %d", F_ISSET(t, B_INMEM) ? "memory" : "disk", t->bt_psize); if (F_ISSET(t, R_RECNO)) - (void)fprintf(stderr, " keys %lu", (unsigned long) t->bt_nrecs); + (void)fprintf(tracefp, " keys %lu", (unsigned long) t->bt_nrecs); #undef X #define X(flag, name) \ if (F_ISSET(t, flag)) { \ - (void)fprintf(stderr, "%s%s", sep, name); \ + (void)fprintf(tracefp, "%s%s", sep, name); \ sep = ", "; \ } if (t->flags != 0) { @@ -81,14 +106,15 @@ __bt_dump(DB *dbp) X(B_RDONLY, "RDONLY"); X(R_RECNO, "RECNO"); X(B_METADIRTY,"METADIRTY"); - (void)fprintf(stderr, ")\n"); + (void)fprintf(tracefp, ")\n"); } #undef X - for (i = P_ROOT; (h = mpool_get(t->bt_mp, i, 0)) != NULL; ++i) { + for (i = P_ROOT; i < t->bt_mp->npages && + (h = mpool_getf(t->bt_mp, i, MPOOL_IGNOREPIN)) != NULL; ++i) __bt_dpage(h); - (void)mpool_put(t->bt_mp, h, 0); - } + + (void)fflush(tracefp); } /* @@ -104,24 +130,26 @@ __bt_dmpage(PAGE *h) const char *sep; m = (BTMETA *)(void *)h; - (void)fprintf(stderr, "magic %lx\n", (unsigned long) m->magic); - (void)fprintf(stderr, "version %lu\n", (unsigned long) m->version); - (void)fprintf(stderr, "psize %lu\n", (unsigned long) m->psize); - (void)fprintf(stderr, "free %lu\n", (unsigned long) m->free); - (void)fprintf(stderr, "nrecs %lu\n", (unsigned long) m->nrecs); - (void)fprintf(stderr, "flags %lu", (unsigned long) m->flags); + (void)fprintf(tracefp, "magic %lx\n", (unsigned long) m->magic); + (void)fprintf(tracefp, "version %lu\n", (unsigned long) m->version); + (void)fprintf(tracefp, "psize %lu\n", (unsigned long) m->psize); + (void)fprintf(tracefp, "free %lu\n", (unsigned long) m->free); + (void)fprintf(tracefp, "nrecs %lu\n", (unsigned long) m->nrecs); + (void)fprintf(tracefp, "flags %lu", (unsigned long) m->flags); #undef X #define X(flag, name) \ if (m->flags & flag) { \ - (void)fprintf(stderr, "%s%s", sep, name); \ + (void)fprintf(tracefp, "%s%s", sep, name); \ sep = ", "; \ } if (m->flags) { sep = " ("; X(B_NODUPS, "NODUPS"); X(R_RECNO, "RECNO"); - (void)fprintf(stderr, ")"); + (void)fprintf(tracefp, ")"); } + (void)fprintf(tracefp, "\n"); + (void)fflush(tracefp); } static pgno_t @@ -152,11 +180,14 @@ __bt_dnpage(DB *dbp, pgno_t pgno) BTREE *t; PAGE *h; + __bt_dinit(); + t = dbp->internal; - if ((h = mpool_get(t->bt_mp, pgno, 0)) != NULL) { + if ((h = mpool_getf(t->bt_mp, pgno, MPOOL_IGNOREPIN)) != NULL) { __bt_dpage(h); (void)mpool_put(t->bt_mp, h, 0); } + (void)fflush(tracefp); } /* @@ -175,11 +206,13 @@ __bt_dpage(PAGE *h) indx_t cur, top; const char *sep; - (void)fprintf(stderr, " page %d: (", h->pgno); + __bt_dinit(); + + (void)fprintf(tracefp, " page %d: (", h->pgno); #undef X #define X(flag, name) \ if (h->flags & flag) { \ - (void)fprintf(stderr, "%s%s", sep, name); \ + (void)fprintf(tracefp, "%s%s", sep, name); \ sep = ", "; \ } sep = ""; @@ -189,68 +222,69 @@ __bt_dpage(PAGE *h) X(P_RLEAF, "RLEAF") X(P_OVERFLOW, "OVERFLOW") X(P_PRESERVE, "PRESERVE"); - (void)fprintf(stderr, ")\n"); + (void)fprintf(tracefp, ")\n"); #undef X - (void)fprintf(stderr, "\tprev %2d next %2d", h->prevpg, h->nextpg); + (void)fprintf(tracefp, "\tprev %2d next %2d", h->prevpg, h->nextpg); if (h->flags & P_OVERFLOW) return; top = NEXTINDEX(h); - (void)fprintf(stderr, " lower %3d upper %3d nextind %d\n", + (void)fprintf(tracefp, " lower %3d upper %3d nextind %d\n", h->lower, h->upper, top); for (cur = 0; cur < top; cur++) { - (void)fprintf(stderr, "\t[%03d] %4d ", cur, h->linp[cur]); + (void)fprintf(tracefp, "\t[%03d] %4d ", cur, h->linp[cur]); switch (h->flags & P_TYPE) { case P_BINTERNAL: bi = GETBINTERNAL(h, cur); - (void)fprintf(stderr, + (void)fprintf(tracefp, "size %03d pgno %03d", bi->ksize, bi->pgno); if (bi->flags & P_BIGKEY) - (void)fprintf(stderr, " (indirect)"); + (void)fprintf(tracefp, " (indirect)"); else if (bi->ksize) - (void)fprintf(stderr, + (void)fprintf(tracefp, " {%.*s}", (int)bi->ksize, bi->bytes); break; case P_RINTERNAL: ri = GETRINTERNAL(h, cur); - (void)fprintf(stderr, "entries %03d pgno %03d", + (void)fprintf(tracefp, "entries %03d pgno %03d", ri->nrecs, ri->pgno); break; case P_BLEAF: bl = GETBLEAF(h, cur); if (bl->flags & P_BIGKEY) - (void)fprintf(stderr, + (void)fprintf(tracefp, "big key page %lu size %u/", (unsigned long) __bt_pgno_t(bl->bytes), __bt_uint32_t(bl->bytes + sizeof(pgno_t))); else if (bl->ksize) - (void)fprintf(stderr, "%s/", bl->bytes); + (void)fprintf(tracefp, "%s/", bl->bytes); if (bl->flags & P_BIGDATA) - (void)fprintf(stderr, + (void)fprintf(tracefp, "big data page %lu size %u", (unsigned long) __bt_pgno_t(bl->bytes + bl->ksize), __bt_uint32_t(bl->bytes + bl->ksize + sizeof(pgno_t))); else if (bl->dsize) - (void)fprintf(stderr, "%.*s", + (void)fprintf(tracefp, "%.*s", (int)bl->dsize, bl->bytes + bl->ksize); break; case P_RLEAF: rl = GETRLEAF(h, cur); if (rl->flags & P_BIGDATA) - (void)fprintf(stderr, + (void)fprintf(tracefp, "big data page %lu size %u", (unsigned long) __bt_pgno_t(rl->bytes), __bt_uint32_t(rl->bytes + sizeof(pgno_t))); else if (rl->dsize) - (void)fprintf(stderr, + (void)fprintf(tracefp, "%.*s", (int)rl->dsize, rl->bytes); break; } - (void)fprintf(stderr, "\n"); + (void)fprintf(tracefp, "\n"); } + (void)fflush(tracefp); } #endif @@ -272,10 +306,13 @@ __bt_stat(DB *dbp) unsigned long ifree, lfree, nkeys; int levels; + __bt_dinit(); + t = dbp->internal; pcont = pinternal = pleaf = 0; nkeys = ifree = lfree = 0; - for (i = P_ROOT; (h = mpool_get(t->bt_mp, i, 0)) != NULL; ++i) { + for (i = P_ROOT; i < t->bt_mp->npages && + (h = mpool_getf(t->bt_mp, i, MPOOL_IGNOREPIN)) != NULL; ++i) switch (h->flags & P_TYPE) { case P_BINTERNAL: case P_RINTERNAL: @@ -297,7 +334,7 @@ __bt_stat(DB *dbp) /* Count the levels of the tree. */ for (i = P_ROOT, levels = 0 ;; ++levels) { - h = mpool_get(t->bt_mp, i, 0); + h = mpool_getf(t->bt_mp, i, MPOOL_IGNOREPIN); if (h->flags & (P_BLEAF|P_RLEAF)) { if (levels == 0) levels = 1; @@ -310,32 +347,33 @@ __bt_stat(DB *dbp) (void)mpool_put(t->bt_mp, h, 0); } - (void)fprintf(stderr, "%d level%s with %ld keys", + (void)fprintf(tracefp, "%d level%s with %ld keys", levels, levels == 1 ? "" : "s", nkeys); if (F_ISSET(t, R_RECNO)) - (void)fprintf(stderr, " (%ld header count)", (long)t->bt_nrecs); - (void)fprintf(stderr, + (void)fprintf(tracefp, " (%ld header count)", (long)t->bt_nrecs); + (void)fprintf(tracefp, "\n%lu pages (leaf %ld, internal %ld, overflow %ld)\n", (long)pinternal + pleaf + pcont, (long)pleaf, (long)pinternal, (long)pcont); - (void)fprintf(stderr, "%ld cache hits, %ld cache misses\n", + (void)fprintf(tracefp, "%ld cache hits, %ld cache misses\n", bt_cache_hit, bt_cache_miss); - (void)fprintf(stderr, "%ld splits (%ld root splits, %ld sort splits)\n", + (void)fprintf(tracefp, "%ld splits (%ld root splits, %ld sort splits)\n", bt_split, bt_rootsplit, bt_sortsplit); pleaf *= t->bt_psize - BTDATAOFF; if (pleaf) - (void)fprintf(stderr, + (void)fprintf(tracefp, "%.0f%% leaf fill (%ld bytes used, %ld bytes free)\n", ((double)(pleaf - lfree) / pleaf) * 100, pleaf - lfree, lfree); pinternal *= t->bt_psize - BTDATAOFF; if (pinternal) - (void)fprintf(stderr, + (void)fprintf(tracefp, "%.0f%% internal fill (%ld bytes used, %ld bytes free\n", ((double)(pinternal - ifree) / pinternal) * 100, pinternal - ifree, ifree); if (bt_pfxsaved) - (void)fprintf(stderr, "prefix checking removed %lu bytes.\n", + (void)fprintf(tracefp, "prefix checking removed %lu bytes.\n", bt_pfxsaved); + (void)fflush(tracefp); } #endif diff --git a/lib/libc/db/btree/bt_delete.c b/lib/libc/db/btree/bt_delete.c index 701c8b2016bd..db20b98e7ba5 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.17 2009/01/29 02:02:36 lukem Exp $ */ +/* $NetBSD: bt_delete.c,v 1.18 2016/09/24 20:11:12 christos Exp $ */ /*- * Copyright (c) 1990, 1993, 1994 @@ -37,7 +37,7 @@ #endif #include -__RCSID("$NetBSD: bt_delete.c,v 1.17 2009/01/29 02:02:36 lukem Exp $"); +__RCSID("$NetBSD: bt_delete.c,v 1.18 2016/09/24 20:11:12 christos Exp $"); #include "namespace.h" #include @@ -53,7 +53,6 @@ __RCSID("$NetBSD: bt_delete.c,v 1.17 2009/01/29 02:02:36 lukem Exp $"); static int __bt_bdelete(BTREE *, const DBT *); static int __bt_curdel(BTREE *, const DBT *, PAGE *, u_int); static int __bt_pdelete(BTREE *, PAGE *); -static int __bt_relink(BTREE *, PAGE *); static int __bt_stkacq(BTREE *, PAGE **, CURSOR *); /* @@ -97,7 +96,7 @@ __bt_delete(const DB *dbp, const DBT *key, u_int flags) 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) + if ((h = mpool_getf(t->bt_mp, c->pg.pgno, 0)) == NULL) return (RET_ERROR); /* @@ -181,7 +180,7 @@ __bt_stkacq(BTREE *t, PAGE **hp, CURSOR *c) /* 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) + if ((h = mpool_getf(t->bt_mp, parent->pgno, 0)) == NULL) return (1); /* Move to the next index. */ @@ -204,12 +203,12 @@ __bt_stkacq(BTREE *t, PAGE **hp, CURSOR *c) mpool_put(t->bt_mp, h, 0); /* Get the next level down. */ - if ((h = mpool_get(t->bt_mp, pgno, 0)) == NULL) + if ((h = mpool_getf(t->bt_mp, pgno, 0)) == NULL) return (1); idx = 0; } mpool_put(t->bt_mp, h, 0); - if ((h = mpool_get(t->bt_mp, nextpg, 0)) == NULL) + if ((h = mpool_getf(t->bt_mp, nextpg, 0)) == NULL) return (1); } @@ -236,7 +235,7 @@ __bt_stkacq(BTREE *t, PAGE **hp, CURSOR *c) /* 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) + if ((h = mpool_getf(t->bt_mp, parent->pgno, 0)) == NULL) return (1); /* Move to the next index. */ @@ -258,20 +257,20 @@ __bt_stkacq(BTREE *t, PAGE **hp, CURSOR *c) mpool_put(t->bt_mp, h, 0); /* Get the next level down. */ - if ((h = mpool_get(t->bt_mp, pgno, 0)) == NULL) + if ((h = mpool_getf(t->bt_mp, pgno, 0)) == NULL) return (1); idx = NEXTINDEX(h) - 1; BT_PUSH(t, pgno, idx); } mpool_put(t->bt_mp, h, 0); - if ((h = mpool_get(t->bt_mp, prevpg, 0)) == NULL) + if ((h = mpool_getf(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); + return ((*hp = mpool_getf(t->bt_mp, c->pg.pgno, 0)) == NULL); } /* @@ -394,7 +393,7 @@ __bt_pdelete(BTREE *t, PAGE *h) */ while ((parent = BT_POP(t)) != NULL) { /* Get the parent page. */ - if ((pg = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL) + if ((pg = mpool_getf(t->bt_mp, parent->pgno, 0)) == NULL) return (RET_ERROR); idx = parent->index; @@ -577,7 +576,7 @@ __bt_curdel(BTREE *t, const DBT *key, PAGE *h, u_int idx) } /* Check previous key if at the beginning of the page. */ if (idx == 0 && h->prevpg != P_INVALID) { - if ((pg = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL) + if ((pg = mpool_getf(t->bt_mp, h->prevpg, 0)) == NULL) return (RET_ERROR); e.page = pg; e.index = NEXTINDEX(pg) - 1; @@ -589,7 +588,7 @@ __bt_curdel(BTREE *t, const DBT *key, PAGE *h, u_int idx) } /* Check next key if at the end of the page. */ if (idx == (unsigned)(NEXTINDEX(h) - 1) && h->nextpg != P_INVALID) { - if ((pg = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL) + if ((pg = mpool_getf(t->bt_mp, h->nextpg, 0)) == NULL) return (RET_ERROR); e.page = pg; e.index = 0; @@ -621,19 +620,19 @@ dup2: c->pg.pgno = e.page->pgno; * t: tree * h: page to be deleted */ -static int +int __bt_relink(BTREE *t, PAGE *h) { PAGE *pg; if (h->nextpg != P_INVALID) { - if ((pg = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL) + if ((pg = mpool_getf(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) + if ((pg = mpool_getf(t->bt_mp, h->prevpg, 0)) == NULL) return (RET_ERROR); pg->nextpg = h->nextpg; mpool_put(t->bt_mp, pg, MPOOL_DIRTY); diff --git a/lib/libc/db/btree/bt_open.c b/lib/libc/db/btree/bt_open.c index 53717afc24c1..23ec2bf1322a 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.27 2013/12/01 00:22:48 christos Exp $ */ +/* $NetBSD: bt_open.c,v 1.28 2016/09/24 20:11:12 christos Exp $ */ /*- * Copyright (c) 1990, 1993, 1994 @@ -37,7 +37,7 @@ #endif #include -__RCSID("$NetBSD: bt_open.c,v 1.27 2013/12/01 00:22:48 christos Exp $"); +__RCSID("$NetBSD: bt_open.c,v 1.28 2016/09/24 20:11:12 christos Exp $"); /* * Implementation of btree access method for 4.4BSD. @@ -354,18 +354,25 @@ nroot(BTREE *t) PAGE *meta, *root; pgno_t npg; - if ((meta = mpool_get(t->bt_mp, 0, 0)) != NULL) { - mpool_put(t->bt_mp, meta, 0); - return (RET_SUCCESS); + if ((root = mpool_getf(t->bt_mp, 1, 0)) != NULL) { + if (root->lower == 0 && + root->pgno == 0 && + root->linp[0] == 0) { + mpool_delete(t->bt_mp, root); + errno = EINVAL; + } else { + mpool_put(t->bt_mp, root, 0); + return RET_SUCCESS; + } } if (errno != EINVAL) /* It's OK to not exist. */ return (RET_ERROR); errno = 0; - if ((meta = mpool_new(t->bt_mp, &npg)) == NULL) + if ((meta = mpool_newf(t->bt_mp, &npg, MPOOL_PAGE_NEXT)) == NULL) return (RET_ERROR); - if ((root = mpool_new(t->bt_mp, &npg)) == NULL) + if ((root = mpool_newf(t->bt_mp, &npg, MPOOL_PAGE_NEXT)) == NULL) return (RET_ERROR); if (npg != P_ROOT) diff --git a/lib/libc/db/btree/bt_overflow.c b/lib/libc/db/btree/bt_overflow.c index e083852fc0fa..132ae926bf47 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.20 2013/12/14 18:04:56 christos Exp $ */ +/* $NetBSD: bt_overflow.c,v 1.21 2016/09/24 20:11:12 christos Exp $ */ /*- * Copyright (c) 1990, 1993, 1994 @@ -37,7 +37,7 @@ #endif #include -__RCSID("$NetBSD: bt_overflow.c,v 1.20 2013/12/14 18:04:56 christos Exp $"); +__RCSID("$NetBSD: bt_overflow.c,v 1.21 2016/09/24 20:11:12 christos Exp $"); #include "namespace.h" #include @@ -112,7 +112,7 @@ __ovfl_get(BTREE *t, void *p, size_t *ssz, void **buf, size_t *bufsz) _DBFIT(temp, uint32_t); plen = (uint32_t)temp; for (p = *buf;; p = (char *)p + nb, pg = h->nextpg) { - if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) + if ((h = mpool_getf(t->bt_mp, pg, 0)) == NULL) return (RET_ERROR); nb = MIN(sz, plen); @@ -208,7 +208,7 @@ __ovfl_delete(BTREE *t, void *p) if (pg == P_INVALID || sz == 0) abort(); #endif - if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) + if ((h = mpool_getf(t->bt_mp, pg, 0)) == NULL) return (RET_ERROR); /* Don't delete chains used by internal pages. */ @@ -226,7 +226,7 @@ __ovfl_delete(BTREE *t, void *p) __bt_free(t, h); if (sz <= plen) break; - if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) + if ((h = mpool_getf(t->bt_mp, pg, 0)) == NULL) return (RET_ERROR); } return (RET_SUCCESS); diff --git a/lib/libc/db/btree/bt_page.c b/lib/libc/db/btree/bt_page.c index 0db4aeb8b9ba..dcb5c03386bf 100644 --- a/lib/libc/db/btree/bt_page.c +++ b/lib/libc/db/btree/bt_page.c @@ -1,4 +1,4 @@ -/* $NetBSD: bt_page.c,v 1.13 2008/09/11 12:58:00 joerg Exp $ */ +/* $NetBSD: bt_page.c,v 1.14 2016/09/24 20:11:12 christos Exp $ */ /*- * Copyright (c) 1990, 1993, 1994 @@ -34,7 +34,7 @@ #endif #include -__RCSID("$NetBSD: bt_page.c,v 1.13 2008/09/11 12:58:00 joerg Exp $"); +__RCSID("$NetBSD: bt_page.c,v 1.14 2016/09/24 20:11:12 christos Exp $"); #include "namespace.h" #include @@ -89,7 +89,7 @@ __bt_new(BTREE *t, pgno_t *npg) PAGE *h; if (t->bt_free != P_INVALID && - (h = mpool_get(t->bt_mp, t->bt_free, 0)) != NULL) { + (h = mpool_getf(t->bt_mp, t->bt_free, 0)) != NULL) { *npg = t->bt_free; t->bt_free = h->nextpg; F_SET(t, B_METADIRTY); diff --git a/lib/libc/db/btree/bt_put.c b/lib/libc/db/btree/bt_put.c index 986d6c18428d..7de49b2c7068 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.20 2011/06/26 22:20:31 christos Exp $ */ +/* $NetBSD: bt_put.c,v 1.21 2016/09/24 20:11:12 christos Exp $ */ /*- * Copyright (c) 1990, 1993, 1994 @@ -37,7 +37,7 @@ #endif #include -__RCSID("$NetBSD: bt_put.c,v 1.20 2011/06/26 22:20:31 christos Exp $"); +__RCSID("$NetBSD: bt_put.c,v 1.21 2016/09/24 20:11:12 christos Exp $"); #include "namespace.h" #include @@ -152,7 +152,7 @@ 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_cursor.pg.pgno, 0)) == NULL) + if ((h = mpool_getf(t->bt_mp, t->bt_cursor.pg.pgno, 0)) == NULL) return (RET_ERROR); idx = t->bt_cursor.pg.index; goto delete; @@ -271,7 +271,7 @@ bt_fast(BTREE *t, const DBT *key, const DBT *data, int *exactp) uint32_t nbytes; int cmp; - if ((h = mpool_get(t->bt_mp, t->bt_last.pgno, 0)) == NULL) { + if ((h = mpool_getf(t->bt_mp, t->bt_last.pgno, 0)) == NULL) { t->bt_order = NOT; return (NULL); } diff --git a/lib/libc/db/btree/bt_search.c b/lib/libc/db/btree/bt_search.c index 00da7c9b68ba..c534d1bd01aa 100644 --- a/lib/libc/db/btree/bt_search.c +++ b/lib/libc/db/btree/bt_search.c @@ -1,4 +1,4 @@ -/* $NetBSD: bt_search.c,v 1.17 2008/09/11 12:58:00 joerg Exp $ */ +/* $NetBSD: bt_search.c,v 1.18 2016/09/24 20:11:12 christos Exp $ */ /*- * Copyright (c) 1990, 1993, 1994 @@ -37,7 +37,7 @@ #endif #include -__RCSID("$NetBSD: bt_search.c,v 1.17 2008/09/11 12:58:00 joerg Exp $"); +__RCSID("$NetBSD: bt_search.c,v 1.18 2016/09/24 20:11:12 christos Exp $"); #include "namespace.h" #include @@ -75,7 +75,7 @@ __bt_search(BTREE *t, const DBT *key, int *exactp) BT_CLR(t); for (pg = P_ROOT;;) { - if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) + if ((h = mpool_getf(t->bt_mp, pg, 0)) == NULL) return (NULL); /* Do a binary search on the current page. */ @@ -150,23 +150,65 @@ next: BT_PUSH(t, h->pgno, idx); static int __bt_snext(BTREE *t, PAGE *h, const DBT *key, int *exactp) { + BINTERNAL *bi; EPG e; + EPGNO *parent; + indx_t idx = 0; + pgno_t pgno; + int level; /* * Get the next page. The key is either an exact * match, or not as good as the one we already have. */ - if ((e.page = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL) - return (0); + if ((e.page = mpool_getf(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); + if (__bt_cmp(t, key, &e) != 0) { + mpool_put(t->bt_mp, e.page, 0); + return 0; } - mpool_put(t->bt_mp, e.page, 0); - return (0); + mpool_put(t->bt_mp, h, 0); + t->bt_cur = e; + *exactp = 1; + + /* + * Adjust the stack for the movement. + * + * Move up the stack. + */ + for (level = 0; (parent = BT_POP(t)) != NULL; ++level) { + /* Get the parent page. */ + if ((h = mpool_getf(t->bt_mp, parent->pgno, 0)) == NULL) + return 0; + + /* Move to the next index. */ + if (parent->index != NEXTINDEX(h) - 1) { + idx = parent->index + 1; + BT_PUSH(t, h->pgno, idx); + break; + } + + mpool_put(t->bt_mp, h, 0); + } + + /* Restore the stack. */ + while (level--) { + /* Push the next level down onto the stack. */ + bi = GETBINTERNAL(h, idx); + 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_getf(t->bt_mp, pgno, 0)) == NULL) + return 0; + idx = 0; + } + mpool_put(t->bt_mp, h, 0); + return 1; } /* @@ -185,21 +227,64 @@ __bt_snext(BTREE *t, PAGE *h, const DBT *key, int *exactp) static int __bt_sprev(BTREE *t, PAGE *h, const DBT *key, int *exactp) { + BINTERNAL *bi; EPG e; + EPGNO *parent; + indx_t idx = 0; + pgno_t pgno; + int level; /* * Get the previous page. The key is either an exact * match, or not as good as the one we already have. */ - if ((e.page = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL) - return (0); + if ((e.page = mpool_getf(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); + if (__bt_cmp(t, key, &e) != 0) { + mpool_put(t->bt_mp, e.page, 0); + return 0; } - mpool_put(t->bt_mp, e.page, 0); - return (0); + + mpool_put(t->bt_mp, h, 0); + t->bt_cur = e; + *exactp = 1; + + /* + * Adjust the stack for the movement. + * + * Move up the stack. + */ + for (level = 0; (parent = BT_POP(t)) != NULL; ++level) { + /* Get the parent page. */ + if ((h = mpool_getf(t->bt_mp, parent->pgno, 0)) == NULL) + return 1; + + /* Move to the next index. */ + if (parent->index != 0) { + idx = parent->index - 1; + BT_PUSH(t, h->pgno, idx); + break; + } + mpool_put(t->bt_mp, h, 0); + } + + /* Restore the stack. */ + while (level--) { + /* Push the next level down onto the stack. */ + bi = GETBINTERNAL(h, idx); + pgno = bi->pgno; + + /* Lose the currently pinned page. */ + mpool_put(t->bt_mp, h, 0); + + /* Get the next level down. */ + if ((h = mpool_getf(t->bt_mp, pgno, 0)) == NULL) + return 1; + + idx = NEXTINDEX(h) - 1; + BT_PUSH(t, pgno, idx); + } + mpool_put(t->bt_mp, h, 0); + return 1; } diff --git a/lib/libc/db/btree/bt_seq.c b/lib/libc/db/btree/bt_seq.c index 3f5b4cfa2204..93a9dfb84770 100644 --- a/lib/libc/db/btree/bt_seq.c +++ b/lib/libc/db/btree/bt_seq.c @@ -1,4 +1,4 @@ -/* $NetBSD: bt_seq.c,v 1.18 2013/09/04 13:03:22 ryoon Exp $ */ +/* $NetBSD: bt_seq.c,v 1.19 2016/09/24 20:11:12 christos Exp $ */ /*- * Copyright (c) 1990, 1993, 1994 @@ -37,7 +37,7 @@ #endif #include -__RCSID("$NetBSD: bt_seq.c,v 1.18 2013/09/04 13:03:22 ryoon Exp $"); +__RCSID("$NetBSD: bt_seq.c,v 1.19 2016/09/24 20:11:12 christos Exp $"); #include "namespace.h" #include @@ -54,6 +54,8 @@ __RCSID("$NetBSD: bt_seq.c,v 1.18 2013/09/04 13:03:22 ryoon Exp $"); static int __bt_first(BTREE *, const DBT *, EPG *, int *); static int __bt_seqadv(BTREE *, EPG *, int); static int __bt_seqset(BTREE *, EPG *, DBT *, int); +static int __bt_rseq_next(BTREE *, EPG *); +static int __bt_rseq_prev(BTREE *, EPG *); /* * Sequential scan support. @@ -71,7 +73,7 @@ static int __bt_seqset(BTREE *, EPG *, DBT *, int); * dbp: pointer to access method * key: key for positioning and return value * data: data return value - * flags: R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV. + * flags: R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV, R_RNEXT, R_RPREV. * * Returns: * RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key. @@ -99,6 +101,8 @@ __bt_seq(const DB *dbp, DBT *key, DBT *data, u_int flags) switch (flags) { case R_NEXT: case R_PREV: + case R_RNEXT: + case R_RPREV: if (F_ISSET(&t->bt_cursor, CURS_INIT)) { status = __bt_seqadv(t, &e, (int)flags); break; @@ -140,7 +144,7 @@ __bt_seq(const DB *dbp, DBT *key, DBT *data, u_int flags) * t: tree * ep: storage for returned key * key: key for initial scan position - * flags: R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV + * flags: R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV, R_RNEXT, R_RPREV. * * Side effects: * Pins the page the cursor references. @@ -173,9 +177,11 @@ __bt_seqset(BTREE *t, EPG *ep, DBT *key, int flags) return (__bt_first(t, key, ep, &exact)); case R_FIRST: /* First record. */ case R_NEXT: + case R_RNEXT: + BT_CLR(t); /* Walk down the left-hand side of the tree. */ for (pg = P_ROOT;;) { - if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) + if ((h = mpool_getf(t->bt_mp, pg, 0)) == NULL) return (RET_ERROR); /* Check for an empty tree. */ @@ -187,6 +193,7 @@ __bt_seqset(BTREE *t, EPG *ep, DBT *key, int flags) if (h->flags & (P_BLEAF | P_RLEAF)) break; pg = GETBINTERNAL(h, 0)->pgno; + BT_PUSH(t, h->pgno, 0); mpool_put(t->bt_mp, h, 0); } ep->page = h; @@ -194,9 +201,11 @@ __bt_seqset(BTREE *t, EPG *ep, DBT *key, int flags) break; case R_LAST: /* Last record. */ case R_PREV: + case R_RPREV: + BT_CLR(t); /* Walk down the right-hand side of the tree. */ for (pg = P_ROOT;;) { - if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) + if ((h = mpool_getf(t->bt_mp, pg, 0)) == NULL) return (RET_ERROR); /* Check for an empty tree. */ @@ -208,6 +217,7 @@ __bt_seqset(BTREE *t, EPG *ep, DBT *key, int flags) if (h->flags & (P_BLEAF | P_RLEAF)) break; pg = GETBINTERNAL(h, NEXTINDEX(h) - 1)->pgno; + BT_PUSH(t, h->pgno, NEXTINDEX(h) - 1); mpool_put(t->bt_mp, h, 0); } @@ -224,7 +234,7 @@ __bt_seqset(BTREE *t, EPG *ep, DBT *key, int flags) * * Parameters: * t: tree - * flags: R_NEXT, R_PREV + * flags: R_NEXT, R_PREV, R_RNEXT, R_RPREV * * Side effects: * Pins the page the new key/data record is on. @@ -239,7 +249,7 @@ __bt_seqadv(BTREE *t, EPG *ep, int flags) PAGE *h; indx_t idx = 0; /* pacify gcc */ pgno_t pg; - int exact; + int exact, rval; /* * There are a couple of states that we can be in. The cursor has @@ -248,18 +258,48 @@ __bt_seqadv(BTREE *t, EPG *ep, int flags) c = &t->bt_cursor; /* - * The cursor was deleted where there weren't any duplicate records, - * so the key was saved. Find out where that key would go in the - * current tree. It doesn't matter if the returned key is an exact - * match or not -- if it's an exact match, the record was added after - * the delete so we can just return it. If not, as long as there's - * a record there, return it. + * The cursor was deleted and there weren't any duplicate records, + * so the cursor's key was saved. Find out where that key would + * be in the current tree. If the returned key is an exact match, + * it means that a key/data pair was inserted into the tree after + * the delete. We could reasonably return the key, but the problem + * is that this is the access pattern we'll see if the user is + * doing seq(..., R_NEXT)/put(..., 0) pairs, i.e. the put deletes + * the cursor record and then replaces it, so the cursor was saved, + * and we'll simply return the same "new" record until the user + * notices and doesn't do a put() of it. Since the key is an exact + * match, we could as easily put the new record before the cursor, + * and we've made no guarantee to return it. So, move forward or + * back a record if it's an exact match. + * + * XXX + * In the current implementation, put's to the cursor are done with + * delete/add pairs. This has two consequences. First, it means + * that seq(..., R_NEXT)/put(..., R_CURSOR) pairs are going to exhibit + * the same behavior as above. Second, you can return the same key + * twice if you have duplicate records. The scenario is that the + * cursor record is deleted, moving the cursor forward or backward + * to a duplicate. The add then inserts the new record at a location + * ahead of the cursor because duplicates aren't sorted in any way, + * and the new record is later returned. This has to be fixed at some + * point. */ - if (F_ISSET(c, CURS_ACQUIRE)) - return (__bt_first(t, &c->key, ep, &exact)); + if (F_ISSET(c, CURS_ACQUIRE)) { + if ((rval = __bt_first(t, &c->key, ep, &exact)) == RET_ERROR) + return RET_ERROR; + if (!exact) + return rval; + /* + * XXX + * Kluge -- get, release, get the page. + */ + c->pg.pgno = ep->page->pgno; + c->pg.index = ep->index; + mpool_put(t->bt_mp, ep->page, 0); + } /* Get the page referenced by the cursor. */ - if ((h = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL) + if ((h = mpool_getf(t->bt_mp, c->pg.pgno, 0)) == NULL) return (RET_ERROR); /* @@ -268,6 +308,7 @@ __bt_seqadv(BTREE *t, EPG *ep, int flags) */ switch (flags) { case R_NEXT: /* Next record. */ + case R_RNEXT: /* * The cursor was deleted in duplicate records, and moved * forward to a record that has yet to be returned. Clear @@ -277,16 +318,22 @@ __bt_seqadv(BTREE *t, EPG *ep, int flags) goto usecurrent; idx = c->pg.index; if (++idx == NEXTINDEX(h)) { + if (flags == R_RNEXT) { + ep->page = h; + ep->index = idx; + return __bt_rseq_next(t, ep); + } 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); + return RET_SPECIAL; + if ((h = mpool_getf(t->bt_mp, pg, 0)) == NULL) + return RET_ERROR; idx = 0; } break; case R_PREV: /* Previous record. */ + case R_RPREV: /* * The cursor was deleted in duplicate records, and moved * backward to a record that has yet to be returned. Clear @@ -300,12 +347,17 @@ usecurrent: F_CLR(c, CURS_AFTER | CURS_BEFORE); } idx = c->pg.index; if (idx == 0) { + if (flags == R_RPREV) { + ep->page = h; + ep->index = idx; + return __bt_rseq_prev(t, ep); + } 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); + return RET_SPECIAL; + if ((h = mpool_getf(t->bt_mp, pg, 0)) == NULL) + return RET_ERROR; idx = NEXTINDEX(h) - 1; } else --idx; @@ -316,6 +368,83 @@ usecurrent: F_CLR(c, CURS_AFTER | CURS_BEFORE); ep->index = idx; return (RET_SUCCESS); } +/* + * Get the first item on the next page, but by going up and down the tree. + */ +static int +__bt_rseq_next(BTREE *t, EPG *ep) +{ + PAGE *h; + indx_t idx; + EPGNO *up; + pgno_t pg; + + h = ep->page; + idx = ep->index; + do { + /* Move up the tree. */ + up = BT_POP(t); + mpool_put(t->bt_mp, h, 0); + /* Did we hit the right edge of the root? */ + if (up == NULL) + return RET_SPECIAL; + if ((h = mpool_getf(t->bt_mp, up->pgno, 0)) == NULL) + return RET_ERROR; + idx = up->index; + } while (++idx == NEXTINDEX(h)); + + while (!(h->flags & (P_BLEAF | P_RLEAF))) { + /* Move back down the tree. */ + BT_PUSH(t, h->pgno, idx); + pg = GETBINTERNAL(h, idx)->pgno; + mpool_put(t->bt_mp, h, 0); + if ((h = mpool_getf(t->bt_mp, pg, 0)) == NULL) + return RET_ERROR; + idx = 0; + } + ep->page = h; + ep->index = idx; + return RET_SUCCESS; +} + +/* + * Get the last item on the previous page, but by going up and down the tree. + */ +static int +__bt_rseq_prev(BTREE *t, EPG *ep) +{ + PAGE *h; + indx_t idx; + EPGNO *up; + pgno_t pg; + + h = ep->page; + idx = ep->index; + do { + /* Move up the tree. */ + up = BT_POP(t); + mpool_put(t->bt_mp, h, 0); + /* Did we hit the left edge of the root? */ + if (up == NULL) + return RET_SPECIAL; + if ((h = mpool_getf(t->bt_mp, up->pgno, 0)) == NULL) + return RET_ERROR; + idx = up->index; + } while (idx == 0); + --idx; + while (!(h->flags & (P_BLEAF | P_RLEAF))) { + /* Move back down the tree. */ + BT_PUSH(t, h->pgno, idx); + pg = GETBINTERNAL(h, idx)->pgno; + mpool_put(t->bt_mp, h, 0); + if ((h = mpool_getf(t->bt_mp, pg, 0)) == NULL) + return RET_ERROR; + idx = NEXTINDEX(h) - 1; + } + ep->page = h; + ep->index = idx; + return RET_SUCCESS; +} /* * __bt_first -- @@ -334,7 +463,7 @@ usecurrent: F_CLR(c, CURS_AFTER | CURS_BEFORE); static int __bt_first(BTREE *t, const DBT *key, EPG *erval, int *exactp) { - PAGE *h; + PAGE *h, *hprev; EPG *ep, save; pgno_t pg; @@ -347,13 +476,13 @@ __bt_first(BTREE *t, const DBT *key, EPG *erval, int *exactp) * page) and return it. */ if ((ep = __bt_search(t, key, exactp)) == NULL) - return (0); + return RET_SPECIAL; if (*exactp) { if (F_ISSET(t, B_NODUPS)) { *erval = *ep; return (RET_SUCCESS); } - + /* * Walk backwards, as long as the entry matches and there are * keys left in the tree. Save a copy of each match in case @@ -378,10 +507,14 @@ __bt_first(BTREE *t, const DBT *key, EPG *erval, int *exactp) 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) - return (RET_ERROR); - ep->page = h; + if ((hprev = mpool_getf(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 = hprev; ep->index = NEXTINDEX(h); } --ep->index; @@ -406,7 +539,7 @@ __bt_first(BTREE *t, const DBT *key, EPG *erval, int *exactp) mpool_put(t->bt_mp, h, 0); if (pg == P_INVALID) return (RET_SPECIAL); - if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) + if ((h = mpool_getf(t->bt_mp, pg, 0)) == NULL) return (RET_ERROR); ep->index = 0; ep->page = h; diff --git a/lib/libc/db/btree/bt_split.c b/lib/libc/db/btree/bt_split.c index f7356c7e30d8..c3e792b9f73c 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.20 2011/06/20 09:11:17 mrg Exp $ */ +/* $NetBSD: bt_split.c,v 1.21 2016/09/24 20:11:12 christos Exp $ */ /*- * Copyright (c) 1990, 1993, 1994 @@ -37,7 +37,7 @@ #endif #include -__RCSID("$NetBSD: bt_split.c,v 1.20 2011/06/20 09:11:17 mrg Exp $"); +__RCSID("$NetBSD: bt_split.c,v 1.21 2016/09/24 20:11:12 christos Exp $"); #include "namespace.h" #include @@ -153,7 +153,7 @@ __bt_split(BTREE *t, PAGE *sp, const DBT *key, const DBT *data, int flags, rchild = r; /* Get the parent page. */ - if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL) + if ((h = mpool_getf(t->bt_mp, parent->pgno, 0)) == NULL) goto err2; /* @@ -401,7 +401,7 @@ bt_page(BTREE *t, PAGE *h, PAGE **lp, PAGE **rp, indx_t *skip, size_t ilen) /* Fix up the previous pointer of the page after the split page. */ if (h->nextpg != P_INVALID) { - if ((tp = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL) { + if ((tp = mpool_getf(t->bt_mp, h->nextpg, 0)) == NULL) { free(l); /* XXX mpool_free(t->bt_mp, r->pgno); */ return (NULL); @@ -799,7 +799,7 @@ bt_preserve(BTREE *t, pgno_t pg) { PAGE *h; - if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) + if ((h = mpool_getf(t->bt_mp, pg, 0)) == NULL) return (RET_ERROR); h->flags |= P_PRESERVE; mpool_put(t->bt_mp, h, MPOOL_DIRTY); diff --git a/lib/libc/db/btree/extern.h b/lib/libc/db/btree/extern.h index 665f852a54b0..5ea7f11e5eb9 100644 --- a/lib/libc/db/btree/extern.h +++ b/lib/libc/db/btree/extern.h @@ -1,4 +1,4 @@ -/* $NetBSD: extern.h,v 1.12 2008/09/26 11:41:06 tsutsui Exp $ */ +/* $NetBSD: extern.h,v 1.13 2016/09/24 20:11:12 christos Exp $ */ /*- * Copyright (c) 1991, 1993, 1994 @@ -48,6 +48,7 @@ void __bt_pgin(void *, pgno_t, void *); void __bt_pgout(void *, pgno_t, void *); int __bt_push(BTREE *, pgno_t, int); int __bt_put(const DB *dbp, DBT *, const DBT *, unsigned int); +int __bt_relink(BTREE *, PAGE *); int __bt_ret(BTREE *, EPG *, DBT *, DBT *, DBT *, DBT *, int); EPG *__bt_search(BTREE *, const DBT *, int *); int __bt_seq(const DB *, DBT *, DBT *, unsigned int); diff --git a/lib/libc/db/mpool/mpool.c b/lib/libc/db/mpool/mpool.c index 020c53770aeb..aa4253aa25f1 100644 --- a/lib/libc/db/mpool/mpool.c +++ b/lib/libc/db/mpool/mpool.c @@ -1,4 +1,4 @@ -/* $NetBSD: mpool.c,v 1.21 2013/12/14 18:04:00 christos Exp $ */ +/* $NetBSD: mpool.c,v 1.22 2016/09/24 20:11:12 christos Exp $ */ /*- * Copyright (c) 1990, 1993, 1994 @@ -34,7 +34,7 @@ #endif #include -__RCSID("$NetBSD: mpool.c,v 1.21 2013/12/14 18:04:00 christos Exp $"); +__RCSID("$NetBSD: mpool.c,v 1.22 2016/09/24 20:11:12 christos Exp $"); #include "namespace.h" #include @@ -55,7 +55,9 @@ __RCSID("$NetBSD: mpool.c,v 1.21 2013/12/14 18:04:00 christos Exp $"); __weak_alias(mpool_close,_mpool_close) __weak_alias(mpool_filter,_mpool_filter) __weak_alias(mpool_get,_mpool_get) +__weak_alias(mpool_getf,_mpool_getf) __weak_alias(mpool_new,_mpool_new) +__weak_alias(mpool_newf,_mpool_newf) __weak_alias(mpool_open,_mpool_open) __weak_alias(mpool_put,_mpool_put) __weak_alias(mpool_sync,_mpool_sync) @@ -121,7 +123,7 @@ mpool_filter(MPOOL *mp, void (*pgin)(void *, pgno_t, void *), * Get a new page of memory. */ void * -mpool_new( MPOOL *mp, pgno_t *pgnoaddr) +mpool_newf(MPOOL *mp, pgno_t *pgnoaddr, unsigned int flags) { struct _hqh *head; BKT *bp; @@ -140,8 +142,14 @@ mpool_new( MPOOL *mp, pgno_t *pgnoaddr) */ if ((bp = mpool_bkt(mp)) == NULL) return NULL; - *pgnoaddr = bp->pgno = mp->npages++; - bp->flags = MPOOL_PINNED; + + if (flags == MPOOL_PAGE_REQUEST) { + mp->npages++; + bp->pgno = *pgnoaddr; + } else + bp->pgno = *pgnoaddr = mp->npages++; + + bp->flags = MPOOL_PINNED | MPOOL_INUSE; head = &mp->hqh[HASHKEY(bp->pgno)]; TAILQ_INSERT_HEAD(head, bp, hq); @@ -149,13 +157,44 @@ mpool_new( MPOOL *mp, pgno_t *pgnoaddr) return bp->page; } +void * +mpool_new(MPOOL *mp, pgno_t *pgnoaddr) +{ + return mpool_newf(mp, pgnoaddr, 0); +} + +int +mpool_delete(MPOOL *mp, void *page) +{ + struct _hqh *head; + BKT *bp; + + bp = (void *)((char *)page - sizeof(BKT)); + +#ifdef DEBUG + if (!(bp->flags & MPOOL_PINNED)) { + (void)fprintf(stderr, + "%s: page %d not pinned\n", __func__, bp->pgno); + abort(); + } +#endif + + /* Remove from the hash and lru queues. */ + head = &mp->hqh[HASHKEY(bp->pgno)]; + TAILQ_REMOVE(head, bp, hq); + TAILQ_REMOVE(&mp->lqh, bp, q); + + free(bp); + return RET_SUCCESS; +} + /* * mpool_get * Get a page. */ /*ARGSUSED*/ void * -mpool_get(MPOOL *mp, pgno_t pgno, u_int flags) +mpool_getf(MPOOL *mp, pgno_t pgno, unsigned int flags) { struct _hqh *head; BKT *bp; @@ -175,7 +214,7 @@ mpool_get(MPOOL *mp, pgno_t pgno, u_int flags) /* Check for a page that is cached. */ if ((bp = mpool_look(mp, pgno)) != NULL) { #ifdef DEBUG - if (bp->flags & MPOOL_PINNED) { + if (!(flags & MPOOL_IGNOREPIN) && bp->flags & MPOOL_PINNED) { (void)fprintf(stderr, "mpool_get: page %d already pinned\n", bp->pgno); abort(); @@ -192,7 +231,8 @@ mpool_get(MPOOL *mp, pgno_t pgno, u_int flags) TAILQ_INSERT_TAIL(&mp->lqh, bp, q); /* Return a pinned page. */ - bp->flags |= MPOOL_PINNED; + if (!(flags & MPOOL_IGNOREPIN)) + bp->flags |= MPOOL_PINNED; return bp->page; } @@ -205,15 +245,32 @@ mpool_get(MPOOL *mp, pgno_t pgno, u_int flags) ++mp->pageread; #endif off = mp->pagesize * pgno; + if (off / mp->pagesize != pgno) { + /* Run past the end of the file, or at least the part we + can address without large-file support? */ + errno = E2BIG; + return NULL; + } + if ((nr = pread(mp->fd, bp->page, (size_t)mp->pagesize, off)) != (int)mp->pagesize) { - if (nr >= 0) + if (nr > 0) { errno = EFTYPE; - return NULL; + return NULL; + } else if (nr == 0) { + /* + * A zero-length reads, means you need to create a + * new page. + */ + memset(bp->page, 0, mp->pagesize); + } else + return NULL; } /* Set the page number, pin the page. */ bp->pgno = pgno; - bp->flags = MPOOL_PINNED; + if (!(flags & MPOOL_IGNOREPIN)) + bp->flags = MPOOL_PINNED; +bp->flags |= MPOOL_INUSE; /* * Add the page to the head of the hash chain and the tail @@ -230,6 +287,12 @@ mpool_get(MPOOL *mp, pgno_t pgno, u_int flags) return bp->page; } +void * +mpool_get(MPOOL *mp, pgno_t pgno) +{ + return mpool_getf(mp, pgno, 0); +} + /* * mpool_put * Return a page. @@ -252,7 +315,8 @@ mpool_put(MPOOL *mp, void *page, u_int flags) } #endif bp->flags &= ~MPOOL_PINNED; - bp->flags |= flags & MPOOL_DIRTY; + if (flags & MPOOL_DIRTY) + bp->flags |= flags & MPOOL_DIRTY; return (RET_SUCCESS); } @@ -371,6 +435,13 @@ mpool_write(MPOOL *mp, BKT *bp) (mp->pgout)(mp->pgcookie, bp->pgno, bp->page); off = mp->pagesize * bp->pgno; + if (off / mp->pagesize != bp->pgno) { + /* Run past the end of the file, or at least the part we + can address without large-file support? */ + errno = E2BIG; + return RET_ERROR; + } + if (pwrite(mp->fd, bp->page, (size_t)mp->pagesize, off) != (ssize_t)mp->pagesize) return RET_ERROR; diff --git a/lib/libc/db/recno/rec_open.c b/lib/libc/db/recno/rec_open.c index 5f9de858c3c8..08ef198035fe 100644 --- a/lib/libc/db/recno/rec_open.c +++ b/lib/libc/db/recno/rec_open.c @@ -1,4 +1,4 @@ -/* $NetBSD: rec_open.c,v 1.20 2013/12/01 00:22:48 christos Exp $ */ +/* $NetBSD: rec_open.c,v 1.21 2016/09/24 20:11:12 christos Exp $ */ /*- * Copyright (c) 1990, 1993, 1994 @@ -37,7 +37,7 @@ #endif #include -__RCSID("$NetBSD: rec_open.c,v 1.20 2013/12/01 00:22:48 christos Exp $"); +__RCSID("$NetBSD: rec_open.c,v 1.21 2016/09/24 20:11:12 christos Exp $"); #include "namespace.h" #include @@ -197,7 +197,7 @@ slow: if ((t->bt_rfp = fdopen(rfd, "r")) == NULL) dbp->sync = __rec_sync; /* If the root page was created, reset the flags. */ - if ((h = mpool_get(t->bt_mp, P_ROOT, 0)) == NULL) + if ((h = mpool_getf(t->bt_mp, P_ROOT, 0)) == NULL) goto err; if ((h->flags & P_TYPE) == P_BLEAF) { F_CLR(h, P_TYPE); diff --git a/lib/libc/db/recno/rec_search.c b/lib/libc/db/recno/rec_search.c index 1238c8db3284..baa564a6d06b 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.14 2008/09/11 12:58:00 joerg Exp $ */ +/* $NetBSD: rec_search.c,v 1.15 2016/09/24 20:11:12 christos Exp $ */ /*- * Copyright (c) 1990, 1993 @@ -34,7 +34,7 @@ #endif #include -__RCSID("$NetBSD: rec_search.c,v 1.14 2008/09/11 12:58:00 joerg Exp $"); +__RCSID("$NetBSD: rec_search.c,v 1.15 2016/09/24 20:11:12 christos Exp $"); #include "namespace.h" #include @@ -77,7 +77,7 @@ __rec_search(BTREE *t, recno_t recno, enum SRCHOP op) BT_CLR(t); for (pg = P_ROOT, total = 0;;) { - if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) + if ((h = mpool_getf(t->bt_mp, pg, 0)) == NULL) goto err; if (h->flags & P_RLEAF) { t->bt_cur.page = h; @@ -113,7 +113,7 @@ __rec_search(BTREE *t, recno_t recno, enum SRCHOP op) err: sverrno = errno; if (op != SEARCH) while ((parent = BT_POP(t)) != NULL) { - if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL) + if ((h = mpool_getf(t->bt_mp, parent->pgno, 0)) == NULL) break; if (op == SINSERT) --GETRINTERNAL(h, parent->index)->nrecs;