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 }