modules.nas: change reload trigger from property to fgcommand, fix a logprint call, add module name to debug output
This commit is contained in:
parent
1035ed4269
commit
251a376f68
1 changed files with 61 additions and 66 deletions
|
@ -5,7 +5,7 @@
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
# modules.nas allowes to load and unload Nasal modules at runtime (e.g. without
|
# modules.nas allowes to load and unload Nasal modules at runtime (e.g. without
|
||||||
# restarting Flightgear as a whole). It implements resource tracking for
|
# restarting Flightgear as a whole). It implements resource tracking for
|
||||||
# setlistener and maketimer to make unloading easier
|
# setlistener and maketimer to make unloading easier.
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
# Example - generic module load:
|
# Example - generic module load:
|
||||||
#
|
#
|
||||||
|
@ -22,9 +22,9 @@
|
||||||
# my_foo_sys.setMainFile("foo.nas");
|
# my_foo_sys.setMainFile("foo.nas");
|
||||||
# my_foo_sys.load();
|
# my_foo_sys.load();
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
|
|
||||||
var MODULES_DIR = getprop("/sim/fg-root")~"/Nasal/modules/";
|
var MODULES_DIR = getprop("/sim/fg-root")~"/Nasal/modules/";
|
||||||
var MODULES_NODE = nil;
|
var MODULES_NODE = nil;
|
||||||
|
var MODULES_DEFAULT_FILENAME = "main.nas";
|
||||||
var _modules_available = {};
|
var _modules_available = {};
|
||||||
|
|
||||||
# Hash storing Module objects; keep this outside Module to avoid stack overflow
|
# Hash storing Module objects; keep this outside Module to avoid stack overflow
|
||||||
|
@ -43,7 +43,7 @@ var Module = {
|
||||||
# node: optional property node for module management
|
# node: optional property node for module management
|
||||||
new: func(id, ns = "", node = nil) {
|
new: func(id, ns = "", node = nil) {
|
||||||
if (!id or typeof(id) != "scalar") {
|
if (!id or typeof(id) != "scalar") {
|
||||||
logprint(5, "Module.new(): id: must be a string without special characters or spaces");
|
logprint(LOG_ALERT, "Module.new(): id: must be a string without special characters or spaces");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_instances[id] != nil) {
|
if (_instances[id] != nil) {
|
||||||
|
@ -58,7 +58,7 @@ var Module = {
|
||||||
id: id,
|
id: id,
|
||||||
version: 1,
|
version: 1,
|
||||||
file_path: MODULES_DIR,
|
file_path: MODULES_DIR,
|
||||||
main_file: "main.nas",
|
main_file: MODULES_DEFAULT_FILENAME,
|
||||||
namespace: ns ? ns : id,
|
namespace: ns ? ns : id,
|
||||||
node: nil,
|
node: nil,
|
||||||
};
|
};
|
||||||
|
@ -67,26 +67,17 @@ var Module = {
|
||||||
} else {
|
} else {
|
||||||
obj.node = MODULES_NODE.getNode(id, 1);
|
obj.node = MODULES_NODE.getNode(id, 1);
|
||||||
}
|
}
|
||||||
obj.reloadN = obj.node.initNode("reload", 0, "BOOL");
|
|
||||||
obj.loadedN = obj.node.initNode("loaded", 0, "BOOL");
|
obj.loadedN = obj.node.initNode("loaded", 0, "BOOL");
|
||||||
obj.lcountN = obj.node.initNode("listeners", 0, "INT");
|
obj.lcountN = obj.node.initNode("listeners", 0, "INT");
|
||||||
obj.tcountN = obj.node.initNode("timers", 0, "INT");
|
obj.tcountN = obj.node.initNode("timers", 0, "INT");
|
||||||
obj.lhitN = obj.node.initNode("listener-hits", 0, "INT");
|
obj.lhitN = obj.node.initNode("listener-hits", 0, "INT");
|
||||||
|
|
||||||
obj.reloadL = setlistener(obj.reloadN, func(n) {
|
|
||||||
if (n.getValue()) {
|
|
||||||
n.setValue(0);
|
|
||||||
logprint(3, "Reload listener for ", obj.id, " triggered (",
|
|
||||||
obj.reloadL, ")");
|
|
||||||
obj.reload();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
_instances[id] = obj;
|
_instances[id] = obj;
|
||||||
return obj;
|
return obj;
|
||||||
},
|
},
|
||||||
|
|
||||||
getNode: func { return me.node; },
|
getNode: func { return me.node; },
|
||||||
getReloadNode: func { return me.reloadN; },
|
|
||||||
getNamespaceName: func { return me.namespace; },
|
getNamespaceName: func { return me.namespace; },
|
||||||
getNamespace: func { return globals[me.namespace]; },
|
getNamespace: func { return globals[me.namespace]; },
|
||||||
getFilePath: func { return me.file_path; },
|
getFilePath: func { return me.file_path; },
|
||||||
|
@ -98,7 +89,7 @@ var Module = {
|
||||||
|
|
||||||
setDebug: func (debug = 1) {
|
setDebug: func (debug = 1) {
|
||||||
me._debug = debug;
|
me._debug = debug;
|
||||||
logprint(4, "Module "~me.id~" debug = "~debug);
|
logprint(DEV_WARN, "Module "~me.id~" debug = "~debug);
|
||||||
},
|
},
|
||||||
|
|
||||||
setFilePath: func(path) {
|
setFilePath: func(path) {
|
||||||
|
@ -116,7 +107,7 @@ var Module = {
|
||||||
me.main_file = filename;
|
me.main_file = filename;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
logprint("4", "setMainFile() needs a string parameter");
|
logprint(LOG_WARN, "setMainFile() needs a string parameter");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -125,7 +116,7 @@ var Module = {
|
||||||
me.namespace = ns;
|
me.namespace = ns;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
logprint("4", "setNamespace() needs a string parameter");
|
logprint(LOG_WARN, "setNamespace() needs a string parameter");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -136,7 +127,7 @@ var Module = {
|
||||||
if (globals[me.namespace] == nil) {
|
if (globals[me.namespace] == nil) {
|
||||||
globals[me.namespace] = {};
|
globals[me.namespace] = {};
|
||||||
}
|
}
|
||||||
logprint(5, "Module.load() ", me.id);
|
logprint(LOG_INFO, "Module.load() ", me.id);
|
||||||
me.lcountN.setIntValue(0);
|
me.lcountN.setIntValue(0);
|
||||||
me.tcountN.setIntValue(0);
|
me.tcountN.setIntValue(0);
|
||||||
me.lhitN.setIntValue(0);
|
me.lhitN.setIntValue(0);
|
||||||
|
@ -163,36 +154,38 @@ var Module = {
|
||||||
}
|
}
|
||||||
return me;
|
return me;
|
||||||
}
|
}
|
||||||
else { return nil; }
|
else { # loading failed
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
# unload a module and remove its tracked resources
|
# unload a module and remove its tracked resources
|
||||||
unload: func() {
|
unload: func() {
|
||||||
if (!me.loadedN.getValue()) {
|
if (!me.loadedN.getValue()) {
|
||||||
logprint(5, "! ", me.id, " was not fully loaded.");
|
logprint(DEV_ALERT, "! ", me.id, " was not fully loaded.");
|
||||||
}
|
}
|
||||||
if (globals[me.namespace] != nil
|
if (globals[me.namespace] != nil
|
||||||
and typeof(globals[me.namespace]) == "hash")
|
and typeof(globals[me.namespace]) == "hash")
|
||||||
{
|
{
|
||||||
logprint(5, "- Removing module ", me.id);
|
logprint(LOG_INFO, "- Removing module ", me.id);
|
||||||
if (globals[me.namespace]["setlistener"] != nil)
|
if (globals[me.namespace]["setlistener"] != nil)
|
||||||
globals[me.namespace]["setlistener"] = func {};
|
globals[me.namespace]["setlistener"] = func {};
|
||||||
foreach (var id; me._listeners) {
|
foreach (var id; me._listeners) {
|
||||||
logprint(3, "Removing listener "~id);
|
logprint(DEV_WARN, "Removing listener "~id);
|
||||||
if (removelistener(id)) {
|
if (removelistener(id)) {
|
||||||
me.lcountN.setValue(me.lcountN.getValue() - 1);
|
me.lcountN.setValue(me.lcountN.getValue() - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
me._listeners = [];
|
me._listeners = [];
|
||||||
|
|
||||||
logprint(3, "Stopping timers ");
|
logprint(LOG_INFO, "Stopping timers ");
|
||||||
if (globals[me.namespace]["maketimer"] != nil)
|
if (globals[me.namespace]["maketimer"] != nil)
|
||||||
globals[me.namespace]["maketimer"] = func {};
|
globals[me.namespace]["maketimer"] = func {};
|
||||||
foreach (var t; me._timers) {
|
foreach (var t; me._timers) {
|
||||||
if (typeof(t.stop) == "func") {
|
if (typeof(t.stop) == "func") {
|
||||||
t.stop();
|
t.stop();
|
||||||
me.tcountN.setValue(me.tcountN.getValue() - 1);
|
me.tcountN.setValue(me.tcountN.getValue() - 1);
|
||||||
logprint(2, " .");
|
logprint(DEV_WARN, " .");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
me._timers = [];
|
me._timers = [];
|
||||||
|
@ -208,7 +201,7 @@ var Module = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
me.loadedN.setBoolValue(0);
|
me.loadedN.setBoolValue(0);
|
||||||
#kill namespace (replace with empty hash and hope GC cleans up behind us)
|
#kill namespace (and hope GC will clean up behind us)
|
||||||
globals[me.namespace] = nil;
|
globals[me.namespace] = nil;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -218,7 +211,7 @@ var Module = {
|
||||||
me.load();
|
me.load();
|
||||||
},
|
},
|
||||||
|
|
||||||
printTrackedResources: func(loglevel = 3) {
|
printTrackedResources: func(loglevel = LOG_INFO) {
|
||||||
logprint(loglevel, "Tracked resources after running the main() function of " ~
|
logprint(loglevel, "Tracked resources after running the main() function of " ~
|
||||||
me.id~":");
|
me.id~":");
|
||||||
logprint(loglevel, "#listeners: "~size(me._listeners));
|
logprint(loglevel, "#listeners: "~size(me._listeners));
|
||||||
|
@ -245,8 +238,8 @@ var Module = {
|
||||||
append(me._listeners, Module._orig_setlistener(p, f_debug, start, runtime));
|
append(me._listeners, Module._orig_setlistener(p, f_debug, start, runtime));
|
||||||
var c = caller(1);
|
var c = caller(1);
|
||||||
if (c != nil) {
|
if (c != nil) {
|
||||||
print(sprintf("setlistener for %s called from %s:%s",
|
print(sprintf("[%s] setlistener for %s called from %s:%s",
|
||||||
p.getPath(), io.basename(c[2]), c[3]));
|
me.namespace, p.getPath(), io.basename(c[2]), c[3]));
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
append(me._listeners, Module._orig_setlistener(p,
|
append(me._listeners, Module._orig_setlistener(p,
|
||||||
|
@ -266,14 +259,14 @@ var Module = {
|
||||||
append(me._timers,
|
append(me._timers,
|
||||||
Module._orig_maketimer(arg[0], arg[1], arg[2]));
|
Module._orig_maketimer(arg[0], arg[1], arg[2]));
|
||||||
} else {
|
} else {
|
||||||
logprint(5, "Invalid number of arguments to maketimer()");
|
logprint(DEV_ALERT, "Invalid number of arguments to maketimer()");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (me._debug) {
|
if (me._debug) {
|
||||||
var c = caller(1);
|
var c = caller(1);
|
||||||
if (c != nil) {
|
if (c != nil) {
|
||||||
print(sprintf("maketimer called from %s:%s",
|
print(sprintf("[%s] maketimer called from %s:%s",
|
||||||
io.basename(c[2]), c[3]));
|
me.namespace, io.basename(c[2]), c[3]));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
me.tcountN.setValue(me.tcountN.getValue() + 1);
|
me.tcountN.setValue(me.tcountN.getValue() + 1);
|
||||||
|
@ -285,7 +278,7 @@ var Module = {
|
||||||
_redirect_settimer: func() {
|
_redirect_settimer: func() {
|
||||||
globals[me.namespace].settimer = func() {
|
globals[me.namespace].settimer = func() {
|
||||||
var c = caller(1);
|
var c = caller(1);
|
||||||
logprint(5, sprintf("\n\Unsupported settimer() call from %s:%s. "~
|
logprint(DEV_ALERT, sprintf("\n\Unsupported settimer() call from %s:%s. "~
|
||||||
"Use maketimer() instead.",
|
"Use maketimer() instead.",
|
||||||
io.basename(c[2]), c[3]));
|
io.basename(c[2]), c[3]));
|
||||||
}
|
}
|
||||||
|
@ -326,6 +319,8 @@ var _findModules = func() {
|
||||||
var module_dirs = io.subdirectories(MODULES_DIR);
|
var module_dirs = io.subdirectories(MODULES_DIR);
|
||||||
_modules_available = {};
|
_modules_available = {};
|
||||||
foreach (var name; module_dirs) {
|
foreach (var name; module_dirs) {
|
||||||
|
if (!io.is_regular_file(MODULES_DIR~"/"~name~"/"~MODULES_DEFAULT_FILENAME))
|
||||||
|
break;
|
||||||
_modules_available[name] = 1;
|
_modules_available[name] = 1;
|
||||||
MODULES_NODE.getNode(name~"/available",1).setBoolValue(1);
|
MODULES_NODE.getNode(name~"/available",1).setBoolValue(1);
|
||||||
}
|
}
|
||||||
|
@ -342,7 +337,7 @@ var commandModuleReload = func(node)
|
||||||
var module = node.getChild("module").getValue();
|
var module = node.getChild("module").getValue();
|
||||||
var m = _getInstance(module);
|
var m = _getInstance(module);
|
||||||
if (m == nil) {
|
if (m == nil) {
|
||||||
logprint(5, "Unknown module to reload: %s", module);
|
logprint(LOG_WARN, "Unknown module to reload: "~module);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue