Index: src/wal.c ================================================================== --- src/wal.c +++ src/wal.c @@ -1907,10 +1907,13 @@ ** the wal-index header do not match the contents of the ** file-system. To avoid this, update the wal-index header to ** indicate that the log file contains zero valid frames. */ walRestartHdr(pWal, salt1); rc = sqlite3OsTruncate(pWal->pWalFd, 0); + }else if( walIsServer(pWal) ){ + assert( eMode==SQLITE_CHECKPOINT_RESTART ); + walRestartHdr(pWal, salt1); } walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1); } } } @@ -3124,11 +3127,11 @@ } /* See if it is possible to write these frames into the start of the ** log file, instead of appending to it at pWal->hdr.mxFrame. */ - if( SQLITE_OK!=(rc = walRestartLog(pWal)) ){ + if( walIsServer(pWal)==0 && SQLITE_OK!=(rc = walRestartLog(pWal)) ){ return rc; } /* If this is the first frame written into the log, write the WAL ** header to the start of the WAL file. See comments at the top of @@ -3377,11 +3380,17 @@ ** writer lock retried until either the busy-handler returns 0 or the ** lock is successfully obtained. */ if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){ if( walIsServer(pWal) ){ - rc = sqlite3ServerLock(pWal->pServer, 0, 1, 1); + if( eMode>=SQLITE_CHECKPOINT_RESTART ){ + /* Exclusive lock on page 1. This is exclusive access to the db. */ + rc = sqlite3ServerLock(pWal->pServer, 1, 1, 1); + }else{ + /* Take the server write-lock ("page" 0) */ + rc = sqlite3ServerLock(pWal->pServer, 0, 1, 1); + } }else{ rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_WRITE_LOCK, 1); } if( rc==SQLITE_OK ){ pWal->writeLock = 1; @@ -3429,10 +3438,11 @@ /* Release the locks. */ sqlite3WalEndWriteTransaction(pWal); walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1); pWal->ckptLock = 0; WALTRACE(("WAL%p: checkpoint %s\n", pWal, rc ? "failed" : "ok")); + if( walIsServer(pWal) ) sqlite3ServerEnd(pWal->pServer); return (rc==SQLITE_OK && eMode!=eMode2 ? SQLITE_BUSY : rc); } /* Return the value to pass to a sqlite3_wal_hook callback, the ** number of frames in the WAL at the point of the last commit since Index: test/serverwal.test ================================================================== --- test/serverwal.test +++ test/serverwal.test @@ -59,10 +59,11 @@ do_test 2.2 { execsql COMMIT db execsql COMMIT db2 } {} db close +db2 close #------------------------------------------------------------------------- # That the wal file can be wrapped around. # reset_db @@ -77,11 +78,11 @@ } {wal} do_test 3.1 { set N [file size test.db-wal] execsql { - PRAGMA wal_checkpoint; + PRAGMA wal_checkpoint = restart; INSERT INTO ttt VALUES(11, 12); INSERT INTO ttt VALUES(13, 14); } expr {$N == [file size test.db-wal]} } {1} @@ -107,7 +108,31 @@ UPDATE ttt SET b=a; ROLLBACK; PRAGMA integrity_check; } {ok ok} +reset_db +do_execsql_test 5.1 { + CREATE TABLE xyz(a); + PRAGMA journal_mode = wal; + INSERT INTO xyz VALUES(1); + INSERT INTO xyz VALUES(2); + INSERT INTO xyz VALUES(3); +} {wal} + +breakpoint + +do_test 5.2 { + sqlite3 db2 test.db + execsql { SELECT * FROM xyz } db2 +} {1 2 3} + +do_execsql_test 5.3 { + PRAGMA wal_checkpoint = restart +} {0 0 0} + +do_test 5.4 { + execsql { SELECT * FROM xyz } db2 +} {1 2 3} + finish_test