diff options
Diffstat (limited to 'ext/sqlite/libsqlite/src/pager.c')
-rw-r--r-- | ext/sqlite/libsqlite/src/pager.c | 81 |
1 files changed, 72 insertions, 9 deletions
diff --git a/ext/sqlite/libsqlite/src/pager.c b/ext/sqlite/libsqlite/src/pager.c index 7b32f6e089..e133a3cad0 100644 --- a/ext/sqlite/libsqlite/src/pager.c +++ b/ext/sqlite/libsqlite/src/pager.c @@ -928,6 +928,34 @@ int sqlitepager_pagecount(Pager *pPager){ } /* +** Forward declaration +*/ +static int syncAllPages(Pager*); + +/* +** Truncate the file to the number of pages specified. +*/ +int sqlitepager_truncate(Pager *pPager, Pgno nPage){ + int rc; + if( pPager->dbSize<0 ){ + sqlitepager_pagecount(pPager); + } + if( pPager->errMask!=0 ){ + rc = pager_errcode(pPager); + return rc; + } + if( nPage>=pPager->dbSize ){ + return SQLITE_OK; + } + syncAllPages(pPager); + rc = sqliteOsTruncate(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)nPage); + if( rc==SQLITE_OK ){ + pPager->dbSize = nPage; + } + return rc; +} + +/* ** Shutdown the page cache. Free all memory and close all files. ** ** If a transaction was in progress when this routine is called, that @@ -966,6 +994,10 @@ int sqlitepager_close(Pager *pPager){ ** } */ CLR_PAGER(pPager); + if( pPager->zFilename!=(char*)&pPager[1] ){ + sqliteFree(pPager->zFilename); + sqliteFree(pPager->zJournal); + } sqliteFree(pPager); return SQLITE_OK; } @@ -1171,6 +1203,7 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){ */ assert( pPager!=0 ); assert( pgno!=0 ); + *ppPage = 0; if( pPager->errMask & ~(PAGER_ERR_FULL) ){ return pager_errcode(pPager); } @@ -1181,7 +1214,6 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){ if( pPager->nRef==0 ){ rc = sqliteOsReadLock(&pPager->fd); if( rc!=SQLITE_OK ){ - *ppPage = 0; return rc; } pPager->state = SQLITE_READLOCK; @@ -1199,7 +1231,6 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){ /* This should never happen! */ rc = SQLITE_INTERNAL; } - *ppPage = 0; return rc; } pPager->state = SQLITE_WRITELOCK; @@ -1215,7 +1246,6 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){ if( rc!=SQLITE_OK ){ rc = sqliteOsUnlock(&pPager->fd); assert( rc==SQLITE_OK ); - *ppPage = 0; return SQLITE_BUSY; } pPager->journalOpen = 1; @@ -1243,7 +1273,6 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){ pPg = sqliteMallocRaw( sizeof(*pPg) + SQLITE_PAGE_SIZE + sizeof(u32) + pPager->nExtra ); if( pPg==0 ){ - *ppPage = 0; pager_unwritelock(pPager); pPager->errMask |= PAGER_ERR_MEM; return SQLITE_NOMEM; @@ -1272,7 +1301,6 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){ int rc = syncAllPages(pPager); if( rc!=0 ){ sqlitepager_rollback(pPager); - *ppPage = 0; return SQLITE_IOERR; } pPg = pPager->pFirst; @@ -1287,7 +1315,6 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){ rc = pager_write_pagelist( pPg ); if( rc!=SQLITE_OK ){ sqlitepager_rollback(pPager); - *ppPage = 0; return SQLITE_IOERR; } } @@ -1365,7 +1392,15 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){ assert( pPg->pNextHash->pPrevHash==0 ); pPg->pNextHash->pPrevHash = pPg; } + if( pPager->nExtra>0 ){ + memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra); + } if( pPager->dbSize<0 ) sqlitepager_pagecount(pPager); + if( pPager->errMask!=0 ){ + sqlitepager_unref(PGHDR_TO_DATA(pPg)); + rc = pager_errcode(pPager); + return rc; + } if( pPager->dbSize<(int)pgno ){ memset(PGHDR_TO_DATA(pPg), 0, SQLITE_PAGE_SIZE); }else{ @@ -1376,15 +1411,13 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){ off_t fileSize; if( sqliteOsFileSize(&pPager->fd,&fileSize)!=SQLITE_OK || fileSize>=pgno*SQLITE_PAGE_SIZE ){ + sqlitepager_unref(PGHDR_TO_DATA(pPg)); return rc; }else{ memset(PGHDR_TO_DATA(pPg), 0, SQLITE_PAGE_SIZE); } } } - if( pPager->nExtra>0 ){ - memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra); - } }else{ /* The requested page is in the page cache. */ pPager->nHit++; @@ -1506,6 +1539,10 @@ static int pager_open_journal(Pager *pPager){ pPager->alwaysRollback = 0; pPager->nRec = 0; sqlitepager_pagecount(pPager); + if( pPager->errMask!=0 ){ + rc = pager_errcode(pPager); + return rc; + } pPager->origDbSize = pPager->dbSize; if( journal_format==JOURNAL_FORMAT_3 ){ rc = sqliteOsWrite(&pPager->jfd, aJournalMagic3, sizeof(aJournalMagic3)); @@ -1723,6 +1760,25 @@ int sqlitepager_iswriteable(void *pData){ } /* +** Replace the content of a single page with the information in the third +** argument. +*/ +int sqlitepager_overwrite(Pager *pPager, Pgno pgno, void *pData){ + void *pPage; + int rc; + + rc = sqlitepager_get(pPager, pgno, &pPage); + if( rc==SQLITE_OK ){ + rc = sqlitepager_write(pPage); + if( rc==SQLITE_OK ){ + memcpy(pPage, pData, SQLITE_PAGE_SIZE); + } + sqlitepager_unref(pPage); + } + return rc; +} + +/* ** A call to this routine tells the pager that it is not necessary to ** write the information on page "pgno" back to the disk, even though ** that page might be marked as dirty. @@ -2007,6 +2063,13 @@ int sqlitepager_ckpt_rollback(Pager *pPager){ return rc; } +/* +** Return the full pathname of the database file. +*/ +const char *sqlitepager_filename(Pager *pPager){ + return pPager->zFilename; +} + #ifdef SQLITE_TEST /* ** Print a listing of all referenced pages and their ref count. |