فهرست منبع

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
 	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,
 // a lessor is the owner of leases. It can grant, revoke,
 // renew and modify leases for lessee.
 // renew and modify leases for lessee.
 // TODO: persist lease on to stable backend for failure recovery.
 // 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.
 	// FindExpired and Renew should be the most frequent operations.
 	leaseMap map[uint64]*lease
 	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
 	idgen *idutil.Generator
 }
 }
 
 
-func NewLessor(lessorID uint8) *lessor {
+func NewLessor(lessorID uint8, dr DeleteableRange) *lessor {
 	return &lessor{
 	return &lessor{
 		leaseMap: make(map[uint64]*lease),
 		leaseMap: make(map[uint64]*lease),
+		dr:       dr,
 		idgen:    idutil.NewGenerator(lessorID, time.Now()),
 		idgen:    idutil.NewGenerator(lessorID, time.Now()),
 	}
 	}
 }
 }
@@ -62,7 +77,7 @@ func (le *lessor) Grant(expiry time.Time) *lease {
 	le.mu.Lock()
 	le.mu.Lock()
 	defer le.mu.Unlock()
 	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 {
 	if _, ok := le.leaseMap[id]; ok {
 		panic("lease: unexpected duplicate ID!")
 		panic("lease: unexpected duplicate ID!")
 	}
 	}
@@ -85,7 +100,10 @@ func (le *lessor) Revoke(id uint64) error {
 
 
 	delete(le.leaseMap, l.id)
 	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
 	return nil
 }
 }
 
 

+ 31 - 4
lease/lessor_test.go

@@ -24,7 +24,7 @@ import (
 // The granted lease should have a unique ID with a term
 // The granted lease should have a unique ID with a term
 // that is greater than minLeaseTerm.
 // that is greater than minLeaseTerm.
 func TestLessorGrant(t *testing.T) {
 func TestLessorGrant(t *testing.T) {
-	le := NewLessor(1)
+	le := NewLessor(1, &fakeDeleteable{})
 
 
 	l := le.Grant(time.Now().Add(time.Second))
 	l := le.Grant(time.Now().Add(time.Second))
 	gl := le.get(l.id)
 	gl := le.get(l.id)
@@ -43,15 +43,28 @@ func TestLessorGrant(t *testing.T) {
 }
 }
 
 
 // TestLessorRevoke ensures Lessor can revoke a lease.
 // 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.
 // The revoked lease cannot be got from Lessor again.
 func TestLessorRevoke(t *testing.T) {
 func TestLessorRevoke(t *testing.T) {
-	le := NewLessor(1)
+	fd := &fakeDeleteable{}
+	le := NewLessor(1, fd)
 
 
 	// grant a lease with long term (100 seconds) to
 	// grant a lease with long term (100 seconds) to
 	// avoid early termination during the test.
 	// avoid early termination during the test.
 	l := le.Grant(time.Now().Add(100 * time.Second))
 	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 {
 	if err != nil {
 		t.Fatal("failed to revoke lease:", err)
 		t.Fatal("failed to revoke lease:", err)
 	}
 	}
@@ -59,11 +72,16 @@ func TestLessorRevoke(t *testing.T) {
 	if le.get(l.id) != nil {
 	if le.get(l.id) != nil {
 		t.Errorf("got revoked lease %x", l.id)
 		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.
 // TestLessorRenew ensures Lessor can renew an existing lease.
 func TestLessorRenew(t *testing.T) {
 func TestLessorRenew(t *testing.T) {
-	le := NewLessor(1)
+	le := NewLessor(1, &fakeDeleteable{})
 	l := le.Grant(time.Now().Add(5 * time.Second))
 	l := le.Grant(time.Now().Add(5 * time.Second))
 
 
 	le.Renew(l.id, time.Now().Add(100*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")
 		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
+}