support for live reloading of DSM scripts, preloading of modules, registering of applications, listing DSMs

git-svn-id: http://svn.berlios.de/svnroot/repos/sems/trunk@1551 8eb893ce-cfd4-0310-b710-fb5ebe64c474
sayer/1.4-spce2.6
Stefan Sayer 17 years ago
parent 850dec4500
commit 612e1754fc

@ -77,6 +77,8 @@ DSMFactory::DSMFactory(const string& _app_name)
loaded(false)
{
AmEventDispatcher::instance()->addEventQueue("dsm", this);
diags = new DSMStateDiagramCollection();
}
void DSMFactory::postEvent(AmEvent* e) {
@ -183,32 +185,20 @@ int DSMFactory::onLoad()
string ModPath = cfg.getParameter("mod_path");
string preload_mods = cfg.getParameter("preload_mods");
vector<string> preload_names = explode(preload_mods, ",");
if (preload_names.size()) {
for (vector<string>::iterator it=
preload_names.begin(); it != preload_names.end(); it++) {
DBG("preloading '%s'...\n", it->c_str());
if (!preload_reader.importModule("import("+*it+")", ModPath)) {
ERROR("importing module '%s' for preload\n", it->c_str());
return -1;
}
DSMModule* last_loaded = preload_reader.mods.back();
if (last_loaded) {
if (last_loaded->preload()) {
DBG("Error while preloading '%s'\n", it->c_str());
return -1;
}
}
}
string err;
int res = preloadModules(cfg, err, ModPath);
if (res<0) {
ERROR("%s\n", err.c_str());
return res;
}
// todo: pass preloaded mods to chart reader
string LoadDiags = cfg.getParameter("load_diags");
vector<string> diags_names = explode(LoadDiags, ",");
for (vector<string>::iterator it=
diags_names.begin(); it != diags_names.end(); it++) {
if (!diags.loadFile(DiagPath+*it+".dsm", *it, ModPath)) {
if (!diags->loadFile(DiagPath+*it+".dsm", *it, ModPath)) {
ERROR("loading %s from %s\n",
it->c_str(), (DiagPath+*it+".dsm").c_str());
return -1;
@ -219,7 +209,7 @@ int DSMFactory::onLoad()
vector<string> register_names = explode(RegisterDiags, ",");
for (vector<string>::iterator it=
register_names.begin(); it != register_names.end(); it++) {
if (diags.hasDiagram(*it)) {
if (diags->hasDiagram(*it)) {
bool res = AmPlugIn::instance()->registerFactory4App(*it,this);
if(res)
INFO("DSM state machine registered: %s.\n",
@ -448,7 +438,10 @@ AmSession* DSMFactory::onInvite(const AmSipRequest& req)
} else {
start_diag = req.cmd;
}
DSMCall* s = new DSMCall(&prompts, diags, start_diag, NULL);
diags_mut.lock();
DSMCall* s = new DSMCall(&prompts, *diags, start_diag, NULL);
diags_mut.unlock();
prepareSession(s);
addVariables(s, "config.", config);
@ -503,7 +496,7 @@ AmSession* DSMFactory::onInvite(const AmSipRequest& req,
AmArg2DSMStrMap(session_params, vars);
}
DSMCall* s = new DSMCall(&prompts, diags, start_diag, cred);
DSMCall* s = new DSMCall(&prompts, *diags, start_diag, cred);
prepareSession(s);
addVariables(s, "config.", config);
@ -532,11 +525,206 @@ AmSession* DSMFactory::onInvite(const AmSipRequest& req,
return s;
}
void DSMFactory::reloadDSMs(const AmArg& args, AmArg& ret) {
DSMStateDiagramCollection* new_diags = new DSMStateDiagramCollection();
AmConfigReader cfg;
if(cfg.loadFile(AmConfig::ModConfigPath + string(MOD_NAME ".conf"))) {
ret.push(500);
ret.push("loading config file " +AmConfig::ModConfigPath + string(MOD_NAME ".conf"));
return ;
}
string DiagPath = cfg.getParameter("diag_path");
if (DiagPath.length() && DiagPath[DiagPath.length()-1] != '/')
DiagPath += '/';
string ModPath = cfg.getParameter("mod_path");
string LoadDiags = cfg.getParameter("load_diags");
vector<string> diags_names = explode(LoadDiags, ",");
for (vector<string>::iterator it=
diags_names.begin(); it != diags_names.end(); it++) {
if (!new_diags->loadFile(DiagPath+*it+".dsm", *it, ModPath)) {
ERROR("loading %s from %s\n",
it->c_str(), (DiagPath+*it+".dsm").c_str());
ret.push(500);
ret.push("loading " +*it+ " from "+ DiagPath+*it+".dsm");
return;
}
}
diags_mut.lock();
DSMStateDiagramCollection* old_diags = diags;
diags = new_diags;
diags_mut.unlock();
DBG("deleting old diagram collection\n");
delete old_diags;
ret.push(200);
ret.push("DSMs reloaded");
}
int DSMFactory::preloadModules(AmConfigReader& cfg, string& res, const string& ModPath) {
string preload_mods = cfg.getParameter("preload_mods");
vector<string> preload_names = explode(preload_mods, ",");
if (preload_names.size()) {
for (vector<string>::iterator it=
preload_names.begin(); it != preload_names.end(); it++) {
DBG("preloading '%s'...\n", it->c_str());
if (!preload_reader.importModule("import("+*it+")", ModPath)) {
res = "importing module '"+*it+"' for preload\n";
return -1;
}
DSMModule* last_loaded = preload_reader.mods.back();
if (last_loaded) {
if (last_loaded->preload()) {
res = "Error while preloading '"+*it+"'\n";
return -1;
}
}
}
}
return 0;
}
void DSMFactory::preloadModules(const AmArg& args, AmArg& ret) {
AmConfigReader cfg;
if(cfg.loadFile(AmConfig::ModConfigPath + string(MOD_NAME ".conf"))) {
ret.push(500);
ret.push("loading config file " +AmConfig::ModConfigPath + string(MOD_NAME ".conf"));
return ;
}
string err;
string ModPath = cfg.getParameter("mod_path");
int res = preloadModules(cfg, err, ModPath);
if (res<0) {
ret.push(500);
ret.push(err);
} else {
ret.push(200);
ret.push("modules preloaded");
}
}
void DSMFactory::preloadModule(const AmArg& args, AmArg& ret) {
string mod_name = args.get(0).asCStr();
string mod_path = args.get(1).asCStr();
if (!preload_reader.importModule("import("+mod_name+")", mod_path)) {
ret.push(500);
ret.push("importing module '"+mod_name+"' for preload");
return;
}
DSMModule* last_loaded = preload_reader.mods.back();
if (last_loaded) {
if (last_loaded->preload()) {
ret.push(500);
ret.push("Error while preloading '"+mod_name+"'");
return;
}
}
ret.push(200);
ret.push("module preloaded.");
return;
}
void DSMFactory::listDSMs(const AmArg& args, AmArg& ret) {
diags_mut.lock();
vector<string> names = diags->getDiagramNames();
diags_mut.unlock();
for (vector<string>::iterator it=
names.begin(); it != names.end(); it++) {
ret.push(*it);
}
}
void DSMFactory::hasDSM(const AmArg& args, AmArg& ret) {
diags_mut.lock();
bool res = diags->hasDiagram(args.get(0).asCStr());
diags_mut.unlock();
if (res)
ret.push("1");
else
ret.push("0");
}
void DSMFactory::registerApplication(const AmArg& args, AmArg& ret) {
string diag_name = args.get(0).asCStr();
diags_mut.lock();
bool has_diag = diags->hasDiagram(diag_name);
diags_mut.unlock();
if (!has_diag) {
ret.push(400);
ret.push("unknown application (DSM)");
return;
}
bool res = AmPlugIn::instance()->registerFactory4App(diag_name,this);
if(res) {
INFO("DSM state machine registered: %s.\n",diag_name.c_str());
ret.push(200);
ret.push("registered DSM application");
} else {
ret.push(500);
ret.push("Error registering DSM application (already registered?)");
}
}
void DSMFactory::loadDSM(const AmArg& args, AmArg& ret) {
string dsm_name = args.get(0).asCStr();
AmConfigReader cfg;
if(cfg.loadFile(AmConfig::ModConfigPath + string(MOD_NAME ".conf"))) {
ret.push(500);
ret.push("loading config file " +AmConfig::ModConfigPath + string(MOD_NAME ".conf"));
return ;
}
string DiagPath = cfg.getParameter("diag_path");
if (DiagPath.length() && DiagPath[DiagPath.length()-1] != '/')
DiagPath += '/';
string ModPath = cfg.getParameter("mod_path");
string dsm_file_name = DiagPath+dsm_name+".dsm";
string res = "OK";
diags_mut.lock();
if (!diags->loadFile(dsm_file_name, dsm_name, ModPath)) {
ret.push(500);
ret.push("error loading "+dsm_name+" from "+ dsm_file_name);
} else {
ret.push(200);
ret.push("loaded "+dsm_name+" from "+ dsm_file_name);
}
diags_mut.unlock();
}
void DSMFactory::loadDSMWithPaths(const AmArg& args, AmArg& ret) {
string dsm_name = args.get(0).asCStr();
string diag_path = args.get(1).asCStr();
string mod_path = args.get(2).asCStr();
string res = "OK";
diags_mut.lock();
if (!diags->loadFile(diag_path+dsm_name+".dsm", dsm_name, mod_path)) {
ret.push(500);
ret.push("error loading "+dsm_name+" from "+ diag_path+dsm_name+".dsm");
} else {
ret.push(200);
ret.push("loaded "+dsm_name+" from "+ diag_path+dsm_name+".dsm");
}
diags_mut.unlock();
}
void DSMFactory::invoke(const string& method, const AmArg& args,
AmArg& ret)
{
if(method == "postDSMEvent"){
if (method == "postDSMEvent"){
assertArgCStr(args.get(0))
DSMEvent* ev = new DSMEvent();
@ -550,9 +738,37 @@ void DSMFactory::invoke(const string& method, const AmArg& args,
ret.push(AmArg(404));
ret.push(AmArg("Session not found"));
}
} else if (method == "reloadDSMs"){
reloadDSMs(args,ret);
} else if (method == "loadDSM"){
args.assertArrayFmt("s");
loadDSM(args,ret);
} else if (method == "loadDSMWithPath"){
args.assertArrayFmt("sss");
loadDSMWithPaths(args,ret);
} else if (method == "preloadModules"){
preloadModules(args,ret);
} else if (method == "preloadModule"){
args.assertArrayFmt("ss");
preloadModule(args,ret);
} else if (method == "hasDSM"){
args.assertArrayFmt("s");
hasDSM(args,ret);
} else if (method == "listDSMs"){
listDSMs(args,ret);
} else if (method == "registerApplication"){
args.assertArrayFmt("s");
registerApplication(args,ret);
} else if(method == "_list"){
ret.push(AmArg("postDSMEvent"));
ret.push(AmArg("reloadDSMs"));
ret.push(AmArg("loadDSM"));
ret.push(AmArg("loadDSMWithPaths"));
ret.push(AmArg("preloadModules"));
ret.push(AmArg("preloadModule"));
ret.push(AmArg("hasDSM"));
ret.push(AmArg("listDSMs"));
ret.push(AmArg("registerApplication"));
} else
throw AmDynInvoke::NotImplemented(method);
}

@ -60,7 +60,8 @@ class DSMFactory
public AmEventQueueInterface
{
AmPromptCollection prompts;
DSMStateDiagramCollection diags;
DSMStateDiagramCollection* diags;
AmMutex diags_mut;
static string InboundStartDiag;
static string OutboundStartDiag;
@ -83,6 +84,18 @@ class DSMFactory
void addParams(DSMCall* s, const string& hdrs);
DSMChartReader preload_reader;
void listDSMs(const AmArg& args, AmArg& ret);
void hasDSM(const AmArg& args, AmArg& ret);
void reloadDSMs(const AmArg& args, AmArg& ret);
void preloadModules(const AmArg& args, AmArg& ret);
void preloadModule(const AmArg& args, AmArg& ret);
void loadDSM(const AmArg& args, AmArg& ret);
void loadDSMWithPaths(const AmArg& args, AmArg& ret);
void registerApplication(const AmArg& args, AmArg& ret);
int preloadModules(AmConfigReader& cfg, string& res, const string& ModPath);
public:
static DSMFactory* instance();

@ -78,6 +78,14 @@ bool DSMStateDiagramCollection::hasDiagram(const string& name) {
return false;
}
vector<string> DSMStateDiagramCollection::getDiagramNames() {
vector<string> res;
for (vector<DSMStateDiagram>::iterator it=
diags.begin(); it != diags.end(); it++)
res.push_back(it->getName());
return res;
}
void DSMStateDiagramCollection::addToEngine(DSMStateEngine* e) {
DBG("adding %zd diags to engine\n", diags.size());
for (vector <DSMStateDiagram>::iterator it =

@ -46,6 +46,7 @@ class DSMStateDiagramCollection
bool loadFile(const string& filename, const string& name, const string& mod_path);
void addToEngine(DSMStateEngine* e);
bool hasDiagram(const string& name);
vector<string> getDiagramNames();
};
#endif

@ -44,10 +44,49 @@ A patch for fmsc 1.0.4 from the graphical FSM editor fsme
(http://fsme.sf.net) is available, so DSMs can be defined in
click-n-drag fashion and compiled to SEMS DSM diagrams.
DI commands
===========
postDSMEvent(string call_id, [ [[param0,val0],[param1,val1],...] ]
post a DSM event into a call. can be used to interact with running
calls in DSM. See DSM + monitoring + DI example in
examples/dsm_di_monit.
Example:
s.postDSMEvent(call_id, [['action', 'take'],['roomname', 'realworld']])
reloadDSMs()
reload all DSMs from config file (load_diags)
loadDSM(string diag_name)
load DSM with name diag_name, paths are taken from config file
loadDSMWithPaths(string diag_name, string diag_path, string mod_path)
load DSM with specified paths
preloadModules()
preload all modules specified in config file (preload_mods)
preloadModule(string mod_name, string mod_path)
preload module from specific path
hasDSM(string diag_name)
returns 1 if DSM with diag_name is loaded, 0 if not
listDSMs()
return list of loaded DSMs
registerApplication(string diag_name)
register DSM with name diag_name as application in SEMS
(e.g. to be used with application=$(apphdr), $(ruri.param)
or $(ruri.user)
More info
=========
o doc/dsm_syntax.txt has a quick reference for dsm syntax
o doc/examples/ and lib/ some example DSMs
o doc/examples/dsm_di_monit example on interfacing with DSM
o mods/ (will) have modules
Internals

Loading…
Cancel
Save