فهرست منبع

lease: delete items when the lease is revoked.

Add minimum KV interface and implmement the deleting mechanism for
revoking lease.
Xiang Li 10 سال پیش
والد
کامیت
bf3bc0ed6b
2فایلهای تغییر یافته به همراه52 افزوده شده و 7 حذف شده
  1. 21 3
      lease/lessor.go
  2. 31 4
      lease/lessor_test.go

+ 21 - 3
lease/lessor.go

@@ -26,6 +26,15 @@ var (
 	minLeaseTerm = 5 * time.Second
 )
 
+// DeleteableRange defines an interface with DeleteRange method.
+// We define this interface only for lessor to limit the number
+// of methods of storage.KV to what lessor actually needs.
+//
+// Having a minimum interface makes testing easy.
+type DeleteableRange interface {
+	DeleteRange(key, end []byte) (int64, int64)
+}
+
 // a lessor is the owner of leases. It can grant, revoke,
 // renew and modify leases for lessee.
 // TODO: persist lease on to stable backend for failure recovery.
@@ -40,12 +49,18 @@ type lessor struct {
 	// FindExpired and Renew should be the most frequent operations.
 	leaseMap map[uint64]*lease
 
+	// A DeleteableRange the lessor operates on.
+	// When a lease expires, the lessor will delete the
+	// leased range (or key) from the DeleteableRange.
+	dr DeleteableRange
+
 	idgen *idutil.Generator
 }
 
-func NewLessor(lessorID uint8) *lessor {
+func NewLessor(lessorID uint8, dr DeleteableRange) *lessor {
 	return &lessor{
 		leaseMap: make(map[uint64]*lease),
+		dr:       dr,
 		idgen:    idutil.NewGenerator(lessorID, time.Now()),
 	}
 }
@@ -62,7 +77,7 @@ func (le *lessor) Grant(expiry time.Time) *lease {
 	le.mu.Lock()
 	defer le.mu.Unlock()
 
-	l := &lease{id: id, expiry: expiry}
+	l := &lease{id: id, expiry: expiry, itemSet: make(map[leaseItem]struct{})}
 	if _, ok := le.leaseMap[id]; ok {
 		panic("lease: unexpected duplicate ID!")
 	}
@@ -85,7 +100,10 @@ func (le *lessor) Revoke(id uint64) error {
 
 	delete(le.leaseMap, l.id)
 
-	// TODO: remove attached items
+	for item := range l.itemSet {
+		le.dr.DeleteRange([]byte(item.key), []byte(item.endRange))
+	}
+
 	return nil
 }
 

+ 31 - 4
lease/lessor_test.go

@@ -24,7 +24,7 @@ import (
 // The granted lease should have a unique ID with a term
 // that is greater than minLeaseTerm.
 func TestLessorGrant(t *testing.T) {
-	le := NewLessor(1)
+	le := NewLessor(1, &fakeDeleteable{})
 
 	l := le.Grant(time.Now().Add(time.Second))
 	gl := le.get(l.id)
@@ -43,15 +43,28 @@ func TestLessorGrant(t *testing.T) {
 }
 
 // TestLessorRevoke ensures Lessor can revoke a lease.
+// The items in the revoked lease should be removed from
+// the DeleteableKV.
 // The revoked lease cannot be got from Lessor again.
 func TestLessorRevoke(t *testing.T) {
-	le := NewLessor(1)
+	fd := &fakeDeleteable{}
+	le := NewLessor(1, fd)
 
 	// grant a lease with long term (100 seconds) to
 	// avoid early termination during the test.
 	l := le.Grant(time.Now().Add(100 * time.Second))
 
-	err := le.Revoke(l.id)
+	items := []leaseItem{
+		{"foo", ""},
+		{"bar", "zar"},
+	}
+
+	err := le.Attach(l.id, items)
+	if err != nil {
+		t.Fatalf("failed to attach items to the lease: %v", err)
+	}
+
+	err = le.Revoke(l.id)
 	if err != nil {
 		t.Fatal("failed to revoke lease:", err)
 	}
@@ -59,11 +72,16 @@ func TestLessorRevoke(t *testing.T) {
 	if le.get(l.id) != nil {
 		t.Errorf("got revoked lease %x", l.id)
 	}
+
+	wdeleted := []string{"foo_", "bar_zar"}
+	if !reflect.DeepEqual(fd.deleted, wdeleted) {
+		t.Errorf("deleted= %v, want %v", fd.deleted, wdeleted)
+	}
 }
 
 // TestLessorRenew ensures Lessor can renew an existing lease.
 func TestLessorRenew(t *testing.T) {
-	le := NewLessor(1)
+	le := NewLessor(1, &fakeDeleteable{})
 	l := le.Grant(time.Now().Add(5 * time.Second))
 
 	le.Renew(l.id, time.Now().Add(100*time.Second))
@@ -73,3 +91,12 @@ func TestLessorRenew(t *testing.T) {
 		t.Errorf("failed to renew the lease for 100 seconds")
 	}
 }
+
+type fakeDeleteable struct {
+	deleted []string
+}
+
+func (fd *fakeDeleteable) DeleteRange(key, end []byte) (int64, int64) {
+	fd.deleted = append(fd.deleted, string(key)+"_"+string(end))
+	return 0, 0
+}