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;
- bool id_0_registered = false;
unsigned int id_value;
std::string codecEngineName;
throw ex;
}
- if (id_value == 0) {
- id_0_registered = true;
- bpd = d;
- }
+ bpd = d; // base protocol dictionary in case of monostack. If multistack, will be calculated later
// Create codec engine and register it in the codec engine manager:
codecEngineName = anna::functions::asString("CodecEngineForStackId_%llu", id_value);
// Basic checking for multistack:
bool multistack = (stackEngine.stack_size() > 1);
if (multistack) {
- if(!id_0_registered)
+ bpd = stackEngine.getDictionary(0);
+ if(!bpd)
throw anna::RuntimeException("In multistack applications is mandatory register a stack id = 0 using a dictionary which contains the needed elements to build base protocol messages (CER/A, DWR/A, DPR/A, STR/A, etc.)", ANNA_FILE_LOCATION);
}
- else { // monostack
- if (!bpd)
- bpd = ce->getDictionary(); // in mono-stack applications, we understand the existing stack as the used
- // for base protocol, regardless if it is registered with stack id 0 or not
- }
// REALMS:
for(anna::xml::Node::const_child_iterator it = servicesNode->child_begin(); it != servicesNode->child_end(); it++) {
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 (if missing, the file 'services.xml' will be used). This is used";
+ result += "\n to load new nodes once the ADML is started, regardless if command";
+ result += "\n line '--services' parameter was used or not. Those services which";
+ result += "\n are not correctly loaded will be ignored to keep the process alive.";
result += "\n";
result += "\ndiameterServerSessions|<integer> Updates the maximum number of accepted connections to diameter";
result += "\n server socket.";
result += "\n This operation applies over all the registered realm nodes";
result += "\n except if one specific working node has been set.";
result += "\nforceCountersRecord Forces dump to file the current counters of the process.";
+ result += "\noam-and-stats Dumps current counters and statistics of the process. This is";
+ result += "\n also done at process context dump.";
result += "\n";
result += "\n<visibility action>[|<address>:<port>][|socket id]";
result += "\n";
result += "\n received from entity (waitfe) or from client (waitfc).";
result += "\n";
result += "\n wait<fe/fc>-regexp|<regexp>";
- result += "\n Wait condition, from entity (waitfe-regexp) or client (waitfc-regexp)";
+ result += "\n Wait condition, from entity (waitfe-regexp) or client (waitfc-regexp)";
result += "\n to match the serialized xml content for received messages. CPU cost";
result += "\n is bigger than the former ones because the whole message must be";
result += "\n decoded and converted to xml instead of doing a direct hexadecimal";
result += "\n buffer search. The main advantage is the great flexibility to identify";
result += "\n any content with a regular expression.";
result += "\n";
- result += "\n sh-command|<script>[|parameters]";
- result += "\n External execution for script/executable via shell through an";
- result += "\n independent thread, providing the script name and the parameters.";
- result += "\n You could use dynamic variables ##<tag> to have more flexibility:";
+ result += "\n sh-command|<script> External execution for script/executable via shell through a dedicated";
+ result += "\n thread, providing the command and parameters. You could use dynamic";
+ result += "\n variables ##<tag> to have more flexibility:";
result += "\n Test pool cycle id: "; result += SH_COMMAND_TAG_FOR_REPLACE__CYCLE_ID;
result += "\n Test case id: "; result += SH_COMMAND_TAG_FOR_REPLACE__TESTCASE_ID;
result += "\n Test step id: "; result += SH_COMMAND_TAG_FOR_REPLACE__TESTSTEP_ID;
result += "\n";
- result += "\n For example, your command could be something like this:";
- result += "\n script: insert_sql.sh";
- result += "\n parameters: -db dbname --verbose > /tmp/cycle-"; result += SH_COMMAND_TAG_FOR_REPLACE__CYCLE_ID; result += ".";
- result += "\n testcase-"; result += SH_COMMAND_TAG_FOR_REPLACE__TESTCASE_ID; result += ".teststep-"; result += SH_COMMAND_TAG_FOR_REPLACE__TESTSTEP_ID; result += ".out";
- result += "\n";
- result += "\n You could also make substitutions on script name: insert_sql_"; result += SH_COMMAND_TAG_FOR_REPLACE__TESTCASE_ID; result += ".sh";
- result += "\n";
- result += "\n Don't try to redirect stdout and stderr to avoid ADML output contamination";
- result += "\n with the possible outputs from the scripts.";
+ result += "\n For example, your command could be something like this:";
+ result += "\n insert_sql_"; result += SH_COMMAND_TAG_FOR_REPLACE__TESTCASE_ID; result += ".sh -db dbname --verbose";
+ result += "\n > /tmp/cycle-"; result += SH_COMMAND_TAG_FOR_REPLACE__CYCLE_ID;
+ result += ".testcase-"; result += SH_COMMAND_TAG_FOR_REPLACE__TESTCASE_ID;
+ result += ".teststep-"; result += SH_COMMAND_TAG_FOR_REPLACE__TESTSTEP_ID;
+ result += ".out";
+ result += "\n Try to redirect stdout and stderr to avoid ADML output contamination";
+ result += "\n with the possible outputs from the scripts. You could also put your";
+ result += "\n job in background although sh-command will return 0-value immediately.";
result += "\n";
result += "\n <condition>: Optional parameters which must be fulfilled to continue through the next step.";
result += "\n Any received message over diameter interfaces will be evaluated against the";
result += "\n";
result += "\n test|report-hex[|[yes]|no] Reports could include the diameter messages in hexadecimal format. Disabled by default.";
result += "\n";
- result += "\n test|report-hex[|[yes]|no] Reports could include the diameter messages in hexadecimal format. Disabled by default.";
+ result += "\n test|interact|amount|id Makes interactive a specific test case id. The amount is the margin of execution steps";
+ result += "\n to be done. Normally, we will execute 'test|interact|0|<test case id>', which means that";
+ result += "\n the test case is selected to be interactive, but no step is executed. Then you have to";
+ result += "\n interact with positive amounts (usually 1), executing the provided number of steps if";
+ result += "\n they are ready and fulfill the needed conditions. The value of 0, implies no execution";
+ result += "\n steps margin, which could be useful to 'freeze' a test in the middle of its execution.";
+ result += "\n You could also provide -1 to make it non-interactive resuming it from the current step.";
result += "\n";
result += "\n test|reset|<soft/hard>[|id] Reset the test case for id provided, all the tests when missing. It could be hard/soft:";
result += "\n - hard: you probably may need to stop the load rate before. This operation initializes";
result += "\n";
result += "\n test|clear Clears all the programmed test cases and stop testing (if in progress).";
result += "\n";
+ result += "\n test|summary Test manager general report (number of test cases, counts by state, global configuration,";
+ result += "\n forced in-progress limitation, reports visibility, etc.). Be careful when you have reports";
+ result += "\n dumps enabled because all the programmed test cases will be dump and that could be heavy.";
+ result += "\n";
result += "\n";
result += "\nUSING OPERATIONS INTERFACE";
result += "\n--------------------------";
return;
}
+ // OAM & statistics:
+ if(operation == "oam-and-stats") {
+ anna::xml::Node root("root");
+ response_content = anna::xml::Compiler().apply(oamAndStatsAsXML(&root));
+ return;
+ }
+
///////////////////////////////////////////////////////////////////
// Tokenize operation
Tokenizer params;
}
catch(anna::RuntimeException &ex) {
ex.trace();
- response_content = anna::functions::asString("Loaded services from file '%s' with some problems (ignored ones)", servicesFile.c_str());
+ response_content = anna::functions::asString("Loaded services from file '%s' with errors", servicesFile.c_str());
return;
}
response_content = anna::functions::asString("Loaded services from file '%s'", servicesFile.c_str());
// test|report-hex[|[yes]|no] Reports could include the diameter messages in hexadecimal format. Disabled by default.
// test|goto|<id> Updates current test pointer position.
// test|look[|id] Show programmed test case for id provided, current when missing ...
+ // test|interact|amount|id Makes interactive a specific test case id. The amount is the margin of execution steps ...
// test|reset|<soft/hard>[|id] Reset the test case for id provided, all the tests when missing ...
// test|clear Clears all the programmed test cases.
+ // test|summary Test manager general report (number of test cases, counts by state ...
+
if(param1 == "ttps") {
if (numParams > 2)
}
}
else if(param1 == "repeats") {
- if (numParams > 2 || numParams < 2)
+ if (numParams != 2)
throw anna::RuntimeException("Wrong body content format on HTTP Request. Use 'help' management command to see more information.", ANNA_FILE_LOCATION);
int repeats = atoi(param2.c_str());
if (repeats < 0) repeats = -1;
}
}
}
+ else if (param1 == "interact") {
+ if (numParams != 3)
+ throw anna::RuntimeException("Wrong body content format on HTTP Request. Use 'help' management command to see more information.", ANNA_FILE_LOCATION);
+
+ int amount = atoi(param2.c_str());
+ if (amount < -1)
+ throw anna::RuntimeException("Interactive amount must be -1 (to disable interactive mode) or a positive number.", ANNA_FILE_LOCATION);
+
+ int id = atoi(param3.c_str());
+ TestCase *testCase = testManager.findTestCase(id);
+ if (testCase) {
+ if (amount == -1) {
+ testCase->makeInteractive(false);
+ opt_response_content = "interactive mode disabled";
+ }
+ else {
+ testCase->addInteractiveAmount(amount);
+ opt_response_content = "added interactive amount of ";
+ opt_response_content += anna::functions::asString(amount);
+ opt_response_content += " units";
+ if (amount == 0) opt_response_content += " (0: freezing a non-interactive testcase, no effect on already interactive)";
+ }
+ opt_response_content += " for test case id ";
+ opt_response_content += anna::functions::asString(id);
+ }
+ else {
+ opt_response_content = "cannot found test id (";
+ opt_response_content += anna::functions::asString(id);
+ opt_response_content += ")";
+ }
+ }
else if(param1 == "reset") {
if (numParams > 3)
throw anna::RuntimeException("Wrong body content format on HTTP Request. Use 'help' management command to see more information.", ANNA_FILE_LOCATION);
else {
if (id == -1) {
bool anyReset = testManager.resetPool((param2 == "hard") ? true:false);
- opt_response_content = "reset have been sent to all programmed tests: "; opt_response_content += anyReset ? "some/all was actually reset" : "nothing was reset";
+ opt_response_content = "reset have been sent to all programmed tests: "; opt_response_content += anyReset ? "some/all have been reset" : "nothing was reset";
}
else {
opt_response_content = "cannot found test id (";
opt_response_content = "there are not programmed test cases to be removed";
}
}
+ else if(param1 == "summary") {
+ response_content = testManager.asXMLString();
+ return;
+ }
else {
int id = atoi(param1.c_str());
if(id < 0)
else if (param2 == "sh-command") {
if (numParams > 4)
throw anna::RuntimeException("Wrong body content format on HTTP Request. Use 'help' management command to see more information.", ANNA_FILE_LOCATION);
- if(param3 == "") throw anna::RuntimeException("Missing script for 'sh-command' in test id operation", ANNA_FILE_LOCATION);
- testManager.getTestCase(id)->addCmd(param3, param4); // creates / reuses
+ if(param3 == "") throw anna::RuntimeException("Missing script/executable command-line for 'sh-command' in test id operation", ANNA_FILE_LOCATION);
+ testManager.getTestCase(id)->addCommand(param3); // creates / reuses
}
else {
throw anna::RuntimeException("Wrong body content format on HTTP Request. Use 'help' management command to see more information.", ANNA_FILE_LOCATION);
it->second->asXML(result);
}
+ // OAM & statistics:
+ oamAndStatsAsXML(result);
+
+ // Testing: could be heavy if test case reports are enabled
+ TestManager::instantiate().asXML(result);
+
+ return result;
+}
+
+anna::xml::Node* Launcher::oamAndStatsAsXML(anna::xml::Node* parent) const
+throw() {
+ anna::xml::Node* result = parent->createChild("OamAndStatistics");
+
// OAM:
anna::diameter::comm::OamModule::instantiate().asXML(result);
anna::diameter::comm::ApplicationMessageOamModule::instantiate().asXML(result);
// Statistics:
anna::statistics::Engine::instantiate().asXML(result);
- // Testing: could be heavy if test case reports are enabled
- //TestManager::instantiate().asXML(result);
-
return result;
}
+