From d213257874344d58c44c668a2b9fabef05119abc Mon Sep 17 00:00:00 2001 From: Marko Zivanovic Date: Sun, 6 Sep 2015 21:58:35 +0200 Subject: [PATCH] Implement frequency limiting class to be used for controlled messages-per-second ratio during send to syslog --- CMakeLists.txt | 1 + src/FrequencyLimit.cpp | 35 ++++++++++++++++++++ src/FrequencyLimit.h | 63 ++++++++++++++++++++++++++++++++++++ test/CMakeLists.txt | 10 +++++- test/FrequencyLimitTests.cpp | 51 +++++++++++++++++++++++++++++ 5 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 src/FrequencyLimit.cpp create mode 100644 src/FrequencyLimit.h create mode 100644 test/FrequencyLimitTests.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index cc4089e..2aedfa1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,4 +8,5 @@ enable_testing() add_test(NAME SyslogBulkUploaderTests COMMAND SyslogBulkUploaderTests) add_test(NAME SyslogMessageTests COMMAND SyslogMessageTests) add_test(NAME RFC3164FormattedSyslogMessageTests COMMAND RFC3164FormattedSyslogMessageTests) +add_test(NAME FrequencyLimitTests COMMAND FrequencyLimitTests) diff --git a/src/FrequencyLimit.cpp b/src/FrequencyLimit.cpp new file mode 100644 index 0000000..cc003a7 --- /dev/null +++ b/src/FrequencyLimit.cpp @@ -0,0 +1,35 @@ +/* + The MIT License (MIT) + +Copyright (c) 2015 Marko Živanović + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +#include "FrequencyLimit.h" + +FrequencyLimit::FrequencyLimit() { +} + +FrequencyLimit::FrequencyLimit(const FrequencyLimit& orig) { +} + +FrequencyLimit::~FrequencyLimit() { +} + diff --git a/src/FrequencyLimit.h b/src/FrequencyLimit.h new file mode 100644 index 0000000..53f1113 --- /dev/null +++ b/src/FrequencyLimit.h @@ -0,0 +1,63 @@ +/* + The MIT License (MIT) + +Copyright (c) 2015 Marko Živanović + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +#ifndef FREQUENCYLIMIT_H +#define FREQUENCYLIMIT_H + +#include +#include +#include + +class FrequencyLimit { +public: + + FrequencyLimit(const size_t& limit) : _target(boost::posix_time::microseconds(1000000 / limit)), _delay(boost::posix_time::milliseconds(0)) { + }; + + void tick() { + auto now(boost::posix_time::microsec_clock::local_time()); + if (_prev == boost::posix_time::not_a_date_time) { + _prev = now; + } else { + auto dur = now - _prev; + auto diff = _target - dur; +// _delay = (_delay + diff) / 2; + _delay = _delay + diff; +// std::cout << "dur: " << dur << " diff: " << diff << " _delay: " << _delay << std::endl; + if (diff > boost::posix_time::microseconds(0)) { + boost::this_thread::sleep(_delay); + } +// _prev = boost::posix_time::microsec_clock::local_time(); + _prev = now; + } + }; + +private: + const boost::posix_time::time_duration _target; + boost::posix_time::time_duration _delay; + boost::posix_time::ptime _prev; +}; + +#endif /* FREQUENCYLIMIT_H */ + diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 98b07ee..3d38508 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,4 +1,4 @@ -find_package(Boost COMPONENTS unit_test_framework date_time filesystem system REQUIRED) +find_package(Boost COMPONENTS unit_test_framework date_time filesystem system thread REQUIRED) find_package(Threads) include_directories( ${TEST_SOURCE_DIR/src} @@ -30,3 +30,11 @@ target_link_libraries(RFC3164FormattedSyslogMessageTests ${Boost_DATE_TIME_LIBRARY} ) +add_executable(FrequencyLimitTests FrequencyLimitTests.cpp) +target_link_libraries(FrequencyLimitTests + slbu-lib + ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} + ${Boost_DATE_TIME_LIBRARY} + ${Boost_THREAD_LIBRARY} +) + diff --git a/test/FrequencyLimitTests.cpp b/test/FrequencyLimitTests.cpp new file mode 100644 index 0000000..0754452 --- /dev/null +++ b/test/FrequencyLimitTests.cpp @@ -0,0 +1,51 @@ +/* + The MIT License (MIT) + +Copyright (c) 2015 Marko Živanović + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +#define BOOST_TEST_MODULE FrequencyLimitTests +#include +#include +#include "../src/FrequencyLimit.h" + +using namespace boost::posix_time; + +size_t countInLoop(size_t freq, time_duration duration) { + FrequencyLimit f(freq); + ptime start(second_clock::local_time()); + int c = 0; + while (second_clock::local_time() - start < duration) { + f.tick(); + c++; + } + return c; +} + +BOOST_AUTO_TEST_CASE(test_slow) { + size_t c = countInLoop(5, seconds(5)); + BOOST_WARN_CLOSE((float) c, 25, 10); +} + +BOOST_AUTO_TEST_CASE(test_fast) { + size_t c = countInLoop(100, seconds(5)); + BOOST_WARN_CLOSE((float) c, 500, 10); +}