@@ -17,6 +17,7 @@ import (
1717 "github.com/cockroachdb/crlib/fifo"
1818 "github.com/cockroachdb/errors"
1919 "github.com/cockroachdb/pebble/internal/base"
20+ "github.com/cockroachdb/pebble/internal/bitflip"
2021 "github.com/cockroachdb/pebble/internal/cache"
2122 "github.com/cockroachdb/pebble/internal/crc"
2223 "github.com/cockroachdb/pebble/internal/invariants"
@@ -174,53 +175,30 @@ func ValidateChecksum(checksumType ChecksumType, b []byte, bh Handle) error {
174175 if expectedChecksum != computedChecksum {
175176 // Check if the checksum was due to a singular bit flip and report it.
176177 data := slices .Clone (b [:bh .Length + 1 ])
177- found , indexFound , bitFound := checkSliceForBitFlip (data , checksumType , expectedChecksum )
178+ var checksumFunction func ([]byte ) uint32
179+ switch checksumType {
180+ case ChecksumTypeCRC32c :
181+ checksumFunction = func (data []byte ) uint32 {
182+ return crc .New (data ).Value ()
183+ }
184+ case ChecksumTypeXXHash64 :
185+ checksumFunction = func (data []byte ) uint32 {
186+ return uint32 (xxhash .Sum64 (data ))
187+ }
188+ }
189+ found , indexFound , bitFound := bitflip .CheckSliceForBitFlip (data , checksumFunction , expectedChecksum )
178190 err := base .CorruptionErrorf ("block %d/%d: %s checksum mismatch %x != %x" ,
179191 errors .Safe (bh .Offset ), errors .Safe (bh .Length ), checksumType ,
180192 expectedChecksum , computedChecksum )
181193 if found {
182- err = errors .WithSafeDetails (err , ". bit flip found: byte index %d. got: %x. want: %x." ,
183- indexFound , data [indexFound ], data [indexFound ]^ (1 << bitFound ))
194+ err = errors .WithSafeDetails (err , ". bit flip found: byte index %d. got: 0x %x. want: 0x %x." ,
195+ errors . Safe ( indexFound ), errors . Safe ( data [indexFound ]), errors . Safe ( data [indexFound ]^ (1 << bitFound ) ))
184196 }
185197 return err
186198 }
187199 return nil
188200}
189201
190- func checkSliceForBitFlip (
191- data []byte , checksumType ChecksumType , expectedChecksum uint32 ,
192- ) (found bool , indexFound int , bitFound int ) {
193- // TODO(edward) This checking process likely can be made faster.
194- iterationLimit := 40 * (1 << 10 ) // 40KB
195- for i := 0 ; i < min (len (data ), iterationLimit ); i ++ {
196- foundFlip , bit := checkByteForFlip (data , i , checksumType , expectedChecksum )
197- if foundFlip {
198- return true , i , bit
199- }
200- }
201- return false , 0 , 0
202- }
203-
204- func checkByteForFlip (
205- data []byte , i int , checksumType ChecksumType , expectedChecksum uint32 ,
206- ) (found bool , bit int ) {
207- for bit := 0 ; bit < 8 ; bit ++ {
208- data [i ] ^= (1 << bit )
209- var computedChecksum uint32
210- switch checksumType {
211- case ChecksumTypeCRC32c :
212- computedChecksum = crc .New (data ).Value ()
213- case ChecksumTypeXXHash64 :
214- computedChecksum = uint32 (xxhash .Sum64 (data ))
215- }
216- data [i ] ^= (1 << bit )
217- if computedChecksum == expectedChecksum {
218- return true , bit
219- }
220- }
221- return false , 0
222- }
223-
224202// Metadata is an in-memory buffer that stores metadata for a block. It is
225203// allocated together with the buffer storing the block and is initialized once
226204// when the block is read from disk.
0 commit comments