github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/worker/uniter/runner/context/cache.go (about) 1 // Copyright 2012-2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package context 5 6 import ( 7 "sort" 8 9 "github.com/juju/juju/apiserver/params" 10 ) 11 12 // SettingsFunc returns the relation settings for a unit. 13 type SettingsFunc func(unitName string) (params.Settings, error) 14 15 // SettingsMap is a map from unit name to relation settings. 16 type SettingsMap map[string]params.Settings 17 18 // RelationCache stores a relation's remote unit membership and settings. 19 // Member settings are stored until invalidated or removed by name; settings 20 // of non-member units are stored only until the cache is pruned. 21 type RelationCache struct { 22 // readSettings is used to get settings data if when not already present. 23 readSettings SettingsFunc 24 // members' keys define the relation's membership; non-nil values hold 25 // cached settings. 26 members SettingsMap 27 // others is a short-term cache for non-member settings. 28 others SettingsMap 29 } 30 31 // NewRelationCache creates a new RelationCache that will use the supplied 32 // SettingsFunc to populate itself on demand. Initial membership is determined 33 // by memberNames. 34 func NewRelationCache(readSettings SettingsFunc, memberNames []string) *RelationCache { 35 cache := &RelationCache{ 36 readSettings: readSettings, 37 } 38 cache.Prune(memberNames) 39 return cache 40 } 41 42 // Prune resets the membership to the supplied list, and discards the settings 43 // of all non-member units. 44 func (cache *RelationCache) Prune(memberNames []string) { 45 newMembers := SettingsMap{} 46 for _, memberName := range memberNames { 47 newMembers[memberName] = cache.members[memberName] 48 } 49 cache.members = newMembers 50 cache.others = SettingsMap{} 51 } 52 53 // MemberNames returns the names of the remote units present in the relation. 54 func (cache *RelationCache) MemberNames() (memberNames []string) { 55 for memberName := range cache.members { 56 memberNames = append(memberNames, memberName) 57 } 58 sort.Strings(memberNames) 59 return memberNames 60 } 61 62 // Settings returns the settings of the named remote unit. It's valid to get 63 // the settings of any unit that has ever been in the relation. 64 func (cache *RelationCache) Settings(unitName string) (params.Settings, error) { 65 settings, isMember := cache.members[unitName] 66 if settings == nil { 67 if !isMember { 68 settings = cache.others[unitName] 69 } 70 if settings == nil { 71 var err error 72 settings, err = cache.readSettings(unitName) 73 if err != nil { 74 return nil, err 75 } 76 } 77 } 78 if isMember { 79 cache.members[unitName] = settings 80 } else { 81 cache.others[unitName] = settings 82 } 83 return settings, nil 84 } 85 86 // InvalidateMember ensures that the named remote unit will be considered a 87 // member of the relation, and that the next attempt to read its settings will 88 // use fresh data. 89 func (cache *RelationCache) InvalidateMember(memberName string) { 90 cache.members[memberName] = nil 91 } 92 93 // RemoveMember ensures that the named remote unit will not be considered a 94 // member of the relation, 95 func (cache *RelationCache) RemoveMember(memberName string) { 96 delete(cache.members, memberName) 97 }