-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
kvserver: decouple cmd checks in replicaAppBatch
This refactors the command application pre-flight checks on replicaAppBatch such that they can move to appBatch once that struct evolves from a stub into an actual implementation of `apply.Batch`. Epic: CRDB-220 Release note: None
- Loading branch information
Showing
4 changed files
with
156 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
// Copyright 2022 The Cockroach Authors. | ||
// | ||
// Use of this software is governed by the Business Source License | ||
// included in the file licenses/BSL.txt. | ||
// | ||
// As of the Change Date specified in that file, in accordance with | ||
// the Business Source License, use of this software will be governed | ||
// by the Apache License, Version 2.0, included in the file | ||
// licenses/APL.txt. | ||
|
||
package kvserver | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/cockroachdb/cockroach/pkg/kv/kvserver/kvserverbase" | ||
"github.com/cockroachdb/cockroach/pkg/kv/kvserver/kvserverpb" | ||
"github.com/cockroachdb/cockroach/pkg/kv/kvserver/raftlog" | ||
"github.com/cockroachdb/cockroach/pkg/roachpb" | ||
"github.com/cockroachdb/cockroach/pkg/util/log" | ||
"github.com/cockroachdb/errors" | ||
) | ||
|
||
// appBatch is the in-progress foundation for standalone log entry | ||
// application[^1], i.e. the act of applying raft log entries to the state | ||
// machine in a library-style fashion, without a running CockroachDB server. | ||
// | ||
// The intended usage is as follows. Starting with a ReplicatedCmd per Entry, | ||
// | ||
// 1. check it via assertAndCheckCommand followed by toCheckedCmd | ||
// 2. run pre-add triggers (which may augment the WriteBatch) | ||
// 3. stage the WriteBatch into a pebble Batch | ||
// 4. run post-add triggers (metrics, etc) | ||
// | ||
// when all Entries have been added, the batch can be committed. In the course | ||
// of time, appBatch will become an implementation of apply.Batch itself; at the | ||
// time of writing it is only used by the replicaAppBatch implementation of | ||
// apply.Batch, which goes through the above steps while interspersing: | ||
// | ||
// 1a. testing interceptors between assertAndCheckCommand and toCheckedCmd | ||
// 2b. pre-add triggers specific to online command application (e.g. acquiring locks | ||
// during replica-spanning operations), and | ||
// 4b. post-add triggers specific to online command application (e.g. updates to | ||
// Replica in-mem state) | ||
// | ||
// [^1]: https://github.com/cockroachdb/cockroach/issues/75729 | ||
type appBatch struct { | ||
// TODO(tbg): this will absorb the following fields from replicaAppBatch: | ||
// | ||
// - batch | ||
// - state | ||
// - changeRemovesReplica | ||
} | ||
|
||
func (b *appBatch) assertAndCheckCommand( | ||
ctx context.Context, cmd *raftlog.ReplicatedCmd, state *kvserverpb.ReplicaState, isLocal bool, | ||
) (leaseIndex uint64, _ kvserverbase.ProposalRejectionType, forcedErr *roachpb.Error, _ error) { | ||
if log.V(4) { | ||
log.Infof(ctx, "processing command %x: raftIndex=%d maxLeaseIndex=%d closedts=%s", | ||
cmd.ID, cmd.Index(), cmd.Cmd.MaxLeaseIndex, cmd.Cmd.ClosedTimestamp) | ||
} | ||
|
||
if cmd.Index() == 0 { | ||
return 0, 0, nil, errors.AssertionFailedf("processRaftCommand requires a non-zero index") | ||
} | ||
if idx, applied := cmd.Index(), state.RaftAppliedIndex; idx != applied+1 { | ||
// If we have an out-of-order index, there's corruption. No sense in | ||
// trying to update anything or running the command. Simply return. | ||
return 0, 0, nil, errors.AssertionFailedf("applied index jumped from %d to %d", applied, idx) | ||
} | ||
|
||
// TODO(sep-raft-log): move the closedts checks from replicaAppBatch here as | ||
// well. This just needs a bit more untangling as they reference *Replica, but | ||
// for no super-convincing reason. | ||
|
||
leaseIndex, rej, forcedErr := kvserverbase.CheckForcedErr(ctx, cmd.ID, &cmd.Cmd, isLocal, state) | ||
return leaseIndex, rej, forcedErr, nil | ||
} | ||
|
||
func (b *appBatch) toCheckedCmd( | ||
ctx context.Context, | ||
cmd *raftlog.ReplicatedCmd, | ||
leaseIndex uint64, | ||
rej kvserverbase.ProposalRejectionType, | ||
forcedErr *roachpb.Error, | ||
) { | ||
cmd.LeaseIndex, cmd.Rejection, cmd.ForcedErr = leaseIndex, rej, forcedErr | ||
if cmd.Rejected() { | ||
log.VEventf(ctx, 1, "applying command with forced error: %s", cmd.ForcedErr) | ||
|
||
// Apply an empty command. | ||
cmd.Cmd.ReplicatedEvalResult = kvserverpb.ReplicatedEvalResult{} | ||
cmd.Cmd.WriteBatch = nil | ||
cmd.Cmd.LogicalOpLog = nil | ||
cmd.Cmd.ClosedTimestamp = nil | ||
} else { | ||
log.Event(ctx, "applying command") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters