process_error();
break;
case MSG_CONFIGURE:
- process_configure(msg_end);
+ process_configure(msg_end, false);
break;
case MSG_CREATE_MTC:
process_create_mtc();
case MSG_EXIT_MTC:
process_exit_mtc();
break;
+ case MSG_CONFIGURE:
+ process_configure(msg_end, true);
+ break;
default:
process_unsupported_message(msg_type, msg_end);
}
}
}
-void TTCN_Communication::process_configure(int msg_end)
+void TTCN_Communication::process_configure(int msg_end, bool to_mtc)
{
switch (TTCN_Runtime::get_state()) {
case TTCN_Runtime::HC_IDLE:
case TTCN_Runtime::HC_ACTIVE:
case TTCN_Runtime::HC_OVERLOADED:
- break;
+ if (!to_mtc) {
+ break;
+ }
+ // no break
+ case TTCN_Runtime::MTC_IDLE:
+ if (to_mtc) {
+ break;
+ }
+ // no break
default:
incoming_buf.cut_message();
send_error("Message CONFIGURE arrived in invalid state.");
return;
}
- TTCN_Runtime::set_state(TTCN_Runtime::HC_CONFIGURING);
+ TTCN_Runtime::set_state(to_mtc ? TTCN_Runtime::MTC_CONFIGURING : TTCN_Runtime::HC_CONFIGURING);
TTCN_Logger::log_configdata(TitanLoggerApiSimple::ExecutorConfigdata_reason::received__from__mc);
// take the config string directly from the buffer for efficiency reasons
if (success) {
send_configure_ack();
- TTCN_Runtime::set_state(TTCN_Runtime::HC_ACTIVE);
+ TTCN_Runtime::set_state(to_mtc ? TTCN_Runtime::MTC_IDLE : TTCN_Runtime::HC_ACTIVE);
TTCN_Logger::log_configdata(
TitanLoggerApiSimple::ExecutorConfigdata_reason::processing__succeeded);
} else {
send_configure_nak();
- TTCN_Runtime::set_state(TTCN_Runtime::HC_IDLE);
+ TTCN_Runtime::set_state(to_mtc ? TTCN_Runtime::MTC_IDLE : TTCN_Runtime::HC_IDLE);
}
incoming_buf.cut_message();
/** @name Handlers of various messages
* @{
*/
- static void process_configure(int msg_end);
+ static void process_configure(int msg_end, bool to_mtc);
static void process_create_mtc();
static void process_create_ptc();
static void process_kill_process();
/* Messages from MC to HC (down) */
-#define MSG_CONFIGURE 1
#define MSG_CREATE_MTC 2
#define MSG_CREATE_PTC 3
#define MSG_KILL_PROCESS 4
/* Messages from HC to MC (up) */
-#define MSG_CONFIGURE_ACK 2
-#define MSG_CONFIGURE_NAK 3
#define MSG_CREATE_NAK 4
#define MSG_HC_READY 5
#define MSG_DEBUG_RETURN_VALUE 100
+/* Messages from MC to HC or MTC (down) */
+
+#define MSG_CONFIGURE 200
+
+/* Messages from HC or MTC to MC (up) */
+
+#define MSG_CONFIGURE_ACK 200
+#define MSG_CONFIGURE_NAK 201
+
#endif
MTC_TERMINATING_TESTCASE, MTC_TERMINATING_EXECUTION, MTC_PAUSED, // 14-16
MTC_CREATE, MTC_START, MTC_STOP, MTC_KILL, MTC_RUNNING, MTC_ALIVE, // 17-22
MTC_DONE, MTC_KILLED, MTC_CONNECT, MTC_DISCONNECT, MTC_MAP, MTC_UNMAP, // 23-28
- MTC_EXIT, // 29
+ MTC_CONFIGURING, MTC_EXIT, // 30
- PTC_INITIAL, PTC_IDLE, PTC_FUNCTION, PTC_CREATE, PTC_START, PTC_STOP, // 30-35
- PTC_KILL, PTC_RUNNING, PTC_ALIVE, PTC_DONE, PTC_KILLED, PTC_CONNECT, // 36-41
- PTC_DISCONNECT, PTC_MAP, PTC_UNMAP, PTC_STOPPED, PTC_EXIT // 42-46
+ PTC_INITIAL, PTC_IDLE, PTC_FUNCTION, PTC_CREATE, PTC_START, PTC_STOP, // 31-36
+ PTC_KILL, PTC_RUNNING, PTC_ALIVE, PTC_DONE, PTC_KILLED, PTC_CONNECT, // 37-42
+ PTC_DISCONNECT, PTC_MAP, PTC_UNMAP, PTC_STOPPED, PTC_EXIT // 43-47
};
private:
static executor_state_enum executor_state;
perror("Cli::Cli: pthread_cond_init failed.");
exit(EXIT_FAILURE);
}
+ cfg_file_name = NULL;
}
Cli::~Cli()
{
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
+ Free(cfg_file_name);
}
//----------------------------------------------------------------------------
printWelcome();
if (argc == 2) {
- printf("Using configuration file: %s\n", argv[1]);
- if (process_config_read_file(argv[1], &mycfg)) {
+ cfg_file_name = mcopystr(argv[1]);
+ printf("Using configuration file: %s\n", cfg_file_name);
+ if (process_config_read_file(cfg_file_name, &mycfg)) {
puts("Error was found in the configuration file. Exiting.");
cleanUp();
return EXIT_FAILURE;
void Cli::reconfCallback(const char *arguments)
{
- if(*arguments == 0) { // reconf called without its optional argument
- puts("Reconfiguration of MC and HCs using original configuration "
- "data\n -- not supported, yet.");
- } else { // reconf called with config_file argument
- puts("Reconfiguration of MC and HCs using configuration file"
- "specified in\ncommand line argument -- not supported, yet.");
+ if (!MainController::start_reconfiguring()) {
+ return;
+ }
+ if (*arguments != 0) {
+ Free(cfg_file_name);
+ cfg_file_name = mcopystr(arguments);
+ }
+
+ printf("Using configuration file: %s\n", cfg_file_name);
+ if (process_config_read_file(cfg_file_name, &mycfg)) {
+ puts("Error was found in the configuration file. Exiting.");
+ cleanUp();
+ puts("exit");
+ exitCallback("");
+ }
+ else {
+ MainController::set_kill_timer(mycfg.kill_timer);
+
+ for (int i = 0; i < mycfg.group_list_len; ++i) {
+ MainController::add_host(mycfg.group_list[i].group_name,
+ mycfg.group_list[i].host_name);
+ }
+
+ for (int i = 0; i < mycfg.component_list_len; ++i) {
+ MainController::assign_component(mycfg.component_list[i].host_or_group,
+ mycfg.component_list[i].component);
+ }
+
+ if (MainController::get_state() == mctr::MC_RECONFIGURING) {
+ MainController::configure(mycfg.config_read_buffer);
+ }
}
}
if (*arguments == 0) {
switch (MainController::get_state()) {
case mctr::MC_READY:
+ case mctr::MC_RECONFIGURING:
MainController::exit_mtc();
waitMCState(WAIT_MTC_TERMINATED);
case mctr::MC_LISTENING:
*/
int executeListIndex;
+ char* cfg_file_name;
config_data mycfg;
};
host->hostname);
}
send_configure(host, config_str);
- send_debug_setup(host);
+ if (mc_state != MC_RECONFIGURING) {
+ send_debug_setup(host);
+ }
+ }
+}
+
+void MainController::configure_mtc()
+{
+ if (config_str == NULL) {
+ fatal_error("MainController::configure_mtc: no config file");
+ }
+ if (mtc->tc_state != TC_IDLE) {
+ error("MainController::configure_mtc(): MTC is in wrong state.");
+ }
+ else {
+ mtc->tc_state = MTC_CONFIGURING;
+ send_configure_mtc(config_str);
}
}
void MainController::check_all_hc_configured()
{
+ bool reconf = mc_state == MC_RECONFIGURING;
if (is_hc_in_state(HC_CONFIGURING) ||
is_hc_in_state(HC_CONFIGURING_OVERLOADED)) return;
if (is_hc_in_state(HC_IDLE)) {
error("There were errors during configuring HCs.");
- mc_state = MC_HC_CONNECTED;
+ mc_state = reconf ? MC_READY : MC_HC_CONNECTED;
} else if (is_hc_in_state(HC_ACTIVE) || is_hc_in_state(HC_OVERLOADED)) {
notify("Configuration file was processed on all HCs.");
- mc_state = MC_ACTIVE;
+ mc_state = reconf ? MC_READY : MC_ACTIVE;
} else {
error("There is no HC connection after processing the configuration "
"file.");
if (all_hc_in_state(HC_DOWN)) mc_state = MC_LISTENING;
break;
case MC_CONFIGURING:
+ case MC_RECONFIGURING:
check_all_hc_configured();
break;
case MC_ACTIVE:
case MSG_MTC_READY:
process_mtc_ready();
break;
+ case MSG_CONFIGURE_ACK:
+ process_configure_ack_mtc();
+ break;
+ case MSG_CONFIGURE_NAK:
+ process_configure_nak_mtc();
+ break;
default:
error("Invalid message type (%d) was received "
"from the MTC at %s [%s].", message_type,
send_message(mtc->tc_fd, text_buf);
}
+void MainController::send_configure_mtc(const char* config_file)
+{
+ Text_Buf text_buf;
+ text_buf.push_int(MSG_CONFIGURE);
+ text_buf.push_string(config_file);
+ send_message(mtc->tc_fd, text_buf);
+}
+
+
void MainController::send_cancel_done_ptc(component_struct *tc,
component component_reference)
{
"received.");
return;
}
- if (mc_state == MC_CONFIGURING) check_all_hc_configured();
+ if (mc_state == MC_CONFIGURING || mc_state == MC_RECONFIGURING)
+ check_all_hc_configured();
else notify("Host %s was configured successfully.", hc->hostname);
status_change();
}
"received.");
return;
}
- if (mc_state == MC_CONFIGURING) check_all_hc_configured();
+ if (mc_state == MC_CONFIGURING || mc_state == MC_RECONFIGURING)
+ check_all_hc_configured();
else notify("Processing of configuration file failed on host %s.",
hc->hostname);
status_change();
status_change();
}
+void MainController::process_configure_ack_mtc()
+{
+ if (mtc->tc_state != MTC_CONFIGURING) {
+ send_error_str(mtc->tc_fd, "Unexpected message CONFIGURE_ACK was received.");
+ return;
+ }
+ mtc->tc_state = TC_IDLE;
+ notify("Configuration file was processed on the MTC.");
+}
+
+void MainController::process_configure_nak_mtc()
+{
+ if (mtc->tc_state != MTC_CONFIGURING) {
+ send_error_str(mtc->tc_fd, "Unexpected message CONFIGURE_NAK was received.");
+ return;
+ }
+ mtc->tc_state = TC_IDLE;
+ notify("Processing of configuration file failed on the MTC.");
+}
+
void MainController::process_stopped(component_struct *tc, int message_end)
{
switch (tc->tc_state) {
void MainController::set_kill_timer(double timer_val)
{
lock();
- if (mc_state != MC_INACTIVE)
+ switch (mc_state) {
+ case MC_INACTIVE:
+ case MC_LISTENING:
+ case MC_HC_CONNECTED:
+ case MC_RECONFIGURING:
+ if (timer_val < 0.0)
+ error("MainController::set_kill_timer: setting a negative kill timer "
+ "value.");
+ else kill_timer = timer_val;
+ break;
+ default:
error("MainController::set_kill_timer: called in wrong state.");
- else if (timer_val < 0.0)
- error("MainController::set_kill_timer: setting a negative kill timer "
- "value.");
- else kill_timer = timer_val;
+ break;
+ }
unlock();
}
case MC_LISTENING_CONFIGURED:
mc_state = MC_LISTENING_CONFIGURED;
break;
+ case MC_RECONFIGURING:
+ break;
default:
error("MainController::configure: called in wrong state.");
unlock();
}
Free(config_str);
config_str = mcopystr(config_file);
- if(mc_state == MC_CONFIGURING) {
+ if (mc_state == MC_CONFIGURING || mc_state == MC_RECONFIGURING) {
notify("Downloading configuration file to all HCs.");
for (int i = 0; i < n_hosts; i++) configure_host(hosts[i], FALSE);
}
+ if (mc_state == MC_RECONFIGURING) {
+ notify("Downloading configuration file to the MTC.");
+ configure_mtc();
+ }
status_change();
unlock();
}
+bool MainController::start_reconfiguring()
+{
+ switch (mc_state) {
+ case MC_READY:
+ mc_state = MC_RECONFIGURING;
+ return true;
+ case MC_LISTENING:
+ case MC_HC_CONNECTED:
+ return true;
+ default:
+ lock();
+ error("MainController::start_reconfiguring: called in wrong state.");
+ unlock();
+ return false;
+ }
+}
+
void MainController::create_mtc(int host_index)
{
lock();
void MainController::exit_mtc()
{
lock();
- if (mc_state != MC_READY) {
+ if (mc_state != MC_READY && mc_state != MC_RECONFIGURING) {
error("MainController::exit_mtc: called in wrong state.");
unlock();
return;
MC_INACTIVE, MC_LISTENING, MC_LISTENING_CONFIGURED, MC_HC_CONNECTED,
MC_CONFIGURING, MC_ACTIVE, MC_SHUTDOWN, MC_CREATING_MTC, MC_READY,
MC_TERMINATING_MTC, MC_EXECUTING_CONTROL, MC_EXECUTING_TESTCASE,
- MC_TERMINATING_TESTCASE, MC_PAUSED
+ MC_TERMINATING_TESTCASE, MC_PAUSED, MC_RECONFIGURING
};
/** Data structure for unknown incoming connections (before receiving
MTC_CONTROLPART, MTC_TESTCASE, MTC_ALL_COMPONENT_STOP,
MTC_ALL_COMPONENT_KILL, MTC_TERMINATING_TESTCASE, MTC_PAUSED,
PTC_FUNCTION, PTC_STARTING, PTC_STOPPED, PTC_KILLING, PTC_STOPPING_KILLING,
- PTC_STALE, TC_SYSTEM };
+ PTC_STALE, TC_SYSTEM, MTC_CONFIGURING };
/** Data structure for each TC */
struct component_struct {
static boolean is_hc_in_state(hc_state_enum checked_state);
static boolean all_hc_in_state(hc_state_enum checked_state);
static void configure_host(host_struct *host, boolean should_notify);
+ static void configure_mtc();
static void check_all_hc_configured();
static void add_component_to_host(host_struct *host,
component_struct *comp);
static void send_ptc_verdict(boolean continue_execution);
static void send_continue();
static void send_exit_mtc();
+ static void send_configure_mtc(const char *config_file);
/** Messages to PTCs */
static void send_cancel_done_ptc(component_struct *tc,
static void process_testcase_started();
static void process_testcase_finished();
static void process_mtc_ready();
+ static void process_configure_ack_mtc();
+ static void process_configure_nak_mtc();
/* Incoming messages from PTCs */
static void process_stopped(component_struct *tc, int message_end);
static void shutdown_session();
static void configure(const char *config_file);
+ static bool start_reconfiguring();
static void create_mtc(int host_index);
static void exit_mtc();