aboutsummaryrefslogtreecommitdiff
path: root/src/memjournal.c
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2016-03-16 01:16:30 +0000
committerdrh <drh@noemail.net>2016-03-16 01:16:30 +0000
commit47e1842e5bd5c5f467b0290f3fde9df69fa42a25 (patch)
tree69786029a35258e2ee2a76f5d023764e19a074f0 /src/memjournal.c
parentc5c67abb9ab2c58d41f75a41a1693e4b30e00bd5 (diff)
parent32f57d4c373c8f49b59f4a40149c136ef8a5632b (diff)
downloadsqlite-47e1842e5bd5c5f467b0290f3fde9df69fa42a25.tar.gz
sqlite-47e1842e5bd5c5f467b0290f3fde9df69fa42a25.zip
Merge all recent enhancements from trunk.
FossilOrigin-Name: 6a7ee04b0ddac36a87d5ed2ac89a53e537f4d5a3
Diffstat (limited to 'src/memjournal.c')
-rw-r--r--src/memjournal.c158
1 files changed, 75 insertions, 83 deletions
diff --git a/src/memjournal.c b/src/memjournal.c
index 04780df99..b81682de8 100644
--- a/src/memjournal.c
+++ b/src/memjournal.c
@@ -69,7 +69,6 @@ struct MemJournal {
int flags; /* xOpen flags */
sqlite3_vfs *pVfs; /* The "real" underlying VFS */
const char *zJournal; /* Name of the journal file */
- sqlite3_file *pReal; /* The "real" underlying file descriptor */
};
/*
@@ -83,41 +82,42 @@ static int memjrnlRead(
sqlite_int64 iOfst /* Begin reading at this offset */
){
MemJournal *p = (MemJournal *)pJfd;
- if( p->pReal ){
- return sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst);
- }else if( (iAmt+iOfst)>p->endpoint.iOffset ){
+ u8 *zOut = zBuf;
+ int nRead = iAmt;
+ int iChunkOffset;
+ FileChunk *pChunk;
+
+#ifdef SQLITE_ENABLE_ATOMIC_WRITE
+ if( (iAmt+iOfst)>p->endpoint.iOffset ){
return SQLITE_IOERR_SHORT_READ;
- }else{
- u8 *zOut = zBuf;
- int nRead = iAmt;
- int iChunkOffset;
- FileChunk *pChunk;
-
- if( p->readpoint.iOffset!=iOfst || iOfst==0 ){
- sqlite3_int64 iOff = 0;
- for(pChunk=p->pFirst;
- ALWAYS(pChunk) && (iOff+p->nChunkSize)<=iOfst;
- pChunk=pChunk->pNext
- ){
- iOff += p->nChunkSize;
- }
- }else{
- pChunk = p->readpoint.pChunk;
- }
+ }
+#endif
- iChunkOffset = (int)(iOfst%p->nChunkSize);
- do {
- int iSpace = p->nChunkSize - iChunkOffset;
- int nCopy = MIN(nRead, (p->nChunkSize - iChunkOffset));
- memcpy(zOut, (u8*)pChunk->zChunk + iChunkOffset, nCopy);
- zOut += nCopy;
- nRead -= iSpace;
- iChunkOffset = 0;
- } while( nRead>=0 && (pChunk=pChunk->pNext)!=0 && nRead>0 );
- p->readpoint.iOffset = iOfst+iAmt;
- p->readpoint.pChunk = pChunk;
+ assert( (iAmt+iOfst)<=p->endpoint.iOffset );
+ if( p->readpoint.iOffset!=iOfst || iOfst==0 ){
+ sqlite3_int64 iOff = 0;
+ for(pChunk=p->pFirst;
+ ALWAYS(pChunk) && (iOff+p->nChunkSize)<=iOfst;
+ pChunk=pChunk->pNext
+ ){
+ iOff += p->nChunkSize;
+ }
+ }else{
+ pChunk = p->readpoint.pChunk;
}
+ iChunkOffset = (int)(iOfst%p->nChunkSize);
+ do {
+ int iSpace = p->nChunkSize - iChunkOffset;
+ int nCopy = MIN(nRead, (p->nChunkSize - iChunkOffset));
+ memcpy(zOut, (u8*)pChunk->zChunk + iChunkOffset, nCopy);
+ zOut += nCopy;
+ nRead -= iSpace;
+ iChunkOffset = 0;
+ } while( nRead>=0 && (pChunk=pChunk->pNext)!=0 && nRead>0 );
+ p->readpoint.iOffset = iOfst+iAmt;
+ p->readpoint.pChunk = pChunk;
+
return SQLITE_OK;
}
@@ -138,37 +138,37 @@ static void memjrnlFreeChunks(MemJournal *p){
** Flush the contents of memory to a real file on disk.
*/
static int memjrnlCreateFile(MemJournal *p){
- int rc = SQLITE_OK;
- if( !p->pReal ){
- sqlite3_file *pReal = (sqlite3_file *)&p[1];
- rc = sqlite3OsOpen(p->pVfs, p->zJournal, pReal, p->flags, 0);
- if( rc==SQLITE_OK ){
- int nChunk = p->nChunkSize;
- i64 iOff = 0;
- FileChunk *pIter;
- p->pReal = pReal;
- for(pIter=p->pFirst; pIter && rc==SQLITE_OK; pIter=pIter->pNext){
- int nWrite = nChunk;
- if( pIter==p->endpoint.pChunk ){
- nWrite = p->endpoint.iOffset % p->nChunkSize;
- if( nWrite==0 ) nWrite = p->nChunkSize;
- }
- rc = sqlite3OsWrite(pReal, (u8*)pIter->zChunk, nWrite, iOff);
- iOff += nWrite;
- }
- if( rc!=SQLITE_OK ){
- /* If an error occurred while writing to the file, close it before
- ** returning. This way, SQLite uses the in-memory journal data to
- ** roll back changes made to the internal page-cache before this
- ** function was called. */
- sqlite3OsClose(pReal);
- p->pReal = 0;
- }else{
- /* No error has occurred. Free the in-memory buffers. */
- memjrnlFreeChunks(p);
+ int rc;
+ sqlite3_file *pReal = (sqlite3_file*)p;
+ MemJournal copy = *p;
+
+ memset(p, 0, sizeof(MemJournal));
+ rc = sqlite3OsOpen(copy.pVfs, copy.zJournal, pReal, copy.flags, 0);
+ if( rc==SQLITE_OK ){
+ int nChunk = copy.nChunkSize;
+ i64 iOff = 0;
+ FileChunk *pIter;
+ for(pIter=copy.pFirst; pIter; pIter=pIter->pNext){
+ if( iOff + nChunk > copy.endpoint.iOffset ){
+ nChunk = copy.endpoint.iOffset - iOff;
}
+ rc = sqlite3OsWrite(pReal, (u8*)pIter->zChunk, nChunk, iOff);
+ if( rc ) break;
+ iOff += nChunk;
+ }
+ if( rc==SQLITE_OK ){
+ /* No error has occurred. Free the in-memory buffers. */
+ memjrnlFreeChunks(&copy);
}
}
+ if( rc!=SQLITE_OK ){
+ /* If an error occurred while creating or writing to the file, restore
+ ** the original before returning. This way, SQLite uses the in-memory
+ ** journal data to roll back changes made to the internal page-cache
+ ** before this function was called. */
+ sqlite3OsClose(pReal);
+ *p = copy;
+ }
return rc;
}
@@ -186,16 +186,12 @@ static int memjrnlWrite(
int nWrite = iAmt;
u8 *zWrite = (u8 *)zBuf;
- /* If the file has already been created on disk. */
- if( p->pReal ){
- return sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst);
- }
-
- /* If the file should be created now. */
- else if( p->nSpill>0 && (iAmt+iOfst)>p->nSpill ){
+ /* If the file should be created now, create it and write the new data
+ ** into the file on disk. */
+ if( p->nSpill>0 && (iAmt+iOfst)>p->nSpill ){
int rc = memjrnlCreateFile(p);
if( rc==SQLITE_OK ){
- rc = memjrnlWrite(pJfd, zBuf, iAmt, iOfst);
+ rc = sqlite3OsWrite(pJfd, zBuf, iAmt, iOfst);
}
return rc;
}
@@ -208,10 +204,15 @@ static int memjrnlWrite(
** atomic-write optimization. In this case the first 28 bytes of the
** journal file may be written as part of committing the transaction. */
assert( iOfst==p->endpoint.iOffset || iOfst==0 );
+#ifdef SQLITE_ENABLE_ATOMIC_WRITE
if( iOfst==0 && p->pFirst ){
assert( p->nChunkSize>iAmt );
memcpy((u8*)p->pFirst->zChunk, zBuf, iAmt);
- }else{
+ }else
+#else
+ assert( iOfst>0 || p->pFirst==0 );
+#endif
+ {
while( nWrite>0 ){
FileChunk *pChunk = p->endpoint.pChunk;
int iChunkOffset = (int)(p->endpoint.iOffset%p->nChunkSize);
@@ -255,9 +256,7 @@ static int memjrnlWrite(
*/
static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){
MemJournal *p = (MemJournal *)pJfd;
- if( p->pReal ){
- return sqlite3OsTruncate(p->pReal, size);
- }else if( size==0 ){
+ if( ALWAYS(size==0) ){
memjrnlFreeChunks(p);
p->nSize = 0;
p->endpoint.pChunk = 0;
@@ -274,7 +273,6 @@ static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){
static int memjrnlClose(sqlite3_file *pJfd){
MemJournal *p = (MemJournal *)pJfd;
memjrnlFreeChunks(p);
- if( p->pReal ) sqlite3OsClose(p->pReal);
return SQLITE_OK;
}
@@ -285,10 +283,7 @@ static int memjrnlClose(sqlite3_file *pJfd){
** syncing an in-memory journal is a no-op.
*/
static int memjrnlSync(sqlite3_file *pJfd, int flags){
- MemJournal *p = (MemJournal *)pJfd;
- if( p->pReal ){
- return sqlite3OsSync(p->pReal, flags);
- }
+ UNUSED_PARAMETER2(pJfd, flags);
return SQLITE_OK;
}
@@ -297,9 +292,6 @@ static int memjrnlSync(sqlite3_file *pJfd, int flags){
*/
static int memjrnlFileSize(sqlite3_file *pJfd, sqlite_int64 *pSize){
MemJournal *p = (MemJournal *)pJfd;
- if( p->pReal ){
- return sqlite3OsFileSize(p->pReal, pSize);
- }
*pSize = (sqlite_int64) p->endpoint.iOffset;
return SQLITE_OK;
}
@@ -354,7 +346,7 @@ int sqlite3JournalOpen(
** it using the sqlite3OsOpen() function of the underlying VFS. In this
** case none of the code in this module is executed as a result of calls
** made on the journal file-handle. */
- memset(p, 0, sizeof(MemJournal) + (pVfs ? pVfs->szOsFile : 0));
+ memset(p, 0, sizeof(MemJournal));
if( nSpill==0 ){
return sqlite3OsOpen(pVfs, zName, pJfd, flags, 0);
}
@@ -403,7 +395,7 @@ int sqlite3JournalCreate(sqlite3_file *p){
** or false otherwise.
*/
int sqlite3JournalIsInMemory(sqlite3_file *p){
- return p->pMethods==&MemJournalMethods && ((MemJournal*)p)->pReal==0;
+ return p->pMethods==&MemJournalMethods;
}
/*
@@ -411,5 +403,5 @@ int sqlite3JournalIsInMemory(sqlite3_file *p){
** pVfs to create the underlying on-disk files.
*/
int sqlite3JournalSize(sqlite3_vfs *pVfs){
- return pVfs->szOsFile + sizeof(MemJournal);
+ return MAX(pVfs->szOsFile, sizeof(MemJournal));
}