Comparison

mod_inotify_reload/mod_inotify_reload.lua @ 652:3e6f43ab7e22

mod_inotify_reload: Reload modules when their code changes
author Matthew Wild <mwild1@gmail.com>
date Sun, 29 Apr 2012 16:57:21 +0100
child 744:ab988e98a9f9
comparison
equal deleted inserted replaced
651:78a23a7dc613 652:3e6f43ab7e22
1 -- mod_inotify_reload
2 -- Reloads modules when their files change
3 -- Depends on linotify: https://github.com/hoelzro/linotify
4
5 module:set_global();
6
7 local inotify = require "inotify";
8 local modulemanager = require "core.modulemanager";
9
10 local inh = inotify.init();
11
12 local watches = {};
13 local watch_ids = {};
14
15 -- Fake socket object around inotify
16 local inh_conn = {
17 getfd = function () return inh:fileno(); end;
18 dirty = function (self) return false; end;
19 settimeout = function () end;
20 send = function (_, d) return #d, 0; end;
21 close = function () end;
22 receive = function ()
23 local events = inh:read();
24 for _, event in ipairs(events) do
25 local mod = watches[watch_ids[event.wd]];
26 if mod then
27 local host, name = mod.host, mod.name;
28 module:log("debug", "Reloading changed module mod_%s on %s", name, host);
29 modulemanager.reload(host, name);
30 else
31 module:log("warn", "no watch for %d", event.wd);
32 end
33 end
34 return "";
35 end
36 };
37 require "net.server".wrapclient(inh_conn, "inotify", inh:fileno(), {
38 onincoming = function () end, ondisconnect = function () end
39 }, "*a");
40
41 function watch_module(name, host, path)
42 local id, err = inh:addwatch(path, inotify.IN_CLOSE_WRITE);
43 if not id then return nil, err; end
44 local k = host.."\0"..name;
45 watches[k] = { id = id, path = path, name = name, host = host };
46 watch_ids[id] = k;
47 return true;
48 end
49
50 function unwatch_module(name, host)
51 local k = host.."\0"..name;
52 if not watches[k] then
53 return nil, "not-watching";
54 end
55 local id = watches[k].id;
56 local ok, err = inh:rmwatch(id);
57 watches[k] = nil;
58 watch_ids[id] = nil;
59 return ok, err;
60 end
61
62 function module_loaded(event)
63 local host, name = event.host, event.module;
64 local path = modulemanager.get_module(host, name).module.path;
65 if not path then
66 module:log("warn", "Couldn't watch mod_%s, no path", name);
67 return;
68 end
69 if watch_module(name, host, path) then
70 module:log("debug", "Watching mod_%s", name);
71 end
72 end
73
74 function module_unloaded(event)
75 unwatch_module(event.module, event.host);
76 end
77
78 function module.add_host(module)
79 module:hook("module-loaded", module_loaded);
80 module:hook("module-unloaded", module_unloaded);
81 end
82
83 module:hook("module-loaded", module_loaded);
84 module:hook("module-unloaded", module_unloaded);
85