diff options
| author | Gordon Sim <gsim@apache.org> | 2009-03-10 22:48:51 +0000 |
|---|---|---|
| committer | Gordon Sim <gsim@apache.org> | 2009-03-10 22:48:51 +0000 |
| commit | b9a77d5a5d482a7a9828f64c4d06def816997f16 (patch) | |
| tree | 00e38af08e6031e713e372e2e885e253106b9c5b /cpp/src/qpid/replication | |
| parent | 2d9d07806037ce5e91dd0bad53fdfbe25ca5f8b1 (diff) | |
| download | qpid-python-b9a77d5a5d482a7a9828f64c4d06def816997f16.tar.gz | |
QPID-1724: Allow replication events to be shared across multiple federations bridges.
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@752290 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/src/qpid/replication')
| -rw-r--r-- | cpp/src/qpid/replication/ReplicatingEventListener.cpp | 78 | ||||
| -rw-r--r-- | cpp/src/qpid/replication/ReplicatingEventListener.h | 5 | ||||
| -rw-r--r-- | cpp/src/qpid/replication/ReplicationExchange.cpp | 1 |
3 files changed, 63 insertions, 21 deletions
diff --git a/cpp/src/qpid/replication/ReplicatingEventListener.cpp b/cpp/src/qpid/replication/ReplicatingEventListener.cpp index e3990a13cc..60d5fffc0b 100644 --- a/cpp/src/qpid/replication/ReplicatingEventListener.cpp +++ b/cpp/src/qpid/replication/ReplicatingEventListener.cpp @@ -21,6 +21,7 @@ #include "ReplicatingEventListener.h" #include "constants.h" #include "qpid/broker/Broker.h" +#include "qpid/broker/DeliverableMessage.h" #include "qpid/broker/QueueEvents.h" #include "qpid/framing/AMQFrame.h" #include "qpid/framing/FrameHandler.h" @@ -60,7 +61,9 @@ void ReplicatingEventListener::deliverDequeueMessage(const QueuedMessage& dequeu headers.setInt(REPLICATION_EVENT_TYPE, DEQUEUE); headers.setInt(DEQUEUED_MESSAGE_POSITION, dequeued.position); boost::intrusive_ptr<Message> msg(createMessage(headers)); - queue->deliver(msg); + DeliveryProperties* props = msg->getFrames().getHeaders()->get<DeliveryProperties>(true); + props->setRoutingKey(dequeued.queue->getName()); + route(msg); } void ReplicatingEventListener::deliverEnqueueMessage(const QueuedMessage& enqueued) @@ -69,9 +72,26 @@ void ReplicatingEventListener::deliverEnqueueMessage(const QueuedMessage& enqueu FieldTable& headers = msg->getProperties<MessageProperties>()->getApplicationHeaders(); headers.setString(REPLICATION_TARGET_QUEUE, enqueued.queue->getName()); headers.setInt(REPLICATION_EVENT_TYPE, ENQUEUE); - queue->deliver(msg); + route(msg); } +void ReplicatingEventListener::route(boost::intrusive_ptr<qpid::broker::Message> msg) +{ + try { + if (exchange) { + DeliverableMessage deliverable(msg); + exchange->route(deliverable, msg->getRoutingKey(), msg->getApplicationHeaders()); + } else if (queue) { + queue->deliver(msg); + } else { + QPID_LOG(error, "Cannot route replication event, neither replication queue nor exchange configured"); + } + } catch (const std::exception& e) { + QPID_LOG(error, "Error enqueing replication event: " << e.what()); + } +} + + boost::intrusive_ptr<Message> ReplicatingEventListener::createMessage(const FieldTable& headers) { boost::intrusive_ptr<Message> msg(new Message()); @@ -127,33 +147,49 @@ Options* ReplicatingEventListener::getOptions() void ReplicatingEventListener::initialize(Plugin::Target& target) { - Broker* broker = dynamic_cast<broker::Broker*>(&target); - if (broker && !options.queue.empty()) { - broker->addFinalizer(boost::bind(&ReplicatingEventListener::shutdown, this)); - if (options.createQueue) { - queue = broker->getQueues().declare(options.queue).first; - } else { - queue = broker->getQueues().find(options.queue); - } - if (queue) { - queue->insertSequenceNumbers(REPLICATION_EVENT_SEQNO); - QueueEvents::EventListener callback = boost::bind(&ReplicatingEventListener::handle, this, _1); - broker->getQueueEvents().registerListener(options.name, callback); - QPID_LOG(info, "Registered replicating queue event listener"); - } else { - QPID_LOG(error, "Replication queue named '" << options.queue << "' does not exist; replication plugin disabled."); - } - } + Broker* broker = dynamic_cast<broker::Broker*>(&target); + if (broker) { + broker->addFinalizer(boost::bind(&ReplicatingEventListener::shutdown, this)); + if (!options.exchange.empty()) { + if (!options.queue.empty()) { + QPID_LOG(warning, "Replication queue option ignored as replication exchange has been specified"); + } + try { + exchange = broker->getExchanges().declare(options.exchange, options.exchangeType).first; + } catch (const UnknownExchangeTypeException&) { + QPID_LOG(error, "Replication disabled due to invalid type: " << options.exchangeType); + } + } else if (!options.queue.empty()) { + if (options.createQueue) { + queue = broker->getQueues().declare(options.queue).first; + } else { + queue = broker->getQueues().find(options.queue); + } + if (queue) { + queue->insertSequenceNumbers(REPLICATION_EVENT_SEQNO); + } else { + QPID_LOG(error, "Replication queue named '" << options.queue << "' does not exist; replication plugin disabled."); + } + } + if (queue || exchange) { + QueueEvents::EventListener callback = boost::bind(&ReplicatingEventListener::handle, this, _1); + broker->getQueueEvents().registerListener(options.name, callback); + QPID_LOG(info, "Registered replicating queue event listener"); + } + } } void ReplicatingEventListener::earlyInitialize(Target&) {} -void ReplicatingEventListener::shutdown() { queue.reset(); } +void ReplicatingEventListener::shutdown() { queue.reset(); exchange.reset(); } ReplicatingEventListener::PluginOptions::PluginOptions() : Options("Queue Replication Options"), - name("replicator"), + exchangeType("direct"), + name("replicator"), createQueue(false) { addOptions() + ("replication-exchange-name", optValue(exchange, "EXCHANGE"), "Exchange to which events for other queues are routed") + ("replication-exchange-type", optValue(exchangeType, "direct|topic etc"), "Type of exchange to use") ("replication-queue", optValue(queue, "QUEUE"), "Queue on which events for other queues are recorded") ("replication-listener-name", optValue(name, "NAME"), "name by which to register the replicating event listener") ("create-replication-queue", optValue(createQueue), "if set, the replication will be created if it does not exist"); diff --git a/cpp/src/qpid/replication/ReplicatingEventListener.h b/cpp/src/qpid/replication/ReplicatingEventListener.h index 3d8f23e7ac..74418d00e6 100644 --- a/cpp/src/qpid/replication/ReplicatingEventListener.h +++ b/cpp/src/qpid/replication/ReplicatingEventListener.h @@ -24,6 +24,7 @@ #include "qpid/Plugin.h" #include "qpid/Options.h" +#include "qpid/broker/Exchange.h" #include "qpid/broker/Message.h" #include "qpid/broker/Queue.h" #include "qpid/broker/QueueEvents.h" @@ -50,6 +51,8 @@ class ReplicatingEventListener : public Plugin struct PluginOptions : public Options { std::string queue; + std::string exchange; + std::string exchangeType; std::string name; bool createQueue; @@ -58,9 +61,11 @@ class ReplicatingEventListener : public Plugin PluginOptions options; qpid::broker::Queue::shared_ptr queue; + qpid::broker::Exchange::shared_ptr exchange; void deliverDequeueMessage(const qpid::broker::QueuedMessage& enqueued); void deliverEnqueueMessage(const qpid::broker::QueuedMessage& enqueued); + void route(boost::intrusive_ptr<qpid::broker::Message>); void shutdown(); boost::intrusive_ptr<qpid::broker::Message> createMessage(const qpid::framing::FieldTable& headers); diff --git a/cpp/src/qpid/replication/ReplicationExchange.cpp b/cpp/src/qpid/replication/ReplicationExchange.cpp index 88c94ad7ba..29cdf21bc6 100644 --- a/cpp/src/qpid/replication/ReplicationExchange.cpp +++ b/cpp/src/qpid/replication/ReplicationExchange.cpp @@ -102,6 +102,7 @@ void ReplicationExchange::handleDequeueEvent(const FieldTable* args) bool ReplicationExchange::isDuplicate(const FieldTable* args) { + if (!args->get(REPLICATION_EVENT_SEQNO)) return false; SequenceNumber seqno(args->getAsInt(REPLICATION_EVENT_SEQNO)); if (!init) { init = true; |
