Plumb disabling caches through the policy store

This commit is contained in:
Jeff Mitchell
2016-04-21 13:52:42 +00:00
parent e2091c34e7
commit b18854be70
6 changed files with 70 additions and 21 deletions

View File

@@ -26,6 +26,10 @@ type SystemView interface {
// when the stored CRL will be removed during the unmounting process // when the stored CRL will be removed during the unmounting process
// anyways), we can ignore the errors to allow unmounting to complete. // anyways), we can ignore the errors to allow unmounting to complete.
Tainted() bool Tainted() bool
// Returns true if caching is disabled. If true, no caches should be used,
// despite known slowdowns.
CacheDisabled() bool
} }
type StaticSystemView struct { type StaticSystemView struct {
@@ -33,6 +37,7 @@ type StaticSystemView struct {
MaxLeaseTTLVal time.Duration MaxLeaseTTLVal time.Duration
SudoPrivilegeVal bool SudoPrivilegeVal bool
TaintedVal bool TaintedVal bool
CacheDisabledVal bool
} }
func (d StaticSystemView) DefaultLeaseTTL() time.Duration { func (d StaticSystemView) DefaultLeaseTTL() time.Duration {
@@ -50,3 +55,7 @@ func (d StaticSystemView) SudoPrivilege(path string, token string) bool {
func (d StaticSystemView) Tainted() bool { func (d StaticSystemView) Tainted() bool {
return d.TaintedVal return d.TaintedVal
} }
func (d StaticSystemView) CacheDisabled() bool {
return d.CacheDisabledVal
}

View File

@@ -218,6 +218,9 @@ type Core struct {
maxLeaseTTL time.Duration maxLeaseTTL time.Duration
logger *log.Logger logger *log.Logger
// cacheDisabled indicates whether caches are disabled
cacheDisabled bool
} }
// CoreConfig is used to parameterize a core // CoreConfig is used to parameterize a core
@@ -315,6 +318,7 @@ func NewCore(conf *CoreConfig) (*Core, error) {
logger: conf.Logger, logger: conf.Logger,
defaultLeaseTTL: conf.DefaultLeaseTTL, defaultLeaseTTL: conf.DefaultLeaseTTL,
maxLeaseTTL: conf.MaxLeaseTTL, maxLeaseTTL: conf.MaxLeaseTTL,
cacheDisabled: conf.DisableCache,
} }
// Setup the backends // Setup the backends

View File

@@ -69,3 +69,8 @@ func (d dynamicSystemView) fetchTTLs() (def, max time.Duration) {
func (d dynamicSystemView) Tainted() bool { func (d dynamicSystemView) Tainted() bool {
return d.mountEntry.Tainted return d.mountEntry.Tainted
} }
// CacheDisabled indicates whether to use caching behavior
func (d dynamicSystemView) CacheDisabled() bool {
return d.core.cacheDisabled
}

View File

@@ -24,6 +24,7 @@ const (
type PolicyStore struct { type PolicyStore struct {
view *BarrierView view *BarrierView
lru *lru.TwoQueueCache lru *lru.TwoQueueCache
system logical.SystemView
} }
// PolicyEntry is used to store a policy by name // PolicyEntry is used to store a policy by name
@@ -34,12 +35,16 @@ type PolicyEntry struct {
// NewPolicyStore creates a new PolicyStore that is backed // NewPolicyStore creates a new PolicyStore that is backed
// using a given view. It used used to durable store and manage named policy. // using a given view. It used used to durable store and manage named policy.
func NewPolicyStore(view *BarrierView) *PolicyStore { func NewPolicyStore(view *BarrierView, system logical.SystemView) *PolicyStore {
cache, _ := lru.New2Q(policyCacheSize)
p := &PolicyStore{ p := &PolicyStore{
view: view, view: view,
lru: cache, system: system,
} }
if !system.CacheDisabled() {
cache, _ := lru.New2Q(policyCacheSize)
p.lru = cache
}
return p return p
} }
@@ -50,7 +55,7 @@ func (c *Core) setupPolicyStore() error {
view := c.systemBarrierView.SubView(policySubPath) view := c.systemBarrierView.SubView(policySubPath)
// Create the policy store // Create the policy store
c.policyStore = NewPolicyStore(view) c.policyStore = NewPolicyStore(view, &dynamicSystemView{core: c})
// Ensure that the default policy exists, and if not, create it // Ensure that the default policy exists, and if not, create it
policy, err := c.policyStore.GetPolicy("default") policy, err := c.policyStore.GetPolicy("default")
@@ -95,23 +100,29 @@ func (ps *PolicyStore) SetPolicy(p *Policy) error {
return fmt.Errorf("failed to persist policy: %v", err) return fmt.Errorf("failed to persist policy: %v", err)
} }
if !ps.system.CacheDisabled() {
// Update the LRU cache // Update the LRU cache
ps.lru.Add(p.Name, p) ps.lru.Add(p.Name, p)
}
return nil return nil
} }
// GetPolicy is used to fetch the named policy // GetPolicy is used to fetch the named policy
func (ps *PolicyStore) GetPolicy(name string) (*Policy, error) { func (ps *PolicyStore) GetPolicy(name string) (*Policy, error) {
defer metrics.MeasureSince([]string{"policy", "get_policy"}, time.Now()) defer metrics.MeasureSince([]string{"policy", "get_policy"}, time.Now())
if !ps.system.CacheDisabled() {
// Check for cached policy // Check for cached policy
if raw, ok := ps.lru.Get(name); ok { if raw, ok := ps.lru.Get(name); ok {
return raw.(*Policy), nil return raw.(*Policy), nil
} }
}
// Special case the root policy // Special case the root policy
if name == "root" { if name == "root" {
p := &Policy{Name: "root"} p := &Policy{Name: "root"}
if !ps.system.CacheDisabled() {
ps.lru.Add(p.Name, p) ps.lru.Add(p.Name, p)
}
return p, nil return p, nil
} }
@@ -152,8 +163,11 @@ func (ps *PolicyStore) GetPolicy(name string) (*Policy, error) {
policy = p policy = p
} }
if !ps.system.CacheDisabled() {
// Update the LRU cache // Update the LRU cache
ps.lru.Add(name, policy) ps.lru.Add(name, policy)
}
return policy, nil return policy, nil
} }
@@ -178,8 +192,10 @@ func (ps *PolicyStore) DeletePolicy(name string) error {
return fmt.Errorf("failed to delete policy: %v", err) return fmt.Errorf("failed to delete policy: %v", err)
} }
if !ps.system.CacheDisabled() {
// Clear the cache // Clear the cache
ps.lru.Remove(name) ps.lru.Remove(name)
}
return nil return nil
} }

