Skip to content

Commit 73243d1

Browse files
authored
Merge pull request #612 from mtconnect/611_obervation_duplication_when_using_agent_adapter
611 obervation duplication when using agent adapter
2 parents 6d90252 + dbf835f commit 73243d1

13 files changed

Lines changed: 418 additions & 27 deletions

File tree

CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
set(AGENT_VERSION_MAJOR 2)
33
set(AGENT_VERSION_MINOR 7)
44
set(AGENT_VERSION_PATCH 0)
5-
set(AGENT_VERSION_BUILD 11)
5+
set(AGENT_VERSION_BUILD 12)
66
set(AGENT_VERSION_RC "")
77

88
# This minimum version is to support Visual Studio 2019 and C++ feature checking and FetchContent
@@ -71,6 +71,7 @@ include(cmake/remove_link_directories.cmake)
7171
include(cmake/osx_no_app_or_frameworks.cmake)
7272
include(cmake/ClangFormat.cmake)
7373
include(cmake/ClangTidy.cmake)
74+
include(cmake/Coverage.cmake)
7475

7576
# Add our projects
7677
add_subdirectory(agent_lib)

cmake/Coverage.cmake

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Code coverage instrumentation.
2+
#
3+
# Enable with -DAGENT_ENABLE_COVERAGE=ON (or, via Conan, -o "&:coverage=True").
4+
# Must be included before the agent/test targets are defined so the flags
5+
# propagate to every subsequently-declared target.
6+
#
7+
# Clang/AppleClang -> LLVM source-based coverage (llvm-profdata + llvm-cov)
8+
# GCC -> gcov instrumentation (gcov/gcovr/lcov)
9+
10+
option(AGENT_ENABLE_COVERAGE "Instrument the agent and tests for code coverage" OFF)
11+
12+
if(AGENT_ENABLE_COVERAGE)
13+
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
14+
message(STATUS "Coverage: enabling LLVM source-based coverage instrumentation")
15+
add_compile_options(
16+
$<$<COMPILE_LANGUAGE:CXX>:-fprofile-instr-generate>
17+
$<$<COMPILE_LANGUAGE:CXX>:-fcoverage-mapping>)
18+
add_link_options(-fprofile-instr-generate)
19+
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
20+
message(STATUS "Coverage: enabling gcov instrumentation")
21+
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:--coverage>)
22+
add_link_options(--coverage)
23+
else()
24+
message(WARNING
25+
"AGENT_ENABLE_COVERAGE requested but compiler '${CMAKE_CXX_COMPILER_ID}' is not supported")
26+
endif()
27+
endif()

