acl: Adding additional tier of caching
This commit is contained in:
parent
db8f896c58
commit
bee6e4e559
45
acl/cache.go
45
acl/cache.go
|
@ -19,10 +19,11 @@ type aclEntry struct {
|
||||||
|
|
||||||
// Cache is used to implement policy and ACL caching
|
// Cache is used to implement policy and ACL caching
|
||||||
type Cache struct {
|
type Cache struct {
|
||||||
aclCache *lru.Cache
|
aclCache *lru.Cache // Cache id -> acl
|
||||||
faultfn FaultFunc
|
faultfn FaultFunc
|
||||||
parent ACL
|
parent ACL
|
||||||
policyCache *lru.Cache
|
policyCache *lru.Cache // Cache policy -> acl
|
||||||
|
ruleCache *lru.Cache // Cache rules -> policy
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCache contructs a new policy and ACL cache of a given size
|
// NewCache contructs a new policy and ACL cache of a given size
|
||||||
|
@ -30,6 +31,7 @@ func NewCache(size int, parent ACL, faultfn FaultFunc) (*Cache, error) {
|
||||||
if size <= 0 {
|
if size <= 0 {
|
||||||
return nil, fmt.Errorf("Must provide positive cache size")
|
return nil, fmt.Errorf("Must provide positive cache size")
|
||||||
}
|
}
|
||||||
|
rc, _ := lru.New(size)
|
||||||
pc, _ := lru.New(size)
|
pc, _ := lru.New(size)
|
||||||
ac, _ := lru.New(size)
|
ac, _ := lru.New(size)
|
||||||
c := &Cache{
|
c := &Cache{
|
||||||
|
@ -37,6 +39,7 @@ func NewCache(size int, parent ACL, faultfn FaultFunc) (*Cache, error) {
|
||||||
faultfn: faultfn,
|
faultfn: faultfn,
|
||||||
parent: parent,
|
parent: parent,
|
||||||
policyCache: pc,
|
policyCache: pc,
|
||||||
|
ruleCache: rc,
|
||||||
}
|
}
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
@ -50,7 +53,7 @@ func (c *Cache) GetPolicy(rules string) (*Policy, error) {
|
||||||
// getPolicy is an internal method to get a cached policy,
|
// getPolicy is an internal method to get a cached policy,
|
||||||
// but it assumes a pre-computed ID
|
// but it assumes a pre-computed ID
|
||||||
func (c *Cache) getPolicy(id, rules string) (*Policy, error) {
|
func (c *Cache) getPolicy(id, rules string) (*Policy, error) {
|
||||||
raw, ok := c.policyCache.Get(id)
|
raw, ok := c.ruleCache.Get(id)
|
||||||
if ok {
|
if ok {
|
||||||
return raw.(*Policy), nil
|
return raw.(*Policy), nil
|
||||||
}
|
}
|
||||||
|
@ -59,7 +62,7 @@ func (c *Cache) getPolicy(id, rules string) (*Policy, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
policy.ID = id
|
policy.ID = id
|
||||||
c.policyCache.Add(id, policy)
|
c.ruleCache.Add(id, policy)
|
||||||
return policy, nil
|
return policy, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -75,7 +78,7 @@ func (c *Cache) GetACLPolicy(id string) (*Policy, error) {
|
||||||
// Check for a cached acl
|
// Check for a cached acl
|
||||||
if raw, ok := c.aclCache.Get(id); ok {
|
if raw, ok := c.aclCache.Get(id); ok {
|
||||||
cached := raw.(aclEntry)
|
cached := raw.(aclEntry)
|
||||||
if raw, ok := c.policyCache.Get(cached.PolicyID); ok {
|
if raw, ok := c.ruleCache.Get(cached.PolicyID); ok {
|
||||||
return raw.(*Policy), nil
|
return raw.(*Policy), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,21 +109,31 @@ func (c *Cache) GetACL(id string) (ACL, error) {
|
||||||
}
|
}
|
||||||
ruleID := c.ruleID(rules)
|
ruleID := c.ruleID(rules)
|
||||||
|
|
||||||
// Get the policy
|
// Check for a compiled ACL
|
||||||
policy, err := c.getPolicy(ruleID, rules)
|
var compiled ACL
|
||||||
if err != nil {
|
if raw, ok := c.policyCache.Get(ruleID); ok {
|
||||||
return nil, err
|
compiled = raw.(ACL)
|
||||||
}
|
} else {
|
||||||
|
// Get the policy
|
||||||
|
policy, err := c.getPolicy(ruleID, rules)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// Get the ACL
|
// Compile the ACL
|
||||||
acl, err := New(c.parent, policy)
|
acl, err := New(c.parent, policy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache the compiled ACL
|
||||||
|
c.policyCache.Add(ruleID, acl)
|
||||||
|
compiled = acl
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache and return the ACL
|
// Cache and return the ACL
|
||||||
c.aclCache.Add(id, aclEntry{acl, ruleID})
|
c.aclCache.Add(id, aclEntry{compiled, ruleID})
|
||||||
return acl, nil
|
return compiled, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearACL is used to clear the ACL cache if any
|
// ClearACL is used to clear the ACL cache if any
|
||||||
|
|
|
@ -43,7 +43,7 @@ func TestCache_GetPolicy(t *testing.T) {
|
||||||
func TestCache_GetACL(t *testing.T) {
|
func TestCache_GetACL(t *testing.T) {
|
||||||
policies := map[string]string{
|
policies := map[string]string{
|
||||||
"foo": testSimplePolicy,
|
"foo": testSimplePolicy,
|
||||||
"bar": testSimplePolicy,
|
"bar": testSimplePolicy2,
|
||||||
}
|
}
|
||||||
faultfn := func(id string) (string, error) {
|
faultfn := func(id string) (string, error) {
|
||||||
return policies[id], nil
|
return policies[id], nil
|
||||||
|
@ -113,6 +113,9 @@ func TestCache_ClearACL(t *testing.T) {
|
||||||
// Nuke the cache
|
// Nuke the cache
|
||||||
c.ClearACL("foo")
|
c.ClearACL("foo")
|
||||||
|
|
||||||
|
// Clear the policy cache
|
||||||
|
c.policyCache.Remove(c.ruleID(testSimplePolicy))
|
||||||
|
|
||||||
acl2, err := c.GetACL("foo")
|
acl2, err := c.GetACL("foo")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
|
@ -170,3 +173,9 @@ key "foo/" {
|
||||||
policy = "read"
|
policy = "read"
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
var testSimplePolicy2 = `
|
||||||
|
key "bar/" {
|
||||||
|
policy = "read"
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
Loading…
Reference in New Issue