aboutsummaryrefslogtreecommitdiffstats
path: root/server/resty/session/storage/shm.lua
diff options
context:
space:
mode:
Diffstat (limited to 'server/resty/session/storage/shm.lua')
-rw-r--r--server/resty/session/storage/shm.lua125
1 files changed, 125 insertions, 0 deletions
diff --git a/server/resty/session/storage/shm.lua b/server/resty/session/storage/shm.lua
new file mode 100644
index 0000000..6f81435
--- /dev/null
+++ b/server/resty/session/storage/shm.lua
@@ -0,0 +1,125 @@
+local lock = require "resty.lock"
+
+local setmetatable = setmetatable
+local tonumber = tonumber
+local concat = table.concat
+local var = ngx.var
+local shared = ngx.shared
+
+local function enabled(value)
+ if value == nil then return nil end
+ return value == true or (value == "1" or value == "true" or value == "on")
+end
+
+local function ifnil(value, default)
+ if value == nil then
+ return default
+ end
+
+ return enabled(value)
+end
+
+local defaults = {
+ store = var.session_shm_store or "sessions",
+ uselocking = enabled(var.session_shm_uselocking or true),
+ lock = {
+ exptime = tonumber(var.session_shm_lock_exptime, 10) or 30,
+ timeout = tonumber(var.session_shm_lock_timeout, 10) or 5,
+ step = tonumber(var.session_shm_lock_step, 10) or 0.001,
+ ratio = tonumber(var.session_shm_lock_ratio, 10) or 2,
+ max_step = tonumber(var.session_shm_lock_max_step, 10) or 0.5,
+ }
+}
+
+local storage = {}
+
+storage.__index = storage
+
+function storage.new(session)
+ local config = session.shm or defaults
+ local store = config.store or defaults.store
+ local locking = ifnil(config.uselocking, defaults.uselocking)
+
+ local self = {
+ store = shared[store],
+ uselocking = locking,
+ }
+
+ if locking then
+ local lock_opts = config.lock or defaults.lock
+ local opts = {
+ exptime = tonumber(lock_opts.exptime, 10) or defaults.exptime,
+ timeout = tonumber(lock_opts.timeout, 10) or defaults.timeout,
+ step = tonumber(lock_opts.step, 10) or defaults.step,
+ ratio = tonumber(lock_opts.ratio, 10) or defaults.ratio,
+ max_step = tonumber(lock_opts.max_step, 10) or defaults.max_step,
+ }
+ self.lock = lock:new(store, opts)
+ end
+
+ return setmetatable(self, storage)
+end
+
+function storage:open(id, keep_lock)
+ if self.uselocking then
+ local ok, err = self.lock:lock(concat{ id, ".lock" })
+ if not ok then
+ return nil, err
+ end
+ end
+
+ local data, err = self.store:get(id)
+
+ if self.uselocking and (err or not data or not keep_lock) then
+ self.lock:unlock()
+ end
+
+ return data, err
+end
+
+function storage:start(id)
+ if self.uselocking then
+ return self.lock:lock(concat{ id, ".lock" })
+ end
+
+ return true
+end
+
+function storage:save(id, ttl, data, close)
+ local ok, err = self.store:set(id, data, ttl)
+ if close and self.uselocking then
+ self.lock:unlock()
+ end
+
+ return ok, err
+end
+
+function storage:close()
+ if self.uselocking then
+ self.lock:unlock()
+ end
+
+ return true
+end
+
+function storage:destroy(id)
+ self.store:delete(id)
+
+ if self.uselocking then
+ self.lock:unlock()
+ end
+
+ return true
+end
+
+function storage:ttl(id, lifetime, close)
+ local ok, err = self.store:expire(id, lifetime)
+
+ if close and self.uselocking then
+ self.lock:unlock()
+ end
+
+ return ok, err
+end
+
+return storage