Author: sayer
Date: 2009-10-22 00:35:27 +0200 (Thu, 22 Oct 2009)
New Revision: 1551
Modified:
trunk/apps/dsm/DSM.cpp
trunk/apps/dsm/DSM.h
trunk/apps/dsm/DSMStateDiagramCollection.cpp
trunk/apps/dsm/DSMStateDiagramCollection.h
trunk/apps/dsm/doc/Readme.dsm.txt
Log:
support for live reloading of DSM scripts, preloading of modules, registering
of applications, listing DSMs
Modified: trunk/apps/dsm/DSM.cpp
===================================================================
--- trunk/apps/dsm/DSM.cpp 2009-10-21 21:56:32 UTC (rev 1550)
+++ trunk/apps/dsm/DSM.cpp 2009-10-21 22:35:27 UTC (rev 1551)
@@ -77,6 +77,8 @@
loaded(false)
{
AmEventDispatcher::instance()->addEventQueue("dsm", this);
+
+ diags = new DSMStateDiagramCollection();
}
void DSMFactory::postEvent(AmEvent* e) {
@@ -183,32 +185,20 @@
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 @@
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 @@
} 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 @@
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 @@
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 @@
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);
}
Modified: trunk/apps/dsm/DSM.h
===================================================================
--- trunk/apps/dsm/DSM.h 2009-10-21 21:56:32 UTC (rev 1550)
+++ trunk/apps/dsm/DSM.h 2009-10-21 22:35:27 UTC (rev 1551)
@@ -60,7 +60,8 @@
public AmEventQueueInterface
{
AmPromptCollection prompts;
- DSMStateDiagramCollection diags;
+ DSMStateDiagramCollection* diags;
+ AmMutex diags_mut;
static string InboundStartDiag;
static string OutboundStartDiag;
@@ -83,6 +84,18 @@
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();
Modified: trunk/apps/dsm/DSMStateDiagramCollection.cpp
===================================================================
--- trunk/apps/dsm/DSMStateDiagramCollection.cpp 2009-10-21 21:56:32 UTC
(rev 1550)
+++ trunk/apps/dsm/DSMStateDiagramCollection.cpp 2009-10-21 22:35:27 UTC
(rev 1551)
@@ -78,6 +78,14 @@
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 =
Modified: trunk/apps/dsm/DSMStateDiagramCollection.h
===================================================================
--- trunk/apps/dsm/DSMStateDiagramCollection.h 2009-10-21 21:56:32 UTC (rev
1550)
+++ trunk/apps/dsm/DSMStateDiagramCollection.h 2009-10-21 22:35:27 UTC (rev
1551)
@@ -46,6 +46,7 @@
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
Modified: trunk/apps/dsm/doc/Readme.dsm.txt
===================================================================
--- trunk/apps/dsm/doc/Readme.dsm.txt 2009-10-21 21:56:32 UTC (rev 1550)
+++ trunk/apps/dsm/doc/Readme.dsm.txt 2009-10-21 22:35:27 UTC (rev 1551)
@@ -44,10 +44,49 @@
(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
_______________________________________________
Semsdev mailing list
[email protected]
http://lists.iptel.org/mailman/listinfo/semsdev