diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/btree.c | 10 | ||||
-rw-r--r-- | src/main.c | 4 | ||||
-rw-r--r-- | src/os_unix.c | 11 | ||||
-rw-r--r-- | src/pager.c | 219 | ||||
-rw-r--r-- | src/pragma.c | 12 | ||||
-rw-r--r-- | src/sqliteInt.h | 2 | ||||
-rw-r--r-- | src/test_config.c | 6 | ||||
-rw-r--r-- | src/vdbe.c | 5 | ||||
-rw-r--r-- | src/vdbeapi.c | 8 | ||||
-rw-r--r-- | src/wal.c | 4 | ||||
-rw-r--r-- | src/wal.h | 17 |
11 files changed, 204 insertions, 94 deletions
diff --git a/src/btree.c b/src/btree.c index e60754e58..eace01fff 100644 --- a/src/btree.c +++ b/src/btree.c @@ -2261,6 +2261,15 @@ static int lockBtree(BtShared *pBt){ if( memcmp(page1, zMagicHeader, 16)!=0 ){ goto page1_init_failed; } + +#ifdef SQLITE_OMIT_WAL + if( page1[18]>1 ){ + pBt->readOnly = 1; + } + if( page1[19]>1 ){ + goto page1_init_failed; + } +#else if( page1[18]>2 ){ pBt->readOnly = 1; } @@ -2287,6 +2296,7 @@ static int lockBtree(BtShared *pBt){ } rc = SQLITE_NOTADB; } +#endif /* The maximum embedded fraction must be exactly 25%. And the minimum ** embedded fraction must be 12.5% for both leaf-data and non-leaf-data. diff --git a/src/main.c b/src/main.c index c723a4ef5..57ea9736a 100644 --- a/src/main.c +++ b/src/main.c @@ -1195,6 +1195,7 @@ void *sqlite3_wal_hook( int(*xCallback)(void *, sqlite3*, const char*, int), void *pArg /* First argument passed to xCallback() */ ){ +#ifndef SQLITE_OMIT_WAL void *pRet; sqlite3_mutex_enter(db->mutex); pRet = db->pWalArg; @@ -1202,6 +1203,9 @@ void *sqlite3_wal_hook( db->pWalArg = pArg; sqlite3_mutex_leave(db->mutex); return pRet; +#else + return 0; +#endif } /* diff --git a/src/os_unix.c b/src/os_unix.c index f37afa1f1..b2c22c365 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -4562,6 +4562,8 @@ static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){ return 0; } +#ifndef SQLITE_OMIT_WAL + /* Forward reference */ typedef struct unixShm unixShm; typedef struct unixShmFile unixShmFile; @@ -5334,6 +5336,15 @@ static int unixShmDelete(sqlite3_vfs *pVfs, const char *zName){ return pVfs->xDelete(pVfs, zName, 0); } +#else +# define unixShmOpen 0 +# define unixShmSize 0 +# define unixShmGet 0 +# define unixShmRelease 0 +# define unixShmLock 0 +# define unixShmClose 0 +# define unixShmDelete 0 +#endif /* #ifndef SQLITE_OMIT_WAL */ /* ************************ End of sqlite3_vfs methods *************************** diff --git a/src/pager.c b/src/pager.c index ee0c575a5..00d07caff 100644 --- a/src/pager.c +++ b/src/pager.c @@ -399,7 +399,9 @@ struct Pager { char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */ PCache *pPCache; /* Pointer to page cache object */ sqlite3_backup *pBackup; /* Pointer to list of ongoing backup processes */ +#ifndef SQLITE_OMIT_WAL Wal *pWal; /* Write-ahead log used by "journal_mode=wal" */ +#endif }; /* @@ -1192,9 +1194,16 @@ static int addToSavepointBitvecs(Pager *pPager, Pgno pgno){ ** Return true if this pager uses a write-ahead log instead of the usual ** rollback journal. Otherwise false. */ +#ifndef SQLITE_OMIT_WAL static int pagerUseWal(Pager *pPager){ return (pPager->pWal!=0); } +#else +# define pagerUseWal(x) 0 +# define pagerRollbackWal(x) 0 +# define pagerWalFrames(v,w,x,y,z) 0 +# define pagerOpenWalIfPresent(z) SQLITE_OK +#endif /* ** Unlock the database file. This function is a no-op if the pager @@ -2242,6 +2251,7 @@ static int readDbPage(PgHdr *pPg){ return rc; } +#ifndef SQLITE_OMIT_WAL /* ** This function is invoked once for each page that has already been ** written into the log file when a WAL transaction is rolled back. @@ -2312,6 +2322,115 @@ static int pagerRollbackWal(Pager *pPager){ } /* +** This function is a wrapper around sqlite3WalFrames(). As well as logging +** the contents of the list of pages headed by pList (connected by pDirty), +** this function notifies any active backup processes that the pages have +** changed. +*/ +static int pagerWalFrames( + Pager *pPager, /* Pager object */ + PgHdr *pList, /* List of frames to log */ + Pgno nTruncate, /* Database size after this commit */ + int isCommit, /* True if this is a commit */ + int sync_flags /* Flags to pass to OsSync() (or 0) */ +){ + int rc; /* Return code */ + + assert( pPager->pWal ); + rc = sqlite3WalFrames(pPager->pWal, + pPager->pageSize, pList, nTruncate, isCommit, sync_flags + ); + if( rc==SQLITE_OK && pPager->pBackup ){ + PgHdr *p; + for(p=pList; p; p=p->pDirty){ + sqlite3BackupUpdate(pPager->pBackup, p->pgno, (u8 *)p->pData); + } + } + return rc; +} + +/* +** Open a WAL snapshot on the log file this pager is connected to. +*/ +static int pagerOpenSnapshot(Pager *pPager){ + int rc; /* Return code */ + int changed = 0; /* True if cache must be reset */ + + assert( pagerUseWal(pPager) ); + + rc = sqlite3WalOpenSnapshot(pPager->pWal, &changed); + if( rc==SQLITE_OK ){ + int dummy; + if( changed ){ + pager_reset(pPager); + assert( pPager->errCode || pPager->dbSizeValid==0 ); + } + rc = sqlite3PagerPagecount(pPager, &dummy); + } + pPager->state = PAGER_SHARED; + + return rc; +} + +/* +** Check if the *-wal file that corresponds to the database opened by pPager +** exists. Assuming no error occurs, set *pExists to 1 if the file exists, +** or 0 otherwise and return SQLITE_OK. If an IO or OOM error occurs, return +** an SQLite error code. +*/ +static int pagerHasWAL(Pager *pPager, int *pExists){ + int rc; /* Return code */ + + if( !pPager->tempFile ){ + char *zWal = sqlite3_mprintf("%s-wal", pPager->zFilename); + if( !zWal ){ + rc = SQLITE_NOMEM; + }else{ + rc = sqlite3OsAccess(pPager->pVfs, zWal, SQLITE_ACCESS_EXISTS, pExists); + sqlite3_free(zWal); + } + }else{ + rc = SQLITE_OK; + *pExists = 0; + } + return rc; +} + +/* +** Check if the *-wal file that corresponds to the database opened by pPager +** exists. If it does, open the pager in WAL mode. Otherwise, if no error +** occurs, make sure Pager.journalMode is not set to PAGER_JOURNALMODE_WAL. +** If an IO or OOM error occurs, return an SQLite error code. +** +** If the WAL file is opened, also open a snapshot (read transaction). +** +** The caller must hold a SHARED lock on the database file to call this +** function. Because an EXCLUSIVE lock on the db file is required to delete +** a WAL, this ensures there is no race condition between the xAccess() +** below and an xDelete() being executed by some other connection. +*/ +static int pagerOpenWalIfPresent(Pager *pPager){ + int rc = SQLITE_OK; + if( !pPager->tempFile ){ + int isWal; /* True if WAL file exists */ + rc = pagerHasWAL(pPager, &isWal); + if( rc==SQLITE_OK ){ + if( isWal ){ + pager_reset(pPager); + rc = sqlite3PagerOpenWal(pPager, 0); + if( rc==SQLITE_OK ){ + rc = pagerOpenSnapshot(pPager); + } + }else if( pPager->journalMode==PAGER_JOURNALMODE_WAL ){ + pPager->journalMode = PAGER_JOURNALMODE_DELETE; + } + } + } + return rc; +} +#endif + +/* ** Playback savepoint pSavepoint. Or, if pSavepoint==NULL, then playback ** the entire master journal file. The case pSavepoint==NULL occurs when ** a ROLLBACK TO command is invoked on a SAVEPOINT that is a transaction @@ -2934,10 +3053,12 @@ int sqlite3PagerClose(Pager *pPager){ sqlite3BeginBenignMalloc(); pPager->errCode = 0; pPager->exclusiveMode = 0; +#ifndef SQLITE_OMIT_WAL sqlite3WalClose(pPager->pWal, pPager->fd, (pPager->noSync ? 0 : pPager->sync_flags), pTmp ); pPager->pWal = 0; +#endif pager_reset(pPager); if( MEMDB ){ pager_unlock(pPager); @@ -3281,34 +3402,6 @@ static int subjournalPage(PgHdr *pPg){ } /* -** This function is a wrapper around sqlite3WalFrames(). As well as logging -** the contents of the list of pages headed by pList (connected by pDirty), -** this function notifies any active backup processes that the pages have -** changed. -*/ -static int pagerWalFrames( - Pager *pPager, /* Pager object */ - PgHdr *pList, /* List of frames to log */ - Pgno nTruncate, /* Database size after this commit */ - int isCommit, /* True if this is a commit */ - int sync_flags /* Flags to pass to OsSync() (or 0) */ -){ - int rc; /* Return code */ - - assert( pPager->pWal ); - rc = sqlite3WalFrames(pPager->pWal, - pPager->pageSize, pList, nTruncate, isCommit, sync_flags - ); - if( rc==SQLITE_OK && pPager->pBackup ){ - PgHdr *p; - for(p=pList; p; p=p->pDirty){ - sqlite3BackupUpdate(pPager->pBackup, p->pgno, (u8 *)p->pData); - } - } - return rc; -} - -/* ** This function is called by the pcache layer when it has reached some ** soft memory limit. The first argument is a pointer to a Pager object ** (cast as a void*). The pager is always 'purgeable' (not an in-memory @@ -3820,55 +3913,6 @@ static int hasHotJournal(Pager *pPager, int *pExists){ } /* -** Check if the *-wal file that corresponds to the database opened by pPager -** exists. Assuming no error occurs, set *pExists to 1 if the file exists, -** or 0 otherwise and return SQLITE_OK. If an IO or OOM error occurs, return -** an SQLite error code. -** -** The caller must hold a SHARED lock on the database file to call this -** function. Because an EXCLUSIVE lock on the db file is required to delete -** a WAL, this ensures there is no race condition between the xAccess() -** below and an xDelete() being executed by some other connection. -*/ -static int pagerHasWAL(Pager *pPager, int *pExists){ - int rc; /* Return code */ - - if( !pPager->tempFile ){ - char *zWal = sqlite3_mprintf("%s-wal", pPager->zFilename); - if( !zWal ){ - rc = SQLITE_NOMEM; - }else{ - rc = sqlite3OsAccess(pPager->pVfs, zWal, SQLITE_ACCESS_EXISTS, pExists); - sqlite3_free(zWal); - } - }else{ - rc = SQLITE_OK; - *pExists = 0; - } - return rc; -} - -static int pagerOpenSnapshot(Pager *pPager){ - int rc; /* Return code */ - int changed = 0; /* True if cache must be reset */ - - assert( pagerUseWal(pPager) ); - - rc = sqlite3WalOpenSnapshot(pPager->pWal, &changed); - if( rc==SQLITE_OK ){ - int dummy; - if( changed ){ - pager_reset(pPager); - assert( pPager->errCode || pPager->dbSizeValid==0 ); - } - rc = sqlite3PagerPagecount(pPager, &dummy); - } - pPager->state = PAGER_SHARED; - - return rc; -} - -/* ** This function is called to obtain a shared lock on the database file. ** It is illegal to call sqlite3PagerAcquire() until after this function ** has been successfully called. If a shared-lock is already held when @@ -3926,7 +3970,6 @@ int sqlite3PagerSharedLock(Pager *pPager){ }else if( pPager->state==PAGER_UNLOCK || isErrorReset ){ sqlite3_vfs * const pVfs = pPager->pVfs; int isHotJournal = 0; - int isWal = 0; assert( !MEMDB ); assert( sqlite3PcacheRefCount(pPager->pPCache)==0 ); if( pPager->noReadlock ){ @@ -4081,19 +4124,10 @@ int sqlite3PagerSharedLock(Pager *pPager){ } assert( pPager->exclusiveMode || pPager->state==PAGER_SHARED ); - rc = pagerHasWAL(pPager, &isWal); - if( rc!=SQLITE_OK ){ - goto failed; - } - if( isWal ){ - pager_reset(pPager); - rc = sqlite3PagerOpenWal(pPager, 0); - if( rc==SQLITE_OK ){ - rc = pagerOpenSnapshot(pPager); - } - }else if( pPager->journalMode==PAGER_JOURNALMODE_WAL ){ - pPager->journalMode = PAGER_JOURNALMODE_DELETE; - } + /* If there is a WAL file in the file-system, open this database in WAL + ** mode. Otherwise, the following function call is a no-op. + */ + rc = pagerOpenWalIfPresent(pPager); } failed: @@ -5789,6 +5823,7 @@ sqlite3_backup **sqlite3PagerBackupPtr(Pager *pPager){ return &pPager->pBackup; } +#ifndef SQLITE_OMIT_WAL /* ** This function is called when the user invokes "PRAGMA checkpoint". */ @@ -5836,7 +5871,6 @@ int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen){ return rc; } - /* ** This function is called to close the connection to the log file prior ** to switching from WAL to rollback mode. @@ -5881,5 +5915,6 @@ int sqlite3PagerCloseWal(Pager *pPager){ } return rc; } +#endif #endif /* SQLITE_OMIT_DISKIO */ diff --git a/src/pragma.c b/src/pragma.c index da6a6807f..263b7fc0c 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -265,7 +265,10 @@ static const char *actionName(u8 action){ */ const char *sqlite3JournalModename(int eMode){ static char * const azModeName[] = { - "delete", "persist", "off", "truncate", "memory", "wal" + "delete", "persist", "off", "truncate", "memory" +#ifndef SQLITE_OMIT_WAL + , "wal" +#endif }; assert( PAGER_JOURNALMODE_DELETE==0 ); assert( PAGER_JOURNALMODE_PERSIST==1 ); @@ -1397,10 +1400,17 @@ void sqlite3Pragma( }else #endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */ +#ifndef SQLITE_OMIT_WAL + /* + ** PRAGMA [database.]checkpoint + ** + ** Checkpoint the database. + */ if( sqlite3StrICmp(zLeft, "checkpoint")==0 ){ sqlite3VdbeUsesBtree(v, iDb); sqlite3VdbeAddOp3(v, OP_Checkpoint, iDb, 0, 0); }else +#endif #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) /* diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 54effce12..28268104c 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -823,8 +823,10 @@ struct sqlite3 { void (*xRollbackCallback)(void*); /* Invoked at every commit. */ void *pUpdateArg; void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64); +#ifndef SQLITE_OMIT_WAL int (*xWalCallback)(void *, sqlite3 *, const char *, int); void *pWalArg; +#endif void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*); void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*); void *pCollNeededArg; diff --git a/src/test_config.c b/src/test_config.c index 8544ee535..092d6a222 100644 --- a/src/test_config.c +++ b/src/test_config.c @@ -499,6 +499,12 @@ Tcl_SetVar2(interp, "sqlite_options", "long_double", Tcl_SetVar2(interp, "sqlite_options", "vtab", "1", TCL_GLOBAL_ONLY); #endif +#ifdef SQLITE_OMIT_WAL + Tcl_SetVar2(interp, "sqlite_options", "wal", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "wal", "1", TCL_GLOBAL_ONLY); +#endif + #ifdef SQLITE_OMIT_WSD Tcl_SetVar2(interp, "sqlite_options", "wsd", "0", TCL_GLOBAL_ONLY); #else diff --git a/src/vdbe.c b/src/vdbe.c index c6a38c5ba..c040fb8d2 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -5186,6 +5186,7 @@ case OP_AggFinal: { break; } +#ifndef SQLITE_OMIT_WAL /* Opcode: Checkpoint P1 * * * * ** ** Checkpoint database P1. This is a no-op if P1 is not currently in @@ -5200,6 +5201,7 @@ case OP_Checkpoint: { rc = sqlite3PagerCheckpoint(sqlite3BtreePager(pBt)); break; }; +#endif /* Opcode: JournalMode P1 P2 P3 * * ** @@ -5234,6 +5236,8 @@ case OP_JournalMode: { /* out2-prerelease */ pBt = db->aDb[pOp->p1].pBt; pPager = sqlite3BtreePager(pBt); + +#ifndef SQLITE_OMIT_WAL zFilename = sqlite3PagerFilename(pPager); pVfs = sqlite3PagerVfs(pPager); @@ -5282,6 +5286,7 @@ case OP_JournalMode: { /* out2-prerelease */ } } } +#endif /* ifndef SQLITE_OMIT_WAL */ eNew = sqlite3PagerJournalMode(pPager, eNew); pOut = &aMem[pOp->p2]; diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 12100ce56..5aec7ca0f 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -306,9 +306,14 @@ void sqlite3_result_error_nomem(sqlite3_context *pCtx){ pCtx->s.db->mallocFailed = 1; } +/* +** This function is called after a transaction has been committed. It +** invokes callbacks registered with sqlite3_wal_hook() as required. +*/ static int doWalCallbacks(sqlite3 *db){ - int i; int rc = SQLITE_OK; +#ifndef SQLITE_OMIT_WAL + int i; for(i=0; i<db->nDb; i++){ Btree *pBt = db->aDb[i].pBt; if( pBt ){ @@ -320,6 +325,7 @@ static int doWalCallbacks(sqlite3 *db){ } } } +#endif return rc; } @@ -13,6 +13,8 @@ ** This file contains the implementation of a write-ahead log file used in ** "journal_mode=wal" mode. */ +#ifndef SQLITE_OMIT_WAL + #include "wal.h" @@ -1271,6 +1273,7 @@ int sqlite3WalCheckpoint( int isChanged = 0; /* True if a new wal-index header is loaded */ assert( pWal->lockState==SQLITE_SHM_UNLOCK ); + assert( pWal->pWiData==0 ); /* Get the CHECKPOINT lock */ do { @@ -1315,3 +1318,4 @@ int sqlite3WalCallback(Wal *pWal){ } return (int)ret; } +#endif /* #ifndef SQLITE_OMIT_WAL */ @@ -19,6 +19,22 @@ #include "sqliteInt.h" +#ifdef SQLITE_OMIT_WAL +# define sqlite3WalOpen(x,y,z) 0 +# define sqlite3WalClose(w,x,y,z) 0 +# define sqlite3WalOpenSnapshot(y,z) 0 +# define sqlite3WalCloseSnapshot(z) +# define sqlite3WalRead(w,x,y,z) 0 +# define sqlite3WalDbsize(y,z) +# define sqlite3WalWriteLock(y,z) 0 +# define sqlite3WalUndo(x,y,z) 0 +# define sqlite3WalSavepoint(z) 0 +# define sqlite3WalSavepointUndo(y,z) 0 +# define sqlite3WalFrames(u,v,w,x,y,z) 0 +# define sqlite3WalCheckpoint(u,v,w,x,y,z) 0 +# define sqlite3WalCallback(z) 0 +#else + /* Connection to a write-ahead log (WAL) file. ** There is one object of this type for each pager. */ @@ -79,4 +95,5 @@ int sqlite3WalCheckpoint( */ int sqlite3WalCallback(Wal *pWal); +#endif /* ifndef SQLITE_OMIT_WAL */ #endif /* _WAL_H_ */ |