From c2e42f4ef4951a70356442ac55f626e6ff4ff752 Mon Sep 17 00:00:00 2001 From: Jacqueline Deans Date: Tue, 23 Aug 2022 13:47:56 -0500 Subject: [PATCH 1/5] Refactor and test Variable Server. - Split VariableServerThread into VariableServerSession and VariableReference classes - Use C++ streams for data handling - Unit tests --- .gitignore | 4 +- Makefile | 3 + include/trick/ClientConnection.hh | 43 + include/trick/ClientListener.hh | 47 ++ include/trick/MulticastManager.hh | 28 + include/trick/TCConnection.hh | 48 ++ include/trick/VariableReference.hh | 99 +++ include/trick/VariableServer.hh | 23 +- include/trick/VariableServerListenThread.hh | 24 +- include/trick/VariableServerReference.hh | 44 - include/trick/VariableServerSession.hh | 481 +++++++++++ include/trick/VariableServerThread.hh | 530 +----------- include/trick/var_binary_parser.hh | 2 +- include/trick/variable_server.h | 68 -- share/trick/makefiles/Makefile.common | 2 +- test/SIM_test_varserv/RUN_test/unit_test.py | 2 +- test/SIM_test_varserv/S_overrides.mk | 2 +- .../models/test_client/test_client.cpp | 280 ++++++- .../SIM_billiards/Modified_data/realtime.py | 5 + trick_sims/SIM_billiards/RUN_break/input.py | 14 - .../models/graphics/cpp/main.cpp | 21 +- .../simcontrol/SimControlApplication.java | 7 +- .../utils/SimControlActionController.java | 2 +- trick_source/sim_services/CMakeLists.txt | 1 - .../sim_services/InputProcessor/Makefile_deps | 2 +- .../sim_services/MonteCarlo/test/Makefile | 2 +- .../sim_services/VariableServer/Makefile_deps | 263 +++--- .../VariableServer/VariableReference.cpp | 758 ++++++++++++++++-- .../VariableServer/VariableServer.cpp | 36 +- .../VariableServerListenThread.cpp | 193 ++--- .../VariableServer/VariableServerSession.cpp | 139 ++++ .../VariableServerSession_commands.cpp | 401 +++++++++ ...pp => VariableServerSession_copy_data.cpp} | 12 +- .../VariableServerSession_copy_sim_data.cpp | 35 + ... => VariableServerSession_freeze_init.cpp} | 6 +- .../VariableServerSession_write_data.cpp | 188 +++++ .../VariableServerSession_write_stdio.cpp | 17 + .../VariableServer/VariableServerThread.cpp | 157 ++-- .../VariableServerThread_commands.cpp | 516 ------------ .../VariableServerThread_connect.cpp | 9 - .../VariableServerThread_copy_sim_data.cpp | 105 --- .../VariableServerThread_create_socket.cpp | 44 - .../VariableServerThread_loop.cpp | 156 ++-- .../VariableServerThread_restart.cpp | 45 -- .../VariableServerThread_write_data.cpp | 322 -------- .../VariableServerThread_write_stdio.cpp | 13 - .../VariableServer_copy_data_freeze.cpp | 4 +- ...iableServer_copy_data_freeze_scheduled.cpp | 13 +- .../VariableServer_copy_data_scheduled.cpp | 13 +- .../VariableServer_copy_data_top.cpp | 4 +- .../VariableServer_freeze_init.cpp | 14 +- ...riableServer_get_next_freeze_call_time.cpp | 12 +- ...VariableServer_get_next_sync_call_time.cpp | 12 +- .../VariableServer_get_var_server_port.cpp | 39 +- .../VariableServer/VariableServer_init.cpp | 4 +- .../VariableServer/VariableServer_restart.cpp | 8 +- .../VariableServer_shutdown.cpp | 6 + .../VariableServer/exit_var_thread.cpp | 3 +- .../VariableServer/test/.gitignore | 4 + .../sim_services/VariableServer/test/Makefile | 87 ++ .../VariableServer/test/TestConnection.hh | 80 ++ .../test/VariableReference_test.cc | 512 ++++++++++++ .../test/VariableReference_test.hh | 56 ++ .../VariableReference_writeValueAscii_test.cc | 252 ++++++ ...VariableReference_writeValueBinary_test.cc | 177 ++++ .../test/VariableServerSession_test.cc | 190 +++++ .../VariableServer/var_server_ext.cpp | 380 +++++---- .../VariableServer/vs_format_ascii.cpp | 265 ------ trick_source/trick_utils/CMakeLists.txt | 3 + .../connection_handlers/ClientConnection.cpp | 1 + .../connection_handlers/ClientListener.cpp | 115 +++ .../trick_utils/connection_handlers/Makefile | 15 + .../connection_handlers/MulticastManager.cpp | 63 ++ .../connection_handlers/TCConnection.cpp | 117 +++ .../trick_utils/var_binary_parser/.gitignore | 2 +- .../var_binary_parser/test/Makefile | 2 +- .../include/VariableServerSessionWeb.hh | 51 ++ trickops.py | 8 + 78 files changed, 5021 insertions(+), 2690 deletions(-) create mode 100644 include/trick/ClientConnection.hh create mode 100644 include/trick/ClientListener.hh create mode 100644 include/trick/MulticastManager.hh create mode 100644 include/trick/TCConnection.hh create mode 100644 include/trick/VariableReference.hh delete mode 100644 include/trick/VariableServerReference.hh create mode 100644 include/trick/VariableServerSession.hh delete mode 100644 include/trick/variable_server.h create mode 100644 trick_source/sim_services/VariableServer/VariableServerSession.cpp create mode 100644 trick_source/sim_services/VariableServer/VariableServerSession_commands.cpp rename trick_source/sim_services/VariableServer/{VariableServerThread_copy_data.cpp => VariableServerSession_copy_data.cpp} (85%) create mode 100644 trick_source/sim_services/VariableServer/VariableServerSession_copy_sim_data.cpp rename trick_source/sim_services/VariableServer/{VariableServerThread_freeze_init.cpp => VariableServerSession_freeze_init.cpp} (58%) create mode 100644 trick_source/sim_services/VariableServer/VariableServerSession_write_data.cpp create mode 100644 trick_source/sim_services/VariableServer/VariableServerSession_write_stdio.cpp delete mode 100644 trick_source/sim_services/VariableServer/VariableServerThread_commands.cpp delete mode 100644 trick_source/sim_services/VariableServer/VariableServerThread_connect.cpp delete mode 100644 trick_source/sim_services/VariableServer/VariableServerThread_copy_sim_data.cpp delete mode 100644 trick_source/sim_services/VariableServer/VariableServerThread_create_socket.cpp delete mode 100644 trick_source/sim_services/VariableServer/VariableServerThread_restart.cpp delete mode 100644 trick_source/sim_services/VariableServer/VariableServerThread_write_data.cpp delete mode 100644 trick_source/sim_services/VariableServer/VariableServerThread_write_stdio.cpp create mode 100644 trick_source/sim_services/VariableServer/test/.gitignore create mode 100644 trick_source/sim_services/VariableServer/test/Makefile create mode 100644 trick_source/sim_services/VariableServer/test/TestConnection.hh create mode 100644 trick_source/sim_services/VariableServer/test/VariableReference_test.cc create mode 100644 trick_source/sim_services/VariableServer/test/VariableReference_test.hh create mode 100644 trick_source/sim_services/VariableServer/test/VariableReference_writeValueAscii_test.cc create mode 100644 trick_source/sim_services/VariableServer/test/VariableReference_writeValueBinary_test.cc create mode 100644 trick_source/sim_services/VariableServer/test/VariableServerSession_test.cc delete mode 100644 trick_source/sim_services/VariableServer/vs_format_ascii.cpp create mode 100644 trick_source/trick_utils/connection_handlers/ClientConnection.cpp create mode 100644 trick_source/trick_utils/connection_handlers/ClientListener.cpp create mode 100644 trick_source/trick_utils/connection_handlers/Makefile create mode 100644 trick_source/trick_utils/connection_handlers/MulticastManager.cpp create mode 100644 trick_source/trick_utils/connection_handlers/TCConnection.cpp create mode 100644 trick_source/web/CivetServer/include/VariableServerSessionWeb.hh diff --git a/.gitignore b/.gitignore index 2d3bd41f..d4c6167c 100644 --- a/.gitignore +++ b/.gitignore @@ -40,4 +40,6 @@ archive/ trickops_logs/ *.gcda *.gcno -coverage.info \ No newline at end of file +coverage.info +*.dSYM + diff --git a/Makefile b/Makefile index 48cdf205..0ec17113 100644 --- a/Makefile +++ b/Makefile @@ -95,6 +95,7 @@ UTILS_DIRS := \ ${TRICK_HOME}/trick_source/trick_utils/interpolator \ ${TRICK_HOME}/trick_source/trick_utils/trick_adt \ ${TRICK_HOME}/trick_source/trick_utils/comm \ + ${TRICK_HOME}/trick_source/trick_utils/connection_handlers \ ${TRICK_HOME}/trick_source/trick_utils/shm \ ${TRICK_HOME}/trick_source/trick_utils/math \ ${TRICK_HOME}/trick_source/trick_utils/units \ @@ -105,6 +106,7 @@ UTILS_OBJS := $(addsuffix /object_$(TRICK_HOST_CPU)/*.o ,$(UTILS_DIRS)) # filter out the directories that make their own libraries UTILS_OBJS := $(filter-out ${TRICK_HOME}/trick_source/trick_utils/comm/%, $(UTILS_OBJS)) +UTILS_OBJS := $(filter-out ${TRICK_HOME}/trick_source/trick_utils/connection_handlers/%, $(UTILS_OBJS)) UTILS_OBJS := $(filter-out ${TRICK_HOME}/trick_source/trick_utils/math/%, $(UTILS_OBJS)) UTILS_OBJS := $(filter-out ${TRICK_HOME}/trick_source/trick_utils/units/%, $(UTILS_OBJS)) UTILS_OBJS := $(filter-out ${TRICK_HOME}/trick_source/trick_utils/var_binary_parser/%, $(UTILS_OBJS)) @@ -458,6 +460,7 @@ uninstall: rm -f ${PREFIX}/$(notdir ${TRICK_LIB_DIR})/liber7_utils.a rm -f ${PREFIX}/$(notdir ${TRICK_LIB_DIR})/libtrick.a rm -f ${PREFIX}/$(notdir ${TRICK_LIB_DIR})/libtrick_comm.a + rm -f ${PREFIX}/$(notdir ${TRICK_LIB_DIR})/libtrick_connection_handlers.a rm -f ${PREFIX}/$(notdir ${TRICK_LIB_DIR})/libtrick_math.a rm -f ${PREFIX}/$(notdir ${TRICK_LIB_DIR})/libtrick_mm.a rm -f ${PREFIX}/$(notdir ${TRICK_LIB_DIR})/libtrick_pyip.a diff --git a/include/trick/ClientConnection.hh b/include/trick/ClientConnection.hh new file mode 100644 index 00000000..50883c4f --- /dev/null +++ b/include/trick/ClientConnection.hh @@ -0,0 +1,43 @@ +/************************************************************************ +PURPOSE: (Abstract base class for a connection to a client. Should +be inherited by variable server and web server connections. ) +LIBRARY DEPENDENCIES: + () ) +**************************************************************************/ + +#ifndef CLIENT_CONNECTION_HH +#define CLIENT_CONNECTION_HH + +#include +// #include + +namespace Trick { + class ClientConnection { + public: + // Should this be here? ¯\_(ツ)_/¯ + enum ConnectionType { TCP, UDP, MCAST, WS } ; + + virtual int initialize() = 0; + + virtual int write (const std::string& message) = 0; + virtual int write (char * message, int size) = 0; + + virtual std::string read (int max_len = MAX_CMD_LEN) = 0; + + virtual int disconnect () = 0; + virtual std::string get_client_tag () = 0; + virtual int set_client_tag(std::string tag) = 0; + virtual int setBlockMode (int mode) = 0; + + static const unsigned int MAX_CMD_LEN = 200000 ; + + protected: + ConnectionType _connection_type; + + // RHEL appears to have an issue with std::atomic + // std::atomic_bool _is_initialized; + + }; +} + +#endif \ No newline at end of file diff --git a/include/trick/ClientListener.hh b/include/trick/ClientListener.hh new file mode 100644 index 00000000..c9df618d --- /dev/null +++ b/include/trick/ClientListener.hh @@ -0,0 +1,47 @@ +#ifndef CLIENT_LISTENER_HH +#define CLIENT_LISTENER_HH + +#include "trick/tc.h" +#include "trick/TCConnection.hh" +#include + +namespace Trick { + + class TCConnection; + + class ClientListener { + public: + ClientListener (); + ~ClientListener (); + + // We'll see if we need separate methods for these + int initialize(std::string hostname, int port); + int initialize(); + + int setBlockMode(TCCommBlocking mode); + + bool checkForNewConnections(); + + const char * getHostname (); + + int getPort(); + + int disconnect(); + + int checkSocket(); + + bool validateSourceAddress(std::string source_address); + + bool isInitialized(); + + friend int accept(ClientListener* listener, TCConnection* connection); + + private: + TCDevice _listen_dev; + std::string saved_source; + int port; + bool initialized; + }; +} + +#endif \ No newline at end of file diff --git a/include/trick/MulticastManager.hh b/include/trick/MulticastManager.hh new file mode 100644 index 00000000..a69da6b2 --- /dev/null +++ b/include/trick/MulticastManager.hh @@ -0,0 +1,28 @@ +/* + PURPOSE: ( Encapsulate multicast functionality. ) +*/ + +#include +#include +#include + +namespace Trick { + class MulticastManager { + public: + MulticastManager(); + ~MulticastManager(); + + int broadcast (std::string message); + int addAddress (std::string addr, int port); + int restart (); + int initialize(); + int is_initialized(); + + + private: + std::vector addresses; /**< trick_io(**) Addresses to multicast to. */ + int mcast_socket; /**< trick_io(**) Socket opened in initialization. */ + int initialized; /**< trick_io(**) Whether manager is ready */ + + }; +} \ No newline at end of file diff --git a/include/trick/TCConnection.hh b/include/trick/TCConnection.hh new file mode 100644 index 00000000..070892d1 --- /dev/null +++ b/include/trick/TCConnection.hh @@ -0,0 +1,48 @@ +#ifndef TC_CONNECTION_HH +#define TC_CONNECTION_HH + +/* + PURPOSE: ( Encapsulate a connection with TrickComm. ) +*/ + +#include "trick/ClientConnection.hh" +#include "trick/ClientListener.hh" +#include "tc.h" + + +namespace Trick { + + class ClientListener; + + class TCConnection : public ClientConnection { + public: + + TCConnection (); + + int initialize() override; + + int write (const std::string& message) override; + int write (char * message, int size) override; + + std::string read (int max_len) override; + + int disconnect () override; + std::string get_client_tag () override; + int set_client_tag(std::string tag) override; + int get_socket(); + + int setBlockMode(int block_mode) override; + int setErrorReporting (bool on); + + static const unsigned int MAX_CMD_LEN = 200000 ; + + friend int accept(ClientListener* listener, TCConnection* connection); + + private: + TCDevice _device; /**< trick_io(**) */ + }; + + int accept(ClientListener* listener, TCConnection* connection); +} + +#endif \ No newline at end of file diff --git a/include/trick/VariableReference.hh b/include/trick/VariableReference.hh new file mode 100644 index 00000000..6e97b217 --- /dev/null +++ b/include/trick/VariableReference.hh @@ -0,0 +1,99 @@ +/************************************************************************* +PURPOSE: (A variable server variable reference. Refactor of VariableReference + based on the VariableServerVariable class previously in the webserver.) +**************************************************************************/ +#ifndef VARIABLE_REFERENCE_HH +#define VARIABLE_REFERENCE_HH + +#include +#include + +#include +#include + +#define MAX_ARRAY_LENGTH 4096 + +union cv_converter ; +namespace Trick { + class VariableReference { + + public: + friend std::ostream& operator<< (std::ostream& s, const Trick::VariableReference& ref); + + VariableReference(std::string var_name); + + // Special constructor to deal with time + VariableReference(std::string var_name, double* time); + + ~VariableReference(); + + const char* getName() const; + TRICK_TYPE getType() const; + + // There are 2 different "units" variables used - REF2->units and REF2->attr->units + // REF2->attr->units should not be changed, it is what the variable is represented in internally + // REF2->units is the unit that has been requested by the variable server client + // REF2->units should be null unless var_units or var_add with units is called + // We'll refer to REF2->attr->units as BaseUnits and REF2->units as RequestedUnits + // Encapsulate all of this away so that no one else has to think about ref->attr->units vs ref->units + // ^ TODO: this is not where the above documentation should be. put it somewhere else. + const char* getBaseUnits() const; + int setRequestedUnits(std::string new_units); + + // These variables have 2 staging buffers that we can swap between to allow for different copy and write-out modes + // stageValue copies data from the simulation into one of the buffers (stage_buffer) + // prepareForWrite swaps the pointers for stage_buffer and write_buffer + // This way we can have data ready for writing, but also be copying out from the sim at the same time + // stageValue must be called first, and then prepare for write, and then writeValue* can be called. + int stageValue(bool validate_address = false); + int prepareForWrite(); + bool isStaged() const; + bool isWriteReady() const; + + // Write out the value to the given outstream. + // write_ready must be true + int getSizeAscii() const; + int getSizeBinary() const; + int writeValueAscii( std::ostream& out ) const; + int writeValueBinary( std::ostream& out , bool byteswap = false) const; + int writeNameBinary( std::ostream& out, bool byteswap = false) const; + int writeSizeBinary( std::ostream& out, bool byteswap = false) const; + int writeTypeBinary( std::ostream& out, bool byteswap = false) const; + + bool validate(); + void tagAsInvalid(); + + // Helper method for byteswapping + static void byteswap_var (char * out, char * in, const VariableReference& ref); + + // TODO: Some system for error messaging + + private: + VariableReference(); + void byteswap_var(char * out, char * in) const; + + // Error refs + static REF2* make_error_ref(std::string in_name); + static REF2* make_do_not_resolve_ref(std::string in_name); + + static int bad_ref_int; + static int do_not_resolve_bad_ref_int; + + REF2 *var_info; + void *address; // -- address of data copied to buffer + int size; // -- size of data copied to buffer + bool deref; // -- indicates whether variable is pointer that needs to be dereferenced + cv_converter * conversion_factor ; // ** udunits conversion factor + TRICK_TYPE trick_type ; // -- Trick type of this variable + + // TODO: use atomics for these + bool staged; + bool write_ready; + + void *stage_buffer; + void *write_buffer; + }; + + std::ostream& operator<< (std::ostream& s, const Trick::VariableReference& ref); +} +#endif diff --git a/include/trick/VariableServer.hh b/include/trick/VariableServer.hh index 10cf4ee2..eeff4b6a 100644 --- a/include/trick/VariableServer.hh +++ b/include/trick/VariableServer.hh @@ -107,17 +107,33 @@ namespace Trick { */ void add_vst(pthread_t thread_id, VariableServerThread * in_vst ) ; + /** + @brief Adds a vst to the map. + */ + void add_session(pthread_t thread_id, VariableServerSession * in_session ) ; + /** @brief Get a vst mapped by thread id @return the VariableServerThread mapped to the thread id if found, or NULL if not found. */ Trick::VariableServerThread * get_vst(pthread_t thread_id) ; + /** + @brief Get a session mapped by thread id + @return the VariableServerSession mapped to the thread id if found, or NULL if not found. + */ + Trick::VariableServerSession * get_session(pthread_t thread_id) ; + /** @brief Delete a vst in the map */ void delete_vst(pthread_t thread_id) ; + /** + @brief Delete a session in the map + */ + void delete_session(pthread_t thread_id) ; + /** @brief @userdesc Return host name from the listen device. @par Python Usage: @@ -283,6 +299,7 @@ namespace Trick { /** Map thread id to the VariableServerThread object.\n */ std::map < pthread_t , VariableServerThread * > var_server_threads ; /**< trick_io(**) */ + std::map < pthread_t , VariableServerSession * > var_server_sessions ; /**< trick_io(**) */ /** Mutex to ensure only one thread manipulates the map of var_server_threads\n */ pthread_mutex_t map_mutex ; /**< trick_io(**) */ @@ -295,8 +312,6 @@ namespace Trick { } -int vs_format_ascii(Trick::VariableReference * var, char *value, size_t value_size); - Trick::VariableServer * var_server_get_var_server() ; // external calls to be made available from input processor @@ -331,8 +346,8 @@ int var_set_freeze_frame_multiple(unsigned int mult) ; int var_set_freeze_frame_offset(unsigned int offset) ; int var_byteswap(bool on_off) ; -int var_signal() ; -int var_multicast(bool on_off) ; +// int var_signal() ; +// int var_multicast(bool on_off) ; int var_send_list_size() ; diff --git a/include/trick/VariableServerListenThread.hh b/include/trick/VariableServerListenThread.hh index 4b7af4e6..41fa2052 100644 --- a/include/trick/VariableServerListenThread.hh +++ b/include/trick/VariableServerListenThread.hh @@ -8,8 +8,11 @@ #include #include -#include "trick/tc.h" +// #include "trick/tc.h" +#include "trick/ClientListener.hh" #include "trick/SysThread.hh" +#include "trick/MulticastManager.hh" + namespace Trick { @@ -41,8 +44,6 @@ namespace Trick { virtual int init_listen_device() ; virtual int check_and_move_listen_device() ; - void create_tcp_socket(const char * address, unsigned short in_port ) ; - virtual void * thread_body() ; int restart() ; @@ -51,17 +52,21 @@ namespace Trick { void pause_listening() ; void restart_listening() ; + void create_tcp_socket(const char * address, unsigned short in_port ) ; + virtual void dump( std::ostream & oss = std::cout ) ; protected: + void initializeMulticast(); + /** Requested variable server source address\n */ - std::string source_address ; /**< trick_units(--) */ + std::string requested_source_address ; /**< trick_units(--) */ /** Requested variable server port number.\n */ - unsigned short port ; /**< trick_units(--) */ + unsigned short requested_port ; /**< trick_units(--) */ /** User requested specific port number\n */ - bool user_port_requested ; /**< trick_units(--) */ + bool user_requested_address ; /**< trick_units(--) */ /** User defined unique tag to easily identify this variable server port.\n */ std::string user_tag; /**< trick_units(--) */ @@ -69,8 +74,11 @@ namespace Trick { /** Turn on/off broadcasting of variable server port.\n */ bool broadcast ; /**< trick_units(--) */ - /** The listen device\n */ - TCDevice listen_dev; /**< trick_io(**) */ + /** The listen device */ + ClientListener listener; + + /* Multicast broadcaster */ + MulticastManager multicast; /** The mutex to stop accepting new connections during restart\n */ pthread_mutex_t restart_pause ; /**< trick_io(**) */ diff --git a/include/trick/VariableServerReference.hh b/include/trick/VariableServerReference.hh deleted file mode 100644 index 6becfd27..00000000 --- a/include/trick/VariableServerReference.hh +++ /dev/null @@ -1,44 +0,0 @@ -/* - PURPOSE: - (VariableServerReference) -*/ - -#ifndef VARIABLESERVERREFERENCE_HH -#define VARIABLESERVERREFERENCE_HH - -#include -#include "trick/reference.h" - -union cv_converter ; - -#define MAX_ARRAY_LENGTH 4096 - -namespace Trick { - -/** - This class provides reference information for variables requested from the variable server by the client. - @author Alex Lin - */ - - class VariableReference { - public: - VariableReference(REF2 * in_ref) ; - ~VariableReference() ; - - friend std::ostream& operator<< (std::ostream& s, const Trick::VariableReference& vref); - - /** Pointer to trick variable reference structure.\n */ - REF2 * ref ; - cv_converter * conversion_factor ; // ** udunits conversion factor - void * buffer_in ; - void * buffer_out ; - void * address ; // -- address of data copied to buffer - int size ; // -- size of data copied to buffer - TRICK_TYPE string_type ; // -- indicate if this is a string or wstring - bool need_deref ; // -- inidicate this is a painter to be dereferenced - } ; - -} - -#endif - diff --git a/include/trick/VariableServerSession.hh b/include/trick/VariableServerSession.hh new file mode 100644 index 00000000..00a05704 --- /dev/null +++ b/include/trick/VariableServerSession.hh @@ -0,0 +1,481 @@ +/************************************************************************* +PURPOSE: (Represent the state of a variable server connection.) +**************************************************************************/ + +#ifndef WSSESSION_HH +#define WSSESSION_HH + +#include +#include + +#include "trick/VariableReference.hh" +#include "trick/ClientConnection.hh" +#include "trick/variable_server_sync_types.h" +#include "trick/tc.h" +#include "trick/variable_server_message_types.h" + + +namespace Trick { + class VariableServerSession { + public: + VariableServerSession(ClientConnection * connection); + ~VariableServerSession(); + + friend std::ostream& operator<< (std::ostream& s, const Trick::VariableServerSession& session); + + int handleMessage(); + + /** + @brief @userdesc Command to add a variable to a list of registered variables for value retrieval. + The variable server will immediately begin returning the variable values to the client at a + frequency according to var_cycle. + @par Python Usage: + @code trick.var_add("") @endcode + @param in_name - the variable name to retrieve + @return always 0 + */ + int var_add( std::string in_name ) ; + + /** + @brief @userdesc Command to add a variable to a list of registered variables for value retrieval, + and also instructs the variable server to return the value in the specified measurement units. + The unit specification will be returned after the variable's value (var_ascii mode only). + Specifying units as "{xx}" will use the unit specification from the variable's model code declaration, + which is essentially a method of querying a variable's unit specification. + The variable server will immediately begin returning the variable values/units to the client at + a frequency according to var_cycle. + @par Python Usage: + @code trick.var_add("", "") @endcode + @param in_name - the variable name to retrieve + @param units_name - the desired units, specified within curly braces + @return always 0 + */ + int var_add( std::string in_name, std::string units_name ) ; + + /** + @brief @userdesc Command to remove a variable (previously registered with var_add) + from the list of registered variables for value retrieval. + @par Python Usage: + @code trick.var_remove("") @endcode + @param in_name - the variable name to remove + @return always 0 + */ + int var_remove( std::string in_name ) ; + + /** + @brief @userdesc Command to instruct the variable server to return the value of a variable + in the specified units (var_ascii mode only). + The variable must have been previously registered with the var_add command. + The unit specification will be returned after the variable's value. + @par Python Usage: + @code trick.var_units("", "") @endcode + @param var_name - the variable name previously registered with var_add + @param units_name - the desired units, specified within curly braces + @return always 0 + @note trick.var_add("my_object.my_variable"); trick.var_units("my_object.my_variable","{m}") + is the same as trick.var_add("my_object.my_variable","{m}") + */ + int var_units(std::string var_name , std::string units_name) ; + + /** + @brief @userdesc Command to instruct the variable server to send a Boolean value indicating + whether the specified variable exists + (is a Trick processed variable in the current simulation). + - var_binary mode: the message indicator is 1, and the returned value is a binary 0 or 1. + - var_ascii mode: the message indicator is "1" followed by a tab, then an ASCII "0" or "1" returned value. + . + @par Python Usage: + @code trick.var_exists("") @endcode + @param in_name - the variable name to query + @return always 0 + */ + int var_exists( std::string in_name ) ; + + /** + @brief @userdesc Command to immediately send the value of a comma separated list of variables + @par Python Usage: + @code trick.var_send_once("", ) @endcode + @param in_name_list - the variables name to retrieve, comma separated + @param num_vars - number of vars in in_name_list + @return always 0 + */ + int var_send_once(std::string in_name_list, int num_vars); + + /** + @brief @userdesc Command to instruct the variable server to immediately send back the values of + variables that are registered with the var_add command + (typically used when var_pause is in effect). Each var_send command sends back all current values + once instead of cyclically. + @par Python Usage: + @code trick.var_send() @endcode + @return always 0 + */ + int var_send() ; + + /** + @brief @userdesc Command to remove all variables from the list of variables currently + registered with the var_add command, + so the variable server will no longer send cyclic values until new var_add commands are issued. + @par Python Usage: + @code trick.var_clear() @endcode + @return always 0 + */ + int var_clear() ; + + /** + @brief @userdesc Turns on validating addresses before they are referenced + @par Python Usage: + @code trick.var_validate_address() @endcode + @return always 0 + */ + int var_validate_address(bool on_off) ; + + /** + @brief @userdesc Command to instruct the variable server to output debug information. + @par Python Usage: + @code trick.var_debug() @endcode + @return always 0 + @param level - 1,2,or 3, higher number increases amount of info output + */ + int var_debug(int level) ; + + /** + @brief @userdesc Command to instruct the variable server to return values in ASCII format (this is the default). + @par Python Usage: + @code trick.var_ascii() @endcode + @return always 0 + */ + int var_ascii() ; + + /** + @brief @userdesc Command to instruct the variable server to return values in binary format. + @par Python Usage: + @code trick.var_binary() @endcode + @return always 0 + */ + int var_binary() ; + + /** + @brief @userdesc Command to instruct the variable server to return values in binary format, + but saves space in the returned messages + by omitting the variable names. + @par Python Usage: + @code trick.var_binary_nonames() @endcode + @return always 0 + */ + int var_binary_nonames() ; + + /** + @brief @userdesc Command to tell the server when to copy data + - VS_COPY_ASYNC = copies data asynchronously. (default) + - VS_COPY_SCHEDULED = copies data as an automatic_last job in main thread + - VS_COPY_TOP_OF_FRAME = copies data at top of frame + @par Python Usage: + @code trick.var_set_copy_mode() @endcode + @param mode - One of the above enumerations + @return 0 if successful, -1 if error + */ + int var_set_copy_mode(int on_off) ; + + /** + @brief @userdesc Command to tell the server when to copy data + - VS_WRITE_ASYNC = writes data asynchronously. (default) + - VS_WRITE_WHEN_COPIED = writes data as soon as it's copied from sim + @par Python Usage: + @code trick.var_set_write_mode() @endcode + @param mode - One of the above enumerations + @return 0 if successful, -1 if error + */ + int var_set_write_mode(int on_off) ; + + /** + @brief @userdesc Command to put the current variable server/client connection in sync mode, + so that values to be sent to the client + are guaranteed to be homogenous, that is from the same execution frame (the default is asynchronous). + - async/async mode: the variable server thread itself copies the client data, + independent of the execution frame so may not be homogenous. + - sync/async mode: a variable server automatic_last job retrieves client requested data. + Data is sent asynchronously on separate thread. + - sync/sync mode: a variable server automatic_last job retrieves client requested data. + Data is sent in same automatic_last job. + . + @par Python Usage: + @code trick.var_sync() @endcode + @param on_off - 0 = fully asynchronous. 1 = sync data gather, async socket write. + 2 = sync data gather, sync socket write + @return always 0 + */ + int var_sync(int on_off) ; + + /** + @brief @userdesc Set the frame multiple + @par Python Usage: + @code trick.var_set_frame_multiple() @endcode + @param mult - The requested multiple + @return 0 + */ + int var_set_frame_multiple(unsigned int mult) ; + + /** + @brief @userdesc Set the frame offset + @par Python Usage: + @code trick.var_set_frame_offset() @endcode + @param offset - The requested offset + @return 0 + */ + int var_set_frame_offset(unsigned int offset) ; + + /** + @brief @userdesc Set the frame multiple + @par Python Usage: + @code trick.var_set_freeze_frame_multiple() @endcode + @param mult - The requested multiple + @return 0 + */ + int var_set_freeze_frame_multiple(unsigned int mult) ; + + /** + @brief @userdesc Set the frame offset + @par Python Usage: + @code trick.var_set_freeze_frame_offset() @endcode + @param offset - The requested offset + @return 0 + */ + int var_set_freeze_frame_offset(unsigned int offset) ; + + /** + @brief @userdesc Command to instruct the variable server to byteswap the return values + (only has an effect in var_binary mode). + The default is no byteswap - it is assumed server and client are same endianness. + If not, the user must issue the var_byteswap command. + @par Python Usage: + @code trick.var_byteswap() @endcode + @param on_off - true (or 1) to byteswap the return data, false (or 0) to return data as is + @return always 0 + */ + int var_byteswap(bool on_off) ; + + /** + @brief @userdesc Command to turn on variable server logged messages to a playback file. + All messages received from all clients will be saved to file named "playback" in the RUN directory. + @par Python Usage: + @code trick.set_log_on() @endcode + @return always 0 + */ + int set_log_on() ; + + /** + @brief @userdesc Command to turn off variable server logged messages to a playback file. + @par Python Usage: + @code trick.set_log_off() @endcode + @return always 0 + */ + int set_log_off() ; + + /** + @brief Command to send the number of items in the var_add list. + The variable server sends a message indicator of "3", followed by the total number of variables being sent. + */ + int send_list_size(); + + /** + @brief Special command to instruct the variable server to send the contents of the S_sie.resource file; used by TV. + The variable server sends a message indicator of "2", followed by a tab, followed by the file contents + which are then sent as sequential ASCII messages with a maximum size of 4096 bytes each. + */ + int send_sie_resource(); + + /** + @brief Special command to only send the class sie class information + */ + int send_sie_class(); + + /** + @brief Special command to only send the enumeration sie class information + */ + int send_sie_enum(); + + /** + @brief Special command to only send the top level objects sie class information + */ + int send_sie_top_level_objects(); + + /** + @brief Special command to send an arbitrary file through the variable server. + */ + int send_file(std::string file_name); + + /** + @brief gets the send_stdio flag. + */ + bool get_send_stdio() ; + + /** + @brief sets the send_stdio flag. + */ + int set_send_stdio(bool on_off) ; + + /** + @brief @userdesc Command to set the frequencty at which the variable server will send values + of variables that have been registered using + the var_add command. If var_cycle is not specified, the default cycle is 0.1 seconds. + @par Python Usage: + @code trick.var_cycle() @endcode + @param in_cycle - the desired frequency in seconds + @return always 0 + */ + int var_cycle(double in_cycle) ; + + /** + @brief Get the pause state of this thread. + */ + bool get_pause() ; + + /** + @brief Set the pause state of this thread. + */ + void set_pause(bool on_off) ; + + /** + @brief Write data in the appropriate format (var_ascii or var_binary) from variable output buffers to socket. + */ + int write_data(); + + /** + @brief Write data from the given var only to the appropriate format (var_ascii or var_binary) from variable output buffers to socket. + */ + int write_data(std::vector& var, VS_MESSAGE_TYPE message_type) ; + + /** + @brief Copy client variable values from Trick memory to each variable's output buffer. + */ + int copy_sim_data(); + + /** + @brief Copy given variable values from Trick memory to each variable's output buffer. + cyclical indicated whether it is a normal cyclical copy or a send_once copy + */ + int copy_sim_data(std::vector& given_vars, bool cyclical); + + int var_exit(); + + int transmit_file(std::string sie_file); + + int copy_data_freeze(); + int copy_data_freeze_scheduled(long long curr_tics); + int copy_data_scheduled(long long curr_tics); + int copy_data_top(); + + // VS_COPY_MODE get_copy_mode(); + // VS_WRITE_MODE get_write_mode(); + + void disconnect_references(); + + long long get_next_tics() const; + + long long get_freeze_next_tics() const; + + int freeze_init(); + + double get_update_rate() const; + + // These should be private probably + int write_binary_data(const std::vector& given_vars, VS_MESSAGE_TYPE message_type); + int write_ascii_data(const std::vector& given_vars, VS_MESSAGE_TYPE message_type ); + int write_stdio(int stream, std::string text); + + VS_WRITE_MODE get_write_mode () const; + VS_COPY_MODE get_copy_mode () const; + + + pthread_mutex_t copy_mutex; /**< trick_io(**) */ + + /** Toggle to indicate var_exit commanded.\n */ + bool exit_cmd ; /**< trick_io(**) */ + + private: + // int sendErrorMessage(const char* fmt, ... ); + // int sendSieMessage(void); + // int sendUnitsMessage(const char* vname); + + ClientConnection * connection; /**< trick_io(**) */ + /** The trickcomm device used for the connection to the client.\n */ + + VariableReference * find_session_variable(std::string name) const; + + double stageTime; + bool dataStaged; + + std::vector session_variables; /**< trick_io(**) */ + bool cyclicSendEnabled; /**< trick_io(**) */ + long long nextTime; /**< trick_io(**) */ + long long intervalTimeTics; /**< trick_io(**) */ + + /** Value set in var_cycle command.\n */ + double update_rate ; /**< trick_io(**) */ + + /** The update rate in integer tics.\n */ + long long cycle_tics ; /**< trick_io(**) */ + + /** The next call time in integer tics of the job to copy client data (sync mode).\n */ + long long next_tics ; /**< trick_io(**) */ + + /** The next call time in integer tics of the job to copy client data (sync mode).\n */ + long long freeze_next_tics ; /**< trick_io(**) */ + + /** The simulation time converted to seconds\n */ + double time ; /**< trick_units(s) */ + + /** Toggle to set variable server copy as top_of_frame, scheduled, async \n */ + VS_COPY_MODE copy_mode ; /**< trick_io(**) */ + + /** Toggle to set variable server writes as when copied or async.\n */ + VS_WRITE_MODE write_mode ; /**< trick_io(**) */ + + /** multiples of frame_count to copy data. Only used at top_of_frame\n */ + int frame_multiple ; /**< trick_io(**) */ + + /** multiples of frame_count to copy data. Only used at top_of_frame\n */ + int frame_offset ; /**< trick_io(**) */ + + /** multiples of frame_count to copy data. Only used at top_of_frame\n */ + int freeze_frame_multiple ; /**< trick_io(**) */ + + /** multiples of frame_count to copy data. Only used at top_of_frame\n */ + int freeze_frame_offset ; /**< trick_io(**) */ + + // The way the modes are handled is confusing. TODO: refactor >:( + + /** Toggle to tell variable server to byteswap returned values.\n */ + bool byteswap ; /**< trick_io(**) */ + + /** Toggle to tell variable server return data in binary format.\n */ + bool binary_data ; /**< trick_io(**) */ + + /** Toggle to tell variable server return data in binary format without the variable names.\n */ + bool binary_data_nonames ; /**< trick_io(**) */ + + /** Value (1,2,or 3) that causes the variable server to output increasing amounts of debug information.\n */ + int debug ; /**< trick_io(**) */ + + /** Toggle to enable/disable this variable server thread.\n */ + bool enabled ; /**< trick_io(**) */ + + /** Toggle to turn on/off variable server logged messages to a playback file.\n */ + bool log ; /**< trick_io(**) */ + + /** Toggle to indicate var_pause commanded.\n */ + bool pause_cmd ; /**< trick_io(**) */ + + /** Save pause state while reloading a checkpoint.\n */ + bool saved_pause_cmd ; /**< trick_io(**) */ + + bool send_stdio; + + bool validate_address; + + int packets_copied; + }; +} + +#endif diff --git a/include/trick/VariableServerThread.hh b/include/trick/VariableServerThread.hh index fed81f59..3d932524 100644 --- a/include/trick/VariableServerThread.hh +++ b/include/trick/VariableServerThread.hh @@ -11,16 +11,21 @@ #include #include #include "trick/tc.h" +#include "trick/TCConnection.hh" #include "trick/SysThread.hh" -#include "trick/VariableServerReference.hh" +#include "trick/VariableServerSession.hh" #include "trick/variable_server_sync_types.h" #include "trick/variable_server_message_types.h" - +#include "trick/ClientListener.hh" namespace Trick { class VariableServer ; + /** Flag to indicate the connection has been made\n */ + enum ConnectionStatus { CONNECTION_PENDING, CONNECTION_SUCCESS, CONNECTION_FAIL }; + + /** This class provides variable server command processing on a separate thread for each client. @author Alex Lin @@ -28,15 +33,13 @@ namespace Trick { class VariableServerThread : public Trick::SysThread { public: - enum ConnectionType { TCP, UDP, MCAST } ; - friend std::ostream& operator<< (std::ostream& s, Trick::VariableServerThread& vst); /** @brief Constructor. @param listen_dev - the TCDevice set up in listen() */ - VariableServerThread(TCDevice * in_listen_dev ) ; + VariableServerThread(ClientListener * in_listen_dev ) ; virtual ~VariableServerThread() ; /** @@ -45,10 +48,12 @@ namespace Trick { */ static void set_vs_ptr(Trick::VariableServer * in_vs) ; + void set_client_tag(std::string tag); + /** - @brief Wait for the connection_accepted flag to be set. + @brief Block until thread has accepted connection */ - void wait_for_accept() ; + ConnectionStatus wait_for_accept() ; /** @brief The main loop of the variable server thread that reads and processes client commands. @@ -56,391 +61,12 @@ namespace Trick { */ virtual void * thread_body() ; - /** - @brief @userdesc Command to add a variable to a list of registered variables for value retrieval. - The variable server will immediately begin returning the variable values to the client at a - frequency according to var_cycle. - @par Python Usage: - @code trick.var_add("") @endcode - @param in_name - the variable name to retrieve - @return always 0 - */ - int var_add( std::string in_name ) ; - - /** - @brief @userdesc Command to add a variable to a list of registered variables for value retrieval, - and also instructs the variable server to return the value in the specified measurement units. - The unit specification will be returned after the variable's value (var_ascii mode only). - Specifying units as "{xx}" will use the unit specification from the variable's model code declaration, - which is essentially a method of querying a variable's unit specification. - The variable server will immediately begin returning the variable values/units to the client at - a frequency according to var_cycle. - @par Python Usage: - @code trick.var_add("", "") @endcode - @param in_name - the variable name to retrieve - @param units_name - the desired units, specified within curly braces - @return always 0 - */ - int var_add( std::string in_name, std::string units_name ) ; - - /** - @brief @userdesc Command to remove a variable (previously registered with var_add) - from the list of registered variables for value retrieval. - @par Python Usage: - @code trick.var_remove("") @endcode - @param in_name - the variable name to remove - @return always 0 - */ - int var_remove( std::string in_name ) ; - - /** - @brief @userdesc Command to instruct the variable server to return the value of a variable - in the specified units (var_ascii mode only). - The variable must have been previously registered with the var_add command. - The unit specification will be returned after the variable's value. - @par Python Usage: - @code trick.var_units("", "") @endcode - @param var_name - the variable name previously registered with var_add - @param units_name - the desired units, specified within curly braces - @return always 0 - @note trick.var_add("my_object.my_variable"); trick.var_units("my_object.my_variable","{m}") - is the same as trick.var_add("my_object.my_variable","{m}") - */ - int var_units(std::string var_name , std::string units_name) ; - - /** - @brief @userdesc Command to instruct the variable server to send a Boolean value indicating - whether the specified variable exists - (is a Trick processed variable in the current simulation). - - var_binary mode: the message indicator is 1, and the returned value is a binary 0 or 1. - - var_ascii mode: the message indicator is "1" followed by a tab, then an ASCII "0" or "1" returned value. - . - @par Python Usage: - @code trick.var_exists("") @endcode - @param in_name - the variable name to query - @return always 0 - */ - int var_exists( std::string in_name ) ; - - /** - @brief @userdesc Command to immediately send the value of a comma separated list of variables - @par Python Usage: - @code trick.var_send_once("", ) @endcode - @param in_name_list - the variables name to retrieve, comma separated - @param num_vars - number of vars in in_name_list - @return always 0 - */ - int var_send_once(std::string in_name_list, int num_vars); - - /** - @brief @userdesc Command to instruct the variable server to immediately send back the values of - variables that are registered with the var_add command - (typically used when var_pause is in effect). Each var_send command sends back all current values - once instead of cyclically. - @par Python Usage: - @code trick.var_send() @endcode - @return always 0 - */ - int var_send() ; - - /** - @brief @userdesc Command to remove all variables from the list of variables currently - registered with the var_add command, - so the variable server will no longer send cyclic values until new var_add commands are issued. - @par Python Usage: - @code trick.var_clear() @endcode - @return always 0 - */ - int var_clear() ; - - /** - @brief @userdesc Command to set the frequencty at which the variable server will send values - of variables that have been registered using - the var_add command. If var_cycle is not specified, the default cycle is 0.1 seconds. - @par Python Usage: - @code trick.var_cycle() @endcode - @param in_cycle - the desired frequency in seconds - @return always 0 - */ - int var_cycle(double in_cycle) ; - - /** - @brief Get the pause state of this thread. - */ - bool get_pause() ; - - /** - @brief Set the pause state of this thread. - */ - void set_pause(bool on_off) ; - - /** - @brief @userdesc Command to terminate the current variable server/client connection. - @par Python Usage: - @code trick.var_exit() @endcode - @return always 0 - */ - int var_exit() ; - - /** - @brief @userdesc Turns on validating addresses before they are referenced - @par Python Usage: - @code trick.var_validate_address() @endcode - @return always 0 - */ - int var_validate_address(bool on_off) ; - - /** - @brief @userdesc Command to instruct the variable server to output debug information. - @par Python Usage: - @code trick.var_debug() @endcode - @return always 0 - @param level - 1,2,or 3, higher number increases amount of info output - */ - int var_debug(int level) ; - - /** - @brief @userdesc Command to instruct the variable server to return values in ASCII format (this is the default). - @par Python Usage: - @code trick.var_ascii() @endcode - @return always 0 - */ - int var_ascii() ; - - /** - @brief @userdesc Command to instruct the variable server to return values in binary format. - @par Python Usage: - @code trick.var_binary() @endcode - @return always 0 - */ - int var_binary() ; - - /** - @brief @userdesc Command to instruct the variable server to return values in binary format, - but saves space in the returned messages - by omitting the variable names. - @par Python Usage: - @code trick.var_binary_nonames() @endcode - @return always 0 - */ - int var_binary_nonames() ; - - /** - @brief @userdesc Command to tell the server when to copy data - - VS_COPY_ASYNC = copies data asynchronously. (default) - - VS_COPY_SCHEDULED = copies data as an automatic_last job in main thread - - VS_COPY_TOP_OF_FRAME = copies data at top of frame - @par Python Usage: - @code trick.var_set_copy_mode() @endcode - @param mode - One of the above enumerations - @return 0 if successful, -1 if error - */ - int var_set_copy_mode(int on_off) ; - - /** - @brief @userdesc Command to tell the server when to copy data - - VS_WRITE_ASYNC = writes data asynchronously. (default) - - VS_WRITE_WHEN_COPIED = writes data as soon as it's copied from sim - @par Python Usage: - @code trick.var_set_write_mode() @endcode - @param mode - One of the above enumerations - @return 0 if successful, -1 if error - */ - int var_set_write_mode(int on_off) ; - - /** - @brief @userdesc Command to put the current variable server/client connection in sync mode, - so that values to be sent to the client - are guaranteed to be homogenous, that is from the same execution frame (the default is asynchronous). - - async/async mode: the variable server thread itself copies the client data, - independent of the execution frame so may not be homogenous. - - sync/async mode: a variable server automatic_last job retrieves client requested data. - Data is sent asynchronously on separate thread. - - sync/sync mode: a variable server automatic_last job retrieves client requested data. - Data is sent in same automatic_last job. - . - @par Python Usage: - @code trick.var_sync() @endcode - @param on_off - 0 = fully asynchronous. 1 = sync data gather, async socket write. - 2 = sync data gather, sync socket write - @return always 0 - */ - int var_sync(int on_off) ; - - /** - @brief @userdesc Set the frame multiple - @par Python Usage: - @code trick.var_set_frame_multiple() @endcode - @param mult - The requested multiple - @return 0 - */ - int var_set_frame_multiple(unsigned int mult) ; - - /** - @brief @userdesc Set the frame offset - @par Python Usage: - @code trick.var_set_frame_offset() @endcode - @param offset - The requested offset - @return 0 - */ - int var_set_frame_offset(unsigned int offset) ; - - /** - @brief @userdesc Set the frame multiple - @par Python Usage: - @code trick.var_set_freeze_frame_multiple() @endcode - @param mult - The requested multiple - @return 0 - */ - int var_set_freeze_frame_multiple(unsigned int mult) ; - - /** - @brief @userdesc Set the frame offset - @par Python Usage: - @code trick.var_set_freeze_frame_offset() @endcode - @param offset - The requested offset - @return 0 - */ - int var_set_freeze_frame_offset(unsigned int offset) ; - - /** - @brief @userdesc Command to instruct the variable server to byteswap the return values - (only has an effect in var_binary mode). - The default is no byteswap - it is assumed server and client are same endianness. - If not, the user must issue the var_byteswap command. - @par Python Usage: - @code trick.var_byteswap() @endcode - @param on_off - true (or 1) to byteswap the return data, false (or 0) to return data as is - @return always 0 - */ - int var_byteswap(bool on_off) ; - - /** - @brief CURRENTLY NOT IMPLEMENTED - */ - int var_signal() ; - - /** - @brief @userdesc Command to turn on variable server logged messages to a playback file. - All messages received from all clients will be saved to file named "playback" in the RUN directory. - @par Python Usage: - @code trick.set_log_on() @endcode - @return always 0 - */ - int set_log_on() ; - - /** - @brief @userdesc Command to turn off variable server logged messages to a playback file. - @par Python Usage: - @code trick.set_log_off() @endcode - @return always 0 - */ - int set_log_off() ; - - /** - @brief CURRENTLY NOT IMPLEMENTED\n - Command to instruct the variable server to send values via multicast socket. - */ - int var_multicast(bool on_off) ; - - /** - @brief Command to send the number of items in the var_add list. - The variable server sends a message indicator of "3", followed by the total number of variables being sent. - */ - int send_list_size(); - - /** - @brief Special command to instruct the variable server to send the contents of the S_sie.resource file; used by TV. - The variable server sends a message indicator of "2", followed by a tab, followed by the file contents - which are then sent as sequential ASCII messages with a maximum size of 4096 bytes each. - */ - int send_sie_resource(); - - /** - @brief Special command to only send the class sie class information - */ - int send_sie_class(); - - /** - @brief Special command to only send the enumeration sie class information - */ - int send_sie_enum(); - - /** - @brief Special command to only send the top level objects sie class information - */ - int send_sie_top_level_objects(); - - /** - @brief Special command to send an arbitrary file through the variable server. - */ - int send_file(std::string file_name); - - /** - @brief Copy client variable values from Trick memory to each variable's output buffer. - */ - int copy_sim_data(); - - /** - @brief Copy given variable values from Trick memory to each variable's output buffer. - cyclical indicated whether it is a normal cyclical copy or a send_once copy - */ - int copy_sim_data(std::vector given_vars, bool cyclical); - - /** - @brief Write data in the appropriate format (var_ascii or var_binary) from variable output buffers to socket. - */ - int write_data(); - - /** - @brief Write data from the given var only to the appropriate format (var_ascii or var_binary) from variable output buffers to socket. - */ - int write_data(std::vector var) ; - - /** - @brief gets the send_stdio flag. - */ - bool get_send_stdio() ; - - /** - @brief sets the send_stdio flag. - */ - int set_send_stdio(bool on_off) ; - VariableServer * get_vs() ; - TCDevice & get_connection() ; - - /** - @brief Internal function used by input processor to send stdout and stderr to the client. - @return always 0 - */ - int write_stdio(int stream , std::string text ) ; - - int freeze_init() ; - - int copy_data_freeze() ; - int copy_data_freeze_scheduled(long long curr_tics) ; - int copy_data_scheduled(long long curr_tics) ; - int copy_data_top() ; void preload_checkpoint() ; + void restart() ; - long long get_next_tics() ; - long long get_freeze_next_tics() ; - - /** - @brief creates a udp socket with the specified address and port. UDP ports do not go through - the listen and accept states - */ - int create_udp_socket(const char * address, unsigned short in_port) ; - - /** - @brief creates a multicast socket with the specified address and port. mcast ports do not go through - the listen and accept states - */ - int create_mcast_socket(const char * mcast_address, const char * address, unsigned short in_port) ; - protected: /** @@ -448,42 +74,15 @@ namespace Trick { */ int transmit_file(std::string file_name); - /** - @brief Called by write_data to write given variables to socket in var_binary format. - */ - int write_binary_data( int Start, char *buf1, const std::vector& given_vars, VS_MESSAGE_TYPE message_type); - - /** - @brief Called by write_data to write given variables to socket in var_ascii format. - */ - int write_ascii_data(char * dest_buf, size_t dest_buf_size, const std::vector& given_vars, VS_MESSAGE_TYPE message_type ); - - /** - @brief Construct a variable reference from the string in_name and handle error checking - */ - VariableReference* create_var_reference(std::string in_name); - - /** - @brief Make a time reference. - */ - REF2* make_time_ref(); - - /** - @brief Make a "bad-reference" reference. - */ - REF2* make_error_ref(std::string in_name); - /** The Master variable server object. */ static VariableServer * vs ; + /** this is where a lot of this should happen now */ + VariableServerSession * session; + /** The listen device from the variable server\n */ - TCDevice * listen_dev; /**< trick_io(**) */ - - /** The trickcomm device used for the connection to the client.\n */ - TCDevice connection ; /**< trick_io(**) */ - - /** The type of connection we have.\n */ - ConnectionType conn_type ; /**< trick_io(**) */ + ClientListener * listener; /**< trick_io(**) */ + TCConnection connection; /**< trick_io(**) */ /** Value (1,2,or 3) that causes the variable server to output increasing amounts of debug information.\n */ int debug ; /**< trick_io(**) */ @@ -491,102 +90,25 @@ namespace Trick { /** Toggle to enable/disable this variable server thread.\n */ bool enabled ; /**< trick_io(**) */ - /** Toggle to turn on/off variable server logged messages to a playback file.\n */ - bool log ; /**< trick_io(**) */ - - /** Toggle to indicate var_pause commanded.\n */ - bool pause_cmd ; /**< trick_io(**) */ - - /** Save pause state while reloading a checkpoint.\n */ - bool saved_pause_cmd ; /**< trick_io(**) */ - - /** Toggle to indicate var_exit commanded.\n */ - bool exit_cmd ; /**< trick_io(**) */ - - /** Set to true to validate all addresses before copying.\n */ - bool validate_address ; /**< trick_io(**) */ - - /** The mutex to protect variable output buffers when copying variable values to them from Trick memory.\n */ - pthread_mutex_t copy_mutex ; /**< trick_io(**) */ + ConnectionStatus connection_status ; /**< trick_io(**) */ + pthread_mutex_t connection_status_mutex; + pthread_cond_t connection_status_cv; /** The mutex pauses all processing during checkpoint restart */ pthread_mutex_t restart_pause ; /**< trick_io(**) */ - /** Dummy integer for bad references.\n */ - static int bad_ref_int ; /**< trick_io(**) */ - - /** Dummy integer for bad references. If a variable points here, do not try to re-resolve address\n */ - static int do_not_resolve_bad_ref_int ; /**< trick_io(**) */ + // bool pause_cmd; + bool saved_pause_cmd; /** The simulation time converted to seconds\n */ double time ; /**< trick_units(s) */ - /** List of client requested variables.\n */ - std::vector vars; /**< trick_io(**) */ - - /** Toggle to set variable server copy as top_of_frame, scheduled, async \n */ - VS_COPY_MODE copy_mode ; /**< trick_io(**) */ - - /** Toggle to set variable server writes as when copied or async.\n */ - VS_WRITE_MODE write_mode ; /**< trick_io(**) */ - - /** multiples of frame_count to copy data. Only used at top_of_frame\n */ - int frame_multiple ; /**< trick_io(**) */ - - /** multiples of frame_count to copy data. Only used at top_of_frame\n */ - int frame_offset ; /**< trick_io(**) */ - - /** multiples of frame_count to copy data. Only used at top_of_frame\n */ - int freeze_frame_multiple ; /**< trick_io(**) */ - - /** multiples of frame_count to copy data. Only used at top_of_frame\n */ - int freeze_frame_offset ; /**< trick_io(**) */ - - /** Toggle to tell variable server to byteswap returned values.\n */ - bool byteswap ; /**< trick_io(**) */ - - /** Toggle to tell variable server return data in binary format.\n */ - bool binary_data ; /**< trick_io(**) */ - - /** Toggle to tell variable server return data in binary format without the variable names.\n */ - bool binary_data_nonames ; /**< trick_io(**) */ - /** Toggle to tell variable server to send data multicast or point to point.\n */ bool multicast ; /**< trick_io(**) */ - - /** Flag to indicate the connection has been made\n */ - bool connection_accepted ; /**< trick_io(**) */ - - /** Value set in var_cycle command.\n */ - double update_rate ; /**< trick_io(**) */ - - /** The update rate in integer tics.\n */ - long long cycle_tics ; /**< trick_io(**) */ - - /** The next call time in integer tics of the job to copy client data (sync mode).\n */ - long long next_tics ; /**< trick_io(**) */ - - /** The next call time in integer tics of the job to copy client data (sync mode).\n */ - long long freeze_next_tics ; /**< trick_io(**) */ - - /** Indicate whether variable data has been written into buffer_in.\n */ - bool var_data_staged; /**< trick_io(**) */ - - /** number of packets copied to client \n */ - unsigned int packets_copied ; /**< trick_io(**) */ - - /** Toggle to indicate sending python stdout and stderr to client\n */ - bool send_stdio ; /**< trick_io(**) */ - - /** Holding area for the incoming message\n */ - char *incoming_msg; /**< trick_io(**) */ - - /** Message with '\r' characters removed\n */ - char *stripped_msg; /**< trick_io(**) */ - - /** Maximum size of incoming message\n */ - static const unsigned int MAX_CMD_LEN = 200000 ; } ; + + std::ostream& operator<< (std::ostream& s, VariableServerThread& vst); + } #endif diff --git a/include/trick/var_binary_parser.hh b/include/trick/var_binary_parser.hh index 723166b5..17a6c4e8 100644 --- a/include/trick/var_binary_parser.hh +++ b/include/trick/var_binary_parser.hh @@ -139,4 +139,4 @@ class ParsedBinaryMessage { const static size_t variable_name_length_size; const static size_t variable_type_size; const static size_t variable_size_size; -}; \ No newline at end of file +}; diff --git a/include/trick/variable_server.h b/include/trick/variable_server.h deleted file mode 100644 index 163b2d3e..00000000 --- a/include/trick/variable_server.h +++ /dev/null @@ -1,68 +0,0 @@ -/* -PURPOSE: - (Allows clients to get and set Trick parameters) -PROGRAMMERS: - (((Keith Vetter) (LinCom) (September 2001) (--))) -*/ - -#ifndef VARIABLE_SERVER_H -#define VARIABLE_SERVER_H - -#include - -#include "trick/reference.h" -#include "trick/tc.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - REF2 ref; - double scale_factor; - double bias; -} VARIABLE_NODE; - -typedef struct { - int socket ; /* ** multicast socket file descriptor */ - struct sockaddr_in addr ; /* ** multicast socket info */ -} MCAST_INFO; - -typedef struct VARIABLE_SERVER_struct { - int enabled ; - int debug; /* ** Variable_server debugging */ - int synchronous ; - double update_rate; - double next; - int binary_data; - int no_handshake; - int num_vars; - int clear_cmd; - int send_cmd; - int pause_cmd; - int exists_cmd; - int exit_cmd; - VARIABLE_NODE *vars; - - int multicast_on ; /* -- flag to switch between TCdevice and multcast socket */ - TCDevice * connection ; - MCAST_INFO mcast_info ; - char local_byteorder ; - - pthread_t thread_id ; -} VARIABLE_SERVER; - -//void *var_server(void *); /* Server thread */ -//void *var_serve_init(void *); /* Initialize server */ -//void exit_var_server(void *); /* Exit handler for var init server */ -//void exit_var_serv_threads( void ); /* Exit handler for var init server */ - -int vs_mcast_init(MCAST_INFO * M, char * address , int port ) ; -//int vs_write_data(VARIABLE_SERVER * V) ; -//int vs_write_error(VARIABLE_SERVER * V, char * incoming_str , char * error_str ) ; -//int vs_format_ascii(REF2 * ref, double scale_factor, double bias, char *value) ; - -#ifdef __cplusplus -} -#endif -#endif diff --git a/share/trick/makefiles/Makefile.common b/share/trick/makefiles/Makefile.common index 104d5aad..154621fa 100644 --- a/share/trick/makefiles/Makefile.common +++ b/share/trick/makefiles/Makefile.common @@ -66,7 +66,7 @@ export TRICK_PYTHON_PATH := $(TRICK_PYTHON_PATH) export TRICK_GTE_EXT := $(TRICK_GTE_EXT) export TRICK_HOST_CPU := $(shell TRICK_FORCE_32BIT=$(TRICK_FORCE_32BIT) $(TRICK_HOME)/bin/trick-gte TRICK_HOST_CPU) export TRICK_EXEC_LINK_LIBS := ${PTHREAD_LIBS} $(PYTHON_LIB) $(UDUNITS_LDFLAGS) $(PLATFORM_LIBS) -lm -ldl -export TRICK_LIBS := ${RPATH} -L${TRICK_LIB_DIR} -ltrick -ltrick_pyip -ltrick_comm -ltrick_math -ltrick_units -ltrick_mm +export TRICK_LIBS := ${RPATH} -L${TRICK_LIB_DIR} -ltrick -ltrick_pyip -ltrick_comm -ltrick_math -ltrick_units -ltrick_mm -ltrick_connection_handlers export TRICK_SYSTEM_LDFLAGS := $(TRICK_SYSTEM_LDFLAGS) export TRICK_SYSTEM_ICG_EXCLUDE := $(TRICK_SYSTEM_ICG_EXCLUDE) export TRICK_SWIG_FLAGS := $(TRICK_SWIG_FLAGS) diff --git a/test/SIM_test_varserv/RUN_test/unit_test.py b/test/SIM_test_varserv/RUN_test/unit_test.py index bfdd413a..e2de1e92 100644 --- a/test/SIM_test_varserv/RUN_test/unit_test.py +++ b/test/SIM_test_varserv/RUN_test/unit_test.py @@ -5,7 +5,7 @@ from trick.unit_test import * def main(): - trick.var_server_set_port(40000) + trick.var_server_set_port(4000) trick.var_ascii() trick.real_time_enable() trick.exec_set_software_frame(0.01) diff --git a/test/SIM_test_varserv/S_overrides.mk b/test/SIM_test_varserv/S_overrides.mk index 36707008..1157f7b9 100644 --- a/test/SIM_test_varserv/S_overrides.mk +++ b/test/SIM_test_varserv/S_overrides.mk @@ -12,4 +12,4 @@ test_client: models/test_client/test_client.cpp clean_test_client: rm -f models/test_client/test_client - \ No newline at end of file + diff --git a/test/SIM_test_varserv/models/test_client/test_client.cpp b/test/SIM_test_varserv/models/test_client/test_client.cpp index 070606ed..ffc1aefb 100644 --- a/test/SIM_test_varserv/models/test_client/test_client.cpp +++ b/test/SIM_test_varserv/models/test_client/test_client.cpp @@ -150,7 +150,6 @@ class Socket { std::string receive () { char buffer[SOCKET_BUF_SIZE]; - int numBytes = recv(_socket_fd, buffer, SOCKET_BUF_SIZE, 0); if (numBytes < 0) { } else if (numBytes < SOCKET_BUF_SIZE) { @@ -164,6 +163,25 @@ class Socket { ret = receive(); } + std::vector receive_bytes() { + unsigned char buffer[SOCKET_BUF_SIZE]; + int numBytes = recv(_socket_fd, buffer, SOCKET_BUF_SIZE, 0); + if (numBytes < 0) { + std::cout << "Failed to read from socket" << std::endl; + } + + std::vector bytes; + for (int i = 0; i < numBytes; i++) { + bytes.push_back(buffer[i]); + } + + return bytes; + } + + void operator>> (std::string& ret) { + ret = receive(); + } + std::vector receive_bytes() { unsigned char buffer[SOCKET_BUF_SIZE]; int numBytes = recv(_socket_fd, buffer, SOCKET_BUF_SIZE, 0); @@ -412,12 +430,23 @@ TEST_F (VariableServerTestMulticast, Strings) { EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0); + expected = std::string("5\tI am already far north of London, and as I walk in the streets of Petersburgh, I feel a cold northern breeze play upon my cheeks, which braces my nerves and fills me with delight. Do you understand this feeling?"); socket << "trick.var_send_once(\"vsx.vst.p\")\n"; multicast_listener >> reply; EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0); + + // TODO: Does wchar actually work? + // expected = std::string("5\tThis breeze, which has travelled from the regions towards which I am advancing, gives me a foretaste of those icy climes. Inspirited by this wind of promise, my daydreams become more fervent and vivid."); + // socket << "trick.var_send_once(\"vsx.vst.q\")\n"; + + // socket >> reply; + + // std::cout << "\tExpected: " << expected << "\n\tActual: " << reply << std::endl; + + // EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0); } @@ -572,6 +601,7 @@ TEST_F (VariableServerTestAltListener, Strings) { socket >> reply; EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0); + } TEST_F (VariableServerTestAltListener, AddRemove) { @@ -649,6 +679,10 @@ TEST_F (VariableServerTestAltListener, RestartAndSet) { /* Normal case tests */ /*********************************************/ +void spin (Socket& socket, int wait_cycles = 5) { + socket.receive(); +} + TEST_F (VariableServerTest, Strings) { if (socket_status != 0) { FAIL(); @@ -715,7 +749,42 @@ TEST_F (VariableServerTest, NoExtraTab) { EXPECT_STREQ(reply.c_str(), expected.c_str()); } -TEST_F (VariableServerTest, AddRemove) { +TEST_F (VariableServerTest, NoExtraTab) { + if (socket_status != 0) { + FAIL(); + } + + std::string reply; + std::string expected; + + socket << "trick.var_add(\"vsx.vst.c\")\n"; + socket >> reply; + expected = std::string("0\t-1234\n"); + + EXPECT_STREQ(reply.c_str(), expected.c_str()); + + socket >> reply; + + EXPECT_STREQ(reply.c_str(), expected.c_str()); + + socket << "trick.var_add(\"vsx.vst.m\")\n"; + socket >> reply; + expected = std::string("0\t-1234\t1\n"); + + EXPECT_STREQ(reply.c_str(), expected.c_str()); + + socket << "trick.var_remove(\"vsx.vst.m\")\n"; + socket >> reply; + expected = std::string("0\t-1234\n"); + + socket << "trick.var_add(\"vsx.vst.n\")\n"; + socket >> reply; + expected = std::string("0\t-1234\t0,1,2,3,4\n"); + + EXPECT_STREQ(reply.c_str(), expected.c_str()); +} + +TEST_F (VariableServerTest, DISABLED_AddRemove) { if (socket_status != 0) { FAIL(); } @@ -742,6 +811,10 @@ TEST_F (VariableServerTest, AddRemove) { socket << "trick.var_remove(\"vsx.vst.m\")\n"; socket >> reply; expected = std::string("0 -1234"); + + socket << "trick.var_add(\"vsx.vst.n\")\n"; + socket >> reply; + expected = std::string("0 -1234 0,1,2,3,4"); EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0); @@ -1190,7 +1263,18 @@ TEST_F (VariableServerTest, Freeze) { ASSERT_EQ(mode, MODE_RUN); } +<<<<<<< HEAD +<<<<<<< HEAD +======= + +<<<<<<< HEAD +>>>>>>> 6fe76071 (Add multicast test) +TEST_F (VariableServerTest, DISABLED_CopyAndWriteModes) { +======= +======= +>>>>>>> d158199e (Added var_send_list_size test, various other fixes) TEST_F (VariableServerTest, CopyAndWriteModes) { +>>>>>>> f9665aba (Fix and test var_send_stdio) if (socket_status != 0) { FAIL(); } @@ -1388,6 +1472,38 @@ TEST_F (VariableServerTest, send_stdio) { std::stringstream message_stream(message); std::string token; +<<<<<<< HEAD +======= + std::getline(message_stream, token, ' '); + int message_type = stoi(token); + std::getline(message_stream, token, ' '); + int stream_num = stoi(token); + std::getline(message_stream, token, '\n'); + int text_size = stoi(token); + std::string text; + std::getline(message_stream, text); + + EXPECT_EQ (message_type, 4); + EXPECT_EQ (stream_num, 1); + EXPECT_EQ (text_size, 41); + + EXPECT_EQ(text, std::string("This message should redirect to varserver")); +} + +TEST_F (VariableServerTest, RestartAndSet) { + if (socket_status != 0) { + FAIL(); + } + + std::string reply; + std::string expected; + + socket << "trick.var_add(\"vsx.vst.c\")\n"; + socket >> reply; + expected = std::string("0\t-1234\n"); + + EXPECT_EQ(reply, expected); +>>>>>>> f9665aba (Fix and test var_send_stdio) int message_type; int stream_num; @@ -1414,6 +1530,12 @@ TEST_F (VariableServerTest, send_stdio) { #ifndef __APPLE__ +<<<<<<< HEAD +<<<<<<< HEAD +TEST_F (VariableServerTest, MulticastAfterRestart) { +======= +======= + TEST_F (VariableServerTest, MulticastAfterRestart) { if (socket_status != 0) { FAIL(); @@ -1422,9 +1544,7 @@ TEST_F (VariableServerTest, MulticastAfterRestart) { socket << "trick.var_server_set_user_tag(\"VSTestServer\")\n"; Socket multicast_socket; - if (multicast_socket.init_multicast("224.3.14.15", 9265) != 0) { - FAIL() << "Multicast Socket failed to initialize."; - } + multicast_socket.init_multicast("224.3.14.15", 9265); int max_multicast_tries = 100; int tries = 0; @@ -1432,7 +1552,7 @@ TEST_F (VariableServerTest, MulticastAfterRestart) { char expected_hostname[80]; gethostname(expected_hostname, 80); - int expected_port = 40000; + int expected_port = 4000; // get expected username struct passwd *passp = getpwuid(getuid()) ; @@ -1488,8 +1608,154 @@ TEST_F (VariableServerTest, MulticastAfterRestart) { FAIL() << "Multicast message never received"; } +>>>>>>> 6490e49d (Add more tests, error handling) +TEST_F (VariableServerTest, LargeMessages) { +>>>>>>> f9665aba (Fix and test var_send_stdio) + if (socket_status != 0) { + FAIL(); + } + + socket << "trick.var_server_set_user_tag(\"VSTestServer\")\n"; + +<<<<<<< HEAD + Socket multicast_socket; + if (multicast_socket.init_multicast("224.3.14.15", 9265) != 0) { + FAIL() << "Multicast Socket failed to initialize."; + } + + int max_multicast_tries = 100; + int tries = 0; + bool found = false; + + char expected_hostname[80]; + gethostname(expected_hostname, 80); + int expected_port = 40000; + + // get expected username + struct passwd *passp = getpwuid(getuid()) ; + char * expected_username; + if ( passp == NULL ) { + expected_username = strdup("unknown") ; + } else { + expected_username = strdup(passp->pw_name) ; + } + + // Don't care about PID, just check that it's > 0 + char * expected_sim_dir = "trick/test/SIM_test_varserv"; // Compare against the end of the string for this one + // Don't care about cmdline name + char * expected_input_file = "RUN_test/unit_test.py"; + // Don't care about trick_version + char * expected_tag = "VSTestServer"; + + // Variables to be populated by the multicast message + char actual_hostname[80]; + unsigned short actual_port = 0; + char actual_username[80]; + int actual_pid = 0; + char actual_sim_dir[80]; + char actual_cmdline_name[80]; + char actual_input_file[80]; + char actual_trick_version[80]; + char actual_tag[80]; + unsigned short actual_duplicate_port = 0; +======= + socket << "trick.var_pause()\n"; + + for (int i = 0; i < 4000; i++) { + std::string var_add = "trick.var_add(\"vsx.vst.large_arr[" + std::to_string(i) + "]\")\n"; + socket << var_add; + } + + // Message size limit is 8192 + // Message size should be somewhere between the limit and limit-5 due to size of variable + const static int msg_size_limit = 8192; + + auto get_last_number_in_string = [](const std::string& s) -> int { + int index = s.size() - 1; + while (!isdigit(s.at(index))) { index--; } + int num = 0; + int exp = 0; + while (isdigit(s.at(index))) { + num += (s.at(index) - '0') * pow(10, exp); + index--; + exp++; + } + return num; + }; + + auto get_first_number_in_string = [](const std::string& s) -> int { + std::stringstream message_stream(s); + std::string token; + std::getline(message_stream, token, '\t'); + if (token.size() == 0) { std::getline(message_stream, token, '\t'); } + int ret = stoi(token); + return ret; + }; + + socket.clear_buffered_data(); + + bool ready = false; + while (!ready) { + socket << "trick.var_send_list_size()\n"; + socket >> reply; + if (reply == std::string("3\t4000\n")) + ready = true; + } + + int new_reply_first = 0; + int prev_reply_last = 0; + + socket << "trick.var_send()\n"; + + socket >> reply; + new_reply_first = get_first_number_in_string(reply); + prev_reply_last = get_last_number_in_string(reply); + EXPECT_EQ(new_reply_first, 0); + EXPECT_TRUE(reply.size() <= msg_size_limit && reply.size() >= msg_size_limit-5); + + while (prev_reply_last != 3999) { + socket >> reply; + new_reply_first = get_first_number_in_string(reply); + + EXPECT_TRUE(reply.size() <= msg_size_limit); + EXPECT_EQ(prev_reply_last + 1, new_reply_first); +>>>>>>> d158199e (Added var_send_list_size test, various other fixes) + +<<<<<<< HEAD + while (!found && tries++ < max_multicast_tries) { + std::string broadcast_data = multicast_socket.receive(); + sscanf(broadcast_data.c_str(), "%s\t%hu\t%s\t%d\t%s\t%s\t%s\t%s\t%s\t%hu\n" , actual_hostname, &actual_port , + actual_username , &actual_pid , actual_sim_dir , actual_cmdline_name , + actual_input_file , actual_trick_version , actual_tag, &actual_duplicate_port) ; + + if (strcmp(actual_hostname, expected_hostname) == 0 && strcmp(expected_tag, actual_tag) == 0) { + found = true; + EXPECT_STREQ(actual_hostname, expected_hostname); + EXPECT_EQ(actual_port, expected_port); + EXPECT_STREQ(actual_username, expected_username); + EXPECT_GT(actual_pid, 0); + std::string expected_sim_dir_str(expected_sim_dir); + std::string actual_sim_dir_str(actual_sim_dir); + std::string end_of_actual = actual_sim_dir_str.substr(actual_sim_dir_str.length() - expected_sim_dir_str.length(), actual_sim_dir_str.length()); + EXPECT_EQ(expected_sim_dir_str, end_of_actual); + EXPECT_STREQ(actual_input_file, expected_input_file); + EXPECT_STREQ(actual_tag, expected_tag); + EXPECT_EQ(actual_duplicate_port, expected_port); + } +======= + prev_reply_last = get_last_number_in_string(reply); +>>>>>>> 6490e49d (Add more tests, error handling) + } + + if (!found) + FAIL() << "Multicast message never received"; +} + +<<<<<<< HEAD #endif +======= +>>>>>>> f9665aba (Fix and test var_send_stdio) TEST_F (VariableServerTest, Binary) { if (socket_status != 0) { FAIL(); @@ -1652,7 +1918,7 @@ int main(int argc, char **argv) { int result = RUN_ALL_TESTS(); Socket socket; - socket.init("localhost", 40000); + socket.init("localhost", 4000); if (result == 0) { // Success diff --git a/trick_sims/SIM_billiards/Modified_data/realtime.py b/trick_sims/SIM_billiards/Modified_data/realtime.py index 172b2f1b..a13797be 100644 --- a/trick_sims/SIM_billiards/Modified_data/realtime.py +++ b/trick_sims/SIM_billiards/Modified_data/realtime.py @@ -6,5 +6,10 @@ trick.itimer_enable() trick.exec_set_enable_freeze(True) # trick.exec_set_freeze_command(True) +# Print stack trace if signal is caught. default True +trick.exec_set_stack_trace(False) +# Attach a debugger to the process if a signal is caught. default False +trick.exec_set_attach_debugger(False) + simControlPanel = trick.SimControlPanel() trick.add_external_application(simControlPanel) diff --git a/trick_sims/SIM_billiards/RUN_break/input.py b/trick_sims/SIM_billiards/RUN_break/input.py index e6e05b7c..5b1a81d9 100644 --- a/trick_sims/SIM_billiards/RUN_break/input.py +++ b/trick_sims/SIM_billiards/RUN_break/input.py @@ -146,17 +146,3 @@ else : print('===================================') print('PoolTableDisplay needs to be built.') print('===================================') - - -# PoolTableDisplay_path = "models/graphics/java/dist/PoolTableDisplay.jar" - -# if (os.path.isfile(PoolTableDisplay_path)) : -# PoolTableDisplay_cmd = "java -jar " \ -# + PoolTableDisplay_path \ -# + " " + str(varServerPort) + " &" ; -# print(PoolTableDisplay_cmd) -# os.system( PoolTableDisplay_cmd); -# else : -# print('=================================================================================================') -# print('PoolTableDisplay needs to be built. Please \"cd\" into ../models/graphics/java and type \"make\".') -# print('=================================================================================================') diff --git a/trick_sims/SIM_billiards/models/graphics/cpp/main.cpp b/trick_sims/SIM_billiards/models/graphics/cpp/main.cpp index f0e98769..21290ce9 100644 --- a/trick_sims/SIM_billiards/models/graphics/cpp/main.cpp +++ b/trick_sims/SIM_billiards/models/graphics/cpp/main.cpp @@ -492,7 +492,7 @@ std::vector split (std::string& str, const char delim) { std::stringstream ss(str); std::string s; std::vector ret; - while (std::getline(ss, s, delim)) { + while (ss >> s) { ret.push_back(s); } return ret; @@ -526,9 +526,11 @@ template T getVar(Socket& socket, std::string varName) { std::string requestString = "trick.var_send_once(\"" + varName + "\")\n"; std::string reply; + // std::cout << "Request: " << requestString << std::endl; socket << requestString; socket >> reply; + // std::cout << "Reply: " << reply << std::endl; return stringConvert(split(reply, '\t')[1]); } @@ -554,10 +556,13 @@ std::vector getVarList(Socket& socket, std::string varName, int num) { } std::string requestString = "trick.var_send_once(\"" + totalRequest + "\", " + std::to_string(num) + ")\n"; + // std::cout << "Request: " << requestString << std::endl; std::string reply; socket << requestString; socket >> reply; + + // std::cout << "Reply: " << reply << std::endl; return trickResponseConvert(reply); } @@ -604,6 +609,13 @@ int main(int argc, char *argv[]) std::vector tablePoints = fold(table_x, table_y); Table table; + // std::cout << "TablePoints: "; + + for (auto point : tablePoints ) { + // std::cout << point << " "; + } + // std::cout << "\ttableShape: " << tableShape << std::endl; + table.addShape(tablePoints, Eigen::Vector3d(0.2, 0.6, 0.2), true, tableShape, layer_TABLE); // Make the rail - translate each point on the table out from center by railWidth @@ -697,7 +709,7 @@ int main(int argc, char *argv[]) std::string cueRequest = ""; std::string templateString = "dyn.table.applyCueForce(%.3f, %.3f) \n"; - char buf[128]; + char buf[2048]; snprintf(buf, sizeof(buf), templateString.c_str(), mouseX, mouseY); cueRequest += std::string(buf); socket << cueRequest; @@ -716,7 +728,10 @@ int main(int argc, char *argv[]) view->callback_pre_draw = [&](igl::opengl::glfw::Viewer& viewer) -> bool { // Look for new data and redraw + // std::cout << "Waiting vars" << std::endl; socket >> reply; + // std::cout << "Got vars: " << reply << std::endl; + std::vector replyData = trickResponseConvert(reply); if (replyData.size() <= 1) { @@ -804,7 +819,7 @@ int main(int argc, char *argv[]) std::string positionRequest = ""; char * templateString = "trick.var_add(\"dyn.table.balls[%d][0].pos._x\")\ntrick.var_add(\"dyn.table.balls[%d][0].pos._y\")\ntrick.var_add(\"dyn.table.balls[%d][0].inPlay\")\n"; for (int i = 0; i < numBalls; i++) { - char buf[128]; + char buf[2048]; snprintf(buf, sizeof(buf), templateString, i, i, i); positionRequest += std::string(buf); } diff --git a/trick_source/java/src/main/java/trick/simcontrol/SimControlApplication.java b/trick_source/java/src/main/java/trick/simcontrol/SimControlApplication.java index 1bd6cfec..ac436568 100644 --- a/trick_source/java/src/main/java/trick/simcontrol/SimControlApplication.java +++ b/trick_source/java/src/main/java/trick/simcontrol/SimControlApplication.java @@ -1572,6 +1572,7 @@ public class SimControlApplication extends TrickApplication implements PropertyC @Override protected void finished() { try { + System.out.println("Finished with health status socket channel"); if (healthStatusSocketChannel != null) { healthStatusSocketChannel.close() ; } @@ -1606,7 +1607,11 @@ public class SimControlApplication extends TrickApplication implements PropertyC if (statusSimcom != null) { - results = statusSimcom.get().split("\t"); + String resultsStr = statusSimcom.get(); + if (resultsStr == null) + break; + + results = resultsStr.split("\t"); ii = 1 ; // whenever there is data in statusSimcom socket, do something diff --git a/trick_source/java/src/main/java/trick/simcontrol/utils/SimControlActionController.java b/trick_source/java/src/main/java/trick/simcontrol/utils/SimControlActionController.java index 3b8086e8..0e2adc7c 100644 --- a/trick_source/java/src/main/java/trick/simcontrol/utils/SimControlActionController.java +++ b/trick_source/java/src/main/java/trick/simcontrol/utils/SimControlActionController.java @@ -295,7 +295,7 @@ public class SimControlActionController { simcom.put("trick.debug_pause_off()\n" ) ; } } catch (IOException e) { - System.out.println("Put failed!"); + System.out.println("Put failed! Exception: " + e.getMessage()); } } diff --git a/trick_source/sim_services/CMakeLists.txt b/trick_source/sim_services/CMakeLists.txt index 9f92fa95..42a6e895 100644 --- a/trick_source/sim_services/CMakeLists.txt +++ b/trick_source/sim_services/CMakeLists.txt @@ -215,7 +215,6 @@ set( SS_SRC VariableServer/VariableServer_shutdown VariableServer/exit_var_thread VariableServer/var_server_ext - VariableServer/vs_format_ascii Zeroconf/Zeroconf mains/master ) diff --git a/trick_source/sim_services/InputProcessor/Makefile_deps b/trick_source/sim_services/InputProcessor/Makefile_deps index e72afe5c..b8703ada 100644 --- a/trick_source/sim_services/InputProcessor/Makefile_deps +++ b/trick_source/sim_services/InputProcessor/Makefile_deps @@ -135,6 +135,6 @@ object_${TRICK_HOST_CPU}/MTV.o: MTV.cpp ${TRICK_HOME}/include/trick/MTV.hh \ ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/EventManager_c_intf.hh diff --git a/trick_source/sim_services/MonteCarlo/test/Makefile b/trick_source/sim_services/MonteCarlo/test/Makefile index c0f892b6..81df6675 100644 --- a/trick_source/sim_services/MonteCarlo/test/Makefile +++ b/trick_source/sim_services/MonteCarlo/test/Makefile @@ -9,7 +9,7 @@ include $(dir $(lastword $(MAKEFILE_LIST)))../../../../share/trick/makefiles/Mak # Flags passed to the preprocessor. TRICK_CXXFLAGS += -I$(GTEST_HOME)/include -I$(TRICK_HOME)/include -g -Wall -Wextra ${TRICK_TEST_FLAGS} -TRICK_LIBS = -L${TRICK_LIB_DIR} -ltrick -ltrick_pyip -ltrick_comm -ltrick_math -ltrick_mm -ltrick_units +TRICK_LIBS = -L${TRICK_LIB_DIR} -ltrick -ltrick_pyip -ltrick_comm -ltrick_math -ltrick_mm -ltrick_units -ltrick_var_binary_parser -ltrick_connection_handlers -ltrick_comm TRICK_EXEC_LINK_LIBS += -L${GTEST_HOME}/lib64 -L${GTEST_HOME}/lib -lgtest -lgtest_main # All tests produced by this Makefile. Remember to add new tests you diff --git a/trick_source/sim_services/VariableServer/Makefile_deps b/trick_source/sim_services/VariableServer/Makefile_deps index aac0a008..a95824db 100644 --- a/trick_source/sim_services/VariableServer/Makefile_deps +++ b/trick_source/sim_services/VariableServer/Makefile_deps @@ -12,7 +12,8 @@ object_${TRICK_HOST_CPU}/VariableServerThread_loop.o: VariableServerThread_loop. ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/input_processor_proto.h \ ${TRICK_HOME}/include/trick/tc_proto.h \ @@ -39,7 +40,8 @@ object_${TRICK_HOST_CPU}/VariableServer_copy_data_scheduled.o: \ ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/TrickConstant.hh object_${TRICK_HOST_CPU}/VariableServer_shutdown.o: VariableServer_shutdown.cpp \ @@ -56,7 +58,8 @@ object_${TRICK_HOST_CPU}/VariableServer_shutdown.o: VariableServer_shutdown.cpp ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh object_${TRICK_HOST_CPU}/VariableServer_copy_data_freeze_scheduled.o: \ VariableServer_copy_data_freeze_scheduled.cpp \ @@ -73,10 +76,11 @@ object_${TRICK_HOST_CPU}/VariableServer_copy_data_freeze_scheduled.o: \ ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/TrickConstant.hh -object_${TRICK_HOST_CPU}/VariableReference.o: VariableReference.cpp \ +object_${TRICK_HOST_CPU}/VariableReference.o: \ ${TRICK_HOME}/include/trick/VariableServer.hh \ ${TRICK_HOME}/include/trick/tc.h \ ${TRICK_HOME}/include/trick/trick_error_hndlr.h \ @@ -90,7 +94,8 @@ object_${TRICK_HOST_CPU}/VariableReference.o: VariableReference.cpp \ ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/memorymanager_c_intf.h \ ${TRICK_HOME}/include/trick/var.h \ @@ -113,7 +118,8 @@ object_${TRICK_HOST_CPU}/VariableServer_get_next_freeze_call_time.o: \ ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/TrickConstant.hh object_${TRICK_HOST_CPU}/VariableServerThread_write_stdio.o: VariableServerThread_write_stdio.cpp \ @@ -130,7 +136,8 @@ object_${TRICK_HOST_CPU}/VariableServerThread_write_stdio.o: VariableServerThrea ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/variable_server_message_types.h \ ${TRICK_HOME}/include/trick/tc_proto.h @@ -149,7 +156,8 @@ object_${TRICK_HOST_CPU}/VariableServer_get_next_sync_call_time.o: \ ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/TrickConstant.hh object_${TRICK_HOST_CPU}/VariableServer_restart.o: VariableServer_restart.cpp \ @@ -166,7 +174,8 @@ object_${TRICK_HOST_CPU}/VariableServer_restart.o: VariableServer_restart.cpp \ ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/message_proto.h \ ${TRICK_HOME}/include/trick/message_type.h \ @@ -185,7 +194,8 @@ object_${TRICK_HOST_CPU}/var_server_ext.o: var_server_ext.cpp \ ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/exec_proto.h \ ${TRICK_HOME}/include/trick/sim_mode.h \ @@ -200,7 +210,8 @@ object_${TRICK_HOST_CPU}/VariableServerThread_create_socket.o: \ ${TRICK_HOME}/include/trick/tc.h \ ${TRICK_HOME}/include/trick/trick_error_hndlr.h \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/reference.h \ ${TRICK_HOME}/include/trick/attributes.h \ ${TRICK_HOME}/include/trick/parameter_types.h \ @@ -216,7 +227,8 @@ object_${TRICK_HOST_CPU}/VariableServerListenThread.o: VariableServerListenThrea ${TRICK_HOME}/include/trick/trick_error_hndlr.h \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/reference.h \ ${TRICK_HOME}/include/trick/attributes.h \ ${TRICK_HOME}/include/trick/parameter_types.h \ @@ -243,7 +255,8 @@ object_${TRICK_HOST_CPU}/VariableServerThread_write_data.o: VariableServerThread ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/variable_server_message_types.h \ ${TRICK_HOME}/include/trick/bitfield_proto.h \ @@ -265,7 +278,8 @@ object_${TRICK_HOST_CPU}/VariableServer_init.o: VariableServer_init.cpp \ ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/exec_proto.hh \ ${TRICK_HOME}/include/trick/Executive.hh \ @@ -291,7 +305,8 @@ object_${TRICK_HOST_CPU}/VariableServer_copy_data_freeze.o: VariableServer_copy_ ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh object_${TRICK_HOST_CPU}/VariableServer_default_data.o: VariableServer_default_data.cpp \ ${TRICK_HOME}/include/trick/VariableServer.hh \ @@ -307,7 +322,8 @@ object_${TRICK_HOST_CPU}/VariableServer_default_data.o: VariableServer_default_d ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh object_${TRICK_HOST_CPU}/VariableServer_freeze_init.o: VariableServer_freeze_init.cpp \ ${TRICK_HOME}/include/trick/VariableServer.hh \ @@ -323,7 +339,8 @@ object_${TRICK_HOST_CPU}/VariableServer_freeze_init.o: VariableServer_freeze_ini ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/variable_server_proto.h \ ${TRICK_HOME}/include/trick/TrickConstant.hh @@ -341,34 +358,17 @@ object_${TRICK_HOST_CPU}/VariableServer.o: VariableServer.cpp \ ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/tc_proto.h -object_${TRICK_HOST_CPU}/vs_format_ascii.o: vs_format_ascii.cpp \ - ${TRICK_HOME}/include/trick/parameter_types.h \ - ${TRICK_HOME}/include/trick/attributes.h \ - ${TRICK_HOME}/include/trick/bitfield_proto.h \ - ${TRICK_HOME}/include/trick/wcs_ext.h \ - ${TRICK_HOME}/include/trick/VariableServer.hh \ - ${TRICK_HOME}/include/trick/tc.h \ - ${TRICK_HOME}/include/trick/trick_error_hndlr.h \ - ${TRICK_HOME}/include/trick/reference.h \ - ${TRICK_HOME}/include/trick/value.h \ - ${TRICK_HOME}/include/trick/dllist.h \ - ${TRICK_HOME}/include/trick/JobData.hh \ - ${TRICK_HOME}/include/trick/InstrumentBase.hh \ - ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ - ${TRICK_HOME}/include/trick/VariableServerThread.hh \ - ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ - ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ - ${TRICK_HOME}/include/trick/TrickConstant.hh object_${TRICK_HOST_CPU}/VariableServerThread_restart.o: VariableServerThread_restart.cpp \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/tc.h \ ${TRICK_HOME}/include/trick/trick_error_hndlr.h \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/reference.h \ ${TRICK_HOME}/include/trick/attributes.h \ ${TRICK_HOME}/include/trick/parameter_types.h \ @@ -389,7 +389,8 @@ object_${TRICK_HOST_CPU}/VariableServer_copy_data_top.o: VariableServer_copy_dat ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh object_${TRICK_HOST_CPU}/exit_var_thread.o: exit_var_thread.cpp \ ${TRICK_HOME}/include/trick/VariableServer.hh \ @@ -405,7 +406,8 @@ object_${TRICK_HOST_CPU}/exit_var_thread.o: exit_var_thread.cpp \ ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/tc_proto.h object_${TRICK_HOST_CPU}/VariableServerThread_copy_data.o: VariableServerThread_copy_data.cpp \ @@ -422,7 +424,8 @@ object_${TRICK_HOST_CPU}/VariableServerThread_copy_data.o: VariableServerThread_ ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/exec_proto.h \ ${TRICK_HOME}/include/trick/sim_mode.h \ @@ -443,7 +446,8 @@ object_${TRICK_HOST_CPU}/VariableServerThread_connect.o: VariableServerThread_co ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/release.h object_${TRICK_HOST_CPU}/VariableServerThread_copy_sim_data.o: \ @@ -461,19 +465,21 @@ object_${TRICK_HOST_CPU}/VariableServerThread_copy_sim_data.o: \ ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/memorymanager_c_intf.h \ ${TRICK_HOME}/include/trick/var.h \ ${TRICK_HOME}/include/trick/io_alloc.h \ ${TRICK_HOME}/include/trick/exec_proto.h \ ${TRICK_HOME}/include/trick/sim_mode.h -object_${TRICK_HOST_CPU}/VariableServerThread_freeze_init.o: VariableServerThread_freeze_init.cpp \ - ${TRICK_HOME}/include/trick/VariableServerThread.hh \ +object_${TRICK_HOST_CPU}/VariableServerSession_freeze_init.o: VariableServerSession_freeze_init.cpp \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/tc.h \ ${TRICK_HOME}/include/trick/trick_error_hndlr.h \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/reference.h \ ${TRICK_HOME}/include/trick/attributes.h \ ${TRICK_HOME}/include/trick/parameter_types.h \ @@ -496,14 +502,16 @@ object_${TRICK_HOST_CPU}/VariableServer_get_var_server_port.o: \ ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh object_${TRICK_HOST_CPU}/VariableServerThread.o: VariableServerThread.cpp \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/tc.h \ ${TRICK_HOME}/include/trick/trick_error_hndlr.h \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/reference.h \ ${TRICK_HOME}/include/trick/attributes.h \ ${TRICK_HOME}/include/trick/parameter_types.h \ @@ -527,7 +535,8 @@ object_${TRICK_HOST_CPU}/VariableServerThread_loop.o: VariableServerThread_loop. ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/input_processor_proto.h \ ${TRICK_HOME}/include/trick/tc_proto.h \ @@ -554,7 +563,8 @@ object_${TRICK_HOST_CPU}/VariableServer_copy_data_scheduled.o: \ ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/TrickConstant.hh object_${TRICK_HOST_CPU}/VariableServer_shutdown.o: VariableServer_shutdown.cpp \ @@ -571,7 +581,8 @@ object_${TRICK_HOST_CPU}/VariableServer_shutdown.o: VariableServer_shutdown.cpp ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh object_${TRICK_HOST_CPU}/VariableServer_copy_data_freeze_scheduled.o: \ VariableServer_copy_data_freeze_scheduled.cpp \ @@ -588,10 +599,13 @@ object_${TRICK_HOST_CPU}/VariableServer_copy_data_freeze_scheduled.o: \ ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/TrickConstant.hh -object_${TRICK_HOST_CPU}/VariableReference.o: VariableReference.cpp \ +object_${TRICK_HOST_CPU}/VariableReference.o: \ +VariableReference.cpp \ +${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServer.hh \ ${TRICK_HOME}/include/trick/tc.h \ ${TRICK_HOME}/include/trick/trick_error_hndlr.h \ @@ -605,7 +619,8 @@ object_${TRICK_HOST_CPU}/VariableReference.o: VariableReference.cpp \ ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/memorymanager_c_intf.h \ ${TRICK_HOME}/include/trick/var.h \ @@ -627,7 +642,8 @@ object_${TRICK_HOST_CPU}/VariableServerThread_write_stdio.o: VariableServerThrea ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/variable_server_message_types.h \ ${TRICK_HOME}/include/trick/tc_proto.h @@ -645,7 +661,8 @@ object_${TRICK_HOST_CPU}/VariableServerThread_commands.o: VariableServerThread_c ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/variable_server_message_types.h \ ${TRICK_HOME}/include/trick/memorymanager_c_intf.h \ @@ -676,7 +693,8 @@ object_${TRICK_HOST_CPU}/VariableServer_get_next_sync_call_time.o: \ ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/TrickConstant.hh object_${TRICK_HOST_CPU}/VariableServer_restart.o: VariableServer_restart.cpp \ @@ -693,7 +711,8 @@ object_${TRICK_HOST_CPU}/VariableServer_restart.o: VariableServer_restart.cpp \ ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/message_proto.h \ ${TRICK_HOME}/include/trick/message_type.h \ @@ -712,7 +731,8 @@ object_${TRICK_HOST_CPU}/var_server_ext.o: var_server_ext.cpp \ ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/exec_proto.h \ ${TRICK_HOME}/include/trick/sim_mode.h \ @@ -727,7 +747,8 @@ object_${TRICK_HOST_CPU}/VariableServerThread_create_socket.o: \ ${TRICK_HOME}/include/trick/tc.h \ ${TRICK_HOME}/include/trick/trick_error_hndlr.h \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/reference.h \ ${TRICK_HOME}/include/trick/attributes.h \ ${TRICK_HOME}/include/trick/parameter_types.h \ @@ -741,9 +762,12 @@ object_${TRICK_HOST_CPU}/VariableServerListenThread.o: VariableServerListenThrea ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/tc.h \ ${TRICK_HOME}/include/trick/trick_error_hndlr.h \ + ${TRICK_HOME}/include/trick/ClientListener.hh \ + ${TRICK_HOME}/include/trick/MulticastManager.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/reference.h \ ${TRICK_HOME}/include/trick/attributes.h \ ${TRICK_HOME}/include/trick/parameter_types.h \ @@ -770,7 +794,8 @@ object_${TRICK_HOST_CPU}/VariableServerThread_write_data.o: VariableServerThread ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/variable_server_message_types.h \ ${TRICK_HOME}/include/trick/bitfield_proto.h \ @@ -792,7 +817,8 @@ object_${TRICK_HOST_CPU}/VariableServer_init.o: VariableServer_init.cpp \ ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/exec_proto.hh \ ${TRICK_HOME}/include/trick/Executive.hh \ @@ -818,7 +844,8 @@ object_${TRICK_HOST_CPU}/VariableServer_copy_data_freeze.o: VariableServer_copy_ ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh object_${TRICK_HOST_CPU}/VariableServer_default_data.o: VariableServer_default_data.cpp \ ${TRICK_HOME}/include/trick/VariableServer.hh \ @@ -834,7 +861,8 @@ object_${TRICK_HOST_CPU}/VariableServer_default_data.o: VariableServer_default_d ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh object_${TRICK_HOST_CPU}/VariableServer_freeze_init.o: VariableServer_freeze_init.cpp \ ${TRICK_HOME}/include/trick/VariableServer.hh \ @@ -850,7 +878,8 @@ object_${TRICK_HOST_CPU}/VariableServer_freeze_init.o: VariableServer_freeze_ini ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/variable_server_proto.h \ ${TRICK_HOME}/include/trick/TrickConstant.hh @@ -868,34 +897,17 @@ object_${TRICK_HOST_CPU}/VariableServer.o: VariableServer.cpp \ ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/tc_proto.h -object_${TRICK_HOST_CPU}/vs_format_ascii.o: vs_format_ascii.cpp \ - ${TRICK_HOME}/include/trick/parameter_types.h \ - ${TRICK_HOME}/include/trick/attributes.h \ - ${TRICK_HOME}/include/trick/bitfield_proto.h \ - ${TRICK_HOME}/include/trick/wcs_ext.h \ - ${TRICK_HOME}/include/trick/VariableServer.hh \ - ${TRICK_HOME}/include/trick/tc.h \ - ${TRICK_HOME}/include/trick/trick_error_hndlr.h \ - ${TRICK_HOME}/include/trick/reference.h \ - ${TRICK_HOME}/include/trick/value.h \ - ${TRICK_HOME}/include/trick/dllist.h \ - ${TRICK_HOME}/include/trick/JobData.hh \ - ${TRICK_HOME}/include/trick/InstrumentBase.hh \ - ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ - ${TRICK_HOME}/include/trick/VariableServerThread.hh \ - ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ - ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ - ${TRICK_HOME}/include/trick/TrickConstant.hh object_${TRICK_HOST_CPU}/VariableServerThread_restart.o: VariableServerThread_restart.cpp \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/tc.h \ ${TRICK_HOME}/include/trick/trick_error_hndlr.h \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/reference.h \ ${TRICK_HOME}/include/trick/attributes.h \ ${TRICK_HOME}/include/trick/parameter_types.h \ @@ -916,7 +928,8 @@ object_${TRICK_HOST_CPU}/VariableServer_copy_data_top.o: VariableServer_copy_dat ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh object_${TRICK_HOST_CPU}/exit_var_thread.o: exit_var_thread.cpp \ ${TRICK_HOME}/include/trick/VariableServer.hh \ @@ -932,7 +945,8 @@ object_${TRICK_HOST_CPU}/exit_var_thread.o: exit_var_thread.cpp \ ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/tc_proto.h object_${TRICK_HOST_CPU}/VariableServerThread_copy_data.o: VariableServerThread_copy_data.cpp \ @@ -949,7 +963,8 @@ object_${TRICK_HOST_CPU}/VariableServerThread_copy_data.o: VariableServerThread_ ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/exec_proto.h \ ${TRICK_HOME}/include/trick/sim_mode.h \ @@ -971,7 +986,8 @@ object_${TRICK_HOST_CPU}/VariableServer_get_next_freeze_call_time.o: \ ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/TrickConstant.hh object_${TRICK_HOST_CPU}/VariableServerThread_connect.o: VariableServerThread_connect.cpp \ @@ -988,7 +1004,8 @@ object_${TRICK_HOST_CPU}/VariableServerThread_connect.o: VariableServerThread_co ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/release.h object_${TRICK_HOST_CPU}/VariableServerThread_copy_sim_data.o: \ @@ -1006,7 +1023,8 @@ object_${TRICK_HOST_CPU}/VariableServerThread_copy_sim_data.o: \ ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh \ ${TRICK_HOME}/include/trick/memorymanager_c_intf.h \ ${TRICK_HOME}/include/trick/var.h \ @@ -1018,7 +1036,8 @@ object_${TRICK_HOST_CPU}/VariableServerThread_freeze_init.o: VariableServerThrea ${TRICK_HOME}/include/trick/tc.h \ ${TRICK_HOME}/include/trick/trick_error_hndlr.h \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/reference.h \ ${TRICK_HOME}/include/trick/attributes.h \ ${TRICK_HOME}/include/trick/parameter_types.h \ @@ -1041,14 +1060,16 @@ object_${TRICK_HOST_CPU}/VariableServer_get_var_server_port.o: \ ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/VariableServerListenThread.hh object_${TRICK_HOST_CPU}/VariableServerThread.o: VariableServerThread.cpp \ ${TRICK_HOME}/include/trick/VariableServerThread.hh \ ${TRICK_HOME}/include/trick/tc.h \ ${TRICK_HOME}/include/trick/trick_error_hndlr.h \ ${TRICK_HOME}/include/trick/ThreadBase.hh \ - ${TRICK_HOME}/include/trick/VariableServerReference.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ ${TRICK_HOME}/include/trick/reference.h \ ${TRICK_HOME}/include/trick/attributes.h \ ${TRICK_HOME}/include/trick/parameter_types.h \ @@ -1058,3 +1079,51 @@ object_${TRICK_HOST_CPU}/VariableServerThread.o: VariableServerThread.cpp \ ${TRICK_HOME}/include/trick/exec_proto.h \ ${TRICK_HOME}/include/trick/sim_mode.h \ ${TRICK_HOME}/include/trick/TrickConstant.hh +object_${TRICK_HOST_CPU}/VariableServerSession.o: VariableServerSession.cpp \ + ${TRICK_HOME}/include/trick/VariableServerThread.hh \ + ${TRICK_HOME}/include/trick/tc.h \ + ${TRICK_HOME}/include/trick/trick_error_hndlr.h \ + ${TRICK_HOME}/include/trick/ThreadBase.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ + ${TRICK_HOME}/include/trick/reference.h \ + ${TRICK_HOME}/include/trick/attributes.h \ + ${TRICK_HOME}/include/trick/parameter_types.h \ + ${TRICK_HOME}/include/trick/value.h \ + ${TRICK_HOME}/include/trick/dllist.h \ + ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ + ${TRICK_HOME}/include/trick/exec_proto.h \ + ${TRICK_HOME}/include/trick/sim_mode.h \ + ${TRICK_HOME}/include/trick/TrickConstant.hh + object_${TRICK_HOST_CPU}/TCConnection.o: TCConnection.cpp \ + ${TRICK_HOME}/include/trick/TCConnection.hh \ + ${TRICK_HOME}/include/trick/ClientConnection.hh \ + ${TRICK_HOME}/include/trick/ClientListener.hh \ + ${TRICK_HOME}/include/trick/VariableServerThread.hh \ + ${TRICK_HOME}/include/trick/tc.h \ + ${TRICK_HOME}/include/trick/trick_error_hndlr.h \ + ${TRICK_HOME}/include/trick/ThreadBase.hh \ + ${TRICK_HOME}/include/trick/VariableReference.hh \ + ${TRICK_HOME}/include/trick/VariableServerSession.hh \ + ${TRICK_HOME}/include/trick/reference.h \ + ${TRICK_HOME}/include/trick/attributes.h \ + ${TRICK_HOME}/include/trick/parameter_types.h \ + ${TRICK_HOME}/include/trick/value.h \ + ${TRICK_HOME}/include/trick/dllist.h \ + ${TRICK_HOME}/include/trick/variable_server_sync_types.h \ + ${TRICK_HOME}/include/trick/exec_proto.h \ + ${TRICK_HOME}/include/trick/sim_mode.h \ + ${TRICK_HOME}/include/trick/TrickConstant.hh \ + ${TRICK_HOME}/include/trick/tc_proto.h +object_${TRICK_HOST_CPU}/ClientListener.o: ClientListener.cpp \ + ${TRICK_HOME}/include/trick/TCConnection.hh \ + ${TRICK_HOME}/include/trick/ClientConnection.hh \ + ${TRICK_HOME}/include/trick/ClientListener.hh \ + ${TRICK_HOME}/include/trick/tc.h \ + ${TRICK_HOME}/include/trick/trick_error_hndlr.h \ + ${TRICK_HOME}/include/trick/tc_proto.h + object_${TRICK_HOST_CPU}/MulticastManager.o: MulticastManager.cpp \ + ${TRICK_HOME}/include/trick/MulticastManager.hh \ + ${TRICK_HOME}/include/trick/tc.h \ + ${TRICK_HOME}/include/trick/trick_error_hndlr.h \ + ${TRICK_HOME}/include/trick/tc_proto.h diff --git a/trick_source/sim_services/VariableServer/VariableReference.cpp b/trick_source/sim_services/VariableServer/VariableReference.cpp index 925adec3..dcaa4925 100644 --- a/trick_source/sim_services/VariableServer/VariableReference.cpp +++ b/trick_source/sim_services/VariableServer/VariableReference.cpp @@ -1,80 +1,736 @@ - #include #include #include -#include "trick/VariableServer.hh" +#include // for fpclassify +#include // for setprecision +#include +#include + +#include "trick/VariableReference.hh" #include "trick/memorymanager_c_intf.h" #include "trick/wcs_ext.h" +#include "trick/map_trick_units_to_udunits.hh" #include "trick/message_proto.h" #include "trick/message_type.h" - -Trick::VariableReference::VariableReference(REF2 * in_ref ) { +#include "trick/UdUnits.hh" +#include "trick/bitfield_proto.h" +#include "trick/trick_byteswap.h" +#include "trick/tc_proto.h" - int k ; +// Static variables to be addresses that are known to be the error ref address +int Trick::VariableReference::bad_ref_int = 0 ; +int Trick::VariableReference::do_not_resolve_bad_ref_int = 0 ; - // VariableReference copy setup: set address & size to copy into buffer - conversion_factor = cv_get_trivial() ; +REF2* Trick::VariableReference::make_error_ref(std::string in_name) { + REF2* new_ref; + new_ref = (REF2*)calloc(1, sizeof(REF2)); + new_ref->reference = strdup(in_name.c_str()) ; + new_ref->units = NULL ; + new_ref->address = (char *)&bad_ref_int ; + new_ref->attr = (ATTRIBUTES*)calloc(1, sizeof(ATTRIBUTES)) ; + new_ref->attr->type = TRICK_NUMBER_OF_TYPES ; + new_ref->attr->units = (char *)"--" ; + new_ref->attr->size = sizeof(int) ; + return new_ref; +} - ref = in_ref ; - address = ref->address ; - size = ref->attr->size ; - // char* and wchar* in Trick 7 have a type of string and wstring, respectively - // but in Trick 10 they are type char and wchar (probably John Penn's fault), - // so we need to keep track that they are really string and wstring - string_type = ref->attr->type ; - need_deref = false ; +REF2* Trick::VariableReference::make_do_not_resolve_ref(std::string in_name) { + REF2* new_ref; + new_ref = (REF2*)calloc(1, sizeof(REF2)); + new_ref->reference = strdup(in_name.c_str()) ; + new_ref->units = NULL ; + new_ref->address = (char *)&do_not_resolve_bad_ref_int ; + new_ref->attr = (ATTRIBUTES*)calloc(1, sizeof(ATTRIBUTES)) ; + new_ref->attr->type = TRICK_NUMBER_OF_TYPES ; + new_ref->attr->units = (char *)"--" ; + new_ref->attr->size = sizeof(int) ; + return new_ref; +} - if ( ref->num_index == ref->attr->num_index ) { - // single value - } else if ( ref->attr->index[ref->attr->num_index - 1].size != 0 ) { - // fixed array - for ( k = ref->attr->num_index-1; k > ref->num_index-1 ; k-- ) { - size *= ref->attr->index[k].size ; +// Helper function to deal with time variable +REF2* make_time_ref(double * time) { + REF2* new_ref; + new_ref = (REF2*)calloc(1, sizeof(REF2)); + new_ref->reference = strdup("time") ; + new_ref->units = strdup("s") ; + new_ref->address = (char *)time ; + new_ref->attr = (ATTRIBUTES*)calloc(1, sizeof(ATTRIBUTES)) ; + new_ref->attr->type = TRICK_DOUBLE ; + new_ref->attr->units = strdup("s") ; + new_ref->attr->size = sizeof(double) ; + return new_ref; +} + +Trick::VariableReference::VariableReference(std::string var_name, double* time) : staged(false), write_ready(false) { + if (var_name != "time") { + ASSERT(0); + } + + var_info = make_time_ref(time); + + // Set up member variables + address = var_info->address; + size = var_info->attr->size ; + deref = false; + + // Deal with weirdness around string vs wstring + trick_type = var_info->attr->type ; + + // Allocate stage and write buffers + stage_buffer = calloc(size, 1) ; + write_buffer = calloc(size, 1) ; + + conversion_factor = cv_get_trivial(); +} + +Trick::VariableReference::VariableReference(std::string var_name) : staged(false), write_ready(false) { + + if (var_name == "time") { + ASSERT(0); + } else { + // get variable attributes from memory manager + var_info = ref_attributes(var_name.c_str()); + } + + // Handle error cases + if ( var_info == NULL ) { + // TODO: ERROR LOGGER sendErrorMessage("Variable Server could not find variable %s.\n", var_name); + // PRINTF IS NOT AN ERROR LOGGER @me + printf("Variable Server could not find variable %s.\n", var_name.c_str()); + var_info = make_error_ref(var_name); + } else if ( var_info->attr ) { + if ( var_info->attr->type == TRICK_STRUCTURED ) { + // sendErrorMessage("Variable Server: var_add cant add \"%s\" because its a composite variable.\n", var_name); + printf("Variable Server: var_add cant add \"%s\" because its a composite variable.\n", var_name.c_str()); + + free(var_info); + var_info = make_do_not_resolve_ref(var_name); + + } else if ( var_info->attr->type == TRICK_STL ) { + // sendErrorMessage("Variable Server: var_add cant add \"%s\" because its an STL variable.\n", var_name); + printf("Variable Server: var_add cant add \"%s\" because its an STL variable.\n", var_name.c_str()); + + free(var_info); + var_info = make_do_not_resolve_ref(var_name); } } else { - // arrays with pointers - if ((ref->attr->num_index - ref->num_index) > 1 ) { - // you cannot request more than one dimension because they are not contiguous - message_publish(MSG_ERROR, "Variable Server Error: var_add(%s) requests more than one dimension of dynamic array.\n", ref->reference); - message_publish(MSG_ERROR, "Data is not contiguous so returned values are unpredictable.\n") ; + // sendErrorMessage("Variable Server: BAD MOJO - Missing ATTRIBUTES."); + printf("Variable Server: BAD MOJO - Missing ATTRIBUTES."); + + free(var_info); + var_info = make_error_ref(var_name); + } + + // Set up member variables + var_info->units = NULL; + address = var_info->address; + size = var_info->attr->size ; + deref = false; + + // Deal with weirdness around string vs wstring + trick_type = var_info->attr->type ; + + if ( var_info->num_index == var_info->attr->num_index ) { + // single value - nothing else necessary + } else if ( var_info->attr->index[var_info->attr->num_index - 1].size != 0 ) { + // Constrained array + for ( int i = var_info->attr->num_index-1; i > var_info->num_index-1 ; i-- ) { + size *= var_info->attr->index[i].size ; } - if ( ref->attr->type == TRICK_CHARACTER ) { - // treat char* like a c++ string (see below) - string_type = TRICK_STRING ; - need_deref = true; - } else if ( ref->attr->type == TRICK_WCHAR ) { - // treat wchar_t* like a wstring (see below) - string_type = TRICK_WSTRING ; + } else { + // Unconstrained array + if ((var_info->attr->num_index - var_info->num_index) > 1 ) { + // TODO: ERROR LOGGER + printf("Variable Server Error: var_add(%s) requests more than one dimension of dynamic array.\n", var_info->reference); + printf("Data is not contiguous so returned values are unpredictable.\n") ; + } + if ( var_info->attr->type == TRICK_CHARACTER ) { + trick_type = TRICK_STRING ; + deref = true; + } else if ( var_info->attr->type == TRICK_WCHAR ) { + trick_type = TRICK_WSTRING ; + deref = true; } else { - need_deref = true ; + deref = true ; size *= get_size((char*)address) ; } } - // handle strings: set a max buffer size, the copy size may vary so will be set in copy_sim_data - if (( string_type == TRICK_STRING ) || ( string_type == TRICK_WSTRING )) { + if (( trick_type == TRICK_STRING ) || ( trick_type == TRICK_WSTRING )) { size = MAX_ARRAY_LENGTH ; } - buffer_in = calloc( size, 1 ) ; - buffer_out = calloc( size, 1 ) ; + // Allocate stage and write buffers + stage_buffer = calloc(size, 1) ; + write_buffer = calloc(size, 1) ; + conversion_factor = cv_get_trivial(); -} - -std::ostream& Trick::operator<< (std::ostream& s, const Trick::VariableReference& vref) { - - if (vref.ref->reference != NULL) { - s << " \"" << vref.ref->reference << "\""; - } else { - s<< " null"; - } - return s; + // Done! } Trick::VariableReference::~VariableReference() { - free(ref) ; - free(buffer_in) ; - free(buffer_out) ; + if (var_info != NULL) { + free( var_info ); + var_info = NULL; + } + if (stage_buffer != NULL) { + free (stage_buffer); + stage_buffer = NULL; + } + if (write_buffer != NULL) { + free (write_buffer); + write_buffer = NULL; + } + if (conversion_factor != NULL) { + cv_free(conversion_factor); + } } + +const char* Trick::VariableReference::getName() const { + return var_info->reference; +} + +int Trick::VariableReference::getSizeBinary() const { + return size; +} + +TRICK_TYPE Trick::VariableReference::getType() const { + return trick_type; +} + +const char* Trick::VariableReference::getBaseUnits() const { + return var_info->attr->units; +} + +int Trick::VariableReference::setRequestedUnits(std::string units_name) { + // Some error logging lambdas - these should probably go somewhere else + // But I do kinda like them + auto publish = [](MESSAGE_TYPE type, const std::string& message) { + std::ostringstream oss; + oss << "Variable Server: " << message << std::endl; + message_publish(type, oss.str().c_str()); + }; + + auto publishError = [&](const std::string& units) { + std::ostringstream oss; + oss << "units error for [" << getName() << "] [" << units << "]"; + publish(MSG_ERROR, oss.str()); + }; + + // If the units_name parameter is "xx", set it to the current units. + if (!units_name.compare("xx")) { + units_name = getBaseUnits(); + } + + // if unitless ('--') then do not convert to udunits + if(units_name.compare("--")) { + // Check to see if this is an old style Trick unit that needs to be converted to new udunits + std::string new_units = map_trick_units_to_udunits(units_name) ; + // Warn if a conversion has taken place + if ( units_name.compare(new_units) ) { + // TODO: MAKE BETTER SYSTEM FOR ERROR LOGGING + std::ostringstream oss; + oss << "[" << getName() << "] old-style units converted from [" + << units_name << "] to [" << new_units << "]"; + publish(MSG_WARNING, oss.str()); + } + + // Interpret base unit + ut_unit * from = ut_parse(Trick::UdUnits::get_u_system(), getBaseUnits(), UT_ASCII) ; + if ( !from ) { + std::cout << "Error in interpreting base units" << std::endl; + publishError(getBaseUnits()); + ut_free(from) ; + return -1 ; + } + + // Interpret requested unit + ut_unit * to = ut_parse(Trick::UdUnits::get_u_system(), new_units.c_str(), UT_ASCII) ; + if ( !to ) { + std::cout << "Error in interpreting requested units" << std::endl; + publishError(new_units); + ut_free(from) ; + ut_free(to) ; + return -1 ; + } + + // Create a converter from the base to the requested + auto new_conversion_factor = ut_get_converter(from, to) ; + ut_free(from) ; + ut_free(to) ; + if ( !new_conversion_factor ) { + std::ostringstream oss; + oss << "[" << getName() << "] cannot convert units from [" << getBaseUnits() + << "] to [" << new_units << "]"; + publish(MSG_ERROR, oss.str()); + return -1 ; + } else { + conversion_factor = new_conversion_factor; + } + + // Don't memory leak the old units! + if (var_info->units != NULL) { + free(var_info->units); + } + + // Set the requested units. This will cause the unit string to be printed in write_value_ascii + var_info->units = strdup(new_units.c_str());; + } + return 0; +} + +int Trick::VariableReference::stageValue(bool validate_address) { + write_ready = false; + + // Copy bytes from
to staging_point. + + // Try to recreate connection if it has been broken + if (var_info->address == &bad_ref_int) { + REF2 *new_ref = ref_attributes(var_info->reference); + if (new_ref != NULL) { + var_info = new_ref; + address = var_info->address; + } + } + + // if there's a pointer somewhere in the address path, follow it in case pointer changed + if ( var_info->pointer_present == 1 ) { + address = follow_address_path(var_info) ; + if (address == NULL) { + tagAsInvalid(); + } else if ( validate_address ) { + validate(); + } else { + var_info->address = address ; + } + } + + // if this variable is a string we need to get the raw character string out of it. + if (( trick_type == TRICK_STRING ) && !deref) { + std::string * str_ptr = (std::string *)var_info->address ; + // Get a pointer to the internal character array + address = (void *)(str_ptr->c_str()) ; + } + + // if this variable itself is a pointer, dereference it + if ( deref ) { + address = *(void**)var_info->address ; + } + + // handle c++ string and char* + if ( trick_type == TRICK_STRING ) { + if (address == NULL) { + size = 0 ; + } else { + size = strlen((char*)address) + 1 ; + } + } + // handle c++ wstring and wchar_t* + if ( trick_type == TRICK_WSTRING ) { + if (address == NULL) { + size = 0 ; + } else { + size = wcslen((wchar_t *)address) * sizeof(wchar_t); + } + } + if(address != NULL) { + memcpy( stage_buffer , address , size ) ; + } + + staged = true; + return 0; +} + +bool Trick::VariableReference::validate() { + // The address is not NULL. + // Should be called by VariableServer Session if validateAddress is on. + // check the memory manager if the address falls into + // any of the memory blocks it knows of. Don't do this if we have a std::string or + // wstring type, or we already are pointing to a bad ref. + if ( (trick_type != TRICK_STRING) and + (trick_type != TRICK_WSTRING) and + (var_info->address != &bad_ref_int) and + (get_alloc_info_of(address) == NULL) ) { + + // This variable is broken, make it into an error ref + tagAsInvalid(); + return false; + } + + // Everything is fine + return true; +} + +static void write_escaped_string( std::ostream& os, const char* s) { + for (int ii=0 ; iiattr->size ; + + switch (trick_type) { + + case TRICK_CHARACTER: + if (var_info->attr->num_index == var_info->num_index) { + // Single char + out << (int)cv_convert_double(conversion_factor, *(char *)buf_ptr); + } else { + // All but last dim specified, leaves a char array + write_escaped_string(out, (const char *) buf_ptr); + bytes_written = size ; + } + break; + case TRICK_UNSIGNED_CHARACTER: + if (var_info->attr->num_index == var_info->num_index) { + // Single char + out << (unsigned int)cv_convert_double(conversion_factor,*(unsigned char *)buf_ptr); + } else { + // All but last dim specified, leaves a char array + write_escaped_string(out, (const char *) buf_ptr); + bytes_written = size ; + } + break; + + case TRICK_WCHAR:{ + if (var_info->attr->num_index == var_info->num_index) { + out << *(wchar_t *) buf_ptr; + } else { + // convert wide char string char string + size_t len = wcs_to_ncs_len((wchar_t *)buf_ptr) + 1 ; + + char temp_buf[len]; + wcs_to_ncs((wchar_t *) buf_ptr, temp_buf, len); + out << temp_buf; + bytes_written = size ; + } + } + break; + + case TRICK_STRING: + if ((char *) buf_ptr != NULL) { + write_escaped_string(out, (const char *) buf_ptr); + bytes_written = size ; + } else { + out << '\0'; + } + break; + + case TRICK_WSTRING: + if ((wchar_t *) buf_ptr != NULL) { + // convert wide char string char string + size_t len = wcs_to_ncs_len( (wchar_t *)buf_ptr) + 1 ; + + char temp_buf[len]; + wcs_to_ncs( (wchar_t *) buf_ptr, temp_buf, len); + out << temp_buf; + bytes_written = size ; + } else { + out << '\0'; + } + break; + case TRICK_SHORT: + out << (short)cv_convert_double(conversion_factor,*(short *)buf_ptr); + break; + + case TRICK_UNSIGNED_SHORT: + out << (unsigned short)cv_convert_double(conversion_factor,*(unsigned short *)buf_ptr); + break; + + case TRICK_INTEGER: + case TRICK_ENUMERATED: + out << (int)cv_convert_double(conversion_factor,*(int *)buf_ptr); + break; + + case TRICK_BOOLEAN: + out << (int)cv_convert_double(conversion_factor,*(bool *)buf_ptr); + break; + + case TRICK_BITFIELD: + out << (GET_BITFIELD(buf_ptr, var_info->attr->size, var_info->attr->index[0].start, var_info->attr->index[0].size)); + break; + + case TRICK_UNSIGNED_BITFIELD: + out << (GET_UNSIGNED_BITFIELD(buf_ptr, var_info->attr->size, var_info->attr->index[0].start, var_info->attr->index[0].size)); + break; + + case TRICK_UNSIGNED_INTEGER: + out << (unsigned int)cv_convert_double(conversion_factor,*(unsigned int *)buf_ptr); + break; + + case TRICK_LONG: { + long l = *(long *)buf_ptr; + if (conversion_factor != cv_get_trivial()) { + l = (long)cv_convert_double(conversion_factor, l); + } + out << l; + break; + } + + case TRICK_UNSIGNED_LONG: { + unsigned long ul = *(unsigned long *)buf_ptr; + if (conversion_factor != cv_get_trivial()) { + ul = (unsigned long)cv_convert_double(conversion_factor, ul); + } + out << ul; + break; + } + + case TRICK_FLOAT: + out << std::setprecision(8) << cv_convert_float(conversion_factor,*(float *)buf_ptr); + break; + + case TRICK_DOUBLE: + out << std::setprecision(16) << cv_convert_double(conversion_factor,*(double *)buf_ptr); + break; + + case TRICK_LONG_LONG: { + long long ll = *(long long *)buf_ptr; + if (conversion_factor != cv_get_trivial()) { + ll = (long long)cv_convert_double(conversion_factor, ll); + } + out << ll; + break; + } + + case TRICK_UNSIGNED_LONG_LONG: { + unsigned long long ull = *(unsigned long long *)buf_ptr; + if (conversion_factor != cv_get_trivial()) { + ull = (unsigned long long)cv_convert_double(conversion_factor, ull); + } + out << ull; + break; + } + + case TRICK_NUMBER_OF_TYPES: + out << "BAD_REF"; + break; + + default:{ + + break; + } + } // end switch + + if (bytes_written < size) { + // if returning an array, continue array as comma separated values + out << ","; + buf_ptr = (void*) ((long)buf_ptr + var_info->attr->size) ; + } + } //end while + + if (var_info->units) { + if ( var_info->attr->mods & TRICK_MODS_UNITSDASHDASH ) { + out << " {--}"; + } else { + out << " {" << var_info->units << "}"; + } + } + + return 0; +} + +void Trick::VariableReference::tagAsInvalid () { + std::string save_name(getName()) ; + free(var_info) ; + var_info = make_error_ref(save_name) ; + address = var_info->address ; +} + + +int Trick::VariableReference::prepareForWrite() { + if (!staged) { + return 1; + } + + void * temp_p = stage_buffer; + stage_buffer = write_buffer; + write_buffer = temp_p; + + staged = false; + write_ready = true; + return 0; +} + +bool Trick::VariableReference::isStaged() const { + return staged; +} + +bool Trick::VariableReference::isWriteReady() const { + return write_ready; +} + +int Trick::VariableReference::writeTypeBinary( std::ostream& out, bool byteswap ) const { + int local_type = trick_type; + if (byteswap) { + local_type = trick_byteswap_int(local_type); + } + out.write(const_cast(reinterpret_cast(&local_type)), sizeof(int)); + + return 0; +} + +int Trick::VariableReference::writeSizeBinary( std::ostream& out, bool byteswap ) const { + int local_size = size; + if (byteswap) { + local_size = trick_byteswap_int(local_size); + } + out.write(const_cast(reinterpret_cast(&local_size)), sizeof(int)); + + return 0; +} + +int Trick::VariableReference::writeNameBinary( std::ostream& out, bool byteswap ) const { + const char * name = getName(); + + int name_size = strlen(name); + if (byteswap) { + name_size = trick_byteswap_int(name_size); + } + + out.write(const_cast(reinterpret_cast(&name_size)), sizeof(int)); + out.write(name, strlen(name)); + + return 0; +} + +void Trick::VariableReference::byteswap_var (char * out, char * in) const { + byteswap_var(out, in, *this); +} + + +void Trick::VariableReference::byteswap_var (char * out, char * in, const VariableReference& ref) { + ATTRIBUTES * attr = ref.var_info->attr; + int array_size = 1; + + // Determine how many elements are in this array if it is an array + for (int j = 0; j < ref.var_info->attr->num_index; j++) { + array_size *= attr->index[j].size; + } + + switch (attr->size) { + case 1: + // If these are just characters, no need to byteswap + for (int j = 0; j < array_size; j++) { + out[j] = in[j]; + } + break; + + case 2: { + short * short_in = reinterpret_cast (in); + short * short_out = reinterpret_cast (out); + + for (int j = 0; j < array_size; j++) { + short_out[j] = trick_byteswap_short(short_in[j]); + } + break; + } + + case 4: { + int * int_in = reinterpret_cast (in); + int * int_out = reinterpret_cast (out); + + for (int j = 0; j < array_size; j++) { + int_out[j] = trick_byteswap_int(int_in[j]); + } + break; + } + case 8: { + // We don't actually care if this is double or long, just that it's the right size + double * double_in = reinterpret_cast (in); + double * double_out = reinterpret_cast (out); + + for (int j = 0; j < array_size; j++) { + double_out[j] = trick_byteswap_double(double_in[j]); + } + break; + } + } +} + + + +int Trick::VariableReference::writeValueBinary( std::ostream& out, bool byteswap ) const { + + char buf[20480]; + int temp_i ; + unsigned int temp_ui ; + + // int offset = 0; + + switch ( var_info->attr->type ) { + case TRICK_BITFIELD: + temp_i = GET_BITFIELD(address , var_info->attr->size , + var_info->attr->index[0].start, var_info->attr->index[0].size) ; + memcpy(buf, &temp_i , (size_t)size) ; + break ; + case TRICK_UNSIGNED_BITFIELD: + temp_ui = GET_UNSIGNED_BITFIELD(address , var_info->attr->size , + var_info->attr->index[0].start, var_info->attr->index[0].size) ; + memcpy(buf , &temp_ui , (size_t)size) ; + break ; + case TRICK_NUMBER_OF_TYPES: + // TRICK_NUMBER_OF_TYPES is an error case + temp_i = 0 ; + memcpy(buf , &temp_i , (size_t)size) ; + break ; + default: + if (byteswap) + byteswap_var(buf, (char *) address); + else + memcpy(buf , address , (size_t)size) ; + break ; + } + + out.write(buf, size); +} + +std::ostream& Trick::operator<< (std::ostream& s, const Trick::VariableReference& ref) { + + s << " \"" << ref.getName() << "\""; + return s; +} \ No newline at end of file diff --git a/trick_source/sim_services/VariableServer/VariableServer.cpp b/trick_source/sim_services/VariableServer/VariableServer.cpp index f791d67f..01c3db97 100644 --- a/trick_source/sim_services/VariableServer/VariableServer.cpp +++ b/trick_source/sim_services/VariableServer/VariableServer.cpp @@ -16,6 +16,7 @@ Trick::VariableServer::VariableServer() : } Trick::VariableServer::~VariableServer() { + } std::ostream& Trick::operator<< (std::ostream& s, Trick::VariableServer& vs) { @@ -65,8 +66,8 @@ bool Trick::VariableServer::get_log() { void Trick::VariableServer::set_var_server_log_on() { log = true; // turn log on for all current vs clients - std::map < pthread_t , VariableServerThread * >::iterator it ; - for ( it = var_server_threads.begin() ; it != var_server_threads.end() ; it++ ) { + std::map < pthread_t , VariableServerSession * >::iterator it ; + for ( it = var_server_sessions.begin() ; it != var_server_sessions.end() ; it++ ) { (*it).second->set_log_on(); } } @@ -74,14 +75,15 @@ void Trick::VariableServer::set_var_server_log_on() { void Trick::VariableServer::set_var_server_log_off() { log = false; // turn log off for all current vs clients - std::map < pthread_t , VariableServerThread * >::iterator it ; - for ( it = var_server_threads.begin() ; it != var_server_threads.end() ; it++ ) { + std::map < pthread_t , VariableServerSession * >::iterator it ; + for ( it = var_server_sessions.begin() ; it != var_server_sessions.end() ; it++ ) { (*it).second->set_log_off(); } } const char * Trick::VariableServer::get_hostname() { - return (listen_thread.get_hostname()) ; + const char * ret = (listen_thread.get_hostname()) ; + return ret; } Trick::VariableServerListenThread & Trick::VariableServer::get_listen_thread() { @@ -94,6 +96,12 @@ void Trick::VariableServer::add_vst(pthread_t in_thread_id, VariableServerThread pthread_mutex_unlock(&map_mutex) ; } +void Trick::VariableServer::add_session(pthread_t in_thread_id, VariableServerSession * in_session) { + pthread_mutex_lock(&map_mutex) ; + var_server_sessions[in_thread_id] = in_session ; + pthread_mutex_unlock(&map_mutex) ; +} + Trick::VariableServerThread * Trick::VariableServer::get_vst(pthread_t thread_id) { std::map < pthread_t , Trick::VariableServerThread * >::iterator it ; Trick::VariableServerThread * ret = NULL ; @@ -106,12 +114,30 @@ Trick::VariableServerThread * Trick::VariableServer::get_vst(pthread_t thread_id return ret ; } +Trick::VariableServerSession * Trick::VariableServer::get_session(pthread_t thread_id) { + std::map < pthread_t , Trick::VariableServerSession * >::iterator it ; + Trick::VariableServerSession * ret = NULL ; + pthread_mutex_lock(&map_mutex) ; + it = var_server_sessions.find(thread_id) ; + if ( it != var_server_sessions.end() ) { + ret = (*it).second ; + } + pthread_mutex_unlock(&map_mutex) ; + return ret ; +} + void Trick::VariableServer::delete_vst(pthread_t thread_id) { pthread_mutex_lock(&map_mutex) ; var_server_threads.erase(thread_id) ; pthread_mutex_unlock(&map_mutex) ; } +void Trick::VariableServer::delete_session(pthread_t thread_id) { + pthread_mutex_lock(&map_mutex) ; + var_server_sessions.erase(thread_id) ; + pthread_mutex_unlock(&map_mutex) ; +} + void Trick::VariableServer::set_copy_data_job( Trick::JobData * in_job ) { copy_data_job = in_job ; } diff --git a/trick_source/sim_services/VariableServer/VariableServerListenThread.cpp b/trick_source/sim_services/VariableServer/VariableServerListenThread.cpp index 34e4a125..72ac7ea4 100644 --- a/trick_source/sim_services/VariableServer/VariableServerListenThread.cpp +++ b/trick_source/sim_services/VariableServer/VariableServerListenThread.cpp @@ -10,37 +10,38 @@ #include "trick/message_proto.h" #include "trick/message_type.h" + Trick::VariableServerListenThread::VariableServerListenThread() : Trick::SysThread("VarServListen"), - port(0), - user_port_requested(false), + requested_port(0), + requested_source_address(""), + user_requested_address(false), broadcast(true), - listen_dev() + listener() { - char hname[80]; - gethostname(hname , (size_t) 80 ) ; - source_address = std::string(hname) ; - strcpy(listen_dev.client_tag, ""); - tc_error(&listen_dev, 0); pthread_mutex_init(&restart_pause, NULL); } Trick::VariableServerListenThread::~VariableServerListenThread() { - free(listen_dev.hostname) ; - free(listen_dev.error_handler) ; + // if (multicast != NULL) { + // delete multicast; + // multicast = NULL; + // } } + const char * Trick::VariableServerListenThread::get_hostname() { - return listen_dev.hostname; + const char * ret = listener.getHostname(); + return ret; } unsigned short Trick::VariableServerListenThread::get_port() { - return port; + return requested_port; } void Trick::VariableServerListenThread::set_port(unsigned short in_port) { - port = in_port; - user_port_requested = true ; + requested_port = in_port; + user_requested_address = true ; } std::string Trick::VariableServerListenThread::get_user_tag() { @@ -57,140 +58,116 @@ void Trick::VariableServerListenThread::set_user_tag(std::string in_tag) { void Trick::VariableServerListenThread::set_source_address(const char * address) { if ( address == NULL ) { - source_address = std::string("") ; + requested_source_address = std::string("") ; } else { - source_address = std::string(address) ; + requested_source_address = std::string(address) ; } - user_port_requested = true ; + user_requested_address = true ; } std::string Trick::VariableServerListenThread::get_source_address() { - return source_address ; + return listener.getHostname() ; } bool Trick::VariableServerListenThread::get_broadcast() { return broadcast; } +// in_broadcast atomic? We'll see what tsan says. Maybe go nuts with atomics void Trick::VariableServerListenThread::set_broadcast(bool in_broadcast) { broadcast = in_broadcast; } int Trick::VariableServerListenThread::init_listen_device() { - int ret; - - ret = tc_init(&listen_dev); - if (ret == TC_SUCCESS) { - port = listen_dev.port ; - } else { - fprintf(stderr, "ERROR: Could not establish listen port for Variable Server. Aborting.\n"); - ret = -1 ; - } - return ret ; + int ret = listener.initialize(); + requested_port = listener.getPort(); + requested_source_address = std::string(listener.getHostname()); + return ret; } int Trick::VariableServerListenThread::check_and_move_listen_device() { int ret ; - if ( source_address.compare(listen_dev.hostname) or port != listen_dev.port ) { + if ( user_requested_address ) { + /* The user has requested a different source address or port in the input file */ - tc_disconnect(&listen_dev) ; - ret = tc_init_with_connection_info(&listen_dev, AF_INET, SOCK_STREAM, source_address.c_str(), port) ; + listener.disconnect(); + ret = listener.initialize(requested_source_address, requested_port); + requested_port = listener.getPort(); + requested_source_address = std::string(listener.getHostname()); if (ret != TC_SUCCESS) { + std::cout << "Unsuccessful initialization " << std::endl; message_publish(MSG_ERROR, "ERROR: Could not establish variable server source_address %s: port %d. Aborting.\n", - source_address.c_str(), port); + requested_source_address.c_str(), requested_port); return -1 ; } } + return 0 ; } void Trick::VariableServerListenThread::create_tcp_socket(const char * address, unsigned short in_port ) { - int result = tc_init_with_connection_info(&listen_dev, AF_INET, SOCK_STREAM, address, in_port) ; - if (result != 0) { - message_publish(MSG_ERROR, "ERROR: Could not establish additional listen port at address %s and port %d for Variable Server.\n", address, in_port); - } + listener.initialize(address, in_port); } void * Trick::VariableServerListenThread::thread_body() { + // This thread listens for incoming client connections, and when one is received, creates a new thread to handle the session + // Also broadcasts on multicast channel - fd_set rfds; - struct timeval timeout_time = { 2, 0 }; - char buf1[1024] = { 0 } ; - struct passwd * passp ; - Trick::VariableServerThread * vst ; - int value; - std::string version; - char * user_name ; - - int mcast_socket = 0; - struct sockaddr_in mcast_addr ; - struct sockaddr_in mcast_addr_legacy ; - - version = std::string(exec_get_current_version()) ; + std::string version = std::string(exec_get_current_version()) ; version.erase(version.find_last_not_of(" \t\f\v\n\r")+1); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); - passp = getpwuid(getuid()) ; - + // get username to broadcast on multicast channel + struct passwd *passp = getpwuid(getuid()) ; + std::string user_name; if ( passp == NULL ) { user_name = strdup("unknown") ; } else { user_name = strdup(passp->pw_name) ; } - - tc_blockio(&listen_dev, TC_COMM_BLOCKIO); + + listener.setBlockMode(TC_COMM_BLOCKIO); if ( broadcast ) { - if ((mcast_socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - perror("vs_mcast_init socket"); - } - - value = 1; - if (setsockopt(mcast_socket, SOL_SOCKET, SO_REUSEADDR, (char *) &value, (socklen_t) sizeof(value)) < 0) { - perror("setsockopt: reuseaddr"); - } -#ifdef SO_REUSEPORT - if (setsockopt(mcast_socket, SOL_SOCKET, SO_REUSEPORT, (char *) &value, sizeof(value)) < 0) { - perror("setsockopt: reuseport"); - } -#endif - - /* Set up destination address */ - memset(&mcast_addr, 0, sizeof(mcast_addr)); - mcast_addr.sin_family = AF_INET; - mcast_addr.sin_addr.s_addr = inet_addr("239.3.14.15"); - mcast_addr.sin_port = htons((uint16_t) 9265); - - memset(&mcast_addr_legacy, 0, sizeof(mcast_addr_legacy)); - mcast_addr_legacy.sin_family = AF_INET; - mcast_addr_legacy.sin_addr.s_addr = inet_addr("224.3.14.15"); - mcast_addr_legacy.sin_port = htons((uint16_t) 9265); + initializeMulticast(); } while (1) { - FD_ZERO(&rfds); - FD_SET(listen_dev.socket, &rfds); - timeout_time.tv_sec = 2 ; - select(listen_dev.socket + 1, &rfds, NULL, NULL, &timeout_time); - - if (FD_ISSET(listen_dev.socket, &rfds)) { + // Look for a new client requesting a connection + if (listener.checkForNewConnections()) { // pause here during restart pthread_mutex_lock(&restart_pause) ; - vst = new Trick::VariableServerThread(&listen_dev) ; + + // Create a new thread to service this connection + VariableServerThread * vst = new Trick::VariableServerThread(&listener) ; vst->copy_cpus(get_cpus()) ; vst->create_thread() ; vst->wait_for_accept() ; + pthread_mutex_unlock(&restart_pause) ; } else if ( broadcast ) { +<<<<<<< HEAD snprintf(buf1 , sizeof(buf1), "%s\t%hu\t%s\t%d\t%s\t%s\t%s\t%s\t%s\t%hu\n" , listen_dev.hostname , (unsigned short)listen_dev.port , user_name , (int)getpid() , command_line_args_get_default_dir() , command_line_args_get_cmdline_name() , command_line_args_get_input_file() , version.c_str() , user_tag.c_str(), (unsigned short)listen_dev.port ) ; +======= + // Otherwise, broadcast on the multicast channel if enabled + char buf1[1024]; + sprintf(buf1 , "%s\t%hu\t%s\t%d\t%s\t%s\t%s\t%s\t%s\t%hu\n" , listener.getHostname(), (unsigned short)listener.getPort() , + user_name.c_str() , (int)getpid() , command_line_args_get_default_dir() , command_line_args_get_cmdline_name() , + command_line_args_get_input_file() , version.c_str() , user_tag.c_str(), (unsigned short)listener.getPort() ) ; +>>>>>>> e8ba4328 (Encapsulated listen device into ClientListener) - sendto(mcast_socket , buf1 , strlen(buf1) , 0 , (struct sockaddr *)&mcast_addr , (socklen_t)sizeof(mcast_addr)) ; - sendto(mcast_socket , buf1 , strlen(buf1) , 0 , (struct sockaddr *)&mcast_addr_legacy , (socklen_t)sizeof(mcast_addr)) ; + std::string message = buf1; + + if (!multicast.is_initialized()) { + // In case broadcast was turned on after this loop was entered + initializeMulticast(); + } + multicast.broadcast(message); } } @@ -203,38 +180,34 @@ int Trick::VariableServerListenThread::restart() { int ret ; - if ( user_port_requested ) { + if ( user_requested_address ) { - char hname[80]; - static struct sockaddr_in s_in; - gethostname(hname, (size_t) 80); - // Test to see if the restart address is on this machine. If it is not, it's not an error, clear source address - if ( strcmp( source_address.c_str(), hname )) { - if (! inet_pton(AF_INET, source_address.c_str(), (struct in_addr *)&s_in.sin_addr.s_addr) ) { - //printf("clearing source_address\n") ; - source_address.clear() ; - } + if (!listener.validateSourceAddress(requested_source_address)) { + requested_source_address.clear() ; } - printf("variable server restart user_port requested set %d\n", port) ; - - tc_disconnect(&listen_dev) ; - ret = tc_init_with_connection_info(&listen_dev, AF_INET, SOCK_STREAM, source_address.c_str(), port) ; + listener.disconnect(); + ret = listener.initialize(requested_source_address, requested_port); + if (ret != TC_SUCCESS) { - message_publish(MSG_ERROR, "ERROR: Could not establish listen port %d for Variable Server. Aborting.\n", port); + message_publish(MSG_ERROR, "ERROR: Could not establish listen port %d for Variable Server. Aborting.\n", requested_port); return (-1); } } else { - struct sockaddr_in s_in; - int s_in_size = sizeof(s_in) ; - getsockname( listen_dev.socket , (struct sockaddr *)&s_in, (socklen_t *)&s_in_size) ; - printf("restart variable server message port = %d\n" , ntohs(s_in.sin_port)) ; - port = listen_dev.port = ntohs(s_in.sin_port); + listener.checkSocket(); } + initializeMulticast(); + return 0 ; } +void Trick::VariableServerListenThread::initializeMulticast() { + multicast.initialize(); + multicast.addAddress("239.3.14.15", 9265); + multicast.addAddress("224.3.14.15", 9265); +} + void Trick::VariableServerListenThread::pause_listening() { pthread_mutex_lock(&restart_pause) ; } @@ -245,9 +218,9 @@ void Trick::VariableServerListenThread::restart_listening() { void Trick::VariableServerListenThread::dump( std::ostream & oss ) { oss << "Trick::VariableServerListenThread (" << name << ")" << std::endl ; - oss << " source_address = " << source_address << std::endl ; - oss << " port = " << port << std::endl ; - oss << " user_port_requested = " << user_port_requested << std::endl ; + oss << " source_address = " << listener.getHostname() << std::endl ; + oss << " port = " << listener.getPort() << std::endl ; + oss << " user_requested_address = " << user_requested_address << std::endl ; oss << " user_tag = " << user_tag << std::endl ; oss << " broadcast = " << broadcast << std::endl ; Trick::ThreadBase::dump(oss) ; diff --git a/trick_source/sim_services/VariableServer/VariableServerSession.cpp b/trick_source/sim_services/VariableServer/VariableServerSession.cpp new file mode 100644 index 00000000..32c03932 --- /dev/null +++ b/trick_source/sim_services/VariableServer/VariableServerSession.cpp @@ -0,0 +1,139 @@ +#include "trick/VariableServerSession.hh" +#include "trick/TrickConstant.hh" +#include "trick/exec_proto.h" +#include "trick/message_proto.h" +#include "trick/input_processor_proto.h" +#include "trick/realtimesync_proto.h" + + +Trick::VariableServerSession::VariableServerSession(ClientConnection * conn) { + debug = 0; + enabled = true ; + log = false ; + copy_mode = VS_COPY_ASYNC ; + write_mode = VS_WRITE_ASYNC ; + frame_multiple = 1 ; + frame_offset = 0 ; + freeze_frame_multiple = 1 ; + freeze_frame_offset = 0 ; + update_rate = 0.1 ; + cycle_tics = (long long)(update_rate * exec_get_time_tic_value()) ; + if (cycle_tics == 0) { + cycle_tics = 1; + } + + next_tics = TRICK_MAX_LONG_LONG ; + freeze_next_tics = TRICK_MAX_LONG_LONG ; + // multicast = false; + connection = conn; + byteswap = false ; + validate_address = false ; + send_stdio = false ; + + binary_data = false; + byteswap = false; + binary_data_nonames = false; + packets_copied = 0 ; + + exit_cmd = false; + pause_cmd = false; + + + // incoming_msg = (char *) calloc(MAX_CMD_LEN, 1); + // stripped_msg = (char *) calloc(MAX_CMD_LEN, 1); + + + pthread_mutex_init(©_mutex, NULL); +} + +Trick::VariableServerSession::~VariableServerSession() { + // free (incoming_msg); + // free (stripped_msg); +} + +// Command to turn on log to varserver_log file +int Trick::VariableServerSession::set_log_on() { + log = true; + return(0) ; +} + +// Command to turn off log to varserver_log file +int Trick::VariableServerSession::set_log_off() { + log = false; + return(0) ; +} + +void Trick::VariableServerSession::disconnect_references() { + for (VariableReference * variable : session_variables) { + variable->tagAsInvalid(); + } +} + +long long Trick::VariableServerSession::get_next_tics() const { + if ( ! enabled ) { + return TRICK_MAX_LONG_LONG ; + } + return next_tics ; +} + +long long Trick::VariableServerSession::get_freeze_next_tics() const { + if ( ! enabled ) { + return TRICK_MAX_LONG_LONG ; + } + return freeze_next_tics ; +} + +int Trick::VariableServerSession::handleMessage() { + + std::string received_message = connection->read(ClientConnection::MAX_CMD_LEN); + if (received_message.size() > 0) { + ip_parse(received_message.c_str()); /* returns 0 if no parsing error */ + } + +} + +Trick::VariableReference * Trick::VariableServerSession::find_session_variable(std::string name) const { + for (VariableReference * ref : session_variables) { + // Look for matching name + if (name.compare(ref->getName()) == 0) { + return ref; + } + } + + return NULL; +} + +double Trick::VariableServerSession::get_update_rate() const { + return update_rate; +} + +VS_WRITE_MODE Trick::VariableServerSession::get_write_mode () const { + return write_mode; +} + +VS_COPY_MODE Trick::VariableServerSession::get_copy_mode () const { + return copy_mode; +} + +std::ostream& Trick::operator<< (std::ostream& s, const Trick::VariableServerSession& session) { + if (session.binary_data) { + s << " \"format\":\"BINARY\",\n"; + } else { + s << " \"format\":\"ASCII\",\n"; + } + s << " \"update_rate\":" << session.get_update_rate() << ",\n"; + + s << " \"variables\":[\n"; + + int n_vars = (int)session.session_variables.size(); + for (int i=0 ; i1) { + s << "," ; + } + s << "\n"; + } + s << " ]\n"; + + return s; +} \ No newline at end of file diff --git a/trick_source/sim_services/VariableServer/VariableServerSession_commands.cpp b/trick_source/sim_services/VariableServer/VariableServerSession_commands.cpp new file mode 100644 index 00000000..e1d837ca --- /dev/null +++ b/trick_source/sim_services/VariableServer/VariableServerSession_commands.cpp @@ -0,0 +1,401 @@ + +#include +#include +#include +#include +#include +#include "trick/VariableServerSession.hh" +#include "trick/variable_server_message_types.h" +#include "trick/memorymanager_c_intf.h" +// #include "trick/tc_proto.h" +#include "trick/exec_proto.h" +#include "trick/command_line_protos.h" +#include "trick/message_proto.h" +#include "trick/message_type.h" +#include "trick/TrickConstant.hh" +#include "trick/sie_c_intf.h" +#include "trick/UdUnits.hh" +#include "trick/map_trick_units_to_udunits.hh" + + +int Trick::VariableServerSession::var_add(std::string in_name) { + VariableReference * new_var; + if (in_name == "time") { + new_var = new VariableReference(in_name, &time); + } else { + new_var = new VariableReference(in_name); + } + + session_variables.push_back(new_var) ; + + return(0) ; +} + +int Trick::VariableServerSession::var_add(std::string var_name, std::string units_name) { + var_add(var_name) ; + var_units(var_name, units_name) ; + return(0) ; +} + +// Helper function for var_send_once +std::vector split (const std::string& str, const char delim) { + std::stringstream ss(str); + std::string s; + std::vector ret; + while (std::getline(ss, s, delim)) { + ret.push_back(s); + } + return ret; +} + +int Trick::VariableServerSession::var_send_once(std::string in_name, int num_vars) { + std::vector var_names = split(in_name, ','); + + if (var_names.size() != num_vars) { + message_publish(MSG_ERROR, "Number of variables sent to var_send_once (%d) does not match num_vars (%d).\n", var_names.size(), num_vars); + return -1; + } + + std::vector given_vars; + for (auto& varName : var_names) { + VariableReference * new_var; + if (varName == "time") { + new_var = new VariableReference(varName, &time); + } else { + new_var = new VariableReference(varName); + } + given_vars.push_back(new_var); + } + copy_sim_data(given_vars, false); + write_data(given_vars, VS_SEND_ONCE); + + return(0) ; +} + + +int Trick::VariableServerSession::var_remove(std::string in_name) { + + for (unsigned int ii = 0 ; ii < session_variables.size() ; ii++ ) { + std::string var_name = session_variables[ii]->getName(); + if ( ! var_name.compare(in_name) ) { + delete session_variables[ii]; + session_variables.erase(session_variables.begin() + ii) ; + break ; + } + } + + return(0) ; + +} + +int Trick::VariableServerSession::var_units(std::string var_name, std::string units_name) { + VariableReference * variable = find_session_variable(var_name); + + if (variable == NULL) { + // TODO: ERROR LOGGER HERE + return -1; + } + + return variable->setRequestedUnits(units_name); +} + +int Trick::VariableServerSession::var_exists(std::string in_name) { + char buf1[5] ; + bool error = false ; + + unsigned int msg_type ; + REF2* var_ref = ref_attributes(in_name.c_str()); + + if ( var_ref == (REF2*)NULL ) { + error = true; + } + + if (binary_data) { + /* send binary 1 or 0 */ + msg_type = VS_VAR_EXISTS ; + memcpy(buf1, &msg_type , sizeof(msg_type)) ; + + buf1[4] = (error==false); + + if (debug >= 2) { + // message_publish(MSG_DEBUG, "%p tag=<%s> var_server sending 1 binary byte\n", &connection, connection.client_tag); + } + + connection->write(buf1, 5); + } else { + /* send ascii "1" or "0" */ + sprintf(buf1, "%d\t%d\n", VS_VAR_EXISTS, (error==false)); + if (debug >= 2) { + // message_publish(MSG_DEBUG, "%p tag=<%s> var_server sending:\n%s\n", &connection, connection.client_tag, buf1) ; + } + std::string write_string(buf1); + if (write_string.length() != strlen(buf1)) { + std::cout << "PROBLEM WITH STRING LENGTH: VAR_EXISTS ASCII" << std::endl; + } + connection->write(write_string); + } + + return(0) ; +} + +int Trick::VariableServerSession::var_clear() { + + while( !session_variables.empty() ) { + delete session_variables.back(); + session_variables.pop_back(); + } + + return(0) ; +} + +int Trick::VariableServerSession::var_send() { + copy_sim_data(); + write_data(); + return(0) ; +} + +int Trick::VariableServerSession::var_cycle(double in_rate) { + update_rate = in_rate ; + cycle_tics = (long long)(update_rate * exec_get_time_tic_value()) ; + return(0) ; +} + +bool Trick::VariableServerSession::get_pause() { + return pause_cmd ; +} + +void Trick::VariableServerSession::set_pause( bool on_off) { + pause_cmd = on_off ; +} + +int Trick::VariableServerSession::var_exit() { + exit_cmd = true ; + return(0) ; +} + +int Trick::VariableServerSession::var_validate_address(bool on_off) { + validate_address = on_off ; + return(0) ; +} + +int Trick::VariableServerSession::var_debug(int level) { + debug = level ; + return(0) ; +} + +int Trick::VariableServerSession::var_ascii() { + binary_data = 0 ; + return(0) ; +} + +int Trick::VariableServerSession::var_binary() { + binary_data = 1 ; + return(0) ; +} + +int Trick::VariableServerSession::var_binary_nonames() { + binary_data = 1 ; + binary_data_nonames = 1 ; + return(0) ; +} + +int Trick::VariableServerSession::var_set_copy_mode(int mode) { + if ( mode >= VS_COPY_ASYNC and mode <= VS_COPY_TOP_OF_FRAME ) { + copy_mode = (VS_COPY_MODE)mode ; + if ( copy_mode == VS_COPY_SCHEDULED ) { + long long sim_time_tics ; + sim_time_tics = exec_get_time_tics() ; + // round the next call time to a multiple of the cycle + sim_time_tics -= sim_time_tics % cycle_tics ; + next_tics = sim_time_tics + cycle_tics ; + + sim_time_tics = exec_get_freeze_time_tics() ; + // round the next call time to a multiple of the cycle + sim_time_tics -= sim_time_tics % cycle_tics ; + freeze_next_tics = sim_time_tics + cycle_tics ; + + } else { + next_tics = TRICK_MAX_LONG_LONG ; + } + return 0 ; + } + return -1 ; +} + +int Trick::VariableServerSession::var_set_write_mode(int mode) { + if ( mode >= VS_WRITE_ASYNC and mode <= VS_WRITE_WHEN_COPIED ) { + write_mode = (VS_WRITE_MODE)mode ; + return 0 ; + } + return -1 ; +} + +int Trick::VariableServerSession::var_sync(int mode) { + + switch (mode) { + case 1: + var_set_copy_mode(VS_COPY_SCHEDULED) ; + var_set_write_mode(VS_WRITE_ASYNC) ; + break ; + case 2: + var_set_copy_mode(VS_COPY_SCHEDULED) ; + var_set_write_mode(VS_WRITE_WHEN_COPIED) ; + break ; + case 0: + default: + var_set_copy_mode(VS_COPY_ASYNC) ; + var_set_write_mode(VS_WRITE_ASYNC) ; + break ; + } + + return 0 ; +} + +int Trick::VariableServerSession::var_set_frame_multiple(unsigned int mult) { + frame_multiple = mult ; + return 0 ; +} + +int Trick::VariableServerSession::var_set_frame_offset(unsigned int offset) { + frame_offset = offset ; + return 0 ; +} + +int Trick::VariableServerSession::var_set_freeze_frame_multiple(unsigned int mult) { + freeze_frame_multiple = mult ; + return 0 ; +} + +int Trick::VariableServerSession::var_set_freeze_frame_offset(unsigned int offset) { + freeze_frame_offset = offset ; + return 0 ; +} + +int Trick::VariableServerSession::var_byteswap(bool on_off) { + byteswap = on_off ; + return(0) ; +} + +bool Trick::VariableServerSession::get_send_stdio() { + return send_stdio ; +} + +int Trick::VariableServerSession::set_send_stdio(bool on_off) { + send_stdio = on_off ; + return(0) ; +} + +int Trick::VariableServerSession::send_list_size() { + + unsigned int msg_type = VS_LIST_SIZE; + int var_count = session_variables.size(); + + // send number of variables + if (binary_data) { + // send in the binary message header format: + // + char buf1[12] ; + + unsigned int msg_type = VS_LIST_SIZE; + memcpy(buf1, &msg_type , sizeof(msg_type)) ; + + memset(&(buf1[4]), 0, sizeof(int)); // message size = 0 + memcpy(&(buf1[8]), &var_count, sizeof(var_count)); + + if (debug >= 2) { + message_publish(MSG_DEBUG, "%p tag=<%s> var_server sending %d event variables\n", connection, connection->get_client_tag().c_str(), var_count); + } + + connection->write(buf1, sizeof (buf1)); + } else { + std::stringstream write_string; + write_string << VS_LIST_SIZE << "\t" << var_count << "\n"; + // ascii + if (debug >= 2) { + message_publish(MSG_DEBUG, "%p tag=<%s> var_server sending number of event variables:\n%s\n", connection, connection->get_client_tag().c_str(), write_string.str().c_str()) ; + } + + connection->write(write_string.str()); + } + + return 0 ; +} + +int Trick::VariableServerSession::transmit_file(std::string sie_file) { + const unsigned int packet_size = 4095 ; + FILE * fp ; + unsigned int file_size ; + unsigned int current_size = 0 ; + unsigned int bytes_read ; + char buffer[packet_size+1] ; + int ret ; + + if (debug >= 2) { + message_publish(MSG_DEBUG,"%p tag=<%s> var_server opening %s.\n", connection, connection->get_client_tag().c_str(), sie_file.c_str()) ; + } + + if ((fp = fopen(sie_file.c_str() , "r")) == NULL ) { + message_publish(MSG_ERROR,"Variable Server Error: Cannot open %s.\n", sie_file.c_str()) ; + sprintf(buffer, "%d\t-1\n", VS_SIE_RESOURCE) ; + std::string message(buffer); + connection->write(message); + return(-1) ; + } + + fseek(fp , 0L, SEEK_END) ; + file_size = ftell(fp) ; + + sprintf(buffer, "%d\t%u\n\0" , VS_SIE_RESOURCE, file_size) ; + std::string message(buffer); + connection->write(message); + rewind(fp) ; + + // Switch to blocking writes since this could be a large transfer. + if (connection->setBlockMode(TC_COMM_BLOCKIO)) { + message_publish(MSG_DEBUG,"Variable Server Error: Failed to set TCDevice to TC_COMM_BLOCKIO.\n"); + } + + while ( current_size < file_size ) { + bytes_read = fread(buffer , 1 , packet_size , fp) ; + message = std::string(buffer); + message.resize(bytes_read); + ret = connection->write(message); + if (ret != (int)bytes_read) { + message_publish(MSG_ERROR,"Variable Server Error: Failed to send SIE file. Bytes read: %d Bytes sent: %d\n", bytes_read, ret) ; + return(-1); + } + current_size += bytes_read ; + } + + // Switch back to non-blocking writes. + if (connection->setBlockMode(TC_COMM_NOBLOCKIO)) { + message_publish(MSG_ERROR,"Variable Server Error: Failed to set TCDevice to TC_COMM_NOBLOCKIO.\n"); + return(-1); + } + + return(0) ; +} + +int Trick::VariableServerSession::send_file(std::string file_name) { + return transmit_file(file_name) ; +} + +int Trick::VariableServerSession::send_sie_resource() { + sie_append_runtime_objs() ; + return transmit_file(std::string(command_line_args_get_default_dir()) + "/S_sie.resource") ; +} + +int Trick::VariableServerSession::send_sie_class() { + sie_class_attr_map_print_xml() ; + return transmit_file(std::string(command_line_args_get_default_dir()) + "/" + "S_sie_class.xml") ; +} + +int Trick::VariableServerSession::send_sie_enum() { + sie_enum_attr_map_print_xml() ; + return transmit_file(std::string(command_line_args_get_default_dir()) + "/" + "S_sie_enum.xml") ; +} + +int Trick::VariableServerSession::send_sie_top_level_objects() { + sie_top_level_objects_print_xml() ; + return transmit_file(std::string(command_line_args_get_default_dir()) + "/" + "S_sie_top_level_objects.xml") ; +} diff --git a/trick_source/sim_services/VariableServer/VariableServerThread_copy_data.cpp b/trick_source/sim_services/VariableServer/VariableServerSession_copy_data.cpp similarity index 85% rename from trick_source/sim_services/VariableServer/VariableServerThread_copy_data.cpp rename to trick_source/sim_services/VariableServer/VariableServerSession_copy_data.cpp index b02e6267..2b6325fc 100644 --- a/trick_source/sim_services/VariableServer/VariableServerThread_copy_data.cpp +++ b/trick_source/sim_services/VariableServer/VariableServerSession_copy_data.cpp @@ -2,12 +2,14 @@ #include #include -#include "trick/VariableServer.hh" +#include "trick/VariableServerSession.hh" #include "trick/variable_server_sync_types.h" #include "trick/exec_proto.h" #include "trick/realtimesync_proto.h" -int Trick::VariableServerThread::copy_data_freeze() { +// These methods should be called from main thread jobs + +int Trick::VariableServerSession::copy_data_freeze() { int ret = 0 ; long long curr_frame = exec_get_freeze_frame_count() ; @@ -28,7 +30,7 @@ int Trick::VariableServerThread::copy_data_freeze() { return ret ; } -int Trick::VariableServerThread::copy_data_freeze_scheduled(long long curr_tics) { +int Trick::VariableServerSession::copy_data_freeze_scheduled(long long curr_tics) { int ret = 0 ; @@ -47,7 +49,7 @@ int Trick::VariableServerThread::copy_data_freeze_scheduled(long long curr_tics) return ret ; } -int Trick::VariableServerThread::copy_data_scheduled(long long curr_tics) { +int Trick::VariableServerSession::copy_data_scheduled(long long curr_tics) { int ret = 0 ; @@ -66,7 +68,7 @@ int Trick::VariableServerThread::copy_data_scheduled(long long curr_tics) { return ret ; } -int Trick::VariableServerThread::copy_data_top() { +int Trick::VariableServerSession::copy_data_top() { int ret = 0 ; long long curr_frame = exec_get_frame_count() ; diff --git a/trick_source/sim_services/VariableServer/VariableServerSession_copy_sim_data.cpp b/trick_source/sim_services/VariableServer/VariableServerSession_copy_sim_data.cpp new file mode 100644 index 00000000..2598f39f --- /dev/null +++ b/trick_source/sim_services/VariableServer/VariableServerSession_copy_sim_data.cpp @@ -0,0 +1,35 @@ + +#include +#include + +#include "trick/VariableServerSession.hh" +#include "trick/memorymanager_c_intf.h" +#include "trick/exec_proto.h" + + +// These actually do the copying + +int Trick::VariableServerSession::copy_sim_data() { + return copy_sim_data(session_variables, true); +} + +int Trick::VariableServerSession::copy_sim_data(std::vector& given_vars, bool cyclical) { + + if (given_vars.size() == 0) { + return 0; + } + + if ( pthread_mutex_trylock(©_mutex) == 0 ) { + // Get the simulation time we start this copy + time = (double)exec_get_time_tics() / exec_get_time_tic_value() ; + + + for (auto curr_var : given_vars ) { + curr_var->stageValue(); + } + + pthread_mutex_unlock(©_mutex) ; + } + + return 0; +} diff --git a/trick_source/sim_services/VariableServer/VariableServerThread_freeze_init.cpp b/trick_source/sim_services/VariableServer/VariableServerSession_freeze_init.cpp similarity index 58% rename from trick_source/sim_services/VariableServer/VariableServerThread_freeze_init.cpp rename to trick_source/sim_services/VariableServer/VariableServerSession_freeze_init.cpp index 93a491a4..03baeba2 100644 --- a/trick_source/sim_services/VariableServer/VariableServerThread_freeze_init.cpp +++ b/trick_source/sim_services/VariableServer/VariableServerSession_freeze_init.cpp @@ -2,11 +2,11 @@ #include #include -#include "trick/VariableServerThread.hh" +#include "trick/VariableServerSession.hh" #include "trick/TrickConstant.hh" -int Trick::VariableServerThread::freeze_init() { - if ( enabled and copy_mode == VS_COPY_SCHEDULED) { +int Trick::VariableServerSession::freeze_init() { + if ( enabled && copy_mode == VS_COPY_SCHEDULED) { freeze_next_tics = cycle_tics ; } else { freeze_next_tics = TRICK_MAX_LONG_LONG ; diff --git a/trick_source/sim_services/VariableServer/VariableServerSession_write_data.cpp b/trick_source/sim_services/VariableServer/VariableServerSession_write_data.cpp new file mode 100644 index 00000000..33cda9ab --- /dev/null +++ b/trick_source/sim_services/VariableServer/VariableServerSession_write_data.cpp @@ -0,0 +1,188 @@ +/* +PURPOSE: (Allows clients to get and set Trick parameters) +PROGRAMMERS: (((Alex Lin) (NASA) (8/06) (--))) +*/ + +#include +#include +#include +#include // for setprecision +#include "trick/VariableServerSession.hh" +#include "trick/parameter_types.h" +#include "trick/bitfield_proto.h" +#include "trick/trick_byteswap.h" +#include "trick/tc_proto.h" +#include "trick/message_proto.h" +#include "trick/message_type.h" + + +extern "C" { + void *trick_bswap_buffer(void *out, void *in, ATTRIBUTES * attr, int tofrom) ; +} + +#define MAX_MSG_LEN 8192 + + +int Trick::VariableServerSession::write_binary_data(const std::vector& given_vars, VS_MESSAGE_TYPE message_type) { + // Some constants to make size calculations more readable + static const int header_size = 12; + static const int sizeof_size = 4; + static const int type_size = 4; + + std::vector> message_sizes_and_num_vars; + + // Calculate how many messages and how many vars in each + int total_size = header_size; + int num_vars = 0; + for (int i = 0; i < given_vars.size(); i++) { + const VariableReference * var = given_vars[i]; + int total_var_size = 0; + if (!binary_data_nonames) { + total_var_size += sizeof_size; + total_var_size += strlen(var->getName()); + } + + total_var_size += type_size; + total_var_size += sizeof_size; + total_var_size += var->getSizeBinary(); + + // If this variable won't fit in the current message, truncate the message and plan to put this var in a new one + if (total_size + total_var_size > MAX_MSG_LEN) { + message_sizes_and_num_vars.push_back(std::pair(total_size, num_vars)); + total_size = header_size; + num_vars = 0; + } + total_size += total_var_size; + num_vars++; + } + + message_sizes_and_num_vars.push_back(std::pair(total_size, num_vars)); + + // Now write out all of these messages + int var_index = 0; + for (std::pair message_info : message_sizes_and_num_vars) { + int curr_message_size = message_info.first; + int curr_message_num_vars = message_info.second; + + std::stringstream stream; + + int written_message_type = message_type; + int written_header_size = curr_message_size - 4; + int written_num_vars = curr_message_num_vars; + + if (byteswap) { + written_message_type = trick_byteswap_int(written_message_type); + written_header_size = trick_byteswap_int(written_header_size); + written_num_vars = trick_byteswap_int(written_num_vars); + } + + // Write the header first + stream.write((char *)(&written_message_type), sizeof(int)); + stream.write((char *)(&written_header_size), sizeof(int)); + stream.write ((char *)(&written_num_vars), sizeof(int)); + + // Write variables next + for (int i = var_index; i < var_index + curr_message_num_vars; i++) { + VariableReference * var = given_vars[i]; + if (!binary_data_nonames) { + var->writeNameBinary(stream, byteswap); + } + var->writeTypeBinary(stream, byteswap); + var->writeSizeBinary(stream, byteswap); + var->writeValueBinary(stream, byteswap); + } + var_index += curr_message_num_vars; + + char write_buf[MAX_MSG_LEN]; + stream.read(write_buf, curr_message_size); + connection->write(write_buf, curr_message_size); + } + + return 0; +} + +int Trick::VariableServerSession::write_ascii_data(const std::vector& given_vars, VS_MESSAGE_TYPE message_type ) { + // Load message type first + std::stringstream message_stream; + message_stream << (int)message_type; + + int message_size = message_stream.str().size(); + + // Load each variable + for (int i = 0; i < given_vars.size(); i++) { + message_stream << "\t"; + + std::stringstream var_stream; + if (given_vars[i]->writeValueAscii(var_stream) == -1) { + // If one of the values isn't ready, we need to abort the write + return 0; + } + + std::string var_string = var_stream.str(); + int var_size = var_string.size(); + + // Check that there's enough room for the next variable, tab character, and possible newline + if (message_size + var_size + 2 > MAX_MSG_LEN) { + + // Write out an incomplete message + std::string message = message_stream.str(); + int result = connection->write(message); + if (result < 0) + return result; + // Clear out the message stream + message_stream.str(""); + message_size = 0; + } + + // Concatenate + message_stream << var_string; + message_size += var_size + 1; + } + + + // End with newline + message_stream << '\n'; + std::string message = message_stream.str(); + int result = connection->write(message); + return result; +} + +int Trick::VariableServerSession::write_data() { + return write_data(session_variables, VS_VAR_LIST); +} + +int Trick::VariableServerSession::write_data(std::vector& given_vars, VS_MESSAGE_TYPE message_type) { + // do not send anything when there are no variables! + if ( given_vars.size() == 0) { + return(0); + } + + int result = 0; + + if ( pthread_mutex_trylock(©_mutex) == 0 ) { + // Check that all of the variables are staged + for (VariableReference * variable : given_vars ) { + if (!variable->isStaged()) { + pthread_mutex_unlock(©_mutex) ; + return 1; + } + } + + // Swap buffer_in and buffer_out for each vars[ii]. + for (VariableReference * variable : given_vars ) { + variable->prepareForWrite(); + } + + pthread_mutex_unlock(©_mutex) ; + + // Send out in correct format + if (binary_data) { + result = write_binary_data(given_vars, message_type ); + } else { + // ascii mode + result = write_ascii_data(given_vars, message_type ); + } + } + + return result; +} diff --git a/trick_source/sim_services/VariableServer/VariableServerSession_write_stdio.cpp b/trick_source/sim_services/VariableServer/VariableServerSession_write_stdio.cpp new file mode 100644 index 00000000..7732867e --- /dev/null +++ b/trick_source/sim_services/VariableServer/VariableServerSession_write_stdio.cpp @@ -0,0 +1,17 @@ +#include + +#include "trick/VariableServerSession.hh" +#include "trick/variable_server_message_types.h" +#include "trick/tc_proto.h" + +int Trick::VariableServerSession::write_stdio(int stream, std::string text) { + + std::stringstream outstream; + + outstream << VS_STDIO << " " << stream << " " << (int)text.length() << "\n"; + outstream << text; + + connection->write(outstream.str()); + + return 0 ; +} diff --git a/trick_source/sim_services/VariableServer/VariableServerThread.cpp b/trick_source/sim_services/VariableServer/VariableServerThread.cpp index 45b75747..68548fc2 100644 --- a/trick_source/sim_services/VariableServer/VariableServerThread.cpp +++ b/trick_source/sim_services/VariableServer/VariableServerThread.cpp @@ -7,73 +7,32 @@ Trick::VariableServer * Trick::VariableServerThread::vs = NULL ; -Trick::VariableServerThread::VariableServerThread(TCDevice * in_listen_dev) : - Trick::SysThread("VarServer", true) , - listen_dev(in_listen_dev) { +Trick::VariableServerThread::VariableServerThread(ClientListener * in_listen_dev) : + Trick::SysThread("VarServer") , debug(0), + listener(in_listen_dev), session(NULL) { - debug = 0 ; - enabled = true ; - log = false ; - connection_accepted = false ; - conn_type = TCP ; - copy_mode = VS_COPY_ASYNC ; - write_mode = VS_WRITE_ASYNC ; - frame_multiple = 1 ; - frame_offset = 0 ; - freeze_frame_multiple = 1 ; - freeze_frame_offset = 0 ; - binary_data = false; - multicast = false; - byteswap = false ; + connection_status = CONNECTION_PENDING ; - pause_cmd = false ; - exit_cmd = false ; + connection.initialize(); - validate_address = false ; - send_stdio = false ; + pthread_mutex_init(&connection_status_mutex, NULL); + pthread_cond_init(&connection_status_cv, NULL); - update_rate = 0.1 ; - cycle_tics = (long long)(update_rate * exec_get_time_tic_value()) ; - - next_tics = TRICK_MAX_LONG_LONG ; - freeze_next_tics = TRICK_MAX_LONG_LONG ; - - connection.disabled = TC_COMM_FALSE ; - connection.disable_handshaking = TC_COMM_TRUE ; - connection.blockio_limit = 0.0 ; - connection.blockio_type = TC_COMM_BLOCKIO ; - connection.client_id = 0 ; - strcpy(connection.client_tag, "") ; - connection.error_handler = (TrickErrorHndlr *) calloc(1, (int)sizeof(TrickErrorHndlr)); - connection.error_handler->report_level = TRICK_ERROR_CAUTION; - - pthread_mutex_init(©_mutex, NULL); pthread_mutex_init(&restart_pause, NULL); - var_data_staged = false; - packets_copied = 0 ; - - incoming_msg = (char *) calloc(1, MAX_CMD_LEN); - stripped_msg = (char *) calloc(1, MAX_CMD_LEN); - -} - -Trick::VariableServerThread::~VariableServerThread() { - free( incoming_msg ) ; - free( stripped_msg ) ; } +Trick::VariableServerThread::~VariableServerThread() {} std::ostream& Trick::operator<< (std::ostream& s, Trick::VariableServerThread& vst) { - // Write a JSON representation of a Trick::VariableServerThread to an ostream. struct sockaddr_in otherside; socklen_t len = (socklen_t)sizeof(otherside); s << " \"connection\":{\n"; - s << " \"client_tag\":\"" << vst.connection.client_tag << "\",\n"; + s << " \"client_tag\":\"" << vst.connection.get_client_tag() << "\",\n"; - int err = getpeername(vst.connection.socket, (struct sockaddr*)&otherside, &len); + int err = getpeername(vst.connection.get_socket(), (struct sockaddr*)&otherside, &len); if (err == 0) { s << " \"client_IP_address\":\"" << inet_ntoa(otherside.sin_addr) << "\",\n"; @@ -83,24 +42,8 @@ std::ostream& Trick::operator<< (std::ostream& s, Trick::VariableServerThread& v s << " \"client_port\":\"unknown\","; } - if (vst.binary_data) { - s << " \"format\":\"BINARY\",\n"; - } else { - s << " \"format\":\"ASCII\",\n"; - } - s << " \"update_rate\":" << vst.update_rate << ",\n"; + s << *(vst.session); - s << " \"variables\":[\n"; - - int n_vars = (int)vst.vars.size(); - for (int i=0 ; i1) { - s << "," ; - } - s << "\n"; - } - s << " ]\n"; s << " }" << std::endl; return s; } @@ -109,38 +52,60 @@ void Trick::VariableServerThread::set_vs_ptr(Trick::VariableServer * in_vs) { vs = in_vs ; } -// Command to turn on log to varserver_log file -int Trick::VariableServerThread::set_log_on() { - log = true; - return(0) ; -} - -// Command to turn off log to varserver_log file -int Trick::VariableServerThread::set_log_off() { - log = false; - return(0) ; -} - -long long Trick::VariableServerThread::get_next_tics() { - if ( ! enabled ) { - return TRICK_MAX_LONG_LONG ; - } - return next_tics ; -} - -long long Trick::VariableServerThread::get_freeze_next_tics() { - if ( ! enabled ) { - return TRICK_MAX_LONG_LONG ; - } - return freeze_next_tics ; -} - Trick::VariableServer * Trick::VariableServerThread::get_vs() { return vs ; } -TCDevice & Trick::VariableServerThread::get_connection() { - return connection ; +void Trick::VariableServerThread::set_client_tag(std::string tag) { + connection.set_client_tag(tag); +} + +Trick::ConnectionStatus Trick::VariableServerThread::wait_for_accept() { + + pthread_mutex_lock(&connection_status_mutex); + while ( connection_status == CONNECTION_PENDING ) { + pthread_cond_wait(&connection_status_cv, &connection_status_mutex); + } + pthread_mutex_unlock(&connection_status_mutex); + + return connection_status; +} + +// This should maybe go somewhere completely different +// Leaving it in thread for now +// Gets called from the main thread as a job +void Trick::VariableServerThread::preload_checkpoint() { + + // Stop variable server processing at the top of the processing loop. + pthread_mutex_lock(&restart_pause); + + // Let the thread complete any data copying it has to do + // and then suspend data copying until the checkpoint is reloaded. + pthread_mutex_lock(&(session->copy_mutex)); + + // Save the pause state of this thread. + saved_pause_cmd = session->get_pause(); + + // Disallow data writing. + session->set_pause(true); + + // Temporarily "disconnect" the variable references from Trick Managed Memory + // by tagging each as a "bad reference". + session->disconnect_references(); + + + // Allow data copying to continue. + pthread_mutex_unlock(&(session->copy_mutex)); + +} + +// Gets called from the main thread as a job +void Trick::VariableServerThread::restart() { + // Set the pause state of this thread back to its "pre-checkpoint reload" state. + session->set_pause(saved_pause_cmd) ; + + // Restart the variable server processing. + pthread_mutex_unlock(&restart_pause); } diff --git a/trick_source/sim_services/VariableServer/VariableServerThread_commands.cpp b/trick_source/sim_services/VariableServer/VariableServerThread_commands.cpp deleted file mode 100644 index a96ce6e8..00000000 --- a/trick_source/sim_services/VariableServer/VariableServerThread_commands.cpp +++ /dev/null @@ -1,516 +0,0 @@ - -#include -#include -#include -#include -#include -#include "trick/VariableServer.hh" -#include "trick/variable_server_message_types.h" -#include "trick/memorymanager_c_intf.h" -#include "trick/tc_proto.h" -#include "trick/exec_proto.h" -#include "trick/command_line_protos.h" -#include "trick/message_proto.h" -#include "trick/message_type.h" -#include "trick/TrickConstant.hh" -#include "trick/sie_c_intf.h" -#include "trick/UdUnits.hh" -#include "trick/map_trick_units_to_udunits.hh" - -int Trick::VariableServerThread::bad_ref_int = 0 ; -int Trick::VariableServerThread::do_not_resolve_bad_ref_int = 0 ; - -REF2* Trick::VariableServerThread::make_time_ref() { - REF2* new_ref; - new_ref = (REF2*)calloc(1, sizeof(REF2)); - new_ref->reference = strdup("time") ; - new_ref->units = strdup("s") ; - new_ref->address = (char *)&time ; - new_ref->attr = (ATTRIBUTES*)calloc(1, sizeof(ATTRIBUTES)) ; - new_ref->attr->type = TRICK_DOUBLE ; - new_ref->attr->units = strdup("s") ; - new_ref->attr->size = sizeof(double) ; - return new_ref; -} - -REF2* Trick::VariableServerThread::make_error_ref(std::string in_name) { - REF2* new_ref; - new_ref = (REF2*)calloc(1, sizeof(REF2)); - new_ref->reference = strdup(in_name.c_str()) ; - new_ref->units = NULL ; - new_ref->address = (char *)&bad_ref_int ; - new_ref->attr = (ATTRIBUTES*)calloc(1, sizeof(ATTRIBUTES)) ; - new_ref->attr->type = TRICK_NUMBER_OF_TYPES ; - new_ref->attr->units = (char *)"--" ; - new_ref->attr->size = sizeof(int) ; - return new_ref; -} - -Trick::VariableReference* Trick::VariableServerThread::create_var_reference(std::string in_name) { - REF2 * new_ref ; - - // Time var is treated specially - if ( in_name.compare("time") == 0 ) { - new_ref = make_time_ref() ; - } else { - // otherwise ref_attributes takes care of the hard part - new_ref = ref_attributes(in_name.c_str()) ; - } - - // Check error cases - if ( new_ref == NULL ) { - message_publish(MSG_ERROR, "Variable Server could not find variable %s.\n", in_name.c_str()); - new_ref = make_error_ref(in_name); - } else if ( new_ref->attr ) { - if ( new_ref->attr->type == TRICK_STRUCTURED ) { - message_publish(MSG_ERROR, "Variable Server: var_add cant add \"%s\" because its a composite variable.\n", in_name.c_str()); - // Replace the REF2 object we got from ref_attributes with an error-ref. - free(new_ref); - new_ref = make_error_ref(in_name); - // set the address of the data to the do_not_resolve address. We won't retry resolving the name - new_ref->address = (char *)&do_not_resolve_bad_ref_int ; - } else if ( new_ref->attr->type == TRICK_STL ) { - message_publish(MSG_ERROR, "Variable Server: var_add cant add \"%s\" because its an STL variable.\n", in_name.c_str()); - // Replace the REF2 object we got from ref_attributes with an error-ref. - free(new_ref); - new_ref = make_error_ref(in_name); - // set the address of the data to the do_not_resolve address. We won't retry resolving the name - new_ref->address = (char *)&do_not_resolve_bad_ref_int ; - } - } else { - message_publish(MSG_ERROR, "Variable Server: BAD MOJO - Missing ATTRIBUTES."); - new_ref = make_error_ref(in_name); - } - - // Actually constructs the variable reference in the success case - return new VariableReference(new_ref) ; -} - -int Trick::VariableServerThread::var_add(std::string in_name) { - VariableReference * new_var = create_var_reference(in_name); - vars.push_back(new_var) ; - - return(0) ; -} - -int Trick::VariableServerThread::var_add(std::string var_name, std::string units_name) { - var_add(var_name) ; - var_units(var_name, units_name) ; - return(0) ; -} - -// Helper function for var_send_once -std::vector split (const std::string& str, const char delim) { - std::stringstream ss(str); - std::string s; - std::vector ret; - while (std::getline(ss, s, delim)) { - ret.push_back(s); - } - return ret; -} - -int Trick::VariableServerThread::var_send_once(std::string in_name, int num_vars) { - std::vector var_names = split(in_name, ','); - - if (var_names.size() != num_vars) { - message_publish(MSG_ERROR, "Number of variables sent to var_send_once (%d) does not match num_vars (%d).\n", var_names.size(), num_vars); - return -1; - } - - std::vector given_vars; - for (auto& varName : var_names) { - given_vars.push_back(create_var_reference(varName)); - } - copy_sim_data(given_vars, false); - write_data(given_vars); - - return(0) ; -} - - -int Trick::VariableServerThread::var_remove(std::string in_name) { - - unsigned int ii ; - for ( ii = 0 ; ii < vars.size() ; ii++ ) { - std::string var_name = vars[ii]->ref->reference; - if ( ! var_name.compare(in_name) ) { - delete vars[ii]; - vars.erase(vars.begin() + ii) ; - break ; - } - } - - return(0) ; - -} - -int Trick::VariableServerThread::var_units(std::string var_name, std::string units_name) { - for ( VariableReference* variable : vars ) { - if ( std::string(variable->ref->reference).compare(var_name) ) { - continue; - } - - if (!units_name.compare("xx")) { - units_name = variable->ref->attr->units; - } - - auto publish = [](MESSAGE_TYPE type, const std::string& message) { - std::ostringstream oss; - oss << "Variable Server: " << message << std::endl; - message_publish(type, oss.str().c_str()); - }; - /* if unitless ('--') then do not convert to udunits*/ - if(units_name.compare("--")){ - std::string new_units = map_trick_units_to_udunits(units_name) ; - if ( units_name.compare(new_units) ) { - std::ostringstream oss; - oss << "[" << var_name << "] old-style units converted from [" - << units_name << "] to [" << new_units << "]"; - publish(MSG_WARNING, oss.str()); - } - - auto publishError = [&](const std::string& units) { - std::ostringstream oss; - oss << "units error for [" << var_name << "] [" << units << "]"; - publish(MSG_ERROR, oss.str()); - }; - - ut_unit * from = ut_parse(Trick::UdUnits::get_u_system(), variable->ref->attr->units, UT_ASCII) ; - if ( !from ) { - publishError(variable->ref->attr->units); - ut_free(from) ; - return -1 ; - } - - ut_unit * to = ut_parse(Trick::UdUnits::get_u_system(), new_units.c_str(), UT_ASCII) ; - if ( !to ) { - publishError(new_units); - ut_free(from) ; - ut_free(to) ; - return -1 ; - } - - cv_converter * conversion_factor = ut_get_converter(from, to) ; - ut_free(from) ; - ut_free(to) ; - if ( !conversion_factor ) { - std::ostringstream oss; - oss << "[" << var_name << "] cannot convert units from [" << variable->ref->attr->units - << "] to [" << new_units << "]"; - publish(MSG_ERROR, oss.str()); - return -1 ; - } - - cv_free(variable->conversion_factor); - variable->conversion_factor = conversion_factor ; - free(variable->ref->units); - variable->ref->units = strdup(new_units.c_str()); - } - } - return(0) ; -} - -int Trick::VariableServerThread::var_exists(std::string in_name) { - - char buf1[5] ; - bool error = false ; - - unsigned int msg_type ; - REF2* var_ref = ref_attributes(in_name.c_str()); - - if ( var_ref == (REF2*)NULL ) { - error = true; - } - - if (binary_data) { - /* send binary 1 or 0 */ - msg_type = VS_VAR_EXISTS ; - memcpy(buf1, &msg_type , sizeof(msg_type)) ; - - buf1[4] = (error==false); - - if (debug >= 2) { - message_publish(MSG_DEBUG, "%p tag=<%s> var_server sending 1 binary byte\n", &connection, connection.client_tag); - } - tc_write(&connection, (char *) buf1, 5); - } else { - /* send ascii "1" or "0" */ - snprintf(buf1, sizeof(buf1), "%d\t%d\n", VS_VAR_EXISTS, (error==false)); - if (debug >= 2) { - message_publish(MSG_DEBUG, "%p tag=<%s> var_server sending:\n%s\n", &connection, connection.client_tag, buf1) ; - } - tc_write(&connection, (char *) buf1, strlen(buf1)); - } - - return(0) ; -} - -int Trick::VariableServerThread::var_clear() { - while( !vars.empty() ) { - delete vars.back(); - vars.pop_back(); - } - return(0) ; -} - - -int Trick::VariableServerThread::var_send() { - copy_sim_data(); - write_data(); - return(0) ; -} - -int Trick::VariableServerThread::var_cycle(double in_rate) { - update_rate = in_rate ; - cycle_tics = (long long)(update_rate * exec_get_time_tic_value()) ; - return(0) ; -} - -bool Trick::VariableServerThread::get_pause() { - return pause_cmd ; -} - -void Trick::VariableServerThread::set_pause( bool on_off) { - pause_cmd = on_off ; -} - -int Trick::VariableServerThread::var_exit() { - exit_cmd = true ; - return(0) ; -} - -int Trick::VariableServerThread::var_validate_address(bool on_off) { - validate_address = on_off ; - return(0) ; -} - -int Trick::VariableServerThread::var_debug(int level) { - debug = level ; - return(0) ; -} - -int Trick::VariableServerThread::var_ascii() { - binary_data = 0 ; - return(0) ; -} - -int Trick::VariableServerThread::var_binary() { - binary_data = 1 ; - return(0) ; -} - -int Trick::VariableServerThread::var_binary_nonames() { - binary_data = 1 ; - binary_data_nonames = 1 ; - return(0) ; -} - -int Trick::VariableServerThread::var_set_copy_mode(int mode) { - if ( mode >= VS_COPY_ASYNC and mode <= VS_COPY_TOP_OF_FRAME ) { - copy_mode = (VS_COPY_MODE)mode ; - if ( copy_mode == VS_COPY_SCHEDULED ) { - long long sim_time_tics ; - sim_time_tics = exec_get_time_tics() ; - // round the next call time to a multiple of the cycle - sim_time_tics -= sim_time_tics % cycle_tics ; - next_tics = sim_time_tics + cycle_tics ; - - sim_time_tics = exec_get_freeze_time_tics() ; - // round the next call time to a multiple of the cycle - sim_time_tics -= sim_time_tics % cycle_tics ; - freeze_next_tics = sim_time_tics + cycle_tics ; - - } else { - next_tics = TRICK_MAX_LONG_LONG ; - } - return 0 ; - } - return -1 ; -} - -int Trick::VariableServerThread::var_set_write_mode(int mode) { - if ( mode >= VS_WRITE_ASYNC and mode <= VS_WRITE_WHEN_COPIED ) { - write_mode = (VS_WRITE_MODE)mode ; - return 0 ; - } - return -1 ; -} - -int Trick::VariableServerThread::var_sync(int mode) { - - switch (mode) { - case 1: - var_set_copy_mode(VS_COPY_SCHEDULED) ; - var_set_write_mode(VS_WRITE_ASYNC) ; - break ; - case 2: - var_set_copy_mode(VS_COPY_SCHEDULED) ; - var_set_write_mode(VS_WRITE_WHEN_COPIED) ; - break ; - case 0: - default: - var_set_copy_mode(VS_COPY_ASYNC) ; - var_set_write_mode(VS_WRITE_ASYNC) ; - break ; - } - - return 0 ; -} - -int Trick::VariableServerThread::var_set_frame_multiple(unsigned int mult) { - frame_multiple = mult ; - return 0 ; -} - -int Trick::VariableServerThread::var_set_frame_offset(unsigned int offset) { - frame_offset = offset ; - return 0 ; -} - -int Trick::VariableServerThread::var_set_freeze_frame_multiple(unsigned int mult) { - freeze_frame_multiple = mult ; - return 0 ; -} - -int Trick::VariableServerThread::var_set_freeze_frame_offset(unsigned int offset) { - freeze_frame_offset = offset ; - return 0 ; -} - -int Trick::VariableServerThread::var_byteswap(bool on_off) { - byteswap = on_off ; - return(0) ; -} - -bool Trick::VariableServerThread::get_send_stdio() { - return send_stdio ; -} - -int Trick::VariableServerThread::set_send_stdio(bool on_off) { - send_stdio = on_off ; - return(0) ; -} - -int Trick::VariableServerThread::var_signal() { - - message_publish(MSG_ERROR,"Variable Server Error: var_signal is currently not implemented.\n") ; - - return(0) ; -} - -int Trick::VariableServerThread::var_multicast(bool on_off) { - - multicast = on_off ; - - message_publish(MSG_ERROR, "Variable Server Error: var_multicast is currently not implemented.\n") ; - - return(0) ; -} - -int Trick::VariableServerThread::send_list_size() { - char buf1[12] ; - unsigned int msg_type ; - int var_count; - - // send number of variables - var_count = vars.size(); - if (binary_data) { - // send in the binary message header format: - // - msg_type = VS_LIST_SIZE; - memcpy(buf1, &msg_type , sizeof(msg_type)) ; - - memset(&(buf1[4]), 0, sizeof(int)); // message size = 0 - memcpy(&(buf1[8]), &var_count, sizeof(var_count)); - - if (debug >= 2) { - message_publish(MSG_DEBUG, "%p tag=<%s> var_server sending %d event variables\n", &connection, connection.client_tag, var_count); - } - tc_write(&connection, (char *) buf1, 12); - } else { - // ascii - snprintf(buf1, sizeof(buf1), "%d\t%d\n", VS_LIST_SIZE, var_count); - if (debug >= 2) { - message_publish(MSG_DEBUG, "%p tag=<%s> var_server sending number of event variables:\n%s\n", &connection, connection.client_tag, buf1) ; - } - tc_write(&connection, (char *) buf1, strlen(buf1)); - } - - return 0 ; -} - -int Trick::VariableServerThread::transmit_file(std::string sie_file) { - const unsigned int packet_size = 4095 ; - FILE * fp ; - unsigned int file_size ; - unsigned int current_size = 0 ; - unsigned int bytes_read ; - char buffer[packet_size] ; - int ret ; - - if (debug >= 2) { - message_publish(MSG_DEBUG,"%p tag=<%s> var_server opening %s.\n", &connection, connection.client_tag, sie_file.c_str()) ; - } - - if ((fp = fopen(sie_file.c_str() , "r")) == NULL ) { - message_publish(MSG_ERROR,"Variable Server Error: Cannot open %s.\n", sie_file.c_str()) ; - snprintf(buffer, sizeof(buffer), "%d\t-1\n", VS_SIE_RESOURCE) ; - tc_write(&connection , buffer , strlen(buffer)) ; - return(-1) ; - } - - fseek(fp , 0L, SEEK_END) ; - file_size = ftell(fp) ; - - snprintf(buffer, sizeof(buffer), "%d\t%u\n" , VS_SIE_RESOURCE, file_size) ; - tc_write(&connection , buffer , strlen(buffer)) ; - rewind(fp) ; - - // Switch to blocking writes since this could be a large transfer. - if (tc_blockio(&connection, TC_COMM_BLOCKIO)) { - message_publish(MSG_DEBUG,"Variable Server Error: Failed to set TCDevice to TC_COMM_BLOCKIO.\n"); - } - - while ( current_size < file_size ) { - bytes_read = fread(buffer , 1 , packet_size , fp) ; - ret = tc_write(&connection , buffer , bytes_read ) ; - if (ret != (int)bytes_read) { - message_publish(MSG_ERROR,"Variable Server Error: Failed to send SIE file.\n", sie_file.c_str()) ; - return(-1); - } - current_size += bytes_read ; - } - - // Switch back to non-blocking writes. - if (tc_blockio(&connection, TC_COMM_NOBLOCKIO)) { - message_publish(MSG_ERROR,"Variable Server Error: Failed to set TCDevice to TC_COMM_NOBLOCKIO.\n"); - return(-1); - } - - return(0) ; -} - -int Trick::VariableServerThread::send_file(std::string file_name) { - return transmit_file(file_name) ; -} - -int Trick::VariableServerThread::send_sie_resource() { - sie_append_runtime_objs() ; - return transmit_file(std::string(sie_get_runtime_sie_dir()) + "/S_sie.resource") ; -} - -int Trick::VariableServerThread::send_sie_class() { - sie_class_attr_map_print_xml() ; - return transmit_file(std::string(sie_get_runtime_sie_dir()) + "/" + "S_sie_class.xml") ; -} - -int Trick::VariableServerThread::send_sie_enum() { - sie_enum_attr_map_print_xml() ; - return transmit_file(std::string(sie_get_runtime_sie_dir()) + "/" + "S_sie_enum.xml") ; -} - -int Trick::VariableServerThread::send_sie_top_level_objects() { - sie_top_level_objects_print_xml() ; - return transmit_file(std::string(sie_get_runtime_sie_dir()) + "/" + "S_sie_top_level_objects.xml") ; -} diff --git a/trick_source/sim_services/VariableServer/VariableServerThread_connect.cpp b/trick_source/sim_services/VariableServer/VariableServerThread_connect.cpp deleted file mode 100644 index 3d9b145b..00000000 --- a/trick_source/sim_services/VariableServer/VariableServerThread_connect.cpp +++ /dev/null @@ -1,9 +0,0 @@ - -#include "trick/VariableServer.hh" -#include "trick/release.h" - -void Trick::VariableServerThread::wait_for_accept() { - while ( connection_accepted == false ) { - RELEASE() ; - } -} diff --git a/trick_source/sim_services/VariableServer/VariableServerThread_copy_sim_data.cpp b/trick_source/sim_services/VariableServer/VariableServerThread_copy_sim_data.cpp deleted file mode 100644 index 611825ea..00000000 --- a/trick_source/sim_services/VariableServer/VariableServerThread_copy_sim_data.cpp +++ /dev/null @@ -1,105 +0,0 @@ - -#include -#include - -#include "trick/VariableServer.hh" -#include "trick/memorymanager_c_intf.h" -#include "trick/exec_proto.h" - -int Trick::VariableServerThread::copy_sim_data() { - return copy_sim_data(vars, true); -} - -int Trick::VariableServerThread::copy_sim_data(std::vector given_vars, bool cyclical) { - - if (given_vars.size() == 0) { - return 0; - } - - if ( pthread_mutex_trylock(©_mutex) == 0 ) { - - // Get the simulation time we start this copy - if (cyclical) { - time = (double)exec_get_time_tics() / exec_get_time_tic_value() ; - } - - for (auto curr_var : given_vars ) { - - if (curr_var->ref->address == &bad_ref_int) { - REF2 *new_ref = ref_attributes(curr_var->ref->reference); - if (new_ref != NULL) { - curr_var->ref = new_ref; - } - } - - // if there's a pointer somewhere in the address path, follow it in case pointer changed - if ( curr_var->ref->pointer_present == 1 ) { - curr_var->address = follow_address_path(curr_var->ref) ; - if (curr_var->address == NULL) { - std::string save_name(curr_var->ref->reference) ; - free(curr_var->ref) ; - curr_var->ref = make_error_ref(save_name) ; - curr_var->address = curr_var->ref->address ; - } else if ( validate_address ) { - // The address is not NULL. - // If validate_address is on, check the memory manager if the address falls into - // any of the memory blocks it knows of. Don't do this if we have a std::string or - // wstring type, or we already are pointing to a bad ref. - if ( (curr_var->string_type != TRICK_STRING) and - (curr_var->string_type != TRICK_WSTRING) and - (curr_var->ref->address != &bad_ref_int) and - (get_alloc_info_of(curr_var->address) == NULL) ) { - std::string save_name(curr_var->ref->reference) ; - free(curr_var->ref) ; - curr_var->ref = make_error_ref(save_name) ; - curr_var->address = curr_var->ref->address ; - } - } else { - curr_var->ref->address = curr_var->address ; - } - - } - - // if this variable is a string we need to get the raw character string out of it. - if (( curr_var->string_type == TRICK_STRING ) && !curr_var->need_deref) { - std::string * str_ptr = (std::string *)curr_var->ref->address ; - curr_var->address = (void *)(str_ptr->c_str()) ; - } - - // if this variable itself is a pointer, dereference it - if ( curr_var->need_deref) { - curr_var->address = *(void**)curr_var->ref->address ; - } - - // handle c++ string and char* - if ( curr_var->string_type == TRICK_STRING ) { - if (curr_var->address == NULL) { - curr_var->size = 0 ; - } else { - curr_var->size = strlen((char*)curr_var->address) + 1 ; - } - } - // handle c++ wstring and wchar_t* - if ( curr_var->string_type == TRICK_WSTRING ) { - if (curr_var->address == NULL) { - curr_var->size = 0 ; - } else { - curr_var->size = wcslen((wchar_t *)curr_var->address) * sizeof(wchar_t); - } - } - if(curr_var->address != NULL) { - memcpy( curr_var->buffer_in , curr_var->address , curr_var->size ) ; - } - } - - // Indicate that sim data has been written and is now ready in the buffer_in's of the vars variable list. - if (cyclical) { - var_data_staged = true; - packets_copied++ ; - } - - pthread_mutex_unlock(©_mutex) ; - } - - return 0; -} diff --git a/trick_source/sim_services/VariableServer/VariableServerThread_create_socket.cpp b/trick_source/sim_services/VariableServer/VariableServerThread_create_socket.cpp deleted file mode 100644 index 1acea03b..00000000 --- a/trick_source/sim_services/VariableServer/VariableServerThread_create_socket.cpp +++ /dev/null @@ -1,44 +0,0 @@ - -#include -#include "trick/VariableServerThread.hh" -#include "trick/tc_proto.h" -#include "trick/message_proto.h" -#include "trick/message_type.h" - -int Trick::VariableServerThread::create_udp_socket(const char * address, unsigned short in_port) { - listen_dev = &connection ; - tc_init_with_connection_info(&connection, AF_INET, SOCK_DGRAM, address, in_port) ; - message_publish(MSG_INFO, "Created udp variable server %s:%d\n", listen_dev->hostname, listen_dev->port) ; - tc_blockio( &connection , TC_COMM_NOBLOCKIO ) ; - conn_type = UDP ; - return 0 ; -} - -int Trick::VariableServerThread::create_mcast_socket(const char * mcast_address, const char * address, unsigned short in_port) { - int ret ; - if ( mcast_address == NULL || mcast_address[0] == '\0' ) { - message_publish(MSG_ERROR, "Multicast address must be defined.\n") ; - return -1 ; - } - create_udp_socket(address, in_port) ; - - conn_type = MCAST ; - - struct ip_mreq mreq; - mreq.imr_multiaddr.s_addr = inet_addr(mcast_address); - mreq.imr_interface.s_addr = htonl(INADDR_ANY); - ret = setsockopt(connection.socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) ; - if ( ret < 0 ) { - perror("ip_add_membership") ; - return ret ; - } - - memset(&connection.remoteServAddr, 0, sizeof(struct sockaddr_in)); - connection.remoteServAddr.sin_family = AF_INET; - connection.remoteServAddr.sin_addr.s_addr = inet_addr(mcast_address); - connection.remoteServAddr.sin_port = htons(in_port); - - message_publish(MSG_INFO, "Multicast variable server output %s:%d\n", mcast_address, listen_dev->port) ; - return 0 ; - -} diff --git a/trick_source/sim_services/VariableServer/VariableServerThread_loop.cpp b/trick_source/sim_services/VariableServer/VariableServerThread_loop.cpp index a5190eed..660688a7 100644 --- a/trick_source/sim_services/VariableServer/VariableServerThread_loop.cpp +++ b/trick_source/sim_services/VariableServer/VariableServerThread_loop.cpp @@ -22,141 +22,81 @@ void exit_var_thread(void *in_vst) ; void * Trick::VariableServerThread::thread_body() { - int ii , jj; - int msg_len; - int ret; - int nbytes = -1; - char *last_newline ; - unsigned int size ; - socklen_t sock_size ; - // We need to make the thread to VariableServerThread map before we accept the connection. // Otherwise we have a race where this thread is unknown to the variable server and the // client gets confirmation that the connection is ready for communication. vs->add_vst( pthread_self() , this ) ; - if ( listen_dev->socket_type == SOCK_STREAM ) { - tc_accept(listen_dev, &connection); - tc_blockio(&connection, TC_COMM_ALL_OR_NOTHING); + // Accept client connection + int accept_status = accept(listener, &connection); + if (accept_status != 0) { + // TODO: Use a real error handler + std::cout << "Accept failed, variable server session exiting" << std::endl; + vs->delete_vst(pthread_self()); + + // Tell main thread that we failed to initialize + pthread_mutex_lock(&connection_status_mutex); + connection_status = CONNECTION_FAIL; + pthread_cond_signal(&connection_status_cv); + pthread_mutex_unlock(&connection_status_mutex); + + pthread_exit(NULL); } - connection_accepted = true ; + + connection.setBlockMode(TC_COMM_ALL_OR_NOTHING); + + // Create session + session = new VariableServerSession(&connection); + vs->add_session( pthread_self(), session ); + + // Tell main that we are ready + pthread_mutex_lock(&connection_status_mutex); + connection_status = CONNECTION_SUCCESS; + pthread_cond_signal(&connection_status_cv); + pthread_mutex_unlock(&connection_status_mutex); + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) ; - pthread_cleanup_push(exit_var_thread, (void *) this); - - /* Save off the host and port information of the source port. We want to ignore messages from - this port if we are a multicast socket */ - struct sockaddr_in self_s_in ; - int s_in_size = sizeof(self_s_in) ; - if ( conn_type == MCAST ) { - getsockname( connection.socket , (struct sockaddr *)&self_s_in, (socklen_t *)&s_in_size) ; - if ( self_s_in.sin_addr.s_addr == 0 ) { - char hname[80]; - struct hostent *ip_host; - gethostname(hname, (size_t) 80); - ip_host = gethostbyname(hname); - memcpy(&(self_s_in.sin_addr.s_addr), ip_host->h_addr, (size_t) ip_host->h_length); - } - } + pthread_cleanup_push(exit_var_thread, (void *) this) ; // if log is set on for variable server (e.g., in input file), turn log on for each client if (vs->get_log()) { - log = true ; + session->set_log_on(); } try { while (1) { - // Pause here if we are in a restart condition pthread_mutex_lock(&restart_pause) ; - /* Check the length of the message on the socket */ - nbytes = recvfrom( connection.socket, incoming_msg, MAX_CMD_LEN, MSG_PEEK, NULL, NULL ) ; - if (nbytes == 0 ) { - break ; - } + // Look for a message from the client + // Parse and execute if one is availible + session->handleMessage(); - if (nbytes != -1) { // -1 means socket is nonblocking and no data to read - /* find the last newline that is present on the socket */ - incoming_msg[nbytes] = '\0' ; - last_newline = rindex( incoming_msg , '\n') ; - - /* if there is a newline then there is a complete command on the socket */ - if ( last_newline != NULL ) { - /* only remove up to (and including) the last newline on the socket */ - size = last_newline - incoming_msg + 1; - if ( conn_type == UDP ) { - // Save the remote host information, that is where we are going to send replies. - sock_size = sizeof(connection.remoteServAddr) ; - nbytes = recvfrom( connection.socket, incoming_msg, size, 0 , - (struct sockaddr *)&connection.remoteServAddr, &sock_size ) ; - } else if ( conn_type == MCAST ) { - // Save the remove host information for test against ourself. - struct sockaddr_in s_in ; - sock_size = sizeof(s_in) ; - nbytes = recvfrom( connection.socket, incoming_msg, size, 0 , - (struct sockaddr *)&s_in, &sock_size ) ; - // If this message is from us, then ignore it. - if ( s_in.sin_addr.s_addr == self_s_in.sin_addr.s_addr and s_in.sin_port == self_s_in.sin_port) { - nbytes = 0 ; - } - } else { - // We know where we are sending information, no need to save it. - nbytes = recvfrom( connection.socket, incoming_msg, size, 0 , NULL, NULL ) ; - } - } else { - nbytes = 0 ; - } - } - - if ( nbytes > 0 ) { - - msg_len = nbytes ; - if (debug >= 3) { - message_publish(MSG_DEBUG, "%p tag=<%s> var_server received bytes = msg_len = %d\n", &connection, connection.client_tag, nbytes); - } - - incoming_msg[msg_len] = '\0' ; - - if (vs->get_info_msg() || (debug >= 1)) { - message_publish(MSG_DEBUG, "%p tag=<%s> var_server received: %s", &connection, connection.client_tag, incoming_msg) ; - } - if (log) { - message_publish(MSG_PLAYBACK, "tag=<%s> time=%f %s", connection.client_tag, exec_get_sim_time(), incoming_msg) ; - } - - for( ii = 0 , jj = 0 ; ii <= msg_len ; ii++ ) { - if ( incoming_msg[ii] != '\r' ) { - stripped_msg[jj++] = incoming_msg[ii] ; - } - } - - ip_parse(stripped_msg); /* returns 0 if no parsing error */ - - } - - /* break out of loop if exit command found */ - if (exit_cmd == true) { + // Check to see if exit is necessary + if (session->exit_cmd == true) { break; } - if ( copy_mode == VS_COPY_ASYNC ) { - copy_sim_data() ; + // Copy data out of sim if async mode + if ( session->get_copy_mode() == VS_COPY_ASYNC ) { + session->copy_sim_data() ; } + + bool should_write_async = (session->get_write_mode() == VS_WRITE_ASYNC) || + ( session->get_copy_mode() == VS_COPY_ASYNC && (session->get_write_mode() == VS_WRITE_WHEN_COPIED)) || + (! is_real_time()); - if ( (write_mode == VS_WRITE_ASYNC) or - ((copy_mode == VS_COPY_ASYNC) and (write_mode == VS_WRITE_WHEN_COPIED)) or - (! is_real_time()) ) { - if ( !pause_cmd ) { - ret = write_data() ; - if ( ret < 0 ) { - break ; - } + // Write data out to connection if async mode and not paused + if ( should_write_async && !session->get_pause()) { + int ret = session->write_data() ; + if ( ret < 0 ) { + break ; } } pthread_mutex_unlock(&restart_pause) ; - usleep((unsigned int) (update_rate * 1000000)); + usleep((unsigned int) (session->get_update_rate() * 1000000)); } } catch (Trick::ExecutiveException & ex ) { message_publish(MSG_ERROR, "\nVARIABLE SERVER COMMANDED exec_terminate\n ROUTINE: %s\n DIAGNOSTIC: %s\n" , @@ -192,7 +132,7 @@ void * Trick::VariableServerThread::thread_body() { } if (debug >= 3) { - message_publish(MSG_DEBUG, "%p tag=<%s> var_server receive loop exiting\n", &connection, connection.client_tag); + message_publish(MSG_DEBUG, "%p tag=<%s> var_server receive loop exiting\n", &connection, connection.get_client_tag().c_str()); } pthread_cleanup_pop(1); diff --git a/trick_source/sim_services/VariableServer/VariableServerThread_restart.cpp b/trick_source/sim_services/VariableServer/VariableServerThread_restart.cpp deleted file mode 100644 index 9c9f752a..00000000 --- a/trick_source/sim_services/VariableServer/VariableServerThread_restart.cpp +++ /dev/null @@ -1,45 +0,0 @@ - -#include -#include "trick/VariableServerThread.hh" - -void Trick::VariableServerThread::preload_checkpoint() { - - // Stop variable server processing at the top of the processing loop. - pthread_mutex_lock(&restart_pause); - - // Let the thread complete any data copying it has to do - // and then suspend data copying until the checkpoint is reloaded. - pthread_mutex_lock(©_mutex); - - // Save the pause state of this thread. - saved_pause_cmd = pause_cmd; - - // Disallow data writing. - pause_cmd = true ; - - // Temporarily "disconnect" the variable references from Trick Managed Memory - // by tagging each as a "bad reference". - std::vector ::iterator it ; - for (it = vars.begin(); it != vars.end() ; it++) { - (*it)->ref->address = (char*)&bad_ref_int; - (*it)->ref->attr = new ATTRIBUTES() ; - (*it)->ref->attr->type = TRICK_NUMBER_OF_TYPES ; - (*it)->ref->attr->units = (char *)"--" ; - (*it)->ref->attr->size = sizeof(int) ; - } - - // Allow data copying to continue. - pthread_mutex_unlock(©_mutex); - -} - -void Trick::VariableServerThread::restart() { - // Set the pause state of this thread back to its "pre-checkpoint reload" state. - pause_cmd = saved_pause_cmd ; - - // Restart the variable server processing. - pthread_mutex_unlock(&restart_pause); - -} - - diff --git a/trick_source/sim_services/VariableServer/VariableServerThread_write_data.cpp b/trick_source/sim_services/VariableServer/VariableServerThread_write_data.cpp deleted file mode 100644 index 17709b3d..00000000 --- a/trick_source/sim_services/VariableServer/VariableServerThread_write_data.cpp +++ /dev/null @@ -1,322 +0,0 @@ -/* -PURPOSE: (Allows clients to get and set Trick parameters) -PROGRAMMERS: (((Alex Lin) (NASA) (8/06) (--))) -*/ - -#include -#include -#include "trick/VariableServer.hh" -#include "trick/parameter_types.h" -#include "trick/bitfield_proto.h" -#include "trick/trick_byteswap.h" -#include "trick/tc_proto.h" -#include "trick/message_proto.h" -#include "trick/message_type.h" - - -extern "C" { - void *trick_bswap_buffer(void *out, void *in, ATTRIBUTES * attr, int tofrom) ; -} - -#define MAX_MSG_LEN 8192 - - -int Trick::VariableServerThread::write_binary_data( int Start, char *buf1, const std::vector& given_vars, VS_MESSAGE_TYPE message_type) { - int i; - int ret ; - int HeaderSize, MessageSize; - int NumVariablesProcessed; - unsigned int msg_type , offset, len ; - unsigned int size ; - unsigned int swap_int ; - char * address = 0 ; - char* param_name; - - /* start the offset 4 bytes into the message, we'll subtract the sizeof offset at the end */ - offset = sizeof(msg_type) + sizeof(offset) ; - - if (byteswap) { - /* Swap message type bytes */ - msg_type = trick_byteswap_int((int)message_type) ; - } else { - msg_type = message_type; - } - memcpy(buf1, &msg_type , sizeof(msg_type)) ; - HeaderSize = sizeof(msg_type); - - offset += sizeof(unsigned int) ; - HeaderSize += sizeof(unsigned int); - - for (i = Start; i < (int)given_vars.size() ; i++) { - - // data to send was copied to buffer in copy_sim_data - address = (char *)given_vars[i]->buffer_out; - size = given_vars[i]->size ; - - param_name = given_vars[i]->ref->reference; - len = strlen(param_name) ; - // when var_binary_nonames, do not put the variable names into the message to be sent - if (binary_data_nonames) { - MessageSize = sizeof(int) + sizeof(size) + size ; - } else { - MessageSize = sizeof(len) + len + sizeof(int) + sizeof(size) + size ; - } - - /* make sure this message will fit in a packet by itself */ - if ( (HeaderSize + MessageSize) > MAX_MSG_LEN ) { - message_publish(MSG_WARNING, "%p Variable Server buffer[%d] too small (need %d) for symbol %s, SKIPPING IT.\n", - &connection, MAX_MSG_LEN, - (int)(HeaderSize + MessageSize), - given_vars[i]->ref->reference ); - continue; - } - - if ( (offset + MessageSize) < MAX_MSG_LEN ) { - if (byteswap) { - if (!binary_data_nonames) { - swap_int = trick_byteswap_int((int)len) ; - memcpy(&buf1[offset] , &swap_int , sizeof(len)) ; - offset += sizeof(len) ; - - memcpy(&buf1[offset] , param_name , (size_t)len) ; - offset += len ; - } - - swap_int = trick_byteswap_int(given_vars[i]->ref->attr->type) ; - memcpy(&buf1[offset] , &swap_int , sizeof(int)) ; - offset += sizeof(int) ; - - swap_int = trick_byteswap_int((int)size) ; - memcpy(&buf1[offset] , &swap_int , sizeof(size)) ; - offset += sizeof(size) ; - - trick_bswap_single_parameter(&buf1[offset], address, given_vars[i]->ref->attr, 1); - offset += size ; - } - else { - int temp_i ; - unsigned int temp_ui ; - - if (!binary_data_nonames) { - memcpy(&buf1[offset] , &len , sizeof(len)) ; - offset += sizeof(len) ; - - memcpy(&buf1[offset] , param_name , (size_t)len) ; - offset += len ; - } - - memcpy(&buf1[offset] , &given_vars[i]->ref->attr->type , sizeof(int)) ; - offset += sizeof(int) ; - - memcpy(&buf1[offset] , &size , sizeof(size)) ; - offset += sizeof(size) ; - - switch ( given_vars[i]->ref->attr->type ) { - case TRICK_BITFIELD: - temp_i = GET_BITFIELD(address , given_vars[i]->ref->attr->size , - given_vars[i]->ref->attr->index[0].start, given_vars[i]->ref->attr->index[0].size) ; - memcpy(&buf1[offset] , &temp_i , (size_t)size) ; - break ; - case TRICK_UNSIGNED_BITFIELD: - temp_ui = GET_UNSIGNED_BITFIELD(address , given_vars[i]->ref->attr->size , - given_vars[i]->ref->attr->index[0].start, given_vars[i]->ref->attr->index[0].size) ; - memcpy(&buf1[offset] , &temp_ui , (size_t)size) ; - break ; - case TRICK_NUMBER_OF_TYPES: - // TRICK_NUMBER_OF_TYPES is an error case - temp_i = 0 ; - memcpy(&buf1[offset] , &temp_i , (size_t)size) ; - break ; - default: - memcpy(&buf1[offset] , address , (size_t)size) ; - break ; - } - offset += size ; - } - } - else { - /* indicate that we're over the maximum size */ - if (debug >= 2) { - message_publish(MSG_DEBUG, "%p tag=<%s> var_server buffer[%d] too small (need %d), sending multiple binary packets.\n", - &connection, connection.client_tag, MAX_MSG_LEN, - (int)(offset + MessageSize) ); - } - break ; - } - } - - /* adjust the header with the correct information reflecting what has been accomplished */ - NumVariablesProcessed = i - Start; - - offset -= sizeof(offset) ; - if (byteswap) { - swap_int = trick_byteswap_int((int)offset) ; - memcpy(buf1 + sizeof(msg_type) , &swap_int , sizeof(offset)) ; - - swap_int = trick_byteswap_int( NumVariablesProcessed ) ; - memcpy( buf1 + sizeof(msg_type) + sizeof(offset), &swap_int , sizeof(swap_int)) ; - } - else { - memcpy(buf1 + sizeof(msg_type) , &offset , sizeof(offset)) ; - memcpy( buf1 + sizeof(msg_type) + sizeof(offset), &NumVariablesProcessed , sizeof( NumVariablesProcessed )) ; - } - - if (debug >= 2) { - message_publish(MSG_DEBUG, "%p tag=<%s> var_server sending %u binary bytes containing %d variables.\n", &connection, - connection.client_tag, (unsigned int)(offset + sizeof(offset)), NumVariablesProcessed); - } - - len = offset + sizeof(msg_type) ; - ret = tc_write(&connection, (char *) buf1, len); - if ( ret != (int)len ) { - return(-1) ; - } - - /* return the index to the next symbol to send or V->num_vars if all done */ - return i; -} - -int Trick::VariableServerThread::write_ascii_data(char * dest_buf, size_t dest_buf_size, const std::vector& given_vars, VS_MESSAGE_TYPE message_type ) { - - snprintf(dest_buf, dest_buf_size, "%d\t", message_type) ; - - for (unsigned long i = 0; i < given_vars.size(); i++) { - char curr_buf[MAX_MSG_LEN]; - int ret = vs_format_ascii( given_vars[i] , curr_buf, sizeof(curr_buf)); - - if (ret < 0) { - message_publish(MSG_WARNING, "%p Variable Server string buffer[%d] too small for symbol %s, TRUNCATED IT.\n", - &connection, MAX_MSG_LEN, given_vars[i]->ref->reference ); - } - - /* make sure this message will fit in a packet by itself */ - if( strlen( curr_buf ) + 2 > MAX_MSG_LEN ) { - message_publish(MSG_WARNING, "%p Variable Server buffer[%d] too small for symbol %s, TRUNCATED IT.\n", - &connection, MAX_MSG_LEN, given_vars[i]->ref->reference ); - curr_buf[MAX_MSG_LEN - 1] = '\0'; - } - - int len = strlen(dest_buf) ; - - /* make sure there is space for the next tab or next newline and null */ - if( len + strlen( curr_buf ) + 2 > MAX_MSG_LEN ) { - // If there isn't, send incomplete message - if (debug >= 2) { - message_publish(MSG_DEBUG, "%p tag=<%s> var_server sending %d ascii bytes:\n%s\n", - &connection, connection.client_tag, (int)strlen(dest_buf), dest_buf) ; - } - - ret = tc_write(&connection, (char *) dest_buf, len); - if ( ret != len ) { - return(-1) ; - } - dest_buf[0] = '\0'; - } - - strcat(dest_buf, curr_buf); - strcat(dest_buf, "\t"); - } - - int len = strlen(dest_buf) ; - - if ( len > 0 ) { - dest_buf[ strlen(dest_buf) - 1 ] = '\n'; - - if (debug >= 2) { - message_publish(MSG_DEBUG, "%p tag=<%s> var_server sending %d ascii bytes:\n%s\n", - &connection, connection.client_tag, (int)strlen(dest_buf), dest_buf) ; - } - int ret = tc_write(&connection, (char *) dest_buf, (int)strlen(dest_buf)); - if ( ret != (int)strlen(dest_buf) ) { - return(-1) ; - } - } - - return 0; -} - -int Trick::VariableServerThread::write_data() { - - int ret; - unsigned int i ; - char buf1[ MAX_MSG_LEN ]; - int len ; - - // do not send anything when there are no variables! - if ( vars.size() == 0 or packets_copied == 0 ) { - return 0; - } - - /* Acquire sole access to vars[ii]->buffer_in. */ - if ( var_data_staged and pthread_mutex_trylock(©_mutex) == 0 ) { - unsigned int ii; - void * temp_p; - // Swap buffer_in and buffer_out for each vars[ii]. - for ( ii = 0 ; ii < vars.size() ; ii++ ) { - temp_p = vars[ii]->buffer_in; - vars[ii]->buffer_in = vars[ii]->buffer_out; - vars[ii]->buffer_out = temp_p; - } - var_data_staged = false; - - /* Relinquish sole access to vars[ii]->buffer_in. */ - pthread_mutex_unlock(©_mutex) ; - - if (binary_data) { - int index = 0; - - do { - ret = write_binary_data( index, buf1, vars, VS_VAR_LIST ); - if ( ret >= 0 ) { - index = ret ; - } else { - return(-1) ; - } - } while( index < (int)vars.size() ); - - return 0; - - } else { /* ascii mode */ - return write_ascii_data(buf1, sizeof(buf1), vars, VS_VAR_LIST ); - } - } -} - -int Trick::VariableServerThread::write_data(std::vector given_vars) { - // do not send anything when there are no variables! - if ( given_vars.size() == 0) { - return(0); - } - - /* Acquire sole access to vars[ii]->buffer_in. */ - if ( pthread_mutex_trylock(©_mutex) == 0 ) { - // Swap buffer_in and buffer_out for each vars[ii]. - for (int i = 0 ; i < given_vars.size() ; i++ ) { - void *temp_p = given_vars[i]->buffer_in; - given_vars[i]->buffer_in = given_vars[i]->buffer_out; - given_vars[i]->buffer_out = temp_p; - } - /* Relinquish sole access to vars[ii]->buffer_in. */ - pthread_mutex_unlock(©_mutex) ; - - char buf1[ MAX_MSG_LEN ]; - - if (binary_data) { - int index = 0; - - do { - int ret = write_binary_data( index, buf1, given_vars, VS_SEND_ONCE ); - if ( ret >= 0 ) { - index = ret ; - } else { - return(-1) ; - } - } while( index < (int)given_vars.size() ); - - return 0; - - } else { /* ascii mode */ - return write_ascii_data(buf1, sizeof(buf1), given_vars, VS_SEND_ONCE); - } - } -} diff --git a/trick_source/sim_services/VariableServer/VariableServerThread_write_stdio.cpp b/trick_source/sim_services/VariableServer/VariableServerThread_write_stdio.cpp deleted file mode 100644 index 684f44d6..00000000 --- a/trick_source/sim_services/VariableServer/VariableServerThread_write_stdio.cpp +++ /dev/null @@ -1,13 +0,0 @@ - -#include "trick/VariableServer.hh" -#include "trick/variable_server_message_types.h" -#include "trick/tc_proto.h" - -int Trick::VariableServerThread::write_stdio(int stream, std::string text) { - - char header[16] ; - snprintf(header, sizeof(header), "%-2d %1d %8d\n" , VS_STDIO, stream , (int)text.length()) ; - tc_write(&connection , (char *) header , strlen(header)) ; - tc_write(&connection , (char *) text.c_str() , text.length()) ; - return 0 ; -} diff --git a/trick_source/sim_services/VariableServer/VariableServer_copy_data_freeze.cpp b/trick_source/sim_services/VariableServer/VariableServer_copy_data_freeze.cpp index bc90291c..62b4bcdf 100644 --- a/trick_source/sim_services/VariableServer/VariableServer_copy_data_freeze.cpp +++ b/trick_source/sim_services/VariableServer/VariableServer_copy_data_freeze.cpp @@ -6,10 +6,10 @@ int Trick::VariableServer::copy_data_freeze() { - std::map < pthread_t , VariableServerThread * >::iterator it ; + std::map < pthread_t , VariableServerSession * >::iterator it ; pthread_mutex_lock(&map_mutex) ; - for ( it = var_server_threads.begin() ; it != var_server_threads.end() ; it++ ) { + for ( it = var_server_sessions.begin() ; it != var_server_sessions.end() ; it++ ) { (*it).second->copy_data_freeze() ; } pthread_mutex_unlock(&map_mutex) ; diff --git a/trick_source/sim_services/VariableServer/VariableServer_copy_data_freeze_scheduled.cpp b/trick_source/sim_services/VariableServer/VariableServer_copy_data_freeze_scheduled.cpp index d770e451..cd6ecf7d 100644 --- a/trick_source/sim_services/VariableServer/VariableServer_copy_data_freeze_scheduled.cpp +++ b/trick_source/sim_services/VariableServer/VariableServer_copy_data_freeze_scheduled.cpp @@ -8,17 +8,16 @@ int Trick::VariableServer::copy_data_freeze_scheduled() { long long next_call_tics ; - VariableServerThread * vst ; - std::map < pthread_t , VariableServerThread * >::iterator it ; + std::map < pthread_t , VariableServerSession * >::iterator it ; next_call_tics = TRICK_MAX_LONG_LONG ; pthread_mutex_lock(&map_mutex) ; - for ( it = var_server_threads.begin() ; it != var_server_threads.end() ; it++ ) { - vst = (*it).second ; - vst->copy_data_freeze_scheduled(copy_data_freeze_job->next_tics) ; - if ( vst->get_freeze_next_tics() < next_call_tics ) { - next_call_tics = vst->get_freeze_next_tics() ; + for ( it = var_server_sessions.begin() ; it != var_server_sessions.end() ; it++ ) { + VariableServerSession * session = (*it).second ; + session->copy_data_freeze_scheduled(copy_data_freeze_job->next_tics) ; + if ( session->get_freeze_next_tics() < next_call_tics ) { + next_call_tics = session->get_freeze_next_tics() ; } } pthread_mutex_unlock(&map_mutex) ; diff --git a/trick_source/sim_services/VariableServer/VariableServer_copy_data_scheduled.cpp b/trick_source/sim_services/VariableServer/VariableServer_copy_data_scheduled.cpp index 80f9d967..4ba077ea 100644 --- a/trick_source/sim_services/VariableServer/VariableServer_copy_data_scheduled.cpp +++ b/trick_source/sim_services/VariableServer/VariableServer_copy_data_scheduled.cpp @@ -8,17 +8,16 @@ int Trick::VariableServer::copy_data_scheduled() { long long next_call_tics ; - VariableServerThread * vst ; - std::map < pthread_t , VariableServerThread * >::iterator it ; + std::map < pthread_t , VariableServerSession * >::iterator it ; next_call_tics = TRICK_MAX_LONG_LONG ; pthread_mutex_lock(&map_mutex) ; - for ( it = var_server_threads.begin() ; it != var_server_threads.end() ; it++ ) { - vst = (*it).second ; - vst->copy_data_scheduled(copy_data_job->next_tics) ; - if ( vst->get_next_tics() < next_call_tics ) { - next_call_tics = vst->get_next_tics() ; + for ( it = var_server_sessions.begin() ; it != var_server_sessions.end() ; it++ ) { + auto session = (*it).second ; + session->copy_data_scheduled(copy_data_job->next_tics) ; + if ( session->get_next_tics() < next_call_tics ) { + next_call_tics = session->get_next_tics() ; } } pthread_mutex_unlock(&map_mutex) ; diff --git a/trick_source/sim_services/VariableServer/VariableServer_copy_data_top.cpp b/trick_source/sim_services/VariableServer/VariableServer_copy_data_top.cpp index 4c4c2623..3b4dad61 100644 --- a/trick_source/sim_services/VariableServer/VariableServer_copy_data_top.cpp +++ b/trick_source/sim_services/VariableServer/VariableServer_copy_data_top.cpp @@ -6,10 +6,10 @@ int Trick::VariableServer::copy_data_top() { - std::map < pthread_t , VariableServerThread * >::iterator it ; + std::map < pthread_t , VariableServerSession * >::iterator it ; pthread_mutex_lock(&map_mutex) ; - for ( it = var_server_threads.begin() ; it != var_server_threads.end() ; it++ ) { + for ( it = var_server_sessions.begin() ; it != var_server_sessions.end() ; it++ ) { (*it).second->copy_data_top() ; } pthread_mutex_unlock(&map_mutex) ; diff --git a/trick_source/sim_services/VariableServer/VariableServer_freeze_init.cpp b/trick_source/sim_services/VariableServer/VariableServer_freeze_init.cpp index 1a8f3e36..8f7bddce 100644 --- a/trick_source/sim_services/VariableServer/VariableServer_freeze_init.cpp +++ b/trick_source/sim_services/VariableServer/VariableServer_freeze_init.cpp @@ -10,17 +10,17 @@ int Trick::VariableServer::freeze_init() { long long next_call_tics ; - VariableServerThread * vst ; - std::map < pthread_t , VariableServerThread * >::iterator it ; + VariableServerSession * session ; + std::map < pthread_t , VariableServerSession * >::iterator it ; next_call_tics = TRICK_MAX_LONG_LONG ; pthread_mutex_lock(&map_mutex) ; - for ( it = var_server_threads.begin() ; it != var_server_threads.end() ; it++ ) { - vst = (*it).second ; - vst->freeze_init() ; - if ( vst->get_freeze_next_tics() < next_call_tics ) { - next_call_tics = vst->get_freeze_next_tics() ; + for ( it = var_server_sessions.begin() ; it != var_server_sessions.end() ; it++ ) { + session = (*it).second ; + session->freeze_init() ; + if ( session->get_freeze_next_tics() < next_call_tics ) { + next_call_tics = session->get_freeze_next_tics() ; } } pthread_mutex_unlock(&map_mutex) ; diff --git a/trick_source/sim_services/VariableServer/VariableServer_get_next_freeze_call_time.cpp b/trick_source/sim_services/VariableServer/VariableServer_get_next_freeze_call_time.cpp index 1fb12377..12c33189 100644 --- a/trick_source/sim_services/VariableServer/VariableServer_get_next_freeze_call_time.cpp +++ b/trick_source/sim_services/VariableServer/VariableServer_get_next_freeze_call_time.cpp @@ -6,18 +6,18 @@ int Trick::VariableServer::get_next_freeze_call_time() { - std::map < pthread_t , VariableServerThread * >::iterator it ; - VariableServerThread * vst ; + std::map < pthread_t , VariableServerSession * >::iterator it ; + VariableServerSession * session ; long long next_call_tics ; next_call_tics = TRICK_MAX_LONG_LONG ; pthread_mutex_lock(&map_mutex) ; - for ( it = var_server_threads.begin() ; it != var_server_threads.end() ; it++ ) { - vst = (*it).second ; - if ( vst->get_freeze_next_tics() < next_call_tics ) { - next_call_tics = vst->get_freeze_next_tics() ; + for ( it = var_server_sessions.begin() ; it != var_server_sessions.end() ; it++ ) { + session = (*it).second ; + if ( session->get_freeze_next_tics() < next_call_tics ) { + next_call_tics = session->get_freeze_next_tics() ; } } pthread_mutex_unlock(&map_mutex) ; diff --git a/trick_source/sim_services/VariableServer/VariableServer_get_next_sync_call_time.cpp b/trick_source/sim_services/VariableServer/VariableServer_get_next_sync_call_time.cpp index d728952d..e6d6d552 100644 --- a/trick_source/sim_services/VariableServer/VariableServer_get_next_sync_call_time.cpp +++ b/trick_source/sim_services/VariableServer/VariableServer_get_next_sync_call_time.cpp @@ -6,18 +6,18 @@ int Trick::VariableServer::get_next_sync_call_time() { - std::map < pthread_t , VariableServerThread * >::iterator it ; - VariableServerThread * vst ; + std::map < pthread_t , VariableServerSession * >::iterator it ; + VariableServerSession * session ; long long next_call_tics ; next_call_tics = TRICK_MAX_LONG_LONG ; pthread_mutex_lock(&map_mutex) ; - for ( it = var_server_threads.begin() ; it != var_server_threads.end() ; it++ ) { - vst = (*it).second ; - if ( vst->get_next_tics() < next_call_tics ) { - next_call_tics = vst->get_next_tics() ; + for ( it = var_server_sessions.begin() ; it != var_server_sessions.end() ; it++ ) { + session = (*it).second ; + if ( session->get_next_tics() < next_call_tics ) { + next_call_tics = session->get_next_tics() ; } } pthread_mutex_unlock(&map_mutex) ; diff --git a/trick_source/sim_services/VariableServer/VariableServer_get_var_server_port.cpp b/trick_source/sim_services/VariableServer/VariableServer_get_var_server_port.cpp index a3093af1..322bccc5 100644 --- a/trick_source/sim_services/VariableServer/VariableServer_get_var_server_port.cpp +++ b/trick_source/sim_services/VariableServer/VariableServer_get_var_server_port.cpp @@ -2,41 +2,42 @@ #include #include "trick/VariableServer.hh" + int Trick::VariableServer::create_tcp_socket(const char * address, unsigned short in_port ) { Trick::VariableServerListenThread * new_listen_thread = new Trick::VariableServerListenThread ; new_listen_thread->create_tcp_socket(address, in_port) ; new_listen_thread->copy_cpus(listen_thread.get_cpus()) ; new_listen_thread->create_thread() ; - additional_listen_threads[new_listen_thread->get_pthread_id()] = new_listen_thread ; + // additional_listen_threads[new_listen_thread->get_pthread_id()] = new_listen_thread ; return 0 ; } int Trick::VariableServer::create_udp_socket(const char * address, unsigned short in_port ) { - int ret ; - Trick::VariableServerThread * vst ; - vst = new Trick::VariableServerThread(NULL) ; - ret = vst->create_udp_socket(address, in_port) ; - if ( ret == 0 ) { - vst->copy_cpus(listen_thread.get_cpus()) ; - vst->create_thread() ; - } + // int ret ; + // Trick::VariableServerThread * vst ; + // vst = new Trick::VariableServerThread(NULL) ; + // ret = vst->create_udp_socket(address, in_port) ; + // if ( ret == 0 ) { + // vst->copy_cpus(listen_thread.get_cpus()) ; + // vst->create_thread() ; + // } //vst->var_debug(3) ; - return ret ; + return 0 ; } int Trick::VariableServer::create_multicast_socket(const char * mcast_address, const char * address, unsigned short in_port ) { - int ret ; - Trick::VariableServerThread * vst ; - vst = new Trick::VariableServerThread(NULL) ; - ret = vst->create_mcast_socket(mcast_address, address, in_port) ; - if ( ret == 0 ) { - vst->copy_cpus(listen_thread.get_cpus()) ; - vst->create_thread() ; - } + // int ret ; + // Trick::VariableServerThread * vst ; + // vst = new Trick::VariableServerThread(NULL) ; + // ret = vst->create_mcast_socket(mcast_address, address, in_port) ; + // if ( ret == 0 ) { + // vst->copy_cpus(listen_thread.get_cpus()) ; + // vst->create_thread() ; + // } //vst->var_debug(3) ; - return ret ; + return 0 ; } diff --git a/trick_source/sim_services/VariableServer/VariableServer_init.cpp b/trick_source/sim_services/VariableServer/VariableServer_init.cpp index 9a6bfa31..0b224b22 100644 --- a/trick_source/sim_services/VariableServer/VariableServer_init.cpp +++ b/trick_source/sim_services/VariableServer/VariableServer_init.cpp @@ -4,11 +4,9 @@ int Trick::VariableServer::init() { - int ret ; - /* start up a thread for the input processor variable server */ if ( enabled ) { - ret = listen_thread.check_and_move_listen_device() ; + int ret = listen_thread.check_and_move_listen_device() ; if ( ret != 0 ) { return ret ; } diff --git a/trick_source/sim_services/VariableServer/VariableServer_restart.cpp b/trick_source/sim_services/VariableServer/VariableServer_restart.cpp index 2dfae9fe..7bd8c0f8 100644 --- a/trick_source/sim_services/VariableServer/VariableServer_restart.cpp +++ b/trick_source/sim_services/VariableServer/VariableServer_restart.cpp @@ -9,10 +9,10 @@ int Trick::VariableServer::restart() { if ( listen_thread.get_pthread_id() == 0 ) { listen_thread.create_thread() ; } - std::map < pthread_t , VariableServerListenThread * >::iterator it ; - for( it = additional_listen_threads.begin() ; it != additional_listen_threads.end() ; it++ ) { - (*it).second->restart() ; - } + // std::map < pthread_t , VariableServerListenThread * >::iterator it ; + // for( it = additional_listen_threads.begin() ; it != additional_listen_threads.end() ; it++ ) { + // (*it).second->restart() ; + // } return 0 ; } diff --git a/trick_source/sim_services/VariableServer/VariableServer_shutdown.cpp b/trick_source/sim_services/VariableServer/VariableServer_shutdown.cpp index bb99db07..14bd7830 100644 --- a/trick_source/sim_services/VariableServer/VariableServer_shutdown.cpp +++ b/trick_source/sim_services/VariableServer/VariableServer_shutdown.cpp @@ -4,13 +4,19 @@ int Trick::VariableServer::shutdown() { listen_thread.cancel_thread() ; std::map < pthread_t , VariableServerThread * >::iterator it ; + pthread_mutex_lock(&map_mutex) ; + std::vector ids; for ( it = var_server_threads.begin() ; it != var_server_threads.end() ; it++ ) { (*it).second->cancel_thread() ; + ids.push_back((*it).first); // cancelling causes each var_server_thread map element to be erased by the exit_var_thread function } pthread_mutex_unlock(&map_mutex) ; + for (pthread_t id : ids) { + pthread_join(id, NULL); + } return 0 ; } diff --git a/trick_source/sim_services/VariableServer/exit_var_thread.cpp b/trick_source/sim_services/VariableServer/exit_var_thread.cpp index 95b30e82..e40996c6 100644 --- a/trick_source/sim_services/VariableServer/exit_var_thread.cpp +++ b/trick_source/sim_services/VariableServer/exit_var_thread.cpp @@ -6,8 +6,9 @@ void exit_var_thread(void *in_vst) { Trick::VariableServerThread * vst = (Trick::VariableServerThread *) in_vst ; Trick::VariableServer * vs = vst->get_vs() ; - tc_disconnect(&vst->get_connection()); + // tc_disconnect(&vst->get_connection()); + vs->delete_session(vst->get_pthread_id()); // Tell the variable server that this thread is exiting. vs->delete_vst(vst->get_pthread_id()) ; diff --git a/trick_source/sim_services/VariableServer/test/.gitignore b/trick_source/sim_services/VariableServer/test/.gitignore new file mode 100644 index 00000000..ea339cfd --- /dev/null +++ b/trick_source/sim_services/VariableServer/test/.gitignore @@ -0,0 +1,4 @@ +lcov_html/* +*.o +*_test +*.info \ No newline at end of file diff --git a/trick_source/sim_services/VariableServer/test/Makefile b/trick_source/sim_services/VariableServer/test/Makefile new file mode 100644 index 00000000..43d77b14 --- /dev/null +++ b/trick_source/sim_services/VariableServer/test/Makefile @@ -0,0 +1,87 @@ + +#SYNOPSIS: +# +# make [all] - makes everything. +# make TARGET - makes the given target. +# make clean - removes all files generated by make. + +include $(dir $(lastword $(MAKEFILE_LIST)))../../../../share/trick/makefiles/Makefile.common + +# Replace -isystem with -I so ICG doesn't skip Trick headers +TRICK_SYSTEM_CXXFLAGS := $(subst -isystem,-I,$(TRICK_SYSTEM_CXXFLAGS)) + +# Flags passed to the preprocessor. +TRICK_CXXFLAGS += -I$(GTEST_HOME)/include -I$(TRICK_HOME)/include -g -Wall -Wextra -Wno-sign-compare -std=c++11 ${TRICK_SYSTEM_CXXFLAGS} ${TRICK_TEST_FLAGS} +TRICK_LIBS = -L${TRICK_LIB_DIR} -ltrick_mm -ltrick_units -ltrick_comm -ltrick_pyip -ltrick -ltrick_mm -ltrick_units -ltrick_comm -ltrick_pyip -ltrick -ltrick_var_binary_parser -ltrick_connection_handlers -ltrick_comm +TRICK_EXEC_LINK_LIBS += -L${GTEST_HOME}/lib64 -L${GTEST_HOME}/lib -lgtest -lgtest_main -lpthread + +# All tests produced by this Makefile. Remember to add new tests you +# created to the list. + +VARIABLE_REFERENCE_TESTS = VariableReference_test \ + VariableReference_writeValueAscii_test \ + VariableReference_writeValueBinary_test + +VARIABLE_SESSION_TESTS = VariableServerSession_test + +TESTS = $(VARIABLE_REFERENCE_TESTS) $(VARIABLE_SESSION_TESTS) + +TEST_OBJS = $(addprefix $(OBJ_DIR)/, $(addsuffix .o, $(TESTS))) + +TO_ICG = VariableReference_test \ + TestConnection + +ICG_OBJS = $(addprefix $(OBJ_DIR)/io_, $(addsuffix .o, $(TO_ICG))) + +OBJ_DIR = obj + +print: + echo $(ICG_OBJS) + +# House-keeping build targets. + +all : test + +test: $(TESTS) + for TEST in $(TESTS) ; do \ + ./$$TEST --gtest_output=xml:${TRICK_HOME}/trick_test/$$TEST.xml ; \ + done + +$(OBJ_DIR): + mkdir $(OBJ_DIR) + +$(TEST_OBJS): $(OBJ_DIR)/%.o: %.cc $(OBJ_DIR) + $(TRICK_CXX) $(TRICK_CXXFLAGS) -c $< -o $@ -L${TRICK_HOME}/lib_${TRICK_HOST_CPU} $(TRICK_LIBS) $(TRICK_EXEC_LINK_LIBS) + +$(ICG_OBJS): $(OBJ_DIR)/io_%.o : %.hh $(OBJ_DIR) + ${TRICK_HOME}/bin/trick-ICG -sim_services -o ./io_src $(TRICK_CXXFLAGS) $< + $(TRICK_CXX) $(TRICK_CXXFLAGS) -c io_src/io_$*.cpp -o $@ -L${TRICK_HOME}/lib_${TRICK_HOST_CPU} $(TRICK_LIBS) $(TRICK_EXEC_LINK_LIBS) + +$(VARIABLE_REFERENCE_TESTS): %: $(OBJ_DIR)/%.o $(OBJ_DIR)/io_VariableReference_test.o + $(TRICK_CXX) $(TRICK_SYSTEM_LDFLAGS) -o $@ $^ -L${TRICK_HOME}/lib_${TRICK_HOST_CPU} $(TRICK_LIBS) $(TRICK_EXEC_LINK_LIBS) + +$(VARIABLE_SESSION_TESTS): %: $(OBJ_DIR)/%.o $(OBJ_DIR)/io_TestConnection.o + $(TRICK_CXX) $(TRICK_SYSTEM_LDFLAGS) -o $@ $^ -L${TRICK_HOME}/lib_${TRICK_HOST_CPU} $(TRICK_LIBS) $(TRICK_EXEC_LINK_LIBS) + +code-coverage: test + # Give rid of any old code-coverage HTML we may have. + rm -rf lcov_html + # Gather coverage information about the src code. + lcov --capture \ + --directory ../object_${TRICK_HOST_CPU} \ + --base-directory ../ \ + --output-file src_coverage.info + # Filter out information about directories that we don't care about. + lcov --remove src_coverage.info '/Applications/*' '/usr/include/*' '/Library/*' \ + --output-file VariableServer_code_coverage.info + # Generate HTML + genhtml VariableServer_code_coverage.info \ + --output-directory lcov_html + # Clean up + # rm *.info + lcov --list VariableServer_code_coverage.info + +clean : + rm -f $(TESTS) + rm -f *.gcno *.gcda + rm -rf io_src xml obj \ No newline at end of file diff --git a/trick_source/sim_services/VariableServer/test/TestConnection.hh b/trick_source/sim_services/VariableServer/test/TestConnection.hh new file mode 100644 index 00000000..0372dac4 --- /dev/null +++ b/trick_source/sim_services/VariableServer/test/TestConnection.hh @@ -0,0 +1,80 @@ +#ifndef TEST_CONNECTION_HH +#define TEST_CONNECTION_HH + +#include "trick/ClientConnection.hh" +#include +#include +#include +#include + +class TestConnection : public Trick::ClientConnection { + public: + ~TestConnection () { + for (char * message : binary_messages_written) { + free (message); + } + } + + int initialize() { + valid = true; + } + + int write (const std::string& message) { + if (!valid) + return -1; + + ascii_messages_written.emplace_back(message); + return 0; + } + + int write (char * message, int size) { + if (!valid) + return -1; + + char * msg_copy = (char *) malloc(size+1); + memcpy(msg_copy, message, size+1); + binary_messages_written.push_back(msg_copy); + + return 0; + } + + std::string read (int max_len = MAX_CMD_LEN) { + if (queued_messages.empty()) { + return ""; + } + + std::string ret = queued_messages.front(); + queued_messages.pop(); + return ret; + } + + int disconnect () { + valid = false; + return 0; + } + + std::string get_client_tag () { + return client_tag; + } + + int set_client_tag(std::string tag) { + client_tag = tag; + } + + int setBlockMode (int mode) { + return 0; + } + + + std::queue queued_messages; + std::vector ascii_messages_written; + std::vector binary_messages_written; + + + std::string client_tag; + bool valid = true; + +}; + + +#endif \ No newline at end of file diff --git a/trick_source/sim_services/VariableServer/test/VariableReference_test.cc b/trick_source/sim_services/VariableServer/test/VariableReference_test.cc new file mode 100644 index 00000000..6ff68a5f --- /dev/null +++ b/trick_source/sim_services/VariableServer/test/VariableReference_test.cc @@ -0,0 +1,512 @@ +#include "VariableReference_test.hh" + +TEST_F(VariableReference_test, getName) { + // ARRANGE + // Create a variable to make a reference for + int test_int = 5; + (void) memmgr->declare_extern_var(&test_int, "int test_int"); + Trick::VariableReference ref("test_int"); + + // ACT + // ASSERT + EXPECT_EQ(strcmp(ref.getName(), "test_int"), 0); +} + +TEST_F(VariableReference_test, validateAddress) { + // ARRANGE + // Create a variable to make a reference for + int test_a = 5; + (void) memmgr->declare_extern_var(&test_a, "int test_a"); + Trick::VariableReference ref("test_a"); + + float test_b = 5.0; + (void) memmgr->declare_extern_var(&test_b, "float test_b"); + Trick::VariableReference ref_broken("test_b"); + memmgr->delete_var("test_b"); + + float test_c = 5.0; + (void) memmgr->declare_extern_var(&test_c, "float test_c"); + Trick::VariableReference ref_tagged("test_c"); + ref_tagged.tagAsInvalid(); + + // ACT + // ASSERT + EXPECT_EQ(ref.validate(), true); + EXPECT_EQ(ref_broken.validate(), false); + // A reference already tagged as invalid is considered ok by this check + EXPECT_EQ(ref_tagged.validate(), true); +} + + +TEST_F(VariableReference_test, stageValue_set) { + // ARRANGE + // Create a variable to make a reference for + int test_a = 5; + (void) memmgr->declare_extern_var(&test_a, "int test_a"); + Trick::VariableReference ref("test_a"); + + // ACT + ref.stageValue(); + + // ASSERT + EXPECT_EQ(ref.isStaged(), true); + EXPECT_EQ(ref.isWriteReady(), false); +} + +TEST_F(VariableReference_test, prepareForWrite_set) { + // ARRANGE + // Create a variable to make a reference for + int test_a = 5; + (void) memmgr->declare_extern_var(&test_a, "int test_a"); + Trick::VariableReference ref("test_a"); + + // ACT + ref.stageValue(); + ref.prepareForWrite(); + + // ASSERT + EXPECT_EQ(ref.isStaged(), false); + EXPECT_EQ(ref.isWriteReady(), true); +} + +TEST_F(VariableReference_test, prepareForWrite_fails_if_not_staged) { + // ARRANGE + // Create a variable to make a reference for + int test_a = 5; + (void) memmgr->declare_extern_var(&test_a, "int test_a"); + Trick::VariableReference ref("test_a"); + + // ACT + ref.prepareForWrite(); + + // ASSERT + EXPECT_EQ(ref.isStaged(), false); + EXPECT_EQ(ref.isWriteReady(), false); +} + +TEST_F(VariableReference_test, writeValueAscii_fails_if_not_write_ready) { + // ARRANGE + // Create a variable to make a reference for + int test_a = 5; + (void) memmgr->declare_extern_var(&test_a, "int test_a"); + Trick::VariableReference ref("test_a"); + std::stringstream ss; + + // ACT + // ASSERT + EXPECT_EQ(ref.writeValueAscii(ss), -1); +} + +TEST_F(VariableReference_test, var_does_not_exist) { + // ARRANGE + Trick::VariableReference ref("no_such_var"); + std::stringstream ss; + + // ACT + ref.stageValue(); + ref.prepareForWrite(); + ref.writeValueAscii(ss); + + // ASSERT + EXPECT_EQ(ref.getType(), TRICK_NUMBER_OF_TYPES); + EXPECT_EQ(ss.str(), "BAD_REF"); +} + +TEST_F(VariableReference_test, stl_var) { + // ARRANGE + TestObject my_test; + my_test.vec.push_back(5); + (void) memmgr->declare_extern_var(&my_test, "TestObject my_test"); + + Trick::VariableReference ref("my_test.vec"); + std::stringstream ss; + + // ACT + ref.stageValue(); + ref.prepareForWrite(); + ref.writeValueAscii(ss); + + // ASSERT + EXPECT_EQ(ref.isWriteReady(), true); + EXPECT_EQ(ref.getType(), TRICK_NUMBER_OF_TYPES); + EXPECT_EQ(ss.str(), "BAD_REF"); +} + +TEST_F(VariableReference_test, structured_var) { + // ARRANGE + TestObject my_test; + my_test.obj.a = 5; + (void) memmgr->declare_extern_var(&my_test, "TestObject my_test"); + + Trick::VariableReference ref("my_test.obj"); + std::stringstream ss; + + // ACT + ref.stageValue(); + ref.prepareForWrite(); + ref.writeValueAscii(ss); + + // ASSERT + EXPECT_EQ(ref.isWriteReady(), true); + EXPECT_EQ(ref.getType(), TRICK_NUMBER_OF_TYPES); + EXPECT_EQ(ss.str(), "BAD_REF"); +} + +TEST_F(VariableReference_test, printWithoutUnits) { + // ARRANGE + // Create a variable to make a reference for + TestObject obj; + obj.length = 5000; + (void) memmgr->declare_extern_var(&obj, "TestObject obj"); + Trick::VariableReference ref("obj.length"); + std::stringstream ss; + + // ACT + EXPECT_STREQ(ref.getBaseUnits(), "m"); + + // ASSERT + // Doesn't actually print with units unless set + ref.stageValue(); + ref.prepareForWrite(); + ref.writeValueAscii(ss); + EXPECT_EQ(ss.str(), "5000"); +} + +TEST_F(VariableReference_test, setUnits) { + // ARRANGE + // Create a variable to make a reference for + TestObject obj; + obj.length = 5000; + (void) memmgr->declare_extern_var(&obj, "TestObject obj"); + Trick::VariableReference ref("obj.length"); + std::stringstream ss; + + // ACT + ref.setRequestedUnits("km"); + + // ASSERT + ref.stageValue(); + ref.prepareForWrite(); + ref.writeValueAscii(ss); + EXPECT_EQ(ss.str(), "5 {km}"); +} + +TEST_F(VariableReference_test, setUnitsTwice) { + // ARRANGE + // Create a variable to make a reference for + TestObject obj; + obj.length = 5000; + (void) memmgr->declare_extern_var(&obj, "TestObject obj"); + Trick::VariableReference ref("obj.length"); + std::stringstream ss; + + // ACT + ref.setRequestedUnits("km"); + + // ASSERT + ref.stageValue(); + ref.prepareForWrite(); + ref.writeValueAscii(ss); + EXPECT_EQ(ss.str(), "5 {km}"); + ss.str(""); + + // ACT + ref.setRequestedUnits("mm"); + + // ASSERT + ref.stageValue(); + ref.prepareForWrite(); + ref.writeValueAscii(ss); + EXPECT_EQ(ss.str(), "5000000 {mm}"); +} + + +TEST_F(VariableReference_test, setUnitsBadFromUnits) { + // ARRANGE + // Create a variable to make a reference for + TestObject obj; + obj.error_units = 50; + (void) memmgr->declare_extern_var(&obj, "TestObject obj"); + Trick::VariableReference ref("obj.error_units"); + std::stringstream ss; + + // ACT + ref.setRequestedUnits("mm"); + + // ASSERT + ref.stageValue(); + ref.prepareForWrite(); + ref.writeValueAscii(ss); + EXPECT_EQ(ss.str(), "50"); +} + +TEST_F(VariableReference_test, setUnitsBadToUnits) { + // ARRANGE + // Create a variable to make a reference for + TestObject obj; + obj.a = 0.5; + (void) memmgr->declare_extern_var(&obj, "TestObject obj"); + Trick::VariableReference ref("obj.a"); + std::stringstream ss; + + // ACT + ref.setRequestedUnits("asldfjks"); + + // ASSERT + ref.stageValue(); + ref.prepareForWrite(); + ref.writeValueAscii(ss); + EXPECT_EQ(ss.str(), "0.5"); +} + +TEST_F(VariableReference_test, setUnitsDouble) { + // ARRANGE + // Create a variable to make a reference for + TestObject obj; + obj.a = 0.5; + (void) memmgr->declare_extern_var(&obj, "TestObject obj"); + Trick::VariableReference ref("obj.a"); + std::stringstream ss; + + // ACT + ref.setRequestedUnits("ms"); + + // ASSERT + ref.stageValue(); + ref.prepareForWrite(); + ref.writeValueAscii(ss); + EXPECT_EQ(ss.str(), "500 {ms}"); +} + +TEST_F(VariableReference_test, setUnitsLong) { + // ARRANGE + // Create a variable to make a reference for + TestObject obj; + obj.b = 1; + (void) memmgr->declare_extern_var(&obj, "TestObject obj"); + Trick::VariableReference ref("obj.b"); + std::stringstream ss; + + // ACT + ref.setRequestedUnits("m"); + + // ASSERT + ref.stageValue(); + ref.prepareForWrite(); + ref.writeValueAscii(ss); + EXPECT_EQ(ss.str(), "1852 {m}"); +} + +TEST_F(VariableReference_test, setUnitsLongLong) { + // ARRANGE + // Create a variable to make a reference for + TestObject obj; + obj.c = 10000000; + (void) memmgr->declare_extern_var(&obj, "TestObject obj"); + Trick::VariableReference ref("obj.c"); + std::stringstream ss; + + // ACT + ref.setRequestedUnits("m"); + + // ASSERT + ref.stageValue(); + ref.prepareForWrite(); + ref.writeValueAscii(ss); + EXPECT_EQ(ss.str(), "254000 {m}"); +} + +TEST_F(VariableReference_test, setUnitsUnsignedLong) { + // ARRANGE + // Create a variable to make a reference for + TestObject obj; + obj.d = 1; + (void) memmgr->declare_extern_var(&obj, "TestObject obj"); + Trick::VariableReference ref("obj.d"); + std::stringstream ss; + + // ACT + ref.setRequestedUnits("mi"); + + // ASSERT + ref.stageValue(); + ref.prepareForWrite(); + ref.writeValueAscii(ss); + EXPECT_EQ(ss.str(), "5878625079535 {mi}"); +} + +TEST_F(VariableReference_test, setUnitsUnsignedLongLong) { + // ARRANGE + // Create a variable to make a reference for + TestObject obj; + obj.e = 1; + (void) memmgr->declare_extern_var(&obj, "TestObject obj"); + Trick::VariableReference ref("obj.e"); + std::stringstream ss; + + // ACT + ref.setRequestedUnits("mm"); + + // ASSERT + ref.stageValue(); + ref.prepareForWrite(); + ref.writeValueAscii(ss); + EXPECT_EQ(ss.str(), "1609344 {mm}"); +} + +// Byteswap tests + +TEST_F(VariableReference_test, byteswap_chars) { + // ARRANGE + char in = 'a'; + char out; + + memmgr->declare_extern_var(&in, "char a"); + Trick::VariableReference ref("a"); + + // ACT + Trick::VariableReference::byteswap_var(&out, &in, ref); + + // ASSERT + EXPECT_EQ(in, 'a'); + EXPECT_EQ(out, 'a'); +} + +TEST_F(VariableReference_test, byteswap_char_array) { + // ARRANGE + char in[7] = "Jackie"; + char out[7]; + + memmgr->declare_extern_var(&in, "char a[7]"); + Trick::VariableReference ref("a"); + + // ACT + Trick::VariableReference::byteswap_var(out, in, ref); + + // ASSERT + for (int i = 0; i < 7; i++) { + EXPECT_EQ(out[i], in[i]); + } +} + +// Pointers to the beginning of the variables +bool check_that_val_is_byteswapped (char * expected, char * byteswap, int val_size) { + for (int i = 0; i < val_size; i++) { + if (expected[i] != byteswap[val_size-i-1]) return false; + } + return true; +} + +TEST_F(VariableReference_test, byteswap_short) { + // ARRANGE + short in = 100; + short out; + + memmgr->declare_extern_var(&in, "short a"); + Trick::VariableReference ref("a"); + + // ACT + Trick::VariableReference::byteswap_var((char *)(&out),(char *)(&in), ref); + + // ASSERT + EXPECT_TRUE(check_that_val_is_byteswapped((char *)(&out),(char *)(&in), sizeof(short))); +} + +TEST_F(VariableReference_test, byteswap_int) { + // ARRANGE + int in = 123456; + int out; + + memmgr->declare_extern_var(&in, "int a"); + Trick::VariableReference ref("a"); + + // ACT + Trick::VariableReference::byteswap_var((char *)(&out),(char *)(&in), ref); + + // ASSERT + EXPECT_TRUE(check_that_val_is_byteswapped((char *)(&out),(char *)(&in), sizeof(int))); +} + +TEST_F(VariableReference_test, byteswap_long) { + // ARRANGE + long in = 123456789; + long out; + + memmgr->declare_extern_var(&in, "long a"); + Trick::VariableReference ref("a"); + + // ACT + Trick::VariableReference::byteswap_var((char *)(&out),(char *)(&in), ref); + + // ASSERT + EXPECT_TRUE(check_that_val_is_byteswapped((char *)(&out),(char *)(&in), sizeof(long))); +} + +TEST_F(VariableReference_test, byteswap_long_arr) { + // ARRANGE + long in[5] = {123456789, 123456780, __LONG_MAX__, -100000000, 0}; + long out[5]; + + memmgr->declare_extern_var(&in, "long a[5]"); + Trick::VariableReference ref("a"); + + // ACT + Trick::VariableReference::byteswap_var((char *)(out),(char *)(in), ref); + + // ASSERT + for (int i = 0; i < 5; i++) { + EXPECT_TRUE(check_that_val_is_byteswapped((char *)(&out[i]),(char *)(&in[i]), sizeof(long))); + } +} + +TEST_F(VariableReference_test, byteswap_int_arr) { + // ARRANGE + int in[5] = {20945, -29384293, INT32_MAX, INT32_MIN, 0}; + int out[5]; + + memmgr->declare_extern_var(&in, "int a[5]"); + Trick::VariableReference ref("a"); + + // ACT + Trick::VariableReference::byteswap_var((char *)(out),(char *)(in), ref); + + // ASSERT + for (int i = 0; i < 5; i++) { + EXPECT_TRUE(check_that_val_is_byteswapped((char *)(&out[i]),(char *)(&in[i]), sizeof(int))); + } +} + +TEST_F(VariableReference_test, byteswap_int_multidimensional_arr) { + // ARRANGE + int multidim_arr[5][4][3][2]; + int out[5][4][3][2]; + + + int counter = 500; + for (int i = 0; i < 5; i++) { + for (int j = 0; j < 4; j++) { + for (int k = 0; k < 3; k++) { + for (int l = 0; l < 2; l++) { + multidim_arr[i][j][k][l] = counter++; + } + } + } + } + + memmgr->declare_extern_var(&multidim_arr, "int multidim_arr[5][4][3][2]"); + Trick::VariableReference ref("multidim_arr"); + + // ACT + Trick::VariableReference::byteswap_var((char *)(out),(char *)(multidim_arr), ref); + + // ASSERT + for (int i = 0; i < 5; i++) { + for (int j = 0; j < 4; j++) { + for (int k = 0; k < 3; k++) { + for (int l = 0; l < 2; l++) { + EXPECT_TRUE(check_that_val_is_byteswapped((char *)(&(out[i][j][k][l])),(char *)(&(multidim_arr[i][j][k][l])), sizeof(int))); + } + } + } + } +} \ No newline at end of file diff --git a/trick_source/sim_services/VariableServer/test/VariableReference_test.hh b/trick_source/sim_services/VariableServer/test/VariableReference_test.hh new file mode 100644 index 00000000..ac532bc8 --- /dev/null +++ b/trick_source/sim_services/VariableServer/test/VariableReference_test.hh @@ -0,0 +1,56 @@ +/******************************TRICK HEADER************************************* +PURPOSE: ( Common definitions for testing the VariableReference class ) +*******************************************************************************/ + +#include +#include +#include +#include +#include + +#include "trick/MemoryManager.hh" +#include "trick/VariableReference.hh" +#include "trick/UdUnits.hh" + +#include + +class NestedObject { + public: + int a; + int b; +}; + +class TestObject { + public: + TestObject() {} + + int length; /* m xy-position */ + double a; /* s time */ + long b; /* nautical_mile miles */ + long long c; /* in inches */ + unsigned long d; /* light_year miles */ + unsigned long long e; /* mi miles */ + int error_units; /* asvdsfkj fake units */ + wchar_t * wchar_str; + std::vector vec; + + NestedObject obj; +}; + +/* + Test Fixture. + */ +class VariableReference_test : public ::testing::Test { + protected: + Trick::MemoryManager *memmgr; + Trick::UdUnits * udunits; + VariableReference_test() { + memmgr = new Trick::MemoryManager; + udunits = new Trick::UdUnits; + + udunits->read_default_xml(); + } + ~VariableReference_test() { delete memmgr; } + void SetUp() {} + void TearDown() {} +}; \ No newline at end of file diff --git a/trick_source/sim_services/VariableServer/test/VariableReference_writeValueAscii_test.cc b/trick_source/sim_services/VariableServer/test/VariableReference_writeValueAscii_test.cc new file mode 100644 index 00000000..dd3a7fba --- /dev/null +++ b/trick_source/sim_services/VariableServer/test/VariableReference_writeValueAscii_test.cc @@ -0,0 +1,252 @@ +#include "VariableReference_test.hh" + + +TEST_F(VariableReference_test, writeValueAscii_int) { + // ARRANGE + // Create a variable to make a reference for + int test_a = 5; + (void) memmgr->declare_extern_var(&test_a, "int test_a"); + Trick::VariableReference ref("test_a"); + std::stringstream ss; + + // ACT + ref.stageValue(); + ref.prepareForWrite(); + ref.writeValueAscii(ss); + + // ASSERT + EXPECT_EQ(ss.str(), "5"); +} + +TEST_F(VariableReference_test, writeValueAscii_int_arr) { + // ARRANGE + // Create a variable to make a reference for + int test_a[5] = {1, 2, 3, 4, 5}; + (void) memmgr->declare_extern_var(&test_a, "int test_a[5]"); + Trick::VariableReference ref("test_a"); + std::stringstream ss; + + // ACT + ref.stageValue(); + ref.prepareForWrite(); + ref.writeValueAscii(ss); + + // ASSERT + EXPECT_EQ(ss.str(), "1,2,3,4,5"); +} + +TEST_F(VariableReference_test, writeValueAscii_double) { + // ARRANGE + // Create a variable to make a reference for + double test_a = 867.309; + (void) memmgr->declare_extern_var(&test_a, "double test_a"); + Trick::VariableReference ref_a("test_a"); + std::stringstream ss_a; + + double test_b = std::numeric_limits::max(); + (void) memmgr->declare_extern_var(&test_b, "double test_b"); + Trick::VariableReference ref_b("test_b"); + std::stringstream ss_b; + + double test_c = std::numeric_limits::min(); + (void) memmgr->declare_extern_var(&test_c, "double test_c"); + Trick::VariableReference ref_c("test_c"); + std::stringstream ss_c; + + // ACT + ref_a.stageValue(); + ref_a.prepareForWrite(); + ref_a.writeValueAscii(ss_a); + + ref_b.stageValue(); + ref_b.prepareForWrite(); + ref_b.writeValueAscii(ss_b); + + ref_c.stageValue(); + ref_c.prepareForWrite(); + ref_c.writeValueAscii(ss_c); + + // ASSERT + EXPECT_EQ(ss_a.str(), "867.309"); + EXPECT_EQ(ss_b.str(), "1.797693134862316e+308"); + EXPECT_EQ(ss_c.str(), "2.225073858507201e-308"); +} + +TEST_F(VariableReference_test, writeValueAscii_char) { + // ARRANGE + // Create a variable to make a reference for + char test_a = 'j'; + (void) memmgr->declare_extern_var(&test_a, "char test_a"); + Trick::VariableReference ref_a("test_a"); + std::stringstream ssa; + + char test_b[7] = "jackie"; + (void) memmgr->declare_extern_var(&test_b, "char test_b[7]"); + Trick::VariableReference ref_b("test_b"); + std::stringstream ssb; + + // ACT + ref_a.stageValue(); + ref_b.stageValue(); + + ref_a.prepareForWrite(); + ref_b.prepareForWrite(); + + ref_a.writeValueAscii(ssa); + ref_b.writeValueAscii(ssb); + + + // ASSERT + EXPECT_EQ(ssa.str(), "106"); + EXPECT_EQ(ssb.str(), "jackie"); +} + + +TEST_F(VariableReference_test, writeValueAscii_unsigned_char) { + // ARRANGE + // Create a variable to make a reference for + unsigned char test_a = 'j'; + (void) memmgr->declare_extern_var(&test_a, "unsigned char test_a"); + Trick::VariableReference ref_a("test_a"); + std::stringstream ssa; + + unsigned char test_b[8] = "jackie\n"; + (void) memmgr->declare_extern_var(&test_b, "unsigned char test_b[8]"); + Trick::VariableReference ref_b("test_b"); + std::stringstream ssb; + + // ACT + ref_a.stageValue(); + ref_b.stageValue(); + + ref_a.prepareForWrite(); + ref_b.prepareForWrite(); + + ref_a.writeValueAscii(ssa); + ref_b.writeValueAscii(ssb); + + // ASSERT + EXPECT_EQ(ssa.str(), "106"); + EXPECT_EQ(ssb.str(), "jackie\\n"); +} + + +TEST_F(VariableReference_test, writeValueAscii_wide_char) { + // ARRANGE + // Create a variable to make a reference for + wchar_t test_a = L'J'; + (void) memmgr->declare_extern_var(&test_a, "wchar_t test_a"); + Trick::VariableReference ref_a("test_a"); + std::stringstream ssa; + + wchar_t test_b[15] = L"jackiebutwider"; + (void) memmgr->declare_extern_var(&test_b, "wchar_t test_b[15]"); + Trick::VariableReference ref_b("test_b"); + std::stringstream ssb; + + // ACT + ref_a.stageValue(); + ref_b.stageValue(); + + ref_a.prepareForWrite(); + ref_b.prepareForWrite(); + + ref_a.writeValueAscii(ssa); + ref_b.writeValueAscii(ssb); + + // ASSERT + // Original variable server behavior prints individual wchar as its ascii value + EXPECT_EQ(ssa.str(), "74"); + EXPECT_EQ(ssb.str(), "jackiebutwider"); +} + +TEST_F(VariableReference_test, writeValueAscii_wide_char_unconstrained) { + TestObject obj; + obj.wchar_str = (wchar_t *) malloc (sizeof(wchar_t) * 7); + for (int i = 0; i < 6; i++) { + obj.wchar_str[i] = L'j'; + } + obj.wchar_str[6] = L'\0'; + (void) memmgr->declare_extern_var(&obj, "TestObject obj"); + // (void) memmgr->declare_extern_var(&obj.wchar_str, "wchar_t * obj.wchar_str"); + + Trick::VariableReference ref("obj.wchar_str"); + std::stringstream ss; + + // ACT + ref.stageValue(); + ref.prepareForWrite(); + ref.writeValueAscii(ss); + + // ASSERT + EXPECT_EQ(ss.str(), "jjjjjj"); + +} + +TEST_F(VariableReference_test, writeValueAscii_std_string) { + // ARRANGE + // Create a variable to make a reference for + std::string test_a = "jackiebutstringy"; + (void) memmgr->declare_extern_var(&test_a, "std::string test_a"); + Trick::VariableReference ref("test_a"); + std::stringstream ss; + + // ACT + ref.stageValue(); + ref.prepareForWrite(); + ref.writeValueAscii(ss); + + // ASSERT + EXPECT_EQ(ss.str(), "jackiebutstringy"); +} + +TEST_F(VariableReference_test, writeValueAscii_escape_characters) { + // ARRANGE + // Create a variable to make a reference for + std::string test_a = "\n\t\b\a\"\f\r\v"; + (void) memmgr->declare_extern_var(&test_a, "std::string test_a"); + Trick::VariableReference ref("test_a"); + std::stringstream ss; + + // ACT + ref.stageValue(); + ref.prepareForWrite(); + ref.writeValueAscii(ss); + + // ASSERT + EXPECT_EQ(ss.str(), "\\n\\t\\b\\a\"\\f\\n\\v"); +} + +TEST_F(VariableReference_test, writeValueAscii_boolean) { + // ARRANGE + // Create a variable to make a reference for + bool test_a = true; + (void) memmgr->declare_extern_var(&test_a, "bool test_a"); + Trick::VariableReference ref("test_a"); + std::stringstream ss; + + // ACT + ref.stageValue(); + ref.prepareForWrite(); + ref.writeValueAscii(ss); + + // ASSERT + EXPECT_EQ(ss.str(), "1"); +} + +TEST_F(VariableReference_test, writeValueAscii_short) { + // ARRANGE + // Create a variable to make a reference for + short test_a = 255; + (void) memmgr->declare_extern_var(&test_a, "short test_a"); + Trick::VariableReference ref("test_a"); + std::stringstream ss; + + // ACT + ref.stageValue(); + ref.prepareForWrite(); + ref.writeValueAscii(ss); + + // ASSERT + EXPECT_EQ(ss.str(), "255"); +} \ No newline at end of file diff --git a/trick_source/sim_services/VariableServer/test/VariableReference_writeValueBinary_test.cc b/trick_source/sim_services/VariableServer/test/VariableReference_writeValueBinary_test.cc new file mode 100644 index 00000000..7f4ba5a9 --- /dev/null +++ b/trick_source/sim_services/VariableServer/test/VariableReference_writeValueBinary_test.cc @@ -0,0 +1,177 @@ +#include "VariableReference_test.hh" + + +TEST_F(VariableReference_test, writeValueBinary_int) { + // ARRANGE + // Create a variable to make a reference for + int test_a = 4095; + (void) memmgr->declare_extern_var(&test_a, "int test_a"); + Trick::VariableReference ref("test_a"); + std::stringstream ss; + + // ACT + ref.stageValue(); + ref.prepareForWrite(); + ref.writeValueBinary(ss); + + + unsigned char expected_bytes[4] = {0xFF, 0x0F, 0x00, 0x00}; + char * actual_bytes = (char *) malloc (sizeof(int)); + + ss.read(actual_bytes, 4); + + // ASSERT + for (int i = 0; i < 4; i++) { + EXPECT_EQ(static_cast(actual_bytes[i]), expected_bytes[i]); + } +} + +TEST_F(VariableReference_test, writeValueBinary_float) { + // ARRANGE + // Create a variable to make a reference for + float test_a = 40.95; + (void) memmgr->declare_extern_var(&test_a, "float test_a"); + Trick::VariableReference ref("test_a"); + std::stringstream ss; + + // ACT + ref.stageValue(); + ref.prepareForWrite(); + ref.writeValueBinary(ss); + + unsigned char expected_bytes[4] = {0xcd, 0xcc, 0x23, 0x42}; + + char * actual_bytes = (char *) malloc (sizeof(float)); + + ss.read(actual_bytes, 4); + + // ASSERT + for (int i = 0; i < 4; i++) { + EXPECT_EQ(static_cast(actual_bytes[i]), expected_bytes[i]); + } +} + +TEST_F(VariableReference_test, writeValueBinary_int_arr) { + // ARRANGE + // Create a variable to make a reference for + int test_a[3] = {1, 2, 3}; + (void) memmgr->declare_extern_var(&test_a, "int test_a[3]"); + Trick::VariableReference ref("test_a"); + std::stringstream ss; + + // ACT + ref.stageValue(); + ref.prepareForWrite(); + ref.writeValueBinary(ss); + + // ASSERT + char * actual_bytes = (char *) malloc (sizeof(int )* 3); + ss.read(actual_bytes, sizeof(int) * 3); + unsigned char expected_bytes[12] = {0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00}; + + + // ASSERT + for (int i = 0; i < 12; i++) { + EXPECT_EQ(static_cast(actual_bytes[i]), expected_bytes[i]); + } +} + + +TEST_F(VariableReference_test, writeValueBinary_double_arr) { + // ARRANGE + // Create a variable to make a reference for + double test_a[3] = {1.0, 10.0, 100.0}; + (void) memmgr->declare_extern_var(&test_a, "double test_a[3]"); + Trick::VariableReference ref("test_a"); + std::stringstream ss; + + // ACT + ref.stageValue(); + ref.prepareForWrite(); + ref.writeValueBinary(ss); + + // ASSERT + char * actual_bytes = (char *) malloc (sizeof(double )* 3); + ss.read(actual_bytes, sizeof(double) * 3); + unsigned char expected_bytes[24] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0x40}; + + // ASSERT + for (int i = 0; i < 12; i++) { + EXPECT_EQ(static_cast(actual_bytes[i]), expected_bytes[i]); + } +} + + +TEST_F(VariableReference_test, writeValueBinary_string) { + // ARRANGE + // Create a variable to make a reference for + std::string test_a = "abcdef"; + (void) memmgr->declare_extern_var(&test_a, "std::string test_a"); + Trick::VariableReference ref("test_a"); + std::stringstream ss; + + // ACT + ref.stageValue(); + ref.prepareForWrite(); + ref.writeValueBinary(ss); + + // ASSERT + char * actual_bytes = (char *) malloc (test_a.length()); + ss.read(actual_bytes, test_a.length()); + unsigned char expected_bytes[6] = {0x61, 0x62, 0x63, 0x64, 0x65, 0x66}; + + // ASSERT + for (int i = 0; i < test_a.length(); i++) { + EXPECT_EQ(static_cast(actual_bytes[i]), expected_bytes[i]); + } +} + +TEST_F(VariableReference_test, writeNameBinary) { + // ARRANGE + // Create a variable to make a reference for + std::string test_a = "abcdef"; + (void) memmgr->declare_extern_var(&test_a, "std::string test_a"); + Trick::VariableReference ref("test_a"); + std::stringstream ss; + + // ACT + ref.stageValue(); + ref.prepareForWrite(); + ref.writeNameBinary(ss); + + // ASSERT + char * actual_bytes = (char *) malloc (sizeof(int) + strlen(ref.getName())); + ss.read(actual_bytes, sizeof(int) + 6); + unsigned char expected_bytes[sizeof(int) + 6] = {0x06, 0x00, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x61}; + + // ASSERT + for (int i = 0; i < sizeof(int) + strlen(ref.getName()); i++) { + EXPECT_EQ(static_cast(actual_bytes[i]), expected_bytes[i]); + } +} + + +TEST_F(VariableReference_test, writeValueBinaryByteswap_int) { + // ARRANGE + // Create a variable to make a reference for + int test_a = 4095; + (void) memmgr->declare_extern_var(&test_a, "int test_a"); + Trick::VariableReference ref("test_a"); + std::stringstream ss; + + // ACT + ref.stageValue(); + ref.prepareForWrite(); + ref.writeValueBinary(ss, true); + + + unsigned char expected_bytes[4] = {0x00, 0x00, 0x0F, 0xFF}; + char * actual_bytes = (char *) malloc (sizeof(int)); + + ss.read(actual_bytes, 4); + + // ASSERT + for (int i = 0; i < 4; i++) { + EXPECT_EQ(static_cast(actual_bytes[i]), expected_bytes[i]); + } +} \ No newline at end of file diff --git a/trick_source/sim_services/VariableServer/test/VariableServerSession_test.cc b/trick_source/sim_services/VariableServer/test/VariableServerSession_test.cc new file mode 100644 index 00000000..66069a16 --- /dev/null +++ b/trick_source/sim_services/VariableServer/test/VariableServerSession_test.cc @@ -0,0 +1,190 @@ +/******************************TRICK HEADER************************************* +PURPOSE: ( Tests for the VariableServerSession class ) +*******************************************************************************/ + +#include +#include +#include +#include +#include + +#include "trick/MemoryManager.hh" +#include "trick/UdUnits.hh" + +#include "TestConnection.hh" +#include "trick/VariableServerSession.hh" +#include "trick/var_binary_parser.hh" + + +/* + Test Fixture. + */ +class VariableServerSession_test : public ::testing::Test { + protected: + Trick::MemoryManager *memmgr; + Trick::UdUnits * udunits; + + TestConnection connection; + + VariableServerSession_test() { + memmgr = new Trick::MemoryManager; + udunits = new Trick::UdUnits; + + udunits->read_default_xml(); + } + ~VariableServerSession_test() { delete memmgr; } + void SetUp() {} + void TearDown() {} +}; + +TEST_F(VariableServerSession_test, toString) { + + int a = 5; + double b = 6; + std::string c = "Hello"; + (void) memmgr->declare_extern_var(&a, "int a"); + (void) memmgr->declare_extern_var(&b, "double b"); + (void) memmgr->declare_extern_var(&c, "std::string c"); + + Trick::VariableServerSession session(&connection); + + session.var_add("a"); + session.var_add("b"); + session.var_add("c"); + session.var_binary(); + + std::stringstream ss; + ss << session; + + std::string expected = " \"format\":\"BINARY\",\n \"update_rate\":0.1,\n \"variables\":[\n \"a\",\n \"b\",\n \"c\"\n ]\n"; + EXPECT_EQ(ss.str(), expected); + + session.var_ascii(); + expected = " \"format\":\"ASCII\",\n \"update_rate\":0.1,\n \"variables\":[\n \"a\",\n \"b\",\n \"c\"\n ]\n"; + ss.str(""); + ss << session; + EXPECT_EQ(ss.str(), expected); +} + +TEST_F(VariableServerSession_test, var_sync) { + // ARRANGE + Trick::VariableServerSession session(&connection); + + + // ACT + session.var_sync(0); + // ASSERT + ASSERT_EQ(session.get_copy_mode(), VS_COPY_ASYNC); + ASSERT_EQ(session.get_write_mode(), VS_WRITE_ASYNC); + + + // ACT + session.var_sync(1); + // ASSERT + ASSERT_EQ(session.get_copy_mode(), VS_COPY_SCHEDULED); + ASSERT_EQ(session.get_write_mode(), VS_WRITE_ASYNC); + + // ACT + session.var_sync(2); + // ASSERT + ASSERT_EQ(session.get_copy_mode(), VS_COPY_SCHEDULED); + ASSERT_EQ(session.get_write_mode(), VS_WRITE_WHEN_COPIED); +} + + +TEST_F(VariableServerSession_test, large_message_ascii) { + // ARRANGE + Trick::VariableServerSession session(&connection); + + const static int big_arr_size = 4000; + // Make an array too big to fit in a single message + + int big_arr[big_arr_size]; + for (int i = 0; i < big_arr_size; i++) { + big_arr[i] = i; + } + + (void) memmgr->declare_extern_var(&big_arr, "int big_arr[4000]"); + + for (int i = 0; i < big_arr_size; i++) { + std::string var_name = "big_arr[" + std::to_string(i) + "]"; + session.var_add(var_name.c_str()); + } + + // ACT + session.copy_sim_data(); + session.write_data(); + + // ASSERT + ASSERT_TRUE(connection.ascii_messages_written.size() > 1); + int counter = 0; + + int message_index = 0; + for (int i = 0; i < connection.ascii_messages_written.size(); i++) { + std::string message = connection.ascii_messages_written[i]; + std::stringstream ss(message); + std::string token; + + // First val in first message should be the message type, 0 + if (i == 0) { + std::getline(ss, token, '\t'); + int message_type = stoi(token); + EXPECT_EQ(message_type, 0); + } + + while (std::getline(ss, token, '\t')) { + if (token == "\n") { break; } + + int num = stoi(token); + EXPECT_EQ(counter, num); + counter++; + } + } + + EXPECT_EQ(counter, big_arr_size); +} + +TEST_F(VariableServerSession_test, large_message_binary) { + // ARRANGE + Trick::VariableServerSession session(&connection); + session.var_binary(); + + const static int big_arr_size = 4000; + // Make an array too big to fit in a single message + + int big_arr[big_arr_size]; + for (int i = 0; i < big_arr_size; i++) { + big_arr[i] = i; + } + + (void) memmgr->declare_extern_var(&big_arr, "int big_arr[4000]"); + + for (int i = 0; i < big_arr_size; i++) { + std::string var_name = "big_arr[" + std::to_string(i) + "]"; + session.var_add(var_name.c_str()); + } + + // ACT + session.copy_sim_data(); + session.write_data(); + + // ASSERT + ParsedBinaryMessage full_message; + for (int i = 0; i < connection.binary_messages_written.size(); i++) { + ParsedBinaryMessage partial_message; + partial_message.parse(connection.binary_messages_written[i]); + full_message.combine(partial_message); + } + + ASSERT_EQ(full_message.getNumVars(), big_arr_size); + for (int i = 0; i < big_arr_size; i++) { + try { + std::string var_name = "big_arr[" + std::to_string(i) + "]"; + Var variable = full_message.getVariable(var_name); + + EXPECT_EQ(variable.getValue(), i); + } catch (std::exception& ex) { + FAIL() << ex.what(); + } + } +} diff --git a/trick_source/sim_services/VariableServer/var_server_ext.cpp b/trick_source/sim_services/VariableServer/var_server_ext.cpp index dffa6ad9..a5d5d010 100644 --- a/trick_source/sim_services/VariableServer/var_server_ext.cpp +++ b/trick_source/sim_services/VariableServer/var_server_ext.cpp @@ -11,161 +11,215 @@ extern Trick::VariableServer * the_vs ; +int command_debug = 0; + Trick::VariableServerThread * get_vst() { return the_vs->get_vst(pthread_self()) ; } +Trick::VariableServerSession * get_session() { + return the_vs->get_session(pthread_self()) ; +} + int var_add(std::string in_name) { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->var_add(in_name) ; + if (command_debug) { + std::cout << "var_add: " << in_name << std::endl; + } + + Trick::VariableServerSession * session = get_session(); + + if (session != NULL ) { + session->var_add(in_name) ; } return(0) ; } int var_add(std::string in_name, std::string in_units) { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->var_add(in_name, in_units) ; + if (command_debug) { + std::cout << "var_add: " << in_name << std::endl; + } + Trick::VariableServerSession * session = get_session(); + + if (session != NULL ) { + session->var_add(in_name, in_units) ; } return(0) ; } int var_remove(std::string in_name) { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->var_remove(in_name) ; + if (command_debug) { + std::cout << "var_remove: " << in_name << std::endl; + } + Trick::VariableServerSession * session = get_session(); + + if (session != NULL ) { + session->var_remove(in_name) ; } return(0) ; } int var_units(std::string var_name , std::string units_name) { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->var_units(var_name , units_name) ; + if (command_debug) { + std::cout << "var_units: " << var_name << std::endl; + } + Trick::VariableServerSession * session = get_session(); + + if (session != NULL ) { + session->var_units(var_name , units_name) ; } return(0) ; } int var_exists(std::string in_name) { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->var_exists(in_name) ; + if (command_debug) { + std::cout << "var_exists: " << in_name << std::endl; + } + Trick::VariableServerSession * session = get_session(); + + if (session != NULL ) { + session->var_exists(in_name) ; } return(0) ; } int var_send_once(std::string in_name) { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->var_send_once(in_name, 1) ; + if (command_debug) { + std::cout << "var_send_once: " << in_name << std::endl; + } + Trick::VariableServerSession * session = get_session(); + + if (session != NULL ) { + session->var_send_once(in_name, 1) ; } return(0) ; } int var_send_once(std::string in_name, int num) { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->var_send_once(in_name, num) ; + if (command_debug) { + std::cout << "var_send_once: " << in_name << std::endl; + } + Trick::VariableServerSession * session = get_session(); + + if (session != NULL ) { + session->var_send_once(in_name, num) ; } return(0) ; } int var_send() { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->var_send() ; + if (command_debug) { + std::cout << "var_send: " << std::endl; + } + + Trick::VariableServerSession * session = get_session(); + + if (session != NULL ) { + session->var_send() ; } return(0) ; } int var_clear() { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->var_clear() ; + if (command_debug) { + std::cout << "var_clear: " << std::endl; } + Trick::VariableServerSession * session = get_session(); + + if (session != NULL ) { + session->var_clear() ; + } + + // std::cout << "Done with var_clear" << std::endl; return(0) ; } int var_cycle(double in_rate) { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->var_cycle(in_rate) ; + if (command_debug) { + std::cout << "var_cycle: " << in_rate << std::endl; + } + + Trick::VariableServerSession * session = get_session(); + + if (session != NULL ) { + session->var_cycle(in_rate) ; } return(0) ; } int var_pause() { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->set_pause(true) ; + if (command_debug) { + std::cout << "var_pause" << std::endl; + } + + Trick::VariableServerSession * session = get_session(); + + if (session != NULL ) { + session->set_pause(true) ; } return(0) ; } int var_unpause() { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->set_pause(false) ; + if (command_debug) { + std::cout << "var_unpause" << std::endl; + } + Trick::VariableServerSession * session = get_session(); + + if (session != NULL ) { + session->set_pause(false) ; } return(0) ; } int var_exit() { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->var_exit() ; + if (command_debug) { + std::cout << "var_exit" << std::endl; + } + Trick::VariableServerSession * session = get_session(); + + if (session != NULL ) { + session->var_exit() ; } return(0) ; } int var_validate_address(int on_off) { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->var_validate_address((bool)on_off) ; + if (command_debug) { + std::cout << "var_validate_address" << std::endl; + } + Trick::VariableServerSession * session = get_session(); + + if (session != NULL ) { + session->var_validate_address((bool)on_off) ; } return(0) ; } int var_debug(int level) { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->var_debug(level) ; + Trick::VariableServerSession * session = get_session(); + + if (session != NULL ) { + session->var_debug(level) ; } return(0) ; } int var_ascii() { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->var_ascii() ; + Trick::VariableServerSession * session = get_session(); + + if (session != NULL ) { + session->var_ascii() ; } return(0) ; } int var_binary() { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->var_binary() ; + Trick::VariableServerSession * session = get_session(); + + if (session != NULL ) { + session->var_binary() ; } return(0) ; } @@ -176,19 +230,19 @@ int var_retry_bad_ref() { } int var_binary_nonames() { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->var_binary_nonames() ; + Trick::VariableServerSession * session = get_session(); + + if (session != NULL ) { + session->var_binary_nonames() ; } return(0) ; } int var_set_copy_mode(int mode) { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->var_set_copy_mode(mode) ; + Trick::VariableServerSession * session = get_session(); + + if (session != NULL ) { + session->var_set_copy_mode(mode) ; if ( mode == VS_COPY_SCHEDULED ) { the_vs->get_next_sync_call_time() ; the_vs->get_next_freeze_call_time() ; @@ -198,28 +252,25 @@ int var_set_copy_mode(int mode) { } int var_set_write_mode(int mode) { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->var_set_write_mode(mode) ; +Trick::VariableServerSession * session = get_session(); + if (session != NULL ) { + session->var_set_write_mode(mode) ; } return 0 ; } int var_set_send_stdio(int mode) { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->set_send_stdio((bool)mode) ; +Trick::VariableServerSession * session = get_session(); + if (session != NULL ) { + session->set_send_stdio((bool)mode) ; } return 0 ; } int var_sync(int mode) { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->var_sync(mode) ; +Trick::VariableServerSession * session = get_session(); + if (session != NULL ) { + session->var_sync(mode) ; if ( mode ) { the_vs->get_next_sync_call_time() ; the_vs->get_next_freeze_call_time() ; @@ -229,73 +280,66 @@ int var_sync(int mode) { } int var_set_frame_multiple(unsigned int mult) { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->var_set_frame_multiple(mult) ; +Trick::VariableServerSession * session = get_session(); + if (session != NULL ) { + session->var_set_frame_multiple(mult) ; } return 0 ; } int var_set_frame_offset(unsigned int offset) { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->var_set_frame_offset(offset) ; +Trick::VariableServerSession * session = get_session(); + if (session != NULL ) { + session->var_set_frame_offset(offset) ; } return 0 ; } int var_set_freeze_frame_multiple(unsigned int mult) { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->var_set_freeze_frame_multiple(mult) ; +Trick::VariableServerSession * session = get_session(); + if (session != NULL ) { + session->var_set_freeze_frame_multiple(mult) ; } return 0 ; } int var_set_freeze_frame_offset(unsigned int offset) { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->var_set_freeze_frame_offset(offset) ; +Trick::VariableServerSession * session = get_session(); + if (session != NULL ) { + session->var_set_freeze_frame_offset(offset) ; } return 0 ; } int var_byteswap(bool on_off) { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->var_byteswap(on_off) ; +Trick::VariableServerSession * session = get_session(); + if (session != NULL ) { + session->var_byteswap(on_off) ; } return(0) ; } -int var_signal() { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->var_signal() ; - } - return(0) ; -} +// int var_signal() { +// Trick::VariableServerSession * session = get_session(); +// if (session != NULL ) { +// session->var_signal() ; +// } +// return(0) ; +// } -int var_multicast(bool on_off) { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->var_multicast(on_off) ; - } - return(0) ; -} +// int var_multicast(bool on_off) { +// Trick::VariableServerSession * session = get_session(); +// if (session != NULL ) { +// session->var_multicast(on_off) ; +// } +// return(0) ; +// } int var_write_stdio(int stream , std::string text ) { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL and vst->get_send_stdio() == true) { - vst->write_stdio(stream, text) ; + // std::cout << "Executing var_write_stdio" << std::endl; + Trick::VariableServerSession * session = get_session(); + if (session != NULL and session->get_send_stdio() == true) { + session->write_stdio(stream, text) ; } else { if ( stream == 1 ) { fprintf( stdout , "%s" , text.c_str() ) ; @@ -307,14 +351,14 @@ int var_write_stdio(int stream , std::string text ) { } int var_set_client_tag( std::string text ) { - Trick::VariableServerThread * vst ; - vst = get_vst() ; + if (command_debug) { + std::cout << "var_set_client_tag: " << text << std::endl; + } + Trick::VariableServerThread * vst = get_vst(); if (vst != NULL) { - // tag char declared length is 80 - if (text.length()>=80) { - text.resize(79); - } - strcpy(vst->get_connection().client_tag, text.c_str()); + + vst->set_client_tag(text); + #if __linux #ifdef __GNUC__ #if __GNUC__ >= 4 && __GNUC_MINOR__ >= 2 @@ -328,55 +372,53 @@ int var_set_client_tag( std::string text ) { } int var_send_list_size() { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->send_list_size() ; + if (command_debug) { + std::cout << "var_send_list_size" << std::endl; + } + + Trick::VariableServerSession * session = get_session(); + if (session != NULL ) { + session->send_list_size() ; } return(0) ; } int send_sie_resource() { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->send_sie_resource() ; +Trick::VariableServerSession * session = get_session(); + if (session != NULL ) { + session->send_sie_resource() ; } return 0 ; } int send_sie_class() { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->send_sie_class() ; +Trick::VariableServerSession * session = get_session(); + if (session != NULL ) { + session->send_sie_class() ; } return 0 ; } int send_sie_enum() { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - vst->send_sie_enum() ; +Trick::VariableServerSession * session = get_session(); + if (session != NULL ) { + session->send_sie_enum() ; } return 0 ; } int send_sie_top_level_objects() { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - return vst->send_sie_top_level_objects() ; +Trick::VariableServerSession * session = get_session(); + if (session != NULL ) { + return session->send_sie_top_level_objects() ; } return 0 ; } int send_file(std::string file_name) { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - return vst->send_file(file_name) ; +Trick::VariableServerSession * session = get_session(); + if (session != NULL ) { + return session->send_file(file_name) ; } return 0 ; } @@ -384,20 +426,18 @@ int send_file(std::string file_name) { // Command to turn on log to playback file int var_server_log_on() { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - return vst->set_log_on() ; +Trick::VariableServerSession * session = get_session(); + if (session != NULL ) { + return session->set_log_on() ; } return 0 ; } // Command to turn off log to playback file int var_server_log_off() { - Trick::VariableServerThread * vst ; - vst = get_vst() ; - if (vst != NULL ) { - return vst->set_log_off() ; +Trick::VariableServerSession * session = get_session(); + if (session != NULL ) { + return session->set_log_off() ; } return 0 ; } @@ -416,7 +456,9 @@ extern "C" void var_server_list_connections(void) { * C wrapper Trick::VariableServer::get_hostname */ extern "C" const char * var_server_get_hostname(void) { - return(the_vs->get_hostname()) ; + const char * ret = (the_vs->get_hostname()) ; + printf("varserverext: %s", ret); + return ret; } /** @@ -556,8 +598,10 @@ int var_set_base( const char * var , T value , const char * units ) { ref_assignment(ref , &v_tree) ; if(ref->units != NULL) { free(ref->units) ; + ref->units = NULL; } free(ref) ; + ref = NULL; } else { message_publish(MSG_WARNING,"Cannot assign to %s because io_spec does not allow input\n", var) ; } diff --git a/trick_source/sim_services/VariableServer/vs_format_ascii.cpp b/trick_source/sim_services/VariableServer/vs_format_ascii.cpp deleted file mode 100644 index 932f2f4d..00000000 --- a/trick_source/sim_services/VariableServer/vs_format_ascii.cpp +++ /dev/null @@ -1,265 +0,0 @@ -/* -PURPOSE: (Allows clients to get and set Trick parameters) -PROGRAMMERS: (((Keith Vetter) (LinCom) (September 2001) (--))) -*/ - -#include -#include -#include -#include -#include -#include -#include - -#include "trick/parameter_types.h" -#include "trick/attributes.h" -#include "trick/bitfield_proto.h" -#include "trick/wcs_ext.h" -#include "trick/VariableServer.hh" -#include "trick/TrickConstant.hh" - -/* PROTO */ -size_t escape_str(const char *in_s, char *out_s); - -#define MAX_VAL_STRLEN 2048 - -int vs_format_ascii(Trick::VariableReference * var, char *value, size_t value_size) { - - /* for string types, return -1 if string is too big to fit in buffer (MAX_VAL_STRLEN) */ - REF2 * ref ; - ref = var->ref ; - std::string var_name = ref->reference; - - // handle returning an array - int size = 0 ; - value[0] = '\0' ; - - // data to send was copied to buffer in copy_sim_data - void * buf_ptr = var->buffer_out ; - while (size < var->size) { - size += var->ref->attr->size ; - char temp_buf[MAX_VAL_STRLEN]; - - switch (ref->attr->type) { - - case TRICK_CHARACTER: - if (ref->attr->num_index == ref->num_index) { - snprintf(temp_buf, value_size, "%d",(char)cv_convert_double(var->conversion_factor, *(char *)buf_ptr)); - } else { - /* All but last dim specified, leaves a char array */ - escape_str((char *) buf_ptr, temp_buf); - size = var->size ; - } - break; - case TRICK_UNSIGNED_CHARACTER: - if (ref->attr->num_index == ref->num_index) { - snprintf(temp_buf, value_size, "%u",(unsigned char)cv_convert_double(var->conversion_factor,*(unsigned char *)buf_ptr)); - } else { - /* All but last dim specified, leaves a char array */ - escape_str((char *) buf_ptr, temp_buf); - size = var->size ; - } - break; - - case TRICK_WCHAR:{ - if (ref->attr->num_index == ref->num_index) { - snprintf(temp_buf, value_size, "%d",*(wchar_t *) buf_ptr); - } else { - // convert wide char string char string - size_t len = wcs_to_ncs_len((wchar_t *)buf_ptr) + 1 ; - if (len > MAX_VAL_STRLEN) { - return (-1); - } - wcs_to_ncs((wchar_t *) buf_ptr, temp_buf, len); - size = var->size ; - } - } - break; - - case TRICK_STRING: - if ((char *) buf_ptr != NULL) { - escape_str((char *) buf_ptr, temp_buf); - size = var->size ; - } else { - temp_buf[0] = '\0'; - } - break; - - case TRICK_WSTRING: - if ((wchar_t *) buf_ptr != NULL) { - // convert wide char string char string - size_t len = wcs_to_ncs_len((wchar_t *)buf_ptr) + 1 ; - if (len > MAX_VAL_STRLEN) { - return (-1); - } - wcs_to_ncs((wchar_t *) buf_ptr, temp_buf, len); - size = var->size ; - } else { - temp_buf[0] = '\0'; - } - break; - -#if ( __linux | __sgi ) - case TRICK_BOOLEAN: - snprintf(temp_buf, value_size, "%d",(unsigned char)cv_convert_double(var->conversion_factor,*(unsigned char *)buf_ptr)); - break; -#endif - - case TRICK_SHORT: - snprintf(temp_buf, value_size, "%d", (short)cv_convert_double(var->conversion_factor,*(short *)buf_ptr)); - break; - - case TRICK_UNSIGNED_SHORT: - snprintf(temp_buf, value_size, "%u",(unsigned short)cv_convert_double(var->conversion_factor,*(unsigned short *)buf_ptr)); - break; - - case TRICK_INTEGER: - case TRICK_ENUMERATED: -#if ( __sun | __APPLE__ ) - case TRICK_BOOLEAN: -#endif - snprintf(temp_buf, value_size, "%d", (int)cv_convert_double(var->conversion_factor,*(int *)buf_ptr)); - break; - - case TRICK_BITFIELD: - snprintf(temp_buf, value_size, "%d", GET_BITFIELD(buf_ptr, ref->attr->size, ref->attr->index[0].start, ref->attr->index[0].size)); - break; - - case TRICK_UNSIGNED_BITFIELD: - snprintf(temp_buf, value_size, "%u", GET_UNSIGNED_BITFIELD(buf_ptr, ref->attr->size, ref->attr->index[0].start, ref->attr->index[0].size)); - break; - case TRICK_UNSIGNED_INTEGER: - snprintf(temp_buf, value_size, "%u", (unsigned int)cv_convert_double(var->conversion_factor,*(unsigned int *)buf_ptr)); - break; - - case TRICK_LONG: { - long l = *(long *)buf_ptr; - if (var->conversion_factor != cv_get_trivial()) { - l = (long)cv_convert_double(var->conversion_factor, l); - } - snprintf(temp_buf, value_size, "%ld", l); - break; - } - - case TRICK_UNSIGNED_LONG: { - unsigned long ul = *(unsigned long *)buf_ptr; - if (var->conversion_factor != cv_get_trivial()) { - ul = (unsigned long)cv_convert_double(var->conversion_factor, ul); - } - snprintf(temp_buf, value_size, "%lu", ul); - break; - } - - case TRICK_FLOAT: - snprintf(temp_buf, value_size, "%.8g", cv_convert_float(var->conversion_factor,*(float *)buf_ptr)); - break; - - case TRICK_DOUBLE: - snprintf(temp_buf, value_size, "%.16g", cv_convert_double(var->conversion_factor,*(double *)buf_ptr)); - break; - - case TRICK_LONG_LONG: { - long long ll = *(long long *)buf_ptr; - if (var->conversion_factor != cv_get_trivial()) { - ll = (long long)cv_convert_double(var->conversion_factor, ll); - } - snprintf(temp_buf, value_size, "%lld", ll); - break; - } - - case TRICK_UNSIGNED_LONG_LONG: { - unsigned long long ull = *(unsigned long long *)buf_ptr; - if (var->conversion_factor != cv_get_trivial()) { - ull = (unsigned long long)cv_convert_double(var->conversion_factor, ull); - } - snprintf(temp_buf, value_size, "%llu", ull); - break; - } - - case TRICK_NUMBER_OF_TYPES: - snprintf(temp_buf, value_size, "BAD_REF" ); - break; - - default:{ - return (-1); - } - } // end switch - - if (size < var->size) { - // if returning an array, continue array as comma separated values - strcat(temp_buf, ",") ; - buf_ptr = (void*) ((long)buf_ptr + var->ref->attr->size) ; - } - strncat(value, temp_buf, value_size - strlen(value) - 1); - } //end while - - if (ref->units) { - std::stringstream unit_str; - if ( ref->attr->mods & TRICK_MODS_UNITSDASHDASH ) { - unit_str << " {--}"; - } else { - unit_str << " {" << ref->units << "}"; - - } - size_t max_copy_size = value_size - strlen(value) - 1; - strncat(value, unit_str.str().c_str(), max_copy_size); - } - - return (0); -} - - -/** - * Escape all of the non printable characters in a string. - */ -size_t escape_str(const char *in_s, char *out_s) -{ - size_t i, in_len, out_len; - if (in_s == NULL) { - out_s[0] = '\0'; - return 0; - } - in_len = strlen(in_s); - out_len = 0; - if (out_s != NULL) { - out_s[0] = '\0'; - } - for (i = 0; i < in_len; i++) { - int ch = in_s[i]; - char work_s[6]; - - if (isprint(ch)) { - work_s[0] = ch; - work_s[1] = '\0'; - } else { - if (ch == '\a') { - snprintf(work_s, sizeof(work_s), "\\a"); - } else if (ch == '\b') { - snprintf(work_s, sizeof(work_s), "\\b"); - } else if (ch == '\f') { - snprintf(work_s, sizeof(work_s), "\\f"); - } else if (ch == '\n') { - snprintf(work_s, sizeof(work_s), "\\n"); - } else if (ch == '\r') { - snprintf(work_s, sizeof(work_s), "\\n"); - } else if (ch == '\t') { - snprintf(work_s, sizeof(work_s), "\\t"); - } else if (ch == '\v') { - snprintf(work_s, sizeof(work_s), "\\v"); - } else { - snprintf(work_s, sizeof(work_s), "\\x%02x", ch); - } - } - out_len += strlen(work_s); - if (out_s != NULL) { - if (out_len < MAX_VAL_STRLEN) { - strcat(out_s, work_s); - } else { - // indicate string is truncated because it's too big - return -1; - } - } - } - - return (out_len); -} diff --git a/trick_source/trick_utils/CMakeLists.txt b/trick_source/trick_utils/CMakeLists.txt index aca9fec6..d7941c5e 100644 --- a/trick_source/trick_utils/CMakeLists.txt +++ b/trick_source/trick_utils/CMakeLists.txt @@ -23,6 +23,9 @@ add_library( trick_utils_objs OBJECT ${TRICK_UTILS_SRC} ) ############################################################### add_subdirectory(comm) +add_subdirectory(connection_handlers) add_subdirectory(math) add_subdirectory(units) +add_subdirectory(var_binary_parser) + diff --git a/trick_source/trick_utils/connection_handlers/ClientConnection.cpp b/trick_source/trick_utils/connection_handlers/ClientConnection.cpp new file mode 100644 index 00000000..3df752b4 --- /dev/null +++ b/trick_source/trick_utils/connection_handlers/ClientConnection.cpp @@ -0,0 +1 @@ +#include "trick/ClientConnection.hh" \ No newline at end of file diff --git a/trick_source/trick_utils/connection_handlers/ClientListener.cpp b/trick_source/trick_utils/connection_handlers/ClientListener.cpp new file mode 100644 index 00000000..331e253b --- /dev/null +++ b/trick_source/trick_utils/connection_handlers/ClientListener.cpp @@ -0,0 +1,115 @@ +#include +#include +#include + +#include "trick/ClientListener.hh" +#include "trick/tc_proto.h" + + + +Trick::ClientListener::ClientListener () : _listen_dev(), initialized(false) { + char hname[80]; + gethostname(hname , (size_t) 80 ) ; + saved_source = std::string(hname); + strcpy(_listen_dev.client_tag, ""); + tc_error(&_listen_dev, 0); +} + +Trick::ClientListener::~ClientListener () { + +} + +int Trick::ClientListener::initialize(std::string hostname, int port) { + int ret = tc_init_with_connection_info(&_listen_dev, AF_INET, SOCK_STREAM, hostname.c_str(), port); + initialized = true; + return ret; +} + +int Trick::ClientListener::initialize() { + int ret = tc_init(&_listen_dev); + if (ret != TC_SUCCESS) { + + fprintf(stderr, "ERROR: Could not establish listen port for Variable Server. Aborting.\n"); + ret = -1 ; + } + initialized = true; + return ret; +} + + +int Trick::ClientListener::setBlockMode(TCCommBlocking mode) { + if (!initialized) + return -1; + + return tc_blockio(&_listen_dev, mode); +} + + +bool Trick::ClientListener::checkForNewConnections() { + if (!initialized) + return -1; + + fd_set rfds; + struct timeval timeout_time = { 2, 0 }; + FD_ZERO(&rfds); + FD_SET(_listen_dev.socket, &rfds); + timeout_time.tv_sec = 2 ; + select(_listen_dev.socket + 1, &rfds, NULL, NULL, &timeout_time); + + return FD_ISSET(_listen_dev.socket, &rfds); +} + + +const char * Trick::ClientListener::getHostname () { + if (!initialized) + return ""; + + return _listen_dev.hostname; +} + + +int Trick::ClientListener::getPort() { + if (!initialized) + return -1; + + return _listen_dev.port; +} + + +int Trick::ClientListener::disconnect() { + if (!initialized) + return -1; + + return tc_disconnect(&_listen_dev) ; +} + +bool Trick::ClientListener::validateSourceAddress(std::string requested_source_address) { + char hname[80]; + static struct sockaddr_in s_in; + gethostname(hname, (size_t) 80); + + // Test to see if the restart address is on this machine. If it is not, it's not an error + if ( strcmp( requested_source_address.c_str(), hname )) { + if (! inet_pton(AF_INET, requested_source_address.c_str(), (struct in_addr *)&s_in.sin_addr.s_addr) ) { + return false; + } + } + + return true; +} + +int Trick::ClientListener::checkSocket() { + if (!initialized) + return -1; + + struct sockaddr_in s_in; + int s_in_size = sizeof(s_in) ; + getsockname( _listen_dev.socket , (struct sockaddr *)&s_in, (socklen_t *)&s_in_size) ; + printf("restart variable server message port = %d\n" , ntohs(s_in.sin_port)) ; + _listen_dev.port = ntohs(s_in.sin_port); +} + +bool Trick::ClientListener::isInitialized() { + return initialized; +} + diff --git a/trick_source/trick_utils/connection_handlers/Makefile b/trick_source/trick_utils/connection_handlers/Makefile new file mode 100644 index 00000000..3e66afd6 --- /dev/null +++ b/trick_source/trick_utils/connection_handlers/Makefile @@ -0,0 +1,15 @@ +TRICK_HOME := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))../../..) + +# set CONFIG_MK to allow compilation without running configure +CONFIG_MK = 1 + +include ${TRICK_HOME}/share/trick/makefiles/Makefile.common +# set the TRICK_LIB variable to create a separate library for comm +TRICK_LIB := $(TRICK_LIB_DIR)/libtrick_connection_handlers.a +include ${TRICK_HOME}/share/trick/makefiles/Makefile.tricklib +-include Makefile_deps + +TRICK_CXXFLAGS += -std=c++11 + +# make the comm library when called by the master makefile. +trick: ${TRICK_LIB} diff --git a/trick_source/trick_utils/connection_handlers/MulticastManager.cpp b/trick_source/trick_utils/connection_handlers/MulticastManager.cpp new file mode 100644 index 00000000..7dd8c10e --- /dev/null +++ b/trick_source/trick_utils/connection_handlers/MulticastManager.cpp @@ -0,0 +1,63 @@ +#include "trick/MulticastManager.hh" +#include +#include + +Trick::MulticastManager::MulticastManager() { +} + +Trick::MulticastManager::~MulticastManager() { + +} + +int Trick::MulticastManager::restart () { + // Keep address list the same, but we may need to get a new socket + return initialize(); +} + + +int Trick::MulticastManager::broadcast (std::string message) { + if (!is_initialized()) { + initialize(); + } + const char * message_send = message.c_str(); + for (struct sockaddr_in& address : addresses) { + sendto(mcast_socket , message_send , strlen(message_send) , 0 , (struct sockaddr *)&address , (socklen_t)sizeof(address)) ; + } +} + +int Trick::MulticastManager::addAddress (std::string addr, int port) { + + struct sockaddr_in mcast_addr; + memset(&mcast_addr, 0, sizeof(mcast_addr)); + mcast_addr.sin_family = AF_INET; + mcast_addr.sin_addr.s_addr = inet_addr(addr.c_str()); + mcast_addr.sin_port = htons((uint16_t) port); + addresses.emplace_back(mcast_addr); +} + +int Trick::MulticastManager::is_initialized () { + return initialized; +} + +int Trick::MulticastManager::initialize() { + + mcast_socket = socket(AF_INET, SOCK_DGRAM, 0); + if (mcast_socket < 0) { + perror("vs_mcast_init socket"); + return -1; + } + + int option_value = 1; + if (setsockopt(mcast_socket, SOL_SOCKET, SO_REUSEADDR, (char *) &option_value, (socklen_t) sizeof(option_value)) < 0) { + perror("setsockopt: reuseaddr"); + return -1; + } +#ifdef SO_REUSEPORT + if (setsockopt(mcast_socket, SOL_SOCKET, SO_REUSEPORT, (char *) &option_value, sizeof(option_value)) < 0) { + perror("setsockopt: reuseport"); + return -1; + } +#endif + initialized = 1; + return 0; +} \ No newline at end of file diff --git a/trick_source/trick_utils/connection_handlers/TCConnection.cpp b/trick_source/trick_utils/connection_handlers/TCConnection.cpp new file mode 100644 index 00000000..51f398cf --- /dev/null +++ b/trick_source/trick_utils/connection_handlers/TCConnection.cpp @@ -0,0 +1,117 @@ +#include "trick/TCConnection.hh" +#include "trick/tc.h" +#include "trick/tc_proto.h" +#include +#include + +Trick::TCConnection::TCConnection () {} + +int Trick::accept(ClientListener *listener, Trick::TCConnection *connection) { + if (!listener->isInitialized()) + return -1; + + if ( listener->_listen_dev.socket_type == SOCK_STREAM ) { + return tc_accept(&(listener->_listen_dev), &(connection->_device)); + } + + return 0; +} + +int Trick::TCConnection::initialize() { + _device.disabled = TC_COMM_FALSE ; + _device.disable_handshaking = TC_COMM_TRUE ; + _device.blockio_limit = 0.0 ; + _device.blockio_type = TC_COMM_BLOCKIO ; + _device.client_id = 0 ; + strcpy(_device.client_tag, "") ; + _device.error_handler = (TrickErrorHndlr *) calloc(1, (int)sizeof(TrickErrorHndlr)); + _device.error_handler->report_level = TRICK_ERROR_CAUTION; +} + +int Trick::TCConnection::write (char * message, int size) { + int ret = tc_write(&_device, message, size); + return ret; +} + +int Trick::TCConnection::write (const std::string& message) { + char send_buf[message.length()+1]; + strcpy (send_buf, message.c_str()); + int ret = tc_write(&_device, send_buf, message.length()); + return ret; +} + +std::string Trick::TCConnection::read (int max_len) { + char incoming_msg[max_len]; + int nbytes = recvfrom( _device.socket, incoming_msg, MAX_CMD_LEN, MSG_PEEK, NULL, NULL ) ; + if (nbytes == 0 ) { + return 0; + } + + if (nbytes != -1) { // -1 means socket is nonblocking and no data to read + /* find the last newline that is present on the socket */ + incoming_msg[nbytes] = '\0' ; + char *last_newline = rindex( incoming_msg , '\n') ; + + /* if there is a newline then there is a complete command on the socket */ + if ( last_newline != NULL ) { + /* only remove up to (and including) the last newline on the socket */ + int size = last_newline - incoming_msg + 1; + nbytes = recvfrom( _device.socket, incoming_msg, size, 0 , NULL, NULL ) ; + } else { + nbytes = 0 ; + } + } + + std::stringstream msg_stream; + + if ( nbytes > 0 ) { + + int msg_len = nbytes ; + // if (debug >= 3) { + // message_publish(MSG_DEBUG, "%p tag=<%s> var_server received bytes = msg_len = %d\n", &_device, _device.client_tag, nbytes); + // } + + incoming_msg[msg_len] = '\0' ; + + for( int ii = 0 , jj = 0 ; ii <= msg_len ; ii++ ) { + if ( incoming_msg[ii] != '\r' ) { + msg_stream << incoming_msg[ii] ; + } + } + } + + return msg_stream.str(); +} + + +std::string Trick::TCConnection::get_client_tag () { + return std::string(_device.client_tag); +} + +int Trick::TCConnection::set_client_tag(std::string tag) { + // Max size of device client tag is 80 + + // TODO: Make 80 a constant somewhere, probably in TC device + if (tag.length() >= 80) { + tag.resize(79); + } + strcpy(_device.client_tag, tag.c_str()); + return 0; +} + +int Trick::TCConnection::get_socket() { + return _device.socket; +} + + +int Trick::TCConnection::disconnect () { + return tc_disconnect(&_device); +} + +int Trick::TCConnection::setBlockMode(int block_mode) { + return tc_blockio(&_device, (TCCommBlocking)block_mode); +} + +int Trick::TCConnection::setErrorReporting (bool on) { + return tc_error(&_device, (int)on); +} \ No newline at end of file diff --git a/trick_source/trick_utils/var_binary_parser/.gitignore b/trick_source/trick_utils/var_binary_parser/.gitignore index 2b9516df..9e345c98 100644 --- a/trick_source/trick_utils/var_binary_parser/.gitignore +++ b/trick_source/trick_utils/var_binary_parser/.gitignore @@ -1,2 +1,2 @@ *.o -TEST_var_binary_parser \ No newline at end of file +TEST_var_binary_parser diff --git a/trick_source/trick_utils/var_binary_parser/test/Makefile b/trick_source/trick_utils/var_binary_parser/test/Makefile index 59090679..d82b950c 100644 --- a/trick_source/trick_utils/var_binary_parser/test/Makefile +++ b/trick_source/trick_utils/var_binary_parser/test/Makefile @@ -34,4 +34,4 @@ TEST_var_binary_parser.o : TEST_var_binary_parser.cc $(OTHER_OBJECTS) TEST_var_binary_parser : TEST_var_binary_parser.o $(OTHER_OBJECTS) @echo 'Building TEST_var_binary_parser' - $(CXX) $(TRICK_SYSTEM_LDFLAGS) $(CPPFLAGS) -o $@ $^ -L${TRICK_HOME}/lib_${TRICK_HOST_CPU} $(LIBS) $(EXEC_LINK_LIBS) \ No newline at end of file + $(CXX) $(TRICK_SYSTEM_LDFLAGS) $(CPPFLAGS) -o $@ $^ -L${TRICK_HOME}/lib_${TRICK_HOST_CPU} $(LIBS) $(EXEC_LINK_LIBS) diff --git a/trick_source/web/CivetServer/include/VariableServerSessionWeb.hh b/trick_source/web/CivetServer/include/VariableServerSessionWeb.hh new file mode 100644 index 00000000..a138fc19 --- /dev/null +++ b/trick_source/web/CivetServer/include/VariableServerSessionWeb.hh @@ -0,0 +1,51 @@ +/************************************************************************* +PURPOSE: (Represent the state of a variable server websocket connection.) +**************************************************************************/ + +#ifndef WSSESSION_HH +#define WSSESSION_HH + +#include +#include + +#ifndef SWIG +#include "CivetServer.h" +#endif + +#include "trick/WebSocketSession.hh" +#include "VariableServerVariable.hh" + +class VariableServerSession : public WebSocketSession { + public: + VariableServerSession(struct mg_connection *nc); + ~VariableServerSession(); + void marshallData(); /* -- base */ + void sendMessage(); /* -- base */ + int handleMessage(const std::string&); /* -- base */ + + void setTimeInterval(unsigned int milliseconds); + void addVariable(char* vname); + void stageValues(); + void pause(); + void unpause(); + void clear(); + void exit(); + + // static int bad_ref_int ; + + private: + int sendErrorMessage(const char* fmt, ... ); + int sendSieMessage(void); + int sendUnitsMessage(const char* vname); + // REF2* make_error_ref(const char* in_name); + double stageTime; + bool dataStaged; + + std::vector session_variables; + bool cyclicSendEnabled; + long long nextTime; + long long intervalTimeTics; +}; + +WebSocketSession* makeVariableServerSession( struct mg_connection *nc ); +#endif diff --git a/trickops.py b/trickops.py index 14027706..3e9b74dd 100644 --- a/trickops.py +++ b/trickops.py @@ -37,6 +37,14 @@ class SimTestWorkflow(TrickWorkflow): # are only in the remaining_run_jobs list. - Jordan 2/2023 remaining_run_jobs.remove(job) + # Some tests fail intermittently for reasons not related to the tests themselves, mostly network weirdness. + # Allow retries so that we can still cover some network-adjacent code + retry_allowed_sims = self.get_sims(labels='retries_allowed') + retry_allowed_jobs = [run.get_run_job() for run in [item for sublist in [sim.get_runs() for sim in retry_allowed_sims] for item in sublist]] + for job in retry_allowed_jobs: + run_jobs.remove(job) + + builds_status = self.execute_jobs(build_jobs, max_concurrent=self.cpus, header='Executing all sim builds.') first_phase_run_status = self.execute_jobs(first_run_jobs, max_concurrent=self.cpus, header="Executing first phase runs.") runs_status = self.execute_jobs(remaining_run_jobs, max_concurrent=self.cpus, header='Executing remaining runs.') From 0788dcfa9bd6fb4ea256a9ee2d438f285efd4f12 Mon Sep 17 00:00:00 2001 From: Jacqueline Deans Date: Wed, 22 Feb 2023 11:35:30 -0600 Subject: [PATCH 2/5] Replace TrickComm with new connection_handler library --- include/trick/ClientConnection.hh | 23 +- include/trick/ClientListener.hh | 40 +- include/trick/SysThread.hh | 3 +- include/trick/SystemInterface.hh | 50 ++ include/trick/TCConnection.hh | 48 -- include/trick/TCPConnection.hh | 46 ++ include/trick/ThreadBase.hh | 16 +- include/trick/UDPConnection.hh | 56 ++ include/trick/VariableServerListenThread.hh | 4 +- include/trick/VariableServerThread.hh | 30 +- share/trick/trickops/WorkflowCommon.py | 38 +- test/SIM_test_varserv/RUN_test/unit_test.py | 4 +- .../models/test_client/test_client.cpp | 521 +----------------- .../MonteCarlo/MonteCarlo_master_shutdown.cpp | 3 + .../MonteCarlo/MonteCarlo_slave_funcs.cpp | 7 + .../sim_services/ThreadBase/SysThread.cpp | 25 +- .../sim_services/ThreadBase/ThreadBase.cpp | 54 +- .../sim_services/VariableServer/Makefile_deps | 2 +- .../VariableServer/VariableReference.cpp | 2 +- .../VariableServerListenThread.cpp | 83 ++- .../VariableServerSession_commands.cpp | 14 +- .../VariableServer/VariableServerThread.cpp | 106 +++- .../VariableServerThread_loop.cpp | 29 +- .../VariableServer_get_var_server_port.cpp | 19 +- .../VariableServer/VariableServer_restart.cpp | 14 +- .../VariableServer_shutdown.cpp | 14 +- .../VariableServer/exit_var_thread.cpp | 14 +- .../VariableServer/test/TestConnection.hh | 2 +- trick_source/sim_services/mains/master.cpp | 1 - .../connection_handlers/ClientConnection.cpp | 11 +- .../connection_handlers/ClientListener.cpp | 232 ++++++-- .../connection_handlers/MulticastManager.cpp | 2 + .../connection_handlers/TCConnection.cpp | 117 ---- .../connection_handlers/TCPConnection.cpp | 156 ++++++ .../connection_handlers/UDPConnection.cpp | 215 ++++++++ .../connection_handlers/test/.gitignore | 1 + .../test/ClientListener_test.cpp | 400 ++++++++++++++ .../connection_handlers/test/Makefile | 38 ++ .../SystemInterfaceMock.hh | 238 ++++++++ .../test/TCPConnection_test.cpp | 367 ++++++++++++ .../test/UDPConnection_test.cpp | 394 +++++++++++++ trickops.py | 67 +-- 42 files changed, 2562 insertions(+), 944 deletions(-) create mode 100644 include/trick/SystemInterface.hh delete mode 100644 include/trick/TCConnection.hh create mode 100644 include/trick/TCPConnection.hh create mode 100644 include/trick/UDPConnection.hh delete mode 100644 trick_source/trick_utils/connection_handlers/TCConnection.cpp create mode 100644 trick_source/trick_utils/connection_handlers/TCPConnection.cpp create mode 100644 trick_source/trick_utils/connection_handlers/UDPConnection.cpp create mode 100644 trick_source/trick_utils/connection_handlers/test/.gitignore create mode 100644 trick_source/trick_utils/connection_handlers/test/ClientListener_test.cpp create mode 100644 trick_source/trick_utils/connection_handlers/test/Makefile create mode 100644 trick_source/trick_utils/connection_handlers/test/SystemInterfaceMock/SystemInterfaceMock.hh create mode 100644 trick_source/trick_utils/connection_handlers/test/TCPConnection_test.cpp create mode 100644 trick_source/trick_utils/connection_handlers/test/UDPConnection_test.cpp diff --git a/include/trick/ClientConnection.hh b/include/trick/ClientConnection.hh index 50883c4f..064a1e4a 100644 --- a/include/trick/ClientConnection.hh +++ b/include/trick/ClientConnection.hh @@ -14,28 +14,31 @@ LIBRARY DEPENDENCIES: namespace Trick { class ClientConnection { public: - // Should this be here? ¯\_(ツ)_/¯ + static const unsigned int MAX_CMD_LEN = 200000 ; + enum ConnectionType { TCP, UDP, MCAST, WS } ; - virtual int initialize() = 0; + // Pure virtual methods + virtual int start() = 0; virtual int write (const std::string& message) = 0; virtual int write (char * message, int size) = 0; virtual std::string read (int max_len = MAX_CMD_LEN) = 0; + virtual int setBlockMode (bool blocking) = 0; virtual int disconnect () = 0; - virtual std::string get_client_tag () = 0; - virtual int set_client_tag(std::string tag) = 0; - virtual int setBlockMode (int mode) = 0; - - static const unsigned int MAX_CMD_LEN = 200000 ; + + virtual bool isInitialized() = 0; + + virtual std::string getClientTag (); + virtual int setClientTag (std::string tag); + + virtual int restart() {}; protected: ConnectionType _connection_type; - - // RHEL appears to have an issue with std::atomic - // std::atomic_bool _is_initialized; + std::string _client_tag; }; } diff --git a/include/trick/ClientListener.hh b/include/trick/ClientListener.hh index c9df618d..ebba212f 100644 --- a/include/trick/ClientListener.hh +++ b/include/trick/ClientListener.hh @@ -1,28 +1,39 @@ #ifndef CLIENT_LISTENER_HH #define CLIENT_LISTENER_HH -#include "trick/tc.h" -#include "trick/TCConnection.hh" +/* + PURPOSE: ( Encapsulate a TCP server. ) +*/ + #include +#include "trick/SystemInterface.hh" +#include "trick/TCPConnection.hh" + +#define LISTENER_ERROR -1 + namespace Trick { - class TCConnection; + class TCPConnection; class ClientListener { public: + ClientListener (); + ClientListener (SystemInterface * system_interface); + ~ClientListener (); - // We'll see if we need separate methods for these int initialize(std::string hostname, int port); int initialize(); - int setBlockMode(TCCommBlocking mode); + int setBlockMode(bool blocking); bool checkForNewConnections(); - const char * getHostname (); + TCPConnection * setUpNewConnection (); + + std::string getHostname (); int getPort(); @@ -34,13 +45,18 @@ namespace Trick { bool isInitialized(); - friend int accept(ClientListener* listener, TCConnection* connection); - + int restart(); + private: - TCDevice _listen_dev; - std::string saved_source; - int port; - bool initialized; + + int _listen_socket; + std::string _hostname; + int _port; + std::string _client_tag; + + bool _initialized; + + SystemInterface * _system_interface; /* ** */ }; } diff --git a/include/trick/SysThread.hh b/include/trick/SysThread.hh index a565b8c5..d5f639dd 100644 --- a/include/trick/SysThread.hh +++ b/include/trick/SysThread.hh @@ -33,7 +33,7 @@ namespace Trick { **/ class SysThread : public Trick::ThreadBase { public: - SysThread(std::string in_name, bool self_deleting = false); + SysThread(std::string in_name); ~SysThread(); static int ensureAllShutdown(); @@ -47,7 +47,6 @@ namespace Trick { static bool shutdown_finished; - bool self_deleting; } ; } diff --git a/include/trick/SystemInterface.hh b/include/trick/SystemInterface.hh new file mode 100644 index 00000000..b6daa767 --- /dev/null +++ b/include/trick/SystemInterface.hh @@ -0,0 +1,50 @@ + +#ifndef __SYSTEM_INTERFACE__ +#define __SYSTEM_INTERFACE__ + + +#include +#include +#include +#include +#include +#include +#include +#include + +class SystemInterface { + public: + + virtual int socket (int domain, int type, int protocol) { return ::socket ( domain, type, protocol); } + + virtual int setsockopt (int socket, int level, int option_name, const void * option_value, socklen_t option_len) { return ::setsockopt ( socket, level, option_name, option_value, option_len); } + + virtual int bind (int socket, struct sockaddr * address, socklen_t address_len) { return ::bind ( socket, address, address_len); } + + virtual int getsockname (int socket, struct sockaddr * address, socklen_t * address_len) { return ::getsockname ( socket, address, address_len); } + + virtual int listen (int socket, int backlog) { return ::listen ( socket, backlog); } + + virtual int select (int nfds, fd_set * readfds, fd_set * writefds, fd_set * errorfds, struct timeval * timeout) { return ::select ( nfds, readfds, writefds, errorfds, timeout); } + + virtual int close (int fildes) { return ::close ( fildes); } + + virtual int getaddrinfo (const char * hostname, const char * servname, const struct addrinfo * hints, struct addrinfo ** res) { return ::getaddrinfo ( hostname, servname, hints, res); } + + virtual int fcntl (int fildes, int cmd, int arg) { return ::fcntl ( fildes, cmd, arg); } + + virtual int shutdown (int socket, int how) { return ::shutdown ( socket, how); } + + virtual int accept (int socket, struct sockaddr * address, socklen_t * address_len) { return ::accept ( socket, address, address_len); } + + virtual ssize_t send (int socket, const void * buffer, size_t length, int flags) { return ::send ( socket, buffer, length, flags); } + + virtual ssize_t sendto (int socket, const void * buffer, size_t length, int flags, const struct sockaddr * dest_addr, socklen_t dest_len) { return ::sendto ( socket, buffer, length, flags, dest_addr, dest_len); } + + virtual ssize_t recv (int socket, void * buffer, size_t length, int flags) { return ::recv ( socket, buffer, length, flags); } + + virtual ssize_t recvfrom (int socket, void * buffer, size_t length, int flags, struct sockaddr * address, socklen_t * address_len) { return ::recvfrom ( socket, buffer, length, flags, address, address_len); } + +}; + +#endif diff --git a/include/trick/TCConnection.hh b/include/trick/TCConnection.hh deleted file mode 100644 index 070892d1..00000000 --- a/include/trick/TCConnection.hh +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef TC_CONNECTION_HH -#define TC_CONNECTION_HH - -/* - PURPOSE: ( Encapsulate a connection with TrickComm. ) -*/ - -#include "trick/ClientConnection.hh" -#include "trick/ClientListener.hh" -#include "tc.h" - - -namespace Trick { - - class ClientListener; - - class TCConnection : public ClientConnection { - public: - - TCConnection (); - - int initialize() override; - - int write (const std::string& message) override; - int write (char * message, int size) override; - - std::string read (int max_len) override; - - int disconnect () override; - std::string get_client_tag () override; - int set_client_tag(std::string tag) override; - int get_socket(); - - int setBlockMode(int block_mode) override; - int setErrorReporting (bool on); - - static const unsigned int MAX_CMD_LEN = 200000 ; - - friend int accept(ClientListener* listener, TCConnection* connection); - - private: - TCDevice _device; /**< trick_io(**) */ - }; - - int accept(ClientListener* listener, TCConnection* connection); -} - -#endif \ No newline at end of file diff --git a/include/trick/TCPConnection.hh b/include/trick/TCPConnection.hh new file mode 100644 index 00000000..9285610d --- /dev/null +++ b/include/trick/TCPConnection.hh @@ -0,0 +1,46 @@ +#ifndef TCP_CONNECTION_HH +#define TCP_CONNECTION_HH + +/* + PURPOSE: ( Encapsulate a TCP connection. ) +*/ + +#include "trick/ClientConnection.hh" +#include "trick/SystemInterface.hh" + +namespace Trick { + + class TCPConnection : public ClientConnection { + public: + + TCPConnection (int listen_socket); + TCPConnection (SystemInterface * system_interface); + TCPConnection (int listen_socket, SystemInterface * system_interface); + + int start() override; + + int write (const std::string& message) override; + int write (char * message, int size) override; + + std::string read (int max_len = MAX_CMD_LEN) override; + + int disconnect () override; + bool isInitialized() override; + + int setBlockMode(bool blocking) override; + + int restart() override; + + private: + int _socket; + bool _connected; + + // This is needed to be able to accept an incoming connection, after being set up by the listener + int _listen_socket; + + SystemInterface * _system_interface; /* ** */ + + }; +} + +#endif \ No newline at end of file diff --git a/include/trick/ThreadBase.hh b/include/trick/ThreadBase.hh index 41ec3273..ffe51ceb 100644 --- a/include/trick/ThreadBase.hh +++ b/include/trick/ThreadBase.hh @@ -131,7 +131,7 @@ namespace Trick { virtual int cancel_thread() ; /** - * Cancels thread. + * Joins thread. * @return always 0 */ virtual int join_thread() ; @@ -153,6 +153,12 @@ namespace Trick { */ virtual void dump( std::ostream & oss = std::cout ) ; + virtual void test_shutdown(); + virtual void test_shutdown(void (*exit_handler) (void *), void * exit_arg); + + virtual void thread_shutdown(); + virtual void thread_shutdown(void (*exit_handler) (void *), void * exit_arg); + protected: /** optional name of thread */ @@ -170,6 +176,14 @@ namespace Trick { /** Set of cpus to use with thread */ unsigned int max_cpu ; /**< trick_io(**) */ + /** Track whether the thread has been created */ + bool created ; /**< trick_io(**) */ + + /** Manage thread shutdown */ + bool should_shutdown; /**< trick_io(**) */ + bool cancellable; /**< trick_io(**) */ + pthread_mutex_t shutdown_mutex; /**< trick_io(**) */ + #if __linux #ifndef SWIG /** Set of cpus to use with thread */ diff --git a/include/trick/UDPConnection.hh b/include/trick/UDPConnection.hh new file mode 100644 index 00000000..abfc7e6a --- /dev/null +++ b/include/trick/UDPConnection.hh @@ -0,0 +1,56 @@ +#ifndef UDP_CONNECTION_HH +#define UDP_CONNECTION_HH + +/* + PURPOSE: ( Encapsulate a UDP socket. ) +*/ + +#include "trick/ClientConnection.hh" +#include "trick/SystemInterface.hh" + + +namespace Trick { + + class UDPConnection : public ClientConnection { + public: + + UDPConnection (); + UDPConnection (SystemInterface * system_interface); + + int start() override; + + int write (const std::string& message) override; + int write (char * message, int size) override; + + std::string read (int max_len = MAX_CMD_LEN) override; + + int disconnect () override; + bool isInitialized() override; + + int setBlockMode(bool block_mode) override; + int restart() override; + + // Non-override functions + int initialize(const std::string& hostname, int port); + + + int getPort(); + std::string getHostname(); + + + private: + bool _initialized; + bool _started; + int _socket; + + int _port; + std::string _hostname; + + struct sockaddr_in _remote_serv_addr; + + SystemInterface * _system_interface; /* ** */ + }; + +} + +#endif \ No newline at end of file diff --git a/include/trick/VariableServerListenThread.hh b/include/trick/VariableServerListenThread.hh index 41fa2052..bc87a34e 100644 --- a/include/trick/VariableServerListenThread.hh +++ b/include/trick/VariableServerListenThread.hh @@ -75,10 +75,10 @@ namespace Trick { bool broadcast ; /**< trick_units(--) */ /** The listen device */ - ClientListener listener; + ClientListener listener; /**< trick_io(**) trick_units(--) */ /* Multicast broadcaster */ - MulticastManager multicast; + MulticastManager multicast; /**< trick_io(**) trick_units(--) */ /** The mutex to stop accepting new connections during restart\n */ pthread_mutex_t restart_pause ; /**< trick_io(**) */ diff --git a/include/trick/VariableServerThread.hh b/include/trick/VariableServerThread.hh index 3d932524..0b046035 100644 --- a/include/trick/VariableServerThread.hh +++ b/include/trick/VariableServerThread.hh @@ -11,11 +11,12 @@ #include #include #include "trick/tc.h" -#include "trick/TCConnection.hh" #include "trick/SysThread.hh" #include "trick/VariableServerSession.hh" #include "trick/variable_server_sync_types.h" #include "trick/variable_server_message_types.h" + +#include "trick/ClientConnection.hh" #include "trick/ClientListener.hh" namespace Trick { @@ -39,7 +40,7 @@ namespace Trick { @brief Constructor. @param listen_dev - the TCDevice set up in listen() */ - VariableServerThread(ClientListener * in_listen_dev ) ; + VariableServerThread() ; virtual ~VariableServerThread() ; /** @@ -50,6 +51,16 @@ namespace Trick { void set_client_tag(std::string tag); + /** + @brief Open a UDP socket for this thread + */ + int open_udp_socket(const std::string& hostname, int port); + + /** + @brief Open a TCP connection for this thread + */ + int open_tcp_connection(ClientListener * listener); + /** @brief Block until thread has accepted connection */ @@ -67,6 +78,8 @@ namespace Trick { void restart() ; + void cleanup(); + protected: /** @@ -77,12 +90,11 @@ namespace Trick { /** The Master variable server object. */ static VariableServer * vs ; - /** this is where a lot of this should happen now */ - VariableServerSession * session; + /** Manages the variable list */ + VariableServerSession * session; /**< trick_io(**) */ - /** The listen device from the variable server\n */ - ClientListener * listener; /**< trick_io(**) */ - TCConnection connection; /**< trick_io(**) */ + /** Connection to the client */ + ClientConnection * connection; /**< trick_io(**) */ /** Value (1,2,or 3) that causes the variable server to output increasing amounts of debug information.\n */ int debug ; /**< trick_io(**) */ @@ -91,8 +103,8 @@ namespace Trick { bool enabled ; /**< trick_io(**) */ ConnectionStatus connection_status ; /**< trick_io(**) */ - pthread_mutex_t connection_status_mutex; - pthread_cond_t connection_status_cv; + pthread_mutex_t connection_status_mutex; /**< trick_io(**) */ + pthread_cond_t connection_status_cv; /**< trick_io(**) */ /** The mutex pauses all processing during checkpoint restart */ pthread_mutex_t restart_pause ; /**< trick_io(**) */ diff --git a/share/trick/trickops/WorkflowCommon.py b/share/trick/trickops/WorkflowCommon.py index 0846313b..6b164cc4 100644 --- a/share/trick/trickops/WorkflowCommon.py +++ b/share/trick/trickops/WorkflowCommon.py @@ -205,7 +205,7 @@ class Job(object): for getting status information. More specific types of Jobs should inherit from this base clasee. """ - enums = ['NOT_STARTED', 'RUNNING', 'SUCCESS', 'FAILED'] + enums = ['NOT_STARTED', 'RUNNING', 'SUCCESS', 'FAILED', 'TIMEOUT'] Status = collections.namedtuple('Status', enums)(*(range(len(enums)))) _success_progress_bar = create_progress_bar(1, 'Success') @@ -220,7 +220,9 @@ class Job(object): Job.Status.NOT_STARTED: ('NOT RUN', 'DARK_YELLOW'), Job.Status.SUCCESS: ('OK', 'DARK_GREEN'), Job.Status.FAILED: ('FAIL:' + str(self._expected_exit_status) + '/' + - str(self._exit_status), 'DARK_RED') }[self.get_status()] + str(self._exit_status), 'DARK_RED'), + Job.Status.TIMEOUT: ('TIMEOUT after ' + str(self._timeout) + ' seconds', 'YELLOW') + }[self.get_status()] return printer.colorstr(text, color) def __init__(self, name, command, log_file, expected_exit_status=0): @@ -245,6 +247,7 @@ class Job(object): self._stop_time = None self._exit_status = None self._expected_exit_status = expected_exit_status + self._timeout = None def start(self): """ @@ -275,6 +278,8 @@ class Job(object): This job completed with an exit status of zero. Status.FAILED This job completed with a non-zero exit status. + Status.TIMEOUT + This job ran longer than the allotted time given by execute_job """ if self._process is None: return self.Status.NOT_STARTED @@ -283,6 +288,9 @@ class Job(object): if self._exit_status is None: return self.Status.RUNNING + if self._timeout is not None: + return self.Status.TIMEOUT + if self._stop_time is None: self._stop_time = time.time() @@ -368,6 +376,17 @@ class Job(object): """ return self._done_string() + def _timeout_string(self): + """ + Get a string to display when this Job has failed. + + Returns + ------- + str + A string to be displayed when in the FAILED state. + """ + return self._done_string() + def _done_string(self): """ This class uses the same string for SUCCESS and FAILED, but @@ -573,7 +592,7 @@ class WorkflowCommon: else: return 'unknown' - def execute_jobs(self, jobs, max_concurrent=None, header=None): + def execute_jobs(self, jobs, max_concurrent=None, header=None, job_timeout=None): """ Run jobs, blocking until all have returned. @@ -694,6 +713,15 @@ class WorkflowCommon: for i in range(min(len(waitingJobs), available_cpus)): waitingJobs[i].start() + if job_timeout is not None: + # Check if any jobs have timed out + runningJobs = [job for job in jobs if job.get_status() is job.Status.RUNNING] + for runningJob in runningJobs: + if time.time() - runningJob._start_time > job_timeout: + runningJob._timeout = job_timeout + runningJob._stop_time = time.time() + runningJob.die() + # display the status if enabled if stdscr: status_pad.erase() @@ -802,8 +830,8 @@ class WorkflowCommon: text, color = { job.Status.NOT_STARTED: ('was not run', 'GREY40'), job.Status.SUCCESS: ('succeeded', 'DARK_GREEN'), - job.Status.FAILED: ('failed', 'DARK_RED') - }[job.get_status()] + job.Status.FAILED: ('failed', 'DARK_RED'), + job.Status.TIMEOUT: ('timed out', 'YELLOW') }[job.get_status()] text = job.name + ' ' + text diff --git a/test/SIM_test_varserv/RUN_test/unit_test.py b/test/SIM_test_varserv/RUN_test/unit_test.py index e2de1e92..afd494eb 100644 --- a/test/SIM_test_varserv/RUN_test/unit_test.py +++ b/test/SIM_test_varserv/RUN_test/unit_test.py @@ -5,7 +5,7 @@ from trick.unit_test import * def main(): - trick.var_server_set_port(4000) + trick.var_server_set_port(40000) trick.var_ascii() trick.real_time_enable() trick.exec_set_software_frame(0.01) @@ -15,7 +15,7 @@ def main(): trick.var_server_create_udp_socket('', 48000) trick.var_server_create_multicast_socket('224.10.10.10','', 47000) - trick.exec_set_terminate_time(1000.0) + trick.exec_set_terminate_time(100.0) varServerPort = trick.var_server_get_port() test_output = ( os.getenv("TRICK_HOME") + "/trick_test/SIM_test_varserv.xml" ) diff --git a/test/SIM_test_varserv/models/test_client/test_client.cpp b/test/SIM_test_varserv/models/test_client/test_client.cpp index ffc1aefb..6d172d39 100644 --- a/test/SIM_test_varserv/models/test_client/test_client.cpp +++ b/test/SIM_test_varserv/models/test_client/test_client.cpp @@ -12,7 +12,7 @@ #include #include #include -#include + #include #include "trick/var_binary_parser.hh" @@ -44,20 +44,14 @@ class Socket { return -1; } - int value = 1; - if (setsockopt(_socket_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &value, (socklen_t) sizeof(value)) < 0) { - std::cout << "init_multicast: Socket option failed" << std::endl; - return -1; - } - - if (setsockopt(_socket_fd, SOL_SOCKET, SO_REUSEPORT, (char *) &value, sizeof(value)) < 0) { - perror("setsockopt: reuseport"); - } - struct sockaddr_in serv_addr; serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(port); // convert to weird network byte format - serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); + + if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0) { + std::cout << "Invalid address/ Address not supported" << std::endl; + return -1; + } tries = 0; int connection_status; @@ -81,7 +75,8 @@ class Socket { _port = port; int tries = 0; - _socket_fd = socket(AF_INET, SOCK_DGRAM, 0); + while ((_socket_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 && tries < max_retries) tries++; + if (_socket_fd < 0) { std::cout << "init_multicast: Socket open failed" << std::endl; return -1; @@ -93,10 +88,6 @@ class Socket { return -1; } - if (setsockopt(_socket_fd, SOL_SOCKET, SO_REUSEPORT, (char *) &value, sizeof(value)) < 0) { - perror("setsockopt: reuseport"); - } - struct ip_mreq mreq; // Use setsockopt() to request that the kernel join a multicast group mreq.imr_multiaddr.s_addr = inet_addr(_hostname.c_str()); @@ -109,10 +100,9 @@ class Socket { struct sockaddr_in sockin ; - // Set up local interface - // We must bind to the multicast address + // Set up destination address sockin.sin_family = AF_INET; - sockin.sin_addr.s_addr = inet_addr(_hostname.c_str()); + sockin.sin_addr.s_addr = htonl(INADDR_ANY); sockin.sin_port = htons(_port); if ( bind(_socket_fd, (struct sockaddr *) &sockin, (socklen_t) sizeof(sockin)) < 0 ) { @@ -120,14 +110,6 @@ class Socket { return -1; } - char loopch = 1; - - if(setsockopt(_socket_fd, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&loopch, sizeof(loopch)) < 0) - { - perror("Setting IP_MULTICAST_LOOP error"); - return -1; - } - _initialized = true; return 0; } @@ -163,25 +145,6 @@ class Socket { ret = receive(); } - std::vector receive_bytes() { - unsigned char buffer[SOCKET_BUF_SIZE]; - int numBytes = recv(_socket_fd, buffer, SOCKET_BUF_SIZE, 0); - if (numBytes < 0) { - std::cout << "Failed to read from socket" << std::endl; - } - - std::vector bytes; - for (int i = 0; i < numBytes; i++) { - bytes.push_back(buffer[i]); - } - - return bytes; - } - - void operator>> (std::string& ret) { - ret = receive(); - } - std::vector receive_bytes() { unsigned char buffer[SOCKET_BUF_SIZE]; int numBytes = recv(_socket_fd, buffer, SOCKET_BUF_SIZE, 0); @@ -228,6 +191,7 @@ class Socket { int _socket_fd; bool _initialized; bool _multicast_socket; + }; class VariableServerTest : public ::testing::Test { @@ -303,42 +267,12 @@ class VariableServerTestAltListener : public ::testing::Test { static int numSession; }; -#ifndef __APPLE__ -class VariableServerTestMulticast : public ::testing::Test { - protected: - VariableServerTestMulticast() { - socket_status = socket.init("", 47000, SOCK_DGRAM); - multicast_listener.init_multicast("224.10.10.10", 47000); - - if (socket_status == 0) { - std::stringstream request; - request << "trick.var_set_client_tag(\"multicast_VSTest"; - request << numSession++; - request << "\") \n"; - - socket << request.str(); - } - } - ~VariableServerTestMulticast() { - socket.close(); - multicast_listener.close(); - } - - Socket socket; - Socket multicast_listener; - - int socket_status; - - static int numSession; -}; -int VariableServerTestMulticast::numSession = 0; -#endif - int VariableServerTest::numSession = 0; int VariableServerUDPTest::numSession = 0; int VariableServerTestAltListener::numSession = 0; + /**********************************************************/ /* Helpful constants and functions */ /**********************************************************/ @@ -411,108 +345,6 @@ void load_checkpoint (Socket& socket, const std::string& checkpoint_name) { socket << "trick.var_unpause()\n"; } -/*****************************************/ -/* Multicast Test */ -/*****************************************/ - -#ifndef __APPLE__ - -TEST_F (VariableServerTestMulticast, Strings) { - if (socket_status != 0) { - FAIL(); - } - - std::string reply; - socket << "trick.var_send_once(\"vsx.vst.o\")\n"; - std::string expected("5\tYou will rejoice to hear that no disaster has accompanied the commencement of an enterprise which you have regarded with such evil forebodings. I arrived here yesterday, and my first task is to assure my dear sister of my welfare and increasing confidence in the success of my undertaking."); - - multicast_listener >> reply; - - EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0); - - - expected = std::string("5\tI am already far north of London, and as I walk in the streets of Petersburgh, I feel a cold northern breeze play upon my cheeks, which braces my nerves and fills me with delight. Do you understand this feeling?"); - socket << "trick.var_send_once(\"vsx.vst.p\")\n"; - - multicast_listener >> reply; - - EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0); - - // TODO: Does wchar actually work? - // expected = std::string("5\tThis breeze, which has travelled from the regions towards which I am advancing, gives me a foretaste of those icy climes. Inspirited by this wind of promise, my daydreams become more fervent and vivid."); - // socket << "trick.var_send_once(\"vsx.vst.q\")\n"; - - // socket >> reply; - - // std::cout << "\tExpected: " << expected << "\n\tActual: " << reply << std::endl; - - // EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0); -} - - -TEST_F (VariableServerTestMulticast, AddRemove) { - if (socket_status != 0) { - FAIL(); - } - - std::string reply; - std::string expected; - - int max_tries = 3; - int tries = 0; - - socket << "trick.var_add(\"vsx.vst.c\")\n"; - multicast_listener >> reply; - expected = std::string("0 -1234"); - - tries = 0; - while (strcmp_IgnoringWhiteSpace(reply, expected) != 0 && tries++ < max_tries) { - multicast_listener >> reply; - } - - EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0) << "Expected: " << expected << "\tAcutal: " << reply; - - multicast_listener >> reply; - tries = 0; - while (strcmp_IgnoringWhiteSpace(reply, expected) != 0 && tries++ < max_tries) { - multicast_listener >> reply; - } - - EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0) << "Expected: " << expected << "\tAcutal: " << reply; - - socket << "trick.var_add(\"vsx.vst.m\")\n"; - multicast_listener >> reply; - expected = std::string("0 -1234 1"); - tries = 0; - while (strcmp_IgnoringWhiteSpace(reply, expected) != 0 && tries++ < max_tries) { - multicast_listener >> reply; - } - EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0) << "Expected: " << expected << "\tAcutal: " << reply; - - socket << "trick.var_remove(\"vsx.vst.m\")\n"; - multicast_listener >> reply; - expected = std::string("0 -1234"); - tries = 0; - while (strcmp_IgnoringWhiteSpace(reply, expected) != 0 && tries++ < max_tries) { - multicast_listener >> reply; - } - - EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0) << "Expected: " << expected << "\tAcutal: " << reply; - - socket << "trick.var_add(\"vsx.vst.n\")\n"; - multicast_listener >> reply; - expected = std::string("0 -1234 0,1,2,3,4"); - tries = 0; - while (strcmp_IgnoringWhiteSpace(reply, expected) != 0 && tries++ < max_tries) { - multicast_listener >> reply; - } - EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0) << "Expected: " << expected << "\tAcutal: " << reply; - - socket << "trick.var_exit()\n"; -} - -#endif - /************************************/ /* UDP Tests */ /************************************/ @@ -601,7 +433,6 @@ TEST_F (VariableServerTestAltListener, Strings) { socket >> reply; EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0); - } TEST_F (VariableServerTestAltListener, AddRemove) { @@ -679,10 +510,6 @@ TEST_F (VariableServerTestAltListener, RestartAndSet) { /* Normal case tests */ /*********************************************/ -void spin (Socket& socket, int wait_cycles = 5) { - socket.receive(); -} - TEST_F (VariableServerTest, Strings) { if (socket_status != 0) { FAIL(); @@ -749,42 +576,7 @@ TEST_F (VariableServerTest, NoExtraTab) { EXPECT_STREQ(reply.c_str(), expected.c_str()); } -TEST_F (VariableServerTest, NoExtraTab) { - if (socket_status != 0) { - FAIL(); - } - - std::string reply; - std::string expected; - - socket << "trick.var_add(\"vsx.vst.c\")\n"; - socket >> reply; - expected = std::string("0\t-1234\n"); - - EXPECT_STREQ(reply.c_str(), expected.c_str()); - - socket >> reply; - - EXPECT_STREQ(reply.c_str(), expected.c_str()); - - socket << "trick.var_add(\"vsx.vst.m\")\n"; - socket >> reply; - expected = std::string("0\t-1234\t1\n"); - - EXPECT_STREQ(reply.c_str(), expected.c_str()); - - socket << "trick.var_remove(\"vsx.vst.m\")\n"; - socket >> reply; - expected = std::string("0\t-1234\n"); - - socket << "trick.var_add(\"vsx.vst.n\")\n"; - socket >> reply; - expected = std::string("0\t-1234\t0,1,2,3,4\n"); - - EXPECT_STREQ(reply.c_str(), expected.c_str()); -} - -TEST_F (VariableServerTest, DISABLED_AddRemove) { +TEST_F (VariableServerTest, AddRemove) { if (socket_status != 0) { FAIL(); } @@ -811,10 +603,6 @@ TEST_F (VariableServerTest, DISABLED_AddRemove) { socket << "trick.var_remove(\"vsx.vst.m\")\n"; socket >> reply; expected = std::string("0 -1234"); - - socket << "trick.var_add(\"vsx.vst.n\")\n"; - socket >> reply; - expected = std::string("0 -1234 0,1,2,3,4"); EXPECT_EQ(strcmp_IgnoringWhiteSpace(reply, expected), 0); @@ -1115,7 +903,7 @@ TEST_F (VariableServerTest, Multicast) { FAIL() << "Multicast Socket failed to initialize."; } - int max_multicast_tries = 100; + int max_multicast_tries = 10000; int tries = 0; bool found = false; @@ -1263,18 +1051,7 @@ TEST_F (VariableServerTest, Freeze) { ASSERT_EQ(mode, MODE_RUN); } -<<<<<<< HEAD -<<<<<<< HEAD -======= - -<<<<<<< HEAD ->>>>>>> 6fe76071 (Add multicast test) -TEST_F (VariableServerTest, DISABLED_CopyAndWriteModes) { -======= -======= ->>>>>>> d158199e (Added var_send_list_size test, various other fixes) TEST_F (VariableServerTest, CopyAndWriteModes) { ->>>>>>> f9665aba (Fix and test var_send_stdio) if (socket_status != 0) { FAIL(); } @@ -1357,6 +1134,8 @@ TEST_F (VariableServerTest, CopyAndWriteModes) { command = "trick.var_clear()\n" + test_vars_command + "trick.var_set_write_mode(1)\ntrick.var_add(\"vsx.vst.e\")\ntrick.var_add(\"vsx.vst.f\")\ntrick.var_unpause()\n"; socket << command; + spin(socket); + parse_message(socket.receive()); expected = "-123456 123456"; EXPECT_EQ(strcmp_IgnoringWhiteSpace(vars, expected), 0) << "Received: " << vars << " Expected: " << expected; @@ -1384,7 +1163,7 @@ TEST_F (VariableServerTest, CopyAndWriteModes) { socket << command; // Same issue as copy mode 1 write mode 0 - // spin(); + spin(socket); parse_message(socket.receive()); expected = "-1234567 123456789"; EXPECT_EQ(strcmp_IgnoringWhiteSpace(vars, expected), 0) << "Received: " << vars << " Expected: " << expected; @@ -1410,6 +1189,8 @@ TEST_F (VariableServerTest, CopyAndWriteModes) { command = "trick.var_clear()\n" + test_vars_command + "trick.var_set_copy_mode(2)\ntrick.var_set_write_mode(1)\ntrick.var_set_frame_multiple(" + std::to_string(frame_multiple) + ")\ntrick.var_set_frame_offset(" + std::to_string(frame_offset) + ")\ntrick.var_add(\"vsx.vst.i\")\ntrick.var_add(\"vsx.vst.j\")\ntrick.var_unpause()\n"; socket << command; + spin(socket); + expected = "1234.5677 -1234.56789"; parse_message(socket.receive()); EXPECT_EQ(strcmp_IgnoringWhiteSpace(vars, expected), 0) << "Received: " << vars << " Expected: " << expected; @@ -1472,38 +1253,6 @@ TEST_F (VariableServerTest, send_stdio) { std::stringstream message_stream(message); std::string token; -<<<<<<< HEAD -======= - std::getline(message_stream, token, ' '); - int message_type = stoi(token); - std::getline(message_stream, token, ' '); - int stream_num = stoi(token); - std::getline(message_stream, token, '\n'); - int text_size = stoi(token); - std::string text; - std::getline(message_stream, text); - - EXPECT_EQ (message_type, 4); - EXPECT_EQ (stream_num, 1); - EXPECT_EQ (text_size, 41); - - EXPECT_EQ(text, std::string("This message should redirect to varserver")); -} - -TEST_F (VariableServerTest, RestartAndSet) { - if (socket_status != 0) { - FAIL(); - } - - std::string reply; - std::string expected; - - socket << "trick.var_add(\"vsx.vst.c\")\n"; - socket >> reply; - expected = std::string("0\t-1234\n"); - - EXPECT_EQ(reply, expected); ->>>>>>> f9665aba (Fix and test var_send_stdio) int message_type; int stream_num; @@ -1528,234 +1277,6 @@ TEST_F (VariableServerTest, RestartAndSet) { } -#ifndef __APPLE__ - -<<<<<<< HEAD -<<<<<<< HEAD -TEST_F (VariableServerTest, MulticastAfterRestart) { -======= -======= - -TEST_F (VariableServerTest, MulticastAfterRestart) { - if (socket_status != 0) { - FAIL(); - } - - socket << "trick.var_server_set_user_tag(\"VSTestServer\")\n"; - - Socket multicast_socket; - multicast_socket.init_multicast("224.3.14.15", 9265); - - int max_multicast_tries = 100; - int tries = 0; - bool found = false; - - char expected_hostname[80]; - gethostname(expected_hostname, 80); - int expected_port = 4000; - - // get expected username - struct passwd *passp = getpwuid(getuid()) ; - char * expected_username; - if ( passp == NULL ) { - expected_username = strdup("unknown") ; - } else { - expected_username = strdup(passp->pw_name) ; - } - - // Don't care about PID, just check that it's > 0 - char * expected_sim_dir = "trick/test/SIM_test_varserv"; // Compare against the end of the string for this one - // Don't care about cmdline name - char * expected_input_file = "RUN_test/unit_test.py"; - // Don't care about trick_version - char * expected_tag = "VSTestServer"; - - // Variables to be populated by the multicast message - char actual_hostname[80]; - unsigned short actual_port = 0; - char actual_username[80]; - int actual_pid = 0; - char actual_sim_dir[80]; - char actual_cmdline_name[80]; - char actual_input_file[80]; - char actual_trick_version[80]; - char actual_tag[80]; - unsigned short actual_duplicate_port = 0; - - while (!found && tries++ < max_multicast_tries) { - std::string broadcast_data = multicast_socket.receive(); - sscanf(broadcast_data.c_str(), "%s\t%hu\t%s\t%d\t%s\t%s\t%s\t%s\t%s\t%hu\n" , actual_hostname, &actual_port , - actual_username , &actual_pid , actual_sim_dir , actual_cmdline_name , - actual_input_file , actual_trick_version , actual_tag, &actual_duplicate_port) ; - - if (strcmp(actual_hostname, expected_hostname) == 0 && strcmp(expected_tag, actual_tag) == 0) { - found = true; - EXPECT_STREQ(actual_hostname, expected_hostname); - EXPECT_EQ(actual_port, expected_port); - EXPECT_STREQ(actual_username, expected_username); - EXPECT_GT(actual_pid, 0); - std::string expected_sim_dir_str(expected_sim_dir); - std::string actual_sim_dir_str(actual_sim_dir); - std::string end_of_actual = actual_sim_dir_str.substr(actual_sim_dir_str.length() - expected_sim_dir_str.length(), actual_sim_dir_str.length()); - EXPECT_EQ(expected_sim_dir_str, end_of_actual); - EXPECT_STREQ(actual_input_file, expected_input_file); - EXPECT_STREQ(actual_tag, expected_tag); - EXPECT_EQ(actual_duplicate_port, expected_port); - } - } - - if (!found) - FAIL() << "Multicast message never received"; -} - ->>>>>>> 6490e49d (Add more tests, error handling) -TEST_F (VariableServerTest, LargeMessages) { ->>>>>>> f9665aba (Fix and test var_send_stdio) - if (socket_status != 0) { - FAIL(); - } - - socket << "trick.var_server_set_user_tag(\"VSTestServer\")\n"; - -<<<<<<< HEAD - Socket multicast_socket; - if (multicast_socket.init_multicast("224.3.14.15", 9265) != 0) { - FAIL() << "Multicast Socket failed to initialize."; - } - - int max_multicast_tries = 100; - int tries = 0; - bool found = false; - - char expected_hostname[80]; - gethostname(expected_hostname, 80); - int expected_port = 40000; - - // get expected username - struct passwd *passp = getpwuid(getuid()) ; - char * expected_username; - if ( passp == NULL ) { - expected_username = strdup("unknown") ; - } else { - expected_username = strdup(passp->pw_name) ; - } - - // Don't care about PID, just check that it's > 0 - char * expected_sim_dir = "trick/test/SIM_test_varserv"; // Compare against the end of the string for this one - // Don't care about cmdline name - char * expected_input_file = "RUN_test/unit_test.py"; - // Don't care about trick_version - char * expected_tag = "VSTestServer"; - - // Variables to be populated by the multicast message - char actual_hostname[80]; - unsigned short actual_port = 0; - char actual_username[80]; - int actual_pid = 0; - char actual_sim_dir[80]; - char actual_cmdline_name[80]; - char actual_input_file[80]; - char actual_trick_version[80]; - char actual_tag[80]; - unsigned short actual_duplicate_port = 0; -======= - socket << "trick.var_pause()\n"; - - for (int i = 0; i < 4000; i++) { - std::string var_add = "trick.var_add(\"vsx.vst.large_arr[" + std::to_string(i) + "]\")\n"; - socket << var_add; - } - - // Message size limit is 8192 - // Message size should be somewhere between the limit and limit-5 due to size of variable - const static int msg_size_limit = 8192; - - auto get_last_number_in_string = [](const std::string& s) -> int { - int index = s.size() - 1; - while (!isdigit(s.at(index))) { index--; } - int num = 0; - int exp = 0; - while (isdigit(s.at(index))) { - num += (s.at(index) - '0') * pow(10, exp); - index--; - exp++; - } - return num; - }; - - auto get_first_number_in_string = [](const std::string& s) -> int { - std::stringstream message_stream(s); - std::string token; - std::getline(message_stream, token, '\t'); - if (token.size() == 0) { std::getline(message_stream, token, '\t'); } - int ret = stoi(token); - return ret; - }; - - socket.clear_buffered_data(); - - bool ready = false; - while (!ready) { - socket << "trick.var_send_list_size()\n"; - socket >> reply; - if (reply == std::string("3\t4000\n")) - ready = true; - } - - int new_reply_first = 0; - int prev_reply_last = 0; - - socket << "trick.var_send()\n"; - - socket >> reply; - new_reply_first = get_first_number_in_string(reply); - prev_reply_last = get_last_number_in_string(reply); - EXPECT_EQ(new_reply_first, 0); - EXPECT_TRUE(reply.size() <= msg_size_limit && reply.size() >= msg_size_limit-5); - - while (prev_reply_last != 3999) { - socket >> reply; - new_reply_first = get_first_number_in_string(reply); - - EXPECT_TRUE(reply.size() <= msg_size_limit); - EXPECT_EQ(prev_reply_last + 1, new_reply_first); ->>>>>>> d158199e (Added var_send_list_size test, various other fixes) - -<<<<<<< HEAD - while (!found && tries++ < max_multicast_tries) { - std::string broadcast_data = multicast_socket.receive(); - sscanf(broadcast_data.c_str(), "%s\t%hu\t%s\t%d\t%s\t%s\t%s\t%s\t%s\t%hu\n" , actual_hostname, &actual_port , - actual_username , &actual_pid , actual_sim_dir , actual_cmdline_name , - actual_input_file , actual_trick_version , actual_tag, &actual_duplicate_port) ; - - if (strcmp(actual_hostname, expected_hostname) == 0 && strcmp(expected_tag, actual_tag) == 0) { - found = true; - EXPECT_STREQ(actual_hostname, expected_hostname); - EXPECT_EQ(actual_port, expected_port); - EXPECT_STREQ(actual_username, expected_username); - EXPECT_GT(actual_pid, 0); - std::string expected_sim_dir_str(expected_sim_dir); - std::string actual_sim_dir_str(actual_sim_dir); - std::string end_of_actual = actual_sim_dir_str.substr(actual_sim_dir_str.length() - expected_sim_dir_str.length(), actual_sim_dir_str.length()); - EXPECT_EQ(expected_sim_dir_str, end_of_actual); - EXPECT_STREQ(actual_input_file, expected_input_file); - EXPECT_STREQ(actual_tag, expected_tag); - EXPECT_EQ(actual_duplicate_port, expected_port); - } -======= - prev_reply_last = get_last_number_in_string(reply); ->>>>>>> 6490e49d (Add more tests, error handling) - } - - if (!found) - FAIL() << "Multicast message never received"; -} - -<<<<<<< HEAD -#endif - -======= ->>>>>>> f9665aba (Fix and test var_send_stdio) TEST_F (VariableServerTest, Binary) { if (socket_status != 0) { FAIL(); @@ -1918,7 +1439,7 @@ int main(int argc, char **argv) { int result = RUN_ALL_TESTS(); Socket socket; - socket.init("localhost", 4000); + socket.init("localhost", 40000); if (result == 0) { // Success @@ -1932,4 +1453,4 @@ int main(int argc, char **argv) { socket << "trick.stop() \n"; return result; -} +} \ No newline at end of file diff --git a/trick_source/sim_services/MonteCarlo/MonteCarlo_master_shutdown.cpp b/trick_source/sim_services/MonteCarlo/MonteCarlo_master_shutdown.cpp index 38b67256..1b53cb75 100644 --- a/trick_source/sim_services/MonteCarlo/MonteCarlo_master_shutdown.cpp +++ b/trick_source/sim_services/MonteCarlo/MonteCarlo_master_shutdown.cpp @@ -6,6 +6,7 @@ #include "trick/message_type.h" #include "trick/tc_proto.h" #include "trick/exec_proto.h" +#include "trick/SysThread.hh" /** @par Detailed Design: */ void Trick::MonteCarlo::master_shutdown() { @@ -41,6 +42,8 @@ void Trick::MonteCarlo::master_shutdown() { except_return = -2 ; } + SysThread::ensureAllShutdown(); + exit(except_return); } diff --git a/trick_source/sim_services/MonteCarlo/MonteCarlo_slave_funcs.cpp b/trick_source/sim_services/MonteCarlo/MonteCarlo_slave_funcs.cpp index 777381cf..8fd5bf19 100644 --- a/trick_source/sim_services/MonteCarlo/MonteCarlo_slave_funcs.cpp +++ b/trick_source/sim_services/MonteCarlo/MonteCarlo_slave_funcs.cpp @@ -1,5 +1,7 @@ #include "trick/MonteCarlo.hh" +#include "trick/SysThread.hh" + /** @par Detailed Design: */ void Trick::MonteCarlo::slave_shutdown() { @@ -8,6 +10,8 @@ void Trick::MonteCarlo::slave_shutdown() { /**
  • Run the shutdown jobs and exit. */ run_queue(&slave_shutdown_queue, "in slave_shutdown queue") ; + SysThread::ensureAllShutdown(); + exit(0); } @@ -15,6 +19,9 @@ void Trick::MonteCarlo::slave_shutdown() { void Trick::MonteCarlo::slave_die() { /**