Software /
code /
prosody-modules
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 |