Refactor and test Variable Server.

- Split VariableServerThread into VariableServerSession and VariableReference classes
- Use C++ streams for data handling
- Unit tests
This commit is contained in:
Jacqueline Deans 2022-08-23 13:47:56 -05:00
parent e89bf083b2
commit c2e42f4ef4
78 changed files with 5021 additions and 2690 deletions

4
.gitignore vendored
View File

@ -40,4 +40,6 @@ archive/
trickops_logs/
*.gcda
*.gcno
coverage.info
coverage.info
*.dSYM

View File

@ -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

View File

@ -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 <string>
// #include <atomic>
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

View File

@ -0,0 +1,47 @@
#ifndef CLIENT_LISTENER_HH
#define CLIENT_LISTENER_HH
#include "trick/tc.h"
#include "trick/TCConnection.hh"
#include <string>
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

View File

@ -0,0 +1,28 @@
/*
PURPOSE: ( Encapsulate multicast functionality. )
*/
#include <string>
#include <vector>
#include <arpa/inet.h>
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<struct sockaddr_in> addresses; /**< trick_io(**) Addresses to multicast to. */
int mcast_socket; /**< trick_io(**) Socket opened in initialization. */
int initialized; /**< trick_io(**) Whether manager is ready */
};
}

View File

@ -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

View File

@ -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 <time.h>
#include <vector>
#include <iostream>
#include <trick/reference.h>
#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

View File

@ -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() ;

View File

@ -8,8 +8,11 @@
#include <string>
#include <iostream>
#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(**) */

View File

@ -1,44 +0,0 @@
/*
PURPOSE:
(VariableServerReference)
*/
#ifndef VARIABLESERVERREFERENCE_HH
#define VARIABLESERVERREFERENCE_HH
#include <iostream>
#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

View File

@ -0,0 +1,481 @@
/*************************************************************************
PURPOSE: (Represent the state of a variable server connection.)
**************************************************************************/
#ifndef WSSESSION_HH
#define WSSESSION_HH
#include <vector>
#include <string>
#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("<in_name>") @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("<in_name>", "<units_name>") @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("<in_name>") @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("<var_name>", "<units_name>") @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("<in_name>") @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("<in_name_list>", <number of variables in list>) @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(<level>) @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(<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(<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(<on_off>) @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(<mult>) @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(<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(<mult>) @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(<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(<on_off>) @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(<in_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<VariableReference *>& 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<VariableReference *>& 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<VariableReference *>& given_vars, VS_MESSAGE_TYPE message_type);
int write_ascii_data(const std::vector<VariableReference *>& 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<VariableReference *> 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

View File

@ -11,16 +11,21 @@
#include <iostream>
#include <pthread.h>
#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("<in_name>") @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("<in_name>", "<units_name>") @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("<in_name>") @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("<var_name>", "<units_name>") @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("<in_name>") @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("<in_name_list>", <number of variables in list>) @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(<in_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(<level>) @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(<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(<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(<on_off>) @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(<mult>) @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(<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(<mult>) @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(<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(<on_off>) @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<VariableReference *> 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<VariableReference *> 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<VariableReference *>& 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<VariableReference *>& 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 <VariableReference *> 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

View File

@ -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;
};
};

View File

@ -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 <pthread.h>
#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

View File

@ -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)

View File

@ -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)

View File

@ -12,4 +12,4 @@ test_client: models/test_client/test_client.cpp
clean_test_client:
rm -f models/test_client/test_client

View File

@ -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<unsigned char> 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<unsigned char> bytes;
for (int i = 0; i < numBytes; i++) {
bytes.push_back(buffer[i]);
}
return bytes;
}
void operator>> (std::string& ret) {
ret = receive();
}
std::vector<unsigned char> 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

View File

@ -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)

View File

@ -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('=================================================================================================')

View File

@ -492,7 +492,7 @@ std::vector<std::string> split (std::string& str, const char delim) {
std::stringstream ss(str);
std::string s;
std::vector<std::string> ret;
while (std::getline(ss, s, delim)) {
while (ss >> s) {
ret.push_back(s);
}
return ret;
@ -526,9 +526,11 @@ template <typename T>
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<T>(split(reply, '\t')[1]);
}
@ -554,10 +556,13 @@ std::vector<T> 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<T>(reply);
}
@ -604,6 +609,13 @@ int main(int argc, char *argv[])
std::vector<double> 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<double> replyData = trickResponseConvert<double>(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);
}

View File

@ -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

View File

@ -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());
}
}

View File

