@@ -17,6 +17,7 @@ import (
17
17
"github.com/cockroachdb/crlib/fifo"
18
18
"github.com/cockroachdb/errors"
19
19
"github.com/cockroachdb/pebble/internal/base"
20
+ "github.com/cockroachdb/pebble/internal/bitflip"
20
21
"github.com/cockroachdb/pebble/internal/cache"
21
22
"github.com/cockroachdb/pebble/internal/crc"
22
23
"github.com/cockroachdb/pebble/internal/invariants"
@@ -174,53 +175,30 @@ func ValidateChecksum(checksumType ChecksumType, b []byte, bh Handle) error {
174
175
if expectedChecksum != computedChecksum {
175
176
// Check if the checksum was due to a singular bit flip and report it.
176
177
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 )
178
190
err := base .CorruptionErrorf ("block %d/%d: %s checksum mismatch %x != %x" ,
179
191
errors .Safe (bh .Offset ), errors .Safe (bh .Length ), checksumType ,
180
192
expectedChecksum , computedChecksum )
181
193
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 ) ))
184
196
}
185
197
return err
186
198
}
187
199
return nil
188
200
}
189
201
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
-
224
202
// Metadata is an in-memory buffer that stores metadata for a block. It is
225
203
// allocated together with the buffer storing the block and is initialized once
226
204
// when the block is read from disk.
0 commit comments