mirror of
https://github.com/FairRootGroup/FairMQ.git
synced 2025-10-13 16:46:47 +00:00
SDK: Add Topology::AsyncSetProperties
Co-Author: Alexey Rybalchenko <alexryba@gmail.com>
This commit is contained in:
parent
25658370fa
commit
1c8ad03f3c
|
@ -1,3 +1,3 @@
|
||||||
---
|
---
|
||||||
Checks: '*,-google-*,-fuchsia-*,-cert-*,-llvm-header-guard,-readability-named-parameter,-misc-non-private-member-variables-in-classes,-*-magic-numbers,-llvm-include-order,-hicpp-no-array-decay,-performance-unnecessary-value-param,-cppcoreguidelines-pro-bounds-array-to-pointer-decay'
|
Checks: '*,-google-*,-fuchsia-*,-cert-*,-llvm-header-guard,-readability-named-parameter,-misc-non-private-member-variables-in-classes,-*-magic-numbers,-llvm-include-order,-hicpp-no-array-decay,-performance-unnecessary-value-param,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-modernize-use-trailing-return-type,-readability-redundant-member-init'
|
||||||
HeaderFilterRegex: '/(fairmq/)'
|
HeaderFilterRegex: '/(fairmq/)'
|
||||||
|
|
|
@ -324,7 +324,6 @@ auto DDS::HeartbeatSender() -> void
|
||||||
|
|
||||||
auto DDS::SubscribeForCustomCommands() -> void
|
auto DDS::SubscribeForCustomCommands() -> void
|
||||||
{
|
{
|
||||||
using namespace sdk::cmd;
|
|
||||||
LOG(debug) << "Subscribing for DDS custom commands.";
|
LOG(debug) << "Subscribing for DDS custom commands.";
|
||||||
|
|
||||||
string id = GetProperty<string>("id");
|
string id = GetProperty<string>("id");
|
||||||
|
@ -332,59 +331,59 @@ auto DDS::SubscribeForCustomCommands() -> void
|
||||||
fDDS.SubscribeCustomCmd([id, this](const string& cmdStr, const string& cond, uint64_t senderId) {
|
fDDS.SubscribeCustomCmd([id, this](const string& cmdStr, const string& cond, uint64_t senderId) {
|
||||||
// LOG(info) << "Received command: '" << cmdStr << "' from " << senderId;
|
// LOG(info) << "Received command: '" << cmdStr << "' from " << senderId;
|
||||||
|
|
||||||
Cmds inCmds;
|
using namespace fair::mq::sdk;
|
||||||
|
cmd::Cmds inCmds;
|
||||||
inCmds.Deserialize(cmdStr);
|
inCmds.Deserialize(cmdStr);
|
||||||
|
|
||||||
for (const auto& cmd : inCmds) {
|
for (const auto& cmd : inCmds) {
|
||||||
// LOG(info) << "Received command type: '" << cmd->GetType() << "' from " << senderId;
|
// LOG(info) << "Received command type: '" << cmd->GetType() << "' from " << senderId;
|
||||||
switch (cmd->GetType()) {
|
switch (cmd->GetType()) {
|
||||||
case Type::check_state: {
|
case cmd::Type::check_state: {
|
||||||
fDDS.Send(Cmds(make<CurrentState>(id, GetCurrentDeviceState())).Serialize(), to_string(senderId));
|
fDDS.Send(cmd::Cmds(cmd::make<cmd::CurrentState>(id, GetCurrentDeviceState()))
|
||||||
}
|
.Serialize(),
|
||||||
break;
|
to_string(senderId));
|
||||||
case Type::change_state: {
|
} break;
|
||||||
Transition transition = static_cast<ChangeState&>(*cmd).GetTransition();
|
case cmd::Type::change_state: {
|
||||||
|
Transition transition = static_cast<cmd::ChangeState&>(*cmd).GetTransition();
|
||||||
if (ChangeDeviceState(transition)) {
|
if (ChangeDeviceState(transition)) {
|
||||||
Cmds outCmds(make<TransitionStatus>(id, Result::Ok, transition));
|
cmd::Cmds outCmds(
|
||||||
|
cmd::make<cmd::TransitionStatus>(id, cmd::Result::Ok, transition));
|
||||||
fDDS.Send(outCmds.Serialize(), to_string(senderId));
|
fDDS.Send(outCmds.Serialize(), to_string(senderId));
|
||||||
} else {
|
} else {
|
||||||
Cmds outCmds(make<TransitionStatus>(id, Result::Failure, transition));
|
sdk::cmd::Cmds outCmds(
|
||||||
|
cmd::make<cmd::TransitionStatus>(id, cmd::Result::Failure, transition));
|
||||||
fDDS.Send(outCmds.Serialize(), to_string(senderId));
|
fDDS.Send(outCmds.Serialize(), to_string(senderId));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
lock_guard<mutex> lock{fStateChangeSubscriberMutex};
|
lock_guard<mutex> lock{fStateChangeSubscriberMutex};
|
||||||
fLastExternalController = senderId;
|
fLastExternalController = senderId;
|
||||||
}
|
}
|
||||||
}
|
} break;
|
||||||
break;
|
case cmd::Type::dump_config: {
|
||||||
case Type::dump_config: {
|
|
||||||
stringstream ss;
|
stringstream ss;
|
||||||
for (const auto pKey: GetPropertyKeys()) {
|
for (const auto pKey : GetPropertyKeys()) {
|
||||||
ss << id << ": " << pKey << " -> " << GetPropertyAsString(pKey) << "\n";
|
ss << id << ": " << pKey << " -> " << GetPropertyAsString(pKey) << "\n";
|
||||||
}
|
}
|
||||||
Cmds outCmds(make<Config>(id, ss.str()));
|
cmd::Cmds outCmds(cmd::make<cmd::Config>(id, ss.str()));
|
||||||
fDDS.Send(outCmds.Serialize(), to_string(senderId));
|
fDDS.Send(outCmds.Serialize(), to_string(senderId));
|
||||||
}
|
} break;
|
||||||
break;
|
case cmd::Type::subscribe_to_heartbeats: {
|
||||||
case Type::subscribe_to_heartbeats: {
|
|
||||||
{
|
{
|
||||||
lock_guard<mutex> lock{fHeartbeatSubscriberMutex};
|
lock_guard<mutex> lock{fHeartbeatSubscriberMutex};
|
||||||
fHeartbeatSubscribers.insert(senderId);
|
fHeartbeatSubscribers.insert(senderId);
|
||||||
}
|
}
|
||||||
Cmds outCmds(make<HeartbeatSubscription>(id, Result::Ok));
|
cmd::Cmds outCmds(cmd::make<cmd::HeartbeatSubscription>(id, cmd::Result::Ok));
|
||||||
fDDS.Send(outCmds.Serialize(), to_string(senderId));
|
fDDS.Send(outCmds.Serialize(), to_string(senderId));
|
||||||
}
|
} break;
|
||||||
break;
|
case cmd::Type::unsubscribe_from_heartbeats: {
|
||||||
case Type::unsubscribe_from_heartbeats: {
|
|
||||||
{
|
{
|
||||||
lock_guard<mutex> lock{fHeartbeatSubscriberMutex};
|
lock_guard<mutex> lock{fHeartbeatSubscriberMutex};
|
||||||
fHeartbeatSubscribers.erase(senderId);
|
fHeartbeatSubscribers.erase(senderId);
|
||||||
}
|
}
|
||||||
Cmds outCmds(make<HeartbeatUnsubscription>(id, Result::Ok));
|
cmd::Cmds outCmds(cmd::make<cmd::HeartbeatUnsubscription>(id, cmd::Result::Ok));
|
||||||
fDDS.Send(outCmds.Serialize(), to_string(senderId));
|
fDDS.Send(outCmds.Serialize(), to_string(senderId));
|
||||||
}
|
} break;
|
||||||
break;
|
case cmd::Type::state_change_exiting_received: {
|
||||||
case Type::state_change_exiting_received: {
|
|
||||||
{
|
{
|
||||||
lock_guard<mutex> lock{fStateChangeSubscriberMutex};
|
lock_guard<mutex> lock{fStateChangeSubscriberMutex};
|
||||||
if (fLastExternalController == senderId) {
|
if (fLastExternalController == senderId) {
|
||||||
|
@ -392,31 +391,50 @@ auto DDS::SubscribeForCustomCommands() -> void
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fExitingAcked.notify_one();
|
fExitingAcked.notify_one();
|
||||||
}
|
} break;
|
||||||
break;
|
case cmd::Type::subscribe_to_state_change: {
|
||||||
case Type::subscribe_to_state_change: {
|
|
||||||
lock_guard<mutex> lock{fStateChangeSubscriberMutex};
|
lock_guard<mutex> lock{fStateChangeSubscriberMutex};
|
||||||
fStateChangeSubscribers.insert(senderId);
|
fStateChangeSubscribers.insert(senderId);
|
||||||
if (!fControllerThread.joinable()) {
|
if (!fControllerThread.joinable()) {
|
||||||
fControllerThread = thread(&DDS::WaitForExitingAck, this);
|
fControllerThread = thread(&DDS::WaitForExitingAck, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(debug) << "Publishing state-change: " << fLastState << "->" << fCurrentState << " to " << senderId;
|
LOG(debug) << "Publishing state-change: " << fLastState << "->" << fCurrentState
|
||||||
|
<< " to " << senderId;
|
||||||
|
|
||||||
Cmds outCmds(make<StateChangeSubscription>(id, Result::Ok), make<StateChange>(id, dds::env_prop<dds::task_id>(), fLastState, fCurrentState));
|
cmd::Cmds outCmds(
|
||||||
|
cmd::make<cmd::StateChangeSubscription>(id, cmd::Result::Ok),
|
||||||
|
cmd::make<cmd::StateChange>(
|
||||||
|
id, dds::env_prop<dds::task_id>(), fLastState, fCurrentState));
|
||||||
|
|
||||||
fDDS.Send(outCmds.Serialize(), to_string(senderId));
|
fDDS.Send(outCmds.Serialize(), to_string(senderId));
|
||||||
}
|
} break;
|
||||||
break;
|
case cmd::Type::unsubscribe_from_state_change: {
|
||||||
case Type::unsubscribe_from_state_change: {
|
|
||||||
{
|
{
|
||||||
lock_guard<mutex> lock{fStateChangeSubscriberMutex};
|
lock_guard<mutex> lock{fStateChangeSubscriberMutex};
|
||||||
fStateChangeSubscribers.erase(senderId);
|
fStateChangeSubscribers.erase(senderId);
|
||||||
}
|
}
|
||||||
Cmds outCmds(make<StateChangeUnsubscription>(id, Result::Ok));
|
cmd::Cmds outCmds(
|
||||||
|
cmd::make<cmd::StateChangeUnsubscription>(id, cmd::Result::Ok));
|
||||||
fDDS.Send(outCmds.Serialize(), to_string(senderId));
|
fDDS.Send(outCmds.Serialize(), to_string(senderId));
|
||||||
}
|
} break;
|
||||||
break;
|
case cmd::Type::set_properties: {
|
||||||
|
auto _cmd(static_cast<cmd::SetProperties&>(*cmd));
|
||||||
|
auto const request_id(_cmd.GetRequestId());
|
||||||
|
auto result(cmd::Result::Ok);
|
||||||
|
try {
|
||||||
|
fair::mq::Properties props;
|
||||||
|
for (auto const& prop : _cmd.GetProps()) {
|
||||||
|
props.insert({prop.first, fair::mq::Property(prop.second)});
|
||||||
|
}
|
||||||
|
SetProperties(props);
|
||||||
|
} catch (...) {
|
||||||
|
LOG(warn) << "Setting properties (request id: " << request_id << ") failed";
|
||||||
|
result = cmd::Result::Failure;
|
||||||
|
}
|
||||||
|
cmd::Cmds const outCmds(cmd::make<cmd::PropertiesSet>(id, request_id, result));
|
||||||
|
fDDS.Send(outCmds.Serialize(), to_string(senderId));
|
||||||
|
} break;
|
||||||
default:
|
default:
|
||||||
LOG(warn) << "Unexpected/unknown command received: " << cmdStr;
|
LOG(warn) << "Unexpected/unknown command received: " << cmdStr;
|
||||||
LOG(warn) << "Origin: " << senderId;
|
LOG(warn) << "Origin: " << senderId;
|
||||||
|
|
|
@ -27,6 +27,8 @@ std::string ErrorCategory::message(int ev) const
|
||||||
return "async operation canceled";
|
return "async operation canceled";
|
||||||
case ErrorCode::DeviceChangeStateFailed:
|
case ErrorCode::DeviceChangeStateFailed:
|
||||||
return "failed to change state of a fairmq device";
|
return "failed to change state of a fairmq device";
|
||||||
|
case ErrorCode::DeviceSetPropertiesFailed:
|
||||||
|
return "failed to set fairmq device properties";
|
||||||
default:
|
default:
|
||||||
return "(unrecognized error)";
|
return "(unrecognized error)";
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,8 @@ enum class ErrorCode
|
||||||
OperationInProgress = 10,
|
OperationInProgress = 10,
|
||||||
OperationTimeout,
|
OperationTimeout,
|
||||||
OperationCanceled,
|
OperationCanceled,
|
||||||
DeviceChangeStateFailed
|
DeviceChangeStateFailed,
|
||||||
|
DeviceSetPropertiesFailed
|
||||||
};
|
};
|
||||||
|
|
||||||
std::error_code MakeErrorCode(ErrorCode);
|
std::error_code MakeErrorCode(ErrorCode);
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <fairmq/sdk/Error.h>
|
#include <fairmq/sdk/Error.h>
|
||||||
#include <fairmq/States.h>
|
#include <fairmq/States.h>
|
||||||
#include <fairmq/tools/Semaphore.h>
|
#include <fairmq/tools/Semaphore.h>
|
||||||
|
#include <fairmq/tools/Unique.h>
|
||||||
|
|
||||||
#include <fairlogger/Logger.h>
|
#include <fairlogger/Logger.h>
|
||||||
|
|
||||||
|
@ -35,6 +36,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
#include <set>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
@ -45,6 +47,7 @@ namespace fair {
|
||||||
namespace mq {
|
namespace mq {
|
||||||
namespace sdk {
|
namespace sdk {
|
||||||
|
|
||||||
|
using DeviceId = std::string;
|
||||||
using DeviceState = fair::mq::State;
|
using DeviceState = fair::mq::State;
|
||||||
using DeviceTransition = fair::mq::Transition;
|
using DeviceTransition = fair::mq::Transition;
|
||||||
|
|
||||||
|
@ -70,6 +73,9 @@ struct DeviceStatus
|
||||||
DDSCollection::Id collectionId;
|
DDSCollection::Id collectionId;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using DeviceProperty = std::pair<std::string, std::string>; /// pair := (key, value)
|
||||||
|
using DeviceProperties = std::vector<DeviceProperty>;
|
||||||
|
|
||||||
using TopologyState = std::vector<DeviceStatus>;
|
using TopologyState = std::vector<DeviceStatus>;
|
||||||
using TopologyStateIndex = std::unordered_map<DDSTask::Id, int>; // task id -> index in the data vector
|
using TopologyStateIndex = std::unordered_map<DDSTask::Id, int>; // task id -> index in the data vector
|
||||||
using TopologyStateByTask = std::unordered_map<DDSTask::Id, DeviceStatus>;
|
using TopologyStateByTask = std::unordered_map<DDSTask::Id, DeviceStatus>;
|
||||||
|
@ -168,20 +174,21 @@ class BasicTopology : public AsioBase<Executor, Allocator>
|
||||||
Cmds inCmds;
|
Cmds inCmds;
|
||||||
inCmds.Deserialize(msg);
|
inCmds.Deserialize(msg);
|
||||||
// LOG(debug) << "Received " << inCmds.Size() << " command(s) with total size of " << msg.length() << " bytes: ";
|
// LOG(debug) << "Received " << inCmds.Size() << " command(s) with total size of " << msg.length() << " bytes: ";
|
||||||
|
|
||||||
for (const auto& cmd : inCmds) {
|
for (const auto& cmd : inCmds) {
|
||||||
// LOG(debug) << " > " << cmd->GetType();
|
// LOG(debug) << " > " << cmd->GetType();
|
||||||
switch (cmd->GetType()) {
|
switch (cmd->GetType()) {
|
||||||
case Type::state_change: {
|
case Type::state_change: {
|
||||||
DDSTask::Id taskId(static_cast<StateChange&>(*cmd).GetTaskId());
|
auto _cmd = static_cast<StateChange&>(*cmd);
|
||||||
|
DDSTask::Id taskId(_cmd.GetTaskId());
|
||||||
fDDSSession.UpdateChannelToTaskAssociation(senderId, taskId);
|
fDDSSession.UpdateChannelToTaskAssociation(senderId, taskId);
|
||||||
if (static_cast<StateChange&>(*cmd).GetCurrentState() == DeviceState::Exiting) {
|
if (_cmd.GetCurrentState() == DeviceState::Exiting) {
|
||||||
Cmds outCmds;
|
Cmds outCmds;
|
||||||
outCmds.Add<StateChangeExitingReceived>();
|
outCmds.Add<StateChangeExitingReceived>();
|
||||||
fDDSSession.SendCommand(outCmds.Serialize(), senderId);
|
fDDSSession.SendCommand(outCmds.Serialize(), senderId);
|
||||||
}
|
}
|
||||||
UpdateStateEntry(taskId, static_cast<StateChange&>(*cmd).GetCurrentState());
|
UpdateStateEntry(taskId, _cmd.GetCurrentState());
|
||||||
}
|
} break;
|
||||||
break;
|
|
||||||
case Type::state_change_subscription:
|
case Type::state_change_subscription:
|
||||||
if (static_cast<StateChangeSubscription&>(*cmd).GetResult() != Result::Ok) {
|
if (static_cast<StateChangeSubscription&>(*cmd).GetResult() != Result::Ok) {
|
||||||
LOG(error) << "State change subscription failed for " << static_cast<StateChangeSubscription&>(*cmd).GetDeviceId();
|
LOG(error) << "State change subscription failed for " << static_cast<StateChangeSubscription&>(*cmd).GetDeviceId();
|
||||||
|
@ -203,6 +210,10 @@ class BasicTopology : public AsioBase<Executor, Allocator>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case Type::properties_set: {
|
||||||
|
HandleCmd(static_cast<cmd::PropertiesSet&>(*cmd));
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
LOG(warn) << "Unexpected/unknown command received: " << cmd->GetType();
|
LOG(warn) << "Unexpected/unknown command received: " << cmd->GetType();
|
||||||
LOG(warn) << "Origin: " << senderId;
|
LOG(warn) << "Origin: " << senderId;
|
||||||
|
@ -320,55 +331,53 @@ class BasicTopology : public AsioBase<Executor, Allocator>
|
||||||
/// }
|
/// }
|
||||||
/// @endcode
|
/// @endcode
|
||||||
template<typename CompletionToken>
|
template<typename CompletionToken>
|
||||||
auto AsyncChangeState(TopologyTransition transition,
|
auto AsyncChangeState(const TopologyTransition transition,
|
||||||
Duration timeout,
|
Duration timeout,
|
||||||
CompletionToken&& token)
|
CompletionToken&& token)
|
||||||
{
|
{
|
||||||
return asio::async_initiate<CompletionToken, ChangeStateCompletionSignature>(
|
return asio::async_initiate<CompletionToken, ChangeStateCompletionSignature>([&](auto handler) {
|
||||||
[&](auto handler) {
|
std::lock_guard<std::mutex> lk(fMtx);
|
||||||
std::lock_guard<std::mutex> lk(fMtx);
|
|
||||||
|
|
||||||
if (fChangeStateOp.IsCompleted()) {
|
if (fChangeStateOp.IsCompleted()) {
|
||||||
fChangeStateOp = ChangeStateOp(AsioBase<Executor, Allocator>::GetExecutor(),
|
fChangeStateOp = ChangeStateOp(AsioBase<Executor, Allocator>::GetExecutor(),
|
||||||
AsioBase<Executor, Allocator>::GetAllocator(),
|
AsioBase<Executor, Allocator>::GetAllocator(),
|
||||||
std::move(handler));
|
std::move(handler));
|
||||||
fChangeStateTarget = expectedState.at(transition);
|
fChangeStateTarget = expectedState.at(transition);
|
||||||
ResetTransitionedCount(fChangeStateTarget);
|
ResetTransitionedCount(fChangeStateTarget);
|
||||||
cmd::Cmds cmds(cmd::make<cmd::ChangeState>(transition));
|
cmd::Cmds cmds(cmd::make<cmd::ChangeState>(transition));
|
||||||
fDDSSession.SendCommand(cmds.Serialize());
|
fDDSSession.SendCommand(cmds.Serialize());
|
||||||
if (timeout > std::chrono::milliseconds(0)) {
|
if (timeout > std::chrono::milliseconds(0)) {
|
||||||
fChangeStateOpTimer.expires_after(timeout);
|
fChangeStateOpTimer.expires_after(timeout);
|
||||||
fChangeStateOpTimer.async_wait([&](std::error_code ec) {
|
fChangeStateOpTimer.async_wait([&](std::error_code ec) {
|
||||||
if (!ec) {
|
if (!ec) {
|
||||||
std::lock_guard<std::mutex> lk2(fMtx);
|
std::lock_guard<std::mutex> lk2(fMtx);
|
||||||
fChangeStateOp.Timeout(fStateData);
|
fChangeStateOp.Timeout(fStateData);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// TODO refactor to hide boiler plate
|
|
||||||
auto ex2(asio::get_associated_executor(handler, AsioBase<Executor, Allocator>::GetExecutor()));
|
|
||||||
auto alloc2(asio::get_associated_allocator(handler, AsioBase<Executor, Allocator>::GetAllocator()));
|
|
||||||
auto state(GetCurrentStateUnsafe());
|
|
||||||
|
|
||||||
ex2.post(
|
|
||||||
[h = std::move(handler), s = std::move(state)]() mutable {
|
|
||||||
try {
|
|
||||||
h(MakeErrorCode(ErrorCode::OperationInProgress), s);
|
|
||||||
} catch (const std::exception& e) {
|
|
||||||
LOG(error) << "Uncaught exception in completion handler: " << e.what();
|
|
||||||
} catch (...) {
|
|
||||||
LOG(error) << "Unknown uncaught exception in completion handler.";
|
|
||||||
}
|
|
||||||
},
|
|
||||||
alloc2);
|
|
||||||
}
|
}
|
||||||
},
|
} else {
|
||||||
token);
|
// TODO refactor to hide boiler plate
|
||||||
|
auto ex2(asio::get_associated_executor(handler, AsioBase<Executor, Allocator>::GetExecutor()));
|
||||||
|
auto alloc2(asio::get_associated_allocator(handler, AsioBase<Executor, Allocator>::GetAllocator()));
|
||||||
|
auto state(GetCurrentStateUnsafe());
|
||||||
|
|
||||||
|
ex2.post([h = std::move(handler), s = std::move(state)]() mutable {
|
||||||
|
try {
|
||||||
|
h(MakeErrorCode(ErrorCode::OperationInProgress), s);
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
LOG(error) << "Uncaught exception in completion handler: " << e.what();
|
||||||
|
} catch (...) {
|
||||||
|
LOG(error) << "Unknown uncaught exception in completion handler.";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
alloc2);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
token);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename CompletionToken>
|
template<typename CompletionToken>
|
||||||
auto AsyncChangeState(TopologyTransition transition, CompletionToken&& token)
|
auto AsyncChangeState(const TopologyTransition transition, CompletionToken&& token)
|
||||||
{
|
{
|
||||||
return AsyncChangeState(transition, Duration(0), std::move(token));
|
return AsyncChangeState(transition, Duration(0), std::move(token));
|
||||||
}
|
}
|
||||||
|
@ -378,7 +387,7 @@ class BasicTopology : public AsioBase<Executor, Allocator>
|
||||||
/// @param timeout Timeout in milliseconds, 0 means no timeout
|
/// @param timeout Timeout in milliseconds, 0 means no timeout
|
||||||
/// @tparam CompletionToken Asio completion token type
|
/// @tparam CompletionToken Asio completion token type
|
||||||
/// @throws std::system_error
|
/// @throws std::system_error
|
||||||
auto ChangeState(TopologyTransition transition, Duration timeout = Duration(0))
|
auto ChangeState(const TopologyTransition transition, Duration timeout = Duration(0))
|
||||||
-> std::pair<std::error_code, TopologyState>
|
-> std::pair<std::error_code, TopologyState>
|
||||||
{
|
{
|
||||||
tools::SharedSemaphore blocker;
|
tools::SharedSemaphore blocker;
|
||||||
|
@ -406,6 +415,146 @@ class BasicTopology : public AsioBase<Executor, Allocator>
|
||||||
|
|
||||||
auto StateEqualsTo(DeviceState state) const -> bool { return sdk::StateEqualsTo(GetCurrentState(), state); }
|
auto StateEqualsTo(DeviceState state) const -> bool { return sdk::StateEqualsTo(GetCurrentState(), state); }
|
||||||
|
|
||||||
|
using FailedDevices = std::set<DeviceId>;
|
||||||
|
using SetPropertiesCompletionSignature = void(std::error_code, FailedDevices);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct SetPropertiesOp
|
||||||
|
{
|
||||||
|
using Id = std::size_t;
|
||||||
|
using SetCount = unsigned int;
|
||||||
|
|
||||||
|
template<typename Handler>
|
||||||
|
SetPropertiesOp(Id id,
|
||||||
|
SetCount expectedCount,
|
||||||
|
Duration timeout,
|
||||||
|
std::mutex& mutex,
|
||||||
|
Executor const & ex,
|
||||||
|
Allocator const & alloc,
|
||||||
|
Handler&& handler)
|
||||||
|
: fId(id)
|
||||||
|
, fOp(ex, alloc, std::move(handler))
|
||||||
|
, fTimer(ex)
|
||||||
|
, fCount(0)
|
||||||
|
, fExpectedCount(expectedCount)
|
||||||
|
, fFailedDevices(alloc)
|
||||||
|
, fMtx(mutex)
|
||||||
|
{
|
||||||
|
if (timeout > std::chrono::milliseconds(0)) {
|
||||||
|
fTimer.expires_after(timeout);
|
||||||
|
fTimer.async_wait([&](std::error_code ec) {
|
||||||
|
if (!ec) {
|
||||||
|
std::lock_guard<std::mutex> lk(fMtx);
|
||||||
|
fOp.Timeout(fFailedDevices);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// LOG(debug) << "SetProperties " << fId << " with expected count of " << fExpectedCount << " started.";
|
||||||
|
}
|
||||||
|
SetPropertiesOp() = delete;
|
||||||
|
SetPropertiesOp(const SetPropertiesOp&) = delete;
|
||||||
|
SetPropertiesOp& operator=(const SetPropertiesOp&) = delete;
|
||||||
|
SetPropertiesOp(SetPropertiesOp&&) = default;
|
||||||
|
SetPropertiesOp& operator=(SetPropertiesOp&&) = default;
|
||||||
|
~SetPropertiesOp() = default;
|
||||||
|
|
||||||
|
auto Update(const std::string& deviceId, cmd::Result result) -> void
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lk(fMtx);
|
||||||
|
if (cmd::Result::Ok != result) {
|
||||||
|
fFailedDevices.insert(deviceId);
|
||||||
|
}
|
||||||
|
++fCount;
|
||||||
|
TryCompletion();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Id const fId;
|
||||||
|
AsioAsyncOp<Executor, Allocator, SetPropertiesCompletionSignature> fOp;
|
||||||
|
asio::steady_timer fTimer;
|
||||||
|
SetCount fCount;
|
||||||
|
SetCount const fExpectedCount;
|
||||||
|
FailedDevices fFailedDevices;
|
||||||
|
std::mutex& fMtx;
|
||||||
|
|
||||||
|
/// precondition: fMtx is locked.
|
||||||
|
auto TryCompletion() -> void
|
||||||
|
{
|
||||||
|
if (!fOp.IsCompleted() && fCount == fExpectedCount) {
|
||||||
|
fTimer.cancel();
|
||||||
|
if (fFailedDevices.size() > 0) {
|
||||||
|
fOp.Complete(MakeErrorCode(ErrorCode::DeviceSetPropertiesFailed), fFailedDevices);
|
||||||
|
} else {
|
||||||
|
fOp.Complete(fFailedDevices);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto HandleCmd(cmd::PropertiesSet const& cmd) -> void
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lk(fMtx);
|
||||||
|
try {
|
||||||
|
auto& op(fSetPropertiesOps.at(cmd.GetRequestId()));
|
||||||
|
lk.unlock();
|
||||||
|
op.Update(cmd.GetDeviceId(), cmd.GetResult());
|
||||||
|
} catch (std::out_of_range& e) {
|
||||||
|
LOG(debug) << "SetProperties operation (request id: " << cmd.GetRequestId()
|
||||||
|
<< ") not found (probably completed or timed out), "
|
||||||
|
<< "discarding reply of device " << cmd.GetDeviceId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
template<typename CompletionToken>
|
||||||
|
auto AsyncSetProperties(const DeviceProperties& props,
|
||||||
|
Duration timeout,
|
||||||
|
CompletionToken&& token)
|
||||||
|
{
|
||||||
|
return asio::async_initiate<CompletionToken, SetPropertiesCompletionSignature>(
|
||||||
|
[&](auto handler) {
|
||||||
|
typename SetPropertiesOp::Id const id(tools::UuidHash());
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lk(fMtx);
|
||||||
|
fSetPropertiesOps.emplace(
|
||||||
|
std::piecewise_construct,
|
||||||
|
std::forward_as_tuple(id),
|
||||||
|
std::forward_as_tuple(id,
|
||||||
|
fStateData.size(),
|
||||||
|
timeout,
|
||||||
|
fMtx,
|
||||||
|
AsioBase<Executor, Allocator>::GetExecutor(),
|
||||||
|
AsioBase<Executor, Allocator>::GetAllocator(),
|
||||||
|
std::move(handler)));
|
||||||
|
|
||||||
|
cmd::Cmds const cmds(cmd::make<cmd::SetProperties>(id, props));
|
||||||
|
fDDSSession.SendCommand(cmds.Serialize());
|
||||||
|
},
|
||||||
|
token);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename CompletionToken>
|
||||||
|
auto AsyncSetProperties(DeviceProperties const & properties, CompletionToken&& token)
|
||||||
|
{
|
||||||
|
return AsyncSetProperties(properties, Duration(0), std::move(token));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto SetProperties(DeviceProperties const& properties, Duration timeout = Duration(0))
|
||||||
|
-> std::pair<std::error_code, FailedDevices>
|
||||||
|
{
|
||||||
|
tools::SharedSemaphore blocker;
|
||||||
|
std::error_code ec;
|
||||||
|
FailedDevices failed;
|
||||||
|
AsyncSetProperties(
|
||||||
|
properties, timeout, [&, blocker](std::error_code _ec, FailedDevices _failed) mutable {
|
||||||
|
ec = _ec;
|
||||||
|
failed = _failed;
|
||||||
|
blocker.Signal();
|
||||||
|
});
|
||||||
|
blocker.Wait();
|
||||||
|
return {ec, failed};
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using TransitionedCount = unsigned int;
|
using TransitionedCount = unsigned int;
|
||||||
|
|
||||||
|
@ -421,6 +570,8 @@ class BasicTopology : public AsioBase<Executor, Allocator>
|
||||||
DeviceState fChangeStateTarget;
|
DeviceState fChangeStateTarget;
|
||||||
TransitionedCount fTransitionedCount;
|
TransitionedCount fTransitionedCount;
|
||||||
|
|
||||||
|
std::unordered_map<typename SetPropertiesOp::Id, SetPropertiesOp> fSetPropertiesOps;
|
||||||
|
|
||||||
auto makeTopologyState() -> void
|
auto makeTopologyState() -> void
|
||||||
{
|
{
|
||||||
fStateData.reserve(fDDSTopo.GetTasks().size());
|
fStateData.reserve(fDDSTopo.GetTasks().size());
|
||||||
|
|
|
@ -46,7 +46,7 @@ array<string, 2> resultNames =
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
array<string, 17> typeNames =
|
array<string, 18> typeNames =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
"CheckState",
|
"CheckState",
|
||||||
|
@ -57,6 +57,7 @@ array<string, 17> typeNames =
|
||||||
"SubscribeToStateChange",
|
"SubscribeToStateChange",
|
||||||
"UnsubscribeFromStateChange",
|
"UnsubscribeFromStateChange",
|
||||||
"StateChangeExitingReceived",
|
"StateChangeExitingReceived",
|
||||||
|
"SetProperties",
|
||||||
|
|
||||||
"CurrentState",
|
"CurrentState",
|
||||||
"TransitionStatus",
|
"TransitionStatus",
|
||||||
|
@ -66,7 +67,8 @@ array<string, 17> typeNames =
|
||||||
"Heartbeat",
|
"Heartbeat",
|
||||||
"StateChangeSubscription",
|
"StateChangeSubscription",
|
||||||
"StateChangeUnsubscription",
|
"StateChangeUnsubscription",
|
||||||
"StateChange"
|
"StateChange",
|
||||||
|
"PropertiesSet"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -148,7 +150,7 @@ array<sdk::cmd::FBTransition, 12> mqTransitionToFBTransition =
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
array<FBCmd, 17> typeToFBCmd =
|
array<FBCmd, 19> typeToFBCmd =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
FBCmd::FBCmd_check_state,
|
FBCmd::FBCmd_check_state,
|
||||||
|
@ -159,6 +161,7 @@ array<FBCmd, 17> typeToFBCmd =
|
||||||
FBCmd::FBCmd_subscribe_to_state_change,
|
FBCmd::FBCmd_subscribe_to_state_change,
|
||||||
FBCmd::FBCmd_unsubscribe_from_state_change,
|
FBCmd::FBCmd_unsubscribe_from_state_change,
|
||||||
FBCmd::FBCmd_state_change_exiting_received,
|
FBCmd::FBCmd_state_change_exiting_received,
|
||||||
|
FBCmd::FBCmd_set_properties,
|
||||||
FBCmd::FBCmd_current_state,
|
FBCmd::FBCmd_current_state,
|
||||||
FBCmd::FBCmd_transition_status,
|
FBCmd::FBCmd_transition_status,
|
||||||
FBCmd::FBCmd_config,
|
FBCmd::FBCmd_config,
|
||||||
|
@ -167,11 +170,12 @@ array<FBCmd, 17> typeToFBCmd =
|
||||||
FBCmd::FBCmd_heartbeat,
|
FBCmd::FBCmd_heartbeat,
|
||||||
FBCmd::FBCmd_state_change_subscription,
|
FBCmd::FBCmd_state_change_subscription,
|
||||||
FBCmd::FBCmd_state_change_unsubscription,
|
FBCmd::FBCmd_state_change_unsubscription,
|
||||||
FBCmd::FBCmd_state_change
|
FBCmd::FBCmd_state_change,
|
||||||
|
FBCmd::FBCmd_properties_set
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
array<Type, 17> fbCmdToType =
|
array<Type, 19> fbCmdToType =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
Type::check_state,
|
Type::check_state,
|
||||||
|
@ -182,6 +186,7 @@ array<Type, 17> fbCmdToType =
|
||||||
Type::subscribe_to_state_change,
|
Type::subscribe_to_state_change,
|
||||||
Type::unsubscribe_from_state_change,
|
Type::unsubscribe_from_state_change,
|
||||||
Type::state_change_exiting_received,
|
Type::state_change_exiting_received,
|
||||||
|
Type::set_properties,
|
||||||
Type::current_state,
|
Type::current_state,
|
||||||
Type::transition_status,
|
Type::transition_status,
|
||||||
Type::config,
|
Type::config,
|
||||||
|
@ -190,7 +195,8 @@ array<Type, 17> fbCmdToType =
|
||||||
Type::heartbeat,
|
Type::heartbeat,
|
||||||
Type::state_change_subscription,
|
Type::state_change_subscription,
|
||||||
Type::state_change_unsubscription,
|
Type::state_change_unsubscription,
|
||||||
Type::state_change
|
Type::state_change,
|
||||||
|
Type::properties_set
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -249,41 +255,60 @@ string Cmds::Serialize(const Format type) const
|
||||||
cmdBuilder = tools::make_unique<FBCommandBuilder>(fbb);
|
cmdBuilder = tools::make_unique<FBCommandBuilder>(fbb);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case Type::set_properties: {
|
||||||
|
auto _cmd = static_cast<SetProperties&>(*cmd);
|
||||||
|
std::vector<flatbuffers::Offset<FBProperty>> propsVector;
|
||||||
|
for (auto const& e : _cmd.GetProps()) {
|
||||||
|
auto const key(fbb.CreateString(e.first));
|
||||||
|
auto const val(fbb.CreateString(e.second));
|
||||||
|
propsVector.push_back(CreateFBProperty(fbb, key, val));
|
||||||
|
}
|
||||||
|
auto props = fbb.CreateVector(propsVector);
|
||||||
|
cmdBuilder = tools::make_unique<FBCommandBuilder>(fbb);
|
||||||
|
cmdBuilder->add_request_id(_cmd.GetRequestId());
|
||||||
|
cmdBuilder->add_properties(props);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case Type::current_state: {
|
case Type::current_state: {
|
||||||
auto deviceId = fbb.CreateString(static_cast<CurrentState&>(*cmd).GetDeviceId());
|
auto _cmd = static_cast<CurrentState&>(*cmd);
|
||||||
|
auto deviceId = fbb.CreateString(_cmd.GetDeviceId());
|
||||||
cmdBuilder = tools::make_unique<FBCommandBuilder>(fbb);
|
cmdBuilder = tools::make_unique<FBCommandBuilder>(fbb);
|
||||||
cmdBuilder->add_device_id(deviceId);
|
cmdBuilder->add_device_id(deviceId);
|
||||||
cmdBuilder->add_current_state(GetFBState(static_cast<CurrentState&>(*cmd).GetCurrentState()));
|
cmdBuilder->add_current_state(GetFBState(_cmd.GetCurrentState()));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Type::transition_status: {
|
case Type::transition_status: {
|
||||||
auto deviceId = fbb.CreateString(static_cast<TransitionStatus&>(*cmd).GetDeviceId());
|
auto _cmd = static_cast<TransitionStatus&>(*cmd);
|
||||||
|
auto deviceId = fbb.CreateString(_cmd.GetDeviceId());
|
||||||
cmdBuilder = tools::make_unique<FBCommandBuilder>(fbb);
|
cmdBuilder = tools::make_unique<FBCommandBuilder>(fbb);
|
||||||
cmdBuilder->add_device_id(deviceId);
|
cmdBuilder->add_device_id(deviceId);
|
||||||
cmdBuilder->add_result(GetFBResult(static_cast<TransitionStatus&>(*cmd).GetResult()));
|
cmdBuilder->add_result(GetFBResult(_cmd.GetResult()));
|
||||||
cmdBuilder->add_transition(GetFBTransition(static_cast<TransitionStatus&>(*cmd).GetTransition()));
|
cmdBuilder->add_transition(GetFBTransition(_cmd.GetTransition()));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Type::config: {
|
case Type::config: {
|
||||||
auto deviceId = fbb.CreateString(static_cast<Config&>(*cmd).GetDeviceId());
|
auto _cmd = static_cast<Config&>(*cmd);
|
||||||
auto config = fbb.CreateString(static_cast<Config&>(*cmd).GetConfig());
|
auto deviceId = fbb.CreateString(_cmd.GetDeviceId());
|
||||||
|
auto config = fbb.CreateString(_cmd.GetConfig());
|
||||||
cmdBuilder = tools::make_unique<FBCommandBuilder>(fbb);
|
cmdBuilder = tools::make_unique<FBCommandBuilder>(fbb);
|
||||||
cmdBuilder->add_device_id(deviceId);
|
cmdBuilder->add_device_id(deviceId);
|
||||||
cmdBuilder->add_config_string(config);
|
cmdBuilder->add_config_string(config);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Type::heartbeat_subscription: {
|
case Type::heartbeat_subscription: {
|
||||||
auto deviceId = fbb.CreateString(static_cast<HeartbeatSubscription&>(*cmd).GetDeviceId());
|
auto _cmd = static_cast<HeartbeatSubscription&>(*cmd);
|
||||||
|
auto deviceId = fbb.CreateString(_cmd.GetDeviceId());
|
||||||
cmdBuilder = tools::make_unique<FBCommandBuilder>(fbb);
|
cmdBuilder = tools::make_unique<FBCommandBuilder>(fbb);
|
||||||
cmdBuilder->add_device_id(deviceId);
|
cmdBuilder->add_device_id(deviceId);
|
||||||
cmdBuilder->add_result(GetFBResult(static_cast<HeartbeatSubscription&>(*cmd).GetResult()));
|
cmdBuilder->add_result(GetFBResult(_cmd.GetResult()));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Type::heartbeat_unsubscription: {
|
case Type::heartbeat_unsubscription: {
|
||||||
auto deviceId = fbb.CreateString(static_cast<HeartbeatUnsubscription&>(*cmd).GetDeviceId());
|
auto _cmd = static_cast<HeartbeatUnsubscription&>(*cmd);
|
||||||
|
auto deviceId = fbb.CreateString(_cmd.GetDeviceId());
|
||||||
cmdBuilder = tools::make_unique<FBCommandBuilder>(fbb);
|
cmdBuilder = tools::make_unique<FBCommandBuilder>(fbb);
|
||||||
cmdBuilder->add_device_id(deviceId);
|
cmdBuilder->add_device_id(deviceId);
|
||||||
cmdBuilder->add_result(GetFBResult(static_cast<HeartbeatUnsubscription&>(*cmd).GetResult()));
|
cmdBuilder->add_result(GetFBResult(_cmd.GetResult()));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Type::heartbeat: {
|
case Type::heartbeat: {
|
||||||
|
@ -293,26 +318,38 @@ string Cmds::Serialize(const Format type) const
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Type::state_change_subscription: {
|
case Type::state_change_subscription: {
|
||||||
auto deviceId = fbb.CreateString(static_cast<StateChangeSubscription&>(*cmd).GetDeviceId());
|
auto _cmd = static_cast<StateChangeSubscription&>(*cmd);
|
||||||
|
auto deviceId = fbb.CreateString(_cmd.GetDeviceId());
|
||||||
cmdBuilder = tools::make_unique<FBCommandBuilder>(fbb);
|
cmdBuilder = tools::make_unique<FBCommandBuilder>(fbb);
|
||||||
cmdBuilder->add_device_id(deviceId);
|
cmdBuilder->add_device_id(deviceId);
|
||||||
cmdBuilder->add_result(GetFBResult(static_cast<StateChangeSubscription&>(*cmd).GetResult()));
|
cmdBuilder->add_result(GetFBResult(_cmd.GetResult()));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Type::state_change_unsubscription: {
|
case Type::state_change_unsubscription: {
|
||||||
auto deviceId = fbb.CreateString(static_cast<StateChangeUnsubscription&>(*cmd).GetDeviceId());
|
auto _cmd = static_cast<StateChangeUnsubscription&>(*cmd);
|
||||||
|
auto deviceId = fbb.CreateString(_cmd.GetDeviceId());
|
||||||
cmdBuilder = tools::make_unique<FBCommandBuilder>(fbb);
|
cmdBuilder = tools::make_unique<FBCommandBuilder>(fbb);
|
||||||
cmdBuilder->add_device_id(deviceId);
|
cmdBuilder->add_device_id(deviceId);
|
||||||
cmdBuilder->add_result(GetFBResult(static_cast<StateChangeUnsubscription&>(*cmd).GetResult()));
|
cmdBuilder->add_result(GetFBResult(_cmd.GetResult()));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Type::state_change: {
|
case Type::state_change: {
|
||||||
auto deviceId = fbb.CreateString(static_cast<StateChange&>(*cmd).GetDeviceId());
|
auto _cmd = static_cast<StateChange&>(*cmd);
|
||||||
|
auto deviceId = fbb.CreateString(_cmd.GetDeviceId());
|
||||||
cmdBuilder = tools::make_unique<FBCommandBuilder>(fbb);
|
cmdBuilder = tools::make_unique<FBCommandBuilder>(fbb);
|
||||||
cmdBuilder->add_device_id(deviceId);
|
cmdBuilder->add_device_id(deviceId);
|
||||||
cmdBuilder->add_task_id(static_cast<StateChange&>(*cmd).GetTaskId());
|
cmdBuilder->add_task_id(_cmd.GetTaskId());
|
||||||
cmdBuilder->add_last_state(GetFBState(static_cast<StateChange&>(*cmd).GetLastState()));
|
cmdBuilder->add_last_state(GetFBState(_cmd.GetLastState()));
|
||||||
cmdBuilder->add_current_state(GetFBState(static_cast<StateChange&>(*cmd).GetCurrentState()));
|
cmdBuilder->add_current_state(GetFBState(_cmd.GetCurrentState()));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Type::properties_set: {
|
||||||
|
auto _cmd = static_cast<PropertiesSet&>(*cmd);
|
||||||
|
auto deviceId = fbb.CreateString(_cmd.GetDeviceId());
|
||||||
|
cmdBuilder = tools::make_unique<FBCommandBuilder>(fbb);
|
||||||
|
cmdBuilder->add_device_id(deviceId);
|
||||||
|
cmdBuilder->add_request_id(_cmd.GetRequestId());
|
||||||
|
cmdBuilder->add_result(GetFBResult(_cmd.GetResult()));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -391,6 +428,14 @@ void Cmds::Deserialize(const string& str, const Format type)
|
||||||
case FBCmd_state_change_exiting_received:
|
case FBCmd_state_change_exiting_received:
|
||||||
fCmds.emplace_back(make<StateChangeExitingReceived>());
|
fCmds.emplace_back(make<StateChangeExitingReceived>());
|
||||||
break;
|
break;
|
||||||
|
case FBCmd_set_properties: {
|
||||||
|
std::vector<std::pair<std::string, std::string>> properties;
|
||||||
|
auto props = cmdPtr.properties();
|
||||||
|
for (unsigned int j = 0; j < props->size(); ++j) {
|
||||||
|
properties.emplace_back(props->Get(j)->key()->str(), props->Get(j)->value()->str());
|
||||||
|
}
|
||||||
|
fCmds.emplace_back(make<SetProperties>(cmdPtr.request_id(), properties));
|
||||||
|
} break;
|
||||||
case FBCmd_current_state:
|
case FBCmd_current_state:
|
||||||
fCmds.emplace_back(make<CurrentState>(cmdPtr.device_id()->str(), GetMQState(cmdPtr.current_state())));
|
fCmds.emplace_back(make<CurrentState>(cmdPtr.device_id()->str(), GetMQState(cmdPtr.current_state())));
|
||||||
break;
|
break;
|
||||||
|
@ -418,6 +463,9 @@ void Cmds::Deserialize(const string& str, const Format type)
|
||||||
case FBCmd_state_change:
|
case FBCmd_state_change:
|
||||||
fCmds.emplace_back(make<StateChange>(cmdPtr.device_id()->str(), cmdPtr.task_id(), GetMQState(cmdPtr.last_state()), GetMQState(cmdPtr.current_state())));
|
fCmds.emplace_back(make<StateChange>(cmdPtr.device_id()->str(), cmdPtr.task_id(), GetMQState(cmdPtr.last_state()), GetMQState(cmdPtr.current_state())));
|
||||||
break;
|
break;
|
||||||
|
case FBCmd_properties_set:
|
||||||
|
fCmds.emplace_back(make<PropertiesSet>(cmdPtr.device_id()->str(), cmdPtr.request_id(), GetResult(cmdPtr.result())));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw CommandFormatError("unrecognized command type given to fair::mq::cmd::Cmds::Deserialize()");
|
throw CommandFormatError("unrecognized command type given to fair::mq::cmd::Cmds::Deserialize()");
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -47,6 +47,7 @@ enum class Type : int
|
||||||
subscribe_to_state_change, // args: { }
|
subscribe_to_state_change, // args: { }
|
||||||
unsubscribe_from_state_change, // args: { }
|
unsubscribe_from_state_change, // args: { }
|
||||||
state_change_exiting_received, // args: { }
|
state_change_exiting_received, // args: { }
|
||||||
|
set_properties, // args: { request_id, properties }
|
||||||
|
|
||||||
current_state, // args: { device_id, current_state }
|
current_state, // args: { device_id, current_state }
|
||||||
transition_status, // args: { device_id, Result, transition }
|
transition_status, // args: { device_id, Result, transition }
|
||||||
|
@ -56,12 +57,14 @@ enum class Type : int
|
||||||
heartbeat, // args: { device_id }
|
heartbeat, // args: { device_id }
|
||||||
state_change_subscription, // args: { device_id, Result }
|
state_change_subscription, // args: { device_id, Result }
|
||||||
state_change_unsubscription, // args: { device_id, Result }
|
state_change_unsubscription, // args: { device_id, Result }
|
||||||
state_change // args: { device_id, task_id, last_state, current_state }
|
state_change, // args: { device_id, task_id, last_state, current_state }
|
||||||
|
properties_set // args: { device_id, request_id, Result }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Cmd
|
struct Cmd
|
||||||
{
|
{
|
||||||
explicit Cmd(const Type type) : fType(type) {}
|
explicit Cmd(const Type type) : fType(type) {}
|
||||||
|
virtual ~Cmd() = default;
|
||||||
|
|
||||||
Type GetType() const { return fType; }
|
Type GetType() const { return fType; }
|
||||||
|
|
||||||
|
@ -118,6 +121,24 @@ struct StateChangeExitingReceived : Cmd
|
||||||
explicit StateChangeExitingReceived() : Cmd(Type::state_change_exiting_received) {}
|
explicit StateChangeExitingReceived() : Cmd(Type::state_change_exiting_received) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SetProperties : Cmd
|
||||||
|
{
|
||||||
|
SetProperties(std::size_t request_id, std::vector<std::pair<std::string, std::string>> properties)
|
||||||
|
: Cmd(Type::set_properties)
|
||||||
|
, fRequestId(request_id)
|
||||||
|
, fProperties(std::move(properties))
|
||||||
|
{}
|
||||||
|
|
||||||
|
auto GetRequestId() const -> std::size_t { return fRequestId; }
|
||||||
|
auto SetRequestId(std::size_t requestId) -> void { fRequestId = requestId; }
|
||||||
|
auto GetProps() const -> std::vector<std::pair<std::string, std::string>> { return fProperties; }
|
||||||
|
auto SetProps(std::vector<std::pair<std::string, std::string>> properties) -> void { fProperties = std::move(properties); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::size_t fRequestId;
|
||||||
|
std::vector<std::pair<std::string, std::string>> fProperties;
|
||||||
|
};
|
||||||
|
|
||||||
struct CurrentState : Cmd
|
struct CurrentState : Cmd
|
||||||
{
|
{
|
||||||
explicit CurrentState(const std::string& id, State currentState)
|
explicit CurrentState(const std::string& id, State currentState)
|
||||||
|
@ -288,6 +309,27 @@ struct StateChange : Cmd
|
||||||
fair::mq::State fCurrentState;
|
fair::mq::State fCurrentState;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct PropertiesSet : Cmd {
|
||||||
|
PropertiesSet(std::string deviceId, std::size_t requestId, Result result)
|
||||||
|
: Cmd(Type::properties_set)
|
||||||
|
, fDeviceId(std::move(deviceId))
|
||||||
|
, fRequestId(requestId)
|
||||||
|
, fResult(result)
|
||||||
|
{}
|
||||||
|
|
||||||
|
auto GetDeviceId() const -> std::string { return fDeviceId; }
|
||||||
|
auto SetDeviceId(std::string deviceId) -> void { fDeviceId = std::move(deviceId); }
|
||||||
|
auto GetRequestId() const -> std::size_t { return fRequestId; }
|
||||||
|
auto SetRequestId(std::size_t requestId) -> void { fRequestId = requestId; }
|
||||||
|
auto GetResult() const -> Result { return fResult; }
|
||||||
|
auto SetResult(Result result) -> void { fResult = result; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string fDeviceId;
|
||||||
|
std::size_t fRequestId;
|
||||||
|
Result fResult;
|
||||||
|
};
|
||||||
|
|
||||||
template<typename C, typename... Args>
|
template<typename C, typename... Args>
|
||||||
std::unique_ptr<Cmd> make(Args&&... args)
|
std::unique_ptr<Cmd> make(Args&&... args)
|
||||||
{
|
{
|
||||||
|
@ -307,7 +349,6 @@ struct Cmds
|
||||||
Unpack(std::forward<std::unique_ptr<Cmd>&&>(first), std::forward<Rest>(rest)...);
|
Unpack(std::forward<std::unique_ptr<Cmd>&&>(first), std::forward<Rest>(rest)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Add(std::unique_ptr<Cmd>&& cmd) { fCmds.emplace_back(std::move(cmd)); }
|
void Add(std::unique_ptr<Cmd>&& cmd) { fCmds.emplace_back(std::move(cmd)); }
|
||||||
|
|
||||||
template<typename C, typename... Args>
|
template<typename C, typename... Args>
|
||||||
|
|
|
@ -38,6 +38,11 @@ enum FBTransition:byte {
|
||||||
ErrorFound
|
ErrorFound
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table FBProperty {
|
||||||
|
key:string;
|
||||||
|
value:string;
|
||||||
|
}
|
||||||
|
|
||||||
enum FBCmd:byte {
|
enum FBCmd:byte {
|
||||||
check_state, // args: { }
|
check_state, // args: { }
|
||||||
change_state, // args: { transition }
|
change_state, // args: { transition }
|
||||||
|
@ -47,6 +52,7 @@ enum FBCmd:byte {
|
||||||
subscribe_to_state_change, // args: { }
|
subscribe_to_state_change, // args: { }
|
||||||
unsubscribe_from_state_change, // args: { }
|
unsubscribe_from_state_change, // args: { }
|
||||||
state_change_exiting_received, // args: { }
|
state_change_exiting_received, // args: { }
|
||||||
|
set_properties, // args: { key, value }
|
||||||
|
|
||||||
current_state, // args: { device_id, current_state }
|
current_state, // args: { device_id, current_state }
|
||||||
transition_status, // args: { device_id, Result, transition }
|
transition_status, // args: { device_id, Result, transition }
|
||||||
|
@ -56,13 +62,15 @@ enum FBCmd:byte {
|
||||||
heartbeat, // args: { device_id }
|
heartbeat, // args: { device_id }
|
||||||
state_change_subscription, // args: { device_id, Result }
|
state_change_subscription, // args: { device_id, Result }
|
||||||
state_change_unsubscription, // args: { device_id, Result }
|
state_change_unsubscription, // args: { device_id, Result }
|
||||||
state_change // args: { device_id, task_id, last_state, current_state }
|
state_change, // args: { device_id, task_id, last_state, current_state }
|
||||||
|
properties_set // args: { device_id, request_id, Result }
|
||||||
}
|
}
|
||||||
|
|
||||||
table FBCommand {
|
table FBCommand {
|
||||||
command_id:FBCmd;
|
command_id:FBCmd;
|
||||||
device_id:string;
|
device_id:string;
|
||||||
task_id:uint64;
|
task_id:uint64;
|
||||||
|
request_id:uint64;
|
||||||
state:FBState;
|
state:FBState;
|
||||||
transition:FBTransition;
|
transition:FBTransition;
|
||||||
result:FBResult;
|
result:FBResult;
|
||||||
|
@ -70,6 +78,7 @@ table FBCommand {
|
||||||
last_state:FBState;
|
last_state:FBState;
|
||||||
current_state:FBState;
|
current_state:FBState;
|
||||||
debug:string;
|
debug:string;
|
||||||
|
properties:[FBProperty];
|
||||||
}
|
}
|
||||||
|
|
||||||
table FBCommands {
|
table FBCommands {
|
||||||
|
|
|
@ -19,6 +19,8 @@ using namespace fair::mq::sdk::cmd;
|
||||||
|
|
||||||
TEST(Format, Construction)
|
TEST(Format, Construction)
|
||||||
{
|
{
|
||||||
|
auto const props(std::vector<std::pair<std::string, std::string>>({{"k1", "v1"}, {"k2", "v2"}}));
|
||||||
|
|
||||||
Cmds checkStateCmds(make<CheckState>());
|
Cmds checkStateCmds(make<CheckState>());
|
||||||
Cmds changeStateCmds(make<ChangeState>(Transition::Stop));
|
Cmds changeStateCmds(make<ChangeState>(Transition::Stop));
|
||||||
Cmds dumpConfigCmds(make<DumpConfig>());
|
Cmds dumpConfigCmds(make<DumpConfig>());
|
||||||
|
@ -27,6 +29,7 @@ TEST(Format, Construction)
|
||||||
Cmds subscribeToStateChangeCmds(make<SubscribeToStateChange>());
|
Cmds subscribeToStateChangeCmds(make<SubscribeToStateChange>());
|
||||||
Cmds unsubscribeFromStateChangeCmds(make<UnsubscribeFromStateChange>());
|
Cmds unsubscribeFromStateChangeCmds(make<UnsubscribeFromStateChange>());
|
||||||
Cmds stateChangeExitingReceivedCmds(make<StateChangeExitingReceived>());
|
Cmds stateChangeExitingReceivedCmds(make<StateChangeExitingReceived>());
|
||||||
|
Cmds setPropertiesCmds(make<SetProperties>(42, props));
|
||||||
Cmds currentStateCmds(make<CurrentState>("somedeviceid", State::Running));
|
Cmds currentStateCmds(make<CurrentState>("somedeviceid", State::Running));
|
||||||
Cmds transitionStatusCmds(make<TransitionStatus>("somedeviceid", Result::Ok, Transition::Stop));
|
Cmds transitionStatusCmds(make<TransitionStatus>("somedeviceid", Result::Ok, Transition::Stop));
|
||||||
Cmds configCmds(make<Config>("somedeviceid", "someconfig"));
|
Cmds configCmds(make<Config>("somedeviceid", "someconfig"));
|
||||||
|
@ -36,6 +39,7 @@ TEST(Format, Construction)
|
||||||
Cmds stateChangeSubscriptionCmds(make<StateChangeSubscription>("somedeviceid", Result::Ok));
|
Cmds stateChangeSubscriptionCmds(make<StateChangeSubscription>("somedeviceid", Result::Ok));
|
||||||
Cmds stateChangeUnsubscriptionCmds(make<StateChangeUnsubscription>("somedeviceid", Result::Ok));
|
Cmds stateChangeUnsubscriptionCmds(make<StateChangeUnsubscription>("somedeviceid", Result::Ok));
|
||||||
Cmds stateChangeCmds(make<StateChange>("somedeviceid", 123456, State::Running, State::Ready));
|
Cmds stateChangeCmds(make<StateChange>("somedeviceid", 123456, State::Running, State::Ready));
|
||||||
|
Cmds propertiesSetCmds(make<PropertiesSet>("somedeviceid", 42, Result::Ok));
|
||||||
|
|
||||||
ASSERT_EQ(checkStateCmds.At(0).GetType(), Type::check_state);
|
ASSERT_EQ(checkStateCmds.At(0).GetType(), Type::check_state);
|
||||||
ASSERT_EQ(changeStateCmds.At(0).GetType(), Type::change_state);
|
ASSERT_EQ(changeStateCmds.At(0).GetType(), Type::change_state);
|
||||||
|
@ -46,6 +50,9 @@ TEST(Format, Construction)
|
||||||
ASSERT_EQ(subscribeToStateChangeCmds.At(0).GetType(), Type::subscribe_to_state_change);
|
ASSERT_EQ(subscribeToStateChangeCmds.At(0).GetType(), Type::subscribe_to_state_change);
|
||||||
ASSERT_EQ(unsubscribeFromStateChangeCmds.At(0).GetType(), Type::unsubscribe_from_state_change);
|
ASSERT_EQ(unsubscribeFromStateChangeCmds.At(0).GetType(), Type::unsubscribe_from_state_change);
|
||||||
ASSERT_EQ(stateChangeExitingReceivedCmds.At(0).GetType(), Type::state_change_exiting_received);
|
ASSERT_EQ(stateChangeExitingReceivedCmds.At(0).GetType(), Type::state_change_exiting_received);
|
||||||
|
ASSERT_EQ(setPropertiesCmds.At(0).GetType(), Type::set_properties);
|
||||||
|
ASSERT_EQ(static_cast<SetProperties&>(setPropertiesCmds.At(0)).GetRequestId(), 42);
|
||||||
|
ASSERT_EQ(static_cast<SetProperties&>(setPropertiesCmds.At(0)).GetProps(), props);
|
||||||
ASSERT_EQ(currentStateCmds.At(0).GetType(), Type::current_state);
|
ASSERT_EQ(currentStateCmds.At(0).GetType(), Type::current_state);
|
||||||
ASSERT_EQ(static_cast<CurrentState&>(currentStateCmds.At(0)).GetDeviceId(), "somedeviceid");
|
ASSERT_EQ(static_cast<CurrentState&>(currentStateCmds.At(0)).GetDeviceId(), "somedeviceid");
|
||||||
ASSERT_EQ(static_cast<CurrentState&>(currentStateCmds.At(0)).GetCurrentState(), State::Running);
|
ASSERT_EQ(static_cast<CurrentState&>(currentStateCmds.At(0)).GetCurrentState(), State::Running);
|
||||||
|
@ -75,10 +82,16 @@ TEST(Format, Construction)
|
||||||
ASSERT_EQ(static_cast<StateChange&>(stateChangeCmds.At(0)).GetTaskId(), 123456);
|
ASSERT_EQ(static_cast<StateChange&>(stateChangeCmds.At(0)).GetTaskId(), 123456);
|
||||||
ASSERT_EQ(static_cast<StateChange&>(stateChangeCmds.At(0)).GetLastState(), State::Running);
|
ASSERT_EQ(static_cast<StateChange&>(stateChangeCmds.At(0)).GetLastState(), State::Running);
|
||||||
ASSERT_EQ(static_cast<StateChange&>(stateChangeCmds.At(0)).GetCurrentState(), State::Ready);
|
ASSERT_EQ(static_cast<StateChange&>(stateChangeCmds.At(0)).GetCurrentState(), State::Ready);
|
||||||
|
ASSERT_EQ(propertiesSetCmds.At(0).GetType(), Type::properties_set);
|
||||||
|
ASSERT_EQ(static_cast<PropertiesSet&>(propertiesSetCmds.At(0)).GetDeviceId(), "somedeviceid");
|
||||||
|
ASSERT_EQ(static_cast<PropertiesSet&>(propertiesSetCmds.At(0)).GetRequestId(), 42);
|
||||||
|
ASSERT_EQ(static_cast<PropertiesSet&>(propertiesSetCmds.At(0)).GetResult(), Result::Ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fillCommands(Cmds& cmds)
|
void fillCommands(Cmds& cmds)
|
||||||
{
|
{
|
||||||
|
auto const props(std::vector<std::pair<std::string, std::string>>({{"k1", "v1"}, {"k2", "v2"}}));
|
||||||
|
|
||||||
cmds.Add<CheckState>();
|
cmds.Add<CheckState>();
|
||||||
cmds.Add<ChangeState>(Transition::Stop);
|
cmds.Add<ChangeState>(Transition::Stop);
|
||||||
cmds.Add<DumpConfig>();
|
cmds.Add<DumpConfig>();
|
||||||
|
@ -87,6 +100,7 @@ void fillCommands(Cmds& cmds)
|
||||||
cmds.Add<SubscribeToStateChange>();
|
cmds.Add<SubscribeToStateChange>();
|
||||||
cmds.Add<UnsubscribeFromStateChange>();
|
cmds.Add<UnsubscribeFromStateChange>();
|
||||||
cmds.Add<StateChangeExitingReceived>();
|
cmds.Add<StateChangeExitingReceived>();
|
||||||
|
cmds.Add<SetProperties>(42, props);
|
||||||
cmds.Add<CurrentState>("somedeviceid", State::Running);
|
cmds.Add<CurrentState>("somedeviceid", State::Running);
|
||||||
cmds.Add<TransitionStatus>("somedeviceid", Result::Ok, Transition::Stop);
|
cmds.Add<TransitionStatus>("somedeviceid", Result::Ok, Transition::Stop);
|
||||||
cmds.Add<Config>("somedeviceid", "someconfig");
|
cmds.Add<Config>("somedeviceid", "someconfig");
|
||||||
|
@ -96,13 +110,15 @@ void fillCommands(Cmds& cmds)
|
||||||
cmds.Add<StateChangeSubscription>("somedeviceid", Result::Ok);
|
cmds.Add<StateChangeSubscription>("somedeviceid", Result::Ok);
|
||||||
cmds.Add<StateChangeUnsubscription>("somedeviceid", Result::Ok);
|
cmds.Add<StateChangeUnsubscription>("somedeviceid", Result::Ok);
|
||||||
cmds.Add<StateChange>("somedeviceid", 123456, State::Running, State::Ready);
|
cmds.Add<StateChange>("somedeviceid", 123456, State::Running, State::Ready);
|
||||||
|
cmds.Add<PropertiesSet>("somedeviceid", 42, Result::Ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkCommands(Cmds& cmds)
|
void checkCommands(Cmds& cmds)
|
||||||
{
|
{
|
||||||
ASSERT_EQ(cmds.Size(), 17);
|
ASSERT_EQ(cmds.Size(), 19);
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
auto const props(std::vector<std::pair<std::string, std::string>>({{"k1", "v1"}, {"k2", "v2"}}));
|
||||||
|
|
||||||
for (const auto& cmd : cmds) {
|
for (const auto& cmd : cmds) {
|
||||||
switch (cmd->GetType()) {
|
switch (cmd->GetType()) {
|
||||||
|
@ -131,6 +147,11 @@ void checkCommands(Cmds& cmds)
|
||||||
case Type::state_change_exiting_received:
|
case Type::state_change_exiting_received:
|
||||||
++count;
|
++count;
|
||||||
break;
|
break;
|
||||||
|
case Type::set_properties:
|
||||||
|
++count;
|
||||||
|
ASSERT_EQ(static_cast<SetProperties&>(*cmd).GetRequestId(), 42);
|
||||||
|
ASSERT_EQ(static_cast<SetProperties&>(*cmd).GetProps(), props);
|
||||||
|
break;
|
||||||
case Type::current_state:
|
case Type::current_state:
|
||||||
++count;
|
++count;
|
||||||
ASSERT_EQ(static_cast<CurrentState&>(*cmd).GetDeviceId(), "somedeviceid");
|
ASSERT_EQ(static_cast<CurrentState&>(*cmd).GetDeviceId(), "somedeviceid");
|
||||||
|
@ -178,13 +199,19 @@ void checkCommands(Cmds& cmds)
|
||||||
ASSERT_EQ(static_cast<StateChange&>(*cmd).GetLastState(), State::Running);
|
ASSERT_EQ(static_cast<StateChange&>(*cmd).GetLastState(), State::Running);
|
||||||
ASSERT_EQ(static_cast<StateChange&>(*cmd).GetCurrentState(), State::Ready);
|
ASSERT_EQ(static_cast<StateChange&>(*cmd).GetCurrentState(), State::Ready);
|
||||||
break;
|
break;
|
||||||
|
case Type::properties_set:
|
||||||
|
++count;
|
||||||
|
ASSERT_EQ(static_cast<PropertiesSet&>(*cmd).GetDeviceId(), "somedeviceid");
|
||||||
|
ASSERT_EQ(static_cast<PropertiesSet&>(*cmd).GetRequestId(), 42);
|
||||||
|
ASSERT_EQ(static_cast<PropertiesSet&>(*cmd).GetResult(), Result::Ok);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ASSERT_TRUE(false);
|
ASSERT_TRUE(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT_EQ(count, 17);
|
ASSERT_EQ(count, 19);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Format, SerializationBinary)
|
TEST(Format, SerializationBinary)
|
||||||
|
|
|
@ -243,4 +243,104 @@ TEST_F(Topology, ChangeStateFullDeviceLifecycle2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(Topology, SetProperties)
|
||||||
|
{
|
||||||
|
using namespace fair::mq;
|
||||||
|
using fair::mq::sdk::TopologyTransition;
|
||||||
|
|
||||||
|
sdk::Topology topo(mDDSTopo, mDDSSession);
|
||||||
|
ASSERT_EQ(topo.ChangeState(TopologyTransition::InitDevice).first, std::error_code());
|
||||||
|
|
||||||
|
auto const result1 = topo.SetProperties({{"key1", "val1"}});
|
||||||
|
LOG(info) << result1.first;
|
||||||
|
ASSERT_EQ(result1.first, std::error_code());
|
||||||
|
ASSERT_EQ(result1.second.size(), 0);
|
||||||
|
auto const result2 = topo.SetProperties({{"key2", "val2"}, {"key3", "val3"}});
|
||||||
|
LOG(info) << result2.first;
|
||||||
|
ASSERT_EQ(result2.first, std::error_code());
|
||||||
|
ASSERT_EQ(result2.second.size(), 0);
|
||||||
|
|
||||||
|
ASSERT_EQ(topo.ChangeState(TopologyTransition::CompleteInit).first, std::error_code());
|
||||||
|
ASSERT_EQ(topo.ChangeState(TopologyTransition::ResetDevice).first, std::error_code());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(Topology, AsyncSetPropertiesConcurrent)
|
||||||
|
{
|
||||||
|
using namespace fair::mq;
|
||||||
|
using fair::mq::sdk::TopologyTransition;
|
||||||
|
|
||||||
|
sdk::Topology topo(mDDSTopo, mDDSSession);
|
||||||
|
ASSERT_EQ(topo.ChangeState(TopologyTransition::InitDevice).first, std::error_code());
|
||||||
|
|
||||||
|
tools::SharedSemaphore blocker(2);
|
||||||
|
topo.AsyncSetProperties(
|
||||||
|
{{"key1", "val1"}},
|
||||||
|
[=](std::error_code ec, sdk::Topology::FailedDevices failed) mutable {
|
||||||
|
LOG(info) << ec;
|
||||||
|
ASSERT_EQ(ec, std::error_code());
|
||||||
|
ASSERT_EQ(failed.size(), 0);
|
||||||
|
blocker.Signal();
|
||||||
|
});
|
||||||
|
topo.AsyncSetProperties(
|
||||||
|
{{"key2", "val2"}, {"key3", "val3"}},
|
||||||
|
[=](std::error_code ec, sdk::Topology::FailedDevices failed) mutable {
|
||||||
|
LOG(info) << ec;
|
||||||
|
ASSERT_EQ(ec, std::error_code());
|
||||||
|
ASSERT_EQ(failed.size(), 0);
|
||||||
|
blocker.Signal();
|
||||||
|
});
|
||||||
|
blocker.Wait();
|
||||||
|
|
||||||
|
ASSERT_EQ(topo.ChangeState(TopologyTransition::CompleteInit).first, std::error_code());
|
||||||
|
ASSERT_EQ(topo.ChangeState(TopologyTransition::ResetDevice).first, std::error_code());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(Topology, AsyncSetPropertiesTimeout)
|
||||||
|
{
|
||||||
|
using namespace fair::mq;
|
||||||
|
using fair::mq::sdk::TopologyTransition;
|
||||||
|
|
||||||
|
sdk::Topology topo(mDDSTopo, mDDSSession);
|
||||||
|
ASSERT_EQ(topo.ChangeState(TopologyTransition::InitDevice).first, std::error_code());
|
||||||
|
|
||||||
|
topo.AsyncSetProperties({{"key1", "val1"}},
|
||||||
|
std::chrono::milliseconds(1),
|
||||||
|
[=](std::error_code ec, sdk::Topology::FailedDevices) mutable {
|
||||||
|
LOG(info) << ec;
|
||||||
|
EXPECT_EQ(ec, MakeErrorCode(ErrorCode::OperationTimeout));
|
||||||
|
});
|
||||||
|
|
||||||
|
ASSERT_EQ(topo.ChangeState(TopologyTransition::CompleteInit).first, std::error_code());
|
||||||
|
ASSERT_EQ(topo.ChangeState(TopologyTransition::ResetDevice).first, std::error_code());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(Topology, SetPropertiesMixed)
|
||||||
|
{
|
||||||
|
using namespace fair::mq;
|
||||||
|
using fair::mq::sdk::TopologyTransition;
|
||||||
|
|
||||||
|
sdk::Topology topo(mDDSTopo, mDDSSession);
|
||||||
|
ASSERT_EQ(topo.ChangeState(TopologyTransition::InitDevice).first, std::error_code());
|
||||||
|
|
||||||
|
tools::SharedSemaphore blocker;
|
||||||
|
topo.AsyncSetProperties(
|
||||||
|
{{"key1", "val1"}},
|
||||||
|
[=](std::error_code ec, sdk::Topology::FailedDevices failed) mutable {
|
||||||
|
LOG(info) << ec;
|
||||||
|
ASSERT_EQ(ec, std::error_code());
|
||||||
|
ASSERT_EQ(failed.size(), 0);
|
||||||
|
blocker.Signal();
|
||||||
|
});
|
||||||
|
|
||||||
|
auto result = topo.SetProperties({{"key2", "val2"}});
|
||||||
|
LOG(info) << result.first;
|
||||||
|
ASSERT_EQ(result.first, std::error_code());
|
||||||
|
ASSERT_EQ(result.second.size(), 0);
|
||||||
|
|
||||||
|
blocker.Wait();
|
||||||
|
|
||||||
|
ASSERT_EQ(topo.ChangeState(TopologyTransition::CompleteInit).first, std::error_code());
|
||||||
|
ASSERT_EQ(topo.ChangeState(TopologyTransition::ResetDevice).first, std::error_code());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
Loading…
Reference in New Issue
Block a user