@ -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
)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -1,80 +1,736 @@
#include <stdlib.h>
#include <iostream>
#include <udunits2.h>
#include "trick/VariableServer.hh"
#include <math.h> // for fpclassify
#include <iomanip> // for setprecision
#include <string.h>
#include <sstream>
#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 <size> bytes from <address> 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 ; ii<strlen(s) ; ii++) {
if (isprint(s[ii])) {
os << s[ii];
} else {
switch ((s)[ii]) {
case '\n': os << "\\n"; break;
case '\t': os << "\\t"; break;
case '\b': os << "\\b"; break;
case '\a': os << "\\a"; break;
case '\f': os << "\\f"; break;
case '\r': os << "\\n"; break;
case '\v': os << "\\v"; break;
case '\"': os << "\\\""; break;
default : {
// Replicating behavior from original vs_format_ascii
char temp_s[6];
sprintf(temp_s, "\\x%02x", s[ii]);
os << temp_s ;
break;
}
}
}
}
}
int Trick::VariableReference::getSizeAscii() const {
std::stringstream ss;
writeValueAscii(ss);
return ss.str().length();
}
int Trick::VariableReference::writeValueAscii( std::ostream& out ) const {
// This is copied and modified from vs_format_ascii
// There's a lot here that doesn't make sense to me that I need to come back to
// There seems to be a huge buffer overflow issue in the original.
// Only strings are checked for length, arrays aren't
// But using a stream instead should make that better
// The way that arrays are handled seems weird.
if (!isWriteReady()) {
return -1;
}
int bytes_written = 0;
void * buf_ptr = write_buffer ;
while (bytes_written < size) {
bytes_written += var_info->attr->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<const char *>(reinterpret_cast<char *>(&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<const char *>(reinterpret_cast<char *>(&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<const char *>(reinterpret_cast<char *>(&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<short *> (in);
short * short_out = reinterpret_cast<short *> (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<int *> (in);
int * int_out = reinterpret_cast<int *> (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<double *> (in);
double * double_out = reinterpret_cast<double *> (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;
}

View File

@ -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 ;
}

View File

@ -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, "<empty>");
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) ;

View File

@ -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(&copy_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 ; i<n_vars ; i++) {
s << *(session.session_variables[i]);
if ((n_vars-i)>1) {
s << "," ;
}
s << "\n";
}
s << " ]\n";
return s;
}

View File

@ -0,0 +1,401 @@
#include <string.h>
#include <iostream>
#include <sstream>
#include <stdlib.h>
#include <udunits2.h>
#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<std::string> split (const std::string& str, const char delim) {
std::stringstream ss(str);
std::string s;
std::vector<std::string> 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<std::string> 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<VariableReference *> 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:
// <message_indicator><message_size><number_of_variables>
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") ;
}

View File

@ -2,12 +2,14 @@
#include <iostream>
#include <string.h>
#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() ;

View File

@ -0,0 +1,35 @@
#include <iostream>
#include <string.h>
#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<VariableReference *>& given_vars, bool cyclical) {
if (given_vars.size() == 0) {
return 0;
}
if ( pthread_mutex_trylock(&copy_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(&copy_mutex) ;
}
return 0;
}

View File

@ -2,11 +2,11 @@
#include <iostream>
#include <string.h>
#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 ;

View File

@ -0,0 +1,188 @@
/*
PURPOSE: (Allows clients to get and set Trick parameters)
PROGRAMMERS: (((Alex Lin) (NASA) (8/06) (--)))
*/
#include <iostream>
#include <sstream>
#include <pthread.h>
#include <iomanip> // 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<VariableReference *>& 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<std::pair<int,int>> 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<int,int>(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<int,int>(total_size, num_vars));
// Now write out all of these messages
int var_index = 0;
for (std::pair<int,int> 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<VariableReference *>& 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<VariableReference *>& 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(&copy_mutex) == 0 ) {
// Check that all of the variables are staged
for (VariableReference * variable : given_vars ) {
if (!variable->isStaged()) {
pthread_mutex_unlock(&copy_mutex) ;
return 1;
}
}
// Swap buffer_in and buffer_out for each vars[ii].
for (VariableReference * variable : given_vars ) {
variable->prepareForWrite();
}
pthread_mutex_unlock(&copy_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;
}

View File

@ -0,0 +1,17 @@
#include <sstream>
#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 ;
}

View File

@ -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(&copy_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 ; i<n_vars ; i++) {
s << *(vst.vars[i]);
if ((n_vars-i)>1) {
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);
}

View File

@ -1,516 +0,0 @@
#include <string.h>
#include <iostream>
#include <sstream>
#include <stdlib.h>
#include <udunits2.h>
#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<std::string> split (const std::string& str, const char delim) {
std::stringstream ss(str);
std::string s;
std::vector<std::string> 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<std::string> 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<VariableReference *> 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:
// <message_indicator><message_size><number_of_variables>
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") ;
}

View File

@ -1,9 +0,0 @@
#include "trick/VariableServer.hh"
#include "trick/release.h"
void Trick::VariableServerThread::wait_for_accept() {
while ( connection_accepted == false ) {
RELEASE() ;
}
}

View File

@ -1,105 +0,0 @@
#include <iostream>
#include <string.h>
#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<VariableReference *> given_vars, bool cyclical) {
if (given_vars.size() == 0) {
return 0;
}
if ( pthread_mutex_trylock(&copy_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(&copy_mutex) ;
}
return 0;
}

View File

@ -1,44 +0,0 @@
#include <stdlib.h>
#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 ;
}

View File

@ -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);

View File

@ -1,45 +0,0 @@
#include <stdlib.h>
#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(&copy_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 <VariableReference *>::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(&copy_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);
}

View File

@ -1,322 +0,0 @@
/*
PURPOSE: (Allows clients to get and set Trick parameters)
PROGRAMMERS: (((Alex Lin) (NASA) (8/06) (--)))
*/
#include <iostream>
#include <pthread.h>
#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<VariableReference *>& 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<VariableReference *>& 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(&copy_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(&copy_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<VariableReference *> 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(&copy_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(&copy_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);
}
}
}

