Qpid
  1. Qpid
  2. QPID-4969

C++ Broker headers exchange allows creation of bindings with duplicate keys

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 0.22
    • Fix Version/s: 0.23
    • Component/s: C++ Broker
    • Labels:
      None

      Description

      The test case:

      qpid-config add queue MyQueue --durable
      qpid-config bind amq.match MyQueue SomeKey any property1=value1
      qpid-config bind amq.match MyQueue SomeKey all property1=value1
      

      Causes a management error as two bindings are created with amq.match,MyQueue,SomeKey managementId.

        Activity

        Justin Ross made changes -
        Status Resolved [ 5 ] Closed [ 6 ]
        Hide
        Justin Ross added a comment -
        Show
        Justin Ross added a comment - Released in Qpid 0.24, http://qpid.apache.org/releases/qpid-0.24/index.html
        Hide
        Fraser Adams added a comment -

        Thanks guys, I've just rebuilt off trunk on r1499027 and all seems to be well with my little test case again, yay!!!

        Show
        Fraser Adams added a comment - Thanks guys, I've just rebuilt off trunk on r1499027 and all seems to be well with my little test case again, yay!!!
        Hide
        Gordon Sim added a comment -

        Ah... no wonder it didn't work then. Odd as I have the ! in my local copy. Anyway... looks good as committed.

        Show
        Gordon Sim added a comment - Ah... no wonder it didn't work then. Odd as I have the ! in my local copy. Anyway... looks good as committed.
        Hide
        ASF subversion and git services added a comment -

        Commit 1498671 from chug@apache.org
        [ https://svn.apache.org/r1498671 ]

        QPID-4969: C++ Broker headers exchange allows creation of bindings
        with duplicate keys
        Patch from Gordon Sim to correct issues in initial fix.
        Now successive bind requests are accepted when the key, queue, and exchange
        are identical if and only if all of the binding args are also identical.

        Show
        ASF subversion and git services added a comment - Commit 1498671 from chug@apache.org [ https://svn.apache.org/r1498671 ] QPID-4969 : C++ Broker headers exchange allows creation of bindings with duplicate keys Patch from Gordon Sim to correct issues in initial fix. Now successive bind requests are accepted when the key, queue, and exchange are identical if and only if all of the binding args are also identical.
        Hide
        Chuck Rolke added a comment -

        We need to call the federation addOrigin function as you are correctly concerned. In your original patch I think you meant

        +                if (matchKey(*i) && !matchArgs(*i)) {
        

        where you left out the "!".

        Show
        Chuck Rolke added a comment - We need to call the federation addOrigin function as you are correctly concerned. In your original patch I think you meant + if (matchKey(*i) && !matchArgs(*i)) { where you left out the "!".
        Hide
        Gordon Sim added a comment -

        Actually... I take that back. I'm not sure it is correct to skip the addOrigin() if the binding matches, is it? Before this issue, if the arguments matched for that queue, the binding would not be added but addOrigin() would be called instead. Now, I don't really understand the fedOrigin stuff, but it would probably be worth having an explicit reason to change the previous behaviour there (which is independent from refusing to allow the same key to be used for different args).

        Show
        Gordon Sim added a comment - Actually... I take that back. I'm not sure it is correct to skip the addOrigin() if the binding matches, is it? Before this issue, if the arguments matched for that queue, the binding would not be added but addOrigin() would be called instead. Now, I don't really understand the fedOrigin stuff, but it would probably be worth having an explicit reason to change the previous behaviour there (which is independent from refusing to allow the same key to be used for different args).
        Hide
        Gordon Sim added a comment -

        My patch does fix Fraser's case (at least as far as I understand it). I.e. I can run two receivers with the address string he gave either in parallel or one after the other, without error. The only difference I see with your patch is that it explicitly skips the actual bind step (the add_unless would fail anyway, but I suppose it is clearer to skip it, especially with the fedOrigin nonsense).

        So I agree with your modification, I'm just confused as to the given reason for it.

        Show
        Gordon Sim added a comment - My patch does fix Fraser's case (at least as far as I understand it). I.e. I can run two receivers with the address string he gave either in parallel or one after the other, without error. The only difference I see with your patch is that it explicitly skips the actual bind step (the add_unless would fail anyway, but I suppose it is clearer to skip it, especially with the fedOrigin nonsense). So I agree with your modification, I'm just confused as to the given reason for it.
        Hide
        Chuck Rolke added a comment -

        Gordon's patch (thanks for that!) still fails Fraser's case. I propose something to satisfy both camps:

        When a binding with a duplicate key and duplicate args comes up then just pass on it. Don't create a new binding nor complain just let the old binding continue to exist.

        When a binding with a duplicate key but different args comes up then it gets failed. This means that one binding can't specify 'any' and another specify 'all' but have both survive with the same key.

        This scheme gets Fraser's test case to pass but still fails this issue's test case.

        Index: cpp/src/tests/ExchangeTest.cpp
        ===================================================================
        --- cpp/src/tests/ExchangeTest.cpp      (revision 1498469)
        +++ cpp/src/tests/ExchangeTest.cpp      (working copy)
        @@ -138,7 +138,7 @@
             args3.setInt("b", 6);
         
             headers.bind(a, "", &args1);
        -    headers.bind(a, "", &args3);
        +    headers.bind(a, "other", &args3);//need to use different binding key to correctly identify second binding
             headers.bind(b, "", &args2);
             headers.bind(c, "", &args1);
         
        Index: cpp/src/qpid/broker/HeadersExchange.h
        ===================================================================
        --- cpp/src/qpid/broker/HeadersExchange.h       (revision 1498469)
        +++ cpp/src/qpid/broker/HeadersExchange.h       (working copy)
        @@ -48,7 +48,7 @@
                 const Queue::shared_ptr queue;        
                 const qpid::framing::FieldTable* args;
                 MatchArgs(Queue::shared_ptr q, const qpid::framing::FieldTable* a);
        -        bool operator()(BoundKey & bk);
        +        bool operator()(const BoundKey & bk);
             };
             
             struct MatchKey
        @@ -56,7 +56,7 @@
                 const Queue::shared_ptr queue;
                 const std::string& key;
                 MatchKey(Queue::shared_ptr q, const std::string& k);
        -        bool operator()(BoundKey & bk);
        +        bool operator()(const BoundKey & bk);
             };
         
             struct FedUnbindModifier
        Index: cpp/src/qpid/broker/HeadersExchange.cpp
        ===================================================================
        --- cpp/src/qpid/broker/HeadersExchange.cpp     (revision 1498469)
        +++ cpp/src/qpid/broker/HeadersExchange.cpp     (working copy)
        @@ -189,7 +189,7 @@
             // the non federation args in case a federated propagate is needed
             FieldTable extra_args;
             getNonFedArgs(args, extra_args);
        -    
        +
             if (fedOp.empty() || fedOp == fedOpBind) {
                 // x-match arg MUST be present for a bind call
                 std::string x_match_value = getMatch(args);
        @@ -198,18 +198,31 @@
                     throw InternalErrorException(QPID_MSG("Invalid or missing x-match value binding to headers exchange. Must be a string [\"all\" or \"any\"]"));
                 }
         
        +        bool duplicateBinding(false);
                 Bindings::ConstPtr p = bindings.snapshot();
                 if (p.get()) {
        +            MatchArgs matchArgs(queue, &extra_args);
        +            MatchKey matchKey(queue, bindingKey);
                     for (std::vector<BoundKey>::const_iterator i = p->begin(); i != p->end(); ++i) {
        -                if (queue == i->binding->queue && bindingKey == i->binding->key) {
        -                    throw InternalErrorException(QPID_MSG("Exchange: " << getName()
        -                        << ", binding key: " << bindingKey
        -                        << " Duplicate binding key not allowed." ));
        +                if (matchKey(*i)) {
        +                    // bindings with same keys may be duplicates
        +                    if (matchArgs(*i)) {
        +                        // duplicate bindings (same key, args) are not added anew
        +                        duplicateBinding = true;
        +                    } else {
        +                        // bindings with same key but different args are not allowed
        +                        throw InternalErrorException(QPID_MSG("Exchange: " << getName()
        +                            << ", binding key: " << bindingKey
        +                            << " Duplicate binding key not allowed." ));
        +                    }
        +                    break;
        +                } else {
        +                    // bindings with different keys are not duplicates
                         }
                     }
                 }
         
        -        {
        +        if (!duplicateBinding) {
                     Mutex::ScopedLock l(lock);
                     //NOTE: do not include the fed op/tags/origin in the
                     //arguments as when x-match is 'all' these would prevent
        @@ -372,7 +385,7 @@
         //---------
         HeadersExchange::MatchArgs::MatchArgs(Queue::shared_ptr q, const qpid::framing::FieldTable* a) : queue(q), args(a) {}
         
        -bool HeadersExchange::MatchArgs::operator()(BoundKey & bk)
        +bool HeadersExchange::MatchArgs::operator()(const BoundKey & bk)
         {
             return bk.binding->queue == queue && bk.binding->args == *args;
         }
        @@ -380,7 +393,7 @@
         //---------
         HeadersExchange::MatchKey::MatchKey(Queue::shared_ptr q, const std::string& k) : queue(q), key(k) {}
         
        -bool HeadersExchange::MatchKey::operator()(BoundKey & bk)
        +bool HeadersExchange::MatchKey::operator()(const BoundKey & bk)
         {
             return bk.binding->queue == queue && bk.binding->key == key;
         }
        
        Show
        Chuck Rolke added a comment - Gordon's patch (thanks for that!) still fails Fraser's case. I propose something to satisfy both camps: When a binding with a duplicate key and duplicate args comes up then just pass on it. Don't create a new binding nor complain just let the old binding continue to exist. When a binding with a duplicate key but different args comes up then it gets failed. This means that one binding can't specify 'any' and another specify 'all' but have both survive with the same key. This scheme gets Fraser's test case to pass but still fails this issue's test case. Index: cpp/src/tests/ExchangeTest.cpp =================================================================== --- cpp/src/tests/ExchangeTest.cpp (revision 1498469) +++ cpp/src/tests/ExchangeTest.cpp (working copy) @@ -138,7 +138,7 @@ args3.setInt("b", 6); headers.bind(a, "", &args1); - headers.bind(a, "", &args3); + headers.bind(a, "other", &args3);//need to use different binding key to correctly identify second binding headers.bind(b, "", &args2); headers.bind(c, "", &args1); Index: cpp/src/qpid/broker/HeadersExchange.h =================================================================== --- cpp/src/qpid/broker/HeadersExchange.h (revision 1498469) +++ cpp/src/qpid/broker/HeadersExchange.h (working copy) @@ -48,7 +48,7 @@ const Queue::shared_ptr queue; const qpid::framing::FieldTable* args; MatchArgs(Queue::shared_ptr q, const qpid::framing::FieldTable* a); - bool operator()(BoundKey & bk); + bool operator()(const BoundKey & bk); }; struct MatchKey @@ -56,7 +56,7 @@ const Queue::shared_ptr queue; const std::string& key; MatchKey(Queue::shared_ptr q, const std::string& k); - bool operator()(BoundKey & bk); + bool operator()(const BoundKey & bk); }; struct FedUnbindModifier Index: cpp/src/qpid/broker/HeadersExchange.cpp =================================================================== --- cpp/src/qpid/broker/HeadersExchange.cpp (revision 1498469) +++ cpp/src/qpid/broker/HeadersExchange.cpp (working copy) @@ -189,7 +189,7 @@ // the non federation args in case a federated propagate is needed FieldTable extra_args; getNonFedArgs(args, extra_args); - + if (fedOp.empty() || fedOp == fedOpBind) { // x-match arg MUST be present for a bind call std::string x_match_value = getMatch(args); @@ -198,18 +198,31 @@ throw InternalErrorException(QPID_MSG("Invalid or missing x-match value binding to headers exchange. Must be a string [\"all\" or \"any\"]")); } + bool duplicateBinding(false); Bindings::ConstPtr p = bindings.snapshot(); if (p.get()) { + MatchArgs matchArgs(queue, &extra_args); + MatchKey matchKey(queue, bindingKey); for (std::vector<BoundKey>::const_iterator i = p->begin(); i != p->end(); ++i) { - if (queue == i->binding->queue && bindingKey == i->binding->key) { - throw InternalErrorException(QPID_MSG("Exchange: " << getName() - << ", binding key: " << bindingKey - << " Duplicate binding key not allowed." )); + if (matchKey(*i)) { + // bindings with same keys may be duplicates + if (matchArgs(*i)) { + // duplicate bindings (same key, args) are not added anew + duplicateBinding = true; + } else { + // bindings with same key but different args are not allowed + throw InternalErrorException(QPID_MSG("Exchange: " << getName() + << ", binding key: " << bindingKey + << " Duplicate binding key not allowed." )); + } + break; + } else { + // bindings with different keys are not duplicates } } } - { + if (!duplicateBinding) { Mutex::ScopedLock l(lock); //NOTE: do not include the fed op/tags/origin in the //arguments as when x-match is 'all' these would prevent @@ -372,7 +385,7 @@ //--------- HeadersExchange::MatchArgs::MatchArgs(Queue::shared_ptr q, const qpid::framing::FieldTable* a) : queue(q), args(a) {} -bool HeadersExchange::MatchArgs::operator()(BoundKey & bk) +bool HeadersExchange::MatchArgs::operator()(const BoundKey & bk) { return bk.binding->queue == queue && bk.binding->args == *args; } @@ -380,7 +393,7 @@ //--------- HeadersExchange::MatchKey::MatchKey(Queue::shared_ptr q, const std::string& k) : queue(q), key(k) {} -bool HeadersExchange::MatchKey::operator()(BoundKey & bk) +bool HeadersExchange::MatchKey::operator()(const BoundKey & bk) { return bk.binding->queue == queue && bk.binding->key == key; }
        Hide
        Gordon Sim added a comment -

        The test should also be fixed, e.g.:

        Index: src/tests/ExchangeTest.cpp
        ===================================================================
        --- src/tests/ExchangeTest.cpp	(revision 1498354)
        +++ src/tests/ExchangeTest.cpp	(working copy)
        @@ -138,7 +138,7 @@
             args3.setInt("b", 6);
         
             headers.bind(a, "", &args1);
        -    headers.bind(a, "", &args3);
        +    headers.bind(a, "other", &args3);//need to use different binding key to correctly identify second binding
             headers.bind(b, "", &args2);
             headers.bind(c, "", &args1);
        
        Show
        Gordon Sim added a comment - The test should also be fixed, e.g.: Index: src/tests/ExchangeTest.cpp =================================================================== --- src/tests/ExchangeTest.cpp (revision 1498354) +++ src/tests/ExchangeTest.cpp (working copy) @@ -138,7 +138,7 @@ args3.setInt("b", 6); headers.bind(a, "", &args1); - headers.bind(a, "", &args3); + headers.bind(a, "other", &args3);//need to use different binding key to correctly identify second binding headers.bind(b, "", &args2); headers.bind(c, "", &args1);
        Hide
        Gordon Sim added a comment -

        This also breaks the unit tests, though in that case it is the test itself that is really at fault. Since unbind works only on the binding key (not the args), I think it is generally good to disallow different bindings to the same queue with the same key. Any use case that relied on different args and the same key would I think already be subtly (sometimes not so subtly!) broken.

        The issue with the change as it stands is I think simply that a bind is no longer idempotent, i.e. you should not prevent the same binding being requested (you don't actually need to do anything for it though, since it is already in place). So the thrid command in the reproducer above should fail, but just reissuing the second command should not.

        Suggested change:

        Index: src/qpid/broker/HeadersExchange.cpp
        ===================================================================
        --- src/qpid/broker/HeadersExchange.cpp	(revision 1498354)
        +++ src/qpid/broker/HeadersExchange.cpp	(working copy)
        @@ -200,8 +200,10 @@
         
                 Bindings::ConstPtr p = bindings.snapshot();
                 if (p.get()) {
        +            MatchArgs matchArgs(queue, &extra_args);
        +            MatchKey matchKey(queue, bindingKey);
                     for (std::vector<BoundKey>::const_iterator i = p->begin(); i != p->end(); ++i) {
        -                if (queue == i->binding->queue && bindingKey == i->binding->key) {
        +                if (matchKey(*i) && matchArgs(*i)) {
                             throw InternalErrorException(QPID_MSG("Exchange: " << getName()
                                 << ", binding key: " << bindingKey
                                 << " Duplicate binding key not allowed." ));
        @@ -372,7 +374,7 @@
         //---------
         HeadersExchange::MatchArgs::MatchArgs(Queue::shared_ptr q, const qpid::framing::FieldTable* a) : queue(q), args(a) {}
         
        -bool HeadersExchange::MatchArgs::operator()(BoundKey & bk)
        +bool HeadersExchange::MatchArgs::operator()(const BoundKey & bk)
         {
             return bk.binding->queue == queue && bk.binding->args == *args;
         }
        @@ -380,7 +382,7 @@
         //---------
         HeadersExchange::MatchKey::MatchKey(Queue::shared_ptr q, const std::string& k) : queue(q), key(k) {}
         
        -bool HeadersExchange::MatchKey::operator()(BoundKey & bk)
        +bool HeadersExchange::MatchKey::operator()(const BoundKey & bk)
         {
             return bk.binding->queue == queue && bk.binding->key == key;
         }
        Index: src/qpid/broker/HeadersExchange.h
        ===================================================================
        --- src/qpid/broker/HeadersExchange.h	(revision 1498354)
        +++ src/qpid/broker/HeadersExchange.h	(working copy)
        @@ -48,7 +48,7 @@
                 const Queue::shared_ptr queue;        
                 const qpid::framing::FieldTable* args;
                 MatchArgs(Queue::shared_ptr q, const qpid::framing::FieldTable* a);
        -        bool operator()(BoundKey & bk);
        +        bool operator()(const BoundKey & bk);
             };
             
             struct MatchKey
        @@ -56,7 +56,7 @@
                 const Queue::shared_ptr queue;
                 const std::string& key;
                 MatchKey(Queue::shared_ptr q, const std::string& k);
        -        bool operator()(BoundKey & bk);
        +        bool operator()(const BoundKey & bk);
             };
         
             struct FedUnbindModifier
        
        Show
        Gordon Sim added a comment - This also breaks the unit tests, though in that case it is the test itself that is really at fault. Since unbind works only on the binding key (not the args), I think it is generally good to disallow different bindings to the same queue with the same key. Any use case that relied on different args and the same key would I think already be subtly (sometimes not so subtly!) broken. The issue with the change as it stands is I think simply that a bind is no longer idempotent, i.e. you should not prevent the same binding being requested (you don't actually need to do anything for it though, since it is already in place). So the thrid command in the reproducer above should fail, but just reissuing the second command should not. Suggested change: Index: src/qpid/broker/HeadersExchange.cpp =================================================================== --- src/qpid/broker/HeadersExchange.cpp (revision 1498354) +++ src/qpid/broker/HeadersExchange.cpp (working copy) @@ -200,8 +200,10 @@ Bindings::ConstPtr p = bindings.snapshot(); if (p.get()) { + MatchArgs matchArgs(queue, &extra_args); + MatchKey matchKey(queue, bindingKey); for (std::vector<BoundKey>::const_iterator i = p->begin(); i != p->end(); ++i) { - if (queue == i->binding->queue && bindingKey == i->binding->key) { + if (matchKey(*i) && matchArgs(*i)) { throw InternalErrorException(QPID_MSG("Exchange: " << getName() << ", binding key: " << bindingKey << " Duplicate binding key not allowed." )); @@ -372,7 +374,7 @@ //--------- HeadersExchange::MatchArgs::MatchArgs(Queue::shared_ptr q, const qpid::framing::FieldTable* a) : queue(q), args(a) {} -bool HeadersExchange::MatchArgs::operator()(BoundKey & bk) +bool HeadersExchange::MatchArgs::operator()(const BoundKey & bk) { return bk.binding->queue == queue && bk.binding->args == *args; } @@ -380,7 +382,7 @@ //--------- HeadersExchange::MatchKey::MatchKey(Queue::shared_ptr q, const std::string& k) : queue(q), key(k) {} -bool HeadersExchange::MatchKey::operator()(BoundKey & bk) +bool HeadersExchange::MatchKey::operator()(const BoundKey & bk) { return bk.binding->queue == queue && bk.binding->key == key; } Index: src/qpid/broker/HeadersExchange.h =================================================================== --- src/qpid/broker/HeadersExchange.h (revision 1498354) +++ src/qpid/broker/HeadersExchange.h (working copy) @@ -48,7 +48,7 @@ const Queue::shared_ptr queue; const qpid::framing::FieldTable* args; MatchArgs(Queue::shared_ptr q, const qpid::framing::FieldTable* a); - bool operator()(BoundKey & bk); + bool operator()(const BoundKey & bk); }; struct MatchKey @@ -56,7 +56,7 @@ const Queue::shared_ptr queue; const std::string& key; MatchKey(Queue::shared_ptr q, const std::string& k); - bool operator()(BoundKey & bk); + bool operator()(const BoundKey & bk); }; struct FedUnbindModifier
        Hide
        Fraser Adams added a comment -

        whoah there chuck. I think in principal this is good, however this work has also caused the perfectly reasonable case of consumer clients reconnecting to non-exclusive queues to fail.

        I just fired up a fairly standard headers exchange C++ consumer that I use as a bit of a test case, which has the address string:

        "testqueue; {create: receiver, node: {x-declare: {arguments: {'qpid.policy_type': ring, 'qpid.max_size': 500000000}}, x-bindings: [{exchange: 'amq.match', queue: 'testqueue', key: 'data1', arguments: {x-match: all, data-service: amqp-delivery, item-owner: fadams}}]}}"

        This has worked for me since 0.8 and is a pattern I use for most of my operational subscriptions albeit with different headers. The key thing though is that I expect the first time I fire this up to create the queue/binding etc. and subsequently be it when I shut down this consumer and restart it or whether I stand up additional consumer instances I expect my consumers to retrieve data off the already created queue/binding. As I say this has worked consistently since 0.8 and today I'm getting the following when I shut down my consumer then restart it:

        2013-06-29 14:19:58 [Client] warning Exception received from broker: internal-error: internal-error: Exchange: amq.match, binding key: data1 Duplicate binding key not allowed. (/home/fadams/qpid/qpid-trunk/qpid/cpp/src/qpid/broker/HeadersExchange.cpp:207) [caused by 3 \x07:\x04]
        ItemProducer Exception: internal-error: internal-error: Exchange: amq.match, binding key: data1 Duplicate binding key not allowed. (/home/fadams/qpid/qpid-trunk/qpid/cpp/src/qpid/broker/HeadersExchange.cpp:207)

        I'm currently using headers exchange and only testing on AMQP 0.10 built off trunk using r1497991.

        I was going to raise a JIRA relating to this but I noticed this one as I was typing and this is almost certainly the cause of what I'm currently seeing.

        This is a fairly critical regression for me and would cause significant issues to my operational system as I use the "consumer self service" pattern (illustrated above in the example address string) for queue creation/subscription pretty much exclusively.

        Show
        Fraser Adams added a comment - whoah there chuck. I think in principal this is good, however this work has also caused the perfectly reasonable case of consumer clients reconnecting to non-exclusive queues to fail. I just fired up a fairly standard headers exchange C++ consumer that I use as a bit of a test case, which has the address string: "testqueue; {create: receiver, node: {x-declare: {arguments: {'qpid.policy_type': ring, 'qpid.max_size': 500000000}}, x-bindings: [{exchange: 'amq.match', queue: 'testqueue', key: 'data1', arguments: {x-match: all, data-service: amqp-delivery, item-owner: fadams}}] }}" This has worked for me since 0.8 and is a pattern I use for most of my operational subscriptions albeit with different headers. The key thing though is that I expect the first time I fire this up to create the queue/binding etc. and subsequently be it when I shut down this consumer and restart it or whether I stand up additional consumer instances I expect my consumers to retrieve data off the already created queue/binding. As I say this has worked consistently since 0.8 and today I'm getting the following when I shut down my consumer then restart it: 2013-06-29 14:19:58 [Client] warning Exception received from broker: internal-error: internal-error: Exchange: amq.match, binding key: data1 Duplicate binding key not allowed. (/home/fadams/qpid/qpid-trunk/qpid/cpp/src/qpid/broker/HeadersExchange.cpp:207) [caused by 3 \x07:\x04] ItemProducer Exception: internal-error: internal-error: Exchange: amq.match, binding key: data1 Duplicate binding key not allowed. (/home/fadams/qpid/qpid-trunk/qpid/cpp/src/qpid/broker/HeadersExchange.cpp:207) I'm currently using headers exchange and only testing on AMQP 0.10 built off trunk using r1497991. I was going to raise a JIRA relating to this but I noticed this one as I was typing and this is almost certainly the cause of what I'm currently seeing. This is a fairly critical regression for me and would cause significant issues to my operational system as I use the "consumer self service" pattern (illustrated above in the example address string) for queue creation/subscription pretty much exclusively.
        Chuck Rolke made changes -
        Field Original Value New Value
        Status Open [ 1 ] Resolved [ 5 ]
        Fix Version/s 0.23 [ 12324273 ]
        Resolution Fixed [ 1 ]
        Hide
        Chuck Rolke added a comment -

        Throw an error to prevent creation of duplicate binding name.

        Show
        Chuck Rolke added a comment - Throw an error to prevent creation of duplicate binding name.
        Hide
        ASF subversion and git services added a comment -

        Commit 1497926 from chug@apache.org
        [ https://svn.apache.org/r1497926 ]

        QPID-4969: Headers exchange allows bindings with duplicate managementId.

        Show
        ASF subversion and git services added a comment - Commit 1497926 from chug@apache.org [ https://svn.apache.org/r1497926 ] QPID-4969 : Headers exchange allows bindings with duplicate managementId.
        Chuck Rolke created issue -

          People

          • Assignee:
            Chuck Rolke
            Reporter:
            Chuck Rolke
          • Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development