Skip to content

Commit 28ccadf

Browse files
authored
Merge pull request #18569 from lucasrod16/18538-backport-3.4
Backport TestLessorRenewExtendPileup race condition fix for release-3.4
2 parents 728e3c2 + 0621622 commit 28ccadf

File tree

2 files changed

+23
-15
lines changed

2 files changed

+23
-15
lines changed

lease/lessor.go

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ var (
4545

4646
leaseBucketName = []byte("lease")
4747

48-
// maximum number of leases to revoke per second; configurable for tests
49-
leaseRevokeRate = 1000
48+
// default number of leases to revoke per second; configurable for tests
49+
defaultLeaseRevokeRate = 1000
5050

5151
// maximum number of lease checkpoints recorded to the consensus log per second; configurable for tests
5252
leaseCheckpointRate = 1000
@@ -173,6 +173,9 @@ type lessor struct {
173173
// requests for shorter TTLs are extended to the minimum TTL.
174174
minLeaseTTL int64
175175

176+
// maximum number of leases to revoke per second
177+
leaseRevokeRate int
178+
176179
expiredC chan []*Lease
177180
// stopC is a channel whose closure indicates that the lessor should be stopped.
178181
stopC chan struct{}
@@ -201,6 +204,8 @@ type LessorConfig struct {
201204
CheckpointInterval time.Duration
202205
ExpiredLeasesRetryInterval time.Duration
203206
CheckpointPersist bool
207+
208+
leaseRevokeRate int
204209
}
205210

206211
func NewLessor(lg *zap.Logger, b backend.Backend, cluster cluster, cfg LessorConfig) Lessor {
@@ -210,19 +215,24 @@ func NewLessor(lg *zap.Logger, b backend.Backend, cluster cluster, cfg LessorCon
210215
func newLessor(lg *zap.Logger, b backend.Backend, cluster cluster, cfg LessorConfig) *lessor {
211216
checkpointInterval := cfg.CheckpointInterval
212217
expiredLeaseRetryInterval := cfg.ExpiredLeasesRetryInterval
218+
leaseRevokeRate := cfg.leaseRevokeRate
213219
if checkpointInterval == 0 {
214220
checkpointInterval = defaultLeaseCheckpointInterval
215221
}
216222
if expiredLeaseRetryInterval == 0 {
217223
expiredLeaseRetryInterval = defaultExpiredleaseRetryInterval
218224
}
225+
if leaseRevokeRate == 0 {
226+
leaseRevokeRate = defaultLeaseRevokeRate
227+
}
219228
l := &lessor{
220229
leaseMap: make(map[LeaseID]*Lease),
221230
itemMap: make(map[LeaseItem]LeaseID),
222231
leaseExpiredNotifier: newLeaseExpiredNotifier(),
223232
leaseCheckpointHeap: make(LeaseQueue, 0),
224233
b: b,
225234
minLeaseTTL: cfg.MinLeaseTTL,
235+
leaseRevokeRate: leaseRevokeRate,
226236
checkpointInterval: checkpointInterval,
227237
expiredLeaseRetryInterval: expiredLeaseRetryInterval,
228238
checkpointPersist: cfg.CheckpointPersist,
@@ -475,7 +485,7 @@ func (le *lessor) Promote(extend time.Duration) {
475485
le.scheduleCheckpointIfNeeded(l)
476486
}
477487

478-
if len(le.leaseMap) < leaseRevokeRate {
488+
if len(le.leaseMap) < le.leaseRevokeRate {
479489
// no possibility of lease pile-up
480490
return
481491
}
@@ -489,7 +499,7 @@ func (le *lessor) Promote(extend time.Duration) {
489499
expires := 0
490500
// have fewer expires than the total revoke rate so piled up leases
491501
// don't consume the entire revoke limit
492-
targetExpiresPerSecond := (3 * leaseRevokeRate) / 4
502+
targetExpiresPerSecond := (3 * le.leaseRevokeRate) / 4
493503
for _, l := range leases {
494504
remaining := l.Remaining()
495505
if remaining > nextWindow {
@@ -628,7 +638,7 @@ func (le *lessor) revokeExpiredLeases() {
628638
var ls []*Lease
629639

630640
// rate limit
631-
revokeLimit := leaseRevokeRate / 2
641+
revokeLimit := le.leaseRevokeRate / 2
632642

633643
le.mu.RLock()
634644
if le.isPrimary() {

lease/lessor_test.go

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -289,17 +289,15 @@ func TestLessorRenewWithCheckpointer(t *testing.T) {
289289
// TestLessorRenewExtendPileup ensures Lessor extends leases on promotion if too many
290290
// expire at the same time.
291291
func TestLessorRenewExtendPileup(t *testing.T) {
292-
oldRevokeRate := leaseRevokeRate
293-
defer func() { leaseRevokeRate = oldRevokeRate }()
292+
leaseRevokeRate := 10
294293
lg := zap.NewNop()
295-
leaseRevokeRate = 10
296294

297295
dir, be := NewTestBackend(t)
298296
defer os.RemoveAll(dir)
299297

300-
le := newLessor(lg, be, clusterV3_6(), LessorConfig{MinLeaseTTL: minLeaseTTL})
298+
le := newLessor(lg, be, clusterV3_6(), LessorConfig{MinLeaseTTL: minLeaseTTL, leaseRevokeRate: leaseRevokeRate})
301299
ttl := int64(10)
302-
for i := 1; i <= leaseRevokeRate*10; i++ {
300+
for i := 1; i <= le.leaseRevokeRate*10; i++ {
303301
if _, err := le.Grant(LeaseID(2*i), ttl); err != nil {
304302
t.Fatal(err)
305303
}
@@ -316,7 +314,7 @@ func TestLessorRenewExtendPileup(t *testing.T) {
316314
bcfg.Path = filepath.Join(dir, "be")
317315
be = backend.New(bcfg)
318316
defer be.Close()
319-
le = newLessor(lg, be, clusterV3_6(), LessorConfig{MinLeaseTTL: minLeaseTTL})
317+
le = newLessor(lg, be, clusterV3_6(), LessorConfig{MinLeaseTTL: minLeaseTTL, leaseRevokeRate: leaseRevokeRate})
320318
defer le.Stop()
321319

322320
// extend after recovery should extend expiration on lease pile-up
@@ -331,11 +329,11 @@ func TestLessorRenewExtendPileup(t *testing.T) {
331329

332330
for i := ttl; i < ttl+20; i++ {
333331
c := windowCounts[i]
334-
if c > leaseRevokeRate {
335-
t.Errorf("expected at most %d expiring at %ds, got %d", leaseRevokeRate, i, c)
332+
if c > le.leaseRevokeRate {
333+
t.Errorf("expected at most %d expiring at %ds, got %d", le.leaseRevokeRate, i, c)
336334
}
337-
if c < leaseRevokeRate/2 {
338-
t.Errorf("expected at least %d expiring at %ds, got %d", leaseRevokeRate/2, i, c)
335+
if c < le.leaseRevokeRate/2 {
336+
t.Errorf("expected at least %d expiring at %ds, got %d", le.leaseRevokeRate/2, i, c)
339337
}
340338
}
341339
}

0 commit comments

Comments
 (0)