SQLite4
Check-in [60c8db5553]
Not logged in

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

Overview
Comment:Fix a bug in merge-tree rollback operations.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 60c8db55530b9f6be2d363e505b01c5847c3f2ec
User & Date: dan 2014-01-26 17:13:07
Context
2014-02-03
07:40
Fix various problems causing block and page leaks during merge operations. check-in: aaac4355c7 user: dan tags: trunk
2014-01-26
17:13
Fix a bug in merge-tree rollback operations. check-in: 60c8db5553 user: dan tags: trunk
2014-01-25
15:14
Fix a problem with iterating in reverse order through the merge-tree. check-in: 6998cd99b8 user: dan tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/btInt.h.

283
284
285
286
287
288
289

290
291
292
293
294
295
296
int sqlite4BtLogPagecount(BtLog*);
u32 sqlite4BtLogCookie(BtLog*);
#endif
BtDbHdr *sqlite4BtLogDbhdr(BtLog*);

int sqlite4BtLogSetCookie(BtLog*, u32 iCookie);
int sqlite4BtLogDbhdrFlush(BtLog*);


/*
** End of bt_log.c interface.
*************************************************************************/

/*************************************************************************
** Interface to bt_lock.c functionality.







>







283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
int sqlite4BtLogPagecount(BtLog*);
u32 sqlite4BtLogCookie(BtLog*);
#endif
BtDbHdr *sqlite4BtLogDbhdr(BtLog*);

int sqlite4BtLogSetCookie(BtLog*, u32 iCookie);
int sqlite4BtLogDbhdrFlush(BtLog*);
void sqlite4BtLogReloadDbHdr(BtLog*);

/*
** End of bt_log.c interface.
*************************************************************************/

/*************************************************************************
** Interface to bt_lock.c functionality.

Changes to src/bt_log.c.

1959
1960
1961
1962
1963
1964
1965





1966
1967
1968
1969
1970
1971
1972
  return pLog->snapshot.dbhdr.iCookie;
}
#endif

BtDbHdr *sqlite4BtLogDbhdr(BtLog *pLog){
  return &pLog->snapshot.dbhdr;
}






int sqlite4BtLogDbhdrFlush(BtLog *pLog){
  BtPager *pPager = (BtPager *)(pLog->pLock);
  BtPage *pOne = 0;
  int rc;

  rc = sqlite4BtPageGet(pPager, 1, &pOne);







>
>
>
>
>







1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
  return pLog->snapshot.dbhdr.iCookie;
}
#endif

BtDbHdr *sqlite4BtLogDbhdr(BtLog *pLog){
  return &pLog->snapshot.dbhdr;
}

void sqlite4BtLogReloadDbHdr(BtLog *pLog){
  BtShm *pShm = btLogShm(pLog);
  memcpy(&pLog->snapshot, &pShm->hdr1, sizeof(BtShmHdr));
}

int sqlite4BtLogDbhdrFlush(BtLog *pLog){
  BtPager *pPager = (BtPager *)(pLog->pLock);
  BtPage *pOne = 0;
  int rc;

  rc = sqlite4BtPageGet(pPager, 1, &pOne);

Changes to src/bt_pager.c.

48
49
50
51
52
53
54

55
56
57
58
59
60
61
...
272
273
274
275
276
277
278

279
280
281
282
283
284
285
...
370
371
372
373
374
375
376




377
378
379
380
381
382
383
...
647
648
649
650
651
652
653

654
655
656
657
658
659
660
/*
** There is one object of this type for each open sub-transaction. Stored
** in the BtPager.aSavepoint[] array.
*/
struct BtSavepoint {
  int iLevel;                     /* Transaction level value (always >2) */
  BtSavepage *pSavepage;          /* First in linked list of saved data */

};

struct BtSavepage {
  BtPage *pPg;                    /* Pointer to page this object belongs to */
  u8 *aData;                      /* Saved data */
  BtSavepage *pNext;              /* Next saved page in the same savepoint */
  int iSavepoint;                 /* Transaction number of savepoint */
................................................................................

