From 0fa059ec49c0eff215c6e78b4d2ffe403926ea44 Mon Sep 17 00:00:00 2001 From: James Phillips Date: Tue, 9 Aug 2016 11:00:22 -0700 Subject: [PATCH] Switches all ACL caches to 2Q. --- acl/cache.go | 25 +++++++++++++++++++------ acl/cache_test.go | 44 +++++++++++++++++++++++++++++++++++++------- consul/acl.go | 10 +++++----- 3 files changed, 61 insertions(+), 18 deletions(-) diff --git a/acl/cache.go b/acl/cache.go index 0debd1d20..0387f9fbe 100644 --- a/acl/cache.go +++ b/acl/cache.go @@ -21,9 +21,9 @@ type aclEntry struct { // Cache is used to implement policy and ACL caching type Cache struct { faultfn FaultFunc - aclCache *lru.Cache // Cache id -> acl - policyCache *lru.Cache // Cache policy -> acl - ruleCache *lru.Cache // Cache rules -> policy + aclCache *lru.TwoQueueCache // Cache id -> acl + policyCache *lru.TwoQueueCache // Cache policy -> acl + ruleCache *lru.TwoQueueCache // Cache rules -> policy } // NewCache constructs a new policy and ACL cache of a given size @@ -31,9 +31,22 @@ func NewCache(size int, faultfn FaultFunc) (*Cache, error) { if size <= 0 { return nil, fmt.Errorf("Must provide positive cache size") } - rc, _ := lru.New(size) - pc, _ := lru.New(size) - ac, _ := lru.New(size) + + rc, err := lru.New2Q(size) + if err != nil { + return nil, err + } + + pc, err := lru.New2Q(size) + if err != nil { + return nil, err + } + + ac, err := lru.New2Q(size) + if err != nil { + return nil, err + } + c := &Cache{ faultfn: faultfn, aclCache: ac, diff --git a/acl/cache_test.go b/acl/cache_test.go index f880bcaf4..d144b0009 100644 --- a/acl/cache_test.go +++ b/acl/cache_test.go @@ -5,7 +5,7 @@ import ( ) func TestCache_GetPolicy(t *testing.T) { - c, err := NewCache(1, nil) + c, err := NewCache(2, nil) if err != nil { t.Fatalf("err: %v", err) } @@ -24,11 +24,23 @@ func TestCache_GetPolicy(t *testing.T) { t.Fatalf("should be cached") } - // Cache a new policy + // Work with some new policies to evict the original one _, err = c.GetPolicy(testSimplePolicy) if err != nil { t.Fatalf("err: %v", err) } + _, err = c.GetPolicy(testSimplePolicy) + if err != nil { + t.Fatalf("err: %v", err) + } + _, err = c.GetPolicy(testSimplePolicy2) + if err != nil { + t.Fatalf("err: %v", err) + } + _, err = c.GetPolicy(testSimplePolicy2) + if err != nil { + t.Fatalf("err: %v", err) + } // Test invalidation of p p3, err := c.GetPolicy("") @@ -44,12 +56,13 @@ func TestCache_GetACL(t *testing.T) { policies := map[string]string{ "foo": testSimplePolicy, "bar": testSimplePolicy2, + "baz": testSimplePolicy3, } faultfn := func(id string) (string, string, error) { return "deny", policies[id], nil } - c, err := NewCache(1, faultfn) + c, err := NewCache(2, faultfn) if err != nil { t.Fatalf("err: %v", err) } @@ -80,6 +93,18 @@ func TestCache_GetACL(t *testing.T) { if err != nil { t.Fatalf("err: %v", err) } + _, err = c.GetACL("bar") + if err != nil { + t.Fatalf("err: %v", err) + } + _, err = c.GetACL("baz") + if err != nil { + t.Fatalf("err: %v", err) + } + _, err = c.GetACL("baz") + if err != nil { + t.Fatalf("err: %v", err) + } acl3, err := c.GetACL("foo") if err != nil { @@ -100,7 +125,7 @@ func TestCache_ClearACL(t *testing.T) { return "deny", policies[id], nil } - c, err := NewCache(1, faultfn) + c, err := NewCache(16, faultfn) if err != nil { t.Fatalf("err: %v", err) } @@ -135,7 +160,7 @@ func TestCache_Purge(t *testing.T) { return "deny", policies[id], nil } - c, err := NewCache(1, faultfn) + c, err := NewCache(16, faultfn) if err != nil { t.Fatalf("err: %v", err) } @@ -167,7 +192,7 @@ func TestCache_GetACLPolicy(t *testing.T) { faultfn := func(id string) (string, string, error) { return "deny", policies[id], nil } - c, err := NewCache(1, faultfn) + c, err := NewCache(16, faultfn) if err != nil { t.Fatalf("err: %v", err) } @@ -220,7 +245,7 @@ func TestCache_GetACL_Parent(t *testing.T) { return "", "", nil } - c, err := NewCache(1, faultfn) + c, err := NewCache(16, faultfn) if err != nil { t.Fatalf("err: %v", err) } @@ -296,3 +321,8 @@ key "bar/" { policy = "read" } ` +var testSimplePolicy3 = ` +key "baz/" { + policy = "read" +} +` diff --git a/consul/acl.go b/consul/acl.go index df8846698..278395f84 100644 --- a/consul/acl.go +++ b/consul/acl.go @@ -112,16 +112,16 @@ func (s *Server) resolveToken(id string) (acl.ACL, error) { // rpcFn is used to make an RPC call to the client or server. type rpcFn func(string, interface{}, interface{}) error -// aclCache is used to cache ACL's and policies. +// aclCache is used to cache ACLs and policies. type aclCache struct { config *Config logger *log.Logger // acls is a non-authoritative ACL cache. - acls *lru.Cache + acls *lru.TwoQueueCache // aclPolicyCache is a non-authoritative policy cache. - policies *lru.Cache + policies *lru.TwoQueueCache // rpc is a function used to talk to the client/server. rpc rpcFn @@ -144,13 +144,13 @@ func newAclCache(conf *Config, logger *log.Logger, rpc rpcFn, local acl.FaultFun } // Initialize the non-authoritative ACL cache - cache.acls, err = lru.New(aclCacheSize) + cache.acls, err = lru.New2Q(aclCacheSize) if err != nil { return nil, fmt.Errorf("Failed to create ACL cache: %v", err) } // Initialize the ACL policy cache - cache.policies, err = lru.New(aclCacheSize) + cache.policies, err = lru.New2Q(aclCacheSize) if err != nil { return nil, fmt.Errorf("Failed to create ACL policy cache: %v", err) }