1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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
|