github.com/gogf/gf/v2@v2.7.4/os/gcache/gcache_adapter_memory_data.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/gogf/gf.
     6  
     7  package gcache
     8  
     9  import (
    10  	"context"
    11  	"sync"
    12  	"time"
    13  
    14  	"github.com/gogf/gf/v2/os/gtime"
    15  )
    16  
    17  type adapterMemoryData struct {
    18  	mu   sync.RWMutex                      // dataMu ensures the concurrent safety of underlying data map.
    19  	data map[interface{}]adapterMemoryItem // data is the underlying cache data which is stored in a hash table.
    20  }
    21  
    22  func newAdapterMemoryData() *adapterMemoryData {
    23  	return &adapterMemoryData{
    24  		data: make(map[interface{}]adapterMemoryItem),
    25  	}
    26  }
    27  
    28  // Update updates the value of `key` without changing its expiration and returns the old value.
    29  // The returned value `exist` is false if the `key` does not exist in the cache.
    30  //
    31  // It deletes the `key` if given `value` is nil.
    32  // It does nothing if `key` does not exist in the cache.
    33  func (d *adapterMemoryData) Update(key interface{}, value interface{}) (oldValue interface{}, exist bool, err error) {
    34  	d.mu.Lock()
    35  	defer d.mu.Unlock()
    36  	if item, ok := d.data[key]; ok {
    37  		d.data[key] = adapterMemoryItem{
    38  			v: value,
    39  			e: item.e,
    40  		}
    41  		return item.v, true, nil
    42  	}
    43  	return nil, false, nil
    44  }
    45  
    46  // UpdateExpire updates the expiration of `key` and returns the old expiration duration value.
    47  //
    48  // It returns -1 and does nothing if the `key` does not exist in the cache.
    49  // It deletes the `key` if `duration` < 0.
    50  func (d *adapterMemoryData) UpdateExpire(key interface{}, expireTime int64) (oldDuration time.Duration, err error) {
    51  	d.mu.Lock()
    52  	defer d.mu.Unlock()
    53  	if item, ok := d.data[key]; ok {
    54  		d.data[key] = adapterMemoryItem{
    55  			v: item.v,
    56  			e: expireTime,
    57  		}
    58  		return time.Duration(item.e-gtime.TimestampMilli()) * time.Millisecond, nil
    59  	}
    60  	return -1, nil
    61  }
    62  
    63  // Remove deletes the one or more keys from cache, and returns its value.
    64  // If multiple keys are given, it returns the value of the deleted last item.
    65  func (d *adapterMemoryData) Remove(keys ...interface{}) (removedKeys []interface{}, value interface{}, err error) {
    66  	d.mu.Lock()
    67  	defer d.mu.Unlock()
    68  	removedKeys = make([]interface{}, 0)
    69  	for _, key := range keys {
    70  		item, ok := d.data[key]
    71  		if ok {
    72  			value = item.v
    73  			delete(d.data, key)
    74  			removedKeys = append(removedKeys, key)
    75  		}
    76  	}
    77  	return removedKeys, value, nil
    78  }
    79  
    80  // Data returns a copy of all key-value pairs in the cache as map type.
    81  func (d *adapterMemoryData) Data() (map[interface{}]interface{}, error) {
    82  	d.mu.RLock()
    83  	m := make(map[interface{}]interface{}, len(d.data))
    84  	for k, v := range d.data {
    85  		if !v.IsExpired() {
    86  			m[k] = v.v
    87  		}
    88  	}
    89  	d.mu.RUnlock()
    90  	return m, nil
    91  }
    92  
    93  // Keys returns all keys in the cache as slice.
    94  func (d *adapterMemoryData) Keys() ([]interface{}, error) {
    95  	d.mu.RLock()
    96  	var (
    97  		index = 0
    98  		keys  = make([]interface{}, len(d.data))
    99  	)
   100  	for k, v := range d.data {
   101  		if !v.IsExpired() {
   102  			keys[index] = k
   103  			index++
   104  		}
   105  	}
   106  	d.mu.RUnlock()
   107  	return keys, nil
   108  }
   109  
   110  // Values returns all values in the cache as slice.
   111  func (d *adapterMemoryData) Values() ([]interface{}, error) {
   112  	d.mu.RLock()
   113  	var (
   114  		index  = 0
   115  		values = make([]interface{}, len(d.data))
   116  	)
   117  	for _, v := range d.data {
   118  		if !v.IsExpired() {
   119  			values[index] = v.v
   120  			index++
   121  		}
   122  	}
   123  	d.mu.RUnlock()
   124  	return values, nil
   125  }
   126  
   127  // Size returns the size of the cache.
   128  func (d *adapterMemoryData) Size() (size int, err error) {
   129  	d.mu.RLock()
   130  	size = len(d.data)
   131  	d.mu.RUnlock()
   132  	return size, nil
   133  }
   134  
   135  // Clear clears all data of the cache.
   136  // Note that this function is sensitive and should be carefully used.
   137  func (d *adapterMemoryData) Clear() error {
   138  	d.mu.Lock()
   139  	defer d.mu.Unlock()
   140  	d.data = make(map[interface{}]adapterMemoryItem)
   141  	return nil
   142  }
   143  
   144  func (d *adapterMemoryData) Get(key interface{}) (item adapterMemoryItem, ok bool) {
   145  	d.mu.RLock()
   146  	item, ok = d.data[key]
   147  	d.mu.RUnlock()
   148  	return
   149  }
   150  
   151  func (d *adapterMemoryData) Set(key interface{}, value adapterMemoryItem) {
   152  	d.mu.Lock()
   153  	d.data[key] = value
   154  	d.mu.Unlock()
   155  }
   156  
   157  // SetMap batch sets cache with key-value pairs by `data`, which is expired after `duration`.
   158  //
   159  // It does not expire if `duration` == 0.
   160  // It deletes the keys of `data` if `duration` < 0 or given `value` is nil.
   161  func (d *adapterMemoryData) SetMap(data map[interface{}]interface{}, expireTime int64) error {
   162  	d.mu.Lock()
   163  	for k, v := range data {
   164  		d.data[k] = adapterMemoryItem{
   165  			v: v,
   166  			e: expireTime,
   167  		}
   168  	}
   169  	d.mu.Unlock()
   170  	return nil
   171  }
   172  
   173  func (d *adapterMemoryData) SetWithLock(ctx context.Context, key interface{}, value interface{}, expireTimestamp int64) (interface{}, error) {
   174  	d.mu.Lock()
   175  	defer d.mu.Unlock()
   176  	var (
   177  		err error
   178  	)
   179  	if v, ok := d.data[key]; ok && !v.IsExpired() {
   180  		return v.v, nil
   181  	}
   182  	f, ok := value.(Func)
   183  	if !ok {
   184  		// Compatible with raw function value.
   185  		f, ok = value.(func(ctx context.Context) (value interface{}, err error))
   186  	}
   187  	if ok {
   188  		if value, err = f(ctx); err != nil {
   189  			return nil, err
   190  		}
   191  		if value == nil {
   192  			return nil, nil
   193  		}
   194  	}
   195  	d.data[key] = adapterMemoryItem{v: value, e: expireTimestamp}
   196  	return value, nil
   197  }
   198  
   199  func (d *adapterMemoryData) DeleteWithDoubleCheck(key interface{}, force ...bool) {
   200  	d.mu.Lock()
   201  	// Doubly check before really deleting it from cache.
   202  	if item, ok := d.data[key]; (ok && item.IsExpired()) || (len(force) > 0 && force[0]) {
   203  		delete(d.data, key)
   204  	}
   205  	d.mu.Unlock()
   206  }