/ Check-in [d6986d1e]
Login

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

Overview
Comment:Fixes to the overflow-chain optization of (3672). (CVS 3674)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: d6986d1e7cba1d114fa06c5560ffc6bb1feb7389
User & Date: drh 2007-03-06 15:53:44
Context
2007-03-06
16:03
Catch an out-of-memory condition in vacuum code. (Bug in (3373)). (CVS 3675) check-in: 302ec768 user: danielk1977 tags: trunk
15:53
Fixes to the overflow-chain optization of (3672). (CVS 3674) check-in: d6986d1e user: drh tags: trunk
13:46
Use heap instead of stack for large buffers in the pager. Fix for #2262. (CVS 3673) check-in: dfe1dffa user: danielk1977 tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/btree.c.

     5      5   ** a legal notice, here is a blessing:
     6      6   **
     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12         -** $Id: btree.c,v 1.337 2007/03/06 11:42:19 drh Exp $
           12  +** $Id: btree.c,v 1.338 2007/03/06 15:53:44 drh Exp $
    13     13   **
    14     14   ** This file implements a external (disk-based) database using BTrees.
    15     15   ** For a detailed discussion of BTrees, refer to
    16     16   **
    17     17   **     Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3:
    18     18   **     "Sorting And Searching", pages 473-480. Addison-Wesley
    19     19   **     Publishing Company, Reading, Massachusetts.
................................................................................
   361    361   ** based on information extract from the raw disk page.
   362    362   */
   363    363   typedef struct CellInfo CellInfo;
   364    364   struct CellInfo {
   365    365     u8 *pCell;     /* Pointer to the start of cell content */
   366    366     i64 nKey;      /* The key for INTKEY tables, or number of bytes in key */
   367    367     u32 nData;     /* Number of bytes of data */
          368  +  u32 nPayload;  /* Total amount of payload */
   368    369     u16 nHeader;   /* Size of the cell content header in bytes */
   369    370     u16 nLocal;    /* Amount of payload held locally */
   370    371     u16 iOverflow; /* Offset to overflow page number.  Zero if no overflow */
   371    372     u16 nSize;     /* Size of the cell content on the main b-tree page */
   372    373   };
   373    374   
   374    375   /*
................................................................................
   940    941       n += getVarint(&pCell[n], (u64 *)&pInfo->nKey);
   941    942     }else{
   942    943       u32 x;
   943    944       n += getVarint32(&pCell[n], &x);
   944    945       pInfo->nKey = x;
   945    946       nPayload += x;
   946    947     }
          948  +  pInfo->nPayload = nPayload;
   947    949     pInfo->nHeader = n;
   948    950     if( nPayload<=pPage->maxLocal ){
   949    951       /* This is the (easy) common case where the entire payload fits
   950    952       ** on the local page.  No overflow is required.
   951    953       */
   952    954       int nSize;          /* Total size of cell content in bytes */
   953    955       pInfo->nLocal = nPayload;
................................................................................
  1016   1018   ** to an overflow page, insert an entry into the pointer-map
  1017   1019   ** for the overflow page.
  1018   1020   */
  1019   1021   static int ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell){
  1020   1022     if( pCell ){
  1021   1023       CellInfo info;
  1022   1024       parseCellPtr(pPage, pCell, &info);
         1025  +    assert( (info.nData+(pPage->intKey?0:info.nKey))==info.nPayload );
  1023   1026       if( (info.nData+(pPage->intKey?0:info.nKey))>info.nLocal ){
  1024   1027         Pgno ovfl = get4byte(&pCell[info.iOverflow]);
  1025   1028         return ptrmapPut(pPage->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno);
  1026   1029       }
  1027   1030     }
  1028   1031     return SQLITE_OK;
  1029   1032   }
