Fix a problem with OTA updates in the presence of database readers.

FossilOrigin-Name: 144bb29ffcbfe96dc10c0224113e73a80e89314b
This commit is contained in:
dan 2015-02-18 17:40:05 +00:00
parent eadc772beb
commit d092df51de
6 changed files with 246 additions and 161 deletions

View File

@ -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

View File

@ -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

View File

@ -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 }
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
while {[ota step] == "SQLITE_OK"} {}
ota close
} -test {
faultsim_test_result {*}$::reslist
for {set iStep 0} {$iStep<=21} {incr iStep} {
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!"
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
# sqlite3 x ota.db ; puts "XYZ [x eval { SELECT * FROM ota_state } ]" ; x 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 }
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!"
}
}
}
}

View File

@ -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);
** 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);
/* 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;
if( p->rc==SQLITE_OK ){
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);
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,27 +2269,29 @@ sqlite3ota *sqlite3ota_open(const char *zTarget, const char *zOta){
}
assert( p->rc!=SQLITE_OK || p->eStage!=0 );
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");
}
/* 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");
}
}
if( p->rc==SQLITE_OK ){
if( p->eStage==OTA_STAGE_OAL ){
/* 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==OTA_STAGE_OAL
&& p->pTargetFd->iCookie!=pState->iCookie
){
p->rc = SQLITE_BUSY;
p->zErrmsg = sqlite3_mprintf("database modified during ota update");
}
/* Open the transaction */
if( p->rc==SQLITE_OK ){
p->rc = sqlite3_exec(p->db, "BEGIN IMMEDIATE", 0, 0, &p->zErrmsg);
@ -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);

View File

@ -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

View File

@ -1 +1 @@
a438fa6c9ad2fb1d78ac747172d07455d6381387
144bb29ffcbfe96dc10c0224113e73a80e89314b