Commit 23c10ffb authored by Hélène Ortiz's avatar Hélène Ortiz

Merge branch 'multi-client2'

parents 30b1e4bd 178ee02e
......@@ -84,6 +84,8 @@ libnomad_la_SOURCES = \
dataprovider/message/notification/SurveyXMLMessage.cpp \
dataprovider/message/notification/LogDataImageReadyMessage.cpp \
dataprovider/message/notification/NewFileMessage.cpp \
dataprovider/message/notification/TokenStateChangedMessage.cpp \
dataprovider/message/notification/ChatMessage.cpp \
\
dataprovider/database/IndexGenerator.cpp \
dataprovider/database/DatabaseLoader.cpp \
......@@ -169,7 +171,7 @@ libnomad_la_SOURCES = \
dataprovider/transportlayer/dataprovider/CommandAccessorDirectImpl.cpp \
dataprovider/transportlayer/dataprovider/DataChangePublisherDirectImpl.cpp \
dataprovider/transportlayer/dataprovider/LogAccessorDirectImpl.cpp \
dataprovider/transportlayer/dataprovider/PropertyExpressionAccessorDirectImpl.cpp \
dataprovider/transportlayer/dataprovider/StateAccessorDirectImpl.cpp \
dataprovider/transportlayer/dataprovider/DirectServerLogAccessor.cpp \
dataprovider/transportlayer/dataprovider/SurveyAccessorDirectImpl.cpp \
dataprovider/transportlayer/MultiThreadCommunication.cpp \
......@@ -425,6 +427,9 @@ libnomad_la_SOURCES = \
core/base/MathExpression.cpp \
core/base/BooleanExpression.cpp \
core/base/MathExpressionRenamer.cpp \
core/base/Hostname.cpp \
\
core/session/SessionManager.cpp \
\
core/transportlayer/command/CommandLauncher.cpp \
core/transportlayer/command/DirectCommandLauncher.cpp \
......@@ -450,10 +455,10 @@ libnomad_la_SOURCES = \
core/transportlayer/dataprovider/LogAccessor.cpp \
core/transportlayer/dataprovider/DirectLogAccessor.cpp \
core/transportlayer/dataprovider/DirectServerLogAccessor.cpp \
core/transportlayer/dataprovider/PropertyExpressionAccessor.cpp \
core/transportlayer/dataprovider/StateAccessor.cpp \
core/transportlayer/dataprovider/SurveyAccessor.cpp \
core/transportlayer/dataprovider/DirectSurveyAccessor.cpp \
core/transportlayer/dataprovider/DirectPropertyExpressionAccessor.cpp \
core/transportlayer/dataprovider/DirectStateAccessor.cpp \
core/transportlayer/MultiThreadCommunication.cpp \
core/DirectCore.cpp \
\
......
......@@ -85,6 +85,11 @@ namespace common {
* Expression error.
*/
typedef enum {NO_EXPRESSION_ERROR = 0, DISABLED_CONTROLLER_ERROR, ENUMERATED_VALUE_ERROR, UNDEFINED_VARIABLE_ERROR, PARSER_ERROR} ExpressionError;
/**
* Token state.
*/
enum class TokenState {FREE, OWNED};
}
#endif /*COMMON_COMMONTYPES_H_*/
......@@ -161,6 +161,7 @@ message Message {
GetTree = 88;
DeleteFile = 89;
CreateDirectory = 90;
AppendToFile = 91;
}
required Type type = 1;
......@@ -565,4 +566,11 @@ message CreateDirectoryRequest {
required string parentDirectory = 1;
required string fileName = 2;
}
\ No newline at end of file
}
message AppendToFileRequest {
required string fileName = 1;
required string StringToAppend = 2;
}
......@@ -59,6 +59,9 @@ message Message {
UserVariableStateChanged = 28;
CommandZoneSync = 29;
TokenState = 30;
Chat = 31;
}
required Type type = 1;
......@@ -215,7 +218,28 @@ message UserVariableStateChanged {
}
message CommandZoneSync {
required bytes serializedType = 1;
required bytes serializedContent = 2;
required bytes serializedResponse = 3;
}
message TokenState {
enum State {
FREE = 1;
OWNED = 2;
}
required State state = 1;
required uint32 ownerClientID = 2;
required string ownerEndpoint = 3;
}
message ChatMessage {
required uint32 clientID = 1;
required int64 date = 2;
required string sender = 3;
required string message = 4;
}
......@@ -59,6 +59,8 @@ message Message {
UserLog = 25;
GetControllerTypesInheritingType = 26;
HasRunningCommands = 27;
}
required Type type = 1;
......
......@@ -27,6 +27,10 @@ message Message {
enum Type {
Login = 1;
GetToken = 2;
Sync = 3;
ReleaseToken = 4;
Chat = 5;
}
required Type type = 1;
......@@ -43,3 +47,23 @@ message LoginResponse {
optional bool value = 2;
}
message GetTokenRequest {
required uint32 clientID = 1;
required string clientType = 2;
}
message ReleaseTokenRequest {
required uint32 clientID = 1;
}
message EmptyRequest {
}
message ChatMessage {
required uint32 clientID = 1;
required string sender = 2;
required string message = 3;
}
......@@ -36,6 +36,7 @@
#include <core/commandzone/CommandZoneEventServer.h>
#include <core/log/LogHandler.h>
#include <core/log/SimpleLog.h>
#include <core/session/SessionManager.h>
#include <dataprovider/transportlayer/MultiThreadCommunication.h>
#include <common/base/ServerProperties.h>
#include <common/base/Convert.h>
......@@ -100,6 +101,7 @@ void DirectCore::init(int argc, char* argv[]) {
ServantCloner::initInstance(dataprovider::MultiThreadCommunication::getInstance()->getServantAccessor());
ServantInfo::initInstance();
SessionManager::initInstance();
CommandZone::initInstance(commandZoneID);
CommandZoneEventServer::initInstance(MultiThreadCommunication::getInstance()->getCommandZoneEventPublisher());
......@@ -163,6 +165,7 @@ void DirectCore::reset() {
Scheduler::getInstance()->stop();
CommandZone::resetInstances();
SessionManager::resetInstance();
Spy::resetInstance();
Survey::resetInstance();
......
/*
* Nomad Instrument Control Software
*
* Copyright 2011 Institut Laue-Langevin
*
* Licensed under the EUPL, Version 1.1 only (the "License");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
* http://joinup.ec.europa.eu/software/page/eupl
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the Licence is distributed on an "AS IS" basis,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Licence for the specific language governing permissions and
* limitations under the Licence.
*/
#include "Hostname.h"
using namespace std;
namespace core {
std::string hostname(const std::string endpoint) {
string::size_type pos1 = endpoint.find_first_of(':');
if (pos1 == string::npos) {
return "?";
}
string::size_type pos2 = endpoint.find_first_of(':', pos1 + 1);
if (pos2 == string::npos) {
return "?";
}
return endpoint.substr(pos1 + 3, pos2 - pos1 - 3);
}
}
/*
* Nomad Instrument Control Software
*
* Copyright 2011 Institut Laue-Langevin
*
* Licensed under the EUPL, Version 1.1 only (the "License");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
* http://joinup.ec.europa.eu/software/page/eupl
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the Licence is distributed on an "AS IS" basis,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Licence for the specific language governing permissions and
* limitations under the Licence.
*/
#ifndef CORE_HOSTNAME_H_
#define CORE_HOSTNAME_H_
#include <string>
namespace core {
/**
* Extracts the hostname from the endpoint.
*/
std::string hostname(const std::string endpoint);
}
#endif
......@@ -24,9 +24,12 @@
#include <core/log/LogHandler.h>
#include <core/log/CommandZoneContentLog.h>
#include <core/log/CommandZoneEventLog.h>
#include <core/log/SimpleLog.h>
#include <core/base/Hostname.h>
#include <core/dataaccess/DataAccess.h>
#include <common/base/Convert.h>
#include <common/output/OutputStream.h>
#include <common/base/CommonTypes.h>
#include <ics/IcsServerManager.h>
using namespace std;
......@@ -137,7 +140,7 @@ const std::vector<CommandBox*>& CommandZone::getCommandBoxes() const {
return _container->getCommandBoxes();
}
void CommandZone::execute(unsigned long databaseID) {
void CommandZone::execute(const std::string& endpoint, unsigned long databaseID) {
// set the database ID for the command zone
_container->setExecutionDatabaseID(databaseID);
......@@ -156,6 +159,8 @@ void CommandZone::execute(unsigned long databaseID) {
ics::ServerManager::getInstance()->onCommandZoneStarted();
}
LogHandler::getInstance()->write(SimpleLog(common::LOG_INFO, "Client " + hostname(endpoint) + " started launch pad"));
try {
// start the execution
_container->startExecution();
......@@ -165,38 +170,45 @@ void CommandZone::execute(unsigned long databaseID) {
}
}
void CommandZone::stop() {
void CommandZone::stop(const std::string& endpoint) {
_container->stop();
LogHandler::getInstance()->write(CommandZoneEventLog("Command zone stopped"));
if (endpoint == "") {
LogHandler::getInstance()->write(SimpleLog(common::LOG_INFO, "Server stopped launch pad"));
}
else {
LogHandler::getInstance()->write(SimpleLog(common::LOG_INFO, "Client " + hostname(endpoint) + " stopped launch pad"));
}
}
void CommandZone::stopAtEnd() {
void CommandZone::stopAtEnd(const std::string& endpoint) {
_container->stopAtEnd();
LogHandler::getInstance()->write(CommandZoneEventLog("Command zone stopped at end"));
LogHandler::getInstance()->write(SimpleLog(common::LOG_INFO, "Client " + hostname(endpoint) + " stopped launch pad at end of command box"));
}
void CommandZone::restart() {
void CommandZone::restart(const std::string& endpoint) {
try {
// restart the execution
_container->restart();
CommandZoneEventServer::getInstance()->commandZoneStarted(_ID);
LogHandler::getInstance()->write(CommandZoneEventLog("Command zone restarted"));
LogHandler::getInstance()->write(SimpleLog(common::LOG_INFO, "Client " + hostname(endpoint) + " restarted launch pad"));
} catch (CommandBoxContainer::CannotRunException& e) {
throw link(CommandConflicts(_ID), e);
}
}
void CommandZone::pause() {
void CommandZone::pause(const std::string& endpoint) {
_container->pause();
CommandZoneEventServer::getInstance()->commandZonePaused(_ID);
LogHandler::getInstance()->write(CommandZoneEventLog("Command zone paused"));
LogHandler::getInstance()->write(SimpleLog(common::LOG_INFO, "Client " + hostname(endpoint) + " paused launch pad"));
}
void CommandZone::resetCommandZone(unsigned long databaseID) {
......
......@@ -123,27 +123,27 @@ public:
/**
* Executes the command zone.
*/
void execute(unsigned long databaseID);
void execute(const std::string& endpoint, unsigned long databaseID);
/**
* Stops the command zone.
*/
void stop();
void stop(const std::string& endpoint);
/**
* Stops the command zone at end (terminates the current commands).
*/
void stopAtEnd();
void stopAtEnd(const std::string& endpoint);
/**
* Pauses the command zone.
*/
void pause();
void pause(const std::string& endpoint = "");
/**
* Restarts the command zone.
*/
void restart();
void restart(const std::string& endpoint = "");
/**
* Resets the command zone.
......
......@@ -155,7 +155,7 @@ void Alarm::delay() {
// stop command zone if required
if (_stopCommandZone) {
out << "alarm : " << getMessage() << " : stops command zone" << eol;
CommandZone::getInstance()->stop();
CommandZone::getInstance()->stop("");
}
notify();
......
......@@ -24,13 +24,13 @@
#include <core/dataaccess/DataNotificationRouter.h>
#include <core/dataaccess/DataAccess.h>
#include <core/transportlayer/MultiThreadCommunication.h>
#include <core/transportlayer/dataprovider/PropertyExpressionAccessor.h>
#include <core/log/LogHandler.h>
#include <core/log/SimpleLog.h>
#include <iostream>
#include <algorithm>
#include <boost/tokenizer.hpp>
#include <boost/algorithm/string.hpp>
#include "../transportlayer/dataprovider/StateAccessor.h"
using namespace std;
......@@ -53,7 +53,7 @@ Condition::Condition(common::ConditionType type, const std::string& name) :
_conditionId = _index;
_index = _index + 1;
_propertyExpressionAccessor = MultiThreadCommunication::getInstance()->getPropertyExpressionAccessor();
_stateAccessor = MultiThreadCommunication::getInstance()->getStateAccessor();
}
Condition::~Condition() {
......@@ -151,7 +151,7 @@ void Condition::resetAndCheck() {
}
// notification
_propertyExpressionAccessor->notifyConditionState(_conditionId, _on, _state);
_stateAccessor->notifyConditionState(_conditionId, _on, _state);
LogHandler::getInstance()->write(SimpleLog(common::LOG_INFO, getStringType() + " " + _name + " is " + (_on ? "ON" : "OFF")));
}
......@@ -278,7 +278,7 @@ void Condition::setState(common::ConditionState state) {
}
if (oldState != _state) {
_propertyExpressionAccessor->notifyConditionState(_conditionId, _on, _state);
_stateAccessor->notifyConditionState(_conditionId, _on, _state);
}
}
......
......@@ -29,7 +29,7 @@
namespace core {
class ConditionElement;
class PropertyExpressionAccessor;
class StateAccessor;
/**
* Base class defining a Condition for the ConditionManager.
......@@ -226,7 +226,7 @@ private:
bool _oldValue;
bool _first;
PropertyExpressionAccessor* _propertyExpressionAccessor;
StateAccessor* _stateAccessor;
static const std::string SMS_MAIL_RECIPIENT;
};
......
This diff is collapsed.
/*
* Nomad Instrument Control Software
*
* Copyright 2011 Institut Laue-Langevin
*
* Licensed under the EUPL, Version 1.1 only (the "License");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
* http://joinup.ec.europa.eu/software/page/eupl
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the Licence is distributed on an "AS IS" basis,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Licence for the specific language governing permissions and
* limitations under the Licence.
*/
#ifndef CORE_SESSIONMANAGER_H_
#define CORE_SESSIONMANAGER_H_
#include <common/base/CommonTypes.h>
#include <common/base/Exception.h>
#include <common/base/TimeCondition.h>
#include <cameo/cameo.h>
#include <string>
#include <vector>
#include <memory>
#include <thread>
#include <atomic>
namespace core {
class StateAccessor;
/**
* Class helping to manage the server/instance pair.
*/
struct RequesterApplication {
std::unique_ptr<cameo::Server> server;
std::unique_ptr<cameo::application::Instance> instance;
/**
* Constructor.
*/
RequesterApplication();
/**
* Move constructor.
*/
RequesterApplication(RequesterApplication && application);
/**
* Resets the object.
*/
void reset();
/**
* Operator=.
*/
RequesterApplication & operator= (RequesterApplication && application);
};
/**
* Class defining the singleton session manager.
*/
class SessionManager {
public:
/**
* Returns the instance.
*/
static SessionManager* getInstance();
/**
* Initialises the instance.
*/
static void initInstance();
/**
* resets the instance.
*/
static void resetInstance();
/**
* Logins a session. Returns the id of the session if accepted, -1 otherwise.
*/
int login(cameo::application::Request * request);
/**
* Requests the token.
*/
void requestToken(cameo::application::Request * request, uint32 clientID, const std::string& clientType);
/**
* Releases the token.
*/
void releaseToken(cameo::application::Request * request, uint32 clientID);
/**
* Requests a synchronization so that a token event is sent.
*/
void notifyTokenState();
/**
* Notifies an activity using the token. The timeout is reset.
*/
void notifyTokenActivity();
/**
* Sends a chat message.
*/
void sendChatMessage(cameo::application::Request * request, uint32 clientID, const std::string& sender, const std::string& message);
private:
SessionManager();
~SessionManager();
void init();
RequesterApplication getRequesterApplication(cameo::application::Request * request);
void checkRequesterApplications();
int nextId();
std::chrono::system_clock::time_point lastTokenActivityDate();
void updateTokenActivity();
static SessionManager* m_instance;
int m_tokenTimeout;
std::atomic_bool m_running;
std::unique_ptr<std::thread> m_checkThread;
int m_multipleClients;
int m_currentId;
std::vector<RequesterApplication> m_applications;
common::TokenState m_tokenState = common::TokenState::FREE;
uint32 m_tokenClientID;
std::string m_tokenOwner;
std::mutex m_mutex;
std::chrono::system_clock::time_point m_lastTokenActivityDate;
StateAccessor* m_stateAccessor;
static const std::string MULTIPLE_CLIENTS_PROPERTY;
static const int SINGLE_CLIENT = 0;
static const int SINGLE_CLIENT_PER_ENDPOINT = 1;
static const int MULTIPLE_CLIENTS = 2;
static const std::string MAIN_TYPE;
static const std::string REMOTE_TYPE;
static const std::string VIRTUAL_TYPE;
static const std::string TABLET_TYPE;
static const std::string TOKEN_TIMEOUT_PROPERTY;
};
}
#endif
......@@ -32,13 +32,13 @@
#include <core/transportlayer/dataprovider/DirectLogAccessor.h>
#include <core/transportlayer/dataprovider/DirectServerLogAccessor.h>
#include <core/transportlayer/dataprovider/DirectSurveyAccessor.h>
#include "dataprovider/DirectPropertyExpressionAccessor.h"
#include <common/base/ServerProperties.h>
#include <common/output/OutputStream.h>
#include <command/transportlayer/MultiThreadProcessorManagerCommunication.h>
#include <dataprovider/transportlayer/MultiThreadCommunication.h>
#include <iostream>
#include <core/transportlayer/core/commandzone/CommandZoneResponder.h>
#include "dataprovider/DirectStateAccessor.h"
using namespace common;
using namespace std;
......@@ -130,7 +130,7 @@ void MultiThreadCommunication::init(int argc, char* argv[], bool remote, const s
_commandLauncher = new DirectCommandLauncher(command::MultiThreadProcessorManagerCommunication::getInstance()->getCommandLauncher(), _completionHandler);
_logAccessor = new DirectLogAccessor(dataprovider::MultiThreadCommunication::getInstance()->getLogAccessor());
_surveyAccessor = new DirectSurveyAccessor(dataprovider::MultiThreadCommunication::getInstance()->getSurveyAccessor());
_propertyExpressionAccessor = new DirectPropertyExpressionAccessor(dataprovider::MultiThreadCommunication::getInstance()->getPropertyExpressionAccessor());
_stateAccessor = new DirectStateAccessor(dataprovider::MultiThreadCommunication::getInstance()->getPropertyExpressionAccessor());
out << "core communications ready" << eol;
......@@ -159,7 +159,7 @@ void MultiThreadCommunication::reset() {
delete _logAccessor;
delete _surveyAccessor;
delete _propertyExpressionAccessor;
delete _stateAccessor;
delete _completionHandler;
delete _dataChangeSubscriber;
......@@ -188,8 +188,8 @@ SurveyAccessor* MultiThreadCommunication::getSurveyAccessor() const {
return _surveyAccessor;
}
PropertyExpressionAccessor* MultiThreadCommunication::getPropertyExpressionAccessor() const {
return _propertyExpressionAccessor;
StateAccessor* MultiThreadCommunication::getStateAccessor() const {
return _stateAccessor;
}
CommandZoneEventPublisher* MultiThreadCommunication::getCommandZoneEventPublisher() const {
......
......@@ -45,7 +45,7 @@ class CommandZoneEventPublisher;
class DataChangePublisher;
class LogAccessor;
class SurveyAccessor;
class PropertyExpressionAccessor;
class StateAccessor;
/**
* Class defining the thread communication manager of the Core application.
......@@ -127,7 +127,7 @@ public:
/**
* Gets the condition accessor.
*/
PropertyExpressionAccessor* getPropertyExpressionAccessor() const;
StateAccessor* getStateAccessor() const;
/**
* Gets the command accessor.
......@@ -170,7 +170,7 @@ private:
LogAccessor* _logAccessor;
SurveyAccessor* _surveyAccessor;
PropertyExpressionAccessor* _propertyExpressionAccessor;
StateAccessor* _stateAccessor;
DataChangePublisher* _dataChangePublisher;
DataChangeSubscriberDirectImpl* _dataChangeSubscriber;
......
......@@ -21,6 +21,7 @@
#include <common/protobuf/generated/ConditionManagerRequests.pb.h>
#include <common/output/OutputStream.h>
#include <core/conditions/ConditionManager.h>
#include <core/session/SessionManager.h>
using namespace std;
using namespace cameo;
......@@ -57,20 +58,20 @@ void ConditionManagerResponder::stop() {
void ConditionManagerResponder::initProcessFunctions() {
m_processFunctions[::condition::Message::VerifyExpression] = &ConditionManagerResponder::processVerifyExpression;
m_processFunctions[::condition::Message::AddAlarm] = &ConditionManagerResponder::processAddAlarm;
m_processFunctions[::condition::Message::EditAlarm] = &ConditionManagerResponder::processEditAlarm;
m_processFunctions[::condition::Message::AddWarning] = &ConditionManagerResponder::processAddWarning;
m_processFunctions[::condition::Message::EditWarning] = &ConditionManagerResponder::processEditWarning;
m_processFunctions[::condition::Message::AddWatchdog] = &ConditionManagerResponder::processAddWatchdog;
m_processFunctions[::condition::Message::EditWatchdog] = &ConditionManagerResponder::processEditWatchdog;
m_processFunctions[::condition::Message::AddCommandZoneTermination] = &ConditionManagerResponder::processAddCommandZoneTermination;
m_processFunctions[::condition::Message::EditCommandZoneTermination] = &ConditionManagerResponder::processEditCommandZoneTermination;
m_processFunctions[::condition::Message::RemoveCondition] = &ConditionManagerResponder::processRemoveCondition;
m_processFunctions[::condition::Message::SetConditionOn] = &ConditionManagerResponder::processSetConditionOn;
m_processFunctions[::condition::Message::RenameCondition] = &ConditionManagerResponder::processRenameCondition;
m_processFunctions[::condition::Message::GetConditionState] = &ConditionManagerResponder::processGetConditionState;
m_processFunctions[::condition::Message::GetConditionsXMLContent] = &ConditionManagerResponder::processGetConditionsXMLContent;
m_processFunctions[::condition::Message::VerifyExpression] = ProcessFunction(&ConditionManagerResponder::processVerifyExpression, true);
m_processFunctions[::condition::Message::AddAlarm] = ProcessFunction(&ConditionManagerResponder::processAddAlarm, false);
m_processFunctions[::condition::Message::EditAlarm] = ProcessFunction(&ConditionManagerResponder::processEditAlarm, false);
m_processFunctions[::condition::Message::AddWarning] = ProcessFunction(&ConditionManagerResponder::processAddWarning, false);
m_processFunctions[::condition::Message::EditWarning] = ProcessFunction