@@ -23,10 +23,9 @@ import (
2323 "github.com/cockroachdb/cockroach/pkg/roachpb"
2424 "github.com/cockroachdb/cockroach/pkg/storage"
2525 "github.com/cockroachdb/cockroach/pkg/storage/enginepb"
26- "github.com/cockroachdb/cockroach/pkg/util"
2726 "github.com/cockroachdb/cockroach/pkg/util/log"
27+ "github.com/cockroachdb/cockroach/pkg/util/must"
2828 "github.com/cockroachdb/errors"
29- "github.com/kr/pretty"
3029)
3130
3231// ClearRangeBytesThreshold is the threshold over which the ClearRange
@@ -174,63 +173,60 @@ func computeStatsDelta(
174173
175174 // We can avoid manually computing the stats delta if we're clearing
176175 // the entire range.
177- entireRange := desc .StartKey .Equal (from ) && desc .EndKey .Equal (to )
178- if entireRange {
176+ if desc .StartKey .Equal (from ) && desc .EndKey .Equal (to ) {
179177 // Note this it is safe to use the full range MVCC stats, as
180- // opposed to the usual method of computing only a localizied
178+ // opposed to the usual method of computing only a localized
181179 // stats delta, because a full-range clear prevents any concurrent
182180 // access to the stats. Concurrent changes to range-local keys are
183181 // explicitly ignored (i.e. SysCount, SysBytes).
184182 delta = cArgs .EvalCtx .GetMVCCStats ()
185183 delta .SysCount , delta .SysBytes , delta .AbortSpanBytes = 0 , 0 , 0 // no change to system stats
186- }
187184
188- // If we can't use the fast stats path, or race test is enabled, compute stats
189- // across the key span to be cleared.
190- if ! entireRange || util .RaceEnabled {
191- computed , err := storage .ComputeStats (readWriter , from , to , delta .LastUpdateNanos )
185+ // Assert correct stats.
186+ if err := must .Expensive (func () error {
187+ if delta .ContainsEstimates != 0 {
188+ return nil
189+ }
190+ computed , err := storage .ComputeStats (readWriter , from , to , delta .LastUpdateNanos )
191+ if err != nil {
192+ return err
193+ }
194+ return must .Equal (ctx , delta , computed , "range MVCC stats differ from computed" )
195+ }); err != nil {
196+ return enginepb.MVCCStats {}, err
197+ }
198+
199+ } else {
200+ // If we can't use the fast path, compute stats across the cleared span.
201+ var err error
202+ delta , err = storage .ComputeStats (readWriter , from , to , delta .LastUpdateNanos )
192203 if err != nil {
193204 return enginepb.MVCCStats {}, err
194205 }
195- // If we took the fast path but race is enabled, assert stats were correctly
196- // computed.
197- if entireRange {
198- // Retain the value of ContainsEstimates for tests under race.
199- computed .ContainsEstimates = delta .ContainsEstimates
200- // We only want to assert the correctness of stats that do not contain
201- // estimates.
202- if delta .ContainsEstimates == 0 && ! delta .Equal (computed ) {
203- log .Fatalf (ctx , "fast-path MVCCStats computation gave wrong result: diff(fast, computed) = %s" ,
204- pretty .Diff (delta , computed ))
205- }
206+
207+ // We need to adjust for the fragmentation of any MVCC range tombstones that
208+ // straddle the span bounds. The clearing of the inner fragments has already
209+ // been accounted for above. We take care not to peek outside the Raft range
210+ // bounds.
211+ leftPeekBound , rightPeekBound := rangeTombstonePeekBounds (
212+ from , to , desc .StartKey .AsRawKey (), desc .EndKey .AsRawKey ())
213+ rkIter := readWriter .NewMVCCIterator (storage .MVCCKeyIterKind , storage.IterOptions {
214+ KeyTypes : storage .IterKeyTypeRangesOnly ,
215+ LowerBound : leftPeekBound ,
216+ UpperBound : rightPeekBound ,
217+ })
218+ defer rkIter .Close ()
219+
220+ if cmp , lhs , err := storage .PeekRangeKeysLeft (rkIter , from ); err != nil {
221+ return enginepb.MVCCStats {}, err
222+ } else if cmp > 0 {
223+ delta .Subtract (storage .UpdateStatsOnRangeKeySplit (from , lhs .Versions ))
206224 }
207- delta = computed
208-
209- // If we're not clearing the entire range, we need to adjust for the
210- // fragmentation of any MVCC range tombstones that straddle the span bounds.
211- // The clearing of the inner fragments has already been accounted for above.
212- // We take care not to peek outside the Raft range bounds.
213- if ! entireRange {
214- leftPeekBound , rightPeekBound := rangeTombstonePeekBounds (
215- from , to , desc .StartKey .AsRawKey (), desc .EndKey .AsRawKey ())
216- rkIter := readWriter .NewMVCCIterator (storage .MVCCKeyIterKind , storage.IterOptions {
217- KeyTypes : storage .IterKeyTypeRangesOnly ,
218- LowerBound : leftPeekBound ,
219- UpperBound : rightPeekBound ,
220- })
221- defer rkIter .Close ()
222-
223- if cmp , lhs , err := storage .PeekRangeKeysLeft (rkIter , from ); err != nil {
224- return enginepb.MVCCStats {}, err
225- } else if cmp > 0 {
226- delta .Subtract (storage .UpdateStatsOnRangeKeySplit (from , lhs .Versions ))
227- }
228225
229- if cmp , rhs , err := storage .PeekRangeKeysRight (rkIter , to ); err != nil {
230- return enginepb.MVCCStats {}, err
231- } else if cmp < 0 {
232- delta .Subtract (storage .UpdateStatsOnRangeKeySplit (to , rhs .Versions ))
233- }
226+ if cmp , rhs , err := storage .PeekRangeKeysRight (rkIter , to ); err != nil {
227+ return enginepb.MVCCStats {}, err
228+ } else if cmp < 0 {
229+ delta .Subtract (storage .UpdateStatsOnRangeKeySplit (to , rhs .Versions ))
234230 }
235231 }
236232
0 commit comments