From: Tom Yu Date: Mon, 8 Aug 2016 12:50:40 +0000 (-0400) Subject: Add bttest unlink page command X-Git-Tag: krb5-1.15-beta1~87 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f7e4078de12cb77fa55e3f6aaa8137c1ced2e796;p=thirdparty%2Fkrb5.git Add bttest unlink page command To enable testing of recursive btree traversal, add an unlink page command to the bttest program (used for debugging the libdb2 btree back end). This new bttest command can unlink a specified page number, or it can search for and unlink a page that has both a left and a right sibling. (The user can specify whether to find an internal page or a leaf page.) This unlinking makes the page inaccessible to conventional sequential traversal, simulating some btree corruption that has been seen in the field. ticket: 8476 --- diff --git a/src/plugins/kdb/db2/libdb2/btree/bt_delete.c b/src/plugins/kdb/db2/libdb2/btree/bt_delete.c index 4133aa3f0b..b2f3a75286 100644 --- a/src/plugins/kdb/db2/libdb2/btree/bt_delete.c +++ b/src/plugins/kdb/db2/libdb2/btree/bt_delete.c @@ -50,7 +50,6 @@ static char sccsid[] = "@(#)bt_delete.c 8.13 (Berkeley) 7/28/94"; 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 *)); /* @@ -634,7 +633,7 @@ dup2: c->pg.pgno = e.page->pgno; * t: tree * h: page to be deleted */ -static int +int __bt_relink(t, h) BTREE *t; PAGE *h; diff --git a/src/plugins/kdb/db2/libdb2/btree/extern.h b/src/plugins/kdb/db2/libdb2/btree/extern.h index c29b084644..9f4082aff2 100644 --- a/src/plugins/kdb/db2/libdb2/btree/extern.h +++ b/src/plugins/kdb/db2/libdb2/btree/extern.h @@ -62,6 +62,7 @@ #define __bt_dpage __kdb2_bt_dpage #define __bt_dump __kdb2_bt_dump #define __bt_stat __kdb2_bt_stat +#define __bt_relink __kdb2_bt_relink int __bt_close __P((DB *)); int __bt_cmp __P((BTREE *, const DBT *, EPG *)); @@ -90,12 +91,11 @@ int __ovfl_delete __P((BTREE *, void *)); int __ovfl_get __P((BTREE *, void *, size_t *, void **, size_t *)); int __ovfl_put __P((BTREE *, const DBT *, db_pgno_t *)); -#ifdef DEBUG int __bt_dnpage __P((DB *, db_pgno_t)); int __bt_dpage __P((DB *, PAGE *)); int __bt_dmpage __P((PAGE *)); int __bt_dump __P((DB *)); -#endif -#ifdef STATISTICS + int __bt_stat __P((DB *)); -#endif + +int __bt_relink __P((BTREE *, PAGE *)); diff --git a/src/plugins/kdb/db2/libdb2/libdb.exports b/src/plugins/kdb/db2/libdb2/libdb.exports index 7828da1146..0c1689187f 100644 --- a/src/plugins/kdb/db2/libdb2/libdb.exports +++ b/src/plugins/kdb/db2/libdb2/libdb.exports @@ -24,6 +24,7 @@ __kdb2_bt_open __kdb2_bt_pgin __kdb2_bt_pgout __kdb2_bt_put +__kdb2_bt_relink __kdb2_bt_ret __kdb2_bt_search __kdb2_bt_seq diff --git a/src/plugins/kdb/db2/libdb2/test/btree.tests/main.c b/src/plugins/kdb/db2/libdb2/test/btree.tests/main.c index 33de7a2ff8..8281d0e77a 100644 --- a/src/plugins/kdb/db2/libdb2/test/btree.tests/main.c +++ b/src/plugins/kdb/db2/libdb2/test/btree.tests/main.c @@ -33,6 +33,35 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ +/* + * Copyright (C) 2016 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/4/93"; @@ -98,6 +127,7 @@ void rnext __P((DB *, char **)); void rprev __P((DB *, char **)); void usage __P((void)); void user __P((DB *)); +void unlinkpg __P((DB *, char **)); cmd_table commands[] = { "?", 0, 0, help, "help", NULL, @@ -138,6 +168,8 @@ cmd_table commands[] = { #ifdef DEBUG "sh", 1, 0, show, "show page", "dump a page", #endif + "u", 1, 0, unlinkpg, "unlink pgno|internal|leaf", "unlink a page", + { NULL }, }; @@ -883,3 +915,59 @@ usage() progname); exit (1); } + +/* Find a candidate page to unlink. */ +static PAGE * +candidatepg(BTREE *t, char *arg) +{ + PAGE *h = NULL; + db_pgno_t pg; + u_int32_t sflags; + + if (arg[0] == 'i') + sflags = P_BINTERNAL | P_RINTERNAL; + if (arg[0] == 'l') + sflags = P_BLEAF | P_RLEAF; + for (pg = P_ROOT; pg < t->bt_mp->npages; + mpool_put(t->bt_mp, h, 0), pg++) { + if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) + return h; + /* Look for a nonempty page of the correct + * type that has both left and right siblings. */ + if (h->prevpg == P_INVALID || h->nextpg == P_INVALID) + continue; + if ((h->flags & sflags) && NEXTINDEX(h) != 0) + break; + } + if (pg == t->bt_mp->npages) + h = NULL; + return h; +} + +void +unlinkpg(DB *db, char **argv) +{ + BTREE *t = db->internal; + PAGE *h = NULL; + db_pgno_t pg; + + pg = atoi(argv[1]); + if (pg == 0) + h = candidatepg(t, argv[1]); + else + h = mpool_get(t->bt_mp, pg, 0); + + if (h == NULL) { + fprintf(stderr, "unable to find appropriate page to unlink\n"); + return; + } + printf("chain %d <- %d -> %d\n", h->prevpg, h->pgno, h->nextpg); + if (__bt_relink(t, h) != 0) { + perror("unlinkpg"); + goto cleanup; + } + h->prevpg = P_INVALID; + h->nextpg = P_INVALID; +cleanup: + mpool_put(t->bt_mp, h, MPOOL_DIRTY); +}