-C Merge\strunk\schanges\swith\sthis\sbranch.
-D 2015-08-24T06:44:17.840
+C Consolidate\stwo\sblocks\sof\ssimilar\scode\sin\sbtreeFixUnlocked().
+D 2015-08-24T10:05:03.012
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in e2218eb228374422969de7b1680eda6864affcef
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F src/backup.c 4d9134dc988a87838c06056c89c0e8c4700a0452
F src/bitvec.c d1f21d7d91690747881f03940584f4cc548c9d3d
F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
-F src/btree.c 245bc696824d5107f3570905325c6ac5b05c18f8
+F src/btree.c e807409602996359211c855078fa5cbcf59da032
F src/btree.h 00d4cdb747c4172a5566faf037116985dbbc377e
F src/btreeInt.h 0c19847f87ab82e4f5e67750a069f10829475da6
F src/build.c e47b6fffe14a28d9050e6747beebb01597d37542
F test/unixexcl.test cd6c765f75e50e8e2c2ba763149e5d340ea19825
F test/unlocked.test d143a871bd874311d4e5c98ce458218ca6b579fd
F test/unlocked2.test aaa42a08052a146466220b6c3a062ff3c4776ad6
-F test/unlocked3.test 1bc4e3ad8693302639e50b4833a527807ee4863b
+F test/unlocked3.test 2cacc31742561f6924706ed9472d0095839da9e4
F test/unordered.test ca7adce0419e4ca0c50f039885e76ed2c531eda8
F test/update.test 6c68446b8a0a33d522a7c72b320934596a2d7d32
F test/uri.test 23662b7b61958b0f0e47082de7d06341ccf85d5b
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 4460764ea8fc948fe02f0a09476857839b3aa1ae f0aba0e120074430cd7ad93291fcc97b8a25a054
-R c9a4c2c74a91d952dffb223e6caf31f7
+P 876810c28b3ad573ae46050ec699ef7eea4e313d
+R 11d77b8f4d3f6d9b5ad54020bb4092ee
U dan
-Z 9a4849fb712895f27dbf139db01b2763
+Z 46d9657b2162cb9e544c380eb188ec18
#endif
#ifdef SQLITE_ENABLE_UNLOCKED
+/*
+** This function is called as part of merging an UNLOCKED transaction with
+** the snapshot at the head of the wal file. It relocates all pages in the
+** range iFirst..iLast, inclusive. It is assumed that the BtreePtrmap
+** structure at BtShared.pMap contains the location of the pointers to each
+** page in the range.
+**
+** If pnCurrent is NULL, then all pages in the range are moved to currently
+** free locations (i.e. free-list entries) within the database file before page
+** iFirst.
+**
+** Or, if pnCurrent is not NULL, then it points to a value containing the
+** current size of the database file in pages. In this case, all pages are
+** relocated to the end of the database file - page iFirst is relocated to
+** page (*pnCurrent+1), page iFirst+1 to page (*pnCurrent+2), and so on.
+** Value *pnCurrent is set to the new size of the database before this
+** function returns.
+**
+** If no error occurs, SQLITE_OK is returned. Otherwise, an SQLite error code.
+*/
+static int btreeRelocateRange(
+ BtShared *pBt, /* B-tree handle */
+ Pgno iFirst, /* First page to relocate */
+ Pgno iLast, /* Last page to relocate */
+ Pgno *pnCurrent /* If not NULL, IN/OUT: Database size */
+){
+ int rc = SQLITE_OK;
+ BtreePtrmap *pMap = pBt->pMap;
+ Pgno iPg;
+
+ for(iPg=iFirst; iPg<=iLast && rc==SQLITE_OK; iPg++){
+ MemPage *pFree = 0; /* Page allocated from free-list */
+ MemPage *pPg = 0;
+ Pgno iNew; /* New page number for pPg */
+ PtrmapEntry *pEntry; /* Pointer map entry for page iPg */
+
+ if( iPg==PENDING_BYTE_PAGE(pBt) ) continue;
+ pEntry = &pMap->aPtr[iPg - pMap->iFirst];
+
+ if( pEntry->eType==PTRMAP_FREEPAGE ){
+ Pgno dummy;
+ rc = allocateBtreePage(pBt, &pFree, &dummy, iPg, BTALLOC_EXACT);
+ releasePage(pFree);
+ assert( rc!=SQLITE_OK || dummy==iPg );
+ }else if( pnCurrent ){
+ btreeGetPage(pBt, iPg, &pPg, 0);
+ assert( sqlite3PagerIswriteable(pPg->pDbPage) );
+ assert( sqlite3PagerPageRefcount(pPg->pDbPage)==1 );
+ iNew = ++(*pnCurrent);
+ if( iNew==PENDING_BYTE_PAGE(pBt) ) iNew = ++(*pnCurrent);
+ rc = relocatePage(pBt, pPg, pEntry->eType, pEntry->parent, iNew, 1);
+ releasePageNotNull(pPg);
+ }else{
+ rc = allocateBtreePage(pBt, &pFree, &iNew, iFirst-1, BTALLOC_LE);
+ assert( rc!=SQLITE_OK || iNew<iFirst );
+ releasePage(pFree);
+ if( rc==SQLITE_OK ){
+ MemPage *pPg = 0;
+ btreeGetPage(pBt, iPg, &pPg, 0);
+ rc = relocatePage(pBt, pPg, pEntry->eType, pEntry->parent,iNew,1);
+ releasePage(pPg);
+ }
+ }
+ }
+ return rc;
+}
+
/*
** The b-tree handle passed as the only argument is about to commit an
** UNLOCKED transaction. At this point it is guaranteed that this is
if( rc==SQLITE_OK ){
Pgno nHPage = get4byte(&p1[28]);
- Pgno nFinal = nHPage; /* Size of db after transaction merge */
+ Pgno nFin = nHPage; /* Size of db after transaction merge */
if( sqlite3PagerIswriteable(pPage1->pDbPage) ){
Pgno iHTrunk = get4byte(&p1[32]);
/* The current transaction allocated pages pMap->iFirst through
** nPage (inclusive) at the end of the database file. Meanwhile,
** other transactions have allocated (iFirst..nHPage). So move
- ** pages (iFirst..MIN(nPage,nHPage)) to (MAX(nPage,nHPage)+1).
- */
+ ** pages (iFirst..MIN(nPage,nHPage)) to (MAX(nPage,nHPage)+1). */
Pgno iLast = MIN(nPage, nHPage); /* Last page to move */
- Pgno iPg;
Pgno nCurrent; /* Current size of db */
nCurrent = MAX(nPage, nHPage);
+ rc = btreeRelocateRange(pBt, pMap->iFirst, iLast, &nCurrent);
- for(iPg=pMap->iFirst; iPg<=iLast && rc==SQLITE_OK; iPg++){
- MemPage *pPg = 0;
- Pgno iNew; /* New page number for pPg */
- PtrmapEntry *pEntry; /* Pointer map entry for page iPg */
-
- if( iPg==PENDING_BYTE_PAGE(pBt) ) continue;
- pEntry = &pMap->aPtr[iPg - pMap->iFirst];
- if( pEntry->eType==PTRMAP_FREEPAGE ){
- MemPage *pFree = 0;
- Pgno dummy;
- rc = allocateBtreePage(pBt, &pFree, &dummy, iPg, BTALLOC_EXACT);
- releasePage(pFree);
- assert( rc!=SQLITE_OK || dummy==iPg );
- }else{
- btreeGetPage(pBt, iPg, &pPg, 0);
- assert( sqlite3PagerIswriteable(pPg->pDbPage) );
- assert( sqlite3PagerPageRefcount(pPg->pDbPage)==1 );
- iNew = ++nCurrent;
- if( iNew==PENDING_BYTE_PAGE(pBt) ) iNew = ++nCurrent;
- rc = relocatePage(pBt, pPg, pEntry->eType, pEntry->parent, iNew, 1);
- releasePageNotNull(pPg);
+ /* There are now no collisions with the snapshot at the head of the
+ ** database file. So at this point it would be possible to write
+ ** the transaction out to disk. Before doing so though, attempt to
+ ** relocate some of the new pages to free locations within the body
+ ** of the database file (i.e. free-list entries). */
+ if( rc==SQLITE_OK ){
+ assert( nCurrent!=PENDING_BYTE_PAGE(pBt) );
+ sqlite3PagerSetDbsize(pBt->pPager, nCurrent);
+ nFree = get4byte(&p1[36]);
+ nFin = MAX(nCurrent-nFree, nHPage);
+ if( nCurrent>PENDING_BYTE_PAGE(pBt) && nFin<=PENDING_BYTE_PAGE(pBt) ){
+ nFin--;
}
- }
- sqlite3PagerSetDbsize(pPager, nCurrent);
- assert( nCurrent!=PENDING_BYTE_PAGE(pBt) );
-
- nFree = get4byte(&p1[36]);
- nFinal = MAX(nCurrent-nFree, nHPage);
- if( nCurrent>PENDING_BYTE_PAGE(pBt) && nFinal<=PENDING_BYTE_PAGE(pBt) ){
- nFinal--;
+ rc = btreeRelocateRange(pBt, nFin+1, nCurrent, 0);
}
- for(iPg=nFinal+1; rc==SQLITE_OK && iPg<=nCurrent; iPg++){
- Pgno iNew; /* New page number for pPg */
- MemPage *pFree;
- PtrmapEntry *pEntry; /* Pointer map entry for page iPg */
-
- if( iPg==PENDING_BYTE_PAGE(pBt) ) continue;
- pEntry = &pMap->aPtr[iPg - pMap->iFirst];
- if( pEntry->eType==PTRMAP_FREEPAGE ){
- rc = allocateBtreePage(pBt, &pFree, &iNew, iPg, BTALLOC_EXACT);
- releasePage(pFree);
- }else{
- rc = allocateBtreePage(pBt, &pFree, &iNew, nFinal, BTALLOC_LE);
- assert( rc!=SQLITE_OK || iNew<=nFinal );
- releasePage(pFree);
- if( rc==SQLITE_OK ){
- MemPage *pPg = 0;
- btreeGetPage(pBt, iPg, &pPg, 0);
- rc = relocatePage(pBt, pPg, pEntry->eType, pEntry->parent,iNew,1);
- releasePage(pPg);
- }
- }
- }
- put4byte(&p1[28], nFinal);
+ put4byte(&p1[28], nFin);
}
}
- sqlite3PagerSetDbsize(pPager, nFinal);
+ sqlite3PagerSetDbsize(pPager, nFin);
}
return rc;