View File

@ -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 ;
}

View File

@ -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) ;

View File

@ -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) ;

View File

@ -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) ;

View File

@ -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) ;

View File

@ -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) ;

View File

@ -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) ;

View File

@ -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) ;

View File

@ -2,41 +2,42 @@
#include <stdio.h>
#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 ;
}

View File

@ -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 ;
}

View File

@ -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 ;
}

View File

@ -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<pthread_t> 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 ;
}

View File

@ -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()) ;

View File

@ -0,0 +1,4 @@
lcov_html/*
*.o
*_test
*.info

View File

@ -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

View File

@ -0,0 +1,80 @@
#ifndef TEST_CONNECTION_HH
#define TEST_CONNECTION_HH
#include "trick/ClientConnection.hh"
#include <iostream>
#include <vector>
#include <queue>
#include <string.h>
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 <std::string> queued_messages;
std::vector <std::string> ascii_messages_written;
std::vector <char *> binary_messages_written;
std::string client_tag;
bool valid = true;
};
#endif

View File

@ -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)));
}
}
}
}
}

View File

@ -0,0 +1,56 @@
/******************************TRICK HEADER*************************************
PURPOSE: ( Common definitions for testing the VariableReference class )
*******************************************************************************/
#include <gtest/gtest.h>
#include <iostream>
#include <iomanip>
#include <limits>
#include <vector>
#include "trick/MemoryManager.hh"
#include "trick/VariableReference.hh"
#include "trick/UdUnits.hh"
#include <vector>
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<int> 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() {}
};

View File

@ -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<double>::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<double>::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");
}

View File

@ -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<unsigned char>(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<unsigned char>(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<unsigned char>(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<unsigned char>(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<unsigned char>(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<unsigned char>(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<unsigned char>(actual_bytes[i]), expected_bytes[i]);
}
}

View File

@ -0,0 +1,190 @@
/******************************TRICK HEADER*************************************
PURPOSE: ( Tests for the VariableServerSession class )
*******************************************************************************/
#include <gtest/gtest.h>
#include <iostream>
#include <iomanip>
#include <limits>
#include <vector>
#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<int>(), i);
} catch (std::exception& ex) {
FAIL() << ex.what();
}
}
}

View File

@ -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) ;
}

View File

@ -1,265 +0,0 @@
/*
PURPOSE: (Allows clients to get and set Trick parameters)
PROGRAMMERS: (((Keith Vetter) (LinCom) (September 2001) (--)))
*/
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits>
#include <udunits2.h>
#include <sstream>
#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);
}

View File

@ -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)

View File

@ -0,0 +1 @@
#include "trick/ClientConnection.hh"

View File

@ -0,0 +1,115 @@
#include <unistd.h>
#include <iostream>
#include <sys/select.h>
#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, "<empty>");
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;
}

View File

@ -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}

View File

@ -0,0 +1,63 @@
#include "trick/MulticastManager.hh"
#include <string.h>
#include <vector>
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;
}

View File

@ -0,0 +1,117 @@
#include "trick/TCConnection.hh"
#include "trick/tc.h"
#include "trick/tc_proto.h"
#include <sstream>
#include <iostream>
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);
}

View File

@ -1,2 +1,2 @@
*.o
TEST_var_binary_parser
TEST_var_binary_parser

View File

@ -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)
$(CXX) $(TRICK_SYSTEM_LDFLAGS) $(CPPFLAGS) -o $@ $^ -L${TRICK_HOME}/lib_${TRICK_HOST_CPU} $(LIBS) $(EXEC_LINK_LIBS)

View File

@ -0,0 +1,51 @@
/*************************************************************************
PURPOSE: (Represent the state of a variable server websocket connection.)
**************************************************************************/
#ifndef WSSESSION_HH
#define WSSESSION_HH
#include <vector>
#include <string>
#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<VariableServerVariable*> session_variables;
bool cyclicSendEnabled;
long long nextTime;
long long intervalTimeTics;
};
WebSocketSession* makeVariableServerSession( struct mg_connection *nc );
#endif

View File

@ -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.')