diff --git a/src/remote/channelSearchManager.h b/src/remote/channelSearchManager.h index 45ec9b2..5f5458d 100644 --- a/src/remote/channelSearchManager.h +++ b/src/remote/channelSearchManager.h @@ -67,7 +67,7 @@ class ChannelSearchManager { * Register channel. * @param channel */ - virtual void registerSearchInstance(SearchInstance::shared_pointer const & channel) = 0; + virtual void registerSearchInstance(SearchInstance::shared_pointer const & channel, bool penalize = false) = 0; /** diff --git a/src/remote/simpleChannelSearchManagerImpl.cpp b/src/remote/simpleChannelSearchManagerImpl.cpp index 25db05c..f8a42a6 100644 --- a/src/remote/simpleChannelSearchManagerImpl.cpp +++ b/src/remote/simpleChannelSearchManagerImpl.cpp @@ -28,10 +28,11 @@ const int SimpleChannelSearchManagerImpl::PAYLOAD_POSITION = 4; const double SimpleChannelSearchManagerImpl::ATOMIC_PERIOD = 0.225; const int SimpleChannelSearchManagerImpl::PERIOD_JITTER_MS = 25; +const int SimpleChannelSearchManagerImpl::DEFAULT_USER_VALUE = 1; const int SimpleChannelSearchManagerImpl::BOOST_VALUE = 1; // must be power of two (so that search is done) -const int SimpleChannelSearchManagerImpl::MAX_COUNT_VALUE = 1 << 7; -const int SimpleChannelSearchManagerImpl::MAX_FALLBACK_COUNT_VALUE = (1 << 6) + 1; +const int SimpleChannelSearchManagerImpl::MAX_COUNT_VALUE = 1 << 8; +const int SimpleChannelSearchManagerImpl::MAX_FALLBACK_COUNT_VALUE = (1 << 7) + 1; const int SimpleChannelSearchManagerImpl::MAX_FRAMES_AT_ONCE = 10; const int SimpleChannelSearchManagerImpl::DELAY_BETWEEN_FRAMES_MS = 50; @@ -105,25 +106,26 @@ int32_t SimpleChannelSearchManagerImpl::registeredCount() return static_cast(m_channels.size()); } -void SimpleChannelSearchManagerImpl::registerSearchInstance(SearchInstance::shared_pointer const & channel) +void SimpleChannelSearchManagerImpl::registerSearchInstance(SearchInstance::shared_pointer const & channel, bool penalize) { if (m_canceled.get()) return; - bool immediateTrigger; - { - Lock guard(m_channelMutex); - //overrides if already registered - m_channels[channel->getSearchInstanceID()] = channel; - immediateTrigger = m_channels.size() == 1; + bool immediateTrigger; + { + Lock guard(m_channelMutex); - Lock guard2(m_userValueMutex); - int32_t& userValue = channel->getUserValue(); - userValue = 1; - } + // overrides if already registered + m_channels[channel->getSearchInstanceID()] = channel; + immediateTrigger = (m_channels.size() == 1); - if (immediateTrigger) - callback(); + Lock guard2(m_userValueMutex); + int32_t& userValue = channel->getUserValue(); + userValue = (penalize ? MAX_FALLBACK_COUNT_VALUE : DEFAULT_USER_VALUE); + } + + if (immediateTrigger) + callback(); } void SimpleChannelSearchManagerImpl::unregisterSearchInstance(SearchInstance::shared_pointer const & channel) @@ -314,7 +316,7 @@ void SimpleChannelSearchManagerImpl::callback() int32_t& countValue = (*siter)->getUserValue(); bool skip = !isPowerOfTwo(countValue); - if (countValue == MAX_COUNT_VALUE) + if (countValue >= MAX_COUNT_VALUE) countValue = MAX_FALLBACK_COUNT_VALUE; else countValue++; diff --git a/src/remote/simpleChannelSearchManagerImpl.h b/src/remote/simpleChannelSearchManagerImpl.h index ad2cff9..cead8ff 100644 --- a/src/remote/simpleChannelSearchManagerImpl.h +++ b/src/remote/simpleChannelSearchManagerImpl.h @@ -81,7 +81,7 @@ class SimpleChannelSearchManagerImpl : * Register channel. * @param channel to register. */ - void registerSearchInstance(SearchInstance::shared_pointer const & channel); + void registerSearchInstance(SearchInstance::shared_pointer const & channel, bool penalize = false); /** * Unregister channel. * @param channel to unregister. @@ -190,11 +190,12 @@ class SimpleChannelSearchManagerImpl : static const double ATOMIC_PERIOD; static const int PERIOD_JITTER_MS; - static const int BOOST_VALUE; - static const int MAX_COUNT_VALUE; - static const int MAX_FALLBACK_COUNT_VALUE; + static const int DEFAULT_USER_VALUE; + static const int BOOST_VALUE; + static const int MAX_COUNT_VALUE; + static const int MAX_FALLBACK_COUNT_VALUE; - static const int MAX_FRAMES_AT_ONCE; + static const int MAX_FRAMES_AT_ONCE; static const int DELAY_BETWEEN_FRAMES_MS; }; diff --git a/src/remoteClient/clientContextImpl.cpp b/src/remoteClient/clientContextImpl.cpp index 9d7c5d7..fbe4d8d 100644 --- a/src/remoteClient/clientContextImpl.cpp +++ b/src/remoteClient/clientContextImpl.cpp @@ -3622,12 +3622,12 @@ namespace epics { void createChannel(Transport::shared_pointer const & transport) { Lock guard(m_channelMutex); - + // do not allow duplicate creation to the same transport if (!m_allowCreation) return; m_allowCreation = false; - + // check existing transport if (m_transport.get() && m_transport.get() != transport.get()) { @@ -3660,10 +3660,18 @@ namespace epics { virtual void createChannelFailed() { Lock guard(m_channelMutex); - + cancel(); - // ... and search again - initiateSearch(); + + // release transport if active + if (m_transport) + { + m_transport->release(getID()); + m_transport.reset(); + } + + // ... and search again, with penalty + initiateSearch(true); } /** @@ -3814,7 +3822,7 @@ namespace epics { /** * Initiate search (connect) procedure. */ - void initiateSearch() + void initiateSearch(bool penalize = false) { Lock guard(m_channelMutex); @@ -3822,7 +3830,7 @@ namespace epics { if (!m_addresses.get()) { - m_context->getChannelSearchManager()->registerSearchInstance(shared_from_this()); + m_context->getChannelSearchManager()->registerSearchInstance(shared_from_this(), penalize); } else if (!m_addresses->empty()) { @@ -3854,11 +3862,12 @@ namespace epics { Transport::shared_pointer transport = m_transport; if (transport.get()) { + // TODO use GUID to determine whether there are multiple servers with the same channel // multiple defined PV or reconnect request (same server address) if (!sockAddrAreIdentical(transport->getRemoteAddress(), serverAddress)) { EXCEPTION_GUARD(m_requester->message("More than one channel with name '" + m_name + - "' detected, additional response from: " + inetAddressToString(*serverAddress), warningMessage)); + "' detected, connected to: " + inetAddressToString(*transport->getRemoteAddress()) + ", ignored: " + inetAddressToString(*serverAddress), warningMessage)); return; } }