mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Extend the refactoring into extensions. Clean up stray newlines.
FossilOrigin-Name: 7a876209a678a34c198b54ceef9e3c041f128a14dc73357f6a57cadadaa6cf7b
This commit is contained in:
332
src/pager.c
332
src/pager.c
@@ -70,8 +70,8 @@
|
||||
** (5) All writes to the database file are synced prior to the rollback journal
|
||||
** being deleted, truncated, or zeroed.
|
||||
**
|
||||
** (6) If a master journal file is used, then all writes to the database file
|
||||
** are synced prior to the master journal being deleted.
|
||||
** (6) If a super-journal file is used, then all writes to the database file
|
||||
** are synced prior to the super-journal being deleted.
|
||||
**
|
||||
** Definition: Two databases (or the same database at two points it time)
|
||||
** are said to be "logically equivalent" if they give the same answer to
|
||||
@@ -488,29 +488,29 @@ struct PagerSavepoint {
|
||||
** need only update the change-counter once, for the first transaction
|
||||
** committed.
|
||||
**
|
||||
** setMaster
|
||||
** setSuper
|
||||
**
|
||||
** When PagerCommitPhaseOne() is called to commit a transaction, it may
|
||||
** (or may not) specify a master-journal name to be written into the
|
||||
** (or may not) specify a super-journal name to be written into the
|
||||
** journal file before it is synced to disk.
|
||||
**
|
||||
** Whether or not a journal file contains a master-journal pointer affects
|
||||
** Whether or not a journal file contains a super-journal pointer affects
|
||||
** the way in which the journal file is finalized after the transaction is
|
||||
** committed or rolled back when running in "journal_mode=PERSIST" mode.
|
||||
** If a journal file does not contain a master-journal pointer, it is
|
||||
** If a journal file does not contain a super-journal pointer, it is
|
||||
** finalized by overwriting the first journal header with zeroes. If
|
||||
** it does contain a master-journal pointer the journal file is finalized
|
||||
** it does contain a super-journal pointer the journal file is finalized
|
||||
** by truncating it to zero bytes, just as if the connection were
|
||||
** running in "journal_mode=truncate" mode.
|
||||
**
|
||||
** Journal files that contain master journal pointers cannot be finalized
|
||||
** Journal files that contain super-journal pointers cannot be finalized
|
||||
** simply by overwriting the first journal-header with zeroes, as the
|
||||
** master journal pointer could interfere with hot-journal rollback of any
|
||||
** super-journal pointer could interfere with hot-journal rollback of any
|
||||
** subsequently interrupted transaction that reuses the journal file.
|
||||
**
|
||||
** The flag is cleared as soon as the journal file is finalized (either
|
||||
** by PagerCommitPhaseTwo or PagerRollback). If an IO error prevents the
|
||||
** journal file from being successfully finalized, the setMaster flag
|
||||
** journal file from being successfully finalized, the setSuper flag
|
||||
** is cleared anyway (and the pager will move to ERROR state).
|
||||
**
|
||||
** doNotSpill
|
||||
@@ -642,7 +642,7 @@ struct Pager {
|
||||
u8 eState; /* Pager state (OPEN, READER, WRITER_LOCKED..) */
|
||||
u8 eLock; /* Current lock held on database file */
|
||||
u8 changeCountDone; /* Set after incrementing the change-counter */
|
||||
u8 setMaster; /* True if a m-j name has been written to jrnl */
|
||||
u8 setSuper; /* Super-jrnl name is written into jrnl */
|
||||
u8 doNotSpill; /* Do not spill the cache when non-zero */
|
||||
u8 subjInMemory; /* True to use in-memory sub-journals */
|
||||
u8 bUseFetch; /* True to use xFetch() */
|
||||
@@ -920,7 +920,7 @@ static int assert_pager_state(Pager *p){
|
||||
assert( pPager->dbSize==pPager->dbOrigSize );
|
||||
assert( pPager->dbOrigSize==pPager->dbFileSize );
|
||||
assert( pPager->dbOrigSize==pPager->dbHintSize );
|
||||
assert( pPager->setMaster==0 );
|
||||
assert( pPager->setSuper==0 );
|
||||
break;
|
||||
|
||||
case PAGER_WRITER_CACHEMOD:
|
||||
@@ -1274,66 +1274,66 @@ static void checkPage(PgHdr *pPg){
|
||||
|
||||
/*
|
||||
** When this is called the journal file for pager pPager must be open.
|
||||
** This function attempts to read a master journal file name from the
|
||||
** This function attempts to read a super-journal file name from the
|
||||
** end of the file and, if successful, copies it into memory supplied
|
||||
** by the caller. See comments above writeMasterJournal() for the format
|
||||
** used to store a master journal file name at the end of a journal file.
|
||||
** by the caller. See comments above writeSuperJournal() for the format
|
||||
** used to store a super-journal file name at the end of a journal file.
|
||||
**
|
||||
** zMaster must point to a buffer of at least nMaster bytes allocated by
|
||||
** zSuper must point to a buffer of at least nSuper bytes allocated by
|
||||
** the caller. This should be sqlite3_vfs.mxPathname+1 (to ensure there is
|
||||
** enough space to write the master journal name). If the master journal
|
||||
** name in the journal is longer than nMaster bytes (including a
|
||||
** nul-terminator), then this is handled as if no master journal name
|
||||
** enough space to write the super-journal name). If the super-journal
|
||||
** name in the journal is longer than nSuper bytes (including a
|
||||
** nul-terminator), then this is handled as if no super-journal name
|
||||
** were present in the journal.
|
||||
**
|
||||
** If a master journal file name is present at the end of the journal
|
||||
** file, then it is copied into the buffer pointed to by zMaster. A
|
||||
** nul-terminator byte is appended to the buffer following the master
|
||||
** journal file name.
|
||||
** If a super-journal file name is present at the end of the journal
|
||||
** file, then it is copied into the buffer pointed to by zSuper. A
|
||||
** nul-terminator byte is appended to the buffer following the
|
||||
** super-journal file name.
|
||||
**
|
||||
** If it is determined that no master journal file name is present
|
||||
** zMaster[0] is set to 0 and SQLITE_OK returned.
|
||||
** If it is determined that no super-journal file name is present
|
||||
** zSuper[0] is set to 0 and SQLITE_OK returned.
|
||||
**
|
||||
** If an error occurs while reading from the journal file, an SQLite
|
||||
** error code is returned.
|
||||
*/
|
||||
static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, u32 nMaster){
|
||||
static int readSuperJournal(sqlite3_file *pJrnl, char *zSuper, u32 nSuper){
|
||||
int rc; /* Return code */
|
||||
u32 len; /* Length in bytes of master journal name */
|
||||
u32 len; /* Length in bytes of super-journal name */
|
||||
i64 szJ; /* Total size in bytes of journal file pJrnl */
|
||||
u32 cksum; /* MJ checksum value read from journal */
|
||||
u32 u; /* Unsigned loop counter */
|
||||
unsigned char aMagic[8]; /* A buffer to hold the magic header */
|
||||
zMaster[0] = '\0';
|
||||
zSuper[0] = '\0';
|
||||
|
||||
if( SQLITE_OK!=(rc = sqlite3OsFileSize(pJrnl, &szJ))
|
||||
|| szJ<16
|
||||
|| SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len))
|
||||
|| len>=nMaster
|
||||
|| len>=nSuper
|
||||
|| len>szJ-16
|
||||
|| len==0
|
||||
|| SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum))
|
||||
|| SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8))
|
||||
|| memcmp(aMagic, aJournalMagic, 8)
|
||||
|| SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, zMaster, len, szJ-16-len))
|
||||
|| SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, zSuper, len, szJ-16-len))
|
||||
){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* See if the checksum matches the master journal name */
|
||||
/* See if the checksum matches the super-journal name */
|
||||
for(u=0; u<len; u++){
|
||||
cksum -= zMaster[u];
|
||||
cksum -= zSuper[u];
|
||||
}
|
||||
if( cksum ){
|
||||
/* If the checksum doesn't add up, then one or more of the disk sectors
|
||||
** containing the master journal filename is corrupted. This means
|
||||
** containing the super-journal filename is corrupted. This means
|
||||
** definitely roll back, so just return SQLITE_OK and report a (nul)
|
||||
** master-journal filename.
|
||||
** super-journal filename.
|
||||
*/
|
||||
len = 0;
|
||||
}
|
||||
zMaster[len] = '\0';
|
||||
zMaster[len+1] = '\0';
|
||||
zSuper[len] = '\0';
|
||||
zSuper[len+1] = '\0';
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -1661,50 +1661,50 @@ static int readJournalHdr(
|
||||
|
||||
|
||||
/*
|
||||
** Write the supplied master journal name into the journal file for pager
|
||||
** pPager at the current location. The master journal name must be the last
|
||||
** Write the supplied super-journal name into the journal file for pager
|
||||
** pPager at the current location. The super-journal name must be the last
|
||||
** thing written to a journal file. If the pager is in full-sync mode, the
|
||||
** journal file descriptor is advanced to the next sector boundary before
|
||||
** anything is written. The format is:
|
||||
**
|
||||
** + 4 bytes: PAGER_MJ_PGNO.
|
||||
** + N bytes: Master journal filename in utf-8.
|
||||
** + 4 bytes: N (length of master journal name in bytes, no nul-terminator).
|
||||
** + 4 bytes: Master journal name checksum.
|
||||
** + N bytes: super-journal filename in utf-8.
|
||||
** + 4 bytes: N (length of super-journal name in bytes, no nul-terminator).
|
||||
** + 4 bytes: super-journal name checksum.
|
||||
** + 8 bytes: aJournalMagic[].
|
||||
**
|
||||
** The master journal page checksum is the sum of the bytes in the master
|
||||
** journal name, where each byte is interpreted as a signed 8-bit integer.
|
||||
** The super-journal page checksum is the sum of the bytes in thesuper-journal
|
||||
** name, where each byte is interpreted as a signed 8-bit integer.
|
||||
**
|
||||
** If zMaster is a NULL pointer (occurs for a single database transaction),
|
||||
** If zSuper is a NULL pointer (occurs for a single database transaction),
|
||||
** this call is a no-op.
|
||||
*/
|
||||
static int writeMasterJournal(Pager *pPager, const char *zMaster){
|
||||
static int writeSuperJournal(Pager *pPager, const char *zSuper){
|
||||
int rc; /* Return code */
|
||||
int nMaster; /* Length of string zMaster */
|
||||
int nSuper; /* Length of string zSuper */
|
||||
i64 iHdrOff; /* Offset of header in journal file */
|
||||
i64 jrnlSize; /* Size of journal file on disk */
|
||||
u32 cksum = 0; /* Checksum of string zMaster */
|
||||
u32 cksum = 0; /* Checksum of string zSuper */
|
||||
|
||||
assert( pPager->setMaster==0 );
|
||||
assert( pPager->setSuper==0 );
|
||||
assert( !pagerUseWal(pPager) );
|
||||
|
||||
if( !zMaster
|
||||
if( !zSuper
|
||||
|| pPager->journalMode==PAGER_JOURNALMODE_MEMORY
|
||||
|| !isOpen(pPager->jfd)
|
||||
){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
pPager->setMaster = 1;
|
||||
pPager->setSuper = 1;
|
||||
assert( pPager->journalHdr <= pPager->journalOff );
|
||||
|
||||
/* Calculate the length in bytes and the checksum of zMaster */
|
||||
for(nMaster=0; zMaster[nMaster]; nMaster++){
|
||||
cksum += zMaster[nMaster];
|
||||
/* Calculate the length in bytes and the checksum of zSuper */
|
||||
for(nSuper=0; zSuper[nSuper]; nSuper++){
|
||||
cksum += zSuper[nSuper];
|
||||
}
|
||||
|
||||
/* If in full-sync mode, advance to the next disk sector before writing
|
||||
** the master journal name. This is in case the previous page written to
|
||||
** the super-journal name. This is in case the previous page written to
|
||||
** the journal has already been synced.
|
||||
*/
|
||||
if( pPager->fullSync ){
|
||||
@@ -1712,25 +1712,25 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){
|
||||
}
|
||||
iHdrOff = pPager->journalOff;
|
||||
|
||||
/* Write the master journal data to the end of the journal file. If
|
||||
/* Write the super-journal data to the end of the journal file. If
|
||||
** an error occurs, return the error code to the caller.
|
||||
*/
|
||||
if( (0 != (rc = write32bits(pPager->jfd, iHdrOff, PAGER_MJ_PGNO(pPager))))
|
||||
|| (0 != (rc = sqlite3OsWrite(pPager->jfd, zMaster, nMaster, iHdrOff+4)))
|
||||
|| (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nMaster, nMaster)))
|
||||
|| (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nMaster+4, cksum)))
|
||||
|| (0 != (rc = sqlite3OsWrite(pPager->jfd, zSuper, nSuper, iHdrOff+4)))
|
||||
|| (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nSuper, nSuper)))
|
||||
|| (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nSuper+4, cksum)))
|
||||
|| (0 != (rc = sqlite3OsWrite(pPager->jfd, aJournalMagic, 8,
|
||||
iHdrOff+4+nMaster+8)))
|
||||
iHdrOff+4+nSuper+8)))
|
||||
){
|
||||
return rc;
|
||||
}
|
||||
pPager->journalOff += (nMaster+20);
|
||||
pPager->journalOff += (nSuper+20);
|
||||
|
||||
/* If the pager is in peristent-journal mode, then the physical
|
||||
** journal-file may extend past the end of the master-journal name
|
||||
** journal-file may extend past the end of the super-journal name
|
||||
** and 8 bytes of magic data just written to the file. This is
|
||||
** dangerous because the code to rollback a hot-journal file
|
||||
** will not be able to find the master-journal name to determine
|
||||
** will not be able to find the super-journal name to determine
|
||||
** whether or not the journal is hot.
|
||||
**
|
||||
** Easiest thing to do in this scenario is to truncate the journal
|
||||
@@ -1891,7 +1891,7 @@ static void pager_unlock(Pager *pPager){
|
||||
|
||||
pPager->journalOff = 0;
|
||||
pPager->journalHdr = 0;
|
||||
pPager->setMaster = 0;
|
||||
pPager->setSuper = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2007,7 +2007,7 @@ static int pagerFlushOnCommit(Pager *pPager, int bCommit){
|
||||
** to the first error encountered (the journal finalization one) is
|
||||
** returned.
|
||||
*/
|
||||
static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
|
||||
static int pager_end_transaction(Pager *pPager, int hasSuper, int bCommit){
|
||||
int rc = SQLITE_OK; /* Error code from journal finalization operation */
|
||||
int rc2 = SQLITE_OK; /* Error code from db file unlock operation */
|
||||
|
||||
@@ -2059,7 +2059,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
|
||||
}else if( pPager->journalMode==PAGER_JOURNALMODE_PERSIST
|
||||
|| (pPager->exclusiveMode && pPager->journalMode!=PAGER_JOURNALMODE_WAL)
|
||||
){
|
||||
rc = zeroJournalHdr(pPager, hasMaster||pPager->tempFile);
|
||||
rc = zeroJournalHdr(pPager, hasSuper||pPager->tempFile);
|
||||
pPager->journalOff = 0;
|
||||
}else{
|
||||
/* This branch may be executed with Pager.journalMode==MEMORY if
|
||||
@@ -2132,7 +2132,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
|
||||
rc2 = pagerUnlockDb(pPager, SHARED_LOCK);
|
||||
}
|
||||
pPager->eState = PAGER_READER;
|
||||
pPager->setMaster = 0;
|
||||
pPager->setSuper = 0;
|
||||
|
||||
return (rc==SQLITE_OK?rc2:rc);
|
||||
}
|
||||
@@ -2440,36 +2440,36 @@ static int pager_playback_one_page(
|
||||
}
|
||||
|
||||
/*
|
||||
** Parameter zMaster is the name of a master journal file. A single journal
|
||||
** file that referred to the master journal file has just been rolled back.
|
||||
** This routine checks if it is possible to delete the master journal file,
|
||||
** Parameter zSuper is the name of a super-journal file. A single journal
|
||||
** file that referred to the super-journal file has just been rolled back.
|
||||
** This routine checks if it is possible to delete the super-journal file,
|
||||
** and does so if it is.
|
||||
**
|
||||
** Argument zMaster may point to Pager.pTmpSpace. So that buffer is not
|
||||
** Argument zSuper may point to Pager.pTmpSpace. So that buffer is not
|
||||
** available for use within this function.
|
||||
**
|
||||
** When a master journal file is created, it is populated with the names
|
||||
** When a super-journal file is created, it is populated with the names
|
||||
** of all of its child journals, one after another, formatted as utf-8
|
||||
** encoded text. The end of each child journal file is marked with a
|
||||
** nul-terminator byte (0x00). i.e. the entire contents of a master journal
|
||||
** nul-terminator byte (0x00). i.e. the entire contents of a super-journal
|
||||
** file for a transaction involving two databases might be:
|
||||
**
|
||||
** "/home/bill/a.db-journal\x00/home/bill/b.db-journal\x00"
|
||||
**
|
||||
** A master journal file may only be deleted once all of its child
|
||||
** A super-journal file may only be deleted once all of its child
|
||||
** journals have been rolled back.
|
||||
**
|
||||
** This function reads the contents of the master-journal file into
|
||||
** This function reads the contents of the super-journal file into
|
||||
** memory and loops through each of the child journal names. For
|
||||
** each child journal, it checks if:
|
||||
**
|
||||
** * if the child journal exists, and if so
|
||||
** * if the child journal contains a reference to master journal
|
||||
** file zMaster
|
||||
** * if the child journal contains a reference to super-journal
|
||||
** file zSuper
|
||||
**
|
||||
** If a child journal can be found that matches both of the criteria
|
||||
** above, this function returns without doing anything. Otherwise, if
|
||||
** no such child journal can be found, file zMaster is deleted from
|
||||
** no such child journal can be found, file zSuper is deleted from
|
||||
** the file-system using sqlite3OsDelete().
|
||||
**
|
||||
** If an IO error within this function, an error code is returned. This
|
||||
@@ -2478,64 +2478,64 @@ static int pager_playback_one_page(
|
||||
** occur, SQLITE_OK is returned.
|
||||
**
|
||||
** TODO: This function allocates a single block of memory to load
|
||||
** the entire contents of the master journal file. This could be
|
||||
** the entire contents of the super-journal file. This could be
|
||||
** a couple of kilobytes or so - potentially larger than the page
|
||||
** size.
|
||||
*/
|
||||
static int pager_delmaster(Pager *pPager, const char *zMaster){
|
||||
static int pager_delsuper(Pager *pPager, const char *zSuper){
|
||||
sqlite3_vfs *pVfs = pPager->pVfs;
|
||||
int rc; /* Return code */
|
||||
sqlite3_file *pMaster; /* Malloc'd master-journal file descriptor */
|
||||
sqlite3_file *pSuper; /* Malloc'd super-journal file descriptor */
|
||||
sqlite3_file *pJournal; /* Malloc'd child-journal file descriptor */
|
||||
char *zMasterJournal = 0; /* Contents of master journal file */
|
||||
i64 nMasterJournal; /* Size of master journal file */
|
||||
char *zSuperJournal = 0; /* Contents of super-journal file */
|
||||
i64 nSuperJournal; /* Size of super-journal file */
|
||||
char *zJournal; /* Pointer to one journal within MJ file */
|
||||
char *zMasterPtr; /* Space to hold MJ filename from a journal file */
|
||||
int nMasterPtr; /* Amount of space allocated to zMasterPtr[] */
|
||||
char *zSuperPtr; /* Space to hold super-journal filename */
|
||||
int nSuperPtr; /* Amount of space allocated to zSuperPtr[] */
|
||||
|
||||
/* Allocate space for both the pJournal and pMaster file descriptors.
|
||||
** If successful, open the master journal file for reading.
|
||||
/* Allocate space for both the pJournal and pSuper file descriptors.
|
||||
** If successful, open the super-journal file for reading.
|
||||
*/
|
||||
pMaster = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile * 2);
|
||||
pJournal = (sqlite3_file *)(((u8 *)pMaster) + pVfs->szOsFile);
|
||||
if( !pMaster ){
|
||||
pSuper = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile * 2);
|
||||
pJournal = (sqlite3_file *)(((u8 *)pSuper) + pVfs->szOsFile);
|
||||
if( !pSuper ){
|
||||
rc = SQLITE_NOMEM_BKPT;
|
||||
}else{
|
||||
const int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_SUPER_JOURNAL);
|
||||
rc = sqlite3OsOpen(pVfs, zMaster, pMaster, flags, 0);
|
||||
rc = sqlite3OsOpen(pVfs, zSuper, pSuper, flags, 0);
|
||||
}
|
||||
if( rc!=SQLITE_OK ) goto delmaster_out;
|
||||
if( rc!=SQLITE_OK ) goto delsuper_out;
|
||||
|
||||
/* Load the entire master journal file into space obtained from
|
||||
** sqlite3_malloc() and pointed to by zMasterJournal. Also obtain
|
||||
** sufficient space (in zMasterPtr) to hold the names of master
|
||||
** journal files extracted from regular rollback-journals.
|
||||
/* Load the entire super-journal file into space obtained from
|
||||
** sqlite3_malloc() and pointed to by zSuperJournal. Also obtain
|
||||
** sufficient space (in zSuperPtr) to hold the names of super-journal
|
||||
** files extracted from regular rollback-journals.
|
||||
*/
|
||||
rc = sqlite3OsFileSize(pMaster, &nMasterJournal);
|
||||
if( rc!=SQLITE_OK ) goto delmaster_out;
|
||||
nMasterPtr = pVfs->mxPathname+1;
|
||||
zMasterJournal = sqlite3Malloc(nMasterJournal + nMasterPtr + 2);
|
||||
if( !zMasterJournal ){
|
||||
rc = sqlite3OsFileSize(pSuper, &nSuperJournal);
|
||||
if( rc!=SQLITE_OK ) goto delsuper_out;
|
||||
nSuperPtr = pVfs->mxPathname+1;
|
||||
zSuperJournal = sqlite3Malloc(nSuperJournal + nSuperPtr + 2);
|
||||
if( !zSuperJournal ){
|
||||
rc = SQLITE_NOMEM_BKPT;
|
||||
goto delmaster_out;
|
||||
goto delsuper_out;
|
||||
}
|
||||
zMasterPtr = &zMasterJournal[nMasterJournal+2];
|
||||
rc = sqlite3OsRead(pMaster, zMasterJournal, (int)nMasterJournal, 0);
|
||||
if( rc!=SQLITE_OK ) goto delmaster_out;
|
||||
zMasterJournal[nMasterJournal] = 0;
|
||||
zMasterJournal[nMasterJournal+1] = 0;
|
||||
zSuperPtr = &zSuperJournal[nSuperJournal+2];
|
||||
rc = sqlite3OsRead(pSuper, zSuperJournal, (int)nSuperJournal, 0);
|
||||
if( rc!=SQLITE_OK ) goto delsuper_out;
|
||||
zSuperJournal[nSuperJournal] = 0;
|
||||
zSuperJournal[nSuperJournal+1] = 0;
|
||||
|
||||
zJournal = zMasterJournal;
|
||||
while( (zJournal-zMasterJournal)<nMasterJournal ){
|
||||
zJournal = zSuperJournal;
|
||||
while( (zJournal-zSuperJournal)<nSuperJournal ){
|
||||
int exists;
|
||||
rc = sqlite3OsAccess(pVfs, zJournal, SQLITE_ACCESS_EXISTS, &exists);
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto delmaster_out;
|
||||
goto delsuper_out;
|
||||
}
|
||||
if( exists ){
|
||||
/* One of the journals pointed to by the master journal exists.
|
||||
** Open it and check if it points at the master journal. If
|
||||
** so, return without deleting the master journal file.
|
||||
/* One of the journals pointed to by the super-journal exists.
|
||||
** Open it and check if it points at the super-journal. If
|
||||
** so, return without deleting the super-journal file.
|
||||
** NB: zJournal is really a MAIN_JOURNAL. But call it a
|
||||
** SUPER_JOURNAL here so that the VFS will not send the zJournal
|
||||
** name into sqlite3_database_file_object().
|
||||
@@ -2544,33 +2544,33 @@ static int pager_delmaster(Pager *pPager, const char *zMaster){
|
||||
int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_SUPER_JOURNAL);
|
||||
rc = sqlite3OsOpen(pVfs, zJournal, pJournal, flags, 0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto delmaster_out;
|
||||
goto delsuper_out;
|
||||
}
|
||||
|
||||
rc = readMasterJournal(pJournal, zMasterPtr, nMasterPtr);
|
||||
rc = readSuperJournal(pJournal, zSuperPtr, nSuperPtr);
|
||||
sqlite3OsClose(pJournal);
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto delmaster_out;
|
||||
goto delsuper_out;
|
||||
}
|
||||
|
||||
c = zMasterPtr[0]!=0 && strcmp(zMasterPtr, zMaster)==0;
|
||||
c = zSuperPtr[0]!=0 && strcmp(zSuperPtr, zSuper)==0;
|
||||
if( c ){
|
||||
/* We have a match. Do not delete the master journal file. */
|
||||
goto delmaster_out;
|
||||
/* We have a match. Do not delete the super-journal file. */
|
||||
goto delsuper_out;
|
||||
}
|
||||
}
|
||||
zJournal += (sqlite3Strlen30(zJournal)+1);
|
||||
}
|
||||
|
||||
sqlite3OsClose(pMaster);
|
||||
rc = sqlite3OsDelete(pVfs, zMaster, 0);
|
||||
sqlite3OsClose(pSuper);
|
||||
rc = sqlite3OsDelete(pVfs, zSuper, 0);
|
||||
|
||||
delmaster_out:
|
||||
sqlite3_free(zMasterJournal);
|
||||
if( pMaster ){
|
||||
sqlite3OsClose(pMaster);
|
||||
delsuper_out:
|
||||
sqlite3_free(zSuperJournal);
|
||||
if( pSuper ){
|
||||
sqlite3OsClose(pSuper);
|
||||
assert( !isOpen(pJournal) );
|
||||
sqlite3_free(pMaster);
|
||||
sqlite3_free(pSuper);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -2648,7 +2648,7 @@ int sqlite3SectorSize(sqlite3_file *pFile){
|
||||
** pager based on the value returned by the xSectorSize method
|
||||
** of the open database file. The sector size will be used
|
||||
** to determine the size and alignment of journal header and
|
||||
** master journal pointers within created journal files.
|
||||
** super-journal pointers within created journal files.
|
||||
**
|
||||
** For temporary files the effective sector size is always 512 bytes.
|
||||
**
|
||||
@@ -2747,7 +2747,7 @@ static int pager_playback(Pager *pPager, int isHot){
|
||||
Pgno mxPg = 0; /* Size of the original file in pages */
|
||||
int rc; /* Result code of a subroutine */
|
||||
int res = 1; /* Value returned by sqlite3OsAccess() */
|
||||
char *zMaster = 0; /* Name of master journal file if any */
|
||||
char *zSuper = 0; /* Name of super-journal file if any */
|
||||
int needPagerReset; /* True to reset page prior to first page rollback */
|
||||
int nPlayback = 0; /* Total number of pages restored from journal */
|
||||
u32 savedPageSize = pPager->pageSize;
|
||||
@@ -2761,8 +2761,8 @@ static int pager_playback(Pager *pPager, int isHot){
|
||||
goto end_playback;
|
||||
}
|
||||
|
||||
/* Read the master journal name from the journal, if it is present.
|
||||
** If a master journal file name is specified, but the file is not
|
||||
/* Read the super-journal name from the journal, if it is present.
|
||||
** If a super-journal file name is specified, but the file is not
|
||||
** present on disk, then the journal is not hot and does not need to be
|
||||
** played back.
|
||||
**
|
||||
@@ -2772,12 +2772,12 @@ static int pager_playback(Pager *pPager, int isHot){
|
||||
** mxPathname is 512, which is the same as the minimum allowable value
|
||||
** for pageSize.
|
||||
*/
|
||||
zMaster = pPager->pTmpSpace;
|
||||
rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
|
||||
if( rc==SQLITE_OK && zMaster[0] ){
|
||||
rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res);
|
||||
zSuper = pPager->pTmpSpace;
|
||||
rc = readSuperJournal(pPager->jfd, zSuper, pPager->pVfs->mxPathname+1);
|
||||
if( rc==SQLITE_OK && zSuper[0] ){
|
||||
rc = sqlite3OsAccess(pVfs, zSuper, SQLITE_ACCESS_EXISTS, &res);
|
||||
}
|
||||
zMaster = 0;
|
||||
zSuper = 0;
|
||||
if( rc!=SQLITE_OK || !res ){
|
||||
goto end_playback;
|
||||
}
|
||||
@@ -2904,8 +2904,8 @@ end_playback:
|
||||
pPager->changeCountDone = pPager->tempFile;
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
zMaster = pPager->pTmpSpace;
|
||||
rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
|
||||
zSuper = pPager->pTmpSpace;
|
||||
rc = readSuperJournal(pPager->jfd, zSuper, pPager->pVfs->mxPathname+1);
|
||||
testcase( rc!=SQLITE_OK );
|
||||
}
|
||||
if( rc==SQLITE_OK
|
||||
@@ -2914,14 +2914,14 @@ end_playback:
|
||||
rc = sqlite3PagerSync(pPager, 0);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = pager_end_transaction(pPager, zMaster[0]!='\0', 0);
|
||||
rc = pager_end_transaction(pPager, zSuper[0]!='\0', 0);
|
||||
testcase( rc!=SQLITE_OK );
|
||||
}
|
||||
if( rc==SQLITE_OK && zMaster[0] && res ){
|
||||
/* If there was a master journal and this routine will return success,
|
||||
** see if it is possible to delete the master journal.
|
||||
if( rc==SQLITE_OK && zSuper[0] && res ){
|
||||
/* If there was a super-journal and this routine will return success,
|
||||
** see if it is possible to delete the super-journal.
|
||||
*/
|
||||
rc = pager_delmaster(pPager, zMaster);
|
||||
rc = pager_delsuper(pPager, zSuper);
|
||||
testcase( rc!=SQLITE_OK );
|
||||
}
|
||||
if( isHot && nPlayback ){
|
||||
@@ -3300,7 +3300,7 @@ static int pagerOpenWalIfPresent(Pager *pPager){
|
||||
|
||||
/*
|
||||
** Playback savepoint pSavepoint. Or, if pSavepoint==NULL, then playback
|
||||
** the entire master journal file. The case pSavepoint==NULL occurs when
|
||||
** the entire super-journal file. The case pSavepoint==NULL occurs when
|
||||
** a ROLLBACK TO command is invoked on a SAVEPOINT that is a transaction
|
||||
** savepoint.
|
||||
**
|
||||
@@ -5040,8 +5040,8 @@ sqlite3_file *sqlite3_database_file_object(const char *zName){
|
||||
** just deleted using OsDelete, *pExists is set to 0 and SQLITE_OK
|
||||
** is returned.
|
||||
**
|
||||
** This routine does not check if there is a master journal filename
|
||||
** at the end of the file. If there is, and that master journal file
|
||||
** This routine does not check if there is a super-journal filename
|
||||
** at the end of the file. If there is, and that super-journal file
|
||||
** does not exist, then the journal file is not really hot. In this
|
||||
** case this routine will return a false-positive. The pager_playback()
|
||||
** routine will discover that the journal file is not really hot and
|
||||
@@ -5786,7 +5786,7 @@ static int pager_open_journal(Pager *pPager){
|
||||
/* TODO: Check if all of these are really required. */
|
||||
pPager->nRec = 0;
|
||||
pPager->journalOff = 0;
|
||||
pPager->setMaster = 0;
|
||||
pPager->setSuper = 0;
|
||||
pPager->journalHdr = 0;
|
||||
rc = writeJournalHdr(pPager);
|
||||
}
|
||||
@@ -6298,9 +6298,9 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
|
||||
** If successful, or if called on a pager for which it is a no-op, this
|
||||
** function returns SQLITE_OK. Otherwise, an IO error code is returned.
|
||||
*/
|
||||
int sqlite3PagerSync(Pager *pPager, const char *zMaster){
|
||||
int sqlite3PagerSync(Pager *pPager, const char *zSuper){
|
||||
int rc = SQLITE_OK;
|
||||
void *pArg = (void*)zMaster;
|
||||
void *pArg = (void*)zSuper;
|
||||
rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC, pArg);
|
||||
if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
|
||||
if( rc==SQLITE_OK && !pPager->noSync ){
|
||||
@@ -6338,10 +6338,10 @@ int sqlite3PagerExclusiveLock(Pager *pPager){
|
||||
}
|
||||
|
||||
/*
|
||||
** Sync the database file for the pager pPager. zMaster points to the name
|
||||
** of a master journal file that should be written into the individual
|
||||
** journal file. zMaster may be NULL, which is interpreted as no master
|
||||
** journal (a single database transaction).
|
||||
** Sync the database file for the pager pPager. zSuper points to the name
|
||||
** of a super-journal file that should be written into the individual
|
||||
** journal file. zSuper may be NULL, which is interpreted as no
|
||||
** super-journal (a single database transaction).
|
||||
**
|
||||
** This routine ensures that:
|
||||
**
|
||||
@@ -6353,9 +6353,9 @@ int sqlite3PagerExclusiveLock(Pager *pPager){
|
||||
**
|
||||
** The only thing that remains to commit the transaction is to finalize
|
||||
** (delete, truncate or zero the first part of) the journal file (or
|
||||
** delete the master journal file if specified).
|
||||
** delete the super-journal file if specified).
|
||||
**
|
||||
** Note that if zMaster==NULL, this does not overwrite a previous value
|
||||
** Note that if zSuper==NULL, this does not overwrite a previous value
|
||||
** passed to an sqlite3PagerCommitPhaseOne() call.
|
||||
**
|
||||
** If the final parameter - noSync - is true, then the database file itself
|
||||
@@ -6365,7 +6365,7 @@ int sqlite3PagerExclusiveLock(Pager *pPager){
|
||||
*/
|
||||
int sqlite3PagerCommitPhaseOne(
|
||||
Pager *pPager, /* Pager object */
|
||||
const char *zMaster, /* If not NULL, the master journal name */
|
||||
const char *zSuper, /* If not NULL, the super-journal name */
|
||||
int noSync /* True to omit the xSync on the db file */
|
||||
){
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
@@ -6383,8 +6383,8 @@ int sqlite3PagerCommitPhaseOne(
|
||||
/* Provide the ability to easily simulate an I/O error during testing */
|
||||
if( sqlite3FaultSim(400) ) return SQLITE_IOERR;
|
||||
|
||||
PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n",
|
||||
pPager->zFilename, zMaster, pPager->dbSize));
|
||||
PAGERTRACE(("DATABASE SYNC: File=%s zSuper=%s nSize=%d\n",
|
||||
pPager->zFilename, zSuper, pPager->dbSize));
|
||||
|
||||
/* If no database changes have been made, return early. */
|
||||
if( pPager->eState<PAGER_WRITER_CACHEMOD ) return SQLITE_OK;
|
||||
@@ -6423,7 +6423,7 @@ int sqlite3PagerCommitPhaseOne(
|
||||
*/
|
||||
#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
|
||||
sqlite3_file *fd = pPager->fd;
|
||||
int bBatch = zMaster==0 /* An SQLITE_IOCAP_BATCH_ATOMIC commit */
|
||||
int bBatch = zSuper==0 /* An SQLITE_IOCAP_BATCH_ATOMIC commit */
|
||||
&& (sqlite3OsDeviceCharacteristics(fd) & SQLITE_IOCAP_BATCH_ATOMIC)
|
||||
&& !pPager->noSync
|
||||
&& sqlite3JournalIsInMemory(pPager->jfd);
|
||||
@@ -6461,7 +6461,7 @@ int sqlite3PagerCommitPhaseOne(
|
||||
|| pPager->journalMode==PAGER_JOURNALMODE_OFF
|
||||
|| pPager->journalMode==PAGER_JOURNALMODE_WAL
|
||||
);
|
||||
if( !zMaster && isOpen(pPager->jfd)
|
||||
if( !zSuper && isOpen(pPager->jfd)
|
||||
&& pPager->journalOff==jrnlBufferSize(pPager)
|
||||
&& pPager->dbSize>=pPager->dbOrigSize
|
||||
&& (!(pPg = sqlite3PcacheDirtyList(pPager->pPCache)) || 0==pPg->pDirty)
|
||||
@@ -6482,7 +6482,7 @@ int sqlite3PagerCommitPhaseOne(
|
||||
}
|
||||
#else /* SQLITE_ENABLE_ATOMIC_WRITE */
|
||||
#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
|
||||
if( zMaster ){
|
||||
if( zSuper ){
|
||||
rc = sqlite3JournalCreate(pPager->jfd);
|
||||
if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
|
||||
assert( bBatch==0 );
|
||||
@@ -6492,11 +6492,11 @@ int sqlite3PagerCommitPhaseOne(
|
||||
#endif /* !SQLITE_ENABLE_ATOMIC_WRITE */
|
||||
if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
|
||||
|
||||
/* Write the master journal name into the journal file. If a master
|
||||
** journal file name has already been written to the journal file,
|
||||
** or if zMaster is NULL (no master journal), then this call is a no-op.
|
||||
/* Write the super-journal name into the journal file. If a
|
||||
** super-journal file name has already been written to the journal file,
|
||||
** or if zSuper is NULL (no super-journal), then this call is a no-op.
|
||||
*/
|
||||
rc = writeMasterJournal(pPager, zMaster);
|
||||
rc = writeSuperJournal(pPager, zSuper);
|
||||
if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
|
||||
|
||||
/* Sync the journal file and write all dirty pages to the database.
|
||||
@@ -6564,7 +6564,7 @@ int sqlite3PagerCommitPhaseOne(
|
||||
|
||||
/* Finally, sync the database file. */
|
||||
if( !noSync ){
|
||||
rc = sqlite3PagerSync(pPager, zMaster);
|
||||
rc = sqlite3PagerSync(pPager, zSuper);
|
||||
}
|
||||
IOTRACE(("DBSYNC %p\n", pPager))
|
||||
}
|
||||
@@ -6629,7 +6629,7 @@ int sqlite3PagerCommitPhaseTwo(Pager *pPager){
|
||||
}
|
||||
|
||||
PAGERTRACE(("COMMIT %d\n", PAGERID(pPager)));
|
||||
rc = pager_end_transaction(pPager, pPager->setMaster, 1);
|
||||
rc = pager_end_transaction(pPager, pPager->setSuper, 1);
|
||||
return pager_error(pPager, rc);
|
||||
}
|
||||
|
||||
@@ -6674,7 +6674,7 @@ int sqlite3PagerRollback(Pager *pPager){
|
||||
if( pagerUseWal(pPager) ){
|
||||
int rc2;
|
||||
rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, -1);
|
||||
rc2 = pager_end_transaction(pPager, pPager->setMaster, 0);
|
||||
rc2 = pager_end_transaction(pPager, pPager->setSuper, 0);
|
||||
if( rc==SQLITE_OK ) rc = rc2;
|
||||
}else if( !isOpen(pPager->jfd) || pPager->eState==PAGER_WRITER_LOCKED ){
|
||||
int eState = pPager->eState;
|
||||
|
Reference in New Issue
Block a user