/opt/imunify360-webshield/lualib/resty
-- Copyright (C) Yichun Zhang (agentzh) local ffi = require "ffi" local ffi_new = ffi.new local ffi_sizeof = ffi.sizeof local ffi_cast = ffi.cast local ffi_fill = ffi.fill local ngx_now = ngx.now local uintptr_t = ffi.typeof("uintptr_t") local setmetatable = setmetatable local tonumber = tonumber local type = type local new_tab do local ok ok, new_tab = pcall(require, "table.new") if not ok then new_tab = function(narr, nrec) return {} end end end if string.find(jit.version, " 2.0", 1, true) then ngx.log(ngx.ALERT, "use of lua-resty-lrucache with LuaJIT 2.0 is ", "not recommended; use LuaJIT 2.1+ instead") end local ok, tb_clear = pcall(require, "table.clear") if not ok then local pairs = pairs tb_clear = function (tab) for k, _ in pairs(tab) do tab[k] = nil end end end -- queue data types -- -- this queue is a double-ended queue and the first node -- is reserved for the queue itself. -- the implementation is mostly borrowed from nginx's ngx_queue_t data -- structure. ffi.cdef[[ typedef struct lrucache_queue_s lrucache_queue_t; struct lrucache_queue_s { double expire; /* in seconds */ lrucache_queue_t *prev; lrucache_queue_t *next; uint32_t user_flags; }; ]] local queue_arr_type = ffi.typeof("lrucache_queue_t[?]") local queue_type = ffi.typeof("lrucache_queue_t") local NULL = ffi.null -- queue utility functions local function queue_insert_tail(h, x) local last = h[0].prev x.prev = last last.next = x x.next = h h[0].prev = x end local function queue_init(size) if not size then size = 0 end local q = ffi_new(queue_arr_type, size + 1) ffi_fill(q, ffi_sizeof(queue_type, size + 1), 0) if size == 0 then q[0].prev = q q[0].next = q else local prev = q[0] for i = 1, size do local e = q + i e.user_flags = 0 prev.next = e e.prev = prev prev = e end local last = q[size] last.next = q q[0].prev = last end return q end local function queue_is_empty(q) -- print("q: ", tostring(q), "q.prev: ", tostring(q), ": ", q == q.prev) return q == q[0].prev end local function queue_remove(x) local prev = x.prev local next = x.next next.prev = prev prev.next = next -- for debugging purpose only: x.prev = NULL x.next = NULL end local function queue_insert_head(h, x) x.next = h[0].next x.next.prev = x x.prev = h h[0].next = x end local function queue_last(h) return h[0].prev end local function queue_head(h) return h[0].next end -- true module stuffs local _M = { _VERSION = '0.14' } local mt = { __index = _M } local function ptr2num(ptr) local v = tonumber(ffi_cast(uintptr_t, ptr)) return v end function _M.new(size) if size < 1 then return nil, "size too small" end local self = { hasht = {}, free_queue = queue_init(size), cache_queue = queue_init(), key2node = {}, node2key = {}, num_items = 0, max_items = size, } setmetatable(self, mt) return self end function _M.count(self) return self.num_items end function _M.capacity(self) return self.max_items end function _M.get(self, key) local hasht = self.hasht local val = hasht[key] if val == nil then return nil end local node = self.key2node[key] -- 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, node.user_flags end return val, nil, node.user_flags end function _M.delete(self, key) self.hasht[key] = nil local key2node = self.key2node local node = key2node[key] if not node then return false end key2node[key] = nil self.node2key[ptr2num(node)] = nil queue_remove(node) queue_insert_tail(self.free_queue, node) self.num_items = self.num_items - 1 return true end function _M.set(self, key, value, ttl, flags) 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 else -- take a free queue node node = queue_head(free_queue) -- only add count if we are not evicting self.num_items = self.num_items + 1 -- print(key, ": get a new free node: ", tostring(node)) end node2key[ptr2num(node)] = key key2node[key] = node end queue_remove(node) queue_insert_head(self.cache_queue, node) if ttl then node.expire = ngx_now() + ttl else node.expire = -1 end if type(flags) == "number" and flags >= 0 then node.user_flags = flags else node.user_flags = 0 end end function _M.get_keys(self, max_count, res) if not max_count or max_count == 0 then max_count = self.num_items end if not res then res = new_tab(max_count + 1, 0) -- + 1 for trailing hole end local cache_queue = self.cache_queue local node2key = self.node2key local i = 0 local node = queue_head(cache_queue) while node ~= cache_queue do if i >= max_count then break end i = i + 1 res[i] = node2key[ptr2num(node)] node = node.next end res[i + 1] = nil return res end function _M.flush_all(self) tb_clear(self.hasht) tb_clear(self.node2key) tb_clear(self.key2node) self.num_items = 0 local cache_queue = self.cache_queue local free_queue = self.free_queue -- splice the cache_queue into free_queue if not queue_is_empty(cache_queue) then local free_head = free_queue[0] local free_last = free_head.prev local cache_head = cache_queue[0] local cache_first = cache_head.next local cache_last = cache_head.prev free_last.next = cache_first cache_first.prev = free_last cache_last.next = free_head free_head.prev = cache_last cache_head.next = cache_queue cache_head.prev = cache_queue end end return _M
.
Edit
..
Edit
aes.lua
Edit
cookie.lua
Edit
core
Edit
core.lua
Edit
dns
Edit
http.lua
Edit
http_headers.lua
Edit
limit
Edit
lock.lua
Edit
lrucache
Edit
lrucache.lua
Edit
md5.lua
Edit
random.lua
Edit
sha.lua
Edit
sha1.lua
Edit
sha224.lua
Edit
sha256.lua
Edit
sha384.lua
Edit
sha512.lua
Edit
shell.lua
Edit
signal.lua
Edit
string.lua
Edit
template
Edit
template.lua
Edit
upstream
Edit
websocket
Edit