-void Launcher::servicesFromXML(const anna::xml::Node* servicesNode) throw(anna::RuntimeException) {
+void Launcher::servicesFromXML(const anna::xml::Node* servicesNode, bool eventOperation) throw(anna::RuntimeException) {
//<!ATTLIST stack id CDATA #REQUIRED dictionary CDATA #REQUIRED>
const anna::xml::Attribute *id, *dictionary;
// Stacks
anna::diameter::stack::Engine &stackEngine = anna::diameter::stack::Engine::instantiate();
anna::diameter::stack::Dictionary *d;
+ ///////////////////////////////////////////
+ // APPLICATION MESSAGE OAM MODULE SCOPES //
+ ///////////////////////////////////////////
+ // We will register a scope per stack id registered. The counters will be dynamically registered at count method.
+ anna::diameter::comm::ApplicationMessageOamModule & appMsgOamModule = anna::diameter::comm::ApplicationMessageOamModule::instantiate();
+ appMsgOamModule.enableCounters(); // this special module is disabled by default (the only)
+ static int scope_id = 3;
for(anna::xml::Node::const_child_iterator it = servicesNode->child_begin(); it != servicesNode->child_end(); it++) {
std::string nodeName = (*it)->getName();
try {
d = stackEngine.createDictionary(id->getIntegerValue(), dictionary->getValue());
getCodecEngine()->setDictionary(d);
+
+ // OAM module for counters:
+ appMsgOamModule.createStackCounterScope(scope_id, id->getIntegerValue() /* application-id */);
+ scope_id++;
+
} catch(anna::RuntimeException &ex) {
//_exit(ex.asString());
throw ex;
}
}
+ // Show loaded stacks:
+ std::cout << "Stacks currently loaded:" << std::endl;
+ std::cout << anna::functions::tab(stackEngine.asString(false /* light */));
+ std::cout << std::endl;
+
+
// Codec engine adjustments:
// Auto stack selection based on Application-ID:
bool multistack = (stackEngine.stack_size() > 1);
a_workingNode->setRequestRetransmissions(retransmissions);
a_workingNode->getEntity()->setSessionBasedModelsType(sessionBasedModelsType);
a_workingNode->getEntity()->setBalance(balance ? (balance->getValue() == "yes") : false); // for sendings
+ if (eventOperation) a_workingNode->getEntity()->bind();
}
}
a_workingNode->setLogs(s_log, b_splitLog, b_detailedLog, b_dumpLog, s_burstLog);
+ // Lazy initialization for comm engine:
+ if (eventOperation) commEngine->lazyInitialize();
+
// New Node assignment //////////////////////////////////////////////////////////////////////
a_nodes[originRealm->getValue()] = a_workingNode;
/////////////////////////////////////////////////////////////////////////////////////////////
}
}
+
+ // Diameter comm engines which are loaded after application start (via management operation 'services') are not really started,
+ // but this don't care because application startComponents() -> initialize() -> do_initialize() -> do nothing.
+ // And when stopped, running state is not checked and it will be stopped anyway.
}
-void Launcher::loadServices(const std::string & xmlPathFile) throw(anna::RuntimeException) {
+void Launcher::loadServices(const std::string & xmlPathFile, bool eventOperation) throw(anna::RuntimeException) {
+
+ if (xmlPathFile == "null" || xmlPathFile == "") {
+ LOGWARNING(anna::Logger::warning("Ignoring services configuration on start: empty or 'null' string provided as xml file. Use management interface (operation 'services') in order to add services", ANNA_FILE_LOCATION));
+ return;
+ }
LOGDEBUG(
std::string trace = "Loading ADML services file '";
trace += anna::xml::Compiler().apply(rootNode);
anna::Logger::debug(trace, ANNA_FILE_LOCATION);
);
- servicesFromXML(rootNode);
+ servicesFromXML(rootNode, eventOperation);
}
throw RuntimeException(msg, ANNA_FILE_LOCATION);
}
+RealmNode *Launcher::getWorkingNode() const throw(anna::RuntimeException) {
+
+ if (!a_workingNode)
+ throw RuntimeException("No services yet loaded. Try 'services' operation (via management interface), or restart process using command-line 'services' parameter", ANNA_FILE_LOCATION);
+
+ return a_workingNode;
+}
+
bool Launcher::setWorkingNode(const std::string &name) throw() {
bool result = false;
}
RealmNode *Launcher::getRealmNode(const std::string &realmName) const throw() {
- for (realm_nodes_it it = a_nodes.begin(); it != a_nodes.end(); it++)
- if(it->second->getMyDiameterEngine()->getRealm() == realmName) return it->second;
+ realm_nodes_it it = a_nodes.find(realmName);
+ if (it != a_nodes.end()) return it->second;
return NULL; // this never happens
}
a_counterRecorder = new MyCounterRecorder(cntDir + anna::functions::asString("/Counters.Pid%d", (int)getPid()));
}
+ // Tracing:
+ if(cl.exists("trace"))
+ anna::Logger::setLevel(anna::Logger::asLevel(cl.getValue("trace")));
+
// Load launcher services:
loadServices(cl.getValue("services")); // before run (have components to be created)
-
- // Show loaded stacks:
- std::cout << "Stacks provided:" << std::endl;
- std::cout << anna::functions::tab(anna::diameter::stack::Engine::instantiate().asString(false /* light */));
- std::cout << std::endl;
}
void Launcher::run()
// Statistics:
anna::statistics::Engine::instantiate().enable();
- // Tracing:
- if(cl.exists("trace"))
- anna::Logger::setLevel(anna::Logger::asLevel(cl.getValue("trace")));
-
LOGINFORMATION(
// Help on startup traces:
anna::Logger::information(help(), ANNA_FILE_LOCATION);
oamDiameterCodec.registerCounter(anna::diameter::codec::OamModule::Counter::LevelValidation__FailedRuleForCardinalityMoreThanNeeded, "", 17 /*2017*/);
oamDiameterCodec.registerCounter(anna::diameter::codec::OamModule::Counter::LevelValidation__FailedGenericAvpRuleForCardinalityFoundDisregardedItem, "", 18 /*2018*/);
oamDiameterCodec.registerCounter(anna::diameter::codec::OamModule::Counter::LevelValidation__FoundDisregardedItemsAndGenericAVPWasNotSpecified, "", 19 /*2019*/);
- ///////////////////////////////////////////
- // APPLICATION MESSAGE OAM MODULE SCOPES //
- ///////////////////////////////////////////
- // We will register a scope per stack id registered. The counters will be dynamically registered at count method.
- anna::diameter::comm::ApplicationMessageOamModule & appMsgOamModule = anna::diameter::comm::ApplicationMessageOamModule::instantiate();
- int scope_id = 3;
- for (anna::diameter::stack::Engine::const_stack_iterator it = stackEngine.stack_begin(); it != stackEngine.stack_end(); it++) {
- appMsgOamModule.createStackCounterScope(scope_id, it->first);
- scope_id++;
- }
- appMsgOamModule.enableCounters(); // this special module is disabled by default (the only)
-
/////////////////////////////////
if(a_counterRecorderClock) {
oamDiameterComm.setCounterRecorder(a_counterRecorder);
oamDiameterCodec.setCounterRecorder(a_counterRecorder);
- appMsgOamModule.setCounterRecorder(a_counterRecorder);
+ anna::diameter::comm::ApplicationMessageOamModule::instantiate().setCounterRecorder(a_counterRecorder);
a_timeEngine->activate(a_counterRecorderClock); // start clock
}
if (entity) entity->bind();
}
-
// Go into communicator poll
// Reconnection period (tcp reconnect retry time):
const char *varname = "reconnectionPeriod";
result += "\n";
result += "\n------------------------------------------------------------------------------------------- Hot changes";
result += "\n";
+ result += "\nservices[|source file] Adds and starts the services specified in the xml file provided.";
+ result += "\n (if missing, the file 'services.xml' will be used).";
+ result += "\n The last loaded realm node will be automatically the new current";
+ result += "\n working node. This is used to load new nodes once the ADML is";
+ result += "\n started, regardless if '--services' command line parameter was";
+ result += "\n used or not. Those services which are not correctly loaded, will";
+ result += "\n be ignored, keeping the process alive.";
+ result += "\n";
result += "\ndiameterServerSessions|<integer> Updates the maximum number of accepted connections to diameter";
result += "\n server socket.";
result += "\ncontext[|target file] Application context could also be written by mean this operation,";
std::string result = "";
anna::DataBlock db_aux(true);
anna::diameter::codec::Message codecMsg(getCodecEngine());
- MyDiameterEntity *entity = getWorkingNode()->getEntity();
- MyDiameterEngine *commEngine = getWorkingNode()->getMyDiameterEngine();
- MyLocalServer *localServer = getWorkingNode()->getDiameterServer();
///////////////////////////////////////////////////////////////////
// Simple operations without arguments:
return;
}
+ if(opType == "services") {
+ std::string servicesFile = ((numParams == 1) ? param1 : "services.xml");
+ try {
+ loadServices(servicesFile, true /* bind entities */);
+ }
+ catch(anna::RuntimeException &ex) {
+ ex.trace();
+ response_content = anna::functions::asString("Loaded services from file '%s' with some problems (ignored ones)\n", servicesFile.c_str());
+ return;
+ }
+ response_content = anna::functions::asString("Loaded services from file '%s'\n", servicesFile.c_str());
+ return;
+ }
+
// Realm switch:
if(opType == "node") {
if (param1 != "") {
return;
}
+ // Diameter endpoints:
+ MyDiameterEntity *entity = getWorkingNode()->getEntity();
+ MyDiameterEngine *commEngine = getWorkingNode()->getMyDiameterEngine();
+ MyLocalServer *localServer = getWorkingNode()->getDiameterServer();
+
+
if(opType == "code") {
codecMsg.loadXML(param1);
std::string hexString = anna::functions::asHexString(codecMsg.code());