SQLite4
Check-in [6bf6b00b8b]
Not logged in

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

Overview
Comment:Fix a compressed mode bug unrelated to the free block list.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | freelist-rework
Files: files | file ages | folders
SHA1: 6bf6b00b8b3e47f0571400de0e76cd6c9b96c655
User & Date: dan 2012-10-31 16:37:01
Context
2012-10-31
18:46
Remove dead code. Fix a read-lock related problem causing the multi-threaded tests to fail. check-in: f512ea3c4d user: dan tags: freelist-rework
16:37
Fix a compressed mode bug unrelated to the free block list. check-in: 6bf6b00b8b user: dan tags: freelist-rework
11:15
Improve the complex assert() used to check that database file blocks are not leaked or over-allocated. check-in: 1ac4435e5c user: dan tags: freelist-rework
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/lsm_file.c.

   185    185     lsm_file *fdDb;                 /* Database file */
   186    186     lsm_file *fdLog;                /* Log file */
   187    187     int szSector;                   /* Database file sector size */
   188    188   
   189    189     /* If this is a compressed database, a pointer to the compression methods.
   190    190     ** For an uncompressed database, a NULL pointer.  */
   191    191     lsm_compress *pCompress;
   192         -  u8 *aBuffer;                    /* Buffer to compress into */
          192  +  u8 *aIBuffer;                   /* Buffer to compress to */
          193  +  u8 *aOBuffer;                   /* Buffer to uncompress from */
   193    194     int nBuffer;                    /* Allocated size of aBuffer[] in bytes */
   194    195   
   195    196     /* mmap() mode things */
   196    197     int bUseMmap;                   /* True to use mmap() to access db file */
   197    198     void *pMap;                     /* Current mapping of database file */
   198    199     i64 nMap;                       /* Bytes mapped at pMap */
   199    200     Page *pFree;
