/ Check-in [2b5df3e8]
Login

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

Overview
Comment:Avoid reading or writing the 32 locking bytes at the end of the first meta-page of an LSM database.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | lsm-metapage-fix
Files: files | file ages | folders
SHA3-256: 2b5df3e8a80ae5c0415081dd9b29acaad1464be2e7971399e52c1c98408322d9
User & Date: dan 2017-06-29 20:13:44
Context
2017-06-29
20:23
Avoid reading or writing the 32 locking bytes at the end of the first meta-page of an LSM database. check-in: 3ed6877f user: dan tags: trunk
20:13
Avoid reading or writing the 32 locking bytes at the end of the first meta-page of an LSM database. Closed-Leaf check-in: 2b5df3e8 user: dan tags: lsm-metapage-fix
19:08
Fix issues in the POSIX and Win32 interfaces for lsm1. check-in: 38ec4141 user: mistachkin tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/lsm1/lsmInt.h.

    61     61   #define LSM_DFLT_USE_LOG            1
    62     62   
    63     63   /* Initial values for log file checksums. These are only used if the 
    64     64   ** database file does not contain a valid checkpoint.  */
    65     65   #define LSM_CKSUM0_INIT 42
    66     66   #define LSM_CKSUM1_INIT 42
    67     67   
    68         -#define LSM_META_PAGE_SIZE 4096
    69         -
    70     68   /* "mmap" mode is currently only used in environments with 64-bit address 
    71     69   ** spaces. The following macro is used to test for this.  */
    72     70   #define LSM_IS_64_BIT (sizeof(void*)==8)
    73     71   
    74     72   #define LSM_AUTOWORK_QUANT 32
    75     73   
    76     74   typedef struct Database Database;
................................................................................
   150    148   #define LSM_LOCK_WRITER       4
   151    149   #define LSM_LOCK_WORKER       5
   152    150   #define LSM_LOCK_CHECKPOINTER 6
   153    151   #define LSM_LOCK_ROTRANS      7
   154    152   #define LSM_LOCK_READER(i)    ((i) + LSM_LOCK_ROTRANS + 1)
   155    153   #define LSM_LOCK_RWCLIENT(i)  ((i) + LSM_LOCK_READER(LSM_LOCK_NREADER))
   156    154   
          155  +#define LSM_N_LOCK LSM_LOCK_RWCLIENT(LSM_LOCK_NRWCLIENT)
          156  +
          157  +/*
          158  +** Meta-page size and usable size.
          159  +*/
          160  +#define LSM_META_PAGE_SIZE 4096
          161  +
          162  +#define LSM_META_RW_PAGE_SIZE (LSM_META_PAGE_SIZE - LSM_N_LOCK)
          163  +
   157    164   /*
   158    165   ** Hard limit on the number of free-list entries that may be stored in 
   159    166   ** a checkpoint (the remainder are stored as a system record in the LSM).
   160    167   ** See also LSM_CONFIG_MAX_FREELIST.
   161    168   */
   162    169   #define LSM_MAX_FREELIST_ENTRIES 24
   163    170   

