Полезная информация

The debug command to the dbtest utility provides assistance for debugging the test suite. If you don't specify a parameter, e.g.:

debug causes dbtest to display a running count of the calls made into the DB library. There is an optional argument to debug which is the number of the operation on which you want to stop. By using your debugger to set a breakpoint in the function __db_loadme, you can obtain control of the tester immediately before a particular operation. For example:

To set a counter breakpoint from inside a debugger, set the global variable debug_test to the counter value at which you want to stop. For example, you might first stop at operation 100, and then stop at operation 200 by initially setting a breakpoint in __db_loadme, issuing a debug 100 command and then setting debug_test to 200 in the debugger. (Some of the trickier bugs in DB are best solved by binary search, looking for the precise moment at which the page contents go bad.)

If you want to stop on each iteration, set the variable debug_stop to a non-zero value.


There are a number of routines to help you display page and tree contents. These routines live in the file ../db/db_pr.c. Some of the more useful ones are:

Examples of calling these functions from gdb are as follows.


The __db_prpage function displays a page as specified by a reference to a PAGE structure. In this case, cp references a CURSOR structure, which contains the pointer to the page.

(gdb) whatis cp
type = CURSOR *
(gdb) whatis cp->page
type = PAGE *
(gdb) print *cp
$1 = {dbc = 0x807e040, page = 0xc110400, pgno = 2, indx = 0, dpgno = 0,
  dindx = 0, lock = 0, mode = DB_LOCK_NG, flags = 0}
(gdb) print __db_prpage(cp->page, 1)
page    2: (btree leaf)
    lsn.file: 0 lsn.offset: 0
    prev:    0 next:    3 level:  1 entries:   28 offset:  136
    [000]  500 len:   6 data: aback0x00
    [001]  488 len:   6 data: aback0x00
    [002]  476 len:   6 data: abaft0x00
    [003]  464 len:   6 data: abaft0x00
    [004]  452 len:   8 data: abandon0x00
    [005]  440 len:   8 data: abandon0x00
    [006]  424 len:  10 data: abandoned0x00
    [007]  408 len:  10 data: abandoned0x00
    [008]  392 len:  11 data: abandoning0x00
    [009]  376 len:  11 data: abandoning0x00
    [010]  360 len:  12 data: abandonment0x00
    [011]  344 len:  12 data: abandonment0x00
    [012]  332 len:   9 data: abandons0x00
    [013]  320 len:   9 data: abandons0x00
    [014]  308 len:   6 data: abase0x00
    [015]  296 len:   6 data: abase0x00
    [016]  284 len:   7 data: abased0x00
    [017]  272 len:   7 data: abased0x00
    [018]  256 len:  10 data: abasement0x00
    [019]  240 len:  10 data: abasement0x00
    [020]  224 len:  11 data: abasements0x00
    [021]  208 len:  11 data: abasements0x00
    [022]  196 len:   7 data: abases0x00
    [023]  184 len:   7 data: abases0x00
    [024]  172 len:   6 data: abash0x00
    [025]  160 len:   6 data: abash0x00
    [026]  148 len:   8 data: abashed0x00
    [027]  136 len:   8 data: abashed0x00
$2 = 0
(gdb)

The __db_prnpage function displays any page in the database, as specified by a page number argument. The dbp->mpf pointer references a DB_MPOOLFILE structure, which is the per-process shared memory buffer pool structure.

(gdb) whatis dbp->mpf
type = DB_MPOOLFILE *
(gdb) print __db_prnpage(dbp->mpf, 2)
page    2: (btree leaf)
    lsn.file: 0 lsn.offset: 0
    prev:    0 next:    3 level:  1 entries:   28 offset:  136
    [000]  500 len:   6 data: aback0x00
    [001]  488 len:   6 data: aback0x00
    [002]  476 len:   6 data: abaft0x00
    [003]  464 len:   6 data: abaft0x00
    [004]  452 len:   8 data: abandon0x00
    [005]  440 len:   8 data: abandon0x00
    [006]  424 len:  10 data: abandoned0x00
    [007]  408 len:  10 data: abandoned0x00
    [008]  392 len:  11 data: abandoning0x00
    [009]  376 len:  11 data: abandoning0x00
    [010]  360 len:  12 data: abandonment0x00
    [011]  344 len:  12 data: abandonment0x00
    [012]  332 len:   9 data: abandons0x00
    [013]  320 len:   9 data: abandons0x00
    [014]  308 len:   6 data: abase0x00
    [015]  296 len:   6 data: abase0x00
    [016]  284 len:   7 data: abased0x00
    [017]  272 len:   7 data: abased0x00
    [018]  256 len:  10 data: abasement0x00
    [019]  240 len:  10 data: abasement0x00
    [020]  224 len:  11 data: abasements0x00
    [021]  208 len:  11 data: abasements0x00
    [022]  196 len:   7 data: abases0x00
    [023]  184 len:   7 data: abases0x00
    [024]  172 len:   6 data: abash0x00
    [025]  160 len:   6 data: abash0x00
    [026]  148 len:   8 data: abashed0x00
    [027]  136 len:   8 data: abashed0x00
$1 = 0
(gdb)

The __db_dump function dumps the entire database to a file. The dbp pointer references a DB structure as might be returned by the db_open function. After this command has been run, the file /tmp/dump will have a copy of the entire database. This is often useful to compare all the changes in the database after running a single subroutine that may have split pages and/or otherwise modified more than a single page.

(gdb) whatis dbp
type = DB *
(gdb) print *dbp
$3 = {mutexp = 0x0, type = DB_BTREE, dbenv = 0x807b000, mp_dbenv = 0x0,
  master = 0x807d000, internal = 0x807d100, mp = 0x807b080, mpf = 0x807e000,
  curs_queue = {tqh_first = 0x807e040, tqh_last = 0x807e048}, handleq = {
    lh_first = 0x807d000}, links = {le_next = 0x0, le_prev = 0x807d028},
  log_fileid = 0, txn = 0x0, locker = 0, lock_dbt = {data = 0x0, size = 0,
    ulen = 0, dlen = 0, doff = 0, flags = 0}, lock = {pgno = 0,
    fileid = "\000\004\017\001\001 \000\a5\223Щж\000\000\000\000\000\000\000"}, pgsize = 512, db_malloc = 0, close = 0x804a810 ,
  cursor = 0x8064540 <__bam_cursor>, del = 0x8066554 <__bam_delete>,
  fd = 0x804aa60 , get = 0x80649b0 <__bam_get>,
  put = 0x8067b50 <__bam_put>, stat = 0x806c708 <__bam_stat>,
  sync = 0x8063f30 <__bam_sync>, flags = 80}
(gdb) print __db_dump(dbp, "/tmp/dump", 1)
$4 = 0
(gdb)