    aNew = sqlite4_realloc(p->btl.pEnv, p->aSavepoint, nByte);
    if( aNew ){
      int i;
      for(i=p->nSavepoint; i<nReq; i++){
        aNew[i].pSavepage = 0;
        aNew[i].iLevel = i+3;

      }
      p->aSavepoint = aNew;
      p->nSavepoint = nReq;
    }else{
      rc = btErrorBkpt(SQLITE4_NOMEM);
    }
  }
................................................................................

  if( nReq<=p->nSavepoint ){
    int i;
    for(i=p->nSavepoint-1; i>=nReq; i--){
      BtSavepoint *pSavepoint = &p->aSavepoint[i];
      BtSavepage *pSavepg;
      BtSavepage *pNext;





      /* Loop through each of the BtSavepage objects associated with this
      ** savepoint. Detach them from the BtPage objects and free all
      ** allocated memory.  */
      for(pSavepg=pSavepoint->pSavepage; pSavepg; pSavepg=pNext){
        BtPage *pPg = pSavepg->pPg;
        pNext = pSavepg->pNext;
................................................................................
      btHashRemove(p, pPg);
      btFreePage(p, pPg);
    }else if( rc==SQLITE4_OK && (pPg->pgno<=p->pHdr->nPg) ){
      rc = btLoadPageData(p, pPg);
    }
  }
  p->pDirty = 0;


  return rc;
}

/*
** Transactions. These methods are more or less the same as their 
** counterparts in bt.h.







>







 







>







 







>
>
>
>







 







>







48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
...
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
...
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
...
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
/*
** There is one object of this type for each open sub-transaction. Stored
** in the BtPager.aSavepoint[] array.
*/
struct BtSavepoint {
  int iLevel;                     /* Transaction level value (always >2) */
  BtSavepage *pSavepage;          /* First in linked list of saved data */
  BtDbHdr hdr;                    /* Database header at start of savepoint */
};

struct BtSavepage {
  BtPage *pPg;                    /* Pointer to page this object belongs to */
  u8 *aData;                      /* Saved data */
  BtSavepage *pNext;              /* Next saved page in the same savepoint */
  int iSavepoint;                 /* Transaction number of savepoint */
................................................................................

    aNew = sqlite4_realloc(p->btl.pEnv, p->aSavepoint, nByte);
    if( aNew ){
      int i;
      for(i=p->nSavepoint; i<nReq; i++){
        aNew[i].pSavepage = 0;
        aNew[i].iLevel = i+3;
        memcpy(&aNew[i].hdr, p->pHdr, sizeof(BtDbHdr));
      }
      p->aSavepoint = aNew;
      p->nSavepoint = nReq;
    }else{
      rc = btErrorBkpt(SQLITE4_NOMEM);
    }
  }
................................................................................

  if( nReq<=p->nSavepoint ){
    int i;
    for(i=p->nSavepoint-1; i>=nReq; i--){
      BtSavepoint *pSavepoint = &p->aSavepoint[i];
      BtSavepage *pSavepg;
      BtSavepage *pNext;

      /* Restore the BtDbHdr object to the state it was in at the start of
      ** this savepoint.  */
      memcpy(p->pHdr, &pSavepoint->hdr, sizeof(BtDbHdr));

      /* Loop through each of the BtSavepage objects associated with this
      ** savepoint. Detach them from the BtPage objects and free all
      ** allocated memory.  */
      for(pSavepg=pSavepoint->pSavepage; pSavepg; pSavepg=pNext){
        BtPage *pPg = pSavepg->pPg;
        pNext = pSavepg->pNext;
................................................................................
      btHashRemove(p, pPg);
      btFreePage(p, pPg);
    }else if( rc==SQLITE4_OK && (pPg->pgno<=p->pHdr->nPg) ){
      rc = btLoadPageData(p, pPg);
    }
  }
  p->pDirty = 0;
  sqlite4BtLogReloadDbHdr(p->pLog);

  return rc;
}

/*
** Transactions. These methods are more or less the same as their 
** counterparts in bt.h.