From 54bc7641f43cf5c34da6bb8eefb89042627dd60f Mon Sep 17 00:00:00 2001 From: Paul Sutton Date: Wed, 4 Sep 2013 16:25:53 +0100 Subject: [PATCH 01/24] Adding analytics --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index d7b3edf..ccdd169 100644 --- a/README.md +++ b/README.md @@ -26,3 +26,5 @@ The installation guide can be found here: http://www.softwareradiosystems.com/re ## License Iris is licensed under LGPL v3. For more information see LICENSE. + +[![githalytics.com alpha](https://cruel-carlota.pagodabox.com/565a545f5d61e93dd441e8ee1eea0a25 "githalytics.com")](http://githalytics.com/softwareradiosystems/iris_core) From 542a22888060731061e73877714f5198c84c64be Mon Sep 17 00:00:00 2001 From: Bitdeli Chef Date: Wed, 4 Sep 2013 16:03:37 +0000 Subject: [PATCH 02/24] Add a Bitdeli badge to README --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index ccdd169..2021fe5 100644 --- a/README.md +++ b/README.md @@ -28,3 +28,7 @@ The installation guide can be found here: http://www.softwareradiosystems.com/re Iris is licensed under LGPL v3. For more information see LICENSE. [![githalytics.com alpha](https://cruel-carlota.pagodabox.com/565a545f5d61e93dd441e8ee1eea0a25 "githalytics.com")](http://githalytics.com/softwareradiosystems/iris_core) + + +[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/softwareradiosystems/iris_core/trend.png)](https://bitdeli.com/free "Bitdeli Badge") + From db98fac9f3a9d33f5e2eb60f149e68d9c3c0f7d2 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 16 Oct 2013 17:23:53 +0200 Subject: [PATCH 03/24] Rework colorful logging for console output only --- irisapi/Logging.h | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/irisapi/Logging.h b/irisapi/Logging.h index 4bd12f3..bcb72fc 100644 --- a/irisapi/Logging.h +++ b/irisapi/Logging.h @@ -57,6 +57,9 @@ inline std::string NowTime(); /// The log levels available for logging enum LogLevel {LDEBUG, LINFO, LWARNING, LERROR, LFATAL}; +/// Convert a log level to a color +inline std::string ToColor(LogLevel level); + /** The logging policy. This class determines the output streams of the logging element. * * Logger objects use a policy to determine the output streams. @@ -83,14 +86,15 @@ class LoggingPolicy return &thePolicy; } - void output(const std::string& msg) + void output(const std::string& msg, const LogLevel level) { boost::mutex::scoped_lock lock(mutex_); // Output to console if(consoleStream) { - fprintf(consoleStream, "%s", msg.c_str()); + std::string tmp = ToColor(level) + msg + "\033[0m"; + fprintf(consoleStream, "%s", tmp.c_str()); fflush(consoleStream); } @@ -141,6 +145,7 @@ class Logger : boost::noncopyable protected: std::ostringstream os; + LogLevel level; }; /// Constructor sets LoggingPolicy if required @@ -161,6 +166,8 @@ inline std::ostringstream& Logger::Get(LogLevel level) tmp += std::string(sizeof("WARNING")+1 - tmp.size(), ' '); os << tmp << " "; + + this->level = level; return os; } @@ -169,7 +176,7 @@ inline std::ostringstream& Logger::Get(LogLevel level) inline Logger::~Logger() { os << std::endl; - getPolicy()->output(os.str()); + getPolicy()->output(os.str(), level); } /// Get ref to pointer to the current LoggingPolicy @@ -227,6 +234,17 @@ inline std::string NowTime() return to_simple_string(microsec_clock::local_time()); } +/// Get the escape sequence to set console color for a given level +inline std::string ToColor(LogLevel level) +{ + static const char* const buffer[] = {"\033[36m" /* DEBUG is cyan */, + "\033[0m" /* INFO is default */, + "\033[33m" /* WARNING is yellow */, + "\033[31m" /* ERROR is red */, + "\033[31m\033[1m" /* FATAL is red, bold */}; + return buffer[level]; +} + } // namespace iris #endif // IRISAPI_LOGGING_H_ From 7f900e46a3980fcd4db032cffb66a54d1675d2c6 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 10 Jan 2014 09:37:02 +0100 Subject: [PATCH 04/24] enable compiling with -fPIC parameter on ARM architectures --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e90207..ad3dd91 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -162,9 +162,9 @@ ADD_CUSTOM_TARGET(uninstall # Macro to add -fPIC property to static libs ######################################################################## MACRO(IRIS_SET_PIC) - IF( CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" ) + IF( CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "^arm" ) SET_TARGET_PROPERTIES(${ARGV} PROPERTIES COMPILE_FLAGS -fPIC) - ENDIF( CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" ) + ENDIF( CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "^arm" ) ENDMACRO(IRIS_SET_PIC) ######################################################################## From 9bf6c5a6f382abf844c899ab00c463d9d1fb1181 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 4 Mar 2014 14:49:46 +0100 Subject: [PATCH 05/24] allow PhyComponents to receive commands --- irisapi/PhyComponent.h | 6 ++++++ src/engines/phyengine/PhyEngine.cpp | 22 +++++++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/irisapi/PhyComponent.h b/irisapi/PhyComponent.h index d557e31..71ddcf5 100644 --- a/irisapi/PhyComponent.h +++ b/irisapi/PhyComponent.h @@ -123,6 +123,12 @@ class PhyComponent numRuns_++; }; + /// Post a command to this component + void postCommand(Command command) + { + prison_.release(command); + }; + /// \name To be implemented in derived classes. //@{ virtual void calculateOutputTypes(std::map& inputTypes, diff --git a/src/engines/phyengine/PhyEngine.cpp b/src/engines/phyengine/PhyEngine.cpp index 1658a4d..267d73b 100644 --- a/src/engines/phyengine/PhyEngine.cpp +++ b/src/engines/phyengine/PhyEngine.cpp @@ -319,7 +319,7 @@ namespace iris { (*compIt)->setValue(reconfig.parameterName, reconfig.parameterValue); (*compIt)->parameterHasChanged(reconfig.parameterName); - LOG(LINFO) << "Reconfigured parameter " << reconfig.parameterName << " : " << reconfig.parameterValue; + LOG(LDEBUG) << "Reconfigured parameter " << reconfig.parameterName << " : " << reconfig.parameterValue; bFound = true; } } @@ -332,8 +332,24 @@ namespace iris void PhyEngine::postCommand(Command command) { - LOG(LERROR) << "PhyComponents do not support commands - failed to post command " << - command.commandName << " to " << command.componentName; + bool bFound = false; + + //Find component and post command + vector< b::shared_ptr >::iterator compIt; + for(compIt = components_.begin(); compIt != components_.end(); ++compIt) + { + if((*compIt)->getName() == command.componentName) + { + (*compIt)->postCommand(command); + bFound = true; + } + } + + if(!bFound) + { + LOG(LERROR) << "Posting command failed: could not find component: " << command.componentName; + } + } void PhyEngine::activateEvent(Event &e) From 2c0af26c96a4f175d1c49ef61adcc2f1dcb38e77 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 12 Mar 2014 11:41:51 +0100 Subject: [PATCH 06/24] add generic metadata header --- irisapi/Metadata.h | 189 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 irisapi/Metadata.h diff --git a/irisapi/Metadata.h b/irisapi/Metadata.h new file mode 100644 index 0000000..2aa96e8 --- /dev/null +++ b/irisapi/Metadata.h @@ -0,0 +1,189 @@ +/** + * \file Metadata.h + * \version 1.0 + * + * \section COPYRIGHT + * + * Copyright 2012-2013 The Iris Project Developers. See the + * COPYRIGHT file at the top-level directory of this distribution + * and at http://www.softwareradiosystems.com/iris/copyright.html. + * + * \section LICENSE + * + * This file is part of the Iris Project. + * + * Iris is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * Iris is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * A copy of the GNU Lesser General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + * \section DESCRIPTION + * + * A metadata class that holds different datatypes in a map + * accessible through keywords. + */ + +#ifndef METADATA_H +#define METADATA_H + +#include +#include + +class MetadataBase : boost::noncopyable +{ +public: + MetadataBase() + : description(""), + source("") + {} + virtual ~MetadataBase(){} + std::string description; ///< Optional, a description of the metadata + std::string source; ///< Optional, component that created the metadata +}; + + +template +class Metadata : public MetadataBase +{ +public: + T data; ///< The actual data passed. +}; + + +class MetadataMap +{ + typedef std::map > MetadataContainer; +public: + /** + * Default constructor + */ + MetadataMap() {} + + + /** + * Provide a constructor with samplerate and timestamp + */ + MetadataMap(double s = 0, double t = 0) + { + setMetadata("sampleRate", s); + setMetadata("timeStamp", t); + } + + /** + * Copy constructor to initialize mutex properly + */ + MetadataMap(const MetadataMap& other) : mutex_() {} + + + /** + * Assignment operator + */ + MetadataMap& operator=(const MetadataMap& other) + { + boost::mutex::scoped_lock lock(mutex_); + map_ = other.map_; // Actual map is copied using default operator + return *this; + } + + + /** + * Set metadata. + * + * @param key The key + * @param e The data to store + */ + template + void setMetadata(const std::string key, T e) + { + boost::mutex::scoped_lock lock(mutex_); + boost::shared_ptr b(new Metadata); + boost::dynamic_pointer_cast< Metadata >(b)->data = e; + map_[key] = b; + } + + + /** + * Tries to retrieve a specific key from the metadata. + * + * @param key The key to look for + * @param e A reference to the variable that should hold the metadata. + * @return True if data could be retrieved, false otherwise + */ + template + bool getMetadata(const std::string key, T& e) + { + if (hasMetadata(key)) { + boost::mutex::scoped_lock lock(mutex_); + boost::shared_ptr b = map_[key]; + e = boost::dynamic_pointer_cast< Metadata >(b)->data; + return true; + } + return false; + } + + + /** + * Tries to delete a specific key from the metadata. + * + * @param The key to delete + * @return True if key could be deleted, false otherwise + */ + bool removeMetadata(const std::string key) + { + boost::mutex::scoped_lock lock(mutex_); + if (hasMetadata(key)) { + map_.erase(key); + return true; + } + return false; + } + + + /** + * Checks whether there is metadata at all. + * + * @return True if metadata is available, false otherwise + */ + bool hasMetadata() const { + boost::mutex::scoped_lock lock(mutex_); + return (map_.empty() ? false : true); + } + + + /** + * Checks for a specific key inside metadata. + * + * @param The key to look for + * @return True if metadata is available, false otherwise + */ + bool hasMetadata(const std::string key) const { + boost::mutex::scoped_lock lock(mutex_); + return (map_.find(key) == map_.end() ? false : true); + } + + + /** + * Return the number of metadata items. + * + * @return The number of items stored + */ + size_t getMetadataCount() const { + boost::mutex::scoped_lock lock(mutex_); + return map_.size(); + } + +private: + MetadataContainer map_; ///< The container for storing the data. + mutable boost::mutex mutex_; ///< Mutex used for thread safety. +}; + +#endif // METADATA_H From 0f2ce0db4b572663d07c206b000fce57287e5627 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 12 Mar 2014 11:42:40 +0100 Subject: [PATCH 07/24] add testcase for metadata class --- tests/CMakeLists.txt | 1 + tests/Metadata_test.cpp | 174 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 175 insertions(+) create mode 100644 tests/Metadata_test.cpp diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 4271b4b..97e799f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -58,6 +58,7 @@ SET(test_sources Interval_test.cpp Logging_test.cpp MemoryManager_test.cpp + Metadata_test.cpp PhyEngine_test.cpp RadioRepresentation_test.cpp ReconfigurationManager_test.cpp diff --git a/tests/Metadata_test.cpp b/tests/Metadata_test.cpp new file mode 100644 index 0000000..3040546 --- /dev/null +++ b/tests/Metadata_test.cpp @@ -0,0 +1,174 @@ +/** + * \file Metadata_test.cpp + * \version 1.0 + * + * \section COPYRIGHT + * + * Copyright 2012-2013 The Iris Project Developers. See the + * COPYRIGHT file at the top-level directory of this distribution + * and at http://www.softwareradiosystems.com/iris/copyright.html. + * + * \section LICENSE + * + * This file is part of the Iris Project. + * + * Iris is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * Iris is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * A copy of the GNU Lesser General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + * \section DESCRIPTION + * + * Main test file for the Metadata class. + */ + +#define BOOST_TEST_MODULE MetadataTest + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "irisapi/StackDataBuffer.h" +#include "iris/DataBuffer.h" + +using namespace std; +using namespace iris; + +BOOST_AUTO_TEST_SUITE (MetadataTest) + +BOOST_AUTO_TEST_CASE(MetadataBasicTest) +{ + StackDataSet* stackDataSource = NULL; + BOOST_CHECK_NO_THROW(stackDataSource = new StackDataSet); + BOOST_REQUIRE(stackDataSource != NULL); + + BOOST_CHECK_EQUAL(stackDataSource->metadata.hasMetadata(), true); + BOOST_CHECK_EQUAL(stackDataSource->metadata.hasMetadata("timeStamp"), true); + BOOST_CHECK_EQUAL(stackDataSource->metadata.hasMetadata("sampleRate"), true); + BOOST_CHECK_EQUAL(stackDataSource->metadata.hasMetadata("deadbeef"), false); + + int i = 11; + stackDataSource->metadata.setMetadata("integer", i); + + BOOST_CHECK_EQUAL(stackDataSource->metadata.hasMetadata(), true); + BOOST_CHECK_EQUAL(stackDataSource->metadata.hasMetadata("integer"), true); + BOOST_CHECK_EQUAL(stackDataSource->metadata.hasMetadata("float"), false); + + int out; + stackDataSource->metadata.getMetadata("integer", out); + BOOST_CHECK_EQUAL(out, i); + + float f = 3.14; + stackDataSource->metadata.setMetadata("float", f); + BOOST_CHECK_EQUAL(stackDataSource->metadata.hasMetadata("float"), true); + + float out2; + bool ret = stackDataSource->metadata.getMetadata("notthere", out2); + BOOST_CHECK_EQUAL(ret, false); + + ret = stackDataSource->metadata.getMetadata("float", out2); + BOOST_CHECK_EQUAL(ret, true); + BOOST_CHECK_EQUAL(out2, f); + + // Check if vectors are working + std::vector int_vec_in; + int_vec_in.push_back(10); + int_vec_in.push_back(20); + int_vec_in.push_back(30); + stackDataSource->metadata.setMetadata("intvector", int_vec_in); + BOOST_CHECK_EQUAL(stackDataSource->metadata.hasMetadata("intvector"), true); + + std::vector int_vec_out; + ret = stackDataSource->metadata.getMetadata("intvector", int_vec_out); + BOOST_CHECK_EQUAL(int_vec_out.size(), 3); + + // Check if the data is equal + for(int i = 0; i < 3; i++) { + BOOST_CHECK_EQUAL(int_vec_in.at(i), int_vec_out.at(i)); + } + + delete stackDataSource; +} + +BOOST_AUTO_TEST_CASE(MetadataStackDataSetCopyTest) +{ + // First create two StackDataSet objects + StackDataSet* stackDataSource = NULL; + BOOST_CHECK_NO_THROW(stackDataSource = new StackDataSet); + BOOST_REQUIRE(stackDataSource != NULL); + + StackDataSet* stackDataDest = NULL; + BOOST_CHECK_NO_THROW(stackDataDest = new StackDataSet); + BOOST_REQUIRE(stackDataDest != NULL); + + // Both should have the default metadata timeStamp and sampleRate + BOOST_CHECK_EQUAL(stackDataSource->metadata.hasMetadata("timeStamp"), true); + BOOST_CHECK_EQUAL(stackDataSource->metadata.hasMetadata("sampleRate"), true); + BOOST_CHECK_EQUAL(stackDataDest->metadata.hasMetadata("timeStamp"), true); + BOOST_CHECK_EQUAL(stackDataDest->metadata.hasMetadata("sampleRate"), true); + + // Create artificial metadata and attach it to source + float f = 3.14; + stackDataSource->metadata.setMetadata("float", f); + std::vector int_vec; + int_vec.push_back(10); + int_vec.push_back(20); + int_vec.push_back(30); + stackDataSource->metadata.setMetadata("intvector", int_vec); + + // Now simply copy the metadata to the destionation + stackDataDest->metadata = stackDataSource->metadata; + + // Check if this looks alright (two are there by default, plus the two we added) + BOOST_CHECK_EQUAL(stackDataDest->metadata.getMetadataCount(), 4); + + float out; + stackDataDest->metadata.getMetadata("float", out); + BOOST_CHECK_EQUAL(out, f); + + std::vector int_vec_out; + bool ret = stackDataSource->metadata.getMetadata("intvector", int_vec_out); + + delete stackDataDest; + delete stackDataSource; +} + + +BOOST_AUTO_TEST_CASE(MetadataDataSetCopyTest) +{ + StackDataSet* stackDataSource = NULL; + BOOST_CHECK_NO_THROW(stackDataSource = new StackDataSet); + BOOST_REQUIRE(stackDataSource != NULL); + + uint64_t tx_time = 12000223112; + stackDataSource->metadata.setMetadata("tx_time", tx_time); + + DataSet< uint8_t >* dataset = new DataSet< uint8_t >; + dataset->metadata = stackDataSource->metadata; + + uint64_t tx_time_out; + dataset->metadata.getMetadata("tx_time", tx_time_out); + BOOST_CHECK_EQUAL(tx_time, tx_time_out); + + delete dataset; + delete stackDataSource; +} + +BOOST_AUTO_TEST_SUITE_END() + From 35d43d6915df6e0037d205c36970b827b2cfcc14 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 12 Mar 2014 11:43:15 +0100 Subject: [PATCH 08/24] adapt datastructures etc. to new metadata layout --- iris/DataBuffer.h | 2 +- irisapi/DataBufferInterfaces.h | 8 ++++---- irisapi/StackDataBuffer.h | 5 +++-- src/engines/phyengine/PhyDataBuffer.h | 2 +- src/engines/stackengine/StackInTranslator.cpp | 2 +- src/engines/stackengine/StackOutTranslator.cpp | 4 ++-- 6 files changed, 12 insertions(+), 11 deletions(-) diff --git a/iris/DataBuffer.h b/iris/DataBuffer.h index 323561b..0d46c99 100644 --- a/iris/DataBuffer.h +++ b/iris/DataBuffer.h @@ -143,7 +143,7 @@ class DataBuffer : public ReadBuffer, public WriteBuffer isWriteLocked_ = true; if(buffer_[writeIndex_].data.size() != size) buffer_[writeIndex_].data.resize(size); - buffer_[writeIndex_].timeStamp = 0; + buffer_[writeIndex_].metadata.setMetadata("timeStamp", 0); setPtr = &buffer_[writeIndex_]; }; diff --git a/irisapi/DataBufferInterfaces.h b/irisapi/DataBufferInterfaces.h index d4196ac..60efa9f 100644 --- a/irisapi/DataBufferInterfaces.h +++ b/irisapi/DataBufferInterfaces.h @@ -37,6 +37,7 @@ #include #include #include +#include "Metadata.h" namespace iris { @@ -49,13 +50,12 @@ namespace iris template struct DataSet{ std::vector< T, std::allocator > data; //We can change this to another container or - //use a custom allocator if we want - double sampleRate; - double timeStamp; + //use a custom allocator if we want + MetadataMap metadata; //! Constructor initializes our variables DataSet(int l=10, double s=0, double t=0) - :data(l), sampleRate(s), timeStamp(t){} + :data(l), metadata(s, t){} }; /** The DataBufferBase class allows us to store vectors of DataBuffers of different types diff --git a/irisapi/StackDataBuffer.h b/irisapi/StackDataBuffer.h index ba32a08..2c62b11 100644 --- a/irisapi/StackDataBuffer.h +++ b/irisapi/StackDataBuffer.h @@ -43,6 +43,7 @@ #include "irisapi/Exceptions.h" #include "irisapi/TypeInfo.h" +#include "Metadata.h" namespace iris { @@ -62,12 +63,12 @@ struct StackDataSet std::string sourcePortName; ///< Name of the port this was sent from. std::string destPortName; ///< Name of the port this arrived on. std::deque data; ///< The actual data. - double timeStamp; ///< Timestamp for this data. + MetadataMap metadata; ///< Metadata. std::string lastComponent; ///< ?? /// Constructor initializes our variables StackDataSet(double t=0) - : timeStamp(t) + : metadata(0.0, t) {} }; diff --git a/src/engines/phyengine/PhyDataBuffer.h b/src/engines/phyengine/PhyDataBuffer.h index 7e9671a..04c8745 100644 --- a/src/engines/phyengine/PhyDataBuffer.h +++ b/src/engines/phyengine/PhyDataBuffer.h @@ -138,7 +138,7 @@ class PhyDataBuffer : public ReadBuffer, public WriteBuffer isWriteLocked_ = true; if(buffer_[writeIndex_].data.size() != size) buffer_[writeIndex_].data.resize(size); - buffer_[writeIndex_].timeStamp = 0; + buffer_[writeIndex_].metadata.setMetadata("timeStamp", 0); setPtr = &buffer_[writeIndex_]; }; diff --git a/src/engines/stackengine/StackInTranslator.cpp b/src/engines/stackengine/StackInTranslator.cpp index 6500569..a067711 100644 --- a/src/engines/stackengine/StackInTranslator.cpp +++ b/src/engines/stackengine/StackInTranslator.cpp @@ -85,7 +85,7 @@ void StackInTranslator::threadLoop() boost::shared_ptr set(new StackDataSet); set->data.resize(inData->data.size()); std::copy(inData->data.begin(), inData->data.end(), set->data.begin()); - set->timeStamp = inData->timeStamp; + set->metadata = inData->metadata; //Send up to the StackComponent sendUpwards(set); diff --git a/src/engines/stackengine/StackOutTranslator.cpp b/src/engines/stackengine/StackOutTranslator.cpp index 945627f..073960b 100644 --- a/src/engines/stackengine/StackOutTranslator.cpp +++ b/src/engines/stackengine/StackOutTranslator.cpp @@ -86,8 +86,8 @@ namespace iris //Fill the DataSet with info from the StackDataSet std::copy(p->data.begin(), p->data.end(), outData->data.begin()); - outData->timeStamp = p->timeStamp; - outData->sampleRate = 0; + outData->metadata = p->metadata; + outData->metadata.setMetadata("sampleRate", 0); //Release the DataSet outputBuffer_->releaseWriteData(outData); From 0684f496a167fab6644e55ab45dbb9f841029bb9 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Thu, 30 Jan 2014 12:24:40 +0100 Subject: [PATCH 09/24] implement a configurable logging file --- iris/Iris.h | 7 +++++-- iris/System.h | 7 +++++-- src/Iris.cpp | 18 +++++++++++++++--- src/IrisStateMachine.cpp | 2 ++ src/IrisStateMachine.h | 10 ++++++++-- src/Launcher.cpp | 13 +++++++++---- src/System.cpp | 26 ++++++++++++++++++-------- 7 files changed, 62 insertions(+), 21 deletions(-) diff --git a/iris/Iris.h b/iris/Iris.h index c24fcd8..86a6c7f 100644 --- a/iris/Iris.h +++ b/iris/Iris.h @@ -16,12 +16,12 @@ * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. - * + * * Iris is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. - * + * * A copy of the GNU Lesser General Public License can be found in * the LICENSE file in the top-level directory of this distribution * and at http://www.gnu.org/licenses/. @@ -63,6 +63,9 @@ IRIS_DLL bool IRISSetContRepository(std::string rep); /// Set the log level IRIS_DLL bool IRISSetLogLevel(std::string level); +/// Set the logging file +IRIS_DLL bool IRISSetLoggingFile(std::string file); + /** Load the radio * * \param radioConfig The radio configuration to load. diff --git a/iris/System.h b/iris/System.h index 2c49ad0..c5d5aa5 100644 --- a/iris/System.h +++ b/iris/System.h @@ -16,12 +16,12 @@ * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. - * + * * Iris is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. - * + * * A copy of the GNU Lesser General Public License can be found in * the LICENSE file in the top-level directory of this distribution * and at http://www.gnu.org/licenses/. @@ -68,6 +68,9 @@ class System /// Set the log level void setLogLevel(std::string level); + /// Set the logging file + void setLoggingFile(std::string file); + /// Load a radio given a configuration file name bool loadRadio(std::string radioConfig); diff --git a/src/Iris.cpp b/src/Iris.cpp index 740078f..fc53a70 100644 --- a/src/Iris.cpp +++ b/src/Iris.cpp @@ -16,12 +16,12 @@ * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. - * + * * Iris is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. - * + * * A copy of the GNU Lesser General Public License can be found in * the LICENSE file in the top-level directory of this distribution * and at http://www.gnu.org/licenses/. @@ -43,7 +43,7 @@ using namespace iris; boost::scoped_ptr< System > theSystem; string getName() -{ +{ return "Iris"; } @@ -119,6 +119,18 @@ bool IRISSetLogLevel(std::string level) } } +bool IRISSetLoggingFile(std::string file) +{ + if(theSystem == NULL) + { + LOG(LERROR) << "System has not been initialized."; + return false; + }else{ + theSystem->setLoggingFile(file); + return true; + } +} + bool IRISLoadRadio(std::string radioConfig) { if(theSystem == NULL) diff --git a/src/IrisStateMachine.cpp b/src/IrisStateMachine.cpp index 1808e2e..eed3577 100644 --- a/src/IrisStateMachine.cpp +++ b/src/IrisStateMachine.cpp @@ -44,12 +44,14 @@ Active::Active(my_context ctx) : my_base(ctx) std::string sdfRadioRepository = context().getSdfRadioRepository(); std::string contRadioRepository = context().getContRadioRepository(); std::string logLevel = context().getLogLevel(); + std::string loggingFile = context().getLoggingFile(); IRISInitSystem(); IRISSetStackRepository(stackRadioRepository); IRISSetPhyRepository(phyRadioRepository); IRISSetSdfRepository(sdfRadioRepository); IRISSetContRepository(contRadioRepository); IRISSetLogLevel(logLevel); + IRISSetLoggingFile(loggingFile); } Loaded::Loaded(my_context ctx) diff --git a/src/IrisStateMachine.h b/src/IrisStateMachine.h index b5bf1c8..90f5a81 100644 --- a/src/IrisStateMachine.h +++ b/src/IrisStateMachine.h @@ -16,12 +16,12 @@ * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. - * + * * Iris is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. - * + * * A copy of the GNU Lesser General Public License can be found in * the LICENSE file in the top-level directory of this distribution * and at http://www.gnu.org/licenses/. @@ -128,8 +128,12 @@ struct IrisStateMachine : boost::statechart::state_machine< IrisStateMachine, Ac std::string getContRadioRepository() const { return contRadioRepository_; } //! set log level void setLogLevel(std::string level) { logLevel_ = level; } + //! set logging file + void setLoggingFile(std::string file) { loggingFile_ = file; } //! return log level std::string getLogLevel() const { return logLevel_; } + //! return logging file + std::string getLoggingFile() const { return loggingFile_; } //! Reconfigure the radio void reconfigureRadio(); private: @@ -145,6 +149,8 @@ struct IrisStateMachine : boost::statechart::state_machine< IrisStateMachine, Ac std::string contRadioRepository_; //! stores the log level std::string logLevel_; + //! stores to logging file + std::string loggingFile_; }; //! Active is the parent of all other states, destruction means termination diff --git a/src/Launcher.cpp b/src/Launcher.cpp index d7ed820..e5b5716 100644 --- a/src/Launcher.cpp +++ b/src/Launcher.cpp @@ -16,12 +16,12 @@ * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. - * + * * Iris is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. - * + * * A copy of the GNU Lesser General Public License can be found in * the LICENSE file in the top-level directory of this distribution * and at http://www.gnu.org/licenses/. @@ -85,6 +85,8 @@ class Launcher string contRepoPath_; //! log level string logLevel_; + //! filename for logging + string loggingFile_; //! whether to load the radio automatically at startup bool autoLoad_; //! whether to start the radio automatically at startup @@ -144,8 +146,8 @@ int main(int argc, char* argv[]) Launcher::Launcher() :radioConfig_(""), phyRepoPath_(""), sdfRepoPath_(""), contRepoPath_(""), - logLevel_("debug"), autoLoad_(true), autoStart_(true), stateMachine_(), - isRunning_(true) + logLevel_("debug"), loggingFile_("iris2.log"), autoLoad_(true), autoStart_(true), + stateMachine_(), isRunning_(true) { printBanner(); } @@ -179,6 +181,7 @@ void Launcher::parseOptions(int argc, char* argv[]) ("sdfrepository,s", po::value(&sdfRepoPath_), "Repository of Iris SDF components") ("controllerrepository,c", po::value(&contRepoPath_), "Repository of Iris controllers") ("loglevel,l", po::value(&logLevel_), "Log level (options are debug, info, warning, error & fatal)") + ("logging-file", po::value(&loggingFile_), "Filename for logging (set to null to turn off)") ("no-load", "Do not automatically load radio (implies --no-start)") ("no-start", "Do not automatically start radio") ; @@ -260,6 +263,7 @@ void Launcher::menuLoop() stateMachine_.setSdfRadioRepository(sdfRepoPath_); stateMachine_.setContRadioRepository(contRepoPath_); stateMachine_.setLogLevel(logLevel_); + stateMachine_.setLoggingFile(loggingFile_); stateMachine_.initiate(); if (autoLoad_) @@ -310,6 +314,7 @@ void Launcher::printStatus() cout << "SDF Repository : " << sdfRepoPath_ << endl; cout << "Controller Repository : " << contRepoPath_ << endl; cout << "Log level : " << logLevel_ << endl; + cout << "Logging file: " << loggingFile_ << endl; cout << "Radio Config: " << radioConfig_ << endl; } diff --git a/src/System.cpp b/src/System.cpp index 85526bc..9003052 100644 --- a/src/System.cpp +++ b/src/System.cpp @@ -16,12 +16,12 @@ * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. - * + * * Iris is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. - * + * * A copy of the GNU Lesser General Public License can be found in * the LICENSE file in the top-level directory of this distribution * and at http://www.gnu.org/licenses/. @@ -50,12 +50,6 @@ namespace iris :status_(RADIOUNLOADED), pFile_(NULL) { - //Set up logging - pFile_ = fopen("iris2.log", "a+"); - if(pFile_ != NULL) - LoggingPolicy::getPolicyInstance()->setFileStream(pFile_); - - LoggingPolicy::getPolicyInstance()->ReportingLevel() = LDEBUG; } System::~System() @@ -109,6 +103,22 @@ namespace iris } } + void System::setLoggingFile(std::string file) + { + //Set up logging + if (file != "null") { + pFile_ = fopen(file.c_str(), "a+"); + if(pFile_ != NULL) + LoggingPolicy::getPolicyInstance()->setFileStream(pFile_); + } + else + { + LoggingPolicy::getPolicyInstance()->setFileStream(NULL); + } + + LoggingPolicy::getPolicyInstance()->ReportingLevel() = LDEBUG; + } + bool System::loadRadio(std::string radioConfig) { RadioRepresentation rad; From df484827c9d77479d89755888a1da6066d77f270 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 1 Apr 2014 11:27:15 +0200 Subject: [PATCH 10/24] setting logging level after logging file --- src/IrisStateMachine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/IrisStateMachine.cpp b/src/IrisStateMachine.cpp index eed3577..090da4f 100644 --- a/src/IrisStateMachine.cpp +++ b/src/IrisStateMachine.cpp @@ -50,8 +50,8 @@ Active::Active(my_context ctx) : my_base(ctx) IRISSetPhyRepository(phyRadioRepository); IRISSetSdfRepository(sdfRadioRepository); IRISSetContRepository(contRadioRepository); - IRISSetLogLevel(logLevel); IRISSetLoggingFile(loggingFile); + IRISSetLogLevel(logLevel); } Loaded::Loaded(my_context ctx) From 81c6e6188f096a2d61f61ea734bdef4105bd6baa Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 4 Jun 2013 09:39:35 +0200 Subject: [PATCH 11/24] allow PhyComponents to wait for commands --- irisapi/PhyComponent.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/irisapi/PhyComponent.h b/irisapi/PhyComponent.h index 71ddcf5..ecdef38 100644 --- a/irisapi/PhyComponent.h +++ b/irisapi/PhyComponent.h @@ -36,6 +36,7 @@ #include #include +#include #include @@ -216,12 +217,19 @@ class PhyComponent return dynamic_cast< ReadBuffer* >(buf); }; + /// Wait for a named command + Command waitForCommand(std::string command) + { + return prison_.trap(command); + } + std::vector inputBuffers; ///< Inputs to this component. std::vector outputBuffers; ///< Outputs from this component. private: boost::posix_time::time_duration totalTime_; ///< Time taken in process() so far. int numRuns_; ///< Number of process() calls so far. + CommandPrison prison_; ///< Used to wait for commands issued by a controller. std::map namedInputBuffers_; std::map namedOutputBuffers_; From 2dc647342c4ab1a6f68e23b4afdc844f65a4198a Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 4 Jun 2013 09:39:35 +0200 Subject: [PATCH 12/24] allow PhyComponents to wait for commands --- irisapi/PhyComponent.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/irisapi/PhyComponent.h b/irisapi/PhyComponent.h index 71ddcf5..ecdef38 100644 --- a/irisapi/PhyComponent.h +++ b/irisapi/PhyComponent.h @@ -36,6 +36,7 @@ #include #include +#include #include @@ -216,12 +217,19 @@ class PhyComponent return dynamic_cast< ReadBuffer* >(buf); }; + /// Wait for a named command + Command waitForCommand(std::string command) + { + return prison_.trap(command); + } + std::vector inputBuffers; ///< Inputs to this component. std::vector outputBuffers; ///< Outputs from this component. private: boost::posix_time::time_duration totalTime_; ///< Time taken in process() so far. int numRuns_; ///< Number of process() calls so far. + CommandPrison prison_; ///< Used to wait for commands issued by a controller. std::map namedInputBuffers_; std::map namedOutputBuffers_; From e193835540b9126dcaafcbc3ae4ef7567bcce81e Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 15 May 2013 18:43:10 +0200 Subject: [PATCH 13/24] add trapWait to Command scheme to avoid race conditions/deadlock among components --- irisapi/Command.h | 5 +++-- irisapi/CommandPrison.h | 31 +++++++++++++++++++-------- tests/CommandPrison_test.cpp | 41 ++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 11 deletions(-) diff --git a/irisapi/Command.h b/irisapi/Command.h index 3ffedc1..7ad22b2 100644 --- a/irisapi/Command.h +++ b/irisapi/Command.h @@ -16,12 +16,12 @@ * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. - * + * * Iris is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. - * + * * A copy of the GNU Lesser General Public License can be found in * the LICENSE file in the top-level directory of this distribution * and at http://www.gnu.org/licenses/. @@ -44,6 +44,7 @@ struct Command { std::vector data; ///< Data passed with this command. int typeId; ///< Type of the data. + bool trapWait; ///< Whether to wait for someone being caught before releasing trap. std::string commandName; ///< Name of this command. std::string componentName; ///< Target component. std::string engineName; ///< Target engine. diff --git a/irisapi/CommandPrison.h b/irisapi/CommandPrison.h index 9d236bd..7eec104 100644 --- a/irisapi/CommandPrison.h +++ b/irisapi/CommandPrison.h @@ -120,6 +120,7 @@ class CommandPrison boost::mutex::scoped_lock lock(mutex_); boost::shared_ptr< Cage > cage(new Cage); cages_.insert(CagePair(c,cage)); + trapWaitCondition_.notify_all(); return cage->trap(lock); } @@ -129,15 +130,26 @@ class CommandPrison */ void release(Command c) { - boost::mutex::scoped_lock lock(mutex_); - std::pair found; - CageMM::iterator it; - found = cages_.equal_range(c.commandName); - for (it=found.first; it!=found.second; ++it) - { - it->second->release(c); - } - cages_.erase(found.first, found.second); + boost::mutex::scoped_lock lock(mutex_); + bool foundItem = false; + do + { + std::pair found; + CageMM::iterator it; + found = cages_.equal_range(c.commandName); + for (it=found.first; it!=found.second; ++it) + { + it->second->release(c); + foundItem = true; + } + cages_.erase(found.first, found.second); + if (!c.trapWait) + break; + + if (!foundItem && c.trapWait) + trapWaitCondition_.wait(lock); + } + while (!foundItem); } /// Get the number of threads currently held in this CommandPrison. @@ -153,6 +165,7 @@ class CommandPrison mutable boost::mutex mutex_; ///< Mutex protecting this CommandPrison. CageMM cages_; ///< The cages within this CommandPrison. + boost::condition_variable trapWaitCondition_; ///< Wait condition variable for CommandPrision. }; diff --git a/tests/CommandPrison_test.cpp b/tests/CommandPrison_test.cpp index 8f9f231..a512a8a 100644 --- a/tests/CommandPrison_test.cpp +++ b/tests/CommandPrison_test.cpp @@ -70,6 +70,7 @@ static void release(Command command, boost::shared_ptr prison) BOOST_AUTO_TEST_CASE(CommandPrison_Basic_Test) { + LOG(LDEBUG) << "CommandPrison_Basic_Test"; boost::shared_ptr prison(new CommandPrison); BOOST_CHECK(prison->size() == 0); @@ -119,6 +120,7 @@ BOOST_AUTO_TEST_CASE(CommandPrison_Basic_Test) BOOST_AUTO_TEST_CASE(CommandPrison_MultiRelease_Test) { + LOG(LDEBUG) << "CommandPrison_MultiRelease_Test"; boost::shared_ptr prison(new CommandPrison); BOOST_CHECK(prison->size() == 0); @@ -168,4 +170,43 @@ BOOST_AUTO_TEST_CASE(CommandPrison_MultiRelease_Test) BOOST_CHECK(prison->size() == 0); } +BOOST_AUTO_TEST_CASE(CommandPrison_OutOfOrderRelease_Test) +{ + LOG(LDEBUG) << "CommandPrison_OutOfOrderRelease_Test"; + boost::shared_ptr prison(new CommandPrison); + + BOOST_CHECK(prison->size() == 0); + + // Create a number of threads to wait in prison + boost::thread t0( boost::bind( &trap, "go1", prison ,0) ); + + //Wait for threads to start + boost::this_thread::sleep(boost::posix_time::seconds(1)); + + Command c; + //Release thread with trapWait set to false (default) + c.commandName = "go1"; + boost::thread r0( boost::bind( &release, c, prison ) ); + + boost::this_thread::sleep(boost::posix_time::seconds(1)); + // set go2: if trapWait is false, this boost test should fail + // because the release call is already gone, if t1 runs, if set to + // true, the test should run smoothly + c.commandName = "go2"; + c.trapWait = true; + boost::thread r2( boost::bind( &release, c, prison ) ); + + // wait + boost::this_thread::sleep(boost::posix_time::seconds(1)); + + // now start thread for g2, which should still return + // if trapWait has been set to true in release call + boost::thread t1( boost::bind( &trap, "go2", prison ,1) ); + + t0.join(); + t1.join(); + + BOOST_CHECK(prison->size() == 0); +} + BOOST_AUTO_TEST_SUITE_END() From 7a0c2256c8e9c11f5d72bc5c11b9aba56a6ce6a4 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 26 May 2014 15:11:25 +0200 Subject: [PATCH 14/24] making sure metadata will be initialized correctly --- iris/DataBuffer.h | 2 +- irisapi/StackDataBuffer.h | 2 +- src/engines/phyengine/PhyDataBuffer.h | 2 +- src/engines/stackengine/StackOutTranslator.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/iris/DataBuffer.h b/iris/DataBuffer.h index 0d46c99..6806cc5 100644 --- a/iris/DataBuffer.h +++ b/iris/DataBuffer.h @@ -143,7 +143,7 @@ class DataBuffer : public ReadBuffer, public WriteBuffer isWriteLocked_ = true; if(buffer_[writeIndex_].data.size() != size) buffer_[writeIndex_].data.resize(size); - buffer_[writeIndex_].metadata.setMetadata("timeStamp", 0); + buffer_[writeIndex_].metadata.setMetadata("timeStamp", double(0)); setPtr = &buffer_[writeIndex_]; }; diff --git a/irisapi/StackDataBuffer.h b/irisapi/StackDataBuffer.h index 2c62b11..4d9745e 100644 --- a/irisapi/StackDataBuffer.h +++ b/irisapi/StackDataBuffer.h @@ -68,7 +68,7 @@ struct StackDataSet /// Constructor initializes our variables StackDataSet(double t=0) - : metadata(0.0, t) + : metadata(double(0), t) {} }; diff --git a/src/engines/phyengine/PhyDataBuffer.h b/src/engines/phyengine/PhyDataBuffer.h index 04c8745..b8ef54f 100644 --- a/src/engines/phyengine/PhyDataBuffer.h +++ b/src/engines/phyengine/PhyDataBuffer.h @@ -138,7 +138,7 @@ class PhyDataBuffer : public ReadBuffer, public WriteBuffer isWriteLocked_ = true; if(buffer_[writeIndex_].data.size() != size) buffer_[writeIndex_].data.resize(size); - buffer_[writeIndex_].metadata.setMetadata("timeStamp", 0); + buffer_[writeIndex_].metadata.setMetadata("timeStamp", double(0)); setPtr = &buffer_[writeIndex_]; }; diff --git a/src/engines/stackengine/StackOutTranslator.cpp b/src/engines/stackengine/StackOutTranslator.cpp index 073960b..0839be3 100644 --- a/src/engines/stackengine/StackOutTranslator.cpp +++ b/src/engines/stackengine/StackOutTranslator.cpp @@ -87,7 +87,7 @@ namespace iris //Fill the DataSet with info from the StackDataSet std::copy(p->data.begin(), p->data.end(), outData->data.begin()); outData->metadata = p->metadata; - outData->metadata.setMetadata("sampleRate", 0); + outData->metadata.setMetadata("sampleRate", double(0)); //Release the DataSet outputBuffer_->releaseWriteData(outData); From 242e50e76f24bb8b86e14bfcd6dd031196e1f994 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 26 May 2014 15:15:58 +0200 Subject: [PATCH 15/24] adding new test case for metadata handling --- tests/Metadata_test.cpp | 45 ++++++++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/tests/Metadata_test.cpp b/tests/Metadata_test.cpp index 3040546..6b0121b 100644 --- a/tests/Metadata_test.cpp +++ b/tests/Metadata_test.cpp @@ -78,12 +78,12 @@ BOOST_AUTO_TEST_CASE(MetadataBasicTest) stackDataSource->metadata.setMetadata("float", f); BOOST_CHECK_EQUAL(stackDataSource->metadata.hasMetadata("float"), true); + // this should throw an exception float out2; - bool ret = stackDataSource->metadata.getMetadata("notthere", out2); - BOOST_CHECK_EQUAL(ret, false); + BOOST_CHECK_THROW(stackDataSource->metadata.getMetadata("notthere", out2), MetadataException); - ret = stackDataSource->metadata.getMetadata("float", out2); - BOOST_CHECK_EQUAL(ret, true); + // this should not fail + BOOST_CHECK_NO_THROW(stackDataSource->metadata.getMetadata("float", out2)); BOOST_CHECK_EQUAL(out2, f); // Check if vectors are working @@ -95,7 +95,7 @@ BOOST_AUTO_TEST_CASE(MetadataBasicTest) BOOST_CHECK_EQUAL(stackDataSource->metadata.hasMetadata("intvector"), true); std::vector int_vec_out; - ret = stackDataSource->metadata.getMetadata("intvector", int_vec_out); + stackDataSource->metadata.getMetadata("intvector", int_vec_out); BOOST_CHECK_EQUAL(int_vec_out.size(), 3); // Check if the data is equal @@ -138,12 +138,12 @@ BOOST_AUTO_TEST_CASE(MetadataStackDataSetCopyTest) // Check if this looks alright (two are there by default, plus the two we added) BOOST_CHECK_EQUAL(stackDataDest->metadata.getMetadataCount(), 4); - float out; + float out = 0.0; stackDataDest->metadata.getMetadata("float", out); BOOST_CHECK_EQUAL(out, f); std::vector int_vec_out; - bool ret = stackDataSource->metadata.getMetadata("intvector", int_vec_out); + stackDataSource->metadata.getMetadata("intvector", int_vec_out); delete stackDataDest; delete stackDataSource; @@ -159,7 +159,11 @@ BOOST_AUTO_TEST_CASE(MetadataDataSetCopyTest) uint64_t tx_time = 12000223112; stackDataSource->metadata.setMetadata("tx_time", tx_time); + uint64_t my_tx_time = 22000223112; DataSet< uint8_t >* dataset = new DataSet< uint8_t >; + dataset->metadata.setMetadata("my_tx_time", tx_time); + + // copy the metadata dataset->metadata = stackDataSource->metadata; uint64_t tx_time_out; @@ -170,5 +174,32 @@ BOOST_AUTO_TEST_CASE(MetadataDataSetCopyTest) delete stackDataSource; } + +BOOST_AUTO_TEST_CASE(MetadataDataTypeTest) +{ + StackDataSet* stackDataSource = NULL; + BOOST_CHECK_NO_THROW(stackDataSource = new StackDataSet); + BOOST_REQUIRE(stackDataSource != NULL); + + int in = 365; + stackDataSource->metadata.setMetadata("integer", in); + + int in2 = 100; + stackDataSource->metadata.setMetadata("integer", in2); + + DataSet< uint8_t >* dataset = new DataSet< uint8_t >; + dataset->metadata.setMetadata("woh", in); + dataset->metadata = stackDataSource->metadata; + + // copy the metadata + dataset->metadata = stackDataSource->metadata; + + double out; + BOOST_CHECK_THROW(dataset->metadata.getMetadata("integer", out), MetadataException); + + delete dataset; + delete stackDataSource; +} + BOOST_AUTO_TEST_SUITE_END() From affcd9aecf1a1d32c6ee1eab84de9c9f738c682f Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 26 May 2014 15:31:37 +0200 Subject: [PATCH 16/24] adding exception handling to metadata class --- irisapi/Metadata.h | 64 +++++++++++++++++++++++++++++++++------------- 1 file changed, 46 insertions(+), 18 deletions(-) diff --git a/irisapi/Metadata.h b/irisapi/Metadata.h index 2aa96e8..3bea519 100644 --- a/irisapi/Metadata.h +++ b/irisapi/Metadata.h @@ -38,6 +38,23 @@ #include #include +//! Exception which can be thrown by this class +class MetadataException : public std::exception +{ +private: + std::string message_; +public: + MetadataException(const std::string &message) throw() + :exception(), message_(message) + {}; + virtual const char* what() const throw() + { + return message_.c_str(); + }; + virtual ~MetadataException() throw() + {}; +}; + class MetadataBase : boost::noncopyable { public: @@ -68,7 +85,6 @@ class MetadataMap */ MetadataMap() {} - /** * Provide a constructor with samplerate and timestamp */ @@ -78,23 +94,25 @@ class MetadataMap setMetadata("timeStamp", t); } + /** + * Destructor + */ + ~MetadataMap() {} + /** * Copy constructor to initialize mutex properly */ MetadataMap(const MetadataMap& other) : mutex_() {} - /** * Assignment operator */ - MetadataMap& operator=(const MetadataMap& other) + MetadataMap& operator=(const MetadataMap& orig) { - boost::mutex::scoped_lock lock(mutex_); - map_ = other.map_; // Actual map is copied using default operator + map_ = orig.map_; // Actual map is copied using default operator return *this; } - /** * Set metadata. * @@ -105,9 +123,19 @@ class MetadataMap void setMetadata(const std::string key, T e) { boost::mutex::scoped_lock lock(mutex_); - boost::shared_ptr b(new Metadata); - boost::dynamic_pointer_cast< Metadata >(b)->data = e; - map_[key] = b; + if (map_.find(key) != map_.end()) { + // try to update existing entry + boost::shared_ptr< Metadata > tmp(boost::dynamic_pointer_cast< Metadata >(map_[key])); + if (tmp == NULL) + throw MetadataException("Key already exists with different data type!"); + + tmp->data = e; + } else { + // add new entry + boost::shared_ptr b(new Metadata); + boost::dynamic_pointer_cast< Metadata >(b)->data = e; + map_[key] = b; + } } @@ -116,18 +144,18 @@ class MetadataMap * * @param key The key to look for * @param e A reference to the variable that should hold the metadata. - * @return True if data could be retrieved, false otherwise */ template - bool getMetadata(const std::string key, T& e) + void getMetadata(const std::string key, T& e) { - if (hasMetadata(key)) { - boost::mutex::scoped_lock lock(mutex_); - boost::shared_ptr b = map_[key]; - e = boost::dynamic_pointer_cast< Metadata >(b)->data; - return true; - } - return false; + if (not hasMetadata(key)) + throw MetadataException("Requested metadata not present."); + + boost::mutex::scoped_lock lock(mutex_); + boost::shared_ptr< Metadata > tmp(boost::dynamic_pointer_cast< Metadata >(map_[key])); + if (tmp == NULL) + throw MetadataException("Failed to cast metadata to desired type."); + e = tmp->data; } From 02a2b98d94dd0142752a1abb025a3e47bf3c4fc2 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 2 Jun 2014 13:58:35 +0200 Subject: [PATCH 17/24] cleaning up metadata related header --- iris/DataBuffer.h | 1 - irisapi/Metadata.h | 4 ---- src/engines/phyengine/PhyDataBuffer.h | 1 - 3 files changed, 6 deletions(-) diff --git a/iris/DataBuffer.h b/iris/DataBuffer.h index 6806cc5..64f97b1 100644 --- a/iris/DataBuffer.h +++ b/iris/DataBuffer.h @@ -143,7 +143,6 @@ class DataBuffer : public ReadBuffer, public WriteBuffer isWriteLocked_ = true; if(buffer_[writeIndex_].data.size() != size) buffer_[writeIndex_].data.resize(size); - buffer_[writeIndex_].metadata.setMetadata("timeStamp", double(0)); setPtr = &buffer_[writeIndex_]; }; diff --git a/irisapi/Metadata.h b/irisapi/Metadata.h index 3bea519..9b68339 100644 --- a/irisapi/Metadata.h +++ b/irisapi/Metadata.h @@ -80,10 +80,6 @@ class MetadataMap { typedef std::map > MetadataContainer; public: - /** - * Default constructor - */ - MetadataMap() {} /** * Provide a constructor with samplerate and timestamp diff --git a/src/engines/phyengine/PhyDataBuffer.h b/src/engines/phyengine/PhyDataBuffer.h index b8ef54f..0056bc2 100644 --- a/src/engines/phyengine/PhyDataBuffer.h +++ b/src/engines/phyengine/PhyDataBuffer.h @@ -138,7 +138,6 @@ class PhyDataBuffer : public ReadBuffer, public WriteBuffer isWriteLocked_ = true; if(buffer_[writeIndex_].data.size() != size) buffer_[writeIndex_].data.resize(size); - buffer_[writeIndex_].metadata.setMetadata("timeStamp", double(0)); setPtr = &buffer_[writeIndex_]; }; From 9818f82e577c5afdb4c990e8d1f065ed058b9fe2 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 18 Feb 2015 14:26:03 +0100 Subject: [PATCH 18/24] adding support for controllers to trigger events --- irisapi/Controller.h | 53 ++++++++++++++++++++++++++- irisapi/ControllerCallbackInterface.h | 1 + 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/irisapi/Controller.h b/irisapi/Controller.h index ee9491b..93d655d 100644 --- a/irisapi/Controller.h +++ b/irisapi/Controller.h @@ -44,6 +44,7 @@ #include #include +#include #include #include #include @@ -89,7 +90,8 @@ namespace iris * of the running radio. */ class Controller - : public ModuleParameters + : public ModuleParameters, + public ComponentEvents { public: @@ -252,6 +254,16 @@ class Controller destroy(); } + //! Activate an event + template + inline void activateEvent(std::string name, T &data) + throw (EventNotFoundException, InvalidDataTypeException); + + //! Activate an event + template + inline void activateEvent(std::string name, std::vector &data) + throw (EventNotFoundException, InvalidDataTypeException); + std::string getName() const { return name_; @@ -305,6 +317,45 @@ class Controller }; +// Get the name of this component and pass everything on to ComponentEvents +template +inline void Controller::activateEvent(std::string name, T &data) + throw (EventNotFoundException, InvalidDataTypeException) +{ + if(controllerManager_ == NULL) + return; + + boost::to_lower(name); + + Event e; + e.data.push_back(boost::any(data)); + e.eventName = name; + e.componentName = this->getName(); + e.typeId = TypeInfo::identifier; + controllerManager_->activateEvent(e); + return; +} + +// Get the name of this component and pass everything on to ComponentEvents +template +inline void Controller::activateEvent(std::string name, std::vector &data) + throw (EventNotFoundException, InvalidDataTypeException) +{ + if(controllerManager_ == NULL) + return; + + boost::to_lower(name); + + Event e; + e.data.resize(data.size()); + std::copy(data.begin(), data.end(), e.data.begin()); + e.eventName = name; + e.componentName = this->getName(); + e.typeId = TypeInfo::identifier; + controllerManager_->activateEvent(e); + return; +} + } /* namespace iris */ diff --git a/irisapi/ControllerCallbackInterface.h b/irisapi/ControllerCallbackInterface.h index d48ad50..2a6855b 100644 --- a/irisapi/ControllerCallbackInterface.h +++ b/irisapi/ControllerCallbackInterface.h @@ -55,6 +55,7 @@ class ControllerCallbackInterface{ virtual void postCommand(Command command) = 0; virtual std::string getParameterValue(std::string paramName, std::string componentName) = 0; virtual void subscribeToEvent(std::string eventName, std::string componentName, Controller *cont) = 0; + virtual void activateEvent(Event &e) = 0; }; } /* namespace iris */ From 5d43f49c16fa56d826c720d65c060d9793351979 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Thu, 16 May 2013 11:24:17 +0200 Subject: [PATCH 19/24] disable type-checking for event parameter --- irisapi/ComponentEvents.h | 64 ++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/irisapi/ComponentEvents.h b/irisapi/ComponentEvents.h index 1942508..8e7ab38 100644 --- a/irisapi/ComponentEvents.h +++ b/irisapi/ComponentEvents.h @@ -59,7 +59,7 @@ struct EventDescription /** An interface to the events of a component * - * The ComponentEvents class permits components to register events of different types. + * The ComponentEvents class permits components to register events of different types. * These events can then be triggered by the component together with relevent data. */ class ComponentEvents : boost::noncopyable @@ -113,22 +113,22 @@ inline void ComponentEvents::activateEventInternal(std::string compName, std::st std::map::const_iterator it = events_.find(name); if (it == events_.end()) throw EventNotFoundException("Event " + name + " not found"); - - if(it->second.typeId == TypeInfo::identifier) - { - //std::vector d; - //d.push_back(boost::any(data)); - //d_engine->activateEvent(name, d); - Event e; - e.data.push_back(boost::any(data)); - e.eventName = name; - e.componentName = compName; - e.typeId = TypeInfo::identifier; - engine_->activateEvent(e); - return; - }else{ - throw InvalidDataTypeException("Event data type did not match registered type for event " + name); - } + + /* + * FIXME: + * - disable typeId check to allow complex types beyond TypeInfo.h + * - type checking could be done using a boost::any_cast + */ + //std::vector d; + //d.push_back(boost::any(data)); + //d_engine->activateEvent(name, d); + Event e; + e.data.push_back(boost::any(data)); + e.eventName = name; + e.componentName = compName; + e.typeId = TypeInfo::identifier; + engine_->activateEvent(e); + return; } template @@ -145,23 +145,19 @@ inline void ComponentEvents::activateEventInternal(std::string compName, std::st if (it == events_.end()) throw EventNotFoundException("Event " + name + " not found"); - if(it->second.typeId == TypeInfo::identifier) - { - //std::vector d; - //d.resize(data.size()); - //std::copy(data.begin(), data.end(), d.begin()); - //d_engine->activateEvent(name, d); - Event e; - e.data.resize(data.size()); - std::copy(data.begin(), data.end(), e.data.begin()); - e.eventName = name; - e.componentName = compName; - e.typeId = TypeInfo::identifier; - engine_->activateEvent(e); - return; - }else{ - throw InvalidDataTypeException("Event data type did not match registered type for event " + name); - } + // disable type checking as well, see above for comments + //std::vector d; + //d.resize(data.size()); + //std::copy(data.begin(), data.end(), d.begin()); + //d_engine->activateEvent(name, d); + Event e; + e.data.resize(data.size()); + std::copy(data.begin(), data.end(), e.data.begin()); + e.eventName = name; + e.componentName = compName; + e.typeId = TypeInfo::identifier; + engine_->activateEvent(e); + return; } } // namespace iris From b54668cbc1f1f40ec0747857355f5ad1d9f25f72 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Thu, 26 Feb 2015 16:42:52 +0100 Subject: [PATCH 20/24] core: expose more functions for obtaining radio parameters --- iris/ControllerManager.h | 50 ++++++++- iris/ControllerManagerCallbackInterface.h | 15 +++ iris/EngineManager.h | 7 ++ iris/RadioRepresentation.h | 18 +++- irisapi/Controller.h | 36 +++++++ irisapi/ControllerCallbackInterface.h | 9 ++ src/ControllerManager.cpp | 42 ++++++++ src/EngineManager.cpp | 35 +++++++ src/RadioRepresentation.cpp | 117 ++++++++++++++++++++++ 9 files changed, 325 insertions(+), 4 deletions(-) diff --git a/iris/ControllerManager.h b/iris/ControllerManager.h index 1b8ccf3..74960e6 100644 --- a/iris/ControllerManager.h +++ b/iris/ControllerManager.h @@ -16,12 +16,12 @@ * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. - * + * * Iris is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. - * + * * A copy of the GNU Lesser General Public License can be found in * the LICENSE file in the top-level directory of this distribution * and at http://www.gnu.org/licenses/. @@ -162,6 +162,52 @@ class ControllerManager */ std::string getParameterValue(std::string paramName, std::string componentName); + /** Get a components' parameter name + * + * @param componentName The name of the component containing the parameter. + * @param paramIndex The paramter index + * @return paramValue The parameter value returned by reference + */ + std::string getParameterName(std::string componentName, int paramIndex, std::string ¶mValue); + + /** Get the name of an engine + * + * @param componentName The name of the component that resides in the engine + * @param engineIndex The engine index + * @param compIndex The component index + * @return engineName The engine name + */ + std::string getEngineName(std::string componentName, int *engineIndex, int *compIndex); + + /** Get the number of engines in the current radio + * + * @return The number of engine + */ + int getNrEngines(); + + /** Get the number of components in the current radio + * + * @return The number of components + */ + int getNrComponents(); + + /** Get the engine name for a given index + * + * @param index The index of the engine + * @return The name of the the engine + */ + std::string getEngineNameFromIndex(int index); + + /** Get the component name for a given index + * + * @param index The index of the component + * @return The name of the the component + */ + std::string getComponentName(int index); + + /// returns the number of parameters in a given component + int getNrParameters(std::string componentName); + /** Subscribe to an event (Called by controllers) * * @param eventName The event name. diff --git a/iris/ControllerManagerCallbackInterface.h b/iris/ControllerManagerCallbackInterface.h index 38286b2..0205398 100644 --- a/iris/ControllerManagerCallbackInterface.h +++ b/iris/ControllerManagerCallbackInterface.h @@ -36,6 +36,7 @@ #include "irisapi/ReconfigurationDescriptions.h" #include "irisapi/Command.h" +#include "RadioRepresentation.h" namespace iris { @@ -56,6 +57,20 @@ class ControllerManagerCallbackInterface{ virtual void postCommand(Command command) = 0; virtual std::string getParameterValue(std::string paramName, std::string componentName) = 0; + + virtual std::string getParameterName(std::string componentName, int paramIndex, std::string ¶mValue) = 0; + + virtual std::string getEngineName(std::string componentName, int *engineIndex, int *compIndex) = 0; + + virtual int getNrEngines() = 0; + + virtual int getNrComponents() = 0; + + virtual std::string getEngineNameFromIndex(int index) = 0; + + virtual std::string getComponentName(int index) = 0; + + virtual int getNrParameters(std::string componentName) = 0; }; } // namespace iris diff --git a/iris/EngineManager.h b/iris/EngineManager.h index 67e8f71..869ebb7 100644 --- a/iris/EngineManager.h +++ b/iris/EngineManager.h @@ -98,6 +98,13 @@ class EngineManager: void reconfigureRadio(ReconfigSet reconfigs); void postCommand(Command command); std::string getParameterValue(std::string paramName, std::string componentName); + std::string getParameterName(std::string componentName, int paramIndex, std::string ¶mValue); + std::string getEngineName(std::string componentName, int *engineIndex, int *compIndex); + int getNrEngines(); + int getNrComponents(); + std::string getEngineNameFromIndex(int index); + std::string getComponentName(int index); + int getNrParameters(std::string componentName); void activateEvent(Event &e); }; diff --git a/iris/RadioRepresentation.h b/iris/RadioRepresentation.h index 72e5559..e159699 100644 --- a/iris/RadioRepresentation.h +++ b/iris/RadioRepresentation.h @@ -16,12 +16,12 @@ * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. - * + * * Iris is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. - * + * * A copy of the GNU Lesser General Public License can be found in * the LICENSE file in the top-level directory of this distribution * and at http://www.gnu.org/licenses/. @@ -220,6 +220,20 @@ class RadioRepresentation static bool findComponent(std::string name, const RadioGraph& graph, Vertex& ver); /// Find an engine in an EngineGraph static bool findEngine(std::string name, const EngineGraph& graph, EngVertex& ver); + /// Get the engine name for a given component + std::string getEngineName(std::string componentName, int *engineIndex, int *compIndex); + /// Get the number of engines in the current radio + int getNrEngines(); + /// Get the number of components in the current radio + int getNrComponents(); + /// Get the engine name for a given index + std::string getEngineNameFromIndex(int index); + /// Get the component name for a given component index + std::string getComponentName(int index); + /// Get the number of parameters of a given component + int getNrParameters(std::string componentName); + /// Get a components' parameter name + std::string getParameterName(std::string componentName, int paramIndex, std::string ¶mValue); private: /// Reconfigure a parameter within the representation diff --git a/irisapi/Controller.h b/irisapi/Controller.h index ee9491b..7b1e33e 100644 --- a/irisapi/Controller.h +++ b/irisapi/Controller.h @@ -252,6 +252,42 @@ class Controller destroy(); } + + std::string getEngineName(std::string componentName, int *engineIndex, int *compIndex) + { + return controllerManager_->getEngineName(componentName, engineIndex, compIndex); + } + + int getNrEngines() + { + return controllerManager_->getNrEngines(); + } + + int getNrComponents() + { + return controllerManager_->getNrComponents(); + } + + std::string getEngineNameFromIndex(int index) + { + return controllerManager_->getEngineNameFromIndex(index); + } + + std::string getComponentName(int index) + { + return controllerManager_->getComponentName(index); + } + + int getNrParameters(std::string componentName) + { + return controllerManager_->getNrParameters(componentName); + } + + std::string getParameterName(std::string componentName, int paramIndex, std::string ¶mValue) + { + return controllerManager_->getParameterName(componentName, paramIndex, paramValue); + } + std::string getName() const { return name_; diff --git a/irisapi/ControllerCallbackInterface.h b/irisapi/ControllerCallbackInterface.h index d48ad50..275fd8e 100644 --- a/irisapi/ControllerCallbackInterface.h +++ b/irisapi/ControllerCallbackInterface.h @@ -36,6 +36,7 @@ #include "irisapi/ReconfigurationDescriptions.h" #include "irisapi/Command.h" +#include "iris/RadioRepresentation.h" namespace iris { @@ -54,7 +55,15 @@ class ControllerCallbackInterface{ virtual void reconfigureRadio(ReconfigSet reconfigs) = 0; virtual void postCommand(Command command) = 0; virtual std::string getParameterValue(std::string paramName, std::string componentName) = 0; + virtual std::string getParameterName(std::string componentName, int paramIndex, std::string ¶mValue) = 0; virtual void subscribeToEvent(std::string eventName, std::string componentName, Controller *cont) = 0; + virtual void activateEvent(Event &e) = 0; + virtual std::string getEngineName(std::string componentName, int *engineIndex, int *compIndex) = 0; + virtual int getNrEngines() = 0; + virtual int getNrComponents() = 0; + virtual std::string getEngineNameFromIndex(int index) = 0; + virtual std::string getComponentName(int index) = 0; + virtual int getNrParameters(std::string componentName) = 0; }; } /* namespace iris */ diff --git a/src/ControllerManager.cpp b/src/ControllerManager.cpp index aa7a715..2bfce96 100644 --- a/src/ControllerManager.cpp +++ b/src/ControllerManager.cpp @@ -292,4 +292,46 @@ namespace iris } + //! Get the parameter name and value (returned by reference) + std::string ControllerManager::getParameterName(std::string componentName, int paramIndex, std::string ¶mValue) + { + return engineManager_->getParameterName(componentName, paramIndex, paramValue); + } + + //! Get the engine name + std::string ControllerManager::getEngineName(std::string componentName, int *engineIndex, int *compIndex) + { + return engineManager_->getEngineName(componentName, engineIndex, compIndex); + } + + //! Get the number of engines in the current radio + int ControllerManager::getNrEngines() + { + return engineManager_->getNrEngines(); + } + + //! Get the number of components in the current radio + int ControllerManager::getNrComponents() + { + return engineManager_->getNrComponents(); + } + + //! Get the engine name for a given index + std::string ControllerManager::getEngineNameFromIndex(int index) + { + return engineManager_->getEngineNameFromIndex(index); + } + + //! Get the component name for a given component index + std::string ControllerManager::getComponentName(int index) + { + return engineManager_->getComponentName(index); + } + + //! Get the number of parameters of a given component + int ControllerManager::getNrParameters(std::string componentName) + { + return engineManager_->getNrParameters(componentName); + } + } /* namespace iris */ diff --git a/src/EngineManager.cpp b/src/EngineManager.cpp index 4633641..d1a8a21 100644 --- a/src/EngineManager.cpp +++ b/src/EngineManager.cpp @@ -205,6 +205,41 @@ namespace iris return radioRep_.getParameterValue(paramName, componentName); } + std::string EngineManager::getParameterName(std::string componentName, int paramIndex, std::string ¶mValue) + { + return radioRep_.getParameterName(componentName, paramIndex, paramValue); + } + + std::string EngineManager::getEngineName(std::string componentName, int *engineIndex, int *compIndex) + { + return radioRep_.getEngineName(componentName, engineIndex, compIndex); + } + + int EngineManager::getNrEngines() + { + return radioRep_.getNrEngines(); + } + + int EngineManager::getNrComponents() + { + return radioRep_.getNrComponents(); + } + + std::string EngineManager::getEngineNameFromIndex(int index) + { + return radioRep_.getEngineNameFromIndex(index); + } + + std::string EngineManager::getComponentName(int index) + { + return radioRep_.getComponentName(index); + } + + int EngineManager::getNrParameters(std::string componentName) + { + return radioRep_.getNrParameters(componentName); + } + void EngineManager::activateEvent(Event &e) { //Pass the event to the controller manager diff --git a/src/RadioRepresentation.cpp b/src/RadioRepresentation.cpp index ff2c874..49d8c03 100644 --- a/src/RadioRepresentation.cpp +++ b/src/RadioRepresentation.cpp @@ -409,4 +409,121 @@ namespace iris return engineGraph_; } + int RadioRepresentation::getNrComponents() + { + RadioGraph radGraph = getRadioGraph(); + boost::mutex::scoped_lock lock(mutex_); + int comps; + VertexIterator i, iend; + tie(i, iend) = vertices(radGraph); + comps = iend - i; + return comps; + } + + std::string RadioRepresentation::getEngineNameFromIndex(int index) + { + EngineGraph engGraph = getEngineGraph(); + std::string engine = ""; + VertexIterator i, iend; + for(tie(i, iend) = vertices(engGraph); i != iend; ++i) + { + int ver = *i; + if(ver == index) + engine = engGraph[index].name; + } + return engine; + } + + std::string RadioRepresentation::getComponentName(int index) + { + RadioGraph radGraph= getRadioGraph(); + std::string component = ""; + VertexIterator i, iend; + for(tie(i, iend) = vertices(radGraph); i != iend; ++i) + { + int ver = *i; + if(ver == index) + component = radGraph[index].name; + } + return component; + } + + int RadioRepresentation::getNrParameters(std::string componentName) + { + RadioGraph radGraph= getRadioGraph(); + VertexIterator i, iend; + int NrParams = 0; + vector::iterator paramIt; + for(tie(i, iend) = vertices(radGraph); i != iend; ++i) + { + int ver = *i; + if(radGraph[ver].name == componentName) + NrParams = radGraph[ver].parameters.end() - radGraph[ver].parameters.begin(); + } + return NrParams; + } + + std::string RadioRepresentation::getParameterName(std::string componentName, int paramIndex, std::string ¶mValue) + { + RadioGraph radGraph = getRadioGraph(); + VertexIterator i, iend; + std::string paramName = ""; + vector::iterator paramIt; + for(tie(i, iend) = vertices(radGraph); i != iend; ++i) + { + int ver = *i; + if(radGraph[ver].name == componentName) + { + int k = 0; + vector::iterator paramIt; + for(paramIt = radGraph[ver].parameters.begin(); paramIt != radGraph[ver].parameters.end(); ++paramIt) + { + if(k == paramIndex) + { + paramName += paramIt->name; + paramValue = paramIt->value; + } + k++; + } + } + } + return paramName; + } + + std::string RadioRepresentation::getEngineName(std::string componentName, int *engineIndex, int *compIndex) + { + EngineDescription engD; + vector::iterator engIt; + std::string engineName = ""; + int compI=0,engI=0; + for(engIt = engines_.begin(); engIt != engines_.end(); ++engIt) + { + compI=0; + vector::iterator compIt; + for(compIt = engIt->components.begin(); compIt != engIt->components.end(); ++compIt) + { + if(compIt->name == componentName) + { + engineName = engIt->name; + *compIndex = compI; + *engineIndex = engI; + break; + } + compI++; + } + engI++; + } + return engineName; + } + + int RadioRepresentation::getNrEngines() + { + EngineGraph engGraph = getEngineGraph(); + boost::mutex::scoped_lock lock(mutex_); + int engines; + VertexIterator i, iend; + tie(i, iend) = vertices(engGraph); + engines = iend - i; + return engines; + } } From 7a3dae1e802ae322284ce8d7e589b08e4f0092d9 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 27 Feb 2015 10:51:51 +0100 Subject: [PATCH 21/24] core: adding separate work thread to controller base class --- irisapi/Controller.h | 55 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/irisapi/Controller.h b/irisapi/Controller.h index ee9491b..a8a296d 100644 --- a/irisapi/Controller.h +++ b/irisapi/Controller.h @@ -105,7 +105,8 @@ class Controller Controller(std::string name, std::string description, std::string author, std::string version ) : name_(name), description_(description), author_(author), version_(version) ,controllerManager_(NULL) - ,thread_(NULL) + ,eventThread_(NULL) + ,workThread_(NULL) ,started_(false) ,loaded_(false) { @@ -170,14 +171,26 @@ class Controller eventQueue_.push(e); } + //! Execute separate working thread - should be overwritten in the controller subclass + virtual void workFunction() + { + LOG(LINFO) << "Function workFuntion has not been implemented in controller " << name_; + } + /// Called by ControllerManager to load the controller thread. void load() { //Load the controller thread (if it hasn't already been loaded) - if( thread_ == NULL) + if( eventThread_ == NULL) { loaded_ = true; - thread_.reset( new boost::thread( boost::bind( &Controller::eventLoop, this ) ) ); + eventThread_.reset( new boost::thread( boost::bind( &Controller::eventLoop, this ) ) ); + } + + //Load worker thread + if ( workThread_ == NULL) + { + workThread_.reset( new boost::thread( boost::bind( &Controller::workLoop, this ) ) ); } } @@ -198,16 +211,24 @@ class Controller lock.unlock(); conditionVar_.notify_one(); - thread_->interrupt(); + if (workThread_) workThread_->interrupt(); + eventThread_->interrupt(); } /// Called by ControllerManager to unload the controller thread void unload() { + //unload the work thread first + if (workThread_) + { + workThread_->interrupt(); + workThread_->join(); + } + //unload the controller thread loaded_ = false; - thread_->interrupt(); - thread_->join(); + eventThread_->interrupt(); + eventThread_->join(); } /// The main loop for the Controller thread @@ -252,6 +273,25 @@ class Controller destroy(); } + //! The main loop for the worker thread + void workLoop() + { + try { + try { + // Just call workFuntion from here + workFunction(); + } + catch(boost::thread_interrupted) + { + LOG(LINFO) << "Work thread of controller " << name_ << " interrupted"; + } + } + catch(IrisException& ex) + { + LOG(LERROR) << "Error in controller " << name_ << ": " << ex.what() << std::endl << "Worker thread exiting."; + } + } + std::string getName() const { return name_; @@ -296,7 +336,8 @@ class Controller MessageQueue< Event > eventQueue_; ///< Queue of incoming Event objects. ControllerCallbackInterface* controllerManager_; ///< Interface to the ControllerManager. - boost::scoped_ptr< boost::thread > thread_; ///< This controller's thread. + boost::scoped_ptr< boost::thread > eventThread_; ///< This controller's thread for handling events. + boost::scoped_ptr< boost::thread > workThread_; ///< An additional thread that a controller may use. bool started_; bool loaded_; From c017a8d70576907cd20403f68ef491d83620fdfb Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Sat, 7 Mar 2015 22:03:54 +0100 Subject: [PATCH 22/24] metadata: improve info when throwing exceptions --- irisapi/Metadata.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/irisapi/Metadata.h b/irisapi/Metadata.h index 9b68339..5a27351 100644 --- a/irisapi/Metadata.h +++ b/irisapi/Metadata.h @@ -145,12 +145,12 @@ class MetadataMap void getMetadata(const std::string key, T& e) { if (not hasMetadata(key)) - throw MetadataException("Requested metadata not present."); + throw MetadataException("Requested metadata key " + key + " not present."); boost::mutex::scoped_lock lock(mutex_); boost::shared_ptr< Metadata > tmp(boost::dynamic_pointer_cast< Metadata >(map_[key])); if (tmp == NULL) - throw MetadataException("Failed to cast metadata to desired type."); + throw MetadataException("Failed to cast metadata key " + key + " to desired type."); e = tmp->data; } From af030e8b0d3c20efe07c2a5d97b63dab79f2cdad Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 19 Oct 2015 10:24:15 +0200 Subject: [PATCH 23/24] fix bug in copy contructor where metadata map is actually not copied --- irisapi/Metadata.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/irisapi/Metadata.h b/irisapi/Metadata.h index 5a27351..008e003 100644 --- a/irisapi/Metadata.h +++ b/irisapi/Metadata.h @@ -98,7 +98,10 @@ class MetadataMap /** * Copy constructor to initialize mutex properly */ - MetadataMap(const MetadataMap& other) : mutex_() {} + MetadataMap(const MetadataMap& other) : mutex_() + { + map_ = other.map_; + } /** * Assignment operator From 25452a5192ecaf12f860b6ac07646948b081f10d Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 7 Dec 2015 14:58:14 +0100 Subject: [PATCH 24/24] resolve ambiguity between different implementations of tie --- src/RadioRepresentation.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/RadioRepresentation.cpp b/src/RadioRepresentation.cpp index 49d8c03..480e5da 100644 --- a/src/RadioRepresentation.cpp +++ b/src/RadioRepresentation.cpp @@ -415,7 +415,7 @@ namespace iris boost::mutex::scoped_lock lock(mutex_); int comps; VertexIterator i, iend; - tie(i, iend) = vertices(radGraph); + b::tie(i, iend) = vertices(radGraph); comps = iend - i; return comps; } @@ -425,7 +425,7 @@ namespace iris EngineGraph engGraph = getEngineGraph(); std::string engine = ""; VertexIterator i, iend; - for(tie(i, iend) = vertices(engGraph); i != iend; ++i) + for(b::tie(i, iend) = vertices(engGraph); i != iend; ++i) { int ver = *i; if(ver == index) @@ -439,7 +439,7 @@ namespace iris RadioGraph radGraph= getRadioGraph(); std::string component = ""; VertexIterator i, iend; - for(tie(i, iend) = vertices(radGraph); i != iend; ++i) + for(b::tie(i, iend) = vertices(radGraph); i != iend; ++i) { int ver = *i; if(ver == index) @@ -454,7 +454,7 @@ namespace iris VertexIterator i, iend; int NrParams = 0; vector::iterator paramIt; - for(tie(i, iend) = vertices(radGraph); i != iend; ++i) + for(b::tie(i, iend) = vertices(radGraph); i != iend; ++i) { int ver = *i; if(radGraph[ver].name == componentName) @@ -469,7 +469,7 @@ namespace iris VertexIterator i, iend; std::string paramName = ""; vector::iterator paramIt; - for(tie(i, iend) = vertices(radGraph); i != iend; ++i) + for(b::tie(i, iend) = vertices(radGraph); i != iend; ++i) { int ver = *i; if(radGraph[ver].name == componentName) @@ -522,7 +522,7 @@ namespace iris boost::mutex::scoped_lock lock(mutex_); int engines; VertexIterator i, iend; - tie(i, iend) = vertices(engGraph); + b::tie(i, iend) = vertices(engGraph); engines = iend - i; return engines; }