github.com/sohaha/zlsgo@v1.7.13-0.20240501141223-10dd1a906f76/zcache/utils.go (about)

     1  package zcache
     2  
     3  type ActionKind int
     4  
     5  func (k ActionKind) String() string {
     6  	switch k {
     7  	case GET:
     8  		return "GET"
     9  	case SET:
    10  		return "SET"
    11  	case DELETE:
    12  		return "DELETE"
    13  	default:
    14  		return "UNKNOWN"
    15  	}
    16  }
    17  
    18  const (
    19  	SET ActionKind = iota + 1
    20  	GET
    21  	DELETE
    22  )
    23  
    24  type handler func(action ActionKind, key string, valuePtr uintptr)
    25  
    26  // Callback set callback function for cache
    27  func (l *FastCache) Callback(h handler) {
    28  	old := l.callback
    29  	l.callback = func(action ActionKind, key string, valuePtr uintptr) {
    30  		old(action, key, valuePtr)
    31  		h(action, key, valuePtr)
    32  	}
    33  }
    34  
    35  var p, n = uint16(0), uint16(1)
    36  
    37  type (
    38  	value struct {
    39  		value     *interface{}
    40  		byteValue []byte
    41  	}
    42  
    43  	node struct {
    44  		key      string
    45  		value    value
    46  		expireAt int64
    47  		isDelete bool
    48  	}
    49  
    50  	lruCache struct {
    51  		hashmap map[string]uint16
    52  		dlList  [][2]uint16
    53  		nodes   []node
    54  		last    uint16
    55  	}
    56  )
    57  
    58  func (c *lruCache) put(k string, i *interface{}, b []byte, expireAt int64) int {
    59  	if x, ok := c.hashmap[k]; ok {
    60  		c.nodes[x-1].value.value, c.nodes[x-1].value.byteValue, c.nodes[x-1].expireAt, c.nodes[x-1].isDelete = i, b, expireAt, false
    61  		c.adjust(x, p, n)
    62  		return 0
    63  	}
    64  
    65  	if c.last == uint16(cap(c.nodes)) {
    66  		tail := &c.nodes[c.dlList[0][p]-1]
    67  		delete(c.hashmap, (*tail).key)
    68  		c.hashmap[k], (*tail).key, (*tail).value.value, (*tail).value.byteValue, (*tail).expireAt, (*tail).isDelete = c.dlList[0][p], k, i, b, expireAt, false
    69  		c.adjust(c.dlList[0][p], p, n)
    70  		return 1
    71  	}
    72  
    73  	c.last++
    74  	if len(c.hashmap) <= 0 {
    75  		c.dlList[0][p] = c.last
    76  	} else {
    77  		c.dlList[c.dlList[0][n]][p] = c.last
    78  	}
    79  	c.nodes[c.last-1].key, c.nodes[c.last-1].value.value, c.nodes[c.last-1].value.byteValue, c.nodes[c.last-1].expireAt, c.nodes[c.last-1].isDelete, c.dlList[c.last], c.hashmap[k], c.dlList[0][n] = k, i, b, expireAt, false, [2]uint16{0, c.dlList[0][n]}, c.last, c.last
    80  	return 1
    81  }
    82  
    83  func (c *lruCache) get(k string) (*node, int) {
    84  	if x, ok := c.hashmap[k]; ok {
    85  		c.adjust(x, p, n)
    86  		return &c.nodes[x-1], 1
    87  	}
    88  	return nil, 0
    89  }
    90  
    91  func (c *lruCache) delete(k string) (_ *node, _ int, e int64) {
    92  	if x, ok := c.hashmap[k]; ok && !c.nodes[x-1].isDelete {
    93  		c.nodes[x-1].expireAt, c.nodes[x-1].isDelete, e = 0, true, c.nodes[x-1].expireAt
    94  		c.adjust(x, n, p)
    95  		return &c.nodes[x-1], 1, e
    96  	}
    97  	return nil, 0, 0
    98  }
    99  
   100  func (c *lruCache) forEach(walker func(key string, iface interface{}) bool) {
   101  	for idx := c.dlList[0][n]; idx != 0; idx = c.dlList[idx][n] {
   102  		if !c.nodes[idx-1].isDelete {
   103  			if c.nodes[idx-1].value.byteValue != nil {
   104  				if !walker(c.nodes[idx-1].key, c.nodes[idx-1].value.byteValue) {
   105  					return
   106  				}
   107  			} else {
   108  				if !walker(c.nodes[idx-1].key, *c.nodes[idx-1].value.value) {
   109  					return
   110  				}
   111  			}
   112  		}
   113  	}
   114  }
   115  
   116  func (c *lruCache) adjust(idx, f, t uint16) {
   117  	if c.dlList[idx][f] != 0 {
   118  		c.dlList[c.dlList[idx][t]][f], c.dlList[c.dlList[idx][f]][t], c.dlList[idx][f], c.dlList[idx][t], c.dlList[c.dlList[0][t]][f], c.dlList[0][t] = c.dlList[idx][f], c.dlList[idx][t], 0, c.dlList[0][t], idx, idx
   119  	}
   120  }
   121  
   122  func hasher(s string) (hash int32) {
   123  	for i := 0; i < len(s); i++ {
   124  		hash = hash*131 + int32(s[i])
   125  	}
   126  	return hash
   127  }