@@ -21,24 +21,12 @@ import (
21
21
22
22
// AdapterMemory is an adapter implements using memory.
23
23
type AdapterMemory struct {
24
- // cap limits the size of the cache pool.
25
- // If the size of the cache exceeds the cap,
26
- // the cache expiration process performs according to the LRU algorithm.
27
- // It is 0 in default which means no limits.
28
- cap int
29
- data * adapterMemoryData // data is the underlying cache data which is stored in a hash table.
30
- expireTimes * adapterMemoryExpireTimes // expireTimes is the expiring key to its timestamp mapping, which is used for quick indexing and deleting.
31
- expireSets * adapterMemoryExpireSets // expireSets is the expiring timestamp to its key set mapping, which is used for quick indexing and deleting.
32
- lru * adapterMemoryLru // lru is the LRU manager, which is enabled when attribute cap > 0.
33
- lruGetList * glist.List // lruGetList is the LRU history according to Get function.
34
- eventList * glist.List // eventList is the asynchronous event list for internal data synchronization.
35
- closed * gtype.Bool // closed controls the cache closed or not.
36
- }
37
-
38
- // Internal cache item.
39
- type adapterMemoryItem struct {
40
- v interface {} // Value.
41
- e int64 // Expire timestamp in milliseconds.
24
+ data * memoryData // data is the underlying cache data which is stored in a hash table.
25
+ expireTimes * memoryExpireTimes // expireTimes is the expiring key to its timestamp mapping, which is used for quick indexing and deleting.
26
+ expireSets * memoryExpireSets // expireSets is the expiring timestamp to its key set mapping, which is used for quick indexing and deleting.
27
+ lru * memoryLru // lru is the LRU manager, which is enabled when attribute cap > 0.
28
+ eventList * glist.List // eventList is the asynchronous event list for internal data synchronization.
29
+ closed * gtype.Bool // closed controls the cache closed or not.
42
30
}
43
31
44
32
// Internal event item.
@@ -53,21 +41,28 @@ const (
53
41
defaultMaxExpire = 9223372036854
54
42
)
55
43
56
- // NewAdapterMemory creates and returns a new memory cache object.
57
- func NewAdapterMemory (lruCap ... int ) Adapter {
44
+ // NewAdapterMemory creates and returns a new adapter_memory cache object.
45
+ func NewAdapterMemory () * AdapterMemory {
46
+ return doNewAdapterMemory ()
47
+ }
48
+
49
+ // NewAdapterMemoryLru creates and returns a new adapter_memory cache object with LRU.
50
+ func NewAdapterMemoryLru (cap int ) * AdapterMemory {
51
+ c := doNewAdapterMemory ()
52
+ c .lru = newMemoryLru (cap )
53
+ return c
54
+ }
55
+
56
+ // doNewAdapterMemory creates and returns a new adapter_memory cache object.
57
+ func doNewAdapterMemory () * AdapterMemory {
58
58
c := & AdapterMemory {
59
- data : newAdapterMemoryData (),
60
- lruGetList : glist .New (true ),
61
- expireTimes : newAdapterMemoryExpireTimes (),
62
- expireSets : newAdapterMemoryExpireSets (),
59
+ data : newMemoryData (),
60
+ expireTimes : newMemoryExpireTimes (),
61
+ expireSets : newMemoryExpireSets (),
63
62
eventList : glist .New (true ),
64
63
closed : gtype .NewBool (),
65
64
}
66
- if len (lruCap ) > 0 {
67
- c .cap = lruCap [0 ]
68
- c .lru = newMemCacheLru (c )
69
- }
70
- // Here may be a "timer leak" if adapter is manually changed from memory adapter.
65
+ // Here may be a "timer leak" if adapter is manually changed from adapter_memory adapter.
71
66
// Do not worry about this, as adapter is less changed, and it does nothing if it's not used.
72
67
gtimer .AddSingleton (context .Background (), time .Second , c .syncEventAndClearExpired )
73
68
return c
@@ -78,8 +73,9 @@ func NewAdapterMemory(lruCap ...int) Adapter {
78
73
// It does not expire if `duration` == 0.
79
74
// It deletes the keys of `data` if `duration` < 0 or given `value` is nil.
80
75
func (c * AdapterMemory ) Set (ctx context.Context , key interface {}, value interface {}, duration time.Duration ) error {
76
+ defer c .handleLruKey (ctx , key )
81
77
expireTime := c .getInternalExpire (duration )
82
- c .data .Set (key , adapterMemoryItem {
78
+ c .data .Set (key , memoryDataItem {
83
79
v : value ,
84
80
e : expireTime ,
85
81
})
@@ -108,6 +104,11 @@ func (c *AdapterMemory) SetMap(ctx context.Context, data map[interface{}]interfa
108
104
e : expireTime ,
109
105
})
110
106
}
107
+ if c .lru != nil {
108
+ for key := range data {
109
+ c .handleLruKey (ctx , key )
110
+ }
111
+ }
111
112
return nil
112
113
}
113
114
@@ -118,6 +119,7 @@ func (c *AdapterMemory) SetMap(ctx context.Context, data map[interface{}]interfa
118
119
// It does not expire if `duration` == 0.
119
120
// It deletes the `key` if `duration` < 0 or given `value` is nil.
120
121
func (c * AdapterMemory ) SetIfNotExist (ctx context.Context , key interface {}, value interface {}, duration time.Duration ) (bool , error ) {
122
+ defer c .handleLruKey (ctx , key )
121
123
isContained , err := c .Contains (ctx , key )
122
124
if err != nil {
123
125
return false , err
@@ -140,6 +142,7 @@ func (c *AdapterMemory) SetIfNotExist(ctx context.Context, key interface{}, valu
140
142
// It does not expire if `duration` == 0.
141
143
// It deletes the `key` if `duration` < 0 or given `value` is nil.
142
144
func (c * AdapterMemory ) SetIfNotExistFunc (ctx context.Context , key interface {}, f Func , duration time.Duration ) (bool , error ) {
145
+ defer c .handleLruKey (ctx , key )
143
146
isContained , err := c .Contains (ctx , key )
144
147
if err != nil {
145
148
return false , err
@@ -166,6 +169,7 @@ func (c *AdapterMemory) SetIfNotExistFunc(ctx context.Context, key interface{},
166
169
// Note that it differs from function `SetIfNotExistFunc` is that the function `f` is executed within
167
170
// writing mutex lock for concurrent safety purpose.
168
171
func (c * AdapterMemory ) SetIfNotExistFuncLock (ctx context.Context , key interface {}, f Func , duration time.Duration ) (bool , error ) {
172
+ defer c .handleLruKey (ctx , key )
169
173
isContained , err := c .Contains (ctx , key )
170
174
if err != nil {
171
175
return false , err
@@ -185,10 +189,7 @@ func (c *AdapterMemory) SetIfNotExistFuncLock(ctx context.Context, key interface
185
189
func (c * AdapterMemory ) Get (ctx context.Context , key interface {}) (* gvar.Var , error ) {
186
190
item , ok := c .data .Get (key )
187
191
if ok && ! item .IsExpired () {
188
- // Adding to LRU history if LRU feature is enabled.
189
- if c .cap > 0 {
190
- c .lruGetList .PushBack (key )
191
- }
192
+ c .handleLruKey (ctx , key )
192
193
return gvar .New (item .v ), nil
193
194
}
194
195
return nil , nil
@@ -202,6 +203,7 @@ func (c *AdapterMemory) Get(ctx context.Context, key interface{}) (*gvar.Var, er
202
203
// It deletes the `key` if `duration` < 0 or given `value` is nil, but it does nothing
203
204
// if `value` is a function and the function result is nil.
204
205
func (c * AdapterMemory ) GetOrSet (ctx context.Context , key interface {}, value interface {}, duration time.Duration ) (* gvar.Var , error ) {
206
+ defer c .handleLruKey (ctx , key )
205
207
v , err := c .Get (ctx , key )
206
208
if err != nil {
207
209
return nil , err
@@ -220,6 +222,7 @@ func (c *AdapterMemory) GetOrSet(ctx context.Context, key interface{}, value int
220
222
// It deletes the `key` if `duration` < 0 or given `value` is nil, but it does nothing
221
223
// if `value` is a function and the function result is nil.
222
224
func (c * AdapterMemory ) GetOrSetFunc (ctx context.Context , key interface {}, f Func , duration time.Duration ) (* gvar.Var , error ) {
225
+ defer c .handleLruKey (ctx , key )
223
226
v , err := c .Get (ctx , key )
224
227
if err != nil {
225
228
return nil , err
@@ -248,6 +251,7 @@ func (c *AdapterMemory) GetOrSetFunc(ctx context.Context, key interface{}, f Fun
248
251
// Note that it differs from function `GetOrSetFunc` is that the function `f` is executed within
249
252
// writing mutex lock for concurrent safety purpose.
250
253
func (c * AdapterMemory ) GetOrSetFuncLock (ctx context.Context , key interface {}, f Func , duration time.Duration ) (* gvar.Var , error ) {
254
+ defer c .handleLruKey (ctx , key )
251
255
v , err := c .Get (ctx , key )
252
256
if err != nil {
253
257
return nil , err
@@ -274,6 +278,7 @@ func (c *AdapterMemory) Contains(ctx context.Context, key interface{}) (bool, er
274
278
// It returns -1 if the `key` does not exist in the cache.
275
279
func (c * AdapterMemory ) GetExpire (ctx context.Context , key interface {}) (time.Duration , error ) {
276
280
if item , ok := c .data .Get (key ); ok {
281
+ c .handleLruKey (ctx , key )
277
282
return time .Duration (item .e - gtime .TimestampMilli ()) * time .Millisecond , nil
278
283
}
279
284
return - 1 , nil
@@ -282,6 +287,15 @@ func (c *AdapterMemory) GetExpire(ctx context.Context, key interface{}) (time.Du
282
287
// Remove deletes one or more keys from cache, and returns its value.
283
288
// If multiple keys are given, it returns the value of the last deleted item.
284
289
func (c * AdapterMemory ) Remove (ctx context.Context , keys ... interface {}) (* gvar.Var , error ) {
290
+ defer c .lru .Remove (keys ... )
291
+ value , err := c .doRemove (ctx , keys ... )
292
+ if err != nil {
293
+ return nil , err
294
+ }
295
+ return gvar .New (value ), nil
296
+ }
297
+
298
+ func (c * AdapterMemory ) doRemove (_ context.Context , keys ... interface {}) (* gvar.Var , error ) {
285
299
var removedKeys []interface {}
286
300
removedKeys , value , err := c .data .Remove (keys ... )
287
301
if err != nil {
@@ -303,6 +317,9 @@ func (c *AdapterMemory) Remove(ctx context.Context, keys ...interface{}) (*gvar.
303
317
// It does nothing if `key` does not exist in the cache.
304
318
func (c * AdapterMemory ) Update (ctx context.Context , key interface {}, value interface {}) (oldValue * gvar.Var , exist bool , err error ) {
305
319
v , exist , err := c .data .Update (key , value )
320
+ if exist {
321
+ c .handleLruKey (ctx , key )
322
+ }
306
323
return gvar .New (v ), exist , err
307
324
}
308
325
@@ -321,6 +338,7 @@ func (c *AdapterMemory) UpdateExpire(ctx context.Context, key interface{}, durat
321
338
k : key ,
322
339
e : newExpireTime ,
323
340
})
341
+ c .handleLruKey (ctx , key )
324
342
}
325
343
return
326
344
}
@@ -348,14 +366,13 @@ func (c *AdapterMemory) Values(ctx context.Context) ([]interface{}, error) {
348
366
// Clear clears all data of the cache.
349
367
// Note that this function is sensitive and should be carefully used.
350
368
func (c * AdapterMemory ) Clear (ctx context.Context ) error {
351
- return c .data .Clear ()
369
+ c .data .Clear ()
370
+ c .lru .Clear ()
371
+ return nil
352
372
}
353
373
354
374
// Close closes the cache.
355
375
func (c * AdapterMemory ) Close (ctx context.Context ) error {
356
- if c .cap > 0 {
357
- c .lru .Close ()
358
- }
359
376
c .closed .Set (true )
360
377
return nil
361
378
}
@@ -390,9 +407,9 @@ func (c *AdapterMemory) makeExpireKey(expire int64) int64 {
390
407
}
391
408
392
409
// syncEventAndClearExpired does the asynchronous task loop:
393
- // 1. Asynchronously process the data in the event list,
394
- // and synchronize the results to the `expireTimes` and `expireSets` properties.
395
- // 2. Clean up the expired key-value pair data.
410
+ // 1. Asynchronously process the data in the event list,
411
+ // and synchronize the results to the `expireTimes` and `expireSets` properties.
412
+ // 2. Clean up the expired key-value pair data.
396
413
func (c * AdapterMemory ) syncEventAndClearExpired (ctx context.Context ) {
397
414
if c .closed .Val () {
398
415
gtimer .Exit ()
@@ -403,9 +420,9 @@ func (c *AdapterMemory) syncEventAndClearExpired(ctx context.Context) {
403
420
oldExpireTime int64
404
421
newExpireTime int64
405
422
)
406
- // ========================
407
- // Data Synchronization .
408
- // ========================
423
+ // ================================
424
+ // Data expiration synchronization .
425
+ // ================================
409
426
for {
410
427
v := c .eventList .PopFront ()
411
428
if v == nil {
@@ -425,37 +442,24 @@ func (c *AdapterMemory) syncEventAndClearExpired(ctx context.Context) {
425
442
// Updating the expired time for `event.k`.
426
443
c .expireTimes .Set (event .k , newExpireTime )
427
444
}
428
- // Adding the key the LRU history by writing operations.
429
- if c .cap > 0 {
430
- c .lru .Push (event .k )
431
- }
432
- }
433
- // Processing expired keys from LRU.
434
- if c .cap > 0 {
435
- if c .lruGetList .Len () > 0 {
436
- for {
437
- if v := c .lruGetList .PopFront (); v != nil {
438
- c .lru .Push (v )
439
- } else {
440
- break
441
- }
442
- }
443
- }
444
- c .lru .SyncAndClear (ctx )
445
445
}
446
- // ========================
447
- // Data Cleaning up.
448
- // ========================
446
+ // =================================
447
+ // Data expiration auto cleaning up.
448
+ // =================================
449
449
var (
450
- expireSet * gset.Set
451
- ek = c . makeExpireKey ( gtime . TimestampMilli ())
452
- eks = [] int64 { ek - 1000 , ek - 2000 , ek - 3000 , ek - 4000 , ek - 5000 }
450
+ expireSet * gset.Set
451
+ expireTime int64
452
+ currentEk = c . makeExpireKey ( gtime . TimestampMilli ())
453
453
)
454
- for _ , expireTime := range eks {
454
+ // auto removing expiring key set for latest seconds.
455
+ for i := int64 (1 ); i <= 5 ; i ++ {
456
+ expireTime = currentEk - i * 1000
455
457
if expireSet = c .expireSets .Get (expireTime ); expireSet != nil {
456
458
// Iterating the set to delete all keys in it.
457
459
expireSet .Iterator (func (key interface {}) bool {
458
- c .clearByKey (key )
460
+ c .deleteExpiredKey (key )
461
+ // remove auto expired key for lru.
462
+ c .lru .Remove (key )
459
463
return true
460
464
})
461
465
// Deleting the set after all of its keys are deleted.
@@ -464,17 +468,22 @@ func (c *AdapterMemory) syncEventAndClearExpired(ctx context.Context) {
464
468
}
465
469
}
466
470
471
+ func (c * AdapterMemory ) handleLruKey (ctx context.Context , keys ... interface {}) {
472
+ if c .lru == nil {
473
+ return
474
+ }
475
+ if evictedKeys := c .lru .SaveAndEvict (keys ... ); len (evictedKeys ) > 0 {
476
+ _ , _ = c .doRemove (ctx , evictedKeys ... )
477
+ return
478
+ }
479
+ return
480
+ }
481
+
467
482
// clearByKey deletes the key-value pair with given `key`.
468
483
// The parameter `force` specifies whether doing this deleting forcibly.
469
- func (c * AdapterMemory ) clearByKey (key interface {}, force ... bool ) {
484
+ func (c * AdapterMemory ) deleteExpiredKey (key interface {}) {
470
485
// Doubly check before really deleting it from cache.
471
- c .data .DeleteWithDoubleCheck (key , force ... )
472
-
486
+ c .data .Delete (key )
473
487
// Deleting its expiration time from `expireTimes`.
474
488
c .expireTimes .Delete (key )
475
-
476
- // Deleting it from LRU.
477
- if c .cap > 0 {
478
- c .lru .Remove (key )
479
- }
480
489
}
0 commit comments