Program Listing for File commandhandler.cpp¶
↰ Return to documentation for file (falcon/commandhandler.cpp
)
// ---------------------------------------------------------------------
// This file is part of falcon-core.
//
// Copyright (C) 2015, 2016, 2017 Neuro-Electronics Research Flanders
//
// Falcon-server is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Falcon-server is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with falcon-core. If not, see <http://www.gnu.org/licenses/>.
// ---------------------------------------------------------------------
#include <deque>
#include <regex>
#include <unistd.h>
#include "buildconstant.hpp"
#include "commandhandler.hpp"
#include "utilities/filesystem.hpp"
#include "utilities/zmqutil.hpp"
#include "yaml-cpp/yaml.h"
using namespace commands;
bool CommandHandler::DelegateGraphCommand(std::deque<std::string> &command,
std::deque<std::string> &reply) {
// delegate
s_send_multi(*graph_socket_, command);
// get reply
reply = s_blocking_recv_multi(*graph_socket_);
return false;
}
bool CommandHandler::DelegateResourcesCommand(std::deque<std::string> &command,
std::deque<std::string> &reply) {
std::string resources_type;
if (command[0] == "list") {
if(command.size() == 2)
resources_type = command[1]+"://";
else
resources_type = "resources://";
try{
std::string resource_path = global_context_->resolve_path(resources_type);
std::vector<std::string> list_files = getAllFilesInDir(resource_path);
for (auto const &file : list_files) {
reply.push_back(std::regex_replace(file, std::regex(resource_path), resources_type));
}
} catch (YAML::BadFile &e) {
reply.push_back("ERR");
reply.push_back("Unknown resources type requested \"" + resources_type + "\".");
return false;
}
} else if (command[0] == "graphs") {
try {
std::string graph_path =
global_context_->resolve_path(command[1]);
YAML::Node node;
node["falcon"]["version"] = "1.0.0";
node["graph"] = YAML::LoadFile(graph_path);
YAML::Emitter out;
out << node;
reply.push_back(std::string(out.c_str()));
} catch (YAML::BadFile &e) {
reply.push_back("ERR");
reply.push_back("Invalid graph file");
}
}
else{
// error
reply.push_back("ERR");
reply.push_back("Unknown resources command \"" + command[0] + "\".");
}
return false;
}
bool CommandHandler::HandleCommand(std::deque<std::string> &command,
std::deque<std::string> &reply) {
bool finished = false;
std::deque<std::string> local_command;
std::deque<std::string> local_reply;
if (command.empty()) {
return finished;
}
if (command[0] == "graph") {
// delegate
command.pop_front();
finished = DelegateGraphCommand(command, reply);
} else if (command[0] == "resources") {
command.pop_front();
finished = DelegateResourcesCommand(command, reply);
} else if (command[0] == "documentation") {
local_command.push_back("documentation");
finished = DelegateGraphCommand(local_command, reply);
} else if (command[0] == "test") {
if (command.size() > 1) {
if (command[1] == "true" || command[1] == "on") {
global_context_->set_test(true);
reply.push_back("OK");
} else if (command[1] == "false" || command[1] == "off") {
global_context_->set_test(false);
reply.push_back("OK");
} else {
reply.push_back("ERR");
reply.push_back("Invalid argument for test command");
}
} else {
// toggle test flag
global_context_->set_test(!global_context_->test());
reply.push_back("OK");
}
} else if (command[0] == "quit" || command[0] == "kill") {
local_command.push_back("state");
DelegateGraphCommand(local_command, local_reply);
if (local_reply[0] == "PROCESSING" && command[0] == "quit") {
// error
reply.push_back("ERR");
reply.push_back("Cannot quit while graph is processing.");
} else {
if (local_reply[0] == "PROCESSING") {
local_command.back() = "stop";
DelegateGraphCommand(local_command, local_reply);
}
local_command.back() = "destroy";
DelegateGraphCommand(local_command, local_reply);
reply.push_back("OK");
finished = true;
}
} else if (command[0] == "info") {
local_command.push_back("state");
DelegateGraphCommand(local_command, local_reply);
YAML::Emitter out;
out << YAML::BeginMap;
out << YAML::Key << "Falcon version" << YAML::Value << GIT_REVISION;
out << YAML::Key << "run_environment_root" << YAML::Value
<< global_context_->storage_context("runroot");
out << YAML::Key << "resource_root" << YAML::Value
<< global_context_->storage_context("resources");
out << YAML::Key << "graph_state" << YAML::Value << local_reply[0];
out << YAML::Key << "default_test_flag" << YAML::Value
<< global_context_->test();
reply.push_back(std::string(out.c_str()));
} else {
// error
reply.push_back("ERR");
reply.push_back("Unknown command \"" + command[0] + "\".");
}
return finished;
}
void CommandHandler::start() {
if (sources_.size() == 0) {
return;
}
// connect to graph thread
// construct socket here, so that it is automatically destructed when this
// function ends
zmq::socket_t socket(global_context_->zmq(), ZMQ_REQ);
socket.connect("inproc://graph");
// save pointer to socket, so that DelegateGraphCommand can use it
graph_socket_ = &socket;
bool finished = false;
std::deque<std::string> command;
std::deque<std::string> reply;
while (!finished) {
usleep(100000); // 0.1 second
// iterate through sources
for (auto &it : sources_) {
// retrieve command
command.clear();
if (it->getcommand(command)) {
reply.clear();
finished = HandleCommand(command, reply);
it->sendreply(command, reply);
}
if (finished) {
break;
}
}
}
graph_socket_ = nullptr;
}