Changes to ext/lsm1/lsm_ckpt.c.

   713    713   ** checkpoint.
   714    714   */
   715    715   static int ckptChecksumOk(u32 *aCkpt){
   716    716     u32 nCkpt = aCkpt[CKPT_HDR_NCKPT];
   717    717     u32 cksum1;
   718    718     u32 cksum2;
   719    719   
   720         -  if( nCkpt<CKPT_HDR_NCKPT || nCkpt>(LSM_META_PAGE_SIZE)/sizeof(u32) ) return 0;
          720  +  if( nCkpt<CKPT_HDR_NCKPT || nCkpt>(LSM_META_RW_PAGE_SIZE)/sizeof(u32) ){
          721  +    return 0;
          722  +  }
   721    723     ckptChecksum(aCkpt, nCkpt, &cksum1, &cksum2);
   722    724     return (cksum1==aCkpt[nCkpt-2] && cksum2==aCkpt[nCkpt-1]);
   723    725   }
   724    726   
   725    727   /*
   726    728   ** Attempt to load a checkpoint from meta page iMeta.
   727    729   **
................................................................................
   866    868   int lsmCheckpointLoad(lsm_db *pDb, int *piRead){
   867    869     int nRem = LSM_ATTEMPTS_BEFORE_PROTOCOL;
   868    870     ShmHeader *pShm = pDb->pShmhdr;
   869    871     while( (nRem--)>0 ){
   870    872       int nInt;
   871    873   
   872    874       nInt = pShm->aSnap1[CKPT_HDR_NCKPT];
   873         -    if( nInt<=(LSM_META_PAGE_SIZE / sizeof(u32)) ){
          875  +    if( nInt<=(LSM_META_RW_PAGE_SIZE / sizeof(u32)) ){
   874    876         memcpy(pDb->aSnapshot, pShm->aSnap1, nInt*sizeof(u32));
   875    877         if( ckptChecksumOk(pDb->aSnapshot) ){
   876    878           if( piRead ) *piRead = 1;
   877    879           return LSM_OK;
   878    880         }
   879    881       }
   880    882   
   881    883       nInt = pShm->aSnap2[CKPT_HDR_NCKPT];
   882         -    if( nInt<=(LSM_META_PAGE_SIZE / sizeof(u32)) ){
          884  +    if( nInt<=(LSM_META_RW_PAGE_SIZE / sizeof(u32)) ){
   883    885         memcpy(pDb->aSnapshot, pShm->aSnap2, nInt*sizeof(u32));
   884    886         if( ckptChecksumOk(pDb->aSnapshot) ){
   885    887           if( piRead ) *piRead = 2;
   886    888           return LSM_OK;
   887    889         }
   888    890       }
   889    891   
................................................................................
  1081   1083     int rc;
  1082   1084   
  1083   1085     pSnap->iId++;
  1084   1086     rc = ckptExportSnapshot(pDb, bFlush, pSnap->iId, 1, &p, &n);
  1085   1087     if( rc!=LSM_OK ) return rc;
  1086   1088     assert( ckptChecksumOk((u32 *)p) );
  1087   1089   
  1088         -  assert( n<=LSM_META_PAGE_SIZE );
         1090  +  assert( n<=LSM_META_RW_PAGE_SIZE );
  1089   1091     memcpy(pShm->aSnap2, p, n);
  1090   1092     lsmShmBarrier(pDb);
  1091   1093     memcpy(pShm->aSnap1, p, n);
  1092   1094     lsmFree(pDb->pEnv, p);
  1093   1095   
  1094   1096     assert( lsmFsIntegrityCheck(pDb) );
  1095   1097     return LSM_OK;
................................................................................
  1116   1118       rc = lsmFsMetaPageGet(pDb->pFS, 0, iMeta, &pPg);
  1117   1119       if( rc==LSM_OK ){
  1118   1120         int nCkpt;
  1119   1121         int nData;
  1120   1122         u8 *aData; 
  1121   1123   
  1122   1124         aData = lsmFsMetaPageData(pPg, &nData);
  1123         -      assert( nData==LSM_META_PAGE_SIZE );
         1125  +      assert( nData==LSM_META_RW_PAGE_SIZE );
  1124   1126         nCkpt = lsmGetU32(&aData[CKPT_HDR_NCKPT*sizeof(u32)]);
  1125         -      if( nCkpt<(LSM_META_PAGE_SIZE/sizeof(u32)) ){
         1127  +      if( nCkpt<(LSM_META_RW_PAGE_SIZE/sizeof(u32)) ){
  1126   1128           u32 *aCopy = lsmMallocRc(pDb->pEnv, sizeof(u32) * nCkpt, &rc);
  1127   1129           if( aCopy ){
  1128   1130             memcpy(aCopy, aData, nCkpt*sizeof(u32));
  1129   1131             ckptChangeEndianness(aCopy, nCkpt);
  1130   1132             if( ckptChecksumOk(aCopy) ){
  1131   1133               if( piId ) *piId = lsmCheckpointId(aCopy, 0);
  1132   1134               if( piLog ) *piLog = (lsmCheckpointLogOffset(aCopy) >> 1);

Changes to ext/lsm1/lsm_file.c.

   210    210   */
   211    211   struct FileSystem {
   212    212     lsm_db *pDb;                    /* Database handle that owns this object */
   213    213     lsm_env *pEnv;                  /* Environment pointer */
   214    214     char *zDb;                      /* Database file name */
   215    215     char *zLog;                     /* Database file name */
   216    216     int nMetasize;                  /* Size of meta pages in bytes */
          217  +  int nMetaRwSize;                /* Read/written size of meta pages in bytes */
   217    218     int nPagesize;                  /* Database page-size in bytes */
   218    219     int nBlocksize;                 /* Database block-size in bytes */
   219    220   
   220    221     /* r/w file descriptors for both files. */
   221    222     LsmFile *pLsmFile;              /* Used after lsm_close() to link into list */
   222    223     lsm_file *fdDb;                 /* Database file */
   223    224     lsm_file *fdLog;                /* Log file */
................................................................................
   631    632     pFS = (FileSystem *)lsmMallocZeroRc(pDb->pEnv, nByte, &rc);
   632    633     if( pFS ){
   633    634       LsmFile *pLsmFile;
   634    635       pFS->zDb = (char *)&pFS[1];
   635    636       pFS->zLog = &pFS->zDb[nDb+1];
   636    637       pFS->nPagesize = LSM_DFLT_PAGE_SIZE;
   637    638       pFS->nBlocksize = LSM_DFLT_BLOCK_SIZE;
   638         -    pFS->nMetasize = 4 * 1024;
          639  +    pFS->nMetasize = LSM_META_PAGE_SIZE;
          640  +    pFS->nMetaRwSize = LSM_META_RW_PAGE_SIZE;
   639    641       pFS->pDb = pDb;
   640    642       pFS->pEnv = pDb->pEnv;
   641    643   
   642    644       /* Make a copy of the database and log file names. */
   643    645       memcpy(pFS->zDb, zDb, nDb+1);
   644    646       memcpy(pFS->zLog, zDb, nDb);
   645    647       memcpy(&pFS->zLog[nDb], "-log", 5);
................................................................................
  2267   2269       i64 iOff = (iPg-1) * pFS->nMetasize;
  2268   2270       if( pFS->nMapLimit>0 ){
  2269   2271         fsGrowMapping(pFS, 2*pFS->nMetasize, &rc);
  2270   2272         pPg->aData = (u8 *)(pFS->pMap) + iOff;
  2271   2273       }else{
  2272   2274         pPg->aData = lsmMallocRc(pFS->pEnv, pFS->nMetasize, &rc);
  2273   2275         if( rc==LSM_OK && bWrite==0 ){
  2274         -        rc = lsmEnvRead(pFS->pEnv, pFS->fdDb, iOff, pPg->aData, pFS->nMetasize);
         2276  +        rc = lsmEnvRead(
         2277  +            pFS->pEnv, pFS->fdDb, iOff, pPg->aData, pFS->nMetaRwSize
         2278  +        );
  2275   2279         }
  2276   2280   #ifndef NDEBUG
  2277   2281         /* pPg->aData causes an uninitialized access via a downstreadm write().
  2278   2282            After discussion on this list, this memory should not, for performance
  2279   2283            reasons, be memset. However, tracking down "real" misuse is more
  2280   2284            difficult with this "false" positive, so it is set when NDEBUG.
  2281   2285         */
................................................................................
  2307   2311     int rc = LSM_OK;
  2308   2312     if( pPg ){
  2309   2313       FileSystem *pFS = pPg->pFS;
  2310   2314   
  2311   2315       if( pFS->nMapLimit==0 ){
  2312   2316         if( pPg->bWrite ){
  2313   2317           i64 iOff = (pPg->iPg==2 ? pFS->nMetasize : 0);
  2314         -        int nWrite = pFS->nMetasize;
         2318  +        int nWrite = pFS->nMetaRwSize;
  2315   2319           rc = lsmEnvWrite(pFS->pEnv, pFS->fdDb, iOff, pPg->aData, nWrite);
  2316   2320         }
  2317   2321         lsmFree(pFS->pEnv, pPg->aData);
  2318   2322       }
  2319   2323   
  2320   2324       lsmFree(pFS->pEnv, pPg);
  2321   2325     }
................................................................................
  2324   2328   
  2325   2329   /*
  2326   2330   ** Return a pointer to a buffer containing the data associated with the
  2327   2331   ** meta-page passed as the first argument. If parameter pnData is not NULL,
  2328   2332   ** set *pnData to the size of the meta-page in bytes before returning.
  2329   2333   */
  2330   2334   u8 *lsmFsMetaPageData(MetaPage *pPg, int *pnData){
  2331         -  if( pnData ) *pnData = pPg->pFS->nMetasize;
         2335  +  if( pnData ) *pnData = pPg->pFS->nMetaRwSize;
  2332   2336     return pPg->aData;
  2333   2337   }
  2334   2338   
  2335   2339   /*
  2336   2340   ** Return true if page is currently writable. This is used in assert() 
  2337   2341   ** statements only.
  2338   2342   */