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