Skip to content

Commit c830c7b

Browse files
authored
Merge pull request #573 from mtconnect/572_agent_dynanic_device_creation
2 parents 25df43a + 5873106 commit c830c7b

35 files changed

+682
-586
lines changed

CMakeLists.txt

Lines changed: 1 addition & 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 6)
44
set(AGENT_VERSION_PATCH 0)
5-
set(AGENT_VERSION_BUILD 3)
5+
set(AGENT_VERSION_BUILD 4)
66
set(AGENT_VERSION_RC "")
77

88
# This minimum version is to support Visual Studio 2019 and C++ feature checking and FetchContent

src/mtconnect/agent.cpp

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ namespace mtconnect {
252252
catch (std::runtime_error &e)
253253
{
254254
LOG(fatal) << "Cannot start server: " << e.what();
255-
std::exit(1);
255+
throw FatalException(e.what());
256256
}
257257

258258
m_started = true;
@@ -436,14 +436,14 @@ namespace mtconnect {
436436
LOG(fatal) << "Error loading xml configuration: " + deviceFile;
437437
LOG(fatal) << "Error detail: " << e.what();
438438
cerr << e.what() << endl;
439-
throw e;
439+
throw FatalException(e.what());
440440
}
441441
catch (exception &f)
442442
{
443443
LOG(fatal) << "Error loading xml configuration: " + deviceFile;
444444
LOG(fatal) << "Error detail: " << f.what();
445445
cerr << f.what() << endl;
446-
throw f;
446+
throw FatalException(f.what());
447447
}
448448
}
449449