View File

@@ -10,7 +10,16 @@ import (
func mockPolicyStore(t *testing.T) *PolicyStore { func mockPolicyStore(t *testing.T) *PolicyStore {
_, barrier, _ := mockBarrier(t) _, barrier, _ := mockBarrier(t)
view := NewBarrierView(barrier, "foo/") view := NewBarrierView(barrier, "foo/")
p := NewPolicyStore(view) p := NewPolicyStore(view, logical.TestSystemView())
return p
}
func mockPolicyStoreNoCache(t *testing.T) *PolicyStore {
sysView := logical.TestSystemView()
sysView.CacheDisabledVal = true
_, barrier, _ := mockBarrier(t)
view := NewBarrierView(barrier, "foo/")
p := NewPolicyStore(view, sysView)
return p return p
} }
@@ -44,7 +53,13 @@ func TestPolicyStore_Root(t *testing.T) {
func TestPolicyStore_CRUD(t *testing.T) { func TestPolicyStore_CRUD(t *testing.T) {
ps := mockPolicyStore(t) ps := mockPolicyStore(t)
testPolicyStore_CRUD(t, ps)
ps = mockPolicyStoreNoCache(t)
testPolicyStore_CRUD(t, ps)
}
func testPolicyStore_CRUD(t *testing.T, ps *PolicyStore) {
// Get should return nothing // Get should return nothing
p, err := ps.GetPolicy("dev") p, err := ps.GetPolicy("dev")
if err != nil { if err != nil {

View File

@@ -50,9 +50,9 @@ sending a SIGHUP to the server process. These are denoted below.
"tcp" is currently the only option available. A full reference for the "tcp" is currently the only option available. A full reference for the
inner syntax is below. inner syntax is below.
* `disable_cache` (optional) - A boolean. If true, this will disable the * `disable_cache` (optional) - A boolean. If true, this will disable all caches
read cache used by the physical storage subsystem. This will very within Vault, including the read cache used by the physical storage
significantly impact performance. subsystem. This will very significantly impact performance.
* `disable_mlock` (optional) - A boolean. If true, this will disable the * `disable_mlock` (optional) - A boolean. If true, this will disable the
server from executing the `mlock` syscall to prevent memory from being server from executing the `mlock` syscall to prevent memory from being