Skip to content

Commit

Permalink
Add bttest unlink page command
Browse files Browse the repository at this point in the history
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
  • Loading branch information
tlyu committed Aug 16, 2016
1 parent 590af48 commit f7e4078
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 6 deletions.
3 changes: 1 addition & 2 deletions src/plugins/kdb/db2/libdb2/btree/bt_delete.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 *));

/*
Expand Down Expand Up @@ -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;
Expand Down
8 changes: 4 additions & 4 deletions src/plugins/kdb/db2/libdb2/btree/extern.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *));
Expand Down Expand Up @@ -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 *));
1 change: 1 addition & 0 deletions src/plugins/kdb/db2/libdb2/libdb.exports
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
88 changes: 88 additions & 0 deletions src/plugins/kdb/db2/libdb2/test/btree.tests/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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 },
};

Expand Down Expand Up @@ -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);
}

0 comments on commit f7e4078

Please sign in to comment.