@@ -45,18 +45,6 @@ func (mr *mmaReplica) mmaRangeLoad() mmaprototype.RangeLoad {
45
45
// should be sent to mma and overrides mmaSpanConfigIsUpToDate as true. The
46
46
// contract is: if this returns true, mmaReplica must send a fully populated
47
47
// range message to mma.
48
- //
49
- // Ideally, this would be called within isLeaseholderWithDescAndConfig so that we
50
- // acquire the lock on the replica only once. However, we can't do that because,
51
- // at that point, it's still unclear whether the message will be sent. We only
52
- // want to set mmaSpanConfigIsUpToDate to true that the message will definitely
53
- // be sent to MMA. Technically, it should be fine since mmaSpanConfigIsUpToDate
54
- // would be set to true soonly after during markSpanConfigNeedsUpdate, but it
55
- // would be wrong if tryConstructMMARangeMsg is concurrent. Specifically, if
56
- // another call to tryConstructMMARangeMsg sees mmaSpanConfigIsUpToDate as true,
57
- // it may decide to drop the span config even though the most up-to-date span
58
- // config might end up being dropped. In addition, isLeaseholderWithDescAndConfig
59
- // would only need a read lock on the replica without this.
60
48
func (mr * mmaReplica ) maybePromiseSpanConfigUpdate () (needed bool ) {
61
49
r := (* Replica )(mr )
62
50
r .mu .Lock ()
@@ -68,7 +56,7 @@ func (mr *mmaReplica) maybePromiseSpanConfigUpdate() (needed bool) {
68
56
69
57
// markSpanConfigNeedsUpdate marks the span config as needing an update. This is
70
58
// called by tryConstructMMARangeMsg when it cannot construct the RangeMsg. It
71
- // is signaled that mma might have deleted this range state (including the span
59
+ // signals that mma might have deleted this range state (including the span
72
60
// config), so we need to send a full range message to mma the next time
73
61
// mmaReplica is the leaseholder.
74
62
func (mr * mmaReplica ) markSpanConfigNeedsUpdate () {
@@ -110,7 +98,7 @@ func (mr *mmaReplica) isLeaseholderWithDescAndConfig(
110
98
defer r .mu .RUnlock ()
111
99
now := r .store .Clock ().NowAsClockTimestamp ()
112
100
leaseStatus := r .leaseStatusAtRLocked (ctx , now )
113
- // TODO(wenyihu6): Alternatively, we could just read r.shMu.state.Leas` and
101
+ // TODO(wenyihu6): Alternatively, we could just read r.shMu.state.Lease and
114
102
// check if it is non-nil and call OwnedBy(r.store.StoreID()), which would be
115
103
// cheaper. One tradeoff is that if the lease has expired, and a new lease has
116
104
// not been installed in the state machine, the cheaper approach would think
@@ -174,6 +162,14 @@ func constructRangeMsgReplicas(
174
162
// Called periodically by the same entity (and must not be called concurrently).
175
163
// If this method returned isLeaseholder=true and shouldBeSkipped=false the last
176
164
// time, that message must have been fed to the allocator.
165
+ //
166
+ // Concurrency concerns:
167
+ // Caller1 may call into maybePromiseSpanConfigUpdate() and include the SpanConfig
168
+ // (marking it as no longer needed an update), and then Caller2 decides not to
169
+ // include the SpanConfig in the rangeMsg. But caller2 may get ahead and call
170
+ // into mma first with a RangeMsg that is lacking a SpanConfig and mma wouldn't
171
+ // know how to initialize a range it knows nothing about. More thinking is needed
172
+ // to claim this method is not racy.
177
173
func (mr * mmaReplica ) tryConstructMMARangeMsg (
178
174
ctx context.Context , knownStores map [roachpb.StoreID ]struct {},
179
175
) (isLeaseholder bool , shouldBeSkipped bool , msg mmaprototype.RangeMsg ) {
0 commit comments