1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-05 15:55:57 +03:00

Fix a problem that occurs when one process causes the log-summary file to grow and then a second process attempts to read the database.

FossilOrigin-Name: b51a5f8bc660616aa264025dd7ad4bdab458814b
This commit is contained in:
dan
2010-04-27 05:42:32 +00:00
parent 29d4beccc0
commit 31f98fc8e4
8 changed files with 110 additions and 50 deletions

View File

@@ -592,6 +592,22 @@ static int logSummaryMap(LogSummary *pSummary, int nByte){
return SQLITE_OK;
}
/*
** The log-summary file is already mapped to pSummary->aData[], but the
** mapping needs to be resized. Unmap and remap the file so that the mapping
** is at least nByte bytes in size, or the size of the entire file if it
** is larger than nByte bytes.
*/
static int logSummaryRemap(LogSummary *pSummary, int nByte){
int rc;
sqlite3_mutex_enter(pSummary->mutex);
munmap(pSummary->aData, pSummary->nData*4);
pSummary->aData = 0;
rc = logSummaryMap(pSummary, nByte);
sqlite3_mutex_leave(pSummary->mutex);
return rc;
}
/*
** Return the index in the LogSummary.aData array that corresponds to
** frame iFrame. The log-summary file consists of a header, followed by
@@ -613,18 +629,18 @@ static int logSummaryEntry(u32 iFrame){
** the previous call), but that restriction is not enforced or asserted
** here.
*/
static void logSummaryAppend(LogSummary *pSummary, u32 iFrame, u32 iPage){
static int logSummaryAppend(LogSummary *pSummary, u32 iFrame, u32 iPage){
u32 iSlot = logSummaryEntry(iFrame);
while( (iSlot+128)>=pSummary->nData ){
int rc;
int nByte = pSummary->nData*4 + LOGSUMMARY_MMAP_INCREMENT;
/* Unmap and remap the log-summary file. */
sqlite3_mutex_enter(pSummary->mutex);
munmap(pSummary->aData, pSummary->nData*4);
pSummary->aData = 0;
logSummaryMap(pSummary, nByte);
sqlite3_mutex_leave(pSummary->mutex);
rc = logSummaryRemap(pSummary, nByte);
if( rc!=SQLITE_OK ){
return rc;
}
}
/* Set the log-summary entry itself */
@@ -649,6 +665,8 @@ static void logSummaryAppend(LogSummary *pSummary, u32 iFrame, u32 iPage){
logMergesort8(aFrame, aTmp, aIndex, &nIndex);
memset(&aIndex[nIndex], aIndex[nIndex-1], 256-nIndex);
}
return SQLITE_OK;
}
@@ -1496,6 +1514,16 @@ int sqlite3WalOpenSnapshot(Log *pLog, int *pChanged){
if( rc!=SQLITE_OK ){
/* An error occured while attempting log recovery. */
sqlite3WalCloseSnapshot(pLog);
}else{
/* Check if the mapping needs to grow. */
LogSummary *pSummary = pLog->pSummary;
if( pLog->hdr.iLastPg
&& logSummaryEntry(pLog->hdr.iLastPg)>=pSummary->nData
){
rc = logSummaryRemap(pSummary, 0);
assert( rc || logSummaryEntry(pLog->hdr.iLastPg)<pSummary->nData );
}
}
}
return rc;
@@ -1516,20 +1544,20 @@ void sqlite3WalCloseSnapshot(Log *pLog){
** Read a page from the log, if it is present.
*/
int sqlite3WalRead(Log *pLog, Pgno pgno, int *pInLog, u8 *pOut){
LogSummary *pSummary = pLog->pSummary;
u32 iRead = 0;
u32 *aData;
int iFrame = (pLog->hdr.iLastPg & 0xFFFFFF00);
assert( pLog->isLocked );
sqlite3_mutex_enter(pLog->pSummary->mutex);
aData = pLog->pSummary->aData;
sqlite3_mutex_enter(pSummary->mutex);
/* Do a linear search of the unindexed block of page-numbers (if any)
** at the end of the log-summary. An alternative to this would be to
** build an index in private memory each time a read transaction is
** opened on a new snapshot.
*/
aData = pSummary->aData;
if( pLog->hdr.iLastPg ){
u32 *pi = &aData[logSummaryEntry(pLog->hdr.iLastPg)];
u32 *piStop = pi - (pLog->hdr.iLastPg & 0xFF);