Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add a BT_CONTROL_INFO option to query for database header values. Add a command line interface to lsmtest to access this and other options. "lsmtest bt <filename> <option> ....". |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
e09d4c6aa83d7b88c520c9ebcadd9330 |
User & Date: | dan 2013-11-23 18:41:56.814 |
Context
2013-11-25
| ||
20:50 | Begin adding code for blind-writes. check-in: fc9cdc6ca3 user: dan tags: trunk | |
2013-11-23
| ||
18:41 | Add a BT_CONTROL_INFO option to query for database header values. Add a command line interface to lsmtest to access this and other options. "lsmtest bt <filename> <option> ....". check-in: e09d4c6aa8 user: dan tags: trunk | |
2013-11-22
| ||
18:06 | Fix a couple of bugs to do with recovering the database header and recycling large overflow trees. check-in: 8341d438d3 user: dan tags: trunk | |
Changes
Changes to lsm-test/lsmtest.h.
︙ | ︙ | |||
143 144 145 146 147 148 149 150 151 152 153 154 155 156 | void testFetchCompare(TestDb *, TestDb *, void *, int, int *); void *testMalloc(int); void *testMallocCopy(void *pCopy, int nByte); void *testRealloc(void *, int); void testFree(void *); /* testio.c */ int testVfsConfigureDb(TestDb *pDb); /* testfunc.c */ int do_show(int nArg, char **azArg); int do_work(int nArg, char **azArg); | > > > | 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | void testFetchCompare(TestDb *, TestDb *, void *, int, int *); void *testMalloc(int); void *testMallocCopy(void *pCopy, int nByte); void *testRealloc(void *, int); void testFree(void *); /* lsmtest_bt.c */ int do_bt(int nArg, char **azArg); /* testio.c */ int testVfsConfigureDb(TestDb *pDb); /* testfunc.c */ int do_show(int nArg, char **azArg); int do_work(int nArg, char **azArg); |
︙ | ︙ |
Changes to lsm-test/lsmtest_main.c.
︙ | ︙ | |||
1466 1467 1468 1469 1470 1471 1472 1473 1474 | /* no-op */ } #endif int main(int argc, char **argv){ struct TestFunc { const char *zName; int (*xFunc)(int, char **); } aTest[] = { | > | | | | | | | | | | > > | 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 | /* no-op */ } #endif int main(int argc, char **argv){ struct TestFunc { const char *zName; int bRusageReport; int (*xFunc)(int, char **); } aTest[] = { {"random", 1, do_random_tests}, {"writespeed", 1, do_writer_test}, {"io", 1, st_do_io}, {"insert", 1, do_insert}, {"replay", 1, do_replay}, {"speed", 1, do_speed_tests}, {"speed2", 1, do_speed_test2}, {"show", 0, st_do_show}, {"work", 1, st_do_work}, {"test", 1, do_test}, {"bt", 0, do_bt}, {0, 0} }; int rc; /* Return Code */ int iFunc; /* Index into aTest[] */ int nLeakAlloc = 0; /* Allocations leaked by lsm */ int nLeakByte = 0; /* Bytes leaked by lsm */ |
︙ | ︙ | |||
1529 1530 1531 1532 1533 1534 1535 | testPrintError("Leaked %d bytes in %d allocations (%s)\n", nLeakByte, nLeakAlloc, zReport ); if( rc==0 ) rc = -1; } testMallocUninstall(tdb_lsm_env()); | | | < > | 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 | testPrintError("Leaked %d bytes in %d allocations (%s)\n", nLeakByte, nLeakAlloc, zReport ); if( rc==0 ) rc = -1; } testMallocUninstall(tdb_lsm_env()); if( aTest[iFunc].bRusageReport ){ lsmtest_rusage_report(); } return rc; } |
Changes to main.mk.
︙ | ︙ | |||
303 304 305 306 307 308 309 | $(TOP)/lsm-test/lsmtest7.c $(TOP)/lsm-test/lsmtest8.c \ $(TOP)/lsm-test/lsmtest9.c \ $(TOP)/lsm-test/lsmtest_datasource.c \ $(TOP)/lsm-test/lsmtest_func.c $(TOP)/lsm-test/lsmtest_io.c \ $(TOP)/lsm-test/lsmtest_main.c $(TOP)/lsm-test/lsmtest_mem.c \ $(TOP)/lsm-test/lsmtest_tdb.c $(TOP)/lsm-test/lsmtest_tdb3.c \ $(TOP)/lsm-test/lsmtest_tdb4.c \ | | | 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 | $(TOP)/lsm-test/lsmtest7.c $(TOP)/lsm-test/lsmtest8.c \ $(TOP)/lsm-test/lsmtest9.c \ $(TOP)/lsm-test/lsmtest_datasource.c \ $(TOP)/lsm-test/lsmtest_func.c $(TOP)/lsm-test/lsmtest_io.c \ $(TOP)/lsm-test/lsmtest_main.c $(TOP)/lsm-test/lsmtest_mem.c \ $(TOP)/lsm-test/lsmtest_tdb.c $(TOP)/lsm-test/lsmtest_tdb3.c \ $(TOP)/lsm-test/lsmtest_tdb4.c \ $(TOP)/lsm-test/lsmtest_util.c $(TOP)/lsm-test/lsmtest_bt.c LSMTESTHDR = $(TOP)/lsm-test/lsmtest.h $(TOP)/lsm-test/lsmtest_tdb.h # This is the default Makefile target. The objects listed here # are what get build when you type just "make" with no arguments. # all: sqlite4.h libsqlite4.a sqlite4$(EXE) |
︙ | ︙ |
Changes to src/bt.h.
︙ | ︙ | |||
166 167 168 169 170 171 172 | ** ** BT_CONTROL_MULTIPROC: ** The third argument is interpreted as a pointer to type (int). ** ** BT_CONTROL_LOGSIZECB: ** ** BT_CONTROL_CHECKPOINT: | | > > > > > > > > > | | | | | | | | | > | | > | 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 | ** ** BT_CONTROL_MULTIPROC: ** The third argument is interpreted as a pointer to type (int). ** ** BT_CONTROL_LOGSIZECB: ** ** BT_CONTROL_CHECKPOINT: ** ** BT_CONTROL_FAST_INSERT_OP: ** The third argument is currently unused. This file-control causes the ** next call to sqlite4BtReplace() or sqlite4BtCsrOpen() to write to or ** open a cursor on the "fast-insert" tree. Subsequent operations are ** unaffected. ** ** In other words, an app that uses the fast-insert tree exclusively ** must execute this file-control before every call to CsrOpen() or ** Replace(). */ #define BT_CONTROL_INFO 7706389 #define BT_CONTROL_SETVFS 7706390 #define BT_CONTROL_GETVFS 7706391 #define BT_CONTROL_SAFETY 7706392 #define BT_CONTROL_AUTOCKPT 7706393 #define BT_CONTROL_LOGSIZE 7706394 #define BT_CONTROL_MULTIPROC 7706395 #define BT_CONTROL_LOGSIZECB 7706396 #define BT_CONTROL_CHECKPOINT 7706397 #define BT_CONTROL_FAST_INSERT_OP 7706498 int sqlite4BtControl(bt_db*, int op, void *pArg); #define BT_SAFETY_OFF 0 #define BT_SAFETY_NORMAL 1 #define BT_SAFETY_FULL 2 typedef struct bt_info bt_info; struct bt_info { int eType; unsigned int pgno; sqlite4_buffer output; }; #define BT_INFO_PAGEDUMP 1 #define BT_INFO_FILENAME 2 #define BT_INFO_HDRDUMP 3 typedef struct bt_logsizecb bt_logsizecb; struct bt_logsizecb { void *pCtx; /* A copy of this is passed to xLogsize() */ void (*xLogsize)(void*, int); /* Callback function */ }; |
︙ | ︙ |
Changes to src/btInt.h.
︙ | ︙ | |||
134 135 136 137 138 139 140 141 142 143 144 145 146 147 | void sqlite4BtPagerSetAutockpt(BtPager*, int*); void sqlite4BtPagerLogsize(BtPager*, int*); void sqlite4BtPagerMultiproc(BtPager *pPager, int *piVal); void sqlite4BtPagerLogsizeCb(BtPager *pPager, bt_logsizecb*); int sqlite4BtPagerCheckpoint(BtPager *pPager, bt_checkpoint*); /* ** End of bt_pager.c interface. *************************************************************************/ /************************************************************************* ** File-system interface. */ | > > | 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | void sqlite4BtPagerSetAutockpt(BtPager*, int*); void sqlite4BtPagerLogsize(BtPager*, int*); void sqlite4BtPagerMultiproc(BtPager *pPager, int *piVal); void sqlite4BtPagerLogsizeCb(BtPager *pPager, bt_logsizecb*); int sqlite4BtPagerCheckpoint(BtPager *pPager, bt_checkpoint*); int sqlite4BtPagerHdrdump(BtPager *pPager, sqlite4_buffer *pBuf); /* ** End of bt_pager.c interface. *************************************************************************/ /************************************************************************* ** File-system interface. */ |
︙ | ︙ | |||
275 276 277 278 279 280 281 | int sqlite4BtLockShmMap(BtLock*, int iChunk, int nByte, u8 **ppOut); /* ** End of bt_lock.c interface. *************************************************************************/ /************************************************************************* | | > | 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 | int sqlite4BtLockShmMap(BtLock*, int iChunk, int nByte, u8 **ppOut); /* ** End of bt_lock.c interface. *************************************************************************/ /************************************************************************* ** Utility functions. */ void sqlite4BtPutU32(u8 *a, u32 i); u32 sqlite4BtGetU32(const u8 *a); void sqlite4BtBufAppendf(sqlite4_buffer *pBuf, const char *zFormat, ...); /* ** End of utility interface. *************************************************************************/ #ifdef NDEBUG # define sqlite4BtDebugReadPage(a,b,c,d) |
︙ | ︙ |
Changes to src/bt_main.c.
︙ | ︙ | |||
27 28 29 30 31 32 33 34 35 36 37 38 39 40 | /* #define BT_STDERR_DEBUG 1 */ struct bt_db { sqlite4_env *pEnv; /* SQLite environment */ BtPager *pPager; /* Underlying page-based database */ bt_cursor *pAllCsr; /* List of all open cursors */ }; typedef struct BtOvfl BtOvfl; struct BtOvfl { int nKey; int nVal; sqlite4_buffer buf; | > | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | /* #define BT_STDERR_DEBUG 1 */ struct bt_db { sqlite4_env *pEnv; /* SQLite environment */ BtPager *pPager; /* Underlying page-based database */ bt_cursor *pAllCsr; /* List of all open cursors */ int bFastInsertOp; /* Set by CONTROL_FAST_INSERT_OP */ }; typedef struct BtOvfl BtOvfl; struct BtOvfl { int nKey; int nVal; sqlite4_buffer buf; |
︙ | ︙ | |||
210 211 212 213 214 215 216 217 218 219 220 221 222 223 | }else{ btCsrSetup(db, pCsr); pCsr->pNextCsr = db->pAllCsr; db->pAllCsr = pCsr; } btCheckPageRefs(db); return rc; } static void btCsrReleaseAll(bt_cursor *pCsr){ int i; for(i=0; i<pCsr->nPg; i++){ sqlite4BtPageRelease(pCsr->apPage[i]); | > | 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 | }else{ btCsrSetup(db, pCsr); pCsr->pNextCsr = db->pAllCsr; db->pAllCsr = pCsr; } btCheckPageRefs(db); db->bFastInsertOp = 0; return rc; } static void btCsrReleaseAll(bt_cursor *pCsr){ int i; for(i=0; i<pCsr->nPg; i++){ sqlite4BtPageRelease(pCsr->apPage[i]); |
︙ | ︙ | |||
347 348 349 350 351 352 353 | return pgno; } /* **************************************************************************/ | | | | | | | | | | | | | | | 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 | return pgno; } /* **************************************************************************/ void sqlite4BtBufAppendf(sqlite4_buffer *pBuf, const char *zFormat, ...){ char *zAppend; va_list ap; va_start(ap, zFormat); zAppend = sqlite4_vmprintf(0, zFormat, ap); va_end(ap); sqlite4_buffer_append(pBuf, zAppend, strlen(zAppend)); sqlite4_free(0, zAppend); } /* ** Append a human-readable interpretation of the b-tree page in aData/nData ** to buffer pBuf. */ static void btPageToAscii(u32 pgno, u8 *aData, int nData, sqlite4_buffer *pBuf){ int i; int nCell = (int)btCellCount(aData, nData); sqlite4BtBufAppendf(pBuf, "Page %d: ", pgno); sqlite4BtBufAppendf(pBuf, "nCell=%d ", nCell); sqlite4BtBufAppendf(pBuf, "iFree=%d ", (int)btFreeOffset(aData, nData)); sqlite4BtBufAppendf(pBuf, "flags=%d ", (int)btFlags(aData)); if( btFlags(aData) & BT_PGFLAGS_INTERNAL ){ sqlite4BtBufAppendf(pBuf, "rchild=%d ", (int)btGetU32(&aData[1])); } sqlite4BtBufAppendf(pBuf, "cell-offsets=("); for(i=0; i<nCell; i++){ u8 *ptr = btCellPtrFind(aData, nData, i); sqlite4BtBufAppendf(pBuf, "%s%d", i==0?"":" ", (int)btGetU16(ptr)); } sqlite4BtBufAppendf(pBuf, ")\n"); for(i=0; i<nCell; i++){ int nKey; int j; u8 *pCell = btCellFind(aData, nData, i); sqlite4BtBufAppendf(pBuf, " Key %d: ", i); pCell += sqlite4BtVarintGet32(pCell, &nKey); for(j=0; j<nKey; j++){ sqlite4BtBufAppendf(pBuf, "%02X", (int)pCell[j]); } if( btFlags(aData) & BT_PGFLAGS_INTERNAL ){ sqlite4BtBufAppendf(pBuf, " child=%d ", (int)btGetU32(&pCell[j])); } sqlite4BtBufAppendf(pBuf, "\n"); } } int sqlite4BtDebugPage(sqlite4_buffer *pBuf, u32 pgno, char *aData, int nData){ btPageToAscii(pgno, (u8*)aData, nData, pBuf); return SQLITE4_OK; } |
︙ | ︙ | |||
2409 2410 2411 2412 2413 2414 2415 | ** Insert a new key/value pair or replace an existing one. */ int sqlite4BtReplace(bt_db *db, const void *pK, int nK, const void *pV, int nV){ int rc = SQLITE4_OK; bt_cursor csr; rc = btSaveAllCursor(db, 0); | > | | < | | | > > | 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 | ** Insert a new key/value pair or replace an existing one. */ int sqlite4BtReplace(bt_db *db, const void *pK, int nK, const void *pV, int nV){ int rc = SQLITE4_OK; bt_cursor csr; rc = btSaveAllCursor(db, 0); assert( rc!=SQLITE4_NOTFOUND && rc!=SQLITE4_INEXACT ); if( rc==SQLITE4_OK ){ sqlite4BtDebugKV((BtLock*)db->pPager, "replace", (u8*)pK, nK, (u8*)pV, nV); btCheckPageRefs(db); btCsrSetup(db, &csr); rc = btCsrSeek(&csr, pK, nK, BT_SEEK_GE, BT_CSRSEEK_UPDATE); } if( rc==SQLITE4_OK ){ /* The cursor currently points to an entry with key pK/nK. This call ** should therefore replace that entry. So delete it and then re-seek ** the cursor. */ rc = sqlite4BtDelete(&csr); if( rc==SQLITE4_OK && nV>=0 ){ |
︙ | ︙ | |||
2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 | if( kv.eType==KV_CELL ){ sqlite4_free(db->pEnv, (void*)kv.pV); } } btCsrReset(&csr, 1); btCheckPageRefs(db); return rc; } /* ** Delete the entry that the cursor currently points to. */ | > | 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 | if( kv.eType==KV_CELL ){ sqlite4_free(db->pEnv, (void*)kv.pV); } } btCsrReset(&csr, 1); btCheckPageRefs(db); db->bFastInsertOp = 0; return rc; } /* ** Delete the entry that the cursor currently points to. */ |
︙ | ︙ | |||
2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 | int sqlite4BtSetCookie(bt_db *db, unsigned int iVal){ return sqlite4BtPagerSetCookie(db->pPager, iVal); } int sqlite4BtGetCookie(bt_db *db, unsigned int *piVal){ return sqlite4BtPagerGetCookie(db->pPager, piVal); } static int btControlInfo(bt_db *db, bt_info *pInfo){ int rc = SQLITE4_OK; switch( pInfo->eType ){ case BT_INFO_PAGEDUMP: { | > > > > > > > > > > > > > > > | | | > > > > > > > > > > | 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 | int sqlite4BtSetCookie(bt_db *db, unsigned int iVal){ return sqlite4BtPagerSetCookie(db->pPager, iVal); } int sqlite4BtGetCookie(bt_db *db, unsigned int *piVal){ return sqlite4BtPagerGetCookie(db->pPager, piVal); } static int btControlTransaction(bt_db *db, int *piCtx){ int rc = SQLITE4_OK; int iTrans = sqlite4BtTransactionLevel(db); if( iTrans==0 ){ rc = sqlite4BtBegin(db, 1); } *piCtx = iTrans; return rc; } static void btControlTransactionDone(bt_db *db, int iCtx){ if( iCtx==0 ) sqlite4BtCommit(db, 0); } static int btControlInfo(bt_db *db, bt_info *pInfo){ int rc = SQLITE4_OK; switch( pInfo->eType ){ case BT_INFO_PAGEDUMP: { int iCtx; /* ControlTransaction() context */ rc = btControlTransaction(db, &iCtx); if( rc==SQLITE4_OK ){ BtPage *pPg = 0; rc = sqlite4BtPageGet(db->pPager, pInfo->pgno, &pPg); if( rc==SQLITE4_OK ){ u8 *aData; int nData; aData = sqlite4BtPageData(pPg); nData = sqlite4BtPagerPagesize(db->pPager); btPageToAscii(pInfo->pgno, aData, nData, &pInfo->output); sqlite4_buffer_append(&pInfo->output, "", 1); sqlite4BtPageRelease(pPg); } btControlTransactionDone(db, iCtx); } break; } case BT_INFO_FILENAME: { const char *zFile; zFile = sqlite4BtPagerFilename(db->pPager, BT_PAGERFILE_DATABASE); rc = sqlite4_buffer_set(&pInfo->output, zFile, strlen(zFile)+1); break; } case BT_INFO_HDRDUMP: { int iCtx; /* ControlTransaction() context */ rc = btControlTransaction(db, &iCtx); if( rc==SQLITE4_OK ){ rc = sqlite4BtPagerHdrdump(db->pPager, &pInfo->output); btControlTransactionDone(db, iCtx); } break; } default: { rc = SQLITE4_ERROR; break; } } return rc; |
︙ | ︙ | |||
2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 | } case BT_CONTROL_CHECKPOINT: { bt_checkpoint *p = (bt_checkpoint*)pArg; rc = sqlite4BtPagerCheckpoint(db->pPager, p); break; } } return rc; } | > > > > > | 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 | } case BT_CONTROL_CHECKPOINT: { bt_checkpoint *p = (bt_checkpoint*)pArg; rc = sqlite4BtPagerCheckpoint(db->pPager, p); break; } case BT_CONTROL_FAST_INSERT_OP: { db->bFastInsertOp = 1; break; } } return rc; } |
Changes to src/bt_pager.c.
︙ | ︙ | |||
1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 | pPager->xLogsize = p->xLogsize; pPager->pLogsizeCtx = p->pCtx; } int sqlite4BtPagerCheckpoint(BtPager *pPager, bt_checkpoint *pCkpt){ int rc; rc = sqlite4BtLogCheckpoint(pPager->pLog, pCkpt->nFrameBuffer); return rc; } #ifndef NDEBUG int sqlite4BtPagerRefcount(BtPager *p){ return p->nTotalRef; } | > > > > > > > > > > > > > > > > > > > > > > > | 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 | pPager->xLogsize = p->xLogsize; pPager->pLogsizeCtx = p->pCtx; } int sqlite4BtPagerCheckpoint(BtPager *pPager, bt_checkpoint *pCkpt){ int rc; rc = sqlite4BtLogCheckpoint(pPager->pLog, pCkpt->nFrameBuffer); return rc; } /* ** It is guaranteed that at least a read-transaction is open when ** this function is called. It appends a text representation of the ** current database header (BtDbHdr) object to the buffer passed as ** the second argument. ** ** An SQLite4 error code is returned if an error (i.e. OOM) occurs, ** or SQLITE4_OK otherwise. */ int sqlite4BtPagerHdrdump(BtPager *pPager, sqlite4_buffer *pBuf){ BtDbHdr *pHdr = pPager->pHdr; int rc = SQLITE4_OK; sqlite4BtBufAppendf(pBuf, "pgsz=%d nPg=%d iRoot=%d" " iCookie=%d iFreePg=%d iFreeBlk=%d", pHdr->pgsz, pHdr->nPg, pHdr->iRoot, pHdr->iCookie, pHdr->iFreePg, pHdr->iFreeBlk ); return rc; } #ifndef NDEBUG int sqlite4BtPagerRefcount(BtPager *p){ return p->nTotalRef; } |
︙ | ︙ |