]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Add bttest unlink page command
authorTom Yu <tlyu@mit.edu>
Mon, 8 Aug 2016 12:50:40 +0000 (08:50 -0400)
committerTom Yu <tlyu@mit.edu>
Tue, 16 Aug 2016 19:25:03 +0000 (15:25 -0400)
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

src/plugins/kdb/db2/libdb2/btree/bt_delete.c
src/plugins/kdb/db2/libdb2/btree/extern.h
src/plugins/kdb/db2/libdb2/libdb.exports
src/plugins/kdb/db2/libdb2/test/btree.tests/main.c

index 4133aa3f0b1d30a03728ea15d9acd660a2cd6e7b..b2f3a752867ae37b733dd4a171cf02d088742a96 100644 (file)
@@ -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;
index c29b084644d335496bd8152e06990895f0eebd4d..9f4082aff26787db880efb2353a1aea424c8fd62 100644 (file)
@@ -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 *));
index 7828da114606f9a342b79b604dab14f4290b0ba1..0c1689187ff1fd9dd03c067dc965e2cdee3db6fa 100644 (file)
@@ -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
index 33de7a2ff84b3be7321ebccbdab9908991d6dbdc..8281d0e77a4353022a115c085befd81a57351953 100644 (file)
  * 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);
+}