From 968e2806b6664fe709b0010f2b87d2225389bf8b Mon Sep 17 00:00:00 2001 From: splitice Date: Wed, 25 Nov 2015 20:06:02 +1100 Subject: [PATCH 1/5] add increment method (incr) --- lib/resty/lrucache.lua | 85 +++++++++++++++++++++------------- lib/resty/lrucache/pureffi.lua | 28 +++++++++++ 2 files changed, 82 insertions(+), 31 deletions(-) diff --git a/lib/resty/lrucache.lua b/lib/resty/lrucache.lua index fdaccde..c1782d2 100644 --- a/lib/resty/lrucache.lua +++ b/lib/resty/lrucache.lua @@ -111,6 +111,43 @@ local function queue_head(h) end +local function ptr2num(ptr) + return tonumber(ffi_cast(uintptr_t, ptr)) +end + +local function handle_lru(self, key) + local key2node = self.key2node + local node = key2node[key] + if not node then + local free_queue = self.free_queue + local node2key = self.node2key + + if queue_is_empty(free_queue) then + -- evict the least recently used key + -- assert(not queue_is_empty(self.cache_queue)) + node = queue_last(self.cache_queue) + + local oldkey = node2key[ptr2num(node)] + -- print(key, ": evicting oldkey: ", oldkey, ", oldnode: ", + -- tostring(node)) + if oldkey then + self.hasht[oldkey] = nil + key2node[oldkey] = nil + end + + else + -- take a free queue node + node = queue_head(free_queue) + -- print(key, ": get a new free node: ", tostring(node)) + end + + node2key[ptr2num(node)] = key + key2node[key] = node + end + + return node +end + -- true module stuffs local _M = { @@ -119,11 +156,6 @@ local _M = { local mt = { __index = _M } -local function ptr2num(ptr) - return tonumber(ffi_cast(uintptr_t, ptr)) -end - - function _M.new(size) if size < 1 then return nil, "size too small" @@ -181,40 +213,31 @@ function _M.delete(self, key) return true end - function _M.set(self, key, value, ttl) local hasht = self.hasht hasht[key] = value - local key2node = self.key2node - local node = key2node[key] - if not node then - local free_queue = self.free_queue - local node2key = self.node2key - - if queue_is_empty(free_queue) then - -- evict the least recently used key - -- assert(not queue_is_empty(self.cache_queue)) - node = queue_last(self.cache_queue) - - local oldkey = node2key[ptr2num(node)] - -- print(key, ": evicting oldkey: ", oldkey, ", oldnode: ", - -- tostring(node)) - if oldkey then - hasht[oldkey] = nil - key2node[oldkey] = nil - end + local node = handle_lru(self,key) + queue_remove(node) + queue_insert_head(self.cache_queue, node) - else - -- take a free queue node - node = queue_head(free_queue) - -- print(key, ": get a new free node: ", tostring(node)) - end + if ttl then + node.expire = ngx_now() + ttl + else + node.expire = -1 + end +end - node2key[ptr2num(node)] = key - key2node[key] = node +function _M.incr(self, key, ttl, by) + local hasht = self.hasht + local value = hasht[key] + if value == nil then + return value end + value = value + by + hasht[key] = value + local node = handle_lru(self,key) queue_remove(node) queue_insert_head(self.cache_queue, node) diff --git a/lib/resty/lrucache/pureffi.lua b/lib/resty/lrucache/pureffi.lua index 6f82ed5..bfc80a8 100644 --- a/lib/resty/lrucache/pureffi.lua +++ b/lib/resty/lrucache/pureffi.lua @@ -530,5 +530,33 @@ function _M.set(self, key, value, ttl) end end +function _M.incr(self, key, ttl, by) + by = by or 1 + + if type(key) ~= "string" then + key = tostring(key) + end + + local node_id = find_key(self, key) + local node + if not node_id then + return nil + end + + node = self.node_v + node_id + local value = self.val_v[node_id] + by + self.val_v[node_id] = value + + queue_remove(node) + queue_insert_head(self.cache_queue, node) + + if ttl then + node.expire = ngx_now() + ttl + else + node.expire = -1 + end + + return value +end return _M From 846ea4ad7039ccbcd70a95799013afca42475da9 Mon Sep 17 00:00:00 2001 From: splitice Date: Wed, 25 Nov 2015 20:32:36 +1100 Subject: [PATCH 2/5] more concise return statement --- lib/resty/lrucache.lua | 2 +- lib/resty/lrucache/pureffi.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/resty/lrucache.lua b/lib/resty/lrucache.lua index c1782d2..46f9bd2 100644 --- a/lib/resty/lrucache.lua +++ b/lib/resty/lrucache.lua @@ -232,7 +232,7 @@ function _M.incr(self, key, ttl, by) local hasht = self.hasht local value = hasht[key] if value == nil then - return value + return end value = value + by hasht[key] = value diff --git a/lib/resty/lrucache/pureffi.lua b/lib/resty/lrucache/pureffi.lua index bfc80a8..082d8bb 100644 --- a/lib/resty/lrucache/pureffi.lua +++ b/lib/resty/lrucache/pureffi.lua @@ -540,7 +540,7 @@ function _M.incr(self, key, ttl, by) local node_id = find_key(self, key) local node if not node_id then - return nil + return end node = self.node_v + node_id From 8261ce990c899f8cccd6164af298285a15fe0844 Mon Sep 17 00:00:00 2001 From: splitice Date: Thu, 2 Jun 2016 22:33:11 +1000 Subject: [PATCH 3/5] fix expiration for incr, better expiration for get & cleanup method cleanup method not optimal yet --- lib/resty/lrucache.lua | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/lib/resty/lrucache.lua b/lib/resty/lrucache.lua index 46f9bd2..96bf00f 100644 --- a/lib/resty/lrucache.lua +++ b/lib/resty/lrucache.lua @@ -181,16 +181,15 @@ function _M.get(self, key) end local node = self.key2node[key] + if node.expire >= 0 and node.expire < ngx_now() then + return nil, val + end -- print(key, ": moving node ", tostring(node), " to cache queue head") local cache_queue = self.cache_queue queue_remove(node) queue_insert_head(cache_queue, node) - if node.expire >= 0 and node.expire < ngx_now() then - -- print("expired: ", node.expire, " > ", ngx_now()) - return nil, val - end return val end @@ -234,10 +233,15 @@ function _M.incr(self, key, ttl, by) if value == nil then return end + + local node = handle_lru(self,key) + if node.expire >= 0 and node.expire < ngx_now() then + return nil + end + value = value + by hasht[key] = value - local node = handle_lru(self,key) queue_remove(node) queue_insert_head(self.cache_queue, node) @@ -246,7 +250,26 @@ function _M.incr(self, key, ttl, by) else node.expire = -1 end + return value; end +function _M.cleanup(self, n) + n = n or 0 + local node2key = self.node2key + local cachequeue = self.cache_queue + local now = ngx_now() + local node = queue_last(cachequeue) + while node ~= cachequeue do + local expire = node.expire + if expire >= 0 and expire < now then + self:delete(ptr2num(node2key[node])) + end + n = n - 1 + if n == 0 then + return + end + node = node.prev + end +end return _M From 9c1ffb2523dbac38c70f02a80732d36e32da7a42 Mon Sep 17 00:00:00 2001 From: splitice Date: Wed, 8 Jun 2016 23:16:59 +1000 Subject: [PATCH 4/5] cleanup the cleanup function --- lib/resty/lrucache.lua | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/lib/resty/lrucache.lua b/lib/resty/lrucache.lua index 10d0bdd..70138b2 100644 --- a/lib/resty/lrucache.lua +++ b/lib/resty/lrucache.lua @@ -254,20 +254,34 @@ end function _M.cleanup(self, n) n = n or 0 + local key2node = self.key2node local node2key = self.node2key local cachequeue = self.cache_queue local now = ngx_now() local node = queue_last(cachequeue) while node ~= cachequeue do local expire = node.expire - if expire >= 0 and expire < now then - self:delete(ptr2num(node2key[node])) + if expire >= 0 and expire <= now then + local next = node.next + + local ptr = ptr2num(node) + local key = node2key[ptr] + + self.hasht[key] = nil + key2node[key] = nil + self.node2key[ptr] = nil + + queue_remove(node) + queue_insert_tail(self.free_queue, node) + + node = next.prev + else + node = node.prev end n = n - 1 if n == 0 then return end - node = node.prev end end From 8da78b0fc43cf9f3964ed2d6fe3be1c0ce9316c0 Mon Sep 17 00:00:00 2001 From: splitice Date: Tue, 13 Dec 2016 16:23:41 +1100 Subject: [PATCH 5/5] ... --- lib/resty/lrucache.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/resty/lrucache.lua b/lib/resty/lrucache.lua index 70138b2..bfe8eae 100644 --- a/lib/resty/lrucache.lua +++ b/lib/resty/lrucache.lua @@ -162,6 +162,7 @@ function _M.new(size) end local self = { + keys = {}, hasht = {}, free_queue = queue_init(size), cache_queue = queue_init(),