Merge with 0e964e46b15e05887fa9ce6e486681bf0a691654

This commit is contained in:
miha_vitorovic
2010-12-29 15:02:44 +01:00
9 changed files with 408 additions and 89 deletions

View File

@@ -1,10 +0,0 @@
QtC-pvAccess.creator.user
syntax: glob
O.Common
O.linux-x86
syntax: regexp
^bin
^include

View File

@@ -18,11 +18,13 @@ INC += growingCircularBuffer.h
INC += inetAddressUtil.h
INC += logger.h
INC += introspectionRegistry.h
INC += transportRegistry.h
LIBSRCS += hexDump.cpp
LIBSRCS += wildcharMatcher.cpp
LIBSRCS += inetAddressUtil.cpp
LIBSRCS += logger.cpp
LIBSRCS += introspectionRegistry.cpp
LIBSRCS += transportRegistry.cpp
SRC_DIRS += $(PVACCESS)/client

View File

@@ -83,7 +83,6 @@ short IntrospectionRegistry::registerIntrospectionInterface(FieldConstPtr field,
_registryIter = _registry.find(key);
if(_registryIter != _registry.end())
{
cout << "deleting 2" << endl;
_registryIter->second->decReferenceCount();
}
@@ -111,7 +110,7 @@ bool IntrospectionRegistry::registryContainsValue(FieldConstPtr field, short& ke
{
for(_registryRIter = _registry.rbegin(); _registryRIter != _registry.rend(); _registryRIter++)
{
if(compareFields(field,_registryRIter->second))
if((*field) == (*_registryRIter->second))
{
key = _registryRIter->first;
return true;
@@ -120,57 +119,6 @@ bool IntrospectionRegistry::registryContainsValue(FieldConstPtr field, short& ke
return false;
}
bool IntrospectionRegistry::compareFields(FieldConstPtr field1, FieldConstPtr field2)
{
if(field1->getFieldName() != field2->getFieldName())
{
return false;
}
else
{
Type typ1 = field1->getType();
Type typ2 = field2->getType();
if(typ1 != typ2)
{
return false;
}
switch (typ1)
{
case epics::pvData::scalar:
{
if(static_cast<ScalarConstPtr>(field1)->getScalarType() == static_cast<ScalarConstPtr>(field1)->getScalarType())
{
return true;
}
break;
}
case epics::pvData::scalarArray:
{
if(static_cast<ScalarArrayConstPtr>(field1)->getElementType() == static_cast<ScalarArrayConstPtr>(field1)->getElementType())
{
return true;
}
break;
}
case epics::pvData::structure:
{
return true;
break;
}
case epics::pvData::structureArray:
{
if(static_cast<StructureArrayConstPtr>(field1)->getStructure()->getFieldName() == static_cast<StructureArrayConstPtr>(field1)->getStructure()->getFieldName())
{
return true;
}
break;
}
}
return false;
}
}
void IntrospectionRegistry::serialize(FieldConstPtr field, ByteBuffer* buffer, SerializableControl* control)
{
checkBufferAndSerializeControl(buffer, control);
@@ -373,8 +321,10 @@ StructureConstPtr IntrospectionRegistry::deserializeStructureField(ByteBuffer* b
fields[i] = deserialize(buffer, control, registry);
}
}
//TODO stucture constructor created new fields instead of taking this ones
return _fieldCreate->createStructure(structureFieldName, size, fields);
StructureConstPtr structure = _fieldCreate->createStructure(structureFieldName, size, fields);
delete [] fields;
return structure;
}
void IntrospectionRegistry::serializeStructure(ByteBuffer* buffer, SerializableControl* control, PVStructurePtr pvStructure)

View File

@@ -62,6 +62,9 @@ typedef std::map<const short,const Field*> registryMap_t;
/**
* Registers introspection interface and get it's ID. Always OUTGOING.
* If it is already registered only preassigned ID is returned.
*
* TODO !!!!!!this can get very slow in large maps. We need to change this !!!!!!
*
* @param field introspection interface to register
*
* @return id of given introspection interface
@@ -181,7 +184,7 @@ typedef std::map<const short,const Field*> registryMap_t;
/**
* Deserialize PVRequest.
* @param payloadBuffer data buffer.
* @param control
* @param control serialization control.
*
* @return deserialized PVRequest, can be <code>null</code>.
*/
@@ -189,24 +192,28 @@ typedef std::map<const short,const Field*> registryMap_t;
/**
* Deserialize Structure and create PVStructure instance.
*
* @param payloadBuffer data buffer.
* @param control serialization control.
*
* @return PVStructure instance, can be <code>null</code>.
*/
PVStructurePtr deserializeStructureAndCreatePVStructure(ByteBuffer* payloadBuffer, DeserializableControl* control);
/**
* Serialize status.
* TODO optimize duplicates
*
* @param buffer data buffer.
* @param control serializaiton control instance.
* @param control serialization control.
* @param status status to serialize.
*/
void serializeStatus(ByteBuffer* buffer, SerializableControl* control, Status* status);
/**
* Serialize status.
* TODO optimize duplicates
* Deserialize status.
*
* @param buffer data buffer.
* @param control serialization control.
*/
Status* deserializeStatus(ByteBuffer* buffer, DeserializableControl* control);
@@ -234,7 +241,6 @@ typedef std::map<const short,const Field*> registryMap_t;
static FieldCreate* _fieldCreate;
bool registryContainsValue(FieldConstPtr field, short& key);
bool compareFields(FieldConstPtr field1, FieldConstPtr field2);
static void checkBufferAndSerializeControl(ByteBuffer* buffer, SerializableControl* control);
static void checkBufferAndDeserializeControl(ByteBuffer* buffer, DeserializableControl* control);
};

View File

@@ -0,0 +1,184 @@
/*
* transportRegistry.cpp
*/
#include "transportRegistry.h"
namespace epics { namespace pvAccess {
TransportRegistry::TransportRegistry(): _mutex(Mutex())
{
}
TransportRegistry::~TransportRegistry()
{
clear();
}
void TransportRegistry::put(Transport* transport)
{
// TODO support type
if(transport == NULL)
{
throw EpicsException("null transport provided");
}
Lock guard(&_mutex);
//const string type = transport.getType();
const int16 priority = transport->getPriority();
const osiSockAddr* address = transport->getRemoteAddress();
const int32 intAddress = ipv4AddressToInt(*address);
_transportsIter = _transports.find(intAddress);
prioritiesMap_t* priorities;
if(_transportsIter == _transports.end())
{
priorities = new prioritiesMap_t();
_transports[intAddress] = priorities;
}
else
{
priorities = _transportsIter->second;
}
(*priorities)[priority] = transport;
_allTransports.push_back(transport);
}
Transport* TransportRegistry::get(const string type, const osiSockAddr* address, const int16 priority)
{
// TODO support type
if(address == NULL)
{
throw EpicsException("null address provided");
}
Lock guard(&_mutex);
const int32 intAddress = ipv4AddressToInt(*address);
_transportsIter = _transports.find(intAddress);
if(_transportsIter != _transports.end())
{
prioritiesMap_t* priorities = _transportsIter->second;
_prioritiesIter = priorities->find(priority);
if(_prioritiesIter != priorities->end())
{
return _prioritiesIter->second;
}
}
return NULL;
}
Transport** TransportRegistry::get(const string type, const osiSockAddr* address, int32& size)
{
// TODO support type
if(address == NULL)
{
throw EpicsException("null address provided");
}
Lock guard(&_mutex);
const int32 intAddress = ipv4AddressToInt(*address);
_transportsIter = _transports.find(intAddress);
if(_transportsIter != _transports.end())
{
prioritiesMap_t* priorities = _transportsIter->second;
size = priorities->size();
Transport** transportArray = new Transport*[size];
int i = 0;
for(_prioritiesIter = priorities->begin(); _prioritiesIter != priorities->end(); _prioritiesIter++, i++)
{
transportArray[i] = _prioritiesIter->second;
}
return transportArray;
}
return NULL;
}
Transport* TransportRegistry::remove(Transport* transport)
{
// TODO support type
if(transport == NULL)
{
throw EpicsException("null transport provided");
}
Lock guard(&_mutex);
const int16 priority = transport->getPriority();
const osiSockAddr* address = transport->getRemoteAddress();
const int32 intAddress = ipv4AddressToInt(*address);
Transport* retTransport = NULL;
_transportsIter = _transports.find(intAddress);
if(_transportsIter != _transports.end())
{
prioritiesMap_t* priorities = _transportsIter->second;
_prioritiesIter = priorities->find(priority);
if(_prioritiesIter != priorities->end())
{
for(_allTransportsIter = _allTransports.begin(); _allTransportsIter != _allTransports.end(); _allTransportsIter++)
{
if(_prioritiesIter->second == *_allTransportsIter)
{
retTransport = _prioritiesIter->second;
_allTransports.erase(_allTransportsIter);
break;
}
}
priorities->erase(_prioritiesIter);
if(priorities->size() == 0)
{
_transports.erase(_transportsIter);
delete priorities;
}
}
}
return retTransport;
}
void TransportRegistry::clear()
{
Lock guard(&_mutex);
for(_transportsIter = _transports.begin(); _transportsIter != _transports.end(); _transportsIter++)
{
delete _transportsIter->second;
}
_transports.clear();
_allTransports.clear();
}
int TransportRegistry::numberOfActiveTransports()
{
Lock guard(&_mutex);
return (int32)_allTransports.size();
}
Transport** TransportRegistry::toArray(const string type, int32& size)
{
// TODO support type
Lock guard(&_mutex);
size = _allTransports.size();
Transport** transportArray = new Transport*[size];
int i = 0;
for(_allTransportsIter = _allTransports.begin(); _allTransportsIter != _allTransports.end(); _allTransportsIter++, i++)
{
transportArray[i] = *_allTransportsIter;
}
return transportArray;
}
Transport** TransportRegistry::toArray(int32& size)
{
Lock guard(&_mutex);
size = _allTransports.size();
Transport** transportArray = new Transport*[size];
int i = 0;
for(_allTransportsIter = _allTransports.begin(); _allTransportsIter != _allTransports.end(); _allTransportsIter++, i++)
{
transportArray[i] = *_allTransportsIter;
}
return transportArray;
}
}}

View File

@@ -0,0 +1,57 @@
/*
* transportRegistry.h
*/
#ifndef TRANSPORTREGISTRY_H
#define TRANSPORTREGISTRY_H
#include <map>
#include <vector>
#include <iostream>
#include <epicsMutex.h>
#include <osiSock.h>
#include "lock.h"
#include "pvType.h"
#include "epicsException.h"
#include "inetAddressUtil.h"
#include "remote.h"
using namespace epics::pvData;
using namespace std;
namespace epics { namespace pvAccess {
typedef std::map<const int16,Transport*> prioritiesMap_t;
typedef std::map<const int32,prioritiesMap_t*> transportsMap_t;
typedef std::vector<Transport*> allTransports_t;
class TransportRegistry {
public:
TransportRegistry();
virtual ~TransportRegistry();
void put(Transport* transport);
Transport* get(const string type, const osiSockAddr* address, const int16 priority);
Transport** get(const string type, const osiSockAddr* address, int32& size);
Transport* remove(Transport* transport);
void clear();
int32 numberOfActiveTransports();
Transport** toArray(const string type, int32& size);
Transport** toArray(int32& size);
private:
transportsMap_t _transports;
transportsMap_t::iterator _transportsIter;
prioritiesMap_t::iterator _prioritiesIter;
allTransports_t _allTransports;
allTransports_t::iterator _allTransportsIter;
Mutex _mutex;
};
}}
#endif /* INTROSPECTIONREGISTRY_H */

View File

@@ -30,6 +30,10 @@ PROD_HOST += introspectionRegisterTest
introspectionRegisterTest_SRCS += introspectionRegistryTest.cpp
introspectionRegisterTest_LIBS += pvAccess Com pvData
PROD_HOST += transportRegisterTest
transportRegisterTest_SRCS += transportRegistryTest.cpp
transportRegisterTest_LIBS += pvAccess Com pvData
include $(TOP)/configure/RULES
#----------------------------------------
# ADD RULES AFTER THIS LINE

View File

@@ -91,18 +91,12 @@ StructureConstPtr getStructure(string name)
FieldConstPtr powerSupply[3];
powerSupply[0] = standardField->scalar(
String("voltage"),pvDouble,properties);
PVField *pvField = pvDataCreate->createPVField(0,powerSupply[0]);
pvFieldArray.push_back(pvField);
powerSupply[1] = standardField->scalar(
String("power"),pvDouble,properties);
pvField = pvDataCreate->createPVField(0,powerSupply[1]);
pvFieldArray.push_back(pvField);
powerSupply[2] = standardField->scalar(
String("current"),pvDouble,properties);
pvField = pvDataCreate->createPVField(0,powerSupply[2]);
pvFieldArray.push_back(pvField);
StructureConstPtr structure = standardField->structure(name,3,powerSupply);
pvField = pvDataCreate->createPVField(0,structure);
PVField * pvField = pvDataCreate->createPVField(0,structure);
pvFieldArray.push_back(pvField);
return structure;
}
@@ -113,19 +107,13 @@ StructureArrayConstPtr getStructureArray(string name1, string name2)
FieldConstPtr powerSupply[3];
powerSupply[0] = standardField->scalar(
String("voltage"),pvDouble,properties);
PVField *pvField = pvDataCreate->createPVField(0,powerSupply[0]);
pvFieldArray.push_back(pvField);
powerSupply[1] = standardField->scalar(
String("power"),pvDouble,properties);
pvField = pvDataCreate->createPVField(0,powerSupply[1]);
pvFieldArray.push_back(pvField);
powerSupply[2] = standardField->scalar(
String("current"),pvDouble,properties);
pvField = pvDataCreate->createPVField(0,powerSupply[2]);
pvFieldArray.push_back(pvField);
StructureConstPtr structure = standardField->structure(name1,3,powerSupply);
StructureArrayConstPtr structureArray = standardField->structureArray(name2,structure);
pvField = pvDataCreate->createPVField(0,structureArray);
PVField *pvField = pvDataCreate->createPVField(0,structureArray);
pvFieldArray.push_back(pvField);
return structureArray;
}
@@ -283,7 +271,7 @@ void testSerialize()
stringstream ss;
string name1,name2,name3,name4;
for(int i = 0, j = 0; i < 1 ; i++, j++)
for(int i = 0, j = 0; i < 10 ; i++, j++)
{
name1.clear();
name2.clear();
@@ -334,7 +322,7 @@ void testSerialize()
testSerializeCommon(static_cast<FieldConstPtr>(getStructureArray(name1,name2)),static_cast<FieldConstPtr>(getStructureArray(name3,name4)));
}
serverRegistry->printKeysAndValues("server");
//serverRegistry->printKeysAndValues("server");
//clientRegistry->printKeysAndValues("client");
}
@@ -425,8 +413,6 @@ void testSerializeStatus()
}
int main(int argc, char *argv[]) {
//TODO something is wrong with freeing structure and structure array, should be checked.
pvDataCreate = getPVDataCreate();
statusCreate = getStatusCreate();
fieldCreate = getFieldCreate();
@@ -462,6 +448,8 @@ int main(int argc, char *argv[]) {
if(registry) delete registry;
if(clientRegistry) delete clientRegistry;
if(serverRegistry) delete serverRegistry;
getShowConstructDestruct()->constuctDestructTotals(stdout);
cout << "DONE" << endl;
return 0;
}

View File

@@ -0,0 +1,138 @@
/*
* transportRegistryTest.cpp
*
*/
#include "transportRegistry.h"
#include "showConstructDestruct.h"
#include <epicsAssert.h>
#include <iostream>
#include <string>
namespace epics {
namespace pvAccess {
class TestTransport : public Transport{
public:
TestTransport(string type, int16 priority, osiSockAddr* address): _type(type), _priority(priority), _address(address) {/*cout << "Transport::Transport" << endl;*/};
~TestTransport(){/*cout << "Transport::~Transport" << endl;*/};
virtual const string getType() const {return _type;};
virtual int16 getPriority() const { return _priority;};
virtual const osiSockAddr* getRemoteAddress() const {return _address;};
virtual int8 getMajorRevision() const {return 0;};
virtual int8 getMinorRevision() const {return 0;};
virtual int getReceiveBufferSize() const {return 0;};
virtual int getSocketReceiveBufferSize() const {return 0;};
virtual void setRemoteMinorRevision(int8 minor) {};
virtual void setRemoteTransportReceiveBufferSize(
int receiveBufferSize) {};
virtual void setRemoteTransportSocketReceiveBufferSize(
int socketReceiveBufferSize){};
virtual void aliveNotification(){};
virtual void changedTransport(){};
virtual void close(bool force){};
virtual bool isClosed() const{return false;};
virtual bool isVerified() const{return false;};
virtual void verified(){};
virtual void enqueueSendRequest(TransportSender* sender){};
virtual void ensureData(int) {};
private:
string _type;
int16 _priority;
osiSockAddr* _address;
};
}
}
using namespace epics::pvAccess;
using namespace std;
static TransportRegistry* registry;
static const int16 address_max = 10;
static const int16 priority_max = 100;
int main(int argc, char *argv[])
{
registry = new TransportRegistry();
int32 size;
TestTransport** transportArrayOut;
TestTransport** transportArrayIn = new TestTransport*[address_max * priority_max];
osiSockAddr** addrArray = new osiSockAddr*[address_max];
//address
for(int32 i = 0; i < address_max; i++)
{
osiSockAddr* addr = new osiSockAddr;
addrArray[i] = addr;
addr->ia.sin_addr.s_addr = i;
//priority
for(int16 j = 0; j < priority_max; j++)
{
TestTransport* transportIn = new TestTransport("tcp", j, addr);
transportArrayIn[i * priority_max + j] = transportIn;
registry->put(static_cast<Transport*>(transportIn));
TestTransport* transportOut = static_cast<TestTransport*>(registry->get("tcp",addr,(const int16)j));
assert(transportIn == transportOut);
}
transportArrayOut = reinterpret_cast<TestTransport**>(registry->get("tcp",addr,size));
assert(size == priority_max);
for(int32 k = 0; k < priority_max; k++)
{
assert(transportArrayIn[i * priority_max + k] == transportArrayOut[k]);
}
delete[] transportArrayOut;
}
assert(registry->numberOfActiveTransports() == (address_max * priority_max));
transportArrayOut = reinterpret_cast<TestTransport**>(registry->toArray("tcp",size));
assert(size == (address_max * priority_max));
for(int32 i = 0; i < address_max * priority_max; i++)
{
assert(transportArrayIn[i] == transportArrayOut[i]);
}
delete[] transportArrayOut;
transportArrayOut = reinterpret_cast<TestTransport**>(registry->toArray(size));
assert(size == (address_max * priority_max));
for(int32 i = 0; i < address_max * priority_max; i++)
{
assert(transportArrayIn[i] == transportArrayOut[i]);
}
delete[] transportArrayOut;
for(int32 i = 0; i < address_max; i++)
{
for(int16 j = 0; j < priority_max; j++)
{
assert(transportArrayIn[i * priority_max + j] == registry->remove(static_cast<Transport*>(transportArrayIn[i * priority_max + j])));
}
}
assert(registry->numberOfActiveTransports() == 0);
for(int32 i = 0; i < address_max; i++)
{
if( addrArray[i]) delete addrArray[i];
for(int16 j = 0; j < priority_max; j++)
{
if(transportArrayIn[i * priority_max + j]) delete transportArrayIn[i * priority_max + j];
}
}
if(addrArray) delete[] addrArray;
if(transportArrayIn) delete[] transportArrayIn;
if(registry) delete registry;
getShowConstructDestruct()->constuctDestructTotals(stdout);
return 0;
}