/ Check-in [701302b4]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Consolidate two blocks of similar code in btreeFixUnlocked().
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | begin-concurrent
Files: files | file ages | folders
SHA1: 701302b4bd62ca7aefe643eac096a0ee672a62fa
User & Date: dan 2015-08-24 10:05:03
Wiki:begin-concurrent
Context
2015-08-24
16:00
Fix compilation without SQLITE_ENABLE_UNLOCKED. Also other code organization issues. check-in: 04113557 user: dan tags: begin-concurrent
10:05
Consolidate two blocks of similar code in btreeFixUnlocked(). check-in: 701302b4 user: dan tags: begin-concurrent
06:44
Merge trunk changes with this branch. check-in: 876810c2 user: dan tags: begin-concurrent
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/btree.c.

  3843   3843   }
  3844   3844   
  3845   3845   #else /* ifndef SQLITE_OMIT_AUTOVACUUM */
  3846   3846   # define setChildPtrmaps(x) SQLITE_OK
  3847   3847   #endif
  3848   3848   
  3849   3849   #ifdef SQLITE_ENABLE_UNLOCKED
         3850  +/*
         3851  +** This function is called as part of merging an UNLOCKED transaction with
         3852  +** the snapshot at the head of the wal file. It relocates all pages in the
         3853  +** range iFirst..iLast, inclusive. It is assumed that the BtreePtrmap 
         3854  +** structure at BtShared.pMap contains the location of the pointers to each
         3855  +** page in the range.
         3856  +**
         3857  +** If pnCurrent is NULL, then all pages in the range are moved to currently
         3858  +** free locations (i.e. free-list entries) within the database file before page
         3859  +** iFirst.
         3860  +**
         3861  +** Or, if pnCurrent is not NULL, then it points to a value containing the
         3862  +** current size of the database file in pages. In this case, all pages are
         3863  +** relocated to the end of the database file - page iFirst is relocated to
         3864  +** page (*pnCurrent+1), page iFirst+1 to page (*pnCurrent+2), and so on.
         3865  +** Value *pnCurrent is set to the new size of the database before this 
         3866  +** function returns.
         3867  +**
         3868  +** If no error occurs, SQLITE_OK is returned. Otherwise, an SQLite error code.
         3869  +*/
         3870  +static int btreeRelocateRange(
         3871  +  BtShared *pBt,                  /* B-tree handle */
         3872  +  Pgno iFirst,                    /* First page to relocate */
         3873  +  Pgno iLast,                     /* Last page to relocate */
         3874  +  Pgno *pnCurrent                 /* If not NULL, IN/OUT: Database size */
         3875  +){
         3876  +  int rc = SQLITE_OK;
         3877  +  BtreePtrmap *pMap = pBt->pMap;
         3878  +  Pgno iPg;
         3879  +
         3880  +  for(iPg=iFirst; iPg<=iLast && rc==SQLITE_OK; iPg++){
         3881  +    MemPage *pFree = 0;     /* Page allocated from free-list */
         3882  +    MemPage *pPg = 0;
         3883  +    Pgno iNew;              /* New page number for pPg */
         3884  +    PtrmapEntry *pEntry;    /* Pointer map entry for page iPg */
         3885  +
         3886  +    if( iPg==PENDING_BYTE_PAGE(pBt) ) continue;
         3887  +    pEntry = &pMap->aPtr[iPg - pMap->iFirst];
         3888  +
         3889  +    if( pEntry->eType==PTRMAP_FREEPAGE ){
         3890  +      Pgno dummy;
         3891  +      rc = allocateBtreePage(pBt, &pFree, &dummy, iPg, BTALLOC_EXACT);
         3892  +      releasePage(pFree);
         3893  +      assert( rc!=SQLITE_OK || dummy==iPg );
         3894  +    }else if( pnCurrent ){
         3895  +      btreeGetPage(pBt, iPg, &pPg, 0);
         3896  +      assert( sqlite3PagerIswriteable(pPg->pDbPage) );
         3897  +      assert( sqlite3PagerPageRefcount(pPg->pDbPage)==1 );
         3898  +      iNew = ++(*pnCurrent);
         3899  +      if( iNew==PENDING_BYTE_PAGE(pBt) ) iNew = ++(*pnCurrent);
         3900  +      rc = relocatePage(pBt, pPg, pEntry->eType, pEntry->parent, iNew, 1);
         3901  +      releasePageNotNull(pPg);
         3902  +    }else{
         3903  +      rc = allocateBtreePage(pBt, &pFree, &iNew, iFirst-1, BTALLOC_LE);
         3904  +      assert( rc!=SQLITE_OK || iNew<iFirst );
         3905  +      releasePage(pFree);
         3906  +      if( rc==SQLITE_OK ){
         3907  +        MemPage *pPg = 0;
         3908  +        btreeGetPage(pBt, iPg, &pPg, 0);
         3909  +        rc = relocatePage(pBt, pPg, pEntry->eType, pEntry->parent,iNew,1);
         3910  +        releasePage(pPg);
         3911  +      }
         3912  +    }
         3913  +  }
         3914  +  return rc;
         3915  +}
         3916  +
  3850   3917   /*
  3851   3918   ** The b-tree handle passed as the only argument is about to commit an
  3852   3919   ** UNLOCKED transaction. At this point it is guaranteed that this is 
  3853   3920   ** possible - the wal WRITER lock is held and it is known that there are 
  3854   3921   ** no conflicts with committed transactions.
  3855   3922   */
  3856   3923   static int btreeFixUnlocked(Btree *p){
................................................................................
  3871   3938     assert( sqlite3PagerIsUnlocked(pPager) );
  3872   3939     assert( pBt->pMap );
  3873   3940     rc = sqlite3PagerUpgradeSnapshot(pPager, pPage1->pDbPage);
  3874   3941     assert( p1==pPage1->aData );
  3875   3942   
  3876   3943     if( rc==SQLITE_OK ){
  3877   3944       Pgno nHPage = get4byte(&p1[28]);
  3878         -    Pgno nFinal = nHPage;         /* Size of db after transaction merge */
         3945  +    Pgno nFin = nHPage;         /* Size of db after transaction merge */
  3879   3946   
  3880   3947       if( sqlite3PagerIswriteable(pPage1->pDbPage) ){
  3881   3948         Pgno iHTrunk = get4byte(&p1[32]);
  3882   3949         u32 nHFree = get4byte(&p1[36]);
  3883   3950   
  3884   3951         /* Attach the head database free list to the end of the current
  3885   3952         ** transactions free-list (if any).  */
................................................................................
  3903   3970           ** not have shrunk since the transaction was opened. Therefore nHPage
  3904   3971           ** should be set to (pMap->iFirst-1) or greater. */
  3905   3972           rc = SQLITE_CORRUPT_BKPT;
  3906   3973         }else{
  3907   3974           /* The current transaction allocated pages pMap->iFirst through
  3908   3975           ** nPage (inclusive) at the end of the database file. Meanwhile,
  3909   3976           ** other transactions have allocated (iFirst..nHPage). So move
  3910         -        ** pages (iFirst..MIN(nPage,nHPage)) to (MAX(nPage,nHPage)+1).
  3911         -        */
         3977  +        ** pages (iFirst..MIN(nPage,nHPage)) to (MAX(nPage,nHPage)+1).  */
  3912   3978           Pgno iLast = MIN(nPage, nHPage);    /* Last page to move */
  3913         -        Pgno iPg;
  3914   3979           Pgno nCurrent;                      /* Current size of db */
  3915   3980           nCurrent = MAX(nPage, nHPage);
  3916         -
  3917         -        for(iPg=pMap->iFirst; iPg<=iLast && rc==SQLITE_OK; iPg++){
  3918         -          MemPage *pPg = 0;
  3919         -          Pgno iNew;              /* New page number for pPg */
  3920         -          PtrmapEntry *pEntry;    /* Pointer map entry for page iPg */
  3921         -
  3922         -          if( iPg==PENDING_BYTE_PAGE(pBt) ) continue;
  3923         -          pEntry = &pMap->aPtr[iPg - pMap->iFirst];
  3924         -          if( pEntry->eType==PTRMAP_FREEPAGE ){
  3925         -            MemPage *pFree = 0;
  3926         -            Pgno dummy;
  3927         -            rc = allocateBtreePage(pBt, &pFree, &dummy, iPg, BTALLOC_EXACT);
  3928         -            releasePage(pFree);
  3929         -            assert( rc!=SQLITE_OK || dummy==iPg );
  3930         -          }else{
  3931         -            btreeGetPage(pBt, iPg, &pPg, 0);
  3932         -            assert( sqlite3PagerIswriteable(pPg->pDbPage) );
  3933         -            assert( sqlite3PagerPageRefcount(pPg->pDbPage)==1 );
  3934         -            iNew = ++nCurrent;
  3935         -            if( iNew==PENDING_BYTE_PAGE(pBt) ) iNew = ++nCurrent;
  3936         -            rc = relocatePage(pBt, pPg, pEntry->eType, pEntry->parent, iNew, 1);
  3937         -            releasePageNotNull(pPg);
  3938         -          }
  3939         -        }
  3940         -        sqlite3PagerSetDbsize(pPager, nCurrent);
  3941         -        assert( nCurrent!=PENDING_BYTE_PAGE(pBt) );
  3942         -
  3943         -        nFree = get4byte(&p1[36]);
  3944         -        nFinal = MAX(nCurrent-nFree, nHPage);
  3945         -        if( nCurrent>PENDING_BYTE_PAGE(pBt) && nFinal<=PENDING_BYTE_PAGE(pBt) ){
  3946         -          nFinal--;
  3947         -        }
  3948         -
  3949         -        for(iPg=nFinal+1; rc==SQLITE_OK && iPg<=nCurrent; iPg++){
  3950         -          Pgno iNew;              /* New page number for pPg */
  3951         -          MemPage *pFree;
  3952         -          PtrmapEntry *pEntry;    /* Pointer map entry for page iPg */
  3953         -
  3954         -          if( iPg==PENDING_BYTE_PAGE(pBt) ) continue;
  3955         -          pEntry = &pMap->aPtr[iPg - pMap->iFirst];
  3956         -          if( pEntry->eType==PTRMAP_FREEPAGE ){
  3957         -            rc = allocateBtreePage(pBt, &pFree, &iNew, iPg, BTALLOC_EXACT);
  3958         -            releasePage(pFree);
  3959         -          }else{
  3960         -            rc = allocateBtreePage(pBt, &pFree, &iNew, nFinal, BTALLOC_LE);
  3961         -            assert( rc!=SQLITE_OK || iNew<=nFinal );
  3962         -            releasePage(pFree);
  3963         -            if( rc==SQLITE_OK ){
  3964         -              MemPage *pPg = 0;
  3965         -              btreeGetPage(pBt, iPg, &pPg, 0);
  3966         -              rc = relocatePage(pBt, pPg, pEntry->eType, pEntry->parent,iNew,1);
  3967         -              releasePage(pPg);
  3968         -            }
  3969         -          }
  3970         -        }
  3971         -        put4byte(&p1[28], nFinal);
  3972         -      }
  3973         -    }
  3974         -    sqlite3PagerSetDbsize(pPager, nFinal);
         3981  +        rc = btreeRelocateRange(pBt, pMap->iFirst, iLast, &nCurrent);
         3982  +
         3983  +        /* There are now no collisions with the snapshot at the head of the
         3984  +        ** database file. So at this point it would be possible to write
         3985  +        ** the transaction out to disk. Before doing so though, attempt to
         3986  +        ** relocate some of the new pages to free locations within the body
         3987  +        ** of the database file (i.e. free-list entries). */
         3988  +        if( rc==SQLITE_OK ){
         3989  +          assert( nCurrent!=PENDING_BYTE_PAGE(pBt) );
         3990  +          sqlite3PagerSetDbsize(pBt->pPager, nCurrent);
         3991  +          nFree = get4byte(&p1[36]);
         3992  +          nFin = MAX(nCurrent-nFree, nHPage);
         3993  +          if( nCurrent>PENDING_BYTE_PAGE(pBt) && nFin<=PENDING_BYTE_PAGE(pBt) ){
         3994  +            nFin--;
         3995  +          }
         3996  +          rc = btreeRelocateRange(pBt, nFin+1, nCurrent, 0);
         3997  +        }
         3998  +
         3999  +        put4byte(&p1[28], nFin);
         4000  +      }
         4001  +    }
         4002  +    sqlite3PagerSetDbsize(pPager, nFin);
  3975   4003     }
  3976   4004   
  3977   4005     return rc;
  3978   4006   }
  3979   4007   #endif
  3980   4008   
  3981   4009   /*

Changes to test/unlocked3.test.

    80     80   }
    81     81   
    82     82   
    83     83   set DBLIST {db1 db2 db3 db4} 
    84     84   
    85     85   create_schema
    86     86   foreach {tn oplist} {
    87         -  1 {1i   2i   3i   4i} 
    88         -  2 {1iii 2iii 3iii 4iii}
    89         -  3 {1d   2d   3d   4d} 
    90         -  . -----------------------
    91         -  4 {1i}
    92         -  5 {1d 2i}
    93         -  . -----------------------
    94         -  6 {1iii 2iii 3iii 4iii}
    95         -  7 {1di  2id  3iii 4ddd}
    96         -  8 {1iii 2iii 3iii 4iii}
    97         -  9 {1D  2II}
           87  +  1  {1i   2i   3i   4i} 
           88  +  2  {1iii 2iii 3iii 4iii}
           89  +  3  {1d   2d   3d   4d} 
           90  +  .  -----------------------
           91  +  4  {1i}
           92  +  5  {1d 2i}
           93  +  .  -----------------------
           94  +  6  {1iii 2iii 3iii 4iii}
           95  +  7  {1di  2id  3iii 4ddd}
           96  +  8  {1iii 2iii 3iii 4iii}
           97  +  9  {1D  2II}
           98  +  10 {1I  2D  3I  4D}
           99  +  11 {1III 3dddddd 4III}
    98    100   } {
    99    101     if {[string range $oplist 0 0]=="-"} {
   100    102       reset_db
   101    103       create_schema
   102    104       continue
   103    105     }
   104    106     foreach db $DBLIST { sqlite3 $db test.db }