File

mod_inotify_reload/mod_inotify_reload.lua @ 2608:362ca94192ee

mod_smacks: Add resumed session to event "smacks-hibernation-end" Older versions of this event only have the "intermediate" session in event.session (the one used to resume the existing session), but not the resumed one. This adds event.resumed which contains the resumed one alongside to event.session.
author tmolitor <thilo@eightysoft.de>
date Sat, 11 Mar 2017 01:37:28 +0100
parent 744:ab988e98a9f9
child 5395:82207f936f1f
line wrap: on
line source

-- mod_inotify_reload
-- Reloads modules when their files change
-- Depends on linotify: https://github.com/hoelzro/linotify

module:set_global();

local inotify = require "inotify";
local modulemanager = require "core.modulemanager";

local inh = inotify.init();

local watches = {};
local watch_ids = {};

-- Fake socket object around inotify
local inh_conn = {
	getfd = function () return inh:fileno(); end;
	dirty = function (self) return false; end;
	settimeout = function () end;
	send = function (_, d) return #d, 0; end;
	close = function () end;
	receive = function ()
		local events = inh:read();
		for _, event in ipairs(events) do
			local mod = watches[watch_ids[event.wd]];
			if mod then
				local host, name = mod.host, mod.name;
				module:log("debug", "Reloading changed module mod_%s on %s", name, host);
				modulemanager.reload(host, name);
			else
				module:log("warn", "no watch for %d", event.wd);
			end
		end
		return "";
	end
};
require "net.server".wrapclient(inh_conn, "inotify", inh:fileno(), {
	onincoming = function () end, ondisconnect = function () end
}, "*a");

function watch_module(name, host, path)
	local id, err = inh:addwatch(path, inotify.IN_CLOSE_WRITE);
	if not id then return nil, err; end
	local k = host.."\0"..name;
	watches[k] = { id = id, path = path, name = name, host = host };
	watch_ids[id] = k;
	module:log("debug", "Watching %s:%s with id %d", name, host, id);
	return true;
end

function unwatch_module(name, host)
	local k = host.."\0"..name;
	if not watches[k] then
		module:log("warn", "Not watching %s:%s", name, host);
		return nil, "not-watching";
	end
	local id = watches[k].id;
	local ok, err = inh:rmwatch(id);
	module:log("info", "Removed watch %d", id);
	watches[k] = nil;
	watch_ids[id] = nil;
	return ok, err;
end

function module_loaded(event)
	local host, name = event.host, event.module;
	local path = modulemanager.get_module(host, name).module.path;
	if not path then
		module:log("warn", "Couldn't watch mod_%s, no path", name);
		return;
	end
	if watch_module(name, host, path) then
		module:log("debug", "Watching mod_%s", name);
	end
end

function module_unloaded(event)
	unwatch_module(event.module, event.host);
end

function module.add_host(module)
	module:hook("module-loaded", module_loaded);
	module:hook("module-unloaded", module_unloaded);
end

module:hook("module-loaded", module_loaded);
module:hook("module-unloaded", module_unloaded);