diff --git a/pvAccessApp/Makefile b/pvAccessApp/Makefile index 01422d6..a97d249 100644 --- a/pvAccessApp/Makefile +++ b/pvAccessApp/Makefile @@ -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 diff --git a/pvAccessApp/utils/introspectionRegistry.cpp b/pvAccessApp/utils/introspectionRegistry.cpp index 3304c8d..e808475 100644 --- a/pvAccessApp/utils/introspectionRegistry.cpp +++ b/pvAccessApp/utils/introspectionRegistry.cpp @@ -119,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(field1)->getScalarType() == static_cast(field1)->getScalarType()) - { - return true; - } - break; - } - case epics::pvData::scalarArray: - { - if(static_cast(field1)->getElementType() == static_cast(field1)->getElementType()) - { - return true; - } - break; - } - case epics::pvData::structure: - { - return true; - break; - } - case epics::pvData::structureArray: - { - if(static_cast(field1)->getStructure()->getFieldName() == static_cast(field1)->getStructure()->getFieldName()) - { - return true; - } - break; - } - } - return false; - } -} - void IntrospectionRegistry::serialize(FieldConstPtr field, ByteBuffer* buffer, SerializableControl* control) { checkBufferAndSerializeControl(buffer, control); diff --git a/pvAccessApp/utils/introspectionRegistry.h b/pvAccessApp/utils/introspectionRegistry.h index 4429cf1..cc2192d 100644 --- a/pvAccessApp/utils/introspectionRegistry.h +++ b/pvAccessApp/utils/introspectionRegistry.h @@ -61,7 +61,7 @@ typedef std::map 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 larg maps. We need to change this !!!!!! + * TODO !!!!!!this can get very slow in large maps. We need to change this !!!!!! * * @param field introspection interface to register * @@ -239,7 +239,6 @@ typedef std::map 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); }; diff --git a/pvAccessApp/utils/transportRegistry.cpp b/pvAccessApp/utils/transportRegistry.cpp new file mode 100644 index 0000000..11194d0 --- /dev/null +++ b/pvAccessApp/utils/transportRegistry.cpp @@ -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; +} + +}} + diff --git a/pvAccessApp/utils/transportRegistry.h b/pvAccessApp/utils/transportRegistry.h new file mode 100644 index 0000000..f4ed110 --- /dev/null +++ b/pvAccessApp/utils/transportRegistry.h @@ -0,0 +1,57 @@ +/* + * transportRegistry.h + */ + +#ifndef TRANSPORTREGISTRY_H +#define TRANSPORTREGISTRY_H + + +#include +#include +#include +#include + +#include + +#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 prioritiesMap_t; +typedef std::map transportsMap_t; +typedef std::vector 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 */