Commit 4d5d63a1 authored by legoc's avatar legoc

Integrated Xavier training's project by replacing protocol buffers encoding.

parent 3bf87b6a
/*
* 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 COMMON_PORTABLEBYTEARRAY_H_
#define COMMON_PORTABLEBYTEARRAY_H_
#include "BaseTypes.h"
#include "Endian.h"
namespace common {
enum EncodedType {ERROR_TYPE, NULL_TYPE, FLOAT64_TYPE, INT64_TYPE, INT32_TYPE, FLOAT32_TYPE};
// Specialized for supported types.
template<typename Type>
struct SerializeType;
template<>
struct SerializeType<double> {
static const EncodedType value = FLOAT64_TYPE;
};
template<>
struct SerializeType<float> {
static const EncodedType value = FLOAT32_TYPE;
};
template<>
struct SerializeType<int32_t> {
static const EncodedType value = INT32_TYPE;
};
template<>
struct SerializeType<int64_t> {
static const EncodedType value = INT64_TYPE;
};
struct BasePortableByteArray {
static inline int16 reverseInt16(int16 value) {
return (int32) ((value >> 8 & 0xff) |
(value >> 0 & 0xff) << 8);
}
static inline int32 reverseInt32(int32 value) {
return (int32) ((value >> 24 & 0xff) |
(value >> 16 & 0xff) << 8 |
(value >> 8 & 0xff) << 16 |
(value >> 0 & 0xff) << 24);
}
static inline int64 reverseInt64(int64 value) {
return (int64) ((value >> 56 & 0xff) |
(value >> 48 & 0xff) << 8 |
(value >> 40 & 0xff) << 16 |
(value >> 32 & 0xff) << 24 |
((int64)(value >> 24 & 0xff) << 0 |
(value >> 16 & 0xff) << 8 |
(value >> 8 & 0xff) << 16 |
(value & 0xff) << 24) << 32 );
}
/**
* Detect if we have to reverse bytes when we serialize.
*/
static bool needReverse(int endian) {
bool reverse;
if (((ENDIANNESS == LITTLE_ENDIAN_ORDER) && endian == 1) ||
((ENDIANNESS == BIG_ENDIAN_ORDER) && endian != 1)) {
reverse = false;
}
else {
reverse = true;
}
return reverse;
}
};
/**
* Class providing a portable byte array to speed up protocol buffers in the transfer of arrays.
*/
template<typename Type>
class PortableByteArray : public BasePortableByteArray {
public:
void encode(const Type * data, std::size_t size, std::string & encodedString, int outputEndian = LITTLE_ENDIAN_ORDER);
void encodeError(EncodedType type, std::string & encodedString, int outputEndian = LITTLE_ENDIAN_ORDER);
// static inline size_t byte_size(void * encoded_data) {
// // the size of the portable_byte_array is the size of the original array in bytes + 8
// if (type(encoded_data) == FLOAT64_TYPE || type(encoded_data) == INT64_TYPE) {
// return array_size(encoded_data)*8+8;
// } else {
// return array_size(encoded_data)*4+8;
// }
// }
//
// static inline size_t array_size(void * encoded_data) {
// size_t size;
// size = ((int32_t *)encoded_data)[1];
//
// // check if the data is not in the same endianness
// if (((int16_t *)encoded_data)[0] != 1) {
// size = reverseInt32(size);
// }
// return size;
// }
// static inline EncodedType type(void * encoded_data) {
// EncodedType type;
//
// type = (EncodedType) ((int16_t *)encoded_data)[1];
//
// // check if the data is not in the same endianness
// if (((int16_t *)encoded_data)[0] != 1) {
// type = (EncodedType)reverseInt16((int16_t)type);
// }
// return type;
// }
};
template<typename Type>
void PortableByteArray<Type>::encode(const Type * data, std::size_t size, std::string & encodedString, int outputEndian) {
EncodedType type = SerializeType<Type>::value;
int16_t byteSize = (type == FLOAT64_TYPE || type == INT64_TYPE) ? 8 : 4;
// Reserve the string.
encodedString.resize(size * byteSize + 8);
// Get the allocated array.
char const * array = encodedString.data();
// Check reverse.
if (needReverse(outputEndian)) {
// We have to serialize with reversing bytes.
((int16 *)array)[0] = reverseInt16(1);
((int16 *)array)[1] = reverseInt16(type);
((int32 *)array)[1] = reverseInt32(size);
if (type == FLOAT32_TYPE || type == INT32_TYPE) {
int32 tmp;
for (int i = 0; i < size; i++) {
tmp = reverseInt32((((int32 *)data)[i]));
// The real array start at byte 8.
memcpy(&((int32 *)array)[i + 2], &tmp, sizeof(int32));
}
}
else if (type == FLOAT64_TYPE || type == INT64_TYPE) {
int64 tmp;
for (int i = 0; i < size; i++) {
int64 tmp;
tmp = reverseInt64((((int64 *)data)[i]));
// The real array start at byte 8.
memcpy(&((int64 *)array)[i + 1], &tmp, sizeof(int64));
}
}
}
else {
((int16 *)array)[0] = 1;
((int16 *)array)[1] = type;
((int32 *)array)[1] = size;
memcpy((int8 *)array + 8, data, size * byteSize);
}
}
template<typename Type>
void PortableByteArray<Type>::encodeError(EncodedType type, std::string & encodedString, int outputEndian) {
// Reserve the string.
encodedString.resize(8);
// Get the allocated array.
char const * array = encodedString.data();
// Check reverse.
if (needReverse(outputEndian)) {
// We have to serialize with reversing bytes.
((int16 *)array)[0] = reverseInt16(1);
((int16 *)array)[1] = reverseInt16(type);
((int32 *)array)[1] = reverseInt32(0);
}
else {
((int16 *)array)[0] = 1;
((int16 *)array)[1] = type;
}
}
}
#endif
......@@ -326,58 +326,74 @@ void DatabaseResponder::processGetArraySize(const std::string & message, std::st
responseMessage.SerializeToString(&response);
}
//void DatabaseResponder::processGetInt32Array(const std::string & message, std::string & response) {
//
// database::GetValueRequest messageRequest;
// messageRequest.ParseFromString(message);
//
// common::Int32ArrayResponse responseMessage;
//
// try {
// vector<int32> values;
// m_propertyAccessor->getIcsInt32ArrayValue(messageRequest.databaseid(), messageRequest.propertyid(), values);
//
// vector<int32>::const_iterator end = values.end();
// for (vector<int32>::const_iterator v = values.begin(); v != end; ++v) {
// responseMessage.add_value(*v);
// }
// }
// catch (PropertyAccessorDirectImpl::NoSuchPropertyException& e) {
// responseMessage.set_error(common::Error::NO_SUCH_PROPERTY);
// }
// catch (PropertyAccessorDirectImpl::BadPropertyTypeException& e) {
// responseMessage.set_error(common::Error::BAD_PROPERTY_TYPE);
// }
//
// // Serialize the response.
// responseMessage.SerializeToString(&response);
//}
void DatabaseResponder::processGetInt32Array(const std::string & message, std::string & response) {
database::GetValueRequest messageRequest;
messageRequest.ParseFromString(message);
common::Int32ArrayResponse responseMessage;
try {
vector<int32> values;
m_propertyAccessor->getIcsInt32ArrayValue(messageRequest.databaseid(), messageRequest.propertyid(), values);
vector<int32>::const_iterator end = values.end();
for (vector<int32>::const_iterator v = values.begin(); v != end; ++v) {
responseMessage.add_value(*v);
}
}
catch (PropertyAccessorDirectImpl::NoSuchPropertyException& e) {
responseMessage.set_error(common::Error::NO_SUCH_PROPERTY);
}
catch (PropertyAccessorDirectImpl::BadPropertyTypeException& e) {
responseMessage.set_error(common::Error::BAD_PROPERTY_TYPE);
}
// Serialize the response.
responseMessage.SerializeToString(&response);
m_propertyAccessor->getEncodedInt32ArrayValue(messageRequest.databaseid(), messageRequest.propertyid(), response);
}
//void DatabaseResponder::processGetFloat64Array(const std::string & message, std::string & response) {
//
// database::GetValueRequest messageRequest;
// messageRequest.ParseFromString(message);
//
// common::Float64ArrayResponse responseMessage;
//
// try {
// vector<float64> values;
// m_propertyAccessor->getIcsFloat64ArrayValue(messageRequest.databaseid(), messageRequest.propertyid(), values);
//
// vector<float64>::const_iterator end = values.end();
// for (vector<float64>::const_iterator v = values.begin(); v != end; ++v) {
// responseMessage.add_value(*v);
// }
// }
// catch (PropertyAccessorDirectImpl::NoSuchPropertyException& e) {
// responseMessage.set_error(common::Error::NO_SUCH_PROPERTY);
// }
// catch (PropertyAccessorDirectImpl::BadPropertyTypeException& e) {
// responseMessage.set_error(common::Error::BAD_PROPERTY_TYPE);
// }
//
// // Serialize the response.
// responseMessage.SerializeToString(&response);
//}
void DatabaseResponder::processGetFloat64Array(const std::string & message, std::string & response) {
database::GetValueRequest messageRequest;
messageRequest.ParseFromString(message);
common::Float64ArrayResponse responseMessage;
try {
vector<float64> values;
m_propertyAccessor->getIcsFloat64ArrayValue(messageRequest.databaseid(), messageRequest.propertyid(), values);
vector<float64>::const_iterator end = values.end();
for (vector<float64>::const_iterator v = values.begin(); v != end; ++v) {
responseMessage.add_value(*v);
}
}
catch (PropertyAccessorDirectImpl::NoSuchPropertyException& e) {
responseMessage.set_error(common::Error::NO_SUCH_PROPERTY);
}
catch (PropertyAccessorDirectImpl::BadPropertyTypeException& e) {
responseMessage.set_error(common::Error::BAD_PROPERTY_TYPE);
}
// Serialize the response.
responseMessage.SerializeToString(&response);
m_propertyAccessor->getEncodedFloat64ArrayValue(messageRequest.databaseid(), messageRequest.propertyid(), response);
}
void DatabaseResponder::processSetInt32Array(const std::string & message, std::string & response) {
......
......@@ -690,6 +690,12 @@ public:
template<typename ValueType>
long getIcsArraySize(unsigned long propertyID);
/**
* Gets the encoded array.
*/
template<typename ValueType>
void getEncodedArrayValue(unsigned long propertyID, std::string & encodedString);
/**
* Gets the formatted value.
* throw NoSuchPropertyException
......
......@@ -20,6 +20,7 @@
#include <common/base/RealArray.h>
#include <common/base/PropertyType.h>
#include <common/base/TypeToString.h>
#include <common/base/PortableByteArray.h>
#include <dataprovider/dataelement/Command.h>
#include <dataprovider/dataelement/Controller.h>
#include <dataprovider/dataelement/Driver.h>
......@@ -299,6 +300,39 @@ long Database::getIcsArraySize(unsigned long propertyID) {
}
}
template<typename ValueType>
void Database::getEncodedArrayValue(unsigned long propertyID, std::string & encodedString) {
try {
unsigned long propertyKeyID = getPropertyKeyID(propertyID);
ScopedLock lock(_lockManager->lockPropertyForWriting(propertyKeyID, common::eol));
BaseProperty * property = getPropertyFromKeyID(propertyKeyID);
IcsArrayProperty<ValueType> * typedProperty = dynamic_cast<IcsArrayProperty<ValueType> *>(property);
if (typedProperty == 0) {
throw BadPropertyTypeException(propertyID, common::TypeToString<ValueType>::convert(), property->getType());
}
long size = typedProperty->getSizeValue();
ValueType * data = typedProperty->getPointerValue();
common::PortableByteArray<ValueType> portableByteArray;
portableByteArray.encode(data, size, encodedString, common::LITTLE_ENDIAN_ORDER);
} catch (NoSuchPropertyException const & e) {
common::PortableByteArray<ValueType> portableByteArray;
portableByteArray.encodeError(common::NULL_TYPE, encodedString, common::LITTLE_ENDIAN_ORDER);
} catch (BadPropertyTypeException const & e) {
common::PortableByteArray<ValueType> portableByteArray;
portableByteArray.encodeError(common::ERROR_TYPE, encodedString, common::LITTLE_ENDIAN_ORDER);
}
}
template<typename ValueType>
void Database::getArray(unsigned long propertyID, common::ArrayTransferService<ValueType>* arrayTransferService) {
......
......@@ -505,6 +505,16 @@ int32 PropertyAccessorDirectImpl::getArraySize(unsigned long databaseID, unsigne
}
}
void PropertyAccessorDirectImpl::getEncodedInt32ArrayValue(unsigned long databaseID, unsigned long propertyID, std::string & encodedString) {
Database::getInstance(databaseID)->getEncodedArrayValue<int32>(propertyID, encodedString);
}
void PropertyAccessorDirectImpl::getEncodedFloat64ArrayValue(unsigned long databaseID, unsigned long propertyID, std::string & encodedString) {
Database::getInstance(databaseID)->getEncodedArrayValue<float64>(propertyID, encodedString);
}
std::string PropertyAccessorDirectImpl::getFormattedValue(unsigned long databaseID, unsigned long propertyID) {
try {
return Database::getInstance(databaseID)->getFormattedValue(propertyID);
......
......@@ -194,6 +194,9 @@ public:
int32 getArraySize(unsigned long databaseID, unsigned long propertyID);
void getEncodedInt32ArrayValue(unsigned long databaseID, unsigned long propertyID, std::string & encodedString);
void getEncodedFloat64ArrayValue(unsigned long databaseID, unsigned long propertyID, std::string & encodedString);
std::string getFormattedValue(unsigned long databaseID, unsigned long propertyID);
void updateIcsProperty(unsigned long databaseID, unsigned long propertyID);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment