OriginHostManager to abstract Procedure (dyamic) from knowing the OriginHost node
authorEduardo Ramos Testillano <eduardo.ramos.testillano@ericsson.com>
Mon, 26 Jun 2017 10:21:17 +0000 (12:21 +0200)
committerEduardo Ramos Testillano <eduardo.ramos.testillano@ericsson.com>
Mon, 26 Jun 2017 10:22:43 +0000 (12:22 +0200)
dynamic/launcher/default/Procedure.cpp
dynamic/launcher/default/Procedure.hpp
dynamic/launcher/gx/00001/Procedure.cpp
dynamic/launcher/gx/00001/Procedure.hpp
example/diameter/launcher/Launcher.cpp
example/diameter/launcher/Launcher.hpp
include/anna/diameter.comm/OriginHostManager.hpp [new file with mode: 0644]
source/diameter.comm/OriginHostManager.cpp [new file with mode: 0644]

index 62b0ce2..598912e 100644 (file)
@@ -16,7 +16,7 @@
 // Local
 #include "Procedure.hpp"
 
-void Procedure::execute(const std::string &args, std::string &response, anna::diameter::comm::OriginHost *originHost) throw(anna::RuntimeException) {
+void Procedure::execute(const std::string &args, std::string &response) throw(anna::RuntimeException) {
   response = "Empty default implementation. Make dynamic library and reimplement this method.";
   if (args != "" ) {
     response += " Provided argument(s) ignored: ";
index c96ab07..b8096bc 100644 (file)
 #include <anna/comm/comm.hpp>
 
 
-namespace anna {
-  namespace diameter {
-    namespace comm {
-       class OriginHost;
-    }
-  }
-}
-
 class Procedure {
     anna::comm::Application *a_app;
 
   public:
     Procedure(anna::comm::Application *app) : a_app(app) {;}
 
-    virtual void execute(const std::string &args, std::string &response, anna::diameter::comm::OriginHost *originHost)  throw(anna::RuntimeException);
+    virtual void execute(const std::string &args, std::string &response)  throw(anna::RuntimeException);
 };
 
 #endif
index 086a074..20af42c 100644 (file)
@@ -18,6 +18,7 @@
 #include <anna/diameter/helpers/dcca/functions.hpp>
 #include <anna/diameter/helpers/dcca/functions.hpp>
 #include <anna/diameter.comm/OriginHost.hpp>
+#include <anna/diameter.comm/OriginHostManager.hpp>
 
 // Local
 #include "Procedure.hpp"
@@ -47,7 +48,7 @@ namespace {
    }
 }
 
-void Procedure::execute(const std::string &args, std::string &response, anna::diameter::comm::OriginHost *originHost)  throw(anna::RuntimeException) {
+void Procedure::execute(const std::string &args, std::string &response)  throw(anna::RuntimeException) {
 
   response = "Dynamic procedure failed to process '"; response += args; response += "': ";
 
@@ -93,6 +94,7 @@ void Procedure::execute(const std::string &args, std::string &response, anna::di
   anna::diameter::codec::Message ccri, ccrt;
   anna::diameter::codec::Avp *ccri_sessionId, *ccrt_sessionId, *ccri_framedIPAddress, *ccrt_framedIPAddress, *ccri_msisdn, *ccri_imsi;
   anna::diameter::codec::Avp *si1, *si2, *sidata1, *sidata2, *sitype1;
+  anna::diameter::codec::Avp *ccri_originHost;
 
   ///////// CCR-Initial:
   ccri.loadXML(ccr_i);
@@ -100,6 +102,7 @@ void Procedure::execute(const std::string &args, std::string &response, anna::di
   // Session-Id & Framed-Ip-Address AVPs
   ccri_sessionId = ccri.getAvp("Session-Id");
   ccri_framedIPAddress = ccri.getAvp("Framed-IP-Address");
+  ccri_originHost = ccri.getAvp("Origin-Host");
 
   // Subscription-Id AVPs
   if (ccri.countAvp("Subscription-Id") != 2) {
@@ -206,6 +209,12 @@ void Procedure::execute(const std::string &args, std::string &response, anna::di
   char cad_framed[16];
   anna::testing::TestCase *tc;
 
+  // Origin host manager:
+  anna::diameter::comm::OriginHostManager &ohm = anna::diameter::comm::OriginHostManager::instantiate();
+  // Assume the oh name from CCR-I (same as CCR-T):
+  std::string originHostName = ccri_originHost->getDiameterIdentity()->getValue();
+  anna::diameter::comm::OriginHost *originHost = ohm.getOriginHost(originHostName);
+
   for (ll_index = 0; ll_index < ll_seq_size; ll_index++) {
 
     // Calculate next values ////////////////////////////////////////////////////////////
index b46ef74..d6afe5b 100644 (file)
 #include <anna/comm/comm.hpp>
 
 
-namespace anna {
-  namespace diameter {
-    namespace comm {
-       class OriginHost;
-    }
-  }
-}
-
 class Procedure {
     anna::comm::Application *a_app;
 
   public:
     Procedure(anna::comm::Application *app) : a_app(app) {;}
 
-    virtual void execute(const std::string &args, std::string &response, anna::diameter::comm::OriginHost *originHost)  throw(anna::RuntimeException);
+    virtual void execute(const std::string &args, std::string &response)  throw(anna::RuntimeException);
 };
 
 #endif
index 871fcb3..cd20991 100644 (file)
 #include <anna/diameter.comm/ApplicationMessageOamModule.hpp>
 #include <anna/testing/defines.hpp>
 #include <anna/xml/xml.hpp>
+#include <anna/diameter.comm/OriginHost.hpp>
+#include <anna/diameter.comm/OriginHostManager.hpp>
 #include <Procedure.hpp>
 
 // Process
 #include <Launcher.hpp>
 #include <MyDiameterEngine.hpp>
-#include <anna/diameter.comm/OriginHost.hpp>
 #include <anna/testing/TestManager.hpp>
 #include <anna/testing/TestCase.hpp>
 
@@ -141,7 +142,6 @@ Launcher::Launcher() : anna::comm::Application("launcher", "DiameterLauncher", "
   //a_admlMinResolution = (anna::Millisecond)100;
   a_counterRecorderClock = NULL;
 
-  // a_originHosts.clear();
   a_workingNode = NULL;
 
   a_httpServerSocket = NULL;
@@ -302,8 +302,9 @@ void Launcher::servicesFromXML(const anna::xml::Node* servicesNode, bool eventOp
       burstLog = (*it)->getAttribute("burstLog", false /* no exception */); // (yes | no)
 
       // Basic checkings:
-      origin_hosts_it nodeIt = a_originHosts.find(originHost->getValue());
-      if (nodeIt != a_originHosts.end()) {
+      anna::diameter::comm::OriginHostManager &ohm = anna::diameter::comm::OriginHostManager::instantiate();
+      anna::diameter::comm::OriginHost *oh = ohm.getOriginHost(originHost->getValue());
+      if (oh) {
         std::string msg = "Already registered such Origin-Host: "; msg += originHost->getValue();
         throw anna::RuntimeException(msg, ANNA_FILE_LOCATION);
       }
@@ -416,7 +417,7 @@ void Launcher::servicesFromXML(const anna::xml::Node* servicesNode, bool eventOp
       if (eventOperation) commEngine->lazyInitialize();
 
       // Node and Codec Engine registration ///////////////////////////////////////////////////////
-      a_originHosts[originHost->getValue()] = a_workingNode;
+      ohm.registerOriginHost(originHost->getValue(), a_workingNode);
       /////////////////////////////////////////////////////////////////////////////////////////////
     }
   }
@@ -515,25 +516,25 @@ anna::Millisecond Launcher::checkTimeMeasure(const std::string &parameter, const
 bool Launcher::setWorkingNode(const std::string &name) throw() {
   bool result = false;
 
-  origin_hosts_it nodeIt = a_originHosts.find(name);
-  if (nodeIt == a_originHosts.end()) {
-    LOGWARNING(
-        std::string msg = "Unknown node with name '"; msg += name; msg += "'. Ignoring ...";
-    anna::Logger::warning(msg, ANNA_FILE_LOCATION);
-    );
-  }
-  else {
-    a_workingNode = const_cast<anna::diameter::comm::OriginHost*>(nodeIt->second);
+  anna::diameter::comm::OriginHostManager &ohm = anna::diameter::comm::OriginHostManager::instantiate();
+  anna::diameter::comm::OriginHost *oh = ohm.getOriginHost(name);
+
+  if (oh) {
+    a_workingNode = const_cast<anna::diameter::comm::OriginHost*>(oh);
     result = true;
   }
 
   return result;
 }
 
-anna::diameter::comm::OriginHost *Launcher::getOriginHost(const std::string &oh) const throw(anna::RuntimeException) {
-  origin_hosts_it it = a_originHosts.find(oh);
-  if (it != a_originHosts.end()) return it->second;
-  throw anna::RuntimeException(anna::functions::asString("There is no origin host registered as '%s' (set Origin-Host avp correctly or force a specific host with 'node' operation)", oh.c_str()), ANNA_FILE_LOCATION);
+anna::diameter::comm::OriginHost *Launcher::getOriginHost(const std::string &name) const throw(anna::RuntimeException) {
+  anna::diameter::comm::OriginHostManager &ohm = anna::diameter::comm::OriginHostManager::instantiate();
+  anna::diameter::comm::OriginHost *result = ohm.getOriginHost(name);
+
+  if (!result)
+  throw anna::RuntimeException(anna::functions::asString("There is no origin host registered as '%s' (set Origin-Host avp correctly or force a specific host with 'node' operation)", name.c_str()), ANNA_FILE_LOCATION);
+
+  return result;
 }
 
 anna::diameter::comm::OriginHost *Launcher::getOriginHost(const anna::diameter::codec::Message &message) const throw(anna::RuntimeException) {
@@ -541,6 +542,12 @@ anna::diameter::comm::OriginHost *Launcher::getOriginHost(const anna::diameter::
   return (getOriginHost(originHost));
 }
 
+bool Launcher::uniqueOriginHost() const throw() {
+  anna::diameter::comm::OriginHostManager &ohm = anna::diameter::comm::OriginHostManager::instantiate();
+  return (ohm.size() == 1);
+}
+
+
 void Launcher::updateOperatedOriginHostWithMessage(const anna::diameter::codec::Message &message) throw(anna::RuntimeException) {
   if (!a_operatedHost) // priority for working node by mean 'node' operation
     a_operatedHost = getOriginHost(message);
@@ -779,7 +786,8 @@ throw(anna::RuntimeException) {
 
   // Start client connections //////////////////////////////////////////////////////////////////////////////////
   MyDiameterEntity *entity;
-  for (origin_hosts_it it = a_originHosts.begin(); it != a_originHosts.end(); it++) {
+  anna::diameter::comm::OriginHostManager &ohm = anna::diameter::comm::OriginHostManager::instantiate();
+  for (diameter::comm::origin_hosts_it it = ohm.begin(); it != ohm.end(); it++) {
     entity = (MyDiameterEntity *)(it->second->getEntity());
     if (entity) entity->bind();
   }
@@ -839,7 +847,8 @@ void Launcher::resetStatistics() throw() {
     a_workingNode->getCommEngine()->resetStatistics();
   }
   else {
-    for (origin_hosts_it it = a_originHosts.begin(); it != a_originHosts.end(); it++) {
+    anna::diameter::comm::OriginHostManager &ohm = anna::diameter::comm::OriginHostManager::instantiate();
+    for (diameter::comm::origin_hosts_it it = ohm.begin(); it != ohm.end(); it++) {
       it->second->getCommEngine()->resetStatistics();
     }
   }
@@ -1593,7 +1602,7 @@ void Launcher::eventOperation(const std::string &operation, std::string &respons
     if (args == "" && op_size != 7)
       throw anna::RuntimeException("Wrong body content format on HTTP Request. Use 'help' management command to see more information.", ANNA_FILE_LOCATION);
     try {
-      p.execute(args, response_content, getWorkingNode());
+      p.execute(args, response_content);
     }
     catch(anna::RuntimeException &ex) {
       ex.trace();
@@ -2455,7 +2464,8 @@ throw() {
   result->createAttribute("InitialWorkingDirectory", a_initialWorkingDirectory);
   result->createAttribute("SecondsLifeTime", anna::time::functions::lapsedMilliseconds() / 1000);
   // Diameter:
-  for (origin_hosts_it it = a_originHosts.begin(); it != a_originHosts.end(); it++) {
+  anna::diameter::comm::OriginHostManager &ohm = anna::diameter::comm::OriginHostManager::instantiate();
+  for (diameter::comm::origin_hosts_it it = ohm.begin(); it != ohm.end(); it++) {
     it->second->asXML(result);
   }
 
index 7c3596c..1070e40 100644 (file)
@@ -65,7 +65,6 @@ class Launcher : public anna::comm::Application {
   MyCounterRecorderClock *a_counterRecorderClock;
 
   // Nodes deployment:
-  origin_hosts_t a_originHosts;
   anna::diameter::comm::OriginHost *a_workingNode;
   anna::diameter::comm::OriginHost *a_operatedHost; // auxiliary for eventOperation
 
@@ -90,9 +89,9 @@ public:
   void startServices() throw(anna::RuntimeException);
 
   bool setWorkingNode(const std::string &name) throw();
-  anna::diameter::comm::OriginHost *getOriginHost(const std::string &oh) const throw(anna::RuntimeException);
+  anna::diameter::comm::OriginHost *getOriginHost(const std::string &name) const throw(anna::RuntimeException);
   anna::diameter::comm::OriginHost *getOriginHost(const anna::diameter::codec::Message &message) const throw(anna::RuntimeException);
-  bool uniqueOriginHost() const throw() { return (a_originHosts.size() == 1); }
+  bool uniqueOriginHost() const throw();
 
   // Operated host for communication resources smart assignment ////////////////////////////////////////////////////////////
   void updateOperatedOriginHostWithMessage(const anna::diameter::codec::Message &message) throw(anna::RuntimeException);
diff --git a/include/anna/diameter.comm/OriginHostManager.hpp b/include/anna/diameter.comm/OriginHostManager.hpp
new file mode 100644 (file)
index 0000000..af5793b
--- /dev/null
@@ -0,0 +1,105 @@
+// ANNA - Anna is Not Nothingness Anymore                                                         //
+//                                                                                                //
+// (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo                         //
+//                                                                                                //
+// See project site at http://redmine.teslayout.com/projects/anna-suite                           //
+// See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
+
+
+#ifndef anna_diameter_comm_OriginHostManager_hpp
+#define anna_diameter_comm_OriginHostManager_hpp
+
+
+// Project
+#include <anna/core/Singleton.hpp>
+#include <anna/diameter/defines.hpp>
+
+// Standard
+#include <map>
+#include <string>
+
+
+namespace anna {
+
+namespace xml {
+  class Node;
+
+}
+namespace diameter {
+
+namespace comm {
+
+class OriginHost;
+
+typedef std::map<std::string, anna::diameter::comm::OriginHost*> origin_hosts_t;
+typedef std::map<std::string, anna::diameter::comm::OriginHost*>::const_iterator origin_hosts_it;
+typedef std::map<std::string, anna::diameter::comm::OriginHost*>::iterator origin_hosts_nc_it;
+
+
+/**
+ * Helper class to centralize application Origin Host Nodes
+ *
+ */
+class OriginHostManager : public anna::Singleton <OriginHostManager> {
+
+private:
+
+  origin_hosts_t a_origin_hosts;
+
+  // private constructor
+  OriginHostManager() {};
+
+public:
+
+  virtual ~OriginHostManager() {;}
+
+  /**
+   * First element iterator
+   */
+  origin_hosts_it begin() const throw() { return a_origin_hosts.begin(); }
+
+  /**
+   * Last element iterator
+   */
+  origin_hosts_it end() const throw() { return a_origin_hosts.end(); }
+
+  /**
+   * Number of registered origin hosts
+   */
+  int size() const throw() { return a_origin_hosts.size(); }
+
+  /**
+   * Registers a new origin host node (externally allocated) associated to a name.
+   * If the name exists, the new origin host pointer will replace the existing one.
+   *
+   * @param name Origin Host Name
+   * @param originHost Associated Origin Host node
+   */
+  void registerOriginHost(const std::string &name, OriginHost* originHost) throw();
+
+  /**
+   * Get the associated origin host node for a provided name.
+   *
+   * @param name Origin Host Name
+   *
+   * @return Found origin host node, NULL if not found
+   */
+  OriginHost *getOriginHost(const std::string &name) const throw();
+
+  /**
+     Class XML representation.
+     \param parent XML node over which we will put instance information.
+     \return XML with class content.
+  */
+  virtual anna::xml::Node* asXML(anna::xml::Node* parent) const throw();
+
+
+  friend class anna::Singleton <OriginHostManager>;
+};
+
+}
+}
+}
+
+#endif
+
diff --git a/source/diameter.comm/OriginHostManager.cpp b/source/diameter.comm/OriginHostManager.cpp
new file mode 100644 (file)
index 0000000..067444d
--- /dev/null
@@ -0,0 +1,46 @@
+// ANNA - Anna is Not Nothingness Anymore                                                         //
+//                                                                                                //
+// (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo                         //
+//                                                                                                //
+// See project site at http://redmine.teslayout.com/projects/anna-suite                           //
+// See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
+
+
+// Project
+#include <anna/diameter.comm/OriginHostManager.hpp>
+#include <anna/diameter.comm/OriginHost.hpp>
+#include <anna/core/tracing/Logger.hpp>
+#include <anna/xml/Node.hpp>
+
+
+using namespace anna::diameter::comm;
+
+OriginHost *OriginHostManager::getOriginHost(const std::string &name) const throw() {
+  origin_hosts_it it = a_origin_hosts.find(name);
+  if (it != a_origin_hosts.end())
+    return it->second;
+
+  LOGWARNING(
+     std::string msg = "Unknown origin host node with name '"; msg += name; msg += "'";
+     anna::Logger::warning(msg, ANNA_FILE_LOCATION);
+  );
+
+  return NULL;
+}
+
+void OriginHostManager::registerOriginHost(const std::string &name, OriginHost* originHost) throw() {
+  if (!originHost) return; // nothing done
+  a_origin_hosts[name] = originHost;
+}
+
+anna::xml::Node* OriginHostManager::asXML(anna::xml::Node* parent) const
+throw() {
+  anna::xml::Node* result = parent->createChild("OriginHostManager");
+  origin_hosts_it it_min(a_origin_hosts.begin());
+  origin_hosts_it it_max(a_origin_hosts.end());
+  for (origin_hosts_it it = it_min; it != it_max; it++)
+    it->second->asXML(result);
+
+  return result;
+}
+