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

Reply via email to