"Fossies" - the Fresh Open Source Software Archive 
Member "memcached-1.6.15/t/startfile.lua" (30 Mar 2022, 9864 Bytes) of package /linux/www/memcached-1.6.15.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Lua source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
See also the latest
Fossies "Diffs" side-by-side code changes report for "startfile.lua":
1.6.14_vs_1.6.15.
1 -- WARNING: if you cause errors during configuration reload by putting
2 -- incompatible data into the table returned by mcp_config_pools, the daeomon
3 -- will exit.
4 -- TODO: fallback cache for broken/overloaded zones.
5
6 -- local zone could/should be fetched from environment or local file.
7 -- doing so allows all configuration files to be identical, simplifying consistency checks.
8 local my_zone = 'z1'
9
10 local STAT_EXAMPLE <const> = 1
11 local STAT_ANOTHER <const> = 2
12 --mcp.tcp_keepalive(true)
13
14 function mcp_config_pools(oldss)
15 mcp.add_stat(STAT_EXAMPLE, "example")
16 mcp.add_stat(STAT_ANOTHER, "another")
17 mcp.backend_connect_timeout(5.5) -- 5 and a half second timeout.
18 -- alias mcp.backend for convenience.
19 -- important to alias global variables in routes where speed is concerned.
20 local srv = mcp.backend
21 -- local zones = { 'z1', 'z2', 'z3' }
22
23 -- IPs are "127" . "zone" . "pool" . "srv"
24 local pfx = 'fooz1'
25 local fooz1 = {
26 srv(pfx .. 'srv1', '127.1.1.1', 11212),
27 srv(pfx .. 'srv2', '127.1.1.2', 11212),
28 srv(pfx .. 'srv3', '127.1.1.3', 11212),
29 }
30 pfx = 'fooz2'
31 local fooz2 = {
32 srv(pfx .. 'srv1', '127.2.1.1', 11213),
33 srv(pfx .. 'srv2', '127.2.1.2', 11213),
34 srv(pfx .. 'srv3', '127.2.1.3', 11213),
35 }
36 pfx = 'fooz3'
37 local fooz3 = {
38 srv(pfx .. 'srv1', '127.3.1.1', 11214),
39 srv(pfx .. 'srv2', '127.3.1.2', 11214),
40 srv(pfx .. 'srv3', '127.3.1.3', 11214),
41 }
42
43 pfx = 'barz1'
44 -- zone "/bar/"-s primary zone should fail; all down.
45 local barz1 = {
46 srv(pfx .. 'srv1', '127.1.2.1', 11210),
47 srv(pfx .. 'srv2', '127.1.2.2', 11210),
48 srv(pfx .. 'srv3', '127.1.2.3', 11210),
49 }
50 pfx = 'barz2'
51 local barz2 = {
52 srv(pfx .. 'srv1', '127.2.2.1', 11215),
53 srv(pfx .. 'srv2', '127.2.2.2', 11215),
54 srv(pfx .. 'srv3', '127.2.2.3', 11215),
55 }
56 pfx = 'barz3'
57 local barz3 = {
58 srv(pfx .. 'srv1', '127.3.2.1', 11216),
59 srv(pfx .. 'srv2', '127.3.2.2', 11216),
60 srv(pfx .. 'srv3', '127.3.2.3', 11216),
61 }
62
63 -- fallback cache for any zone
64 -- NOT USED YET
65 pfx = 'fallz1'
66 local fallz1 = {
67 srv(pfx .. 'srv1', '127.0.2.1', 11212),
68 }
69 pfx = 'fallz2'
70 local fallz2 = {
71 srv(pfx .. 'srv1', '127.0.2.2', 11212),
72 }
73 pfx = 'fallz3'
74 local fallz3 = {
75 srv(pfx .. 'srv1', '127.0.2.3', 11212),
76 }
77
78 local main_zones = {
79 foo = { z1 = fooz1, z2 = fooz2, z3 = fooz3 },
80 bar = { z1 = barz1, z2 = barz2, z3 = barz3 },
81 -- fall = { z1 = fallz1, z2 = fallz2, z3 = fallz3 },
82 }
83
84 -- FIXME: should we copy the table to keep the pool tables around?
85 -- does the hash selector hold a reference to the pool (but only available in main config?)
86
87 -- convert the pools into hash selectors.
88 -- TODO: is this a good place to add prefixing/hash editing?
89 for _, subs in pairs(main_zones) do
90 for k, v in pairs(subs) do
91 -- next line uses a ring hash in "evcache compat" mode. note the
92 -- hash= override to use MD5 key hashing from ketama.
93 -- subs[k] = mcp.pool(v, { dist = mcp.dist_ring_hash, omode = "evcache", hash = mcp.dist_ring_hash.hash })
94 -- override the number of buckets per server.
95 -- subs[k] = mcp.pool(v, { dist = mcp.dist_ring_hash, omode = "evcache", hash = mcp.dist_ring_hash.hash, obuckets = 240 })
96 -- this line uses the default (currently xxhash + jump hash)
97 subs[k] = mcp.pool(v)
98
99 -- use this next line instead for jump hash.
100 -- the order of servers in the pool argument _must_ not change!
101 -- adding the seed string will give a different key distribution
102 -- for each zone.
103 -- NOTE: 'k' may not be the right seed here:
104 -- instead stitch main_zone's key + the sub key?
105 -- subs[k] = mcp.pool(v, { dist = mcp.dist_jump_hash, seed = k })
106 -- subs[k] = mcp.pool(v, { dist = mcp.dist_jump_hash, seed = k, filter = "stop", filter_conf = "|#|" })
107 -- subs[k] = mcp.pool(v, { dist = mcp.dist_jump_hash, seed = k, filter = "tags", filter_conf = "{}" })
108 end
109 end
110
111 return main_zones
112 end
113
114 -- WORKER CODE:
115
116 -- need to redefine main_zones using fetched selectors?
117
118 -- TODO: Fallback zone here?
119 function failover_factory(zones, local_zone)
120 local near_zone = zones[local_zone]
121 local far_zones = {}
122 -- NOTE: could shuffle/sort to re-order zone retry order
123 -- or use 'next(far_zones, idx)' via a stored upvalue here
124 for k, v in pairs(zones) do
125 if k ~= local_zone then
126 far_zones[k] = v
127 end
128 end
129 return function(r)
130 local res = near_zone(r)
131 if res:hit() == false then
132 -- example for mcp.log... Don't do this though :)
133 mcp.log("failed to find " .. r:key() .. " in zone: " .. local_zone)
134 --for _, zone in pairs(far_zones) do
135 -- res = zone(r)
136 local restable = mcp.await(r, far_zones, 1)
137 for _, res in pairs(restable) do
138 if res:hit() then
139 --break
140 return res
141 end
142 end
143 return restable[1]
144 end
145 return res -- send result back to client
146 end
147 end
148
149 -- SET's to main zone, issues deletes to far zones.
150 function setinvalidate_factory(zones, local_zone)
151 local near_zone = zones[local_zone]
152 local far_zones = {}
153 -- NOTE: could shuffle/sort to re-order zone retry order
154 -- or use 'next(far_zones, idx)' via a stored upvalue here
155 for k, v in pairs(zones) do
156 if k ~= local_zone then
157 far_zones[k] = v
158 end
159 end
160 local new_req = mcp.request
161 return function(r)
162 local res = near_zone(r)
163 if res:ok() == true then
164 -- create a new delete request
165 local dr = new_req("delete /testing/" .. r:key() .. "\r\n")
166 for _, zone in pairs(far_zones) do
167 -- NOTE: can check/do things on the specific response here.
168 zone(dr)
169 end
170 end
171 -- use original response for client, not DELETE's response.
172 -- else client won't understand.
173 return res -- send result back to client
174 end
175 end
176
177 -- NOTE: this function is culling key prefixes. it is an error to use it
178 -- without a left anchored (^) pattern.
179 function prefixtrim_factory(pattern, list, default)
180 local p = pattern
181 local l = list
182 local d = default
183 local s = mcp.stat
184 return function(r)
185 local i, j, match = string.find(r:key(), p)
186 local route
187 if match ~= nil then
188 -- remove the key prefix so we don't waste storage.
189 r:ltrimkey(j)
190 route = l[match]
191 if route == nil then
192 -- example counter: tick when default route hit.
193 s(STAT_EXAMPLE, 1)
194 return d(r)
195 end
196 end
197 return route(r)
198 end
199 end
200
201 function prefix_factory(pattern, list, default)
202 local p = pattern
203 local l = list
204 local d = default
205 local s = mcp.stat
206 return function(r)
207 local route = l[string.match(r:key(), p)]
208 if route == nil then
209 -- example counter: tick when default route hit.
210 s(STAT_EXAMPLE, 1)
211 return d(r)
212 end
213 return route(r)
214 end
215 end
216
217 -- TODO: Check tail call requirements?
218 function command_factory(map, default)
219 local m = map
220 local d = default
221 return function(r)
222 local f = map[r:command()]
223 if f == nil then
224 -- print("default command")
225 return d(r)
226 end
227 -- testing options replacement...
228 -- if r:command() == mcp.CMD_SET then
229 -- r:token(4, "100") -- set exptime.
230 -- end
231 -- print("override command")
232 return f(r)
233 end
234 end
235
236 -- TODO: is the return value the average? anything special?
237 -- walks a list of selectors and repeats the request.
238 function walkall_factory(pool)
239 local p = {}
240 -- TODO: a shuffle could be useful here.
241 for _, v in pairs(pool) do
242 table.insert(p, v)
243 end
244 local x = #p
245 return function(r)
246 local restable = mcp.await(r, p)
247 -- walk results and return "best" result
248 -- print("length of await result table", #restable)
249 for _, res in pairs(restable) do
250 if res:ok() then
251 return res
252 end
253 end
254 -- else we return the first result.
255 return restable[1]
256 end
257 end
258
259 function mcp_config_routes(main_zones)
260 -- generate the prefix routes from zones.
261 local prefixes = {}
262 for pfx, z in pairs(main_zones) do
263 local failover = failover_factory(z, my_zone)
264 local all = walkall_factory(main_zones[pfx])
265 local setdel = setinvalidate_factory(z, my_zone)
266 local map = {}
267 map[mcp.CMD_SET] = all
268 -- NOTE: in t/proxy.t all the backends point to the same place
269 -- which makes replicating delete return NOT_FOUND
270 map[mcp.CMD_DELETE] = all
271 -- similar with ADD. will get an NOT_STORED back.
272 -- need better routes designed for the test suite (edit the key
273 -- prefix or something)
274 map[mcp.CMD_ADD] = failover_factory(z, my_zone)
275 prefixes[pfx] = command_factory(map, failover)
276 end
277
278 local routetop = prefix_factory("^/(%a+)/", prefixes, function(r) return "SERVER_ERROR no route\r\n" end)
279
280 -- internally run parser at top of tree
281 -- also wrap the request string with a convenience object until the C bits
282 -- are attached to the internal parser.
283 --mcp.attach(mcp.CMD_ANY, function (r) return routetop(r) end)
284 mcp.attach(mcp.CMD_ANY_STORAGE, routetop)
285 end