/ Check-in [84955c2e]
Login

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

Overview
Comment:Change the way checksums are calculated.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | wal
Files: files | file ages | folders
SHA1: 84955c2e9ce526c5a3ed479aa09f093a7e37c7d0
User & Date: dan 2010-04-15 10:58:52
Context
2010-04-15
13:33
Merge two leaves on the WAL branch. check-in: c9ed66cc user: dan tags: wal
10:58
Change the way checksums are calculated. check-in: 84955c2e user: dan tags: wal
02:37
Bring over the recent query planner enhancements from the trunk. check-in: 82969f27 user: drh tags: wal
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/log.c.

   137    137   /*
   138    138   ** Generate an 8 byte checksum based on the data in array aByte[] and the
   139    139   ** initial values of aCksum[0] and aCksum[1]. The checksum is written into
   140    140   ** aCksum[] before returning.
   141    141   */
   142    142   #define LOG_CKSM_BYTES 8
   143    143   static void logChecksumBytes(u8 *aByte, int nByte, u32 *aCksum){
   144         -  u32 *z32 = (u32 *)aByte;
   145         -  int n32 = nByte / sizeof(u32);
   146         -  int i;
          144  +  u64 sum1 = aCksum[0];
          145  +  u64 sum2 = aCksum[1];
          146  +  u32 *a32 = (u32 *)aByte;
          147  +  u32 *aEnd = (u32 *)&aByte[nByte];
   147    148   
   148    149     assert( LOG_CKSM_BYTES==2*sizeof(u32) );
   149    150     assert( (nByte&0x00000003)==0 );
   150    151   
   151         -  u32 cksum0 = aCksum[0];
   152         -  u32 cksum1 = aCksum[1];
          152  +  do {
          153  +    sum1 += (*a32++);
          154  +    sum2 += sum1;
          155  +  } while( a32<aEnd );
   153    156   
   154         -  for(i=0; i<n32; i++){
   155         -    cksum0 = (cksum0 >> 8) + (cksum0 ^ z32[i]);
   156         -    cksum1 = (cksum1 >> 8) + (cksum1 ^ z32[i]);
   157         -  }
   158         -
   159         -  aCksum[0] = cksum0;
   160         -  aCksum[1] = cksum1;
          157  +  aCksum[0] = sum1 + (sum1>>24);
          158  +  aCksum[1] = sum2 + (sum2>>24);
   161    159   }
   162    160   
   163    161   /*
   164    162   ** Argument zPath must be a nul-terminated string containing a path-name.
   165    163   ** This function modifies the string in-place by removing any "./" or "../" 
   166    164   ** elements in the path. For example, the following input:
   167    165   **
................................................................................
  1255   1253     if( pLog->isLocked ){
  1256   1254       assert( pLog->isLocked==LOG_REGION_A || pLog->isLocked==LOG_REGION_D );
  1257   1255       logLockRegion(pLog, pLog->isLocked, LOG_UNLOCK);
  1258   1256     }
  1259   1257     pLog->isLocked = 0;
  1260   1258   }
  1261   1259   
  1262         -
  1263         -
  1264   1260   /* 
  1265   1261   ** Read a page from the log, if it is present. 
  1266   1262   */
  1267   1263   int sqlite3LogRead(Log *pLog, Pgno pgno, int *pInLog, u8 *pOut){
  1268   1264     u32 iRead = 0;
  1269   1265     u32 *aData = pLog->pSummary->aData;
  1270   1266     int iFrame = (pLog->hdr.iLastPg & 0xFFFFFF00);
         1267  +
         1268  +  assert( pLog->isLocked );
  1271   1269   
  1272   1270     /* Do a linear search of the unindexed block of page-numbers (if any) 
  1273   1271     ** at the end of the log-summary. An alternative to this would be to
  1274   1272     ** build an index in private memory each time a read transaction is
  1275   1273     ** opened on a new snapshot.
  1276   1274     */
  1277   1275     if( pLog->hdr.iLastPg ){
................................................................................
  1345   1343   
  1346   1344       /* Obtain the writer lock */
  1347   1345       int rc = logLockRegion(pLog, LOG_REGION_C|LOG_REGION_D, LOG_WRLOCK);
  1348   1346       if( rc!=SQLITE_OK ){
  1349   1347         return rc;
  1350   1348       }
  1351   1349   
  1352         -    /* If this is connection is a region D, then the SHARED lock on region
  1353         -    ** D has just been upgraded to EXCLUSIVE. But no lock at all is held on
  1354         -    ** region A. This means that if the write-transaction is committed
         1350  +    /* If this is connection is a region D reader, then the SHARED lock on 
         1351  +    ** region D has just been upgraded to EXCLUSIVE. But no lock at all is 
         1352  +    ** held on region A. This means that if the write-transaction is committed
  1355   1353       ** and this connection downgrades to a reader, it will be left with no
  1356         -    ** lock at all. And its snapshot could get clobbered by a checkpoint
         1354  +    ** lock at all. And so its snapshot could get clobbered by a checkpoint
  1357   1355       ** operation. 
  1358   1356       **
  1359   1357       ** To stop this from happening, grab a SHARED lock on region A now.
  1360   1358       ** This should always be successful, as the only time a client holds
  1361   1359       ** an EXCLUSIVE lock on region A, it must also be holding an EXCLUSIVE
  1362   1360       ** lock on region C (a checkpointer does this). This is not possible,
  1363   1361       ** as this connection currently has the EXCLUSIVE lock on region C.
  1364   1362       */
  1365   1363       if( pLog->isLocked==LOG_REGION_D ){
  1366   1364         logLockRegion(pLog, LOG_REGION_A, LOG_RDLOCK);
  1367   1365         pLog->isLocked = LOG_REGION_A;
  1368   1366       }
  1369   1367   
         1368  +    /* If this connection is not reading the most recent database snapshot,
         1369  +    ** it is not possible to write to the database. In this case release
         1370  +    ** the write locks and return SQLITE_BUSY.
         1371  +    */
  1370   1372       if( memcmp(&pLog->hdr, pLog->pSummary->aData, sizeof(pLog->hdr)) ){
  1371   1373         logLockRegion(pLog, LOG_REGION_C|LOG_REGION_D, LOG_UNLOCK);
  1372   1374         return SQLITE_BUSY;
  1373   1375       }
  1374   1376       pLog->isWriteLocked = 1;
  1375   1377   
  1376   1378     }else if( pLog->isWriteLocked ){
................................................................................
  1531   1533     sqlite3_file *pFd,              /* File descriptor open on db file */
  1532   1534     u8 *zBuf,                       /* Temporary buffer to use */
  1533   1535     int (*xBusyHandler)(void *),    /* Pointer to busy-handler function */
  1534   1536     void *pBusyHandlerArg           /* Argument to pass to xBusyHandler */
  1535   1537   ){
  1536   1538     int rc;                         /* Return code */
  1537   1539   
  1538         -  /* Wait for a write-lock on regions B and C. */
         1540  +  assert( !pLog->isLocked );
         1541  +
         1542  +  /* Wait for an EXCLUSIVE lock on regions B and C. */
  1539   1543     do {
  1540   1544       rc = logLockRegion(pLog, LOG_REGION_B|LOG_REGION_C, LOG_WRLOCK);
  1541   1545     }while( rc==SQLITE_BUSY && xBusyHandler(pBusyHandlerArg) );
  1542   1546     if( rc!=SQLITE_OK ) return rc;
  1543   1547   
  1544         -  /* Wait for a write-lock on region A. */
         1548  +  /* Wait for an EXCLUSIVE lock on region A. */
  1545   1549     do {
  1546   1550       rc = logLockRegion(pLog, LOG_REGION_A, LOG_WRLOCK);
  1547   1551     }while( rc==SQLITE_BUSY && xBusyHandler(pBusyHandlerArg) );
  1548   1552     if( rc!=SQLITE_OK ){
  1549   1553       logLockRegion(pLog, LOG_REGION_B|LOG_REGION_C, LOG_UNLOCK);
  1550   1554       return rc;
  1551   1555     }