................................................................................
  3872   3875   static int clearCell(MemPage *pPage, unsigned char *pCell){
  3873   3876     BtShared *pBt = pPage->pBt;
  3874   3877     CellInfo info;
  3875   3878     Pgno ovflPgno;
  3876   3879     int rc;
  3877   3880     int nOvfl;
  3878   3881     int ovflPageSize;
  3879         -  int nPayload;
  3880   3882   
  3881   3883     parseCellPtr(pPage, pCell, &info);
  3882   3884     if( info.iOverflow==0 ){
  3883   3885       return SQLITE_OK;  /* No overflow pages. Return without doing anything */
  3884   3886     }
  3885   3887     ovflPgno = get4byte(&pCell[info.iOverflow]);
  3886         -  nPayload = pPage->intKey ? info.nData : info.nKey;
  3887   3888     ovflPageSize = pBt->usableSize - 4;
  3888         -  nOvfl = (nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize;
  3889         -  while( ovflPgno!=0 ){
         3889  +  nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize;
         3890  +  assert( ovflPgno==0 || nOvfl>0 );
         3891  +  while( nOvfl-- ){
  3890   3892       MemPage *pOvfl;
  3891         -    nOvfl--;
  3892         -    if( ovflPgno>sqlite3pager_pagecount(pBt->pPager) ){
         3893  +    if( ovflPgno==0 || ovflPgno>sqlite3pager_pagecount(pBt->pPager) ){
  3893   3894         return SQLITE_CORRUPT_BKPT;
  3894   3895       }
  3895         -    rc = getPage(pBt, ovflPgno, &pOvfl, nOvfl==0);
         3896  +    rc = getPage(pBt, ovflPgno, &pOvfl, 0);
  3896   3897       if( rc ) return rc;
  3897         -    ovflPgno = get4byte(pOvfl->aData);
         3898  +    if( nOvfl ){
         3899  +      ovflPgno = get4byte(pOvfl->aData);
         3900  +    }
  3898   3901       rc = freePage(pOvfl);
  3899   3902       sqlite3pager_unref(pOvfl->aData);
  3900   3903       if( rc ) return rc;
  3901   3904     }
  3902         -  assert( nOvfl==0 );
  3903   3905     return SQLITE_OK;
  3904   3906   }
  3905   3907   
  3906   3908   /*
  3907   3909   ** Create the byte sequence used to represent a cell on page pPage
  3908   3910   ** and write that byte sequence into pCell[].  Overflow pages are
  3909   3911   ** allocated and filled in as necessary.  The calling procedure
................................................................................
  4192   4194   #ifndef SQLITE_OMIT_AUTOVACUUM
  4193   4195       if( pPage->pBt->autoVacuum ){
  4194   4196         /* The cell may contain a pointer to an overflow page. If so, write
  4195   4197         ** the entry for the overflow page into the pointer map.
  4196   4198         */
  4197   4199         CellInfo info;
  4198   4200         parseCellPtr(pPage, pCell, &info);
         4201  +      assert( (info.nData+(pPage->intKey?0:info.nKey))==info.nPayload );
  4199   4202         if( (info.nData+(pPage->intKey?0:info.nKey))>info.nLocal ){
  4200   4203           Pgno pgnoOvfl = get4byte(&pCell[info.iOverflow]);
  4201   4204           int rc = ptrmapPut(pPage->pBt, pgnoOvfl, PTRMAP_OVERFLOW1, pPage->pgno);
  4202   4205           if( rc!=SQLITE_OK ) return rc;
  4203   4206         }
  4204   4207       }
  4205   4208   #endif
................................................................................
  6197   6200       /* Check payload overflow pages
  6198   6201       */
  6199   6202       sprintf(zContext, "On tree page %d cell %d: ", iPage, i);
  6200   6203       pCell = findCell(pPage,i);
  6201   6204       parseCellPtr(pPage, pCell, &info);
  6202   6205       sz = info.nData;
  6203   6206       if( !pPage->intKey ) sz += info.nKey;
         6207  +    assert( sz==info.nPayload );
  6204   6208       if( sz>info.nLocal ){
  6205   6209         int nPage = (sz - info.nLocal + usableSize - 5)/(usableSize - 4);
  6206   6210         Pgno pgnoOvfl = get4byte(&pCell[info.iOverflow]);
  6207   6211   #ifndef SQLITE_OMIT_AUTOVACUUM
  6208   6212         if( pBt->autoVacuum ){
  6209   6213           checkPtrmap(pCheck, pgnoOvfl, PTRMAP_OVERFLOW1, iPage, zContext);
  6210   6214         }