Comparison

core/configmanager.lua @ 3573:f31fa6520a4b

configmanager: Atomic reloads, and some other internal changes to achieve this
author Matthew Wild <mwild1@gmail.com>
date Sun, 07 Nov 2010 20:38:01 +0000
parent 3515:bb494c3aa364
child 3609:954b1159f2f3
comparison
equal deleted inserted replaced
3572:fb7fc154a56a 3573:f31fa6520a4b
4 -- 4 --
5 -- This project is MIT/X11 licensed. Please see the 5 -- This project is MIT/X11 licensed. Please see the
6 -- COPYING file in the source package for more information. 6 -- COPYING file in the source package for more information.
7 -- 7 --
8 8
9
10
11 local _G = _G; 9 local _G = _G;
12 local setmetatable, loadfile, pcall, rawget, rawset, io, error, dofile, type, pairs, table, format = 10 local setmetatable, loadfile, pcall, rawget, rawset, io, error, dofile, type, pairs, table, format =
13 setmetatable, loadfile, pcall, rawget, rawset, io, error, dofile, type, pairs, table, string.format; 11 setmetatable, loadfile, pcall, rawget, rawset, io, error, dofile, type, pairs, table, string.format;
14 12
15 13
17 15
18 module "configmanager" 16 module "configmanager"
19 17
20 local parsers = {}; 18 local parsers = {};
21 19
22 local config = { ["*"] = { core = {} } }; 20 local config_mt = { __index = function (t, k) return rawget(t, "*"); end};
23 21 local config = setmetatable({ ["*"] = { core = {} } }, config_mt);
24 local global_config = config["*"];
25 22
26 -- When host not found, use global 23 -- When host not found, use global
27 setmetatable(config, { __index = function () return global_config; end}); 24 local host_mt = { };
28 local host_mt = { __index = global_config };
29 25
30 -- When key not found in section, check key in global's section 26 -- When key not found in section, check key in global's section
31 function section_mt(section_name) 27 function section_mt(section_name)
32 return { __index = function (t, k) 28 return { __index = function (t, k)
33 local section = rawget(global_config, section_name); 29 local section = rawget(config["*"], section_name);
34 if not section then return nil; end 30 if not section then return nil; end
35 return section[k]; 31 return section[k];
36 end 32 end
37 }; 33 };
38 end 34 end
47 return sec[key]; 43 return sec[key];
48 end 44 end
49 return nil; 45 return nil;
50 end 46 end
51 47
52 function set(host, section, key, value) 48 local function set(config, host, section, key, value)
53 if host and section and key then 49 if host and section and key then
54 local hostconfig = rawget(config, host); 50 local hostconfig = rawget(config, host);
55 if not hostconfig then 51 if not hostconfig then
56 hostconfig = rawset(config, host, setmetatable({}, host_mt))[host]; 52 hostconfig = rawset(config, host, setmetatable({}, host_mt))[host];
57 end 53 end
62 return true; 58 return true;
63 end 59 end
64 return false; 60 return false;
65 end 61 end
66 62
63 function _M.set(host, section, key, value)
64 return set(config, host, section, key, value);
65 end
66
67 function load(filename, format) 67 function load(filename, format)
68 format = format or filename:match("%w+$"); 68 format = format or filename:match("%w+$");
69 69
70 if parsers[format] and parsers[format].load then 70 if parsers[format] and parsers[format].load then
71 local f, err = io.open(filename); 71 local f, err = io.open(filename);
72 if f then 72 if f then
73 local ok, err = parsers[format].load(f:read("*a"), filename); 73 local new_config, err = parsers[format].load(f:read("*a"), filename);
74 f:close(); 74 f:close();
75 if ok then 75 if new_config then
76 fire_event("config-reloaded", { filename = filename, format = format }); 76 setmetatable(new_config, config_mt);
77 end 77 config = new_config;
78 return ok, "parser", err; 78 fire_event("config-reloaded", {
79 filename = filename,
80 format = format,
81 config = config
82 });
83 end
84 return not not new_config, "parser", err;
79 end 85 end
80 return f, "file", err; 86 return f, "file", err;
81 end 87 end
82 88
83 if not format then 89 if not format then
109 do 115 do
110 local loadstring, pcall, setmetatable = _G.loadstring, _G.pcall, _G.setmetatable; 116 local loadstring, pcall, setmetatable = _G.loadstring, _G.pcall, _G.setmetatable;
111 local setfenv, rawget, tostring = _G.setfenv, _G.rawget, _G.tostring; 117 local setfenv, rawget, tostring = _G.setfenv, _G.rawget, _G.tostring;
112 parsers.lua = {}; 118 parsers.lua = {};
113 function parsers.lua.load(data, filename) 119 function parsers.lua.load(data, filename)
120 local config = { ["*"] = { core = {} } };
121
114 local env; 122 local env;
115 -- The ' = true' are needed so as not to set off __newindex when we assign the functions below 123 -- The ' = true' are needed so as not to set off __newindex when we assign the functions below
116 env = setmetatable({ 124 env = setmetatable({
117 Host = true, host = true, VirtualHost = true, 125 Host = true, host = true, VirtualHost = true,
118 Component = true, component = true, 126 Component = true, component = true,
122 function (settings_table) 130 function (settings_table)
123 config[__currenthost or "*"][k] = settings_table; 131 config[__currenthost or "*"][k] = settings_table;
124 end; 132 end;
125 end, 133 end,
126 __newindex = function (t, k, v) 134 __newindex = function (t, k, v)
127 set(env.__currenthost or "*", "core", k, v); 135 set(config, env.__currenthost or "*", "core", k, v);
128 end 136 end
129 }); 137 });
130 138
131 rawset(env, "__currenthost", "*") -- Default is global 139 rawset(env, "__currenthost", "*") -- Default is global
132 function env.VirtualHost(name) 140 function env.VirtualHost(name)
134 error(format("Host %q clashes with previously defined %s Component %q, for services use a sub-domain like conference.%s", 142 error(format("Host %q clashes with previously defined %s Component %q, for services use a sub-domain like conference.%s",
135 name, config[name].core.component_module:gsub("^%a+$", { component = "external", muc = "MUC"}), name, name), 0); 143 name, config[name].core.component_module:gsub("^%a+$", { component = "external", muc = "MUC"}), name, name), 0);
136 end 144 end
137 rawset(env, "__currenthost", name); 145 rawset(env, "__currenthost", name);
138 -- Needs at least one setting to logically exist :) 146 -- Needs at least one setting to logically exist :)
139 set(name or "*", "core", "defined", true); 147 set(config, name or "*", "core", "defined", true);
140 return function (config_options) 148 return function (config_options)
141 rawset(env, "__currenthost", "*"); -- Return to global scope 149 rawset(env, "__currenthost", "*"); -- Return to global scope
142 for option_name, option_value in pairs(config_options) do 150 for option_name, option_value in pairs(config_options) do
143 set(name or "*", "core", option_name, option_value); 151 set(config, name or "*", "core", option_name, option_value);
144 end 152 end
145 end; 153 end;
146 end 154 end
147 env.Host, env.host = env.VirtualHost, env.VirtualHost; 155 env.Host, env.host = env.VirtualHost, env.VirtualHost;
148 156
149 function env.Component(name) 157 function env.Component(name)
150 if rawget(config, name) and rawget(config[name].core, "defined") and not rawget(config[name].core, "component_module") then 158 if rawget(config, name) and rawget(config[name].core, "defined") and not rawget(config[name].core, "component_module") then
151 error(format("Component %q clashes with previously defined Host %q, for services use a sub-domain like conference.%s", 159 error(format("Component %q clashes with previously defined Host %q, for services use a sub-domain like conference.%s",
152 name, name, name), 0); 160 name, name, name), 0);
153 end 161 end
154 set(name, "core", "component_module", "component"); 162 set(config, name, "core", "component_module", "component");
155 -- Don't load the global modules by default 163 -- Don't load the global modules by default
156 set(name, "core", "load_global_modules", false); 164 set(config, name, "core", "load_global_modules", false);
157 rawset(env, "__currenthost", name); 165 rawset(env, "__currenthost", name);
158 local function handle_config_options(config_options) 166 local function handle_config_options(config_options)
159 rawset(env, "__currenthost", "*"); -- Return to global scope 167 rawset(env, "__currenthost", "*"); -- Return to global scope
160 for option_name, option_value in pairs(config_options) do 168 for option_name, option_value in pairs(config_options) do
161 set(name or "*", "core", option_name, option_value); 169 set(config, name or "*", "core", option_name, option_value);
162 end 170 end
163 end 171 end
164 172
165 return function (module) 173 return function (module)
166 if type(module) == "string" then 174 if type(module) == "string" then
167 set(name, "core", "component_module", module); 175 set(config, name, "core", "component_module", module);
168 return handle_config_options; 176 return handle_config_options;
169 end 177 end
170 return handle_config_options(module); 178 return handle_config_options(module);
171 end 179 end
172 end 180 end
196 204
197 if not ok then 205 if not ok then
198 return nil, err; 206 return nil, err;
199 end 207 end
200 208
201 return true; 209 return config;
202 end 210 end
203 211
204 end 212 end
205 213
206 return _M; 214 return _M;