................................................................................
   554    555         pPg = pNext;
   555    556       }
   556    557   
   557    558       if( pFS->fdDb ) lsmEnvClose(pFS->pEnv, pFS->fdDb );
   558    559       if( pFS->fdLog ) lsmEnvClose(pFS->pEnv, pFS->fdLog );
   559    560       lsmFree(pEnv, pFS->pLsmFile);
   560    561       lsmFree(pEnv, pFS->apHash);
   561         -    lsmFree(pEnv, pFS->aBuffer);
          562  +    lsmFree(pEnv, pFS->aIBuffer);
          563  +    lsmFree(pEnv, pFS->aOBuffer);
   562    564       lsmFree(pEnv, pFS);
   563    565     }
   564    566   }
   565    567   
   566    568   void lsmFsDeferClose(FileSystem *pFS, LsmFile **pp){
   567    569     LsmFile *p = pFS->pLsmFile;
   568    570     assert( p->pNext==0 );
................................................................................
  1011   1013     }
  1012   1014   
  1013   1015     rc = fsBlockNext(pFS, fsPageToBlock(pFS, iOff), &iBlk);
  1014   1016     *piRes = fsFirstPageOnBlock(pFS, iBlk) + iAdd - (iEob - iOff + 1);
  1015   1017     return rc;
  1016   1018   }
  1017   1019   
  1018         -static int fsAllocateBuffer(FileSystem *pFS){
         1020  +static int fsAllocateBuffer(FileSystem *pFS, int bWrite){
         1021  +  u8 **pp;                        /* Pointer to either aIBuffer or aOBuffer */
         1022  +
  1019   1023     assert( pFS->pCompress );
  1020         -  if( pFS->aBuffer==0 ){
         1024  +
         1025  +  /* If neither buffer has been allocated, figure out how large they
         1026  +  ** should be. Store this value in FileSystem.nBuffer.  */
         1027  +  if( pFS->nBuffer==0 ){
         1028  +    assert( pFS->aIBuffer==0 && pFS->aOBuffer==0 );
  1021   1029       pFS->nBuffer = pFS->pCompress->xBound(pFS->pCompress->pCtx, pFS->nPagesize);
  1022   1030       if( pFS->nBuffer<(pFS->szSector+6) ){
  1023   1031         pFS->nBuffer = pFS->szSector+6;
  1024   1032       }
  1025         -    pFS->aBuffer = lsmMalloc(pFS->pEnv, LSM_MAX(pFS->nBuffer, pFS->nPagesize));
  1026         -    if( pFS->aBuffer==0 ) return LSM_NOMEM_BKPT;
  1027   1033     }
         1034  +
         1035  +  pp = (bWrite ? &pFS->aOBuffer : &pFS->aIBuffer);
         1036  +  if( *pp==0 ){
         1037  +    *pp = lsmMalloc(pFS->pEnv, LSM_MAX(pFS->nBuffer, pFS->nPagesize));
         1038  +    if( *pp==0 ) return LSM_NOMEM_BKPT;
         1039  +  }
         1040  +
  1028   1041     return LSM_OK;
  1029   1042   }
  1030   1043   
  1031   1044   /*
  1032   1045   ** This function is only called in compressed database mode. It reads and
  1033   1046   ** uncompresses the compressed data for page pPg from the database and
  1034   1047   ** populates the pPg->aData[] buffer and pPg->nCompress field.
................................................................................
  1043   1056     lsm_compress *p = pFS->pCompress;
  1044   1057     i64 iOff = pPg->iPg;
  1045   1058     u8 aSz[3];
  1046   1059     int rc;
  1047   1060   
  1048   1061     assert( p && pPg->nCompress==0 );
  1049   1062   
  1050         -  if( fsAllocateBuffer(pFS) ) return LSM_NOMEM;
         1063  +  if( fsAllocateBuffer(pFS, 0) ) return LSM_NOMEM;
  1051   1064   
  1052   1065     rc = fsReadData(pFS, iOff, aSz, sizeof(aSz));
  1053   1066   
  1054   1067     if( rc==LSM_OK ){
  1055   1068       int bFree;
  1056   1069       if( aSz[0] & 0x80 ){
  1057   1070         pPg->nCompress = (int)getRecordSize(aSz, &bFree);
................................................................................
  1067   1080         }
  1068   1081       }else{
  1069   1082         rc = fsAddOffset(pFS, iOff, 3, &iOff);
  1070   1083         if( rc==LSM_OK ){
  1071   1084           if( pPg->nCompress>pFS->nBuffer ){
  1072   1085             rc = LSM_CORRUPT_BKPT;
  1073   1086           }else{
  1074         -          rc = fsReadData(pFS, iOff, pFS->aBuffer, pPg->nCompress);
         1087  +          rc = fsReadData(pFS, iOff, pFS->aIBuffer, pPg->nCompress);
  1075   1088           }
  1076   1089           if( rc==LSM_OK ){
  1077   1090             int n = pFS->nPagesize;
  1078   1091             rc = p->xUncompress(p->pCtx, 
  1079   1092                 (char *)pPg->aData, &n, 
  1080         -              (const char *)pFS->aBuffer, pPg->nCompress
  1081         -              );
         1093  +              (const char *)pFS->aIBuffer, pPg->nCompress
         1094  +          );
  1082   1095             if( rc==LSM_OK && n!=pPg->nData ){
  1083   1096               rc = LSM_CORRUPT_BKPT;
  1084   1097             }
  1085   1098           }
  1086   1099         }
  1087   1100       }
  1088   1101     }
................................................................................
  1843   1856   **
  1844   1857   ** If buffer pFS->aBuffer[] has not been allocated then this function
  1845   1858   ** allocates it. If this fails, LSM_NOMEM is returned. Otherwise, LSM_OK.
  1846   1859   */
  1847   1860   static int fsCompressIntoBuffer(FileSystem *pFS, Page *pPg){
  1848   1861     lsm_compress *p = pFS->pCompress;
  1849   1862   
  1850         -  if( fsAllocateBuffer(pFS) ) return LSM_NOMEM;
         1863  +  if( fsAllocateBuffer(pFS, 1) ) return LSM_NOMEM;
  1851   1864     assert( pPg->nData==pFS->nPagesize );
  1852   1865   
  1853   1866     pPg->nCompress = pFS->nBuffer;
  1854   1867     return p->xCompress(p->pCtx, 
  1855         -      (char *)pFS->aBuffer, &pPg->nCompress, 
         1868  +      (char *)pFS->aOBuffer, &pPg->nCompress, 
  1856   1869         (const char *)pPg->aData, pPg->nData
  1857   1870     );
  1858   1871   }
  1859   1872   
  1860   1873   /*
  1861   1874   ** If the page passed as an argument is dirty, update the database file
  1862   1875   ** (or mapping of the database file) with its current contents and mark
................................................................................
  1879   1892         rc = fsCompressIntoBuffer(pFS, pPg);
  1880   1893   
  1881   1894         /* Serialize the compressed size into buffer aSz[] */
  1882   1895         putRecordSize(aSz, pPg->nCompress, 0);
  1883   1896   
  1884   1897         /* Write the serialized page record into the database file. */
  1885   1898         pPg->iPg = fsAppendData(pFS, pPg->pSeg, aSz, sizeof(aSz), &rc);
  1886         -      fsAppendData(pFS, pPg->pSeg, pFS->aBuffer, pPg->nCompress, &rc);
         1899  +      fsAppendData(pFS, pPg->pSeg, pFS->aOBuffer, pPg->nCompress, &rc);
  1887   1900         fsAppendData(pFS, pPg->pSeg, aSz, sizeof(aSz), &rc);
  1888   1901   
  1889   1902         /* Now that it has a page number, insert the page into the hash table */
  1890   1903         iHash = fsHashKey(pFS->nHash, pPg->iPg);
  1891   1904         pPg->pHashNext = pFS->apHash[iHash];
  1892   1905         pFS->apHash[iHash] = pPg;
  1893   1906   
................................................................................
  1949   1962       assert( nPad>=0 );
  1950   1963   
  1951   1964       if( nPad>=6 ){
  1952   1965         pSeg->nSize += nPad;
  1953   1966         nPad -= 6;
  1954   1967         putRecordSize(aSz, nPad, 1);
  1955   1968         fsAppendData(pFS, pSeg, aSz, sizeof(aSz), &rc);
  1956         -      memset(pFS->aBuffer, 0, nPad);
  1957         -      fsAppendData(pFS, pSeg, pFS->aBuffer, nPad, &rc);
         1969  +      memset(pFS->aOBuffer, 0, nPad);
         1970  +      fsAppendData(pFS, pSeg, pFS->aOBuffer, nPad, &rc);
  1958   1971         fsAppendData(pFS, pSeg, aSz, sizeof(aSz), &rc);
  1959   1972       }else if( nPad>0 ){
  1960   1973         u8 aBuf[5] = {0,0,0,0,0};
  1961   1974         aBuf[0] = (u8)nPad;
  1962   1975         aBuf[nPad-1] = (u8)nPad;
  1963   1976         fsAppendData(pFS, pSeg, aBuf, nPad, &rc);
  1964   1977       }