@@ -525,6 +525,10 @@ namespace mtconnect {
525525
if (changed)
526526
loadCachedProbe();
527527
}
528+
catch (FatalException &e)
529+
{
530+
throw e;
531+
}
528532
catch (runtime_error &e)
529533
{
530534
for (auto device : devices)
@@ -832,7 +836,7 @@ namespace mtconnect {
832836
{
833837
for (auto &e : errors)
834838
LOG(fatal) << "Error creating the agent device: " << e->what();
835-
throw EntityError("Cannot create AgentDevice");
839+
throw FatalException("Cannot create AgentDevice");
836840
}
837841
addDevice(m_agentDevice);
838842
}
@@ -870,14 +874,14 @@ namespace mtconnect {
870874
LOG(fatal) << "Error loading xml configuration: " + configXmlPath;
871875
LOG(fatal) << "Error detail: " << e.what();
872876
cerr << e.what() << endl;
873-
throw e;
877+
throw FatalException(e.what());
874878
}
875879
catch (exception &f)
876880
{
877881
LOG(fatal) << "Error loading xml configuration: " + configXmlPath;
878882
LOG(fatal) << "Error detail: " << f.what();
879883
cerr << f.what() << endl;
880-
throw f;
884+
throw FatalException(f.what());
881885
}
882886

883887
return {};
@@ -976,9 +980,13 @@ namespace mtconnect {
976980
auto di = m_dataItemMap[d->getId()].lock();
977981
if (di && di != d)
978982
{
979-
LOG(fatal) << "Duplicate DataItem id " << d->getId()
980-
<< " for device: " << *device->getComponentName();
981-
std::exit(1);
983+
stringstream msg;
984+
985+
msg << "Duplicate DataItem id " << d->getId()
986+
<< " for device: " << *device->getComponentName()
987+
<< ". Try using configuration option CreateUniqueIds to resolve.";
988+
LOG(fatal) << msg.str();
989+
throw FatalException(msg.str());
982990
}
983991
}
984992
else
@@ -1008,9 +1016,10 @@ namespace mtconnect {
10081016
if (old != idx.end())
10091017
{
10101018
// Update existing device
1011-
LOG(fatal) << "Device " << *device->getUuid() << " already exists. "
1012-
<< " Update not supported yet";
1013-
std::exit(1);
1019+
stringstream msg;
1020+
msg << "Device " << *device->getUuid() << " already exists. "
1021+
<< " Update not supported yet";
1022+
throw msg;
10141023
}
10151024
else
10161025
{

src/mtconnect/configuration/agent_config.cpp

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -182,12 +182,12 @@ namespace mtconnect::configuration {
182182
buffer << file.rdbuf();
183183

184184
FileFormat fmt = MTCONNECT;
185-
if (ends_with(m_configFile.string(), "json"))
185+
if (m_configFile.string().ends_with("json"))
186186
{
187187
LOG(debug) << "Parsing json configuration";
188188
fmt = JSON;
189189
}
190-
else if (ends_with(m_configFile.string(), "xml"))
190+
else if (m_configFile.string().ends_with("xml"))
191191
{
192192
LOG(debug) << "Parsing xml configuration";
193193
fmt = XML;
@@ -392,7 +392,7 @@ namespace mtconnect::configuration {
392392
m_monitorTimer.async_wait(boost::bind(&AgentConfiguration::monitorFiles, this, _1));
393393
}
394394

395-
void AgentConfiguration::start()
395+
int AgentConfiguration::start()
396396
{
397397
if (m_monitorFiles)
398398
{
@@ -411,7 +411,7 @@ namespace mtconnect::configuration {
411411
m_context->setThreadCount(m_workerThreadCount);
412412
m_beforeStartHooks.exec(*this);
413413
m_agent->start();
414-
m_context->start();
414+
return m_context->start();
415415
}
416416

417417
void AgentConfiguration::stop()
@@ -879,12 +879,12 @@ namespace mtconnect::configuration {
879879
LOG(fatal) << "Cannot find device configuration file";
880880
logPaths(LOG_LEVEL(fatal), m_configPaths);
881881

882-
throw runtime_error(((string) "Please make sure the configuration "
883-
"file probe.xml or Devices.xml is in the current "
884-
"directory or specify the correct file "
885-
"in the configuration file " +
886-
m_configFile.string() + " using Devices = <file>")
887-
.c_str());
882+
throw FatalException(((string) "Please make sure the configuration "
883+
"file probe.xml or Devices.xml is in the current "
884+
"directory or specify the correct file "
885+
"in the configuration file " +
886+
m_configFile.string() + " using Devices = <file>")
887+
.c_str());
888888
}
889889

890890
m_name = get<string>(options[configuration::ServiceName]);
@@ -958,7 +958,7 @@ namespace mtconnect::configuration {
958958
if (host.empty())
959959
{
960960
LOG(fatal) << "Malformed URL in configuration file: '" << url << "', exiting";
961-
exit(1);
961+
throw FatalException();
962962
}
963963
options[configuration::Host] = host;
964964

@@ -1252,4 +1252,3 @@ namespace mtconnect::configuration {
12521252
return false;
12531253
}
12541254
} // namespace mtconnect::configuration
1255-

src/mtconnect/configuration/agent_config.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,8 @@ namespace mtconnect {
104104
/// @brief stops the agent. Used in daemons.
105105
void stop() override;
106106
/// @brief starts the agent. Used in daemons.
107-
void start() override;
107+
/// @return 0 on success
108+
int start() override;
108109
/// @brief initializes the configuration of the agent from the command line parameters
109110
/// @param[in] options command line parameters
110111
void initialize(const boost::program_options::variables_map &options) override;

src/mtconnect/configuration/async_context.hpp

Lines changed: 81 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
#include "mtconnect/config.hpp"
2424
#include "mtconnect/logging.hpp"
25+
#include "mtconnect/utilities.hpp"
2526

2627
namespace mtconnect::configuration {
2728

@@ -63,46 +64,96 @@ namespace mtconnect::configuration {
6364
void setThreadCount(int threads) { m_threadCount = threads; }
6465

6566
/// @brief start `m_threadCount` worker threads
66-
void start()
67+
/// @returns the exit code
68+
int start()
6769
{
68-
m_running = true;
69-
m_paused = false;
70-
do
70+
m_exitCode = 0;
71+
try
7172
{
72-
for (int i = 0; i < m_threadCount; i++)
73-
{
74-
m_workers.emplace_back(boost::thread([this]() { m_context.run(); }));
75-
}
76-
auto &first = m_workers.front();
77-
while (m_running && !m_paused)
73+
m_running = true;
74+
m_paused = false;
75+
do
7876
{
79-
if (!first.try_join_for(boost::chrono::seconds(5)) && !m_running)
77+
for (int i = 0; i < m_threadCount; i++)
78+
{
79+
m_workers.emplace_back(boost::thread([this]() {
80+
try
81+
{
82+
m_context.run();
83+
}
84+
85+
catch (FatalException &e)
86+
{
87+
LOG(fatal) << "Fatal exception occurred: " << e.what();
88+
stop();
89+
m_exitCode = 1;
90+
}
91+
catch (std::exception &e)
92+
{
93+
LOG(fatal) << "Uncaught exception occurred: " << e.what();
94+
stop();
95+
m_exitCode = 1;
96+
}
97+
catch (...)
98+
{
99+
LOG(fatal) << "Unknown fatal exception occurred";
100+
stop();
101+
m_exitCode = 1;
102+
}
103+
}));
104+
}
105+
auto &first = m_workers.front();
106+
while (m_running && !m_paused)
80107
{
81-
if (!first.try_join_for(boost::chrono::seconds(5)))
82-
m_context.stop();
108+
if (!first.try_join_for(boost::chrono::seconds(5)) && !m_running)
109+
{
110+
if (!first.try_join_for(boost::chrono::seconds(5)))
111+
m_context.stop();
112+
}
83113
}
84-
}
85114

86-
for (auto &w : m_workers)
87-
{
88-
w.join();
89-
}
90-
m_workers.clear();
115+
for (auto &w : m_workers)
116+
{
117+
w.join();
118+
}
119+
m_workers.clear();
91120

92-
if (m_delayedStop.joinable())
93-
m_delayedStop.join();
121+
if (m_delayedStop.joinable())
122+
m_delayedStop.join();
94123

95-
if (m_syncCallback)
96-
{
97-
m_syncCallback(*this);
98-
if (m_running)
124+
if (m_syncCallback && m_exitCode == 0)
99125
{
100-
m_syncCallback = nullptr;
101-
restart();
126+
m_syncCallback(*this);
127+
if (m_running)
128+
{
129+
m_syncCallback = nullptr;
130+
restart();
131+
}
102132
}
103-
}
104133

105-
} while (m_running);
134+
} while (m_running);
135+
}
136+
137+
catch (FatalException &e)
138+
{
139+
LOG(fatal) << "Fatal exception occurred: " << e.what();
140+
stop();
141+
m_exitCode = 1;
142+
}
143+
catch (std::exception &e)
144+
{
145+
LOG(fatal) << "Uncaught exception occurred: " << e.what();
146+
stop();
147+
m_exitCode = 1;
148+
}
149+
catch (...)
150+
{
151+
LOG(fatal) << "Unknown fatal exception occurred";
152+
stop();
153+
m_exitCode = 1;
154+
}
155+
156+
return m_exitCode;
106157
}
107158

108159
/// @brief pause the worker threads. Sets a callback when the threads are paused.
@@ -190,6 +241,7 @@ namespace mtconnect::configuration {
190241
int m_threadCount = 1;
191242
bool m_running = false;
192243
bool m_paused = false;
244+
int m_exitCode = 0;
193245
};
194246

195247
} // namespace mtconnect::configuration

src/mtconnect/configuration/service.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,8 @@ namespace mtconnect {
176176

177177
using namespace std;
178178

179+
int res = 0;
180+
179181
try
180182
{
181183
// If command-line parameter is "install", install the service. If debug or run
@@ -208,9 +210,9 @@ namespace mtconnect {
208210
m_isDebug = true;
209211

210212
initialize(options);
211-
start();
213+
res = start();
212214
std::thread cmd(commandLine);
213-
return 0;
215+
return res;
214216
}
215217
else
216218
{
@@ -236,14 +238,16 @@ namespace mtconnect {
236238
{
237239
LOG(fatal) << "Agent top level exception: " << e.what();
238240
std::cerr << "Agent top level exception: " << e.what() << std::endl;
241+
res = 1;
239242
}
240243
catch (std::string &s)
241244
{
242245
LOG(fatal) << "Agent top level exception: " << s;
243246
std::cerr << "Agent top level exception: " << s << std::endl;
247+
res = 1;
244248
}
245249

246-
return 0;
250+
return res;
247251
}
248252

249253
bool MTConnectService::isElevated()
@@ -841,8 +845,7 @@ namespace mtconnect {
841845
usage(1);
842846
}
843847

844-
start();
845-
return 0;
848+
return start();
846849
}
847850

848851
void MTConnectService::install() {}

src/mtconnect/configuration/service.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ namespace mtconnect {
4444
/// @brief stop the srvice
4545
virtual void stop() = 0;
4646
/// @brief start the service
47-
virtual void start() = 0;
47+
virtual int start() = 0;
4848

4949
/// @brief set the name of the service
5050
/// @param[in] name name of the service

src/mtconnect/device_model/agent_device.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ namespace mtconnect {
6666
{
6767
LOG(fatal) << "Cannot create AgentDevice: " << e->what();
6868
}
69+
throw FatalException();
6970
}
7071
}
7172

src/mtconnect/device_model/data_item/data_item.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ namespace mtconnect {
130130
auto &category = get<string>("category");
131131

132132
auto units = maybeGet<string>("units");
133-
if (units && ends_with(*units, "3D"))
133+
if (units && units->ends_with("3D"))
134134
m_specialClass = THREE_SPACE_CLS;
135135

136136
if (category == "SAMPLE")

0 commit comments

Comments
 (0)