summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles E. Rolke <chug@apache.org>2012-11-05 20:43:48 +0000
committerCharles E. Rolke <chug@apache.org>2012-11-05 20:43:48 +0000
commit7ce7d0773c1afaaeb93d7ece9c39e692998f40c0 (patch)
tree8afc9883f5a6c60ec51e0882aa8e103a71474cfe
parentc125061215f025f21109954b94538d68ef893f97 (diff)
downloadqpid-python-7ce7d0773c1afaaeb93d7ece9c39e692998f40c0.tar.gz
QPID-4421 Issue with reusing link channel Id number too soon.
Cycle through the entire pool of (32K) channel Id numbers to defer problem of references which are held for a little too long. This problem was exposed by QPID-4392 where a channel number wrap problem was repaired. git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@1405946 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--cpp/src/qpid/broker/Link.cpp28
-rw-r--r--cpp/src/qpid/broker/Link.h1
2 files changed, 23 insertions, 6 deletions
diff --git a/cpp/src/qpid/broker/Link.cpp b/cpp/src/qpid/broker/Link.cpp
index 82389a5e3d..84a3a9ccb1 100644
--- a/cpp/src/qpid/broker/Link.cpp
+++ b/cpp/src/qpid/broker/Link.cpp
@@ -149,6 +149,7 @@ Link::Link(const string& _name,
currentInterval(1),
closing(false),
reconnectNext(0), // Index of next address for reconnecting in url.
+ nextFreeChannel(1),
freeChannels(1, framing::CHANNEL_MAX),
connection(0),
agent(0),
@@ -548,13 +549,28 @@ framing::ChannelId Link::nextChannel()
{
Mutex::ScopedLock mutex(lock);
if (!freeChannels.empty()) {
- framing::ChannelId c = freeChannels.front();
- freeChannels -= c;
- QPID_LOG(debug, "Link " << name << " allocates channel: " << c);
- return c;
- } else {
- throw Exception(Msg() << "Link " << name << " channel pool is empty");
+ // A free channel exists.
+ for (framing::ChannelId i = 1; i <= framing::CHANNEL_MAX; i++)
+ {
+ // extract proposed free channel
+ framing::ChannelId c = nextFreeChannel;
+ // calculate next free channel
+ if (framing::CHANNEL_MAX == nextFreeChannel)
+ nextFreeChannel = 1;
+ else
+ nextFreeChannel += 1;
+ // if proposed channel is free, use it
+ if (freeChannels.contains(c))
+ {
+ freeChannels -= c;
+ QPID_LOG(debug, "Link " << name << " allocates channel: " << c);
+ return c;
+ }
+ }
+ assert (false);
}
+
+ throw Exception(Msg() << "Link " << name << " channel pool is empty");
}
// Return channel to link free pool
diff --git a/cpp/src/qpid/broker/Link.h b/cpp/src/qpid/broker/Link.h
index 12bf28423a..97511de08f 100644
--- a/cpp/src/qpid/broker/Link.h
+++ b/cpp/src/qpid/broker/Link.h
@@ -82,6 +82,7 @@ class Link : public PersistableConfig, public management::Manageable {
Bridges created; // Bridges pending creation
Bridges active; // Bridges active
Bridges cancellations; // Bridges pending cancellation
+ framing::ChannelId nextFreeChannel;
RangeSet<framing::ChannelId> freeChannels;
Connection* connection;
management::ManagementAgent* agent;