SQLite

Check-in [061a282cc0]
Login

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

Overview
Comment:Since walIndexTryHdr() can no longer encounter any error conditions, change tehe function signature so that it does not return an error code. This removes unreachable branches from other code.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 061a282cc0bf76541ab1f99b351a49d489ff93ec
User & Date: dan 2010-05-07 05:46:23.000
Context
2010-05-07
06:59
Fix a problem with checkpointing large log files created by an external process. (check-in: 8f94bde568 user: dan tags: trunk)
05:46
Since walIndexTryHdr() can no longer encounter any error conditions, change tehe function signature so that it does not return an error code. This removes unreachable branches from other code. (check-in: 061a282cc0 user: dan tags: trunk)
00:28
Another attempt to fix permutations.test so that it excludes WAL tests from the journaltest permutation. (check-in: 58c404429c user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/wal.c.
873
874
875
876
877
878
879
880

881
882
883
884
885
886
887




888
889
890
891

892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907


908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932









933
934
935
936
937
938
939
940


941






942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
/*
** Try to read the wal-index header. Attempt to verify the header
** checksum. If the checksum can be verified, copy the wal-index
** header into structure pWal->hdr. If the contents of pWal->hdr are
** modified by this and pChanged is not NULL, set *pChanged to 1. 
** Otherwise leave *pChanged unmodified.
**
** If the checksum cannot be verified return SQLITE_ERROR.

*/
int walIndexTryHdr(Wal *pWal, int *pisValid, int *pChanged){
  u32 aCksum[2] = {1, 1};
  u32 aHdr[WALINDEX_HDR_NFIELD+2];

  assert( *pisValid==0 );
  if( pWal->szWIndex==0 ){




    return SQLITE_OK;
  }

  /* Read the header. The caller may or may not have locked the wal-index

  ** file, meaning it is possible that an inconsistent snapshot is read
  ** from the file. If this happens, return SQLITE_ERROR.
  */
  memcpy(aHdr, pWal->pWiData, sizeof(aHdr));
  walChecksumBytes((u8*)aHdr, sizeof(u32)*WALINDEX_HDR_NFIELD, aCksum);
  if( aCksum[0]!=aHdr[WALINDEX_HDR_NFIELD]
   || aCksum[1]!=aHdr[WALINDEX_HDR_NFIELD+1]
  ){
    return SQLITE_OK;
  }
  *pisValid = 1;

  if( memcmp(&pWal->hdr, aHdr, sizeof(WalIndexHdr)) ){
    *pChanged = 1;
    memcpy(&pWal->hdr, aHdr, sizeof(WalIndexHdr));
  }


  return SQLITE_OK;
}

/*
** Read the wal-index header from the wal-index file into structure 
** pWal->hdr. If attempting to verify the header checksum fails, try
** to recover the log before returning.
**
** If the wal-index header is successfully read, return SQLITE_OK. 
** Otherwise an SQLite error code.
*/
static int walIndexReadHdr(Wal *pWal, int *pChanged){
  int rc;
  int isValid = 0;
  int lockState;

  assert( pWal->lockState>=SQLITE_SHM_READ );
  assert( pChanged );
  rc = walIndexMap(pWal, -1);
  if( rc!=SQLITE_OK ){
    return rc;
  }

  /* First try to read the header without a lock. Verify the checksum
  ** before returning. This will almost always work.  









  */
  rc = walIndexTryHdr(pWal, &isValid, pChanged);
  if( isValid || rc!=SQLITE_OK ){
    return rc;
  }

  /* If the first attempt to read the header failed, lock the wal-index
  ** file and try again. If the header checksum verification fails this


  ** time as well, run log recovery.






  */
  lockState = pWal->lockState;
  if( lockState>SQLITE_SHM_READ
   || SQLITE_OK==(rc = walSetLock(pWal, SQLITE_SHM_RECOVER)) 
  ){
    /* This call to walIndexTryHdr() may not return an error code, as the
    ** wal-index is already mapped. It may find that the header is invalid,
    ** but there is no chance of hitting an actual error.  */
    assert( pWal->pWiData );
    rc = walIndexTryHdr(pWal, &isValid, pChanged);
    assert( rc==SQLITE_OK );
    if( isValid==0 ){
      *pChanged = 1;
      rc = walIndexRecover(pWal);
    }
    if( lockState==SQLITE_SHM_READ ){
      walSetLock(pWal, SQLITE_SHM_READ);
    }
  }







|
>

|



|

>
>
>
>
|


|
>

|






|

<





>
>
|











|
<
|








|
|
>
>
>
>
>
>
>
>
>

|
<
|



|
>
>
|
>
>
>
>
>
>





<
<
<
<
|
<
<







873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907

908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927

928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949

950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968




969


970
971
972
973
974
975
976
/*
** Try to read the wal-index header. Attempt to verify the header
** checksum. If the checksum can be verified, copy the wal-index
** header into structure pWal->hdr. If the contents of pWal->hdr are
** modified by this and pChanged is not NULL, set *pChanged to 1. 
** Otherwise leave *pChanged unmodified.
**
** If the checksum cannot be verified return non-zero. If the header
** is read successfully and the checksum verified, return zero.
*/
int walIndexTryHdr(Wal *pWal, int *pChanged){
  u32 aCksum[2] = {1, 1};
  u32 aHdr[WALINDEX_HDR_NFIELD+2];

  assert( pWal->pWiData );
  if( pWal->szWIndex==0 ){
    /* The wal-index is of size 0 bytes. This is handled in the same way
    ** as an invalid header. The caller will run recovery to construct
    ** a valid wal-index file before accessing the database.
    */
    return 1;
  }

  /* Read the header. The caller may or may not have an exclusive 
  ** (WRITE, PENDING, CHECKPOINT or RECOVER) lock on the wal-index
  ** file, meaning it is possible that an inconsistent snapshot is read
  ** from the file. If this happens, return non-zero.
  */
  memcpy(aHdr, pWal->pWiData, sizeof(aHdr));
  walChecksumBytes((u8*)aHdr, sizeof(u32)*WALINDEX_HDR_NFIELD, aCksum);
  if( aCksum[0]!=aHdr[WALINDEX_HDR_NFIELD]
   || aCksum[1]!=aHdr[WALINDEX_HDR_NFIELD+1]
  ){
    return 1;
  }


  if( memcmp(&pWal->hdr, aHdr, sizeof(WalIndexHdr)) ){
    *pChanged = 1;
    memcpy(&pWal->hdr, aHdr, sizeof(WalIndexHdr));
  }

  /* The header was successfully read. Return zero. */
  return 0;
}

/*
** Read the wal-index header from the wal-index file into structure 
** pWal->hdr. If attempting to verify the header checksum fails, try
** to recover the log before returning.
**
** If the wal-index header is successfully read, return SQLITE_OK. 
** Otherwise an SQLite error code.
*/
static int walIndexReadHdr(Wal *pWal, int *pChanged){
  int rc;                         /* Return code */

  int lockState;                  /* pWal->lockState before running recovery */

  assert( pWal->lockState>=SQLITE_SHM_READ );
  assert( pChanged );
  rc = walIndexMap(pWal, -1);
  if( rc!=SQLITE_OK ){
    return rc;
  }

  /* First attempt to read the wal-index header. This may fail for one
  ** of two reasons: (a) the wal-index does not yet exist or has been
  ** corrupted and needs to be constructed by running recovery, or (b)
  ** the caller is only holding a READ lock and made a dirty read of
  ** the wal-index header.
  **
  ** A dirty read of the wal-index header occurs if another thread or
  ** process happens to be writing to the wal-index header at roughly
  ** the same time as this thread is reading it. In this case it is 
  ** possible that an inconsistent header is read (which is detected
  ** using the header checksum mechanism).
  */
  if( walIndexTryHdr(pWal, pChanged)==0 ){

    return SQLITE_OK;
  }

  /* If the first attempt to read the header failed, lock the wal-index
  ** file with an exclusive lock and try again. If the header checksum 
  ** verification fails again, we can be sure that it is not simply a
  ** dirty read, but that the wal-index really does need to be 
  ** reconstructed by running log recovery.
  **
  ** In the paragraph above, an "exclusive lock" may be any of WRITE,
  ** PENDING, CHECKPOINT or RECOVER. If any of these are already held,
  ** no locking operations are required. If the caller currently holds
  ** a READ lock, then upgrade to a RECOVER lock before re-reading the
  ** wal-index header and revert to a READ lock before returning.
  */
  lockState = pWal->lockState;
  if( lockState>SQLITE_SHM_READ
   || SQLITE_OK==(rc = walSetLock(pWal, SQLITE_SHM_RECOVER)) 
  ){




    if( walIndexTryHdr(pWal, pChanged) ){


      *pChanged = 1;
      rc = walIndexRecover(pWal);
    }
    if( lockState==SQLITE_SHM_READ ){
      walSetLock(pWal, SQLITE_SHM_READ);
    }
  }