Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add tests for handling errors returned by xShm VFS methods. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
fbbcacb137e8f5246b88ad09331236aa |
User & Date: | dan 2010-05-06 07:43:58.000 |
Context
2010-05-06
| ||
11:32 | Add test cases to test the libraries handling of corrupt wal-index headers. (check-in: 9465b267d4 user: dan tags: trunk) | |
07:43 | Add tests for handling errors returned by xShm VFS methods. (check-in: fbbcacb137 user: dan tags: trunk) | |
2010-05-05
| ||
20:00 | Change the behavior of the sqlite3_wal_hook() callback. It should now return SQLITE_OK or an error code and the error code is propagated back up the stack. If a checkpoint is desired, the callback should invoke sqlite3_wal_callback() itself. (check-in: 1b14195e05 user: drh tags: trunk) | |
Changes
Changes to src/test_vfs.c.
︙ | ︙ | |||
337 338 339 340 341 342 343 344 345 346 347 348 349 350 | return PARENTVFS(pVfs)->xCurrentTime(PARENTVFS(pVfs), pTimeOut); } static void tvfsGrowBuffer(TestvfsShm *pShm, int reqSize, int *pNewSize){ TestvfsBuffer *pBuffer = pShm->pBuffer; if( reqSize>pBuffer->n ){ pBuffer->a = (u8 *)ckrealloc((char *)pBuffer->a, reqSize); pBuffer->n = reqSize; } *pNewSize = pBuffer->n; } static void tvfsExecTcl( Testvfs *p, | > | 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 | return PARENTVFS(pVfs)->xCurrentTime(PARENTVFS(pVfs), pTimeOut); } static void tvfsGrowBuffer(TestvfsShm *pShm, int reqSize, int *pNewSize){ TestvfsBuffer *pBuffer = pShm->pBuffer; if( reqSize>pBuffer->n ){ pBuffer->a = (u8 *)ckrealloc((char *)pBuffer->a, reqSize); memset(&pBuffer->a[pBuffer->n], 0x55, reqSize-pBuffer->n); pBuffer->n = reqSize; } *pNewSize = pBuffer->n; } static void tvfsExecTcl( Testvfs *p, |
︙ | ︙ | |||
463 464 465 466 467 468 469 | int reqSize, int *pNewSize ){ int rc = SQLITE_OK; Testvfs *p = (Testvfs *)(pVfs->pAppData); TestvfsShm *pShm = (TestvfsShm *)pShmHandle; | < > > > | 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 | int reqSize, int *pNewSize ){ int rc = SQLITE_OK; Testvfs *p = (Testvfs *)(pVfs->pAppData); TestvfsShm *pShm = (TestvfsShm *)pShmHandle; tvfsExecTcl(p, "xShmSize", Tcl_NewStringObj(pShm->pBuffer->zFile, -1), pShm->id, 0 ); tvfsResultCode(p, &rc); if( rc==SQLITE_OK ){ tvfsGrowBuffer(pShm, reqSize, pNewSize); } return rc; } static int tvfsShmGet( sqlite3_vfs *pVfs, sqlite3_shm *pShmHandle, int reqMapSize, |
︙ | ︙ | |||
545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 | int deleteFlag ){ int rc = SQLITE_OK; Testvfs *p = (Testvfs *)(pVfs->pAppData); TestvfsShm *pShm = (TestvfsShm *)pShmHandle; TestvfsBuffer *pBuffer = pShm->pBuffer; assert( (deleteFlag!=0)==(pBuffer->nRef==1) ); tvfsExecTcl(p, "xShmClose", Tcl_NewStringObj(pShm->pBuffer->zFile, -1), pShm->id, 0 ); tvfsResultCode(p, &rc); pBuffer->nRef--; | > > | 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 | int deleteFlag ){ int rc = SQLITE_OK; Testvfs *p = (Testvfs *)(pVfs->pAppData); TestvfsShm *pShm = (TestvfsShm *)pShmHandle; TestvfsBuffer *pBuffer = pShm->pBuffer; #if 0 assert( (deleteFlag!=0)==(pBuffer->nRef==1) ); #endif tvfsExecTcl(p, "xShmClose", Tcl_NewStringObj(pShm->pBuffer->zFile, -1), pShm->id, 0 ); tvfsResultCode(p, &rc); pBuffer->nRef--; |
︙ | ︙ | |||
755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 | pVfs = (sqlite3_vfs *)ckalloc(sizeof(sqlite3_vfs)); memcpy(pVfs, &tvfs_vfs, sizeof(sqlite3_vfs)); pVfs->pAppData = (void *)p; pVfs->zName = p->zName; pVfs->mxPathname = p->pParent->mxPathname; pVfs->szOsFile += p->pParent->szOsFile; Tcl_CreateObjCommand(interp, zVfs, testvfs_obj_cmd, p, testvfs_obj_del); sqlite3_vfs_register(pVfs, 0); return TCL_OK; } int Sqlitetestvfs_Init(Tcl_Interp *interp){ Tcl_CreateObjCommand(interp, "testvfs", testvfs_cmd, 0, 0); return TCL_OK; } #endif | > | 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 | pVfs = (sqlite3_vfs *)ckalloc(sizeof(sqlite3_vfs)); memcpy(pVfs, &tvfs_vfs, sizeof(sqlite3_vfs)); pVfs->pAppData = (void *)p; pVfs->zName = p->zName; pVfs->mxPathname = p->pParent->mxPathname; pVfs->szOsFile += p->pParent->szOsFile; p->pVfs = pVfs; Tcl_CreateObjCommand(interp, zVfs, testvfs_obj_cmd, p, testvfs_obj_del); sqlite3_vfs_register(pVfs, 0); return TCL_OK; } int Sqlitetestvfs_Init(Tcl_Interp *interp){ Tcl_CreateObjCommand(interp, "testvfs", testvfs_cmd, 0, 0); return TCL_OK; } #endif |
Changes to src/wal.c.
︙ | ︙ | |||
666 667 668 669 670 671 672 | nBlock = 256; } *piPage = iRet; return (iRet==0xFFFFFFFF); } | | > | > > > > > > | 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 | nBlock = 256; } *piPage = iRet; return (iRet==0xFFFFFFFF); } static int walIteratorInit(Wal *pWal, WalIterator **pp){ u32 *aData; /* Content of the wal-index file */ WalIterator *p; /* Return value */ int nSegment; /* Number of segments to merge */ u32 iLast; /* Last frame in log */ int nByte; /* Number of bytes to allocate */ int i; /* Iterator variable */ int nFinal; /* Number of unindexed entries */ struct WalSegment *pFinal; /* Final (unindexed) segment */ u8 *aTmp; /* Temp space used by merge-sort */ int rc; /* Return code of walIndexMap() */ rc = walIndexMap(pWal, -1); if( rc!=SQLITE_OK ){ return rc; } aData = pWal->pWiData; iLast = pWal->hdr.iLastPg; nSegment = (iLast >> 8) + 1; nFinal = (iLast & 0x000000FF); nByte = sizeof(WalIterator) + (nSegment-1)*sizeof(struct WalSegment) + 512; p = (WalIterator *)sqlite3_malloc(nByte); if( !p ){ return SQLITE_NOMEM; } if( p ){ memset(p, 0, nByte); p->nSegment = nSegment; for(i=0; i<nSegment-1; i++){ p->aSegment[i].aDbPage = &aData[walIndexEntry(i*256+1)]; |
︙ | ︙ | |||
706 707 708 709 710 711 712 | for(i=0; i<nFinal; i++){ pFinal->aIndex[i] = i; } walMergesort8(pFinal->aDbPage, aTmp, pFinal->aIndex, &nFinal); p->nFinal = nFinal; } | > | | 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 | for(i=0; i<nFinal; i++){ pFinal->aIndex[i] = i; } walMergesort8(pFinal->aDbPage, aTmp, pFinal->aIndex, &nFinal); p->nFinal = nFinal; } *pp = p; return SQLITE_OK; } /* ** Free a log iterator allocated by walIteratorInit(). */ static void walIteratorFree(WalIterator *p){ sqlite3_free(p); |
︙ | ︙ | |||
733 734 735 736 737 738 739 | int rc; /* Return code */ int pgsz = pWal->hdr.pgsz; /* Database page-size */ WalIterator *pIter = 0; /* Wal iterator context */ u32 iDbpage = 0; /* Next database page to write */ u32 iFrame = 0; /* Wal frame containing data for iDbpage */ /* Allocate the iterator */ | | < < | < | 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 | int rc; /* Return code */ int pgsz = pWal->hdr.pgsz; /* Database page-size */ WalIterator *pIter = 0; /* Wal iterator context */ u32 iDbpage = 0; /* Next database page to write */ u32 iFrame = 0; /* Wal frame containing data for iDbpage */ /* Allocate the iterator */ rc = walIteratorInit(pWal, &pIter); if( rc!=SQLITE_OK || pWal->hdr.iLastPg==0 ){ goto out; } if( pWal->hdr.pgsz!=nBuf ){ rc = SQLITE_CORRUPT_BKPT; goto out; } |
︙ | ︙ |
Changes to test/walfault.test.
︙ | ︙ | |||
49 50 51 52 53 54 55 | sqlite3_extended_result_codes db 1 sqlite3_db_config_lookaside db 0 0 0 } -sqlbody { SELECT count(*) FROM x; } # A [testvfs] callback for the VFS created by [do_shmfault_test]. This | | > > | < < > | < < < > > > > > > > > > > > > > > > < | | < | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 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 | sqlite3_extended_result_codes db 1 sqlite3_db_config_lookaside db 0 0 0 } -sqlbody { SELECT count(*) FROM x; } # A [testvfs] callback for the VFS created by [do_shmfault_test]. This # callback injects SQLITE_IOERR faults into methods for which an entry # in array ::shmfault_ioerr_methods is defined. For example, to enable # errors in xShmOpen: # # set ::shmfault_ioerr_methods(xShmOpen) 1 # # Faults are not injected into xShmRelease, xShmClose or xShmLock method # calls. The global tcl variables used are: # # $::shmfault_ioerr_countdown # $::shmfault_ioerr_persist # $::shmfault_ioerr_methods # proc shmfault_vfs_cb {method args} { # If ::shmfault_ioerr_countdown is not set, always return SQLITE_OK. # if {[info exists ::shmfault_ioerr_countdown]==0} { return SQLITE_OK } if {[info exists ::shmfault_ioerr_methods($method)]} { incr ::shmfault_ioerr_countdown -1 if { ($::shmfault_ioerr_countdown==0) || ($::shmfault_ioerr_countdown<=0 && $::shmfault_ioerr_persist) } { return SQLITE_IOERR } } return SQLITE_OK } # Options are: # # -tclprep TCL # -sqlprep SQL # -sqlbody SQL # proc do_shmfault_test {name args} { set A(-tclprep) "sqlite3 db test.db -vfs shmfault" set A(-sqlprep) "" set A(-sqlbody) "" set A(-methods) [list xShmGet xShmOpen xShmSize] array set A $args # Create a VFS to use: testvfs shmfault shmfault_vfs_cb unset -nocomplain ::shmfault_ioerr_methods foreach m $A(-methods) { set ::shmfault_ioerr_methods($m) 1 } foreach mode {transient persistent} { set ::shmfault_ioerr_persist [expr {$mode == "persistent"}] for {set nDelay 1} {$nDelay < 10000} {incr nDelay} { file delete -force test.db test.db-wal test.db-journal eval $A(-tclprep) db eval $A(-sqlprep) set ::shmfault_ioerr_countdown $nDelay set rc [catch { db eval $A(-sqlbody) } msg] set hit_error [expr {$::shmfault_ioerr_countdown<=0}] unset ::shmfault_ioerr_countdown catch { db close } do_test $name-$mode.$nDelay.1 [list set {} $hit_error] $rc if {$hit_error==0} break } } shmfault delete } do_shmfault_test walfault-shm-1 -sqlbody { PRAGMA journal_mode = WAL; CREATE TABLE t1(a PRIMARY KEY, b); INSERT INTO t1 VALUES('a', 'b'); PRAGMA wal_checkpoint; } do_shmfault_test walfault-shm-2 -methods xShmSize -sqlprep { PRAGMA page_size = 512; PRAGMA journal_mode = WAL; PRAGMA wal_autocheckpoint = 0; } -sqlbody { CREATE TABLE t1(x); BEGIN; INSERT INTO t1 VALUES(randomblob(400)); /* 1 */ INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 2 */ INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 4 */ INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 8 */ INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 16 */ INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 32 */ INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 64 */ INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 128 */ INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 256 */ INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 512 */ INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 1024 */ INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 2048 */ INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 4096 */ INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 8192 */ INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 16384 */ COMMIT; } do_shmfault_test walfault-shm-3 -methods xShmSize -tclprep { sqlite3 db test.db -vfs shmfault unset -nocomplain ::shmfault_ioerr_countdown db eval { PRAGMA page_size = 512; PRAGMA journal_mode = WAL; PRAGMA wal_autocheckpoint = 0; CREATE TABLE t1(x); BEGIN; INSERT INTO t1 VALUES(randomblob(400)); /* 1 */ INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 2 */ INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 4 */ INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 8 */ INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 16 */ INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 32 */ INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 64 */ INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 128 */ INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 256 */ INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 512 */ INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 1024 */ INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 2048 */ INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 4096 */ INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 8192 */ INSERT INTO t1 SELECT randomblob(400) FROM t1; /* 16384 */ COMMIT; } set ::shmfault_ioerr_countdown 1 set ::shmfault_ioerr_methods(xShmGet) 1 db close unset ::shmfault_ioerr_methods(xShmGet) if {[file exists test.db-wal]==0} {error "Failed to create WAL file!"} sqlite3 db test.db -vfs shmfault breakpoint } -sqlbody { SELECT count(*) FROM t1; } finish_test |