diff --git a/bin/trick-CP b/bin/trick-CP index 3ff9d311..4ede38f2 100755 --- a/bin/trick-CP +++ b/bin/trick-CP @@ -15,10 +15,19 @@ $trick_home = dirname($trick_bin) ; #### Handle arguments #### $numArgs = $#ARGV + 1; $makefileAddArgs = ' '; +$sdefine_dir = "."; +$sdefine = "S_define"; +$makefile = "makefile"; foreach $argnum (0 .. $#ARGV) { $arg = $ARGV[$argnum]; if ($arg =~ /(\w+)=(\w+)/ ) { $makefileAddArgs = $makefileAddArgs . $1 . "=" . $2 . " "; + } elsif ($arg eq "-C" || $arg eq "--directory" ) { + $sdefine_dir = abs_path($ARGV[$argnum + 1]); + $makefileAddArgs = $makefileAddArgs . " -C $sdefine_dir "; + $sdefine = $sdefine_dir . "/${sdefine}"; + $makefile = $sdefine_dir . "/${makefile}"; + shift } elsif ($arg =~ /-d/ ) { $makefileAddArgs = $makefileAddArgs . " debug "; } elsif ($arg =~ /-t/ ) { @@ -30,17 +39,17 @@ foreach $argnum (0 .. $#ARGV) { } } -if ( -f "S_define" ) { - if ( not -w "." ) { - print getcwd() , " is not writable\n" ; - print "CP aborted\n" ; +if ( -f $sdefine ) { + if ( not -w $sdefine_dir ) { + print $sdefine_dir , " is not writable\n" ; + print "trick-CP aborted\n" ; exit 1 ; } - unlink "build/Makefile_sim", "makefile" ; + unlink "build/Makefile_sim", $makefile ; $makefile_text = do { local $/; } ; $makefile_text =~ s/SUB_TRICK_HOME/$trick_home/ ; $makefile_text =~ s/SUB_TRICK_BIN/$trick_bin/ ; - open MAKEFILE, ">makefile" ; + open MAKEFILE, ">$makefile" ; print MAKEFILE $makefile_text ; close MAKEFILE ; system("make -f makefile " . $makefileAddArgs) ; @@ -90,6 +99,11 @@ Print the trick-CP help message (this message) Send CP output to FILE_NAME +=item B<-C> | B<--directory> I + +Build a simulation located in a different directory than the current +working directory. + =item B<-p> | B<--no-python> Exclude python input processor from simulation. diff --git a/include/trick/DataRecordGroup.hh b/include/trick/DataRecordGroup.hh index 43ff0fae..421167f5 100644 --- a/include/trick/DataRecordGroup.hh +++ b/include/trick/DataRecordGroup.hh @@ -121,6 +121,9 @@ namespace Trick { /** Current file size for data record file in bytes.\n */ uint64_t total_bytes_written; /**< trick_io(**) trick_units(--) */ + /** Bool to signify that the warning for reaching max filesize has been printed */ + bool max_size_warning; + /** Buffer to hold formatted data ready for disk or other destination.\n */ char * writer_buff ; /**< trick_io(**) trick_units(--) */ diff --git a/include/trick/VariableServer.hh b/include/trick/VariableServer.hh index bbb7b0a1..9aee8409 100644 --- a/include/trick/VariableServer.hh +++ b/include/trick/VariableServer.hh @@ -10,6 +10,7 @@ #include #include #include +#include #include #include "trick/tc.h" #include "trick/reference.h" @@ -39,6 +40,11 @@ namespace Trick { */ ~VariableServer() ; + /** + @brief Write a JSON encoded list of Variable Server Connections to the given stream. + */ + friend std::ostream& operator<< (std::ostream& s, Trick::VariableServer& vs); + /** @brief Set up the listen port during default_data so it is available at the start of initialization. */ diff --git a/include/trick/VariableServerReference.hh b/include/trick/VariableServerReference.hh index c5abf94d..6becfd27 100644 --- a/include/trick/VariableServerReference.hh +++ b/include/trick/VariableServerReference.hh @@ -6,6 +6,7 @@ #ifndef VARIABLESERVERREFERENCE_HH #define VARIABLESERVERREFERENCE_HH +#include #include "trick/reference.h" union cv_converter ; @@ -24,6 +25,8 @@ namespace Trick { 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 diff --git a/include/trick/VariableServerThread.hh b/include/trick/VariableServerThread.hh index 08addfc6..1b3ce499 100644 --- a/include/trick/VariableServerThread.hh +++ b/include/trick/VariableServerThread.hh @@ -8,6 +8,7 @@ #include #include +#include #include #include "trick/tc.h" #include "trick/ThreadBase.hh" @@ -27,6 +28,8 @@ namespace Trick { 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() diff --git a/include/trick/variable_server_proto.h b/include/trick/variable_server_proto.h index d3d7dade..26eb6698 100644 --- a/include/trick/variable_server_proto.h +++ b/include/trick/variable_server_proto.h @@ -6,6 +6,7 @@ extern "C" { #endif +void var_server_list_connections(void); const char * var_server_get_hostname(void) ; unsigned short var_server_get_port(void) ; diff --git a/share/trick/makefiles/trickify.mk b/share/trick/makefiles/trickify.mk index 9fd586f9..46579f55 100644 --- a/share/trick/makefiles/trickify.mk +++ b/share/trick/makefiles/trickify.mk @@ -1,6 +1,6 @@ -# This file can be used to create an object file containing the io_* and py_* -# code that Trick would normally generate during the simulation build process. -# Sims can then link against this object file, reducing compilation time. +# This file can be used to create an object file or library containing the io_* +# and py_* code that Trick would normally generate during the simulation build +# process. Sims can then link against that, reducing compilation time. # # To use it, create a directory that includes a file named S_source.hh that # includes all header files for which you want io_* and py_* code generated. @@ -25,9 +25,26 @@ # paths to the header files included by your S_source.hh. For instance: # -I$(HOME)/myproject/foo/include -I$(HOME)/myproject/bar/include # +# TRICKIFY_BUILD_TYPE (optional) +# Valid options are: +# 1. STATIC (.a) +# Create a static library. This will require the use of --whole-archive (on +# Linux) or -all_load/-force_load (on Mac) when linking the sim executeable. +# Trick uses dlsym to dynamically load symbols at run time, but the linker, +# by default, will not include symbols from static libraries that are not +# known to be needed at compile time. +# 2. SHARED (.so) +# Create a shared object (dynamically linked library). This may require the +# use of -rpath to ensure the linker can find the shared object at runtime +# unless you explicitly link against it (as opposed to using -L and -l) +# during compilation. +# 3. PLO (.o) [default] +# Create a partially-linked object. No special linker options are required. +# # TRICKIFY_OBJECT_NAME (optional) -# The name of the generated object file. The default value is trickified.o. -# You should choose something more meaningful, like trickified_myproject.o. +# The name of the generated object file or library. The default value is +# trickified.o. You should choose something more meaningful, especially if +# you're using another build type. # # TRICKIFY_PTYON_DIR (optional) # The directory into which generated Python modules are placed. The default @@ -74,9 +91,11 @@ ifndef TRICKIFY_CXX_FLAGS $(error TRICKIFY_CXX_FLAGS must be set) endif +TRICKIFY_BUILD_TYPE ?= PLO TRICKIFY_OBJECT_NAME ?= trickified.o TRICKIFY_PYTHON_DIR ?= python TRICK_HOME := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))/../../..) +MAKE_OUT ?= build/MAKE_out ifneq ($(wildcard build),) SWIG_OBJECTS := $(shell cat build/S_library_swig) @@ -92,30 +111,26 @@ TRICK_CXXFLAGS += $(TRICKIFY_CXX_FLAGS) # Ensure we can process all headers TRICK_EXT_LIB_DIRS := -# When given a library, the linker will only link in objects that are known to -# be needed at link time. However, Trick uses dlsym to dynamically load the -# objects we'll be creating here. It cannot be known which objects will be -# needed at link time, so the sim has to link them all. In that case, we might -# as well create an object (which will be fully linked in by the sim) instead -# of a library (which would require the use of the -whole-archive option). -# -# One disadvantage of this approach is that we have to link all of the objects -# in this rule no matter how many have changed, whereas ar would allow us to -# replace only the changed objects. However, Trickified projects are -# necessarily used as third-party libraries, and so would be expected to -# change infrequently. Moreover, the methods for force-linking a library differ -# between Linux and Mac, so obviating the need for it simplifies a Trickified -# project's user-facing makefile. $(TRICKIFY_OBJECT_NAME): $(SWIG_OBJECTS) $(IO_OBJECTS) | $(dir $(TRICKIFY_OBJECT_NAME)) $(info $(call COLOR,Linking) $@) - @ld -r -o $@ $^ +ifeq ($(TRICKIFY_BUILD_TYPE),PLO) + @echo $(LD) $(LD_PARTIAL) -o $@ $^ >> $(MAKE_OUT) + $(ECHO_CMD)ld -r -o $@ $^ 2>&1 | $(TEE) -a $(MAKE_OUT); exit $${PIPESTATUS[0]} +else ifeq ($(TRICKIFY_BUILD_TYPE),SHARED) + @echo $(TRICK_CPPC) -shared -o $@ $^ >> $(MAKE_OUT) + $(ECHO_CMD)c++ -shared -o $@ $^ 2>&1 | $(TEE) -a $(MAKE_OUT); exit $${PIPESTATUS[0]} +else ifeq ($(TRICKIFY_BUILD_TYPE),STATIC) + @echo ar rcs $@ $^ >> $(MAKE_OUT) + $(ECHO_CMD)ar rcs $@ $^ 2>&1 | $(TEE) -a $(MAKE_OUT); exit $${PIPESTATUS[0]} +endif $(dir $(TRICKIFY_OBJECT_NAME)) $(TRICKIFY_PYTHON_DIR) build: @mkdir -p $@ $(IO_OBJECTS): %.o: %.cpp $(info $(call COLOR,Compiling) $<) - @$(TRICK_CPPC) $(TRICK_CXXFLAGS) $(TRICK_SYSTEM_CXXFLAGS) -std=c++11 -Wno-invalid-offsetof -MMD -MP -c -o $@ $< + @echo $(TRICK_CPPC) $(TRICK_CXXFLAGS) $(TRICK_SYSTEM_CXXFLAGS) -std=c++11 -Wno-invalid-offsetof -MMD -MP -c -o $@ $< >> $(MAKE_OUT) + $(ECHO_CMD)$(TRICK_CPPC) $(TRICK_CXXFLAGS) $(TRICK_SYSTEM_CXXFLAGS) -std=c++11 -Wno-invalid-offsetof -MMD -MP -c -o $@ $< 2>&1 | $(TEE) -a $(MAKE_OUT) ; exit $${PIPESTATUS[0]} $(IO_OBJECTS:.o=.d): %.d: ; @@ -123,16 +138,19 @@ $(IO_OBJECTS:.o=.d): %.d: ; $(SWIG_OBJECTS): %.o: %.cpp $(info $(call COLOR,Compiling) $<) - @$(TRICK_CPPC) $(TRICK_CXXFLAGS) $(TRICK_SYSTEM_CXXFLAGS) $(PYTHON_INCLUDES) -Wno-unused-parameter -Wno-shadow -c -o $@ $< + @echo $(TRICK_CPPC) $(TRICK_CXXFLAGS) $(TRICK_SYSTEM_CXXFLAGS) $(PYTHON_INCLUDES) -Wno-unused-parameter -Wno-shadow -c -o $@ $< >> $(MAKE_OUT) + $(ECHO_CMD)$(TRICK_CPPC) $(TRICK_CXXFLAGS) $(TRICK_SYSTEM_CXXFLAGS) $(PYTHON_INCLUDES) -Wno-unused-parameter -Wno-shadow -c -o $@ $< 2>&1 | $(TEE) -a $(MAKE_OUT) ; exit $${PIPESTATUS[0]} $(SWIG_OBJECTS:.o=.cpp): %.cpp: %.i | $(TRICKIFY_PYTHON_DIR) $(SWIG_OBJECTS:.o=.i) $(info $(call COLOR,SWIGing) $<) - @$(SWIG) $(TRICK_INCLUDE) $(TRICK_DEFINES) $(TRICK_VERSIONS) $(TRICK_SWIG_FLAGS) -c++ -python -includeall -ignoremissing -w201,303,325,362,389,401,451 -outdir $(TRICKIFY_PYTHON_DIR) -o $@ $< + @echo $(SWIG) $(TRICK_INCLUDE) $(TRICK_DEFINES) $(TRICK_VERSIONS) $(TRICK_SWIG_FLAGS) -c++ -python -includeall -ignoremissing -w201,303,325,362,389,401,451 -outdir $(TRICKIFY_PYTHON_DIR) -o $@ $< >> $(MAKE_OUT) + $(ECHO_CMD)$(SWIG) $(TRICK_INCLUDE) $(TRICK_DEFINES) $(TRICK_VERSIONS) $(TRICK_SWIG_FLAGS) -c++ -python -includeall -ignoremissing -w201,303,325,362,389,401,451 -outdir $(TRICKIFY_PYTHON_DIR) -o $@ $< 2>&1 | $(TEE) -a $(MAKE_OUT) ; exit $${PIPESTATUS[0]} define create_convert_swig_rule build/%_py.i: /%.$1 $$(info $$(call COLOR,Converting) $$<) - ${TRICK_HOME}/$(LIBEXEC)/trick/convert_swig ${TRICK_CONVERT_SWIG_FLAGS} $$< + @echo ${TRICK_HOME}/$(LIBEXEC)/trick/convert_swig ${TRICK_CONVERT_SWIG_FLAGS} $$< >> $(MAKE_OUT) + $(ECHO_CMD)${TRICK_HOME}/$(LIBEXEC)/trick/convert_swig ${TRICK_CONVERT_SWIG_FLAGS} $$< 2>&1 | $(TEE) -a $(MAKE_OUT) ; exit $$${PIPESTATUS[0]} endef EXTENSIONS := H h hh hxx h++ hpp @@ -170,8 +188,9 @@ $(foreach EXTENSION,$(EXTENSIONS),$(eval $(call create_convert_swig_rule,$(EXTEN # http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/ build/S_source.d: | $(dir $@) - @$(TRICK_HOME)/bin/trick-ICG $(TRICK_CXXFLAGS) $(TRICK_SYSTEM_CXXFLAGS) $(TRICK_ICGFLAGS) S_source.hh - @$(TRICK_HOME)/$(LIBEXEC)/trick/make_makefile_swig - @$(TRICK_CC) -MM -MP -MT $@ -MF $@ $(TRICKIFY_CXX_FLAGS) S_source.hh + $(ECHO_CMD)$(TRICK_HOME)/bin/trick-ICG $(TRICK_CXXFLAGS) $(TRICK_SYSTEM_CXXFLAGS) $(TRICK_ICGFLAGS) S_source.hh + $(ECHO_CMD)$(TRICK_HOME)/$(LIBEXEC)/trick/make_makefile_swig 2>&1 | $(TEE) -a $(MAKE_OUT) ; exit $${PIPESTATUS[0]} + @echo $(TRICK_CC) -MM -MP -MT $@ -MF $@ $(TRICKIFY_CXX_FLAGS) S_source.hh >> $(MAKE_OUT) + $(ECHO_CMD) $(TRICK_CC) -MM -MP -MT $@ -MF $@ $(TRICKIFY_CXX_FLAGS) S_source.hh 2>&1 | $(TEE) -a $(MAKE_OUT) ; exit $${PIPESTATUS[0]} -include build/S_source.d diff --git a/trick_source/codegen/Interface_Code_Gen/PrintAttributes.cpp b/trick_source/codegen/Interface_Code_Gen/PrintAttributes.cpp index 8583c5be..6d6725cd 100644 --- a/trick_source/codegen/Interface_Code_Gen/PrintAttributes.cpp +++ b/trick_source/codegen/Interface_Code_Gen/PrintAttributes.cpp @@ -112,27 +112,6 @@ static void _mkdir(const char *dir) { } } -// this is a subset of tests on the header file to determine if this file is not excluded for any reason. -bool PrintAttributes::isFileIncluded(std::string header_file_name) { - // several tests require the real path of the header file. - char * realPath = almostRealPath(header_file_name.c_str()) ; - - if ( realPath != NULL ) { - // Only include user directories (not system dirs like /usr/include) - if ( hsd.isPathInUserDir(realPath) ) { - // Don't process files in excluded directories - if ( (hsd.isPathInExclude(realPath) == false) and (hsd.isPathInICGExclude(realPath) == false) ) { - // Only include files that do not have ICG: (No) - // hasICGNo uses original header name, not the real path - if ( ! cs.hasICGNo(header_file_name) ) { - return true ; - } - } - } - } - return false ; -} - bool PrintAttributes::openIOFile(const std::string& header_file_name) { /** * There are a lot of conditions to be met in order to open an IO file. We store the headers @@ -258,18 +237,9 @@ void PrintAttributes::printClass( ClassValues * cv ) { outfile.close(); } - if (!isHeaderExcluded(fileName)) { + if (!isHeaderExcluded(fileName, false)) { printer->printClassMap(class_map_outfile, cv); } -/* - char* realPath = almostRealPath(fileName.c_str()); - if (realPath) { - if (isFileIncluded(fileName) or hsd.isPathInExtLib(realPath)) { - printer->printClassMap(class_map_outfile, cv); - } - free(realPath); - } -*/ } void PrintAttributes::printEnum(EnumValues* ev) { @@ -293,14 +263,9 @@ void PrintAttributes::printEnum(EnumValues* ev) { outfile.close() ; } - if (!isHeaderExcluded(fileName)) { + if (!isHeaderExcluded(fileName), false) { printer->printEnumMap(enum_map_outfile, ev); } -/* - if (isFileIncluded(fileName)) { - printer->printEnumMap(enum_map_outfile, ev) ; - } -*/ } void PrintAttributes::createMapFiles() { diff --git a/trick_source/codegen/Interface_Code_Gen/PrintAttributes.hh b/trick_source/codegen/Interface_Code_Gen/PrintAttributes.hh index 5a381419..dc7c09cf 100644 --- a/trick_source/codegen/Interface_Code_Gen/PrintAttributes.hh +++ b/trick_source/codegen/Interface_Code_Gen/PrintAttributes.hh @@ -101,7 +101,6 @@ class PrintAttributes { bool openIOFile(const std::string& header_file_name) ; - bool isFileIncluded(std::string header_file_name) ; bool isIOFileOutOfDate(std::string header_file_name, std::string io_file_name ) ; bool hasBeenProcessed(EnumValues& enumValues); bool hasBeenProcessed(ClassValues& classValues); diff --git a/trick_source/codegen/Interface_Code_Gen/TranslationUnitVisitor.cpp b/trick_source/codegen/Interface_Code_Gen/TranslationUnitVisitor.cpp index 788bf6d0..99a7039b 100644 --- a/trick_source/codegen/Interface_Code_Gen/TranslationUnitVisitor.cpp +++ b/trick_source/codegen/Interface_Code_Gen/TranslationUnitVisitor.cpp @@ -40,48 +40,58 @@ bool TranslationUnitVisitor::TraverseDecl(clang::Decl *d) { break ; case clang::Decl::CXXRecord : { clang::CXXRecordDecl * crd = static_cast(d) ; + clang::RecordDecl * rd = crd->getDefinition() ; + bool is_forward_declaration = false; + /* The definition of the record must exist before we can process it. The definition is NULL when this is only a forward declaration of a class */ + if ( rd == NULL ) { + is_forward_declaration = true; + } /* Sometimes rd is not NULL when we still only have a forward declaration because the file that defines the class is included before processing this fwd declare. In this case the CXXRecordDecl file name will not match the current file name, and is in fact empty */ - clang::RecordDecl * rd = crd->getDefinition() ; - if ( rd != NULL ) { + else { std::string rd_file = getFileName(ci , rd->RBRACELOC(), hsd) ; std::string crd_file = getFileName(ci , crd->RBRACELOC(), hsd) ; - if (!crd_file.empty() and !crd_file.compare(rd_file)) { - //crd->dump() ; std::cout << std::endl ; - if ( isInUserCode(ci , crd->RBRACELOC(), hsd) ) { - CXXRecordVisitor cvis(ci , cs, hsd , pa, true) ; - - cvis.TraverseCXXRecordDecl(static_cast(d)) ; - pa.printClass(cvis.get_class_data()) ; - - /* Check to see if the struct/class is forward declared in the same file. - If it is, then remove the notation that it is forward declared. This - is to allow C structs to be forward declared and typedeffed and io_src - code will be generated for both the original structure name and typedeffed - name. - - struct Astruct ; - typedef struct Astruct {} Bstruct ; - */ - std::set< std::string >::iterator it ; - std::string file_name = getFileName(ci , d->GETLOCEND(), hsd) ; - std::string source_type = cvis.get_class_data()->getName() ; - it = fwd_declared_classes[file_name].find(source_type) ; - if ( it != fwd_declared_classes[file_name].end() ) { - fwd_declared_classes[file_name].erase(it) ; - } - } + if (crd_file.empty() || crd_file.compare(rd_file)) { + is_forward_declaration = true; } - } else { + } + + if (is_forward_declaration) { // These are forward declarations. Insert this into the set of fwd declares keyed by the current file. if ( ! crd->getNameAsString().empty() ) { fwd_declared_classes[getFileName(ci , d->GETLOCEND(), hsd)].insert(crd->getNameAsString()) ; } } + else { + //crd->dump() ; std::cout << std::endl ; + if ( isInUserCode(ci , crd->RBRACELOC(), hsd) ) { + CXXRecordVisitor cvis(ci , cs, hsd , pa, true) ; + + cvis.TraverseCXXRecordDecl(static_cast(d)) ; + pa.printClass(cvis.get_class_data()) ; + + /* Check to see if the struct/class is forward declared in the same file. + If it is, then remove the notation that it is forward declared. This + is to allow C structs to be forward declared and typedeffed and io_src + code will be generated for both the original structure name and typedeffed + name. + + struct Astruct ; + typedef struct Astruct {} Bstruct ; + */ + std::set< std::string >::iterator it ; + std::string file_name = getFileName(ci , d->GETLOCEND(), hsd) ; + std::string source_type = cvis.get_class_data()->getName() ; + it = fwd_declared_classes[file_name].find(source_type) ; + if ( it != fwd_declared_classes[file_name].end() ) { + fwd_declared_classes[file_name].erase(it) ; + } + } + } } break ; case clang::Decl::Enum : { diff --git a/trick_source/sim_services/DataRecord/DataRecordGroup.cpp b/trick_source/sim_services/DataRecord/DataRecordGroup.cpp index ad16655a..4a36939e 100644 --- a/trick_source/sim_services/DataRecord/DataRecordGroup.cpp +++ b/trick_source/sim_services/DataRecord/DataRecordGroup.cpp @@ -73,6 +73,7 @@ Trick::DataRecordGroup::DataRecordGroup( std::string in_name ) : writer_num(0), max_file_size(1<<30), // 1 GB total_bytes_written(0), + max_size_warning(false), writer_buff(NULL), single_prec_only(false), buffer_type(DR_Buffer), @@ -692,6 +693,14 @@ int Trick::DataRecordGroup::write_data(bool must_write) { writer_num++ ; } + + if(!max_size_warning && (total_bytes_written > max_file_size)) { + std::cerr << "WARNING: Data record max file size " << (static_cast(max_file_size))/(1<<20) << "MB reached.\n" + "https://github.com/nasa/trick/wiki/Data-Record#changing-the-max-file-size-of-a-data-record-group-ascii-and-binary-only" + << std::endl; + max_size_warning = true; + } + pthread_mutex_unlock(&buffer_mutex) ; } diff --git a/trick_source/sim_services/VariableServer/VariableReference.cpp b/trick_source/sim_services/VariableServer/VariableReference.cpp index 207d9154..925adec3 100644 --- a/trick_source/sim_services/VariableServer/VariableReference.cpp +++ b/trick_source/sim_services/VariableServer/VariableReference.cpp @@ -63,6 +63,16 @@ Trick::VariableReference::VariableReference(REF2 * in_ref ) { } +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; +} + Trick::VariableReference::~VariableReference() { free(ref) ; free(buffer_in) ; diff --git a/trick_source/sim_services/VariableServer/VariableServer.cpp b/trick_source/sim_services/VariableServer/VariableServer.cpp index b88881eb..6bee8820 100644 --- a/trick_source/sim_services/VariableServer/VariableServer.cpp +++ b/trick_source/sim_services/VariableServer/VariableServer.cpp @@ -1,5 +1,6 @@ #include +#include #include "trick/VariableServer.hh" #include "trick/tc_proto.h" @@ -17,6 +18,26 @@ Trick::VariableServer::VariableServer() : Trick::VariableServer::~VariableServer() { } +std::ostream& Trick::operator<< (std::ostream& s, Trick::VariableServer& vs) { + std::map < pthread_t , VariableServerThread * >::iterator it ; + + s << "{\"variable_server_connections\":[" << std::endl; + int count = 0; + int n_connections = (int)vs.var_server_threads.size(); + for ( it = vs.var_server_threads.begin() ; it != vs.var_server_threads.end() ; it++ ) { + s << "{" << std::endl; + s << *(*it).second; + s << "}"; + if ((n_connections-count)>1) { + s << "," ; + } + s << std::endl; + count ++; + } + s << "]}" << std::endl; + return s; +} + bool Trick::VariableServer::get_enabled() { return enabled ; } diff --git a/trick_source/sim_services/VariableServer/VariableServerThread.cpp b/trick_source/sim_services/VariableServer/VariableServerThread.cpp index ff01da48..56f15153 100644 --- a/trick_source/sim_services/VariableServer/VariableServerThread.cpp +++ b/trick_source/sim_services/VariableServer/VariableServerThread.cpp @@ -1,4 +1,5 @@ +#include #include #include "trick/VariableServerThread.hh" #include "trick/exec_proto.h" @@ -63,6 +64,50 @@ Trick::VariableServerThread::~VariableServerThread() { free( stripped_msg ) ; } + +std::ostream& Trick::operator<< (std::ostream& s, Trick::VariableServerThread& vst) { + + std::vector ::iterator it; + + struct sockaddr_in otherside; + socklen_t len = (socklen_t)sizeof(otherside); + + s << " \"connection\":{" << std::endl; + s << " \"client_tag\":\"" << vst.connection.client_tag << "\"," << std::endl; + + int err = getpeername(vst.connection.socket, (struct sockaddr*)&otherside, &len); + + if (err == 0) { + s << " \"client_IP_address\":\"" << inet_ntoa(otherside.sin_addr) << "\"," << std::endl; + s << " \"client_port\":\"" << ntohs(otherside.sin_port) << "\"," << std::endl; + } else { + s << " \"client_IP_address\":\"unknown\"," << std::endl; + s << " \"client_port\":\"unknown\"," << std::endl; + } + + if (vst.binary_data) { + s << " \"format\":\"BINARY\","; + } else { + s << " \"format\":\"ASCII\","; + } + s << std::endl; + s << " \"update_rate\":" << vst.update_rate << "," << std::endl; + + s << " \"variables\":[" << std::endl; + + int n_vars = (int)vst.vars.size(); + for (int i=0 ; i1) { + s << "," ; + } + s << std::endl; + } + s << " ]" << std::endl; + s << " }" << std::endl; + return s; +} + void Trick::VariableServerThread::set_vs_ptr(Trick::VariableServer * in_vs) { vs = in_vs ; } diff --git a/trick_source/sim_services/VariableServer/var_server_ext.cpp b/trick_source/sim_services/VariableServer/var_server_ext.cpp index 104dd730..4cb9610d 100644 --- a/trick_source/sim_services/VariableServer/var_server_ext.cpp +++ b/trick_source/sim_services/VariableServer/var_server_ext.cpp @@ -387,6 +387,10 @@ Trick::VariableServer * var_server_get_var_server() { return the_vs ; } +extern "C" void var_server_list_connections(void) { + std::cout << *the_vs << std::endl; +} + /** * @relates Trick::VariableServer * @copydoc Trick::VariableServer::get_hostname