diff --git a/core/Communication.cc b/core/Communication.cc index 4d4cb28c922482d65835932e36860ff203cbdae8..574fb0127cb600268a2d5808d19fc08fc394464d 100644 --- a/core/Communication.cc +++ b/core/Communication.cc @@ -1042,13 +1042,18 @@ void TTCN_Communication::send_map_req(component src_component, } void TTCN_Communication::send_mapped(const char *local_port, - const char *system_port, boolean translation) + const char *system_port, Map_Params& params, boolean translation) { Text_Buf text_buf; text_buf.push_int(MSG_MAPPED); text_buf.push_int(translation == FALSE ? 0 : 1); text_buf.push_string(local_port); text_buf.push_string(system_port); + unsigned int nof_params = params.get_nof_params(); + text_buf.push_int(nof_params); + for (unsigned int i = 0; i < nof_params; ++i) { + text_buf.push_string((const char*) params.get_param(i)); + } send_message(text_buf); } @@ -1071,13 +1076,18 @@ void TTCN_Communication::send_unmap_req(component src_component, } void TTCN_Communication::send_unmapped(const char *local_port, - const char *system_port, boolean translation) + const char *system_port, Map_Params& params, boolean translation) { Text_Buf text_buf; text_buf.push_int(MSG_UNMAPPED); text_buf.push_int(translation == FALSE ? 0 : 1); text_buf.push_string(local_port); text_buf.push_string(system_port); + unsigned int nof_params = params.get_nof_params(); + text_buf.push_int(nof_params); + for (unsigned int i = 0; i < nof_params; ++i) { + text_buf.push_string((const char*) params.get_param(i)); + } send_message(text_buf); } @@ -1795,9 +1805,9 @@ void TTCN_Communication::process_map() } if (!TTCN_Runtime::is_single()) { if (translation == FALSE) { - send_mapped(local_port, system_port, translation); + send_mapped(local_port, system_port, params, translation); } else { - send_mapped(system_port, local_port, translation); + send_mapped(system_port, local_port, params, translation); } } } catch (...) { @@ -1812,6 +1822,13 @@ void TTCN_Communication::process_map() void TTCN_Communication::process_map_ack() { + unsigned int nof_params = incoming_buf.pull_int().get_val(); + map_params_cache.reset(nof_params); + for (unsigned int i = 0; i < nof_params; ++i) { + char* par = incoming_buf.pull_string(); + map_params_cache.set_param(i, CHARSTRING(par)); + delete [] par; + } incoming_buf.cut_message(); switch (TTCN_Runtime::get_state()) { @@ -1848,9 +1865,9 @@ void TTCN_Communication::process_unmap() } if (!TTCN_Runtime::is_single()) { if (translation == FALSE) { - send_unmapped(local_port, system_port, translation); + send_unmapped(local_port, system_port, params, translation); } else { - send_unmapped(system_port, local_port, translation); + send_unmapped(system_port, local_port, params, translation); } } } catch (...) { @@ -1865,6 +1882,13 @@ void TTCN_Communication::process_unmap() void TTCN_Communication::process_unmap_ack() { + unsigned int nof_params = incoming_buf.pull_int().get_val(); + map_params_cache.reset(nof_params); + for (unsigned int i = 0; i < nof_params; ++i) { + char* par = incoming_buf.pull_string(); + map_params_cache.set_param(i, CHARSTRING(par)); + delete [] par; + } incoming_buf.cut_message(); switch(TTCN_Runtime::get_state()){ diff --git a/core/Communication.hh b/core/Communication.hh index 5397a04bb51f5fa57bf4878dd55f98993b23b6c5..a9b59cf555f162926d1cfdb4473a4c17a48444b2 100644 --- a/core/Communication.hh +++ b/core/Communication.hh @@ -123,11 +123,11 @@ public: static void send_map_req(component src_component, const char *src_port, const char *system_port, Map_Params& params, boolean translation); static void send_mapped(const char *local_port, - const char *system_port, boolean translation); + const char *system_port, Map_Params& params, boolean translation); static void send_unmap_req(component src_component, const char *src_port, const char *system_port, Map_Params& params, boolean translation); static void send_unmapped(const char *local_port, - const char *system_port, boolean translation); + const char *system_port, Map_Params& params, boolean translation); static void send_mtc_created(); static void send_testcase_started(const char *testcase_module, diff --git a/core/Port.cc b/core/Port.cc index fcc02a312343229abfd66134357f2b6df052c60e..444bec72571988404f81891daff286c153c9434f 100644 --- a/core/Port.cc +++ b/core/Port.cc @@ -53,12 +53,38 @@ #include "../common/dbgnew.hh" -Map_Params::Map_Params(unsigned int p_nof_params) -: nof_params(p_nof_params), params(new CHARSTRING[nof_params]) { } +void Map_Params::init(unsigned int p_nof_params) +{ + nof_params = p_nof_params; + params = new CHARSTRING[nof_params]; +} -Map_Params::~Map_Params() +void Map_Params::clear() { delete[] params; + nof_params = 0; + params = NULL; +} + +void Map_Params::copy(const Map_Params& p_other) +{ + init(p_other.nof_params); + for (unsigned int i = 0; i < nof_params; ++i) { + params[i] = p_other.params[i]; + } +} + +Map_Params& Map_Params::operator=(const Map_Params& p_other) +{ + clear(); + copy(p_other); + return *this; +} + +void Map_Params::reset(unsigned int p_nof_params) +{ + clear(); + init(p_nof_params); } void Map_Params::set_param(unsigned int p_index, const CHARSTRING& p_param) @@ -82,6 +108,8 @@ const CHARSTRING& Map_Params::get_param(unsigned int p_index) const return params[p_index]; } +Map_Params map_params_cache(0); + PORT *PORT::list_head = NULL, *PORT::list_tail = NULL; PORT *PORT::system_list_head = NULL, *PORT::system_list_tail = NULL; @@ -385,13 +413,13 @@ void PORT::deactivate_port(boolean system) TTCN_Logger::log_port_misc( TitanLoggerApi::Port__Misc_reason::removing__unterminated__mapping, port_name, NULL_COMPREF, system_port); + Map_Params params(0); try { - Map_Params params(0); unmap(system_port, params, system); } catch (const TC_Error&) { } if (is_parallel) { try { - TTCN_Communication::send_unmapped(port_name, system_port, system); + TTCN_Communication::send_unmapped(port_name, system_port, params, system); } catch (const TC_Error&) { } } Free(system_port); diff --git a/core/Port.hh b/core/Port.hh index e969b86a6d313b779eff756ed5f5a1b4009519b4..bbc9c7ad099ba8615b82186ddb386f792099e9d7 100644 --- a/core/Port.hh +++ b/core/Port.hh @@ -39,20 +39,31 @@ extern const COMPONENT_template& any_compref; struct port_connection; // no user serviceable parts inside +/** Wrapper class for parameters of 'map' and 'unmap' operations */ class Map_Params { unsigned int nof_params; CHARSTRING* params; - Map_Params(const Map_Params&); // copy disabled - Map_Params& operator=(const Map_Params&); // assignment disabled + void init(unsigned int p_nof_params); + void clear(); + void copy(const Map_Params& p_other); + public: - Map_Params(unsigned int p_nof_params); - ~Map_Params(); + Map_Params(unsigned int p_nof_params) { init(p_nof_params); } + Map_Params(const Map_Params& p_other) { copy(p_other); } // not used + ~Map_Params() { clear(); } + Map_Params& operator=(const Map_Params& p_other); + void reset(unsigned int p_nof_params); void set_param(unsigned int p_index, const CHARSTRING& p_param); unsigned int get_nof_params() const; const CHARSTRING& get_param(unsigned int p_index) const; }; +/** Cached parameters of the last received MAP_ACK or UNMAP_ACK message. + * It is used by the mapping/unmapping requestor to retrieve the output + * parameters of the 'map'/'unmap' operation. (Only used in parallel mode) */ +extern Map_Params map_params_cache; + /** Base class for all test ports */ class PORT : public Fd_And_Timeout_Event_Handler { friend class PORT_LIST; diff --git a/core/Runtime.cc b/core/Runtime.cc index c1bb2a57d37b58159f7807c6fa0a36277cbbf865..a466d5cb98cc5e8d0605d9db8aae23809b503abc 100644 --- a/core/Runtime.cc +++ b/core/Runtime.cc @@ -1924,12 +1924,14 @@ void TTCN_Runtime::map_port( system_port, params, translation); executor_state = MTC_MAP; wait_for_state_change(); + params = map_params_cache; break; case PTC_FUNCTION: TTCN_Communication::send_map_req(comp_reference, comp_port, system_port, params, translation); executor_state = PTC_MAP; wait_for_state_change(); + params = map_params_cache; break; default: if (in_controlpart()) { @@ -2006,12 +2008,14 @@ void TTCN_Runtime::unmap_port( system_port, params, translation); executor_state = MTC_UNMAP; wait_for_state_change(); + params = map_params_cache; break; case PTC_FUNCTION: TTCN_Communication::send_unmap_req(comp_reference, comp_port, system_port, params, translation); executor_state = PTC_UNMAP; wait_for_state_change(); + params = map_params_cache; break; default: if (in_controlpart()) { diff --git a/mctr2/mctr/MainController.cc b/mctr2/mctr/MainController.cc index dc8acb618e6167d0b88b260662c1d01d1eff38ba..8465826e9727ba5e2ae17ad8bd56a0805ab87112 100644 --- a/mctr2/mctr/MainController.cc +++ b/mctr2/mctr/MainController.cc @@ -1192,7 +1192,8 @@ void MainController::destroy_connection(port_connection *conn, remove_connection(conn); } -void MainController::destroy_mapping(port_connection *conn) +void MainController::destroy_mapping(port_connection *conn, + unsigned int nof_params, char** params) { component tc_compref; const char *tc_port, *system_port; @@ -1211,7 +1212,7 @@ void MainController::destroy_mapping(port_connection *conn) component_struct *comp = get_requestor(&conn->requestors, i); if (comp == NULL) break; if (comp->tc_state == TC_UNMAP) { - send_unmap_ack(comp); + send_unmap_ack(comp, nof_params, params); if (comp == mtc) comp->tc_state = MTC_TESTCASE; else comp->tc_state = PTC_FUNCTION; } @@ -1737,12 +1738,12 @@ void MainController::component_terminated(component_struct *tc) // and send out the related messages while (tc->conn_head_list != NULL) { if (tc->conn_head_list->tail.comp_ref == SYSTEM_COMPREF) - destroy_mapping(tc->conn_head_list); + destroy_mapping(tc->conn_head_list, 0, NULL); else destroy_connection(tc->conn_head_list, tc); } while (tc->conn_tail_list != NULL) { if (tc->conn_tail_list->head.comp_ref == SYSTEM_COMPREF) - destroy_mapping(tc->conn_tail_list); + destroy_mapping(tc->conn_tail_list, 0, NULL); else destroy_connection(tc->conn_tail_list, tc); } // drop the name of the currently executed function @@ -3425,10 +3426,15 @@ void MainController::send_map(component_struct *tc, send_message(tc->tc_fd, text_buf); } -void MainController::send_map_ack(component_struct *tc) +void MainController::send_map_ack(component_struct *tc, + unsigned int nof_params, char** params) { Text_Buf text_buf; text_buf.push_int(MSG_MAP_ACK); + text_buf.push_int(nof_params); + for (unsigned int i = 0; i < nof_params; ++i) { + text_buf.push_string(params[i]); + } send_message(tc->tc_fd, text_buf); } @@ -3448,10 +3454,15 @@ void MainController::send_unmap(component_struct *tc, send_message(tc->tc_fd, text_buf); } -void MainController::send_unmap_ack(component_struct *tc) +void MainController::send_unmap_ack(component_struct *tc, + unsigned int nof_params, char** params) { Text_Buf text_buf; text_buf.push_int(MSG_UNMAP_ACK); + text_buf.push_int(nof_params); + for (unsigned int i = 0; i < nof_params; ++i) { + text_buf.push_string(params[i]); + } send_message(tc->tc_fd, text_buf); } @@ -5411,7 +5422,7 @@ void MainController::process_map_req(component_struct *tc) status_change(); break; case CONN_MAPPED: - send_map_ack(tc); + send_map_ack(tc, nof_params, params); break; case CONN_UNMAPPING: send_error(tc->tc_fd, "The port mapping %d:%s - system:%s cannot " @@ -5441,6 +5452,11 @@ void MainController::process_mapped(component_struct *tc) boolean translation = text_buf.pull_int().get_val() == 0 ? FALSE : TRUE; char *src_port = text_buf.pull_string(); char *system_port = text_buf.pull_string(); + unsigned int nof_params = text_buf.pull_int().get_val(); + char** params = new char*[nof_params]; + for (unsigned int i = 0; i < nof_params; ++i) { + params[i] = text_buf.pull_string(); + } port_connection *conn = NULL; if (translation == FALSE) { @@ -5463,7 +5479,7 @@ void MainController::process_mapped(component_struct *tc) component_struct *comp = get_requestor(&conn->requestors, i); if (comp == NULL) break; if (comp->tc_state == TC_MAP) { - send_map_ack(comp); + send_map_ack(comp, nof_params, params); if (comp == mtc) comp->tc_state = MTC_TESTCASE; else comp->tc_state = PTC_FUNCTION; } @@ -5475,6 +5491,10 @@ void MainController::process_mapped(component_struct *tc) delete [] src_port; delete [] system_port; + for (unsigned int i = 0; i < nof_params; ++i) { + delete [] params[i]; + } + delete [] params; } void MainController::process_unmap_req(component_struct *tc) @@ -5502,7 +5522,7 @@ void MainController::process_unmap_req(component_struct *tc) port_connection *conn = find_connection(src_compref, src_port, SYSTEM_COMPREF, system_port); if (conn == NULL) { - send_unmap_ack(tc); + send_unmap_ack(tc, nof_params, params); } else { switch (conn->conn_state) { case CONN_MAPPED: @@ -5543,6 +5563,11 @@ void MainController::process_unmapped(component_struct *tc) boolean translation = text_buf.pull_int().get_val() == 0 ? FALSE : TRUE; char *src_port = text_buf.pull_string(); char *system_port = text_buf.pull_string(); + unsigned int nof_params = text_buf.pull_int().get_val(); + char** params = new char*[nof_params]; + for (unsigned int i = 0; i < nof_params; ++i) { + params[i] = text_buf.pull_string(); + } port_connection *conn = NULL; if (translation == FALSE) { @@ -5557,7 +5582,7 @@ void MainController::process_unmapped(component_struct *tc) case CONN_MAPPING: case CONN_MAPPED: case CONN_UNMAPPING: - destroy_mapping(conn); + destroy_mapping(conn, nof_params, params); break; default: send_error(tc->tc_fd, "Unexpected UNMAPPED message was " @@ -5568,6 +5593,10 @@ void MainController::process_unmapped(component_struct *tc) delete [] src_port; delete [] system_port; + for (unsigned int i = 0; i < nof_params; ++i) { + delete [] params[i]; + } + delete [] params; status_change(); } diff --git a/mctr2/mctr/MainController.h b/mctr2/mctr/MainController.h index 6cb22d4293c83a308338640b898021283f579d03..4daf02fe3b207c7a3ef73e23191de195da698374 100644 --- a/mctr2/mctr/MainController.h +++ b/mctr2/mctr/MainController.h @@ -381,7 +381,8 @@ class MainController { boolean new_connection, component_struct *requestor, const char *operation); static void destroy_connection(port_connection *conn, component_struct *tc); - static void destroy_mapping(port_connection *conn); + static void destroy_mapping(port_connection *conn, unsigned int nof_params, + char** params); static boolean stop_all_components(); static void check_all_component_stop(); static void send_stop_ack_to_requestors(component_struct *tc); @@ -528,11 +529,13 @@ private: static void send_map(component_struct *tc, const char *local_port, const char *system_port, unsigned int nof_params, char** params, boolean translate); - static void send_map_ack(component_struct *tc); + static void send_map_ack(component_struct *tc, unsigned int nof_params, + char** params); static void send_unmap(component_struct *tc, const char *local_port, const char *system_port, unsigned int nof_params, char** params, boolean translate); - static void send_unmap_ack(component_struct *tc); + static void send_unmap_ack(component_struct *tc, unsigned int nof_params, + char** params); static void send_debug_command(int fd, int commandID, const char* arguments); static void send_debug_setup(host_struct *hc); diff --git a/regression_test/map_param/common.ttcn b/regression_test/map_param/common.ttcn index b4810185a4917f22069c6c8aa8671c80e340576d..89e237a1771604c0d9e707ceceac3a738e220234 100644 --- a/regression_test/map_param/common.ttcn +++ b/regression_test/map_param/common.ttcn @@ -36,6 +36,23 @@ const IntList P2_FINAL := { 1, 2, 4, 8 }; const integer P_INITIAL := -2; const integer P_FINAL := 2; +function f_test_params(CT p_comp) runs on CT system CT { + var IntList v_p2 := P2_INITIAL; + map(p_comp:pt, system:pt) param (-, v_p2); + if (v_p2 != P2_FINAL) { + setverdict(fail, "Final value of parameter p2 is incorrect: ", v_p2); + } + + var integer v_p := P_INITIAL; + unmap(p_comp:pt, system:pt) param(v_p); + if (v_p != P_FINAL) { + setverdict(fail, "Final value of parameter p is incorrect: ", v_p); + } + + map(p_comp:pt, system:pt); + unmap(p_comp:pt, system:pt); +} + function f_check_calls() runs on CT { // check whether all 4 user functions have been called if (map_param and unmap_param and map_empty and unmap_empty) { diff --git a/regression_test/map_param/parallel_mode/parallel_test.ttcn b/regression_test/map_param/parallel_mode/parallel_test.ttcn index 418cab6ca5752a9841074f359e2c1bf709eb3d1f..a3726578a5a2d6095300543aa016c8f086374313 100644 --- a/regression_test/map_param/parallel_mode/parallel_test.ttcn +++ b/regression_test/map_param/parallel_mode/parallel_test.ttcn @@ -11,49 +11,18 @@ ******************************************************************************/ // this module contains tests for 'map'/'unmap' parameters in parallel mode -// ('out' and 'inout' do not retain the new values set in the port implementation, -// because the 'map' and 'unmap' operations are asynchronous, i.e. they don't -// wait for a response before the next operation is executed) module parallel_test { import from common all; testcase tc_parallel_mtc() runs on CT { - var IntList v_p2 := P2_INITIAL; - map(mtc:pt, system:pt) param (-, v_p2); - if (v_p2 != P2_INITIAL) { - setverdict(fail, "Final value of parameter p2 is incorrect: ", v_p2); - } - - var integer v_p := P_INITIAL; - unmap(mtc:pt, system:pt) param(v_p); - if (v_p != P_INITIAL) { - setverdict(fail, "Final value of parameter p is incorrect: ", v_p); - } - - map(mtc:pt, system:pt); - unmap(mtc:pt, system:pt); - + f_test_params(mtc); f_check_calls(); } testcase tc_parallel_ptc() runs on CT { var CT ptc := CT.create; - - var IntList v_p2 := P2_INITIAL; - map(ptc:pt, system:pt) param (-, v_p2); - if (v_p2 != P2_INITIAL) { - setverdict(fail, "Final value of parameter p2 is incorrect: ", v_p2); - } - - var integer v_p := P_INITIAL; - unmap(ptc:pt, system:pt) param(v_p); - if (v_p != P_INITIAL) { - setverdict(fail, "Final value of parameter p is incorrect: ", v_p); - } - map(ptc:pt, system:pt); - unmap(ptc:pt, system:pt); - + f_test_params(ptc); ptc.start(f_check_calls()); ptc.done; } diff --git a/regression_test/map_param/single_mode/single_test.ttcn b/regression_test/map_param/single_mode/single_test.ttcn index b2d050454139f60ad082340a19db4e72056b2faa..718dd95759b15bf84b961094b86ea345e5bfa52e 100644 --- a/regression_test/map_param/single_mode/single_test.ttcn +++ b/regression_test/map_param/single_mode/single_test.ttcn @@ -11,28 +11,12 @@ ******************************************************************************/ // this module contains tests for 'map'/'unmap' parameters in single mode -// ('out' and 'inout' parameters function normally, i.e. they retain the new -// values set in the port implementation) module single_test { import from common all; testcase tc_single() runs on CT { - var IntList v_p2 := P2_INITIAL; - map(mtc:pt, system:pt) param (-, v_p2); - if (v_p2 != P2_FINAL) { - setverdict(fail, "Final value of parameter p2 is incorrect: ", v_p2); - } - - var integer v_p := P_INITIAL; - unmap(mtc:pt, system:pt) param(v_p); - if (v_p != P_FINAL) { - setverdict(fail, "Final value of parameter p is incorrect: ", v_p); - } - - map(mtc:pt, system:pt); - unmap(mtc:pt, system:pt); - + f_test_params(mtc); f_check_calls(); }