github.com/TeaOSLab/EdgeNode@v1.3.8/internal/ttlcache/piece.go (about)

     1  package ttlcache
     2  
     3  import (
     4  	"github.com/TeaOSLab/EdgeNode/internal/utils/expires"
     5  	"github.com/TeaOSLab/EdgeNode/internal/utils/fasttime"
     6  	"sync"
     7  )
     8  
     9  type Piece[T any] struct {
    10  	m           map[uint64]*Item[T]
    11  	expiresList *expires.List
    12  	maxItems    int
    13  	lastGCTime  int64
    14  
    15  	locker sync.RWMutex
    16  }
    17  
    18  func NewPiece[T any](maxItems int) *Piece[T] {
    19  	return &Piece[T]{
    20  		m:           map[uint64]*Item[T]{},
    21  		expiresList: expires.NewSingletonList(),
    22  		maxItems:    maxItems,
    23  	}
    24  }
    25  
    26  func (this *Piece[T]) Add(key uint64, item *Item[T]) (ok bool) {
    27  	this.locker.RLock()
    28  	if this.maxItems > 0 && len(this.m) >= this.maxItems {
    29  		this.locker.RUnlock()
    30  		return
    31  	}
    32  	this.locker.RUnlock()
    33  
    34  	this.locker.Lock()
    35  	oldItem, exists := this.m[key]
    36  	if exists && oldItem.expiredAt == item.expiredAt {
    37  		this.locker.Unlock()
    38  		return true
    39  	}
    40  	this.m[key] = item
    41  	this.locker.Unlock()
    42  
    43  	this.expiresList.Add(key, item.expiredAt)
    44  
    45  	return true
    46  }
    47  
    48  func (this *Piece[T]) IncreaseInt64(key uint64, delta T, expiredAt int64, extend bool) (result T) {
    49  	this.locker.Lock()
    50  	item, ok := this.m[key]
    51  	if ok && item.expiredAt > fasttime.Now().Unix() {
    52  		int64Value, isInt64 := any(item.Value).(int64)
    53  		if isInt64 {
    54  			result = any(int64Value + any(delta).(int64)).(T)
    55  		}
    56  		item.Value = result
    57  		if extend {
    58  			item.expiredAt = expiredAt
    59  		}
    60  		this.expiresList.Add(key, expiredAt)
    61  	} else {
    62  		if len(this.m) < this.maxItems {
    63  			result = delta
    64  			this.m[key] = &Item[T]{
    65  				Value:     delta,
    66  				expiredAt: expiredAt,
    67  			}
    68  			this.expiresList.Add(key, expiredAt)
    69  		}
    70  	}
    71  	this.locker.Unlock()
    72  
    73  	return
    74  }
    75  
    76  func (this *Piece[T]) Delete(key uint64) {
    77  	this.expiresList.Remove(key)
    78  
    79  	this.locker.Lock()
    80  	delete(this.m, key)
    81  	this.locker.Unlock()
    82  }
    83  
    84  func (this *Piece[T]) Read(key uint64) (item *Item[T]) {
    85  	this.locker.RLock()
    86  	item = this.m[key]
    87  	if item != nil && item.expiredAt < fasttime.Now().Unix() {
    88  		item = nil
    89  	}
    90  	this.locker.RUnlock()
    91  
    92  	return
    93  }
    94  
    95  func (this *Piece[T]) Count() (count int) {
    96  	this.locker.RLock()
    97  	count = len(this.m)
    98  	this.locker.RUnlock()
    99  	return
   100  }
   101  
   102  func (this *Piece[T]) GC() {
   103  	var currentTime = fasttime.Now().Unix()
   104  	if this.lastGCTime == 0 {
   105  		this.lastGCTime = currentTime - 3600
   106  	}
   107  
   108  	var minTime = this.lastGCTime
   109  	var maxTime = currentTime
   110  	if minTime > maxTime {
   111  		// 过去的时间比现在大,则从这一秒重新开始
   112  		minTime = maxTime
   113  	}
   114  
   115  	for i := minTime; i <= maxTime; i++ {
   116  		var itemMap = this.expiresList.GC(i)
   117  		if len(itemMap) > 0 {
   118  			this.gcItemMap(itemMap)
   119  		}
   120  	}
   121  
   122  	this.lastGCTime = currentTime
   123  }
   124  
   125  func (this *Piece[T]) Clean() {
   126  	this.locker.Lock()
   127  	this.m = map[uint64]*Item[T]{}
   128  	this.locker.Unlock()
   129  
   130  	this.expiresList.Clean()
   131  }
   132  
   133  func (this *Piece[T]) Destroy() {
   134  	this.locker.Lock()
   135  	this.m = nil
   136  	this.locker.Unlock()
   137  
   138  	this.expiresList.Clean()
   139  }
   140  
   141  func (this *Piece[T]) gcItemMap(itemMap expires.ItemMap) {
   142  	this.locker.Lock()
   143  	for key := range itemMap {
   144  		delete(this.m, key)
   145  	}
   146  	this.locker.Unlock()
   147  }