SQLite

Check-in [a40b42c422]
Login

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

Overview
Comment:Fix various bugs revealed by running performance tests.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | server-edition
Files: files | file ages | folders
SHA3-256: a40b42c422a53aa99280eca7ba419a3937699e273efa3377e0fefe52582cbbd4
User & Date: dan 2017-04-28 17:32:57.316
Context
2017-04-29
15:48
Avoid reading the file-size before page 1 is read-locked. (check-in: f6b025bf63 user: dan tags: server-edition)
2017-04-28
17:32
Fix various bugs revealed by running performance tests. (check-in: a40b42c422 user: dan tags: server-edition)
14:09
Add a missing releasePage() call to the server-mode free-list management code. (check-in: a5a085483c user: dan tags: server-edition)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/btree.c.
2912
2913
2914
2915
2916
2917
2918






2919
2920
2921
2922
2923
2924
2925
  if( rc!=SQLITE_OK ) return rc;

  /* Do some checking to help insure the file we opened really is
  ** a valid database file. 
  */
  nPage = nPageHeader = get4byte(28+(u8*)pPage1->aData);
  sqlite3PagerPagecount(pBt->pPager, &nPageFile);






  if( nPage==0 || memcmp(24+(u8*)pPage1->aData, 92+(u8*)pPage1->aData,4)!=0 ){
    nPage = nPageFile;
  }
  if( nPage>0 ){
    u32 pageSize;
    u32 usableSize;
    u8 *page1 = pPage1->aData;







>
>
>
>
>
>







2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
  if( rc!=SQLITE_OK ) return rc;

  /* Do some checking to help insure the file we opened really is
  ** a valid database file. 
  */
  nPage = nPageHeader = get4byte(28+(u8*)pPage1->aData);
  sqlite3PagerPagecount(pBt->pPager, &nPageFile);
#ifdef SQLITE_SERVER_EDITION
  if( sqlite3PagerIsServer(pBt->pPager) ){
    sqlite3PagerSetPagecount(pBt->pPager, nPage);
    nPageFile = nPage;
  }
#endif
  if( nPage==0 || memcmp(24+(u8*)pPage1->aData, 92+(u8*)pPage1->aData,4)!=0 ){
    nPage = nPageFile;
  }
  if( nPage>0 ){
    u32 pageSize;
    u32 usableSize;
    u8 *page1 = pPage1->aData;
5771
5772
5773
5774
5775
5776
5777




5778
5779
5780
5781

5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799

5800
5801
5802




5803
5804
5805
5806
5807
5808
5809
5810
5811


5812
5813
5814
5815
5816
5817



5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
  Pgno *pPgno,           /* Store the page number here */
  Pgno nearby,           /* Search for a page near this one */
  u8 eMode               /* BTALLOC_EXACT, BTALLOC_LT, or BTALLOC_ANY */
){
  int rc;                         /* Return code */
  MemPage *pTrunk = 0;            /* The node page */
  Pgno pgnoNew = 0;





  assert( eMode==BTALLOC_ANY );
  assert( sqlite3_mutex_held(pBt->mutex) );


  rc = findServerTrunk(pBt, 1, &pTrunk);
  if( rc==SQLITE_OK ){
    int nFree;              /* Number of free pages on this trunk page */
    nFree = (int)get4byte(&pTrunk->aData[4]);
    if( nFree==0 ){
      pgnoNew = get4byte(&pTrunk->aData[0]);
      assert( pgnoNew );
    }else{
      nFree--;
      pgnoNew = get4byte(&pTrunk->aData[8+4*nFree]);
      put4byte(&pTrunk->aData[4], (u32)nFree);
      releasePage(pTrunk);
      pTrunk = 0;
    }
  }

  if( rc==SQLITE_OK ){
    MemPage *pNew = 0;

    rc = btreeGetUnusedPage(pBt, pgnoNew, &pNew, pTrunk?0:PAGER_GET_NOCONTENT);
    if( rc==SQLITE_OK ){
      rc = sqlite3PagerWrite(pNew->pDbPage);




    }
    if( rc==SQLITE_OK && pTrunk ){
      memcpy(pTrunk->aData, pNew->aData, pBt->usableSize);
    }
    *ppPage = pNew;
    *pPgno = pgnoNew;
  }

  releasePage(pTrunk);


  return rc;
}

static int freeServerPage2(BtShared *pBt, MemPage *pPage, Pgno iPage){
  int rc;                         /* Return code */
  MemPage *pTrunk = 0;            /* The node page */




  assert( sqlite3_mutex_held(pBt->mutex) );

  rc = findServerTrunk(pBt, 0, &pTrunk);
  if( rc==SQLITE_OK ){
    int nFree;              /* Number of free pages on this trunk page */
    nFree = (int)get4byte(&pTrunk->aData[4]);
    if( nFree>=((pBt->usableSize / 4) - 2) ){
      if( pPage==0 ){
        rc = btreeGetUnusedPage(pBt, iPage, &pPage, 0);







>
>
>
>




>


















>
|


>
>
>
>









>
>






>
>
>


<







5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840

5841
5842
5843
5844
5845
5846
5847
  Pgno *pPgno,           /* Store the page number here */
  Pgno nearby,           /* Search for a page near this one */
  u8 eMode               /* BTALLOC_EXACT, BTALLOC_LT, or BTALLOC_ANY */
){
  int rc;                         /* Return code */
  MemPage *pTrunk = 0;            /* The node page */
  Pgno pgnoNew = 0;

#ifdef SQLITE_DEBUG
  int nRef = sqlite3PagerRefcount(pBt->pPager);
#endif

  assert( eMode==BTALLOC_ANY );
  assert( sqlite3_mutex_held(pBt->mutex) );

  *ppPage = 0;
  rc = findServerTrunk(pBt, 1, &pTrunk);
  if( rc==SQLITE_OK ){
    int nFree;              /* Number of free pages on this trunk page */
    nFree = (int)get4byte(&pTrunk->aData[4]);
    if( nFree==0 ){
      pgnoNew = get4byte(&pTrunk->aData[0]);
      assert( pgnoNew );
    }else{
      nFree--;
      pgnoNew = get4byte(&pTrunk->aData[8+4*nFree]);
      put4byte(&pTrunk->aData[4], (u32)nFree);
      releasePage(pTrunk);
      pTrunk = 0;
    }
  }

  if( rc==SQLITE_OK ){
    MemPage *pNew = 0;
    int flags = pTrunk ? 0 : PAGER_GET_NOCONTENT;
    rc = btreeGetUnusedPage(pBt, pgnoNew, &pNew, flags);
    if( rc==SQLITE_OK ){
      rc = sqlite3PagerWrite(pNew->pDbPage);
      if( rc!=SQLITE_OK ){
        releasePage(pNew);
        pNew = 0;
      }
    }
    if( rc==SQLITE_OK && pTrunk ){
      memcpy(pTrunk->aData, pNew->aData, pBt->usableSize);
    }
    *ppPage = pNew;
    *pPgno = pgnoNew;
  }

  releasePage(pTrunk);
  assert( (rc==SQLITE_OK)==(*ppPage!=0) );
  assert( sqlite3PagerRefcount(pBt->pPager)==(nRef+(*ppPage!=0)) );
  return rc;
}

static int freeServerPage2(BtShared *pBt, MemPage *pPage, Pgno iPage){
  int rc;                         /* Return code */
  MemPage *pTrunk = 0;            /* The node page */
#ifdef SQLITE_DEBUG
  int nRef = sqlite3PagerRefcount(pBt->pPager);
#endif

  assert( sqlite3_mutex_held(pBt->mutex) );

  rc = findServerTrunk(pBt, 0, &pTrunk);
  if( rc==SQLITE_OK ){
    int nFree;              /* Number of free pages on this trunk page */
    nFree = (int)get4byte(&pTrunk->aData[4]);
    if( nFree>=((pBt->usableSize / 4) - 2) ){
      if( pPage==0 ){
        rc = btreeGetUnusedPage(pBt, iPage, &pPage, 0);
5838
5839
5840
5841
5842
5843
5844

5845
5846
5847
5848
5849
5850
5851
    }else{
      put4byte(&pTrunk->aData[8+nFree*4], iPage);
      put4byte(&pTrunk->aData[4], (u32)nFree+1);
    }
    releasePage(pTrunk);
  }


  return rc;
}

#else
# define allocateServerPage(v, w, x, y, z) SQLITE_OK
# define freeServerPage2(x, y, z) SQLITE_OK
#endif /* SQLITE_SERVER_EDITION */







>







5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
    }else{
      put4byte(&pTrunk->aData[8+nFree*4], iPage);
      put4byte(&pTrunk->aData[4], (u32)nFree+1);
    }
    releasePage(pTrunk);
  }

  assert( nRef==sqlite3PagerRefcount(pBt->pPager) );
  return rc;
}

#else
# define allocateServerPage(v, w, x, y, z) SQLITE_OK
# define freeServerPage2(x, y, z) SQLITE_OK
#endif /* SQLITE_SERVER_EDITION */
Changes to src/pager.c.
5123
5124
5125
5126
5127
5128
5129

5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141

5142
5143
5144
5145
5146
5147
5148
    assert( rc==SQLITE_OK || jfd==0 );
    if( jfd ){
      sqlite3_file *saved_jfd = pPager->jfd;
      u8 saved_eState = pPager->eState;
      u8 saved_eLock = pPager->eLock;
      i64 saved_journalOff = pPager->journalOff;
      i64 saved_journalHdr = pPager->journalHdr;


      pPager->eLock = EXCLUSIVE_LOCK;
      pPager->eState = PAGER_WRITER_DBMOD;
      pPager->jfd = jfd;
      rc = pagerSyncHotJournal(pPager);
      if( rc==SQLITE_OK ) rc = pager_playback(pPager, 1);

      pPager->jfd = saved_jfd;
      pPager->eState = saved_eState;
      pPager->eLock = saved_eLock;
      pPager->journalOff = saved_journalOff;
      pPager->journalHdr = saved_journalHdr;


      sqlite3OsCloseFree(jfd);
      if( rc==SQLITE_OK ){
        rc = sqlite3OsDelete(pVfs, zJrnl, 0);
      }
    }
    sqlite3_free(zJrnl);







>












>







5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
    assert( rc==SQLITE_OK || jfd==0 );
    if( jfd ){
      sqlite3_file *saved_jfd = pPager->jfd;
      u8 saved_eState = pPager->eState;
      u8 saved_eLock = pPager->eLock;
      i64 saved_journalOff = pPager->journalOff;
      i64 saved_journalHdr = pPager->journalHdr;
      char *saved_zJournal = pPager->zJournal;

      pPager->eLock = EXCLUSIVE_LOCK;
      pPager->eState = PAGER_WRITER_DBMOD;
      pPager->jfd = jfd;
      rc = pagerSyncHotJournal(pPager);
      if( rc==SQLITE_OK ) rc = pager_playback(pPager, 1);

      pPager->jfd = saved_jfd;
      pPager->eState = saved_eState;
      pPager->eLock = saved_eLock;
      pPager->journalOff = saved_journalOff;
      pPager->journalHdr = saved_journalHdr;
      pPager->zJournal = saved_zJournal;

      sqlite3OsCloseFree(jfd);
      if( rc==SQLITE_OK ){
        rc = sqlite3OsDelete(pVfs, zJrnl, 0);
      }
    }
    sqlite3_free(zJrnl);
7663
7664
7665
7666
7667
7668
7669




7670
7671
7672
7673

#ifdef SQLITE_SERVER_EDITION
int sqlite3PagerIsServer(Pager *pPager){
  return pagerIsServer(pPager);
}
int sqlite3PagerWritelock(Pager *pPager, Pgno pgno){
  return sqlite3ServerLock(pPager->pServer, pgno, 1);




}
#endif

#endif /* SQLITE_OMIT_DISKIO */







>
>
>
>




7665
7666
7667
7668
7669
7670
7671
7672
7673
7674
7675
7676
7677
7678
7679

#ifdef SQLITE_SERVER_EDITION
int sqlite3PagerIsServer(Pager *pPager){
  return pagerIsServer(pPager);
}
int sqlite3PagerWritelock(Pager *pPager, Pgno pgno){
  return sqlite3ServerLock(pPager->pServer, pgno, 1);
}
void sqlite3PagerSetPagecount(Pager *pPager, u32 nPage){
  assert( pPager->eState==PAGER_READER );
  pPager->dbSize = nPage;
}
#endif

#endif /* SQLITE_OMIT_DISKIO */
Changes to src/pager.h.
236
237
238
239
240
241
242

243
244
245
# define enable_simulated_io_errors()
#endif

#ifdef SQLITE_SERVER_EDITION
  int sqlite3PagerRollbackJournal(Pager*, int);
  int sqlite3PagerIsServer(Pager *pPager);
  int sqlite3PagerWritelock(Pager *pPager, Pgno);

#endif

#endif /* SQLITE_PAGER_H */







>



236
237
238
239
240
241
242
243
244
245
246
# define enable_simulated_io_errors()
#endif

#ifdef SQLITE_SERVER_EDITION
  int sqlite3PagerRollbackJournal(Pager*, int);
  int sqlite3PagerIsServer(Pager *pPager);
  int sqlite3PagerWritelock(Pager *pPager, Pgno);
  void sqlite3PagerSetPagecount(Pager*, u32);
#endif

#endif /* SQLITE_PAGER_H */
Changes to src/server.c.
197
198
199
200
201
202
203



204
205
206
207
208
209
210
211
212
213
214
215
216
              rc = serverMapFile(pHma);
            }
            if( rc==SQLITE_OK ){
              memset(pHma->aMap, 0, HMA_FILE_SIZE);
            }else{
              rc = SQLITE_ERROR;
            }



          }else{
            rc = serverMapFile(pHma);
          }
          for(i=0; rc==SQLITE_OK && i<HMA_CLIENT_SLOTS; i++){
            rc = sqlite3PagerRollbackJournal(pPager, i);
          }
          if( rc==SQLITE_OK ){
            rc = posixLock(pHma->fd, 0, SERVER_READ_LOCK, 1);
          }
        }

        if( rc!=SQLITE_OK ){
          serverDecrHmaRefcount(pHma);







>
>
>



<
<
<







197
198
199
200
201
202
203
204
205
206
207
208
209



210
211
212
213
214
215
216
              rc = serverMapFile(pHma);
            }
            if( rc==SQLITE_OK ){
              memset(pHma->aMap, 0, HMA_FILE_SIZE);
            }else{
              rc = SQLITE_ERROR;
            }
            for(i=0; rc==SQLITE_OK && i<HMA_CLIENT_SLOTS; i++){
              rc = sqlite3PagerRollbackJournal(pPager, i);
            }
          }else{
            rc = serverMapFile(pHma);
          }



          if( rc==SQLITE_OK ){
            rc = posixLock(pHma->fd, 0, SERVER_READ_LOCK, 1);
          }
        }

        if( rc!=SQLITE_OK ){
          serverDecrHmaRefcount(pHma);