@@ -15,6 +15,7 @@ import (
1515 "github.com/cockroachdb/cockroach/pkg/kv/kvserver/kvserverpb"
1616 "github.com/cockroachdb/cockroach/pkg/kv/kvserver/lockspanset"
1717 "github.com/cockroachdb/cockroach/pkg/kv/kvserver/spanset"
18+ "github.com/cockroachdb/cockroach/pkg/raft"
1819 "github.com/cockroachdb/cockroach/pkg/roachpb"
1920 "github.com/cockroachdb/cockroach/pkg/storage"
2021 "github.com/cockroachdb/cockroach/pkg/util/log"
@@ -66,21 +67,25 @@ func TruncateLog(
6667 // existing entry's term?
6768 // TODO(pav-kv): some day, make args.Index an inclusive compaction index, and
6869 // eliminate the remaining +-1 arithmetics.
69- firstIndex := cArgs .EvalCtx .GetCompactedIndex () + 1
70- if firstIndex >= args .Index {
71- if log .V (3 ) {
72- log .KvExec .Infof (ctx , "attempting to truncate previously truncated raft log. FirstIndex:%d, TruncateFrom:%d" ,
73- firstIndex , args .Index )
74- }
75- return result.Result {}, nil
76- }
7770
78- // args.Index is the first index to keep.
79- term , err := cArgs .EvalCtx .GetTerm (args .Index - 1 )
71+ // Use the log engine to compute stats for the raft log.
72+ // TODO(#136358): After we precisely maintain the Raft Log size, we could stop
73+ // needing the Log Engine to compute the stats.
74+ compactedIndex , term , logEngineReader , err := cArgs .EvalCtx .PrepareLogEngineTruncation (args .Index )
8075 if err != nil {
81- return result.Result {}, errors .Wrap (err , "getting term" )
76+ if errors .Is (err , raft .ErrCompacted ) {
77+ // The log has already been truncated past this point - this is a no-op.
78+ if log .V (3 ) {
79+ log .KvExec .Infof (ctx , "attempting to truncate previously truncated raft log. FirstIndex:%d, TruncateFrom:%d" ,
80+ compactedIndex + 1 , args .Index )
81+ }
82+ return result.Result {}, nil
83+ }
84+ return result.Result {}, errors .Wrap (err , "preparing log truncation" )
8285 }
86+ defer logEngineReader .Close ()
8387
88+ firstIndex := compactedIndex + 1
8489 // Compute the number of bytes freed by this truncation. Note that using
8590 // firstIndex only make sense for the leaseholder as we base this off its
8691 // own first index (other replicas may have other first indexes). In
@@ -92,34 +97,12 @@ func TruncateLog(
9297 // flight TruncateLogRequests, and using the firstIndex will result in
9398 // duplicate accounting. The ExpectedFirstIndex, populated for clusters at
9499 // LooselyCoupledRaftLogTruncation, allows us to avoid this problem.
95- //
96- // We have an additional source of error not mitigated by
97- // ExpectedFirstIndex. There is nothing synchronizing firstIndex with the
98- // state visible in readWriter. The former uses the in-memory state or
99- // fetches directly from the Engine. The latter uses Engine state from some
100- // point in time which can fall anywhere in the time interval starting from
101- // when the readWriter was created up to where we create an MVCCIterator
102- // below.
103- // TODO(sumeer): we can eliminate this error as part of addressing
104- // https://github.com/cockroachdb/cockroach/issues/55461 and
105- // https://github.com/cockroachdb/cockroach/issues/70974 that discuss taking
106- // a consistent snapshot of some Replica state and the engine.
107100 if args .ExpectedFirstIndex > firstIndex {
108101 firstIndex = args .ExpectedFirstIndex
109102 }
110103 start := keys .RaftLogKey (rangeID , firstIndex )
111104 end := keys .RaftLogKey (rangeID , args .Index )
112105
113- // TODO(pav-kv): GetCompactedIndex, GetTerm, and NewReader calls can disagree
114- // on the state of the log since we don't hold any Replica locks here. Move
115- // the computation inside Replica where locking can be controlled precisely.
116- //
117- // Use the log engine to compute stats for the raft log.
118- // TODO(#136358): After we precisely maintain the Raft Log size, we could stop
119- // needing the Log Engine to compute the stats.
120- logReader := cArgs .EvalCtx .LogEngine ().NewReader (storage .StandardDurability )
121- defer logReader .Close ()
122-
123106 // Compute the stats delta that were to occur should the log entries be
124107 // purged. We do this as a side effect of seeing a new TruncatedState,
125108 // downstream of Raft.
@@ -128,7 +111,7 @@ func TruncateLog(
128111 // are not tracked in the raft log delta. The delta will be adjusted below
129112 // raft.
130113 // We can pass zero as nowNanos because we're only interested in SysBytes.
131- ms , err := storage .ComputeStats (ctx , logReader , start , end , 0 /* nowNanos */ )
114+ ms , err := storage .ComputeStats (ctx , logEngineReader , start , end , 0 /* nowNanos */ )
132115 if err != nil {
133116 return result.Result {}, errors .Wrap (err , "while computing stats of Raft log freed by truncation" )
134117 }
0 commit comments