/ Check-in [bc1ec123]
Login

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

Overview
Comment:Size and performance optimization to dropCell() and freeSpace().
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: bc1ec123ce05c9d16b0942f870381145dc9725764e47806939ff207a73066f4d
User & Date: drh 2017-08-23 20:36:06
Context
2017-08-23
23:09
Performance optimization to pageFindSlot() in the b-tree layer. check-in: 59560d07 user: drh tags: trunk
20:36
Size and performance optimization to dropCell() and freeSpace(). check-in: bc1ec123 user: drh tags: trunk
14:45
Smaller and faster implementation of the fillInCell() routine. check-in: 77074990 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/btree.c.

  1501   1501       /* EVIDENCE-OF: R-22710-53328 The third and fourth bytes of each
  1502   1502       ** freeblock form a big-endian integer which is the size of the freeblock
  1503   1503       ** in bytes, including the 4-byte header. */
  1504   1504       size = get2byte(&aData[pc+2]);
  1505   1505       if( (x = size - nByte)>=0 ){
  1506   1506         testcase( x==4 );
  1507   1507         testcase( x==3 );
  1508         -      if( pc < pPg->cellOffset+2*pPg->nCell || size+pc > usableSize ){
         1508  +      if( size+pc > usableSize ){
  1509   1509           *pRc = SQLITE_CORRUPT_PGNO(pPg->pgno);
  1510   1510           return 0;
  1511   1511         }else if( x<4 ){
  1512   1512           /* EVIDENCE-OF: R-11498-58022 In a well-formed b-tree page, the total
  1513   1513           ** number of bytes in fragments may not exceed 60. */
  1514   1514           if( aData[hdr+7]>57 ) return 0;
  1515   1515   
................................................................................
  1636   1636   */
  1637   1637   static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
  1638   1638     u16 iPtr;                             /* Address of ptr to next freeblock */
  1639   1639     u16 iFreeBlk;                         /* Address of the next freeblock */
  1640   1640     u8 hdr;                               /* Page header size.  0 or 100 */
  1641   1641     u8 nFrag = 0;                         /* Reduction in fragmentation */
  1642   1642     u16 iOrigSize = iSize;                /* Original value of iSize */
  1643         -  u32 iLast = pPage->pBt->usableSize-4; /* Largest possible freeblock offset */
         1643  +  u16 x;                                /* Offset to cell content area */
  1644   1644     u32 iEnd = iStart + iSize;            /* First byte past the iStart buffer */
  1645   1645     unsigned char *data = pPage->aData;   /* Page content */
  1646   1646   
  1647   1647     assert( pPage->pBt!=0 );
  1648   1648     assert( sqlite3PagerIswriteable(pPage->pDbPage) );
  1649   1649     assert( CORRUPT_DB || iStart>=pPage->hdrOffset+6+pPage->childPtrSize );
  1650   1650     assert( CORRUPT_DB || iEnd <= pPage->pBt->usableSize );
  1651   1651     assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  1652   1652     assert( iSize>=4 );   /* Minimum cell size is 4 */
  1653         -  assert( iStart<=iLast );
  1654         -
  1655         -  /* Overwrite deleted information with zeros when the secure_delete
  1656         -  ** option is enabled */
  1657         -  if( pPage->pBt->btsFlags & BTS_FAST_SECURE ){
  1658         -    memset(&data[iStart], 0, iSize);
  1659         -  }
         1653  +  assert( iStart<=pPage->pBt->usableSize-4 );
  1660   1654   
  1661   1655     /* The list of freeblocks must be in ascending order.  Find the 
  1662   1656     ** spot on the list where iStart should be inserted.
  1663   1657     */
  1664   1658     hdr = pPage->hdrOffset;
  1665   1659     iPtr = hdr + 1;
  1666   1660     if( data[iPtr+1]==0 && data[iPtr]==0 ){
................................................................................
  1669   1663       while( (iFreeBlk = get2byte(&data[iPtr]))<iStart ){
  1670   1664         if( iFreeBlk<iPtr+4 ){
  1671   1665           if( iFreeBlk==0 ) break;
  1672   1666           return SQLITE_CORRUPT_PGNO(pPage->pgno);
  1673   1667         }
  1674   1668         iPtr = iFreeBlk;
  1675   1669       }
  1676         -    if( iFreeBlk>iLast ) return SQLITE_CORRUPT_PGNO(pPage->pgno);
         1670  +    if( iFreeBlk>pPage->pBt->usableSize-4 ){
         1671  +      return SQLITE_CORRUPT_PGNO(pPage->pgno);
         1672  +    }
  1677   1673       assert( iFreeBlk>iPtr || iFreeBlk==0 );
  1678   1674     
  1679   1675       /* At this point:
  1680   1676       **    iFreeBlk:   First freeblock after iStart, or zero if none
  1681   1677       **    iPtr:       The address of a pointer to iFreeBlk
  1682   1678       **
  1683   1679       ** Check to see if iFreeBlk should be coalesced onto the end of iStart.
................................................................................
  1705   1701           iSize = iEnd - iPtr;
  1706   1702           iStart = iPtr;
  1707   1703         }
  1708   1704       }
  1709   1705       if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_PGNO(pPage->pgno);
  1710   1706       data[hdr+7] -= nFrag;
  1711   1707     }
  1712         -  if( iStart==get2byte(&data[hdr+5]) ){
         1708  +  x = get2byte(&data[hdr+5]);
         1709  +  if( iStart<=x ){
  1713   1710       /* The new freeblock is at the beginning of the cell content area,
  1714   1711       ** so just extend the cell content area rather than create another
  1715   1712       ** freelist entry */
  1716         -    if( iPtr!=hdr+1 ) return SQLITE_CORRUPT_PGNO(pPage->pgno);
         1713  +    if( iStart<x || iPtr!=hdr+1 ) return SQLITE_CORRUPT_PGNO(pPage->pgno);
  1717   1714       put2byte(&data[hdr+1], iFreeBlk);
  1718   1715       put2byte(&data[hdr+5], iEnd);
  1719   1716     }else{
  1720   1717       /* Insert the new freeblock into the freelist */
  1721   1718       put2byte(&data[iPtr], iStart);
  1722         -    put2byte(&data[iStart], iFreeBlk);
  1723         -    put2byte(&data[iStart+2], iSize);
  1724   1719     }
         1720  +  if( pPage->pBt->btsFlags & BTS_FAST_SECURE ){
         1721  +    /* Overwrite deleted information with zeros when the secure_delete
         1722  +    ** option is enabled */
         1723  +    memset(&data[iStart], 0, iSize);
         1724  +  }
         1725  +  put2byte(&data[iStart], iFreeBlk);
         1726  +  put2byte(&data[iStart+2], iSize);
  1725   1727     pPage->nFree += iOrigSize;
  1726   1728     return SQLITE_OK;
  1727   1729   }
  1728   1730   
  1729   1731   /*
  1730   1732   ** Decode the flags byte (the first byte of the header) for a page
  1731   1733   ** and initialize fields of the MemPage structure accordingly.
................................................................................
  6414   6416     assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  6415   6417     data = pPage->aData;
  6416   6418     ptr = &pPage->aCellIdx[2*idx];
  6417   6419     pc = get2byte(ptr);
  6418   6420     hdr = pPage->hdrOffset;
  6419   6421     testcase( pc==get2byte(&data[hdr+5]) );
  6420   6422     testcase( pc+sz==pPage->pBt->usableSize );
  6421         -  if( pc < (u32)get2byte(&data[hdr+5]) || pc+sz > pPage->pBt->usableSize ){
         6423  +  if( pc+sz > pPage->pBt->usableSize ){
  6422   6424       *pRC = SQLITE_CORRUPT_BKPT;
  6423   6425       return;
  6424   6426     }
  6425   6427     rc = freeSpace(pPage, pc, sz);
  6426   6428     if( rc ){
  6427   6429       *pRC = rc;
  6428   6430       return;