From d092df51deeab776f9782347a8bb7f535a66daa6 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 18 Feb 2015 17:40:05 +0000 Subject: [PATCH] Fix a problem with OTA updates in the presence of database readers. FossilOrigin-Name: 144bb29ffcbfe96dc10c0224113e73a80e89314b --- ext/ota/ota3.test | 20 +++- ext/ota/ota6.test | 5 +- ext/ota/otafault.test | 112 ++++++++++++------- ext/ota/sqlite3ota.c | 244 ++++++++++++++++++++++++------------------ manifest | 18 ++-- manifest.uuid | 2 +- 6 files changed, 243 insertions(+), 158 deletions(-) diff --git a/ext/ota/ota3.test b/ext/ota/ota3.test index da29454b9a..6e1645edda 100644 --- a/ext/ota/ota3.test +++ b/ext/ota/ota3.test @@ -26,6 +26,10 @@ proc run_ota {target ota} { } forcedelete test.db-oal ota.db +db close +sqlite3_shutdown +sqlite3_config_uri 1 +reset_db #-------------------------------------------------------------------- # Test that for an OTA to be applied, no corruption results if the @@ -127,7 +131,6 @@ do_test 2.4 { INSERT INTO data_x2 VALUES(1, 'a', 2, 3, 0); } db2 close - breakpoint list [catch { run_ota test.db ota.db } msg] $msg } {1 SQLITE_ERROR} @@ -153,5 +156,20 @@ do_test 3.2 { sqlite3ota_destroy_vfs win32 } {} +#------------------------------------------------------------------------- +# Test that it is an error to specify an explicit VFS that does not +# include ota VFS functionality. +# +do_test 4.1 { + testvfs tvfs + sqlite3ota ota file:test.db?vfs=tvfs ota.db + list [catch { ota step } msg] $msg +} {0 SQLITE_ERROR} +do_test 4.2 { + list [catch { ota close } msg] $msg +} {1 {SQLITE_ERROR - ota vfs not found}} +tvfs delete + finish_test + diff --git a/ext/ota/ota6.test b/ext/ota/ota6.test index 3b794ee77c..4fe14950b4 100644 --- a/ext/ota/ota6.test +++ b/ext/ota/ota6.test @@ -45,7 +45,7 @@ proc setup_test {} { # file is being generated. Once this has happened, the update cannot be # progressed. # -for {set nStep 1} {$nStep < 7} {incr nStep} { +for {set nStep 1} {$nStep < 8} {incr nStep} { do_test 1.$nStep.1 { setup_test sqlite3ota ota test.db ota.db @@ -68,12 +68,11 @@ for {set nStep 1} {$nStep < 7} {incr nStep} { } {1 {SQLITE_BUSY - database modified during ota update}} } - # Test the outcome of some other client writing the db after the *-oal # file has been copied to the *-wal path. Once this has happened, any # other client writing to the db causes OTA to consider its job finished. # -for {set nStep 7} {$nStep < 20} {incr nStep} { +for {set nStep 8} {$nStep < 20} {incr nStep} { do_test 1.$nStep.1 { setup_test sqlite3ota ota test.db ota.db diff --git a/ext/ota/otafault.test b/ext/ota/otafault.test index efc66673d6..d49f9d58f3 100644 --- a/ext/ota/otafault.test +++ b/ext/ota/otafault.test @@ -37,7 +37,9 @@ foreach {tn2 setup sql expect} { INSERT INTO data_t1 VALUES(2, NULL, NULL, 1); INSERT INTO data_t1 VALUES(3, 'three', NULL, '.x.'); INSERT INTO data_t1 VALUES(4, 4, 4, 0); - } {SELECT * FROM t1} {1 1 1 3 three 3 4 4 4} + } { + SELECT * FROM t1 + } {1 1 1 3 three 3 4 4 4} 2 { CREATE TABLE t2(a PRIMARY KEY, b, c) WITHOUT ROWID; @@ -50,7 +52,9 @@ foreach {tn2 setup sql expect} { INSERT INTO data_t2 VALUES('b', NULL, NULL, 1); INSERT INTO data_t2 VALUES('c', 'see', NULL, '.x.'); INSERT INTO data_t2 VALUES('d', 'd', 'd', 0); - } {SELECT * FROM t2} {a a a c see c d d d} + } { + SELECT * FROM t2 + } {a a a c see c d d d} 3 { CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); @@ -62,7 +66,23 @@ foreach {tn2 setup sql expect} { CREATE TABLE ota.data_t2(a, b, c, ota_control); INSERT INTO data_t1 VALUES(1, 2, 3, 0); INSERT INTO data_t2 VALUES(4, 5, 6, 0); - } {SELECT * FROM t1 UNION ALL SELECT * FROM t2} {1 2 3 4 5 6} + } { + SELECT * FROM t1 UNION ALL SELECT * FROM t2 + } {1 2 3 4 5 6} + + 4 { + CREATE TABLE t1(a PRIMARY KEY, b, c); + CREATE INDEX t1c ON t1(c); + INSERT INTO t1 VALUES('A', 'B', 'C'); + INSERT INTO t1 VALUES('D', 'E', 'F'); + + CREATE TABLE ota.data_t1(a, b, c, ota_control); + INSERT INTO data_t1 VALUES('D', NULL, NULL, 1); + INSERT INTO data_t1 VALUES('A', 'Z', NULL, '.x.'); + INSERT INTO data_t1 VALUES('G', 'H', 'I', 0); + } { + SELECT * FROM t1 ORDER BY a; + } {A Z C G H I} } { catch {db close} @@ -137,47 +157,59 @@ foreach {tn2 setup sql expect} { autoinstall_test_functions - } - - for {set iStep 0} {$iStep<=21} {incr iStep} { - - forcedelete test.db-journal test.db-wal ota.db-journal ota.db-wal - - copy_if_exists test.db.bak test.db - copy_if_exists ota.db.bak ota.db - - sqlite3ota ota test.db ota.db - for {set x 0} {$x < $::iStep} {incr x} { ota step } - ota close - - copy_if_exists test.db test.db.bak.2 - copy_if_exists test.db-wal test.db.bak.2-wal - copy_if_exists test.db-oal test.db.bak.2-oal - copy_if_exists ota.db ota.db.bak.2 - - do_faultsim_test 3.$tn.$iStep -faults $::f -prep { - catch { db close } + for {set iStep 0} {$iStep<=21} {incr iStep} { + forcedelete test.db-journal test.db-wal ota.db-journal ota.db-wal - copy_if_exists test.db.bak.2 test.db - copy_if_exists test.db.bak.2-wal test.db-wal - copy_if_exists test.db.bak.2-oal test.db-oal - copy_if_exists ota.db.bak.2 ota.db - } -body { + + copy_if_exists test.db.bak test.db + copy_if_exists ota.db.bak ota.db + sqlite3ota ota test.db ota.db - while {[ota step] == "SQLITE_OK"} {} + for {set x 0} {$x < $::iStep} {incr x} { ota step } ota close - } -test { - faultsim_test_result {*}$::reslist + +# sqlite3 x ota.db ; puts "XYZ [x eval { SELECT * FROM ota_state } ]" ; x close - if {$testrc==0} { - sqlite3 db test.db - faultsim_integrity_check - set res [db eval $::sql] - if {$res != [list {*}$::expect]} { - puts "" - puts "res: $res" - puts "exp: $expected" - error "data not as expected!" + copy_if_exists test.db test.db.bak.2 + copy_if_exists test.db-wal test.db.bak.2-wal + copy_if_exists test.db-oal test.db.bak.2-oal + copy_if_exists ota.db ota.db.bak.2 + + do_faultsim_test 3.$tn.$iStep -faults $::f -prep { + catch { db close } + forcedelete test.db-journal test.db-wal ota.db-journal ota.db-wal + copy_if_exists test.db.bak.2 test.db + copy_if_exists test.db.bak.2-wal test.db-wal + copy_if_exists test.db.bak.2-oal test.db-oal + copy_if_exists ota.db.bak.2 ota.db + } -body { + sqlite3ota ota test.db ota.db + ota step + ota close + } -test { + + if {$testresult=="SQLITE_OK"} {set testresult "SQLITE_DONE"} + faultsim_test_result {*}$::reslist + + if {$testrc==0} { + # No error occurred. If the OTA has not already been fully applied, + # apply the rest of it now. Then ensure that the final state of the + # target db is as expected. And that "PRAGMA integrity_check" + # passes. + sqlite3ota ota test.db ota.db + while {[ota step] == "SQLITE_OK"} {} + ota close + + sqlite3 db test.db + faultsim_integrity_check + + set res [db eval $::sql] + if {$res != [list {*}$::expect]} { + puts "" + puts "res: $res" + puts "exp: $::expect" + error "data not as expected!" + } } } } diff --git a/ext/ota/sqlite3ota.c b/ext/ota/sqlite3ota.c index b4a475bc0a..0ef1954811 100644 --- a/ext/ota/sqlite3ota.c +++ b/ext/ota/sqlite3ota.c @@ -75,9 +75,10 @@ #define OTA_STATE_COOKIE 7 #define OTA_STAGE_OAL 1 -#define OTA_STAGE_CAPTURE 2 -#define OTA_STAGE_CKPT 3 -#define OTA_STAGE_DONE 4 +#define OTA_STAGE_MOVE 2 +#define OTA_STAGE_CAPTURE 3 +#define OTA_STAGE_CKPT 4 +#define OTA_STAGE_DONE 5 #define OTA_CREATE_STATE "CREATE TABLE IF NOT EXISTS ota.ota_state" \ @@ -949,7 +950,7 @@ static char *otaObjIterGetOldlist( /* For a table with implicit rowids, append "old._rowid_" to the list. */ if( pIter->eType==OTA_PK_EXTERNAL || pIter->eType==OTA_PK_NONE ){ - zList = sqlite3_mprintf("%z, %s._rowid_", zList, zObj); + zList = otaMPrintf(p, "%z, %s._rowid_", zList, zObj); } } return zList; @@ -1116,6 +1117,11 @@ static char *otaWithoutRowidPK(sqlite3ota *p, OtaObjIter *pIter){ return z; } +static void otaFinalize(sqlite3ota *p, sqlite3_stmt *pStmt){ + int rc = sqlite3_finalize(pStmt); + if( p->rc==SQLITE_OK ) p->rc = rc; +} + /* ** This function creates the second imposter table used when writing to ** a table b-tree where the table has an external primary key. If the @@ -1160,18 +1166,13 @@ static void otaCreateImposterTable2(sqlite3ota *p, OtaObjIter *pIter){ if( SQLITE_ROW==sqlite3_step(pQuery) ){ zIdx = (const char*)sqlite3_column_text(pQuery, 0); } - if( zIdx==0 ){ - p->rc = SQLITE_CORRUPT; - } } - assert( (zIdx==0)==(p->rc!=SQLITE_OK) ); - - if( p->rc==SQLITE_OK ){ + if( zIdx ){ p->rc = prepareFreeAndCollectError(p->db, &pXInfo, &p->zErrmsg, sqlite3_mprintf("PRAGMA main.index_xinfo = %Q", zIdx) ); } - sqlite3_finalize(pQuery); + otaFinalize(p, pQuery); while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){ int bKey = sqlite3_column_int(pXInfo, 5); @@ -1680,6 +1681,20 @@ static void otaCheckpointFrame(sqlite3ota *p, OtaFrame *pFrame){ } } + +/* +** Take an EXCLUSIVE lock on the database file. +*/ +static void otaLockDatabase(sqlite3ota *p){ + if( p->rc==SQLITE_OK ){ + sqlite3_file *pReal = p->pTargetFd->pReal; + p->rc = pReal->pMethods->xLock(pReal, SQLITE_LOCK_SHARED); + if( p->rc==SQLITE_OK ){ + p->rc = pReal->pMethods->xLock(pReal, SQLITE_LOCK_EXCLUSIVE); + } + } +} + /* ** The OTA handle is currently in OTA_STAGE_OAL state, with a SHARED lock ** on the database file. This proc moves the *-oal file to the *-wal path, @@ -1693,24 +1708,31 @@ static void otaMoveOalFile(sqlite3ota *p){ char *zWal = sqlite3_mprintf("%s-wal", zBase); char *zOal = sqlite3_mprintf("%s-oal", zBase); - assert( p->eStage==OTA_STAGE_OAL ); + assert( p->eStage==OTA_STAGE_MOVE ); assert( p->rc==SQLITE_OK && p->zErrmsg==0 ); if( zWal==0 || zOal==0 ){ p->rc = SQLITE_NOMEM; }else{ /* Move the *-oal file to *-wal. At this point connection p->db is ** holding a SHARED lock on the target database file (because it is - ** in WAL mode). So no other connection may be writing the db. */ - otaFileSuffix3(zBase, zWal); - otaFileSuffix3(zBase, zOal); - rename(zOal, zWal); - - /* Re-open the databases. */ - otaObjIterFinalize(&p->objiter); - sqlite3_close(p->db); - p->db = 0; - otaOpenDatabase(p); - otaSetupCheckpoint(p, 0); + ** in WAL mode). So no other connection may be writing the db. + ** + ** In order to ensure that there are no database readers, an EXCLUSIVE + ** lock is obtained here before the *-oal is moved to *-wal. + */ + otaLockDatabase(p); + if( p->rc==SQLITE_OK ){ + otaFileSuffix3(zBase, zWal); + otaFileSuffix3(zBase, zOal); + rename(zOal, zWal); + + /* Re-open the databases. */ + otaObjIterFinalize(&p->objiter); + sqlite3_close(p->db); + p->db = 0; + otaOpenDatabase(p); + otaSetupCheckpoint(p, 0); + } } sqlite3_free(zWal); @@ -1904,24 +1926,66 @@ static int otaStep(sqlite3ota *p){ ** Increment the schema cookie of the main database opened by p->db. */ static void otaIncrSchemaCookie(sqlite3ota *p){ - int iCookie = 1000000; - sqlite3_stmt *pStmt; - - assert( p->rc==SQLITE_OK && p->zErrmsg==0 ); - p->rc = prepareAndCollectError(p->db, &pStmt, &p->zErrmsg, - "PRAGMA schema_version" - ); if( p->rc==SQLITE_OK ){ - if( SQLITE_ROW==sqlite3_step(pStmt) ){ - iCookie = sqlite3_column_int(pStmt, 0); + int iCookie = 1000000; + sqlite3_stmt *pStmt; + + p->rc = prepareAndCollectError(p->db, &pStmt, &p->zErrmsg, + "PRAGMA schema_version" + ); + if( p->rc==SQLITE_OK ){ + if( SQLITE_ROW==sqlite3_step(pStmt) ){ + iCookie = sqlite3_column_int(pStmt, 0); + } + p->rc = sqlite3_finalize(pStmt); + } + if( p->rc==SQLITE_OK ){ + otaMPrintfExec(p, "PRAGMA schema_version = %d", iCookie+1); } - p->rc = sqlite3_finalize(pStmt); } - if( p->rc==SQLITE_OK ){ - otaMPrintfExec(p, "PRAGMA schema_version = %d", iCookie+1); +} + +static void otaSaveState(sqlite3ota *p, int eStage){ + if( p->rc==SQLITE_OK || p->rc==SQLITE_DONE ){ + sqlite3_stmt *pInsert = 0; + int rc; + + assert( p->zErrmsg==0 ); + rc = prepareFreeAndCollectError(p->db, &pInsert, &p->zErrmsg, + sqlite3_mprintf( + "INSERT OR REPLACE INTO ota.ota_state(k, v) VALUES " + "(%d, %d), " + "(%d, %Q), " + "(%d, %Q), " + "(%d, %d), " + "(%d, %lld), " + "(%d, %lld), " + "(%d, %lld) ", + OTA_STATE_STAGE, eStage, + OTA_STATE_TBL, p->objiter.zTbl, + OTA_STATE_IDX, p->objiter.zIdx, + OTA_STATE_ROW, p->nStep, + OTA_STATE_PROGRESS, p->nProgress, + OTA_STATE_CKPT, p->iWalCksum, + OTA_STATE_COOKIE, (i64)p->pTargetFd->iCookie + ) + ); + assert( pInsert==0 || rc==SQLITE_OK ); + + if( rc==SQLITE_OK ){ + sqlite3_step(pInsert); + rc = sqlite3_finalize(pInsert); + }else{ + sqlite3_finalize(pInsert); + } + + if( rc!=SQLITE_OK ){ + p->rc = rc; + } } } + /* ** Step the OTA object. */ @@ -1959,14 +2023,20 @@ int sqlite3ota_step(sqlite3ota *p){ } if( p->rc==SQLITE_OK && pIter->zTbl==0 ){ - p->nProgress++; + otaSaveState(p, OTA_STAGE_MOVE); otaIncrSchemaCookie(p); if( p->rc==SQLITE_OK ){ p->rc = sqlite3_exec(p->db, "COMMIT", 0, 0, &p->zErrmsg); } - if( p->rc==SQLITE_OK ){ - otaMoveOalFile(p); - } + p->eStage = OTA_STAGE_MOVE; + } + break; + } + + case OTA_STAGE_MOVE: { + if( p->rc==SQLITE_OK ){ + otaMoveOalFile(p); + p->nProgress++; } break; } @@ -2010,44 +2080,6 @@ int sqlite3ota_step(sqlite3ota *p){ } } -static void otaSaveState(sqlite3ota *p){ - sqlite3_stmt *pInsert; - int rc; - - assert( (p->rc==SQLITE_OK || p->rc==SQLITE_DONE) && p->zErrmsg==0 ); - rc = prepareFreeAndCollectError(p->db, &pInsert, &p->zErrmsg, - sqlite3_mprintf( - "INSERT OR REPLACE INTO ota.ota_state(k, v) VALUES " - "(%d, %d), " - "(%d, %Q), " - "(%d, %Q), " - "(%d, %d), " - "(%d, %lld), " - "(%d, %lld), " - "(%d, %lld) ", - OTA_STATE_STAGE, p->eStage, - OTA_STATE_TBL, p->objiter.zTbl, - OTA_STATE_IDX, p->objiter.zIdx, - OTA_STATE_ROW, p->nStep, - OTA_STATE_PROGRESS, p->nProgress, - OTA_STATE_CKPT, p->iWalCksum, - OTA_STATE_COOKIE, (i64)p->pTargetFd->iCookie - ) - ); - assert( pInsert==0 || rc==SQLITE_OK ); - - if( rc==SQLITE_OK ){ - sqlite3_step(pInsert); - rc = sqlite3_finalize(pInsert); - }else{ - sqlite3_finalize(pInsert); - } - - if( rc!=SQLITE_OK ){ - p->rc = rc; - } -} - static void otaFreeState(OtaState *p){ if( p ){ sqlite3_free(p->zTbl); @@ -2081,6 +2113,7 @@ static OtaState *otaLoadState(sqlite3ota *p){ case OTA_STATE_STAGE: pRet->eStage = sqlite3_column_int(pStmt, 1); if( pRet->eStage!=OTA_STAGE_OAL + && pRet->eStage!=OTA_STAGE_MOVE && pRet->eStage!=OTA_STAGE_CKPT ){ p->rc = SQLITE_CORRUPT; @@ -2236,26 +2269,28 @@ sqlite3ota *sqlite3ota_open(const char *zTarget, const char *zOta){ } assert( p->rc!=SQLITE_OK || p->eStage!=0 ); - if( p->rc==SQLITE_OK ){ - if( p->eStage==OTA_STAGE_OAL ){ + if( p->rc==SQLITE_OK + && (p->eStage==OTA_STAGE_OAL || p->eStage==OTA_STAGE_MOVE) + ){ + /* Check that this is not a wal mode database. If it is, it cannot + ** be updated. */ + if( p->pTargetFd->pWalFd ){ + p->rc = SQLITE_ERROR; + p->zErrmsg = sqlite3_mprintf("cannot update wal mode database"); + } - /* Check that this is not a wal mode database. If it is, it cannot - ** be updated. */ - if( p->pTargetFd->pWalFd ){ - p->rc = SQLITE_ERROR; - p->zErrmsg = sqlite3_mprintf("cannot update wal mode database"); - } + /* At this point (pTargetFd->iCookie) contains the value of the + ** change-counter cookie (the thing that gets incremented when a + ** transaction is committed in rollback mode) currently stored on + ** page 1 of the database file. */ + else if( pState->eStage!=0 && p->pTargetFd->iCookie!=pState->iCookie ){ + p->rc = SQLITE_BUSY; + p->zErrmsg = sqlite3_mprintf("database modified during ota update"); + } + } - /* At this point (pTargetFd->iCookie) contains the value of the - ** change-counter cookie (the thing that gets incremented when a - ** transaction is committed in rollback mode) currently stored on - ** page 1 of the database file. */ - else if( pState->eStage==OTA_STAGE_OAL - && p->pTargetFd->iCookie!=pState->iCookie - ){ - p->rc = SQLITE_BUSY; - p->zErrmsg = sqlite3_mprintf("database modified during ota update"); - } + if( p->rc==SQLITE_OK ){ + if( p->eStage==OTA_STAGE_OAL ){ /* Open the transaction */ if( p->rc==SQLITE_OK ){ @@ -2270,6 +2305,8 @@ sqlite3ota *sqlite3ota_open(const char *zTarget, const char *zOta){ if( p->rc==SQLITE_OK ){ otaLoadTransactionState(p, pState); } + }else if( p->eStage==OTA_STAGE_MOVE ){ + /* no-op */ }else if( p->eStage==OTA_STAGE_CKPT ){ otaSetupCheckpoint(p, pState); p->nStep = pState->nRow; @@ -2325,10 +2362,7 @@ int sqlite3ota_close(sqlite3ota *p, char **pzErrmsg){ ** the ota db. If successful, this call also commits the open ** transaction on the ota db. */ assert( p->rc!=SQLITE_ROW ); - if( p->rc==SQLITE_OK || p->rc==SQLITE_DONE ){ - assert( p->zErrmsg==0 ); - otaSaveState(p); - } + otaSaveState(p, p->eStage); /* Close any open statement handles. */ otaObjIterFinalize(&p->objiter); @@ -2627,7 +2661,7 @@ static int otaVfsShmLock(sqlite3_file *pFile, int ofst, int n, int flags){ #endif assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) ); - if( pOta && pOta->eStage==OTA_STAGE_OAL ){ + if( pOta && (pOta->eStage==OTA_STAGE_OAL || pOta->eStage==OTA_STAGE_MOVE) ){ /* Magic number 1 is the WAL_CKPT_LOCK lock. Preventing SQLite from ** taking this lock also prevents any checkpoints from occurring. ** todo: really, it's not clear why this might occur, as @@ -2636,7 +2670,7 @@ static int otaVfsShmLock(sqlite3_file *pFile, int ofst, int n, int flags){ }else{ int bCapture = 0; if( n==1 && (flags & SQLITE_SHM_EXCLUSIVE) - && p->pOta && p->pOta->eStage==OTA_STAGE_CAPTURE + && pOta && pOta->eStage==OTA_STAGE_CAPTURE && (ofst==WAL_LOCK_WRITE || ofst==WAL_LOCK_CKPT || ofst==WAL_LOCK_READ0) ){ bCapture = 1; @@ -2645,7 +2679,7 @@ static int otaVfsShmLock(sqlite3_file *pFile, int ofst, int n, int flags){ if( bCapture==0 || 0==(flags & SQLITE_SHM_UNLOCK) ){ rc = p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags); if( bCapture && rc==SQLITE_OK ){ - p->pOta->mLock |= (1 << ofst); + pOta->mLock |= (1 << ofst); } } } @@ -2662,12 +2696,13 @@ static int otaVfsShmMap( ){ ota_file *p = (ota_file*)pFile; int rc = SQLITE_OK; + int eStage = (p->pOta ? p->pOta->eStage : 0); /* If not in OTA_STAGE_OAL, allow this call to pass through. Or, if this ** ota is in the OTA_STAGE_OAL state, use heap memory for *-shm space ** instead of a file on disk. */ assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) ); - if( p->pOta && p->pOta->eStage==OTA_STAGE_OAL ){ + if( eStage==OTA_STAGE_OAL || eStage==OTA_STAGE_MOVE ){ if( iRegion<=p->nShm ){ int nByte = (iRegion+1) * sizeof(char*); char **apNew = (char**)sqlite3_realloc(p->apShm, nByte); @@ -2714,9 +2749,10 @@ static void otaVfsShmBarrier(sqlite3_file *pFile){ static int otaVfsShmUnmap(sqlite3_file *pFile, int delFlag){ ota_file *p = (ota_file*)pFile; int rc = SQLITE_OK; + int eStage = (p->pOta ? p->pOta->eStage : 0); assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) ); - if( p->pOta && p->pOta->eStage==OTA_STAGE_OAL ){ + if( eStage==OTA_STAGE_OAL || eStage==OTA_STAGE_MOVE ){ /* no-op */ }else{ rc = p->pReal->pMethods->xShmUnmap(p->pReal, delFlag); diff --git a/manifest b/manifest index 66b0b3d829..48056fe9f6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improve\stest\scoverage\sof\sota\scode\sa\sbit. -D 2015-02-17T20:49:42.756 +C Fix\sa\sproblem\swith\sOTA\supdates\sin\sthe\spresence\sof\sdatabase\sreaders. +D 2015-02-18T17:40:05.856 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 6b9e7677829aa94b9f30949656e27312aefb9a46 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -128,15 +128,15 @@ F ext/ota/ota.c c11a85af71dccc45976622fe7a51169a481caa91 F ext/ota/ota1.test 88a47987dc12780c23d9efbeb0e9416c838eb1f6 F ext/ota/ota10.test 85e0f6e7964db5007590c1b299e75211ed4240d4 F ext/ota/ota11.test 0a0c56b9474f82097018a8f399172417737c64c9 -F ext/ota/ota3.test cd654ef16fc6b3d3596894ee3f3b8fd821b969f5 +F ext/ota/ota3.test 59fc88cf9749156c8a0b3ed9210b72a6af3f29d0 F ext/ota/ota5.test ad0799daf8923ddebffe75ae8c5504ca90b7fadb -F ext/ota/ota6.test 40996b7716dee72a6c5d28c3bee436717a438d3d +F ext/ota/ota6.test 3bde7f69a894748b27206b6753462ec3b75b6bb6 F ext/ota/ota7.test 1fe2c5761705374530e29f70c39693076028221a F ext/ota/ota8.test cd70e63a0c29c45c0906692827deafa34638feda F ext/ota/ota9.test d3eee95dd836824d07a22e5efcdb7bf6e869358b F ext/ota/otaA.test ef4bfa8cfd4ed814ae86f7457b64aa2f18c90171 -F ext/ota/otafault.test 0c7565f69e5e379a5ebdcaea4056f0c69da1becf -F ext/ota/sqlite3ota.c 0c6cb4cea1a9231bc488e9c84da201b796437af6 +F ext/ota/otafault.test c17e0297b4d2b83115fa733b614cf4883cd826f2 +F ext/ota/sqlite3ota.c f04e79519f275ae932ad3573a089e2ef08552a78 F ext/ota/sqlite3ota.h 1cc7201086fe65a36957740381485a24738c4077 F ext/ota/test_ota.c 5dd58e4e6eb3ae7b471566616d44b701971bce88 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 @@ -1256,7 +1256,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P e0b7151962fedbcac975f2216fd6b33b995a8945 -R 13b826f0fe6f2960ec7719bf830cc36a +P a438fa6c9ad2fb1d78ac747172d07455d6381387 +R 4b928e3e4481330de038aee8bbb8f63e U dan -Z 295fff9fbb7cdd54355b757b10496bab +Z 71e8a5928d01f269472bf7adff7d46be diff --git a/manifest.uuid b/manifest.uuid index 3de9df0122..4a97b0bd4d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a438fa6c9ad2fb1d78ac747172d07455d6381387 \ No newline at end of file +144bb29ffcbfe96dc10c0224113e73a80e89314b \ No newline at end of file -- 2.47.3