diff --git a/.hgignore b/.hgignore deleted file mode 100644 index 2090ed3..0000000 --- a/.hgignore +++ /dev/null @@ -1,10 +0,0 @@ -QtC-pvAccess.creator.user - -syntax: glob -O.Common -O.linux-x86 - -syntax: regexp -^bin -^include - diff --git a/pvAccessApp/Makefile b/pvAccessApp/Makefile index be47a78..19a13a8 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 8b52e23..e808475 100644 --- a/pvAccessApp/utils/introspectionRegistry.cpp +++ b/pvAccessApp/utils/introspectionRegistry.cpp @@ -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(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); @@ -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) diff --git a/pvAccessApp/utils/introspectionRegistry.h b/pvAccessApp/utils/introspectionRegistry.h index 549fbdd..ed9b739 100644 --- a/pvAccessApp/utils/introspectionRegistry.h +++ b/pvAccessApp/utils/introspectionRegistry.h @@ -62,6 +62,9 @@ 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 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 registryMap_t; /** * Deserialize PVRequest. * @param payloadBuffer data buffer. - * @param control + * @param control serialization control. * * @return deserialized PVRequest, can be null. */ @@ -189,24 +192,28 @@ typedef std::map registryMap_t; /** * Deserialize Structure and create PVStructure instance. + * * @param payloadBuffer data buffer. + * @param control serialization control. + * * @return PVStructure instance, can be null. */ 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 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 */ diff --git a/testApp/utils/Makefile b/testApp/utils/Makefile index 49343d0..8e364c2 100644 --- a/testApp/utils/Makefile +++ b/testApp/utils/Makefile @@ -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 diff --git a/testApp/utils/introspectionRegistryTest.cpp b/testApp/utils/introspectionRegistryTest.cpp index 7851ad0..bdc9e86 100644 --- a/testApp/utils/introspectionRegistryTest.cpp +++ b/testApp/utils/introspectionRegistryTest.cpp @@ -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(getStructureArray(name1,name2)),static_cast(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; } diff --git a/testApp/utils/transportRegistryTest.cpp b/testApp/utils/transportRegistryTest.cpp new file mode 100644 index 0000000..4d3f004 --- /dev/null +++ b/testApp/utils/transportRegistryTest.cpp @@ -0,0 +1,138 @@ +/* + * transportRegistryTest.cpp + * + */ + +#include "transportRegistry.h" +#include "showConstructDestruct.h" + +#include +#include +#include + +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(transportIn)); + + TestTransport* transportOut = static_cast(registry->get("tcp",addr,(const int16)j)); + assert(transportIn == transportOut); + } + + + transportArrayOut = reinterpret_cast(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(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(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(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; +} + +