@@ -27,7 +27,6 @@ import (
2727
2828 "google.golang.org/grpc/grpclog"
2929 "google.golang.org/grpc/internal/backoff"
30- "google.golang.org/grpc/status"
3130)
3231
3332// Key represents the cache key used to uniquely identify a cache entry.
@@ -44,9 +43,9 @@ type Key struct {
4443// Entry wraps all the data to be stored in a cache entry.
4544type Entry struct {
4645 // Mu synchronizes access to this particular cache entry. The LB policy
47- // will also hold another mutex to synchornize access to the cache as a
46+ // will also hold another mutex to synchronize access to the cache as a
4847 // whole. To avoid holding the top-level mutex for the whole duration for
49- // which one particular cache entry is acted up , we use this entry mutex.
48+ // which one particular cache entry is acted upon , we use this entry mutex.
5049 Mu sync.Mutex
5150 // ExpiryTime is the absolute time at which the data cached as part of this
5251 // entry stops being valid. When an RLS request succeeds, this is set to
@@ -74,9 +73,10 @@ type Entry struct {
7473 // new entry added to the cache is not evicted before the RLS response
7574 // arrives (usually when the cache is too small).
7675 EarliestEvictTime time.Time
77- // CallStatus stores the RPC status of the previous RLS request. Picks for
78- // entries with a non-OK status are failed with the error stored here.
79- CallStatus * status.Status
76+ // CallStatus stores the RPC status of the previous RLS request for this
77+ // entry. Picks for entries with a non-nil value for this field are failed
78+ // with the error stored here.
79+ CallStatus error
8080 // Backoff contains all backoff related state. When an RLS request
8181 // succeeds, backoff state is reset.
8282 Backoff * BackoffState
@@ -85,6 +85,16 @@ type Entry struct {
8585 HeaderData string
8686 // TODO(easwars): Add support to store the ChildPolicy here. Need a
8787 // balancerWrapper type to be implemented for this.
88+
89+ // size stores the size of this cache entry. Uses only a subset of the
90+ // fields. See `entrySize` for this is computed.
91+ size int
92+ // key contains the cache key corresponding to this entry. This is required
93+ // from methods like `removeElement` which only have a pointer to the
94+ // list.Element which contains a reference to the cache.Entry. But these
95+ // methods need the cache.Key to be able to remove the entry from the
96+ // underlying map.
97+ key Key
8898}
8999
90100// BackoffState wraps all backoff related state associated with a cache entry.
@@ -104,15 +114,6 @@ type BackoffState struct {
104114 Callback func ()
105115}
106116
107- // lruEntry is the actual entry which is stored in the LRU cache. It requires
108- // the key (in addition to the actual entry) as well, since the onEvicted
109- // callback and expiry timer would need the key to perform their job.
110- type lruEntry struct {
111- key Key
112- val * Entry
113- size int
114- }
115-
116117// LRU is a cache with a least recently used eviction policy.
117118//
118119// It is not safe for concurrent access. The RLS LB policy will provide a mutex
@@ -160,6 +161,7 @@ func entrySize(key Key, value *Entry) int {
160161// removeToFit removes older entries from the cache to make room for a new
161162// entry of size newSize.
162163func (lru * LRU ) removeToFit (newSize int ) {
164+ now := time .Now ()
163165 for lru .usedSize + newSize > lru .maxSize {
164166 elem := lru .ll .Back ()
165167 if elem == nil {
@@ -169,15 +171,15 @@ func (lru *LRU) removeToFit(newSize int) {
169171 return
170172 }
171173
172- entry := elem .Value .(* lruEntry ). val
173- if t := entry .EarliestEvictTime ; ! t .IsZero () && t .Before (time . Now () ) {
174+ entry := elem .Value .(* Entry )
175+ if t := entry .EarliestEvictTime ; ! t .IsZero () && t .Before (now ) {
174176 // When the oldest entry is too new (it hasn't even spent a default
175177 // minimum amount of time in the cache), we abort and allow the
176178 // cache to grow bigger than the configured maxSize.
177179 grpclog .Info ("rls: LRU eviction finds oldest entry to be too new. Allowing cache to exceed maxSize momentarily" )
178180 return
179181 }
180- lru .removeOldest ( )
182+ lru .removeElement ( elem )
181183 }
182184}
183185
@@ -188,16 +190,18 @@ func (lru *LRU) Add(key Key, value *Entry) {
188190 if ! ok {
189191 lru .removeToFit (size )
190192 lru .usedSize += size
191- elem := lru .ll .PushFront (& lruEntry {key , value , size })
193+ value .size = size
194+ value .key = key
195+ elem := lru .ll .PushFront (value )
192196 lru .cache [key ] = elem
193197 return
194198 }
195199
196- lruE := elem .Value .(* lruEntry )
197- sizeDiff := size - lruE .size
200+ existing := elem .Value .(* Entry )
201+ sizeDiff := size - existing .size
198202 lru .removeToFit (sizeDiff )
199- lruE . val = value
200- lruE . size = size
203+ value . size = size
204+ elem . Value = value
201205 lru .ll .MoveToFront (elem )
202206 lru .usedSize += sizeDiff
203207}
@@ -209,20 +213,13 @@ func (lru *LRU) Remove(key Key) {
209213 }
210214}
211215
212- func (lru * LRU ) removeOldest () {
213- elem := lru .ll .Back ()
214- if elem != nil {
215- lru .removeElement (elem )
216- }
217- }
218-
219216func (lru * LRU ) removeElement (e * list.Element ) {
220- lruE := e .Value .(* lruEntry )
217+ entry := e .Value .(* Entry )
221218 lru .ll .Remove (e )
222- delete (lru .cache , lruE .key )
223- lru .usedSize -= lruE .size
219+ delete (lru .cache , entry .key )
220+ lru .usedSize -= entry .size
224221 if lru .onEvicted != nil {
225- lru .onEvicted (lruE .key , lruE . val )
222+ lru .onEvicted (entry .key , entry )
226223 }
227224}
228225
@@ -233,5 +230,5 @@ func (lru *LRU) Get(key Key) *Entry {
233230 return nil
234231 }
235232 lru .ll .MoveToFront (elem )
236- return elem .Value .(* lruEntry ). val
233+ return elem .Value .(* Entry )
237234}
0 commit comments