Overview
| SHA1 Hash: | 26e235b7a4cd4d0dc9725774d70174c4d369cb98 |
|---|---|
| Date: | 2013-02-25 13:31:30 |
| User: | dan |
| Comment: | Merge the incr-vacuum-opt branch with the trunk. |
Tags And Properties
- branch=trunk inherited from [704b122e53]
- sym-trunk inherited from [704b122e53]
Changes
Changes to src/backup.c
458 if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){ 458 if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){ 459 nDestTruncate--; 459 nDestTruncate--; 460 } 460 } 461 }else{ 461 }else{ 462 nDestTruncate = nSrcPage * (pgszSrc/pgszDest); 462 nDestTruncate = nSrcPage * (pgszSrc/pgszDest); 463 } 463 } 464 assert( nDestTruncate>0 ); 464 assert( nDestTruncate>0 ); 465 sqlite3PagerTruncateImage(pDestPager, nDestTruncate); < 466 465 467 if( pgszSrc<pgszDest ){ 466 if( pgszSrc<pgszDest ){ 468 /* If the source page-size is smaller than the destination page-size, 467 /* If the source page-size is smaller than the destination page-size, 469 ** two extra things may need to happen: 468 ** two extra things may need to happen: 470 ** 469 ** 471 ** * The destination may need to be truncated, and 470 ** * The destination may need to be truncated, and 472 ** 471 ** 473 ** * Data stored on the pages immediately following the 472 ** * Data stored on the pages immediately following the 474 ** pending-byte page in the source database may need to be 473 ** pending-byte page in the source database may need to be 475 ** copied into the destination database. 474 ** copied into the destination database. 476 */ 475 */ 477 const i64 iSize = (i64)pgszSrc * (i64)nSrcPage; 476 const i64 iSize = (i64)pgszSrc * (i64)nSrcPage; 478 sqlite3_file * const pFile = sqlite3PagerFile(pDestPager); 477 sqlite3_file * const pFile = sqlite3PagerFile(pDestPager); > 478 Pgno iPg; > 479 int nDstPage; 479 i64 iOff; 480 i64 iOff; 480 i64 iEnd; 481 i64 iEnd; 481 482 482 assert( pFile ); 483 assert( pFile ); 483 assert( nDestTruncate==0 484 assert( nDestTruncate==0 484 || (i64)nDestTruncate*(i64)pgszDest >= iSize || ( 485 || (i64)nDestTruncate*(i64)pgszDest >= iSize || ( 485 nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1) 486 nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1) 486 && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest 487 && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest 487 )); 488 )); 488 489 489 /* This call ensures that all data required to recreate the original | 490 /* This block ensures that all data required to recreate the original 490 ** database has been stored in the journal for pDestPager and the 491 ** database has been stored in the journal for pDestPager and the 491 ** journal synced to disk. So at this point we may safely modify 492 ** journal synced to disk. So at this point we may safely modify 492 ** the database file in any way, knowing that if a power failure 493 ** the database file in any way, knowing that if a power failure 493 ** occurs, the original database will be reconstructed from the 494 ** occurs, the original database will be reconstructed from the 494 ** journal file. */ 495 ** journal file. */ > 496 sqlite3PagerPagecount(pDestPager, &nDstPage); > 497 for(iPg=nDestTruncate; rc==SQLITE_OK && iPg<=(Pgno)nDstPage; iPg++){ > 498 if( iPg!=PENDING_BYTE_PAGE(p->pDest->pBt) ){ > 499 DbPage *pPg; > 500 rc = sqlite3PagerGet(pDestPager, iPg, &pPg); > 501 if( rc==SQLITE_OK ){ > 502 rc = sqlite3PagerWrite(pPg); > 503 sqlite3PagerUnref(pPg); > 504 } > 505 } > 506 } > 507 if( rc==SQLITE_OK ){ 495 rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1); | 508 rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1); > 509 } 496 510 497 /* Write the extra pages and truncate the database file as required */ 511 /* Write the extra pages and truncate the database file as required */ 498 iEnd = MIN(PENDING_BYTE + pgszDest, iSize); 512 iEnd = MIN(PENDING_BYTE + pgszDest, iSize); 499 for( 513 for( 500 iOff=PENDING_BYTE+pgszSrc; 514 iOff=PENDING_BYTE+pgszSrc; 501 rc==SQLITE_OK && iOff<iEnd; 515 rc==SQLITE_OK && iOff<iEnd; 502 iOff+=pgszSrc 516 iOff+=pgszSrc ................................................................................................................................................................................ 515 } 529 } 516 530 517 /* Sync the database file to disk. */ 531 /* Sync the database file to disk. */ 518 if( rc==SQLITE_OK ){ 532 if( rc==SQLITE_OK ){ 519 rc = sqlite3PagerSync(pDestPager); 533 rc = sqlite3PagerSync(pDestPager); 520 } 534 } 521 }else{ 535 }else{ > 536 sqlite3PagerTruncateImage(pDestPager, nDestTruncate); 522 rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0); 537 rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0); 523 } 538 } 524 539 525 /* Finish committing the transaction to the destination database. */ 540 /* Finish committing the transaction to the destination database. */ 526 if( SQLITE_OK==rc 541 if( SQLITE_OK==rc 527 && SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(p->pDest, 0)) 542 && SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(p->pDest, 0)) 528 ){ 543 ){
Changes to src/btree.c
2591 /* If the btree is already in a write-transaction, or it 2591 /* If the btree is already in a write-transaction, or it 2592 ** is already in a read-transaction and a read-transaction 2592 ** is already in a read-transaction and a read-transaction 2593 ** is requested, this is a no-op. 2593 ** is requested, this is a no-op. 2594 */ 2594 */ 2595 if( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){ 2595 if( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){ 2596 goto trans_begun; 2596 goto trans_begun; 2597 } 2597 } > 2598 assert( pBt->bDoTruncate==0 ); 2598 2599 2599 /* Write transactions are not possible on a read-only database */ 2600 /* Write transactions are not possible on a read-only database */ 2600 if( (pBt->btsFlags & BTS_READ_ONLY)!=0 && wrflag ){ 2601 if( (pBt->btsFlags & BTS_READ_ONLY)!=0 && wrflag ){ 2601 rc = SQLITE_READONLY; 2602 rc = SQLITE_READONLY; 2602 goto trans_begun; 2603 goto trans_begun; 2603 } 2604 } 2604 2605 ................................................................................................................................................................................ 2905 } 2906 } 2906 } 2907 } 2907 return rc; 2908 return rc; 2908 } 2909 } 2909 2910 2910 /* Forward declaration required by incrVacuumStep(). */ 2911 /* Forward declaration required by incrVacuumStep(). */ 2911 static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8); 2912 static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8); > 2913 #define BTALLOC_ANY 0 /* Allocate any page */ > 2914 #define BTALLOC_EXACT 1 /* Allocate exact page if possible */ > 2915 #define BTALLOC_LE 2 /* Allocate any page <= the parameter */ 2912 2916 2913 /* 2917 /* 2914 ** Perform a single step of an incremental-vacuum. If successful, | 2918 ** Perform a single step of an incremental-vacuum. If successful, return 2915 ** return SQLITE_OK. If there is no work to do (and therefore no | 2919 ** SQLITE_OK. If there is no work to do (and therefore no point in 2916 ** point in calling this function again), return SQLITE_DONE. | 2920 ** calling this function again), return SQLITE_DONE. Or, if an error > 2921 ** occurs, return some other error code. 2917 ** 2922 ** 2918 ** More specificly, this function attempts to re-organize the | 2923 ** More specificly, this function attempts to re-organize the database so 2919 ** database so that the last page of the file currently in use | 2924 ** that the last page of the file currently in use is no longer in use. 2920 ** is no longer in use. < 2921 ** 2925 ** > 2926 ** Parameter nFin is the number of pages that this database would contain > 2927 ** were this function called until it returns SQLITE_DONE. > 2928 ** 2922 ** If the nFin parameter is non-zero, this function assumes | 2929 ** If the bCommit parameter is non-zero, this function assumes that the 2923 ** that the caller will keep calling incrVacuumStep() until | 2930 ** caller will keep calling incrVacuumStep() until it returns SQLITE_DONE 2924 ** it returns SQLITE_DONE or an error, and that nFin is the < 2925 ** number of pages the database file will contain after this < 2926 ** process is complete. If nFin is zero, it is assumed that < 2927 ** incrVacuumStep() will be called a finite amount of times < 2928 ** which may or may not empty the freelist. A full autovacuum < 2929 ** has nFin>0. A "PRAGMA incremental_vacuum" has nFin==0. < > 2931 ** or an error. bCommit is passed true for an auto-vacuum-on-commmit > 2932 ** operation, or false for an incremental vacuum. 2930 */ 2933 */ 2931 static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){ | 2934 static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){ 2932 Pgno nFreeList; /* Number of pages still on the free-list */ 2935 Pgno nFreeList; /* Number of pages still on the free-list */ 2933 int rc; 2936 int rc; 2934 2937 2935 assert( sqlite3_mutex_held(pBt->mutex) ); 2938 assert( sqlite3_mutex_held(pBt->mutex) ); 2936 assert( iLastPg>nFin ); 2939 assert( iLastPg>nFin ); 2937 2940 2938 if( !PTRMAP_ISPAGE(pBt, iLastPg) && iLastPg!=PENDING_BYTE_PAGE(pBt) ){ 2941 if( !PTRMAP_ISPAGE(pBt, iLastPg) && iLastPg!=PENDING_BYTE_PAGE(pBt) ){ ................................................................................................................................................................................ 2949 return rc; 2952 return rc; 2950 } 2953 } 2951 if( eType==PTRMAP_ROOTPAGE ){ 2954 if( eType==PTRMAP_ROOTPAGE ){ 2952 return SQLITE_CORRUPT_BKPT; 2955 return SQLITE_CORRUPT_BKPT; 2953 } 2956 } 2954 2957 2955 if( eType==PTRMAP_FREEPAGE ){ 2958 if( eType==PTRMAP_FREEPAGE ){ 2956 if( nFin==0 ){ | 2959 if( bCommit==0 ){ 2957 /* Remove the page from the files free-list. This is not required 2960 /* Remove the page from the files free-list. This is not required 2958 ** if nFin is non-zero. In that case, the free-list will be | 2961 ** if bCommit is non-zero. In that case, the free-list will be 2959 ** truncated to zero after this function returns, so it doesn't 2962 ** truncated to zero after this function returns, so it doesn't 2960 ** matter if it still contains some garbage entries. 2963 ** matter if it still contains some garbage entries. 2961 */ 2964 */ 2962 Pgno iFreePg; 2965 Pgno iFreePg; 2963 MemPage *pFreePg; 2966 MemPage *pFreePg; 2964 rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iLastPg, 1); | 2967 rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iLastPg, BTALLOC_EXACT); 2965 if( rc!=SQLITE_OK ){ 2968 if( rc!=SQLITE_OK ){ 2966 return rc; 2969 return rc; 2967 } 2970 } 2968 assert( iFreePg==iLastPg ); 2971 assert( iFreePg==iLastPg ); 2969 releasePage(pFreePg); 2972 releasePage(pFreePg); 2970 } 2973 } 2971 } else { 2974 } else { 2972 Pgno iFreePg; /* Index of free page to move pLastPg to */ 2975 Pgno iFreePg; /* Index of free page to move pLastPg to */ 2973 MemPage *pLastPg; 2976 MemPage *pLastPg; > 2977 u8 eMode = BTALLOC_ANY; /* Mode parameter for allocateBtreePage() */ > 2978 Pgno iNear = 0; /* nearby parameter for allocateBtreePage() */ 2974 2979 2975 rc = btreeGetPage(pBt, iLastPg, &pLastPg, 0); 2980 rc = btreeGetPage(pBt, iLastPg, &pLastPg, 0); 2976 if( rc!=SQLITE_OK ){ 2981 if( rc!=SQLITE_OK ){ 2977 return rc; 2982 return rc; 2978 } 2983 } 2979 2984 2980 /* If nFin is zero, this loop runs exactly once and page pLastPg | 2985 /* If bCommit is zero, this loop runs exactly once and page pLastPg 2981 ** is swapped with the first free page pulled off the free list. 2986 ** is swapped with the first free page pulled off the free list. 2982 ** 2987 ** 2983 ** On the other hand, if nFin is greater than zero, then keep | 2988 ** On the other hand, if bCommit is greater than zero, then keep 2984 ** looping until a free-page located within the first nFin pages 2989 ** looping until a free-page located within the first nFin pages 2985 ** of the file is found. 2990 ** of the file is found. 2986 */ 2991 */ > 2992 if( bCommit==0 ){ > 2993 eMode = BTALLOC_LE; > 2994 iNear = nFin; > 2995 } 2987 do { 2996 do { 2988 MemPage *pFreePg; 2997 MemPage *pFreePg; 2989 rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, 0, 0); | 2998 rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iNear, eMode); 2990 if( rc!=SQLITE_OK ){ 2999 if( rc!=SQLITE_OK ){ 2991 releasePage(pLastPg); 3000 releasePage(pLastPg); 2992 return rc; 3001 return rc; 2993 } 3002 } 2994 releasePage(pFreePg); 3003 releasePage(pFreePg); 2995 }while( nFin!=0 && iFreePg>nFin ); | 3004 }while( bCommit && iFreePg>nFin ); 2996 assert( iFreePg<iLastPg ); 3005 assert( iFreePg<iLastPg ); 2997 3006 2998 rc = sqlite3PagerWrite(pLastPg->pDbPage); < 2999 if( rc==SQLITE_OK ){ < 3000 rc = relocatePage(pBt, pLastPg, eType, iPtrPage, iFreePg, nFin!=0); | 3007 rc = relocatePage(pBt, pLastPg, eType, iPtrPage, iFreePg, nFin!=0); 3001 } < 3002 releasePage(pLastPg); 3008 releasePage(pLastPg); 3003 if( rc!=SQLITE_OK ){ 3009 if( rc!=SQLITE_OK ){ 3004 return rc; 3010 return rc; 3005 } 3011 } 3006 } 3012 } 3007 } 3013 } 3008 3014 3009 if( nFin==0 ){ | 3015 if( bCommit==0 ){ > 3016 do { 3010 iLastPg--; | 3017 iLastPg--; 3011 while( iLastPg==PENDING_BYTE_PAGE(pBt)||PTRMAP_ISPAGE(pBt, iLastPg) ){ < 3012 if( PTRMAP_ISPAGE(pBt, iLastPg) ){ | 3018 }while( iLastPg==PENDING_BYTE_PAGE(pBt) || PTRMAP_ISPAGE(pBt, iLastPg) ); 3013 MemPage *pPg; | 3019 pBt->bDoTruncate = 1; 3014 rc = btreeGetPage(pBt, iLastPg, &pPg, 0); < 3015 if( rc!=SQLITE_OK ){ < 3016 return rc; < 3017 } < 3018 rc = sqlite3PagerWrite(pPg->pDbPage); < 3019 releasePage(pPg); < 3020 if( rc!=SQLITE_OK ){ < 3021 return rc; < 3022 } < 3023 } < 3024 iLastPg--; < 3025 } < 3026 sqlite3PagerTruncateImage(pBt->pPager, iLastPg); < 3027 pBt->nPage = iLastPg; 3020 pBt->nPage = iLastPg; 3028 } 3021 } 3029 return SQLITE_OK; 3022 return SQLITE_OK; 3030 } 3023 } > 3024 > 3025 /* > 3026 ** The database opened by the first argument is an auto-vacuum database > 3027 ** nOrig pages in size containing nFree free pages. Return the expected > 3028 ** size of the database in pages following an auto-vacuum operation. > 3029 */ > 3030 static Pgno finalDbSize(BtShared *pBt, Pgno nOrig, Pgno nFree){ > 3031 int nEntry; /* Number of entries on one ptrmap page */ > 3032 Pgno nPtrmap; /* Number of PtrMap pages to be freed */ > 3033 Pgno nFin; /* Return value */ > 3034 > 3035 nEntry = pBt->usableSize/5; > 3036 nPtrmap = (nFree-nOrig+PTRMAP_PAGENO(pBt, nOrig)+nEntry)/nEntry; > 3037 nFin = nOrig - nFree - nPtrmap; > 3038 if( nOrig>PENDING_BYTE_PAGE(pBt) && nFin<PENDING_BYTE_PAGE(pBt) ){ > 3039 nFin--; > 3040 } > 3041 while( PTRMAP_ISPAGE(pBt, nFin) || nFin==PENDING_BYTE_PAGE(pBt) ){ > 3042 nFin--; > 3043 } > 3044 > 3045 return nFin; > 3046 } 3031 3047 3032 /* 3048 /* 3033 ** A write-transaction must be opened before calling this function. 3049 ** A write-transaction must be opened before calling this function. 3034 ** It performs a single unit of work towards an incremental vacuum. 3050 ** It performs a single unit of work towards an incremental vacuum. 3035 ** 3051 ** 3036 ** If the incremental vacuum is finished after this function has run, 3052 ** If the incremental vacuum is finished after this function has run, 3037 ** SQLITE_DONE is returned. If it is not finished, but no error occurred, 3053 ** SQLITE_DONE is returned. If it is not finished, but no error occurred, ................................................................................................................................................................................ 3042 BtShared *pBt = p->pBt; 3058 BtShared *pBt = p->pBt; 3043 3059 3044 sqlite3BtreeEnter(p); 3060 sqlite3BtreeEnter(p); 3045 assert( pBt->inTransaction==TRANS_WRITE && p->inTrans==TRANS_WRITE ); 3061 assert( pBt->inTransaction==TRANS_WRITE && p->inTrans==TRANS_WRITE ); 3046 if( !pBt->autoVacuum ){ 3062 if( !pBt->autoVacuum ){ 3047 rc = SQLITE_DONE; 3063 rc = SQLITE_DONE; 3048 }else{ 3064 }else{ > 3065 Pgno nOrig = btreePagecount(pBt); > 3066 Pgno nFree = get4byte(&pBt->pPage1->aData[36]); > 3067 Pgno nFin = finalDbSize(pBt, nOrig, nFree); > 3068 > 3069 if( nOrig<nFin ){ > 3070 rc = SQLITE_CORRUPT_BKPT; > 3071 }else if( nFree>0 ){ 3049 invalidateAllOverflowCache(pBt); | 3072 invalidateAllOverflowCache(pBt); 3050 rc = incrVacuumStep(pBt, 0, btreePagecount(pBt)); | 3073 rc = incrVacuumStep(pBt, nFin, nOrig, 0); 3051 if( rc==SQLITE_OK ){ | 3074 if( rc==SQLITE_OK ){ 3052 rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); | 3075 rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); 3053 put4byte(&pBt->pPage1->aData[28], pBt->nPage); | 3076 put4byte(&pBt->pPage1->aData[28], pBt->nPage); > 3077 } > 3078 }else{ > 3079 rc = SQLITE_DONE; 3054 } 3080 } 3055 } 3081 } 3056 sqlite3BtreeLeave(p); 3082 sqlite3BtreeLeave(p); 3057 return rc; 3083 return rc; 3058 } 3084 } 3059 3085 3060 /* 3086 /* ................................................................................................................................................................................ 3073 3099 3074 assert( sqlite3_mutex_held(pBt->mutex) ); 3100 assert( sqlite3_mutex_held(pBt->mutex) ); 3075 invalidateAllOverflowCache(pBt); 3101 invalidateAllOverflowCache(pBt); 3076 assert(pBt->autoVacuum); 3102 assert(pBt->autoVacuum); 3077 if( !pBt->incrVacuum ){ 3103 if( !pBt->incrVacuum ){ 3078 Pgno nFin; /* Number of pages in database after autovacuuming */ 3104 Pgno nFin; /* Number of pages in database after autovacuuming */ 3079 Pgno nFree; /* Number of pages on the freelist initially */ 3105 Pgno nFree; /* Number of pages on the freelist initially */ 3080 Pgno nPtrmap; /* Number of PtrMap pages to be freed */ < 3081 Pgno iFree; /* The next page to be freed */ 3106 Pgno iFree; /* The next page to be freed */ 3082 int nEntry; /* Number of entries on one ptrmap page */ < 3083 Pgno nOrig; /* Database size before freeing */ 3107 Pgno nOrig; /* Database size before freeing */ 3084 3108 3085 nOrig = btreePagecount(pBt); 3109 nOrig = btreePagecount(pBt); 3086 if( PTRMAP_ISPAGE(pBt, nOrig) || nOrig==PENDING_BYTE_PAGE(pBt) ){ 3110 if( PTRMAP_ISPAGE(pBt, nOrig) || nOrig==PENDING_BYTE_PAGE(pBt) ){ 3087 /* It is not possible to create a database for which the final page 3111 /* It is not possible to create a database for which the final page 3088 ** is either a pointer-map page or the pending-byte page. If one 3112 ** is either a pointer-map page or the pending-byte page. If one 3089 ** is encountered, this indicates corruption. 3113 ** is encountered, this indicates corruption. 3090 */ 3114 */ 3091 return SQLITE_CORRUPT_BKPT; 3115 return SQLITE_CORRUPT_BKPT; 3092 } 3116 } 3093 3117 3094 nFree = get4byte(&pBt->pPage1->aData[36]); 3118 nFree = get4byte(&pBt->pPage1->aData[36]); 3095 nEntry = pBt->usableSize/5; | 3119 nFin = finalDbSize(pBt, nOrig, nFree); 3096 nPtrmap = (nFree-nOrig+PTRMAP_PAGENO(pBt, nOrig)+nEntry)/nEntry; < 3097 nFin = nOrig - nFree - nPtrmap; < 3098 if( nOrig>PENDING_BYTE_PAGE(pBt) && nFin<PENDING_BYTE_PAGE(pBt) ){ < 3099 nFin--; < 3100 } < 3101 while( PTRMAP_ISPAGE(pBt, nFin) || nFin==PENDING_BYTE_PAGE(pBt) ){ < 3102 nFin--; < 3103 } < 3104 if( nFin>nOrig ) return SQLITE_CORRUPT_BKPT; 3120 if( nFin>nOrig ) return SQLITE_CORRUPT_BKPT; 3105 3121 3106 for(iFree=nOrig; iFree>nFin && rc==SQLITE_OK; iFree--){ 3122 for(iFree=nOrig; iFree>nFin && rc==SQLITE_OK; iFree--){ 3107 rc = incrVacuumStep(pBt, nFin, iFree); | 3123 rc = incrVacuumStep(pBt, nFin, iFree, 1); 3108 } 3124 } 3109 if( (rc==SQLITE_DONE || rc==SQLITE_OK) && nFree>0 ){ 3125 if( (rc==SQLITE_DONE || rc==SQLITE_OK) && nFree>0 ){ 3110 rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); 3126 rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); 3111 put4byte(&pBt->pPage1->aData[32], 0); 3127 put4byte(&pBt->pPage1->aData[32], 0); 3112 put4byte(&pBt->pPage1->aData[36], 0); 3128 put4byte(&pBt->pPage1->aData[36], 0); 3113 put4byte(&pBt->pPage1->aData[28], nFin); 3129 put4byte(&pBt->pPage1->aData[28], nFin); 3114 sqlite3PagerTruncateImage(pBt->pPager, nFin); | 3130 pBt->bDoTruncate = 1; 3115 pBt->nPage = nFin; 3131 pBt->nPage = nFin; 3116 } 3132 } 3117 if( rc!=SQLITE_OK ){ 3133 if( rc!=SQLITE_OK ){ 3118 sqlite3PagerRollback(pPager); 3134 sqlite3PagerRollback(pPager); 3119 } 3135 } 3120 } 3136 } 3121 3137 ................................................................................................................................................................................ 3162 if( pBt->autoVacuum ){ 3178 if( pBt->autoVacuum ){ 3163 rc = autoVacuumCommit(pBt); 3179 rc = autoVacuumCommit(pBt); 3164 if( rc!=SQLITE_OK ){ 3180 if( rc!=SQLITE_OK ){ 3165 sqlite3BtreeLeave(p); 3181 sqlite3BtreeLeave(p); 3166 return rc; 3182 return rc; 3167 } 3183 } 3168 } 3184 } > 3185 if( pBt->bDoTruncate ){ > 3186 sqlite3PagerTruncateImage(pBt->pPager, pBt->nPage); > 3187 } 3169 #endif 3188 #endif 3170 rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zMaster, 0); 3189 rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zMaster, 0); 3171 sqlite3BtreeLeave(p); 3190 sqlite3BtreeLeave(p); 3172 } 3191 } 3173 return rc; 3192 return rc; 3174 } 3193 } 3175 3194 ................................................................................................................................................................................ 3177 ** This function is called from both BtreeCommitPhaseTwo() and BtreeRollback() 3196 ** This function is called from both BtreeCommitPhaseTwo() and BtreeRollback() 3178 ** at the conclusion of a transaction. 3197 ** at the conclusion of a transaction. 3179 */ 3198 */ 3180 static void btreeEndTransaction(Btree *p){ 3199 static void btreeEndTransaction(Btree *p){ 3181 BtShared *pBt = p->pBt; 3200 BtShared *pBt = p->pBt; 3182 assert( sqlite3BtreeHoldsMutex(p) ); 3201 assert( sqlite3BtreeHoldsMutex(p) ); 3183 3202 > 3203 #ifndef SQLITE_OMIT_AUTOVACUUM > 3204 pBt->bDoTruncate = 0; > 3205 #endif 3184 btreeClearHasContent(pBt); 3206 btreeClearHasContent(pBt); 3185 if( p->inTrans>TRANS_NONE && p->db->activeVdbeCnt>1 ){ 3207 if( p->inTrans>TRANS_NONE && p->db->activeVdbeCnt>1 ){ 3186 /* If there are other active statements that belong to this database 3208 /* If there are other active statements that belong to this database 3187 ** handle, downgrade to a read-only transaction. The other statements 3209 ** handle, downgrade to a read-only transaction. The other statements 3188 ** may still be reading from the database. */ 3210 ** may still be reading from the database. */ 3189 downgradeAllSharedCacheTableLocks(p); 3211 downgradeAllSharedCacheTableLocks(p); 3190 p->inTrans = TRANS_READ; 3212 p->inTrans = TRANS_READ; ................................................................................................................................................................................ 4863 ** is only used by auto-vacuum databases when allocating a new table. 4885 ** is only used by auto-vacuum databases when allocating a new table. 4864 */ 4886 */ 4865 static int allocateBtreePage( 4887 static int allocateBtreePage( 4866 BtShared *pBt, 4888 BtShared *pBt, 4867 MemPage **ppPage, 4889 MemPage **ppPage, 4868 Pgno *pPgno, 4890 Pgno *pPgno, 4869 Pgno nearby, 4891 Pgno nearby, 4870 u8 exact | 4892 u8 eMode 4871 ){ 4893 ){ 4872 MemPage *pPage1; 4894 MemPage *pPage1; 4873 int rc; 4895 int rc; 4874 u32 n; /* Number of pages on the freelist */ 4896 u32 n; /* Number of pages on the freelist */ 4875 u32 k; /* Number of leaves on the trunk of the freelist */ 4897 u32 k; /* Number of leaves on the trunk of the freelist */ 4876 MemPage *pTrunk = 0; 4898 MemPage *pTrunk = 0; 4877 MemPage *pPrevTrunk = 0; 4899 MemPage *pPrevTrunk = 0; ................................................................................................................................................................................ 4891 u8 searchList = 0; /* If the free-list must be searched for 'nearby' */ 4913 u8 searchList = 0; /* If the free-list must be searched for 'nearby' */ 4892 4914 4893 /* If the 'exact' parameter was true and a query of the pointer-map 4915 /* If the 'exact' parameter was true and a query of the pointer-map 4894 ** shows that the page 'nearby' is somewhere on the free-list, then 4916 ** shows that the page 'nearby' is somewhere on the free-list, then 4895 ** the entire-list will be searched for that page. 4917 ** the entire-list will be searched for that page. 4896 */ 4918 */ 4897 #ifndef SQLITE_OMIT_AUTOVACUUM 4919 #ifndef SQLITE_OMIT_AUTOVACUUM > 4920 if( eMode==BTALLOC_EXACT ){ 4898 if( exact && nearby<=mxPage ){ | 4921 if( nearby<=mxPage ){ 4899 u8 eType; | 4922 u8 eType; 4900 assert( nearby>0 ); | 4923 assert( nearby>0 ); 4901 assert( pBt->autoVacuum ); | 4924 assert( pBt->autoVacuum ); 4902 rc = ptrmapGet(pBt, nearby, &eType, 0); | 4925 rc = ptrmapGet(pBt, nearby, &eType, 0); 4903 if( rc ) return rc; | 4926 if( rc ) return rc; 4904 if( eType==PTRMAP_FREEPAGE ){ | 4927 if( eType==PTRMAP_FREEPAGE ){ 4905 searchList = 1; | 4928 searchList = 1; 4906 } | 4929 } 4907 *pPgno = nearby; < > 4930 } > 4931 }else if( eMode==BTALLOC_LE ){ > 4932 searchList = 1; 4908 } 4933 } 4909 #endif 4934 #endif 4910 4935 4911 /* Decrement the free-list count by 1. Set iTrunk to the index of the 4936 /* Decrement the free-list count by 1. Set iTrunk to the index of the 4912 ** first free-list trunk page. iPrevTrunk is initially 1. 4937 ** first free-list trunk page. iPrevTrunk is initially 1. 4913 */ 4938 */ 4914 rc = sqlite3PagerWrite(pPage1->pDbPage); 4939 rc = sqlite3PagerWrite(pPage1->pDbPage); ................................................................................................................................................................................ 4955 pTrunk = 0; 4980 pTrunk = 0; 4956 TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1)); 4981 TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1)); 4957 }else if( k>(u32)(pBt->usableSize/4 - 2) ){ 4982 }else if( k>(u32)(pBt->usableSize/4 - 2) ){ 4958 /* Value of k is out of range. Database corruption */ 4983 /* Value of k is out of range. Database corruption */ 4959 rc = SQLITE_CORRUPT_BKPT; 4984 rc = SQLITE_CORRUPT_BKPT; 4960 goto end_allocate_page; 4985 goto end_allocate_page; 4961 #ifndef SQLITE_OMIT_AUTOVACUUM 4986 #ifndef SQLITE_OMIT_AUTOVACUUM 4962 }else if( searchList && nearby==iTrunk ){ | 4987 }else if( searchList > 4988 && (nearby==iTrunk || (iTrunk<nearby && eMode==BTALLOC_LE)) > 4989 ){ 4963 /* The list is being searched and this trunk page is the page 4990 /* The list is being searched and this trunk page is the page 4964 ** to allocate, regardless of whether it has leaves. 4991 ** to allocate, regardless of whether it has leaves. 4965 */ 4992 */ 4966 assert( *pPgno==iTrunk ); | 4993 *pPgno = iTrunk; 4967 *ppPage = pTrunk; 4994 *ppPage = pTrunk; 4968 searchList = 0; 4995 searchList = 0; 4969 rc = sqlite3PagerWrite(pTrunk->pDbPage); 4996 rc = sqlite3PagerWrite(pTrunk->pDbPage); 4970 if( rc ){ 4997 if( rc ){ 4971 goto end_allocate_page; 4998 goto end_allocate_page; 4972 } 4999 } 4973 if( k==0 ){ 5000 if( k==0 ){ ................................................................................................................................................................................ 5022 }else if( k>0 ){ 5049 }else if( k>0 ){ 5023 /* Extract a leaf from the trunk */ 5050 /* Extract a leaf from the trunk */ 5024 u32 closest; 5051 u32 closest; 5025 Pgno iPage; 5052 Pgno iPage; 5026 unsigned char *aData = pTrunk->aData; 5053 unsigned char *aData = pTrunk->aData; 5027 if( nearby>0 ){ 5054 if( nearby>0 ){ 5028 u32 i; 5055 u32 i; 5029 int dist; | 5056 closest = 0; > 5057 if( eMode==BTALLOC_LE ){ > 5058 for(i=0; i<k; i++){ > 5059 iPage = get4byte(&aData[8+i*4]); > 5060 if( iPage<=nearby ){ 5030 closest = 0; | 5061 closest = i; > 5062 break; > 5063 } > 5064 } > 5065 }else{ > 5066 int dist; 5031 dist = sqlite3AbsInt32(get4byte(&aData[8]) - nearby); | 5067 dist = sqlite3AbsInt32(get4byte(&aData[8]) - nearby); 5032 for(i=1; i<k; i++){ | 5068 for(i=1; i<k; i++){ 5033 int d2 = sqlite3AbsInt32(get4byte(&aData[8+i*4]) - nearby); | 5069 int d2 = sqlite3AbsInt32(get4byte(&aData[8+i*4]) - nearby); 5034 if( d2<dist ){ | 5070 if( d2<dist ){ 5035 closest = i; | 5071 closest = i; 5036 dist = d2; | 5072 dist = d2; > 5073 } 5037 } 5074 } 5038 } 5075 } 5039 }else{ 5076 }else{ 5040 closest = 0; 5077 closest = 0; 5041 } 5078 } 5042 5079 5043 iPage = get4byte(&aData[8+closest*4]); 5080 iPage = get4byte(&aData[8+closest*4]); 5044 testcase( iPage==mxPage ); 5081 testcase( iPage==mxPage ); 5045 if( iPage>mxPage ){ 5082 if( iPage>mxPage ){ 5046 rc = SQLITE_CORRUPT_BKPT; 5083 rc = SQLITE_CORRUPT_BKPT; 5047 goto end_allocate_page; 5084 goto end_allocate_page; 5048 } 5085 } 5049 testcase( iPage==mxPage ); 5086 testcase( iPage==mxPage ); 5050 if( !searchList || iPage==nearby ){ | 5087 if( !searchList > 5088 || (iPage==nearby || (iPage<nearby && eMode==BTALLOC_LE)) > 5089 ){ 5051 int noContent; 5090 int noContent; 5052 *pPgno = iPage; 5091 *pPgno = iPage; 5053 TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d" 5092 TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d" 5054 ": %d more free pages\n", 5093 ": %d more free pages\n", 5055 *pPgno, closest+1, k, pTrunk->pgno, n-1)); 5094 *pPgno, closest+1, k, pTrunk->pgno, n-1)); 5056 rc = sqlite3PagerWrite(pTrunk->pDbPage); 5095 rc = sqlite3PagerWrite(pTrunk->pDbPage); 5057 if( rc ) goto end_allocate_page; 5096 if( rc ) goto end_allocate_page; ................................................................................................................................................................................ 5070 searchList = 0; 5109 searchList = 0; 5071 } 5110 } 5072 } 5111 } 5073 releasePage(pPrevTrunk); 5112 releasePage(pPrevTrunk); 5074 pPrevTrunk = 0; 5113 pPrevTrunk = 0; 5075 }while( searchList ); 5114 }while( searchList ); 5076 }else{ 5115 }else{ 5077 /* There are no pages on the freelist, so create a new page at the | 5116 /* There are no pages on the freelist, so append a new page to the 5078 ** end of the file */ | 5117 ** database image. > 5118 ** > 5119 ** Normally, new pages allocated by this block can be requested from the > 5120 ** pager layer with the 'no-content' flag set. This prevents the pager > 5121 ** from trying to read the pages content from disk. However, if the > 5122 ** current transaction has already run one or more incremental-vacuum > 5123 ** steps, then the page we are about to allocate may contain content > 5124 ** that is required in the event of a rollback. In this case, do > 5125 ** not set the no-content flag. This causes the pager to load and journal > 5126 ** the current page content before overwriting it. > 5127 ** > 5128 ** Note that the pager will not actually attempt to load or journal > 5129 ** content for any page that really does lie past the end of the database > 5130 ** file on disk. So the effects of disabling the no-content optimization > 5131 ** here are confined to those pages that lie between the end of the > 5132 ** database image and the end of the database file. > 5133 */ > 5134 int bNoContent = (0==pBt->bDoTruncate); > 5135 5079 rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); 5136 rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); 5080 if( rc ) return rc; 5137 if( rc ) return rc; 5081 pBt->nPage++; 5138 pBt->nPage++; 5082 if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ) pBt->nPage++; 5139 if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ) pBt->nPage++; 5083 5140 5084 #ifndef SQLITE_OMIT_AUTOVACUUM 5141 #ifndef SQLITE_OMIT_AUTOVACUUM 5085 if( pBt->autoVacuum && PTRMAP_ISPAGE(pBt, pBt->nPage) ){ 5142 if( pBt->autoVacuum && PTRMAP_ISPAGE(pBt, pBt->nPage) ){ ................................................................................................................................................................................ 5086 /* If *pPgno refers to a pointer-map page, allocate two new pages 5143 /* If *pPgno refers to a pointer-map page, allocate two new pages 5087 ** at the end of the file instead of one. The first allocated page 5144 ** at the end of the file instead of one. The first allocated page 5088 ** becomes a new pointer-map page, the second is used by the caller. 5145 ** becomes a new pointer-map page, the second is used by the caller. 5089 */ 5146 */ 5090 MemPage *pPg = 0; 5147 MemPage *pPg = 0; 5091 TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", pBt->nPage)); 5148 TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", pBt->nPage)); 5092 assert( pBt->nPage!=PENDING_BYTE_PAGE(pBt) ); 5149 assert( pBt->nPage!=PENDING_BYTE_PAGE(pBt) ); 5093 rc = btreeGetPage(pBt, pBt->nPage, &pPg, 1); | 5150 rc = btreeGetPage(pBt, pBt->nPage, &pPg, bNoContent); 5094 if( rc==SQLITE_OK ){ 5151 if( rc==SQLITE_OK ){ 5095 rc = sqlite3PagerWrite(pPg->pDbPage); 5152 rc = sqlite3PagerWrite(pPg->pDbPage); 5096 releasePage(pPg); 5153 releasePage(pPg); 5097 } 5154 } 5098 if( rc ) return rc; 5155 if( rc ) return rc; 5099 pBt->nPage++; 5156 pBt->nPage++; 5100 if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ){ pBt->nPage++; } 5157 if( pBt->nPage==PENDING_BYTE_PAGE(pBt) ){ pBt->nPage++; } 5101 } 5158 } 5102 #endif 5159 #endif 5103 put4byte(28 + (u8*)pBt->pPage1->aData, pBt->nPage); 5160 put4byte(28 + (u8*)pBt->pPage1->aData, pBt->nPage); 5104 *pPgno = pBt->nPage; 5161 *pPgno = pBt->nPage; 5105 5162 5106 assert( *pPgno!=PENDING_BYTE_PAGE(pBt) ); 5163 assert( *pPgno!=PENDING_BYTE_PAGE(pBt) ); 5107 rc = btreeGetPage(pBt, *pPgno, ppPage, 1); | 5164 rc = btreeGetPage(pBt, *pPgno, ppPage, bNoContent); 5108 if( rc ) return rc; 5165 if( rc ) return rc; 5109 rc = sqlite3PagerWrite((*ppPage)->pDbPage); 5166 rc = sqlite3PagerWrite((*ppPage)->pDbPage); 5110 if( rc!=SQLITE_OK ){ 5167 if( rc!=SQLITE_OK ){ 5111 releasePage(*ppPage); 5168 releasePage(*ppPage); 5112 } 5169 } 5113 TRACE(("ALLOCATE: %d from end of file\n", *pPgno)); 5170 TRACE(("ALLOCATE: %d from end of file\n", *pPgno)); 5114 } 5171 } ................................................................................................................................................................................ 7115 } 7172 } 7116 assert( pgnoRoot>=3 ); 7173 assert( pgnoRoot>=3 ); 7117 7174 7118 /* Allocate a page. The page that currently resides at pgnoRoot will 7175 /* Allocate a page. The page that currently resides at pgnoRoot will 7119 ** be moved to the allocated page (unless the allocated page happens 7176 ** be moved to the allocated page (unless the allocated page happens 7120 ** to reside at pgnoRoot). 7177 ** to reside at pgnoRoot). 7121 */ 7178 */ 7122 rc = allocateBtreePage(pBt, &pPageMove, &pgnoMove, pgnoRoot, 1); | 7179 rc = allocateBtreePage(pBt, &pPageMove, &pgnoMove, pgnoRoot, BTALLOC_EXACT); 7123 if( rc!=SQLITE_OK ){ 7180 if( rc!=SQLITE_OK ){ 7124 return rc; 7181 return rc; 7125 } 7182 } 7126 7183 7127 if( pgnoMove!=pgnoRoot ){ 7184 if( pgnoMove!=pgnoRoot ){ 7128 /* pgnoRoot is the page that will be used for the root-page of 7185 /* pgnoRoot is the page that will be used for the root-page of 7129 ** the new table (assuming an error did not occur). But we were 7186 ** the new table (assuming an error did not occur). But we were
Changes to src/btreeInt.h
407 sqlite3 *db; /* Database connection currently using this Btree */ 407 sqlite3 *db; /* Database connection currently using this Btree */ 408 BtCursor *pCursor; /* A list of all open cursors */ 408 BtCursor *pCursor; /* A list of all open cursors */ 409 MemPage *pPage1; /* First page of the database */ 409 MemPage *pPage1; /* First page of the database */ 410 u8 openFlags; /* Flags to sqlite3BtreeOpen() */ 410 u8 openFlags; /* Flags to sqlite3BtreeOpen() */ 411 #ifndef SQLITE_OMIT_AUTOVACUUM 411 #ifndef SQLITE_OMIT_AUTOVACUUM 412 u8 autoVacuum; /* True if auto-vacuum is enabled */ 412 u8 autoVacuum; /* True if auto-vacuum is enabled */ 413 u8 incrVacuum; /* True if incr-vacuum is enabled */ 413 u8 incrVacuum; /* True if incr-vacuum is enabled */ > 414 u8 bDoTruncate; /* True to truncate db on commit */ 414 #endif 415 #endif 415 u8 inTransaction; /* Transaction state */ 416 u8 inTransaction; /* Transaction state */ 416 u8 max1bytePayload; /* Maximum first byte of cell for a 1-byte payload */ 417 u8 max1bytePayload; /* Maximum first byte of cell for a 1-byte payload */ 417 u16 btsFlags; /* Boolean parameters. See BTS_* macros below */ 418 u16 btsFlags; /* Boolean parameters. See BTS_* macros below */ 418 u16 maxLocal; /* Maximum local payload in non-LEAFDATA tables */ 419 u16 maxLocal; /* Maximum local payload in non-LEAFDATA tables */ 419 u16 minLocal; /* Minimum local payload in non-LEAFDATA tables */ 420 u16 minLocal; /* Minimum local payload in non-LEAFDATA tables */ 420 u16 maxLeaf; /* Maximum local payload in a LEAFDATA table */ 421 u16 maxLeaf; /* Maximum local payload in a LEAFDATA table */
Changes to src/pager.c
1834 if( rc2==SQLITE_FULL || rc2==SQLITE_IOERR ){ 1834 if( rc2==SQLITE_FULL || rc2==SQLITE_IOERR ){ 1835 pPager->errCode = rc; 1835 pPager->errCode = rc; 1836 pPager->eState = PAGER_ERROR; 1836 pPager->eState = PAGER_ERROR; 1837 } 1837 } 1838 return rc; 1838 return rc; 1839 } 1839 } 1840 1840 > 1841 static int pager_truncate(Pager *pPager, Pgno nPage); > 1842 1841 /* 1843 /* 1842 ** This routine ends a transaction. A transaction is usually ended by 1844 ** This routine ends a transaction. A transaction is usually ended by 1843 ** either a COMMIT or a ROLLBACK operation. This routine may be called 1845 ** either a COMMIT or a ROLLBACK operation. This routine may be called 1844 ** after rollback of a hot-journal, or if an error occurs while opening 1846 ** after rollback of a hot-journal, or if an error occurs while opening 1845 ** the journal file or writing the very first journal-header of a 1847 ** the journal file or writing the very first journal-header of a 1846 ** database transaction. 1848 ** database transaction. 1847 ** 1849 ** ................................................................................................................................................................................ 1887 ** database then the IO error code is returned to the user. If the 1889 ** database then the IO error code is returned to the user. If the 1888 ** operation to finalize the journal file fails, then the code still 1890 ** operation to finalize the journal file fails, then the code still 1889 ** tries to unlock the database file if not in exclusive mode. If the 1891 ** tries to unlock the database file if not in exclusive mode. If the 1890 ** unlock operation fails as well, then the first error code related 1892 ** unlock operation fails as well, then the first error code related 1891 ** to the first error encountered (the journal finalization one) is 1893 ** to the first error encountered (the journal finalization one) is 1892 ** returned. 1894 ** returned. 1893 */ 1895 */ 1894 static int pager_end_transaction(Pager *pPager, int hasMaster){ | 1896 static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){ 1895 int rc = SQLITE_OK; /* Error code from journal finalization operation */ 1897 int rc = SQLITE_OK; /* Error code from journal finalization operation */ 1896 int rc2 = SQLITE_OK; /* Error code from db file unlock operation */ 1898 int rc2 = SQLITE_OK; /* Error code from db file unlock operation */ 1897 1899 1898 /* Do nothing if the pager does not have an open write transaction 1900 /* Do nothing if the pager does not have an open write transaction 1899 ** or at least a RESERVED lock. This function may be called when there 1901 ** or at least a RESERVED lock. This function may be called when there 1900 ** is no write-transaction active but a RESERVED or greater lock is 1902 ** is no write-transaction active but a RESERVED or greater lock is 1901 ** held under two circumstances: 1903 ** held under two circumstances: ................................................................................................................................................................................ 1973 if( pagerUseWal(pPager) ){ 1975 if( pagerUseWal(pPager) ){ 1974 /* Drop the WAL write-lock, if any. Also, if the connection was in 1976 /* Drop the WAL write-lock, if any. Also, if the connection was in 1975 ** locking_mode=exclusive mode but is no longer, drop the EXCLUSIVE 1977 ** locking_mode=exclusive mode but is no longer, drop the EXCLUSIVE 1976 ** lock held on the database file. 1978 ** lock held on the database file. 1977 */ 1979 */ 1978 rc2 = sqlite3WalEndWriteTransaction(pPager->pWal); 1980 rc2 = sqlite3WalEndWriteTransaction(pPager->pWal); 1979 assert( rc2==SQLITE_OK ); 1981 assert( rc2==SQLITE_OK ); > 1982 }else if( rc==SQLITE_OK && bCommit && pPager->dbFileSize>pPager->dbSize ){ > 1983 /* This branch is taken when committing a transaction in rollback-journal > 1984 ** mode if the database file on disk is larger than the database image. > 1985 ** At this point the journal has been finalized and the transaction > 1986 ** successfully committed, but the EXCLUSIVE lock is still held on the > 1987 ** file. So it is safe to truncate the database file to its minimum > 1988 ** required size. */ > 1989 assert( pPager->eLock==EXCLUSIVE_LOCK ); > 1990 rc = pager_truncate(pPager, pPager->dbSize); 1980 } 1991 } > 1992 1981 if( !pPager->exclusiveMode 1993 if( !pPager->exclusiveMode 1982 && (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0)) 1994 && (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0)) 1983 ){ 1995 ){ 1984 rc2 = pagerUnlockDb(pPager, SHARED_LOCK); 1996 rc2 = pagerUnlockDb(pPager, SHARED_LOCK); 1985 pPager->changeCountDone = 0; 1997 pPager->changeCountDone = 0; 1986 } 1998 } 1987 pPager->eState = PAGER_READER; 1999 pPager->eState = PAGER_READER; ................................................................................................................................................................................ 2012 assert( assert_pager_state(pPager) ); 2024 assert( assert_pager_state(pPager) ); 2013 if( pPager->eState>=PAGER_WRITER_LOCKED ){ 2025 if( pPager->eState>=PAGER_WRITER_LOCKED ){ 2014 sqlite3BeginBenignMalloc(); 2026 sqlite3BeginBenignMalloc(); 2015 sqlite3PagerRollback(pPager); 2027 sqlite3PagerRollback(pPager); 2016 sqlite3EndBenignMalloc(); 2028 sqlite3EndBenignMalloc(); 2017 }else if( !pPager->exclusiveMode ){ 2029 }else if( !pPager->exclusiveMode ){ 2018 assert( pPager->eState==PAGER_READER ); 2030 assert( pPager->eState==PAGER_READER ); 2019 pager_end_transaction(pPager, 0); | 2031 pager_end_transaction(pPager, 0, 0); 2020 } 2032 } 2021 } 2033 } 2022 pager_unlock(pPager); 2034 pager_unlock(pPager); 2023 } 2035 } 2024 2036 2025 /* 2037 /* 2026 ** Parameter aData must point to a buffer of pPager->pageSize bytes 2038 ** Parameter aData must point to a buffer of pPager->pageSize bytes ................................................................................................................................................................................ 2787 } 2799 } 2788 if( rc==SQLITE_OK 2800 if( rc==SQLITE_OK 2789 && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN) 2801 && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN) 2790 ){ 2802 ){ 2791 rc = sqlite3PagerSync(pPager); 2803 rc = sqlite3PagerSync(pPager); 2792 } 2804 } 2793 if( rc==SQLITE_OK ){ 2805 if( rc==SQLITE_OK ){ 2794 rc = pager_end_transaction(pPager, zMaster[0]!='\0'); | 2806 rc = pager_end_transaction(pPager, zMaster[0]!='\0', 0); 2795 testcase( rc!=SQLITE_OK ); 2807 testcase( rc!=SQLITE_OK ); 2796 } 2808 } 2797 if( rc==SQLITE_OK && zMaster[0] && res ){ 2809 if( rc==SQLITE_OK && zMaster[0] && res ){ 2798 /* If there was a master journal and this routine will return success, 2810 /* If there was a master journal and this routine will return success, 2799 ** see if it is possible to delete the master journal. 2811 ** see if it is possible to delete the master journal. 2800 */ 2812 */ 2801 rc = pager_delmaster(pPager, zMaster); 2813 rc = pager_delmaster(pPager, zMaster); ................................................................................................................................................................................ 5881 } 5893 } 5882 } 5894 } 5883 #else 5895 #else 5884 rc = pager_incr_changecounter(pPager, 0); 5896 rc = pager_incr_changecounter(pPager, 0); 5885 #endif 5897 #endif 5886 if( rc!=SQLITE_OK ) goto commit_phase_one_exit; 5898 if( rc!=SQLITE_OK ) goto commit_phase_one_exit; 5887 5899 5888 /* If this transaction has made the database smaller, then all pages < 5889 ** being discarded by the truncation must be written to the journal < 5890 ** file. < 5891 ** < 5892 ** Before reading the pages with page numbers larger than the < 5893 ** current value of Pager.dbSize, set dbSize back to the value < 5894 ** that it took at the start of the transaction. Otherwise, the < 5895 ** calls to sqlite3PagerGet() return zeroed pages instead of < 5896 ** reading data from the database file. < 5897 */ < 5898 if( pPager->dbSize<pPager->dbOrigSize < 5899 && pPager->journalMode!=PAGER_JOURNALMODE_OFF < 5900 ){ < 5901 Pgno i; /* Iterator variable */ < 5902 const Pgno iSkip = PAGER_MJ_PGNO(pPager); /* Pending lock page */ < 5903 const Pgno dbSize = pPager->dbSize; /* Database image size */ < 5904 pPager->dbSize = pPager->dbOrigSize; < 5905 for( i=dbSize+1; i<=pPager->dbOrigSize; i++ ){ < 5906 if( !sqlite3BitvecTest(pPager->pInJournal, i) && i!=iSkip ){ < 5907 PgHdr *pPage; /* Page to journal */ < 5908 rc = sqlite3PagerGet(pPager, i, &pPage); < 5909 if( rc!=SQLITE_OK ) goto commit_phase_one_exit; < 5910 rc = sqlite3PagerWrite(pPage); < 5911 sqlite3PagerUnref(pPage); < 5912 if( rc!=SQLITE_OK ) goto commit_phase_one_exit; < 5913 } < 5914 } < 5915 pPager->dbSize = dbSize; < 5916 } < 5917 < 5918 /* Write the master journal name into the journal file. If a master 5900 /* Write the master journal name into the journal file. If a master 5919 ** journal file name has already been written to the journal file, 5901 ** journal file name has already been written to the journal file, 5920 ** or if zMaster is NULL (no master journal), then this call is a no-op. 5902 ** or if zMaster is NULL (no master journal), then this call is a no-op. 5921 */ 5903 */ 5922 rc = writeMasterJournal(pPager, zMaster); 5904 rc = writeMasterJournal(pPager, zMaster); 5923 if( rc!=SQLITE_OK ) goto commit_phase_one_exit; 5905 if( rc!=SQLITE_OK ) goto commit_phase_one_exit; 5924 5906 ................................................................................................................................................................................ 5938 5920 5939 rc = pager_write_pagelist(pPager,sqlite3PcacheDirtyList(pPager->pPCache)); 5921 rc = pager_write_pagelist(pPager,sqlite3PcacheDirtyList(pPager->pPCache)); 5940 if( rc!=SQLITE_OK ){ 5922 if( rc!=SQLITE_OK ){ 5941 assert( rc!=SQLITE_IOERR_BLOCKED ); 5923 assert( rc!=SQLITE_IOERR_BLOCKED ); 5942 goto commit_phase_one_exit; 5924 goto commit_phase_one_exit; 5943 } 5925 } 5944 sqlite3PcacheCleanAll(pPager->pPCache); 5926 sqlite3PcacheCleanAll(pPager->pPCache); 5945 | 5927 5946 /* If the file on disk is not the same size as the database image, | 5928 /* If the file on disk is smaller than the database image, use 5947 ** then use pager_truncate to grow or shrink the file here. | 5929 ** pager_truncate to grow the file here. This can happen if the database 5948 */ | 5930 ** image was extended as part of the current transaction and then the > 5931 ** last page in the db image moved to the free-list. In this case the > 5932 ** last page is never written out to disk, leaving the database file > 5933 ** undersized. Fix this now if it is the case. */ 5949 if( pPager->dbSize!=pPager->dbFileSize ){ | 5934 if( pPager->dbSize>pPager->dbFileSize ){ 5950 Pgno nNew = pPager->dbSize - (pPager->dbSize==PAGER_MJ_PGNO(pPager)); 5935 Pgno nNew = pPager->dbSize - (pPager->dbSize==PAGER_MJ_PGNO(pPager)); 5951 assert( pPager->eState==PAGER_WRITER_DBMOD ); 5936 assert( pPager->eState==PAGER_WRITER_DBMOD ); 5952 rc = pager_truncate(pPager, nNew); 5937 rc = pager_truncate(pPager, nNew); 5953 if( rc!=SQLITE_OK ) goto commit_phase_one_exit; 5938 if( rc!=SQLITE_OK ) goto commit_phase_one_exit; 5954 } 5939 } 5955 5940 5956 /* Finally, sync the database file. */ 5941 /* Finally, sync the database file. */ ................................................................................................................................................................................ 6015 ){ 6000 ){ 6016 assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) || !pPager->journalOff ); 6001 assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) || !pPager->journalOff ); 6017 pPager->eState = PAGER_READER; 6002 pPager->eState = PAGER_READER; 6018 return SQLITE_OK; 6003 return SQLITE_OK; 6019 } 6004 } 6020 6005 6021 PAGERTRACE(("COMMIT %d\n", PAGERID(pPager))); 6006 PAGERTRACE(("COMMIT %d\n", PAGERID(pPager))); 6022 rc = pager_end_transaction(pPager, pPager->setMaster); | 6007 rc = pager_end_transaction(pPager, pPager->setMaster, 1); 6023 return pager_error(pPager, rc); 6008 return pager_error(pPager, rc); 6024 } 6009 } 6025 6010 6026 /* 6011 /* 6027 ** If a write transaction is open, then all changes made within the 6012 ** If a write transaction is open, then all changes made within the 6028 ** transaction are reverted and the current write-transaction is closed. 6013 ** transaction are reverted and the current write-transaction is closed. 6029 ** The pager falls back to PAGER_READER state if successful, or PAGER_ERROR 6014 ** The pager falls back to PAGER_READER state if successful, or PAGER_ERROR ................................................................................................................................................................................ 6060 assert( assert_pager_state(pPager) ); 6045 assert( assert_pager_state(pPager) ); 6061 if( pPager->eState==PAGER_ERROR ) return pPager->errCode; 6046 if( pPager->eState==PAGER_ERROR ) return pPager->errCode; 6062 if( pPager->eState<=PAGER_READER ) return SQLITE_OK; 6047 if( pPager->eState<=PAGER_READER ) return SQLITE_OK; 6063 6048 6064 if( pagerUseWal(pPager) ){ 6049 if( pagerUseWal(pPager) ){ 6065 int rc2; 6050 int rc2; 6066 rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, -1); 6051 rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, -1); 6067 rc2 = pager_end_transaction(pPager, pPager->setMaster); | 6052 rc2 = pager_end_transaction(pPager, pPager->setMaster, 0); 6068 if( rc==SQLITE_OK ) rc = rc2; 6053 if( rc==SQLITE_OK ) rc = rc2; 6069 }else if( !isOpen(pPager->jfd) || pPager->eState==PAGER_WRITER_LOCKED ){ 6054 }else if( !isOpen(pPager->jfd) || pPager->eState==PAGER_WRITER_LOCKED ){ 6070 int eState = pPager->eState; 6055 int eState = pPager->eState; 6071 rc = pager_end_transaction(pPager, 0); | 6056 rc = pager_end_transaction(pPager, 0, 0); 6072 if( !MEMDB && eState>PAGER_WRITER_LOCKED ){ 6057 if( !MEMDB && eState>PAGER_WRITER_LOCKED ){ 6073 /* This can happen using journal_mode=off. Move the pager to the error 6058 /* This can happen using journal_mode=off. Move the pager to the error 6074 ** state to indicate that the contents of the cache may not be trusted. 6059 ** state to indicate that the contents of the cache may not be trusted. 6075 ** Any active readers will get SQLITE_ABORT. 6060 ** Any active readers will get SQLITE_ABORT. 6076 */ 6061 */ 6077 pPager->errCode = SQLITE_ABORT; 6062 pPager->errCode = SQLITE_ABORT; 6078 pPager->eState = PAGER_ERROR; 6063 pPager->eState = PAGER_ERROR;
Changes to src/test_vfs.c
261 261 262 262 263 static void tvfsExecTcl( 263 static void tvfsExecTcl( 264 Testvfs *p, 264 Testvfs *p, 265 const char *zMethod, 265 const char *zMethod, 266 Tcl_Obj *arg1, 266 Tcl_Obj *arg1, 267 Tcl_Obj *arg2, 267 Tcl_Obj *arg2, 268 Tcl_Obj *arg3 | 268 Tcl_Obj *arg3, > 269 Tcl_Obj *arg4 269 ){ 270 ){ 270 int rc; /* Return code from Tcl_EvalObj() */ 271 int rc; /* Return code from Tcl_EvalObj() */ 271 Tcl_Obj *pEval; 272 Tcl_Obj *pEval; 272 assert( p->pScript ); 273 assert( p->pScript ); 273 274 274 assert( zMethod ); 275 assert( zMethod ); 275 assert( p ); 276 assert( p ); ................................................................................................................................................................................ 278 279 279 pEval = Tcl_DuplicateObj(p->pScript); 280 pEval = Tcl_DuplicateObj(p->pScript); 280 Tcl_IncrRefCount(p->pScript); 281 Tcl_IncrRefCount(p->pScript); 281 Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewStringObj(zMethod, -1)); 282 Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewStringObj(zMethod, -1)); 282 if( arg1 ) Tcl_ListObjAppendElement(p->interp, pEval, arg1); 283 if( arg1 ) Tcl_ListObjAppendElement(p->interp, pEval, arg1); 283 if( arg2 ) Tcl_ListObjAppendElement(p->interp, pEval, arg2); 284 if( arg2 ) Tcl_ListObjAppendElement(p->interp, pEval, arg2); 284 if( arg3 ) Tcl_ListObjAppendElement(p->interp, pEval, arg3); 285 if( arg3 ) Tcl_ListObjAppendElement(p->interp, pEval, arg3); > 286 if( arg4 ) Tcl_ListObjAppendElement(p->interp, pEval, arg4); 285 287 286 rc = Tcl_EvalObjEx(p->interp, pEval, TCL_EVAL_GLOBAL); 288 rc = Tcl_EvalObjEx(p->interp, pEval, TCL_EVAL_GLOBAL); 287 if( rc!=TCL_OK ){ 289 if( rc!=TCL_OK ){ 288 Tcl_BackgroundError(p->interp); 290 Tcl_BackgroundError(p->interp); 289 Tcl_ResetResult(p->interp); 291 Tcl_ResetResult(p->interp); 290 } 292 } 291 } 293 } ................................................................................................................................................................................ 298 int rc; 300 int rc; 299 TestvfsFile *pTestfile = (TestvfsFile *)pFile; 301 TestvfsFile *pTestfile = (TestvfsFile *)pFile; 300 TestvfsFd *pFd = pTestfile->pFd; 302 TestvfsFd *pFd = pTestfile->pFd; 301 Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; 303 Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; 302 304 303 if( p->pScript && p->mask&TESTVFS_CLOSE_MASK ){ 305 if( p->pScript && p->mask&TESTVFS_CLOSE_MASK ){ 304 tvfsExecTcl(p, "xClose", 306 tvfsExecTcl(p, "xClose", 305 Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0 | 307 Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0, 0 306 ); 308 ); 307 } 309 } 308 310 309 if( pFd->pShmId ){ 311 if( pFd->pShmId ){ 310 Tcl_DecrRefCount(pFd->pShmId); 312 Tcl_DecrRefCount(pFd->pShmId); 311 pFd->pShmId = 0; 313 pFd->pShmId = 0; 312 } 314 } ................................................................................................................................................................................ 329 sqlite_int64 iOfst 331 sqlite_int64 iOfst 330 ){ 332 ){ 331 int rc = SQLITE_OK; 333 int rc = SQLITE_OK; 332 TestvfsFd *pFd = tvfsGetFd(pFile); 334 TestvfsFd *pFd = tvfsGetFd(pFile); 333 Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; 335 Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; 334 if( p->pScript && p->mask&TESTVFS_READ_MASK ){ 336 if( p->pScript && p->mask&TESTVFS_READ_MASK ){ 335 tvfsExecTcl(p, "xRead", 337 tvfsExecTcl(p, "xRead", 336 Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0 | 338 Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0, 0 337 ); 339 ); 338 tvfsResultCode(p, &rc); 340 tvfsResultCode(p, &rc); 339 } 341 } 340 if( rc==SQLITE_OK && p->mask&TESTVFS_READ_MASK && tvfsInjectIoerr(p) ){ 342 if( rc==SQLITE_OK && p->mask&TESTVFS_READ_MASK && tvfsInjectIoerr(p) ){ 341 rc = SQLITE_IOERR; 343 rc = SQLITE_IOERR; 342 } 344 } 343 if( rc==SQLITE_OK ){ 345 if( rc==SQLITE_OK ){ ................................................................................................................................................................................ 358 int rc = SQLITE_OK; 360 int rc = SQLITE_OK; 359 TestvfsFd *pFd = tvfsGetFd(pFile); 361 TestvfsFd *pFd = tvfsGetFd(pFile); 360 Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; 362 Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; 361 363 362 if( p->pScript && p->mask&TESTVFS_WRITE_MASK ){ 364 if( p->pScript && p->mask&TESTVFS_WRITE_MASK ){ 363 tvfsExecTcl(p, "xWrite", 365 tvfsExecTcl(p, "xWrite", 364 Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 366 Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 365 Tcl_NewWideIntObj(iOfst) | 367 Tcl_NewWideIntObj(iOfst), Tcl_NewIntObj(iAmt) 366 ); 368 ); 367 tvfsResultCode(p, &rc); 369 tvfsResultCode(p, &rc); 368 } 370 } 369 371 370 if( rc==SQLITE_OK && tvfsInjectFullerr(p) ){ 372 if( rc==SQLITE_OK && tvfsInjectFullerr(p) ){ 371 rc = SQLITE_FULL; 373 rc = SQLITE_FULL; 372 } 374 } ................................................................................................................................................................................ 386 static int tvfsTruncate(sqlite3_file *pFile, sqlite_int64 size){ 388 static int tvfsTruncate(sqlite3_file *pFile, sqlite_int64 size){ 387 int rc = SQLITE_OK; 389 int rc = SQLITE_OK; 388 TestvfsFd *pFd = tvfsGetFd(pFile); 390 TestvfsFd *pFd = tvfsGetFd(pFile); 389 Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; 391 Testvfs *p = (Testvfs *)pFd->pVfs->pAppData; 390 392 391 if( p->pScript && p->mask&TESTVFS_TRUNCATE_MASK ){ 393 if( p->pScript && p->mask&TESTVFS_TRUNCATE_MASK ){ 392 tvfsExecTcl(p, "xTruncate", 394 tvfsExecTcl(p, "xTruncate", 393 Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0 | 395 Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0, 0 394 ); 396 ); 395 tvfsResultCode(p, &rc); 397 tvfsResultCode(p, &rc); 396 } 398 } 397 399 398 if( rc==SQLITE_OK ){ 400 if( rc==SQLITE_OK ){ 399 rc = sqlite3OsTruncate(pFd->pReal, size); 401 rc = sqlite3OsTruncate(pFd->pReal, size); 400 } 402 } ................................................................................................................................................................................ 427 break; 429 break; 428 default: 430 default: 429 assert(0); 431 assert(0); 430 } 432 } 431 433 432 tvfsExecTcl(p, "xSync", 434 tvfsExecTcl(p, "xSync", 433 Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 435 Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 434 Tcl_NewStringObj(zFlags, -1) | 436 Tcl_NewStringObj(zFlags, -1), 0 435 ); 437 ); 436 tvfsResultCode(p, &rc); 438 tvfsResultCode(p, &rc); 437 } 439 } 438 440 439 if( rc==SQLITE_OK && tvfsInjectFullerr(p) ) rc = SQLITE_FULL; 441 if( rc==SQLITE_OK && tvfsInjectFullerr(p) ) rc = SQLITE_FULL; 440 442 441 if( rc==SQLITE_OK ){ 443 if( rc==SQLITE_OK ){ ................................................................................................................................................................................ 574 while( *z ){ 576 while( *z ){ 575 Tcl_ListObjAppendElement(0, pArg, Tcl_NewStringObj(z, -1)); 577 Tcl_ListObjAppendElement(0, pArg, Tcl_NewStringObj(z, -1)); 576 z += strlen(z) + 1; 578 z += strlen(z) + 1; 577 Tcl_ListObjAppendElement(0, pArg, Tcl_NewStringObj(z, -1)); 579 Tcl_ListObjAppendElement(0, pArg, Tcl_NewStringObj(z, -1)); 578 z += strlen(z) + 1; 580 z += strlen(z) + 1; 579 } 581 } 580 } 582 } 581 tvfsExecTcl(p, "xOpen", Tcl_NewStringObj(pFd->zFilename, -1), pArg, 0); | 583 tvfsExecTcl(p, "xOpen", Tcl_NewStringObj(pFd->zFilename, -1), pArg, 0, 0); 582 Tcl_DecrRefCount(pArg); 584 Tcl_DecrRefCount(pArg); 583 if( tvfsResultCode(p, &rc) ){ 585 if( tvfsResultCode(p, &rc) ){ 584 if( rc!=SQLITE_OK ) return rc; 586 if( rc!=SQLITE_OK ) return rc; 585 }else{ 587 }else{ 586 pId = Tcl_GetObjResult(p->interp); 588 pId = Tcl_GetObjResult(p->interp); 587 } 589 } 588 } 590 } ................................................................................................................................................................................ 631 */ 633 */ 632 static int tvfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ 634 static int tvfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ 633 int rc = SQLITE_OK; 635 int rc = SQLITE_OK; 634 Testvfs *p = (Testvfs *)pVfs->pAppData; 636 Testvfs *p = (Testvfs *)pVfs->pAppData; 635 637 636 if( p->pScript && p->mask&TESTVFS_DELETE_MASK ){ 638 if( p->pScript && p->mask&TESTVFS_DELETE_MASK ){ 637 tvfsExecTcl(p, "xDelete", 639 tvfsExecTcl(p, "xDelete", 638 Tcl_NewStringObj(zPath, -1), Tcl_NewIntObj(dirSync), 0 | 640 Tcl_NewStringObj(zPath, -1), Tcl_NewIntObj(dirSync), 0, 0 639 ); 641 ); 640 tvfsResultCode(p, &rc); 642 tvfsResultCode(p, &rc); 641 } 643 } 642 if( rc==SQLITE_OK ){ 644 if( rc==SQLITE_OK ){ 643 rc = sqlite3OsDelete(PARENTVFS(pVfs), zPath, dirSync); 645 rc = sqlite3OsDelete(PARENTVFS(pVfs), zPath, dirSync); 644 } 646 } 645 return rc; 647 return rc; ................................................................................................................................................................................ 659 if( p->pScript && p->mask&TESTVFS_ACCESS_MASK ){ 661 if( p->pScript && p->mask&TESTVFS_ACCESS_MASK ){ 660 int rc; 662 int rc; 661 char *zArg = 0; 663 char *zArg = 0; 662 if( flags==SQLITE_ACCESS_EXISTS ) zArg = "SQLITE_ACCESS_EXISTS"; 664 if( flags==SQLITE_ACCESS_EXISTS ) zArg = "SQLITE_ACCESS_EXISTS"; 663 if( flags==SQLITE_ACCESS_READWRITE ) zArg = "SQLITE_ACCESS_READWRITE"; 665 if( flags==SQLITE_ACCESS_READWRITE ) zArg = "SQLITE_ACCESS_READWRITE"; 664 if( flags==SQLITE_ACCESS_READ ) zArg = "SQLITE_ACCESS_READ"; 666 if( flags==SQLITE_ACCESS_READ ) zArg = "SQLITE_ACCESS_READ"; 665 tvfsExecTcl(p, "xAccess", 667 tvfsExecTcl(p, "xAccess", 666 Tcl_NewStringObj(zPath, -1), Tcl_NewStringObj(zArg, -1), 0 | 668 Tcl_NewStringObj(zPath, -1), Tcl_NewStringObj(zArg, -1), 0, 0 667 ); 669 ); 668 if( tvfsResultCode(p, &rc) ){ 670 if( tvfsResultCode(p, &rc) ){ 669 if( rc!=SQLITE_OK ) return rc; 671 if( rc!=SQLITE_OK ) return rc; 670 }else{ 672 }else{ 671 Tcl_Interp *interp = p->interp; 673 Tcl_Interp *interp = p->interp; 672 if( TCL_OK==Tcl_GetBooleanFromObj(0, Tcl_GetObjResult(interp), pResOut) ){ 674 if( TCL_OK==Tcl_GetBooleanFromObj(0, Tcl_GetObjResult(interp), pResOut) ){ 673 return SQLITE_OK; 675 return SQLITE_OK; ................................................................................................................................................................................ 687 const char *zPath, 689 const char *zPath, 688 int nOut, 690 int nOut, 689 char *zOut 691 char *zOut 690 ){ 692 ){ 691 Testvfs *p = (Testvfs *)pVfs->pAppData; 693 Testvfs *p = (Testvfs *)pVfs->pAppData; 692 if( p->pScript && p->mask&TESTVFS_FULLPATHNAME_MASK ){ 694 if( p->pScript && p->mask&TESTVFS_FULLPATHNAME_MASK ){ 693 int rc; 695 int rc; 694 tvfsExecTcl(p, "xFullPathname", Tcl_NewStringObj(zPath, -1), 0, 0); | 696 tvfsExecTcl(p, "xFullPathname", Tcl_NewStringObj(zPath, -1), 0, 0, 0); 695 if( tvfsResultCode(p, &rc) ){ 697 if( tvfsResultCode(p, &rc) ){ 696 if( rc!=SQLITE_OK ) return rc; 698 if( rc!=SQLITE_OK ) return rc; 697 } 699 } 698 } 700 } 699 return sqlite3OsFullPathname(PARENTVFS(pVfs), zPath, nOut, zOut); 701 return sqlite3OsFullPathname(PARENTVFS(pVfs), zPath, nOut, zOut); 700 } 702 } 701 703 ................................................................................................................................................................................ 767 769 768 /* Evaluate the Tcl script: 770 /* Evaluate the Tcl script: 769 ** 771 ** 770 ** SCRIPT xShmOpen FILENAME 772 ** SCRIPT xShmOpen FILENAME 771 */ 773 */ 772 Tcl_ResetResult(p->interp); 774 Tcl_ResetResult(p->interp); 773 if( p->pScript && p->mask&TESTVFS_SHMOPEN_MASK ){ 775 if( p->pScript && p->mask&TESTVFS_SHMOPEN_MASK ){ 774 tvfsExecTcl(p, "xShmOpen", Tcl_NewStringObj(pFd->zFilename, -1), 0, 0); | 776 tvfsExecTcl(p, "xShmOpen", Tcl_NewStringObj(pFd->zFilename, -1), 0, 0, 0); 775 if( tvfsResultCode(p, &rc) ){ 777 if( tvfsResultCode(p, &rc) ){ 776 if( rc!=SQLITE_OK ) return rc; 778 if( rc!=SQLITE_OK ) return rc; 777 } 779 } 778 } 780 } 779 781 780 assert( rc==SQLITE_OK ); 782 assert( rc==SQLITE_OK ); 781 if( p->mask&TESTVFS_SHMOPEN_MASK && tvfsInjectIoerr(p) ){ 783 if( p->mask&TESTVFS_SHMOPEN_MASK && tvfsInjectIoerr(p) ){ ................................................................................................................................................................................ 837 if( p->pScript && p->mask&TESTVFS_SHMMAP_MASK ){ 839 if( p->pScript && p->mask&TESTVFS_SHMMAP_MASK ){ 838 Tcl_Obj *pArg = Tcl_NewObj(); 840 Tcl_Obj *pArg = Tcl_NewObj(); 839 Tcl_IncrRefCount(pArg); 841 Tcl_IncrRefCount(pArg); 840 Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(iPage)); 842 Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(iPage)); 841 Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(pgsz)); 843 Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(pgsz)); 842 Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(isWrite)); 844 Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(isWrite)); 843 tvfsExecTcl(p, "xShmMap", 845 tvfsExecTcl(p, "xShmMap", 844 Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, pArg | 846 Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, pArg, 0 845 ); 847 ); 846 tvfsResultCode(p, &rc); 848 tvfsResultCode(p, &rc); 847 Tcl_DecrRefCount(pArg); 849 Tcl_DecrRefCount(pArg); 848 } 850 } 849 if( rc==SQLITE_OK && p->mask&TESTVFS_SHMMAP_MASK && tvfsInjectIoerr(p) ){ 851 if( rc==SQLITE_OK && p->mask&TESTVFS_SHMMAP_MASK && tvfsInjectIoerr(p) ){ 850 rc = SQLITE_IOERR; 852 rc = SQLITE_IOERR; 851 } 853 } ................................................................................................................................................................................ 887 if( flags & SQLITE_SHM_SHARED ){ 889 if( flags & SQLITE_SHM_SHARED ){ 888 strcpy(&zLock[nLock], " shared"); 890 strcpy(&zLock[nLock], " shared"); 889 }else{ 891 }else{ 890 strcpy(&zLock[nLock], " exclusive"); 892 strcpy(&zLock[nLock], " exclusive"); 891 } 893 } 892 tvfsExecTcl(p, "xShmLock", 894 tvfsExecTcl(p, "xShmLock", 893 Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 895 Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 894 Tcl_NewStringObj(zLock, -1) | 896 Tcl_NewStringObj(zLock, -1), 0 895 ); 897 ); 896 tvfsResultCode(p, &rc); 898 tvfsResultCode(p, &rc); 897 } 899 } 898 900 899 if( rc==SQLITE_OK && p->mask&TESTVFS_SHMLOCK_MASK && tvfsInjectIoerr(p) ){ 901 if( rc==SQLITE_OK && p->mask&TESTVFS_SHMLOCK_MASK && tvfsInjectIoerr(p) ){ 900 rc = SQLITE_IOERR; 902 rc = SQLITE_IOERR; 901 } 903 } ................................................................................................................................................................................ 933 if( p->isFullshm ){ 935 if( p->isFullshm ){ 934 sqlite3OsShmBarrier(pFd->pReal); 936 sqlite3OsShmBarrier(pFd->pReal); 935 return; 937 return; 936 } 938 } 937 939 938 if( p->pScript && p->mask&TESTVFS_SHMBARRIER_MASK ){ 940 if( p->pScript && p->mask&TESTVFS_SHMBARRIER_MASK ){ 939 tvfsExecTcl(p, "xShmBarrier", 941 tvfsExecTcl(p, "xShmBarrier", 940 Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0 | 942 Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0, 0 941 ); 943 ); 942 } 944 } 943 } 945 } 944 946 945 static int tvfsShmUnmap( 947 static int tvfsShmUnmap( 946 sqlite3_file *pFile, 948 sqlite3_file *pFile, 947 int deleteFlag 949 int deleteFlag ................................................................................................................................................................................ 957 } 959 } 958 960 959 if( !pBuffer ) return SQLITE_OK; 961 if( !pBuffer ) return SQLITE_OK; 960 assert( pFd->pShmId && pFd->pShm ); 962 assert( pFd->pShmId && pFd->pShm ); 961 963 962 if( p->pScript && p->mask&TESTVFS_SHMCLOSE_MASK ){ 964 if( p->pScript && p->mask&TESTVFS_SHMCLOSE_MASK ){ 963 tvfsExecTcl(p, "xShmUnmap", 965 tvfsExecTcl(p, "xShmUnmap", 964 Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0 | 966 Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0, 0 965 ); 967 ); 966 tvfsResultCode(p, &rc); 968 tvfsResultCode(p, &rc); 967 } 969 } 968 970 969 for(ppFd=&pBuffer->pFile; *ppFd!=pFd; ppFd=&((*ppFd)->pNext)); 971 for(ppFd=&pBuffer->pFile; *ppFd!=pFd; ppFd=&((*ppFd)->pNext)); 970 assert( (*ppFd)==pFd ); 972 assert( (*ppFd)==pFd ); 971 *ppFd = pFd->pNext; 973 *ppFd = pFd->pNext;
Added test/incrvacuum3.test
> 1 # 2013 Feb 25 > 2 # > 3 # The author disclaims copyright to this source code. In place of > 4 # a legal notice, here is a blessing: > 5 # > 6 # May you do good and not evil. > 7 # May you find forgiveness for yourself and forgive others. > 8 # May you share freely, never taking more than you give. > 9 # > 10 #*********************************************************************** > 11 # This file implements regression tests for the SQLite library, focusing > 12 # on the incremental vacuum feature. > 13 # > 14 # The tests in this file were added at the same time as optimizations > 15 # were made to: > 16 # > 17 # * Truncate the database after a rollback mode commit, and > 18 # > 19 # * Avoid moving pages to locations from which they may need to be moved > 20 # a second time if an incremental-vacuum proccess is allowed to vacuum > 21 # the entire database. > 22 # > 23 > 24 set testdir [file dirname $argv0] > 25 source $testdir/tester.tcl > 26 set testprefix incrvacuum3 > 27 > 28 # If this build of the library does not support auto-vacuum, omit this > 29 # whole file. > 30 ifcapable {!autovacuum || !pragma} { > 31 finish_test > 32 return > 33 } > 34 > 35 proc check_on_disk {} { > 36 > 37 # Copy the files for database "test.db" to "test2.db". > 38 forcedelete test2.db test2.db-journal test2.db-wal > 39 forcecopy test.db test2.db > 40 if {[file exists test.db-journal]} { > 41 forcecopy test.db-journal test2.db-journal > 42 } > 43 if {[file exists test.db-wal]} { > 44 forcecopy test.db-wal test2.db-wal > 45 } > 46 > 47 # Open "test2.db" and check it is Ok. > 48 sqlite3 dbcheck test2.db > 49 set ret [dbcheck eval { PRAGMA integrity_check }] > 50 dbcheck close > 51 set ret > 52 } > 53 > 54 # Run these tests once in rollback journal mode, and once in wal mode. > 55 # > 56 foreach {T jrnl_mode} { > 57 1 delete > 58 2 wal > 59 } { > 60 catch { db close } > 61 forcedelete test.db test.db-journal test.db-wal > 62 sqlite3 db test.db > 63 db eval { > 64 PRAGMA cache_size = 5; > 65 PRAGMA page_size = 1024; > 66 PRAGMA auto_vacuum = 2; > 67 } > 68 db eval "PRAGMA journal_mode = $jrnl_mode" > 69 > 70 foreach {tn sql} { > 71 1 { > 72 CREATE TABLE t1(x UNIQUE); > 73 INSERT INTO t1 VALUES(randomblob(400)); > 74 INSERT INTO t1 VALUES(randomblob(400)); > 75 INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 4 > 76 INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 8 > 77 INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 16 > 78 INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 32 > 79 INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 64 > 80 INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 128 > 81 INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 256 > 82 } > 83 > 84 2 { > 85 DELETE FROM t1 WHERE rowid%8; > 86 } > 87 > 88 3 { > 89 BEGIN; > 90 PRAGMA incremental_vacuum = 100; > 91 INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 64 > 92 INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 128 > 93 INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 256 > 94 ROLLBACK; > 95 } > 96 > 97 4 { > 98 BEGIN; > 99 SAVEPOINT one; > 100 PRAGMA incremental_vacuum = 100; > 101 SAVEPOINT two; > 102 INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 64 > 103 INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 128 > 104 INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 256 > 105 } > 106 > 107 5 { ROLLBACK to two } > 108 > 109 6 { ROLLBACK to one } > 110 > 111 7 { > 112 INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 64 > 113 PRAGMA incremental_vacuum = 1000; > 114 INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 128 > 115 INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 256 > 116 ROLLBACK; > 117 } > 118 > 119 8 { > 120 BEGIN; > 121 INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 64 > 122 PRAGMA incremental_vacuum = 1000; > 123 INSERT INTO t1 SELECT randomblob(400) FROM t1; -- 128 > 124 COMMIT; > 125 } > 126 } { > 127 do_execsql_test $T.1.$tn.1 $sql > 128 do_execsql_test $T.1.$tn.2 {PRAGMA integrity_check} ok > 129 do_test $T.1.$tn.3 { check_on_disk } ok > 130 } > 131 > 132 do_execsql_test $T.1.x.1 { PRAGMA freelist_count } 0 > 133 do_execsql_test $T.1.x.2 { SELECT count(*) FROM t1 } 128 > 134 } > 135 > 136 finish_test > 137
Changes to test/incrvacuum_ioerr.test
135 135 136 set ::rc 1 136 set ::rc 1 137 for {set iTest 1} {$::rc && $iTest<2000} {incr iTest} { 137 for {set iTest 1} {$::rc && $iTest<2000} {incr iTest} { 138 138 139 # Figure out how big the database is and how many free pages it 139 # Figure out how big the database is and how many free pages it 140 # has before running incremental-vacuum. 140 # has before running incremental-vacuum. 141 # 141 # 142 set nPage [expr {[file size test.db]/1024}] < 143 set nFree [execsql {pragma freelist_count} db1] 142 set nFree [execsql {pragma freelist_count} db1] > 143 set nPage [execsql {pragma page_count} db1] 144 144 145 # Now run incremental-vacuum to vacuum 5 pages from the db file. 145 # Now run incremental-vacuum to vacuum 5 pages from the db file. 146 # The iTest'th I/O call is set to fail. 146 # The iTest'th I/O call is set to fail. 147 # 147 # 148 set ::sqlite_io_error_pending $iTest 148 set ::sqlite_io_error_pending $iTest 149 set ::sqlite_io_error_persist 1 149 set ::sqlite_io_error_persist 1 150 do_test incrvacuum-ioerr-4.$iTest.1 { 150 do_test incrvacuum-ioerr-4.$iTest.1 { ................................................................................................................................................................................ 154 154 155 set ::sqlite_io_error_pending 0 155 set ::sqlite_io_error_pending 0 156 set ::sqlite_io_error_persist 0 156 set ::sqlite_io_error_persist 0 157 set ::sqlite_io_error_hit 0 157 set ::sqlite_io_error_hit 0 158 set ::sqlite_io_error_hardhit 0 158 set ::sqlite_io_error_hardhit 0 159 159 160 set nFree2 [execsql {pragma freelist_count} db1] 160 set nFree2 [execsql {pragma freelist_count} db1] 161 set nPage2 [expr {[file size test.db]/1024}] | 161 set nPage2 [execsql {pragma page_count} db1] 162 162 163 do_test incrvacuum-ioerr-4.$iTest.2 { 163 do_test incrvacuum-ioerr-4.$iTest.2 { 164 set shrink [expr {$nPage-$nPage2}] 164 set shrink [expr {$nPage-$nPage2}] 165 expr {$shrink==0 || $shrink==5} 165 expr {$shrink==0 || $shrink==5} 166 } {1} 166 } {1} 167 167 168 do_test incrvacuum-ioerr-4.$iTest.3 { 168 do_test incrvacuum-ioerr-4.$iTest.3 {
Changes to test/tester.tcl
1113 if {$msg=="child killed: unknown signal"} { 1113 if {$msg=="child killed: unknown signal"} { 1114 set msg "child process exited abnormally" 1114 set msg "child process exited abnormally" 1115 } 1115 } 1116 } 1116 } 1117 1117 1118 lappend r $msg 1118 lappend r $msg 1119 } 1119 } > 1120 > 1121 proc run_ioerr_prep {} { > 1122 set ::sqlite_io_error_pending 0 > 1123 catch {db close} > 1124 catch {db2 close} > 1125 catch {forcedelete test.db} > 1126 catch {forcedelete test.db-journal} > 1127 catch {forcedelete test2.db} > 1128 catch {forcedelete test2.db-journal} > 1129 set ::DB [sqlite3 db test.db; sqlite3_connection_pointer db] > 1130 sqlite3_extended_result_codes $::DB $::ioerropts(-erc) > 1131 if {[info exists ::ioerropts(-tclprep)]} { > 1132 eval $::ioerropts(-tclprep) > 1133 } > 1134 if {[info exists ::ioerropts(-sqlprep)]} { > 1135 execsql $::ioerropts(-sqlprep) > 1136 } > 1137 expr 0 > 1138 } 1120 1139 1121 # Usage: do_ioerr_test <test number> <options...> 1140 # Usage: do_ioerr_test <test number> <options...> 1122 # 1141 # 1123 # This proc is used to implement test cases that check that IO errors 1142 # This proc is used to implement test cases that check that IO errors 1124 # are correctly handled. The first argument, <test number>, is an integer 1143 # are correctly handled. The first argument, <test number>, is an integer 1125 # used to name the tests executed by this proc. Options are as follows: 1144 # used to name the tests executed by this proc. Options are as follows: 1126 # 1145 # ................................................................................................................................................................................ 1146 set ::ioerropts(-ckrefcount) 0 1165 set ::ioerropts(-ckrefcount) 0 1147 set ::ioerropts(-restoreprng) 1 1166 set ::ioerropts(-restoreprng) 1 1148 array set ::ioerropts $args 1167 array set ::ioerropts $args 1149 1168 1150 # TEMPORARY: For 3.5.9, disable testing of extended result codes. There are 1169 # TEMPORARY: For 3.5.9, disable testing of extended result codes. There are 1151 # a couple of obscure IO errors that do not return them. 1170 # a couple of obscure IO errors that do not return them. 1152 set ::ioerropts(-erc) 0 1171 set ::ioerropts(-erc) 0 > 1172 > 1173 # Create a single TCL script from the TCL and SQL specified > 1174 # as the body of the test. > 1175 set ::ioerrorbody {} > 1176 if {[info exists ::ioerropts(-tclbody)]} { > 1177 append ::ioerrorbody "$::ioerropts(-tclbody)\n" > 1178 } > 1179 if {[info exists ::ioerropts(-sqlbody)]} { > 1180 append ::ioerrorbody "db eval {$::ioerropts(-sqlbody)}" > 1181 } > 1182 > 1183 save_prng_state > 1184 if {$::ioerropts(-cksum)} { > 1185 run_ioerr_prep > 1186 eval $::ioerrorbody > 1187 set ::goodcksum [cksum] > 1188 } 1153 1189 1154 set ::go 1 1190 set ::go 1 1155 #reset_prng_state 1191 #reset_prng_state 1156 save_prng_state < 1157 for {set n $::ioerropts(-start)} {$::go} {incr n} { 1192 for {set n $::ioerropts(-start)} {$::go} {incr n} { 1158 set ::TN $n 1193 set ::TN $n 1159 incr ::ioerropts(-count) -1 1194 incr ::ioerropts(-count) -1 1160 if {$::ioerropts(-count)<0} break 1195 if {$::ioerropts(-count)<0} break 1161 1196 1162 # Skip this IO error if it was specified with the "-exclude" option. 1197 # Skip this IO error if it was specified with the "-exclude" option. 1163 if {[info exists ::ioerropts(-exclude)]} { 1198 if {[info exists ::ioerropts(-exclude)]} { ................................................................................................................................................................................ 1166 if {$::ioerropts(-restoreprng)} { 1201 if {$::ioerropts(-restoreprng)} { 1167 restore_prng_state 1202 restore_prng_state 1168 } 1203 } 1169 1204 1170 # Delete the files test.db and test2.db, then execute the TCL and 1205 # Delete the files test.db and test2.db, then execute the TCL and 1171 # SQL (in that order) to prepare for the test case. 1206 # SQL (in that order) to prepare for the test case. 1172 do_test $testname.$n.1 { 1207 do_test $testname.$n.1 { 1173 set ::sqlite_io_error_pending 0 | 1208 run_ioerr_prep 1174 catch {db close} < 1175 catch {db2 close} < 1176 catch {forcedelete test.db} < 1177 catch {forcedelete test.db-journal} < 1178 catch {forcedelete test2.db} < 1179 catch {forcedelete test2.db-journal} < 1180 set ::DB [sqlite3 db test.db; sqlite3_connection_pointer db] < 1181 sqlite3_extended_result_codes $::DB $::ioerropts(-erc) < 1182 if {[info exists ::ioerropts(-tclprep)]} { < 1183 eval $::ioerropts(-tclprep) < 1184 } < 1185 if {[info exists ::ioerropts(-sqlprep)]} { < 1186 execsql $::ioerropts(-sqlprep) < 1187 } < 1188 expr 0 < 1189 } {0} 1209 } {0} 1190 1210 1191 # Read the 'checksum' of the database. 1211 # Read the 'checksum' of the database. 1192 if {$::ioerropts(-cksum)} { 1212 if {$::ioerropts(-cksum)} { 1193 set checksum [cksum] | 1213 set ::checksum [cksum] 1194 } 1214 } 1195 1215 1196 # Set the Nth IO error to fail. 1216 # Set the Nth IO error to fail. 1197 do_test $testname.$n.2 [subst { 1217 do_test $testname.$n.2 [subst { 1198 set ::sqlite_io_error_persist $::ioerropts(-persist) 1218 set ::sqlite_io_error_persist $::ioerropts(-persist) 1199 set ::sqlite_io_error_pending $n 1219 set ::sqlite_io_error_pending $n 1200 }] $n 1220 }] $n 1201 | 1221 1202 # Create a single TCL script from the TCL and SQL specified | 1222 # Execute the TCL script created for the body of this test. If 1203 # as the body of the test. < 1204 set ::ioerrorbody {} < 1205 if {[info exists ::ioerropts(-tclbody)]} { < 1206 append ::ioerrorbody "$::ioerropts(-tclbody)\n" < 1207 } < 1208 if {[info exists ::ioerropts(-sqlbody)]} { < 1209 append ::ioerrorbody "db eval {$::ioerropts(-sqlbody)}" < 1210 } < 1211 < 1212 # Execute the TCL Script created in the above block. If < 1213 # there are at least N IO operations performed by SQLite as | 1223 # at least N IO operations performed by SQLite as a result of 1214 # a result of the script, the Nth will fail. | 1224 # the script, the Nth will fail. 1215 do_test $testname.$n.3 { 1225 do_test $testname.$n.3 { 1216 set ::sqlite_io_error_hit 0 1226 set ::sqlite_io_error_hit 0 1217 set ::sqlite_io_error_hardhit 0 1227 set ::sqlite_io_error_hardhit 0 1218 set r [catch $::ioerrorbody msg] 1228 set r [catch $::ioerrorbody msg] 1219 set ::errseen $r 1229 set ::errseen $r 1220 set rc [sqlite3_errcode $::DB] 1230 set rc [sqlite3_errcode $::DB] 1221 if {$::ioerropts(-erc)} { 1231 if {$::ioerropts(-erc)} { ................................................................................................................................................................................ 1311 # be the same as before the script that caused the IO error was run. 1321 # be the same as before the script that caused the IO error was run. 1312 # 1322 # 1313 if {$::go && $::sqlite_io_error_hardhit && $::ioerropts(-cksum)} { 1323 if {$::go && $::sqlite_io_error_hardhit && $::ioerropts(-cksum)} { 1314 do_test $testname.$n.6 { 1324 do_test $testname.$n.6 { 1315 catch {db close} 1325 catch {db close} 1316 catch {db2 close} 1326 catch {db2 close} 1317 set ::DB [sqlite3 db test.db; sqlite3_connection_pointer db] 1327 set ::DB [sqlite3 db test.db; sqlite3_connection_pointer db] 1318 cksum | 1328 set nowcksum [cksum] > 1329 set res [expr {$nowcksum==$::checksum || $nowcksum==$::goodcksum}] > 1330 if {$res==0} { > 1331 puts "now=$nowcksum" 1319 } $checksum | 1332 puts "the=$::checksum" > 1333 puts "fwd=$::goodcksum" > 1334 } > 1335 set res > 1336 } 1 1320 } 1337 } 1321 1338 1322 set ::sqlite_io_error_hardhit 0 1339 set ::sqlite_io_error_hardhit 0 1323 set ::sqlite_io_error_pending 0 1340 set ::sqlite_io_error_pending 0 1324 if {[info exists ::ioerropts(-cleanup)]} { 1341 if {[info exists ::ioerropts(-cleanup)]} { 1325 catch $::ioerropts(-cleanup) 1342 catch $::ioerropts(-cleanup) 1326 } 1343 }
Changes to test/tkt3762.test
6 # May you do good and not evil. 6 # May you do good and not evil. 7 # May you find forgiveness for yourself and forgive others. 7 # May you find forgiveness for yourself and forgive others. 8 # May you share freely, never taking more than you give. 8 # May you share freely, never taking more than you give. 9 # 9 # 10 #*********************************************************************** 10 #*********************************************************************** 11 # 11 # 12 # Ticket #3762: Make sure that an incremental vacuum that reduces the 12 # Ticket #3762: Make sure that an incremental vacuum that reduces the 13 # size of the database file such that a pointer-map page is elemented | 13 # size of the database file such that if a pointer-map page is eliminated 14 # can be correctly rolled back. | 14 # it can be correctly rolled back. 15 # 15 # 16 # That ticket #3762 has been fixed has already been verified by the 16 # That ticket #3762 has been fixed has already been verified by the 17 # savepoint6.test test script. But this script is simplier and a 17 # savepoint6.test test script. But this script is simplier and a 18 # redundant test never hurts. 18 # redundant test never hurts. 19 # 19 # 20 # $Id: tkt3762.test,v 1.1 2009/03/31 00:50:36 drh Exp $ 20 # $Id: tkt3762.test,v 1.1 2009/03/31 00:50:36 drh Exp $ 21 21