...
 
Commits (23)
......@@ -7,6 +7,7 @@ PROTO_GEN_PATH=$(top_srcdir)/src/common/protobuf/generated
proto:
mkdir -p $(PROTO_GEN_PATH)
protoc -I=$(PROTO_PATH) --cpp_out=$(PROTO_GEN_PATH) $(PROTO_PATH)/AnalysisRequests.proto
protoc -I=$(PROTO_PATH) --cpp_out=$(PROTO_GEN_PATH) $(PROTO_PATH)/ServantConfiguration.proto
protoc -I=$(PROTO_PATH) --cpp_out=$(PROTO_GEN_PATH) $(PROTO_PATH)/NotificationMessages.proto
protoc -I=$(PROTO_PATH) --cpp_out=$(PROTO_GEN_PATH) $(PROTO_PATH)/CommonResponses.proto
......
......@@ -7,6 +7,7 @@ bin_PROGRAMS = nomad moduletest moduleloadsequencer propertyaliascheck
# multi-thread
libnomad_la_SOURCES = \
common/protobuf/generated/AnalysisRequests.pb.cc \
common/protobuf/generated/ServantConfiguration.pb.cc \
common/protobuf/generated/NotificationMessages.pb.cc \
common/protobuf/generated/CommonResponses.pb.cc \
......@@ -434,6 +435,7 @@ libnomad_la_SOURCES = \
core/transportlayer/command/CommandLauncher.cpp \
core/transportlayer/command/DirectCommandLauncher.cpp \
core/transportlayer/common/DataChangeSubscriberDirectImpl.cpp \
core/transportlayer/core/AnalysisResponder.cpp \
core/transportlayer/core/CompletionHandlerDirectImpl.cpp \
core/transportlayer/core/DatabaseResponder.cpp \
core/transportlayer/core/ServantManagerResponder.cpp \
......
......@@ -101,10 +101,10 @@ void LogHandler::write(const SimpleLog& log, bool writeLogFile) {
_messageQueue->put(new WriteSimpleLogMessage(log.getType(), log.getLevel(), log.getMessage(), writeLogFile));
}
void LogHandler::imageDataReady(const std::string& imageName) {
void LogHandler::imageDataReady(const std::string& imageName, const std::string& path) {
// No need for asynchronous queue.
// This simplification should be applied to write (see core::LogHandler)
_logAccessor->imageDataReady(imageName);
_logAccessor->imageDataReady(imageName, path);
}
......
......@@ -75,7 +75,7 @@ public:
*/
void write(const SimpleLog& log, bool writeLogFile);
void imageDataReady(const std::string& imageName);
void imageDataReady(const std::string& imageName, const std::string& path);
/**
* Notifies that the request of request ID has terminated.
......
......@@ -45,8 +45,8 @@ void DirectLogAccessor::write(common::LogType type, common::LogLevel level, cons
_proxy->writeSimpleLog(level, message, writeLogFile);
}
void DirectLogAccessor::imageDataReady(const std::string & imageName) {
_proxy->imageDataReadyLog(imageName);
void DirectLogAccessor::imageDataReady(const std::string & imageName, const std::string & path) {
_proxy->imageDataReadyLog(imageName, path);
}
}
......@@ -58,7 +58,7 @@ public:
/**
* Write image data ready log message
*/
virtual void imageDataReady(const std::string & imageName);
virtual void imageDataReady(const std::string & imageName, const std::string & path);
private:
dataprovider::LogAccessorDirectImpl* _proxy;
......
......@@ -47,7 +47,7 @@ public:
virtual void write(common::LogType type, common::LogLevel level, const std::string & message, bool writeLogFile) = 0;
virtual void imageDataReady(const std::string & imageName) = 0;
virtual void imageDataReady(const std::string & imageName, const std::string & path) = 0;
};
......
......@@ -19,6 +19,7 @@
#include "ServerProperties.h"
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/lexical_cast.hpp>
#include <common/output/OutputStream.h>
#include <common/base/FileUtilities.h>
#include <common/base/Convert.h>
......@@ -195,6 +196,10 @@ std::string const & ServerProperties::getNomadDataPath() const {
return _nomadDataPath;
}
uint32 const & ServerProperties::getPlotyVersion() const {
return _plotyVersion;
}
void ServerProperties::init(std::string const & configPath) {
// Test for endianness.
......@@ -321,6 +326,19 @@ void ServerProperties::init(std::string const & configPath) {
cout << "set the default value " <<_nomadDataPath << " to the property '" << propertyName << "'" << endl;
}
// Mock mode.
propertyName = "plotyVersion";
if (_propertyMap.find(propertyName)) {
try {
_plotyVersion = boost::lexical_cast<uint32>(_propertyMap.get(propertyName));
}
catch(...) {
_plotyVersion = 1;
}
} else {
_plotyVersion = 1;
}
// Set the config path.
setConfigPath(configPath);
}
......
......@@ -111,6 +111,11 @@ public:
*/
std::string const & getNomadDataPath() const;
/**
* Gets the mock mode.
*/
uint32 const & getPlotyVersion() const;
/**
* Gets the number of properties.
*/
......@@ -215,6 +220,7 @@ private:
std::string _nomadNotifications;
std::string _nomadDataPath;
std::string _propertyPath;
uint32 _plotyVersion;
HashMap<std::string, std::string> _propertyMap;
HashMap<std::string, std::string> _dynamicPropertyMap;
......
......@@ -22,3 +22,5 @@ ServantConfiguration.pb.h
/SessionRequests.pb.h
/VariableManagerRequests.pb.cc
/VariableManagerRequests.pb.h
/AnalysisRequests.pb.cc
/AnalysisRequests.pb.h
package analysis;
option java_package = "fr.ill.ics.analysis";
option java_outer_classname = "AnalysisRequests";
option optimize_for = LITE_RUNTIME;
enum FitType {
GaussianFit = 1;
MultiGaussianFit = 2;
CenterOfMass = 3;
}
// Principal Message
message Message {
enum Type {
GetFit = 1;
}
required Type type = 1;
}
message DataToFitMessage {
required FitType type = 1;
repeated double xdata = 2;
repeated double ydata = 3;
}
message FitDataMessage {
required FitType type = 1;
required bool converged = 2;
repeated double fitydata = 3;
optional double min = 4;
optional double max = 5;
optional double integral = 6;
optional double position = 7;
optional double amplitude = 8;
optional double fwhm = 9;
}
......@@ -205,3 +205,9 @@ message StringMapResponse {
repeated StringAndKey map = 1;
}
message DynamicPropertyIds {
repeated int32 id = 1;
}
package ploty;
option java_package = "fr.ill.ics.ploty";
option java_outer_classname = "DataPlotMessages";
option optimize_for = LITE_RUNTIME;
// Principal Message
message Message {
enum Type {
PlotPropertyData = 1;
PlotHisto = 2;
ClosePlots = 3;
RestorePlots = 4;
}
required Type type = 1;
}
// PlotPropertyData Message
message PlotPropertyDataMessage {
required int32 title_id = 1;
required int32 xaxis_title_id = 2;
required int32 yaxis_title_id = 3;
required string windowTitle = 4;
required string plotTitle = 5;
required string xaxis_title = 6;
required string yaxis_title = 7;
required string plotkey = 8;
repeated string keys = 9;
repeated string legend_keys = 10;
repeated string colors = 11;
repeated int32 datax_ids = 12;
repeated int32 datay_ids = 13;
repeated int32 dataz_ids = 14;
repeated int32 plottype_id = 15;
repeated int32 x_id = 16;
repeated int32 y_id = 17;
repeated int32 channel_id = 18;
repeated int32 slice_id = 19;
repeated int32 max_x_id = 20;
repeated int32 max_y_id = 21;
repeated int32 max_channel_id = 22;
repeated int32 max_slice_id = 23;
repeated int32 xphysical_size_id = 24;
repeated int32 yphysical_size_id = 25;
repeated bool error_bars = 26;
repeated int32 optimization_result_found_id = 27;
repeated int32 optimization_result_x_id = 28;
repeated string optimization_result_color = 29;
repeated int32 optimization_fit_found_id = 30;
repeated int32 optimization_fit_y_id = 31;
repeated string optimization_fit_color = 32;
optional int32 use_grid_id = 33;
optional int32 use_log_id = 34;
optional int32 color_map_id = 35;
optional int32 min_color_limit_id = 36;
optional int32 max_color_limit_id = 37;
optional int32 nbRois_id = 38;
repeated int32 x0_parent_id = 39;
repeated int32 y0_parent_id = 40;
repeated int32 x1_parent_id = 41;
repeated int32 y1_parent_id = 42;
repeated int32 sum_parent_id = 43;
optional int32 selectedPlot_id = 44;
optional int32 selectedRoi_id = 45;
optional int32 selectedX0_id = 46;
optional int32 selectedY0_id = 47;
optional int32 selectedX1_id = 48;
optional int32 selectedY1_id = 49;
optional int32 commandRoiAdd_id = 50;
optional int32 commandRoiRaz_id = 51;
optional int32 countActivated_id = 52;
}
// Spy and multiplot message for ploty2
message SpyMultiPlotMessage {
enum Type {
SpyChange = 1;
SpyImage = 2;
MultiPlotImage = 3;
}
required Type type = 1;
required string name = 2;
}
......@@ -69,6 +69,10 @@ message Message {
GetPropertyId = 28;
GetWholeDynamicProperties = 29;
GetPropertyType = 30;
GetDynamicPropertyIds = 31;
}
required Type type = 1;
......@@ -167,3 +171,15 @@ message GetPropertyIDRequest {
required string servantName = 2;
required string propertyName = 3;
}
message GetPropertyTypeRequest {
required uint32 databaseID = 1;
required uint32 propertyID = 2;
}
message GetDynamicPropertyIdsRequest {
required uint32 databaseID = 1;
required uint32 propertyID = 2;
}
......@@ -100,6 +100,7 @@ message MessageXML {
message ImageDataReady {
required string imageName = 1;
required string imagePath = 2;
}
message PropertyChanged {
......
......@@ -138,6 +138,7 @@ message ServantCommandsState {
repeated CommandStateValue commands = 1;
}
// Web spy
message WebSpyMessage {
enum Type {
ControllersProperties = 1;
......@@ -147,7 +148,6 @@ message WebSpyMessage {
optional string filename = 2;
}
// Web spy
message WebSpyProperty {
required int32 ID = 1;
required string name = 2;
......
......@@ -149,7 +149,7 @@ void ConditionManager::init(const std::string& configPath) {
// test environment variable
string notificationsString = ServerProperties::getInstance()->getNomadNotifications();
if (notificationsString == "0") {
if ((notificationsString == "0") || (notificationsString == "-1")) {
_notificationsEnabled = false;
}
}
......
......@@ -25,6 +25,7 @@
#include <core/transportlayer/core/ServantManagerResponder.h>
#include <core/transportlayer/core/commandline/CommandLineResponder.h>
#include <core/transportlayer/core/ConditionManagerResponder.h>
#include <core/transportlayer/core/AnalysisResponder.h>
#include "core/UserVariableManagerResponder.h"
#include <core/transportlayer/core/commandzone/CommandZoneEventPublisher.h>
#include <core/transportlayer/common/DataChangeSubscriberDirectImpl.h>
......@@ -114,6 +115,10 @@ void MultiThreadCommunication::init(int argc, char* argv[], bool remote, const s
m_variableManagerResponder.reset(new UserVariableManagerResponder());
m_variableManagerResponder->init();
// Create the variable manager responder.
m_AnalysisResponder.reset(new AnalysisResponder());
m_AnalysisResponder->init();
// Initialise the command zone event publisher
m_commandZoneEventPublisher.reset(new CommandZoneEventPublisher());
......@@ -154,6 +159,7 @@ void MultiThreadCommunication::reset() {
m_conditionManagerResponder->stop();
m_commandBoxResponder->stop();
m_variableManagerResponder->stop();
m_AnalysisResponder->stop();
delete _dataChangePublisher;
......
......@@ -39,6 +39,7 @@ class CommandLineResponder;
class ConditionManagerResponder;
class CommandZoneResponder;
class UserVariableManagerResponder;
class AnalysisResponder;
class DataChangeSubscriberDirectImpl;
class CommandZoneEventPublisher;
......@@ -167,6 +168,7 @@ private:
std::unique_ptr<CommandZoneResponder> m_commandBoxResponder;
std::unique_ptr<CommandZoneEventPublisher> m_commandZoneEventPublisher;
std::unique_ptr<UserVariableManagerResponder> m_variableManagerResponder;
std::unique_ptr<AnalysisResponder> m_AnalysisResponder;
LogAccessor* _logAccessor;
SurveyAccessor* _surveyAccessor;
......
/*
* 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 "AnalysisResponder.h"
#include <common/protobuf/generated/AnalysisRequests.pb.h>
#include <common/base/BaseTypes.h>
#include "common/analysislibrary/SimpleGaussFinder.h"
#include "common/analysislibrary/MultiGaussPeakFinder.h"
#include "common/analysislibrary/CenterOfMassPeakFinder.h"
#include <numeric>
using namespace std;
using namespace boost;
using namespace cameo;
namespace core {
/*
* constructor
*/
AnalysisResponder::AnalysisResponder() {
}
/*
* destructor
*/
AnalysisResponder::~AnalysisResponder() {
}
/*
* init
*/
void AnalysisResponder::init() {
// Create the responder.
m_responder = application::Responder::create("analysis");
// Start the thread.
m_thread.reset(new boost::thread(boost::bind(&AnalysisResponder::loop, this)));
cout << "Initialised AnalysisResponder" << endl;
}
/*
* stop
*/
void AnalysisResponder::stop() {
// Cancel the responder so that unblocks the waiting thread.
m_responder->cancel();
// Join the thread.
m_thread->join();
cout << "Stopped AnalysisResponder" << endl;
}
/*
* initProcessFunctions
*/
void AnalysisResponder::initProcessFunctions() {
m_processFunctions[analysis::Message::GetFit] = &AnalysisResponder::processGetFit;
}
/*
* processGetFit
*/
void AnalysisResponder::processGetFit(const std::string & message, std::string & response) {
analysis::DataToFitMessage fitMessage;
fitMessage.ParseFromString(message);
if (fitMessage.type() == analysis::GaussianFit) {
simpleGaussianFit(fitMessage, response);
}
else if (fitMessage.type() == analysis::MultiGaussianFit) {
multiGaussianFit(fitMessage, response);
}
else if (fitMessage.type() == analysis::CenterOfMass) {
centerOfMassFit(fitMessage, response);
}
}
/*
* simpleGaussianFit
*/
void AnalysisResponder::simpleGaussianFit(const analysis::DataToFitMessage& data, std::string & response) {
analysis::FitDataMessage fitMessage;
fitMessage.set_type(analysis::GaussianFit);
try {
if ((data.xdata_size() > 0) && ((data.ydata_size() > 0))) {
blitz::Array<float64, 1> y;
blitz::Array<float64, 1> x;
x.resizeAndPreserve(data.xdata_size());
y.resizeAndPreserve(data.ydata_size());
for(uint32 i = 0;i < data.xdata_size(); ++i) {
x(i) = data.xdata(i);
y(i) = data.ydata(i);
}
// ostringstream os;
// os << "y = " << y << endl << "x = " << x;
// cout << "gaussian fit with " << os.str() << endl;
SimpleGaussFinder finder(SimpleGaussFinder::ALL);
finder.fit(y, x);
blitz::Array<float64, 1> parameters = finder.getParameters();
// for (int32 i = 0; i < parameters.size(); i++) {
// cout << "parameters[" << i << "] = " << parameters(i) << endl;
// }
fitMessage.set_converged(finder.fitHasConverged());
if (finder.fitHasConverged()) {
fitMessage.set_position(finder.position());
fitMessage.set_amplitude(finder.gaussianAmplitude());
fitMessage.set_fwhm(2. * sqrt(2. * log(2.)) * parameters(2));
for (int32 i = 0; i < x.size(); i++) {
if (parameters.size() >= 4) {
float64 y = parameters(0) * exp(-pow((x(i) - parameters(1)) / parameters(2), 2.) / 2.) + parameters(3);
if (y < 0.0) {
y = 0.0;
}
// cout << "y = " << y << endl;
fitMessage.add_fitydata(y);
}
}
fitMessage.set_min(*std::min_element(fitMessage.fitydata().begin(), fitMessage.fitydata().end()));
fitMessage.set_max(*std::max_element(fitMessage.fitydata().begin(), fitMessage.fitydata().end()));
fitMessage.set_integral(std::accumulate(fitMessage.fitydata().begin(), fitMessage.fitydata().end(), 0.0));
// cout << "found position " << finder.position() << endl;
} else {
// cout << "SimpleGaussFinderFunction::calculate: no gaussian found" << endl;
}
}
else {
fitMessage.set_converged(false);
}
}
catch (logic_error const & error) {
cerr << error.what() << endl;
fitMessage.set_converged(false);
}
fitMessage.SerializeToString(&response);
}
/*
* multiGaussianFit
*/
void AnalysisResponder::multiGaussianFit(const analysis::DataToFitMessage& data, std::string & response) {
analysis::FitDataMessage fitMessage;
fitMessage.set_type(analysis::MultiGaussianFit);
try {
if ((data.xdata_size() > 0) && ((data.ydata_size() > 0))) {
blitz::Array<float64, 1> y;
blitz::Array<float64, 1> x;
x.resizeAndPreserve(data.xdata_size());
y.resizeAndPreserve(data.ydata_size());
for(uint32 i = 0;i < data.xdata_size(); ++i) {
x(i) = data.xdata(i);
y(i) = data.ydata(i);
}
ostringstream os;
os << "y = " << y << endl << "x = " << x;
cout << "multi gaussian fit with " << os.str() << endl;
MultiGaussPeakFinder finder(y, x);
uint32 nbPeaks = finder.numberOfGoodPeaks();
if (nbPeaks > 0 && finder.getParameters().size() != 0) {
blitz::Array<float64, 2> parameters = finder.getParameters();
// Getting the highest peak.
Peak* peak = finder.bestPeak();
if (peak != 0) {
fitMessage.set_converged(true);
fitMessage.set_position(peak->position());
fitMessage.set_amplitude(peak->amplitude());
int32 peakindex = 0;
for(uint32 i = 0;i < finder.numberOfPeaks();++i) {
if (finder.peak(i) == peak) {
peakindex = i;
break;
}
}
fitMessage.set_fwhm(2. * sqrt(2. * log(2.)) * (float64) parameters(peakindex, 2));
for (int32 i = 0; i < x.size(); i++) {
float64 y = parameters(peakindex, 0) * exp(-pow((x(i) - parameters(peakindex, 1)) / parameters(peakindex, 2), 2.) / 2.) + parameters(peakindex, 3);
if (y < 0.0) {
y = 0.0;
}
cout << "y = " << y << endl;
fitMessage.add_fitydata(y);
}
fitMessage.set_min(*std::min_element(fitMessage.fitydata().begin(), fitMessage.fitydata().end()));
fitMessage.set_max(*std::max_element(fitMessage.fitydata().begin(), fitMessage.fitydata().end()));
fitMessage.set_integral(std::accumulate(fitMessage.fitydata().begin(), fitMessage.fitydata().end(), 0.0));
}
else {
fitMessage.set_converged(false);
cout << "SimpleGaussFinderFunction::calculate: no good peak found" << endl;
}
}
else {
fitMessage.set_converged(false);
cout << "SimpleGaussFinderFunction::calculate: no gaussian found" << endl;
}
}
else {
fitMessage.set_converged(false);
}
}
catch (logic_error const & error) {
cerr << error.what() << endl;
fitMessage.set_converged(false);
}
fitMessage.SerializeToString(&response);
}
/*
* centerOfMassFit
*/
void AnalysisResponder::centerOfMassFit(const analysis::DataToFitMessage& data, std::string & response) {
analysis::FitDataMessage fitMessage;
fitMessage.set_type(analysis::CenterOfMass);
try {
if ((data.xdata_size() > 0) && ((data.ydata_size() > 0))) {
blitz::Array<float64, 1> y;
blitz::Array<float64, 1> x;
x.resizeAndPreserve(data.xdata_size());
y.resizeAndPreserve(data.ydata_size());
for(uint32 i = 0;i < data.xdata_size(); ++i) {
x(i) = data.xdata(i);
y(i) = data.ydata(i);
}
CenterOfMassPeakFinder finderPeak(y, x);
float64 centerOfMass = finderPeak.getPosition();
if (centerOfMass != 0) {
fitMessage.set_converged(true);
fitMessage.set_position(centerOfMass);
float64 amplitude = finderPeak.getAmplitude();
fitMessage.set_amplitude(amplitude);
for (int32 i = 0; i < x.size(); i++) {
fitMessage.add_fitydata(amplitude);
}
fitMessage.set_min(*std::min_element(fitMessage.fitydata().begin(), fitMessage.fitydata().end()));
fitMessage.set_max(*std::max_element(fitMessage.fitydata().begin(), fitMessage.fitydata().end()));
fitMessage.set_integral(std::accumulate(fitMessage.fitydata().begin(), fitMessage.fitydata().end(), 0.0));
} else {
fitMessage.set_converged(false);
}
}
else {
fitMessage.set_converged(false);
}
}
catch (logic_error const & error) {
cerr << error.what() << endl;
fitMessage.set_converged(false);
}
fitMessage.SerializeToString(&response);
}
/*
* loop
*/
void AnalysisResponder::loop() {
// Initialize the map of functions.
initProcessFunctions();
// Loop until cancel is done.
while (true) {
// Wait for a new request.
unique_ptr<application::Request> request = m_responder->receive();
// Stop the loop if cancel is called.
if (request.get() == 0) {
break;
}
// Get the request type.
string firstPart = request->getBinary();
// Get the request message.
string secondPart = request->getSecondBinaryPart();
analysis::Message messageType;
messageType.ParseFromString(firstPart);
string response;
// Get the process function and apply it.
ProcessFunctionType functionPointer = m_processFunctions[messageType.type()];
if (functionPointer != 0) {
(this->*functionPointer)(secondPart, response);
}
else {
cerr << "analysis responder cannot process " << messageType.type() << endl;
}
request->replyBinary(response);
}
}
}
/*
* 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 ANALYSISRESPONDER_H
#define ANALYSISRESPONDER_H
#include <boost/thread.hpp>
#include <cameo/cameo.h>
namespace analysis {
class DataToFitMessage;
}
namespace core {
/**
* Server implementation of the analysis responder class.
*/
class AnalysisResponder {
public:
/**
* Constructor.
*/
AnalysisResponder();
/**
* Virtual destructor.
*/
virtual ~AnalysisResponder();
/**
* Initialises the responder by starting the thread waiting for the requests.
*/
void init();
/**
* Stops the responder and waits for the termination of the thread.
*/
void stop();
private:
void loop();
void initProcessFunctions();
void processGetFit(const std::string & message, std::string & response);
std::unique_ptr<boost::thread> m_thread;
std::unique_ptr<cameo::application::Responder> m_responder;
typedef void (AnalysisResponder:: *ProcessFunctionType)(const std::string &, std::string &);
std::map<int, ProcessFunctionType> m_processFunctions;
void simpleGaussianFit(const analysis::DataToFitMessage& data, std::string & response);
void multiGaussianFit(const analysis::DataToFitMessage& data, std::string & response);
void centerOfMassFit(const analysis::DataToFitMessage& data, std::string & response);
};
}
#endif // ANALYSISRESPONDER_H
......@@ -103,6 +103,8 @@ void DatabaseResponder::initProcessFunctions() {
m_processFunctions[database::Message::GetFormattedValue] = ProcessFunction(&DatabaseResponder::processGetFormattedValue, true);
m_processFunctions[database::Message::GetPropertyId] = ProcessFunction(&DatabaseResponder::processGetPropertyIDRequest, true);
m_processFunctions[database::Message::GetWholeDynamicProperties] = ProcessFunction(&DatabaseResponder::processGetWholeDynamicProperties, true);
m_processFunctions[database::Message::GetPropertyType] = ProcessFunction(&DatabaseResponder::processGetProperyTypeRequest, true);
m_processFunctions[database::Message::GetDynamicPropertyIds] = ProcessFunction(&DatabaseResponder::processGetDynamicPropertyIdsRequest, true);
}
void DatabaseResponder::processGetInt32Value(cameo::application::Request * request, const std::string & message, std::string & response) {
......@@ -384,7 +386,7 @@ void DatabaseResponder::processGetArraySize(cameo::application::Request * reques
common::Int32Response responseMessage;
try {
bool value = m_propertyAccessor->getArraySize(messageRequest.databaseid(), messageRequest.propertyid());
int32 value = m_propertyAccessor->getArraySize(messageRequest.databaseid(), messageRequest.propertyid());
responseMessage.set_value(value);
}
catch (PropertyAccessorDirectImpl::NoSuchPropertyException& e) {
......@@ -624,6 +626,46 @@ void DatabaseResponder::processGetWholeDynamicProperties(cameo::application::Req
// Serialize the response.
responseMessage.SerializeToString(&response);
}
void DatabaseResponder::processGetProperyTypeRequest(cameo::application::Request * request, const std::string & message, std::string & response) {
database::GetPropertyTypeRequest messageRequest;
messageRequest.ParseFromString(message);
common::StringResponse responseMessage;
try {
std::string propertyType = Database::getInstance(messageRequest.databaseid())->getPropertyType(messageRequest.propertyid());
responseMessage.set_value(propertyType);
}
catch (...) {
responseMessage.set_error(common::Error::NO_SUCH_PROPERTY);
}
// Serialize the response.
responseMessage.SerializeToString(&response);
}
void DatabaseResponder::processGetDynamicPropertyIdsRequest(cameo::application::Request * request, const std::string & message, std::string & response) {
database::GetDynamicPropertyIdsRequest messageRequest;
messageRequest.ParseFromString(message);
common::DynamicPropertyIds responseMessage;
// Call to generate the exception.
std::vector<unsigned long> result = Database::getInstance(messageRequest.databaseid())->getDynamicPropertyIDs(messageRequest.propertyid());
for(auto id : result) {
responseMessage.add_id(id);
}
// Serialize the response.
responseMessage.SerializeToString(&response);
}
void DatabaseResponder::loop() {
......
......@@ -96,6 +96,10 @@ private:
void processGetWholeDynamicProperties(cameo::application::Request * request, const std::string & message, std::string & response);
void processGetProperyTypeRequest(cameo::application::Request * request, const std::string & message, std::string & response);
void processGetDynamicPropertyIdsRequest(cameo::application::Request * request, const std::string & message, std::string & response);
dataprovider::PropertyAccessorDirectImpl* m_propertyAccessor;
dataprovider::CommandAccessorDirectImpl* m_commandAccessor;
......
......@@ -1273,16 +1273,21 @@ long Database::getDynamicPropertySize(unsigned long propertyID) {
// Locking the property. No need to get the key ID since a dynamic property cannot be referenced.
ScopedLock lock(_lockManager->lockPropertyForWriting(propertyID, eol));
// Get property
BaseProperty * property = getPropertyFromKeyID(propertyID);
BaseDynamicProperty * dynamicProperty = dynamic_cast<BaseDynamicProperty*>(property);
try {
// Get property
BaseProperty * property = getPropertyFromKeyID(propertyID);
BaseDynamicProperty * dynamicProperty = dynamic_cast<BaseDynamicProperty*>(property);
// verify property is of correct type
if (dynamicProperty != 0) {
return dynamicProperty->getSize();
// verify property is of correct type
if (dynamicProperty != 0) {
return dynamicProperty->getSize();
} else {
err << "should have a BaseDynamicProperty" << eol;
}
}
catch(common::Exception& e) {
} else {
err << "should have a BaseDynamicProperty" << eol;
}
return 0;
......@@ -1298,43 +1303,48 @@ unsigned long Database::getDynamicPropertyIDAtIndex(unsigned long propertyID, lo
// Locking the property. No need to get the key ID since a dynamic property cannot be referenced.
ScopedLock lock(_lockManager->lockPropertyForWriting(propertyID, eol));
// Get property
BaseProperty * property = getPropertyFromKeyID(propertyID);
BaseDynamicProperty * dynamicProperty = dynamic_cast<BaseDynamicProperty*>(property);
try {
// Get property
BaseProperty * property = getPropertyFromKeyID(propertyID);
BaseDynamicProperty * dynamicProperty = dynamic_cast<BaseDynamicProperty*>(property);
// verify property is of correct type
if (dynamicProperty != 0) {
// verify property is of correct type
if (dynamicProperty != 0) {
servantID = dynamicProperty->getParentID();
servantID = dynamicProperty->getParentID();
if (index < dynamicProperty->getSize()) {
if (index < dynamicProperty->getSize()) {
// returning the property ID
return dynamicProperty->getPropertyIDs()[index];
// returning the property ID
return dynamicProperty->getPropertyIDs()[index];
} else if (resize) {
} else if (resize) {
// adding new properties
for (long i = dynamicProperty->getSize(); i < index + 1; i++) {
// adding new properties
for (long i = dynamicProperty->getSize(); i < index + 1; i++) {
DataProperty* newProperty = dynamicProperty->createProperty(true, true);
// new ID
newPropertyID = IndexGenerator::getInstance()->getNextIndex();
newProperty->setID(newPropertyID);
Database::getInstance()->addProperty(newProperty);
DataProperty* newProperty = dynamicProperty->createProperty(true, true);
// new ID
newPropertyID = IndexGenerator::getInstance()->getNextIndex();
newProperty->setID(newPropertyID);
Database::getInstance()->addProperty(newProperty);
dynamicProperty->addProperty(newProperty);
dynamicProperty->addProperty(newProperty);
resized = true;
}
resized = true;
} else {
// index out of bounds
throw IndexOutOfBoundsException(propertyID);
}
} else {
// index out of bounds
throw IndexOutOfBoundsException(propertyID);
err << "should have a BaseDynamicProperty" << eol;
}
}
catch(common::Exception& e) {
} else {
err << "should have a BaseDynamicProperty" << eol;
}
}
......@@ -1350,27 +1360,54 @@ long Database::getIndexOfDynamicPropertyID(unsigned long parentPropertyID, unsig
// Locking the property. No need to get the key ID since a dynamic property cannot be referenced.
ScopedLock lock(_lockManager->lockPropertyForWriting(propertyID, eol));
// Get property
BaseProperty * property = getPropertyFromKeyID(parentPropertyID);
BaseDynamicProperty * dynamicProperty = dynamic_cast<BaseDynamicProperty*>(property);
// verify property is of correct type
if (dynamicProperty != 0) {
long index = 0;
vector<unsigned long> const & properties = dynamicProperty->getPropertyIDs();
vector<unsigned long>::const_iterator it;
for (it = properties.begin(); it != properties.end(); it++) {
if ((*it) == propertyID) {
return index;
try {
// Get property
BaseProperty * property = getPropertyFromKeyID(parentPropertyID);
BaseDynamicProperty * dynamicProperty = dynamic_cast<BaseDynamicProperty*>(property);
// verify property is of correct type
if (dynamicProperty != 0) {
long index = 0;
vector<unsigned long> const & properties = dynamicProperty->getPropertyIDs();
vector<unsigned long>::const_iterator it;
for (it = properties.begin(); it != properties.end(); it++) {
if ((*it) == propertyID) {
return index;
}
index++;
}
index++;
}
}
catch(common::Exception& e) {
}
return -1;
}
const vector<unsigned long>& Database::getDynamicPropertyIDs(unsigned long parentPropertyID) {
// Locking the property. No need to get the key ID since a dynamic property cannot be referenced.
ScopedLock lock(_lockManager->lockPropertyForWriting(parentPropertyID, eol));
try {
// Get property
BaseProperty * property = getPropertyFromKeyID(parentPropertyID);
BaseDynamicProperty * dynamicProperty = dynamic_cast<BaseDynamicProperty*>(property);
// verify property is of correct type
if (dynamicProperty != 0) {
long index = 0;
return dynamicProperty->getPropertyIDs();
}
}
catch(common::Exception& e) {
}
return vector<unsigned long>();
}
void Database::addCommand(Command* command) {
_IDCommandMap.insert(command->getID(), command);
......@@ -2811,8 +2848,15 @@ bool Database::isProperty(unsigned long propertyID) {
std::string Database::getPropertyType(unsigned long propertyID) {
ScopedLock lock(_lockManager->lockPropertyForReading(propertyID, eol));
std::string propertyType;
try {
propertyType = _keyIDPropertyMap.get(propertyID)->getType();
} catch (Exception const & e) {
throw NoSuchPropertyException(propertyID);
}
return _keyIDPropertyMap.get(propertyID)->getType();
return propertyType;
}
PropertyHolder* Database::getPropertyHolder(unsigned long servantID) {
......
......@@ -584,6 +584,11 @@ public:
*/
long getIndexOfDynamicPropertyID(unsigned long parentPropertyID, unsigned long propertyID);
/**
* Gets the list of Id of a dynamic property.
*/
const std::vector<unsigned long>& getDynamicPropertyIDs(unsigned long parentPropertyID);
// add command ////////////////////////////////////////////////////////////////////////////////
/**
......
......@@ -20,9 +20,10 @@
namespace dataprovider {
LogDataImageReadyMessage::LogDataImageReadyMessage(const std::string& imageName) :
LogDataImageReadyMessage::LogDataImageReadyMessage(const std::string& imageName, const std::string& path) :
NotificationMessage(0),
m_imageName(imageName) {
m_imageName(imageName),
m_imagePath(path) {
}
LogDataImageReadyMessage::~LogDataImageReadyMessage() {
......@@ -36,5 +37,8 @@ const std::string& LogDataImageReadyMessage::getImageName() const {
return m_imageName;
}
const std::string& LogDataImageReadyMessage::getImagePath() const {
return m_imagePath;
}
}
......@@ -20,22 +20,25 @@
#define LOGDATAIMAGEREADYMESSAGE_H_
#include "NotificationMessage.h"
#include <common/base/CommonTypes.h>
namespace dataprovider {
class LogDataImageReadyMessage : public NotificationMessage {
public:
LogDataImageReadyMessage(const std::string& imageName);
LogDataImageReadyMessage(const std::string& imageName, const std::string& path);
virtual ~LogDataImageReadyMessage();
virtual Type getType() const;
const std::string& getImageName() const;
const std::string& getImagePath() const;
private:
std::string m_imageName;
std::string m_imagePath;
};
......
......@@ -109,7 +109,7 @@ void LogPublisher::notifyLogXML(const std::string& message) {
m_publisher->sendTwoBinaryParts(messageType.SerializeAsString(), logMessage.SerializeAsString());
}
void LogPublisher::notifyLogImageDataReady(const std::string& imageName) {
void LogPublisher::notifyLogImageDataReady(const std::string& imageName, const std::string& path) {
// Create the type.
notification::Message messageType;
......@@ -119,6 +119,7 @@ void LogPublisher::notifyLogImageDataReady(const std::string& imageName) {
notification::ImageDataReady logMessage;
logMessage.set_imagename(imageName);
logMessage.set_imagepath(path);
// Publish the message
m_publisher->sendTwoBinaryParts(messageType.SerializeAsString(), logMessage.SerializeAsString());
......
......@@ -54,7 +54,7 @@ public:
/**
* Notifies the subscribers of a log which has an image associated.
*/
void notifyLogImageDataReady(const std::string& imageName);
void notifyLogImageDataReady(const std::string& imageName, const std::string& path);
private:
std::unique_ptr<cameo::application::Publisher> m_publisher;
......
......@@ -164,8 +164,8 @@ void NotificationServer::log(common::LogType type, common::LogLevel level, const
_queue->put(new LogMessage(type, level, message, commandID, servantID));
}
void NotificationServer::imageDataReady(const std::string& imageName) {
_queue->put(new LogDataImageReadyMessage(imageName));
void NotificationServer::imageDataReady(const std::string& imageName, const std::string & path) {
_queue->put(new LogDataImageReadyMessage(imageName, path));
}
void NotificationServer::logXML(const std::string& message) {
......@@ -353,7 +353,7 @@ void NotificationServer::processMessage(SurveyXMLMessage* message) {
void NotificationServer::processMessage(LogDataImageReadyMessage* message) {
_logPublisher->notifyLogImageDataReady(message->getImageName());
_logPublisher->notifyLogImageDataReady(message->getImageName(), message->getImagePath());
}
void NotificationServer::processMessage(TokenStateChangedMessage* message) {
......
......@@ -170,7 +170,7 @@ public:
/**
* Data image ready log message
*/
void imageDataReady(const std::string& imageName);
void imageDataReady(const std::string& imageName, const std::string & path);
/**
* Logs the XML message.
......
......@@ -64,9 +64,9 @@ void LogAccessorDirectImpl::writeNLog(common::LogType type, common::LogLevel lev
NotificationServer::getInstance()->log(type, level, logMessage, commandID, servantID);
}
void LogAccessorDirectImpl::imageDataReadyLog(const std::string& imageName) {
void LogAccessorDirectImpl::imageDataReadyLog(const std::string& imageName, const std::string & path) {
//Only notify the NotificationServer, do not send it to the logHandler
NotificationServer::getInstance()->imageDataReady(imageName);
NotificationServer::getInstance()->imageDataReady(imageName, path);
}
......
......@@ -51,7 +51,7 @@ public:
void writeUserScanStartLog(common::LogLevel level, const std::string& name, const std::string& message);
void writeNLog(common::LogType type, common::LogLevel level, const std::list<common::LogElement>& lineElements, const std::string & imageName,unsigned long commandID, unsigned long servantID, bool writeLogFile, unsigned long requestID, command::LogCompletionHandlerDirectImpl* completionHandler);
void imageDataReadyLog(const std::string& imageName);
void imageDataReadyLog(const std::string& imageName, const std::string & path);
void writeServerLog(const std::string& processName, unsigned long threadID, bool error, const std::string& line);
};
......
......@@ -500,6 +500,16 @@ int32 PropertyAccessorDirectImpl::getArraySize(unsigned long databaseID, unsigne
return Database::getInstance(databaseID)->getIcsArraySize<float64>(propertyID);
} catch (Database::NoSuchPropertyException& e) {
throw NoSuchPropertyException();
} catch (Database::BadPropertyTypeException& e) {
// try with int32
//throw NoSuchPropertyException();
}
try {
return Database::getInstance(databaseID)->getIcsArraySize<int32>(propertyID);
} catch (Database::NoSuchPropertyException& e) {
throw NoSuchPropertyException();
} catch (Database::BadPropertyTypeException& e) {
throw NoSuchPropertyException();
}
}
......
......@@ -445,6 +445,7 @@ void AbstractParser::setProperty(ExperimentController* controller, const string&
controller->attach(CommandLineManager::getInstance());
string lvalue = value;
try {
if (propertyName.empty() == false) {
try {
uint32 servantID = dataprovider::Database::getInstance(0)->getServantID(controller->getName());
......@@ -456,7 +457,6 @@ void AbstractParser::setProperty(ExperimentController* controller, const string&
uint32 enumeratedLabelsSize = dataprovider::Database::getInstance(0)->getDynamicPropertySize(enumlabelsID);
// Search for the label.
for (int i = 0; i < enumeratedLabelsSize; ++i) {
uint32 labelPropertyID = dataprovider::Database::getInstance(0)->getDynamicPropertyIDAtIndex(enumlabelsID, i, false);
std::string label = dataprovider::Database::getInstance(0)->getValue<string>(labelPropertyID);
......
......@@ -125,8 +125,8 @@ void Log::log(Level const & level, std::string const & propertyName, std::string
/**
* Notify to NomadGUI (offscreen generator) that an image is ready to be rendered
*/
void Log::imageDataReadyLog(std::string const & imageName) {
command::LogHandler::getInstance()->imageDataReady(imageName);
void Log::imageDataReadyLog(std::string const & imageName, std::string const & path) {
command::LogHandler::getInstance()->imageDataReady(imageName, path);
}
std::string Log::getErrorMessage(std::list<LogElement> const & lineElements) {
......
......@@ -36,7 +36,7 @@ public:
void log(Level const & level, std::string const & message);
void log(std::string const & controllerType, std::string const & controllerName, Level const & level, std::list<common::LogElement> const & lineElements, std::string const & imageName);
void log(Level const & level, std::string const & propertyName, std::string const & propertyType, int32 numor, std::string const & imageName);
void imageDataReadyLog(std::string const & imageName);
void imageDataReadyLog(std::string const & imageName, std::string const & path);
private:
Log();
......