mirror of
https://github.com/FairRootGroup/FairMQ.git
synced 2025-10-13 08:41:16 +00:00
Commands: support JSON in addition to binary
This commit is contained in:
parent
caeee626a3
commit
72a8e9b33c
|
@ -15,7 +15,12 @@ add_custom_command(
|
|||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
add_library(${target} Commands.cxx Commands.h ${CMAKE_CURRENT_BINARY_DIR}/CommandsFormat.h)
|
||||
# JSON serialization needs to see the .fbs file at run time, save it as constexpr string instead of locating/opening it every time
|
||||
file(STRINGS CommandsFormat.fbs tmp)
|
||||
list(JOIN tmp "\n" commands_format_def_fbs)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/CommandsFormatDef.h.in ${CMAKE_CURRENT_BINARY_DIR}/CommandsFormatDef.h)
|
||||
|
||||
add_library(${target} Commands.cxx Commands.h ${CMAKE_CURRENT_BINARY_DIR}/CommandsFormat.h ${CMAKE_CURRENT_BINARY_DIR}/CommandsFormatDef.h)
|
||||
add_library(FairMQ::${target} ALIAS ${target})
|
||||
|
||||
target_link_libraries(${target}
|
||||
|
|
|
@ -8,8 +8,11 @@
|
|||
|
||||
#include "Commands.h"
|
||||
|
||||
#include <fairmq/sdk/commands/CommandsFormatDef.h>
|
||||
#include <fairmq/sdk/commands/CommandsFormat.h>
|
||||
|
||||
#include <flatbuffers/idl.h>
|
||||
|
||||
#include <array>
|
||||
|
||||
using namespace std;
|
||||
|
@ -203,7 +206,7 @@ string GetTypeName(const Type type) { return typeNames.at(static_cast<int>(type)
|
|||
|
||||
FBCmd GetFBCmd(const Type type) { return typeToFBCmd.at(static_cast<int>(type)); }
|
||||
|
||||
string Cmds::Serialize() const
|
||||
string Cmds::Serialize(const Format type) const
|
||||
{
|
||||
flatbuffers::FlatBufferBuilder fbb;
|
||||
vector<flatbuffers::Offset<FBCommand>> commandOffsets;
|
||||
|
@ -327,14 +330,39 @@ string Cmds::Serialize() const
|
|||
auto cmds = CreateFBCommands(fbb, commands);
|
||||
fbb.Finish(cmds);
|
||||
|
||||
if (type == Format::Binary) {
|
||||
return string(reinterpret_cast<char*>(fbb.GetBufferPointer()), fbb.GetSize());
|
||||
} else { // Type == Format::JSON
|
||||
flatbuffers::Parser parser;
|
||||
if (!parser.Parse(commandsFormatDefFbs)) {
|
||||
throw CommandFormatError("Serialize couldn't parse commands format");
|
||||
}
|
||||
std::string json;
|
||||
if (!flatbuffers::GenerateText(parser, fbb.GetBufferPointer(), &json)) {
|
||||
throw CommandFormatError("Serialize couldn't serialize parsed data to JSON!");
|
||||
}
|
||||
return json;
|
||||
}
|
||||
}
|
||||
|
||||
void Cmds::Deserialize(const string& str)
|
||||
void Cmds::Deserialize(const string& str, const Format type)
|
||||
{
|
||||
fCmds.clear();
|
||||
|
||||
auto cmds = cmd::GetFBCommands(const_cast<char*>(str.c_str()))->commands();
|
||||
const flatbuffers::Vector<flatbuffers::Offset<FBCommand>>* cmds;
|
||||
|
||||
if (type == Format::Binary) {
|
||||
cmds = cmd::GetFBCommands(const_cast<char*>(str.c_str()))->commands();
|
||||
} else { // Type == Format::JSON
|
||||
flatbuffers::Parser parser;
|
||||
if (!parser.Parse(commandsFormatDefFbs)) {
|
||||
throw CommandFormatError("Deserialize couldn't parse commands format");
|
||||
}
|
||||
if (!parser.Parse(str.c_str())) {
|
||||
throw CommandFormatError("Deserialize couldn't parse incoming JSON string");
|
||||
}
|
||||
cmds = cmd::GetFBCommands(parser.builder_.GetBufferPointer())->commands();
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < cmds->size(); ++i) {
|
||||
const fair::mq::sdk::cmd::FBCommand& cmdPtr = *(cmds->Get(i));
|
||||
|
|
|
@ -27,6 +27,11 @@ namespace sdk
|
|||
namespace cmd
|
||||
{
|
||||
|
||||
enum class Format : int {
|
||||
Binary,
|
||||
JSON
|
||||
};
|
||||
|
||||
enum class Result : int {
|
||||
Ok,
|
||||
Failure
|
||||
|
@ -133,7 +138,7 @@ struct CurrentState : Cmd
|
|||
|
||||
struct TransitionStatus : Cmd
|
||||
{
|
||||
explicit TransitionStatus(const std::string& id, Result result, Transition transition)
|
||||
explicit TransitionStatus(const std::string& id, const Result result, const Transition transition)
|
||||
: Cmd(Type::transition_status)
|
||||
, fDeviceId(id)
|
||||
, fResult(result)
|
||||
|
@ -143,9 +148,9 @@ struct TransitionStatus : Cmd
|
|||
std::string GetDeviceId() const { return fDeviceId; }
|
||||
void SetDeviceId(const std::string& deviceId) { fDeviceId = deviceId; }
|
||||
Result GetResult() const { return fResult; }
|
||||
void SetResult(Result result) { fResult = result; }
|
||||
void SetResult(const Result result) { fResult = result; }
|
||||
Transition GetTransition() const { return fTransition; }
|
||||
void SetTransition(Transition transition) { fTransition = transition; }
|
||||
void SetTransition(const Transition transition) { fTransition = transition; }
|
||||
|
||||
private:
|
||||
std::string fDeviceId;
|
||||
|
@ -173,7 +178,7 @@ struct Config : Cmd
|
|||
|
||||
struct HeartbeatSubscription : Cmd
|
||||
{
|
||||
explicit HeartbeatSubscription(const std::string& id, Result result)
|
||||
explicit HeartbeatSubscription(const std::string& id, const Result result)
|
||||
: Cmd(Type::heartbeat_subscription)
|
||||
, fDeviceId(id)
|
||||
, fResult(result)
|
||||
|
@ -182,7 +187,7 @@ struct HeartbeatSubscription : Cmd
|
|||
std::string GetDeviceId() const { return fDeviceId; }
|
||||
void SetDeviceId(const std::string& deviceId) { fDeviceId = deviceId; }
|
||||
Result GetResult() const { return fResult; }
|
||||
void SetResult(Result result) { fResult = result; }
|
||||
void SetResult(const Result result) { fResult = result; }
|
||||
|
||||
private:
|
||||
std::string fDeviceId;
|
||||
|
@ -191,7 +196,7 @@ struct HeartbeatSubscription : Cmd
|
|||
|
||||
struct HeartbeatUnsubscription : Cmd
|
||||
{
|
||||
explicit HeartbeatUnsubscription(const std::string& id, Result result)
|
||||
explicit HeartbeatUnsubscription(const std::string& id, const Result result)
|
||||
: Cmd(Type::heartbeat_unsubscription)
|
||||
, fDeviceId(id)
|
||||
, fResult(result)
|
||||
|
@ -200,7 +205,7 @@ struct HeartbeatUnsubscription : Cmd
|
|||
std::string GetDeviceId() const { return fDeviceId; }
|
||||
void SetDeviceId(const std::string& deviceId) { fDeviceId = deviceId; }
|
||||
Result GetResult() const { return fResult; }
|
||||
void SetResult(Result result) { fResult = result; }
|
||||
void SetResult(const Result result) { fResult = result; }
|
||||
|
||||
private:
|
||||
std::string fDeviceId;
|
||||
|
@ -223,7 +228,7 @@ struct Heartbeat : Cmd
|
|||
|
||||
struct StateChangeSubscription : Cmd
|
||||
{
|
||||
explicit StateChangeSubscription(const std::string& id, Result result)
|
||||
explicit StateChangeSubscription(const std::string& id, const Result result)
|
||||
: Cmd(Type::state_change_subscription)
|
||||
, fDeviceId(id)
|
||||
, fResult(result)
|
||||
|
@ -232,7 +237,7 @@ struct StateChangeSubscription : Cmd
|
|||
std::string GetDeviceId() const { return fDeviceId; }
|
||||
void SetDeviceId(const std::string& deviceId) { fDeviceId = deviceId; }
|
||||
Result GetResult() const { return fResult; }
|
||||
void SetResult(Result result) { fResult = result; }
|
||||
void SetResult(const Result result) { fResult = result; }
|
||||
|
||||
private:
|
||||
std::string fDeviceId;
|
||||
|
@ -241,7 +246,7 @@ struct StateChangeSubscription : Cmd
|
|||
|
||||
struct StateChangeUnsubscription : Cmd
|
||||
{
|
||||
explicit StateChangeUnsubscription(const std::string& id, Result result)
|
||||
explicit StateChangeUnsubscription(const std::string& id, const Result result)
|
||||
: Cmd(Type::state_change_unsubscription)
|
||||
, fDeviceId(id)
|
||||
, fResult(result)
|
||||
|
@ -250,7 +255,7 @@ struct StateChangeUnsubscription : Cmd
|
|||
std::string GetDeviceId() const { return fDeviceId; }
|
||||
void SetDeviceId(const std::string& deviceId) { fDeviceId = deviceId; }
|
||||
Result GetResult() const { return fResult; }
|
||||
void SetResult(Result result) { fResult = result; }
|
||||
void SetResult(const Result result) { fResult = result; }
|
||||
|
||||
private:
|
||||
std::string fDeviceId;
|
||||
|
@ -259,7 +264,7 @@ struct StateChangeUnsubscription : Cmd
|
|||
|
||||
struct StateChange : Cmd
|
||||
{
|
||||
explicit StateChange(const std::string& deviceId, uint64_t taskId, State lastState, State currentState)
|
||||
explicit StateChange(const std::string& deviceId, const uint64_t taskId, const State lastState, const State currentState)
|
||||
: Cmd(Type::state_change)
|
||||
, fDeviceId(deviceId)
|
||||
, fTaskId(taskId)
|
||||
|
@ -270,11 +275,11 @@ struct StateChange : Cmd
|
|||
std::string GetDeviceId() const { return fDeviceId; }
|
||||
void SetDeviceId(const std::string& deviceId) { fDeviceId = deviceId; }
|
||||
uint64_t GetTaskId() const { return fTaskId; }
|
||||
void SetTaskId(uint64_t taskId) { fTaskId = taskId; }
|
||||
void SetTaskId(const uint64_t taskId) { fTaskId = taskId; }
|
||||
fair::mq::State GetLastState() const { return fLastState; }
|
||||
void SetLastState(fair::mq::State state) { fLastState = state; }
|
||||
void SetLastState(const fair::mq::State state) { fLastState = state; }
|
||||
fair::mq::State GetCurrentState() const { return fCurrentState; }
|
||||
void SetCurrentState(fair::mq::State state) { fCurrentState = state; }
|
||||
void SetCurrentState(const fair::mq::State state) { fCurrentState = state; }
|
||||
|
||||
private:
|
||||
std::string fDeviceId;
|
||||
|
@ -314,11 +319,11 @@ struct Cmds
|
|||
|
||||
Cmd& At(size_t i) { return *(fCmds.at(i)); }
|
||||
|
||||
size_t Size() { return fCmds.size(); }
|
||||
size_t Size() const { return fCmds.size(); }
|
||||
void Reset() { fCmds.clear(); }
|
||||
|
||||
std::string Serialize() const;
|
||||
void Deserialize(const std::string&);
|
||||
std::string Serialize(const Format type = Format::Binary) const;
|
||||
void Deserialize(const std::string&, const Format type = Format::Binary);
|
||||
|
||||
private:
|
||||
container fCmds;
|
||||
|
|
21
fairmq/sdk/commands/CommandsFormatDef.h.in
Normal file
21
fairmq/sdk/commands/CommandsFormatDef.h.in
Normal file
|
@ -0,0 +1,21 @@
|
|||
/********************************************************************************
|
||||
* Copyright (C) 2019 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
|
||||
* *
|
||||
* This software is distributed under the terms of the *
|
||||
* GNU Lesser General Public Licence (LGPL) version 3, *
|
||||
* copied verbatim in the file "LICENSE" *
|
||||
********************************************************************************/
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace fair {
|
||||
namespace mq {
|
||||
namespace sdk {
|
||||
namespace cmd {
|
||||
|
||||
constexpr auto commandsFormatDefFbs = R"(@commands_format_def_fbs@)";
|
||||
|
||||
} // namespace cmd
|
||||
} // namespace sdk
|
||||
} // namespace mq
|
||||
} // namespace fair
|
|
@ -77,39 +77,34 @@ TEST(Format, Construction)
|
|||
ASSERT_EQ(static_cast<StateChange&>(stateChangeCmds.At(0)).GetCurrentState(), State::Ready);
|
||||
}
|
||||
|
||||
TEST(Format, Serialization)
|
||||
void fillCommands(Cmds& cmds)
|
||||
{
|
||||
Cmds outCmds;
|
||||
cmds.Add<CheckState>();
|
||||
cmds.Add<ChangeState>(Transition::Stop);
|
||||
cmds.Add<DumpConfig>();
|
||||
cmds.Add<SubscribeToHeartbeats>();
|
||||
cmds.Add<UnsubscribeFromHeartbeats>();
|
||||
cmds.Add<SubscribeToStateChange>();
|
||||
cmds.Add<UnsubscribeFromStateChange>();
|
||||
cmds.Add<StateChangeExitingReceived>();
|
||||
cmds.Add<CurrentState>("somedeviceid", State::Running);
|
||||
cmds.Add<TransitionStatus>("somedeviceid", Result::Ok, Transition::Stop);
|
||||
cmds.Add<Config>("somedeviceid", "someconfig");
|
||||
cmds.Add<HeartbeatSubscription>("somedeviceid", Result::Ok);
|
||||
cmds.Add<HeartbeatUnsubscription>("somedeviceid", Result::Ok);
|
||||
cmds.Add<Heartbeat>("somedeviceid");
|
||||
cmds.Add<StateChangeSubscription>("somedeviceid", Result::Ok);
|
||||
cmds.Add<StateChangeUnsubscription>("somedeviceid", Result::Ok);
|
||||
cmds.Add<StateChange>("somedeviceid", 123456, State::Running, State::Ready);
|
||||
}
|
||||
|
||||
outCmds.Add<CheckState>();
|
||||
outCmds.Add<ChangeState>(Transition::Stop);
|
||||
outCmds.Add<DumpConfig>();
|
||||
outCmds.Add<SubscribeToHeartbeats>();
|
||||
outCmds.Add<UnsubscribeFromHeartbeats>();
|
||||
outCmds.Add<SubscribeToStateChange>();
|
||||
outCmds.Add<UnsubscribeFromStateChange>();
|
||||
outCmds.Add<StateChangeExitingReceived>();
|
||||
outCmds.Add<CurrentState>("somedeviceid", State::Running);
|
||||
outCmds.Add<TransitionStatus>("somedeviceid", Result::Ok, Transition::Stop);
|
||||
outCmds.Add<Config>("somedeviceid", "someconfig");
|
||||
outCmds.Add<HeartbeatSubscription>("somedeviceid", Result::Ok);
|
||||
outCmds.Add<HeartbeatUnsubscription>("somedeviceid", Result::Ok);
|
||||
outCmds.Add<Heartbeat>("somedeviceid");
|
||||
outCmds.Add<StateChangeSubscription>("somedeviceid", Result::Ok);
|
||||
outCmds.Add<StateChangeUnsubscription>("somedeviceid", Result::Ok);
|
||||
outCmds.Add<StateChange>("somedeviceid", 123456, State::Running, State::Ready);
|
||||
|
||||
std::string buffer(outCmds.Serialize());
|
||||
|
||||
Cmds inCmds;
|
||||
|
||||
inCmds.Deserialize(buffer);
|
||||
|
||||
ASSERT_EQ(inCmds.Size(), 17);
|
||||
void checkCommands(Cmds& cmds)
|
||||
{
|
||||
ASSERT_EQ(cmds.Size(), 17);
|
||||
|
||||
int count = 0;
|
||||
|
||||
for (const auto& cmd : inCmds) {
|
||||
for (const auto& cmd : cmds) {
|
||||
switch (cmd->GetType()) {
|
||||
case Type::check_state:
|
||||
++count;
|
||||
|
@ -192,4 +187,26 @@ TEST(Format, Serialization)
|
|||
ASSERT_EQ(count, 17);
|
||||
}
|
||||
|
||||
TEST(Format, SerializationBinary)
|
||||
{
|
||||
Cmds outCmds;
|
||||
fillCommands(outCmds);
|
||||
std::string buffer(outCmds.Serialize());
|
||||
|
||||
Cmds inCmds;
|
||||
inCmds.Deserialize(buffer);
|
||||
checkCommands(inCmds);
|
||||
}
|
||||
|
||||
TEST(Format, SerializationJSON)
|
||||
{
|
||||
Cmds outCmds;
|
||||
fillCommands(outCmds);
|
||||
std::string buffer(outCmds.Serialize(Format::JSON));
|
||||
|
||||
Cmds inCmds;
|
||||
inCmds.Deserialize(buffer, Format::JSON);
|
||||
checkCommands(inCmds);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
Loading…
Reference in New Issue
Block a user