conanfile.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ class MTConnectAgentConan(ConanFile):
1414
license = "Apache License 2.0"
1515
settings = "os", "compiler", "arch", "build_type"
1616
options = { "without_ipv6": [True, False],
17-
"with_ruby": [True, False],
17+
"with_ruby": [True, False],
1818
"development" : [True, False],
19+
"coverage" : [True, False],
1920
"shared": [True, False],
2021
"winver": [None, "ANY"],
2122
"with_docs" : [True, False],
@@ -34,6 +35,7 @@ class MTConnectAgentConan(ConanFile):
3435
"without_ipv6": False,
3536
"with_ruby": True,
3637
"development": False,
38+
"coverage": False,
3739
"shared": False,
3840
"winver": "0x0A00",
3941
"with_docs": False,
@@ -177,6 +179,7 @@ def generate(self):
177179
tc.cache_variables['AGENT_WITH_DOCS'] = self.options.with_docs.__bool__()
178180
tc.cache_variables['AGENT_WITHOUT_IPV6'] = self.options.without_ipv6.__bool__()
179181
tc.cache_variables['DEVELOPMENT'] = self.options.development.__bool__()
182+
tc.cache_variables['AGENT_ENABLE_COVERAGE'] = self.options.coverage.__bool__()
180183
if self.options.agent_prefix:
181184
tc.cache_variables['AGENT_PREFIX'] = self.options.agent_prefix
182185
if is_msvc(self):

src/mtconnect/sink/rest_sink/rest_service.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,19 @@ namespace mtconnect {
7474

7575
auto base = GetOption<string>(options, config::ExternalBaseUrl);
7676
if (!base)
77-
base = "http://localhost:" + to_string(m_server->getPort());
78-
m_externalBaseAddress = *base;
77+
{
78+
auto ip = GetOption<string>(options, config::ServerIp);
79+
if (!ip || *ip == "0.0.0.0")
80+
ip = GetBestHostAddress(m_context, true);
81+
string protocol;
82+
if (m_server->isTlsEnabled())
83+
protocol = "https://";
84+
else
85+
protocol = "http://";
86+
base = protocol + *ip + ":" + to_string(m_server->getPort()) + '/';
87+
}
88+
m_baseUrl = *base;
89+
m_server->setBaseUrl(m_baseUrl);
7990

8091
auto xmlPrinter = dynamic_cast<XmlPrinter *>(m_sinkContract->getPrinter("xml"));
8192
auto jsonPrinter = dynamic_cast<JsonPrinter *>(m_sinkContract->getPrinter("json"));

src/mtconnect/sink/rest_sink/rest_service.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ namespace mtconnect {
380380

381381
std::string externalUrl(const std::string &url)
382382
{
383-
std::string fullUrl = m_externalBaseAddress;
383+
std::string fullUrl = m_baseUrl;
384384
if (!fullUrl.empty() && !url.empty())
385385
{
386386
if (fullUrl.back() == '/' && url.front() == '/')
@@ -405,7 +405,7 @@ namespace mtconnect {
405405
std::shared_ptr<source::LoopbackSource> m_loopback;
406406
uint64_t m_instanceId;
407407
std::unique_ptr<Server> m_server;
408-
std::string m_externalBaseAddress;
408+
std::string m_baseUrl;
409409

410410
// Buffers
411411
FileCache m_fileCache;

src/mtconnect/sink/rest_sink/server.cpp

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -371,15 +371,7 @@ namespace mtconnect::sink::rest_sink {
371371
AutoJsonArray<T> ary(writer, "servers");
372372
{
373373
AutoJsonObject<T> obj(writer);
374-
375-
stringstream str;
376-
if (m_tlsEnabled)
377-
str << "https://";
378-
else
379-
str << "http://";
380-
381-
str << GetBestHostAddress(m_context, true) << ':' << m_port << '/';
382-
obj.AddPairs("url", str.str());
374+
obj.AddPairs("url", m_baseUrl);
383375
}
384376
}
385377
{

src/mtconnect/sink/rest_sink/server.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,14 @@ namespace mtconnect::sink::rest_sink {
124124
/// @return the port being bound
125125
auto getPort() const { return m_port; }
126126

127+
///@brief Is TLS enabled?
128+
///@return `true` if TLS is enabled
129+
bool isTlsEnabled() const { return m_tlsEnabled; }
130+
131+
/// @brief Set the external base URL
132+
/// @param[in] url the base URL to set
133+
void setBaseUrl(const std::string &url) { m_baseUrl = url; }
134+
127135
/// @name PUT and POST handling
128136
///@{
129137

@@ -318,6 +326,7 @@ namespace mtconnect::sink::rest_sink {
318326

319327
boost::asio::ip::address m_address;
320328
unsigned short m_port {5000};
329+
std::string m_baseUrl;
321330

322331
bool m_run {false};
323332
bool m_listening {false};

src/mtconnect/source/adapter/agent_adapter/agent_adapter.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -232,8 +232,12 @@ namespace mtconnect::source::adapter::agent_adapter {
232232
m_strand, [weak = std::weak_ptr(getptr())](boost::system::error_code ec) {
233233
if (auto self = weak.lock(); self && !ec)
234234
{
235+
// Rebuild the sample request from the latest processed sequence rather
236+
// than replaying the cached request. In streaming mode the cached
237+
// request's `from` is baked in when the stream opens and never advances,
238+
// so replaying it re-delivers every observation seen during the session.
235239
if (self->canRecover() && self->m_streamRequest)
236-
self->m_session->makeRequest(*self->m_streamRequest);
240+
self->recover();
237241
else
238242
self->run();
239243
}
@@ -352,7 +356,6 @@ namespace mtconnect::source::adapter::agent_adapter {
352356

353357
clear();
354358

355-
m_reconnecting = false;
356359
if (m_probeAgent)
357360
{
358361
probe();
@@ -369,7 +372,6 @@ namespace mtconnect::source::adapter::agent_adapter {
369372
if (m_stopped)
370373
return;
371374

372-
m_reconnecting = false;
373375
sample();
374376
}
375377

src/mtconnect/source/adapter/agent_adapter/agent_adapter.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ namespace mtconnect::source::adapter::agent_adapter {
8989
/// @return reference to the transform feedback
9090
auto &getFeedback() { return m_feedback; }
9191

92+
/// @brief get the current outstanding stream request (for testing)
93+
/// @return reference to the optional stream request
94+
auto &getStreamRequest() { return m_streamRequest; }
95+
9296
~AgentAdapter() override;
9397

9498
/// @name Source interface
@@ -128,7 +132,6 @@ namespace mtconnect::source::adapter::agent_adapter {
128132
url::Url m_url;
129133
int m_count = 1000;
130134
std::chrono::milliseconds m_heartbeat;
131-
bool m_reconnecting = false;
132135
bool m_failed = false;
133136
bool m_stopped = false;
134137
bool m_usePolling = false;

0 commit comments

Comments
 (0)