Merge with 7c40a236787c9744303bb30e6ee9cb2ec81c2215
This commit is contained in:
@@ -21,6 +21,7 @@ INC += introspectionRegistry.h
|
||||
INC += transportRegistry.h
|
||||
INC += namedLockPattern.h
|
||||
INC += referenceCountingLock.h
|
||||
INC += configuration.h
|
||||
LIBSRCS += hexDump.cpp
|
||||
LIBSRCS += wildcharMatcher.cpp
|
||||
LIBSRCS += inetAddressUtil.cpp
|
||||
@@ -29,6 +30,7 @@ LIBSRCS += introspectionRegistry.cpp
|
||||
LIBSRCS += transportRegistry.cpp
|
||||
LIBSRCS += namedLockPattern.cpp
|
||||
LIBSRCS += referenceCountingLock.cpp
|
||||
LIBSRCS += configuration.cpp
|
||||
|
||||
|
||||
SRC_DIRS += $(PVACCESS)/client
|
||||
|
||||
@@ -92,12 +92,12 @@ namespace epics {
|
||||
_sendThreadRunning(false) {
|
||||
|
||||
_socketBuffer = new ByteBuffer(max(MAX_TCP_RECV
|
||||
+MAX_ENSURE_DATA_BUFFER_SIZE, receiveBufferSize));
|
||||
+MAX_ENSURE_DATA_BUFFER_SIZE, receiveBufferSize), EPICS_ENDIAN_BIG);
|
||||
_socketBuffer->setPosition(_socketBuffer->getLimit());
|
||||
_startPosition = _socketBuffer->getPosition();
|
||||
|
||||
// allocate buffer
|
||||
_sendBuffer = new ByteBuffer(_socketBuffer->getSize());
|
||||
_sendBuffer = new ByteBuffer(_socketBuffer->getSize(), EPICS_ENDIAN_BIG);
|
||||
_maxPayloadSize = _sendBuffer->getSize()-2*CA_MESSAGE_HEADER_SIZE; // one for header, one for flow control
|
||||
|
||||
// get send buffer size
|
||||
|
||||
@@ -39,8 +39,8 @@ namespace epics {
|
||||
_closed(false), _responseHandler(responseHandler),
|
||||
_channel(channel), _sendAddresses(sendAddresses),
|
||||
_ignoredAddresses(NULL), _sendTo(NULL), _receiveBuffer(
|
||||
new ByteBuffer(MAX_UDP_RECV)), _sendBuffer(
|
||||
new ByteBuffer(MAX_UDP_RECV)),
|
||||
new ByteBuffer(MAX_UDP_RECV, EPICS_ENDIAN_BIG)), _sendBuffer(
|
||||
new ByteBuffer(MAX_UDP_RECV, EPICS_ENDIAN_BIG)),
|
||||
_lastMessageStartPosition(0), _readBuffer(
|
||||
new char[MAX_UDP_RECV]), _mutex(new Mutex()),
|
||||
_threadId(NULL) {
|
||||
|
||||
@@ -415,7 +415,7 @@ ChannelSearchManager::ChannelSearchManager(ClientContextImpl* context):
|
||||
_sequenceNumber(0)
|
||||
{
|
||||
// create and initialize send buffer
|
||||
_sendBuffer = new ByteBuffer(MAX_UDP_SEND);
|
||||
_sendBuffer = new ByteBuffer(MAX_UDP_SEND, EPICS_ENDIAN_BIG);
|
||||
initializeSendBuffer();
|
||||
|
||||
// TODO should be configurable
|
||||
@@ -435,7 +435,7 @@ ChannelSearchManager::ChannelSearchManager(ClientContextImpl* context):
|
||||
|
||||
// create timers
|
||||
_timers = new SearchTimer*[numberOfTimers];
|
||||
for(int i = 0; i < numberOfTimers; i++)
|
||||
for(int32 i = 0; i < numberOfTimers; i++)
|
||||
{
|
||||
_timers[i] = new SearchTimer(this, i, i > _beaconAnomalyTimerIndex, i != (numberOfTimers-1));
|
||||
}
|
||||
@@ -446,7 +446,7 @@ ChannelSearchManager::ChannelSearchManager(ClientContextImpl* context):
|
||||
|
||||
ChannelSearchManager::~ChannelSearchManager()
|
||||
{
|
||||
for(int i = 0; i < _numberOfTimers; i++)
|
||||
for(int32 i = 0; i < _numberOfTimers; i++)
|
||||
{
|
||||
if(_timers[i]) delete _timers[i];
|
||||
}
|
||||
@@ -550,7 +550,7 @@ void ChannelSearchManager::initializeSendBuffer()
|
||||
_sendBuffer->clear();
|
||||
_sendBuffer->putShort(CA_MAGIC_AND_VERSION);
|
||||
_sendBuffer->putByte((int8)0); // data
|
||||
_sendBuffer->putByte((int8)3); // beacon
|
||||
_sendBuffer->putByte((int8)3); // search
|
||||
_sendBuffer->putInt(sizeof(int32)/sizeof(int8) + 1); // "zero" payload
|
||||
_sendBuffer->putInt(_sequenceNumber);
|
||||
|
||||
|
||||
348
pvAccessApp/utils/configuration.cpp
Normal file
348
pvAccessApp/utils/configuration.cpp
Normal file
@@ -0,0 +1,348 @@
|
||||
/*
|
||||
* configuration.cpp
|
||||
*/
|
||||
|
||||
#include "configuration.h"
|
||||
|
||||
namespace epics { namespace pvAccess {
|
||||
|
||||
Properties::Properties()
|
||||
{
|
||||
_fileName = "";
|
||||
_infile = new ifstream();
|
||||
_infile->exceptions (ifstream::failbit | ifstream::badbit );
|
||||
_outfile = new ofstream();
|
||||
_outfile->exceptions (ofstream::failbit | ofstream::badbit );
|
||||
}
|
||||
|
||||
Properties::Properties(const string fileName)
|
||||
{
|
||||
_fileName = fileName;
|
||||
_infile = new ifstream();
|
||||
_infile->exceptions (ifstream::failbit | ifstream::badbit );
|
||||
_outfile = new ofstream();
|
||||
_outfile->exceptions (ofstream::failbit | ofstream::badbit );
|
||||
}
|
||||
|
||||
Properties::~Properties()
|
||||
{
|
||||
delete _infile;
|
||||
delete _outfile;
|
||||
//clear map
|
||||
for(_propertiesIterator = _properties.begin() ;
|
||||
_propertiesIterator != _properties.end();
|
||||
_propertiesIterator++ )
|
||||
{
|
||||
delete [] _propertiesIterator->first;
|
||||
delete [] _propertiesIterator->second;
|
||||
}
|
||||
_properties.clear();
|
||||
}
|
||||
|
||||
void Properties::setProperty(const string key,const string value)
|
||||
{
|
||||
string oldValue;
|
||||
_propertiesIterator = _properties.find(key.c_str());
|
||||
|
||||
if(_propertiesIterator != _properties.end()) //found in map
|
||||
{
|
||||
delete[] _propertiesIterator->first;
|
||||
delete[] _propertiesIterator->second;
|
||||
_properties.erase(_propertiesIterator);
|
||||
}
|
||||
|
||||
char* chKey = new char[key.length() + 1];
|
||||
strncpy(chKey,key.c_str(),key.length()+ 1);
|
||||
char* chValue = new char[value.length() + 1];
|
||||
strncpy(chValue,value.c_str(),value.length() + 1);
|
||||
_properties[chKey] = chValue;
|
||||
}
|
||||
|
||||
string Properties::getProperty(const string key)
|
||||
{
|
||||
_propertiesIterator = _properties.find(key.c_str());
|
||||
if(_propertiesIterator != _properties.end()) //found in map
|
||||
{
|
||||
return string(_propertiesIterator->second);
|
||||
}
|
||||
else
|
||||
{
|
||||
string errMsg = "Property not found in the map: " + key;
|
||||
throw BaseException(errMsg.c_str(), __FILE__, __LINE__);
|
||||
}
|
||||
}
|
||||
|
||||
string Properties::getProperty(const string key, const string defaultValue)
|
||||
{
|
||||
_propertiesIterator = _properties.find(key.c_str());
|
||||
if(_propertiesIterator != _properties.end()) //found in map
|
||||
{
|
||||
return string(_propertiesIterator->second);
|
||||
}
|
||||
|
||||
char* chKey = new char[key.length() + 1];
|
||||
strncpy(chKey,key.c_str(),key.length()+ 1);
|
||||
char* chValue = new char[defaultValue.length() + 1];
|
||||
strncpy(chValue,defaultValue.c_str(),defaultValue.length() + 1);
|
||||
_properties[chKey] = chValue;
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
void Properties::load()
|
||||
{
|
||||
for (_propertiesIterator = _properties.begin() ;
|
||||
_propertiesIterator != _properties.end();
|
||||
_propertiesIterator++ )
|
||||
{
|
||||
delete [] _propertiesIterator->first;
|
||||
delete [] _propertiesIterator->second;
|
||||
}
|
||||
_properties.clear();
|
||||
|
||||
try
|
||||
{
|
||||
_infile->open(_fileName.c_str(),ifstream::in);
|
||||
}
|
||||
catch (ifstream::failure& e) {
|
||||
string errMsg = "Error opening file: " + string(_fileName.c_str());
|
||||
throw BaseException(errMsg.c_str(), __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
string line;
|
||||
string property;
|
||||
string key;
|
||||
try
|
||||
{
|
||||
while(!_infile->eof())
|
||||
{
|
||||
line.clear();
|
||||
std::getline(*_infile,line);
|
||||
|
||||
//remove trailing spaces
|
||||
truncate(line);
|
||||
|
||||
//empty line
|
||||
if(line.length() == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// comment
|
||||
if(line.at(0) == '#')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//line is in format: propertyName=propertyValue
|
||||
size_t pos = line.find_first_of('=',0);
|
||||
if(pos == string::npos) //bad value (= not found)
|
||||
{
|
||||
string errMsg = "Bad property line found: " + line;
|
||||
throw BaseException(errMsg.c_str(), __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
key = line.substr(0,pos);
|
||||
truncate(key);
|
||||
property = line.substr(pos + 1,line.length());
|
||||
truncate(property);
|
||||
|
||||
char* chKey = new char[key.length() + 1];
|
||||
strncpy(chKey,key.c_str(),key.length()+ 1);
|
||||
char* chProperty = new char[property.length() +1];
|
||||
strncpy(chProperty,property.c_str(),property.length() + 1);
|
||||
_properties[chKey] = chProperty;
|
||||
}
|
||||
}
|
||||
catch (ifstream::failure& e)
|
||||
{
|
||||
_infile->close();
|
||||
if(_infile->eof())
|
||||
{
|
||||
return; //end of file
|
||||
}
|
||||
string errMsg = "Error reading file: " + _fileName;
|
||||
throw BaseException(errMsg.c_str(), __FILE__, __LINE__);
|
||||
}
|
||||
_infile->close();
|
||||
}
|
||||
|
||||
void Properties::load(const string fileName)
|
||||
{
|
||||
_fileName = fileName;
|
||||
load();
|
||||
}
|
||||
|
||||
void Properties::store()
|
||||
{
|
||||
try
|
||||
{
|
||||
_outfile->open(_fileName.c_str(),ifstream::trunc);
|
||||
}
|
||||
catch (ofstream::failure& e) {
|
||||
string errMsg = "Error opening file: " + string(_fileName.c_str());
|
||||
throw BaseException(errMsg.c_str(), __FILE__, __LINE__);
|
||||
}
|
||||
|
||||
|
||||
for (_propertiesIterator = _properties.begin() ;
|
||||
_propertiesIterator != _properties.end();
|
||||
_propertiesIterator++ )
|
||||
{
|
||||
try
|
||||
{
|
||||
string line = string(_propertiesIterator->first) + string("=") + string(_propertiesIterator->second) + string("\n");
|
||||
_outfile->write(line.c_str(),line.length());
|
||||
}
|
||||
catch (ofstream::failure& e) {
|
||||
_outfile->close();
|
||||
string errMsg = "Error writing to file: " + string(_fileName.c_str());
|
||||
throw BaseException(errMsg.c_str(), __FILE__, __LINE__);
|
||||
}
|
||||
}
|
||||
_outfile->close();
|
||||
}
|
||||
|
||||
void Properties::store(const string fileName)
|
||||
{
|
||||
_fileName = fileName;
|
||||
store();
|
||||
}
|
||||
|
||||
void Properties::list()
|
||||
{
|
||||
for (_propertiesIterator = _properties.begin() ;
|
||||
_propertiesIterator != _properties.end();
|
||||
_propertiesIterator++ )
|
||||
{
|
||||
cout << "Key:" << _propertiesIterator->first << ",Value: " << _propertiesIterator->second << endl;
|
||||
}
|
||||
}
|
||||
|
||||
SystemConfigurationImpl::SystemConfigurationImpl()
|
||||
{
|
||||
_envParam.name = new char[MAX_NAME_LENGHT];
|
||||
_envParam.pdflt = NULL;
|
||||
_ibuffer.exceptions ( ifstream::failbit | ifstream::badbit );
|
||||
_obuffer.exceptions ( ifstream::failbit | ifstream::badbit );
|
||||
_properties = new Properties();
|
||||
}
|
||||
|
||||
SystemConfigurationImpl::~SystemConfigurationImpl()
|
||||
{
|
||||
if(_envParam.name) delete[] _envParam.name;
|
||||
if(_properties) delete _properties;
|
||||
}
|
||||
|
||||
bool SystemConfigurationImpl::getPropertyAsBoolean(const string name, const bool defaultValue)
|
||||
{
|
||||
bool retval;
|
||||
_ibuffer.clear();
|
||||
_obuffer.clear();
|
||||
_obuffer.str("");
|
||||
_obuffer << defaultValue;
|
||||
_ibuffer.str(getPropertyAsString(name,_obuffer.str()));
|
||||
_ibuffer >> retval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
int32 SystemConfigurationImpl::getPropertyAsInteger(const string name, const int32 defaultValue)
|
||||
{
|
||||
int32 retval;
|
||||
_ibuffer.clear();
|
||||
_obuffer.clear();
|
||||
_obuffer.str("");
|
||||
_obuffer << defaultValue;
|
||||
_ibuffer.str(getPropertyAsString(name, _obuffer.str()));
|
||||
_ibuffer >> retval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
float SystemConfigurationImpl::getPropertyAsFloat(const string name, const float defaultValue)
|
||||
{
|
||||
float retval;
|
||||
_ibuffer.clear();
|
||||
_obuffer.clear();
|
||||
_obuffer.str("");
|
||||
_obuffer << defaultValue;
|
||||
_ibuffer.str(getPropertyAsString(name, _obuffer.str()));
|
||||
_ibuffer >> retval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
float SystemConfigurationImpl::getPropertyAsDouble(const string name, const double defaultValue)
|
||||
{
|
||||
float retval;
|
||||
_ibuffer.clear();
|
||||
_obuffer.clear();
|
||||
_obuffer.str("");
|
||||
_obuffer << defaultValue;
|
||||
_ibuffer.str(getPropertyAsString(name, _obuffer.str()));
|
||||
_ibuffer >> retval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
string SystemConfigurationImpl::getPropertyAsString(const string name, const string defaultValue)
|
||||
{
|
||||
strncpy(_envParam.name,name.c_str(),name.length() + 1);
|
||||
const char* val = envGetConfigParamPtr(&_envParam);
|
||||
if(val != NULL)
|
||||
{
|
||||
return _properties->getProperty(name, string(val));
|
||||
}
|
||||
return _properties->getProperty(name,defaultValue);
|
||||
}
|
||||
|
||||
ConfigurationProviderImpl::ConfigurationProviderImpl()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ConfigurationProviderImpl::~ConfigurationProviderImpl()
|
||||
{
|
||||
for(_configsIter = _configs.begin() ;
|
||||
_configsIter != _configs.end();
|
||||
_configsIter++ )
|
||||
{
|
||||
delete [] _configsIter->first;
|
||||
}
|
||||
_configs.clear();
|
||||
}
|
||||
|
||||
void ConfigurationProviderImpl::registerConfiguration(const string name, const Configuration* configuration)
|
||||
{
|
||||
Lock guard(&_mutex);
|
||||
_configsIter = _configs.find(name.c_str());
|
||||
if(_configsIter != _configs.end())
|
||||
{
|
||||
string msg = "configuration with name " + name + " already registered";
|
||||
throw BaseException(msg.c_str(), __FILE__, __LINE__);
|
||||
}
|
||||
char* chKey = new char[name.length() + 1];
|
||||
strncpy(chKey,name.c_str(),name.length()+ 1);
|
||||
_configs[chKey] = configuration;
|
||||
}
|
||||
|
||||
Configuration* ConfigurationProviderImpl::getConfiguration(const string name)
|
||||
{
|
||||
_configsIter = _configs.find(name.c_str());
|
||||
if(_configsIter != _configs.end())
|
||||
{
|
||||
return const_cast<Configuration*>(_configsIter->second);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ConfigurationProviderImpl* ConfigurationFactory::_configurationProvider = NULL;
|
||||
Mutex ConfigurationFactory::_conf_factory_mutex = Mutex();
|
||||
|
||||
ConfigurationProviderImpl* ConfigurationFactory::getProvider()
|
||||
{
|
||||
Lock guard(&_conf_factory_mutex);
|
||||
if(_configurationProvider == NULL)
|
||||
{
|
||||
_configurationProvider = new ConfigurationProviderImpl();
|
||||
}
|
||||
return _configurationProvider;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
216
pvAccessApp/utils/configuration.h
Normal file
216
pvAccessApp/utils/configuration.h
Normal file
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* configuration.h
|
||||
*/
|
||||
|
||||
#ifndef CONFIGURATION_H
|
||||
#define CONFIGURATION_H
|
||||
|
||||
#include "pvType.h"
|
||||
#include "noDefaultMethods.h"
|
||||
#include "lock.h"
|
||||
#include "epicsException.h"
|
||||
|
||||
#include "envDefs.h"
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <string.h>
|
||||
#include <map>
|
||||
|
||||
|
||||
using namespace epics::pvData;
|
||||
using namespace std;
|
||||
|
||||
namespace epics { namespace pvAccess {
|
||||
|
||||
#define MAX_NAME_LENGHT 300
|
||||
|
||||
struct conf_cmp_str
|
||||
{
|
||||
bool operator()(char const *a, char const *b)
|
||||
{
|
||||
return strcmp(a, b) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Properties
|
||||
*/
|
||||
class Properties
|
||||
{
|
||||
public:
|
||||
Properties();
|
||||
Properties(const string fileName);
|
||||
virtual ~Properties();
|
||||
|
||||
void setProperty(const string key,const string value);
|
||||
string getProperty(const string key);
|
||||
string getProperty(const string key, const string defaultValue);
|
||||
|
||||
void store();
|
||||
void store(const string fileName);
|
||||
void load();
|
||||
void load(const string fileName);
|
||||
void list();
|
||||
|
||||
private:
|
||||
map<const char*,const char* , conf_cmp_str> _properties;
|
||||
map<const char*,const char* , conf_cmp_str>::iterator _propertiesIterator;
|
||||
ifstream* _infile;
|
||||
ofstream* _outfile;
|
||||
string _fileName;
|
||||
|
||||
inline void truncate(string& str)
|
||||
{
|
||||
while(str.length() != 0 && (str.at(0) == ' ' || str.at(0) == '\t'))
|
||||
{
|
||||
str.erase(0,1);
|
||||
}
|
||||
while(str.length() != 0 && (str.at(str.length()-1) == ' ' || str.at(str.length()-1) == '\t'))
|
||||
{
|
||||
str.erase(str.length()-1,1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Configuration
|
||||
*/
|
||||
class Configuration : private NoDefaultMethods
|
||||
{
|
||||
public:
|
||||
/*
|
||||
* Get the environment variable specified by name or return default value
|
||||
* if it does not exist.
|
||||
*
|
||||
* @param name name of the environment variable to return.
|
||||
* @param defualtValue default value to return if environment variable does not exists.
|
||||
*
|
||||
* @return environment variable value as bool or default value if it does not exist.
|
||||
*/
|
||||
virtual bool getPropertyAsBoolean(const string name, const bool defaultValue) = 0;
|
||||
/*
|
||||
* Get the environment variable specified by name or return default value
|
||||
* if it does not exist.
|
||||
*
|
||||
* @param name name of the environment variable to return.
|
||||
* @param defualtValue default value to return if environment variable does not exists.
|
||||
*
|
||||
* @return environment variable value as int32 or default value if it does not exist.
|
||||
*/
|
||||
virtual int32 getPropertyAsInteger(const string name, const int32 defaultValue) = 0;
|
||||
/*
|
||||
* Get the environment variable specified by name or return default value
|
||||
* if it does not exist.
|
||||
*
|
||||
* @param name name of the environment variable to return.
|
||||
* @param defualtValue default value to return if environment variable does not exists.
|
||||
*
|
||||
* @return environment variable value as float or default value if it does not exist.
|
||||
*/
|
||||
virtual float getPropertyAsFloat(const string name, const float defaultValue) = 0;
|
||||
/*
|
||||
* Get the environment variable specified by name or return default value
|
||||
* if it does not exist.
|
||||
*
|
||||
* @param name name of the environment variable to return.
|
||||
* @param defualtValue default value to return if environment variable does not exists.
|
||||
*
|
||||
* @return environment variable value as double or default value if it does not exist.
|
||||
*/
|
||||
virtual float getPropertyAsDouble(const string name, const double defaultValue) = 0;
|
||||
/*
|
||||
* Get the environment variable specified by name or return default value
|
||||
* if it does not exist.
|
||||
*
|
||||
* @param name name of the environment variable to return.
|
||||
* @param defualtValue default value to return if environment variable does not exists.
|
||||
*
|
||||
* @return environment variable value as string or default value if it does not exist.
|
||||
*/
|
||||
virtual string getPropertyAsString(const string name, const string defaultValue) = 0;
|
||||
};
|
||||
|
||||
class SystemConfigurationImpl: public Configuration
|
||||
{
|
||||
public:
|
||||
SystemConfigurationImpl();
|
||||
virtual ~SystemConfigurationImpl();
|
||||
bool getPropertyAsBoolean(const string name, const bool defaultValue);
|
||||
int32 getPropertyAsInteger(const string name, const int32 defaultValue);
|
||||
float getPropertyAsFloat(const string name, const float defaultValue);
|
||||
float getPropertyAsDouble(const string name, const double defaultValue);
|
||||
string getPropertyAsString(const string name, string defaultValue);
|
||||
Properties* _properties;
|
||||
private:
|
||||
ENV_PARAM _envParam;
|
||||
istringstream _ibuffer;
|
||||
ostringstream _obuffer;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Configuration provider.
|
||||
*/
|
||||
class ConfigurationProvider : private NoDefaultMethods
|
||||
{
|
||||
public:
|
||||
/*
|
||||
* Return configuration specified by name.
|
||||
*
|
||||
* @param name name of the configuration to return.
|
||||
*
|
||||
* @return configuration specified by name or NULL if it does not exists.
|
||||
*/
|
||||
virtual Configuration* getConfiguration(const string name) = 0;
|
||||
/*
|
||||
* Register configuration.
|
||||
*
|
||||
* @param name name of the configuration to register.
|
||||
* @param configuration configuration to register.
|
||||
*/
|
||||
virtual void registerConfiguration(const string name, const Configuration* configuration) = 0;
|
||||
};
|
||||
|
||||
class ConfigurationProviderImpl: public ConfigurationProvider
|
||||
{
|
||||
public:
|
||||
ConfigurationProviderImpl();
|
||||
virtual ~ConfigurationProviderImpl();
|
||||
Configuration* getConfiguration(const string name);
|
||||
void registerConfiguration(const string name, const Configuration* configuration);
|
||||
private:
|
||||
Mutex _mutex;
|
||||
map<const char*,const Configuration*, conf_cmp_str> _configs;
|
||||
map<const char*,const Configuration*, conf_cmp_str>::iterator _configsIter;
|
||||
};
|
||||
|
||||
/**
|
||||
* Configuration factory.
|
||||
*/
|
||||
class ConfigurationFactory : private NoDefaultMethods
|
||||
{
|
||||
public:
|
||||
/*
|
||||
* Lazily creates configuration provider.
|
||||
*
|
||||
* @param name name of the configuration to register.
|
||||
* @param configuration configuration to register.
|
||||
*
|
||||
* @return configuration provider
|
||||
*/
|
||||
static ConfigurationProviderImpl* getProvider();
|
||||
|
||||
private:
|
||||
ConfigurationFactory() {};
|
||||
static ConfigurationProviderImpl* _configurationProvider;
|
||||
static Mutex _conf_factory_mutex;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /* CONFIGURATION_H */
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
/* testRemoteClientImpl.cpp */
|
||||
/* Author: Matej Sekoranja Date: 2011.1.1 */
|
||||
|
||||
@@ -13,6 +14,8 @@
|
||||
#include <caConstants.h>
|
||||
#include <timer.h>
|
||||
#include <blockingUDP.h>
|
||||
#include <blockingTCP.h>
|
||||
#include <namedLockPattern.h>
|
||||
#include <inetAddressUtil.h>
|
||||
#include <hexDump.h>
|
||||
#include <remote.h>
|
||||
@@ -428,7 +431,38 @@ typedef std::map<pvAccessID, ResponseRequest*> IOIDResponseRequestMap;
|
||||
|
||||
class ClientContextImpl;
|
||||
|
||||
class DebugResponse : public ResponseHandler, private epics::pvData::NoDefaultMethods {
|
||||
public:
|
||||
/**
|
||||
* @param context
|
||||
*/
|
||||
DebugResponse()
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~DebugResponse() {
|
||||
}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport* transport, int8 version, int8 command,
|
||||
int payloadSize, epics::pvData::ByteBuffer* payloadBuffer)
|
||||
{
|
||||
char ipAddrStr[48];
|
||||
std::cout << "ole" << std::endl;
|
||||
ipAddrToA(&responseFrom->ia, ipAddrStr, sizeof(ipAddrStr));
|
||||
std::cout << "ole2" << std::endl;
|
||||
|
||||
ostringstream prologue;
|
||||
prologue<<"Message [0x"<<hex<<(int)command<<", v0x"<<hex;
|
||||
prologue<<(int)version<<"] received from "<<ipAddrStr;
|
||||
std::cout << "ole / " << prologue.str() << std::endl;
|
||||
|
||||
hexDump(prologue.str(), "received",
|
||||
(const int8*)payloadBuffer->getArray(),
|
||||
payloadBuffer->getPosition(), payloadSize);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* CA response handler - main handler which dispatches responses to appripriate handlers.
|
||||
@@ -458,7 +492,7 @@ class ClientResponseHandler : public ResponseHandler, private epics::pvData::NoD
|
||||
* @param context
|
||||
*/
|
||||
ClientResponseHandler(ClientContextImpl* context) : m_context(context) {
|
||||
static ResponseHandler* badResponse = 0; //new BadResponse(context);
|
||||
static ResponseHandler* badResponse = new DebugResponse();
|
||||
static ResponseHandler* dataResponse = 0; //new DataResponseHandler(context);
|
||||
|
||||
#define HANDLER_COUNT 28
|
||||
@@ -497,6 +531,8 @@ class ClientResponseHandler : public ResponseHandler, private epics::pvData::NoD
|
||||
Transport* transport, int8 version, int8 command,
|
||||
int payloadSize, ByteBuffer* payloadBuffer)
|
||||
{
|
||||
int c = command+0;
|
||||
std::cout << "received " << c << std::endl;
|
||||
if (command < 0 || command >= HANDLER_COUNT)
|
||||
{
|
||||
// TODO context.getLogger().fine("Invalid (or unsupported) command: " + command + ".");
|
||||
@@ -509,12 +545,28 @@ class ClientResponseHandler : public ResponseHandler, private epics::pvData::NoD
|
||||
}
|
||||
|
||||
// delegate
|
||||
m_handlerTable[command]->handleResponse(responseFrom, transport, version, command, payloadSize, payloadBuffer);
|
||||
m_handlerTable[c]->handleResponse(responseFrom, transport, version, command, payloadSize, payloadBuffer);
|
||||
}
|
||||
};
|
||||
|
||||
class TCI : public TransportSendControl {
|
||||
public:
|
||||
virtual void flushSerializeBuffer() {
|
||||
}
|
||||
|
||||
virtual void ensureBuffer(int size) {
|
||||
}
|
||||
|
||||
virtual void startMessage(int8 command, int ensureCapacity){}
|
||||
virtual void endMessage() {}
|
||||
|
||||
virtual void flush(bool lastMessageCompleted) {}
|
||||
|
||||
virtual void setRecipient(const osiSockAddr& sendTo) {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#include <arrayFIFO.h>
|
||||
|
||||
@@ -548,19 +600,37 @@ class BaseSearchInstance : public SearchInstance
|
||||
virtual void removeAndUnsetListOwnership() {}
|
||||
virtual int getOwnerIndex() { return 0; }
|
||||
|
||||
virtual bool generateSearchRequestMessage(ByteBuffer* buffer, TransportSendControl* control) { return false; };
|
||||
virtual bool generateSearchRequestMessage(ByteBuffer* requestMessage, TransportSendControl* control)
|
||||
{
|
||||
const int DATA_COUNT_POSITION = CA_MESSAGE_HEADER_SIZE + sizeof(int32)/sizeof(int8) + 1;
|
||||
const int PAYLOAD_POSITION = sizeof(int16)/sizeof(int8) + 2;
|
||||
|
||||
int16 dataCount = requestMessage->getShort(DATA_COUNT_POSITION);
|
||||
|
||||
dataCount++;
|
||||
if(dataCount >= MAX_SEARCH_BATCH_COUNT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const string name = getChannelName();
|
||||
// not nice...
|
||||
const int addedPayloadSize = sizeof(int32)/sizeof(int8) + (1 + sizeof(int32)/sizeof(int8) + name.length());
|
||||
|
||||
if(requestMessage->getRemaining() < addedPayloadSize)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
requestMessage->putInt(getChannelID());
|
||||
SerializeHelper::serializeString(name, requestMessage, control);
|
||||
|
||||
requestMessage->putInt(PAYLOAD_POSITION, requestMessage->getPosition() - CA_MESSAGE_HEADER_SIZE);
|
||||
requestMessage->putShort(DATA_COUNT_POSITION, dataCount);
|
||||
return true;
|
||||
};
|
||||
};
|
||||
|
||||
class ChannelSearchManager { // tODO no default, etc.
|
||||
public:
|
||||
virtual void registerChannel(SearchInstance* channel) = 0;
|
||||
virtual void unregisterChannel(SearchInstance* channel) = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class BlockingTCPConnector;
|
||||
class NamedLockPattern;
|
||||
class BeaconHandlerImpl;
|
||||
|
||||
|
||||
@@ -591,9 +661,52 @@ enum ContextState {
|
||||
};
|
||||
|
||||
|
||||
class ClientContextImpl : public ClientContext
|
||||
class ClientContextImpl : public ClientContext,
|
||||
public Context /* TODO */
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class ChannelSearchManager { // tODO no default, etc.
|
||||
ClientContextImpl* _context;
|
||||
public:
|
||||
ChannelSearchManager(ClientContextImpl* context):
|
||||
_context(context) {
|
||||
}
|
||||
|
||||
|
||||
virtual void registerChannel(SearchInstance* channel) {
|
||||
|
||||
ByteBuffer sendBuffer(100, EPICS_ENDIAN_BIG);
|
||||
// new buffer
|
||||
sendBuffer.clear();
|
||||
sendBuffer.putShort(CA_MAGIC_AND_VERSION);
|
||||
sendBuffer.putByte((int8)0); // data
|
||||
sendBuffer.putByte((int8)3); // search
|
||||
sendBuffer.putInt(5); // "zero" payload
|
||||
|
||||
sendBuffer.putInt(0);
|
||||
|
||||
|
||||
sendBuffer.putByte((int8)0);
|
||||
sendBuffer.putShort((int16)0); // count
|
||||
|
||||
TCI tci;
|
||||
|
||||
channel->generateSearchRequestMessage(&sendBuffer, &tci);
|
||||
std::cout << "sending..." << sendBuffer.getPosition() << " bytes." << std::endl;
|
||||
_context->getSearchTransport()->send(&sendBuffer);
|
||||
|
||||
};
|
||||
virtual void unregisterChannel(SearchInstance* channel) {};
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of CAJ JCA <code>Channel</code>.
|
||||
* @author <a href="mailto:matej.sekoranjaATcosylab.com">Matej Sekoranja</a>
|
||||
@@ -1196,7 +1309,6 @@ class ChannelImpl :
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
||||
virtual void getField(GetFieldRequester *requester,epics::pvData::String subField)
|
||||
{
|
||||
requester->getDone(getStatusCreate()->getStatusOK(),m_pvStructure->getSubField(subField)->getField());
|
||||
@@ -1394,7 +1506,25 @@ class ChannelImpl :
|
||||
Lock lock(&m_contextMutex);
|
||||
return m_provider;
|
||||
}
|
||||
|
||||
|
||||
virtual Timer* getTimer()
|
||||
{
|
||||
Lock lock(&m_contextMutex);
|
||||
return m_timer;
|
||||
}
|
||||
|
||||
virtual TransportRegistry* getTransportRegistry()
|
||||
{
|
||||
Lock lock(&m_contextMutex);
|
||||
return m_transportRegistry;
|
||||
}
|
||||
|
||||
virtual BlockingUDPTransport* getSearchTransport()
|
||||
{
|
||||
Lock lock(&m_contextMutex);
|
||||
return m_searchTransport;
|
||||
}
|
||||
|
||||
virtual void initialize() {
|
||||
Lock lock(&m_contextMutex);
|
||||
|
||||
@@ -1484,36 +1614,92 @@ class ChannelImpl :
|
||||
void internalInitialize() {
|
||||
|
||||
m_timer = new Timer("pvAccess-client timer", lowPriority);
|
||||
/* TODO
|
||||
connector = new BlockingTCPConnector(this, receiveBufferSize, beaconPeriod);
|
||||
transportRegistry = new TransportRegistry();
|
||||
namedLocker = new NamedLockPattern();
|
||||
*/
|
||||
m_connector = new BlockingTCPConnector(this, m_receiveBufferSize, m_beaconPeriod);
|
||||
m_transportRegistry = new TransportRegistry();
|
||||
m_namedLocker = new NamedLockPattern<String>();
|
||||
|
||||
// setup UDP transport
|
||||
initializeUDPTransport();
|
||||
|
||||
// TODO
|
||||
// setup search manager
|
||||
//channelSearchManager = new ChannelSearchManager(this);
|
||||
m_channelSearchManager = new ChannelSearchManager(this);
|
||||
}
|
||||
|
||||
void initializeUDPTransport() {
|
||||
// TODO
|
||||
}
|
||||
/**
|
||||
* Initialized UDP transport (broadcast socket and repeater connection).
|
||||
*/
|
||||
void initializeUDPTransport() {
|
||||
// setup UDP transport
|
||||
try
|
||||
{
|
||||
// where to bind (listen) address
|
||||
osiSockAddr listenLocalAddress;
|
||||
listenLocalAddress.ia.sin_family = AF_INET;
|
||||
listenLocalAddress.ia.sin_port = htons(m_broadcastPort);
|
||||
listenLocalAddress.ia.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
// where to send address
|
||||
InetAddrVector* broadcastAddresses = getSocketAddressList("192.168.1.255", m_broadcastPort);
|
||||
// TODO getBroadcastAddresses(broadcastPort)
|
||||
|
||||
/// TOD !!!! addresses !!!!! by pointer and not copied
|
||||
|
||||
BlockingUDPConnector* broadcastConnector = new BlockingUDPConnector(true, broadcastAddresses, true);
|
||||
|
||||
m_broadcastTransport = (BlockingUDPTransport*)broadcastConnector->connect(
|
||||
0, new ClientResponseHandler(this),
|
||||
listenLocalAddress, CA_MINOR_PROTOCOL_REVISION,
|
||||
CA_DEFAULT_PRIORITY);
|
||||
|
||||
BlockingUDPConnector* searchConnector = new BlockingUDPConnector(false, broadcastAddresses, true);
|
||||
|
||||
// undefined address
|
||||
osiSockAddr undefinedAddress;
|
||||
undefinedAddress.ia.sin_family = AF_INET;
|
||||
undefinedAddress.ia.sin_port = htons(0);
|
||||
undefinedAddress.ia.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
m_searchTransport = (BlockingUDPTransport*)searchConnector->connect(
|
||||
0, new ClientResponseHandler(this),
|
||||
undefinedAddress, CA_MINOR_PROTOCOL_REVISION,
|
||||
CA_DEFAULT_PRIORITY);
|
||||
|
||||
// set broadcast address list
|
||||
if (!m_addressList.empty())
|
||||
{
|
||||
// if auto is true, add it to specified list
|
||||
InetAddrVector* appendList = 0;
|
||||
if (m_autoAddressList)
|
||||
appendList = m_broadcastTransport->getSendAddresses();
|
||||
|
||||
InetAddrVector* list = getSocketAddressList(m_addressList, m_broadcastPort, appendList);
|
||||
// TODO delete !!!!
|
||||
if (list && list->size()) {
|
||||
m_broadcastTransport->setBroadcastAddresses(list);
|
||||
m_searchTransport->setBroadcastAddresses(list);
|
||||
}
|
||||
}
|
||||
|
||||
m_broadcastTransport->start();
|
||||
m_searchTransport->start();
|
||||
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
void internalDestroy() {
|
||||
|
||||
// stop searching
|
||||
/* TODO
|
||||
if (m_channelSearchManager)
|
||||
channelSearchManager->destroy();
|
||||
*/
|
||||
delete m_channelSearchManager; //->destroy();
|
||||
|
||||
// stop timer
|
||||
if (m_timer)
|
||||
delete m_timer;
|
||||
|
||||
|
||||
//
|
||||
// cleanup
|
||||
//
|
||||
@@ -1521,13 +1707,15 @@ class ChannelImpl :
|
||||
// this will also close all CA transports
|
||||
destroyAllChannels();
|
||||
|
||||
// close broadcast transport
|
||||
/* TODO
|
||||
// TODO destroy !!!
|
||||
if (m_broadcastTransport)
|
||||
m_broadcastTransport->destroy(true);
|
||||
if (m_searchTransport != null)
|
||||
m_searchTransport->destroy(true);
|
||||
*/
|
||||
delete m_broadcastTransport; //->destroy(true);
|
||||
if (m_searchTransport)
|
||||
delete m_searchTransport; //->destroy(true);
|
||||
|
||||
if (m_namedLocker) delete m_namedLocker;
|
||||
if (m_transportRegistry) delete m_transportRegistry;
|
||||
if (m_connector) delete m_connector;
|
||||
|
||||
m_provider->destroy();
|
||||
delete m_version;
|
||||
@@ -1779,7 +1967,7 @@ class ChannelImpl :
|
||||
/**
|
||||
* Context instance.
|
||||
*/
|
||||
NamedLockPattern* m_namedLocker;
|
||||
NamedLockPattern<String>* m_namedLocker;
|
||||
|
||||
/**
|
||||
* Context instance.
|
||||
@@ -2077,13 +2265,17 @@ int main(int argc,char *argv[])
|
||||
{
|
||||
ClientContextImpl* context = new ClientContextImpl();
|
||||
context->printInfo();
|
||||
|
||||
context->initialize();
|
||||
context->printInfo();
|
||||
|
||||
epicsThreadSleep ( 1.0 );
|
||||
|
||||
ChannelFindRequesterImpl findRequester;
|
||||
context->getProvider()->channelFind("something", &findRequester);
|
||||
//ChannelFindRequesterImpl findRequester;
|
||||
//context->getProvider()->channelFind("something", &findRequester);
|
||||
|
||||
ChannelRequesterImpl channelRequester;
|
||||
Channel* channel = context->getProvider()->createChannel("test", &channelRequester);
|
||||
Channel* channel = context->getProvider()->createChannel("structureArrayTest", &channelRequester);
|
||||
channel->printInfo();
|
||||
/*
|
||||
GetFieldRequesterImpl getFieldRequesterImpl;
|
||||
@@ -2122,6 +2314,7 @@ int main(int argc,char *argv[])
|
||||
|
||||
monitor->destroy();
|
||||
*/
|
||||
epicsThreadSleep ( 10.0 );
|
||||
channel->destroy();
|
||||
|
||||
context->destroy();
|
||||
|
||||
@@ -38,6 +38,10 @@ PROD_HOST += namedLockPatternTest
|
||||
namedLockPatternTest_SRCS += namedLockPatternTest.cpp
|
||||
namedLockPatternTest_LIBS += pvAccess Com pvData
|
||||
|
||||
PROD_HOST += configurationTest
|
||||
configurationTest_SRCS += configurationTest.cpp
|
||||
configurationTest_LIBS += pvAccess Com pvData
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
#----------------------------------------
|
||||
# ADD RULES AFTER THIS LINE
|
||||
|
||||
75
testApp/utils/configurationTest.cpp
Normal file
75
testApp/utils/configurationTest.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* configurationTest.cpp
|
||||
*
|
||||
*/
|
||||
|
||||
#include "configuration.h"
|
||||
#include "showConstructDestruct.h"
|
||||
|
||||
#include <epicsAssert.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <stdlib.h>
|
||||
|
||||
using namespace epics::pvAccess;
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
SystemConfigurationImpl* configuration = new SystemConfigurationImpl();
|
||||
bool boolProperty = configuration->getPropertyAsBoolean("boolProperty", true);
|
||||
assert(boolProperty == true);
|
||||
|
||||
int32 intProperty = configuration->getPropertyAsInteger("intProperty", 1);
|
||||
assert(intProperty == 1);
|
||||
|
||||
float floatProperty = configuration->getPropertyAsFloat("floatProperty", 3);
|
||||
assert(floatProperty == 3);
|
||||
|
||||
double doubleProperty = configuration->getPropertyAsDouble("doubleProperty", -3);
|
||||
assert(doubleProperty == -3);
|
||||
|
||||
string stringProperty = configuration->getPropertyAsString("stringProperty", "string");
|
||||
assert(stringProperty == string("string"));
|
||||
|
||||
ConfigurationProviderImpl* configProvider = ConfigurationFactory::getProvider();
|
||||
configProvider->registerConfiguration("conf1",static_cast<Configuration*>(configuration));
|
||||
|
||||
SystemConfigurationImpl* configurationOut = static_cast<SystemConfigurationImpl*>(configProvider->getConfiguration("conf1"));
|
||||
assert(configurationOut == configuration);
|
||||
|
||||
intProperty = configuration->getPropertyAsInteger("intProperty", 2);
|
||||
assert(intProperty == 1);
|
||||
|
||||
floatProperty = configuration->getPropertyAsFloat("floatProperty", 4);
|
||||
assert(floatProperty == 3);
|
||||
|
||||
doubleProperty = configuration->getPropertyAsDouble("doubleProperty", -4);
|
||||
assert(doubleProperty == -3);
|
||||
|
||||
stringProperty = configuration->getPropertyAsString("stringProperty", "string1");
|
||||
assert(stringProperty == string("string"));
|
||||
|
||||
setenv("boolProperty1", "1", 1);
|
||||
boolProperty = configuration->getPropertyAsInteger("boolProperty1", 0);
|
||||
assert(boolProperty == true);
|
||||
|
||||
setenv("intProperty1", "45", 1);
|
||||
intProperty = configuration->getPropertyAsInteger("intProperty1", 2);
|
||||
assert(intProperty == 45);
|
||||
|
||||
setenv("floatProperty1", "22", 1);
|
||||
floatProperty = configuration->getPropertyAsFloat("floatProperty1", 3);
|
||||
assert(floatProperty == 22);
|
||||
|
||||
setenv("dobuleProperty1", "42", 1);
|
||||
doubleProperty = configuration->getPropertyAsDouble("dobuleProperty1", -3);
|
||||
assert(doubleProperty == 42);
|
||||
|
||||
if(configuration) delete configuration;
|
||||
getShowConstructDestruct()->constuctDestructTotals(stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user