diff options
Diffstat (limited to 'cpp/src/qpid/broker')
161 files changed, 0 insertions, 24272 deletions
diff --git a/cpp/src/qpid/broker/AclModule.h b/cpp/src/qpid/broker/AclModule.h deleted file mode 100644 index 2f4f7eaacc..0000000000 --- a/cpp/src/qpid/broker/AclModule.h +++ /dev/null @@ -1,281 +0,0 @@ -#ifndef QPID_ACLMODULE_ACL_H -#define QPID_ACLMODULE_ACL_H - - -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - - -#include "qpid/RefCounted.h" -#include <boost/shared_ptr.hpp> -#include <map> -#include <set> -#include <string> -#include <sstream> - -namespace qpid { - -namespace acl { - -enum ObjectType {OBJ_QUEUE, OBJ_EXCHANGE, OBJ_BROKER, OBJ_LINK, - OBJ_METHOD, OBJECTSIZE}; // OBJECTSIZE must be last in list -enum Action {ACT_CONSUME, ACT_PUBLISH, ACT_CREATE, ACT_ACCESS, ACT_BIND, - ACT_UNBIND, ACT_DELETE, ACT_PURGE, ACT_UPDATE, - ACTIONSIZE}; // ACTIONSIZE must be last in list -enum Property {PROP_NAME, PROP_DURABLE, PROP_OWNER, PROP_ROUTINGKEY, - PROP_PASSIVE, PROP_AUTODELETE, PROP_EXCLUSIVE, PROP_TYPE, - PROP_ALTERNATE, PROP_QUEUENAME, PROP_SCHEMAPACKAGE, - PROP_SCHEMACLASS, PROP_POLICYTYPE, PROP_MAXQUEUESIZE, - PROP_MAXQUEUECOUNT}; -enum AclResult {ALLOW, ALLOWLOG, DENY, DENYLOG}; - -} // namespace acl - -namespace broker { - - -class AclModule -{ - -public: - - // effienty turn off ACL on message transfer. - virtual bool doTransferAcl()=0; - - virtual bool authorise(const std::string& id, const acl::Action& action, const acl::ObjectType& objType, const std::string& name, - std::map<acl::Property, std::string>* params=0)=0; - virtual bool authorise(const std::string& id, const acl::Action& action, const acl::ObjectType& objType, const std::string& ExchangeName, - const std::string& RoutingKey)=0; - // create specilied authorise methods for cases that need faster matching as needed. - - virtual ~AclModule() {}; -}; - -} // namespace broker - -namespace acl { - -class AclHelper { - private: - AclHelper(){} - public: - static inline ObjectType getObjectType(const std::string& str) { - if (str.compare("queue") == 0) return OBJ_QUEUE; - if (str.compare("exchange") == 0) return OBJ_EXCHANGE; - if (str.compare("broker") == 0) return OBJ_BROKER; - if (str.compare("link") == 0) return OBJ_LINK; - if (str.compare("method") == 0) return OBJ_METHOD; - throw str; - } - static inline std::string getObjectTypeStr(const ObjectType o) { - switch (o) { - case OBJ_QUEUE: return "queue"; - case OBJ_EXCHANGE: return "exchange"; - case OBJ_BROKER: return "broker"; - case OBJ_LINK: return "link"; - case OBJ_METHOD: return "method"; - default: assert(false); // should never get here - } - return ""; - } - static inline Action getAction(const std::string& str) { - if (str.compare("consume") == 0) return ACT_CONSUME; - if (str.compare("publish") == 0) return ACT_PUBLISH; - if (str.compare("create") == 0) return ACT_CREATE; - if (str.compare("access") == 0) return ACT_ACCESS; - if (str.compare("bind") == 0) return ACT_BIND; - if (str.compare("unbind") == 0) return ACT_UNBIND; - if (str.compare("delete") == 0) return ACT_DELETE; - if (str.compare("purge") == 0) return ACT_PURGE; - if (str.compare("update") == 0) return ACT_UPDATE; - throw str; - } - static inline std::string getActionStr(const Action a) { - switch (a) { - case ACT_CONSUME: return "consume"; - case ACT_PUBLISH: return "publish"; - case ACT_CREATE: return "create"; - case ACT_ACCESS: return "access"; - case ACT_BIND: return "bind"; - case ACT_UNBIND: return "unbind"; - case ACT_DELETE: return "delete"; - case ACT_PURGE: return "purge"; - case ACT_UPDATE: return "update"; - default: assert(false); // should never get here - } - return ""; - } - static inline Property getProperty(const std::string& str) { - if (str.compare("name") == 0) return PROP_NAME; - if (str.compare("durable") == 0) return PROP_DURABLE; - if (str.compare("owner") == 0) return PROP_OWNER; - if (str.compare("routingkey") == 0) return PROP_ROUTINGKEY; - if (str.compare("passive") == 0) return PROP_PASSIVE; - if (str.compare("autodelete") == 0) return PROP_AUTODELETE; - if (str.compare("exclusive") == 0) return PROP_EXCLUSIVE; - if (str.compare("type") == 0) return PROP_TYPE; - if (str.compare("alternate") == 0) return PROP_ALTERNATE; - if (str.compare("queuename") == 0) return PROP_QUEUENAME; - if (str.compare("schemapackage") == 0) return PROP_SCHEMAPACKAGE; - if (str.compare("schemaclass") == 0) return PROP_SCHEMACLASS; - if (str.compare("policytype") == 0) return PROP_POLICYTYPE; - if (str.compare("maxqueuesize") == 0) return PROP_MAXQUEUESIZE; - if (str.compare("maxqueuecount") == 0) return PROP_MAXQUEUECOUNT; - throw str; - } - static inline std::string getPropertyStr(const Property p) { - switch (p) { - case PROP_NAME: return "name"; - case PROP_DURABLE: return "durable"; - case PROP_OWNER: return "owner"; - case PROP_ROUTINGKEY: return "routingkey"; - case PROP_PASSIVE: return "passive"; - case PROP_AUTODELETE: return "autodelete"; - case PROP_EXCLUSIVE: return "exclusive"; - case PROP_TYPE: return "type"; - case PROP_ALTERNATE: return "alternate"; - case PROP_QUEUENAME: return "queuename"; - case PROP_SCHEMAPACKAGE: return "schemapackage"; - case PROP_SCHEMACLASS: return "schemaclass"; - case PROP_POLICYTYPE: return "policytype"; - case PROP_MAXQUEUESIZE: return "maxqueuesize"; - case PROP_MAXQUEUECOUNT: return "maxqueuecount"; - default: assert(false); // should never get here - } - return ""; - } - static inline AclResult getAclResult(const std::string& str) { - if (str.compare("allow") == 0) return ALLOW; - if (str.compare("allow-log") == 0) return ALLOWLOG; - if (str.compare("deny") == 0) return DENY; - if (str.compare("deny-log") == 0) return DENYLOG; - throw str; - } - static inline std::string getAclResultStr(const AclResult r) { - switch (r) { - case ALLOW: return "allow"; - case ALLOWLOG: return "allow-log"; - case DENY: return "deny"; - case DENYLOG: return "deny-log"; - default: assert(false); // should never get here - } - return ""; - } - - typedef std::set<Property> propSet; - typedef boost::shared_ptr<propSet> propSetPtr; - typedef std::pair<Action, propSetPtr> actionPair; - typedef std::map<Action, propSetPtr> actionMap; - typedef boost::shared_ptr<actionMap> actionMapPtr; - typedef std::pair<ObjectType, actionMapPtr> objectPair; - typedef std::map<ObjectType, actionMapPtr> objectMap; - typedef objectMap::const_iterator omCitr; - typedef boost::shared_ptr<objectMap> objectMapPtr; - typedef std::map<Property, std::string> propMap; - typedef propMap::const_iterator propMapItr; - - // This map contains the legal combinations of object/action/properties found in an ACL file - static void loadValidationMap(objectMapPtr& map) { - if (!map.get()) return; - map->clear(); - propSetPtr p0; // empty ptr, used for no properties - - // == Exchanges == - - propSetPtr p1(new propSet); - p1->insert(PROP_TYPE); - p1->insert(PROP_ALTERNATE); - p1->insert(PROP_PASSIVE); - p1->insert(PROP_DURABLE); - - propSetPtr p2(new propSet); - p2->insert(PROP_ROUTINGKEY); - - propSetPtr p3(new propSet); - p3->insert(PROP_QUEUENAME); - p3->insert(PROP_ROUTINGKEY); - - actionMapPtr a0(new actionMap); - a0->insert(actionPair(ACT_CREATE, p1)); - a0->insert(actionPair(ACT_DELETE, p0)); - a0->insert(actionPair(ACT_ACCESS, p0)); - a0->insert(actionPair(ACT_BIND, p2)); - a0->insert(actionPair(ACT_UNBIND, p2)); - a0->insert(actionPair(ACT_ACCESS, p3)); - a0->insert(actionPair(ACT_PUBLISH, p0)); - - map->insert(objectPair(OBJ_EXCHANGE, a0)); - - // == Queues == - - propSetPtr p4(new propSet); - p4->insert(PROP_ALTERNATE); - p4->insert(PROP_PASSIVE); - p4->insert(PROP_DURABLE); - p4->insert(PROP_EXCLUSIVE); - p4->insert(PROP_AUTODELETE); - p4->insert(PROP_POLICYTYPE); - p4->insert(PROP_MAXQUEUESIZE); - p4->insert(PROP_MAXQUEUECOUNT); - - actionMapPtr a1(new actionMap); - a1->insert(actionPair(ACT_ACCESS, p0)); - a1->insert(actionPair(ACT_CREATE, p4)); - a1->insert(actionPair(ACT_PURGE, p0)); - a1->insert(actionPair(ACT_DELETE, p0)); - a1->insert(actionPair(ACT_CONSUME, p0)); - - map->insert(objectPair(OBJ_QUEUE, a1)); - - // == Links == - - actionMapPtr a2(new actionMap); - a2->insert(actionPair(ACT_CREATE, p0)); - - map->insert(objectPair(OBJ_LINK, a2)); - - // == Method == - - propSetPtr p5(new propSet); - p5->insert(PROP_SCHEMAPACKAGE); - p5->insert(PROP_SCHEMACLASS); - - actionMapPtr a4(new actionMap); - a4->insert(actionPair(ACT_ACCESS, p5)); - - map->insert(objectPair(OBJ_METHOD, a4)); - } - - static std::string propertyMapToString(const std::map<Property, std::string>* params) { - std::ostringstream ss; - ss << "{"; - if (params) - { - for (propMapItr pMItr = params->begin(); pMItr != params->end(); pMItr++) { - ss << " " << getPropertyStr((Property) pMItr-> first) << "=" << pMItr->second; - } - } - ss << " }"; - return ss.str(); - } -}; - - -}} // namespace qpid::acl - -#endif // QPID_ACLMODULE_ACL_H diff --git a/cpp/src/qpid/broker/AsyncCompletion.h b/cpp/src/qpid/broker/AsyncCompletion.h deleted file mode 100644 index fef994438f..0000000000 --- a/cpp/src/qpid/broker/AsyncCompletion.h +++ /dev/null @@ -1,201 +0,0 @@ -#ifndef _AsyncCompletion_ -#define _AsyncCompletion_ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <boost/intrusive_ptr.hpp> - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/sys/AtomicValue.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Monitor.h" - -namespace qpid { -namespace broker { - -/** - * Class to implement asynchronous notification of completion. - * - * Use-case: An "initiator" needs to wait for a set of "completers" to - * finish a unit of work before an action can occur. This object - * tracks the progress of the set of completers, and allows the action - * to occur once all completers have signalled that they are done. - * - * The initiator and completers may be running in separate threads. - * - * The initiating thread is the thread that initiates the action, - * i.e. the connection read thread. - * - * A completing thread is any thread that contributes to completion, - * e.g. a store thread that does an async write. - * There may be zero or more completers. - * - * When the work is complete, a callback is invoked. The callback - * may be invoked in the Initiator thread, or one of the Completer - * threads. The callback is passed a flag indicating whether or not - * the callback is running under the context of the Initiator thread. - * - * Use model: - * 1) Initiator thread invokes begin() - * 2) After begin() has been invoked, zero or more Completers invoke - * startCompleter(). Completers may be running in the same or - * different thread as the Initiator, as long as they guarantee that - * startCompleter() is invoked at least once before the Initiator invokes end(). - * 3) Completers may invoke finishCompleter() at any time, even after the - * initiator has invoked end(). finishCompleter() may be called from any - * thread. - * 4) startCompleter()/finishCompleter() calls "nest": for each call to - * startCompleter(), a corresponding call to finishCompleter() must be made. - * Once the last finishCompleter() is called, the Completer must no longer - * reference the completion object. - * 5) The Initiator invokes end() at the point where it has finished - * dispatching work to the Completers, and is prepared for the callback - * handler to be invoked. Note: if there are no outstanding Completers - * pending when the Initiator invokes end(), the callback will be invoked - * directly, and the sync parameter will be set true. This indicates to the - * Initiator that the callback is executing in the context of the end() call, - * and the Initiator is free to optimize the handling of the completion, - * assuming no need for synchronization with Completer threads. - */ - -class AsyncCompletion -{ - public: - - /** Supplied by the Initiator to the end() method, allows for a callback - * when all outstanding completers are done. If the callback cannot be - * made during the end() call, the clone() method must supply a copy of - * this callback object that persists after end() returns. The cloned - * callback object will be used by the last completer thread, and - * released when the callback returns. - */ - class Callback : public RefCounted - { - public: - virtual void completed(bool) = 0; - virtual boost::intrusive_ptr<Callback> clone() = 0; - }; - - private: - mutable qpid::sys::AtomicValue<uint32_t> completionsNeeded; - mutable qpid::sys::Monitor callbackLock; - bool inCallback, active; - - void invokeCallback(bool sync) { - qpid::sys::Mutex::ScopedLock l(callbackLock); - if (active) { - if (callback.get()) { - inCallback = true; - { - qpid::sys::Mutex::ScopedUnlock ul(callbackLock); - callback->completed(sync); - } - inCallback = false; - callback = boost::intrusive_ptr<Callback>(); - callbackLock.notifyAll(); - } - active = false; - } - } - - protected: - /** Invoked when all completers have signalled that they have completed - * (via calls to finishCompleter()). bool == true if called via end() - */ - boost::intrusive_ptr<Callback> callback; - - public: - AsyncCompletion() : completionsNeeded(0), inCallback(false), active(true) {}; - virtual ~AsyncCompletion() { cancel(); } - - - /** True when all outstanding operations have compeleted - */ - bool isDone() - { - return !active; - } - - /** Called to signal the start of an asynchronous operation. The operation - * is considered pending until finishCompleter() is called. - * E.g. called when initiating an async store operation. - */ - void startCompleter() { ++completionsNeeded; } - - /** Called by completer to signal that it has finished the operation started - * when startCompleter() was invoked. - * e.g. called when async write complete. - */ - void finishCompleter() - { - if (--completionsNeeded == 0) { - invokeCallback(false); - } - } - - /** called by initiator before any calls to startCompleter can be done. - */ - void begin() - { - ++completionsNeeded; - } - - /** called by initiator after all potential completers have called - * startCompleter(). - */ - void end(Callback& cb) - { - assert(completionsNeeded.get() > 0); // ensure begin() has been called! - // the following only "decrements" the count if it is 1. This means - // there are no more outstanding completers and we are done. - if (completionsNeeded.boolCompareAndSwap(1, 0)) { - // done! Complete immediately - cb.completed(true); - return; - } - - // the compare-and-swap did not succeed. This means there are - // outstanding completers pending (count > 1). Get a persistent - // Callback object to use when the last completer is done. - // Decrement after setting up the callback ensures that pending - // completers cannot touch the callback until it is ready. - callback = cb.clone(); - if (--completionsNeeded == 0) { - // note that a completer may have completed during the - // callback setup or decrement: - invokeCallback(true); - } - } - - /** may be called by Initiator to cancel the callback. Will wait for - * callback to complete if in progress. - */ - virtual void cancel() { - qpid::sys::Mutex::ScopedLock l(callbackLock); - while (inCallback) callbackLock.wait(); - callback = boost::intrusive_ptr<Callback>(); - active = false; - } -}; - -}} // qpid::broker:: -#endif /*!_AsyncCompletion_*/ diff --git a/cpp/src/qpid/broker/Bridge.cpp b/cpp/src/qpid/broker/Bridge.cpp deleted file mode 100644 index 7fbbf4e2c4..0000000000 --- a/cpp/src/qpid/broker/Bridge.cpp +++ /dev/null @@ -1,323 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/Bridge.h" -#include "qpid/broker/FedOps.h" -#include "qpid/broker/ConnectionState.h" -#include "qpid/broker/Connection.h" -#include "qpid/broker/Link.h" -#include "qpid/broker/LinkRegistry.h" -#include "qpid/broker/SessionState.h" - -#include "qpid/management/ManagementAgent.h" -#include "qpid/framing/Uuid.h" -#include "qpid/log/Statement.h" -#include <iostream> - -using qpid::framing::FieldTable; -using qpid::framing::Uuid; -using qpid::framing::Buffer; -using qpid::management::ManagementAgent; -using std::string; -namespace _qmf = qmf::org::apache::qpid::broker; - -namespace qpid { -namespace broker { - -void Bridge::PushHandler::handle(framing::AMQFrame& frame) -{ - conn->received(frame); -} - -Bridge::Bridge(Link* _link, framing::ChannelId _id, CancellationListener l, - const _qmf::ArgsLinkBridge& _args) : - link(_link), id(_id), args(_args), mgmtObject(0), - listener(l), name(Uuid(true).str()), queueName("bridge_queue_"), persistenceId(0) -{ - std::stringstream title; - title << id << "_" << link->getBroker()->getFederationTag(); - queueName += title.str(); - ManagementAgent* agent = link->getBroker()->getManagementAgent(); - if (agent != 0) { - mgmtObject = new _qmf::Bridge - (agent, this, link, id, args.i_durable, args.i_src, args.i_dest, - args.i_key, args.i_srcIsQueue, args.i_srcIsLocal, - args.i_tag, args.i_excludes, args.i_dynamic, args.i_sync); - agent->addObject(mgmtObject); - } - QPID_LOG(debug, "Bridge created from " << args.i_src << " to " << args.i_dest); -} - -Bridge::~Bridge() -{ - mgmtObject->resourceDestroy(); -} - -void Bridge::create(Connection& c) -{ - connState = &c; - conn = &c; - FieldTable options; - if (args.i_sync) options.setInt("qpid.sync_frequency", args.i_sync); - SessionHandler& sessionHandler = c.getChannel(id); - if (args.i_srcIsLocal) { - if (args.i_dynamic) - throw Exception("Dynamic routing not supported for push routes"); - // Point the bridging commands at the local connection handler - pushHandler.reset(new PushHandler(&c)); - channelHandler.reset(new framing::ChannelHandler(id, pushHandler.get())); - - session.reset(new framing::AMQP_ServerProxy::Session(*channelHandler)); - peer.reset(new framing::AMQP_ServerProxy(*channelHandler)); - - session->attach(name, false); - session->commandPoint(0,0); - } else { - sessionHandler.attachAs(name); - // Point the bridging commands at the remote peer broker - peer.reset(new framing::AMQP_ServerProxy(sessionHandler.out)); - } - - if (args.i_srcIsLocal) sessionHandler.getSession()->disableReceiverTracking(); - if (args.i_srcIsQueue) { - peer->getMessage().subscribe(args.i_src, args.i_dest, args.i_sync ? 0 : 1, 0, false, "", 0, options); - peer->getMessage().flow(args.i_dest, 0, 0xFFFFFFFF); - peer->getMessage().flow(args.i_dest, 1, 0xFFFFFFFF); - QPID_LOG(debug, "Activated route from queue " << args.i_src << " to " << args.i_dest); - } else { - FieldTable queueSettings; - - if (args.i_tag.size()) { - queueSettings.setString("qpid.trace.id", args.i_tag); - } else { - const string& peerTag = c.getFederationPeerTag(); - if (peerTag.size()) - queueSettings.setString("qpid.trace.id", peerTag); - } - - if (args.i_excludes.size()) { - queueSettings.setString("qpid.trace.exclude", args.i_excludes); - } else { - const string& localTag = link->getBroker()->getFederationTag(); - if (localTag.size()) - queueSettings.setString("qpid.trace.exclude", localTag); - } - - bool durable = false;//should this be an arg, or would we use srcIsQueue for durable queues? - bool autoDelete = !durable;//auto delete transient queues? - peer->getQueue().declare(queueName, "", false, durable, true, autoDelete, queueSettings); - if (!args.i_dynamic) - peer->getExchange().bind(queueName, args.i_src, args.i_key, FieldTable()); - peer->getMessage().subscribe(queueName, args.i_dest, 1, 0, false, "", 0, FieldTable()); - peer->getMessage().flow(args.i_dest, 0, 0xFFFFFFFF); - peer->getMessage().flow(args.i_dest, 1, 0xFFFFFFFF); - - if (args.i_dynamic) { - Exchange::shared_ptr exchange = link->getBroker()->getExchanges().get(args.i_src); - if (exchange.get() == 0) - throw Exception("Exchange not found for dynamic route"); - exchange->registerDynamicBridge(this); - QPID_LOG(debug, "Activated dynamic route for exchange " << args.i_src); - } else { - QPID_LOG(debug, "Activated static route from exchange " << args.i_src << " to " << args.i_dest); - } - } - if (args.i_srcIsLocal) sessionHandler.getSession()->enableReceiverTracking(); -} - -void Bridge::cancel(Connection&) -{ - if (resetProxy()) { - peer->getMessage().cancel(args.i_dest); - peer->getSession().detach(name); - } -} - -void Bridge::closed() -{ - if (args.i_dynamic) { - Exchange::shared_ptr exchange = link->getBroker()->getExchanges().get(args.i_src); - if (exchange.get() != 0) - exchange->removeDynamicBridge(this); - } -} - -void Bridge::destroy() -{ - listener(this); -} - -void Bridge::setPersistenceId(uint64_t pId) const -{ - persistenceId = pId; -} - -const string& Bridge::getName() const -{ - return name; -} - -Bridge::shared_ptr Bridge::decode(LinkRegistry& links, Buffer& buffer) -{ - string host; - uint16_t port; - string src; - string dest; - string key; - string id; - string excludes; - - buffer.getShortString(host); - port = buffer.getShort(); - bool durable(buffer.getOctet()); - buffer.getShortString(src); - buffer.getShortString(dest); - buffer.getShortString(key); - bool is_queue(buffer.getOctet()); - bool is_local(buffer.getOctet()); - buffer.getShortString(id); - buffer.getShortString(excludes); - bool dynamic(buffer.getOctet()); - uint16_t sync = buffer.getShort(); - - return links.declare(host, port, durable, src, dest, key, - is_queue, is_local, id, excludes, dynamic, sync).first; -} - -void Bridge::encode(Buffer& buffer) const -{ - buffer.putShortString(string("bridge")); - buffer.putShortString(link->getHost()); - buffer.putShort(link->getPort()); - buffer.putOctet(args.i_durable ? 1 : 0); - buffer.putShortString(args.i_src); - buffer.putShortString(args.i_dest); - buffer.putShortString(args.i_key); - buffer.putOctet(args.i_srcIsQueue ? 1 : 0); - buffer.putOctet(args.i_srcIsLocal ? 1 : 0); - buffer.putShortString(args.i_tag); - buffer.putShortString(args.i_excludes); - buffer.putOctet(args.i_dynamic ? 1 : 0); - buffer.putShort(args.i_sync); -} - -uint32_t Bridge::encodedSize() const -{ - return link->getHost().size() + 1 // short-string (host) - + 7 // short-string ("bridge") - + 2 // port - + 1 // durable - + args.i_src.size() + 1 - + args.i_dest.size() + 1 - + args.i_key.size() + 1 - + 1 // srcIsQueue - + 1 // srcIsLocal - + args.i_tag.size() + 1 - + args.i_excludes.size() + 1 - + 1 // dynamic - + 2; // sync -} - -management::ManagementObject* Bridge::GetManagementObject (void) const -{ - return (management::ManagementObject*) mgmtObject; -} - -management::Manageable::status_t Bridge::ManagementMethod(uint32_t methodId, - management::Args& /*args*/, - string&) -{ - if (methodId == _qmf::Bridge::METHOD_CLOSE) { - //notify that we are closed - destroy(); - return management::Manageable::STATUS_OK; - } else { - return management::Manageable::STATUS_UNKNOWN_METHOD; - } -} - -void Bridge::propagateBinding(const string& key, const string& tagList, - const string& op, const string& origin, - qpid::framing::FieldTable* extra_args) -{ - const string& localTag = link->getBroker()->getFederationTag(); - const string& peerTag = connState->getFederationPeerTag(); - - if (tagList.find(peerTag) == tagList.npos) { - FieldTable bindArgs; - if (extra_args) { - for (qpid::framing::FieldTable::ValueMap::iterator i=extra_args->begin(); i != extra_args->end(); ++i) { - bindArgs.insert((*i)); - } - } - string newTagList(tagList + string(tagList.empty() ? "" : ",") + localTag); - - bindArgs.setString(qpidFedOp, op); - bindArgs.setString(qpidFedTags, newTagList); - if (origin.empty()) - bindArgs.setString(qpidFedOrigin, localTag); - else - bindArgs.setString(qpidFedOrigin, origin); - - conn->requestIOProcessing(boost::bind(&Bridge::ioThreadPropagateBinding, this, - queueName, args.i_src, key, bindArgs)); - } -} - -void Bridge::sendReorigin() -{ - FieldTable bindArgs; - - bindArgs.setString(qpidFedOp, fedOpReorigin); - bindArgs.setString(qpidFedTags, link->getBroker()->getFederationTag()); - - conn->requestIOProcessing(boost::bind(&Bridge::ioThreadPropagateBinding, this, - queueName, args.i_src, args.i_key, bindArgs)); -} -bool Bridge::resetProxy() -{ - SessionHandler& sessionHandler = conn->getChannel(id); - if (!sessionHandler.getSession()) peer.reset(); - else peer.reset(new framing::AMQP_ServerProxy(sessionHandler.out)); - return peer.get(); -} - -void Bridge::ioThreadPropagateBinding(const string& queue, const string& exchange, const string& key, FieldTable args) -{ - if (resetProxy()) { - peer->getExchange().bind(queue, exchange, key, args); - } else { - QPID_LOG(error, "Cannot propagate binding for dynamic bridge as session has been detached, deleting dynamic bridge"); - destroy(); - } -} - -bool Bridge::containsLocalTag(const string& tagList) const -{ - const string& localTag = link->getBroker()->getFederationTag(); - return (tagList.find(localTag) != tagList.npos); -} - -const string& Bridge::getLocalTag() const -{ - return link->getBroker()->getFederationTag(); -} - -}} diff --git a/cpp/src/qpid/broker/Bridge.h b/cpp/src/qpid/broker/Bridge.h deleted file mode 100644 index a846254c57..0000000000 --- a/cpp/src/qpid/broker/Bridge.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _Bridge_ -#define _Bridge_ - -#include "qpid/broker/PersistableConfig.h" -#include "qpid/framing/AMQP_ServerProxy.h" -#include "qpid/framing/ChannelHandler.h" -#include "qpid/framing/Buffer.h" -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/management/Manageable.h" -#include "qpid/broker/Exchange.h" -#include "qmf/org/apache/qpid/broker/ArgsLinkBridge.h" -#include "qmf/org/apache/qpid/broker/Bridge.h" - -#include <boost/function.hpp> -#include <memory> - -namespace qpid { -namespace broker { - -class Connection; -class ConnectionState; -class Link; -class LinkRegistry; - -class Bridge : public PersistableConfig, public management::Manageable, public Exchange::DynamicBridge -{ -public: - typedef boost::shared_ptr<Bridge> shared_ptr; - typedef boost::function<void(Bridge*)> CancellationListener; - - Bridge(Link* link, framing::ChannelId id, CancellationListener l, - const qmf::org::apache::qpid::broker::ArgsLinkBridge& args); - ~Bridge(); - - void create(Connection& c); - void cancel(Connection& c); - void closed(); - void destroy(); - bool isDurable() { return args.i_durable; } - - management::ManagementObject* GetManagementObject() const; - management::Manageable::status_t ManagementMethod(uint32_t methodId, - management::Args& args, - std::string& text); - - // PersistableConfig: - void setPersistenceId(uint64_t id) const; - uint64_t getPersistenceId() const { return persistenceId; } - uint32_t encodedSize() const; - void encode(framing::Buffer& buffer) const; - const std::string& getName() const; - static Bridge::shared_ptr decode(LinkRegistry& links, framing::Buffer& buffer); - - // Exchange::DynamicBridge methods - void propagateBinding(const std::string& key, const std::string& tagList, const std::string& op, const std::string& origin, qpid::framing::FieldTable* extra_args=0); - void sendReorigin(); - void ioThreadPropagateBinding(const std::string& queue, const std::string& exchange, const std::string& key, framing::FieldTable args); - bool containsLocalTag(const std::string& tagList) const; - const std::string& getLocalTag() const; - -private: - struct PushHandler : framing::FrameHandler { - PushHandler(Connection* c) { conn = c; } - void handle(framing::AMQFrame& frame); - Connection* conn; - }; - - std::auto_ptr<PushHandler> pushHandler; - std::auto_ptr<framing::ChannelHandler> channelHandler; - std::auto_ptr<framing::AMQP_ServerProxy::Session> session; - std::auto_ptr<framing::AMQP_ServerProxy> peer; - - Link* link; - framing::ChannelId id; - qmf::org::apache::qpid::broker::ArgsLinkBridge args; - qmf::org::apache::qpid::broker::Bridge* mgmtObject; - CancellationListener listener; - std::string name; - std::string queueName; - mutable uint64_t persistenceId; - ConnectionState* connState; - Connection* conn; - - bool resetProxy(); -}; - - -}} - -#endif diff --git a/cpp/src/qpid/broker/Broker.cpp b/cpp/src/qpid/broker/Broker.cpp deleted file mode 100644 index 240766c443..0000000000 --- a/cpp/src/qpid/broker/Broker.cpp +++ /dev/null @@ -1,967 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/Broker.h" -#include "qpid/broker/ConnectionState.h" -#include "qpid/broker/DirectExchange.h" -#include "qpid/broker/FanOutExchange.h" -#include "qpid/broker/HeadersExchange.h" -#include "qpid/broker/MessageStoreModule.h" -#include "qpid/broker/NullMessageStore.h" -#include "qpid/broker/RecoveryManagerImpl.h" -#include "qpid/broker/SaslAuthenticator.h" -#include "qpid/broker/SecureConnectionFactory.h" -#include "qpid/broker/TopicExchange.h" -#include "qpid/broker/Link.h" -#include "qpid/broker/ExpiryPolicy.h" -#include "qpid/broker/QueueFlowLimit.h" - -#include "qmf/org/apache/qpid/broker/Package.h" -#include "qmf/org/apache/qpid/broker/ArgsBrokerCreate.h" -#include "qmf/org/apache/qpid/broker/ArgsBrokerDelete.h" -#include "qmf/org/apache/qpid/broker/ArgsBrokerEcho.h" -#include "qmf/org/apache/qpid/broker/ArgsBrokerGetLogLevel.h" -#include "qmf/org/apache/qpid/broker/ArgsBrokerQueueMoveMessages.h" -#include "qmf/org/apache/qpid/broker/ArgsBrokerSetLogLevel.h" -#include "qmf/org/apache/qpid/broker/EventExchangeDeclare.h" -#include "qmf/org/apache/qpid/broker/EventExchangeDelete.h" -#include "qmf/org/apache/qpid/broker/EventQueueDeclare.h" -#include "qmf/org/apache/qpid/broker/EventQueueDelete.h" -#include "qmf/org/apache/qpid/broker/EventBind.h" -#include "qmf/org/apache/qpid/broker/EventUnbind.h" -#include "qpid/amqp_0_10/Codecs.h" -#include "qpid/management/ManagementDirectExchange.h" -#include "qpid/management/ManagementTopicExchange.h" -#include "qpid/log/Logger.h" -#include "qpid/log/Options.h" -#include "qpid/log/Statement.h" -#include "qpid/log/posix/SinkOptions.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/ProtocolInitiation.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/Uuid.h" -#include "qpid/sys/ProtocolFactory.h" -#include "qpid/sys/Poller.h" -#include "qpid/sys/Dispatcher.h" -#include "qpid/sys/Thread.h" -#include "qpid/sys/Time.h" -#include "qpid/sys/ConnectionInputHandler.h" -#include "qpid/sys/ConnectionInputHandlerFactory.h" -#include "qpid/sys/TimeoutHandler.h" -#include "qpid/sys/SystemInfo.h" -#include "qpid/Address.h" -#include "qpid/StringUtils.h" -#include "qpid/Url.h" -#include "qpid/Version.h" - -#include <boost/bind.hpp> -#include <boost/format.hpp> - -#include <iostream> -#include <memory> - -using qpid::sys::ProtocolFactory; -using qpid::sys::Poller; -using qpid::sys::Dispatcher; -using qpid::sys::Thread; -using qpid::framing::FrameHandler; -using qpid::framing::ChannelId; -using qpid::management::ManagementAgent; -using qpid::management::ManagementObject; -using qpid::management::Manageable; -using qpid::management::Args; -using qpid::management::getManagementExecutionContext; -using qpid::types::Variant; -using std::string; -using std::make_pair; - -namespace _qmf = qmf::org::apache::qpid::broker; - -namespace qpid { -namespace broker { - -Broker::Options::Options(const std::string& name) : - qpid::Options(name), - noDataDir(0), - port(DEFAULT_PORT), - workerThreads(5), - maxConnections(500), - connectionBacklog(10), - enableMgmt(1), - mgmtPubInterval(10), - queueCleanInterval(60*10),//10 minutes - auth(SaslAuthenticator::available()), - realm("QPID"), - replayFlushLimit(0), - replayHardLimit(0), - queueLimit(100*1048576/*100M default limit*/), - tcpNoDelay(false), - requireEncrypted(false), - maxSessionRate(0), - asyncQueueEvents(false), // Must be false in a cluster. - qmf2Support(true), - qmf1Support(true), - queueFlowStopRatio(80), - queueFlowResumeRatio(70), - queueThresholdEventRatio(80) -{ - int c = sys::SystemInfo::concurrency(); - workerThreads=c+1; - std::string home = getHome(); - - if (home.length() == 0) - dataDir += DEFAULT_DATA_DIR_LOCATION; - else - dataDir += home; - dataDir += DEFAULT_DATA_DIR_NAME; - - addOptions() - ("data-dir", optValue(dataDir,"DIR"), "Directory to contain persistent data generated by the broker") - ("no-data-dir", optValue(noDataDir), "Don't use a data directory. No persistent configuration will be loaded or stored") - ("port,p", optValue(port,"PORT"), "Tells the broker to listen on PORT") - ("worker-threads", optValue(workerThreads, "N"), "Sets the broker thread pool size") - ("max-connections", optValue(maxConnections, "N"), "Sets the maximum allowed connections") - ("connection-backlog", optValue(connectionBacklog, "N"), "Sets the connection backlog limit for the server socket") - ("mgmt-enable,m", optValue(enableMgmt,"yes|no"), "Enable Management") - ("mgmt-qmf2", optValue(qmf2Support,"yes|no"), "Enable broadcast of management information over QMF v2") - ("mgmt-qmf1", optValue(qmf1Support,"yes|no"), "Enable broadcast of management information over QMF v1") - ("mgmt-pub-interval", optValue(mgmtPubInterval, "SECONDS"), "Management Publish Interval") - ("queue-purge-interval", optValue(queueCleanInterval, "SECONDS"), - "Interval between attempts to purge any expired messages from queues") - ("auth", optValue(auth, "yes|no"), "Enable authentication, if disabled all incoming connections will be trusted") - ("realm", optValue(realm, "REALM"), "Use the given realm when performing authentication") - ("default-queue-limit", optValue(queueLimit, "BYTES"), "Default maximum size for queues (in bytes)") - ("tcp-nodelay", optValue(tcpNoDelay), "Set TCP_NODELAY on TCP connections") - ("require-encryption", optValue(requireEncrypted), "Only accept connections that are encrypted") - ("known-hosts-url", optValue(knownHosts, "URL or 'none'"), "URL to send as 'known-hosts' to clients ('none' implies empty list)") - ("sasl-config", optValue(saslConfigPath, "DIR"), "gets sasl config info from nonstandard location") - ("max-session-rate", optValue(maxSessionRate, "MESSAGES/S"), "Sets the maximum message rate per session (0=unlimited)") - ("async-queue-events", optValue(asyncQueueEvents, "yes|no"), "Set Queue Events async, used for services like replication") - ("default-flow-stop-threshold", optValue(queueFlowStopRatio, "PERCENT"), "Percent of queue's maximum capacity at which flow control is activated.") - ("default-flow-resume-threshold", optValue(queueFlowResumeRatio, "PERCENT"), "Percent of queue's maximum capacity at which flow control is de-activated.") - ("default-event-threshold-ratio", optValue(queueThresholdEventRatio, "%age of limit"), "The ratio of any specified queue limit at which an event will be raised"); -} - -const std::string empty; -const std::string amq_direct("amq.direct"); -const std::string amq_topic("amq.topic"); -const std::string amq_fanout("amq.fanout"); -const std::string amq_match("amq.match"); -const std::string qpid_management("qpid.management"); -const std::string knownHostsNone("none"); - -Broker::Broker(const Broker::Options& conf) : - poller(new Poller), - config(conf), - managementAgent(conf.enableMgmt ? new ManagementAgent(conf.qmf1Support, - conf.qmf2Support) - : 0), - store(new NullMessageStore), - acl(0), - dataDir(conf.noDataDir ? std::string() : conf.dataDir), - queues(this), - exchanges(this), - links(this), - factory(new SecureConnectionFactory(*this)), - dtxManager(timer), - sessionManager( - qpid::SessionState::Configuration( - conf.replayFlushLimit*1024, // convert kb to bytes. - conf.replayHardLimit*1024), - *this), - queueCleaner(queues, timer), - queueEvents(poller,!conf.asyncQueueEvents), - recovery(true), - inCluster(false), - clusterUpdatee(false), - expiryPolicy(new ExpiryPolicy), - connectionCounter(conf.maxConnections), - getKnownBrokers(boost::bind(&Broker::getKnownBrokersImpl, this)), - deferDelivery(boost::bind(&Broker::deferDeliveryImpl, this, _1, _2)) -{ - try { - if (conf.enableMgmt) { - QPID_LOG(info, "Management enabled"); - managementAgent->configure(dataDir.isEnabled() ? dataDir.getPath() : string(), - conf.mgmtPubInterval, this, conf.workerThreads + 3); - managementAgent->setName("apache.org", "qpidd"); - _qmf::Package packageInitializer(managementAgent.get()); - - System* system = new System (dataDir.isEnabled() ? dataDir.getPath() : string(), this); - systemObject = System::shared_ptr(system); - - mgmtObject = new _qmf::Broker(managementAgent.get(), this, system, "amqp-broker"); - mgmtObject->set_systemRef(system->GetManagementObject()->getObjectId()); - mgmtObject->set_port(conf.port); - mgmtObject->set_workerThreads(conf.workerThreads); - mgmtObject->set_maxConns(conf.maxConnections); - mgmtObject->set_connBacklog(conf.connectionBacklog); - mgmtObject->set_mgmtPubInterval(conf.mgmtPubInterval); - mgmtObject->set_version(qpid::version); - if (dataDir.isEnabled()) - mgmtObject->set_dataDir(dataDir.getPath()); - else - mgmtObject->clr_dataDir(); - - managementAgent->addObject(mgmtObject, 0, true); - - // Since there is currently no support for virtual hosts, a placeholder object - // representing the implied single virtual host is added here to keep the - // management schema correct. - Vhost* vhost = new Vhost(this, this); - vhostObject = Vhost::shared_ptr(vhost); - framing::Uuid uuid(managementAgent->getUuid()); - federationTag = uuid.str(); - vhostObject->setFederationTag(federationTag); - - queues.setParent(vhost); - exchanges.setParent(vhost); - links.setParent(vhost); - } else { - // Management is disabled so there is no broker management ID. - // Create a unique uuid to use as the federation tag. - framing::Uuid uuid(true); - federationTag = uuid.str(); - } - - QueuePolicy::setDefaultMaxSize(conf.queueLimit); - - // Early-Initialize plugins - Plugin::earlyInitAll(*this); - - QueueFlowLimit::setDefaults(conf.queueLimit, conf.queueFlowStopRatio, conf.queueFlowResumeRatio); - - // If no plugin store module registered itself, set up the null store. - if (NullMessageStore::isNullStore(store.get())) - setStore(); - - exchanges.declare(empty, DirectExchange::typeName); // Default exchange. - - if (store.get() != 0) { - // The cluster plug-in will setRecovery(false) on all but the first - // broker to join a cluster. - if (getRecovery()) { - RecoveryManagerImpl recoverer(queues, exchanges, links, dtxManager); - store->recover(recoverer); - } - else { - QPID_LOG(notice, "Cluster recovery: recovered journal data discarded and journal files pushed down"); - store->truncateInit(true); // save old files in subdir - } - } - - //ensure standard exchanges exist (done after recovery from store) - declareStandardExchange(amq_direct, DirectExchange::typeName); - declareStandardExchange(amq_topic, TopicExchange::typeName); - declareStandardExchange(amq_fanout, FanOutExchange::typeName); - declareStandardExchange(amq_match, HeadersExchange::typeName); - - if(conf.enableMgmt) { - exchanges.declare(qpid_management, ManagementTopicExchange::typeName); - Exchange::shared_ptr mExchange = exchanges.get(qpid_management); - Exchange::shared_ptr dExchange = exchanges.get(amq_direct); - managementAgent->setExchange(mExchange, dExchange); - boost::dynamic_pointer_cast<ManagementTopicExchange>(mExchange)->setManagmentAgent(managementAgent.get(), 1); - - std::string qmfTopic("qmf.default.topic"); - std::string qmfDirect("qmf.default.direct"); - - std::pair<Exchange::shared_ptr, bool> topicPair(exchanges.declare(qmfTopic, ManagementTopicExchange::typeName)); - std::pair<Exchange::shared_ptr, bool> directPair(exchanges.declare(qmfDirect, ManagementDirectExchange::typeName)); - - boost::dynamic_pointer_cast<ManagementDirectExchange>(directPair.first)->setManagmentAgent(managementAgent.get(), 2); - boost::dynamic_pointer_cast<ManagementTopicExchange>(topicPair.first)->setManagmentAgent(managementAgent.get(), 2); - - managementAgent->setExchangeV2(topicPair.first, directPair.first); - } - else - QPID_LOG(info, "Management not enabled"); - - /** - * SASL setup, can fail and terminate startup - */ - if (conf.auth) { - SaslAuthenticator::init(qpid::saslName, conf.saslConfigPath); - QPID_LOG(info, "SASL enabled"); - } else { - QPID_LOG(notice, "SASL disabled: No Authentication Performed"); - } - - // Initialize plugins - Plugin::initializeAll(*this); - - if (managementAgent.get()) managementAgent->pluginsInitialized(); - - if (conf.queueCleanInterval) { - queueCleaner.start(conf.queueCleanInterval * qpid::sys::TIME_SEC); - } - - //initialize known broker urls (TODO: add support for urls for other transports (SSL, RDMA)): - if (conf.knownHosts.empty()) { - boost::shared_ptr<ProtocolFactory> factory = getProtocolFactory(TCP_TRANSPORT); - if (factory) { - knownBrokers.push_back ( qpid::Url::getIpAddressesUrl ( factory->getPort() ) ); - } - } else if (conf.knownHosts != knownHostsNone) { - knownBrokers.push_back(Url(conf.knownHosts)); - } - } catch (const std::exception& /*e*/) { - finalize(); - throw; - } -} - -void Broker::declareStandardExchange(const std::string& name, const std::string& type) -{ - bool storeEnabled = store.get() != NULL; - std::pair<Exchange::shared_ptr, bool> status = exchanges.declare(name, type, storeEnabled); - if (status.second && storeEnabled) { - store->create(*status.first, framing::FieldTable ()); - } -} - - -boost::intrusive_ptr<Broker> Broker::create(int16_t port) -{ - Options config; - config.port=port; - return create(config); -} - -boost::intrusive_ptr<Broker> Broker::create(const Options& opts) -{ - return boost::intrusive_ptr<Broker>(new Broker(opts)); -} - -void Broker::setStore (boost::shared_ptr<MessageStore>& _store) -{ - store.reset(new MessageStoreModule (_store)); - setStore(); -} - -void Broker::setStore () { - queues.setStore (store.get()); - dtxManager.setStore (store.get()); - links.setStore (store.get()); -} - -void Broker::run() { - if (config.workerThreads > 0) { - QPID_LOG(notice, "Broker running"); - Dispatcher d(poller); - int numIOThreads = config.workerThreads; - std::vector<Thread> t(numIOThreads-1); - - // Run n-1 io threads - for (int i=0; i<numIOThreads-1; ++i) - t[i] = Thread(d); - - // Run final thread - d.run(); - - // Now wait for n-1 io threads to exit - for (int i=0; i<numIOThreads-1; ++i) { - t[i].join(); - } - } else { - throw Exception((boost::format("Invalid value for worker-threads: %1%") % config.workerThreads).str()); - } -} - -void Broker::shutdown() { - // NB: this function must be async-signal safe, it must not - // call any function that is not async-signal safe. - // Any unsafe shutdown actions should be done in the destructor. - poller->shutdown(); -} - -Broker::~Broker() { - shutdown(); - queueEvents.shutdown(); - finalize(); // Finalize any plugins. - if (config.auth) - SaslAuthenticator::fini(); - timer.stop(); - QPID_LOG(notice, "Shut down"); -} - -ManagementObject* Broker::GetManagementObject(void) const -{ - return (ManagementObject*) mgmtObject; -} - -Manageable* Broker::GetVhostObject(void) const -{ - return vhostObject.get(); -} - -Manageable::status_t Broker::ManagementMethod (uint32_t methodId, - Args& args, - string&) -{ - Manageable::status_t status = Manageable::STATUS_UNKNOWN_METHOD; - - switch (methodId) - { - case _qmf::Broker::METHOD_ECHO : - QPID_LOG (debug, "Broker::echo(" - << dynamic_cast<_qmf::ArgsBrokerEcho&>(args).io_sequence - << ", " - << dynamic_cast<_qmf::ArgsBrokerEcho&>(args).io_body - << ")"); - status = Manageable::STATUS_OK; - break; - case _qmf::Broker::METHOD_CONNECT : { - _qmf::ArgsBrokerConnect& hp= - dynamic_cast<_qmf::ArgsBrokerConnect&>(args); - - QPID_LOG (debug, "Broker::connect()"); - string transport = hp.i_transport.empty() ? TCP_TRANSPORT : hp.i_transport; - if (!getProtocolFactory(transport)) { - QPID_LOG(error, "Transport '" << transport << "' not supported"); - return Manageable::STATUS_NOT_IMPLEMENTED; - } - std::pair<Link::shared_ptr, bool> response = - links.declare (hp.i_host, hp.i_port, transport, hp.i_durable, - hp.i_authMechanism, hp.i_username, hp.i_password); - if (hp.i_durable && response.second) - store->create(*response.first); - status = Manageable::STATUS_OK; - break; - } - case _qmf::Broker::METHOD_QUEUEMOVEMESSAGES : { - _qmf::ArgsBrokerQueueMoveMessages& moveArgs= - dynamic_cast<_qmf::ArgsBrokerQueueMoveMessages&>(args); - QPID_LOG (debug, "Broker::queueMoveMessages()"); - if (queueMoveMessages(moveArgs.i_srcQueue, moveArgs.i_destQueue, moveArgs.i_qty)) - status = Manageable::STATUS_OK; - else - return Manageable::STATUS_PARAMETER_INVALID; - break; - } - case _qmf::Broker::METHOD_SETLOGLEVEL : - setLogLevel(dynamic_cast<_qmf::ArgsBrokerSetLogLevel&>(args).i_level); - QPID_LOG (debug, "Broker::setLogLevel()"); - status = Manageable::STATUS_OK; - break; - case _qmf::Broker::METHOD_GETLOGLEVEL : - dynamic_cast<_qmf::ArgsBrokerGetLogLevel&>(args).o_level = getLogLevel(); - QPID_LOG (debug, "Broker::getLogLevel()"); - status = Manageable::STATUS_OK; - break; - case _qmf::Broker::METHOD_CREATE : - { - _qmf::ArgsBrokerCreate& a = dynamic_cast<_qmf::ArgsBrokerCreate&>(args); - createObject(a.i_type, a.i_name, a.i_properties, a.i_strict, getManagementExecutionContext()); - status = Manageable::STATUS_OK; - break; - } - case _qmf::Broker::METHOD_DELETE : - { - _qmf::ArgsBrokerDelete& a = dynamic_cast<_qmf::ArgsBrokerDelete&>(args); - deleteObject(a.i_type, a.i_name, a.i_options, getManagementExecutionContext()); - status = Manageable::STATUS_OK; - break; - } - default: - QPID_LOG (debug, "Broker ManagementMethod not implemented: id=" << methodId << "]"); - status = Manageable::STATUS_NOT_IMPLEMENTED; - break; - } - - return status; -} - -namespace -{ -const std::string TYPE_QUEUE("queue"); -const std::string TYPE_EXCHANGE("exchange"); -const std::string TYPE_TOPIC("topic"); -const std::string TYPE_BINDING("binding"); -const std::string DURABLE("durable"); -const std::string AUTO_DELETE("auto-delete"); -const std::string ALTERNATE_EXCHANGE("alternate-exchange"); -const std::string EXCHANGE_TYPE("exchange-type"); -const std::string QUEUE_NAME("queue"); -const std::string EXCHANGE_NAME("exchange"); - -const std::string _TRUE("true"); -const std::string _FALSE("false"); -} - -struct InvalidBindingIdentifier : public qpid::Exception -{ - InvalidBindingIdentifier(const std::string& name) : qpid::Exception(name) {} - std::string getPrefix() const { return "invalid binding"; } -}; - -struct BindingIdentifier -{ - std::string exchange; - std::string queue; - std::string key; - - BindingIdentifier(const std::string& name) - { - std::vector<std::string> path; - split(path, name, "/"); - switch (path.size()) { - case 1: - queue = path[0]; - break; - case 2: - exchange = path[0]; - queue = path[1]; - break; - case 3: - exchange = path[0]; - queue = path[1]; - key = path[2]; - break; - default: - throw InvalidBindingIdentifier(name); - } - } -}; - -struct ObjectAlreadyExists : public qpid::Exception -{ - ObjectAlreadyExists(const std::string& name) : qpid::Exception(name) {} - std::string getPrefix() const { return "object already exists"; } -}; - -struct UnknownObjectType : public qpid::Exception -{ - UnknownObjectType(const std::string& type) : qpid::Exception(type) {} - std::string getPrefix() const { return "unknown object type"; } -}; - -void Broker::createObject(const std::string& type, const std::string& name, - const Variant::Map& properties, bool /*strict*/, const ConnectionState* context) -{ - std::string userId; - std::string connectionId; - if (context) { - userId = context->getUserId(); - connectionId = context->getUrl(); - } - //TODO: implement 'strict' option (check there are no unrecognised properties) - QPID_LOG (debug, "Broker::create(" << type << ", " << name << "," << properties << ")"); - if (type == TYPE_QUEUE) { - bool durable(false); - bool autodelete(false); - std::string alternateExchange; - Variant::Map extensions; - for (Variant::Map::const_iterator i = properties.begin(); i != properties.end(); ++i) { - // extract durable, auto-delete and alternate-exchange properties - if (i->first == DURABLE) durable = i->second; - else if (i->first == AUTO_DELETE) autodelete = i->second; - else if (i->first == ALTERNATE_EXCHANGE) alternateExchange = i->second.asString(); - //treat everything else as extension properties - else extensions[i->first] = i->second; - } - framing::FieldTable arguments; - amqp_0_10::translate(extensions, arguments); - - std::pair<boost::shared_ptr<Queue>, bool> result = - createQueue(name, durable, autodelete, 0, alternateExchange, arguments, userId, connectionId); - if (!result.second) { - throw ObjectAlreadyExists(name); - } - } else if (type == TYPE_EXCHANGE || type == TYPE_TOPIC) { - bool durable(false); - std::string exchangeType("topic"); - std::string alternateExchange; - Variant::Map extensions; - for (Variant::Map::const_iterator i = properties.begin(); i != properties.end(); ++i) { - // extract durable, auto-delete and alternate-exchange properties - if (i->first == DURABLE) durable = i->second; - else if (i->first == EXCHANGE_TYPE) exchangeType = i->second.asString(); - else if (i->first == ALTERNATE_EXCHANGE) alternateExchange = i->second.asString(); - //treat everything else as extension properties - else extensions[i->first] = i->second; - } - framing::FieldTable arguments; - amqp_0_10::translate(extensions, arguments); - - try { - std::pair<boost::shared_ptr<Exchange>, bool> result = - createExchange(name, exchangeType, durable, alternateExchange, arguments, userId, connectionId); - if (!result.second) { - throw ObjectAlreadyExists(name); - } - } catch (const UnknownExchangeTypeException&) { - throw Exception(QPID_MSG("Invalid exchange type: " << exchangeType)); - } - } else if (type == TYPE_BINDING) { - BindingIdentifier binding(name); - std::string exchangeType("topic"); - Variant::Map extensions; - for (Variant::Map::const_iterator i = properties.begin(); i != properties.end(); ++i) { - // extract durable, auto-delete and alternate-exchange properties - if (i->first == EXCHANGE_TYPE) exchangeType = i->second.asString(); - //treat everything else as extension properties - else extensions[i->first] = i->second; - } - framing::FieldTable arguments; - amqp_0_10::translate(extensions, arguments); - - bind(binding.queue, binding.exchange, binding.key, arguments, userId, connectionId); - } else { - throw UnknownObjectType(type); - } -} - -void Broker::deleteObject(const std::string& type, const std::string& name, - const Variant::Map& options, const ConnectionState* context) -{ - std::string userId; - std::string connectionId; - if (context) { - userId = context->getUserId(); - connectionId = context->getUrl(); - } - QPID_LOG (debug, "Broker::delete(" << type << ", " << name << "," << options << ")"); - if (type == TYPE_QUEUE) { - deleteQueue(name, userId, connectionId); - } else if (type == TYPE_EXCHANGE || type == TYPE_TOPIC) { - deleteExchange(name, userId, connectionId); - } else if (type == TYPE_BINDING) { - BindingIdentifier binding(name); - unbind(binding.queue, binding.exchange, binding.key, userId, connectionId); - } else { - throw UnknownObjectType(type); - } - -} - -void Broker::setLogLevel(const std::string& level) -{ - QPID_LOG(notice, "Changing log level to " << level); - std::vector<std::string> selectors; - split(selectors, level, ", "); - qpid::log::Logger::instance().reconfigure(selectors); -} - -std::string Broker::getLogLevel() -{ - std::string level; - const std::vector<std::string>& selectors = qpid::log::Logger::instance().getOptions().selectors; - for (std::vector<std::string>::const_iterator i = selectors.begin(); i != selectors.end(); ++i) { - if (i != selectors.begin()) level += std::string(","); - level += *i; - } - return level; -} - -boost::shared_ptr<ProtocolFactory> Broker::getProtocolFactory(const std::string& name) const { - ProtocolFactoryMap::const_iterator i - = name.empty() ? protocolFactories.begin() : protocolFactories.find(name); - if (i == protocolFactories.end()) return boost::shared_ptr<ProtocolFactory>(); - else return i->second; -} - -uint16_t Broker::getPort(const std::string& name) const { - boost::shared_ptr<ProtocolFactory> factory = getProtocolFactory(name); - if (factory) { - return factory->getPort(); - } else { - throw NoSuchTransportException(QPID_MSG("No such transport: '" << name << "'")); - } -} - -void Broker::registerProtocolFactory(const std::string& name, ProtocolFactory::shared_ptr protocolFactory) { - protocolFactories[name] = protocolFactory; - Url::addProtocol(name); -} - -void Broker::accept() { - for (ProtocolFactoryMap::const_iterator i = protocolFactories.begin(); i != protocolFactories.end(); i++) { - i->second->accept(poller, factory.get()); - } -} - -void Broker::connect( - const std::string& host, uint16_t port, const std::string& transport, - boost::function2<void, int, std::string> failed, - sys::ConnectionCodec::Factory* f) -{ - boost::shared_ptr<ProtocolFactory> pf = getProtocolFactory(transport); - if (pf) pf->connect(poller, host, port, f ? f : factory.get(), failed); - else throw NoSuchTransportException(QPID_MSG("Unsupported transport type: " << transport)); -} - -void Broker::connect( - const Url& url, - boost::function2<void, int, std::string> failed, - sys::ConnectionCodec::Factory* f) -{ - url.throwIfEmpty(); - const Address& addr=url[0]; - connect(addr.host, addr.port, addr.protocol, failed, f); -} - -uint32_t Broker::queueMoveMessages( - const std::string& srcQueue, - const std::string& destQueue, - uint32_t qty) -{ - Queue::shared_ptr src_queue = queues.find(srcQueue); - if (!src_queue) - return 0; - Queue::shared_ptr dest_queue = queues.find(destQueue); - if (!dest_queue) - return 0; - - return src_queue->move(dest_queue, qty); -} - - -boost::shared_ptr<sys::Poller> Broker::getPoller() { return poller; } - -std::vector<Url> -Broker::getKnownBrokersImpl() -{ - return knownBrokers; -} - -bool Broker::deferDeliveryImpl(const std::string& , - const boost::intrusive_ptr<Message>& ) -{ return false; } - -void Broker::setClusterTimer(std::auto_ptr<sys::Timer> t) { - clusterTimer = t; -} - -const std::string Broker::TCP_TRANSPORT("tcp"); - - -std::pair<boost::shared_ptr<Queue>, bool> Broker::createQueue( - const std::string& name, - bool durable, - bool autodelete, - const OwnershipToken* owner, - const std::string& alternateExchange, - const qpid::framing::FieldTable& arguments, - const std::string& userId, - const std::string& connectionId) -{ - if (acl) { - std::map<acl::Property, std::string> params; - params.insert(make_pair(acl::PROP_ALTERNATE, alternateExchange)); - params.insert(make_pair(acl::PROP_PASSIVE, _FALSE)); - params.insert(make_pair(acl::PROP_DURABLE, durable ? _TRUE : _FALSE)); - params.insert(make_pair(acl::PROP_EXCLUSIVE, owner ? _TRUE : _FALSE)); - params.insert(make_pair(acl::PROP_AUTODELETE, autodelete ? _TRUE : _FALSE)); - params.insert(make_pair(acl::PROP_POLICYTYPE, arguments.getAsString("qpid.policy_type"))); - params.insert(make_pair(acl::PROP_MAXQUEUECOUNT, boost::lexical_cast<string>(arguments.getAsInt("qpid.max_count")))); - params.insert(make_pair(acl::PROP_MAXQUEUESIZE, boost::lexical_cast<string>(arguments.getAsInt64("qpid.max_size")))); - - if (!acl->authorise(userId,acl::ACT_CREATE,acl::OBJ_QUEUE,name,¶ms) ) - throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied queue create request from " << userId)); - } - - Exchange::shared_ptr alternate; - if (!alternateExchange.empty()) { - alternate = exchanges.get(alternateExchange); - if (!alternate) throw framing::NotFoundException(QPID_MSG("Alternate exchange does not exist: " << alternateExchange)); - } - - std::pair<Queue::shared_ptr, bool> result = queues.declare(name, durable, autodelete, owner, alternate, arguments); - if (result.second) { - //add default binding: - result.first->bind(exchanges.getDefault(), name); - - if (managementAgent.get()) { - //TODO: debatable whether we should raise an event here for - //create when this is a 'declare' event; ideally add a create - //event instead? - managementAgent->raiseEvent( - _qmf::EventQueueDeclare(connectionId, userId, name, - durable, owner, autodelete, - ManagementAgent::toMap(arguments), - "created")); - } - } - return result; -} - -void Broker::deleteQueue(const std::string& name, const std::string& userId, - const std::string& connectionId, QueueFunctor check) -{ - if (acl && !acl->authorise(userId,acl::ACT_DELETE,acl::OBJ_QUEUE,name,NULL)) { - throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied queue delete request from " << userId)); - } - - Queue::shared_ptr queue = queues.find(name); - if (queue) { - if (check) check(queue); - queues.destroy(name); - queue->destroyed(); - } else { - throw framing::NotFoundException(QPID_MSG("Delete failed. No such queue: " << name)); - } - - if (managementAgent.get()) - managementAgent->raiseEvent(_qmf::EventQueueDelete(connectionId, userId, name)); - -} - -std::pair<Exchange::shared_ptr, bool> Broker::createExchange( - const std::string& name, - const std::string& type, - bool durable, - const std::string& alternateExchange, - const qpid::framing::FieldTable& arguments, - const std::string& userId, - const std::string& connectionId) -{ - if (acl) { - std::map<acl::Property, std::string> params; - params.insert(make_pair(acl::PROP_TYPE, type)); - params.insert(make_pair(acl::PROP_ALTERNATE, alternateExchange)); - params.insert(make_pair(acl::PROP_PASSIVE, _FALSE)); - params.insert(make_pair(acl::PROP_DURABLE, durable ? _TRUE : _FALSE)); - if (!acl->authorise(userId,acl::ACT_CREATE,acl::OBJ_EXCHANGE,name,¶ms) ) - throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied exchange create request from " << userId)); - } - - Exchange::shared_ptr alternate; - if (!alternateExchange.empty()) { - alternate = exchanges.get(alternateExchange); - if (!alternate) throw framing::NotFoundException(QPID_MSG("Alternate exchange does not exist: " << alternateExchange)); - } - - std::pair<Exchange::shared_ptr, bool> result; - result = exchanges.declare(name, type, durable, arguments); - if (result.second) { - if (alternate) { - result.first->setAlternate(alternate); - alternate->incAlternateUsers(); - } - if (durable) { - store->create(*result.first, arguments); - } - if (managementAgent.get()) { - //TODO: debatable whether we should raise an event here for - //create when this is a 'declare' event; ideally add a create - //event instead? - managementAgent->raiseEvent(_qmf::EventExchangeDeclare(connectionId, - userId, - name, - type, - alternateExchange, - durable, - false, - ManagementAgent::toMap(arguments), - "created")); - } - } - return result; -} - -void Broker::deleteExchange(const std::string& name, const std::string& userId, - const std::string& connectionId) -{ - if (acl) { - if (!acl->authorise(userId,acl::ACT_DELETE,acl::OBJ_EXCHANGE,name,NULL) ) - throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied exchange delete request from " << userId)); - } - - Exchange::shared_ptr exchange(exchanges.get(name)); - if (!exchange) throw framing::NotFoundException(QPID_MSG("Delete failed. No such exchange: " << name)); - if (exchange->inUseAsAlternate()) throw framing::NotAllowedException(QPID_MSG("Exchange in use as alternate-exchange.")); - if (exchange->isDurable()) store->destroy(*exchange); - if (exchange->getAlternate()) exchange->getAlternate()->decAlternateUsers(); - exchanges.destroy(name); - - if (managementAgent.get()) - managementAgent->raiseEvent(_qmf::EventExchangeDelete(connectionId, userId, name)); - -} - -void Broker::bind(const std::string& queueName, - const std::string& exchangeName, - const std::string& key, - const qpid::framing::FieldTable& arguments, - const std::string& userId, - const std::string& connectionId) -{ - if (acl) { - std::map<acl::Property, std::string> params; - params.insert(make_pair(acl::PROP_QUEUENAME, queueName)); - params.insert(make_pair(acl::PROP_ROUTINGKEY, key)); - - if (!acl->authorise(userId,acl::ACT_BIND,acl::OBJ_EXCHANGE,exchangeName,¶ms)) - throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied exchange bind request from " << userId)); - } - - Queue::shared_ptr queue = queues.find(queueName); - Exchange::shared_ptr exchange = exchanges.get(exchangeName); - if (!queue) { - throw framing::NotFoundException(QPID_MSG("Bind failed. No such queue: " << queueName)); - } else if (!exchange) { - throw framing::NotFoundException(QPID_MSG("Bind failed. No such exchange: " << exchangeName)); - } else { - if (queue->bind(exchange, key, arguments)) { - if (managementAgent.get()) { - managementAgent->raiseEvent(_qmf::EventBind(connectionId, userId, exchangeName, - queueName, key, ManagementAgent::toMap(arguments))); - } - } - } -} - -void Broker::unbind(const std::string& queueName, - const std::string& exchangeName, - const std::string& key, - const std::string& userId, - const std::string& connectionId) -{ - if (acl) { - std::map<acl::Property, std::string> params; - params.insert(make_pair(acl::PROP_QUEUENAME, queueName)); - params.insert(make_pair(acl::PROP_ROUTINGKEY, key)); - if (!acl->authorise(userId,acl::ACT_UNBIND,acl::OBJ_EXCHANGE,exchangeName,¶ms) ) - throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied exchange unbind request from " << userId)); - } - - Queue::shared_ptr queue = queues.find(queueName); - Exchange::shared_ptr exchange = exchanges.get(exchangeName); - if (!queue) { - throw framing::NotFoundException(QPID_MSG("Bind failed. No such queue: " << queueName)); - } else if (!exchange) { - throw framing::NotFoundException(QPID_MSG("Bind failed. No such exchange: " << exchangeName)); - } else { - if (exchange->unbind(queue, key, 0)) { - if (exchange->isDurable() && queue->isDurable()) { - store->unbind(*exchange, *queue, key, qpid::framing::FieldTable()); - } - if (managementAgent.get()) { - managementAgent->raiseEvent(_qmf::EventUnbind(connectionId, userId, exchangeName, queueName, key)); - } - } - } -} - -}} // namespace qpid::broker - diff --git a/cpp/src/qpid/broker/Broker.h b/cpp/src/qpid/broker/Broker.h deleted file mode 100644 index 6d585bf614..0000000000 --- a/cpp/src/qpid/broker/Broker.h +++ /dev/null @@ -1,351 +0,0 @@ -#ifndef _Broker_ -#define _Broker_ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/ConnectionFactory.h" -#include "qpid/broker/ConnectionToken.h" -#include "qpid/broker/DirectExchange.h" -#include "qpid/broker/DtxManager.h" -#include "qpid/broker/ExchangeRegistry.h" -#include "qpid/broker/MessageStore.h" -#include "qpid/broker/QueueRegistry.h" -#include "qpid/broker/LinkRegistry.h" -#include "qpid/broker/SessionManager.h" -#include "qpid/broker/QueueCleaner.h" -#include "qpid/broker/QueueEvents.h" -#include "qpid/broker/Vhost.h" -#include "qpid/broker/System.h" -#include "qpid/broker/ExpiryPolicy.h" -#include "qpid/management/Manageable.h" -#include "qpid/management/ManagementAgent.h" -#include "qmf/org/apache/qpid/broker/Broker.h" -#include "qmf/org/apache/qpid/broker/ArgsBrokerConnect.h" -#include "qpid/Options.h" -#include "qpid/Plugin.h" -#include "qpid/DataDir.h" -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/OutputHandler.h" -#include "qpid/framing/ProtocolInitiation.h" -#include "qpid/sys/Runnable.h" -#include "qpid/sys/Timer.h" -#include "qpid/types/Variant.h" -#include "qpid/RefCounted.h" -#include "qpid/broker/AclModule.h" -#include "qpid/sys/Mutex.h" - -#include <boost/intrusive_ptr.hpp> -#include <string> -#include <vector> - -namespace qpid { - -namespace sys { - class ProtocolFactory; - class Poller; -} - -struct Url; - -namespace broker { - -class ConnectionState; -class ExpiryPolicy; -class Message; - -static const uint16_t DEFAULT_PORT=5672; - -struct NoSuchTransportException : qpid::Exception -{ - NoSuchTransportException(const std::string& s) : Exception(s) {} - virtual ~NoSuchTransportException() throw() {} -}; - -/** - * A broker instance. - */ -class Broker : public sys::Runnable, public Plugin::Target, - public management::Manageable, - public RefCounted -{ -public: - - struct Options : public qpid::Options { - static const std::string DEFAULT_DATA_DIR_LOCATION; - static const std::string DEFAULT_DATA_DIR_NAME; - - QPID_BROKER_EXTERN Options(const std::string& name="Broker Options"); - - bool noDataDir; - std::string dataDir; - uint16_t port; - int workerThreads; - int maxConnections; - int connectionBacklog; - bool enableMgmt; - uint16_t mgmtPubInterval; - uint16_t queueCleanInterval; - bool auth; - std::string realm; - size_t replayFlushLimit; - size_t replayHardLimit; - uint queueLimit; - bool tcpNoDelay; - bool requireEncrypted; - std::string knownHosts; - std::string saslConfigPath; - uint32_t maxSessionRate; - bool asyncQueueEvents; - bool qmf2Support; - bool qmf1Support; - uint queueFlowStopRatio; // producer flow control: on - uint queueFlowResumeRatio; // producer flow control: off - uint16_t queueThresholdEventRatio; - - private: - std::string getHome(); - }; - - class ConnectionCounter { - int maxConnections; - int connectionCount; - sys::Mutex connectionCountLock; - public: - ConnectionCounter(int mc): maxConnections(mc),connectionCount(0) {}; - void inc_connectionCount() { - sys::ScopedLock<sys::Mutex> l(connectionCountLock); - connectionCount++; - } - void dec_connectionCount() { - sys::ScopedLock<sys::Mutex> l(connectionCountLock); - connectionCount--; - } - bool allowConnection() { - sys::ScopedLock<sys::Mutex> l(connectionCountLock); - return (maxConnections <= connectionCount); - } - }; - - private: - typedef std::map<std::string, boost::shared_ptr<sys::ProtocolFactory> > ProtocolFactoryMap; - - void declareStandardExchange(const std::string& name, const std::string& type); - void setStore (); - void setLogLevel(const std::string& level); - std::string getLogLevel(); - void createObject(const std::string& type, const std::string& name, - const qpid::types::Variant::Map& properties, bool strict, const ConnectionState* context); - void deleteObject(const std::string& type, const std::string& name, - const qpid::types::Variant::Map& options, const ConnectionState* context); - - boost::shared_ptr<sys::Poller> poller; - sys::Timer timer; - std::auto_ptr<sys::Timer> clusterTimer; - Options config; - std::auto_ptr<management::ManagementAgent> managementAgent; - ProtocolFactoryMap protocolFactories; - std::auto_ptr<MessageStore> store; - AclModule* acl; - DataDir dataDir; - - QueueRegistry queues; - ExchangeRegistry exchanges; - LinkRegistry links; - boost::shared_ptr<sys::ConnectionCodec::Factory> factory; - DtxManager dtxManager; - SessionManager sessionManager; - qmf::org::apache::qpid::broker::Broker* mgmtObject; - Vhost::shared_ptr vhostObject; - System::shared_ptr systemObject; - QueueCleaner queueCleaner; - QueueEvents queueEvents; - std::vector<Url> knownBrokers; - std::vector<Url> getKnownBrokersImpl(); - bool deferDeliveryImpl(const std::string& queue, - const boost::intrusive_ptr<Message>& msg); - std::string federationTag; - bool recovery; - bool inCluster, clusterUpdatee; - boost::intrusive_ptr<ExpiryPolicy> expiryPolicy; - ConnectionCounter connectionCounter; - - public: - virtual ~Broker(); - - QPID_BROKER_EXTERN Broker(const Options& configuration); - static QPID_BROKER_EXTERN boost::intrusive_ptr<Broker> create(const Options& configuration); - static QPID_BROKER_EXTERN boost::intrusive_ptr<Broker> create(int16_t port = DEFAULT_PORT); - - /** - * Return listening port. If called before bind this is - * the configured port. If called after it is the actual - * port, which will be different if the configured port is - * 0. - */ - virtual uint16_t getPort(const std::string& name) const; - - /** - * Run the broker. Implements Runnable::run() so the broker - * can be run in a separate thread. - */ - virtual void run(); - - /** Shut down the broker */ - virtual void shutdown(); - - QPID_BROKER_EXTERN void setStore (boost::shared_ptr<MessageStore>& store); - MessageStore& getStore() { return *store; } - void setAcl (AclModule* _acl) {acl = _acl;} - AclModule* getAcl() { return acl; } - QueueRegistry& getQueues() { return queues; } - ExchangeRegistry& getExchanges() { return exchanges; } - LinkRegistry& getLinks() { return links; } - DtxManager& getDtxManager() { return dtxManager; } - DataDir& getDataDir() { return dataDir; } - Options& getOptions() { return config; } - QueueEvents& getQueueEvents() { return queueEvents; } - - void setExpiryPolicy(const boost::intrusive_ptr<ExpiryPolicy>& e) { expiryPolicy = e; } - boost::intrusive_ptr<ExpiryPolicy> getExpiryPolicy() { return expiryPolicy; } - - SessionManager& getSessionManager() { return sessionManager; } - const std::string& getFederationTag() const { return federationTag; } - - management::ManagementObject* GetManagementObject (void) const; - management::Manageable* GetVhostObject (void) const; - management::Manageable::status_t ManagementMethod (uint32_t methodId, - management::Args& args, - std::string& text); - - /** Add to the broker's protocolFactorys */ - void registerProtocolFactory(const std::string& name, boost::shared_ptr<sys::ProtocolFactory>); - - /** Accept connections */ - QPID_BROKER_EXTERN void accept(); - - /** Create a connection to another broker. */ - void connect(const std::string& host, uint16_t port, - const std::string& transport, - boost::function2<void, int, std::string> failed, - sys::ConnectionCodec::Factory* =0); - /** Create a connection to another broker. */ - void connect(const Url& url, - boost::function2<void, int, std::string> failed, - sys::ConnectionCodec::Factory* =0); - - /** Move messages from one queue to another. - A zero quantity means to move all messages - */ - uint32_t queueMoveMessages( const std::string& srcQueue, - const std::string& destQueue, - uint32_t qty); - - boost::shared_ptr<sys::ProtocolFactory> getProtocolFactory(const std::string& name = TCP_TRANSPORT) const; - - /** Expose poller so plugins can register their descriptors. */ - boost::shared_ptr<sys::Poller> getPoller(); - - boost::shared_ptr<sys::ConnectionCodec::Factory> getConnectionFactory() { return factory; } - void setConnectionFactory(boost::shared_ptr<sys::ConnectionCodec::Factory> f) { factory = f; } - - /** Timer for local tasks affecting only this broker */ - sys::Timer& getTimer() { return timer; } - - /** Timer for tasks that must be synchronized if we are in a cluster */ - sys::Timer& getClusterTimer() { return clusterTimer.get() ? *clusterTimer : timer; } - void setClusterTimer(std::auto_ptr<sys::Timer>); - - boost::function<std::vector<Url> ()> getKnownBrokers; - - static QPID_BROKER_EXTERN const std::string TCP_TRANSPORT; - - void setRecovery(bool set) { recovery = set; } - bool getRecovery() const { return recovery; } - - /** True of this broker is part of a cluster. - * Only valid after early initialization of plugins is complete. - */ - bool isInCluster() const { return inCluster; } - void setInCluster(bool set) { inCluster = set; } - - /** True if this broker is joining a cluster and in the process of - * receiving a state update. - */ - bool isClusterUpdatee() const { return clusterUpdatee; } - void setClusterUpdatee(bool set) { clusterUpdatee = set; } - - management::ManagementAgent* getManagementAgent() { return managementAgent.get(); } - - ConnectionCounter& getConnectionCounter() {return connectionCounter;} - - /** - * Never true in a stand-alone broker. In a cluster, return true - * to defer delivery of messages deliveredg in a cluster-unsafe - * context. - *@return true if delivery of a message should be deferred. - */ - boost::function<bool (const std::string& queue, - const boost::intrusive_ptr<Message>& msg)> deferDelivery; - - bool isAuthenticating ( ) { return config.auth; } - - typedef boost::function1<void, boost::shared_ptr<Queue> > QueueFunctor; - - std::pair<boost::shared_ptr<Queue>, bool> createQueue( - const std::string& name, - bool durable, - bool autodelete, - const OwnershipToken* owner, - const std::string& alternateExchange, - const qpid::framing::FieldTable& arguments, - const std::string& userId, - const std::string& connectionId); - void deleteQueue(const std::string& name, - const std::string& userId, - const std::string& connectionId, - QueueFunctor check = QueueFunctor()); - std::pair<Exchange::shared_ptr, bool> createExchange( - const std::string& name, - const std::string& type, - bool durable, - const std::string& alternateExchange, - const qpid::framing::FieldTable& args, - const std::string& userId, const std::string& connectionId); - void deleteExchange(const std::string& name, const std::string& userId, - const std::string& connectionId); - void bind(const std::string& queue, - const std::string& exchange, - const std::string& key, - const qpid::framing::FieldTable& arguments, - const std::string& userId, - const std::string& connectionId); - void unbind(const std::string& queue, - const std::string& exchange, - const std::string& key, - const std::string& userId, - const std::string& connectionId); -}; - -}} - -#endif /*!_Broker_*/ diff --git a/cpp/src/qpid/broker/BrokerImportExport.h b/cpp/src/qpid/broker/BrokerImportExport.h deleted file mode 100644 index ee05788063..0000000000 --- a/cpp/src/qpid/broker/BrokerImportExport.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef QPID_BROKER_IMPORT_EXPORT_H -#define QPID_BROKER_IMPORT_EXPORT_H - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#if defined(WIN32) && !defined(QPID_DECLARE_STATIC) -# if defined(BROKER_EXPORT) || defined (qpidbroker_EXPORTS) -# define QPID_BROKER_EXTERN __declspec(dllexport) -# else -# define QPID_BROKER_EXTERN __declspec(dllimport) -# endif -# ifdef _MSC_VER -# define QPID_BROKER_CLASS_EXTERN -# define QPID_BROKER_INLINE_EXTERN QPID_BROKER_EXTERN -# else -# define QPID_BROKER_CLASS_EXTERN QPID_BROKER_EXTERN -# define QPID_BROKER_INLINE_EXTERN -# endif -#else -# define QPID_BROKER_EXTERN -# define QPID_BROKER_CLASS_EXTERN -# define QPID_BROKER_INLINE_EXTERN -#endif - -#endif diff --git a/cpp/src/qpid/broker/Connection.cpp b/cpp/src/qpid/broker/Connection.cpp deleted file mode 100644 index c07e63e68c..0000000000 --- a/cpp/src/qpid/broker/Connection.cpp +++ /dev/null @@ -1,487 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/Connection.h" -#include "qpid/broker/SessionOutputException.h" -#include "qpid/broker/SessionState.h" -#include "qpid/broker/Bridge.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/Queue.h" -#include "qpid/sys/SecuritySettings.h" -#include "qpid/sys/ClusterSafe.h" - -#include "qpid/log/Statement.h" -#include "qpid/ptr_map.h" -#include "qpid/framing/AMQP_ClientProxy.h" -#include "qpid/framing/enum.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qmf/org/apache/qpid/broker/EventClientConnect.h" -#include "qmf/org/apache/qpid/broker/EventClientDisconnect.h" - -#include <boost/bind.hpp> -#include <boost/ptr_container/ptr_vector.hpp> - -#include <algorithm> -#include <iostream> -#include <assert.h> - - - -using namespace qpid::sys; -using namespace qpid::framing; -using qpid::ptr_map_ptr; -using qpid::management::ManagementAgent; -using qpid::management::ManagementObject; -using qpid::management::Manageable; -using qpid::management::Args; -namespace _qmf = qmf::org::apache::qpid::broker; - -namespace qpid { -namespace broker { - -struct ConnectionTimeoutTask : public sys::TimerTask { - sys::Timer& timer; - Connection& connection; - - ConnectionTimeoutTask(uint16_t hb, sys::Timer& t, Connection& c) : - TimerTask(Duration(hb*2*TIME_SEC),"ConnectionTimeout"), - timer(t), - connection(c) - {} - - void touch() { - restart(); - } - - void fire() { - // If we get here then we've not received any traffic in the timeout period - // Schedule closing the connection for the io thread - QPID_LOG(error, "Connection " << connection.getMgmtId() - << " timed out: closing"); - connection.abort(); - } -}; - -Connection::Connection(ConnectionOutputHandler* out_, - Broker& broker_, const - std::string& mgmtId_, - const qpid::sys::SecuritySettings& external, - bool isLink_, - uint64_t objectId_, - bool shadow_, - bool delayManagement) : - ConnectionState(out_, broker_), - securitySettings(external), - adapter(*this, isLink_, shadow_), - isLink(isLink_), - mgmtClosing(false), - mgmtId(mgmtId_), - mgmtObject(0), - links(broker_.getLinks()), - agent(0), - timer(broker_.getTimer()), - errorListener(0), - objectId(objectId_), - shadow(shadow_), - outboundTracker(*this) -{ - outboundTracker.wrap(out); - if (isLink) - links.notifyConnection(mgmtId, this); - // In a cluster, allow adding the management object to be delayed. - if (!delayManagement) addManagementObject(); - if (!isShadow()) broker.getConnectionCounter().inc_connectionCount(); -} - -void Connection::addManagementObject() { - assert(agent == 0); - assert(mgmtObject == 0); - Manageable* parent = broker.GetVhostObject(); - if (parent != 0) { - agent = broker.getManagementAgent(); - if (agent != 0) { - // TODO set last bool true if system connection - mgmtObject = new _qmf::Connection(agent, this, parent, mgmtId, !isLink, false); - mgmtObject->set_shadow(shadow); - agent->addObject(mgmtObject, objectId); - } - ConnectionState::setUrl(mgmtId); - } -} - -void Connection::requestIOProcessing(boost::function0<void> callback) -{ - ScopedLock<Mutex> l(ioCallbackLock); - ioCallbacks.push(callback); - out.activateOutput(); -} - -Connection::~Connection() -{ - if (mgmtObject != 0) { - mgmtObject->resourceDestroy(); - // In a cluster, Connections destroyed during shutdown are in - // a cluster-unsafe context. Don't raise an event in that case. - if (!isLink && isClusterSafe()) - agent->raiseEvent(_qmf::EventClientDisconnect(mgmtId, ConnectionState::getUserId())); - } - if (isLink) - links.notifyClosed(mgmtId); - - if (heartbeatTimer) - heartbeatTimer->cancel(); - if (timeoutTimer) - timeoutTimer->cancel(); - - if (!isShadow()) broker.getConnectionCounter().dec_connectionCount(); -} - -void Connection::received(framing::AMQFrame& frame) { - // Received frame on connection so delay timeout - restartTimeout(); - - if (frame.getChannel() == 0 && frame.getMethod()) { - adapter.handle(frame); - } else { - if (adapter.isOpen()) - getChannel(frame.getChannel()).in(frame); - else - close(connection::CLOSE_CODE_FRAMING_ERROR, "Connection not yet open, invalid frame received."); - } - - if (isLink) //i.e. we are acting as the client to another broker - recordFromServer(frame); - else - recordFromClient(frame); -} - -void Connection::sent(const framing::AMQFrame& frame) -{ - if (isLink) //i.e. we are acting as the client to another broker - recordFromClient(frame); - else - recordFromServer(frame); -} - -bool isMessage(const AMQMethodBody* method) -{ - return method && method->isA<qpid::framing::MessageTransferBody>(); -} - -void Connection::recordFromServer(const framing::AMQFrame& frame) -{ - // Don't record management stats in cluster-unsafe contexts - if (mgmtObject != 0 && isClusterSafe()) - { - mgmtObject->inc_framesToClient(); - mgmtObject->inc_bytesToClient(frame.encodedSize()); - if (isMessage(frame.getMethod())) { - mgmtObject->inc_msgsToClient(); - } - } -} - -void Connection::recordFromClient(const framing::AMQFrame& frame) -{ - // Don't record management stats in cluster-unsafe contexts - if (mgmtObject != 0 && isClusterSafe()) - { - mgmtObject->inc_framesFromClient(); - mgmtObject->inc_bytesFromClient(frame.encodedSize()); - if (isMessage(frame.getMethod())) { - mgmtObject->inc_msgsFromClient(); - } - } -} - -string Connection::getAuthMechanism() -{ - if (!isLink) - return string("ANONYMOUS"); - - return links.getAuthMechanism(mgmtId); -} - -string Connection::getUsername ( ) -{ - if (!isLink) - return string("anonymous"); - - return links.getUsername(mgmtId); -} - -string Connection::getPassword ( ) -{ - if (!isLink) - return string(""); - - return links.getPassword(mgmtId); -} - -string Connection::getHost ( ) -{ - if (!isLink) - return string(""); - - return links.getHost(mgmtId); -} - -uint16_t Connection::getPort ( ) -{ - if (!isLink) - return 0; - - return links.getPort(mgmtId); -} - -string Connection::getAuthCredentials() -{ - if (!isLink) - return string(); - - if (mgmtObject != 0) - { - if (links.getAuthMechanism(mgmtId) == "ANONYMOUS") - mgmtObject->set_authIdentity("anonymous"); - else - mgmtObject->set_authIdentity(links.getAuthIdentity(mgmtId)); - } - - return links.getAuthCredentials(mgmtId); -} - -void Connection::notifyConnectionForced(const string& text) -{ - if (isLink) - links.notifyConnectionForced(mgmtId, text); -} - -void Connection::setUserId(const string& userId) -{ - ConnectionState::setUserId(userId); - // In a cluster, the cluster code will raise the connect event - // when the connection is replicated to the cluster. - if (!broker.isInCluster()) raiseConnectEvent(); -} - -void Connection::raiseConnectEvent() { - if (mgmtObject != 0) { - mgmtObject->set_authIdentity(userId); - agent->raiseEvent(_qmf::EventClientConnect(mgmtId, userId)); - } -} - -void Connection::setFederationLink(bool b) -{ - ConnectionState::setFederationLink(b); - if (mgmtObject != 0) - mgmtObject->set_federationLink(b); -} - -void Connection::close(connection::CloseCode code, const string& text) -{ - QPID_LOG_IF(error, code != connection::CLOSE_CODE_NORMAL, "Connection " << mgmtId << " closed by error: " << text << "(" << code << ")"); - if (heartbeatTimer) - heartbeatTimer->cancel(); - if (timeoutTimer) - timeoutTimer->cancel(); - adapter.close(code, text); - //make sure we delete dangling pointers from outputTasks before deleting sessions - outputTasks.removeAll(); - channels.clear(); - getOutput().close(); -} - -// Send a close to the client but keep the channels. Used by cluster. -void Connection::sendClose() { - if (heartbeatTimer) - heartbeatTimer->cancel(); - if (timeoutTimer) - timeoutTimer->cancel(); - adapter.close(connection::CLOSE_CODE_NORMAL, "OK"); - getOutput().close(); -} - -void Connection::idleOut(){} - -void Connection::idleIn(){} - -void Connection::closed(){ // Physically closed, suspend open sessions. - if (heartbeatTimer) - heartbeatTimer->cancel(); - if (timeoutTimer) - timeoutTimer->cancel(); - try { - while (!channels.empty()) - ptr_map_ptr(channels.begin())->handleDetach(); - } catch(std::exception& e) { - QPID_LOG(error, QPID_MSG("While closing connection: " << e.what())); - assert(0); - } -} - -void Connection::doIoCallbacks() { - { - ScopedLock<Mutex> l(ioCallbackLock); - // Although IO callbacks execute in the connection thread context, they are - // not cluster safe because they are queued for execution in non-IO threads. - ClusterUnsafeScope cus; - while (!ioCallbacks.empty()) { - boost::function0<void> cb = ioCallbacks.front(); - ioCallbacks.pop(); - ScopedUnlock<Mutex> ul(ioCallbackLock); - cb(); // Lend the IO thread for management processing - } - } -} - -bool Connection::doOutput() { - try { - doIoCallbacks(); - if (mgmtClosing) { - closed(); - close(connection::CLOSE_CODE_CONNECTION_FORCED, "Closed by Management Request"); - } else { - //then do other output as needed: - return outputTasks.doOutput(); - } - }catch(const SessionOutputException& e){ - getChannel(e.channel).handleException(e); - return true; - }catch(ConnectionException& e){ - close(e.code, e.getMessage()); - }catch(std::exception& e){ - close(connection::CLOSE_CODE_CONNECTION_FORCED, e.what()); - } - return false; -} - -void Connection::sendHeartbeat() { - adapter.heartbeat(); -} - -void Connection::closeChannel(uint16_t id) { - ChannelMap::iterator i = channels.find(id); - if (i != channels.end()) channels.erase(i); -} - -SessionHandler& Connection::getChannel(ChannelId id) { - ChannelMap::iterator i=channels.find(id); - if (i == channels.end()) { - i = channels.insert(id, new SessionHandler(*this, id)).first; - } - return *ptr_map_ptr(i); -} - -ManagementObject* Connection::GetManagementObject(void) const -{ - return (ManagementObject*) mgmtObject; -} - -Manageable::status_t Connection::ManagementMethod(uint32_t methodId, Args&, string&) -{ - Manageable::status_t status = Manageable::STATUS_UNKNOWN_METHOD; - - QPID_LOG(debug, "Connection::ManagementMethod [id=" << methodId << "]"); - - switch (methodId) - { - case _qmf::Connection::METHOD_CLOSE : - mgmtClosing = true; - if (mgmtObject != 0) mgmtObject->set_closing(1); - out.activateOutput(); - status = Manageable::STATUS_OK; - break; - } - - return status; -} - -void Connection::setSecureConnection(SecureConnection* s) -{ - adapter.setSecureConnection(s); -} - -struct ConnectionHeartbeatTask : public sys::TimerTask { - sys::Timer& timer; - Connection& connection; - ConnectionHeartbeatTask(uint16_t hb, sys::Timer& t, Connection& c) : - TimerTask(Duration(hb*TIME_SEC), "ConnectionHeartbeat"), - timer(t), - connection(c) - {} - - void fire() { - // Setup next firing - setupNextFire(); - timer.add(this); - - // Send Heartbeat - connection.sendHeartbeat(); - } -}; - -void Connection::abort() -{ - // Make sure that we don't try to send a heartbeat as we're - // aborting the connection - if (heartbeatTimer) - heartbeatTimer->cancel(); - - out.abort(); -} - -void Connection::setHeartbeatInterval(uint16_t heartbeat) -{ - setHeartbeat(heartbeat); - if (heartbeat > 0 && !isShadow()) { - heartbeatTimer = new ConnectionHeartbeatTask(heartbeat, timer, *this); - timer.add(heartbeatTimer); - timeoutTimer = new ConnectionTimeoutTask(heartbeat, timer, *this); - timer.add(timeoutTimer); - } -} - -void Connection::restartTimeout() -{ - if (timeoutTimer) - timeoutTimer->touch(); -} - -bool Connection::isOpen() { return adapter.isOpen(); } - -Connection::OutboundFrameTracker::OutboundFrameTracker(Connection& _con) : con(_con), next(0) {} -void Connection::OutboundFrameTracker::close() { next->close(); } -size_t Connection::OutboundFrameTracker::getBuffered() const { return next->getBuffered(); } -void Connection::OutboundFrameTracker::abort() { next->abort(); } -void Connection::OutboundFrameTracker::activateOutput() { next->activateOutput(); } -void Connection::OutboundFrameTracker::giveReadCredit(int32_t credit) { next->giveReadCredit(credit); } -void Connection::OutboundFrameTracker::send(framing::AMQFrame& f) -{ - next->send(f); - con.sent(f); -} -void Connection::OutboundFrameTracker::wrap(sys::ConnectionOutputHandlerPtr& p) -{ - next = p.get(); - p.set(this); -} - -}} diff --git a/cpp/src/qpid/broker/Connection.h b/cpp/src/qpid/broker/Connection.h deleted file mode 100644 index 8f1aa701ef..0000000000 --- a/cpp/src/qpid/broker/Connection.h +++ /dev/null @@ -1,216 +0,0 @@ -#ifndef QPID_BROKER_CONNECTION_H -#define QPID_BROKER_CONNECTION_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <memory> -#include <sstream> -#include <vector> -#include <queue> - -#include <boost/ptr_container/ptr_map.hpp> - -#include "qpid/broker/ConnectionHandler.h" -#include "qpid/broker/ConnectionState.h" -#include "qpid/broker/SessionHandler.h" -#include "qmf/org/apache/qpid/broker/Connection.h" -#include "qpid/Exception.h" -#include "qpid/RefCounted.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/AMQP_ClientProxy.h" -#include "qpid/framing/AMQP_ServerOperations.h" -#include "qpid/framing/ProtocolVersion.h" -#include "qpid/management/ManagementAgent.h" -#include "qpid/management/Manageable.h" -#include "qpid/ptr_map.h" -#include "qpid/sys/AggregateOutput.h" -#include "qpid/sys/ConnectionInputHandler.h" -#include "qpid/sys/ConnectionOutputHandler.h" -#include "qpid/sys/SecuritySettings.h" -#include "qpid/sys/Socket.h" -#include "qpid/sys/TimeoutHandler.h" -#include "qpid/sys/Mutex.h" - -#include <boost/ptr_container/ptr_map.hpp> -#include <boost/bind.hpp> - -#include <algorithm> - -namespace qpid { -namespace broker { - -class Broker; -class LinkRegistry; -class SecureConnection; -struct ConnectionTimeoutTask; - -class Connection : public sys::ConnectionInputHandler, - public ConnectionState, - public RefCounted -{ - public: - /** - * Listener that can be registered with a Connection to be informed of errors. - */ - class ErrorListener - { - public: - virtual ~ErrorListener() {} - virtual void sessionError(uint16_t channel, const std::string&) = 0; - virtual void connectionError(const std::string&) = 0; - }; - - Connection(sys::ConnectionOutputHandler* out, - Broker& broker, - const std::string& mgmtId, - const qpid::sys::SecuritySettings&, - bool isLink = false, - uint64_t objectId = 0, - bool shadow=false, - bool delayManagement = false); - - ~Connection (); - - /** Get the SessionHandler for channel. Create if it does not already exist */ - SessionHandler& getChannel(framing::ChannelId channel); - - /** Close the connection */ - void close(framing::connection::CloseCode code, const std::string& text); - - // ConnectionInputHandler methods - void received(framing::AMQFrame& frame); - void idleOut(); - void idleIn(); - bool doOutput(); - void closed(); - - void closeChannel(framing::ChannelId channel); - - // Manageable entry points - management::ManagementObject* GetManagementObject (void) const; - management::Manageable::status_t - ManagementMethod (uint32_t methodId, management::Args& args, std::string&); - - void requestIOProcessing (boost::function0<void>); - void recordFromServer (const framing::AMQFrame& frame); - void recordFromClient (const framing::AMQFrame& frame); - std::string getAuthMechanism(); - std::string getAuthCredentials(); - std::string getUsername(); - std::string getPassword(); - std::string getHost(); - uint16_t getPort(); - void notifyConnectionForced(const std::string& text); - void setUserId(const std::string& uid); - void raiseConnectEvent(); - const std::string& getUserId() const { return ConnectionState::getUserId(); } - const std::string& getMgmtId() const { return mgmtId; } - management::ManagementAgent* getAgent() const { return agent; } - void setFederationLink(bool b); - /** Connection does not delete the listener. 0 resets. */ - void setErrorListener(ErrorListener* l) { errorListener=l; } - ErrorListener* getErrorListener() { return errorListener; } - - void setHeartbeatInterval(uint16_t heartbeat); - void sendHeartbeat(); - void restartTimeout(); - void abort(); - - template <class F> void eachSessionHandler(F f) { - for (ChannelMap::iterator i = channels.begin(); i != channels.end(); ++i) - f(*ptr_map_ptr(i)); - } - - void sendClose(); - void setSecureConnection(SecureConnection* secured); - - /** True if this is a shadow connection in a cluster. */ - bool isShadow() { return shadow; } - - // Used by cluster to update connection status - sys::AggregateOutput& getOutputTasks() { return outputTasks; } - - /** Cluster delays adding management object in the constructor then calls this. */ - void addManagementObject(); - - const qpid::sys::SecuritySettings& getExternalSecuritySettings() const - { - return securitySettings; - } - - /** @return true if the initial connection negotiation is complete. */ - bool isOpen(); - - // Used by cluster during catch-up, see cluster::OutputInterceptor - void doIoCallbacks(); - - private: - typedef boost::ptr_map<framing::ChannelId, SessionHandler> ChannelMap; - typedef std::vector<boost::shared_ptr<Queue> >::iterator queue_iterator; - - ChannelMap channels; - qpid::sys::SecuritySettings securitySettings; - ConnectionHandler adapter; - const bool isLink; - bool mgmtClosing; - const std::string mgmtId; - sys::Mutex ioCallbackLock; - std::queue<boost::function0<void> > ioCallbacks; - qmf::org::apache::qpid::broker::Connection* mgmtObject; - LinkRegistry& links; - management::ManagementAgent* agent; - sys::Timer& timer; - boost::intrusive_ptr<sys::TimerTask> heartbeatTimer; - boost::intrusive_ptr<ConnectionTimeoutTask> timeoutTimer; - ErrorListener* errorListener; - uint64_t objectId; - bool shadow; - /** - * Chained ConnectionOutputHandler that allows outgoing frames to be - * tracked (for updating mgmt stats). - */ - class OutboundFrameTracker : public sys::ConnectionOutputHandler - { - public: - OutboundFrameTracker(Connection&); - void close(); - size_t getBuffered() const; - void abort(); - void activateOutput(); - void giveReadCredit(int32_t credit); - void send(framing::AMQFrame&); - void wrap(sys::ConnectionOutputHandlerPtr&); - private: - Connection& con; - sys::ConnectionOutputHandler* next; - }; - OutboundFrameTracker outboundTracker; - - - void sent(const framing::AMQFrame& f); - public: - qmf::org::apache::qpid::broker::Connection* getMgmtObject() { return mgmtObject; } -}; - -}} - -#endif /*!QPID_BROKER_CONNECTION_H*/ diff --git a/cpp/src/qpid/broker/ConnectionFactory.cpp b/cpp/src/qpid/broker/ConnectionFactory.cpp deleted file mode 100644 index 9e0020812b..0000000000 --- a/cpp/src/qpid/broker/ConnectionFactory.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/ConnectionFactory.h" -#include "qpid/framing/ProtocolVersion.h" -#include "qpid/amqp_0_10/Connection.h" -#include "qpid/broker/Connection.h" -#include "qpid/sys/SecuritySettings.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace broker { - -using framing::ProtocolVersion; -using qpid::sys::SecuritySettings; -typedef std::auto_ptr<amqp_0_10::Connection> ConnectionPtr; -typedef std::auto_ptr<sys::ConnectionInputHandler> InputPtr; - -ConnectionFactory::ConnectionFactory(Broker& b) : broker(b) {} - -ConnectionFactory::~ConnectionFactory() {} - -sys::ConnectionCodec* -ConnectionFactory::create(ProtocolVersion v, sys::OutputControl& out, const std::string& id, - const SecuritySettings& external) { - if (broker.getConnectionCounter().allowConnection()) - { - QPID_LOG(error, "Client max connection count limit exceeded: " << broker.getOptions().maxConnections << " connection refused"); - return 0; - } - if (v == ProtocolVersion(0, 10)) { - ConnectionPtr c(new amqp_0_10::Connection(out, id, false)); - c->setInputHandler(InputPtr(new broker::Connection(c.get(), broker, id, external, false))); - return c.release(); - } - return 0; -} - -sys::ConnectionCodec* -ConnectionFactory::create(sys::OutputControl& out, const std::string& id, - const SecuritySettings& external) { - // used to create connections from one broker to another - ConnectionPtr c(new amqp_0_10::Connection(out, id, true)); - c->setInputHandler(InputPtr(new broker::Connection(c.get(), broker, id, external, true))); - return c.release(); -} - - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/ConnectionFactory.h b/cpp/src/qpid/broker/ConnectionFactory.h deleted file mode 100644 index 7c1a9a08e1..0000000000 --- a/cpp/src/qpid/broker/ConnectionFactory.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _ConnectionFactory_ -#define _ConnectionFactory_ - -#include "qpid/sys/ConnectionCodec.h" - -namespace qpid { -namespace broker { -class Broker; - -class ConnectionFactory : public sys::ConnectionCodec::Factory -{ - public: - ConnectionFactory(Broker& b); - - virtual ~ConnectionFactory(); - - sys::ConnectionCodec* - create(framing::ProtocolVersion, sys::OutputControl&, const std::string& id, - const qpid::sys::SecuritySettings&); - - sys::ConnectionCodec* - create(sys::OutputControl&, const std::string& id, const qpid::sys::SecuritySettings&); - - private: - Broker& broker; -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/ConnectionHandler.cpp b/cpp/src/qpid/broker/ConnectionHandler.cpp deleted file mode 100644 index 3f97e5b9de..0000000000 --- a/cpp/src/qpid/broker/ConnectionHandler.cpp +++ /dev/null @@ -1,364 +0,0 @@ - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/SaslFactory.h" -#include "qpid/broker/ConnectionHandler.h" -#include "qpid/broker/Connection.h" -#include "qpid/broker/SecureConnection.h" -#include "qpid/Url.h" -#include "qpid/framing/AllInvoker.h" -#include "qpid/framing/enum.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/SecurityLayer.h" -#include "qpid/broker/AclModule.h" -#include "qmf/org/apache/qpid/broker/EventClientConnectFail.h" - -using namespace qpid; -using namespace qpid::broker; -using namespace qpid::framing; -using qpid::sys::SecurityLayer; -namespace _qmf = qmf::org::apache::qpid::broker; - -namespace -{ -const std::string ANONYMOUS = "ANONYMOUS"; -const std::string PLAIN = "PLAIN"; -const std::string en_US = "en_US"; -const std::string QPID_FED_LINK = "qpid.fed_link"; -const std::string QPID_FED_TAG = "qpid.federation_tag"; -const std::string SESSION_FLOW_CONTROL("qpid.session_flow"); -const std::string CLIENT_PROCESS_NAME("qpid.client_process"); -const std::string CLIENT_PID("qpid.client_pid"); -const std::string CLIENT_PPID("qpid.client_ppid"); -const int SESSION_FLOW_CONTROL_VER = 1; -const std::string SPACE(" "); -} - -void ConnectionHandler::close(connection::CloseCode code, const string& text) -{ - handler->proxy.close(code, text); -} - -void ConnectionHandler::heartbeat() -{ - handler->proxy.heartbeat(); -} - -void ConnectionHandler::handle(framing::AMQFrame& frame) -{ - AMQMethodBody* method=frame.getBody()->getMethod(); - Connection::ErrorListener* errorListener = handler->connection.getErrorListener(); - try{ - if (!invoke(static_cast<AMQP_AllOperations::ConnectionHandler&>(*handler.get()), *method)) { - handler->connection.getChannel(frame.getChannel()).in(frame); - } - }catch(ConnectionException& e){ - if (errorListener) errorListener->connectionError(e.what()); - handler->proxy.close(e.code, e.what()); - }catch(std::exception& e){ - if (errorListener) errorListener->connectionError(e.what()); - handler->proxy.close(541/*internal error*/, e.what()); - } -} - -void ConnectionHandler::setSecureConnection(SecureConnection* secured) -{ - handler->secured = secured; -} - -ConnectionHandler::ConnectionHandler(Connection& connection, bool isClient, bool isShadow) : handler(new Handler(connection, isClient, isShadow)) {} - -ConnectionHandler::Handler::Handler(Connection& c, bool isClient, bool isShadow) : - proxy(c.getOutput()), - connection(c), serverMode(!isClient), acl(0), secured(0), - isOpen(false) -{ - if (serverMode) { - - acl = connection.getBroker().getAcl(); - - FieldTable properties; - Array mechanisms(0x95); - - properties.setString(QPID_FED_TAG, connection.getBroker().getFederationTag()); - - authenticator = SaslAuthenticator::createAuthenticator(c, isShadow); - authenticator->getMechanisms(mechanisms); - - Array locales(0x95); - boost::shared_ptr<FieldValue> l(new Str16Value(en_US)); - locales.add(l); - proxy.start(properties, mechanisms, locales); - - } - - maxFrameSize = (64 * 1024) - 1; -} - - -ConnectionHandler::Handler::~Handler() {} - - -void ConnectionHandler::Handler::startOk(const framing::FieldTable& clientProperties, - const string& mechanism, - const string& response, - const string& /*locale*/) -{ - try { - authenticator->start(mechanism, response); - } catch (std::exception& /*e*/) { - management::ManagementAgent* agent = connection.getAgent(); - if (agent) { - string error; - string uid; - authenticator->getError(error); - authenticator->getUid(uid); - agent->raiseEvent(_qmf::EventClientConnectFail(connection.getMgmtId(), uid, error)); - } - throw; - } - connection.setFederationLink(clientProperties.get(QPID_FED_LINK)); - connection.setFederationPeerTag(clientProperties.getAsString(QPID_FED_TAG)); - if (connection.isFederationLink()) { - if (acl && !acl->authorise(connection.getUserId(),acl::ACT_CREATE,acl::OBJ_LINK,"")){ - proxy.close(framing::connection::CLOSE_CODE_CONNECTION_FORCED,"ACL denied creating a federation link"); - return; - } - QPID_LOG(info, "Connection is a federation link"); - } - if (clientProperties.getAsInt(SESSION_FLOW_CONTROL) == SESSION_FLOW_CONTROL_VER) { - connection.setClientThrottling(); - } - - if (connection.getMgmtObject() != 0) { - string procName = clientProperties.getAsString(CLIENT_PROCESS_NAME); - uint32_t pid = clientProperties.getAsInt(CLIENT_PID); - uint32_t ppid = clientProperties.getAsInt(CLIENT_PPID); - - if (!procName.empty()) - connection.getMgmtObject()->set_remoteProcessName(procName); - if (pid != 0) - connection.getMgmtObject()->set_remotePid(pid); - if (ppid != 0) - connection.getMgmtObject()->set_remoteParentPid(ppid); - } -} - -void ConnectionHandler::Handler::secureOk(const string& response) -{ - try { - authenticator->step(response); - } catch (std::exception& /*e*/) { - management::ManagementAgent* agent = connection.getAgent(); - if (agent) { - string error; - string uid; - authenticator->getError(error); - authenticator->getUid(uid); - agent->raiseEvent(_qmf::EventClientConnectFail(connection.getMgmtId(), uid, error)); - } - throw; - } -} - -void ConnectionHandler::Handler::tuneOk(uint16_t /*channelmax*/, - uint16_t framemax, uint16_t heartbeat) -{ - connection.setFrameMax(framemax); - connection.setHeartbeatInterval(heartbeat); -} - -void ConnectionHandler::Handler::open(const string& /*virtualHost*/, - const framing::Array& /*capabilities*/, bool /*insist*/) -{ - std::vector<Url> urls = connection.broker.getKnownBrokers(); - framing::Array array(0x95); // str16 array - for (std::vector<Url>::iterator i = urls.begin(); i < urls.end(); ++i) - array.add(boost::shared_ptr<Str16Value>(new Str16Value(i->str()))); - - //install security layer if one has been negotiated: - if (secured) { - std::auto_ptr<SecurityLayer> sl = authenticator->getSecurityLayer(connection.getFrameMax()); - if (sl.get()) secured->activateSecurityLayer(sl); - } - - isOpen = true; - proxy.openOk(array); -} - - -void ConnectionHandler::Handler::close(uint16_t replyCode, const string& replyText) -{ - if (replyCode != 200) { - QPID_LOG(warning, "Client closed connection with " << replyCode << ": " << replyText); - } - - if (replyCode == framing::connection::CLOSE_CODE_CONNECTION_FORCED) - connection.notifyConnectionForced(replyText); - - proxy.closeOk(); - connection.getOutput().close(); -} - -void ConnectionHandler::Handler::closeOk(){ - connection.getOutput().close(); -} - -void ConnectionHandler::Handler::heartbeat(){ - // For general case, do nothing - the purpose of heartbeats is - // just to make sure that there is some traffic on the connection - // within the heart beat interval, we check for the traffic and - // don't need to do anything in response to heartbeats. The - // exception is when we are in fact the client to another broker - // (i.e. an inter-broker link), in which case we echo the - // heartbeat back to the peer - if (!serverMode) proxy.heartbeat(); -} - -void ConnectionHandler::Handler::start(const FieldTable& serverProperties, - const framing::Array& supportedMechanisms, - const framing::Array& /*locales*/) -{ - string requestedMechanism = connection.getAuthMechanism(); - - std::string username = connection.getUsername(); - - std::string password = connection.getPassword(); - std::string host = connection.getHost(); - std::string service("qpidd"); - - if ( connection.getBroker().isAuthenticating() ) { - sasl = SaslFactory::getInstance().create( username, - password, - service, - host, - 0, // TODO -- mgoulish Fri Sep 24 2010 - 256, - false ); // disallow interaction - } - std::string supportedMechanismsList; - bool requestedMechanismIsSupported = false; - Array::const_iterator i; - - /* - If no specific mechanism has been requested, just make - a list of all of them, and assert that the one the caller - requested is there. ( If *any* are supported! ) - */ - if ( requestedMechanism.empty() ) { - for ( i = supportedMechanisms.begin(); i != supportedMechanisms.end(); ++i) { - if (i != supportedMechanisms.begin()) - supportedMechanismsList += SPACE; - supportedMechanismsList += (*i)->get<std::string>(); - requestedMechanismIsSupported = true; - } - } - else { - requestedMechanismIsSupported = false; - /* - The caller has requested a mechanism. If it's available, - make sure it ends up at the head of the list. - */ - for ( i = supportedMechanisms.begin(); i != supportedMechanisms.end(); ++i) { - string currentMechanism = (*i)->get<std::string>(); - - if ( requestedMechanism == currentMechanism ) { - requestedMechanismIsSupported = true; - supportedMechanismsList = currentMechanism + SPACE + supportedMechanismsList; - } else { - if (i != supportedMechanisms.begin()) - supportedMechanismsList += SPACE; - supportedMechanismsList += currentMechanism; - } - } - } - - connection.setFederationPeerTag(serverProperties.getAsString(QPID_FED_TAG)); - - FieldTable ft; - ft.setInt(QPID_FED_LINK,1); - ft.setString(QPID_FED_TAG, connection.getBroker().getFederationTag()); - - string response; - if (sasl.get()) { - const qpid::sys::SecuritySettings& ss = connection.getExternalSecuritySettings(); - response = sasl->start ( requestedMechanism.empty() - ? supportedMechanismsList - : requestedMechanism, - & ss ); - proxy.startOk ( ft, sasl->getMechanism(), response, en_US ); - } - else { - response = ((char)0) + username + ((char)0) + password; - proxy.startOk ( ft, requestedMechanism, response, en_US ); - } - -} - -void ConnectionHandler::Handler::secure(const string& challenge ) -{ - if (sasl.get()) { - string response = sasl->step(challenge); - proxy.secureOk(response); - } - else { - proxy.secureOk(""); - } -} - -void ConnectionHandler::Handler::tune(uint16_t channelMax, - uint16_t maxFrameSizeProposed, - uint16_t /*heartbeatMin*/, - uint16_t heartbeatMax) -{ - maxFrameSize = std::min(maxFrameSize, maxFrameSizeProposed); - connection.setFrameMax(maxFrameSize); - - connection.setHeartbeat(heartbeatMax); - proxy.tuneOk(channelMax, maxFrameSize, heartbeatMax); - proxy.open("/", Array(), true); -} - -void ConnectionHandler::Handler::openOk(const framing::Array& knownHosts) -{ - for (Array::ValueVector::const_iterator i = knownHosts.begin(); i != knownHosts.end(); ++i) { - Url url((*i)->get<std::string>()); - connection.getKnownHosts().push_back(url); - } - - if (sasl.get()) { - std::auto_ptr<qpid::sys::SecurityLayer> securityLayer = sasl->getSecurityLayer(maxFrameSize); - - if ( securityLayer.get() ) { - secured->activateSecurityLayer(securityLayer, true); - } - - saslUserId = sasl->getUserId(); - } - - isOpen = true; -} - -void ConnectionHandler::Handler::redirect(const string& /*host*/, const framing::Array& /*knownHosts*/) -{ - -} diff --git a/cpp/src/qpid/broker/ConnectionHandler.h b/cpp/src/qpid/broker/ConnectionHandler.h deleted file mode 100644 index b32167669e..0000000000 --- a/cpp/src/qpid/broker/ConnectionHandler.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _ConnectionAdapter_ -#define _ConnectionAdapter_ - -#include <memory> -#include "qpid/Sasl.h" -#include "qpid/broker/SaslAuthenticator.h" -#include "qpid/framing/amqp_types.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/AMQP_AllOperations.h" -#include "qpid/framing/AMQP_AllProxy.h" -#include "qpid/framing/enum.h" -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/ProtocolInitiation.h" -#include "qpid/framing/ProtocolVersion.h" -#include "qpid/Exception.h" -#include "qpid/broker/AclModule.h" -#include "qpid/sys/SecurityLayer.h" - - -namespace qpid { - -namespace sys { -struct SecuritySettings; -} - - -namespace broker { - -class Connection; -class SecureConnection; - -class ConnectionHandler : public framing::FrameHandler -{ - struct Handler : public framing::AMQP_AllOperations::ConnectionHandler - { - framing::AMQP_AllProxy::Connection proxy; - Connection& connection; - bool serverMode; - std::auto_ptr<SaslAuthenticator> authenticator; - AclModule* acl; - SecureConnection* secured; - bool isOpen; - - Handler(Connection& connection, bool isClient, bool isShadow=false); - ~Handler(); - void startOk(const qpid::framing::FieldTable& clientProperties, - const std::string& mechanism, const std::string& response, - const std::string& locale); - void secureOk(const std::string& response); - void tuneOk(uint16_t channelMax, uint16_t frameMax, uint16_t heartbeat); - void heartbeat(); - void open(const std::string& virtualHost, - const framing::Array& capabilities, bool insist); - void close(uint16_t replyCode, const std::string& replyText); - void closeOk(); - - void start(const qpid::framing::FieldTable& serverProperties, - const framing::Array& mechanisms, - const framing::Array& locales); - - void secure(const std::string& challenge); - - void tune(uint16_t channelMax, - uint16_t frameMax, - uint16_t heartbeatMin, - uint16_t heartbeatMax); - - void openOk(const framing::Array& knownHosts); - - void redirect(const std::string& host, const framing::Array& knownHosts); - - std::auto_ptr<Sasl> sasl; - typedef boost::function<const qpid::sys::SecuritySettings*()> GetSecuritySettings; - std::string saslUserId; - uint16_t maxFrameSize; - }; - std::auto_ptr<Handler> handler; - - - public: - ConnectionHandler(Connection& connection, bool isClient, bool isShadow=false ); - void close(framing::connection::CloseCode code, const std::string& text); - void heartbeat(); - void handle(framing::AMQFrame& frame); - void setSecureConnection(SecureConnection* secured); - bool isOpen() { return handler->isOpen; } -}; - - -}} - -#endif diff --git a/cpp/src/qpid/broker/ConnectionState.h b/cpp/src/qpid/broker/ConnectionState.h deleted file mode 100644 index 9c31a931d8..0000000000 --- a/cpp/src/qpid/broker/ConnectionState.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _ConnectionState_ -#define _ConnectionState_ - -#include <vector> - -#include "qpid/sys/AggregateOutput.h" -#include "qpid/sys/ConnectionOutputHandlerPtr.h" -#include "qpid/framing/ProtocolVersion.h" -#include "qpid/management/Manageable.h" -#include "qpid/Url.h" -#include "qpid/broker/Broker.h" - -namespace qpid { -namespace broker { - -class ConnectionState : public ConnectionToken, public management::Manageable -{ - protected: - sys::ConnectionOutputHandlerPtr out; - - public: - ConnectionState(qpid::sys::ConnectionOutputHandler* o, Broker& b) : - out(o), - broker(b), - outputTasks(out), - framemax(65535), - heartbeat(0), - heartbeatmax(120), - federationLink(true), - clientSupportsThrottling(false), - clusterOrderOut(0) - {} - - virtual ~ConnectionState () {} - - uint32_t getFrameMax() const { return framemax; } - uint16_t getHeartbeat() const { return heartbeat; } - uint16_t getHeartbeatMax() const { return heartbeatmax; } - - void setFrameMax(uint32_t fm) { framemax = std::max(fm, (uint32_t) 4096); } - void setHeartbeat(uint16_t hb) { heartbeat = hb; } - void setHeartbeatMax(uint16_t hbm) { heartbeatmax = hbm; } - - virtual void setUserId(const std::string& uid) { userId = uid; } - const std::string& getUserId() const { return userId; } - - void setUrl(const std::string& _url) { url = _url; } - const std::string& getUrl() const { return url; } - - void setFederationLink(bool b) { federationLink = b; } - bool isFederationLink() const { return federationLink; } - void setFederationPeerTag(const std::string& tag) { federationPeerTag = std::string(tag); } - const std::string& getFederationPeerTag() const { return federationPeerTag; } - std::vector<Url>& getKnownHosts() { return knownHosts; } - - void setClientThrottling(bool set=true) { clientSupportsThrottling = set; } - bool getClientThrottling() const { return clientSupportsThrottling; } - - Broker& getBroker() { return broker; } - - Broker& broker; - - //contained output tasks - sys::AggregateOutput outputTasks; - - sys::ConnectionOutputHandler& getOutput() { return out; } - framing::ProtocolVersion getVersion() const { return version; } - void setOutputHandler(qpid::sys::ConnectionOutputHandler* o) { out.set(o); } - - /** - * If the broker is part of a cluster, this is a handler provided - * by cluster code. It ensures consistent ordering of commands - * that are sent based on criteria that are not predictably - * ordered cluster-wide, e.g. a timer firing. - */ - framing::FrameHandler* getClusterOrderOutput() { return clusterOrderOut; } - void setClusterOrderOutput(framing::FrameHandler& fh) { clusterOrderOut = &fh; } - - virtual void requestIOProcessing (boost::function0<void>) = 0; - - protected: - framing::ProtocolVersion version; - uint32_t framemax; - uint16_t heartbeat; - uint16_t heartbeatmax; - std::string userId; - std::string url; - bool federationLink; - std::string federationPeerTag; - std::vector<Url> knownHosts; - bool clientSupportsThrottling; - framing::FrameHandler* clusterOrderOut; -}; - -}} - -#endif diff --git a/cpp/src/qpid/broker/ConnectionToken.h b/cpp/src/qpid/broker/ConnectionToken.h deleted file mode 100644 index 9b40383c80..0000000000 --- a/cpp/src/qpid/broker/ConnectionToken.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _ConnectionToken_ -#define _ConnectionToken_ - -#include "qpid/broker/OwnershipToken.h" -namespace qpid { - namespace broker { - /** - * An empty interface allowing opaque implementations of some - * form of token to identify a connection. - */ - class ConnectionToken : public OwnershipToken { - public: - virtual bool isLocal(const ConnectionToken* t) const { return this == t; } - virtual ~ConnectionToken(){} - }; - } -} - - -#endif diff --git a/cpp/src/qpid/broker/Consumer.h b/cpp/src/qpid/broker/Consumer.h deleted file mode 100644 index 317338a8ad..0000000000 --- a/cpp/src/qpid/broker/Consumer.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _Consumer_ -#define _Consumer_ - -#include "qpid/broker/Message.h" -#include "qpid/broker/QueuedMessage.h" -#include "qpid/broker/OwnershipToken.h" - -namespace qpid { -namespace broker { - -class Queue; -class QueueListeners; - -class Consumer { - const bool acquires; - // inListeners allows QueueListeners to efficiently track if this instance is registered - // for notifications without having to search its containers - bool inListeners; - public: - typedef boost::shared_ptr<Consumer> shared_ptr; - - framing::SequenceNumber position; - - Consumer(bool preAcquires = true) : acquires(preAcquires), inListeners(false) {} - bool preAcquires() const { return acquires; } - virtual bool deliver(QueuedMessage& msg) = 0; - virtual void notify() = 0; - virtual bool filter(boost::intrusive_ptr<Message>) { return true; } - virtual bool accept(boost::intrusive_ptr<Message>) { return true; } - virtual OwnershipToken* getSession() = 0; - virtual ~Consumer(){} - friend class QueueListeners; -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/Daemon.cpp b/cpp/src/qpid/broker/Daemon.cpp deleted file mode 100644 index b30e5f18cb..0000000000 --- a/cpp/src/qpid/broker/Daemon.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -/* - * TODO: Note this is really a Posix specific implementation and so should be - * refactored together with windows/QpiddBroker into a more coherent daemon driver/ - * platform specific split - */ -#include "qpid/broker/Daemon.h" -#include "qpid/log/Statement.h" -#include "qpid/Exception.h" -#include "qpid/sys/posix/PidFile.h" - -#include <errno.h> -#include <fcntl.h> -#include <signal.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> - -namespace qpid { -namespace broker { - -using namespace std; -using qpid::sys::PidFile; - -Daemon::Daemon(std::string _pidDir) : pidDir(_pidDir) { - struct stat s; - pid = -1; - pipeFds[0] = pipeFds[1] = -1; - - if (::stat(pidDir.c_str(), &s)) { - if (errno == ENOENT) { - if (::mkdir(pidDir.c_str(), 0755)) - throw Exception ("Can't create PID directory: " + pidDir); - } - else - throw Exception ("PID directory not found: " + pidDir); - } -} - -string Daemon::pidFile(string pidDir, uint16_t port) { - ostringstream path; - path << pidDir << "/qpidd." << port << ".pid"; - return path.str(); -} - -/* - * Rewritten using low-level IO, for compatibility - * with earlier Boost versions, i.e. 103200. - */ -void Daemon::fork() -{ - if(::pipe(pipeFds) < 0) throw ErrnoException("Can't create pipe"); - if ((pid = ::fork()) < 0) throw ErrnoException("Daemon fork failed"); - if (pid == 0) { // Child - try { - QPID_LOG(debug, "Forked daemon child process"); - - // File descriptors - if(::close(pipeFds[0])<0) throw ErrnoException("Cannot close read pipe"); - if(::close(0)<0) throw ErrnoException("Cannot close stdin"); - if(::close(1)<0) throw ErrnoException("Cannot close stdout"); - if(::close(2)<0) throw ErrnoException("Cannot close stderr"); - int fd=::open("/dev/null",O_RDWR); // stdin - if(fd != 0) throw ErrnoException("Cannot re-open stdin"); - if(::dup(fd)<0) throw ErrnoException("Cannot re-open stdout"); - if(::dup(fd)<0) throw ErrnoException("Cannot re-open stderror"); - - // Misc - if(setsid()<0) throw ErrnoException("Cannot set session ID"); - if(chdir(pidDir.c_str()) < 0) throw ErrnoException("Cannot change directory to "+pidDir); - umask(027); - - // Child behavior - child(); - } - catch (const exception& e) { - QPID_LOG(critical, "Unexpected error: " << e.what()); - uint16_t port = 0; - int unused_ret; //Supress warning about ignoring return value. - unused_ret = write(pipeFds[1], &port, sizeof(uint16_t)); - - std::string pipeFailureMessage = e.what(); - unused_ret = write ( pipeFds[1], - pipeFailureMessage.c_str(), - strlen(pipeFailureMessage.c_str()) - ); - } - } - else { // Parent - close(pipeFds[1]); // Write side. - parent(); - } -} - -Daemon::~Daemon() { - if (!lockFile.empty()) - unlink(lockFile.c_str()); -} - -uint16_t Daemon::wait(int timeout) { // parent waits for child. - try { - errno = 0; - struct timeval tv; - tv.tv_sec = timeout; - tv.tv_usec = 0; - - /* - * Rewritten using low-level IO, for compatibility - * with earlier Boost versions, i.e. 103200. - */ - fd_set fds; - FD_ZERO(&fds); - FD_SET(pipeFds[0], &fds); - int n=select(FD_SETSIZE, &fds, 0, 0, &tv); - if(n==0) throw Exception("Timed out waiting for daemon (If store recovery is in progress, use longer wait time)"); - if(n<0) throw ErrnoException("Error waiting for daemon"); - uint16_t port = 0; - /* - * Read the child's port number from the pipe. - */ - int desired_read = sizeof(uint16_t); - if ( desired_read > ::read(pipeFds[0], & port, desired_read) ) - throw Exception("Cannot read from child process."); - - /* - * If the port number is 0, the child has put an error message - * on the pipe. Get it and throw it. - */ - if ( 0 == port ) { - // Skip whitespace - char c = ' '; - while ( isspace(c) ) { - if ( 1 > ::read(pipeFds[0], &c, 1) ) - throw Exception("Child port == 0, and no error message on pipe."); - } - - // Get Message - string errmsg; - do { - errmsg += c; - } while (::read(pipeFds[0], &c, 1)); - throw Exception("Daemon startup failed"+ - (errmsg.empty() ? string(".") : ": " + errmsg)); - } - return port; - } - catch (const std::exception& e) { - // Print directly to cerr. The caller will catch and log the - // exception, but in the case of a daemon parent process we - // also need to be sure the error goes to stderr. A - // dameon's logging configuration normally does not log to - // stderr. - std::cerr << e.what() << endl; - throw; - } -} - - -/* - * When the child is ready, it writes its pid to the - * lockfile and its port number on the pipe back to - * its parent process. This indicates that the - * child has successfully daemonized. When the parent - * hears the good news, it ill exit. - */ -void Daemon::ready(uint16_t port) { // child - lockFile = pidFile(pidDir, port); - PidFile lf(lockFile, true); - - /* - * Write the PID to the lockfile. - */ - lf.writePid(); - - /* - * Write the port number to the parent. - */ - int desired_write = sizeof(uint16_t); - if ( desired_write > ::write(pipeFds[1], & port, desired_write) ) { - throw Exception("Error writing to parent." ); - } - - QPID_LOG(debug, "Daemon ready on port: " << port); -} - -/* - * The parent process reads the child's pid - * from the lockfile. - */ -pid_t Daemon::getPid(string _pidDir, uint16_t port) { - string name = pidFile(_pidDir, port); - PidFile lf(name, false); - pid_t pid = lf.readPid(); - if (kill(pid, 0) < 0 && errno != EPERM) { - unlink(name.c_str()); - throw Exception("Removing stale lock file "+name); - } - return pid; -} - - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/Daemon.h b/cpp/src/qpid/broker/Daemon.h deleted file mode 100644 index a9cd98bce2..0000000000 --- a/cpp/src/qpid/broker/Daemon.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef _broker_Daemon_h -#define _broker_Daemon_h - -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/sys/IntegerTypes.h" -#include <boost/scoped_ptr.hpp> -#include <boost/function.hpp> -#include <boost/noncopyable.hpp> -#include <string> - - -namespace qpid { -namespace broker { - -/** - * Tools for forking and managing a daemon process. - * NB: Only one Daemon instance is allowed in a process. - */ -class Daemon : private boost::noncopyable -{ - public: - /** Check daemon is running on port, throw exception if not */ - static pid_t getPid(std::string pidDir, uint16_t port); - - Daemon(std::string pidDir); - - virtual ~Daemon(); - - /** - * Fork a daemon process. - * Call parent() in the parent process, child() in the child. - */ - void fork(); - - protected: - - /** Called in parent process */ - virtual void parent() = 0; - - /** Called in child process */ - virtual void child() = 0; - - /** Call from parent(): wait for child to indicate it is ready. - * @timeout in seconds to wait for response. - * @return port passed by child to ready(). - */ - uint16_t wait(int timeout); - - /** Call from child(): Notify the parent we are ready and write the - * PID file. - *@param port returned by parent call to wait(). - */ - void ready(uint16_t port); - - private: - static std::string pidFile(std::string pidDir, uint16_t port); - - pid_t pid; - int pipeFds[2]; - int lockFileFd; - std::string lockFile; - std::string pidDir; -}; - -}} // namespace qpid::broker - -#endif /*!_broker_Daemon_h*/ diff --git a/cpp/src/qpid/broker/Deliverable.h b/cpp/src/qpid/broker/Deliverable.h deleted file mode 100644 index ffb5a77bca..0000000000 --- a/cpp/src/qpid/broker/Deliverable.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _Deliverable_ -#define _Deliverable_ - -#include "qpid/broker/Message.h" - -namespace qpid { - namespace broker { - class Deliverable{ - public: - bool delivered; - Deliverable() : delivered(false) {} - - virtual Message& getMessage() = 0; - - virtual void deliverTo(const boost::shared_ptr<Queue>& queue) = 0; - virtual uint64_t contentSize() { return 0; } - virtual ~Deliverable(){} - }; - } -} - - -#endif diff --git a/cpp/src/qpid/broker/DeliverableMessage.cpp b/cpp/src/qpid/broker/DeliverableMessage.cpp deleted file mode 100644 index 3ebb12461c..0000000000 --- a/cpp/src/qpid/broker/DeliverableMessage.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/DeliverableMessage.h" -#include "qpid/broker/Queue.h" - -using namespace qpid::broker; - -DeliverableMessage::DeliverableMessage(const boost::intrusive_ptr<Message>& _msg) : msg(_msg) -{ -} - -void DeliverableMessage::deliverTo(const boost::shared_ptr<Queue>& queue) -{ - queue->deliver(msg); - delivered = true; -} - -Message& DeliverableMessage::getMessage() -{ - return *msg; -} - -uint64_t DeliverableMessage::contentSize () -{ - return msg->contentSize (); -} diff --git a/cpp/src/qpid/broker/DeliverableMessage.h b/cpp/src/qpid/broker/DeliverableMessage.h deleted file mode 100644 index c8d21001eb..0000000000 --- a/cpp/src/qpid/broker/DeliverableMessage.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _DeliverableMessage_ -#define _DeliverableMessage_ - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/Deliverable.h" -#include "qpid/broker/Message.h" - -#include <boost/intrusive_ptr.hpp> - -namespace qpid { - namespace broker { - class QPID_BROKER_CLASS_EXTERN DeliverableMessage : public Deliverable{ - boost::intrusive_ptr<Message> msg; - public: - QPID_BROKER_EXTERN DeliverableMessage(const boost::intrusive_ptr<Message>& msg); - QPID_BROKER_EXTERN virtual void deliverTo(const boost::shared_ptr<Queue>& queue); - QPID_BROKER_EXTERN Message& getMessage(); - QPID_BROKER_EXTERN uint64_t contentSize(); - virtual ~DeliverableMessage(){} - }; - } -} - - -#endif diff --git a/cpp/src/qpid/broker/DeliveryAdapter.h b/cpp/src/qpid/broker/DeliveryAdapter.h deleted file mode 100644 index b0bec60890..0000000000 --- a/cpp/src/qpid/broker/DeliveryAdapter.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _DeliveryAdapter_ -#define _DeliveryAdapter_ - -#include "qpid/broker/DeliveryId.h" -#include "qpid/broker/Message.h" -#include "qpid/framing/amqp_types.h" - -namespace qpid { -namespace broker { - -class DeliveryRecord; - -/** - * The intention behind this interface is to separate the generic - * handling of some form of message delivery to clients that is - * contained in the version independent Channel class from the - * details required for a particular situation or - * version. i.e. where the existing adapters allow (through - * supporting the generated interface for a version of the - * protocol) inputs of a channel to be adapted to the version - * independent part, this does the same for the outputs. - */ -class DeliveryAdapter -{ - public: - virtual void deliver(DeliveryRecord&, bool sync) = 0; - virtual ~DeliveryAdapter(){} -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/DeliveryId.h b/cpp/src/qpid/broker/DeliveryId.h deleted file mode 100644 index 05b19f032e..0000000000 --- a/cpp/src/qpid/broker/DeliveryId.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _DeliveryId_ -#define _DeliveryId_ - -#include "qpid/framing/SequenceNumber.h" -#include "qpid/framing/SequenceNumberSet.h" - -namespace qpid { -namespace broker { - - typedef framing::SequenceNumber DeliveryId; - typedef framing::SequenceNumberSet DeliveryIds; -}} - - -#endif diff --git a/cpp/src/qpid/broker/DeliveryRecord.cpp b/cpp/src/qpid/broker/DeliveryRecord.cpp deleted file mode 100644 index 58dcc6d7c7..0000000000 --- a/cpp/src/qpid/broker/DeliveryRecord.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/DeliveryRecord.h" -#include "qpid/broker/DeliverableMessage.h" -#include "qpid/broker/SemanticState.h" -#include "qpid/broker/Exchange.h" -#include "qpid/broker/Queue.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/MessageTransferBody.h" - -using namespace qpid; -using namespace qpid::broker; -using std::string; - -DeliveryRecord::DeliveryRecord(const QueuedMessage& _msg, - const Queue::shared_ptr& _queue, - const std::string& _tag, - bool _acquired, - bool accepted, - bool _windowing, - uint32_t _credit) : msg(_msg), - queue(_queue), - tag(_tag), - acquired(_acquired), - acceptExpected(!accepted), - cancelled(false), - completed(false), - ended(accepted && acquired), - windowing(_windowing), - credit(msg.payload ? msg.payload->getRequiredCredit() : _credit) -{} - -bool DeliveryRecord::setEnded() -{ - ended = true; - //reset msg pointer, don't need to hold on to it anymore - msg.payload = boost::intrusive_ptr<Message>(); - QPID_LOG(debug, "DeliveryRecord::setEnded() id=" << id); - return isRedundant(); -} - -void DeliveryRecord::redeliver(SemanticState* const session) { - if (!ended) { - if(cancelled){ - //if subscription was cancelled, requeue it (waiting for - //final confirmation for AMQP WG on this case) - requeue(); - }else{ - msg.payload->redeliver();//mark as redelivered - session->deliver(*this, false); - } - } -} - -void DeliveryRecord::deliver(framing::FrameHandler& h, DeliveryId deliveryId, uint16_t framesize) -{ - id = deliveryId; - if (msg.payload->getRedelivered()){ - msg.payload->getProperties<framing::DeliveryProperties>()->setRedelivered(true); - } - msg.payload->adjustTtl(); - - framing::AMQFrame method((framing::MessageTransferBody(framing::ProtocolVersion(), tag, acceptExpected ? 0 : 1, acquired ? 0 : 1))); - method.setEof(false); - h.handle(method); - msg.payload->sendHeader(h, framesize); - msg.payload->sendContent(*queue, h, framesize); -} - -void DeliveryRecord::requeue() const -{ - if (acquired && !ended) { - msg.payload->redeliver(); - queue->requeue(msg); - } -} - -void DeliveryRecord::release(bool setRedelivered) -{ - if (acquired && !ended) { - if (setRedelivered) msg.payload->redeliver(); - queue->requeue(msg); - acquired = false; - setEnded(); - } else { - QPID_LOG(debug, "Ignoring release for " << id << " acquired=" << acquired << ", ended =" << ended); - } -} - -void DeliveryRecord::complete() { - completed = true; -} - -bool DeliveryRecord::accept(TransactionContext* ctxt) { - if (acquired && !ended) { - queue->dequeue(ctxt, msg); - setEnded(); - QPID_LOG(debug, "Accepted " << id); - } - return isRedundant(); -} - -void DeliveryRecord::dequeue(TransactionContext* ctxt) const{ - if (acquired && !ended) { - queue->dequeue(ctxt, msg); - } -} - -void DeliveryRecord::committed() const{ - queue->dequeueCommitted(msg); -} - -void DeliveryRecord::reject() -{ - if (acquired && !ended) { - Exchange::shared_ptr alternate = queue->getAlternateExchange(); - if (alternate) { - DeliverableMessage delivery(msg.payload); - alternate->routeWithAlternate(delivery); - QPID_LOG(info, "Routed rejected message from " << queue->getName() << " to " - << alternate->getName()); - } else { - //just drop it - QPID_LOG(info, "Dropping rejected message from " << queue->getName()); - } - dequeue(); - setEnded(); - } -} - -uint32_t DeliveryRecord::getCredit() const -{ - return credit; -} - -void DeliveryRecord::acquire(DeliveryIds& results) { - if (queue->acquire(msg)) { - acquired = true; - results.push_back(id); - if (!acceptExpected) { - if (ended) { QPID_LOG(error, "Can't dequeue ended message"); } - else { queue->dequeue(0, msg); setEnded(); } - } - } else { - QPID_LOG(info, "Message already acquired " << id.getValue()); - } -} - -void DeliveryRecord::cancel(const std::string& cancelledTag) -{ - if (tag == cancelledTag) - cancelled = true; -} - -AckRange DeliveryRecord::findRange(DeliveryRecords& records, DeliveryId first, DeliveryId last) -{ - DeliveryRecords::iterator start = lower_bound(records.begin(), records.end(), first); - // Find end - position it just after the last record in range - DeliveryRecords::iterator end = lower_bound(records.begin(), records.end(), last); - if (end != records.end() && end->getId() == last) ++end; - return AckRange(start, end); -} - - -namespace qpid { -namespace broker { - -std::ostream& operator<<(std::ostream& out, const DeliveryRecord& r) -{ - out << "{" << "id=" << r.id.getValue(); - out << ", tag=" << r.tag << "}"; - out << ", queue=" << r.queue->getName() << "}"; - return out; -} - - -}} diff --git a/cpp/src/qpid/broker/DeliveryRecord.h b/cpp/src/qpid/broker/DeliveryRecord.h deleted file mode 100644 index d388ba94be..0000000000 --- a/cpp/src/qpid/broker/DeliveryRecord.h +++ /dev/null @@ -1,143 +0,0 @@ -#ifndef QPID_BROKER_DELIVERYRECORD_H -#define QPID_BROKER_DELIVERYRECORD_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <algorithm> -#include <deque> -#include <vector> -#include <ostream> -#include "qpid/framing/SequenceSet.h" -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/QueuedMessage.h" -#include "qpid/broker/DeliveryId.h" -#include "qpid/broker/Message.h" - -namespace qpid { -namespace broker { - -class TransactionContext; -class SemanticState; -struct AckRange; - -/** - * Record of a delivery for which an ack is outstanding. - */ -class DeliveryRecord -{ - QueuedMessage msg; - mutable boost::shared_ptr<Queue> queue; - std::string tag; - DeliveryId id; - bool acquired : 1; - bool acceptExpected : 1; - bool cancelled : 1; - bool completed : 1; - bool ended : 1; - bool windowing : 1; - - /** - * Record required credit on construction as the pointer to the - * message may be reset once we no longer need to deliver it - * (e.g. when it is accepted), but we will still need to be able - * to reallocate credit when it is completed (which could happen - * after that). - */ - uint32_t credit; - - public: - QPID_BROKER_EXTERN DeliveryRecord(const QueuedMessage& msg, - const boost::shared_ptr<Queue>& queue, - const std::string& tag, - bool acquired, - bool accepted, - bool windowing, - uint32_t credit=0 // Only used if msg is empty. - ); - - bool coveredBy(const framing::SequenceSet* const range) const { return range->contains(id); } - - void dequeue(TransactionContext* ctxt = 0) const; - void requeue() const; - void release(bool setRedelivered); - void reject(); - void cancel(const std::string& tag); - void redeliver(SemanticState* const); - void acquire(DeliveryIds& results); - void complete(); - bool accept(TransactionContext* ctxt); // Returns isRedundant() - bool setEnded(); // Returns isRedundant() - void committed() const; - - bool isAcquired() const { return acquired; } - bool isComplete() const { return completed; } - bool isRedundant() const { return ended && (!windowing || completed); } - bool isCancelled() const { return cancelled; } - bool isAccepted() const { return !acceptExpected; } - bool isEnded() const { return ended; } - bool isWindowing() const { return windowing; } - - uint32_t getCredit() const; - const std::string& getTag() const { return tag; } - - void deliver(framing::FrameHandler& h, DeliveryId deliveryId, uint16_t framesize); - void setId(DeliveryId _id) { id = _id; } - - typedef std::deque<DeliveryRecord> DeliveryRecords; - static AckRange findRange(DeliveryRecords& records, DeliveryId first, DeliveryId last); - const QueuedMessage& getMessage() const { return msg; } - framing::SequenceNumber getId() const { return id; } - boost::shared_ptr<Queue> getQueue() const { return queue; } - - friend std::ostream& operator<<(std::ostream&, const DeliveryRecord&); -}; - -inline bool operator<(const DeliveryRecord& a, const DeliveryRecord& b) { return a.getId() < b.getId(); } -inline bool operator<(const framing::SequenceNumber& a, const DeliveryRecord& b) { return a < b.getId(); } -inline bool operator<(const DeliveryRecord& a, const framing::SequenceNumber& b) { return a.getId() < b; } - -struct AcquireFunctor -{ - DeliveryIds& results; - - AcquireFunctor(DeliveryIds& _results) : results(_results) {} - - void operator()(DeliveryRecord& record) - { - record.acquire(results); - } -}; - -typedef DeliveryRecord::DeliveryRecords DeliveryRecords; - -struct AckRange -{ - DeliveryRecords::iterator start; - DeliveryRecords::iterator end; - AckRange(DeliveryRecords::iterator _start, DeliveryRecords::iterator _end) : start(_start), end(_end) {} -}; - -} -} - - -#endif /*!QPID_BROKER_DELIVERYRECORD_H*/ diff --git a/cpp/src/qpid/broker/DirectExchange.cpp b/cpp/src/qpid/broker/DirectExchange.cpp deleted file mode 100644 index 060f80f60d..0000000000 --- a/cpp/src/qpid/broker/DirectExchange.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/log/Statement.h" -#include "qpid/broker/FedOps.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/DirectExchange.h" -#include <iostream> - -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::sys; -using qpid::management::Manageable; -namespace _qmf = qmf::org::apache::qpid::broker; - -namespace -{ - const std::string qpidExclusiveBinding("qpid.exclusive-binding"); -} - -DirectExchange::DirectExchange(const string& _name, Manageable* _parent, Broker* b) : Exchange(_name, _parent, b) -{ - if (mgmtExchange != 0) - mgmtExchange->set_type(typeName); -} - -DirectExchange::DirectExchange(const string& _name, bool _durable, - const FieldTable& _args, Manageable* _parent, Broker* b) : - Exchange(_name, _durable, _args, _parent, b) -{ - if (mgmtExchange != 0) - mgmtExchange->set_type(typeName); -} - -bool DirectExchange::bind(Queue::shared_ptr queue, const string& routingKey, const FieldTable* args) -{ - string fedOp(fedOpBind); - string fedTags; - string fedOrigin; - bool exclusiveBinding = false; - if (args) { - fedOp = args->getAsString(qpidFedOp); - fedTags = args->getAsString(qpidFedTags); - fedOrigin = args->getAsString(qpidFedOrigin); - exclusiveBinding = args->get(qpidExclusiveBinding); // only direct exchanges take exclusive bindings - } - - bool propagate = false; - - if (args == 0 || fedOp.empty() || fedOp == fedOpBind) { - Mutex::ScopedLock l(lock); - Binding::shared_ptr b(new Binding(routingKey, queue, this, FieldTable(), fedOrigin)); - BoundKey& bk = bindings[routingKey]; - if (exclusiveBinding) bk.queues.clear(); - - QPID_LOG(debug, "Bind key [" << routingKey << "] to queue " << queue->getName() - << " (origin=" << fedOrigin << ")"); - - if (bk.queues.add_unless(b, MatchQueue(queue))) { - b->startManagement(); - propagate = bk.fedBinding.addOrigin(queue->getName(), fedOrigin); - if (mgmtExchange != 0) { - mgmtExchange->inc_bindingCount(); - } - } else { - // queue already present - still need to track fedOrigin - bk.fedBinding.addOrigin(queue->getName(), fedOrigin); - return false; - } - } else if (fedOp == fedOpUnbind) { - Mutex::ScopedLock l(lock); - BoundKey& bk = bindings[routingKey]; - - QPID_LOG(debug, "Bind - fedOpUnbind key [" << routingKey << "] queue " << queue->getName() - << " (origin=" << fedOrigin << ")" << " (count=" << bk.fedBinding.count() << ")"); - - propagate = bk.fedBinding.delOrigin(queue->getName(), fedOrigin); - if (bk.fedBinding.countFedBindings(queue->getName()) == 0) - unbind(queue, routingKey, args); - - } else if (fedOp == fedOpReorigin) { - /** gather up all the keys that need rebinding in a local vector - * while holding the lock. Then propagate once the lock is - * released - */ - std::vector<std::string> keys2prop; - { - Mutex::ScopedLock l(lock); - for (Bindings::iterator iter = bindings.begin(); - iter != bindings.end(); iter++) { - const BoundKey& bk = iter->second; - if (bk.fedBinding.hasLocal()) { - keys2prop.push_back(iter->first); - } - } - } /* lock dropped */ - for (std::vector<std::string>::const_iterator key = keys2prop.begin(); - key != keys2prop.end(); key++) { - propagateFedOp( *key, string(), fedOpBind, string()); - } - } - - routeIVE(); - if (propagate) - propagateFedOp(routingKey, fedTags, fedOp, fedOrigin); - return true; -} - -bool DirectExchange::unbind(Queue::shared_ptr queue, const string& routingKey, const FieldTable* args) -{ - string fedOrigin(args ? args->getAsString(qpidFedOrigin) : ""); - bool propagate = false; - - QPID_LOG(debug, "Unbinding key [" << routingKey << "] from queue " << queue->getName() - << " on exchange " << getName() << " origin=" << fedOrigin << ")" ); - { - Mutex::ScopedLock l(lock); - BoundKey& bk = bindings[routingKey]; - if (bk.queues.remove_if(MatchQueue(queue))) { - propagate = bk.fedBinding.delOrigin(queue->getName(), fedOrigin); - if (mgmtExchange != 0) { - mgmtExchange->dec_bindingCount(); - } - } else { - return false; - } - } - - // If I delete my local binding, propagate this unbind to any upstream brokers - if (propagate) - propagateFedOp(routingKey, string(), fedOpUnbind, string()); - return true; -} - -void DirectExchange::route(Deliverable& msg, const string& routingKey, const FieldTable* /*args*/) -{ - PreRoute pr(msg, this); - ConstBindingList b; - { - Mutex::ScopedLock l(lock); - b = bindings[routingKey].queues.snapshot(); - } - doRoute(msg, b); -} - - -bool DirectExchange::isBound(Queue::shared_ptr queue, const string* const routingKey, const FieldTable* const) -{ - Mutex::ScopedLock l(lock); - if (routingKey) { - Bindings::iterator i = bindings.find(*routingKey); - - if (i == bindings.end()) - return false; - if (!queue) - return true; - - Queues::ConstPtr p = i->second.queues.snapshot(); - return p && std::find_if(p->begin(), p->end(), MatchQueue(queue)) != p->end(); - } else if (!queue) { - //if no queue or routing key is specified, just report whether any bindings exist - return bindings.size() > 0; - } else { - for (Bindings::iterator i = bindings.begin(); i != bindings.end(); i++) { - Queues::ConstPtr p = i->second.queues.snapshot(); - if (p && std::find_if(p->begin(), p->end(), MatchQueue(queue)) != p->end()) return true; - } - return false; - } - - return false; -} - -DirectExchange::~DirectExchange() {} - -const std::string DirectExchange::typeName("direct"); diff --git a/cpp/src/qpid/broker/DirectExchange.h b/cpp/src/qpid/broker/DirectExchange.h deleted file mode 100644 index a6f9cf91af..0000000000 --- a/cpp/src/qpid/broker/DirectExchange.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _DirectExchange_ -#define _DirectExchange_ - -#include <map> -#include <vector> -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/Exchange.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/sys/CopyOnWriteArray.h" -#include "qpid/sys/Mutex.h" - -namespace qpid { -namespace broker { -class DirectExchange : public virtual Exchange { - typedef qpid::sys::CopyOnWriteArray<Binding::shared_ptr> Queues; - struct BoundKey { - Queues queues; - FedBinding fedBinding; - }; - typedef std::map<std::string, BoundKey> Bindings; - Bindings bindings; - qpid::sys::Mutex lock; - -public: - static const std::string typeName; - - QPID_BROKER_EXTERN DirectExchange(const std::string& name, - management::Manageable* parent = 0, Broker* broker = 0); - QPID_BROKER_EXTERN DirectExchange(const std::string& _name, - bool _durable, - const qpid::framing::FieldTable& _args, - management::Manageable* parent = 0, Broker* broker = 0); - - virtual std::string getType() const { return typeName; } - - QPID_BROKER_EXTERN virtual bool bind(boost::shared_ptr<Queue> queue, - const std::string& routingKey, - const qpid::framing::FieldTable* args); - virtual bool unbind(boost::shared_ptr<Queue> queue, const std::string& routingKey, const qpid::framing::FieldTable* args); - QPID_BROKER_EXTERN virtual void route(Deliverable& msg, - const std::string& routingKey, - const qpid::framing::FieldTable* args); - QPID_BROKER_EXTERN virtual bool isBound(boost::shared_ptr<Queue> queue, - const std::string* const routingKey, - const qpid::framing::FieldTable* const args); - - QPID_BROKER_EXTERN virtual ~DirectExchange(); - - virtual bool supportsDynamicBinding() { return true; } -}; - -}} - -#endif diff --git a/cpp/src/qpid/broker/DtxAck.cpp b/cpp/src/qpid/broker/DtxAck.cpp deleted file mode 100644 index bca3f90bbe..0000000000 --- a/cpp/src/qpid/broker/DtxAck.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/DtxAck.h" -#include "qpid/log/Statement.h" - -using std::bind1st; -using std::bind2nd; -using std::mem_fun_ref; -using namespace qpid::broker; - -DtxAck::DtxAck(const qpid::framing::SequenceSet& acked, DeliveryRecords& unacked) -{ - remove_copy_if(unacked.begin(), unacked.end(), inserter(pending, pending.end()), - not1(bind2nd(mem_fun_ref(&DeliveryRecord::coveredBy), &acked))); -} - -bool DtxAck::prepare(TransactionContext* ctxt) throw() -{ - try{ - //record dequeue in the store - for (DeliveryRecords::iterator i = pending.begin(); i != pending.end(); i++) { - i->dequeue(ctxt); - } - return true; - }catch(...){ - QPID_LOG(error, "Failed to prepare"); - return false; - } -} - -void DtxAck::commit() throw() -{ - try { - for_each(pending.begin(), pending.end(), mem_fun_ref(&DeliveryRecord::committed)); - pending.clear(); - } catch (const std::exception& e) { - QPID_LOG(error, "Failed to commit: " << e.what()); - } catch(...) { - QPID_LOG(error, "Failed to commit (unknown error)"); - } - -} - -void DtxAck::rollback() throw() -{ - try { - for_each(pending.begin(), pending.end(), mem_fun_ref(&DeliveryRecord::requeue)); - pending.clear(); - } catch (const std::exception& e) { - QPID_LOG(error, "Failed to complete rollback: " << e.what()); - } catch(...) { - QPID_LOG(error, "Failed to complete rollback (unknown error)"); - } - -} diff --git a/cpp/src/qpid/broker/DtxAck.h b/cpp/src/qpid/broker/DtxAck.h deleted file mode 100644 index 166147e58d..0000000000 --- a/cpp/src/qpid/broker/DtxAck.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _DtxAck_ -#define _DtxAck_ - -#include <algorithm> -#include <functional> -#include <list> -#include "qpid/framing/SequenceSet.h" -#include "qpid/broker/DeliveryRecord.h" -#include "qpid/broker/TxOp.h" - -namespace qpid { - namespace broker { - class DtxAck : public TxOp{ - DeliveryRecords pending; - - public: - DtxAck(const framing::SequenceSet& acked, DeliveryRecords& unacked); - virtual bool prepare(TransactionContext* ctxt) throw(); - virtual void commit() throw(); - virtual void rollback() throw(); - virtual ~DtxAck(){} - virtual void accept(TxOpConstVisitor& visitor) const { visitor(*this); } - }; - } -} - - -#endif diff --git a/cpp/src/qpid/broker/DtxBuffer.cpp b/cpp/src/qpid/broker/DtxBuffer.cpp deleted file mode 100644 index f1b8169cf7..0000000000 --- a/cpp/src/qpid/broker/DtxBuffer.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/DtxBuffer.h" - -using namespace qpid::broker; -using qpid::sys::Mutex; - -DtxBuffer::DtxBuffer(const std::string& _xid) - : xid(_xid), ended(false), suspended(false), failed(false), expired(false) {} - -DtxBuffer::~DtxBuffer() {} - -void DtxBuffer::markEnded() -{ - Mutex::ScopedLock locker(lock); - ended = true; -} - -bool DtxBuffer::isEnded() -{ - Mutex::ScopedLock locker(lock); - return ended; -} - -void DtxBuffer::setSuspended(bool isSuspended) -{ - suspended = isSuspended; -} - -bool DtxBuffer::isSuspended() -{ - return suspended; -} - -void DtxBuffer::fail() -{ - Mutex::ScopedLock locker(lock); - rollback(); - failed = true; - ended = true; -} - -bool DtxBuffer::isRollbackOnly() -{ - Mutex::ScopedLock locker(lock); - return failed; -} - -const std::string& DtxBuffer::getXid() -{ - return xid; -} - -void DtxBuffer::timedout() -{ - Mutex::ScopedLock locker(lock); - expired = true; - fail(); -} - -bool DtxBuffer::isExpired() -{ - Mutex::ScopedLock locker(lock); - return expired; -} diff --git a/cpp/src/qpid/broker/DtxBuffer.h b/cpp/src/qpid/broker/DtxBuffer.h deleted file mode 100644 index 1511cb032f..0000000000 --- a/cpp/src/qpid/broker/DtxBuffer.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _DtxBuffer_ -#define _DtxBuffer_ - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/TxBuffer.h" -#include "qpid/sys/Mutex.h" - -namespace qpid { - namespace broker { - class DtxBuffer : public TxBuffer{ - sys::Mutex lock; - const std::string xid; - bool ended; - bool suspended; - bool failed; - bool expired; - - public: - typedef boost::shared_ptr<DtxBuffer> shared_ptr; - - QPID_BROKER_EXTERN DtxBuffer(const std::string& xid = ""); - QPID_BROKER_EXTERN ~DtxBuffer(); - QPID_BROKER_EXTERN void markEnded(); - bool isEnded(); - void setSuspended(bool suspended); - bool isSuspended(); - void fail(); - bool isRollbackOnly(); - void timedout(); - bool isExpired(); - const std::string& getXid(); - }; - } -} - - -#endif diff --git a/cpp/src/qpid/broker/DtxManager.cpp b/cpp/src/qpid/broker/DtxManager.cpp deleted file mode 100644 index 3caa41c3f4..0000000000 --- a/cpp/src/qpid/broker/DtxManager.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/DtxManager.h" -#include "qpid/broker/DtxTimeout.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Timer.h" -#include "qpid/ptr_map.h" - -#include <boost/format.hpp> -#include <iostream> - -using boost::intrusive_ptr; -using qpid::sys::Mutex; -using qpid::ptr_map_ptr; -using namespace qpid::broker; -using namespace qpid::framing; - -DtxManager::DtxManager(qpid::sys::Timer& t) : store(0), timer(t) {} - -DtxManager::~DtxManager() {} - -void DtxManager::start(const std::string& xid, DtxBuffer::shared_ptr ops) -{ - createWork(xid)->add(ops); -} - -void DtxManager::join(const std::string& xid, DtxBuffer::shared_ptr ops) -{ - getWork(xid)->add(ops); -} - -void DtxManager::recover(const std::string& xid, std::auto_ptr<TPCTransactionContext> txn, DtxBuffer::shared_ptr ops) -{ - createWork(xid)->recover(txn, ops); -} - -bool DtxManager::prepare(const std::string& xid) -{ - QPID_LOG(debug, "preparing: " << xid); - try { - return getWork(xid)->prepare(); - } catch (DtxTimeoutException& e) { - remove(xid); - throw e; - } -} - -bool DtxManager::commit(const std::string& xid, bool onePhase) -{ - QPID_LOG(debug, "committing: " << xid); - try { - bool result = getWork(xid)->commit(onePhase); - remove(xid); - return result; - } catch (DtxTimeoutException& e) { - remove(xid); - throw e; - } -} - -void DtxManager::rollback(const std::string& xid) -{ - QPID_LOG(debug, "rolling back: " << xid); - try { - getWork(xid)->rollback(); - remove(xid); - } catch (DtxTimeoutException& e) { - remove(xid); - throw e; - } -} - -DtxWorkRecord* DtxManager::getWork(const std::string& xid) -{ - Mutex::ScopedLock locker(lock); - WorkMap::iterator i = work.find(xid); - if (i == work.end()) { - throw NotFoundException(QPID_MSG("Unrecognised xid " << xid)); - } - return ptr_map_ptr(i); -} - -void DtxManager::remove(const std::string& xid) -{ - Mutex::ScopedLock locker(lock); - WorkMap::iterator i = work.find(xid); - if (i == work.end()) { - throw NotFoundException(QPID_MSG("Unrecognised xid " << xid)); - } else { - work.erase(i); - } -} - -DtxWorkRecord* DtxManager::createWork(std::string xid) -{ - Mutex::ScopedLock locker(lock); - WorkMap::iterator i = work.find(xid); - if (i != work.end()) { - throw NotAllowedException(QPID_MSG("Xid " << xid << " is already known (use 'join' to add work to an existing xid)")); - } else { - return ptr_map_ptr(work.insert(xid, new DtxWorkRecord(xid, store)).first); - } -} - -void DtxManager::setTimeout(const std::string& xid, uint32_t secs) -{ - DtxWorkRecord* record = getWork(xid); - intrusive_ptr<DtxTimeout> timeout = record->getTimeout(); - if (timeout.get()) { - if (timeout->timeout == secs) return;//no need to do anything further if timeout hasn't changed - timeout->cancel(); - } - timeout = intrusive_ptr<DtxTimeout>(new DtxTimeout(secs, *this, xid)); - record->setTimeout(timeout); - timer.add(timeout); -} - -uint32_t DtxManager::getTimeout(const std::string& xid) -{ - intrusive_ptr<DtxTimeout> timeout = getWork(xid)->getTimeout(); - return !timeout ? 0 : timeout->timeout; -} - -void DtxManager::timedout(const std::string& xid) -{ - Mutex::ScopedLock locker(lock); - WorkMap::iterator i = work.find(xid); - if (i == work.end()) { - QPID_LOG(warning, "Transaction timeout failed: no record for xid"); - } else { - ptr_map_ptr(i)->timedout(); - //TODO: do we want to have a timed task to cleanup, or can we rely on an explicit completion? - //timer.add(intrusive_ptr<TimerTask>(new DtxCleanup(60*30/*30 mins*/, *this, xid))); - } -} - -DtxManager::DtxCleanup::DtxCleanup(uint32_t _timeout, DtxManager& _mgr, const std::string& _xid) - : TimerTask(qpid::sys::Duration(_timeout * qpid::sys::TIME_SEC),"DtxCleanup"), mgr(_mgr), xid(_xid) {} - -void DtxManager::DtxCleanup::fire() -{ - try { - mgr.remove(xid); - } catch (ConnectionException& /*e*/) { - //assume it was explicitly cleaned up after a call to prepare, commit or rollback - } -} - -void DtxManager::setStore (TransactionalStore* _store) -{ - store = _store; -} diff --git a/cpp/src/qpid/broker/DtxManager.h b/cpp/src/qpid/broker/DtxManager.h deleted file mode 100644 index 680b62eeb2..0000000000 --- a/cpp/src/qpid/broker/DtxManager.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _DtxManager_ -#define _DtxManager_ - -#include <boost/ptr_container/ptr_map.hpp> -#include "qpid/broker/DtxBuffer.h" -#include "qpid/broker/DtxWorkRecord.h" -#include "qpid/broker/TransactionalStore.h" -#include "qpid/framing/amqp_types.h" -#include "qpid/sys/Timer.h" -#include "qpid/sys/Mutex.h" - -namespace qpid { -namespace broker { - -class DtxManager{ - typedef boost::ptr_map<std::string, DtxWorkRecord> WorkMap; - - struct DtxCleanup : public sys::TimerTask - { - DtxManager& mgr; - const std::string& xid; - - DtxCleanup(uint32_t timeout, DtxManager& mgr, const std::string& xid); - void fire(); - }; - - WorkMap work; - TransactionalStore* store; - qpid::sys::Mutex lock; - qpid::sys::Timer& timer; - - void remove(const std::string& xid); - DtxWorkRecord* getWork(const std::string& xid); - DtxWorkRecord* createWork(std::string xid); - -public: - DtxManager(qpid::sys::Timer&); - ~DtxManager(); - void start(const std::string& xid, DtxBuffer::shared_ptr work); - void join(const std::string& xid, DtxBuffer::shared_ptr work); - void recover(const std::string& xid, std::auto_ptr<TPCTransactionContext> txn, DtxBuffer::shared_ptr work); - bool prepare(const std::string& xid); - bool commit(const std::string& xid, bool onePhase); - void rollback(const std::string& xid); - void setTimeout(const std::string& xid, uint32_t secs); - uint32_t getTimeout(const std::string& xid); - void timedout(const std::string& xid); - void setStore(TransactionalStore* store); -}; - -} -} - -#endif diff --git a/cpp/src/qpid/broker/DtxTimeout.cpp b/cpp/src/qpid/broker/DtxTimeout.cpp deleted file mode 100644 index c4c52ec40a..0000000000 --- a/cpp/src/qpid/broker/DtxTimeout.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/DtxTimeout.h" -#include "qpid/broker/DtxManager.h" -#include "qpid/sys/Time.h" - -using namespace qpid::broker; - -DtxTimeout::DtxTimeout(uint32_t _timeout, DtxManager& _mgr, const std::string& _xid) - : TimerTask(qpid::sys::Duration(_timeout * qpid::sys::TIME_SEC),"DtxTimeout"), timeout(_timeout), mgr(_mgr), xid(_xid) -{ -} - -void DtxTimeout::fire() -{ - mgr.timedout(xid); -} diff --git a/cpp/src/qpid/broker/DtxTimeout.h b/cpp/src/qpid/broker/DtxTimeout.h deleted file mode 100644 index 680a210e4f..0000000000 --- a/cpp/src/qpid/broker/DtxTimeout.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _DtxTimeout_ -#define _DtxTimeout_ - -#include "qpid/Exception.h" -#include "qpid/sys/Timer.h" - -namespace qpid { -namespace broker { - -class DtxManager; - -struct DtxTimeoutException : public Exception {}; - -struct DtxTimeout : public sys::TimerTask -{ - const uint32_t timeout; - DtxManager& mgr; - const std::string xid; - - DtxTimeout(uint32_t timeout, DtxManager& mgr, const std::string& xid); - void fire(); -}; - -} -} - - -#endif diff --git a/cpp/src/qpid/broker/DtxWorkRecord.cpp b/cpp/src/qpid/broker/DtxWorkRecord.cpp deleted file mode 100644 index 9f33e698db..0000000000 --- a/cpp/src/qpid/broker/DtxWorkRecord.cpp +++ /dev/null @@ -1,177 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/DtxWorkRecord.h" -#include "qpid/framing/reply_exceptions.h" -#include <boost/format.hpp> -#include <boost/mem_fn.hpp> -using boost::mem_fn; -using qpid::sys::Mutex; - -using namespace qpid::broker; -using namespace qpid::framing; - -DtxWorkRecord::DtxWorkRecord(const std::string& _xid, TransactionalStore* const _store) : - xid(_xid), store(_store), completed(false), rolledback(false), prepared(false), expired(false) {} - -DtxWorkRecord::~DtxWorkRecord() -{ - if (timeout.get()) { - timeout->cancel(); - } -} - -bool DtxWorkRecord::prepare() -{ - Mutex::ScopedLock locker(lock); - if (check()) { - txn = store->begin(xid); - if (prepare(txn.get())) { - store->prepare(*txn); - prepared = true; - } else { - abort(); - //TODO: this should probably be flagged as internal error - } - } else { - //some part of the work has been marked rollback only - abort(); - } - return prepared; -} - -bool DtxWorkRecord::prepare(TransactionContext* _txn) -{ - bool succeeded(true); - for (Work::iterator i = work.begin(); succeeded && i != work.end(); i++) { - succeeded = (*i)->prepare(_txn); - } - return succeeded; -} - -bool DtxWorkRecord::commit(bool onePhase) -{ - Mutex::ScopedLock locker(lock); - if (check()) { - if (prepared) { - //already prepared i.e. 2pc - if (onePhase) { - throw IllegalStateException(QPID_MSG("Branch with xid " << xid << " has been prepared, one-phase option not valid!")); - } - - store->commit(*txn); - txn.reset(); - - std::for_each(work.begin(), work.end(), mem_fn(&TxBuffer::commit)); - return true; - } else { - //1pc commit optimisation, don't need a 2pc transaction context: - if (!onePhase) { - throw IllegalStateException(QPID_MSG("Branch with xid " << xid << " has not been prepared, one-phase option required!")); - } - std::auto_ptr<TransactionContext> localtxn = store->begin(); - if (prepare(localtxn.get())) { - store->commit(*localtxn); - std::for_each(work.begin(), work.end(), mem_fn(&TxBuffer::commit)); - return true; - } else { - store->abort(*localtxn); - abort(); - //TODO: this should probably be flagged as internal error - return false; - } - } - } else { - //some part of the work has been marked rollback only - abort(); - return false; - } -} - -void DtxWorkRecord::rollback() -{ - Mutex::ScopedLock locker(lock); - check(); - abort(); -} - -void DtxWorkRecord::add(DtxBuffer::shared_ptr ops) -{ - Mutex::ScopedLock locker(lock); - if (expired) { - throw DtxTimeoutException(); - } - if (completed) { - throw CommandInvalidException(QPID_MSG("Branch with xid " << xid << " has been completed!")); - } - work.push_back(ops); -} - -bool DtxWorkRecord::check() -{ - if (expired) { - throw DtxTimeoutException(); - } - if (!completed) { - //iterate through all DtxBuffers and ensure they are all ended - for (Work::iterator i = work.begin(); i != work.end(); i++) { - if (!(*i)->isEnded()) { - throw IllegalStateException(QPID_MSG("Branch with xid " << xid << " not completed!")); - } else if ((*i)->isRollbackOnly()) { - rolledback = true; - } - } - completed = true; - } - return !rolledback; -} - -void DtxWorkRecord::abort() -{ - if (txn.get()) { - store->abort(*txn); - txn.reset(); - } - std::for_each(work.begin(), work.end(), mem_fn(&TxBuffer::rollback)); -} - -void DtxWorkRecord::recover(std::auto_ptr<TPCTransactionContext> _txn, DtxBuffer::shared_ptr ops) -{ - add(ops); - txn = _txn; - ops->markEnded(); - completed = true; - prepared = true; -} - -void DtxWorkRecord::timedout() -{ - Mutex::ScopedLock locker(lock); - expired = true; - rolledback = true; - if (!completed) { - for (Work::iterator i = work.begin(); i != work.end(); i++) { - if (!(*i)->isEnded()) { - (*i)->timedout(); - } - } - } - abort(); -} diff --git a/cpp/src/qpid/broker/DtxWorkRecord.h b/cpp/src/qpid/broker/DtxWorkRecord.h deleted file mode 100644 index aec2d2aed4..0000000000 --- a/cpp/src/qpid/broker/DtxWorkRecord.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _DtxWorkRecord_ -#define _DtxWorkRecord_ - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/DtxBuffer.h" -#include "qpid/broker/DtxTimeout.h" -#include "qpid/broker/TransactionalStore.h" - -#include "qpid/framing/amqp_types.h" -#include "qpid/sys/Mutex.h" - -#include <algorithm> -#include <functional> -#include <vector> - -#include <boost/intrusive_ptr.hpp> - -namespace qpid { -namespace broker { - -/** - * Represents the work done under a particular distributed transaction - * across potentially multiple channels. Identified by a xid. Allows - * that work to be prepared, committed and rolled-back. - */ -class DtxWorkRecord -{ - typedef std::vector<DtxBuffer::shared_ptr> Work; - - const std::string xid; - TransactionalStore* const store; - bool completed; - bool rolledback; - bool prepared; - bool expired; - boost::intrusive_ptr<DtxTimeout> timeout; - Work work; - std::auto_ptr<TPCTransactionContext> txn; - qpid::sys::Mutex lock; - - bool check(); - void abort(); - bool prepare(TransactionContext* txn); -public: - QPID_BROKER_EXTERN DtxWorkRecord(const std::string& xid, - TransactionalStore* const store); - QPID_BROKER_EXTERN ~DtxWorkRecord(); - QPID_BROKER_EXTERN bool prepare(); - QPID_BROKER_EXTERN bool commit(bool onePhase); - QPID_BROKER_EXTERN void rollback(); - QPID_BROKER_EXTERN void add(DtxBuffer::shared_ptr ops); - void recover(std::auto_ptr<TPCTransactionContext> txn, DtxBuffer::shared_ptr ops); - void timedout(); - void setTimeout(boost::intrusive_ptr<DtxTimeout> t) { timeout = t; } - boost::intrusive_ptr<DtxTimeout> getTimeout() { return timeout; } -}; - -} -} - -#endif diff --git a/cpp/src/qpid/broker/Exchange.cpp b/cpp/src/qpid/broker/Exchange.cpp deleted file mode 100644 index 622cc81002..0000000000 --- a/cpp/src/qpid/broker/Exchange.cpp +++ /dev/null @@ -1,403 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/Broker.h" -#include "qpid/broker/DeliverableMessage.h" -#include "qpid/broker/Exchange.h" -#include "qpid/broker/ExchangeRegistry.h" -#include "qpid/broker/FedOps.h" -#include "qpid/broker/Queue.h" -#include "qpid/framing/MessageProperties.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/log/Statement.h" -#include "qpid/management/ManagementAgent.h" -#include "qpid/sys/ExceptionHolder.h" -#include <stdexcept> - -using namespace qpid::broker; -using namespace qpid::framing; -using qpid::framing::Buffer; -using qpid::framing::FieldTable; -using qpid::sys::Mutex; -using qpid::management::ManagementAgent; -using qpid::management::ManagementObject; -using qpid::management::Manageable; -using qpid::management::Args; -namespace _qmf = qmf::org::apache::qpid::broker; - -namespace -{ - const std::string qpidMsgSequence("qpid.msg_sequence"); - const std::string qpidSequenceCounter("qpid.sequence_counter"); - const std::string qpidIVE("qpid.ive"); - const std::string QPID_MANAGEMENT("qpid.management"); -} - - -Exchange::PreRoute::PreRoute(Deliverable& msg, Exchange* _p):parent(_p) { - if (parent){ - if (parent->sequence || parent->ive) parent->sequenceLock.lock(); - - if (parent->sequence){ - parent->sequenceNo++; - msg.getMessage().getProperties<MessageProperties>()->getApplicationHeaders().setInt64(qpidMsgSequence,parent->sequenceNo); - } - if (parent->ive) { - parent->lastMsg = &( msg.getMessage()); - } - } -} - -Exchange::PreRoute::~PreRoute(){ - if (parent && (parent->sequence || parent->ive)){ - parent->sequenceLock.unlock(); - } -} - -namespace { -/** Store information about an exception to be thrown later. - * If multiple exceptions are stored, save the first of the "most severe" - * exceptions, SESSION is les sever than CONNECTION etc. - */ -class ExInfo { - public: - enum Type { NONE, SESSION, CONNECTION, OTHER }; - - ExInfo(string exchange) : type(NONE), exchange(exchange) {} - void store(Type type_, const qpid::sys::ExceptionHolder& exception_, const boost::shared_ptr<Queue>& queue) { - QPID_LOG(warning, "Exchange " << exchange << " cannot deliver to queue " - << queue->getName() << ": " << exception_.what()); - if (type < type_) { // Replace less severe exception - type = type_; - exception = exception_; - } - } - - void raise() { - exception.raise(); - } - - private: - Type type; - string exchange; - qpid::sys::ExceptionHolder exception; -}; -} - -void Exchange::doRoute(Deliverable& msg, ConstBindingList b) -{ - int count = 0; - - if (b.get()) { - // Block the content release if the message is transient AND there is more than one binding - if (!msg.getMessage().isPersistent() && b->size() > 1) { - msg.getMessage().blockContentRelease(); - } - - - ExInfo error(getName()); // Save exception to throw at the end. - for(std::vector<Binding::shared_ptr>::const_iterator i = b->begin(); i != b->end(); i++, count++) { - try { - msg.deliverTo((*i)->queue); - if ((*i)->mgmtBinding != 0) - (*i)->mgmtBinding->inc_msgMatched(); - } - catch (const SessionException& e) { - error.store(ExInfo::SESSION, framing::createSessionException(e.code, e.what()),(*i)->queue); - } - catch (const ConnectionException& e) { - error.store(ExInfo::CONNECTION, framing::createConnectionException(e.code, e.what()), (*i)->queue); - } - catch (const std::exception& e) { - error.store(ExInfo::OTHER, qpid::sys::ExceptionHolder(new Exception(e.what())), (*i)->queue); - } - } - error.raise(); - } - - if (mgmtExchange != 0) - { - mgmtExchange->inc_msgReceives (); - mgmtExchange->inc_byteReceives (msg.contentSize ()); - if (count == 0) - { - //QPID_LOG(warning, "Exchange " << getName() << " could not route message; no matching binding found"); - mgmtExchange->inc_msgDrops (); - mgmtExchange->inc_byteDrops (msg.contentSize ()); - } - else - { - mgmtExchange->inc_msgRoutes (count); - mgmtExchange->inc_byteRoutes (count * msg.contentSize ()); - } - } -} - -void Exchange::routeIVE(){ - if (ive && lastMsg.get()){ - DeliverableMessage dmsg(lastMsg); - route(dmsg, lastMsg->getRoutingKey(), lastMsg->getApplicationHeaders()); - } -} - - -Exchange::Exchange (const string& _name, Manageable* parent, Broker* b) : - name(_name), durable(false), persistenceId(0), sequence(false), - sequenceNo(0), ive(false), mgmtExchange(0), broker(b), destroyed(false) -{ - if (parent != 0 && broker != 0) - { - ManagementAgent* agent = broker->getManagementAgent(); - if (agent != 0) - { - mgmtExchange = new _qmf::Exchange (agent, this, parent, _name); - mgmtExchange->set_durable(durable); - mgmtExchange->set_autoDelete(false); - agent->addObject(mgmtExchange, 0, durable); - } - } -} - -Exchange::Exchange(const string& _name, bool _durable, const qpid::framing::FieldTable& _args, - Manageable* parent, Broker* b) - : name(_name), durable(_durable), alternateUsers(0), persistenceId(0), - args(_args), sequence(false), sequenceNo(0), ive(false), mgmtExchange(0), broker(b), destroyed(false) -{ - if (parent != 0 && broker != 0) - { - ManagementAgent* agent = broker->getManagementAgent(); - if (agent != 0) - { - mgmtExchange = new _qmf::Exchange (agent, this, parent, _name); - mgmtExchange->set_durable(durable); - mgmtExchange->set_autoDelete(false); - mgmtExchange->set_arguments(ManagementAgent::toMap(args)); - agent->addObject(mgmtExchange, 0, durable); - } - } - - sequence = _args.get(qpidMsgSequence); - if (sequence) { - QPID_LOG(debug, "Configured exchange " << _name << " with Msg sequencing"); - args.setInt64(std::string(qpidSequenceCounter), sequenceNo); - } - - ive = _args.get(qpidIVE); - if (ive) { - if (broker && broker->isInCluster()) - throw framing::NotImplementedException("Cannot use Initial Value Exchanges in a cluster"); - QPID_LOG(debug, "Configured exchange " << _name << " with Initial Value"); - } -} - -Exchange::~Exchange () -{ - if (mgmtExchange != 0) - mgmtExchange->resourceDestroy (); -} - -void Exchange::setAlternate(Exchange::shared_ptr _alternate) -{ - alternate = _alternate; - if (mgmtExchange != 0) { - if (alternate.get() != 0) - mgmtExchange->set_altExchange(alternate->GetManagementObject()->getObjectId()); - else - mgmtExchange->clr_altExchange(); - } -} - -void Exchange::setPersistenceId(uint64_t id) const -{ - persistenceId = id; -} - -Exchange::shared_ptr Exchange::decode(ExchangeRegistry& exchanges, Buffer& buffer) -{ - string name; - string type; - string altName; - FieldTable args; - - buffer.getShortString(name); - bool durable(buffer.getOctet()); - buffer.getShortString(type); - buffer.get(args); - // For backwards compatibility on restoring exchanges from before the alt-exchange update, perform check - if (buffer.available()) - buffer.getShortString(altName); - - try { - Exchange::shared_ptr exch = exchanges.declare(name, type, durable, args).first; - exch->sequenceNo = args.getAsInt64(qpidSequenceCounter); - exch->alternateName.assign(altName); - return exch; - } catch (const UnknownExchangeTypeException&) { - QPID_LOG(warning, "Could not create exchange " << name << "; type " << type << " is not recognised"); - return Exchange::shared_ptr(); - } -} - -void Exchange::encode(Buffer& buffer) const -{ - buffer.putShortString(name); - buffer.putOctet(durable); - buffer.putShortString(getType()); - if (args.isSet(qpidSequenceCounter)) - args.setInt64(std::string(qpidSequenceCounter),sequenceNo); - buffer.put(args); - buffer.putShortString(alternate.get() ? alternate->getName() : string("")); -} - -uint32_t Exchange::encodedSize() const -{ - return name.size() + 1/*short string size*/ - + 1 /*durable*/ - + getType().size() + 1/*short string size*/ - + (alternate.get() ? alternate->getName().size() : 0) + 1/*short string size*/ - + args.encodedSize(); -} - -void Exchange::recoveryComplete(ExchangeRegistry& exchanges) -{ - if (!alternateName.empty()) { - try { - Exchange::shared_ptr ae = exchanges.get(alternateName); - setAlternate(ae); - } catch (const NotFoundException&) { - QPID_LOG(warning, "Could not set alternate exchange \"" << alternateName << "\": does not exist."); - } - } -} - -ManagementObject* Exchange::GetManagementObject (void) const -{ - return (ManagementObject*) mgmtExchange; -} - -void Exchange::registerDynamicBridge(DynamicBridge* db) -{ - if (!supportsDynamicBinding()) - throw Exception("Exchange type does not support dynamic binding"); - - { - Mutex::ScopedLock l(bridgeLock); - for (std::vector<DynamicBridge*>::iterator iter = bridgeVector.begin(); - iter != bridgeVector.end(); iter++) - (*iter)->sendReorigin(); - - bridgeVector.push_back(db); - } - - FieldTable args; - args.setString(qpidFedOp, fedOpReorigin); - bind(Queue::shared_ptr(), string(), &args); -} - -void Exchange::removeDynamicBridge(DynamicBridge* db) -{ - Mutex::ScopedLock l(bridgeLock); - for (std::vector<DynamicBridge*>::iterator iter = bridgeVector.begin(); - iter != bridgeVector.end(); iter++) - if (*iter == db) { - bridgeVector.erase(iter); - break; - } -} - -void Exchange::handleHelloRequest() -{ -} - -void Exchange::propagateFedOp(const string& routingKey, const string& tags, const string& op, const string& origin, qpid::framing::FieldTable* extra_args) -{ - Mutex::ScopedLock l(bridgeLock); - string myOp(op.empty() ? fedOpBind : op); - - for (std::vector<DynamicBridge*>::iterator iter = bridgeVector.begin(); - iter != bridgeVector.end(); iter++) - (*iter)->propagateBinding(routingKey, tags, op, origin, extra_args); -} - -Exchange::Binding::Binding(const string& _key, Queue::shared_ptr _queue, Exchange* _parent, - FieldTable _args, const string& _origin) - : parent(_parent), queue(_queue), key(_key), args(_args), origin(_origin), mgmtBinding(0) -{ -} - -Exchange::Binding::~Binding () -{ - if (mgmtBinding != 0) { - ManagementObject* mo = queue->GetManagementObject(); - if (mo != 0) - static_cast<_qmf::Queue*>(mo)->dec_bindingCount(); - mgmtBinding->resourceDestroy (); - } -} - -void Exchange::Binding::startManagement() -{ - if (parent != 0) - { - Broker* broker = parent->getBroker(); - if (broker != 0) { - ManagementAgent* agent = broker->getManagementAgent(); - if (agent != 0) { - ManagementObject* mo = queue->GetManagementObject(); - if (mo != 0) { - management::ObjectId queueId = mo->getObjectId(); - - mgmtBinding = new _qmf::Binding - (agent, this, (Manageable*) parent, queueId, key, ManagementAgent::toMap(args)); - if (!origin.empty()) - mgmtBinding->set_origin(origin); - agent->addObject(mgmtBinding); - static_cast<_qmf::Queue*>(mo)->inc_bindingCount(); - } - } - } - } -} - -ManagementObject* Exchange::Binding::GetManagementObject () const -{ - return (ManagementObject*) mgmtBinding; -} - -Exchange::MatchQueue::MatchQueue(Queue::shared_ptr q) : queue(q) {} - -bool Exchange::MatchQueue::operator()(Exchange::Binding::shared_ptr b) -{ - return b->queue == queue; -} - -void Exchange::setProperties(const boost::intrusive_ptr<Message>& msg) { - msg->getProperties<DeliveryProperties>()->setExchange(getName()); -} - -bool Exchange::routeWithAlternate(Deliverable& msg) -{ - route(msg, msg.getMessage().getRoutingKey(), msg.getMessage().getApplicationHeaders()); - if (!msg.delivered && alternate) { - alternate->route(msg, msg.getMessage().getRoutingKey(), msg.getMessage().getApplicationHeaders()); - } - return msg.delivered; -} diff --git a/cpp/src/qpid/broker/Exchange.h b/cpp/src/qpid/broker/Exchange.h deleted file mode 100644 index b12af9a1dd..0000000000 --- a/cpp/src/qpid/broker/Exchange.h +++ /dev/null @@ -1,248 +0,0 @@ -#ifndef _broker_Exchange_h -#define _broker_Exchange_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <boost/shared_ptr.hpp> -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/Deliverable.h" -#include "qpid/broker/MessageStore.h" -#include "qpid/broker/PersistableExchange.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/sys/Mutex.h" -#include "qpid/management/Manageable.h" -#include "qmf/org/apache/qpid/broker/Exchange.h" -#include "qmf/org/apache/qpid/broker/Binding.h" - -namespace qpid { -namespace broker { - -class Broker; -class ExchangeRegistry; - -class QPID_BROKER_CLASS_EXTERN Exchange : public PersistableExchange, public management::Manageable { -public: - struct Binding : public management::Manageable { - typedef boost::shared_ptr<Binding> shared_ptr; - typedef std::vector<Binding::shared_ptr> vector; - - Exchange* parent; - boost::shared_ptr<Queue> queue; - const std::string key; - const framing::FieldTable args; - std::string origin; - qmf::org::apache::qpid::broker::Binding* mgmtBinding; - - Binding(const std::string& key, boost::shared_ptr<Queue> queue, Exchange* parent = 0, - framing::FieldTable args = framing::FieldTable(), const std::string& origin = std::string()); - ~Binding(); - void startManagement(); - management::ManagementObject* GetManagementObject() const; - }; - -private: - const std::string name; - const bool durable; - std::string alternateName; - boost::shared_ptr<Exchange> alternate; - uint32_t alternateUsers; - mutable uint64_t persistenceId; - -protected: - mutable qpid::framing::FieldTable args; - bool sequence; - mutable qpid::sys::Mutex sequenceLock; - int64_t sequenceNo; - bool ive; - boost::intrusive_ptr<Message> lastMsg; - - class PreRoute{ - public: - PreRoute(Deliverable& msg, Exchange* _p); - ~PreRoute(); - private: - Exchange* parent; - }; - - typedef boost::shared_ptr<const std::vector<boost::shared_ptr<qpid::broker::Exchange::Binding> > > ConstBindingList; - typedef boost::shared_ptr< std::vector<boost::shared_ptr<qpid::broker::Exchange::Binding> > > BindingList; - void doRoute(Deliverable& msg, ConstBindingList b); - void routeIVE(); - - - struct MatchQueue { - const boost::shared_ptr<Queue> queue; - MatchQueue(boost::shared_ptr<Queue> q); - bool operator()(Exchange::Binding::shared_ptr b); - }; - - /** A FedBinding keeps track of information that Federation needs - to know when to propagate changes. - - Dynamic federation needs to know which exchanges have at least - one local binding. The bindings on these exchanges need to be - propagated. - - Federated binds and unbinds need to know which federation - origins are associated with the bindings for each queue. When - origins are added or deleted, the corresponding bindings need - to be propagated. - - fedBindings[queueName] contains the origins associated with - the given queue. - */ - - class FedBinding { - uint32_t localBindings; - - typedef std::set<std::string> originSet; - std::map<std::string, originSet> fedBindings; - - public: - FedBinding() : localBindings(0) {} - bool hasLocal() const { return localBindings != 0; } - - /** Returns true if propagation is needed. */ - bool addOrigin(const std::string& queueName, const std::string& origin) { - if (origin.empty()) { - localBindings++; - return localBindings == 1; - } - fedBindings[queueName].insert(origin); - return true; - } - - /** Returns true if propagation is needed. */ - bool delOrigin(const std::string& queueName, const std::string& origin){ - if (origin.empty()) { // no remote == local binding - if (localBindings > 0) - localBindings--; - return localBindings == 0; - } - size_t match = fedBindings[queueName].erase(origin); - if (fedBindings[queueName].empty()) - fedBindings.erase(queueName); - return match != 0; - } - - uint32_t count() { - return localBindings + fedBindings.size(); - } - - uint32_t countFedBindings(const std::string& queueName) { - // don't use '[]' - it may increase size of fedBindings! - std::map<std::string, originSet>::iterator i; - if ((i = fedBindings.find(queueName)) != fedBindings.end()) - return i->second.size(); - return 0; - } - }; - - qmf::org::apache::qpid::broker::Exchange* mgmtExchange; - -public: - typedef boost::shared_ptr<Exchange> shared_ptr; - - QPID_BROKER_EXTERN explicit Exchange(const std::string& name, management::Manageable* parent = 0, - Broker* broker = 0); - QPID_BROKER_EXTERN Exchange(const std::string& _name, bool _durable, const qpid::framing::FieldTable& _args, - management::Manageable* parent = 0, Broker* broker = 0); - QPID_BROKER_INLINE_EXTERN virtual ~Exchange(); - - const std::string& getName() const { return name; } - bool isDurable() { return durable; } - qpid::framing::FieldTable& getArgs() { return args; } - - Exchange::shared_ptr getAlternate() { return alternate; } - void setAlternate(Exchange::shared_ptr _alternate); - void incAlternateUsers() { alternateUsers++; } - void decAlternateUsers() { alternateUsers--; } - bool inUseAsAlternate() { return alternateUsers > 0; } - - virtual std::string getType() const = 0; - - /** - * bind() is used for two distinct purposes: - * - * 1. To create a binding, in the conventional sense - * - * 2. As a vehicle for any FedOp, currently including federated - * binding, federated unbinding, federated reorigin. - * - */ - - virtual bool bind(boost::shared_ptr<Queue> queue, const std::string& routingKey, const qpid::framing::FieldTable* args) = 0; - virtual bool unbind(boost::shared_ptr<Queue> queue, const std::string& routingKey, const qpid::framing::FieldTable* args) = 0; - virtual bool isBound(boost::shared_ptr<Queue> queue, const std::string* const routingKey, const qpid::framing::FieldTable* const args) = 0; - QPID_BROKER_EXTERN virtual void setProperties(const boost::intrusive_ptr<Message>&); - virtual void route(Deliverable& msg, const std::string& routingKey, const qpid::framing::FieldTable* args) = 0; - - //PersistableExchange: - QPID_BROKER_EXTERN void setPersistenceId(uint64_t id) const; - uint64_t getPersistenceId() const { return persistenceId; } - QPID_BROKER_EXTERN uint32_t encodedSize() const; - QPID_BROKER_EXTERN virtual void encode(framing::Buffer& buffer) const; - - static QPID_BROKER_EXTERN Exchange::shared_ptr decode(ExchangeRegistry& exchanges, framing::Buffer& buffer); - - // Manageable entry points - QPID_BROKER_EXTERN management::ManagementObject* GetManagementObject(void) const; - - // Federation hooks - class DynamicBridge { - public: - virtual ~DynamicBridge() {} - virtual void propagateBinding(const std::string& key, const std::string& tagList, const std::string& op, const std::string& origin, qpid::framing::FieldTable* extra_args=0) = 0; - virtual void sendReorigin() = 0; - virtual bool containsLocalTag(const std::string& tagList) const = 0; - virtual const std::string& getLocalTag() const = 0; - }; - - void registerDynamicBridge(DynamicBridge* db); - void removeDynamicBridge(DynamicBridge* db); - virtual bool supportsDynamicBinding() { return false; } - Broker* getBroker() const { return broker; } - /** - * Notify exchange that recovery has completed. - */ - void recoveryComplete(ExchangeRegistry& exchanges); - - bool routeWithAlternate(Deliverable& message); - - void destroy() { destroyed = true; } - bool isDestroyed() const { return destroyed; } - -protected: - qpid::sys::Mutex bridgeLock; - std::vector<DynamicBridge*> bridgeVector; - Broker* broker; - bool destroyed; - - QPID_BROKER_EXTERN virtual void handleHelloRequest(); - void propagateFedOp(const std::string& routingKey, const std::string& tags, - const std::string& op, const std::string& origin, - qpid::framing::FieldTable* extra_args=0); -}; - -}} - -#endif /*!_broker_Exchange.cpp_h*/ diff --git a/cpp/src/qpid/broker/ExchangeRegistry.cpp b/cpp/src/qpid/broker/ExchangeRegistry.cpp deleted file mode 100644 index 1c8d26c4f7..0000000000 --- a/cpp/src/qpid/broker/ExchangeRegistry.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/ExchangeRegistry.h" -#include "qpid/broker/DirectExchange.h" -#include "qpid/broker/FanOutExchange.h" -#include "qpid/broker/HeadersExchange.h" -#include "qpid/broker/TopicExchange.h" -#include "qpid/management/ManagementDirectExchange.h" -#include "qpid/management/ManagementTopicExchange.h" -#include "qpid/framing/reply_exceptions.h" - -using namespace qpid::broker; -using namespace qpid::sys; -using std::pair; -using std::string; -using qpid::framing::FieldTable; - -pair<Exchange::shared_ptr, bool> ExchangeRegistry::declare(const string& name, const string& type){ - - return declare(name, type, false, FieldTable()); -} - -pair<Exchange::shared_ptr, bool> ExchangeRegistry::declare(const string& name, const string& type, - bool durable, const FieldTable& args){ - RWlock::ScopedWlock locker(lock); - ExchangeMap::iterator i = exchanges.find(name); - if (i == exchanges.end()) { - Exchange::shared_ptr exchange; - - if (type == TopicExchange::typeName){ - exchange = Exchange::shared_ptr(new TopicExchange(name, durable, args, parent, broker)); - }else if(type == DirectExchange::typeName){ - exchange = Exchange::shared_ptr(new DirectExchange(name, durable, args, parent, broker)); - }else if(type == FanOutExchange::typeName){ - exchange = Exchange::shared_ptr(new FanOutExchange(name, durable, args, parent, broker)); - }else if (type == HeadersExchange::typeName) { - exchange = Exchange::shared_ptr(new HeadersExchange(name, durable, args, parent, broker)); - }else if (type == ManagementDirectExchange::typeName) { - exchange = Exchange::shared_ptr(new ManagementDirectExchange(name, durable, args, parent, broker)); - }else if (type == ManagementTopicExchange::typeName) { - exchange = Exchange::shared_ptr(new ManagementTopicExchange(name, durable, args, parent, broker)); - }else{ - FunctionMap::iterator i = factory.find(type); - if (i == factory.end()) { - throw UnknownExchangeTypeException(); - } else { - exchange = i->second(name, durable, args, parent, broker); - } - } - exchanges[name] = exchange; - return std::pair<Exchange::shared_ptr, bool>(exchange, true); - } else { - return std::pair<Exchange::shared_ptr, bool>(i->second, false); - } -} - -void ExchangeRegistry::destroy(const string& name){ - if (name.empty() || - (name.find("amq.") == 0 && - (name == "amq.direct" || name == "amq.fanout" || name == "amq.topic" || name == "amq.match")) || - name == "qpid.management") - throw framing::NotAllowedException(QPID_MSG("Cannot delete default exchange: '" << name << "'")); - RWlock::ScopedWlock locker(lock); - ExchangeMap::iterator i = exchanges.find(name); - if (i != exchanges.end()) { - i->second->destroy(); - exchanges.erase(i); - } -} - -Exchange::shared_ptr ExchangeRegistry::get(const string& name){ - RWlock::ScopedRlock locker(lock); - ExchangeMap::iterator i = exchanges.find(name); - if (i == exchanges.end()) - throw framing::NotFoundException(QPID_MSG("Exchange not found: " << name)); - return i->second; -} - -bool ExchangeRegistry::registerExchange(const Exchange::shared_ptr& ex) { - return exchanges.insert(ExchangeMap::value_type(ex->getName(), ex)).second; -} - -void ExchangeRegistry::registerType(const std::string& type, FactoryFunction f) -{ - factory[type] = f; -} - - -namespace -{ -const std::string empty; -} - -Exchange::shared_ptr ExchangeRegistry::getDefault() -{ - return get(empty); -} diff --git a/cpp/src/qpid/broker/ExchangeRegistry.h b/cpp/src/qpid/broker/ExchangeRegistry.h deleted file mode 100644 index 2b75a8f3cf..0000000000 --- a/cpp/src/qpid/broker/ExchangeRegistry.h +++ /dev/null @@ -1,93 +0,0 @@ -#ifndef _broker_ExchangeRegistry_h -#define _broker_ExchangeRegistry_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/Exchange.h" -#include "qpid/broker/MessageStore.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/sys/Monitor.h" -#include "qpid/management/Manageable.h" - -#include <boost/function.hpp> -#include <boost/bind.hpp> - -#include <algorithm> -#include <map> - -namespace qpid { -namespace broker { - -struct UnknownExchangeTypeException{}; - -class ExchangeRegistry{ - public: - typedef boost::function5<Exchange::shared_ptr, const std::string&, - bool, const qpid::framing::FieldTable&, qpid::management::Manageable*, qpid::broker::Broker*> FactoryFunction; - - ExchangeRegistry (Broker* b = 0) : parent(0), broker(b) {} - QPID_BROKER_EXTERN std::pair<Exchange::shared_ptr, bool> declare - (const std::string& name, const std::string& type); - QPID_BROKER_EXTERN std::pair<Exchange::shared_ptr, bool> declare - (const std::string& name, - const std::string& type, - bool durable, - const qpid::framing::FieldTable& args = framing::FieldTable()); - QPID_BROKER_EXTERN void destroy(const std::string& name); - QPID_BROKER_EXTERN Exchange::shared_ptr get(const std::string& name); - Exchange::shared_ptr getDefault(); - - /** - * Register the manageable parent for declared exchanges - */ - void setParent (management::Manageable* _parent) { parent = _parent; } - - /** Register an exchange instance. - *@return true if registered, false if exchange with same name is already registered. - */ - bool registerExchange(const Exchange::shared_ptr&); - - QPID_BROKER_EXTERN void registerType(const std::string& type, FactoryFunction); - - /** Call f for each exchange in the registry. */ - template <class F> void eachExchange(F f) const { - qpid::sys::RWlock::ScopedRlock l(lock); - for (ExchangeMap::const_iterator i = exchanges.begin(); i != exchanges.end(); ++i) - f(i->second); - } - - private: - typedef std::map<std::string, Exchange::shared_ptr> ExchangeMap; - typedef std::map<std::string, FactoryFunction > FunctionMap; - - ExchangeMap exchanges; - FunctionMap factory; - mutable qpid::sys::RWlock lock; - management::Manageable* parent; - Broker* broker; -}; - -}} // namespace qpid::broker - - -#endif /*!_broker_ExchangeRegistry_h*/ diff --git a/cpp/src/qpid/broker/ExpiryPolicy.cpp b/cpp/src/qpid/broker/ExpiryPolicy.cpp deleted file mode 100644 index 64a12d918a..0000000000 --- a/cpp/src/qpid/broker/ExpiryPolicy.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/ExpiryPolicy.h" -#include "qpid/broker/Message.h" -#include "qpid/sys/Time.h" - -namespace qpid { -namespace broker { - -ExpiryPolicy::~ExpiryPolicy() {} - -void ExpiryPolicy::willExpire(Message&) {} - -bool ExpiryPolicy::hasExpired(Message& m) { - return m.getExpiration() < sys::AbsTime::now(); -} - -void ExpiryPolicy::forget(Message&) {} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/ExpiryPolicy.h b/cpp/src/qpid/broker/ExpiryPolicy.h deleted file mode 100644 index a723eb0aa8..0000000000 --- a/cpp/src/qpid/broker/ExpiryPolicy.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef QPID_BROKER_EXPIRYPOLICY_H -#define QPID_BROKER_EXPIRYPOLICY_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/RefCounted.h" -#include "qpid/broker/BrokerImportExport.h" - -namespace qpid { -namespace broker { - -class Message; - -/** - * Default expiry policy. - */ -class QPID_BROKER_CLASS_EXTERN ExpiryPolicy : public RefCounted -{ - public: - QPID_BROKER_EXTERN virtual ~ExpiryPolicy(); - QPID_BROKER_EXTERN virtual void willExpire(Message&); - QPID_BROKER_EXTERN virtual bool hasExpired(Message&); - QPID_BROKER_EXTERN virtual void forget(Message&); -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_EXPIRYPOLICY_H*/ diff --git a/cpp/src/qpid/broker/Fairshare.cpp b/cpp/src/qpid/broker/Fairshare.cpp deleted file mode 100644 index 17270ffd8d..0000000000 --- a/cpp/src/qpid/broker/Fairshare.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/Fairshare.h" -#include "qpid/broker/QueuedMessage.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/log/Statement.h" -#include <boost/format.hpp> -#include <boost/lexical_cast.hpp> -#include <boost/assign/list_of.hpp> - -namespace qpid { -namespace broker { - -Fairshare::Fairshare(size_t levels, uint limit) : - PriorityQueue(levels), - limits(levels, limit), priority(levels-1), count(0) {} - - -void Fairshare::setLimit(size_t level, uint limit) -{ - limits[level] = limit; -} - -bool Fairshare::limitReached() -{ - uint l = limits[priority]; - return l && ++count > l; -} - -uint Fairshare::currentLevel() -{ - if (limitReached()) { - return nextLevel(); - } else { - return priority; - } -} - -uint Fairshare::nextLevel() -{ - count = 1; - if (priority) --priority; - else priority = levels-1; - return priority; -} - -bool Fairshare::isNull() -{ - for (int i = 0; i < levels; i++) if (limits[i]) return false; - return true; -} - -bool Fairshare::getState(uint& p, uint& c) const -{ - p = priority; - c = count; - return true; -} - -bool Fairshare::setState(uint p, uint c) -{ - priority = p; - count = c; - return true; -} - -bool Fairshare::findFrontLevel(uint& p, PriorityLevels& messages) -{ - const uint start = p = currentLevel(); - do { - if (!messages[p].empty()) return true; - } while ((p = nextLevel()) != start); - return false; -} - - - -bool Fairshare::getState(const Messages& m, uint& priority, uint& count) -{ - const Fairshare* fairshare = dynamic_cast<const Fairshare*>(&m); - return fairshare && fairshare->getState(priority, count); -} - -bool Fairshare::setState(Messages& m, uint priority, uint count) -{ - Fairshare* fairshare = dynamic_cast<Fairshare*>(&m); - return fairshare && fairshare->setState(priority, count); -} - -int getIntegerSetting(const qpid::framing::FieldTable& settings, const std::vector<std::string>& keys) -{ - qpid::framing::FieldTable::ValuePtr v; - std::vector<std::string>::const_iterator i = keys.begin(); - while (!v && i != keys.end()) { - v = settings.get(*i++); - } - - if (!v) { - return 0; - } else if (v->convertsTo<int>()) { - return v->get<int>(); - } else if (v->convertsTo<std::string>()){ - std::string s = v->get<std::string>(); - try { - return boost::lexical_cast<int>(s); - } catch(const boost::bad_lexical_cast&) { - QPID_LOG(warning, "Ignoring invalid integer value for " << *i << ": " << s); - return 0; - } - } else { - QPID_LOG(warning, "Ignoring invalid integer value for " << *i << ": " << *v); - return 0; - } -} - -int getIntegerSettingForKey(const qpid::framing::FieldTable& settings, const std::string& key) -{ - return getIntegerSetting(settings, boost::assign::list_of<std::string>(key)); -} - -int getSetting(const qpid::framing::FieldTable& settings, const std::vector<std::string>& keys, int minvalue, int maxvalue) -{ - return std::max(minvalue,std::min(getIntegerSetting(settings, keys), maxvalue)); -} - -std::auto_ptr<Fairshare> getFairshareForKey(const qpid::framing::FieldTable& settings, uint levels, const std::string& key) -{ - uint defaultLimit = getIntegerSettingForKey(settings, key); - std::auto_ptr<Fairshare> fairshare(new Fairshare(levels, defaultLimit)); - for (uint i = 0; i < levels; i++) { - std::string levelKey = (boost::format("%1%-%2%") % key % i).str(); - if(settings.isSet(levelKey)) { - fairshare->setLimit(i, getIntegerSettingForKey(settings, levelKey)); - } - } - if (!fairshare->isNull()) { - return fairshare; - } else { - return std::auto_ptr<Fairshare>(); - } -} - -std::auto_ptr<Fairshare> getFairshare(const qpid::framing::FieldTable& settings, - uint levels, - const std::vector<std::string>& keys) -{ - std::auto_ptr<Fairshare> fairshare; - for (std::vector<std::string>::const_iterator i = keys.begin(); i != keys.end() && !fairshare.get(); ++i) { - fairshare = getFairshareForKey(settings, levels, *i); - } - return fairshare; -} - -std::auto_ptr<Messages> Fairshare::create(const qpid::framing::FieldTable& settings) -{ - using boost::assign::list_of; - std::auto_ptr<Messages> result; - size_t levels = getSetting(settings, list_of<std::string>("qpid.priorities")("x-qpid-priorities"), 1, 100); - if (levels) { - std::auto_ptr<Fairshare> fairshare = - getFairshare(settings, levels, list_of<std::string>("qpid.fairshare")("x-qpid-fairshare")); - if (fairshare.get()) result = fairshare; - else result = std::auto_ptr<Messages>(new PriorityQueue(levels)); - } - return result; -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/Fairshare.h b/cpp/src/qpid/broker/Fairshare.h deleted file mode 100644 index 1b25721e0c..0000000000 --- a/cpp/src/qpid/broker/Fairshare.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef QPID_BROKER_FAIRSHARE_H -#define QPID_BROKER_FAIRSHARE_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/PriorityQueue.h" - -namespace qpid { -namespace framing { -class FieldTable; -} -namespace broker { - -/** - * Modifies a basic prioirty queue by limiting the number of messages - * from each priority level that are dispatched before allowing - * dispatch from the next level. - */ -class Fairshare : public PriorityQueue -{ - public: - Fairshare(size_t levels, uint limit); - bool getState(uint& priority, uint& count) const; - bool setState(uint priority, uint count); - void setLimit(size_t level, uint limit); - bool isNull(); - static std::auto_ptr<Messages> create(const qpid::framing::FieldTable& settings); - static bool getState(const Messages&, uint& priority, uint& count); - static bool setState(Messages&, uint priority, uint count); - private: - std::vector<uint> limits; - - uint priority; - uint count; - - uint currentLevel(); - uint nextLevel(); - bool limitReached(); - bool findFrontLevel(uint& p, PriorityLevels&); -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_FAIRSHARE_H*/ diff --git a/cpp/src/qpid/broker/FanOutExchange.cpp b/cpp/src/qpid/broker/FanOutExchange.cpp deleted file mode 100644 index 5879fa0892..0000000000 --- a/cpp/src/qpid/broker/FanOutExchange.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/log/Statement.h" -#include "qpid/broker/FanOutExchange.h" -#include "qpid/broker/FedOps.h" -#include <algorithm> - -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::sys; -namespace _qmf = qmf::org::apache::qpid::broker; - -FanOutExchange::FanOutExchange(const std::string& _name, Manageable* _parent, Broker* b) : - Exchange(_name, _parent, b) -{ - if (mgmtExchange != 0) - mgmtExchange->set_type (typeName); -} - -FanOutExchange::FanOutExchange(const std::string& _name, bool _durable, - const FieldTable& _args, Manageable* _parent, Broker* b) : - Exchange(_name, _durable, _args, _parent, b) -{ - if (mgmtExchange != 0) - mgmtExchange->set_type (typeName); -} - -bool FanOutExchange::bind(Queue::shared_ptr queue, const string& /*key*/, const FieldTable* args) -{ - string fedOp(args ? args->getAsString(qpidFedOp) : fedOpBind); - string fedTags(args ? args->getAsString(qpidFedTags) : ""); - string fedOrigin(args ? args->getAsString(qpidFedOrigin) : ""); - bool propagate = false; - - if (args == 0 || fedOp.empty() || fedOp == fedOpBind) { - Binding::shared_ptr binding (new Binding ("", queue, this, FieldTable(), fedOrigin)); - if (bindings.add_unless(binding, MatchQueue(queue))) { - binding->startManagement(); - propagate = fedBinding.addOrigin(queue->getName(), fedOrigin); - if (mgmtExchange != 0) { - mgmtExchange->inc_bindingCount(); - } - } else { - // queue already present - still need to track fedOrigin - fedBinding.addOrigin(queue->getName(), fedOrigin); - return false; - } - } else if (fedOp == fedOpUnbind) { - propagate = fedBinding.delOrigin(queue->getName(), fedOrigin); - if (fedBinding.countFedBindings(queue->getName()) == 0) - unbind(queue, "", args); - } else if (fedOp == fedOpReorigin) { - if (fedBinding.hasLocal()) { - propagateFedOp(string(), string(), fedOpBind, string()); - } - } - - routeIVE(); - if (propagate) - propagateFedOp(string(), fedTags, fedOp, fedOrigin); - return true; -} - -bool FanOutExchange::unbind(Queue::shared_ptr queue, const string& /*key*/, const FieldTable* args) -{ - string fedOrigin(args ? args->getAsString(qpidFedOrigin) : ""); - bool propagate = false; - - QPID_LOG(debug, "Unbinding queue " << queue->getName() - << " from exchange " << getName() << " origin=" << fedOrigin << ")" ); - - if (bindings.remove_if(MatchQueue(queue))) { - propagate = fedBinding.delOrigin(queue->getName(), fedOrigin); - if (mgmtExchange != 0) { - mgmtExchange->dec_bindingCount(); - } - } else { - return false; - } - - if (propagate) - propagateFedOp(string(), string(), fedOpUnbind, string()); - return true; -} - -void FanOutExchange::route(Deliverable& msg, const string& /*routingKey*/, const FieldTable* /*args*/) -{ - PreRoute pr(msg, this); - doRoute(msg, bindings.snapshot()); -} - -bool FanOutExchange::isBound(Queue::shared_ptr queue, const string* const, const FieldTable* const) -{ - BindingsArray::ConstPtr ptr = bindings.snapshot(); - return ptr && std::find_if(ptr->begin(), ptr->end(), MatchQueue(queue)) != ptr->end(); -} - - -FanOutExchange::~FanOutExchange() {} - -const std::string FanOutExchange::typeName("fanout"); diff --git a/cpp/src/qpid/broker/FanOutExchange.h b/cpp/src/qpid/broker/FanOutExchange.h deleted file mode 100644 index 1a7d486796..0000000000 --- a/cpp/src/qpid/broker/FanOutExchange.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _FanOutExchange_ -#define _FanOutExchange_ - -#include <map> -#include <vector> -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/Exchange.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/sys/CopyOnWriteArray.h" -#include "qpid/broker/Queue.h" - -namespace qpid { -namespace broker { - -class FanOutExchange : public virtual Exchange { - typedef qpid::sys::CopyOnWriteArray<Binding::shared_ptr> BindingsArray; - BindingsArray bindings; - FedBinding fedBinding; - public: - static const std::string typeName; - - QPID_BROKER_EXTERN FanOutExchange(const std::string& name, - management::Manageable* parent = 0, Broker* broker = 0); - QPID_BROKER_EXTERN FanOutExchange(const std::string& _name, - bool _durable, - const qpid::framing::FieldTable& _args, - management::Manageable* parent = 0, Broker* broker = 0); - - virtual std::string getType() const { return typeName; } - - QPID_BROKER_EXTERN virtual bool bind(Queue::shared_ptr queue, - const std::string& routingKey, - const qpid::framing::FieldTable* args); - - virtual bool unbind(Queue::shared_ptr queue, const std::string& routingKey, const qpid::framing::FieldTable* args); - - QPID_BROKER_EXTERN virtual void route(Deliverable& msg, - const std::string& routingKey, - const qpid::framing::FieldTable* args); - - QPID_BROKER_EXTERN virtual bool isBound(Queue::shared_ptr queue, - const std::string* const routingKey, - const qpid::framing::FieldTable* const args); - - QPID_BROKER_EXTERN virtual ~FanOutExchange(); - virtual bool supportsDynamicBinding() { return true; } -}; - -} -} - - - -#endif diff --git a/cpp/src/qpid/broker/FedOps.h b/cpp/src/qpid/broker/FedOps.h deleted file mode 100644 index dc4a38e244..0000000000 --- a/cpp/src/qpid/broker/FedOps.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -/* - * Strings used to identify federated operations and operands. - */ - -namespace -{ - const std::string qpidFedOp("qpid.fed.op"); // a federation primitive - const std::string qpidFedTags("qpid.fed.tags"); // a unique id for a broker - const std::string qpidFedOrigin("qpid.fed.origin"); // the tag of the broker on which a propagated binding originated - - // Operands for qpidFedOp - each identifies a federation primitive - - const std::string fedOpBind("B"); - const std::string fedOpUnbind("U"); - const std::string fedOpReorigin("R"); - const std::string fedOpHello("H"); -} diff --git a/cpp/src/qpid/broker/HandlerImpl.h b/cpp/src/qpid/broker/HandlerImpl.h deleted file mode 100644 index aae636e818..0000000000 --- a/cpp/src/qpid/broker/HandlerImpl.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef _broker_HandlerImpl_h -#define _broker_HandlerImpl_h - -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/broker/SemanticState.h" -#include "qpid/broker/SessionContext.h" -#include "qpid/broker/ConnectionState.h" - -namespace qpid { -namespace broker { - -class Broker; - -/** - * Base template for protocol handler implementations. - * Provides convenience methods for getting common session objects. - */ -class HandlerImpl { - protected: - SemanticState& state; - SessionContext& session; - - HandlerImpl(SemanticState& s) : state(s), session(s.getSession()) {} - - framing::AMQP_ClientProxy& getProxy() { return session.getProxy(); } - ConnectionState& getConnection() { return session.getConnection(); } - Broker& getBroker() { return session.getConnection().getBroker(); } -}; - -}} // namespace qpid::broker - - - -#endif /*!_broker_HandlerImpl_h*/ - - diff --git a/cpp/src/qpid/broker/HeadersExchange.cpp b/cpp/src/qpid/broker/HeadersExchange.cpp deleted file mode 100644 index abcaa5f69d..0000000000 --- a/cpp/src/qpid/broker/HeadersExchange.cpp +++ /dev/null @@ -1,341 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/HeadersExchange.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/log/Statement.h" -#include <algorithm> - - -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::sys; -namespace _qmf = qmf::org::apache::qpid::broker; - -// TODO aconway 2006-09-20: More efficient matching algorithm. -// The current search algorithm really sucks. -// Fieldtables are heavy, maybe use shared_ptr to do handle-body. - -using namespace qpid::broker; - -namespace { - const std::string x_match("x-match"); - // possible values for x-match - const std::string all("all"); - const std::string any("any"); - const std::string empty; - - // federation related args and values - const std::string qpidFedOp("qpid.fed.op"); - const std::string qpidFedTags("qpid.fed.tags"); - const std::string qpidFedOrigin("qpid.fed.origin"); - - const std::string fedOpBind("B"); - const std::string fedOpUnbind("U"); - const std::string fedOpReorigin("R"); - const std::string fedOpHello("H"); -} - -HeadersExchange::HeadersExchange(const string& _name, Manageable* _parent, Broker* b) : - Exchange(_name, _parent, b) -{ - if (mgmtExchange != 0) - mgmtExchange->set_type (typeName); -} - -HeadersExchange::HeadersExchange(const std::string& _name, bool _durable, - const FieldTable& _args, Manageable* _parent, Broker* b) : - Exchange(_name, _durable, _args, _parent, b) -{ - if (mgmtExchange != 0) - mgmtExchange->set_type (typeName); -} - -std::string HeadersExchange::getMatch(const FieldTable* args) -{ - if (!args) { - throw InternalErrorException(QPID_MSG("No arguments given.")); - } - FieldTable::ValuePtr what = args->get(x_match); - if (!what) { - return empty; - } - if (!what->convertsTo<std::string>()) { - throw InternalErrorException(QPID_MSG("Invalid x-match binding format to headers exchange. Must be a string [\"all\" or \"any\"]")); - } - return what->get<std::string>(); -} - -bool HeadersExchange::bind(Queue::shared_ptr queue, const string& bindingKey, const FieldTable* args) -{ - string fedOp(fedOpBind); - string fedTags; - string fedOrigin; - if (args) { - fedOp = args->getAsString(qpidFedOp); - fedTags = args->getAsString(qpidFedTags); - fedOrigin = args->getAsString(qpidFedOrigin); - } - - bool propagate = false; - - // The federation args get propagated directly, so we need to identify - // 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); - - if (x_match_value != all && x_match_value != any) { - throw InternalErrorException(QPID_MSG("Invalid or missing x-match value binding to headers exchange. Must be a string [\"all\" or \"any\"]")); - } - - { - Mutex::ScopedLock l(lock); - Binding::shared_ptr binding (new Binding (bindingKey, queue, this, *args)); - BoundKey bk(binding); - if (bindings.add_unless(bk, MatchArgs(queue, args))) { - binding->startManagement(); - propagate = bk.fedBinding.addOrigin(queue->getName(), fedOrigin); - if (mgmtExchange != 0) { - mgmtExchange->inc_bindingCount(); - } - } else { - bk.fedBinding.addOrigin(queue->getName(), fedOrigin); - return false; - } - } // lock dropped - - } else if (fedOp == fedOpUnbind) { - Mutex::ScopedLock l(lock); - - FedUnbindModifier modifier(queue->getName(), fedOrigin); - bindings.modify_if(MatchKey(queue, bindingKey), modifier); - propagate = modifier.shouldPropagate; - if (modifier.shouldUnbind) { - unbind(queue, bindingKey, args); - } - - } else if (fedOp == fedOpReorigin) { - Bindings::ConstPtr p = bindings.snapshot(); - if (p.get()) - { - Mutex::ScopedLock l(lock); - for (std::vector<BoundKey>::const_iterator i = p->begin(); i != p->end(); ++i) - { - if ((*i).fedBinding.hasLocal()) { - propagateFedOp( (*i).binding->key, string(), fedOpBind, string()); - } - } - } - } - routeIVE(); - if (propagate) { - FieldTable * prop_args = (extra_args.count() != 0 ? &extra_args : 0); - propagateFedOp(bindingKey, fedTags, fedOp, fedOrigin, prop_args); - } - - return true; -} - -bool HeadersExchange::unbind(Queue::shared_ptr queue, const string& bindingKey, const FieldTable *args){ - bool propagate = false; - string fedOrigin(args ? args->getAsString(qpidFedOrigin) : ""); - { - Mutex::ScopedLock l(lock); - - FedUnbindModifier modifier(queue->getName(), fedOrigin); - MatchKey match_key(queue, bindingKey); - bindings.modify_if(match_key, modifier); - propagate = modifier.shouldPropagate; - if (modifier.shouldUnbind) { - if (bindings.remove_if(match_key)) { - if (mgmtExchange != 0) { - mgmtExchange->dec_bindingCount(); - } - } else { - return false; - } - } - } - - if (propagate) { - propagateFedOp(bindingKey, string(), fedOpUnbind, string()); - } - return true; -} - - -void HeadersExchange::route(Deliverable& msg, const string& /*routingKey*/, const FieldTable* args) -{ - if (!args) { - //can't match if there were no headers passed in - if (mgmtExchange != 0) { - mgmtExchange->inc_msgReceives(); - mgmtExchange->inc_byteReceives(msg.contentSize()); - mgmtExchange->inc_msgDrops(); - mgmtExchange->inc_byteDrops(msg.contentSize()); - } - return; - } - - PreRoute pr(msg, this); - - BindingList b(new std::vector<boost::shared_ptr<qpid::broker::Exchange::Binding> >); - Bindings::ConstPtr p = bindings.snapshot(); - if (p.get()) { - for (std::vector<BoundKey>::const_iterator i = p->begin(); i != p->end(); ++i) { - if (match((*i).binding->args, *args)) { - b->push_back((*i).binding); - } - } - } - doRoute(msg, b); -} - - -bool HeadersExchange::isBound(Queue::shared_ptr queue, const string* const, const FieldTable* const args) -{ - Bindings::ConstPtr p = bindings.snapshot(); - if (p.get()){ - for (std::vector<BoundKey>::const_iterator i = p->begin(); i != p->end(); ++i) { - if ( (!args || equal((*i).binding->args, *args)) && (!queue || (*i).binding->queue == queue)) { - return true; - } - } - } - return false; -} - -void HeadersExchange::getNonFedArgs(const FieldTable* args, FieldTable& nonFedArgs) -{ - if (!args) - { - return; - } - - for (qpid::framing::FieldTable::ValueMap::const_iterator i=args->begin(); i != args->end(); ++i) - { - const string & name(i->first); - if (name == qpidFedOp || - name == qpidFedTags || - name == qpidFedOrigin) - { - continue; - } - nonFedArgs.insert((*i)); - } -} - -HeadersExchange::~HeadersExchange() {} - -const std::string HeadersExchange::typeName("headers"); - -namespace -{ - - bool match_values(const FieldValue& bind, const FieldValue& msg) { - return bind.getType() == 0xf0 || bind == msg; - } - -} - - -bool HeadersExchange::match(const FieldTable& bind, const FieldTable& msg) { - typedef FieldTable::ValueMap Map; - std::string what = getMatch(&bind); - if (what == all) { - for (Map::const_iterator i = bind.begin(); - i != bind.end(); - ++i) - { - if (i->first != x_match) - { - Map::const_iterator j = msg.find(i->first); - if (j == msg.end()) return false; - if (!match_values(*(i->second), *(j->second))) return false; - } - } - return true; - } else if (what == any) { - for (Map::const_iterator i = bind.begin(); - i != bind.end(); - ++i) - { - if (i->first != x_match) - { - Map::const_iterator j = msg.find(i->first); - if (j != msg.end()) { - if (match_values(*(i->second), *(j->second))) return true; - } - } - } - return false; - } else { - return false; - } -} - -bool HeadersExchange::equal(const FieldTable& a, const FieldTable& b) { - typedef FieldTable::ValueMap Map; - for (Map::const_iterator i = a.begin(); - i != a.end(); - ++i) - { - Map::const_iterator j = b.find(i->first); - if (j == b.end()) return false; - if (!match_values(*(i->second), *(j->second))) return false; - } - return true; -} - -//--------- -HeadersExchange::MatchArgs::MatchArgs(Queue::shared_ptr q, const qpid::framing::FieldTable* a) : queue(q), args(a) {} - -bool HeadersExchange::MatchArgs::operator()(BoundKey & bk) -{ - return bk.binding->queue == queue && bk.binding->args == *args; -} - -//--------- -HeadersExchange::MatchKey::MatchKey(Queue::shared_ptr q, const std::string& k) : queue(q), key(k) {} - -bool HeadersExchange::MatchKey::operator()(BoundKey & bk) -{ - return bk.binding->queue == queue && bk.binding->key == key; -} - -//---------- -HeadersExchange::FedUnbindModifier::FedUnbindModifier(const string& queueName, const string& origin) : queueName(queueName), fedOrigin(origin), shouldUnbind(false), shouldPropagate(false) {} -HeadersExchange::FedUnbindModifier::FedUnbindModifier() : shouldUnbind(false), shouldPropagate(false) {} - -bool HeadersExchange::FedUnbindModifier::operator()(BoundKey & bk) -{ - shouldPropagate = bk.fedBinding.delOrigin(queueName, fedOrigin); - if (bk.fedBinding.countFedBindings(queueName) == 0) - { - shouldUnbind = true; - } - return true; -} - diff --git a/cpp/src/qpid/broker/HeadersExchange.h b/cpp/src/qpid/broker/HeadersExchange.h deleted file mode 100644 index 3b939d6851..0000000000 --- a/cpp/src/qpid/broker/HeadersExchange.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _HeadersExchange_ -#define _HeadersExchange_ - -#include <vector> -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/Exchange.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/sys/CopyOnWriteArray.h" -#include "qpid/sys/Mutex.h" -#include "qpid/broker/Queue.h" - -namespace qpid { -namespace broker { - - -class HeadersExchange : public virtual Exchange { - - struct BoundKey - { - Binding::shared_ptr binding; - FedBinding fedBinding; - BoundKey(Binding::shared_ptr binding_) : binding(binding_) {} - }; - - struct MatchArgs - { - const Queue::shared_ptr queue; - const qpid::framing::FieldTable* args; - MatchArgs(Queue::shared_ptr q, const qpid::framing::FieldTable* a); - bool operator()(BoundKey & bk); - }; - - struct MatchKey - { - const Queue::shared_ptr queue; - const std::string& key; - MatchKey(Queue::shared_ptr q, const std::string& k); - bool operator()(BoundKey & bk); - }; - - struct FedUnbindModifier - { - std::string queueName; - std::string fedOrigin; - bool shouldUnbind; - bool shouldPropagate; - FedUnbindModifier(); - FedUnbindModifier(const std::string& queueName, const std::string& origin); - bool operator()(BoundKey & bk); - }; - - typedef qpid::sys::CopyOnWriteArray<BoundKey> Bindings; - - Bindings bindings; - qpid::sys::Mutex lock; - - static std::string getMatch(const framing::FieldTable* args); - - protected: - void getNonFedArgs(const framing::FieldTable* args, - framing::FieldTable& nonFedArgs); - - public: - static const std::string typeName; - - QPID_BROKER_EXTERN HeadersExchange(const std::string& name, - management::Manageable* parent = 0, Broker* broker = 0); - QPID_BROKER_EXTERN HeadersExchange(const std::string& _name, - bool _durable, - const qpid::framing::FieldTable& _args, - management::Manageable* parent = 0, Broker* broker = 0); - - virtual std::string getType() const { return typeName; } - - QPID_BROKER_EXTERN virtual bool bind(Queue::shared_ptr queue, - const std::string& routingKey, - const qpid::framing::FieldTable* args); - - virtual bool unbind(Queue::shared_ptr queue, const std::string& routingKey, const qpid::framing::FieldTable* args); - - QPID_BROKER_EXTERN virtual void route(Deliverable& msg, - const std::string& routingKey, - const qpid::framing::FieldTable* args); - - QPID_BROKER_EXTERN virtual bool isBound(Queue::shared_ptr queue, - const std::string* const routingKey, - const qpid::framing::FieldTable* const args); - - QPID_BROKER_EXTERN virtual ~HeadersExchange(); - - virtual bool supportsDynamicBinding() { return true; } - - static QPID_BROKER_EXTERN bool match(const qpid::framing::FieldTable& bindArgs, const qpid::framing::FieldTable& msgArgs); - static bool equal(const qpid::framing::FieldTable& bindArgs, const qpid::framing::FieldTable& msgArgs); -}; - - - -} -} - -#endif diff --git a/cpp/src/qpid/broker/LegacyLVQ.cpp b/cpp/src/qpid/broker/LegacyLVQ.cpp deleted file mode 100644 index a811a86492..0000000000 --- a/cpp/src/qpid/broker/LegacyLVQ.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/LegacyLVQ.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/QueuedMessage.h" - -namespace qpid { -namespace broker { - -LegacyLVQ::LegacyLVQ(const std::string& k, bool b, Broker* br) : MessageMap(k), noBrowse(b), broker(br) {} - -void LegacyLVQ::setNoBrowse(bool b) -{ - noBrowse = b; -} - -bool LegacyLVQ::remove(const framing::SequenceNumber& position, QueuedMessage& message) -{ - Ordering::iterator i = messages.find(position); - if (i != messages.end() && i->second.payload == message.payload) { - message = i->second; - erase(i); - return true; - } else { - return false; - } -} - -bool LegacyLVQ::next(const framing::SequenceNumber& position, QueuedMessage& message) -{ - if (MessageMap::next(position, message)) { - if (!noBrowse) index.erase(getKey(message)); - return true; - } else { - return false; - } -} - -bool LegacyLVQ::push(const QueuedMessage& added, QueuedMessage& removed) -{ - //Hack to disable LVQ behaviour on cluster update: - if (broker && broker->isClusterUpdatee()) { - messages[added.position] = added; - return false; - } else { - return MessageMap::push(added, removed); - } -} - -const QueuedMessage& LegacyLVQ::replace(const QueuedMessage& original, const QueuedMessage& update) -{ - //add the new message into the original position of the replaced message - Ordering::iterator i = messages.find(original.position); - i->second = update; - i->second.position = original.position; - return i->second; -} - -void LegacyLVQ::removeIf(Predicate p) -{ - //Note: This method is currently called periodically on the timer - //thread to expire messages. In a clustered broker this means that - //the purging does not occur on the cluster event dispatch thread - //and consequently that is not totally ordered w.r.t other events - //(including publication of messages). The cluster does ensure - //that the actual expiration of messages (as distinct from the - //removing of those expired messages from the queue) *is* - //consistently ordered w.r.t. cluster events. This means that - //delivery of messages is in general consistent across the cluster - //inspite of any non-determinism in the triggering of a - //purge. However at present purging a last value queue (of the - //legacy sort) could potentially cause inconsistencies in the - //cluster (as the order w.r.t publications can affect the order in - //which messages appear in the queue). Consequently periodic - //purging of an LVQ is not enabled if the broker is clustered - //(expired messages will be removed on delivery and consolidated - //by key as part of normal LVQ operation). - - //TODO: Is there a neater way to check whether broker is - //clustered? Here we assume that if the clustered timer is the - //same as the regular timer, we are not clustered: - if (!broker || &(broker->getClusterTimer()) == &(broker->getTimer())) - MessageMap::removeIf(p); -} - -std::auto_ptr<Messages> LegacyLVQ::updateOrReplace(std::auto_ptr<Messages> current, - const std::string& key, bool noBrowse, Broker* broker) -{ - LegacyLVQ* lvq = dynamic_cast<LegacyLVQ*>(current.get()); - if (lvq) { - lvq->setNoBrowse(noBrowse); - return current; - } else { - return std::auto_ptr<Messages>(new LegacyLVQ(key, noBrowse, broker)); - } -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/LegacyLVQ.h b/cpp/src/qpid/broker/LegacyLVQ.h deleted file mode 100644 index dd0fd7aaec..0000000000 --- a/cpp/src/qpid/broker/LegacyLVQ.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef QPID_BROKER_LEGACYLVQ_H -#define QPID_BROKER_LEGACYLVQ_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/MessageMap.h" -#include <memory> - -namespace qpid { -namespace broker { -class Broker; - -/** - * This class encapsulates the behaviour of the old style LVQ where a - * message replacing another messages for the given key will use the - * position in the queue of the previous message. This however causes - * problems for browsing. Either browsers stop the coalescing of - * messages by key (default) or they may mis updates (if the no-browse - * option is specified). - */ -class LegacyLVQ : public MessageMap -{ - public: - LegacyLVQ(const std::string& key, bool noBrowse = false, Broker* broker = 0); - bool remove(const framing::SequenceNumber&, QueuedMessage&); - bool next(const framing::SequenceNumber&, QueuedMessage&); - bool push(const QueuedMessage& added, QueuedMessage& removed); - void removeIf(Predicate); - void setNoBrowse(bool); - static std::auto_ptr<Messages> updateOrReplace(std::auto_ptr<Messages> current, - const std::string& key, bool noBrowse, - Broker* broker); - protected: - bool noBrowse; - Broker* broker; - - const QueuedMessage& replace(const QueuedMessage&, const QueuedMessage&); -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_LEGACYLVQ_H*/ diff --git a/cpp/src/qpid/broker/Link.cpp b/cpp/src/qpid/broker/Link.cpp deleted file mode 100644 index 91861ade3f..0000000000 --- a/cpp/src/qpid/broker/Link.cpp +++ /dev/null @@ -1,474 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/Link.h" -#include "qpid/broker/LinkRegistry.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/Connection.h" -#include "qmf/org/apache/qpid/broker/EventBrokerLinkUp.h" -#include "qmf/org/apache/qpid/broker/EventBrokerLinkDown.h" -#include "boost/bind.hpp" -#include "qpid/log/Statement.h" -#include "qpid/framing/enum.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/broker/AclModule.h" - -using namespace qpid::broker; -using qpid::framing::Buffer; -using qpid::framing::FieldTable; -using qpid::framing::UnauthorizedAccessException; -using qpid::framing::connection::CLOSE_CODE_CONNECTION_FORCED; -using qpid::management::ManagementAgent; -using qpid::management::ManagementObject; -using qpid::management::Manageable; -using qpid::management::Args; -using qpid::sys::Mutex; -using std::stringstream; -using std::string; -namespace _qmf = qmf::org::apache::qpid::broker; - -Link::Link(LinkRegistry* _links, - MessageStore* _store, - string& _host, - uint16_t _port, - string& _transport, - bool _durable, - string& _authMechanism, - string& _username, - string& _password, - Broker* _broker, - Manageable* parent) - : links(_links), store(_store), host(_host), port(_port), - transport(_transport), - durable(_durable), - authMechanism(_authMechanism), username(_username), password(_password), - persistenceId(0), mgmtObject(0), broker(_broker), state(0), - visitCount(0), - currentInterval(1), - closing(false), - updateUrls(false), - channelCounter(1), - connection(0), - agent(0) -{ - if (parent != 0 && broker != 0) - { - agent = broker->getManagementAgent(); - if (agent != 0) - { - mgmtObject = new _qmf::Link(agent, this, parent, _host, _port, _transport, _durable); - agent->addObject(mgmtObject, 0, durable); - } - } - setStateLH(STATE_WAITING); -} - -Link::~Link () -{ - if (state == STATE_OPERATIONAL && connection != 0) - connection->close(CLOSE_CODE_CONNECTION_FORCED, "closed by management"); - - if (mgmtObject != 0) - mgmtObject->resourceDestroy (); -} - -void Link::setStateLH (int newState) -{ - if (newState == state) - return; - - state = newState; - - if (hideManagement()) - return; - - switch (state) - { - case STATE_WAITING : mgmtObject->set_state("Waiting"); break; - case STATE_CONNECTING : mgmtObject->set_state("Connecting"); break; - case STATE_OPERATIONAL : mgmtObject->set_state("Operational"); break; - case STATE_FAILED : mgmtObject->set_state("Failed"); break; - case STATE_CLOSED : mgmtObject->set_state("Closed"); break; - case STATE_PASSIVE : mgmtObject->set_state("Passive"); break; - } -} - -void Link::startConnectionLH () -{ - try { - // Set the state before calling connect. It is possible that connect - // will fail synchronously and call Link::closed before returning. - setStateLH(STATE_CONNECTING); - broker->connect (host, port, transport, - boost::bind (&Link::closed, this, _1, _2)); - QPID_LOG (debug, "Inter-broker link connecting to " << host << ":" << port); - } catch(std::exception& e) { - setStateLH(STATE_WAITING); - if (!hideManagement()) - mgmtObject->set_lastError (e.what()); - } -} - -void Link::established () -{ - stringstream addr; - addr << host << ":" << port; - QPID_LOG (info, "Inter-broker link established to " << addr.str()); - - if (!hideManagement() && agent) - agent->raiseEvent(_qmf::EventBrokerLinkUp(addr.str())); - - { - Mutex::ScopedLock mutex(lock); - setStateLH(STATE_OPERATIONAL); - currentInterval = 1; - visitCount = 0; - if (closing) - destroy(); - } -} - -void Link::closed (int, std::string text) -{ - Mutex::ScopedLock mutex(lock); - QPID_LOG (info, "Inter-broker link disconnected from " << host << ":" << port << " " << text); - - connection = 0; - - if (state == STATE_OPERATIONAL) { - stringstream addr; - addr << host << ":" << port; - QPID_LOG (warning, "Inter-broker link disconnected from " << addr.str()); - if (!hideManagement() && agent) - agent->raiseEvent(_qmf::EventBrokerLinkDown(addr.str())); - } - - for (Bridges::iterator i = active.begin(); i != active.end(); i++) { - (*i)->closed(); - created.push_back(*i); - } - active.clear(); - - if (state != STATE_FAILED) - { - setStateLH(STATE_WAITING); - if (!hideManagement()) - mgmtObject->set_lastError (text); - } - - if (closing) - destroy(); -} - -void Link::destroy () -{ - Bridges toDelete; - { - Mutex::ScopedLock mutex(lock); - - QPID_LOG (info, "Inter-broker link to " << host << ":" << port << " removed by management"); - if (connection) - connection->close(CLOSE_CODE_CONNECTION_FORCED, "closed by management"); - - setStateLH(STATE_CLOSED); - - // Move the bridges to be deleted into a local vector so there is no - // corruption of the iterator caused by bridge deletion. - for (Bridges::iterator i = active.begin(); i != active.end(); i++) { - (*i)->closed(); - toDelete.push_back(*i); - } - active.clear(); - - for (Bridges::iterator i = created.begin(); i != created.end(); i++) - toDelete.push_back(*i); - created.clear(); - } - // Now delete all bridges on this link (don't hold the lock for this). - for (Bridges::iterator i = toDelete.begin(); i != toDelete.end(); i++) - (*i)->destroy(); - toDelete.clear(); - links->destroy (host, port); -} - -void Link::add(Bridge::shared_ptr bridge) -{ - Mutex::ScopedLock mutex(lock); - created.push_back (bridge); -} - -void Link::cancel(Bridge::shared_ptr bridge) -{ - { - Mutex::ScopedLock mutex(lock); - - for (Bridges::iterator i = created.begin(); i != created.end(); i++) { - if ((*i).get() == bridge.get()) { - created.erase(i); - break; - } - } - for (Bridges::iterator i = active.begin(); i != active.end(); i++) { - if ((*i).get() == bridge.get()) { - cancellations.push_back(bridge); - bridge->closed(); - active.erase(i); - break; - } - } - } - if (!cancellations.empty()) { - connection->requestIOProcessing (boost::bind(&Link::ioThreadProcessing, this)); - } -} - -void Link::ioThreadProcessing() -{ - Mutex::ScopedLock mutex(lock); - - if (state != STATE_OPERATIONAL) - return; - QPID_LOG(debug, "Link::ioThreadProcessing()"); - - //process any pending creates and/or cancellations - if (!created.empty()) { - for (Bridges::iterator i = created.begin(); i != created.end(); ++i) { - active.push_back(*i); - (*i)->create(*connection); - } - created.clear(); - } - if (!cancellations.empty()) { - for (Bridges::iterator i = cancellations.begin(); i != cancellations.end(); ++i) { - (*i)->cancel(*connection); - } - cancellations.clear(); - } -} - -void Link::setConnection(Connection* c) -{ - Mutex::ScopedLock mutex(lock); - connection = c; - updateUrls = true; -} - -void Link::maintenanceVisit () -{ - Mutex::ScopedLock mutex(lock); - - if (connection && updateUrls) { - urls.reset(connection->getKnownHosts()); - QPID_LOG(debug, "Known hosts for peer of inter-broker link: " << urls); - updateUrls = false; - } - - if (state == STATE_WAITING) - { - visitCount++; - if (visitCount >= currentInterval) - { - visitCount = 0; - //switch host and port to next in url list if possible - if (!tryFailover()) { - currentInterval *= 2; - if (currentInterval > MAX_INTERVAL) - currentInterval = MAX_INTERVAL; - startConnectionLH(); - } - } - } - else if (state == STATE_OPERATIONAL && (!created.empty() || !cancellations.empty()) && connection != 0) - connection->requestIOProcessing (boost::bind(&Link::ioThreadProcessing, this)); -} - -void Link::reconnect(const qpid::Address& a) -{ - Mutex::ScopedLock mutex(lock); - host = a.host; - port = a.port; - transport = a.protocol; - startConnectionLH(); - if (!hideManagement()) { - stringstream errorString; - errorString << "Failed over to " << a; - mgmtObject->set_lastError(errorString.str()); - } -} - -bool Link::tryFailover() -{ - Address next; - if (urls.next(next) && - (next.host != host || next.port != port || next.protocol != transport)) { - links->changeAddress(Address(transport, host, port), next); - QPID_LOG(debug, "Link failing over to " << host << ":" << port); - return true; - } else { - return false; - } -} - -// Management updates for a linke are inconsistent in a cluster, so they are -// suppressed. -bool Link::hideManagement() const { - return !mgmtObject || ( broker && broker->isInCluster()); -} - -uint Link::nextChannel() -{ - Mutex::ScopedLock mutex(lock); - - return channelCounter++; -} - -void Link::notifyConnectionForced(const string text) -{ - Mutex::ScopedLock mutex(lock); - - setStateLH(STATE_FAILED); - if (!hideManagement()) - mgmtObject->set_lastError(text); -} - -void Link::setPersistenceId(uint64_t id) const -{ - persistenceId = id; -} - -const string& Link::getName() const -{ - return host; -} - -Link::shared_ptr Link::decode(LinkRegistry& links, Buffer& buffer) -{ - string host; - uint16_t port; - string transport; - string authMechanism; - string username; - string password; - - buffer.getShortString(host); - port = buffer.getShort(); - buffer.getShortString(transport); - bool durable(buffer.getOctet()); - buffer.getShortString(authMechanism); - buffer.getShortString(username); - buffer.getShortString(password); - - return links.declare(host, port, transport, durable, authMechanism, username, password).first; -} - -void Link::encode(Buffer& buffer) const -{ - buffer.putShortString(string("link")); - buffer.putShortString(host); - buffer.putShort(port); - buffer.putShortString(transport); - buffer.putOctet(durable ? 1 : 0); - buffer.putShortString(authMechanism); - buffer.putShortString(username); - buffer.putShortString(password); -} - -uint32_t Link::encodedSize() const -{ - return host.size() + 1 // short-string (host) - + 5 // short-string ("link") - + 2 // port - + transport.size() + 1 // short-string(transport) - + 1 // durable - + authMechanism.size() + 1 - + username.size() + 1 - + password.size() + 1; -} - -ManagementObject* Link::GetManagementObject (void) const -{ - return (ManagementObject*) mgmtObject; -} - -Manageable::status_t Link::ManagementMethod (uint32_t op, Args& args, string& text) -{ - switch (op) - { - case _qmf::Link::METHOD_CLOSE : - if (!closing) { - closing = true; - if (state != STATE_CONNECTING && connection) { - //connection can only be closed on the connections own IO processing thread - connection->requestIOProcessing(boost::bind(&Link::destroy, this)); - } - } - return Manageable::STATUS_OK; - - case _qmf::Link::METHOD_BRIDGE : - _qmf::ArgsLinkBridge& iargs = (_qmf::ArgsLinkBridge&) args; - QPID_LOG(debug, "Link::bridge() request received"); - - // Durable bridges are only valid on durable links - if (iargs.i_durable && !durable) { - text = "Can't create a durable route on a non-durable link"; - return Manageable::STATUS_USER; - } - - if (iargs.i_dynamic) { - Exchange::shared_ptr exchange = getBroker()->getExchanges().get(iargs.i_src); - if (exchange.get() == 0) { - text = "Exchange not found"; - return Manageable::STATUS_USER; - } - if (!exchange->supportsDynamicBinding()) { - text = "Exchange type does not support dynamic routing"; - return Manageable::STATUS_USER; - } - } - - std::pair<Bridge::shared_ptr, bool> result = - links->declare (host, port, iargs.i_durable, iargs.i_src, - iargs.i_dest, iargs.i_key, iargs.i_srcIsQueue, - iargs.i_srcIsLocal, iargs.i_tag, iargs.i_excludes, - iargs.i_dynamic, iargs.i_sync); - - if (result.second && iargs.i_durable) - store->create(*result.first); - - return Manageable::STATUS_OK; - } - - return Manageable::STATUS_UNKNOWN_METHOD; -} - -void Link::setPassive(bool passive) -{ - Mutex::ScopedLock mutex(lock); - if (passive) { - setStateLH(STATE_PASSIVE); - } else { - if (state == STATE_PASSIVE) { - setStateLH(STATE_WAITING); - } else { - QPID_LOG(warning, "Ignoring attempt to activate non-passive link"); - } - } -} diff --git a/cpp/src/qpid/broker/Link.h b/cpp/src/qpid/broker/Link.h deleted file mode 100644 index 4badd8b3a1..0000000000 --- a/cpp/src/qpid/broker/Link.h +++ /dev/null @@ -1,145 +0,0 @@ -#ifndef _broker_Link_h -#define _broker_Link_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <boost/shared_ptr.hpp> -#include "qpid/broker/MessageStore.h" -#include "qpid/broker/PersistableConfig.h" -#include "qpid/broker/Bridge.h" -#include "qpid/broker/RetryList.h" -#include "qpid/sys/Mutex.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/management/Manageable.h" -#include "qpid/management/ManagementAgent.h" -#include "qmf/org/apache/qpid/broker/Link.h" -#include <boost/ptr_container/ptr_vector.hpp> - -namespace qpid { - namespace broker { - - class LinkRegistry; - class Broker; - class Connection; - - class Link : public PersistableConfig, public management::Manageable { - private: - sys::Mutex lock; - LinkRegistry* links; - MessageStore* store; - std::string host; - uint16_t port; - std::string transport; - bool durable; - std::string authMechanism; - std::string username; - std::string password; - mutable uint64_t persistenceId; - qmf::org::apache::qpid::broker::Link* mgmtObject; - Broker* broker; - int state; - uint32_t visitCount; - uint32_t currentInterval; - bool closing; - RetryList urls; - bool updateUrls; - - typedef std::vector<Bridge::shared_ptr> Bridges; - Bridges created; // Bridges pending creation - Bridges active; // Bridges active - Bridges cancellations; // Bridges pending cancellation - uint channelCounter; - Connection* connection; - management::ManagementAgent* agent; - - static const int STATE_WAITING = 1; - static const int STATE_CONNECTING = 2; - static const int STATE_OPERATIONAL = 3; - static const int STATE_FAILED = 4; - static const int STATE_CLOSED = 5; - static const int STATE_PASSIVE = 6; - - static const uint32_t MAX_INTERVAL = 32; - - void setStateLH (int newState); - void startConnectionLH(); // Start the IO Connection - void destroy(); // Called when mgmt deletes this link - void ioThreadProcessing(); // Called on connection's IO thread by request - bool tryFailover(); // Called during maintenance visit - bool hideManagement() const; - - public: - typedef boost::shared_ptr<Link> shared_ptr; - - Link(LinkRegistry* links, - MessageStore* store, - std::string& host, - uint16_t port, - std::string& transport, - bool durable, - std::string& authMechanism, - std::string& username, - std::string& password, - Broker* broker, - management::Manageable* parent = 0); - virtual ~Link(); - - std::string getHost() { return host; } - uint16_t getPort() { return port; } - bool isDurable() { return durable; } - void maintenanceVisit (); - uint nextChannel(); - void add(Bridge::shared_ptr); - void cancel(Bridge::shared_ptr); - - void established(); // Called when connection is created - void closed(int, std::string); // Called when connection goes away - void setConnection(Connection*); // Set pointer to the AMQP Connection - void reconnect(const Address&); //called by LinkRegistry - - std::string getAuthMechanism() { return authMechanism; } - std::string getUsername() { return username; } - std::string getPassword() { return password; } - Broker* getBroker() { return broker; } - - void notifyConnectionForced(const std::string text); - void setPassive(bool p); - - // PersistableConfig: - void setPersistenceId(uint64_t id) const; - uint64_t getPersistenceId() const { return persistenceId; } - uint32_t encodedSize() const; - void encode(framing::Buffer& buffer) const; - const std::string& getName() const; - - static Link::shared_ptr decode(LinkRegistry& links, framing::Buffer& buffer); - - // Manageable entry points - management::ManagementObject* GetManagementObject(void) const; - management::Manageable::status_t ManagementMethod(uint32_t, management::Args&, std::string&); - - }; - } -} - - -#endif /*!_broker_Link.cpp_h*/ diff --git a/cpp/src/qpid/broker/LinkRegistry.cpp b/cpp/src/qpid/broker/LinkRegistry.cpp deleted file mode 100644 index e9885f5462..0000000000 --- a/cpp/src/qpid/broker/LinkRegistry.cpp +++ /dev/null @@ -1,399 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/LinkRegistry.h" -#include "qpid/broker/Link.h" -#include "qpid/broker/Connection.h" -#include "qpid/log/Statement.h" -#include <iostream> -#include <boost/format.hpp> - -using namespace qpid::broker; -using namespace qpid::sys; -using std::string; -using std::pair; -using std::stringstream; -using boost::intrusive_ptr; -using boost::format; -using boost::str; -namespace _qmf = qmf::org::apache::qpid::broker; - -#define LINK_MAINT_INTERVAL 2 - -// TODO: This constructor is only used by the store unit tests - -// That probably indicates that LinkRegistry isn't correctly -// factored: The persistence element and maintenance element -// should be factored separately -LinkRegistry::LinkRegistry () : - broker(0), timer(0), - parent(0), store(0), passive(false), passiveChanged(false), - realm("") -{ -} - -LinkRegistry::LinkRegistry (Broker* _broker) : - broker(_broker), timer(&broker->getTimer()), - maintenanceTask(new Periodic(*this)), - parent(0), store(0), passive(false), passiveChanged(false), - realm(broker->getOptions().realm) -{ - timer->add(maintenanceTask); -} - -LinkRegistry::~LinkRegistry() -{ - // This test is only necessary if the default constructor above is present - if (maintenanceTask) - maintenanceTask->cancel(); -} - -LinkRegistry::Periodic::Periodic (LinkRegistry& _links) : - TimerTask (Duration (LINK_MAINT_INTERVAL * TIME_SEC),"LinkRegistry"), links(_links) {} - -void LinkRegistry::Periodic::fire () -{ - links.periodicMaintenance (); - setupNextFire(); - links.timer->add(this); -} - -void LinkRegistry::periodicMaintenance () -{ - Mutex::ScopedLock locker(lock); - - linksToDestroy.clear(); - bridgesToDestroy.clear(); - if (passiveChanged) { - if (passive) { QPID_LOG(info, "Passivating links"); } - else { QPID_LOG(info, "Activating links"); } - for (LinkMap::iterator i = links.begin(); i != links.end(); i++) { - i->second->setPassive(passive); - } - passiveChanged = false; - } - for (LinkMap::iterator i = links.begin(); i != links.end(); i++) - i->second->maintenanceVisit(); - //now process any requests for re-addressing - for (AddressMap::iterator i = reMappings.begin(); i != reMappings.end(); i++) - updateAddress(i->first, i->second); - reMappings.clear(); -} - -void LinkRegistry::changeAddress(const qpid::Address& oldAddress, const qpid::Address& newAddress) -{ - //done on periodic maintenance thread; hold changes in separate - //map to avoid modifying the link map that is iterated over - reMappings[createKey(oldAddress)] = newAddress; -} - -bool LinkRegistry::updateAddress(const std::string& oldKey, const qpid::Address& newAddress) -{ - std::string newKey = createKey(newAddress); - if (links.find(newKey) != links.end()) { - QPID_LOG(error, "Attempted to update key from " << oldKey << " to " << newKey << " which is already in use"); - return false; - } else { - LinkMap::iterator i = links.find(oldKey); - if (i == links.end()) { - QPID_LOG(error, "Attempted to update key from " << oldKey << " which does not exist, to " << newKey); - return false; - } else { - links[newKey] = i->second; - i->second->reconnect(newAddress); - links.erase(oldKey); - QPID_LOG(info, "Updated link key from " << oldKey << " to " << newKey); - return true; - } - } -} - -pair<Link::shared_ptr, bool> LinkRegistry::declare(string& host, - uint16_t port, - string& transport, - bool durable, - string& authMechanism, - string& username, - string& password) - -{ - Mutex::ScopedLock locker(lock); - string key = createKey(host, port); - - LinkMap::iterator i = links.find(key); - if (i == links.end()) - { - Link::shared_ptr link; - - link = Link::shared_ptr (new Link (this, store, host, port, transport, durable, - authMechanism, username, password, - broker, parent)); - if (passive) link->setPassive(true); - links[key] = link; - return std::pair<Link::shared_ptr, bool>(link, true); - } - return std::pair<Link::shared_ptr, bool>(i->second, false); -} - -pair<Bridge::shared_ptr, bool> LinkRegistry::declare(std::string& host, - uint16_t port, - bool durable, - std::string& src, - std::string& dest, - std::string& key, - bool isQueue, - bool isLocal, - std::string& tag, - std::string& excludes, - bool dynamic, - uint16_t sync) -{ - Mutex::ScopedLock locker(lock); - QPID_LOG(debug, "Bridge declared " << host << ": " << port << " from " << src << " to " << dest << " (" << key << ")"); - - string linkKey = createKey(host, port); - stringstream keystream; - keystream << linkKey << "!" << src << "!" << dest << "!" << key; - string bridgeKey = keystream.str(); - - LinkMap::iterator l = links.find(linkKey); - if (l == links.end()) - return pair<Bridge::shared_ptr, bool>(Bridge::shared_ptr(), false); - - BridgeMap::iterator b = bridges.find(bridgeKey); - if (b == bridges.end()) - { - _qmf::ArgsLinkBridge args; - Bridge::shared_ptr bridge; - - args.i_durable = durable; - args.i_src = src; - args.i_dest = dest; - args.i_key = key; - args.i_srcIsQueue = isQueue; - args.i_srcIsLocal = isLocal; - args.i_tag = tag; - args.i_excludes = excludes; - args.i_dynamic = dynamic; - args.i_sync = sync; - - bridge = Bridge::shared_ptr - (new Bridge (l->second.get(), l->second->nextChannel(), - boost::bind(&LinkRegistry::destroy, this, - host, port, src, dest, key), args)); - bridges[bridgeKey] = bridge; - l->second->add(bridge); - return std::pair<Bridge::shared_ptr, bool>(bridge, true); - } - return std::pair<Bridge::shared_ptr, bool>(b->second, false); -} - -void LinkRegistry::destroy(const string& host, const uint16_t port) -{ - Mutex::ScopedLock locker(lock); - string key = createKey(host, port); - - LinkMap::iterator i = links.find(key); - if (i != links.end()) - { - if (i->second->isDurable() && store) - store->destroy(*(i->second)); - linksToDestroy[key] = i->second; - links.erase(i); - } -} - -void LinkRegistry::destroy(const std::string& host, - const uint16_t port, - const std::string& src, - const std::string& dest, - const std::string& key) -{ - Mutex::ScopedLock locker(lock); - string linkKey = createKey(host, port); - stringstream keystream; - keystream << linkKey << "!" << src << "!" << dest << "!" << key; - string bridgeKey = keystream.str(); - - LinkMap::iterator l = links.find(linkKey); - if (l == links.end()) - return; - - BridgeMap::iterator b = bridges.find(bridgeKey); - if (b == bridges.end()) - return; - - l->second->cancel(b->second); - if (b->second->isDurable()) - store->destroy(*(b->second)); - bridgesToDestroy[bridgeKey] = b->second; - bridges.erase(b); -} - -void LinkRegistry::setStore (MessageStore* _store) -{ - store = _store; -} - -MessageStore* LinkRegistry::getStore() const { - return store; -} - -Link::shared_ptr LinkRegistry::findLink(const std::string& keyOrMgmtId) -{ - // Convert keyOrMgmtId to a host:port key. - // - // TODO aconway 2011-02-01: centralize code that constructs/parses - // connection management IDs. Currently sys:: protocol factories - // and IO plugins construct the IDs and LinkRegistry parses them. - size_t separator = keyOrMgmtId.find('-'); - if (separator == std::string::npos) separator = 0; - std::string key = keyOrMgmtId.substr(separator+1, std::string::npos); - - Mutex::ScopedLock locker(lock); - LinkMap::iterator l = links.find(key); - if (l != links.end()) return l->second; - else return Link::shared_ptr(); -} - -void LinkRegistry::notifyConnection(const std::string& key, Connection* c) -{ - Link::shared_ptr link = findLink(key); - if (link) { - link->established(); - link->setConnection(c); - c->setUserId(str(format("%1%@%2%") % link->getUsername() % realm)); - } -} - -void LinkRegistry::notifyClosed(const std::string& key) -{ - Link::shared_ptr link = findLink(key); - if (link) { - link->closed(0, "Closed by peer"); - } -} - -void LinkRegistry::notifyConnectionForced(const std::string& key, const std::string& text) -{ - Link::shared_ptr link = findLink(key); - if (link) { - link->notifyConnectionForced(text); - } -} - -std::string LinkRegistry::getAuthMechanism(const std::string& key) -{ - Link::shared_ptr link = findLink(key); - if (link) - return link->getAuthMechanism(); - return string("ANONYMOUS"); -} - -std::string LinkRegistry::getAuthCredentials(const std::string& key) -{ - Link::shared_ptr link = findLink(key); - if (!link) - return string(); - - string result; - result += '\0'; - result += link->getUsername(); - result += '\0'; - result += link->getPassword(); - - return result; -} - -std::string LinkRegistry::getUsername(const std::string& key) -{ - Link::shared_ptr link = findLink(key); - if (!link) - return string(); - - return link->getUsername(); -} - -std::string LinkRegistry::getHost(const std::string& key) -{ - Link::shared_ptr link = findLink(key); - if (!link) - return string(); - - return link->getHost(); -} - -uint16_t LinkRegistry::getPort(const std::string& key) -{ - Link::shared_ptr link = findLink(key); - if (!link) - return 0; - - return link->getPort(); -} - -std::string LinkRegistry::getPassword(const std::string& key) -{ - Link::shared_ptr link = findLink(key); - if (!link) - return string(); - - return link->getPassword(); -} - -std::string LinkRegistry::getAuthIdentity(const std::string& key) -{ - Link::shared_ptr link = findLink(key); - if (!link) - return string(); - - return link->getUsername(); -} - - -std::string LinkRegistry::createKey(const qpid::Address& a) { - // TODO aconway 2010-05-11: key should also include protocol/transport to - // be unique. Requires refactor of LinkRegistry interface. - return createKey(a.host, a.port); -} - -std::string LinkRegistry::createKey(const std::string& host, uint16_t port) { - // TODO aconway 2010-05-11: key should also include protocol/transport to - // be unique. Requires refactor of LinkRegistry interface. - stringstream keystream; - keystream << host << ":" << port; - return keystream.str(); -} - -void LinkRegistry::setPassive(bool p) -{ - Mutex::ScopedLock locker(lock); - passiveChanged = p != passive; - passive = p; - //will activate or passivate links on maintenance visit -} - -void LinkRegistry::eachLink(boost::function<void(boost::shared_ptr<Link>)> f) { - for (LinkMap::iterator i = links.begin(); i != links.end(); ++i) f(i->second); -} - -void LinkRegistry::eachBridge(boost::function<void(boost::shared_ptr<Bridge>)> f) { - for (BridgeMap::iterator i = bridges.begin(); i != bridges.end(); ++i) f(i->second); -} - diff --git a/cpp/src/qpid/broker/LinkRegistry.h b/cpp/src/qpid/broker/LinkRegistry.h deleted file mode 100644 index 4c97e4f9d8..0000000000 --- a/cpp/src/qpid/broker/LinkRegistry.h +++ /dev/null @@ -1,163 +0,0 @@ -#ifndef _broker_LinkRegistry_h -#define _broker_LinkRegistry_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <map> -#include "qpid/broker/Bridge.h" -#include "qpid/broker/MessageStore.h" -#include "qpid/Address.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/Timer.h" -#include "qpid/management/Manageable.h" -#include <boost/shared_ptr.hpp> -#include <boost/intrusive_ptr.hpp> -#include <boost/function.hpp> - -namespace qpid { -namespace broker { - - class Link; - class Broker; - class Connection; - class LinkRegistry { - - // Declare a timer task to manage the establishment of link connections and the - // re-establishment of lost link connections. - struct Periodic : public sys::TimerTask - { - LinkRegistry& links; - - Periodic(LinkRegistry& links); - virtual ~Periodic() {}; - void fire(); - }; - - typedef std::map<std::string, boost::shared_ptr<Link> > LinkMap; - typedef std::map<std::string, Bridge::shared_ptr> BridgeMap; - typedef std::map<std::string, Address> AddressMap; - - LinkMap links; - LinkMap linksToDestroy; - BridgeMap bridges; - BridgeMap bridgesToDestroy; - AddressMap reMappings; - - qpid::sys::Mutex lock; - Broker* broker; - sys::Timer* timer; - boost::intrusive_ptr<qpid::sys::TimerTask> maintenanceTask; - management::Manageable* parent; - MessageStore* store; - bool passive; - bool passiveChanged; - std::string realm; - - void periodicMaintenance (); - bool updateAddress(const std::string& oldKey, const Address& newAddress); - boost::shared_ptr<Link> findLink(const std::string& key); - static std::string createKey(const Address& address); - static std::string createKey(const std::string& host, uint16_t port); - - public: - LinkRegistry (); // Only used in store tests - LinkRegistry (Broker* _broker); - ~LinkRegistry(); - - std::pair<boost::shared_ptr<Link>, bool> - declare(std::string& host, - uint16_t port, - std::string& transport, - bool durable, - std::string& authMechanism, - std::string& username, - std::string& password); - std::pair<Bridge::shared_ptr, bool> - declare(std::string& host, - uint16_t port, - bool durable, - std::string& src, - std::string& dest, - std::string& key, - bool isQueue, - bool isLocal, - std::string& id, - std::string& excludes, - bool dynamic, - uint16_t sync); - - void destroy(const std::string& host, const uint16_t port); - void destroy(const std::string& host, - const uint16_t port, - const std::string& src, - const std::string& dest, - const std::string& key); - - /** - * Register the manageable parent for declared queues - */ - void setParent (management::Manageable* _parent) { parent = _parent; } - - /** - * Set the store to use. May only be called once. - */ - void setStore (MessageStore*); - - /** - * Return the message store used. - */ - MessageStore* getStore() const; - - void notifyConnection (const std::string& key, Connection* c); - void notifyClosed (const std::string& key); - void notifyConnectionForced (const std::string& key, const std::string& text); - std::string getAuthMechanism (const std::string& key); - std::string getAuthCredentials (const std::string& key); - std::string getAuthIdentity (const std::string& key); - std::string getUsername (const std::string& key); - std::string getPassword (const std::string& key); - std::string getHost (const std::string& key); - uint16_t getPort (const std::string& key); - - /** - * Called by links failing over to new address - */ - void changeAddress(const Address& oldAddress, const Address& newAddress); - /** - * Called to alter passive state. In passive state the links - * and bridges managed by a link registry will be recorded and - * updated but links won't actually establish connections and - * bridges won't therefore pull or push any messages. - */ - void setPassive(bool); - - - /** Iterate over each link in the registry. Used for cluster updates. */ - void eachLink(boost::function<void(boost::shared_ptr<Link>)> f); - /** Iterate over each bridge in the registry. Used for cluster updates. */ - void eachBridge(boost::function<void(boost::shared_ptr< Bridge>)> f); - }; -} -} - - -#endif /*!_broker_LinkRegistry_h*/ diff --git a/cpp/src/qpid/broker/Message.cpp b/cpp/src/qpid/broker/Message.cpp deleted file mode 100644 index 763dc55e40..0000000000 --- a/cpp/src/qpid/broker/Message.cpp +++ /dev/null @@ -1,452 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/Message.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/ExchangeRegistry.h" -#include "qpid/broker/ExpiryPolicy.h" -#include "qpid/StringUtils.h" -#include "qpid/framing/frame_functors.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/SendContent.h" -#include "qpid/framing/SequenceNumber.h" -#include "qpid/framing/TypeFilter.h" -#include "qpid/log/Statement.h" - -#include <time.h> - -using boost::intrusive_ptr; -using qpid::sys::AbsTime; -using qpid::sys::Duration; -using qpid::sys::TIME_MSEC; -using qpid::sys::FAR_FUTURE; -using std::string; -using namespace qpid::framing; - -namespace qpid { -namespace broker { - -TransferAdapter Message::TRANSFER; - -Message::Message(const framing::SequenceNumber& id) : - frames(id), persistenceId(0), redelivered(false), loaded(false), - staged(false), forcePersistentPolicy(false), publisher(0), adapter(0), - expiration(FAR_FUTURE), dequeueCallback(0), - inCallback(false), requiredCredit(0), isManagementMessage(false) -{} - -Message::Message(const Message& original) : - PersistableMessage(), frames(original.frames), persistenceId(0), redelivered(false), loaded(false), - staged(false), forcePersistentPolicy(false), publisher(0), adapter(0), - expiration(original.expiration), dequeueCallback(0), - inCallback(false), requiredCredit(0) -{ - setExpiryPolicy(original.expiryPolicy); -} - -Message::~Message() -{ - if (expiryPolicy) - expiryPolicy->forget(*this); -} - -void Message::forcePersistent() -{ - // only set forced bit if we actually need to force. - if (! getAdapter().isPersistent(frames) ){ - forcePersistentPolicy = true; - } -} - -bool Message::isForcedPersistent() -{ - return forcePersistentPolicy; -} - -std::string Message::getRoutingKey() const -{ - return getAdapter().getRoutingKey(frames); -} - -std::string Message::getExchangeName() const -{ - return getAdapter().getExchange(frames); -} - -const boost::shared_ptr<Exchange> Message::getExchange(ExchangeRegistry& registry) const -{ - if (!exchange) { - exchange = registry.get(getExchangeName()); - } - return exchange; -} - -bool Message::isImmediate() const -{ - return getAdapter().isImmediate(frames); -} - -const FieldTable* Message::getApplicationHeaders() const -{ - return getAdapter().getApplicationHeaders(frames); -} - -std::string Message::getAppId() const -{ - return getAdapter().getAppId(frames); -} - -bool Message::isPersistent() const -{ - return (getAdapter().isPersistent(frames) || forcePersistentPolicy); -} - -bool Message::requiresAccept() -{ - return getAdapter().requiresAccept(frames); -} - -uint32_t Message::getRequiredCredit() -{ - sys::Mutex::ScopedLock l(lock); - if (!requiredCredit) { - //add up payload for all header and content frames in the frameset - SumBodySize sum; - frames.map_if(sum, TypeFilter2<HEADER_BODY, CONTENT_BODY>()); - requiredCredit = sum.getSize(); - } - return requiredCredit; -} - -void Message::encode(framing::Buffer& buffer) const -{ - //encode method and header frames - EncodeFrame f1(buffer); - frames.map_if(f1, TypeFilter2<METHOD_BODY, HEADER_BODY>()); - - //then encode the payload of each content frame - framing::EncodeBody f2(buffer); - frames.map_if(f2, TypeFilter<CONTENT_BODY>()); -} - -void Message::encodeContent(framing::Buffer& buffer) const -{ - //encode the payload of each content frame - EncodeBody f2(buffer); - frames.map_if(f2, TypeFilter<CONTENT_BODY>()); -} - -uint32_t Message::encodedSize() const -{ - return encodedHeaderSize() + encodedContentSize(); -} - -uint32_t Message::encodedContentSize() const -{ - return frames.getContentSize(); -} - -uint32_t Message::encodedHeaderSize() const -{ - //add up the size for all method and header frames in the frameset - SumFrameSize sum; - frames.map_if(sum, TypeFilter2<METHOD_BODY, HEADER_BODY>()); - return sum.getSize(); -} - -void Message::decodeHeader(framing::Buffer& buffer) -{ - AMQFrame method; - method.decode(buffer); - frames.append(method); - - AMQFrame header; - header.decode(buffer); - frames.append(header); -} - -void Message::decodeContent(framing::Buffer& buffer) -{ - if (buffer.available()) { - //get the data as a string and set that as the content - //body on a frame then add that frame to the frameset - AMQFrame frame((AMQContentBody())); - frame.castBody<AMQContentBody>()->decode(buffer, buffer.available()); - frame.setFirstSegment(false); - frames.append(frame); - } else { - //adjust header flags - MarkLastSegment f; - frames.map_if(f, TypeFilter<HEADER_BODY>()); - } - //mark content loaded - loaded = true; -} - -// Used for testing only -void Message::tryReleaseContent() -{ - if (checkContentReleasable()) { - releaseContent(); - } -} - -void Message::releaseContent(MessageStore* s) -{ - //deprecated, use setStore(store); releaseContent(); instead - if (!store) setStore(s); - releaseContent(); -} - -void Message::releaseContent() -{ - sys::Mutex::ScopedLock l(lock); - if (store) { - if (!getPersistenceId()) { - intrusive_ptr<PersistableMessage> pmsg(this); - store->stage(pmsg); - staged = true; - } - //ensure required credit is cached before content frames are released - getRequiredCredit(); - //remove any content frames from the frameset - frames.remove(TypeFilter<CONTENT_BODY>()); - setContentReleased(); - } -} - -void Message::destroy() -{ - if (staged) { - if (store) { - store->destroy(*this); - } else { - QPID_LOG(error, "Message content was staged but no store is set so it can't be destroyed"); - } - } -} - -bool Message::getContentFrame(const Queue& queue, AMQFrame& frame, uint16_t maxContentSize, uint64_t offset) const -{ - intrusive_ptr<const PersistableMessage> pmsg(this); - - bool done = false; - string& data = frame.castBody<AMQContentBody>()->getData(); - store->loadContent(queue, pmsg, data, offset, maxContentSize); - done = data.size() < maxContentSize; - frame.setBof(false); - frame.setEof(true); - QPID_LOG(debug, "loaded frame" << frame); - if (offset > 0) { - frame.setBos(false); - } - if (!done) { - frame.setEos(false); - } else return false; - return true; -} - -void Message::sendContent(const Queue& queue, framing::FrameHandler& out, uint16_t maxFrameSize) const -{ - sys::Mutex::ScopedLock l(lock); - if (isContentReleased() && !frames.isComplete()) { - sys::Mutex::ScopedUnlock u(lock); - uint16_t maxContentSize = maxFrameSize - AMQFrame::frameOverhead(); - bool morecontent = true; - for (uint64_t offset = 0; morecontent; offset += maxContentSize) - { - AMQFrame frame((AMQContentBody())); - morecontent = getContentFrame(queue, frame, maxContentSize, offset); - out.handle(frame); - } - } else { - Count c; - frames.map_if(c, TypeFilter<CONTENT_BODY>()); - - SendContent f(out, maxFrameSize, c.getCount()); - frames.map_if(f, TypeFilter<CONTENT_BODY>()); - } -} - -void Message::sendHeader(framing::FrameHandler& out, uint16_t /*maxFrameSize*/) const -{ - sys::Mutex::ScopedLock l(lock); - Relay f(out); - frames.map_if(f, TypeFilter<HEADER_BODY>()); -} - -// TODO aconway 2007-11-09: Obsolete, remove. Was used to cover over -// 0-8/0-9 message differences. -MessageAdapter& Message::getAdapter() const -{ - if (!adapter) { - if(frames.isA<MessageTransferBody>()) { - adapter = &TRANSFER; - } else { - const AMQMethodBody* method = frames.getMethod(); - if (!method) throw Exception("Can't adapt message with no method"); - else throw Exception(QPID_MSG("Can't adapt message based on " << *method)); - } - } - return *adapter; -} - -uint64_t Message::contentSize() const -{ - return frames.getContentSize(); -} - -bool Message::isContentLoaded() const -{ - return loaded; -} - - -namespace -{ -const std::string X_QPID_TRACE("x-qpid.trace"); -} - -bool Message::isExcluded(const std::vector<std::string>& excludes) const -{ - const FieldTable* headers = getApplicationHeaders(); - if (headers) { - std::string traceStr = headers->getAsString(X_QPID_TRACE); - if (traceStr.size()) { - std::vector<std::string> trace = split(traceStr, ", "); - - for (std::vector<std::string>::const_iterator i = excludes.begin(); i != excludes.end(); i++) { - for (std::vector<std::string>::const_iterator j = trace.begin(); j != trace.end(); j++) { - if (*i == *j) { - return true; - } - } - } - } - } - return false; -} - -void Message::addTraceId(const std::string& id) -{ - sys::Mutex::ScopedLock l(lock); - if (isA<MessageTransferBody>()) { - FieldTable& headers = getProperties<MessageProperties>()->getApplicationHeaders(); - std::string trace = headers.getAsString(X_QPID_TRACE); - if (trace.empty()) { - headers.setString(X_QPID_TRACE, id); - } else if (trace.find(id) == std::string::npos) { - trace += ","; - trace += id; - headers.setString(X_QPID_TRACE, trace); - } - } -} - -void Message::setTimestamp(const boost::intrusive_ptr<ExpiryPolicy>& e) -{ - DeliveryProperties* props = getProperties<DeliveryProperties>(); - if (props->getTtl()) { - // AMQP requires setting the expiration property to be posix - // time_t in seconds. TTL is in milliseconds - if (!props->getExpiration()) { - //only set expiration in delivery properties if not already set - time_t now = ::time(0); - props->setExpiration(now + (props->getTtl()/1000)); - } - // Use higher resolution time for the internal expiry calculation. - Duration ttl(std::min(props->getTtl() * TIME_MSEC, (uint64_t) std::numeric_limits<int64_t>::max()));//Prevent overflow - expiration = AbsTime(AbsTime::now(), ttl); - setExpiryPolicy(e); - } -} - -void Message::adjustTtl() -{ - DeliveryProperties* props = getProperties<DeliveryProperties>(); - if (props->getTtl()) { - sys::Mutex::ScopedLock l(lock); - if (expiration < FAR_FUTURE) { - sys::Duration d(sys::AbsTime::now(), getExpiration()); - props->setTtl(int64_t(d) > 0 ? int64_t(d)/1000000 : 1); // convert from ns to ms; set to 1 if expired - } - } -} - -void Message::setExpiryPolicy(const boost::intrusive_ptr<ExpiryPolicy>& e) { - expiryPolicy = e; - if (expiryPolicy) - expiryPolicy->willExpire(*this); -} - -bool Message::hasExpired() -{ - return expiryPolicy && expiryPolicy->hasExpired(*this); -} - -namespace { -struct ScopedSet { - sys::Monitor& lock; - bool& flag; - ScopedSet(sys::Monitor& l, bool& f) : lock(l), flag(f) { - sys::Monitor::ScopedLock sl(lock); - flag = true; - } - ~ScopedSet(){ - sys::Monitor::ScopedLock sl(lock); - flag = false; - lock.notifyAll(); - } -}; -} - -void Message::allDequeuesComplete() { - ScopedSet ss(callbackLock, inCallback); - MessageCallback* cb = dequeueCallback; - if (cb && *cb) (*cb)(intrusive_ptr<Message>(this)); -} - -void Message::setDequeueCompleteCallback(MessageCallback& cb) { - sys::Mutex::ScopedLock l(callbackLock); - while (inCallback) callbackLock.wait(); - dequeueCallback = &cb; -} - -void Message::resetDequeueCompleteCallback() { - sys::Mutex::ScopedLock l(callbackLock); - while (inCallback) callbackLock.wait(); - dequeueCallback = 0; -} - -uint8_t Message::getPriority() const { - return getAdapter().getPriority(frames); -} - -framing::FieldTable& Message::getOrInsertHeaders() -{ - return getProperties<MessageProperties>()->getApplicationHeaders(); -} - -bool Message::getIsManagementMessage() const { return isManagementMessage; } -void Message::setIsManagementMessage(bool b) { isManagementMessage = b; } - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/Message.h b/cpp/src/qpid/broker/Message.h deleted file mode 100644 index d85ee434db..0000000000 --- a/cpp/src/qpid/broker/Message.h +++ /dev/null @@ -1,196 +0,0 @@ -#ifndef _broker_Message_h -#define _broker_Message_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/PersistableMessage.h" -#include "qpid/broker/MessageAdapter.h" -#include "qpid/framing/amqp_types.h" -#include "qpid/sys/Monitor.h" -#include "qpid/sys/Time.h" -#include <boost/function.hpp> -#include <boost/shared_ptr.hpp> -#include <string> -#include <vector> - -namespace qpid { - -namespace framing { -class FieldTable; -class SequenceNumber; -} - -namespace broker { -class ConnectionToken; -class Exchange; -class ExchangeRegistry; -class MessageStore; -class Queue; -class ExpiryPolicy; - -class Message : public PersistableMessage { -public: - typedef boost::function<void (const boost::intrusive_ptr<Message>&)> MessageCallback; - - QPID_BROKER_EXTERN Message(const framing::SequenceNumber& id = framing::SequenceNumber()); - QPID_BROKER_EXTERN Message(const Message&); - QPID_BROKER_EXTERN ~Message(); - - uint64_t getPersistenceId() const { return persistenceId; } - void setPersistenceId(uint64_t _persistenceId) const { persistenceId = _persistenceId; } - - bool getRedelivered() const { return redelivered; } - void redeliver() { redelivered = true; } - - const ConnectionToken* getPublisher() const { return publisher; } - void setPublisher(ConnectionToken* p) { publisher = p; } - - const framing::SequenceNumber& getCommandId() { return frames.getId(); } - - QPID_BROKER_EXTERN uint64_t contentSize() const; - - QPID_BROKER_EXTERN std::string getRoutingKey() const; - const boost::shared_ptr<Exchange> getExchange(ExchangeRegistry&) const; - QPID_BROKER_EXTERN std::string getExchangeName() const; - bool isImmediate() const; - QPID_BROKER_EXTERN const framing::FieldTable* getApplicationHeaders() const; - QPID_BROKER_EXTERN std::string getAppId() const; - framing::FieldTable& getOrInsertHeaders(); - QPID_BROKER_EXTERN bool isPersistent() const; - bool requiresAccept(); - - QPID_BROKER_EXTERN void setTimestamp(const boost::intrusive_ptr<ExpiryPolicy>& e); - void setExpiryPolicy(const boost::intrusive_ptr<ExpiryPolicy>& e); - bool hasExpired(); - sys::AbsTime getExpiration() const { return expiration; } - void adjustTtl(); - - framing::FrameSet& getFrames() { return frames; } - const framing::FrameSet& getFrames() const { return frames; } - - template <class T> T* getProperties() { - qpid::framing::AMQHeaderBody* p = frames.getHeaders(); - return p->get<T>(true); - } - - template <class T> const T* getProperties() const { - const qpid::framing::AMQHeaderBody* p = frames.getHeaders(); - return p->get<T>(true); - } - - template <class T> const T* hasProperties() const { - const qpid::framing::AMQHeaderBody* p = frames.getHeaders(); - return p->get<T>(); - } - - template <class T> const T* getMethod() const { - return frames.as<T>(); - } - - template <class T> T* getMethod() { - return frames.as<T>(); - } - - template <class T> bool isA() const { - return frames.isA<T>(); - } - - uint32_t getRequiredCredit(); - - void encode(framing::Buffer& buffer) const; - void encodeContent(framing::Buffer& buffer) const; - - /** - * @returns the size of the buffer needed to encode this - * message in its entirety - */ - uint32_t encodedSize() const; - /** - * @returns the size of the buffer needed to encode the - * 'header' of this message (not just the header frame, - * but other meta data e.g.routing key and exchange) - */ - uint32_t encodedHeaderSize() const; - uint32_t encodedContentSize() const; - - QPID_BROKER_EXTERN void decodeHeader(framing::Buffer& buffer); - QPID_BROKER_EXTERN void decodeContent(framing::Buffer& buffer); - - void QPID_BROKER_EXTERN tryReleaseContent(); - void releaseContent(); - void releaseContent(MessageStore* s);//deprecated, use 'setStore(store); releaseContent();' instead - void destroy(); - - bool getContentFrame(const Queue& queue, framing::AMQFrame& frame, uint16_t maxContentSize, uint64_t offset) const; - QPID_BROKER_EXTERN void sendContent(const Queue& queue, framing::FrameHandler& out, uint16_t maxFrameSize) const; - void sendHeader(framing::FrameHandler& out, uint16_t maxFrameSize) const; - - QPID_BROKER_EXTERN bool isContentLoaded() const; - - bool isExcluded(const std::vector<std::string>& excludes) const; - void addTraceId(const std::string& id); - - void forcePersistent(); - bool isForcedPersistent(); - - - /** Call cb when dequeue is complete, may call immediately. Holds cb by reference. */ - void setDequeueCompleteCallback(MessageCallback& cb); - void resetDequeueCompleteCallback(); - - uint8_t getPriority() const; - bool getIsManagementMessage() const; - void setIsManagementMessage(bool b); - private: - MessageAdapter& getAdapter() const; - void allDequeuesComplete(); - - mutable sys::Mutex lock; - framing::FrameSet frames; - mutable boost::shared_ptr<Exchange> exchange; - mutable uint64_t persistenceId; - bool redelivered; - bool loaded; - bool staged; - bool forcePersistentPolicy; // used to force message as durable, via a broker policy - ConnectionToken* publisher; - mutable MessageAdapter* adapter; - qpid::sys::AbsTime expiration; - boost::intrusive_ptr<ExpiryPolicy> expiryPolicy; - - static TransferAdapter TRANSFER; - - mutable boost::intrusive_ptr<Message> empty; - - sys::Monitor callbackLock; - MessageCallback* dequeueCallback; - bool inCallback; - - uint32_t requiredCredit; - bool isManagementMessage; -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/MessageAdapter.cpp b/cpp/src/qpid/broker/MessageAdapter.cpp deleted file mode 100644 index 0eb4a6fa22..0000000000 --- a/cpp/src/qpid/broker/MessageAdapter.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/MessageAdapter.h" - -#include "qpid/framing/DeliveryProperties.h" -#include "qpid/framing/MessageProperties.h" -#include "qpid/framing/MessageTransferBody.h" - -namespace { - const std::string empty; -} - -namespace qpid { -namespace broker{ - - std::string TransferAdapter::getRoutingKey(const framing::FrameSet& f) - { - const framing::DeliveryProperties* p = f.getHeaders()->get<framing::DeliveryProperties>(); - return p ? p->getRoutingKey() : empty; - } - - std::string TransferAdapter::getExchange(const framing::FrameSet& f) - { - return f.as<framing::MessageTransferBody>()->getDestination(); - } - - bool TransferAdapter::isImmediate(const framing::FrameSet&) - { - //TODO: delete this, immediate is no longer part of the spec - return false; - } - - const framing::FieldTable* TransferAdapter::getApplicationHeaders(const framing::FrameSet& f) - { - const framing::MessageProperties* p = f.getHeaders()->get<framing::MessageProperties>(); - return p ? &(p->getApplicationHeaders()) : 0; - } - - bool TransferAdapter::isPersistent(const framing::FrameSet& f) - { - const framing::DeliveryProperties* p = f.getHeaders()->get<framing::DeliveryProperties>(); - return p && p->getDeliveryMode() == 2; - } - - bool TransferAdapter::requiresAccept(const framing::FrameSet& f) - { - const framing::MessageTransferBody* b = f.as<framing::MessageTransferBody>(); - return b && b->getAcceptMode() == 0/*EXPLICIT == 0*/; - } - - uint8_t TransferAdapter::getPriority(const framing::FrameSet& f) - { - const framing::DeliveryProperties* p = f.getHeaders()->get<framing::DeliveryProperties>(); - return p ? p->getPriority() : 0; - } - - std::string TransferAdapter::getAppId(const framing::FrameSet& f) - { - const framing::MessageProperties* p = f.getHeaders()->get<framing::MessageProperties>(); - return p ? p->getAppId() : empty; - } -}} diff --git a/cpp/src/qpid/broker/MessageAdapter.h b/cpp/src/qpid/broker/MessageAdapter.h deleted file mode 100644 index df50db4063..0000000000 --- a/cpp/src/qpid/broker/MessageAdapter.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef _broker_MessageAdapter_h -#define _broker_MessageAdapter_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <string> -#include "qpid/framing/FieldTable.h" -#include "qpid/framing/FrameSet.h" - -namespace qpid { -namespace broker { - -// TODO aconway 2007-11-09: No longer needed, we only have one type of message. -struct MessageAdapter -{ - virtual ~MessageAdapter() {} - - virtual std::string getRoutingKey(const framing::FrameSet& f) = 0; - virtual std::string getExchange(const framing::FrameSet& f) = 0; - virtual bool isImmediate(const framing::FrameSet& f) = 0; - virtual const framing::FieldTable* getApplicationHeaders(const framing::FrameSet& f) = 0; - virtual bool isPersistent(const framing::FrameSet& f) = 0; - virtual bool requiresAccept(const framing::FrameSet& f) = 0; - virtual uint8_t getPriority(const framing::FrameSet& f) = 0; - virtual std::string getAppId(const framing::FrameSet& f) = 0; -}; - -struct TransferAdapter : MessageAdapter -{ - virtual std::string getRoutingKey(const framing::FrameSet& f); - virtual std::string getExchange(const framing::FrameSet& f); - virtual const framing::FieldTable* getApplicationHeaders(const framing::FrameSet& f); - virtual bool isPersistent(const framing::FrameSet& f); - bool isImmediate(const framing::FrameSet&); - bool requiresAccept(const framing::FrameSet& f); - uint8_t getPriority(const framing::FrameSet& f); - virtual std::string getAppId(const framing::FrameSet& f); -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/MessageBuilder.cpp b/cpp/src/qpid/broker/MessageBuilder.cpp deleted file mode 100644 index a6d605c296..0000000000 --- a/cpp/src/qpid/broker/MessageBuilder.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/MessageBuilder.h" - -#include "qpid/broker/Message.h" -#include "qpid/broker/MessageStore.h" -#include "qpid/broker/NullMessageStore.h" -#include "qpid/framing/AMQFrame.h" -#include "qpid/framing/reply_exceptions.h" - -using boost::intrusive_ptr; -using namespace qpid::broker; -using namespace qpid::framing; - -namespace -{ - std::string type_str(uint8_t type); - const std::string QPID_MANAGEMENT("qpid.management"); -} - -MessageBuilder::MessageBuilder(MessageStore* const _store) : - state(DORMANT), store(_store) {} - -void MessageBuilder::handle(AMQFrame& frame) -{ - uint8_t type = frame.getBody()->type(); - switch(state) { - case METHOD: - checkType(METHOD_BODY, type); - state = HEADER; - break; - case HEADER: - if (type == CONTENT_BODY) { - //TODO: rethink how to handle non-existent headers(?)... - //didn't get a header: add in a dummy - AMQFrame header((AMQHeaderBody())); - header.setBof(false); - header.setEof(false); - message->getFrames().append(header); - } else if (type != HEADER_BODY) { - throw CommandInvalidException( - QPID_MSG("Invalid frame sequence for message, expected header or content got " - << type_str(type) << ")")); - } - state = CONTENT; - break; - case CONTENT: - checkType(CONTENT_BODY, type); - break; - default: - throw CommandInvalidException(QPID_MSG("Invalid frame sequence for message (state=" << state << ")")); - } - message->getFrames().append(frame); -} - -void MessageBuilder::end() -{ - message = 0; - state = DORMANT; -} - -void MessageBuilder::start(const SequenceNumber& id) -{ - message = intrusive_ptr<Message>(new Message(id)); - message->setStore(store); - state = METHOD; -} - -namespace { - -const std::string HEADER_BODY_S = "HEADER"; -const std::string METHOD_BODY_S = "METHOD"; -const std::string CONTENT_BODY_S = "CONTENT"; -const std::string HEARTBEAT_BODY_S = "HEARTBEAT"; -const std::string UNKNOWN = "unknown"; - -std::string type_str(uint8_t type) -{ - switch(type) { - case METHOD_BODY: return METHOD_BODY_S; - case HEADER_BODY: return HEADER_BODY_S; - case CONTENT_BODY: return CONTENT_BODY_S; - case HEARTBEAT_BODY: return HEARTBEAT_BODY_S; - } - return UNKNOWN; -} - -} - -void MessageBuilder::checkType(uint8_t expected, uint8_t actual) -{ - if (expected != actual) { - throw CommandInvalidException(QPID_MSG("Invalid frame sequence for message (expected " - << type_str(expected) << " got " << type_str(actual) << ")")); - } -} diff --git a/cpp/src/qpid/broker/MessageBuilder.h b/cpp/src/qpid/broker/MessageBuilder.h deleted file mode 100644 index b99b8efee6..0000000000 --- a/cpp/src/qpid/broker/MessageBuilder.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _MessageBuilder_ -#define _MessageBuilder_ - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/SequenceNumber.h" -#include "qpid/RefCounted.h" - -#include <boost/intrusive_ptr.hpp> - -namespace qpid { - namespace broker { - class Message; - class MessageStore; - - class QPID_BROKER_CLASS_EXTERN MessageBuilder : public framing::FrameHandler{ - public: - QPID_BROKER_EXTERN MessageBuilder(MessageStore* const store); - QPID_BROKER_EXTERN void handle(framing::AMQFrame& frame); - boost::intrusive_ptr<Message> getMessage() { return message; } - QPID_BROKER_EXTERN void start(const framing::SequenceNumber& id); - void end(); - private: - enum State {DORMANT, METHOD, HEADER, CONTENT}; - State state; - boost::intrusive_ptr<Message> message; - MessageStore* const store; - - void checkType(uint8_t expected, uint8_t actual); - }; - } -} - - -#endif - diff --git a/cpp/src/qpid/broker/MessageDeque.cpp b/cpp/src/qpid/broker/MessageDeque.cpp deleted file mode 100644 index 24b8f6f895..0000000000 --- a/cpp/src/qpid/broker/MessageDeque.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/MessageDeque.h" -#include "qpid/broker/QueuedMessage.h" - -namespace qpid { -namespace broker { - -size_t MessageDeque::size() -{ - return messages.size(); -} - -bool MessageDeque::empty() -{ - return messages.empty(); -} - -void MessageDeque::reinsert(const QueuedMessage& message) -{ - messages.insert(lower_bound(messages.begin(), messages.end(), message), message); -} - -MessageDeque::Deque::iterator MessageDeque::seek(const framing::SequenceNumber& position) -{ - if (!messages.empty()) { - QueuedMessage comp; - comp.position = position; - unsigned long diff = position.getValue() - messages.front().position.getValue(); - long maxEnd = diff < messages.size()? diff : messages.size(); - return lower_bound(messages.begin(),messages.begin()+maxEnd,comp); - } else { - return messages.end(); - } -} - -bool MessageDeque::find(const framing::SequenceNumber& position, QueuedMessage& message, bool remove) -{ - Deque::iterator i = seek(position); - if (i != messages.end() && i->position == position) { - message = *i; - if (remove) messages.erase(i); - return true; - } else { - return false; - } -} - -bool MessageDeque::remove(const framing::SequenceNumber& position, QueuedMessage& message) -{ - return find(position, message, true); -} - -bool MessageDeque::find(const framing::SequenceNumber& position, QueuedMessage& message) -{ - return find(position, message, false); -} - -bool MessageDeque::next(const framing::SequenceNumber& position, QueuedMessage& message) -{ - if (messages.empty()) { - return false; - } else if (position < front().position) { - message = front(); - return true; - } else { - Deque::iterator i = seek(position+1); - if (i != messages.end()) { - message = *i; - return true; - } else { - return false; - } - } -} - -QueuedMessage& MessageDeque::front() -{ - return messages.front(); -} - -void MessageDeque::pop() -{ - if (!messages.empty()) { - messages.pop_front(); - } -} - -bool MessageDeque::pop(QueuedMessage& out) -{ - if (messages.empty()) { - return false; - } else { - out = front(); - messages.pop_front(); - return true; - } -} - -bool MessageDeque::push(const QueuedMessage& added, QueuedMessage& /*not needed*/) -{ - messages.push_back(added); - return false;//adding a message never causes one to be removed for deque -} - -void MessageDeque::foreach(Functor f) -{ - std::for_each(messages.begin(), messages.end(), f); -} - -void MessageDeque::removeIf(Predicate p) -{ - for (Deque::iterator i = messages.begin(); i != messages.end();) { - if (p(*i)) { - i = messages.erase(i); - } else { - ++i; - } - } -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/MessageDeque.h b/cpp/src/qpid/broker/MessageDeque.h deleted file mode 100644 index 0e1aef2986..0000000000 --- a/cpp/src/qpid/broker/MessageDeque.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef QPID_BROKER_MESSAGEDEQUE_H -#define QPID_BROKER_MESSAGEDEQUE_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/Messages.h" -#include "qpid/broker/QueuedMessage.h" -#include <deque> - -namespace qpid { -namespace broker { - -/** - * Provides the standard FIFO queue behaviour. - */ -class MessageDeque : public Messages -{ - public: - size_t size(); - bool empty(); - - void reinsert(const QueuedMessage&); - bool remove(const framing::SequenceNumber&, QueuedMessage&); - bool find(const framing::SequenceNumber&, QueuedMessage&); - bool next(const framing::SequenceNumber&, QueuedMessage&); - - QueuedMessage& front(); - void pop(); - bool pop(QueuedMessage&); - bool push(const QueuedMessage& added, QueuedMessage& removed); - - void foreach(Functor); - void removeIf(Predicate); - - private: - typedef std::deque<QueuedMessage> Deque; - Deque messages; - - Deque::iterator seek(const framing::SequenceNumber&); - bool find(const framing::SequenceNumber&, QueuedMessage&, bool remove); -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_MESSAGEDEQUE_H*/ diff --git a/cpp/src/qpid/broker/MessageMap.cpp b/cpp/src/qpid/broker/MessageMap.cpp deleted file mode 100644 index 39e23df533..0000000000 --- a/cpp/src/qpid/broker/MessageMap.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/MessageMap.h" -#include "qpid/broker/QueuedMessage.h" - -namespace qpid { -namespace broker { -namespace { -const std::string EMPTY; -} - -std::string MessageMap::getKey(const QueuedMessage& message) -{ - const framing::FieldTable* ft = message.payload->getApplicationHeaders(); - if (ft) return ft->getAsString(key); - else return EMPTY; -} - -size_t MessageMap::size() -{ - return messages.size(); -} - -bool MessageMap::empty() -{ - return messages.empty(); -} - -void MessageMap::reinsert(const QueuedMessage& message) -{ - std::string key = getKey(message); - Index::iterator i = index.find(key); - if (i == index.end()) { - index[key] = message; - messages[message.position] = message; - } //else message has already been replaced -} - -bool MessageMap::remove(const framing::SequenceNumber& position, QueuedMessage& message) -{ - Ordering::iterator i = messages.find(position); - if (i != messages.end()) { - message = i->second; - erase(i); - return true; - } else { - return false; - } -} - -bool MessageMap::find(const framing::SequenceNumber& position, QueuedMessage& message) -{ - Ordering::iterator i = messages.find(position); - if (i != messages.end()) { - message = i->second; - return true; - } else { - return false; - } -} - -bool MessageMap::next(const framing::SequenceNumber& position, QueuedMessage& message) -{ - if (!messages.empty() && position < front().position) { - message = front(); - return true; - } else { - Ordering::iterator i = messages.lower_bound(position+1); - if (i != messages.end()) { - message = i->second; - return true; - } else { - return false; - } - } -} - -QueuedMessage& MessageMap::front() -{ - return messages.begin()->second; -} - -void MessageMap::pop() -{ - QueuedMessage dummy; - pop(dummy); -} - -bool MessageMap::pop(QueuedMessage& out) -{ - Ordering::iterator i = messages.begin(); - if (i != messages.end()) { - out = i->second; - erase(i); - return true; - } else { - return false; - } -} - -const QueuedMessage& MessageMap::replace(const QueuedMessage& original, const QueuedMessage& update) -{ - messages.erase(original.position); - messages[update.position] = update; - return update; -} - -bool MessageMap::push(const QueuedMessage& added, QueuedMessage& removed) -{ - std::pair<Index::iterator, bool> result = index.insert(Index::value_type(getKey(added), added)); - if (result.second) { - //there was no previous message for this key; nothing needs to - //be removed, just add the message into its correct position - messages[added.position] = added; - return false; - } else { - //there is already a message with that key which needs to be replaced - removed = result.first->second; - result.first->second = replace(result.first->second, added); - return true; - } -} - -void MessageMap::foreach(Functor f) -{ - for (Ordering::iterator i = messages.begin(); i != messages.end(); ++i) { - f(i->second); - } -} - -void MessageMap::removeIf(Predicate p) -{ - for (Ordering::iterator i = messages.begin(); i != messages.end(); i++) { - if (p(i->second)) { - erase(i); - } - } -} - -void MessageMap::erase(Ordering::iterator i) -{ - index.erase(getKey(i->second)); - messages.erase(i); -} - -MessageMap::MessageMap(const std::string& k) : key(k) {} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/MessageMap.h b/cpp/src/qpid/broker/MessageMap.h deleted file mode 100644 index 1128a1d54a..0000000000 --- a/cpp/src/qpid/broker/MessageMap.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef QPID_BROKER_MESSAGEMAP_H -#define QPID_BROKER_MESSAGEMAP_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/Messages.h" -#include "qpid/framing/SequenceNumber.h" -#include <map> -#include <string> - -namespace qpid { -namespace broker { - -/** - * Provides a last value queue behaviour, whereby a messages replace - * any previous message with the same value for a defined property - * (i.e. the key). - */ -class MessageMap : public Messages -{ - public: - MessageMap(const std::string& key); - virtual ~MessageMap() {} - - size_t size(); - bool empty(); - - void reinsert(const QueuedMessage&); - virtual bool remove(const framing::SequenceNumber&, QueuedMessage&); - bool find(const framing::SequenceNumber&, QueuedMessage&); - virtual bool next(const framing::SequenceNumber&, QueuedMessage&); - - QueuedMessage& front(); - void pop(); - bool pop(QueuedMessage&); - virtual bool push(const QueuedMessage& added, QueuedMessage& removed); - - void foreach(Functor); - virtual void removeIf(Predicate); - - protected: - typedef std::map<std::string, QueuedMessage> Index; - typedef std::map<framing::SequenceNumber, QueuedMessage> Ordering; - const std::string key; - Index index; - Ordering messages; - - std::string getKey(const QueuedMessage&); - virtual const QueuedMessage& replace(const QueuedMessage&, const QueuedMessage&); - void erase(Ordering::iterator); -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_MESSAGEMAP_H*/ diff --git a/cpp/src/qpid/broker/MessageStore.h b/cpp/src/qpid/broker/MessageStore.h deleted file mode 100644 index ab0225ef6b..0000000000 --- a/cpp/src/qpid/broker/MessageStore.h +++ /dev/null @@ -1,205 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _MessageStore_ -#define _MessageStore_ - -#include "qpid/broker/PersistableExchange.h" -#include "qpid/broker/PersistableMessage.h" -#include "qpid/broker/PersistableQueue.h" -#include "qpid/broker/PersistableConfig.h" -#include "qpid/broker/RecoveryManager.h" -#include "qpid/broker/TransactionalStore.h" -#include "qpid/framing/FieldTable.h" - -#include <qpid/Options.h> - -#include <boost/shared_ptr.hpp> -#include <boost/intrusive_ptr.hpp> - -namespace qpid { -namespace broker { - -/** - * An abstraction of the persistent storage for messages. (In - * all methods, any pointers/references to queues or messages - * are valid only for the duration of the call). - */ -class MessageStore : public TransactionalStore, public Recoverable { - public: - - /** - * If called after initialization but before recovery, will discard the database - * content and reinitialize as though it were a new installation. If the parameter - * saveStoreContent is true, the content of the store will be saved in such a way - * that the truncate can be reversed. This is used when cluster nodes recover and - * must get their content from a cluster sync rather than directly from the store. - * - * @param saveStoreContent If true, will move content of the store to a backup - * location where they may be restored later if needed. It is - * not necessary to save more than one prior version of the - * store. - */ - virtual void truncateInit(const bool saveStoreContent = false) = 0; - - /** - * Record the existence of a durable queue - */ - virtual void create(PersistableQueue& queue, - const framing::FieldTable& args) = 0; - /** - * Destroy a durable queue - */ - virtual void destroy(PersistableQueue& queue) = 0; - - /** - * Record the existence of a durable exchange - */ - virtual void create(const PersistableExchange& exchange, - const framing::FieldTable& args) = 0; - /** - * Destroy a durable exchange - */ - virtual void destroy(const PersistableExchange& exchange) = 0; - - /** - * Record a binding - */ - virtual void bind(const PersistableExchange& exchange, const PersistableQueue& queue, - const std::string& key, const framing::FieldTable& args) = 0; - - /** - * Forget a binding - */ - virtual void unbind(const PersistableExchange& exchange, const PersistableQueue& queue, - const std::string& key, const framing::FieldTable& args) = 0; - - /** - * Record generic durable configuration - */ - virtual void create(const PersistableConfig& config) = 0; - - /** - * Destroy generic durable configuration - */ - virtual void destroy(const PersistableConfig& config) = 0; - - /** - * Stores a messages before it has been enqueued - * (enqueueing automatically stores the message so this is - * only required if storage is required prior to that - * point). If the message has not yet been stored it will - * store the headers as well as any content passed in. A - * persistence id will be set on the message which can be - * used to load the content or to append to it. - */ - virtual void stage(const boost::intrusive_ptr<PersistableMessage>& msg) = 0; - - /** - * Destroys a previously staged message. This only needs - * to be called if the message is never enqueued. (Once - * enqueued, deletion will be automatic when the message - * is dequeued from all queues it was enqueued onto). - */ - virtual void destroy(PersistableMessage& msg) = 0; - - /** - * Appends content to a previously staged message - */ - virtual void appendContent(const boost::intrusive_ptr<const PersistableMessage>& msg, - const std::string& data) = 0; - - /** - * Loads (a section) of content data for the specified - * message (previously stored through a call to stage or - * enqueue) into data. The offset refers to the content - * only (i.e. an offset of 0 implies that the start of the - * content should be loaded, not the headers or related - * meta-data). - */ - virtual void loadContent(const qpid::broker::PersistableQueue& queue, - const boost::intrusive_ptr<const PersistableMessage>& msg, - std::string& data, uint64_t offset, uint32_t length) = 0; - - /** - * Enqueues a message, storing the message if it has not - * been previously stored and recording that the given - * message is on the given queue. - * - * Note: that this is async so the return of the function does - * not mean the opperation is complete. - * - * @param msg the message to enqueue - * @param queue the name of the queue onto which it is to be enqueued - * @param xid (a pointer to) an identifier of the - * distributed transaction in which the operation takes - * place or null for 'local' transactions - */ - virtual void enqueue(TransactionContext* ctxt, - const boost::intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue& queue) = 0; - - /** - * Dequeues a message, recording that the given message is - * no longer on the given queue and deleting the message - * if it is no longer on any other queue. - * - * Note: that this is async so the return of the function does - * not mean the opperation is complete. - * - * @param msg the message to dequeue - * @param queue the name of the queue from which it is to be dequeued - * @param xid (a pointer to) an identifier of the - * distributed transaction in which the operation takes - * place or null for 'local' transactions - */ - virtual void dequeue(TransactionContext* ctxt, - const boost::intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue& queue) = 0; - - /** - * Flushes all async messages to disk for the specified queue - * - * Note: that this is async so the return of the function does - * not mean the opperation is complete. - * - * @param queue the name of the queue from which it is to be dequeued - */ - virtual void flush(const qpid::broker::PersistableQueue& queue)=0; - - /** - * Returns the number of outstanding AIO's for a given queue - * - * If 0, than all the enqueue / dequeues have been stored - * to disk - * - * @param queue the name of the queue to check for outstanding AIO - */ - virtual uint32_t outstandingQueueAIO(const PersistableQueue& queue) = 0; - - - virtual ~MessageStore(){} -}; - -} -} - - -#endif diff --git a/cpp/src/qpid/broker/MessageStoreModule.cpp b/cpp/src/qpid/broker/MessageStoreModule.cpp deleted file mode 100644 index cd9fd4c933..0000000000 --- a/cpp/src/qpid/broker/MessageStoreModule.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/MessageStoreModule.h" -#include "qpid/broker/NullMessageStore.h" -#include <iostream> - -// This transfer protects against the unloading of the store lib prior to the handling of the exception -#define TRANSFER_EXCEPTION(fn) try { fn; } catch (std::exception& e) { throw Exception(e.what()); } - -using boost::intrusive_ptr; -using qpid::framing::FieldTable; -using std::string; - -namespace qpid { -namespace broker { - -MessageStoreModule::MessageStoreModule(boost::shared_ptr<MessageStore>& _store) - : store(_store) {} - -MessageStoreModule::~MessageStoreModule() -{ -} - -bool MessageStoreModule::init(const Options*) { return true; } - -void MessageStoreModule::truncateInit(const bool pushDownStoreFiles) -{ - TRANSFER_EXCEPTION(store->truncateInit(pushDownStoreFiles)); -} - -void MessageStoreModule::create(PersistableQueue& queue, const FieldTable& args) -{ - TRANSFER_EXCEPTION(store->create(queue, args)); -} - -void MessageStoreModule::destroy(PersistableQueue& queue) -{ - TRANSFER_EXCEPTION(store->destroy(queue)); -} - -void MessageStoreModule::create(const PersistableExchange& exchange, const FieldTable& args) -{ - TRANSFER_EXCEPTION(store->create(exchange, args)); -} - -void MessageStoreModule::destroy(const PersistableExchange& exchange) -{ - TRANSFER_EXCEPTION(store->destroy(exchange)); -} - -void MessageStoreModule::bind(const PersistableExchange& e, const PersistableQueue& q, - const std::string& k, const framing::FieldTable& a) -{ - TRANSFER_EXCEPTION(store->bind(e, q, k, a)); -} - -void MessageStoreModule::unbind(const PersistableExchange& e, const PersistableQueue& q, - const std::string& k, const framing::FieldTable& a) -{ - TRANSFER_EXCEPTION(store->unbind(e, q, k, a)); -} - -void MessageStoreModule::create(const PersistableConfig& config) -{ - TRANSFER_EXCEPTION(store->create(config)); -} - -void MessageStoreModule::destroy(const PersistableConfig& config) -{ - TRANSFER_EXCEPTION(store->destroy(config)); -} - -void MessageStoreModule::recover(RecoveryManager& registry) -{ - TRANSFER_EXCEPTION(store->recover(registry)); -} - -void MessageStoreModule::stage(const intrusive_ptr<PersistableMessage>& msg) -{ - TRANSFER_EXCEPTION(store->stage(msg)); -} - -void MessageStoreModule::destroy(PersistableMessage& msg) -{ - TRANSFER_EXCEPTION(store->destroy(msg)); -} - -void MessageStoreModule::appendContent(const intrusive_ptr<const PersistableMessage>& msg, - const std::string& data) -{ - TRANSFER_EXCEPTION(store->appendContent(msg, data)); -} - -void MessageStoreModule::loadContent( - const qpid::broker::PersistableQueue& queue, - const intrusive_ptr<const PersistableMessage>& msg, - string& data, uint64_t offset, uint32_t length) -{ - TRANSFER_EXCEPTION(store->loadContent(queue, msg, data, offset, length)); -} - -void MessageStoreModule::enqueue(TransactionContext* ctxt, - const intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue& queue) -{ - TRANSFER_EXCEPTION(store->enqueue(ctxt, msg, queue)); -} - -void MessageStoreModule::dequeue(TransactionContext* ctxt, - const intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue& queue) -{ - TRANSFER_EXCEPTION(store->dequeue(ctxt, msg, queue)); -} - -void MessageStoreModule::flush(const qpid::broker::PersistableQueue& queue) -{ - TRANSFER_EXCEPTION(store->flush(queue)); -} - -uint32_t MessageStoreModule::outstandingQueueAIO(const PersistableQueue& queue) -{ - TRANSFER_EXCEPTION(return store->outstandingQueueAIO(queue)); -} - -std::auto_ptr<TransactionContext> MessageStoreModule::begin() -{ - TRANSFER_EXCEPTION(return store->begin()); -} - -std::auto_ptr<TPCTransactionContext> MessageStoreModule::begin(const std::string& xid) -{ - TRANSFER_EXCEPTION(return store->begin(xid)); -} - -void MessageStoreModule::prepare(TPCTransactionContext& txn) -{ - TRANSFER_EXCEPTION(store->prepare(txn)); -} - -void MessageStoreModule::commit(TransactionContext& ctxt) -{ - TRANSFER_EXCEPTION(store->commit(ctxt)); -} - -void MessageStoreModule::abort(TransactionContext& ctxt) -{ - TRANSFER_EXCEPTION(store->abort(ctxt)); -} - -void MessageStoreModule::collectPreparedXids(std::set<std::string>& xids) -{ - TRANSFER_EXCEPTION(store->collectPreparedXids(xids)); -} - -bool MessageStoreModule::isNull() const -{ - return NullMessageStore::isNullStore(store.get()); -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/MessageStoreModule.h b/cpp/src/qpid/broker/MessageStoreModule.h deleted file mode 100644 index 56b5a3c1ae..0000000000 --- a/cpp/src/qpid/broker/MessageStoreModule.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _MessageStoreModule_ -#define _MessageStoreModule_ - -#include "qpid/broker/MessageStore.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/RecoveryManager.h" - -#include <boost/intrusive_ptr.hpp> -#include <boost/shared_ptr.hpp> - -namespace qpid { -namespace broker { - -/** - * A null implementation of the MessageStore interface - */ -class MessageStoreModule : public MessageStore -{ - boost::shared_ptr<MessageStore> store; - public: - MessageStoreModule(boost::shared_ptr<MessageStore>& store); - - bool init(const Options* options); - void truncateInit(const bool pushDownStoreFiles = false); - std::auto_ptr<TransactionContext> begin(); - std::auto_ptr<TPCTransactionContext> begin(const std::string& xid); - void prepare(TPCTransactionContext& txn); - void commit(TransactionContext& txn); - void abort(TransactionContext& txn); - void collectPreparedXids(std::set<std::string>& xids); - - void create(PersistableQueue& queue, const framing::FieldTable& args); - void destroy(PersistableQueue& queue); - void create(const PersistableExchange& exchange, const framing::FieldTable& args); - void destroy(const PersistableExchange& exchange); - void bind(const PersistableExchange& exchange, const PersistableQueue& queue, - const std::string& key, const framing::FieldTable& args); - void unbind(const PersistableExchange& exchange, const PersistableQueue& queue, - const std::string& key, const framing::FieldTable& args); - void create(const PersistableConfig& config); - void destroy(const PersistableConfig& config); - void recover(RecoveryManager& queues); - void stage(const boost::intrusive_ptr<PersistableMessage>& msg); - void destroy(PersistableMessage& msg); - void appendContent(const boost::intrusive_ptr<const PersistableMessage>& msg, const std::string& data); - void loadContent(const qpid::broker::PersistableQueue& queue, - const boost::intrusive_ptr<const PersistableMessage>& msg, std::string& data, - uint64_t offset, uint32_t length); - - void enqueue(TransactionContext* ctxt, - const boost::intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue& queue); - void dequeue(TransactionContext* ctxt, - const boost::intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue& queue); - uint32_t outstandingQueueAIO(const PersistableQueue& queue); - void flush(const qpid::broker::PersistableQueue& queue); - bool isNull() const; - - ~MessageStoreModule(); -}; - -} -} - - -#endif diff --git a/cpp/src/qpid/broker/Messages.h b/cpp/src/qpid/broker/Messages.h deleted file mode 100644 index 0d75417640..0000000000 --- a/cpp/src/qpid/broker/Messages.h +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef QPID_BROKER_MESSAGES_H -#define QPID_BROKER_MESSAGES_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include <boost/function.hpp> - -namespace qpid { -namespace framing { -class SequenceNumber; -} -namespace broker { -struct QueuedMessage; - -/** - * This interface abstracts out the access to the messages held for - * delivery by a Queue instance. - */ -class Messages -{ - public: - typedef boost::function1<void, QueuedMessage&> Functor; - typedef boost::function1<bool, QueuedMessage&> Predicate; - - virtual ~Messages() {} - /** - * @return the number of messages available for delivery. - */ - virtual size_t size() = 0; - /** - * @return true if there are no messages for delivery, false otherwise - */ - virtual bool empty() = 0; - - /** - * Re-inserts a message back into its original position - used - * when requeing released messages. - */ - virtual void reinsert(const QueuedMessage&) = 0; - /** - * Remove the message at the specified position, returning true if - * found, false otherwise. The removed message is passed back via - * the second parameter. - */ - virtual bool remove(const framing::SequenceNumber&, QueuedMessage&) = 0; - /** - * Find the message at the specified position, returning true if - * found, false otherwise. The matched message is passed back via - * the second parameter. - */ - virtual bool find(const framing::SequenceNumber&, QueuedMessage&) = 0; - /** - * Return the next message to be given to a browsing subscrption - * that has reached the specified poisition. The next messages is - * passed back via the second parameter. - * - * @return true if there is another message, false otherwise. - */ - virtual bool next(const framing::SequenceNumber&, QueuedMessage&) = 0; - - /** - * Note: Caller is responsible for ensuring that there is a front - * (e.g. empty() returns false) - * - * @return the next message to be delivered - */ - virtual QueuedMessage& front() = 0; - /** - * Removes the front message - */ - virtual void pop() = 0; - /** - * @return true if there is a mesage to be delivered - in which - * case that message will be returned via the parameter and - * removed - otherwise false. - */ - virtual bool pop(QueuedMessage&) = 0; - /** - * Pushes a message to the back of the 'queue'. For some types of - * queue this may cause another message to be removed; if that is - * the case the method will return true and the removed message - * will be passed out via the second parameter. - */ - virtual bool push(const QueuedMessage& added, QueuedMessage& removed) = 0; - - /** - * Apply the functor to each message held - */ - virtual void foreach(Functor) = 0; - /** - * Remove every message held that for which the specified - * predicate returns true - */ - virtual void removeIf(Predicate) = 0; - private: -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_MESSAGES_H*/ diff --git a/cpp/src/qpid/broker/NameGenerator.cpp b/cpp/src/qpid/broker/NameGenerator.cpp deleted file mode 100644 index e7f193d546..0000000000 --- a/cpp/src/qpid/broker/NameGenerator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/NameGenerator.h" -#include <sstream> - -using namespace qpid::broker; - -NameGenerator::NameGenerator(const std::string& _base) : base(_base), counter(1) {} - -std::string NameGenerator::generate(){ - std::stringstream ss; - ss << base << counter++; - return ss.str(); -} diff --git a/cpp/src/qpid/broker/NameGenerator.h b/cpp/src/qpid/broker/NameGenerator.h deleted file mode 100644 index 6ea25c9797..0000000000 --- a/cpp/src/qpid/broker/NameGenerator.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _NameGenerator_ -#define _NameGenerator_ - -#include <string> - -namespace qpid { - namespace broker { - class NameGenerator{ - const std::string base; - unsigned int counter; - public: - NameGenerator(const std::string& base); - std::string generate(); - }; - } -} - - -#endif diff --git a/cpp/src/qpid/broker/NullMessageStore.cpp b/cpp/src/qpid/broker/NullMessageStore.cpp deleted file mode 100644 index 43f600eaf1..0000000000 --- a/cpp/src/qpid/broker/NullMessageStore.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/NullMessageStore.h" -#include "qpid/broker/MessageStoreModule.h" -#include "qpid/broker/RecoveryManager.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/reply_exceptions.h" - -#include <iostream> - -using boost::intrusive_ptr; - -namespace qpid{ -namespace broker{ - -const std::string nullxid = ""; - -class SimpleDummyCtxt : public TransactionContext {}; - -class DummyCtxt : public TPCTransactionContext -{ - const std::string xid; -public: - DummyCtxt(const std::string& _xid) : xid(_xid) {} - static std::string getXid(TransactionContext& ctxt) - { - DummyCtxt* c(dynamic_cast<DummyCtxt*>(&ctxt)); - return c ? c->xid : nullxid; - } -}; - -NullMessageStore::NullMessageStore() : nextPersistenceId(1) {} - -bool NullMessageStore::init(const Options* /*options*/) {return true;} - -void NullMessageStore::truncateInit(const bool /*pushDownStoreFiles*/) {} - -void NullMessageStore::create(PersistableQueue& queue, const framing::FieldTable& /*args*/) -{ - queue.setPersistenceId(nextPersistenceId++); -} - -void NullMessageStore::destroy(PersistableQueue&) {} - -void NullMessageStore::create(const PersistableExchange& exchange, const framing::FieldTable& /*args*/) -{ - exchange.setPersistenceId(nextPersistenceId++); -} - -void NullMessageStore::destroy(const PersistableExchange& ) {} - -void NullMessageStore::bind(const PersistableExchange&, const PersistableQueue&, const std::string&, const framing::FieldTable&){} - -void NullMessageStore::unbind(const PersistableExchange&, const PersistableQueue&, const std::string&, const framing::FieldTable&){} - -void NullMessageStore::create(const PersistableConfig& config) -{ - config.setPersistenceId(nextPersistenceId++); -} - -void NullMessageStore::destroy(const PersistableConfig&) {} - -void NullMessageStore::recover(RecoveryManager&) {} - -void NullMessageStore::stage(const intrusive_ptr<PersistableMessage>&) {} - -void NullMessageStore::destroy(PersistableMessage&) {} - -void NullMessageStore::appendContent(const intrusive_ptr<const PersistableMessage>&, const std::string&) {} - -void NullMessageStore::loadContent(const qpid::broker::PersistableQueue&, - const intrusive_ptr<const PersistableMessage>&, - std::string&, uint64_t, uint32_t) -{ - throw qpid::framing::InternalErrorException("Can't load content; persistence not enabled"); -} - -void NullMessageStore::enqueue(TransactionContext*, - const intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue&) -{ - msg->enqueueComplete(); -} - -void NullMessageStore::dequeue(TransactionContext*, - const intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue&) -{ - msg->dequeueComplete(); -} - -void NullMessageStore::flush(const qpid::broker::PersistableQueue&) {} - -uint32_t NullMessageStore::outstandingQueueAIO(const PersistableQueue& ) { - return 0; -} - -std::auto_ptr<TransactionContext> NullMessageStore::begin() -{ - return std::auto_ptr<TransactionContext>(new SimpleDummyCtxt()); -} - -std::auto_ptr<TPCTransactionContext> NullMessageStore::begin(const std::string& xid) -{ - return std::auto_ptr<TPCTransactionContext>(new DummyCtxt(xid)); -} - -void NullMessageStore::prepare(TPCTransactionContext& ctxt) -{ - qpid::sys::ScopedLock<qpid::sys::Mutex> l(lock); - prepared.insert(DummyCtxt::getXid(ctxt)); -} - -void NullMessageStore::commit(TransactionContext& ctxt) -{ - qpid::sys::ScopedLock<qpid::sys::Mutex> l(lock); - prepared.erase(DummyCtxt::getXid(ctxt)); -} - -void NullMessageStore::abort(TransactionContext& ctxt) -{ - qpid::sys::ScopedLock<qpid::sys::Mutex> l(lock); - prepared.erase(DummyCtxt::getXid(ctxt)); -} - -void NullMessageStore::collectPreparedXids(std::set<std::string>& out) -{ - qpid::sys::ScopedLock<qpid::sys::Mutex> l(lock); - out.insert(prepared.begin(), prepared.end()); -} - -bool NullMessageStore::isNull() const -{ - return true; -} - -bool NullMessageStore::isNullStore(const MessageStore* store) -{ - const MessageStoreModule* wrapper = dynamic_cast<const MessageStoreModule*>(store); - if (wrapper) { - return wrapper->isNull(); - } else { - const NullMessageStore* test = dynamic_cast<const NullMessageStore*>(store); - return test && test->isNull(); - } -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/NullMessageStore.h b/cpp/src/qpid/broker/NullMessageStore.h deleted file mode 100644 index c6f402662e..0000000000 --- a/cpp/src/qpid/broker/NullMessageStore.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _NullMessageStore_ -#define _NullMessageStore_ - -#include <set> -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/MessageStore.h" -#include "qpid/broker/Queue.h" -#include "qpid/sys/Mutex.h" - -#include <boost/intrusive_ptr.hpp> - -namespace qpid { -namespace broker { - -/** - * A null implementation of the MessageStore interface - */ -class QPID_BROKER_CLASS_EXTERN NullMessageStore : public MessageStore -{ - std::set<std::string> prepared; - uint64_t nextPersistenceId; - qpid::sys::Mutex lock; - public: - QPID_BROKER_EXTERN NullMessageStore(); - - QPID_BROKER_EXTERN virtual bool init(const Options* options); - QPID_BROKER_EXTERN virtual void truncateInit(const bool pushDownStoreFiles = false); - QPID_BROKER_EXTERN virtual std::auto_ptr<TransactionContext> begin(); - QPID_BROKER_EXTERN virtual std::auto_ptr<TPCTransactionContext> begin(const std::string& xid); - QPID_BROKER_EXTERN virtual void prepare(TPCTransactionContext& txn); - QPID_BROKER_EXTERN virtual void commit(TransactionContext& txn); - QPID_BROKER_EXTERN virtual void abort(TransactionContext& txn); - QPID_BROKER_EXTERN virtual void collectPreparedXids(std::set<std::string>& xids); - - QPID_BROKER_EXTERN virtual void create(PersistableQueue& queue, - const framing::FieldTable& args); - QPID_BROKER_EXTERN virtual void destroy(PersistableQueue& queue); - QPID_BROKER_EXTERN virtual void create(const PersistableExchange& exchange, - const framing::FieldTable& args); - QPID_BROKER_EXTERN virtual void destroy(const PersistableExchange& exchange); - - QPID_BROKER_EXTERN virtual void bind(const PersistableExchange& exchange, - const PersistableQueue& queue, - const std::string& key, - const framing::FieldTable& args); - QPID_BROKER_EXTERN virtual void unbind(const PersistableExchange& exchange, - const PersistableQueue& queue, - const std::string& key, - const framing::FieldTable& args); - QPID_BROKER_EXTERN virtual void create(const PersistableConfig& config); - QPID_BROKER_EXTERN virtual void destroy(const PersistableConfig& config); - QPID_BROKER_EXTERN virtual void recover(RecoveryManager& queues); - QPID_BROKER_EXTERN virtual void stage(const boost::intrusive_ptr<PersistableMessage>& msg); - QPID_BROKER_EXTERN virtual void destroy(PersistableMessage& msg); - QPID_BROKER_EXTERN virtual void appendContent(const boost::intrusive_ptr<const PersistableMessage>& msg, - const std::string& data); - QPID_BROKER_EXTERN virtual void loadContent(const qpid::broker::PersistableQueue& queue, - const boost::intrusive_ptr<const PersistableMessage>& msg, - std::string& data, - uint64_t offset, - uint32_t length); - QPID_BROKER_EXTERN virtual void enqueue(TransactionContext* ctxt, - const boost::intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue& queue); - QPID_BROKER_EXTERN virtual void dequeue(TransactionContext* ctxt, - const boost::intrusive_ptr<PersistableMessage>& msg, - const PersistableQueue& queue); - QPID_BROKER_EXTERN virtual uint32_t outstandingQueueAIO(const PersistableQueue& queue); - QPID_BROKER_EXTERN virtual void flush(const qpid::broker::PersistableQueue& queue); - ~NullMessageStore(){} - - QPID_BROKER_EXTERN virtual bool isNull() const; - static bool isNullStore(const MessageStore*); -}; - -} -} - - -#endif diff --git a/cpp/src/qpid/broker/OwnershipToken.h b/cpp/src/qpid/broker/OwnershipToken.h deleted file mode 100644 index effd2f5b3c..0000000000 --- a/cpp/src/qpid/broker/OwnershipToken.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _OwnershipToken_ -#define _OwnershipToken_ - -namespace qpid { -namespace broker { - -class ConnectionToken; - -class OwnershipToken{ -public: - virtual bool isLocal(const ConnectionToken* t) const = 0; - virtual ~OwnershipToken(){} -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/Persistable.h b/cpp/src/qpid/broker/Persistable.h deleted file mode 100644 index 36499c7a1a..0000000000 --- a/cpp/src/qpid/broker/Persistable.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef _broker_Persistable_h -#define _broker_Persistable_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/framing/amqp_types.h" -#include "qpid/framing/Buffer.h" -#include "qpid/RefCounted.h" - -namespace qpid { -namespace broker { - -/** - * Base class for all persistable objects - */ -class Persistable : public RefCounted -{ -public: - /** - * Allows the store to attach its own identifier to this object - */ - virtual void setPersistenceId(uint64_t id) const = 0; - /** - * Returns any identifier the store may have attached to this - * object - */ - virtual uint64_t getPersistenceId() const = 0; - /** - * Encodes the persistable state of this object into the supplied - * buffer - */ - virtual void encode(framing::Buffer& buffer) const = 0; - /** - * @returns the size of the buffer needed to encode this object - */ - virtual uint32_t encodedSize() const = 0; - - virtual ~Persistable() {}; -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/PersistableConfig.h b/cpp/src/qpid/broker/PersistableConfig.h deleted file mode 100644 index 8ddb84d129..0000000000 --- a/cpp/src/qpid/broker/PersistableConfig.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef _broker_PersistableConfig_h -#define _broker_PersistableConfig_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <string> -#include "qpid/broker/Persistable.h" - -namespace qpid { -namespace broker { - -/** - * The interface used by general-purpose persistable configuration for - * the message store. - */ -class PersistableConfig : public Persistable -{ -public: - virtual const std::string& getName() const = 0; - virtual ~PersistableConfig() {}; -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/PersistableExchange.h b/cpp/src/qpid/broker/PersistableExchange.h deleted file mode 100644 index e1a0853247..0000000000 --- a/cpp/src/qpid/broker/PersistableExchange.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef _broker_PersistableExchange_h -#define _broker_PersistableExchange_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <string> -#include "qpid/broker/Persistable.h" - -namespace qpid { -namespace broker { - -/** - * The interface exchanges must expose to the MessageStore in order to be - * persistable. - */ -class PersistableExchange : public Persistable -{ -public: - virtual const std::string& getName() const = 0; - virtual ~PersistableExchange() {}; -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/PersistableMessage.cpp b/cpp/src/qpid/broker/PersistableMessage.cpp deleted file mode 100644 index 7ba28eb293..0000000000 --- a/cpp/src/qpid/broker/PersistableMessage.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - - -#include "qpid/broker/PersistableMessage.h" -#include "qpid/broker/MessageStore.h" -#include <iostream> - -using namespace qpid::broker; - -namespace qpid { -namespace broker { - -class MessageStore; - -PersistableMessage::~PersistableMessage() {} - -PersistableMessage::PersistableMessage() : - asyncDequeueCounter(0), - store(0) -{} - -void PersistableMessage::flush() -{ - syncList copy; - { - sys::ScopedLock<sys::Mutex> l(storeLock); - if (store) { - copy = synclist; - } else { - return;//early exit as nothing to do - } - } - for (syncList::iterator i = copy.begin(); i != copy.end(); ++i) { - PersistableQueue::shared_ptr q(i->lock()); - if (q) { - q->flush(); - } - } -} - -void PersistableMessage::setContentReleased() -{ - contentReleaseState.released = true; -} - -bool PersistableMessage::isContentReleased() const -{ - return contentReleaseState.released; -} - - -bool PersistableMessage::isStoredOnQueue(PersistableQueue::shared_ptr queue){ - if (store && (queue->getPersistenceId()!=0)) { - for (syncList::iterator i = synclist.begin(); i != synclist.end(); ++i) { - PersistableQueue::shared_ptr q(i->lock()); - if (q && q->getPersistenceId() == queue->getPersistenceId()) return true; - } - } - return false; -} - - -void PersistableMessage::addToSyncList(PersistableQueue::shared_ptr queue, MessageStore* _store) { - if (_store){ - sys::ScopedLock<sys::Mutex> l(storeLock); - store = _store; - boost::weak_ptr<PersistableQueue> q(queue); - synclist.push_back(q); - } -} - -void PersistableMessage::enqueueAsync(PersistableQueue::shared_ptr queue, MessageStore* _store) { - addToSyncList(queue, _store); - enqueueStart(); -} - -bool PersistableMessage::isDequeueComplete() { - sys::ScopedLock<sys::Mutex> l(asyncDequeueLock); - return asyncDequeueCounter == 0; -} - -void PersistableMessage::dequeueComplete() { - bool notify = false; - { - sys::ScopedLock<sys::Mutex> l(asyncDequeueLock); - if (asyncDequeueCounter > 0) { - if (--asyncDequeueCounter == 0) { - notify = true; - } - } - } - if (notify) allDequeuesComplete(); -} - -void PersistableMessage::dequeueAsync(PersistableQueue::shared_ptr queue, MessageStore* _store) { - if (_store){ - sys::ScopedLock<sys::Mutex> l(storeLock); - store = _store; - boost::weak_ptr<PersistableQueue> q(queue); - synclist.push_back(q); - } - dequeueAsync(); -} - -void PersistableMessage::dequeueAsync() { - sys::ScopedLock<sys::Mutex> l(asyncDequeueLock); - asyncDequeueCounter++; -} - -PersistableMessage::ContentReleaseState::ContentReleaseState() : blocked(false), requested(false), released(false) {} - -void PersistableMessage::setStore(MessageStore* s) -{ - store = s; -} - -void PersistableMessage::requestContentRelease() -{ - contentReleaseState.requested = true; -} -void PersistableMessage::blockContentRelease() -{ - contentReleaseState.blocked = true; -} -bool PersistableMessage::checkContentReleasable() -{ - return contentReleaseState.requested && !contentReleaseState.blocked; -} - -bool PersistableMessage::isContentReleaseBlocked() -{ - return contentReleaseState.blocked; -} - -bool PersistableMessage::isContentReleaseRequested() -{ - return contentReleaseState.requested; -} - -}} - - diff --git a/cpp/src/qpid/broker/PersistableMessage.h b/cpp/src/qpid/broker/PersistableMessage.h deleted file mode 100644 index d29c2c45b4..0000000000 --- a/cpp/src/qpid/broker/PersistableMessage.h +++ /dev/null @@ -1,143 +0,0 @@ -#ifndef _broker_PersistableMessage_h -#define _broker_PersistableMessage_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <string> -#include <list> -#include <boost/shared_ptr.hpp> -#include <boost/weak_ptr.hpp> -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/Persistable.h" -#include "qpid/framing/amqp_types.h" -#include "qpid/sys/Mutex.h" -#include "qpid/broker/PersistableQueue.h" -#include "qpid/broker/AsyncCompletion.h" - -namespace qpid { -namespace broker { - -class MessageStore; - -/** - * Base class for persistable messages. - */ -class PersistableMessage : public Persistable -{ - typedef std::list< boost::weak_ptr<PersistableQueue> > syncList; - sys::Mutex asyncDequeueLock; - sys::Mutex storeLock; - - /** - * "Ingress" messages == messages sent _to_ the broker. - * Tracks the number of outstanding asynchronous operations that must - * complete before an inbound message can be considered fully received by the - * broker. E.g. all enqueues have completed, the message has been written - * to store, credit has been replenished, etc. Once all outstanding - * operations have completed, the transfer of this message from the client - * may be considered complete. - */ - AsyncCompletion ingressCompletion; - - /** - * Tracks the number of outstanding asynchronous dequeue - * operations. When the message is dequeued asynchronously the - * count is incremented; when that dequeue completes it is - * decremented. Thus when it is 0, there are no outstanding - * dequeues. - */ - int asyncDequeueCounter; - - void dequeueAsync(); - - syncList synclist; - struct ContentReleaseState - { - bool blocked; - bool requested; - bool released; - - ContentReleaseState(); - }; - ContentReleaseState contentReleaseState; - - protected: - /** Called when all dequeues are complete for this message. */ - virtual void allDequeuesComplete() = 0; - - void setContentReleased(); - - MessageStore* store; - - - public: - typedef boost::shared_ptr<PersistableMessage> shared_ptr; - - /** - * @returns the size of the headers when encoded - */ - virtual uint32_t encodedHeaderSize() const = 0; - - virtual ~PersistableMessage(); - - PersistableMessage(); - - void flush(); - - QPID_BROKER_EXTERN bool isContentReleased() const; - - QPID_BROKER_EXTERN void setStore(MessageStore*); - void requestContentRelease(); - void blockContentRelease(); - bool checkContentReleasable(); - bool isContentReleaseBlocked(); - bool isContentReleaseRequested(); - - virtual QPID_BROKER_EXTERN bool isPersistent() const = 0; - - /** track the progress of a message received by the broker - see ingressCompletion above */ - QPID_BROKER_INLINE_EXTERN bool isIngressComplete() { return ingressCompletion.isDone(); } - QPID_BROKER_INLINE_EXTERN AsyncCompletion& getIngressCompletion() { return ingressCompletion; } - - QPID_BROKER_INLINE_EXTERN void enqueueStart() { ingressCompletion.startCompleter(); } - QPID_BROKER_INLINE_EXTERN void enqueueComplete() { ingressCompletion.finishCompleter(); } - - QPID_BROKER_EXTERN void enqueueAsync(PersistableQueue::shared_ptr queue, - MessageStore* _store); - - - QPID_BROKER_EXTERN bool isDequeueComplete(); - - QPID_BROKER_EXTERN void dequeueComplete(); - - QPID_BROKER_EXTERN void dequeueAsync(PersistableQueue::shared_ptr queue, - MessageStore* _store); - - bool isStoredOnQueue(PersistableQueue::shared_ptr queue); - - void addToSyncList(PersistableQueue::shared_ptr queue, MessageStore* _store); -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/PersistableQueue.h b/cpp/src/qpid/broker/PersistableQueue.h deleted file mode 100644 index 655d26bc74..0000000000 --- a/cpp/src/qpid/broker/PersistableQueue.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef _broker_PersistableQueue_h -#define _broker_PersistableQueue_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <string> -#include "qpid/broker/Persistable.h" -#include "qpid/management/Manageable.h" -#include <boost/shared_ptr.hpp> - -namespace qpid { -namespace broker { - - -/** -* Empty class to be used by any module that wanted to set an external per queue store into -* persistableQueue -*/ - -class ExternalQueueStore : public management::Manageable -{ -public: - virtual ~ExternalQueueStore() {}; - -}; - - -/** - * The interface queues must expose to the MessageStore in order to be - * persistable. - */ -class PersistableQueue : public Persistable -{ -public: - typedef boost::shared_ptr<PersistableQueue> shared_ptr; - - virtual const std::string& getName() const = 0; - virtual ~PersistableQueue() { - if (externalQueueStore) - delete externalQueueStore; - }; - - virtual void setExternalQueueStore(ExternalQueueStore* inst) = 0; - virtual void flush() = 0; - - inline ExternalQueueStore* getExternalQueueStore() const {return externalQueueStore;}; - - PersistableQueue():externalQueueStore(NULL){ - }; - -protected: - ExternalQueueStore* externalQueueStore; - -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/PriorityQueue.cpp b/cpp/src/qpid/broker/PriorityQueue.cpp deleted file mode 100644 index e07e73d323..0000000000 --- a/cpp/src/qpid/broker/PriorityQueue.cpp +++ /dev/null @@ -1,212 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/PriorityQueue.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/QueuedMessage.h" -#include "qpid/framing/reply_exceptions.h" -#include <cmath> - -namespace qpid { -namespace broker { - -PriorityQueue::PriorityQueue(int l) : - levels(l), - messages(levels, Deque()), - frontLevel(0), haveFront(false), cached(false) {} - -size_t PriorityQueue::size() -{ - size_t total(0); - for (int i = 0; i < levels; ++i) { - total += messages[i].size(); - } - return total; -} - -bool PriorityQueue::empty() -{ - for (int i = 0; i < levels; ++i) { - if (!messages[i].empty()) return false; - } - return true; -} - -void PriorityQueue::reinsert(const QueuedMessage& message) -{ - uint p = getPriorityLevel(message); - messages[p].insert(lower_bound(messages[p].begin(), messages[p].end(), message), message); - clearCache(); -} - -bool PriorityQueue::find(const framing::SequenceNumber& position, QueuedMessage& message, bool remove) -{ - QueuedMessage comp; - comp.position = position; - for (int i = 0; i < levels; ++i) { - if (!messages[i].empty()) { - unsigned long diff = position.getValue() - messages[i].front().position.getValue(); - long maxEnd = diff < messages[i].size() ? diff : messages[i].size(); - Deque::iterator l = lower_bound(messages[i].begin(),messages[i].begin()+maxEnd,comp); - if (l != messages[i].end() && l->position == position) { - message = *l; - if (remove) { - messages[i].erase(l); - clearCache(); - } - return true; - } - } - } - return false; -} - -bool PriorityQueue::remove(const framing::SequenceNumber& position, QueuedMessage& message) -{ - return find(position, message, true); -} - -bool PriorityQueue::find(const framing::SequenceNumber& position, QueuedMessage& message) -{ - return find(position, message, false); -} - -bool PriorityQueue::next(const framing::SequenceNumber& position, QueuedMessage& message) -{ - QueuedMessage match; - match.position = position+1; - Deque::iterator lowest; - bool found = false; - for (int i = 0; i < levels; ++i) { - Deque::iterator m = lower_bound(messages[i].begin(), messages[i].end(), match); - if (m != messages[i].end()) { - if (m->position == match.position) { - message = *m; - return true; - } else if (!found || m->position < lowest->position) { - lowest = m; - found = true; - } - } - } - if (found) { - message = *lowest; - } - return found; -} - -QueuedMessage& PriorityQueue::front() -{ - if (checkFront()) { - return messages[frontLevel].front(); - } else { - throw qpid::framing::InternalErrorException(QPID_MSG("No message available")); - } -} - -bool PriorityQueue::pop(QueuedMessage& message) -{ - if (checkFront()) { - message = messages[frontLevel].front(); - messages[frontLevel].pop_front(); - clearCache(); - return true; - } else { - return false; - } -} - -void PriorityQueue::pop() -{ - QueuedMessage dummy; - pop(dummy); -} - -bool PriorityQueue::push(const QueuedMessage& added, QueuedMessage& /*not needed*/) -{ - messages[getPriorityLevel(added)].push_back(added); - clearCache(); - return false;//adding a message never causes one to be removed for deque -} - -void PriorityQueue::foreach(Functor f) -{ - for (int i = 0; i < levels; ++i) { - std::for_each(messages[i].begin(), messages[i].end(), f); - } -} - -void PriorityQueue::removeIf(Predicate p) -{ - for (int priority = 0; priority < levels; ++priority) { - for (Deque::iterator i = messages[priority].begin(); i != messages[priority].end();) { - if (p(*i)) { - i = messages[priority].erase(i); - clearCache(); - } else { - ++i; - } - } - } -} - -uint PriorityQueue::getPriorityLevel(const QueuedMessage& m) const -{ - uint priority = m.payload->getPriority(); - //Use AMQP 0-10 approach to mapping priorities to a fixed level - //(see rule priority-level-implementation) - const uint firstLevel = 5 - uint(std::min(5.0, std::ceil((double) levels/2.0))); - if (priority <= firstLevel) return 0; - return std::min(priority - firstLevel, (uint)levels-1); -} - -void PriorityQueue::clearCache() -{ - cached = false; -} - -bool PriorityQueue::findFrontLevel(uint& l, PriorityLevels& m) -{ - for (int p = levels-1; p >= 0; --p) { - if (!m[p].empty()) { - l = p; - return true; - } - } - return false; -} - -bool PriorityQueue::checkFront() -{ - if (!cached) { - haveFront = findFrontLevel(frontLevel, messages); - cached = true; - } - return haveFront; -} - -uint PriorityQueue::getPriority(const QueuedMessage& message) -{ - const PriorityQueue* queue = dynamic_cast<const PriorityQueue*>(&(message.queue->getMessages())); - if (queue) return queue->getPriorityLevel(message); - else return 0; -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/PriorityQueue.h b/cpp/src/qpid/broker/PriorityQueue.h deleted file mode 100644 index 4bf9d26a9d..0000000000 --- a/cpp/src/qpid/broker/PriorityQueue.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef QPID_BROKER_PRIORITYQUEUE_H -#define QPID_BROKER_PRIORITYQUEUE_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/Messages.h" -#include "qpid/sys/IntegerTypes.h" -#include <deque> -#include <vector> - -namespace qpid { -namespace broker { - -/** - * Basic priority queue with a configurable number of recognised - * priority levels. This is implemented as a separate deque per - * priority level. Browsing is FIFO not priority order. - */ -class PriorityQueue : public Messages -{ - public: - PriorityQueue(int levels); - virtual ~PriorityQueue() {} - size_t size(); - bool empty(); - - void reinsert(const QueuedMessage&); - bool remove(const framing::SequenceNumber&, QueuedMessage&); - bool find(const framing::SequenceNumber&, QueuedMessage&); - bool next(const framing::SequenceNumber&, QueuedMessage&); - - QueuedMessage& front(); - void pop(); - bool pop(QueuedMessage&); - bool push(const QueuedMessage& added, QueuedMessage& removed); - - void foreach(Functor); - void removeIf(Predicate); - static uint getPriority(const QueuedMessage&); - protected: - typedef std::deque<QueuedMessage> Deque; - typedef std::vector<Deque> PriorityLevels; - virtual bool findFrontLevel(uint& p, PriorityLevels&); - - const int levels; - private: - PriorityLevels messages; - uint frontLevel; - bool haveFront; - bool cached; - - bool find(const framing::SequenceNumber&, QueuedMessage&, bool remove); - uint getPriorityLevel(const QueuedMessage&) const; - void clearCache(); - bool checkFront(); -}; - -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_PRIORITYQUEUE_H*/ diff --git a/cpp/src/qpid/broker/Queue.cpp b/cpp/src/qpid/broker/Queue.cpp deleted file mode 100644 index 8efa8be3dc..0000000000 --- a/cpp/src/qpid/broker/Queue.cpp +++ /dev/null @@ -1,1225 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/Broker.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/QueueEvents.h" -#include "qpid/broker/Exchange.h" -#include "qpid/broker/Fairshare.h" -#include "qpid/broker/DeliverableMessage.h" -#include "qpid/broker/LegacyLVQ.h" -#include "qpid/broker/MessageDeque.h" -#include "qpid/broker/MessageMap.h" -#include "qpid/broker/MessageStore.h" -#include "qpid/broker/NullMessageStore.h" -#include "qpid/broker/QueueRegistry.h" -#include "qpid/broker/QueueFlowLimit.h" -#include "qpid/broker/ThresholdAlerts.h" - -#include "qpid/StringUtils.h" -#include "qpid/log/Statement.h" -#include "qpid/management/ManagementAgent.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/sys/ClusterSafe.h" -#include "qpid/sys/Monitor.h" -#include "qpid/sys/Time.h" -#include "qmf/org/apache/qpid/broker/ArgsQueuePurge.h" -#include "qmf/org/apache/qpid/broker/ArgsQueueReroute.h" - -#include <iostream> -#include <algorithm> -#include <functional> - -#include <boost/bind.hpp> -#include <boost/intrusive_ptr.hpp> - - -using namespace qpid::broker; -using namespace qpid::sys; -using namespace qpid::framing; -using qpid::management::ManagementAgent; -using qpid::management::ManagementObject; -using qpid::management::Manageable; -using qpid::management::Args; -using std::for_each; -using std::mem_fun; -namespace _qmf = qmf::org::apache::qpid::broker; - - -namespace -{ -const std::string qpidMaxSize("qpid.max_size"); -const std::string qpidMaxCount("qpid.max_count"); -const std::string qpidNoLocal("no-local"); -const std::string qpidTraceIdentity("qpid.trace.id"); -const std::string qpidTraceExclude("qpid.trace.exclude"); -const std::string qpidLastValueQueueKey("qpid.last_value_queue_key"); -const std::string qpidLastValueQueue("qpid.last_value_queue"); -const std::string qpidLastValueQueueNoBrowse("qpid.last_value_queue_no_browse"); -const std::string qpidPersistLastNode("qpid.persist_last_node"); -const std::string qpidVQMatchProperty("qpid.LVQ_key"); -const std::string qpidQueueEventGeneration("qpid.queue_event_generation"); -const std::string qpidAutoDeleteTimeout("qpid.auto_delete_timeout"); -//following feature is not ready for general use as it doesn't handle -//the case where a message is enqueued on more than one queue well enough: -const std::string qpidInsertSequenceNumbers("qpid.insert_sequence_numbers"); - -const int ENQUEUE_ONLY=1; -const int ENQUEUE_AND_DEQUEUE=2; -} - -Queue::Queue(const string& _name, bool _autodelete, - MessageStore* const _store, - const OwnershipToken* const _owner, - Manageable* parent, - Broker* b) : - - name(_name), - autodelete(_autodelete), - store(_store), - owner(_owner), - consumerCount(0), - exclusive(0), - noLocal(false), - persistLastNode(false), - inLastNodeFailure(false), - messages(new MessageDeque()), - persistenceId(0), - policyExceeded(false), - mgmtObject(0), - eventMode(0), - insertSeqNo(0), - broker(b), - deleted(false), - barrier(*this), - autoDeleteTimeout(0) -{ - if (parent != 0 && broker != 0) { - ManagementAgent* agent = broker->getManagementAgent(); - - if (agent != 0) { - mgmtObject = new _qmf::Queue(agent, this, parent, _name, _store != 0, _autodelete, _owner != 0); - agent->addObject(mgmtObject, 0, store != 0); - } - } -} - -Queue::~Queue() -{ - if (mgmtObject != 0) - mgmtObject->resourceDestroy(); -} - -bool isLocalTo(const OwnershipToken* token, boost::intrusive_ptr<Message>& msg) -{ - return token && token->isLocal(msg->getPublisher()); -} - -bool Queue::isLocal(boost::intrusive_ptr<Message>& msg) -{ - //message is considered local if it was published on the same - //connection as that of the session which declared this queue - //exclusive (owner) or which has an exclusive subscription - //(exclusive) - return noLocal && (isLocalTo(owner, msg) || isLocalTo(exclusive, msg)); -} - -bool Queue::isExcluded(boost::intrusive_ptr<Message>& msg) -{ - return traceExclude.size() && msg->isExcluded(traceExclude); -} - -void Queue::deliver(boost::intrusive_ptr<Message> msg){ - // Check for deferred delivery in a cluster. - if (broker && broker->deferDelivery(name, msg)) - return; - if (msg->isImmediate() && getConsumerCount() == 0) { - if (alternateExchange) { - DeliverableMessage deliverable(msg); - alternateExchange->route(deliverable, msg->getRoutingKey(), msg->getApplicationHeaders()); - } - } else if (isLocal(msg)) { - //drop message - QPID_LOG(info, "Dropping 'local' message from " << getName()); - } else if (isExcluded(msg)) { - //drop message - QPID_LOG(info, "Dropping excluded message from " << getName()); - } else { - enqueue(0, msg); - push(msg); - QPID_LOG(debug, "Message " << msg << " enqueued on " << name); - } -} - -void Queue::recoverPrepared(boost::intrusive_ptr<Message>& msg) -{ - if (policy.get()) policy->recoverEnqueued(msg); -} - -void Queue::recover(boost::intrusive_ptr<Message>& msg){ - if (policy.get()) policy->recoverEnqueued(msg); - - push(msg, true); - if (store){ - // setup synclist for recovered messages, so they don't get re-stored on lastNodeFailure - msg->addToSyncList(shared_from_this(), store); - } - - if (store && (!msg->isContentLoaded() || msg->checkContentReleasable())) { - //content has not been loaded, need to ensure that lazy loading mode is set: - //TODO: find a nicer way to do this - msg->releaseContent(store); - // NOTE: The log message in this section are used for flow-to-disk testing (which checks the log for the - // presence of this message). Do not change this without also checking these tests. - QPID_LOG(debug, "Message id=\"" << msg->getProperties<MessageProperties>()->getMessageId() << "\"; pid=0x" << - std::hex << msg->getPersistenceId() << std::dec << ": Content released after recovery"); - } -} - -void Queue::process(boost::intrusive_ptr<Message>& msg){ - push(msg); - if (mgmtObject != 0){ - mgmtObject->inc_msgTxnEnqueues (); - mgmtObject->inc_byteTxnEnqueues (msg->contentSize ()); - } -} - -void Queue::requeue(const QueuedMessage& msg){ - assertClusterSafe(); - QueueListeners::NotificationSet copy; - { - Mutex::ScopedLock locker(messageLock); - if (!isEnqueued(msg)) return; - messages->reinsert(msg); - listeners.populate(copy); - - // for persistLastNode - don't force a message twice to disk, but force it if no force before - if(inLastNodeFailure && persistLastNode && !msg.payload->isStoredOnQueue(shared_from_this())) { - msg.payload->forcePersistent(); - if (msg.payload->isForcedPersistent() ){ - boost::intrusive_ptr<Message> payload = msg.payload; - enqueue(0, payload); - } - } - } - copy.notify(); -} - -bool Queue::acquireMessageAt(const SequenceNumber& position, QueuedMessage& message) -{ - Mutex::ScopedLock locker(messageLock); - assertClusterSafe(); - QPID_LOG(debug, "Attempting to acquire message at " << position); - if (messages->remove(position, message)) { - QPID_LOG(debug, "Acquired message at " << position << " from " << name); - return true; - } else { - QPID_LOG(debug, "Could not acquire message at " << position << " from " << name << "; no message at that position"); - return false; - } -} - -bool Queue::acquire(const QueuedMessage& msg) { - QueuedMessage copy = msg; - return acquireMessageAt(msg.position, copy); -} - -void Queue::notifyListener() -{ - assertClusterSafe(); - QueueListeners::NotificationSet set; - { - Mutex::ScopedLock locker(messageLock); - if (messages->size()) { - listeners.populate(set); - } - } - set.notify(); -} - -bool Queue::getNextMessage(QueuedMessage& m, Consumer::shared_ptr c) -{ - checkNotDeleted(); - if (c->preAcquires()) { - switch (consumeNextMessage(m, c)) { - case CONSUMED: - return true; - case CANT_CONSUME: - notifyListener();//let someone else try - case NO_MESSAGES: - default: - return false; - } - } else { - return browseNextMessage(m, c); - } -} - -Queue::ConsumeCode Queue::consumeNextMessage(QueuedMessage& m, Consumer::shared_ptr c) -{ - while (true) { - Mutex::ScopedLock locker(messageLock); - if (messages->empty()) { - QPID_LOG(debug, "No messages to dispatch on queue '" << name << "'"); - listeners.addListener(c); - return NO_MESSAGES; - } else { - QueuedMessage msg = messages->front(); - if (msg.payload->hasExpired()) { - QPID_LOG(debug, "Message expired from queue '" << name << "'"); - popAndDequeue(); - continue; - } - - if (c->filter(msg.payload)) { - if (c->accept(msg.payload)) { - m = msg; - pop(); - return CONSUMED; - } else { - //message(s) are available but consumer hasn't got enough credit - QPID_LOG(debug, "Consumer can't currently accept message from '" << name << "'"); - return CANT_CONSUME; - } - } else { - //consumer will never want this message - QPID_LOG(debug, "Consumer doesn't want message from '" << name << "'"); - return CANT_CONSUME; - } - } - } -} - - -bool Queue::browseNextMessage(QueuedMessage& m, Consumer::shared_ptr c) -{ - QueuedMessage msg(this); - while (seek(msg, c)) { - if (c->filter(msg.payload) && !msg.payload->hasExpired()) { - if (c->accept(msg.payload)) { - //consumer wants the message - c->position = msg.position; - m = msg; - return true; - } else { - //browser hasn't got enough credit for the message - QPID_LOG(debug, "Browser can't currently accept message from '" << name << "'"); - return false; - } - } else { - //consumer will never want this message, continue seeking - c->position = msg.position; - QPID_LOG(debug, "Browser skipping message from '" << name << "'"); - } - } - return false; -} - -void Queue::removeListener(Consumer::shared_ptr c) -{ - QueueListeners::NotificationSet set; - { - Mutex::ScopedLock locker(messageLock); - listeners.removeListener(c); - if (messages->size()) { - listeners.populate(set); - } - } - set.notify(); -} - -bool Queue::dispatch(Consumer::shared_ptr c) -{ - QueuedMessage msg(this); - if (getNextMessage(msg, c)) { - c->deliver(msg); - return true; - } else { - return false; - } -} - -// Find the next message -bool Queue::seek(QueuedMessage& msg, Consumer::shared_ptr c) { - Mutex::ScopedLock locker(messageLock); - if (messages->next(c->position, msg)) { - return true; - } else { - listeners.addListener(c); - return false; - } -} - -QueuedMessage Queue::find(SequenceNumber pos) const { - - Mutex::ScopedLock locker(messageLock); - QueuedMessage msg; - messages->find(pos, msg); - return msg; -} - -void Queue::consume(Consumer::shared_ptr c, bool requestExclusive){ - assertClusterSafe(); - Mutex::ScopedLock locker(consumerLock); - if(exclusive) { - throw ResourceLockedException( - QPID_MSG("Queue " << getName() << " has an exclusive consumer. No more consumers allowed.")); - } else if(requestExclusive) { - if(consumerCount) { - throw ResourceLockedException( - QPID_MSG("Queue " << getName() << " already has consumers. Exclusive access denied.")); - } else { - exclusive = c->getSession(); - } - } - consumerCount++; - if (mgmtObject != 0) - mgmtObject->inc_consumerCount (); - //reset auto deletion timer if necessary - if (autoDeleteTimeout && autoDeleteTask) { - autoDeleteTask->cancel(); - } -} - -void Queue::cancel(Consumer::shared_ptr c){ - removeListener(c); - Mutex::ScopedLock locker(consumerLock); - consumerCount--; - if(exclusive) exclusive = 0; - if (mgmtObject != 0) - mgmtObject->dec_consumerCount (); -} - -QueuedMessage Queue::get(){ - Mutex::ScopedLock locker(messageLock); - QueuedMessage msg(this); - messages->pop(msg); - return msg; -} - -bool collect_if_expired(std::deque<QueuedMessage>& expired, QueuedMessage& message) -{ - if (message.payload->hasExpired()) { - expired.push_back(message); - return true; - } else { - return false; - } -} - -void Queue::purgeExpired() -{ - //As expired messages are discarded during dequeue also, only - //bother explicitly expiring if the rate of dequeues since last - //attempt is less than one per second. - - if (dequeueTracker.sampleRatePerSecond() < 1) { - std::deque<QueuedMessage> expired; - { - Mutex::ScopedLock locker(messageLock); - messages->removeIf(boost::bind(&collect_if_expired, expired, _1)); - } - for_each(expired.begin(), expired.end(), boost::bind(&Queue::dequeue, this, (TransactionContext*) 0, _1)); - } -} - -/** - * purge - for purging all or some messages on a queue - * depending on the purge_request - * - * purge_request == 0 then purge all messages - * == N then purge N messages from queue - * Sometimes purge_request == 1 to unblock the top of queue - * - * The dest exchange may be supplied to re-route messages through the exchange. - * It is safe to re-route messages such that they arrive back on the same queue, - * even if the queue is ordered by priority. - */ -uint32_t Queue::purge(const uint32_t purge_request, boost::shared_ptr<Exchange> dest) -{ - Mutex::ScopedLock locker(messageLock); - uint32_t purge_count = purge_request; // only comes into play if >0 - std::deque<DeliverableMessage> rerouteQueue; - - uint32_t count = 0; - // Either purge them all or just the some (purge_count) while the queue isn't empty. - while((!purge_request || purge_count--) && !messages->empty()) { - if (dest.get()) { - // - // If there is a destination exchange, stage the messages onto a reroute queue - // so they don't wind up getting purged more than once. - // - DeliverableMessage msg(messages->front().payload); - rerouteQueue.push_back(msg); - } - popAndDequeue(); - count++; - } - - // - // Re-route purged messages into the destination exchange. Note that there's no need - // to test dest.get() here because if it is NULL, the rerouteQueue will be empty. - // - while (!rerouteQueue.empty()) { - DeliverableMessage msg(rerouteQueue.front()); - rerouteQueue.pop_front(); - dest->routeWithAlternate(msg); - } - - return count; -} - -uint32_t Queue::move(const Queue::shared_ptr destq, uint32_t qty) { - Mutex::ScopedLock locker(messageLock); - uint32_t move_count = qty; // only comes into play if qty >0 - uint32_t count = 0; // count how many were moved for returning - - while((!qty || move_count--) && !messages->empty()) { - QueuedMessage qmsg = messages->front(); - boost::intrusive_ptr<Message> msg = qmsg.payload; - destq->deliver(msg); // deliver message to the destination queue - pop(); - dequeue(0, qmsg); - count++; - } - return count; -} - -void Queue::pop() -{ - assertClusterSafe(); - messages->pop(); - ++dequeueTracker; -} - -void Queue::push(boost::intrusive_ptr<Message>& msg, bool isRecovery){ - assertClusterSafe(); - QueueListeners::NotificationSet copy; - QueuedMessage removed; - bool dequeueRequired = false; - { - Mutex::ScopedLock locker(messageLock); - QueuedMessage qm(this, msg, ++sequence); - if (insertSeqNo) msg->getOrInsertHeaders().setInt64(seqNoKey, sequence); - - dequeueRequired = messages->push(qm, removed); - listeners.populate(copy); - enqueued(qm); - } - copy.notify(); - if (dequeueRequired) { - if (isRecovery) { - //can't issue new requests for the store until - //recovery is complete - pendingDequeues.push_back(removed); - } else { - dequeue(0, removed); - } - } -} - -void isEnqueueComplete(uint32_t* result, const QueuedMessage& message) -{ - if (message.payload->isIngressComplete()) (*result)++; -} - -/** function only provided for unit tests, or code not in critical message path */ -uint32_t Queue::getEnqueueCompleteMessageCount() const -{ - Mutex::ScopedLock locker(messageLock); - uint32_t count = 0; - messages->foreach(boost::bind(&isEnqueueComplete, &count, _1)); - return count; -} - -uint32_t Queue::getMessageCount() const -{ - Mutex::ScopedLock locker(messageLock); - return messages->size(); -} - -uint32_t Queue::getConsumerCount() const -{ - Mutex::ScopedLock locker(consumerLock); - return consumerCount; -} - -bool Queue::canAutoDelete() const -{ - Mutex::ScopedLock locker(consumerLock); - return autodelete && !consumerCount && !owner; -} - -void Queue::clearLastNodeFailure() -{ - inLastNodeFailure = false; -} - -void Queue::forcePersistent(QueuedMessage& message) -{ - if(!message.payload->isStoredOnQueue(shared_from_this())) { - message.payload->forcePersistent(); - if (message.payload->isForcedPersistent() ){ - enqueue(0, message.payload); - } - } -} - -void Queue::setLastNodeFailure() -{ - if (persistLastNode){ - Mutex::ScopedLock locker(messageLock); - try { - messages->foreach(boost::bind(&Queue::forcePersistent, this, _1)); - } catch (const std::exception& e) { - // Could not go into last node standing (for example journal not large enough) - QPID_LOG(error, "Unable to fail to last node standing for queue: " << name << " : " << e.what()); - } - inLastNodeFailure = true; - } -} - - -// return true if store exists, -bool Queue::enqueue(TransactionContext* ctxt, boost::intrusive_ptr<Message>& msg, bool suppressPolicyCheck) -{ - ScopedUse u(barrier); - if (!u.acquired) return false; - - if (policy.get() && !suppressPolicyCheck) { - std::deque<QueuedMessage> dequeues; - { - Mutex::ScopedLock locker(messageLock); - policy->tryEnqueue(msg); - policy->getPendingDequeues(dequeues); - } - //depending on policy, may have some dequeues that need to performed without holding the lock - for_each(dequeues.begin(), dequeues.end(), boost::bind(&Queue::dequeue, this, (TransactionContext*) 0, _1)); - } - - if (inLastNodeFailure && persistLastNode){ - msg->forcePersistent(); - } - - if (traceId.size()) { - //copy on write: take deep copy of message before modifying it - //as the frames may already be available for delivery on other - //threads - boost::intrusive_ptr<Message> copy(new Message(*msg)); - msg = copy; - msg->addTraceId(traceId); - } - - if ((msg->isPersistent() || msg->checkContentReleasable()) && store) { - // mark the message as being enqueued - the store MUST CALL msg->enqueueComplete() - // when it considers the message stored. - msg->enqueueAsync(shared_from_this(), store); - boost::intrusive_ptr<PersistableMessage> pmsg = boost::static_pointer_cast<PersistableMessage>(msg); - store->enqueue(ctxt, pmsg, *this); - return true; - } - if (!store) { - //Messages enqueued on a transient queue should be prevented - //from having their content released as it may not be - //recoverable by these queue for delivery - msg->blockContentRelease(); - } - return false; -} - -void Queue::enqueueAborted(boost::intrusive_ptr<Message> msg) -{ - Mutex::ScopedLock locker(messageLock); - if (policy.get()) policy->enqueueAborted(msg); -} - -// return true if store exists, -bool Queue::dequeue(TransactionContext* ctxt, const QueuedMessage& msg) -{ - ScopedUse u(barrier); - if (!u.acquired) return false; - - { - Mutex::ScopedLock locker(messageLock); - if (!isEnqueued(msg)) return false; - if (!ctxt) { - dequeued(msg); - } - } - // This check prevents messages which have been forced persistent on one queue from dequeuing - // from another on which no forcing has taken place and thus causing a store error. - bool fp = msg.payload->isForcedPersistent(); - if (!fp || (fp && msg.payload->isStoredOnQueue(shared_from_this()))) { - if ((msg.payload->isPersistent() || msg.payload->checkContentReleasable()) && store) { - msg.payload->dequeueAsync(shared_from_this(), store); //increment to async counter -- for message sent to more than one queue - boost::intrusive_ptr<PersistableMessage> pmsg = boost::static_pointer_cast<PersistableMessage>(msg.payload); - store->dequeue(ctxt, pmsg, *this); - return true; - } - } - return false; -} - -void Queue::dequeueCommitted(const QueuedMessage& msg) -{ - Mutex::ScopedLock locker(messageLock); - dequeued(msg); - if (mgmtObject != 0) { - mgmtObject->inc_msgTxnDequeues(); - mgmtObject->inc_byteTxnDequeues(msg.payload->contentSize()); - } -} - -/** - * Removes a message from the in-memory delivery queue as well - * dequeing it from the logical (and persistent if applicable) queue - */ -void Queue::popAndDequeue() -{ - QueuedMessage msg = messages->front(); - pop(); - dequeue(0, msg); -} - -/** - * Updates policy and management when a message has been dequeued, - * expects messageLock to be held - */ -void Queue::dequeued(const QueuedMessage& msg) -{ - if (policy.get()) policy->dequeued(msg); - mgntDeqStats(msg.payload); - for (Observers::const_iterator i = observers.begin(); i != observers.end(); ++i) { - try{ - (*i)->dequeued(msg); - } catch (const std::exception& e) { - QPID_LOG(warning, "Exception on notification of dequeue for queue " << getName() << ": " << e.what()); - } - } -} - - -void Queue::create(const FieldTable& _settings) -{ - settings = _settings; - if (store) { - store->create(*this, _settings); - } - configureImpl(_settings); -} - - -int getIntegerSetting(const qpid::framing::FieldTable& settings, const std::string& key) -{ - qpid::framing::FieldTable::ValuePtr v = settings.get(key); - if (!v) { - return 0; - } else if (v->convertsTo<int>()) { - return v->get<int>(); - } else if (v->convertsTo<std::string>()){ - std::string s = v->get<std::string>(); - try { - return boost::lexical_cast<int>(s); - } catch(const boost::bad_lexical_cast&) { - QPID_LOG(warning, "Ignoring invalid integer value for " << key << ": " << s); - return 0; - } - } else { - QPID_LOG(warning, "Ignoring invalid integer value for " << key << ": " << *v); - return 0; - } -} - -void Queue::configure(const FieldTable& _settings) -{ - settings = _settings; - configureImpl(settings); -} - -void Queue::configureImpl(const FieldTable& _settings) -{ - eventMode = _settings.getAsInt(qpidQueueEventGeneration); - if (eventMode && broker) { - broker->getQueueEvents().observe(*this, eventMode == ENQUEUE_ONLY); - } - - if (QueuePolicy::getType(_settings) == QueuePolicy::FLOW_TO_DISK && - (!store || NullMessageStore::isNullStore(store) || (broker && !(broker->getQueueEvents().isSync())) )) { - if ( NullMessageStore::isNullStore(store)) { - QPID_LOG(warning, "Flow to disk not valid for non-persisted queue:" << getName()); - } else if (broker && !(broker->getQueueEvents().isSync()) ) { - QPID_LOG(warning, "Flow to disk not valid with async Queue Events:" << getName()); - } - FieldTable copy(_settings); - copy.erase(QueuePolicy::typeKey); - setPolicy(QueuePolicy::createQueuePolicy(getName(), copy)); - } else { - setPolicy(QueuePolicy::createQueuePolicy(getName(), _settings)); - } - if (broker && broker->getManagementAgent()) { - ThresholdAlerts::observe(*this, *(broker->getManagementAgent()), _settings, broker->getOptions().queueThresholdEventRatio); - } - - //set this regardless of owner to allow use of no-local with exclusive consumers also - noLocal = _settings.get(qpidNoLocal); - QPID_LOG(debug, "Configured queue " << getName() << " with no-local=" << noLocal); - - std::string lvqKey = _settings.getAsString(qpidLastValueQueueKey); - if (lvqKey.size()) { - QPID_LOG(debug, "Configured queue " << getName() << " as Last Value Queue with key " << lvqKey); - messages = std::auto_ptr<Messages>(new MessageMap(lvqKey)); - } else if (_settings.get(qpidLastValueQueueNoBrowse)) { - QPID_LOG(debug, "Configured queue " << getName() << " as Legacy Last Value Queue with 'no-browse' on"); - messages = LegacyLVQ::updateOrReplace(messages, qpidVQMatchProperty, true, broker); - } else if (_settings.get(qpidLastValueQueue)) { - QPID_LOG(debug, "Configured queue " << getName() << " as Legacy Last Value Queue"); - messages = LegacyLVQ::updateOrReplace(messages, qpidVQMatchProperty, false, broker); - } else { - std::auto_ptr<Messages> m = Fairshare::create(_settings); - if (m.get()) { - messages = m; - QPID_LOG(debug, "Configured queue " << getName() << " as priority queue."); - } - } - - persistLastNode= _settings.get(qpidPersistLastNode); - if (persistLastNode) QPID_LOG(debug, "Configured queue to Persist data if cluster fails to one node for: " << getName()); - - traceId = _settings.getAsString(qpidTraceIdentity); - std::string excludeList = _settings.getAsString(qpidTraceExclude); - if (excludeList.size()) { - split(traceExclude, excludeList, ", "); - } - QPID_LOG(debug, "Configured queue " << getName() << " with qpid.trace.id='" << traceId - << "' and qpid.trace.exclude='"<< excludeList << "' i.e. " << traceExclude.size() << " elements"); - - FieldTable::ValuePtr p =_settings.get(qpidInsertSequenceNumbers); - if (p && p->convertsTo<std::string>()) insertSequenceNumbers(p->get<std::string>()); - - autoDeleteTimeout = getIntegerSetting(_settings, qpidAutoDeleteTimeout); - if (autoDeleteTimeout) - QPID_LOG(debug, "Configured queue " << getName() << " with qpid.auto_delete_timeout=" << autoDeleteTimeout); - - if (mgmtObject != 0) { - mgmtObject->set_arguments(ManagementAgent::toMap(_settings)); - } - - QueueFlowLimit::observe(*this, _settings); -} - -void Queue::destroyed() -{ - unbind(broker->getExchanges()); - if (alternateExchange.get()) { - Mutex::ScopedLock locker(messageLock); - while(!messages->empty()){ - DeliverableMessage msg(messages->front().payload); - alternateExchange->routeWithAlternate(msg); - popAndDequeue(); - } - alternateExchange->decAlternateUsers(); - } - - if (store) { - barrier.destroy(); - store->flush(*this); - store->destroy(*this); - store = 0;//ensure we make no more calls to the store for this queue - } - if (autoDeleteTask) autoDeleteTask = boost::intrusive_ptr<TimerTask>(); - notifyDeleted(); -} - -void Queue::notifyDeleted() -{ - QueueListeners::ListenerSet set; - { - Mutex::ScopedLock locker(messageLock); - listeners.snapshot(set); - deleted = true; - } - set.notifyAll(); -} - -void Queue::bound(const string& exchange, const string& key, - const FieldTable& args) -{ - bindings.add(exchange, key, args); -} - -void Queue::unbind(ExchangeRegistry& exchanges) -{ - bindings.unbind(exchanges, shared_from_this()); -} - -void Queue::setPolicy(std::auto_ptr<QueuePolicy> _policy) -{ - policy = _policy; -} - -const QueuePolicy* Queue::getPolicy() -{ - return policy.get(); -} - -uint64_t Queue::getPersistenceId() const -{ - return persistenceId; -} - -void Queue::setPersistenceId(uint64_t _persistenceId) const -{ - if (mgmtObject != 0 && persistenceId == 0 && externalQueueStore) - { - ManagementObject* childObj = externalQueueStore->GetManagementObject(); - if (childObj != 0) - childObj->setReference(mgmtObject->getObjectId()); - } - persistenceId = _persistenceId; -} - -void Queue::encode(Buffer& buffer) const -{ - buffer.putShortString(name); - buffer.put(settings); - if (policy.get()) { - buffer.put(*policy); - } - buffer.putShortString(alternateExchange.get() ? alternateExchange->getName() : std::string("")); -} - -uint32_t Queue::encodedSize() const -{ - return name.size() + 1/*short string size octet*/ - + (alternateExchange.get() ? alternateExchange->getName().size() : 0) + 1 /* short string */ - + settings.encodedSize() - + (policy.get() ? (*policy).encodedSize() : 0); -} - -Queue::shared_ptr Queue::restore( QueueRegistry& queues, Buffer& buffer ) -{ - string name; - buffer.getShortString(name); - FieldTable settings; - buffer.get(settings); - boost::shared_ptr<Exchange> alternate; - std::pair<Queue::shared_ptr, bool> result = queues.declare(name, true, false, 0, alternate, settings, true); - if (result.first->policy.get() && buffer.available() >= result.first->policy->encodedSize()) { - buffer.get ( *(result.first->policy) ); - } - if (buffer.available()) { - string altExch; - buffer.getShortString(altExch); - result.first->alternateExchangeName.assign(altExch); - } - - return result.first; -} - - -void Queue::setAlternateExchange(boost::shared_ptr<Exchange> exchange) -{ - alternateExchange = exchange; - if (mgmtObject) { - if (exchange.get() != 0) - mgmtObject->set_altExchange(exchange->GetManagementObject()->getObjectId()); - else - mgmtObject->clr_altExchange(); - } -} - -boost::shared_ptr<Exchange> Queue::getAlternateExchange() -{ - return alternateExchange; -} - -void tryAutoDeleteImpl(Broker& broker, Queue::shared_ptr queue) -{ - if (broker.getQueues().destroyIf(queue->getName(), - boost::bind(boost::mem_fn(&Queue::canAutoDelete), queue))) { - QPID_LOG(debug, "Auto-deleting " << queue->getName()); - queue->destroyed(); - } -} - -struct AutoDeleteTask : qpid::sys::TimerTask -{ - Broker& broker; - Queue::shared_ptr queue; - - AutoDeleteTask(Broker& b, Queue::shared_ptr q, AbsTime fireTime) - : qpid::sys::TimerTask(fireTime, "DelayedAutoDeletion"), broker(b), queue(q) {} - - void fire() - { - //need to detect case where queue was used after the task was - //created, but then became unused again before the task fired; - //in this case ignore this request as there will have already - //been a later task added - tryAutoDeleteImpl(broker, queue); - } -}; - -void Queue::tryAutoDelete(Broker& broker, Queue::shared_ptr queue) -{ - if (queue->autoDeleteTimeout && queue->canAutoDelete()) { - AbsTime time(now(), Duration(queue->autoDeleteTimeout * TIME_SEC)); - queue->autoDeleteTask = boost::intrusive_ptr<qpid::sys::TimerTask>(new AutoDeleteTask(broker, queue, time)); - broker.getClusterTimer().add(queue->autoDeleteTask); - QPID_LOG(debug, "Timed auto-delete for " << queue->getName() << " initiated"); - } else { - tryAutoDeleteImpl(broker, queue); - } -} - -bool Queue::isExclusiveOwner(const OwnershipToken* const o) const -{ - Mutex::ScopedLock locker(ownershipLock); - return o == owner; -} - -void Queue::releaseExclusiveOwnership() -{ - Mutex::ScopedLock locker(ownershipLock); - owner = 0; -} - -bool Queue::setExclusiveOwner(const OwnershipToken* const o) -{ - //reset auto deletion timer if necessary - if (autoDeleteTimeout && autoDeleteTask) { - autoDeleteTask->cancel(); - } - Mutex::ScopedLock locker(ownershipLock); - if (owner) { - return false; - } else { - owner = o; - return true; - } -} - -bool Queue::hasExclusiveOwner() const -{ - Mutex::ScopedLock locker(ownershipLock); - return owner != 0; -} - -bool Queue::hasExclusiveConsumer() const -{ - return exclusive; -} - -void Queue::setExternalQueueStore(ExternalQueueStore* inst) { - if (externalQueueStore!=inst && externalQueueStore) - delete externalQueueStore; - externalQueueStore = inst; - - if (inst) { - ManagementObject* childObj = inst->GetManagementObject(); - if (childObj != 0 && mgmtObject != 0) - childObj->setReference(mgmtObject->getObjectId()); - } -} - -ManagementObject* Queue::GetManagementObject (void) const -{ - return (ManagementObject*) mgmtObject; -} - -Manageable::status_t Queue::ManagementMethod (uint32_t methodId, Args& args, string& etext) -{ - Manageable::status_t status = Manageable::STATUS_UNKNOWN_METHOD; - - QPID_LOG (debug, "Queue::ManagementMethod [id=" << methodId << "]"); - - switch (methodId) { - case _qmf::Queue::METHOD_PURGE : - { - _qmf::ArgsQueuePurge& purgeArgs = (_qmf::ArgsQueuePurge&) args; - purge(purgeArgs.i_request); - status = Manageable::STATUS_OK; - } - break; - - case _qmf::Queue::METHOD_REROUTE : - { - _qmf::ArgsQueueReroute& rerouteArgs = (_qmf::ArgsQueueReroute&) args; - boost::shared_ptr<Exchange> dest; - if (rerouteArgs.i_useAltExchange) - dest = alternateExchange; - else { - try { - dest = broker->getExchanges().get(rerouteArgs.i_exchange); - } catch(const std::exception&) { - status = Manageable::STATUS_PARAMETER_INVALID; - etext = "Exchange not found"; - break; - } - } - - purge(rerouteArgs.i_request, dest); - status = Manageable::STATUS_OK; - } - break; - } - - return status; -} - -void Queue::setPosition(SequenceNumber n) { - Mutex::ScopedLock locker(messageLock); - sequence = n; -} - -SequenceNumber Queue::getPosition() { - return sequence; -} - -int Queue::getEventMode() { return eventMode; } - -void Queue::recoveryComplete(ExchangeRegistry& exchanges) -{ - // set the alternate exchange - if (!alternateExchangeName.empty()) { - try { - Exchange::shared_ptr ae = exchanges.get(alternateExchangeName); - setAlternateExchange(ae); - } catch (const NotFoundException&) { - QPID_LOG(warning, "Could not set alternate exchange \"" << alternateExchangeName << "\" on queue \"" << name << "\": exchange does not exist."); - } - } - //process any pending dequeues - for_each(pendingDequeues.begin(), pendingDequeues.end(), boost::bind(&Queue::dequeue, this, (TransactionContext*) 0, _1)); - pendingDequeues.clear(); -} - -void Queue::insertSequenceNumbers(const std::string& key) -{ - seqNoKey = key; - insertSeqNo = !seqNoKey.empty(); - QPID_LOG(debug, "Inserting sequence numbers as " << key); -} - -void Queue::enqueued(const QueuedMessage& m) -{ - for (Observers::iterator i = observers.begin(); i != observers.end(); ++i) { - try { - (*i)->enqueued(m); - } catch (const std::exception& e) { - QPID_LOG(warning, "Exception on notification of enqueue for queue " << getName() << ": " << e.what()); - } - } - if (policy.get()) { - policy->enqueued(m); - } - mgntEnqStats(m.payload); -} - -void Queue::updateEnqueued(const QueuedMessage& m) -{ - if (m.payload) { - boost::intrusive_ptr<Message> payload = m.payload; - enqueue ( 0, payload, true ); - if (policy.get()) { - policy->recoverEnqueued(payload); - } - enqueued(m); - } else { - QPID_LOG(warning, "Queue informed of enqueued message that has no payload"); - } -} - -bool Queue::isEnqueued(const QueuedMessage& msg) -{ - return !policy.get() || policy->isEnqueued(msg); -} - -QueueListeners& Queue::getListeners() { return listeners; } -Messages& Queue::getMessages() { return *messages; } -const Messages& Queue::getMessages() const { return *messages; } - -void Queue::checkNotDeleted() -{ - if (deleted) { - throw ResourceDeletedException(QPID_MSG("Queue " << getName() << " has been deleted.")); - } -} - -void Queue::addObserver(boost::shared_ptr<QueueObserver> observer) -{ - observers.insert(observer); -} - -void Queue::flush() -{ - ScopedUse u(barrier); - if (u.acquired && store) store->flush(*this); -} - - -bool Queue::bind(boost::shared_ptr<Exchange> exchange, const std::string& key, - const qpid::framing::FieldTable& arguments) -{ - if (exchange->bind(shared_from_this(), key, &arguments)) { - bound(exchange->getName(), key, arguments); - if (exchange->isDurable() && isDurable()) { - store->bind(*exchange, *this, key, arguments); - } - return true; - } else { - return false; - } -} - - -const Broker* Queue::getBroker() -{ - return broker; -} - - -Queue::UsageBarrier::UsageBarrier(Queue& q) : parent(q), count(0) {} - -bool Queue::UsageBarrier::acquire() -{ - Monitor::ScopedLock l(parent.messageLock); - if (parent.deleted) { - return false; - } else { - ++count; - return true; - } -} - -void Queue::UsageBarrier::release() -{ - Monitor::ScopedLock l(parent.messageLock); - if (--count == 0) parent.messageLock.notifyAll(); -} - -void Queue::UsageBarrier::destroy() -{ - Monitor::ScopedLock l(parent.messageLock); - parent.deleted = true; - while (count) parent.messageLock.wait(); -} diff --git a/cpp/src/qpid/broker/Queue.h b/cpp/src/qpid/broker/Queue.h deleted file mode 100644 index c4f1bcc07e..0000000000 --- a/cpp/src/qpid/broker/Queue.h +++ /dev/null @@ -1,390 +0,0 @@ -#ifndef _broker_Queue_h -#define _broker_Queue_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/OwnershipToken.h" -#include "qpid/broker/Consumer.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/Messages.h" -#include "qpid/broker/PersistableQueue.h" -#include "qpid/broker/QueuePolicy.h" -#include "qpid/broker/QueueBindings.h" -#include "qpid/broker/QueueListeners.h" -#include "qpid/broker/QueueObserver.h" -#include "qpid/broker/RateTracker.h" - -#include "qpid/framing/FieldTable.h" -#include "qpid/sys/Monitor.h" -#include "qpid/sys/Timer.h" -#include "qpid/management/Manageable.h" -#include "qmf/org/apache/qpid/broker/Queue.h" -#include "qpid/framing/amqp_types.h" - -#include <boost/shared_ptr.hpp> -#include <boost/intrusive_ptr.hpp> -#include <boost/enable_shared_from_this.hpp> - -#include <list> -#include <vector> -#include <memory> -#include <deque> -#include <set> -#include <algorithm> - -namespace qpid { -namespace broker { -class Broker; -class MessageStore; -class QueueEvents; -class QueueRegistry; -class TransactionContext; -class Exchange; - -/** - * The brokers representation of an amqp queue. Messages are - * delivered to a queue from where they can be dispatched to - * registered consumers or be stored until dequeued or until one - * or more consumers registers. - */ -class Queue : public boost::enable_shared_from_this<Queue>, - public PersistableQueue, public management::Manageable { - - struct UsageBarrier - { - Queue& parent; - uint count; - - UsageBarrier(Queue&); - bool acquire(); - void release(); - void destroy(); - }; - - struct ScopedUse - { - UsageBarrier& barrier; - const bool acquired; - ScopedUse(UsageBarrier& b) : barrier(b), acquired(barrier.acquire()) {} - ~ScopedUse() { if (acquired) barrier.release(); } - }; - - typedef std::set< boost::shared_ptr<QueueObserver> > Observers; - enum ConsumeCode {NO_MESSAGES=0, CANT_CONSUME=1, CONSUMED=2}; - - - const std::string name; - const bool autodelete; - MessageStore* store; - const OwnershipToken* owner; - uint32_t consumerCount; - OwnershipToken* exclusive; - bool noLocal; - bool persistLastNode; - bool inLastNodeFailure; - std::string traceId; - std::vector<std::string> traceExclude; - QueueListeners listeners; - std::auto_ptr<Messages> messages; - std::deque<QueuedMessage> pendingDequeues;//used to avoid dequeuing during recovery - mutable qpid::sys::Mutex consumerLock; - mutable qpid::sys::Monitor messageLock; - mutable qpid::sys::Mutex ownershipLock; - mutable uint64_t persistenceId; - framing::FieldTable settings; - std::auto_ptr<QueuePolicy> policy; - bool policyExceeded; - QueueBindings bindings; - std::string alternateExchangeName; - boost::shared_ptr<Exchange> alternateExchange; - framing::SequenceNumber sequence; - qmf::org::apache::qpid::broker::Queue* mgmtObject; - RateTracker dequeueTracker; - int eventMode; - Observers observers; - bool insertSeqNo; - std::string seqNoKey; - Broker* broker; - bool deleted; - UsageBarrier barrier; - int autoDeleteTimeout; - boost::intrusive_ptr<qpid::sys::TimerTask> autoDeleteTask; - - void push(boost::intrusive_ptr<Message>& msg, bool isRecovery=false); - void setPolicy(std::auto_ptr<QueuePolicy> policy); - bool seek(QueuedMessage& msg, Consumer::shared_ptr position); - bool getNextMessage(QueuedMessage& msg, Consumer::shared_ptr c); - ConsumeCode consumeNextMessage(QueuedMessage& msg, Consumer::shared_ptr c); - bool browseNextMessage(QueuedMessage& msg, Consumer::shared_ptr c); - void notifyListener(); - - void removeListener(Consumer::shared_ptr); - - bool isExcluded(boost::intrusive_ptr<Message>& msg); - - void enqueued(const QueuedMessage& msg); - void dequeued(const QueuedMessage& msg); - void pop(); - void popAndDequeue(); - QueuedMessage getFront(); - void forcePersistent(QueuedMessage& msg); - int getEventMode(); - void configureImpl(const qpid::framing::FieldTable& settings); - - inline void mgntEnqStats(const boost::intrusive_ptr<Message>& msg) - { - if (mgmtObject != 0) { - mgmtObject->inc_msgTotalEnqueues (); - mgmtObject->inc_byteTotalEnqueues (msg->contentSize ()); - if (msg->isPersistent ()) { - mgmtObject->inc_msgPersistEnqueues (); - mgmtObject->inc_bytePersistEnqueues (msg->contentSize ()); - } - } - } - inline void mgntDeqStats(const boost::intrusive_ptr<Message>& msg) - { - if (mgmtObject != 0){ - mgmtObject->inc_msgTotalDequeues (); - mgmtObject->inc_byteTotalDequeues (msg->contentSize()); - if (msg->isPersistent ()){ - mgmtObject->inc_msgPersistDequeues (); - mgmtObject->inc_bytePersistDequeues (msg->contentSize()); - } - } - } - - void checkNotDeleted(); - void notifyDeleted(); - - public: - - typedef boost::shared_ptr<Queue> shared_ptr; - - typedef std::vector<shared_ptr> vector; - - QPID_BROKER_EXTERN Queue(const std::string& name, - bool autodelete = false, - MessageStore* const store = 0, - const OwnershipToken* const owner = 0, - management::Manageable* parent = 0, - Broker* broker = 0); - QPID_BROKER_EXTERN ~Queue(); - - QPID_BROKER_EXTERN bool dispatch(Consumer::shared_ptr); - - /** - * Used to configure a new queue and create a persistent record - * for it in store if required. - */ - QPID_BROKER_EXTERN void create(const qpid::framing::FieldTable& settings); - - /** - * Used to reconfigure a recovered queue (does not create - * persistent record in store). - */ - QPID_BROKER_EXTERN void configure(const qpid::framing::FieldTable& settings); - void destroyed(); - QPID_BROKER_EXTERN void bound(const std::string& exchange, - const std::string& key, - const qpid::framing::FieldTable& args); - //TODO: get unbind out of the public interface; only there for purposes of one unit test - QPID_BROKER_EXTERN void unbind(ExchangeRegistry& exchanges); - /** - * Bind self to specified exchange, and record that binding for unbinding on delete. - */ - bool bind(boost::shared_ptr<Exchange> exchange, const std::string& key, - const qpid::framing::FieldTable& arguments=qpid::framing::FieldTable()); - - QPID_BROKER_EXTERN bool acquire(const QueuedMessage& msg); - QPID_BROKER_EXTERN bool acquireMessageAt(const qpid::framing::SequenceNumber& position, QueuedMessage& message); - - /** - * Delivers a message to the queue. Will record it as - * enqueued if persistent then process it. - */ - QPID_BROKER_EXTERN void deliver(boost::intrusive_ptr<Message> msg); - /** - * Dispatches the messages immediately to a consumer if - * one is available or stores it for later if not. - */ - QPID_BROKER_EXTERN void process(boost::intrusive_ptr<Message>& msg); - /** - * Returns a message to the in-memory queue (due to lack - * of acknowledegement from a receiver). If a consumer is - * available it will be dispatched immediately, else it - * will be returned to the front of the queue. - */ - QPID_BROKER_EXTERN void requeue(const QueuedMessage& msg); - /** - * Used during recovery to add stored messages back to the queue - */ - QPID_BROKER_EXTERN void recover(boost::intrusive_ptr<Message>& msg); - - QPID_BROKER_EXTERN void consume(Consumer::shared_ptr c, - bool exclusive = false); - QPID_BROKER_EXTERN void cancel(Consumer::shared_ptr c); - - uint32_t purge(const uint32_t purge_request=0, boost::shared_ptr<Exchange> dest=boost::shared_ptr<Exchange>()); //defaults to all messages - QPID_BROKER_EXTERN void purgeExpired(); - - //move qty # of messages to destination Queue destq - uint32_t move(const Queue::shared_ptr destq, uint32_t qty); - - QPID_BROKER_EXTERN uint32_t getMessageCount() const; - QPID_BROKER_EXTERN uint32_t getEnqueueCompleteMessageCount() const; - QPID_BROKER_EXTERN uint32_t getConsumerCount() const; - inline const std::string& getName() const { return name; } - bool isExclusiveOwner(const OwnershipToken* const o) const; - void releaseExclusiveOwnership(); - bool setExclusiveOwner(const OwnershipToken* const o); - bool hasExclusiveConsumer() const; - bool hasExclusiveOwner() const; - inline bool isDurable() const { return store != 0; } - inline const framing::FieldTable& getSettings() const { return settings; } - inline bool isAutoDelete() const { return autodelete; } - bool canAutoDelete() const; - const QueueBindings& getBindings() const { return bindings; } - - /** - * used to take messages from in memory and flush down to disk. - */ - QPID_BROKER_EXTERN void setLastNodeFailure(); - QPID_BROKER_EXTERN void clearLastNodeFailure(); - - bool enqueue(TransactionContext* ctxt, boost::intrusive_ptr<Message>& msg, bool suppressPolicyCheck = false); - void enqueueAborted(boost::intrusive_ptr<Message> msg); - /** - * dequeue from store (only done once messages is acknowledged) - */ - QPID_BROKER_EXTERN bool dequeue(TransactionContext* ctxt, const QueuedMessage &msg); - /** - * Inform the queue that a previous transactional dequeue - * committed. - */ - void dequeueCommitted(const QueuedMessage& msg); - - /** - * Inform queue of messages that were enqueued, have since - * been acquired but not yet accepted or released (and - * thus are still logically on the queue) - used in - * clustered broker. - */ - void updateEnqueued(const QueuedMessage& msg); - - /** - * Test whether the specified message (identified by its - * sequence/position), is still enqueued (note this - * doesn't mean it is available for delivery as it may - * have been delievered to a subscriber who has not yet - * accepted it). - */ - bool isEnqueued(const QueuedMessage& msg); - - /** - * Gets the next available message - */ - QPID_BROKER_EXTERN QueuedMessage get(); - - /** Get the message at position pos */ - QPID_BROKER_EXTERN QueuedMessage find(framing::SequenceNumber pos) const; - - const QueuePolicy* getPolicy(); - - void setAlternateExchange(boost::shared_ptr<Exchange> exchange); - boost::shared_ptr<Exchange> getAlternateExchange(); - bool isLocal(boost::intrusive_ptr<Message>& msg); - - //PersistableQueue support: - uint64_t getPersistenceId() const; - void setPersistenceId(uint64_t persistenceId) const; - void encode(framing::Buffer& buffer) const; - uint32_t encodedSize() const; - - /** - * Restores a queue from encoded data (used in recovery) - * - * Note: restored queue will be neither auto-deleted or have an - * exclusive owner - */ - static Queue::shared_ptr restore(QueueRegistry& queues, framing::Buffer& buffer); - static void tryAutoDelete(Broker& broker, Queue::shared_ptr); - - virtual void setExternalQueueStore(ExternalQueueStore* inst); - - // Manageable entry points - management::ManagementObject* GetManagementObject (void) const; - management::Manageable::status_t - ManagementMethod (uint32_t methodId, management::Args& args, std::string& text); - - /** Apply f to each Message on the queue. */ - template <class F> void eachMessage(F f) { - sys::Mutex::ScopedLock l(messageLock); - messages->foreach(f); - } - - /** Apply f to each QueueBinding on the queue */ - template <class F> void eachBinding(F f) { - bindings.eachBinding(f); - } - - /** Apply f to each Observer on the queue */ - template <class F> void eachObserver(F f) { - std::for_each<Observers::iterator, F>(observers.begin(), observers.end(), f); - } - - /** Set the position sequence number for the next message on the queue. - * Must be >= the current sequence number. - * Used by cluster to replicate queues. - */ - QPID_BROKER_EXTERN void setPosition(framing::SequenceNumber pos); - /** return current position sequence number for the next message on the queue. - */ - QPID_BROKER_EXTERN framing::SequenceNumber getPosition(); - void addObserver(boost::shared_ptr<QueueObserver>); - QPID_BROKER_EXTERN void insertSequenceNumbers(const std::string& key); - /** - * Notify queue that recovery has completed. - */ - void recoveryComplete(ExchangeRegistry& exchanges); - - // For cluster update - QueueListeners& getListeners(); - Messages& getMessages(); - const Messages& getMessages() const; - - /** - * Reserve space in policy for an enqueued message that - * has been recovered in the prepared state (dtx only) - */ - void recoverPrepared(boost::intrusive_ptr<Message>& msg); - - void flush(); - - const Broker* getBroker(); -}; -} -} - - -#endif /*!_broker_Queue_h*/ diff --git a/cpp/src/qpid/broker/QueueBindings.cpp b/cpp/src/qpid/broker/QueueBindings.cpp deleted file mode 100644 index 60d315acfe..0000000000 --- a/cpp/src/qpid/broker/QueueBindings.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/Queue.h" -#include "qpid/broker/QueueBindings.h" -#include "qpid/broker/ExchangeRegistry.h" -#include "qpid/framing/reply_exceptions.h" - -using qpid::framing::FieldTable; -using qpid::framing::NotFoundException; -using std::string; -using namespace qpid::broker; - -void QueueBindings::add(const string& exchange, const string& key, const FieldTable& args) -{ - bindings.push_back(QueueBinding(exchange, key, args)); -} - -void QueueBindings::unbind(ExchangeRegistry& exchanges, Queue::shared_ptr queue) -{ - for (Bindings::iterator i = bindings.begin(); i != bindings.end(); i++) { - try { - exchanges.get(i->exchange)->unbind(queue, i->key, &(i->args)); - } catch (const NotFoundException&) {} - } -} - -QueueBinding::QueueBinding(const string& _exchange, const string& _key, const FieldTable& _args) - : exchange(_exchange), key(_key), args(_args) -{} diff --git a/cpp/src/qpid/broker/QueueBindings.h b/cpp/src/qpid/broker/QueueBindings.h deleted file mode 100644 index 1b90ba5540..0000000000 --- a/cpp/src/qpid/broker/QueueBindings.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _QueueBindings_ -#define _QueueBindings_ - -#include "qpid/framing/FieldTable.h" -#include <boost/ptr_container/ptr_list.hpp> -#include <boost/shared_ptr.hpp> -#include <algorithm> - -namespace qpid { -namespace broker { - -class ExchangeRegistry; -class Queue; - -struct QueueBinding{ - std::string exchange; - std::string key; - qpid::framing::FieldTable args; - QueueBinding(const std::string& exchange, const std::string& key, const qpid::framing::FieldTable& args); -}; - -class QueueBindings -{ - public: - - /** Apply f to each QueueBinding. */ - template <class F> void eachBinding(F f) const { std::for_each(bindings.begin(), bindings.end(), f); } - - void add(const std::string& exchange, const std::string& key, const qpid::framing::FieldTable& args); - void unbind(ExchangeRegistry& exchanges, boost::shared_ptr<Queue> queue); - - private: - typedef std::vector<QueueBinding> Bindings; - Bindings bindings; -}; - - -}} // namespace qpid::broker - - -#endif diff --git a/cpp/src/qpid/broker/QueueCleaner.cpp b/cpp/src/qpid/broker/QueueCleaner.cpp deleted file mode 100644 index 3499ea8a4d..0000000000 --- a/cpp/src/qpid/broker/QueueCleaner.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/Queue.h" -#include "qpid/broker/QueueCleaner.h" - -#include "qpid/broker/Broker.h" -#include <boost/bind.hpp> - -namespace qpid { -namespace broker { - -QueueCleaner::QueueCleaner(QueueRegistry& q, sys::Timer& t) : queues(q), timer(t) {} - -QueueCleaner::~QueueCleaner() -{ - if (task) task->cancel(); -} - -void QueueCleaner::start(qpid::sys::Duration p) -{ - task = new Task(*this, p); - timer.add(task); -} - -QueueCleaner::Task::Task(QueueCleaner& p, qpid::sys::Duration d) : sys::TimerTask(d,"QueueCleaner"), parent(p) {} - -void QueueCleaner::Task::fire() -{ - parent.fired(); -} - -namespace { -struct CollectQueues -{ - std::vector<Queue::shared_ptr>* queues; - CollectQueues(std::vector<Queue::shared_ptr>* q) : queues(q) {} - void operator()(Queue::shared_ptr q) - { - queues->push_back(q); - } -}; -} - -void QueueCleaner::fired() -{ - //collect copy of list of queues to avoid holding registry lock while we perform purge - std::vector<Queue::shared_ptr> copy; - CollectQueues collect(©); - queues.eachQueue(collect); - std::for_each(copy.begin(), copy.end(), boost::bind(&Queue::purgeExpired, _1)); - task->setupNextFire(); - timer.add(task); -} - - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/QueueCleaner.h b/cpp/src/qpid/broker/QueueCleaner.h deleted file mode 100644 index 11c2d180ac..0000000000 --- a/cpp/src/qpid/broker/QueueCleaner.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef QPID_BROKER_QUEUECLEANER_H -#define QPID_BROKER_QUEUECLEANER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/sys/Timer.h" - -namespace qpid { -namespace broker { - -class QueueRegistry; -/** - * TimerTask to purge expired messages from queues - */ -class QueueCleaner -{ - public: - QPID_BROKER_EXTERN QueueCleaner(QueueRegistry& queues, sys::Timer& timer); - QPID_BROKER_EXTERN ~QueueCleaner(); - QPID_BROKER_EXTERN void start(qpid::sys::Duration period); - private: - class Task : public sys::TimerTask - { - public: - Task(QueueCleaner& parent, qpid::sys::Duration duration); - void fire(); - private: - QueueCleaner& parent; - }; - - boost::intrusive_ptr<sys::TimerTask> task; - QueueRegistry& queues; - sys::Timer& timer; - - void fired(); -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_QUEUECLEANER_H*/ diff --git a/cpp/src/qpid/broker/QueueEvents.cpp b/cpp/src/qpid/broker/QueueEvents.cpp deleted file mode 100644 index 2c540ff1ad..0000000000 --- a/cpp/src/qpid/broker/QueueEvents.cpp +++ /dev/null @@ -1,147 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/QueueEvents.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/QueueObserver.h" -#include "qpid/Exception.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace broker { - -QueueEvents::QueueEvents(const boost::shared_ptr<sys::Poller>& poller, bool isSync) : - eventQueue(boost::bind(&QueueEvents::handle, this, _1), poller), enabled(true), sync(isSync) -{ - if (!sync) eventQueue.start(); -} - -QueueEvents::~QueueEvents() -{ - if (!sync) eventQueue.stop(); -} - -void QueueEvents::enqueued(const QueuedMessage& m) -{ - if (enabled) { - Event enq(ENQUEUE, m); - if (sync) { - for (Listeners::iterator j = listeners.begin(); j != listeners.end(); j++) - j->second(enq); - } else { - eventQueue.push(enq); - } - } -} - -void QueueEvents::dequeued(const QueuedMessage& m) -{ - if (enabled) { - Event deq(DEQUEUE, m); - if (sync) { - for (Listeners::iterator j = listeners.begin(); j != listeners.end(); j++) - j->second(deq); - } else { - eventQueue.push(Event(DEQUEUE, m)); - } - } -} - -void QueueEvents::registerListener(const std::string& id, const EventListener& listener) -{ - qpid::sys::Mutex::ScopedLock l(lock); - if (listeners.find(id) == listeners.end()) { - listeners[id] = listener; - } else { - throw Exception(QPID_MSG("Event listener already registered for '" << id << "'")); - } -} - -void QueueEvents::unregisterListener(const std::string& id) -{ - qpid::sys::Mutex::ScopedLock l(lock); - if (listeners.find(id) == listeners.end()) { - throw Exception(QPID_MSG("No event listener registered for '" << id << "'")); - } else { - listeners.erase(id); - } -} - -QueueEvents::EventQueue::Batch::const_iterator -QueueEvents::handle(const EventQueue::Batch& events) { - qpid::sys::Mutex::ScopedLock l(lock); - for (EventQueue::Batch::const_iterator i = events.begin(); i != events.end(); ++i) { - for (Listeners::iterator j = listeners.begin(); j != listeners.end(); j++) { - j->second(*i); - } - } - return events.end(); -} - -void QueueEvents::shutdown() -{ - if (!sync && !eventQueue.empty() && !listeners.empty()) eventQueue.shutdown(); -} - -void QueueEvents::enable() -{ - enabled = true; - QPID_LOG(debug, "Queue events enabled"); -} - -void QueueEvents::disable() -{ - enabled = false; - QPID_LOG(debug, "Queue events disabled"); -} - -bool QueueEvents::isSync() -{ - return sync; -} - -class EventGenerator : public QueueObserver -{ - public: - EventGenerator(QueueEvents& mgr, bool enqOnly) : manager(mgr), enqueueOnly(enqOnly) {} - void enqueued(const QueuedMessage& m) - { - manager.enqueued(m); - } - void dequeued(const QueuedMessage& m) - { - if (!enqueueOnly) manager.dequeued(m); - } - private: - QueueEvents& manager; - const bool enqueueOnly; -}; - -void QueueEvents::observe(Queue& queue, bool enqueueOnly) -{ - boost::shared_ptr<QueueObserver> observer(new EventGenerator(*this, enqueueOnly)); - queue.addObserver(observer); -} - - -QueueEvents::Event::Event(EventType t, const QueuedMessage& m) : type(t), msg(m) {} - - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/QueueEvents.h b/cpp/src/qpid/broker/QueueEvents.h deleted file mode 100644 index fcddfe9092..0000000000 --- a/cpp/src/qpid/broker/QueueEvents.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef QPID_BROKER_QUEUEEVENTS_H -#define QPID_BROKER_QUEUEEVENTS_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/QueuedMessage.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/PollableQueue.h" -#include <map> -#include <string> -#include <boost/function.hpp> - -namespace qpid { -namespace broker { - -/** - * Event manager for queue events. Allows queues to indicate when - * events have occured; allows listeners to register for notification - * of this. The notification happens asynchronously, in a separate - * thread. - */ -class QueueEvents -{ - public: - enum EventType {ENQUEUE, DEQUEUE}; - - struct Event - { - EventType type; - QueuedMessage msg; - - QPID_BROKER_EXTERN Event(EventType, const QueuedMessage&); - }; - - typedef boost::function<void (Event)> EventListener; - - QPID_BROKER_EXTERN QueueEvents(const boost::shared_ptr<sys::Poller>& poller, bool isSync = false); - QPID_BROKER_EXTERN ~QueueEvents(); - QPID_BROKER_EXTERN void enqueued(const QueuedMessage&); - QPID_BROKER_EXTERN void dequeued(const QueuedMessage&); - QPID_BROKER_EXTERN void registerListener(const std::string& id, - const EventListener&); - QPID_BROKER_EXTERN void unregisterListener(const std::string& id); - void enable(); - void disable(); - void observe(Queue&, bool enqueueOnly); - //process all outstanding events - QPID_BROKER_EXTERN void shutdown(); - QPID_BROKER_EXTERN bool isSync(); - private: - typedef qpid::sys::PollableQueue<Event> EventQueue; - typedef std::map<std::string, EventListener> Listeners; - - EventQueue eventQueue; - Listeners listeners; - volatile bool enabled; - qpid::sys::Mutex lock;//protect listeners from concurrent access - bool sync; - - EventQueue::Batch::const_iterator handle(const EventQueue::Batch& e); - -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_QUEUEEVENTS_H*/ diff --git a/cpp/src/qpid/broker/QueueFlowLimit.cpp b/cpp/src/qpid/broker/QueueFlowLimit.cpp deleted file mode 100644 index b2e2e54bdf..0000000000 --- a/cpp/src/qpid/broker/QueueFlowLimit.cpp +++ /dev/null @@ -1,407 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/QueueFlowLimit.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/Queue.h" -#include "qpid/Exception.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/Mutex.h" -#include "qpid/broker/SessionState.h" -#include "qpid/sys/ClusterSafe.h" - -#include "qmf/org/apache/qpid/broker/Queue.h" - -#include <sstream> - -using namespace qpid::broker; -using namespace qpid::framing; - -namespace { - /** ensure that the configured flow control stop and resume values are - * valid with respect to the maximum queue capacity, and each other - */ - template <typename T> - void validateFlowConfig(T max, T& stop, T& resume, const std::string& type, const std::string& queue) - { - if (resume > stop) { - throw InvalidArgumentException(QPID_MSG("Queue \"" << queue << "\": qpid.flow_resume_" << type - << "=" << resume - << " must be less than qpid.flow_stop_" << type - << "=" << stop)); - } - if (resume == 0) resume = stop; - if (max != 0 && (max < stop)) { - throw InvalidArgumentException(QPID_MSG("Queue \"" << queue << "\": qpid.flow_stop_" << type - << "=" << stop - << " must be less than qpid.max_" << type - << "=" << max)); - } - } - - /** extract a capacity value as passed in an argument map - */ - uint64_t getCapacity(const FieldTable& settings, const std::string& key, uint64_t defaultValue) - { - FieldTable::ValuePtr v = settings.get(key); - - int64_t result = 0; - - if (!v) return defaultValue; - if (v->getType() == 0x23) { - QPID_LOG(debug, "Value for " << key << " specified as float: " << v->get<float>()); - } else if (v->getType() == 0x33) { - QPID_LOG(debug, "Value for " << key << " specified as double: " << v->get<double>()); - } else if (v->convertsTo<int64_t>()) { - result = v->get<int64_t>(); - QPID_LOG(debug, "Got integer value for " << key << ": " << result); - if (result >= 0) return result; - } else if (v->convertsTo<string>()) { - string s(v->get<string>()); - QPID_LOG(debug, "Got string value for " << key << ": " << s); - std::istringstream convert(s); - if (convert >> result && result >= 0) return result; - } - - QPID_LOG(warning, "Cannot convert " << key << " to unsigned integer, using default (" << defaultValue << ")"); - return defaultValue; - } -} - - - -QueueFlowLimit::QueueFlowLimit(Queue *_queue, - uint32_t _flowStopCount, uint32_t _flowResumeCount, - uint64_t _flowStopSize, uint64_t _flowResumeSize) - : StatefulQueueObserver(std::string("QueueFlowLimit")), queue(_queue), queueName("<unknown>"), - flowStopCount(_flowStopCount), flowResumeCount(_flowResumeCount), - flowStopSize(_flowStopSize), flowResumeSize(_flowResumeSize), - flowStopped(false), count(0), size(0), queueMgmtObj(0), broker(0) -{ - uint32_t maxCount(0); - uint64_t maxSize(0); - - if (queue) { - queueName = _queue->getName(); - if (queue->getPolicy()) { - maxSize = _queue->getPolicy()->getMaxSize(); - maxCount = _queue->getPolicy()->getMaxCount(); - } - broker = queue->getBroker(); - queueMgmtObj = dynamic_cast<_qmfBroker::Queue*> (queue->GetManagementObject()); - if (queueMgmtObj) { - queueMgmtObj->set_flowStopped(isFlowControlActive()); - } - } - validateFlowConfig( maxCount, flowStopCount, flowResumeCount, "count", queueName ); - validateFlowConfig( maxSize, flowStopSize, flowResumeSize, "size", queueName ); - QPID_LOG(info, "Queue \"" << queueName << "\": Flow limit created: flowStopCount=" << flowStopCount - << ", flowResumeCount=" << flowResumeCount - << ", flowStopSize=" << flowStopSize << ", flowResumeSize=" << flowResumeSize ); -} - - -QueueFlowLimit::~QueueFlowLimit() -{ - sys::Mutex::ScopedLock l(indexLock); - if (!index.empty()) { - // we're gone - release all pending msgs - for (std::map<framing::SequenceNumber, boost::intrusive_ptr<Message> >::iterator itr = index.begin(); - itr != index.end(); ++itr) - if (itr->second) - try { - itr->second->getIngressCompletion().finishCompleter(); - } catch (...) {} // ignore - not safe for a destructor to throw. - index.clear(); - } -} - - -void QueueFlowLimit::enqueued(const QueuedMessage& msg) -{ - sys::Mutex::ScopedLock l(indexLock); - - ++count; - size += msg.payload->contentSize(); - - if (!flowStopped) { - if (flowStopCount && count > flowStopCount) { - flowStopped = true; - QPID_LOG(info, "Queue \"" << queueName << "\": has reached " << flowStopCount << " enqueued messages. Producer flow control activated." ); - } else if (flowStopSize && size > flowStopSize) { - flowStopped = true; - QPID_LOG(info, "Queue \"" << queueName << "\": has reached " << flowStopSize << " enqueued bytes. Producer flow control activated." ); - } - if (flowStopped && queueMgmtObj) { - queueMgmtObj->set_flowStopped(true); - queueMgmtObj->inc_flowStoppedCount(); - } - } - - if (flowStopped || !index.empty()) { - // ignore flow control if we are populating the queue due to cluster replication: - if (broker && broker->isClusterUpdatee()) { - QPID_LOG(trace, "Queue \"" << queueName << "\": ignoring flow control for msg pos=" << msg.position); - return; - } - QPID_LOG(trace, "Queue \"" << queueName << "\": setting flow control for msg pos=" << msg.position); - msg.payload->getIngressCompletion().startCompleter(); // don't complete until flow resumes - bool unique; - unique = index.insert(std::pair<framing::SequenceNumber, boost::intrusive_ptr<Message> >(msg.position, msg.payload)).second; - assert(unique); - } -} - - - -void QueueFlowLimit::dequeued(const QueuedMessage& msg) -{ - sys::Mutex::ScopedLock l(indexLock); - - if (count > 0) { - --count; - } else { - throw Exception(QPID_MSG("Flow limit count underflow on dequeue. Queue=" << queueName)); - } - - uint64_t _size = msg.payload->contentSize(); - if (_size <= size) { - size -= _size; - } else { - throw Exception(QPID_MSG("Flow limit size underflow on dequeue. Queue=" << queueName)); - } - - if (flowStopped && - (flowResumeSize == 0 || size < flowResumeSize) && - (flowResumeCount == 0 || count < flowResumeCount)) { - flowStopped = false; - if (queueMgmtObj) - queueMgmtObj->set_flowStopped(false); - QPID_LOG(info, "Queue \"" << queueName << "\": has drained below the flow control resume level. Producer flow control deactivated." ); - } - - if (!index.empty()) { - if (!flowStopped) { - // flow enabled - release all pending msgs - for (std::map<framing::SequenceNumber, boost::intrusive_ptr<Message> >::iterator itr = index.begin(); - itr != index.end(); ++itr) - if (itr->second) - itr->second->getIngressCompletion().finishCompleter(); - index.clear(); - } else { - // even if flow controlled, we must release this msg as it is being dequeued - std::map<framing::SequenceNumber, boost::intrusive_ptr<Message> >::iterator itr = index.find(msg.position); - if (itr != index.end()) { // this msg is flow controlled, release it: - msg.payload->getIngressCompletion().finishCompleter(); - index.erase(itr); - } - } - } -} - - -void QueueFlowLimit::encode(Buffer& buffer) const -{ - buffer.putLong(flowStopCount); - buffer.putLong(flowResumeCount); - buffer.putLongLong(flowStopSize); - buffer.putLongLong(flowResumeSize); - buffer.putLong(count); - buffer.putLongLong(size); -} - - -void QueueFlowLimit::decode ( Buffer& buffer ) -{ - flowStopCount = buffer.getLong(); - flowResumeCount = buffer.getLong(); - flowStopSize = buffer.getLongLong(); - flowResumeSize = buffer.getLongLong(); - count = buffer.getLong(); - size = buffer.getLongLong(); -} - - -uint32_t QueueFlowLimit::encodedSize() const { - return sizeof(uint32_t) + // flowStopCount - sizeof(uint32_t) + // flowResumecount - sizeof(uint64_t) + // flowStopSize - sizeof(uint64_t) + // flowResumeSize - sizeof(uint32_t) + // count - sizeof(uint64_t); // size -} - - -const std::string QueueFlowLimit::flowStopCountKey("qpid.flow_stop_count"); -const std::string QueueFlowLimit::flowResumeCountKey("qpid.flow_resume_count"); -const std::string QueueFlowLimit::flowStopSizeKey("qpid.flow_stop_size"); -const std::string QueueFlowLimit::flowResumeSizeKey("qpid.flow_resume_size"); -uint64_t QueueFlowLimit::defaultMaxSize; -uint QueueFlowLimit::defaultFlowStopRatio; -uint QueueFlowLimit::defaultFlowResumeRatio; - - -void QueueFlowLimit::setDefaults(uint64_t maxQueueSize, uint flowStopRatio, uint flowResumeRatio) -{ - defaultMaxSize = maxQueueSize; - defaultFlowStopRatio = flowStopRatio; - defaultFlowResumeRatio = flowResumeRatio; - - /** @todo KAG: Verify valid range on Broker::Options instead of here */ - if (flowStopRatio > 100 || flowResumeRatio > 100) - throw InvalidArgumentException(QPID_MSG("Default queue flow ratios must be between 0 and 100, inclusive:" - << " flowStopRatio=" << flowStopRatio - << " flowResumeRatio=" << flowResumeRatio)); - if (flowResumeRatio > flowStopRatio) - throw InvalidArgumentException(QPID_MSG("Default queue flow stop ratio must be >= flow resume ratio:" - << " flowStopRatio=" << flowStopRatio - << " flowResumeRatio=" << flowResumeRatio)); -} - - -void QueueFlowLimit::observe(Queue& queue, const qpid::framing::FieldTable& settings) -{ - QueueFlowLimit *ptr = createLimit( &queue, settings ); - if (ptr) { - boost::shared_ptr<QueueFlowLimit> observer(ptr); - queue.addObserver(observer); - } -} - -/** returns ptr to a QueueFlowLimit, else 0 if no limit */ -QueueFlowLimit *QueueFlowLimit::createLimit(Queue *queue, const qpid::framing::FieldTable& settings) -{ - std::string type(QueuePolicy::getType(settings)); - - if (type == QueuePolicy::RING || type == QueuePolicy::RING_STRICT) { - // The size of a RING queue is limited by design - no need for flow control. - return 0; - } - - if (settings.get(flowStopCountKey) || settings.get(flowStopSizeKey) || - settings.get(flowResumeCountKey) || settings.get(flowResumeSizeKey)) { - // user provided (some) flow settings manually... - uint32_t flowStopCount = getCapacity(settings, flowStopCountKey, 0); - uint32_t flowResumeCount = getCapacity(settings, flowResumeCountKey, 0); - uint64_t flowStopSize = getCapacity(settings, flowStopSizeKey, 0); - uint64_t flowResumeSize = getCapacity(settings, flowResumeSizeKey, 0); - if (flowStopCount == 0 && flowStopSize == 0) { // disable flow control - return 0; - } - return new QueueFlowLimit(queue, flowStopCount, flowResumeCount, flowStopSize, flowResumeSize); - } - - if (defaultFlowStopRatio) { // broker has a default ratio setup... - uint64_t maxByteCount = getCapacity(settings, QueuePolicy::maxSizeKey, defaultMaxSize); - uint64_t flowStopSize = (uint64_t)(maxByteCount * (defaultFlowStopRatio/100.0) + 0.5); - uint64_t flowResumeSize = (uint64_t)(maxByteCount * (defaultFlowResumeRatio/100.0)); - uint32_t maxMsgCount = getCapacity(settings, QueuePolicy::maxCountKey, 0); // no size by default - uint32_t flowStopCount = (uint32_t)(maxMsgCount * (defaultFlowStopRatio/100.0) + 0.5); - uint32_t flowResumeCount = (uint32_t)(maxMsgCount * (defaultFlowResumeRatio/100.0)); - - return new QueueFlowLimit(queue, flowStopCount, flowResumeCount, flowStopSize, flowResumeSize); - } - return 0; -} - -/* Cluster replication */ - -namespace { - /** pack a set of sequence number ranges into a framing::Array */ - void buildSeqRangeArray(qpid::framing::Array *seqs, - const qpid::framing::SequenceNumber& first, - const qpid::framing::SequenceNumber& last) - { - seqs->push_back(qpid::framing::Array::ValuePtr(new Unsigned32Value(first))); - seqs->push_back(qpid::framing::Array::ValuePtr(new Unsigned32Value(last))); - } -} - -/** Runs on UPDATER to snapshot current state */ -void QueueFlowLimit::getState(qpid::framing::FieldTable& state ) const -{ - sys::Mutex::ScopedLock l(indexLock); - state.clear(); - - framing::SequenceSet ss; - if (!index.empty()) { - /* replicate the set of messages pending flow control */ - for (std::map<framing::SequenceNumber, boost::intrusive_ptr<Message> >::const_iterator itr = index.begin(); - itr != index.end(); ++itr) { - ss.add(itr->first); - } - framing::Array seqs(TYPE_CODE_UINT32); - typedef boost::function<void(framing::SequenceNumber, framing::SequenceNumber)> arrayBuilder; - ss.for_each((arrayBuilder)boost::bind(&buildSeqRangeArray, &seqs, _1, _2)); - state.setArray("pendingMsgSeqs", seqs); - } - QPID_LOG(debug, "Queue \"" << queueName << "\": flow limit replicating pending msgs, range=" << ss); -} - - -/** called on UPDATEE to set state from snapshot */ -void QueueFlowLimit::setState(const qpid::framing::FieldTable& state) -{ - sys::Mutex::ScopedLock l(indexLock); - index.clear(); - - framing::SequenceSet fcmsg; - framing::Array seqArray(TYPE_CODE_UINT32); - if (state.getArray("pendingMsgSeqs", seqArray)) { - assert((seqArray.count() & 0x01) == 0); // must be even since they are sequence ranges - framing::Array::const_iterator i = seqArray.begin(); - while (i != seqArray.end()) { - framing::SequenceNumber first((*i)->getIntegerValue<uint32_t, 4>()); - ++i; - framing::SequenceNumber last((*i)->getIntegerValue<uint32_t, 4>()); - ++i; - fcmsg.add(first, last); - for (SequenceNumber seq = first; seq <= last; ++seq) { - QueuedMessage msg(queue->find(seq)); // fyi: msg.payload may be null if msg is delivered & unacked - bool unique; - unique = index.insert(std::pair<framing::SequenceNumber, boost::intrusive_ptr<Message> >(seq, msg.payload)).second; - assert(unique); - } - } - } - - flowStopped = index.size() != 0; - if (queueMgmtObj) { - queueMgmtObj->set_flowStopped(isFlowControlActive()); - } - QPID_LOG(debug, "Queue \"" << queueName << "\": flow limit replicated the pending msgs, range=" << fcmsg) -} - - -namespace qpid { - namespace broker { - -std::ostream& operator<<(std::ostream& out, const QueueFlowLimit& f) -{ - out << "; flowStopCount=" << f.flowStopCount << ", flowResumeCount=" << f.flowResumeCount; - out << "; flowStopSize=" << f.flowStopSize << ", flowResumeSize=" << f.flowResumeSize; - return out; -} - - } -} - diff --git a/cpp/src/qpid/broker/QueueFlowLimit.h b/cpp/src/qpid/broker/QueueFlowLimit.h deleted file mode 100644 index c02e479976..0000000000 --- a/cpp/src/qpid/broker/QueueFlowLimit.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _QueueFlowLimit_ -#define _QueueFlowLimit_ - -#include <list> -#include <set> -#include <iostream> -#include <memory> -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/QueuedMessage.h" -#include "qpid/broker/StatefulQueueObserver.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/sys/AtomicValue.h" -#include "qpid/sys/Mutex.h" - -namespace qmf { -namespace org { -namespace apache { -namespace qpid { -namespace broker { - class Queue; -}}}}} -namespace _qmfBroker = qmf::org::apache::qpid::broker; - -namespace qpid { -namespace broker { - -class Broker; - -/** - * Producer flow control: when level is > flowStop*, flow control is ON. - * then level is < flowResume*, flow control is OFF. If == 0, flow control - * is not used. If both byte and msg count thresholds are set, then - * passing _either_ level may turn flow control ON, but _both_ must be - * below level before flow control will be turned OFF. - */ - class QueueFlowLimit : public StatefulQueueObserver -{ - static uint64_t defaultMaxSize; - static uint defaultFlowStopRatio; - static uint defaultFlowResumeRatio; - - Queue *queue; - std::string queueName; - - uint32_t flowStopCount; - uint32_t flowResumeCount; - uint64_t flowStopSize; - uint64_t flowResumeSize; - bool flowStopped; // true = producers held in flow control - - // current queue utilization - uint32_t count; - uint64_t size; - - public: - static QPID_BROKER_EXTERN const std::string flowStopCountKey; - static QPID_BROKER_EXTERN const std::string flowResumeCountKey; - static QPID_BROKER_EXTERN const std::string flowStopSizeKey; - static QPID_BROKER_EXTERN const std::string flowResumeSizeKey; - - QPID_BROKER_EXTERN virtual ~QueueFlowLimit(); - - /** the queue has added QueuedMessage. Returns true if flow state changes */ - QPID_BROKER_EXTERN void enqueued(const QueuedMessage&); - /** the queue has removed QueuedMessage. Returns true if flow state changes */ - QPID_BROKER_EXTERN void dequeued(const QueuedMessage&); - - /** for clustering: */ - QPID_BROKER_EXTERN void getState(qpid::framing::FieldTable&) const; - QPID_BROKER_EXTERN void setState(const qpid::framing::FieldTable&); - - uint32_t getFlowStopCount() const { return flowStopCount; } - uint32_t getFlowResumeCount() const { return flowResumeCount; } - uint64_t getFlowStopSize() const { return flowStopSize; } - uint64_t getFlowResumeSize() const { return flowResumeSize; } - - uint32_t getFlowCount() const { return count; } - uint64_t getFlowSize() const { return size; } - bool isFlowControlActive() const { return flowStopped; } - bool monitorFlowControl() const { return flowStopCount || flowStopSize; } - - void encode(framing::Buffer& buffer) const; - void decode(framing::Buffer& buffer); - uint32_t encodedSize() const; - - static QPID_BROKER_EXTERN void observe(Queue& queue, const qpid::framing::FieldTable& settings); - static QPID_BROKER_EXTERN void setDefaults(uint64_t defaultMaxSize, uint defaultFlowStopRatio, uint defaultFlowResumeRatio); - - friend QPID_BROKER_EXTERN std::ostream& operator<<(std::ostream&, const QueueFlowLimit&); - - protected: - // msgs waiting for flow to become available. - std::map<framing::SequenceNumber, boost::intrusive_ptr<Message> > index; - mutable qpid::sys::Mutex indexLock; - - _qmfBroker::Queue *queueMgmtObj; - - const Broker *broker; - - QPID_BROKER_EXTERN QueueFlowLimit(Queue *queue, - uint32_t flowStopCount, uint32_t flowResumeCount, - uint64_t flowStopSize, uint64_t flowResumeSize); - static QPID_BROKER_EXTERN QueueFlowLimit *createLimit(Queue *queue, const qpid::framing::FieldTable& settings); -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/QueueListeners.cpp b/cpp/src/qpid/broker/QueueListeners.cpp deleted file mode 100644 index 591f4443bb..0000000000 --- a/cpp/src/qpid/broker/QueueListeners.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/QueueListeners.h" -#include <boost/bind.hpp> - -namespace qpid { -namespace broker { - -void QueueListeners::addListener(Consumer::shared_ptr c) -{ - if (!c->inListeners) { - if (c->acquires) { - add(consumers, c); - } else { - add(browsers, c); - } - c->inListeners = true; - } -} - -void QueueListeners::removeListener(Consumer::shared_ptr c) -{ - if (c->inListeners) { - if (c->acquires) { - remove(consumers, c); - } else { - remove(browsers, c); - } - c->inListeners = false; - } -} - -void QueueListeners::populate(NotificationSet& set) -{ - if (consumers.size()) { - set.consumer = consumers.front(); - consumers.pop_front(); - set.consumer->inListeners = false; - } else { - // Don't swap the deques, hang on to the memory allocated. - set.browsers = browsers; - browsers.clear(); - for (Listeners::iterator i = set.browsers.begin(); i != set.browsers.end(); i++) - (*i)->inListeners = false; - } -} - -void QueueListeners::add(Listeners& listeners, Consumer::shared_ptr c) -{ - listeners.push_back(c); -} - -void QueueListeners::remove(Listeners& listeners, Consumer::shared_ptr c) -{ - Listeners::iterator i = std::find(listeners.begin(), listeners.end(), c); - if (i != listeners.end()) listeners.erase(i); -} - -void QueueListeners::NotificationSet::notify() -{ - if (consumer) consumer->notify(); - else std::for_each(browsers.begin(), browsers.end(), boost::mem_fn(&Consumer::notify)); -} - -bool QueueListeners::contains(Consumer::shared_ptr c) const { - return c->inListeners; -} - -void QueueListeners::ListenerSet::notifyAll() -{ - std::for_each(listeners.begin(), listeners.end(), boost::mem_fn(&Consumer::notify)); -} - -void QueueListeners::snapshot(ListenerSet& set) -{ - set.listeners.insert(set.listeners.end(), consumers.begin(), consumers.end()); - set.listeners.insert(set.listeners.end(), browsers.begin(), browsers.end()); -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/QueueListeners.h b/cpp/src/qpid/broker/QueueListeners.h deleted file mode 100644 index 0659499253..0000000000 --- a/cpp/src/qpid/broker/QueueListeners.h +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef QPID_BROKER_QUEUELISTENERS_H -#define QPID_BROKER_QUEUELISTENERS_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/Consumer.h" -#include <deque> - -namespace qpid { -namespace broker { - -/** - * Track and notify components that wish to be notified of messages - * that become available on a queue. - * - * None of the methods defined here are protected by locking. However - * the populate method allows a 'snapshot' to be taken of the - * listeners to be notified. NotificationSet::notify() may then be - * called outside of any lock that protects the QueueListeners - * instance from concurrent access. - */ -class QueueListeners -{ - public: - typedef std::deque<Consumer::shared_ptr> Listeners; - - class NotificationSet - { - public: - void notify(); - private: - Listeners browsers; - Consumer::shared_ptr consumer; - friend class QueueListeners; - }; - - class ListenerSet - { - public: - void notifyAll(); - private: - Listeners listeners; - friend class QueueListeners; - }; - - void addListener(Consumer::shared_ptr); - void removeListener(Consumer::shared_ptr); - void populate(NotificationSet&); - void snapshot(ListenerSet&); - bool contains(Consumer::shared_ptr c) const; - void notifyAll(); - - template <class F> void eachListener(F f) { - std::for_each(browsers.begin(), browsers.end(), f); - std::for_each(consumers.begin(), consumers.end(), f); - } - - private: - Listeners consumers; - Listeners browsers; - - void add(Listeners&, Consumer::shared_ptr); - void remove(Listeners&, Consumer::shared_ptr); - -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_QUEUELISTENERS_H*/ diff --git a/cpp/src/qpid/broker/QueueObserver.h b/cpp/src/qpid/broker/QueueObserver.h deleted file mode 100644 index 3ca01c051e..0000000000 --- a/cpp/src/qpid/broker/QueueObserver.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef QPID_BROKER_QUEUEOBSERVER_H -#define QPID_BROKER_QUEUEOBSERVER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -namespace qpid { -namespace broker { - -struct QueuedMessage; -/** - * Interface for notifying classes who want to act as 'observers' of a - * queue of particular events. - */ -class QueueObserver -{ - public: - virtual ~QueueObserver() {} - virtual void enqueued(const QueuedMessage&) = 0; - virtual void dequeued(const QueuedMessage&) = 0; - private: -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_QUEUEOBSERVER_H*/ diff --git a/cpp/src/qpid/broker/QueuePolicy.cpp b/cpp/src/qpid/broker/QueuePolicy.cpp deleted file mode 100644 index a93a6332fd..0000000000 --- a/cpp/src/qpid/broker/QueuePolicy.cpp +++ /dev/null @@ -1,360 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/QueuePolicy.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/PriorityQueue.h" -#include "qpid/Exception.h" -#include "qpid/framing/FieldValue.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/log/Statement.h" -#include <sstream> - -using namespace qpid::broker; -using namespace qpid::framing; - -QueuePolicy::QueuePolicy(const std::string& _name, uint32_t _maxCount, uint64_t _maxSize, const std::string& _type) : - maxCount(_maxCount), maxSize(_maxSize), type(_type), count(0), size(0), policyExceeded(false), name(_name) { - QPID_LOG(info, "Queue \"" << name << "\": Policy created: type=" << type << "; maxCount=" << maxCount << "; maxSize=" << maxSize); -} - -void QueuePolicy::enqueued(uint64_t _size) -{ - if (maxCount) ++count; - if (maxSize) size += _size; -} - -void QueuePolicy::dequeued(uint64_t _size) -{ - if (maxCount) { - if (count > 0) { - --count; - } else { - throw Exception(QPID_MSG("Attempted count underflow on dequeue(" << _size << "): " << *this)); - } - } - if (maxSize) { - if (_size > size) { - throw Exception(QPID_MSG("Attempted size underflow on dequeue(" << _size << "): " << *this)); - } else { - size -= _size; - } - } -} - -bool QueuePolicy::checkLimit(boost::intrusive_ptr<Message> m) -{ - bool sizeExceeded = maxSize && (size + m->contentSize()) > maxSize; - bool countExceeded = maxCount && (count + 1) > maxCount; - bool exceeded = sizeExceeded || countExceeded; - if (exceeded) { - if (!policyExceeded) { - policyExceeded = true; - if (sizeExceeded) QPID_LOG(info, "Queue cumulative message size exceeded policy for " << name); - if (countExceeded) QPID_LOG(info, "Queue message count exceeded policy for " << name); - } - } else { - if (policyExceeded) { - policyExceeded = false; - QPID_LOG(info, "Queue cumulative message size and message count within policy for " << name); - } - } - return !exceeded; -} - -void QueuePolicy::tryEnqueue(boost::intrusive_ptr<Message> m) -{ - if (checkLimit(m)) { - enqueued(m->contentSize()); - } else { - throw ResourceLimitExceededException(QPID_MSG("Policy exceeded on " << name << ", policy: " << *this)); - } -} - -void QueuePolicy::recoverEnqueued(boost::intrusive_ptr<Message> m) -{ - tryEnqueue(m); -} - -void QueuePolicy::enqueueAborted(boost::intrusive_ptr<Message> m) -{ - dequeued(m->contentSize()); -} - -void QueuePolicy::enqueued(const QueuedMessage&) {} - -void QueuePolicy::dequeued(const QueuedMessage& m) -{ - dequeued(m.payload->contentSize()); -} - -bool QueuePolicy::isEnqueued(const QueuedMessage&) -{ - return true; -} - -void QueuePolicy::update(FieldTable& settings) -{ - if (maxCount) settings.setInt(maxCountKey, maxCount); - if (maxSize) settings.setInt(maxSizeKey, maxSize); - settings.setString(typeKey, type); -} - -uint32_t QueuePolicy::getCapacity(const FieldTable& settings, const std::string& key, uint32_t defaultValue) -{ - FieldTable::ValuePtr v = settings.get(key); - - int32_t result = 0; - - if (!v) return defaultValue; - if (v->getType() == 0x23) { - QPID_LOG(debug, "Value for " << key << " specified as float: " << v->get<float>()); - } else if (v->getType() == 0x33) { - QPID_LOG(debug, "Value for " << key << " specified as double: " << v->get<double>()); - } else if (v->convertsTo<int>()) { - result = v->get<int>(); - QPID_LOG(debug, "Got integer value for " << key << ": " << result); - if (result >= 0) return result; - } else if (v->convertsTo<string>()) { - string s(v->get<string>()); - QPID_LOG(debug, "Got string value for " << key << ": " << s); - std::istringstream convert(s); - if (convert >> result && result >= 0 && convert.eof()) return result; - } - - throw IllegalArgumentException(QPID_MSG("Cannot convert " << key << " to unsigned integer: " << *v)); -} - -std::string QueuePolicy::getType(const FieldTable& settings) -{ - FieldTable::ValuePtr v = settings.get(typeKey); - if (v && v->convertsTo<std::string>()) { - std::string t = v->get<std::string>(); - std::transform(t.begin(), t.end(), t.begin(), tolower); - if (t == REJECT || t == FLOW_TO_DISK || t == RING || t == RING_STRICT) return t; - } - return REJECT; -} - -void QueuePolicy::setDefaultMaxSize(uint64_t s) -{ - defaultMaxSize = s; -} - -void QueuePolicy::getPendingDequeues(Messages&) {} - - - - -void QueuePolicy::encode(Buffer& buffer) const -{ - buffer.putLong(maxCount); - buffer.putLongLong(maxSize); - buffer.putLong(count); - buffer.putLongLong(size); -} - -void QueuePolicy::decode ( Buffer& buffer ) -{ - maxCount = buffer.getLong(); - maxSize = buffer.getLongLong(); - count = buffer.getLong(); - size = buffer.getLongLong(); -} - - -uint32_t QueuePolicy::encodedSize() const { - return sizeof(uint32_t) + // maxCount - sizeof(uint64_t) + // maxSize - sizeof(uint32_t) + // count - sizeof(uint64_t); // size -} - - - -const std::string QueuePolicy::maxCountKey("qpid.max_count"); -const std::string QueuePolicy::maxSizeKey("qpid.max_size"); -const std::string QueuePolicy::typeKey("qpid.policy_type"); -const std::string QueuePolicy::REJECT("reject"); -const std::string QueuePolicy::FLOW_TO_DISK("flow_to_disk"); -const std::string QueuePolicy::RING("ring"); -const std::string QueuePolicy::RING_STRICT("ring_strict"); -uint64_t QueuePolicy::defaultMaxSize(0); - -FlowToDiskPolicy::FlowToDiskPolicy(const std::string& _name, uint32_t _maxCount, uint64_t _maxSize) : - QueuePolicy(_name, _maxCount, _maxSize, FLOW_TO_DISK) {} - -bool FlowToDiskPolicy::checkLimit(boost::intrusive_ptr<Message> m) -{ - if (!QueuePolicy::checkLimit(m)) m->requestContentRelease(); - return true; -} - -RingQueuePolicy::RingQueuePolicy(const std::string& _name, - uint32_t _maxCount, uint64_t _maxSize, const std::string& _type) : - QueuePolicy(_name, _maxCount, _maxSize, _type), strict(_type == RING_STRICT) {} - -bool before(const QueuedMessage& a, const QueuedMessage& b) -{ - int priorityA = PriorityQueue::getPriority(a); - int priorityB = PriorityQueue::getPriority(b); - if (priorityA == priorityB) return a.position < b.position; - else return priorityA < priorityB; -} - -void RingQueuePolicy::enqueued(const QueuedMessage& m) -{ - //need to insert in correct location based on position - queue.insert(lower_bound(queue.begin(), queue.end(), m, before), m); -} - -void RingQueuePolicy::dequeued(const QueuedMessage& m) -{ - //find and remove m from queue - if (find(m, pendingDequeues, true) || find(m, queue, true)) { - //now update count and size - QueuePolicy::dequeued(m); - } -} - -bool RingQueuePolicy::isEnqueued(const QueuedMessage& m) -{ - //for non-strict ring policy, a message can be replaced (and - //therefore dequeued) before it is accepted or released by - //subscriber; need to detect this - return find(m, pendingDequeues, false) || find(m, queue, false); -} - -bool RingQueuePolicy::checkLimit(boost::intrusive_ptr<Message> m) -{ - - // If the message is bigger than the queue size, give up - if (getMaxSize() && m->contentSize() > getMaxSize()) { - QPID_LOG(debug, "Message too large for ring queue " << name - << " [" << *this << "] " - << ": message size = " << m->contentSize() << " bytes" - << ": max queue size = " << getMaxSize() << " bytes"); - return false; - } - - // if within limits, ok to accept - if (QueuePolicy::checkLimit(m)) return true; - - // At this point, we've exceeded maxSize, maxCount, or both. - // - // If we've exceeded maxCount, we've exceeded it by 1, so - // replacing the first message is sufficient. If we've exceeded - // maxSize, we need to pop enough messages to get the space we - // need. - - unsigned int haveSpace = getMaxSize() - getCurrentQueueSize(); - - do { - QueuedMessage oldest = queue.front(); - - if (oldest.queue->acquire(oldest) || !strict) { - queue.pop_front(); - pendingDequeues.push_back(oldest); - QPID_LOG(debug, "Ring policy triggered in " << name - << ": removed message " << oldest.position << " to make way for new message"); - - haveSpace += oldest.payload->contentSize(); - - } else { - //in strict mode, if oldest message has been delivered (hence - //cannot be acquired) but not yet acked, it should not be - //removed and the attempted enqueue should fail - QPID_LOG(debug, "Ring policy could not be triggered in " << name - << ": oldest message (seq-no=" << oldest.position << ") has been delivered but not yet acknowledged or requeued"); - return false; - } - } while (haveSpace < m->contentSize()); - - - return true; -} - -void RingQueuePolicy::getPendingDequeues(Messages& result) -{ - result = pendingDequeues; -} - -bool RingQueuePolicy::find(const QueuedMessage& m, Messages& q, bool remove) -{ - for (Messages::iterator i = q.begin(); i != q.end(); i++) { - if (i->payload == m.payload) { - if (remove) q.erase(i); - return true; - } - } - return false; -} - -std::auto_ptr<QueuePolicy> QueuePolicy::createQueuePolicy(uint32_t maxCount, uint64_t maxSize, const std::string& type) -{ - return createQueuePolicy("<unspecified>", maxCount, maxSize, type); -} - -std::auto_ptr<QueuePolicy> QueuePolicy::createQueuePolicy(const qpid::framing::FieldTable& settings) -{ - return createQueuePolicy("<unspecified>", settings); -} - -std::auto_ptr<QueuePolicy> QueuePolicy::createQueuePolicy(const std::string& name, const qpid::framing::FieldTable& settings) -{ - uint32_t maxCount = getCapacity(settings, maxCountKey, 0); - uint32_t maxSize = getCapacity(settings, maxSizeKey, defaultMaxSize); - if (maxCount || maxSize) { - return createQueuePolicy(name, maxCount, maxSize, getType(settings)); - } else { - return std::auto_ptr<QueuePolicy>(); - } -} - -std::auto_ptr<QueuePolicy> QueuePolicy::createQueuePolicy(const std::string& name, - uint32_t maxCount, uint64_t maxSize, const std::string& type) -{ - if (type == RING || type == RING_STRICT) { - return std::auto_ptr<QueuePolicy>(new RingQueuePolicy(name, maxCount, maxSize, type)); - } else if (type == FLOW_TO_DISK) { - return std::auto_ptr<QueuePolicy>(new FlowToDiskPolicy(name, maxCount, maxSize)); - } else { - return std::auto_ptr<QueuePolicy>(new QueuePolicy(name, maxCount, maxSize, type)); - } - -} - -namespace qpid { - namespace broker { - -std::ostream& operator<<(std::ostream& out, const QueuePolicy& p) -{ - if (p.maxSize) out << "size: max=" << p.maxSize << ", current=" << p.size; - else out << "size: unlimited"; - out << "; "; - if (p.maxCount) out << "count: max=" << p.maxCount << ", current=" << p.count; - else out << "count: unlimited"; - out << "; type=" << p.type; - return out; -} - - } -} - diff --git a/cpp/src/qpid/broker/QueuePolicy.h b/cpp/src/qpid/broker/QueuePolicy.h deleted file mode 100644 index 3cdd63784d..0000000000 --- a/cpp/src/qpid/broker/QueuePolicy.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _QueuePolicy_ -#define _QueuePolicy_ - -#include <deque> -#include <iostream> -#include <memory> -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/QueuedMessage.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/sys/AtomicValue.h" -#include "qpid/sys/Mutex.h" - -namespace qpid { -namespace broker { - -class QueuePolicy -{ - static uint64_t defaultMaxSize; - - uint32_t maxCount; - uint64_t maxSize; - const std::string type; - uint32_t count; - uint64_t size; - bool policyExceeded; - - static uint32_t getCapacity(const qpid::framing::FieldTable& settings, const std::string& key, uint32_t defaultValue); - - protected: - uint64_t getCurrentQueueSize() const { return size; } - - public: - typedef std::deque<QueuedMessage> Messages; - static QPID_BROKER_EXTERN const std::string maxCountKey; - static QPID_BROKER_EXTERN const std::string maxSizeKey; - static QPID_BROKER_EXTERN const std::string typeKey; - static QPID_BROKER_EXTERN const std::string REJECT; - static QPID_BROKER_EXTERN const std::string FLOW_TO_DISK; - static QPID_BROKER_EXTERN const std::string RING; - static QPID_BROKER_EXTERN const std::string RING_STRICT; - - virtual ~QueuePolicy() {} - QPID_BROKER_EXTERN void tryEnqueue(boost::intrusive_ptr<Message> msg); - QPID_BROKER_EXTERN void recoverEnqueued(boost::intrusive_ptr<Message> msg); - QPID_BROKER_EXTERN void enqueueAborted(boost::intrusive_ptr<Message> msg); - virtual void enqueued(const QueuedMessage&); - virtual void dequeued(const QueuedMessage&); - virtual bool isEnqueued(const QueuedMessage&); - QPID_BROKER_EXTERN void update(qpid::framing::FieldTable& settings); - uint32_t getMaxCount() const { return maxCount; } - uint64_t getMaxSize() const { return maxSize; } - void encode(framing::Buffer& buffer) const; - void decode ( framing::Buffer& buffer ); - uint32_t encodedSize() const; - virtual void getPendingDequeues(Messages& result); - - static QPID_BROKER_EXTERN std::auto_ptr<QueuePolicy> createQueuePolicy(const std::string& name, const qpid::framing::FieldTable& settings); - static QPID_BROKER_EXTERN std::auto_ptr<QueuePolicy> createQueuePolicy(const std::string& name, uint32_t maxCount, uint64_t maxSize, const std::string& type = REJECT); - static QPID_BROKER_EXTERN std::auto_ptr<QueuePolicy> createQueuePolicy(const qpid::framing::FieldTable& settings); - static QPID_BROKER_EXTERN std::auto_ptr<QueuePolicy> createQueuePolicy(uint32_t maxCount, uint64_t maxSize, const std::string& type = REJECT); - static std::string getType(const qpid::framing::FieldTable& settings); - static void setDefaultMaxSize(uint64_t); - friend QPID_BROKER_EXTERN std::ostream& operator<<(std::ostream&, - const QueuePolicy&); - protected: - const std::string name; - - QueuePolicy(const std::string& name, uint32_t maxCount, uint64_t maxSize, const std::string& type = REJECT); - - virtual bool checkLimit(boost::intrusive_ptr<Message> msg); - void enqueued(uint64_t size); - void dequeued(uint64_t size); -}; - - -class FlowToDiskPolicy : public QueuePolicy -{ - public: - FlowToDiskPolicy(const std::string& name, uint32_t maxCount, uint64_t maxSize); - bool checkLimit(boost::intrusive_ptr<Message> msg); -}; - -class RingQueuePolicy : public QueuePolicy -{ - public: - RingQueuePolicy(const std::string& name, uint32_t maxCount, uint64_t maxSize, const std::string& type = RING); - void enqueued(const QueuedMessage&); - void dequeued(const QueuedMessage&); - bool isEnqueued(const QueuedMessage&); - bool checkLimit(boost::intrusive_ptr<Message> msg); - void getPendingDequeues(Messages& result); - private: - Messages pendingDequeues; - Messages queue; - const bool strict; - - bool find(const QueuedMessage&, Messages&, bool remove); -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/QueueRegistry.cpp b/cpp/src/qpid/broker/QueueRegistry.cpp deleted file mode 100644 index 135a3543d9..0000000000 --- a/cpp/src/qpid/broker/QueueRegistry.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/Queue.h" -#include "qpid/broker/QueueRegistry.h" -#include "qpid/broker/QueueEvents.h" -#include "qpid/broker/Exchange.h" -#include "qpid/log/Statement.h" -#include <sstream> -#include <assert.h> - -using namespace qpid::broker; -using namespace qpid::sys; -using std::string; - -QueueRegistry::QueueRegistry(Broker* b) : - counter(1), store(0), events(0), parent(0), lastNode(false), broker(b) {} - -QueueRegistry::~QueueRegistry(){} - -std::pair<Queue::shared_ptr, bool> -QueueRegistry::declare(const string& declareName, bool durable, - bool autoDelete, const OwnershipToken* owner, - boost::shared_ptr<Exchange> alternate, - const qpid::framing::FieldTable& arguments, - bool recovering/*true if this declare is a - result of recovering queue - definition from persistente - record*/) -{ - RWlock::ScopedWlock locker(lock); - string name = declareName.empty() ? generateName() : declareName; - assert(!name.empty()); - QueueMap::iterator i = queues.find(name); - - if (i == queues.end()) { - Queue::shared_ptr queue(new Queue(name, autoDelete, durable ? store : 0, owner, parent, broker)); - if (alternate) { - queue->setAlternateExchange(alternate);//need to do this *before* create - alternate->incAlternateUsers(); - } - if (!recovering) { - //apply settings & create persistent record if required - queue->create(arguments); - } else { - //i.e. recovering a queue for which we already have a persistent record - queue->configure(arguments); - } - queues[name] = queue; - if (lastNode) queue->setLastNodeFailure(); - - return std::pair<Queue::shared_ptr, bool>(queue, true); - } else { - return std::pair<Queue::shared_ptr, bool>(i->second, false); - } -} - -void QueueRegistry::destroyLH (const string& name){ - queues.erase(name); -} - -void QueueRegistry::destroy (const string& name){ - RWlock::ScopedWlock locker(lock); - destroyLH (name); -} - -Queue::shared_ptr QueueRegistry::find(const string& name){ - RWlock::ScopedRlock locker(lock); - QueueMap::iterator i = queues.find(name); - - if (i == queues.end()) { - return Queue::shared_ptr(); - } else { - return i->second; - } -} - -string QueueRegistry::generateName(){ - string name; - do { - std::stringstream ss; - ss << "tmp_" << counter++; - name = ss.str(); - // Thread safety: Private function, only called with lock held - // so this is OK. - } while(queues.find(name) != queues.end()); - return name; -} - -void QueueRegistry::setStore (MessageStore* _store) -{ - store = _store; -} - -MessageStore* QueueRegistry::getStore() const { - return store; -} - -void QueueRegistry::updateQueueClusterState(bool _lastNode) -{ - RWlock::ScopedRlock locker(lock); - for (QueueMap::iterator i = queues.begin(); i != queues.end(); i++) { - if (_lastNode){ - i->second->setLastNodeFailure(); - } else { - i->second->clearLastNodeFailure(); - } - } - lastNode = _lastNode; -} diff --git a/cpp/src/qpid/broker/QueueRegistry.h b/cpp/src/qpid/broker/QueueRegistry.h deleted file mode 100644 index 8a32a64f05..0000000000 --- a/cpp/src/qpid/broker/QueueRegistry.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _QueueRegistry_ -#define _QueueRegistry_ - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/sys/Mutex.h" -#include "qpid/management/Manageable.h" -#include "qpid/framing/FieldTable.h" -#include <boost/bind.hpp> -#include <boost/shared_ptr.hpp> -#include <algorithm> -#include <map> - -namespace qpid { -namespace broker { - -class Queue; -class QueueEvents; -class Exchange; -class OwnershipToken; -class Broker; -class MessageStore; - -/** - * A registry of queues indexed by queue name. - * - * Queues are reference counted using shared_ptr to ensure that they - * are deleted when and only when they are no longer in use. - * - */ -class QueueRegistry { - public: - QPID_BROKER_EXTERN QueueRegistry(Broker* b = 0); - QPID_BROKER_EXTERN ~QueueRegistry(); - - /** - * Declare a queue. - * - * @return The queue and a boolean flag which is true if the queue - * was created by this declare call false if it already existed. - */ - QPID_BROKER_EXTERN std::pair<boost::shared_ptr<Queue>, bool> declare( - const std::string& name, - bool durable = false, - bool autodelete = false, - const OwnershipToken* owner = 0, - boost::shared_ptr<Exchange> alternateExchange = boost::shared_ptr<Exchange>(), - const qpid::framing::FieldTable& args = framing::FieldTable(), - bool recovering = false); - - /** - * Destroy the named queue. - * - * Note: if the queue is in use it is not actually destroyed until - * all shared_ptrs to it are destroyed. During that time it is - * possible that a new queue with the same name may be - * created. This should not create any problems as the new and - * old queues exist independently. The registry has - * forgotten the old queue so there can be no confusion for - * subsequent calls to find or declare with the same name. - * - */ - QPID_BROKER_EXTERN void destroy(const std::string& name); - template <class Test> bool destroyIf(const std::string& name, Test test) - { - qpid::sys::RWlock::ScopedWlock locker(lock); - if (test()) { - destroyLH (name); - return true; - } else { - return false; - } - } - - /** - * Find the named queue. Return 0 if not found. - */ - QPID_BROKER_EXTERN boost::shared_ptr<Queue> find(const std::string& name); - - /** - * Generate unique queue name. - */ - std::string generateName(); - - /** - * Set the store to use. May only be called once. - */ - void setStore (MessageStore*); - - /** - * Return the message store used. - */ - MessageStore* getStore() const; - - /** - * Register the manageable parent for declared queues - */ - void setParent (management::Manageable* _parent) { parent = _parent; } - - /** Call f for each queue in the registry. */ - template <class F> void eachQueue(F f) const { - qpid::sys::RWlock::ScopedRlock l(lock); - for (QueueMap::const_iterator i = queues.begin(); i != queues.end(); ++i) - f(i->second); - } - - /** - * Change queue mode when cluster size drops to 1 node, expands again - * in practice allows flow queue to disk when last name to be exectuted - */ - void updateQueueClusterState(bool lastNode); - -private: - typedef std::map<std::string, boost::shared_ptr<Queue> > QueueMap; - QueueMap queues; - mutable qpid::sys::RWlock lock; - int counter; - MessageStore* store; - QueueEvents* events; - management::Manageable* parent; - bool lastNode; //used to set mode on queue declare - Broker* broker; - - //destroy impl that assumes lock is already held: - void destroyLH (const std::string& name); -}; - - -}} // namespace qpid::broker - - -#endif diff --git a/cpp/src/qpid/broker/QueuedMessage.h b/cpp/src/qpid/broker/QueuedMessage.h deleted file mode 100644 index 35e48b11f3..0000000000 --- a/cpp/src/qpid/broker/QueuedMessage.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _QueuedMessage_ -#define _QueuedMessage_ - -#include "qpid/broker/Message.h" - -namespace qpid { -namespace broker { - -class Queue; - -struct QueuedMessage -{ - boost::intrusive_ptr<Message> payload; - framing::SequenceNumber position; - Queue* queue; - - QueuedMessage() : queue(0) {} - QueuedMessage(Queue* q, boost::intrusive_ptr<Message> msg, framing::SequenceNumber sn) : - payload(msg), position(sn), queue(q) {} - QueuedMessage(Queue* q) : queue(q) {} - -}; - inline bool operator<(const QueuedMessage& a, const QueuedMessage& b) { return a.position < b.position; } - -}} - - -#endif diff --git a/cpp/src/qpid/broker/RateFlowcontrol.h b/cpp/src/qpid/broker/RateFlowcontrol.h deleted file mode 100644 index 99f9d2c0c4..0000000000 --- a/cpp/src/qpid/broker/RateFlowcontrol.h +++ /dev/null @@ -1,105 +0,0 @@ -#ifndef broker_RateFlowcontrol_h -#define broker_RateFlowcontrol_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/Time.h" -#include "qpid/sys/IntegerTypes.h" - -#include <algorithm> - -namespace qpid { -namespace broker { - -// Class to keep track of issuing flow control to make sure that the peer doesn't exceed -// a given message rate -// -// Create the object with the target rate -// Then call sendCredit() whenever credit is issued to the peer -// Call receivedMessage() whenever a message is received, it returns the credit to issue. -// -// sentCredit() be sensibly called with a 0 parameter to indicate -// that we sent credit but treat it as if the value was 0 (we may do this at the start of the connection -// to allow our peer to send messages) -// -// receivedMessage() can be called with 0 to indicate that we've not received a message, but -// tell me what credit I can send. -class RateFlowcontrol { - uint32_t rate; // messages per second - uint32_t maxCredit; // max credit issued to client (issued at start) - uint32_t requestedCredit; - qpid::sys::AbsTime creditSent; - -public: - RateFlowcontrol(uint32_t r) : - rate(r), - maxCredit(0), - requestedCredit(0), - creditSent(qpid::sys::FAR_FUTURE) - {} - - uint32_t getRate() const { - return rate; - } - void sentCredit(const qpid::sys::AbsTime& t, uint32_t credit); - uint32_t receivedMessage(const qpid::sys::AbsTime& t, uint32_t msgs); - uint32_t availableCredit(const qpid::sys::AbsTime& t); - bool flowStopped() const; -}; - -inline void RateFlowcontrol::sentCredit(const qpid::sys::AbsTime& t, uint32_t credit) { - // If the client isn't currently requesting credit (ie it's not sent us anything yet) then - // this credit goes to the max credit held by the client (it can't go to reduce credit - // less than 0) - int32_t nextRequestedCredit = requestedCredit - credit; - if ( nextRequestedCredit<0 ) { - requestedCredit = 0; - maxCredit -= nextRequestedCredit; - } else { - requestedCredit = nextRequestedCredit; - } - creditSent = t; -} - -inline uint32_t RateFlowcontrol::availableCredit(const qpid::sys::AbsTime& t) { - qpid::sys::Duration d(creditSent, t); - // Could be -ve before first sentCredit - int64_t toSend = std::min(rate * d / qpid::sys::TIME_SEC, static_cast<int64_t>(requestedCredit)); - return toSend > 0 ? toSend : 0; -} - -inline uint32_t RateFlowcontrol::receivedMessage(const qpid::sys::AbsTime& t, uint32_t msgs) { - requestedCredit +=msgs; - // Don't send credit for every message, only send if more than 0.5s since last credit or - // we've got less than .25 of the max left (heuristic) - return requestedCredit*4 >= maxCredit*3 || qpid::sys::Duration(creditSent, t) >= 500*qpid::sys::TIME_MSEC - ? availableCredit(t) - : 0; -} - -inline bool RateFlowcontrol::flowStopped() const { - return requestedCredit >= maxCredit; -} - -}} - -#endif // broker_RateFlowcontrol_h diff --git a/cpp/src/qpid/broker/RateTracker.cpp b/cpp/src/qpid/broker/RateTracker.cpp deleted file mode 100644 index 048349b658..0000000000 --- a/cpp/src/qpid/broker/RateTracker.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/RateTracker.h" - -using qpid::sys::AbsTime; -using qpid::sys::Duration; -using qpid::sys::TIME_SEC; - -namespace qpid { -namespace broker { - -RateTracker::RateTracker() : currentCount(0), lastCount(0), lastTime(AbsTime::now()) {} - -RateTracker& RateTracker::operator++() -{ - ++currentCount; - return *this; -} - -double RateTracker::sampleRatePerSecond() -{ - int32_t increment = currentCount - lastCount; - AbsTime now = AbsTime::now(); - Duration interval(lastTime, now); - lastCount = currentCount; - lastTime = now; - //if sampling at higher frequency than supported, will just return the number of increments - if (interval < TIME_SEC) return increment; - else if (increment == 0) return 0; - else return increment / (interval / TIME_SEC); -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/RateTracker.h b/cpp/src/qpid/broker/RateTracker.h deleted file mode 100644 index 0c20b37312..0000000000 --- a/cpp/src/qpid/broker/RateTracker.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef QPID_BROKER_RATETRACKER_H -#define QPID_BROKER_RATETRACKER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/Time.h" - -namespace qpid { -namespace broker { - -/** - * Simple rate tracker: represents some value that can be incremented, - * then can periodcially sample the rate of increments. - */ -class RateTracker -{ - public: - RateTracker(); - /** - * Increments the count being tracked. Can be called concurrently - * with other calls to this operator as well as with calls to - * sampleRatePerSecond(). - */ - RateTracker& operator++(); - /** - * Returns the rate of increments per second since last - * called. Calls to this method should be serialised, but can be - * called concurrently with the increment operator - */ - double sampleRatePerSecond(); - private: - volatile int32_t currentCount; - int32_t lastCount; - qpid::sys::AbsTime lastTime; -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_RATETRACKER_H*/ diff --git a/cpp/src/qpid/broker/RecoverableConfig.h b/cpp/src/qpid/broker/RecoverableConfig.h deleted file mode 100644 index 838a8582dc..0000000000 --- a/cpp/src/qpid/broker/RecoverableConfig.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef _broker_RecoverableConfig_h -#define _broker_RecoverableConfig_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <boost/shared_ptr.hpp> - -namespace qpid { -namespace broker { - -/** - * The interface through which configurations are recovered. - */ -class RecoverableConfig -{ -public: - typedef boost::shared_ptr<RecoverableConfig> shared_ptr; - - virtual void setPersistenceId(uint64_t id) = 0; - virtual ~RecoverableConfig() {}; -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/RecoverableExchange.h b/cpp/src/qpid/broker/RecoverableExchange.h deleted file mode 100644 index ca6cc1541e..0000000000 --- a/cpp/src/qpid/broker/RecoverableExchange.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef _broker_RecoverableExchange_h -#define _broker_RecoverableExchange_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <boost/shared_ptr.hpp> -#include "qpid/framing/FieldTable.h" - -namespace qpid { -namespace broker { - -/** - * The interface through which bindings are recovered. - */ -class RecoverableExchange -{ -public: - typedef boost::shared_ptr<RecoverableExchange> shared_ptr; - - virtual void setPersistenceId(uint64_t id) = 0; - /** - * Recover binding. Nb: queue must have been recovered earlier. - */ - virtual void bind(const std::string& queue, - const std::string& routingKey, - qpid::framing::FieldTable& args) = 0; - virtual ~RecoverableExchange() {}; -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/RecoverableMessage.h b/cpp/src/qpid/broker/RecoverableMessage.h deleted file mode 100644 index c98857ceb0..0000000000 --- a/cpp/src/qpid/broker/RecoverableMessage.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef _broker_RecoverableMessage_h -#define _broker_RecoverableMessage_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <boost/shared_ptr.hpp> -#include "qpid/framing/amqp_types.h" -#include "qpid/framing/Buffer.h" - -namespace qpid { -namespace broker { - -/** - * The interface through which messages are reloaded on recovery. - */ -class RecoverableMessage -{ -public: - typedef boost::shared_ptr<RecoverableMessage> shared_ptr; - virtual void setPersistenceId(uint64_t id) = 0; - virtual void setRedelivered() = 0; - /** - * Used by store to determine whether to load content on recovery - * or let message load its own content as and when it requires it. - * - * @returns true if the content of the message should be loaded - */ - virtual bool loadContent(uint64_t available) = 0; - /** - * Loads the content held in the supplied buffer (may do checking - * of length as necessary) - */ - virtual void decodeContent(framing::Buffer& buffer) = 0; - virtual ~RecoverableMessage() {}; -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/RecoverableQueue.h b/cpp/src/qpid/broker/RecoverableQueue.h deleted file mode 100644 index 49f05f97a1..0000000000 --- a/cpp/src/qpid/broker/RecoverableQueue.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef _broker_RecoverableQueue_h -#define _broker_RecoverableQueue_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/RecoverableMessage.h" -#include <boost/shared_ptr.hpp> - -namespace qpid { -namespace broker { - -class ExternalQueueStore; - -/** - * The interface through which messages are added back to queues on - * recovery. - */ -class RecoverableQueue -{ -public: - typedef boost::shared_ptr<RecoverableQueue> shared_ptr; - - virtual void setPersistenceId(uint64_t id) = 0; - virtual uint64_t getPersistenceId() const = 0; - /** - * Used during recovery to add stored messages back to the queue - */ - virtual void recover(RecoverableMessage::shared_ptr msg) = 0; - virtual ~RecoverableQueue() {}; - - virtual const std::string& getName() const = 0; - virtual void setExternalQueueStore(ExternalQueueStore* inst) = 0; - virtual ExternalQueueStore* getExternalQueueStore() const = 0; - -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/RecoverableTransaction.h b/cpp/src/qpid/broker/RecoverableTransaction.h deleted file mode 100644 index 1b7d94bd1a..0000000000 --- a/cpp/src/qpid/broker/RecoverableTransaction.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef _broker_RecoverableTransaction_h -#define _broker_RecoverableTransaction_h - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <boost/shared_ptr.hpp> - -#include "qpid/broker/RecoverableMessage.h" -#include "qpid/broker/RecoverableQueue.h" - -namespace qpid { -namespace broker { - -/** - * The interface through which prepared 2pc transactions are - * recovered. - */ -class RecoverableTransaction -{ -public: - typedef boost::shared_ptr<RecoverableTransaction> shared_ptr; - virtual void enqueue(RecoverableQueue::shared_ptr queue, RecoverableMessage::shared_ptr message) = 0; - virtual void dequeue(RecoverableQueue::shared_ptr queue, RecoverableMessage::shared_ptr message) = 0; - virtual ~RecoverableTransaction() {}; -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/RecoveredDequeue.cpp b/cpp/src/qpid/broker/RecoveredDequeue.cpp deleted file mode 100644 index cd6735328f..0000000000 --- a/cpp/src/qpid/broker/RecoveredDequeue.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/Queue.h" -#include "qpid/broker/RecoveredDequeue.h" - -using boost::intrusive_ptr; -using namespace qpid::broker; - -RecoveredDequeue::RecoveredDequeue(Queue::shared_ptr _queue, intrusive_ptr<Message> _msg) : queue(_queue), msg(_msg) -{ - queue->recoverPrepared(msg); -} - -bool RecoveredDequeue::prepare(TransactionContext*) throw() -{ - //should never be called; transaction has already prepared if an enqueue is recovered - return false; -} - -void RecoveredDequeue::commit() throw() -{ - queue->enqueueAborted(msg); -} - -void RecoveredDequeue::rollback() throw() -{ - queue->process(msg); -} - diff --git a/cpp/src/qpid/broker/RecoveredDequeue.h b/cpp/src/qpid/broker/RecoveredDequeue.h deleted file mode 100644 index 66e66f1d5f..0000000000 --- a/cpp/src/qpid/broker/RecoveredDequeue.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _RecoveredDequeue_ -#define _RecoveredDequeue_ - -#include "qpid/broker/Deliverable.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/MessageStore.h" -#include "qpid/broker/TxOp.h" - -#include <boost/intrusive_ptr.hpp> - -#include <algorithm> -#include <functional> -#include <list> - -namespace qpid { - namespace broker { - class RecoveredDequeue : public TxOp{ - boost::shared_ptr<Queue> queue; - boost::intrusive_ptr<Message> msg; - - public: - RecoveredDequeue(boost::shared_ptr<Queue> queue, boost::intrusive_ptr<Message> msg); - virtual bool prepare(TransactionContext* ctxt) throw(); - virtual void commit() throw(); - virtual void rollback() throw(); - virtual ~RecoveredDequeue(){} - virtual void accept(TxOpConstVisitor& visitor) const { visitor(*this); } - - boost::shared_ptr<Queue> getQueue() const { return queue; } - boost::intrusive_ptr<Message> getMessage() const { return msg; } - }; - } -} - - -#endif diff --git a/cpp/src/qpid/broker/RecoveredEnqueue.cpp b/cpp/src/qpid/broker/RecoveredEnqueue.cpp deleted file mode 100644 index 6d2eaee6c4..0000000000 --- a/cpp/src/qpid/broker/RecoveredEnqueue.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/Queue.h" -#include "qpid/broker/RecoveredEnqueue.h" - -using boost::intrusive_ptr; -using namespace qpid::broker; - -RecoveredEnqueue::RecoveredEnqueue(Queue::shared_ptr _queue, intrusive_ptr<Message> _msg) : queue(_queue), msg(_msg) -{ - queue->recoverPrepared(msg); -} - -bool RecoveredEnqueue::prepare(TransactionContext*) throw(){ - //should never be called; transaction has already prepared if an enqueue is recovered - return false; -} - -void RecoveredEnqueue::commit() throw(){ - queue->process(msg); -} - -void RecoveredEnqueue::rollback() throw(){ - queue->enqueueAborted(msg); -} - diff --git a/cpp/src/qpid/broker/RecoveredEnqueue.h b/cpp/src/qpid/broker/RecoveredEnqueue.h deleted file mode 100644 index 5f718001d5..0000000000 --- a/cpp/src/qpid/broker/RecoveredEnqueue.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _RecoveredEnqueue_ -#define _RecoveredEnqueue_ - -#include "qpid/broker/Deliverable.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/MessageStore.h" -#include "qpid/broker/TxOp.h" - -#include <boost/intrusive_ptr.hpp> - -#include <algorithm> -#include <functional> -#include <list> - -namespace qpid { -namespace broker { -class RecoveredEnqueue : public TxOp{ - boost::shared_ptr<Queue> queue; - boost::intrusive_ptr<Message> msg; - - public: - RecoveredEnqueue(boost::shared_ptr<Queue> queue, boost::intrusive_ptr<Message> msg); - virtual bool prepare(TransactionContext* ctxt) throw(); - virtual void commit() throw(); - virtual void rollback() throw(); - virtual ~RecoveredEnqueue(){} - virtual void accept(TxOpConstVisitor& visitor) const { visitor(*this); } - - boost::shared_ptr<Queue> getQueue() const { return queue; } - boost::intrusive_ptr<Message> getMessage() const { return msg; } - -}; -} -} - - -#endif diff --git a/cpp/src/qpid/broker/RecoveryManager.h b/cpp/src/qpid/broker/RecoveryManager.h deleted file mode 100644 index 2929e92250..0000000000 --- a/cpp/src/qpid/broker/RecoveryManager.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _RecoveryManager_ -#define _RecoveryManager_ - -#include "qpid/broker/RecoverableExchange.h" -#include "qpid/broker/RecoverableQueue.h" -#include "qpid/broker/RecoverableMessage.h" -#include "qpid/broker/RecoverableTransaction.h" -#include "qpid/broker/RecoverableConfig.h" -#include "qpid/broker/TransactionalStore.h" -#include "qpid/framing/Buffer.h" - -namespace qpid { -namespace broker { - -class RecoveryManager{ - public: - virtual ~RecoveryManager(){} - virtual RecoverableExchange::shared_ptr recoverExchange(framing::Buffer& buffer) = 0; - virtual RecoverableQueue::shared_ptr recoverQueue(framing::Buffer& buffer) = 0; - virtual RecoverableMessage::shared_ptr recoverMessage(framing::Buffer& buffer) = 0; - virtual RecoverableTransaction::shared_ptr recoverTransaction(const std::string& xid, - std::auto_ptr<TPCTransactionContext> txn) = 0; - virtual RecoverableConfig::shared_ptr recoverConfig(framing::Buffer& buffer) = 0; - - virtual void recoveryComplete() = 0; -}; - -class Recoverable { - public: - virtual ~Recoverable() {} - - /** - * Request recovery of queue and message state. - */ - virtual void recover(RecoveryManager& recoverer) = 0; -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/RecoveryManagerImpl.cpp b/cpp/src/qpid/broker/RecoveryManagerImpl.cpp deleted file mode 100644 index d08409695e..0000000000 --- a/cpp/src/qpid/broker/RecoveryManagerImpl.cpp +++ /dev/null @@ -1,278 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/RecoveryManagerImpl.h" - -#include "qpid/broker/Message.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/Link.h" -#include "qpid/broker/Bridge.h" -#include "qpid/broker/RecoveredEnqueue.h" -#include "qpid/broker/RecoveredDequeue.h" -#include "qpid/framing/reply_exceptions.h" - -using boost::dynamic_pointer_cast; -using boost::intrusive_ptr; -using std::string; - -namespace qpid { -namespace broker { - -RecoveryManagerImpl::RecoveryManagerImpl(QueueRegistry& _queues, ExchangeRegistry& _exchanges, LinkRegistry& _links, - DtxManager& _dtxMgr) - : queues(_queues), exchanges(_exchanges), links(_links), dtxMgr(_dtxMgr) {} - -RecoveryManagerImpl::~RecoveryManagerImpl() {} - -class RecoverableMessageImpl : public RecoverableMessage -{ - intrusive_ptr<Message> msg; -public: - RecoverableMessageImpl(const intrusive_ptr<Message>& _msg); - ~RecoverableMessageImpl() {}; - void setPersistenceId(uint64_t id); - void setRedelivered(); - bool loadContent(uint64_t available); - void decodeContent(framing::Buffer& buffer); - void recover(Queue::shared_ptr queue); - void enqueue(DtxBuffer::shared_ptr buffer, Queue::shared_ptr queue); - void dequeue(DtxBuffer::shared_ptr buffer, Queue::shared_ptr queue); -}; - -class RecoverableQueueImpl : public RecoverableQueue -{ - Queue::shared_ptr queue; -public: - RecoverableQueueImpl(const boost::shared_ptr<Queue>& _queue) : queue(_queue) {} - ~RecoverableQueueImpl() {}; - void setPersistenceId(uint64_t id); - uint64_t getPersistenceId() const; - const std::string& getName() const; - void setExternalQueueStore(ExternalQueueStore* inst); - ExternalQueueStore* getExternalQueueStore() const; - void recover(RecoverableMessage::shared_ptr msg); - void enqueue(DtxBuffer::shared_ptr buffer, RecoverableMessage::shared_ptr msg); - void dequeue(DtxBuffer::shared_ptr buffer, RecoverableMessage::shared_ptr msg); -}; - -class RecoverableExchangeImpl : public RecoverableExchange -{ - Exchange::shared_ptr exchange; - QueueRegistry& queues; -public: - RecoverableExchangeImpl(Exchange::shared_ptr _exchange, QueueRegistry& _queues) : exchange(_exchange), queues(_queues) {} - void setPersistenceId(uint64_t id); - void bind(const std::string& queue, const std::string& routingKey, qpid::framing::FieldTable& args); -}; - -class RecoverableConfigImpl : public RecoverableConfig -{ - Link::shared_ptr link; - Bridge::shared_ptr bridge; -public: - RecoverableConfigImpl(Link::shared_ptr _link) : link(_link) {} - RecoverableConfigImpl(Bridge::shared_ptr _bridge) : bridge(_bridge) {} - void setPersistenceId(uint64_t id); -}; - -class RecoverableTransactionImpl : public RecoverableTransaction -{ - DtxBuffer::shared_ptr buffer; -public: - RecoverableTransactionImpl(DtxBuffer::shared_ptr _buffer) : buffer(_buffer) {} - void enqueue(RecoverableQueue::shared_ptr queue, RecoverableMessage::shared_ptr message); - void dequeue(RecoverableQueue::shared_ptr queue, RecoverableMessage::shared_ptr message); -}; - -RecoverableExchange::shared_ptr RecoveryManagerImpl::recoverExchange(framing::Buffer& buffer) -{ - Exchange::shared_ptr e = Exchange::decode(exchanges, buffer); - if (e) { - return RecoverableExchange::shared_ptr(new RecoverableExchangeImpl(e, queues)); - } else { - return RecoverableExchange::shared_ptr(); - } -} - -RecoverableQueue::shared_ptr RecoveryManagerImpl::recoverQueue(framing::Buffer& buffer) -{ - Queue::shared_ptr queue = Queue::restore(queues, buffer); - try { - Exchange::shared_ptr exchange = exchanges.getDefault(); - if (exchange) { - exchange->bind(queue, queue->getName(), 0); - queue->bound(exchange->getName(), queue->getName(), framing::FieldTable()); - } - } catch (const framing::NotFoundException& /*e*/) { - //assume no default exchange has been declared - } - return RecoverableQueue::shared_ptr(new RecoverableQueueImpl(queue)); -} - -RecoverableMessage::shared_ptr RecoveryManagerImpl::recoverMessage(framing::Buffer& buffer) -{ - boost::intrusive_ptr<Message> message(new Message()); - message->decodeHeader(buffer); - return RecoverableMessage::shared_ptr(new RecoverableMessageImpl(message)); -} - -RecoverableTransaction::shared_ptr RecoveryManagerImpl::recoverTransaction(const std::string& xid, - std::auto_ptr<TPCTransactionContext> txn) -{ - DtxBuffer::shared_ptr buffer(new DtxBuffer()); - dtxMgr.recover(xid, txn, buffer); - return RecoverableTransaction::shared_ptr(new RecoverableTransactionImpl(buffer)); -} - -RecoverableConfig::shared_ptr RecoveryManagerImpl::recoverConfig(framing::Buffer& buffer) -{ - string kind; - - buffer.getShortString (kind); - if (kind == "link") - return RecoverableConfig::shared_ptr(new RecoverableConfigImpl(Link::decode (links, buffer))); - else if (kind == "bridge") - return RecoverableConfig::shared_ptr(new RecoverableConfigImpl(Bridge::decode (links, buffer))); - - return RecoverableConfig::shared_ptr(); // TODO: raise an exception instead -} - -void RecoveryManagerImpl::recoveryComplete() -{ - //notify all queues and exchanges - queues.eachQueue(boost::bind(&Queue::recoveryComplete, _1, boost::ref(exchanges))); - exchanges.eachExchange(boost::bind(&Exchange::recoveryComplete, _1, boost::ref(exchanges))); -} - -RecoverableMessageImpl:: RecoverableMessageImpl(const intrusive_ptr<Message>& _msg) : msg(_msg) -{ - if (!msg->isPersistent()) { - msg->forcePersistent(); // set so that message will get dequeued from store. - } -} - -bool RecoverableMessageImpl::loadContent(uint64_t /*available*/) -{ - return true; -} - -void RecoverableMessageImpl::decodeContent(framing::Buffer& buffer) -{ - msg->decodeContent(buffer); -} - -void RecoverableMessageImpl::recover(Queue::shared_ptr queue) -{ - queue->recover(msg); -} - -void RecoverableMessageImpl::setPersistenceId(uint64_t id) -{ - msg->setPersistenceId(id); -} - -void RecoverableMessageImpl::setRedelivered() -{ - msg->redeliver(); -} - -void RecoverableQueueImpl::recover(RecoverableMessage::shared_ptr msg) -{ - dynamic_pointer_cast<RecoverableMessageImpl>(msg)->recover(queue); -} - -void RecoverableQueueImpl::setPersistenceId(uint64_t id) -{ - queue->setPersistenceId(id); -} - -uint64_t RecoverableQueueImpl::getPersistenceId() const -{ - return queue->getPersistenceId(); -} - -const std::string& RecoverableQueueImpl::getName() const -{ - return queue->getName(); -} - -void RecoverableQueueImpl::setExternalQueueStore(ExternalQueueStore* inst) -{ - queue->setExternalQueueStore(inst); -} - -ExternalQueueStore* RecoverableQueueImpl::getExternalQueueStore() const -{ - return queue->getExternalQueueStore(); -} - -void RecoverableExchangeImpl::setPersistenceId(uint64_t id) -{ - exchange->setPersistenceId(id); -} - -void RecoverableConfigImpl::setPersistenceId(uint64_t id) -{ - if (link.get()) - link->setPersistenceId(id); - else if (bridge.get()) - bridge->setPersistenceId(id); -} - -void RecoverableExchangeImpl::bind(const string& queueName, - const string& key, - framing::FieldTable& args) -{ - Queue::shared_ptr queue = queues.find(queueName); - exchange->bind(queue, key, &args); - queue->bound(exchange->getName(), key, args); -} - -void RecoverableMessageImpl::dequeue(DtxBuffer::shared_ptr buffer, Queue::shared_ptr queue) -{ - buffer->enlist(TxOp::shared_ptr(new RecoveredDequeue(queue, msg))); -} - -void RecoverableMessageImpl::enqueue(DtxBuffer::shared_ptr buffer, Queue::shared_ptr queue) -{ - buffer->enlist(TxOp::shared_ptr(new RecoveredEnqueue(queue, msg))); -} - -void RecoverableQueueImpl::dequeue(DtxBuffer::shared_ptr buffer, RecoverableMessage::shared_ptr message) -{ - dynamic_pointer_cast<RecoverableMessageImpl>(message)->dequeue(buffer, queue); -} - -void RecoverableQueueImpl::enqueue(DtxBuffer::shared_ptr buffer, RecoverableMessage::shared_ptr message) -{ - dynamic_pointer_cast<RecoverableMessageImpl>(message)->enqueue(buffer, queue); -} - -void RecoverableTransactionImpl::dequeue(RecoverableQueue::shared_ptr queue, RecoverableMessage::shared_ptr message) -{ - dynamic_pointer_cast<RecoverableQueueImpl>(queue)->dequeue(buffer, message); -} - -void RecoverableTransactionImpl::enqueue(RecoverableQueue::shared_ptr queue, RecoverableMessage::shared_ptr message) -{ - dynamic_pointer_cast<RecoverableQueueImpl>(queue)->enqueue(buffer, message); -} - -}} diff --git a/cpp/src/qpid/broker/RecoveryManagerImpl.h b/cpp/src/qpid/broker/RecoveryManagerImpl.h deleted file mode 100644 index 1ad7892b13..0000000000 --- a/cpp/src/qpid/broker/RecoveryManagerImpl.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _RecoveryManagerImpl_ -#define _RecoveryManagerImpl_ - -#include <list> -#include "qpid/broker/DtxManager.h" -#include "qpid/broker/ExchangeRegistry.h" -#include "qpid/broker/QueueRegistry.h" -#include "qpid/broker/LinkRegistry.h" -#include "qpid/broker/RecoveryManager.h" - -namespace qpid { -namespace broker { - - class RecoveryManagerImpl : public RecoveryManager{ - QueueRegistry& queues; - ExchangeRegistry& exchanges; - LinkRegistry& links; - DtxManager& dtxMgr; - public: - RecoveryManagerImpl(QueueRegistry& queues, ExchangeRegistry& exchanges, LinkRegistry& links, - DtxManager& dtxMgr); - ~RecoveryManagerImpl(); - - RecoverableExchange::shared_ptr recoverExchange(framing::Buffer& buffer); - RecoverableQueue::shared_ptr recoverQueue(framing::Buffer& buffer); - RecoverableMessage::shared_ptr recoverMessage(framing::Buffer& buffer); - RecoverableTransaction::shared_ptr recoverTransaction(const std::string& xid, - std::auto_ptr<TPCTransactionContext> txn); - RecoverableConfig::shared_ptr recoverConfig(framing::Buffer& buffer); - void recoveryComplete(); - }; - - -} -} - - -#endif diff --git a/cpp/src/qpid/broker/RetryList.cpp b/cpp/src/qpid/broker/RetryList.cpp deleted file mode 100644 index b0477dd0f7..0000000000 --- a/cpp/src/qpid/broker/RetryList.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/RetryList.h" - -namespace qpid { -namespace broker { - -RetryList::RetryList() : urlIndex(0), addressIndex(0) {} - -void RetryList::reset(const std::vector<Url>& u) -{ - urls = u; - urlIndex = addressIndex = 0;//reset indices -} - -bool RetryList::next(Address& address) -{ - while (urlIndex < urls.size()) { - if (addressIndex < urls[urlIndex].size()) { - address = urls[urlIndex][addressIndex++]; - return true; - } - urlIndex++; - addressIndex = 0; - } - urlIndex = addressIndex = 0;//reset indices - return false; -} - -std::ostream& operator<<(std::ostream& os, const RetryList& l) -{ - for (size_t i = 0; i < l.urls.size(); i++) { - os << l.urls[i] << " "; - } - return os; -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/RetryList.h b/cpp/src/qpid/broker/RetryList.h deleted file mode 100644 index 242a7d2122..0000000000 --- a/cpp/src/qpid/broker/RetryList.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef QPID_BROKER_RETRYLIST_H -#define QPID_BROKER_RETRYLIST_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/Address.h" -#include "qpid/Url.h" - -namespace qpid { -namespace broker { - -/** - * Simple utility for managing a list of urls to try on reconnecting a - * link. Currently only supports TCP urls. - */ -class RetryList -{ - public: - QPID_BROKER_EXTERN RetryList(); - QPID_BROKER_EXTERN void reset(const std::vector<Url>& urls); - QPID_BROKER_EXTERN bool next(Address& address); - private: - std::vector<Url> urls; - size_t urlIndex; - size_t addressIndex; - - friend std::ostream& operator<<(std::ostream& os, const RetryList& l); -}; - -std::ostream& operator<<(std::ostream& os, const RetryList& l); - -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_RETRYLIST_H*/ diff --git a/cpp/src/qpid/broker/SaslAuthenticator.cpp b/cpp/src/qpid/broker/SaslAuthenticator.cpp deleted file mode 100644 index acdb4934d4..0000000000 --- a/cpp/src/qpid/broker/SaslAuthenticator.cpp +++ /dev/null @@ -1,467 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "qpid/broker/Connection.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/sys/SecuritySettings.h" -#include <boost/format.hpp> - -#if HAVE_SASL -#include <sasl/sasl.h> -#include "qpid/sys/cyrus/CyrusSecurityLayer.h" -using qpid::sys::cyrus::CyrusSecurityLayer; -#endif - -using namespace qpid::framing; -using qpid::sys::SecurityLayer; -using qpid::sys::SecuritySettings; -using boost::format; -using boost::str; - - -namespace qpid { -namespace broker { - - - -class NullAuthenticator : public SaslAuthenticator -{ - Connection& connection; - framing::AMQP_ClientProxy::Connection client; - std::string realm; - const bool encrypt; -public: - NullAuthenticator(Connection& connection, bool encrypt); - ~NullAuthenticator(); - void getMechanisms(framing::Array& mechanisms); - void start(const std::string& mechanism, const std::string& response); - void step(const std::string&) {} - std::auto_ptr<SecurityLayer> getSecurityLayer(uint16_t maxFrameSize); -}; - -#if HAVE_SASL - - - -class CyrusAuthenticator : public SaslAuthenticator -{ - sasl_conn_t *sasl_conn; - Connection& connection; - framing::AMQP_ClientProxy::Connection client; - const bool encrypt; - - void processAuthenticationStep(int code, const char *challenge, unsigned int challenge_len); - bool getUsername(std::string& uid); - -public: - CyrusAuthenticator(Connection& connection, bool encrypt); - ~CyrusAuthenticator(); - void init(); - void getMechanisms(framing::Array& mechanisms); - void start(const std::string& mechanism, const std::string& response); - void step(const std::string& response); - void getError(std::string& error); - void getUid(std::string& uid) { getUsername(uid); } - std::auto_ptr<SecurityLayer> getSecurityLayer(uint16_t maxFrameSize); -}; - -bool SaslAuthenticator::available(void) { - return true; -} - -// Initialize the SASL mechanism; throw if it fails. -void SaslAuthenticator::init(const std::string& saslName, std::string const & saslConfigPath ) -{ - // Check if we have a version of SASL that supports sasl_set_path() -#if (SASL_VERSION_FULL >= ((2<<16)|(1<<8)|22)) - // If we are not given a sasl path, do nothing and allow the default to be used. - if ( ! saslConfigPath.empty() ) { - int code = sasl_set_path(SASL_PATH_TYPE_CONFIG, - const_cast<char *>(saslConfigPath.c_str())); - if(SASL_OK != code) - throw Exception(QPID_MSG("SASL: sasl_set_path failed [" << code << "] " )); - QPID_LOG(info, "SASL: config path set to " << saslConfigPath ); - } -#endif - - int code = sasl_server_init(NULL, saslName.c_str()); - if (code != SASL_OK) { - // TODO: Figure out who owns the char* returned by - // sasl_errstring, though it probably does not matter much - throw Exception(sasl_errstring(code, NULL, NULL)); - } -} - -void SaslAuthenticator::fini(void) -{ - sasl_done(); -} - -#else - -typedef NullAuthenticator CyrusAuthenticator; - -bool SaslAuthenticator::available(void) { - return false; -} - -void SaslAuthenticator::init(const std::string& /*saslName*/, std::string const & /*saslConfigPath*/ ) -{ - throw Exception("Requested authentication but SASL unavailable"); -} - -void SaslAuthenticator::fini(void) -{ - return; -} - -#endif - -std::auto_ptr<SaslAuthenticator> SaslAuthenticator::createAuthenticator(Connection& c, bool isShadow ) -{ - if (c.getBroker().getOptions().auth) { - if ( isShadow ) - return std::auto_ptr<SaslAuthenticator>(new NullAuthenticator(c, c.getBroker().getOptions().requireEncrypted)); - else - return std::auto_ptr<SaslAuthenticator>(new CyrusAuthenticator(c, c.getBroker().getOptions().requireEncrypted)); - } else { - QPID_LOG(debug, "SASL: No Authentication Performed"); - return std::auto_ptr<SaslAuthenticator>(new NullAuthenticator(c, c.getBroker().getOptions().requireEncrypted)); - } -} - - -NullAuthenticator::NullAuthenticator(Connection& c, bool e) : connection(c), client(c.getOutput()), - realm(c.getBroker().getOptions().realm), encrypt(e) {} -NullAuthenticator::~NullAuthenticator() {} - -void NullAuthenticator::getMechanisms(Array& mechanisms) -{ - mechanisms.add(boost::shared_ptr<FieldValue>(new Str16Value("ANONYMOUS"))); - mechanisms.add(boost::shared_ptr<FieldValue>(new Str16Value("PLAIN")));//useful for testing -} - -void NullAuthenticator::start(const string& mechanism, const string& response) -{ - if (encrypt) { -#if HAVE_SASL - // encryption required - check to see if we are running over an - // encrypted SSL connection. - SecuritySettings external = connection.getExternalSecuritySettings(); - sasl_ssf_t external_ssf = (sasl_ssf_t) external.ssf; - if (external_ssf < 1) // < 1 == unencrypted -#endif - { - QPID_LOG(error, "Rejected un-encrypted connection."); - throw ConnectionForcedException("Connection must be encrypted."); - } - } - if (mechanism == "PLAIN") { // Old behavior - if (response.size() > 0) { - string uid; - string::size_type i = response.find((char)0); - if (i == 0 && response.size() > 1) { - //no authorization id; use authentication id - i = response.find((char)0, 1); - if (i != string::npos) uid = response.substr(1, i-1); - } else if (i != string::npos) { - //authorization id is first null delimited field - uid = response.substr(0, i); - }//else not a valid SASL PLAIN response, throw error? - if (!uid.empty()) { - //append realm if it has not already been added - i = uid.find(realm); - if (i == string::npos || realm.size() + i < uid.size()) { - uid = str(format("%1%@%2%") % uid % realm); - } - connection.setUserId(uid); - } - } - } else { - connection.setUserId("anonymous"); - } - client.tune(framing::CHANNEL_MAX, connection.getFrameMax(), 0, connection.getHeartbeatMax()); -} - - -std::auto_ptr<SecurityLayer> NullAuthenticator::getSecurityLayer(uint16_t) -{ - std::auto_ptr<SecurityLayer> securityLayer; - return securityLayer; -} - - -#if HAVE_SASL - -CyrusAuthenticator::CyrusAuthenticator(Connection& c, bool _encrypt) : - sasl_conn(0), connection(c), client(c.getOutput()), encrypt(_encrypt) -{ - init(); -} - -void CyrusAuthenticator::init() -{ - /* Next to the service name, which specifies the - * /etc/sasl2/<service name>.conf file to read, the realm is - * currently the most important argument below. When - * performing authentication the user that is authenticating - * will be looked up in a specific realm. If none is given - * then the realm defaults to the hostname, which can cause - * confusion when the daemon is run on different hosts that - * may be logically sharing a realm (aka a user domain). This - * is especially important for SASL PLAIN authentication, - * which cannot specify a realm for the user that is - * authenticating. - */ - int code; - - const char *realm = connection.getBroker().getOptions().realm.c_str(); - code = sasl_server_new(BROKER_SASL_NAME, /* Service name */ - NULL, /* Server FQDN, gethostname() */ - realm, /* Authentication realm */ - NULL, /* Local IP, needed for some mechanism */ - NULL, /* Remote IP, needed for some mechanism */ - NULL, /* Callbacks */ - 0, /* Connection flags */ - &sasl_conn); - - if (SASL_OK != code) { - QPID_LOG(error, "SASL: Connection creation failed: [" << code << "] " << sasl_errdetail(sasl_conn)); - - // TODO: Change this to an exception signaling - // server error, when one is available - throw ConnectionForcedException("Unable to perform authentication"); - } - - sasl_security_properties_t secprops; - - //TODO: should the actual SSF values be configurable here? - secprops.min_ssf = encrypt ? 10: 0; - secprops.max_ssf = 256; - - // If the transport provides encryption, notify the SASL library of - // the key length and set the ssf range to prevent double encryption. - SecuritySettings external = connection.getExternalSecuritySettings(); - QPID_LOG(debug, "External ssf=" << external.ssf << " and auth=" << external.authid); - sasl_ssf_t external_ssf = (sasl_ssf_t) external.ssf; - if (external_ssf) { - int result = sasl_setprop(sasl_conn, SASL_SSF_EXTERNAL, &external_ssf); - if (result != SASL_OK) { - throw framing::InternalErrorException(QPID_MSG("SASL error: unable to set external SSF: " << result)); - } - - secprops.max_ssf = secprops.min_ssf = 0; - } - - QPID_LOG(debug, "min_ssf: " << secprops.min_ssf << - ", max_ssf: " << secprops.max_ssf << - ", external_ssf: " << external_ssf ); - - if (!external.authid.empty()) { - const char* external_authid = external.authid.c_str(); - int result = sasl_setprop(sasl_conn, SASL_AUTH_EXTERNAL, external_authid); - if (result != SASL_OK) { - throw framing::InternalErrorException(QPID_MSG("SASL error: unable to set external auth: " << result)); - } - - QPID_LOG(debug, "external auth detected and set to " << external_authid); - } - - secprops.maxbufsize = 65535; - secprops.property_names = 0; - secprops.property_values = 0; - secprops.security_flags = 0; /* or SASL_SEC_NOANONYMOUS etc as appropriate */ - /* - * The nodict flag restricts SASL authentication mechanisms - * to those that are not susceptible to dictionary attacks. - * They are: - * SRP - * PASSDSS-3DES-1 - * EXTERNAL - */ - if (external.nodict) secprops.security_flags |= SASL_SEC_NODICTIONARY; - int result = sasl_setprop(sasl_conn, SASL_SEC_PROPS, &secprops); - if (result != SASL_OK) { - throw framing::InternalErrorException(QPID_MSG("SASL error: " << result)); - } -} - -CyrusAuthenticator::~CyrusAuthenticator() -{ - if (sasl_conn) { - sasl_dispose(&sasl_conn); - sasl_conn = 0; - } -} - -void CyrusAuthenticator::getError(string& error) -{ - error = string(sasl_errdetail(sasl_conn)); -} - -bool CyrusAuthenticator::getUsername(string& uid) -{ - const void* ptr; - - int code = sasl_getprop(sasl_conn, SASL_USERNAME, &ptr); - if (SASL_OK == code) { - uid = string(const_cast<char*>(static_cast<const char*>(ptr))); - return true; - } else { - QPID_LOG(warning, "Failed to retrieve sasl username"); - return false; - } -} - -void CyrusAuthenticator::getMechanisms(Array& mechanisms) -{ - const char *separator = " "; - const char *list; - unsigned int list_len; - int count; - - int code = sasl_listmech(sasl_conn, NULL, - "", separator, "", - &list, &list_len, - &count); - - if (SASL_OK != code) { - QPID_LOG(info, "SASL: Mechanism listing failed: " << sasl_errdetail(sasl_conn)); - - // TODO: Change this to an exception signaling - // server error, when one is available - throw ConnectionForcedException("Mechanism listing failed"); - } else { - string mechanism; - unsigned int start; - unsigned int end; - - QPID_LOG(info, "SASL: Mechanism list: " << list); - - end = 0; - do { - start = end; - - // Seek to end of next mechanism - while (end < list_len && separator[0] != list[end]) - end++; - - // Record the mechanism - mechanisms.add(boost::shared_ptr<FieldValue>(new Str16Value(string(list, start, end - start)))); - end++; - } while (end < list_len); - } -} - -void CyrusAuthenticator::start(const string& mechanism, const string& response) -{ - const char *challenge; - unsigned int challenge_len; - - QPID_LOG(debug, "SASL: Starting authentication with mechanism: " << mechanism); - int code = sasl_server_start(sasl_conn, - mechanism.c_str(), - response.c_str(), response.length(), - &challenge, &challenge_len); - - processAuthenticationStep(code, challenge, challenge_len); -} - -void CyrusAuthenticator::step(const string& response) -{ - const char *challenge; - unsigned int challenge_len; - - int code = sasl_server_step(sasl_conn, - response.c_str(), response.length(), - &challenge, &challenge_len); - - processAuthenticationStep(code, challenge, challenge_len); -} - -void CyrusAuthenticator::processAuthenticationStep(int code, const char *challenge, unsigned int challenge_len) -{ - if (SASL_OK == code) { - std::string uid; - if (!getUsername(uid)) { - // TODO: Change this to an exception signaling - // authentication failure, when one is available - throw ConnectionForcedException("Authenticated username unavailable"); - } - QPID_LOG(info, connection.getMgmtId() << " SASL: Authentication succeeded for: " << uid); - - connection.setUserId(uid); - - client.tune(framing::CHANNEL_MAX, connection.getFrameMax(), 0, connection.getHeartbeatMax()); - } else if (SASL_CONTINUE == code) { - string challenge_str(challenge, challenge_len); - - QPID_LOG(debug, "SASL: sending challenge to client"); - - client.secure(challenge_str); - } else { - std::string uid; - if (!getUsername(uid)) { - QPID_LOG(info, "SASL: Authentication failed (no username available):" << sasl_errdetail(sasl_conn)); - } else { - QPID_LOG(info, "SASL: Authentication failed for " << uid << ":" << sasl_errdetail(sasl_conn)); - } - - // TODO: Change to more specific exceptions, when they are - // available - switch (code) { - case SASL_NOMECH: - throw ConnectionForcedException("Unsupported mechanism"); - break; - case SASL_TRYAGAIN: - throw ConnectionForcedException("Transient failure, try again"); - break; - default: - throw ConnectionForcedException("Authentication failed"); - break; - } - } -} - -std::auto_ptr<SecurityLayer> CyrusAuthenticator::getSecurityLayer(uint16_t maxFrameSize) -{ - - const void* value(0); - int result = sasl_getprop(sasl_conn, SASL_SSF, &value); - if (result != SASL_OK) { - throw framing::InternalErrorException(QPID_MSG("SASL error: " << sasl_errdetail(sasl_conn))); - } - uint ssf = *(reinterpret_cast<const unsigned*>(value)); - std::auto_ptr<SecurityLayer> securityLayer; - if (ssf) { - securityLayer = std::auto_ptr<SecurityLayer>(new CyrusSecurityLayer(sasl_conn, maxFrameSize)); - } - return securityLayer; -} - -#endif - -}} diff --git a/cpp/src/qpid/broker/SaslAuthenticator.h b/cpp/src/qpid/broker/SaslAuthenticator.h deleted file mode 100644 index cfbe1a0cd1..0000000000 --- a/cpp/src/qpid/broker/SaslAuthenticator.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _SaslAuthenticator_ -#define _SaslAuthenticator_ - - -#include "qpid/framing/amqp_types.h" -#include "qpid/framing/AMQP_ClientProxy.h" -#include "qpid/Exception.h" -#include "qpid/sys/SecurityLayer.h" -#include <memory> -#include <vector> -#include <boost/bind.hpp> -#include <boost/function.hpp> - -namespace qpid { -namespace broker { - -class Connection; - -class SaslAuthenticator -{ -public: - virtual ~SaslAuthenticator() {} - virtual void getMechanisms(framing::Array& mechanisms) = 0; - virtual void start(const std::string& mechanism, const std::string& response) = 0; - virtual void step(const std::string& response) = 0; - virtual void getUid(std::string&) {} - virtual bool getUsername(std::string&) { return false; }; - virtual void getError(std::string&) {} - virtual std::auto_ptr<qpid::sys::SecurityLayer> getSecurityLayer(uint16_t maxFrameSize) = 0; - - static bool available(void); - - // Initialize the SASL mechanism; throw if it fails. - static void init(const std::string& saslName, std::string const & saslConfigPath ); - static void fini(void); - - static std::auto_ptr<SaslAuthenticator> createAuthenticator(Connection& connection, bool isShadow); - - virtual void callUserIdCallbacks() { } -}; - -}} - -#endif diff --git a/cpp/src/qpid/broker/SecureConnection.cpp b/cpp/src/qpid/broker/SecureConnection.cpp deleted file mode 100644 index 5c1ebf3e8b..0000000000 --- a/cpp/src/qpid/broker/SecureConnection.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/SecureConnection.h" -#include "qpid/sys/SecurityLayer.h" -#include "qpid/framing/reply_exceptions.h" - -namespace qpid { -namespace broker { - -using qpid::sys::SecurityLayer; - -SecureConnection::SecureConnection() : secured(false) {} - -size_t SecureConnection::decode(const char* buffer, size_t size) -{ - if (!secured && securityLayer.get()) { - //security layer comes into effect on first read after its - //activated - secured = true; - } - if (secured) { - return securityLayer->decode(buffer, size); - } else { - return codec->decode(buffer, size); - } -} - -size_t SecureConnection::encode(const char* buffer, size_t size) -{ - if (secured) { - return securityLayer->encode(buffer, size); - } else { - return codec->encode(buffer, size); - } -} - -bool SecureConnection::canEncode() -{ - if (secured) return securityLayer->canEncode(); - else return codec->canEncode(); -} - -void SecureConnection::closed() -{ - codec->closed(); -} - -bool SecureConnection::isClosed() const -{ - return codec->isClosed(); -} - -framing::ProtocolVersion SecureConnection::getVersion() const -{ - return codec->getVersion(); -} - -void SecureConnection:: setCodec(std::auto_ptr<ConnectionCodec> c) -{ - codec = c; -} - -void SecureConnection::activateSecurityLayer(std::auto_ptr<SecurityLayer> sl, bool secureImmediately) -{ - securityLayer = sl; - securityLayer->init(codec.get()); - - if ( secureImmediately ) - secured = true; -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/SecureConnection.h b/cpp/src/qpid/broker/SecureConnection.h deleted file mode 100644 index 1547faae1e..0000000000 --- a/cpp/src/qpid/broker/SecureConnection.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef QPID_BROKER_SECURECONNECTION_H -#define QPID_BROKER_SECURECONNECTION_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/ConnectionCodec.h" -#include <memory> - -namespace qpid { - -namespace sys { -class SecurityLayer; -} - -namespace broker { - -/** - * A ConnectionCodec 'wrapper' that allows a connection to be - * 'secured' e.g. encrypted based on settings negotiatiated at the - * time of establishment. - */ -class SecureConnection : public qpid::sys::ConnectionCodec -{ - public: - SecureConnection(); - size_t decode(const char* buffer, size_t size); - size_t encode(const char* buffer, size_t size); - bool canEncode(); - void closed(); - bool isClosed() const; - framing::ProtocolVersion getVersion() const; - void setCodec(std::auto_ptr<ConnectionCodec>); - void activateSecurityLayer(std::auto_ptr<qpid::sys::SecurityLayer>, bool secureImmediately=false); - private: - std::auto_ptr<ConnectionCodec> codec; - std::auto_ptr<qpid::sys::SecurityLayer> securityLayer; - bool secured; -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_SECURECONNECTION_H*/ diff --git a/cpp/src/qpid/broker/SecureConnectionFactory.cpp b/cpp/src/qpid/broker/SecureConnectionFactory.cpp deleted file mode 100644 index 754b443c22..0000000000 --- a/cpp/src/qpid/broker/SecureConnectionFactory.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/SecureConnectionFactory.h" -#include "qpid/framing/ProtocolVersion.h" -#include "qpid/amqp_0_10/Connection.h" -#include "qpid/broker/Connection.h" -#include "qpid/broker/SecureConnection.h" -#include "qpid/sys/SecuritySettings.h" -#include "qpid/log/Statement.h" - -namespace qpid { -namespace broker { - -using framing::ProtocolVersion; -using qpid::sys::SecuritySettings; -typedef std::auto_ptr<amqp_0_10::Connection> CodecPtr; -typedef std::auto_ptr<SecureConnection> SecureConnectionPtr; -typedef std::auto_ptr<Connection> ConnectionPtr; -typedef std::auto_ptr<sys::ConnectionInputHandler> InputPtr; - -SecureConnectionFactory::SecureConnectionFactory(Broker& b) : broker(b) {} - -sys::ConnectionCodec* -SecureConnectionFactory::create(ProtocolVersion v, sys::OutputControl& out, const std::string& id, - const SecuritySettings& external) { - if (broker.getConnectionCounter().allowConnection()) - { - QPID_LOG(error, "Client max connection count limit exceeded: " << broker.getOptions().maxConnections << " connection refused"); - return 0; - } - if (v == ProtocolVersion(0, 10)) { - SecureConnectionPtr sc(new SecureConnection()); - CodecPtr c(new amqp_0_10::Connection(out, id, false)); - ConnectionPtr i(new broker::Connection(c.get(), broker, id, external, false)); - i->setSecureConnection(sc.get()); - c->setInputHandler(InputPtr(i.release())); - sc->setCodec(std::auto_ptr<sys::ConnectionCodec>(c)); - return sc.release(); - } - return 0; -} - -sys::ConnectionCodec* -SecureConnectionFactory::create(sys::OutputControl& out, const std::string& id, - const SecuritySettings& external) { - // used to create connections from one broker to another - SecureConnectionPtr sc(new SecureConnection()); - CodecPtr c(new amqp_0_10::Connection(out, id, true)); - ConnectionPtr i(new broker::Connection(c.get(), broker, id, external, true )); - i->setSecureConnection(sc.get()); - c->setInputHandler(InputPtr(i.release())); - sc->setCodec(std::auto_ptr<sys::ConnectionCodec>(c)); - return sc.release(); -} - - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/SecureConnectionFactory.h b/cpp/src/qpid/broker/SecureConnectionFactory.h deleted file mode 100644 index 8a04dfcb15..0000000000 --- a/cpp/src/qpid/broker/SecureConnectionFactory.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _SecureConnectionFactory_ -#define _SecureConnectionFactory_ - -#include "qpid/sys/ConnectionCodec.h" - -namespace qpid { -namespace broker { -class Broker; - -class SecureConnectionFactory : public sys::ConnectionCodec::Factory -{ - public: - SecureConnectionFactory(Broker& b); - - sys::ConnectionCodec* - create(framing::ProtocolVersion, sys::OutputControl&, const std::string& id, - const qpid::sys::SecuritySettings&); - - sys::ConnectionCodec* - create(sys::OutputControl&, const std::string& id, const qpid::sys::SecuritySettings&); - - private: - Broker& broker; -}; - -}} - - -#endif diff --git a/cpp/src/qpid/broker/SemanticState.cpp b/cpp/src/qpid/broker/SemanticState.cpp deleted file mode 100644 index ce86253f4a..0000000000 --- a/cpp/src/qpid/broker/SemanticState.cpp +++ /dev/null @@ -1,823 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/SessionState.h" -#include "qpid/broker/Connection.h" -#include "qpid/broker/DeliverableMessage.h" -#include "qpid/broker/DtxAck.h" -#include "qpid/broker/DtxTimeout.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/SessionContext.h" -#include "qpid/broker/SessionOutputException.h" -#include "qpid/broker/TxAccept.h" -#include "qpid/broker/TxPublish.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/MessageTransferBody.h" -#include "qpid/framing/SequenceSet.h" -#include "qpid/framing/IsInSequenceSet.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/ClusterSafe.h" -#include "qpid/ptr_map.h" -#include "qpid/broker/AclModule.h" - -#include <boost/bind.hpp> -#include <boost/format.hpp> - -#include <iostream> -#include <sstream> -#include <algorithm> -#include <functional> - -#include <assert.h> - -namespace qpid { -namespace broker { - -using namespace std; -using boost::intrusive_ptr; -using boost::bind; -using namespace qpid::broker; -using namespace qpid::framing; -using namespace qpid::sys; -using qpid::ptr_map_ptr; -using qpid::management::ManagementAgent; -using qpid::management::ManagementObject; -using qpid::management::Manageable; -using qpid::management::Args; -namespace _qmf = qmf::org::apache::qpid::broker; - -SemanticState::SemanticState(DeliveryAdapter& da, SessionContext& ss) - : session(ss), - deliveryAdapter(da), - tagGenerator("sgen"), - dtxSelected(false), - authMsg(getSession().getBroker().getOptions().auth && !getSession().getConnection().isFederationLink()), - userID(getSession().getConnection().getUserId()), - userName(getSession().getConnection().getUserId().substr(0,getSession().getConnection().getUserId().find('@'))), - isDefaultRealm(userID.find('@') != std::string::npos && getSession().getBroker().getOptions().realm == userID.substr(userID.find('@')+1,userID.size())), - closeComplete(false) -{ - acl = getSession().getBroker().getAcl(); -} - -SemanticState::~SemanticState() { - closed(); -} - -void SemanticState::closed() { - if (!closeComplete) { - //prevent requeued messages being redelivered to consumers - for (ConsumerImplMap::iterator i = consumers.begin(); i != consumers.end(); i++) { - disable(i->second); - } - if (dtxBuffer.get()) { - dtxBuffer->fail(); - } - recover(true); - - //now unsubscribe, which may trigger queue deletion and thus - //needs to occur after the requeueing of unacked messages - for (ConsumerImplMap::iterator i = consumers.begin(); i != consumers.end(); i++) { - unsubscribe(i->second); - } - closeComplete = true; - } -} - -bool SemanticState::exists(const string& consumerTag){ - return consumers.find(consumerTag) != consumers.end(); -} - -void SemanticState::consume(const string& tag, - Queue::shared_ptr queue, bool ackRequired, bool acquire, - bool exclusive, const string& resumeId, uint64_t resumeTtl, const FieldTable& arguments) -{ - ConsumerImpl::shared_ptr c(new ConsumerImpl(this, tag, queue, ackRequired, acquire, exclusive, resumeId, resumeTtl, arguments)); - queue->consume(c, exclusive);//may throw exception - consumers[tag] = c; -} - -bool SemanticState::cancel(const string& tag) -{ - ConsumerImplMap::iterator i = consumers.find(tag); - if (i != consumers.end()) { - cancel(i->second); - consumers.erase(i); - //should cancel all unacked messages for this consumer so that - //they are not redelivered on recovery - for_each(unacked.begin(), unacked.end(), boost::bind(&DeliveryRecord::cancel, _1, tag)); - return true; - } else { - return false; - } -} - - -void SemanticState::startTx() -{ - txBuffer = TxBuffer::shared_ptr(new TxBuffer()); -} - -void SemanticState::commit(MessageStore* const store) -{ - if (!txBuffer) throw - CommandInvalidException(QPID_MSG("Session has not been selected for use with transactions")); - - TxOp::shared_ptr txAck(static_cast<TxOp*>(new TxAccept(accumulatedAck, unacked))); - txBuffer->enlist(txAck); - if (txBuffer->commitLocal(store)) { - accumulatedAck.clear(); - } else { - throw InternalErrorException(QPID_MSG("Commit failed")); - } -} - -void SemanticState::rollback() -{ - if (!txBuffer) - throw CommandInvalidException(QPID_MSG("Session has not been selected for use with transactions")); - - txBuffer->rollback(); - accumulatedAck.clear(); -} - -void SemanticState::selectDtx() -{ - dtxSelected = true; -} - -void SemanticState::startDtx(const std::string& xid, DtxManager& mgr, bool join) -{ - if (!dtxSelected) { - throw CommandInvalidException(QPID_MSG("Session has not been selected for use with dtx")); - } - dtxBuffer = DtxBuffer::shared_ptr(new DtxBuffer(xid)); - txBuffer = boost::static_pointer_cast<TxBuffer>(dtxBuffer); - if (join) { - mgr.join(xid, dtxBuffer); - } else { - mgr.start(xid, dtxBuffer); - } -} - -void SemanticState::endDtx(const std::string& xid, bool fail) -{ - if (!dtxBuffer) { - throw IllegalStateException(QPID_MSG("xid " << xid << " not associated with this session")); - } - if (dtxBuffer->getXid() != xid) { - throw CommandInvalidException( - QPID_MSG("xid specified on start was " << dtxBuffer->getXid() << ", but " << xid << " specified on end")); - - } - - txBuffer.reset();//ops on this session no longer transactional - - checkDtxTimeout(); - if (fail) { - dtxBuffer->fail(); - } else { - dtxBuffer->markEnded(); - } - dtxBuffer.reset(); -} - -void SemanticState::suspendDtx(const std::string& xid) -{ - if (dtxBuffer->getXid() != xid) { - throw CommandInvalidException( - QPID_MSG("xid specified on start was " << dtxBuffer->getXid() << ", but " << xid << " specified on suspend")); - } - txBuffer.reset();//ops on this session no longer transactional - - checkDtxTimeout(); - dtxBuffer->setSuspended(true); - suspendedXids[xid] = dtxBuffer; - dtxBuffer.reset(); -} - -void SemanticState::resumeDtx(const std::string& xid) -{ - if (!dtxSelected) { - throw CommandInvalidException(QPID_MSG("Session has not been selected for use with dtx")); - } - - dtxBuffer = suspendedXids[xid]; - if (!dtxBuffer) { - throw CommandInvalidException(QPID_MSG("xid " << xid << " not attached")); - } else { - suspendedXids.erase(xid); - } - - if (dtxBuffer->getXid() != xid) { - throw CommandInvalidException( - QPID_MSG("xid specified on start was " << dtxBuffer->getXid() << ", but " << xid << " specified on resume")); - - } - if (!dtxBuffer->isSuspended()) { - throw CommandInvalidException(QPID_MSG("xid " << xid << " not suspended")); - } - - checkDtxTimeout(); - dtxBuffer->setSuspended(false); - txBuffer = boost::static_pointer_cast<TxBuffer>(dtxBuffer); -} - -void SemanticState::checkDtxTimeout() -{ - if (dtxBuffer->isExpired()) { - dtxBuffer.reset(); - throw DtxTimeoutException(); - } -} - -void SemanticState::record(const DeliveryRecord& delivery) -{ - unacked.push_back(delivery); -} - -const std::string QPID_SYNC_FREQUENCY("qpid.sync_frequency"); - -SemanticState::ConsumerImpl::ConsumerImpl(SemanticState* _parent, - const string& _name, - Queue::shared_ptr _queue, - bool ack, - bool _acquire, - bool _exclusive, - const string& _resumeId, - uint64_t _resumeTtl, - const framing::FieldTable& _arguments - - -) : - Consumer(_acquire), - parent(_parent), - name(_name), - queue(_queue), - ackExpected(ack), - acquire(_acquire), - blocked(true), - windowing(true), - exclusive(_exclusive), - resumeId(_resumeId), - resumeTtl(_resumeTtl), - arguments(_arguments), - msgCredit(0), - byteCredit(0), - notifyEnabled(true), - syncFrequency(_arguments.getAsInt(QPID_SYNC_FREQUENCY)), - deliveryCount(0), - mgmtObject(0) -{ - if (parent != 0 && queue.get() != 0 && queue->GetManagementObject() !=0) - { - ManagementAgent* agent = parent->session.getBroker().getManagementAgent(); - qpid::management::Manageable* ms = dynamic_cast<qpid::management::Manageable*> (&(parent->session)); - - if (agent != 0) - { - mgmtObject = new _qmf::Subscription(agent, this, ms , queue->GetManagementObject()->getObjectId() ,name, - !acquire, ackExpected, exclusive, ManagementAgent::toMap(arguments)); - agent->addObject (mgmtObject); - mgmtObject->set_creditMode("WINDOW"); - } - } -} - -ManagementObject* SemanticState::ConsumerImpl::GetManagementObject (void) const -{ - return (ManagementObject*) mgmtObject; -} - -Manageable::status_t SemanticState::ConsumerImpl::ManagementMethod (uint32_t methodId, Args&, string&) -{ - Manageable::status_t status = Manageable::STATUS_UNKNOWN_METHOD; - - QPID_LOG (debug, "Queue::ManagementMethod [id=" << methodId << "]"); - - return status; -} - - -OwnershipToken* SemanticState::ConsumerImpl::getSession() -{ - return &(parent->session); -} - -bool SemanticState::ConsumerImpl::deliver(QueuedMessage& msg) -{ - assertClusterSafe(); - allocateCredit(msg.payload); - DeliveryRecord record(msg, queue, name, acquire, !ackExpected, windowing); - bool sync = syncFrequency && ++deliveryCount >= syncFrequency; - if (sync) deliveryCount = 0;//reset - parent->deliver(record, sync); - if (!ackExpected && acquire) record.setEnded();//allows message to be released now its been delivered - if (windowing || ackExpected || !acquire) { - parent->record(record); - } - if (acquire && !ackExpected) { - queue->dequeue(0, msg); - } - if (mgmtObject) { mgmtObject->inc_delivered(); } - return true; -} - -bool SemanticState::ConsumerImpl::filter(intrusive_ptr<Message>) -{ - return true; -} - -bool SemanticState::ConsumerImpl::accept(intrusive_ptr<Message> msg) -{ - assertClusterSafe(); - // FIXME aconway 2009-06-08: if we have byte & message credit but - // checkCredit fails because the message is to big, we should - // remain on queue's listener list for possible smaller messages - // in future. - // - blocked = !(filter(msg) && checkCredit(msg)); - return !blocked; -} - -namespace { -struct ConsumerName { - const SemanticState::ConsumerImpl& consumer; - ConsumerName(const SemanticState::ConsumerImpl& ci) : consumer(ci) {} -}; - -ostream& operator<<(ostream& o, const ConsumerName& pc) { - return o << pc.consumer.getName() << " on " - << pc.consumer.getParent().getSession().getSessionId(); -} -} - -void SemanticState::ConsumerImpl::allocateCredit(intrusive_ptr<Message>& msg) -{ - assertClusterSafe(); - uint32_t originalMsgCredit = msgCredit; - uint32_t originalByteCredit = byteCredit; - if (msgCredit != 0xFFFFFFFF) { - msgCredit--; - } - if (byteCredit != 0xFFFFFFFF) { - byteCredit -= msg->getRequiredCredit(); - } - QPID_LOG(debug, "Credit allocated for " << ConsumerName(*this) - << ", was " << " bytes: " << originalByteCredit << " msgs: " << originalMsgCredit - << " now bytes: " << byteCredit << " msgs: " << msgCredit); - -} - -bool SemanticState::ConsumerImpl::checkCredit(intrusive_ptr<Message>& msg) -{ - bool enoughCredit = msgCredit > 0 && - (byteCredit == 0xFFFFFFFF || byteCredit >= msg->getRequiredCredit()); - QPID_LOG(debug, (enoughCredit ? "Sufficient credit for " : "Insufficient credit for ") - << ConsumerName(*this) - << ", have bytes: " << byteCredit << " msgs: " << msgCredit - << ", need " << msg->getRequiredCredit() << " bytes"); - return enoughCredit; -} - -SemanticState::ConsumerImpl::~ConsumerImpl() -{ - if (mgmtObject != 0) - mgmtObject->resourceDestroy (); -} - -void SemanticState::disable(ConsumerImpl::shared_ptr c) -{ - c->disableNotify(); - if (session.isAttached()) - session.getConnection().outputTasks.removeOutputTask(c.get()); -} - -void SemanticState::unsubscribe(ConsumerImpl::shared_ptr c) -{ - Queue::shared_ptr queue = c->getQueue(); - if(queue) { - queue->cancel(c); - if (queue->canAutoDelete() && !queue->hasExclusiveOwner()) { - Queue::tryAutoDelete(session.getBroker(), queue); - } - } -} - -void SemanticState::cancel(ConsumerImpl::shared_ptr c) -{ - disable(c); - unsubscribe(c); -} - -void SemanticState::handle(intrusive_ptr<Message> msg) { - if (txBuffer.get()) { - TxPublish* deliverable(new TxPublish(msg)); - TxOp::shared_ptr op(deliverable); - route(msg, *deliverable); - txBuffer->enlist(op); - } else { - DeliverableMessage deliverable(msg); - route(msg, deliverable); - if (msg->isContentReleaseRequested()) { - // NOTE: The log messages in this section are used for flow-to-disk testing (which checks the log for the - // presence of these messages). Do not change these without also checking these tests. - if (msg->isContentReleaseBlocked()) { - QPID_LOG(debug, "Message id=\"" << msg->getProperties<MessageProperties>()->getMessageId() << "\"; pid=0x" << - std::hex << msg->getPersistenceId() << std::dec << ": Content release blocked"); - } else { - msg->releaseContent(); - QPID_LOG(debug, "Message id=\"" << msg->getProperties<MessageProperties>()->getMessageId() << "\"; pid=0x" << - std::hex << msg->getPersistenceId() << std::dec << ": Content released"); - } - } - } -} - -namespace -{ -const std::string nullstring; -} - -void SemanticState::route(intrusive_ptr<Message> msg, Deliverable& strategy) { - msg->setTimestamp(getSession().getBroker().getExpiryPolicy()); - - std::string exchangeName = msg->getExchangeName(); - if (!cacheExchange || cacheExchange->getName() != exchangeName || cacheExchange->isDestroyed()) - cacheExchange = session.getBroker().getExchanges().get(exchangeName); - cacheExchange->setProperties(msg); - - /* verify the userid if specified: */ - std::string id = - msg->hasProperties<MessageProperties>() ? msg->getProperties<MessageProperties>()->getUserId() : nullstring; - - if (authMsg && !id.empty() && !(id == userID || (isDefaultRealm && id == userName))) - { - QPID_LOG(debug, "authorised user id : " << userID << " but user id in message declared as " << id); - throw UnauthorizedAccessException(QPID_MSG("authorised user id : " << userID << " but user id in message declared as " << id)); - } - - if (acl && acl->doTransferAcl()) - { - if (!acl->authorise(getSession().getConnection().getUserId(),acl::ACT_PUBLISH,acl::OBJ_EXCHANGE,exchangeName, msg->getRoutingKey() )) - throw UnauthorizedAccessException(QPID_MSG(userID << " cannot publish to " << - exchangeName << " with routing-key " << msg->getRoutingKey())); - } - - cacheExchange->route(strategy, msg->getRoutingKey(), msg->getApplicationHeaders()); - - if (!strategy.delivered) { - //TODO:if discard-unroutable, just drop it - //TODO:else if accept-mode is explicit, reject it - //else route it to alternate exchange - if (cacheExchange->getAlternate()) { - cacheExchange->getAlternate()->route(strategy, msg->getRoutingKey(), msg->getApplicationHeaders()); - } - if (!strategy.delivered) { - msg->destroy(); - } - } - -} - -void SemanticState::requestDispatch() -{ - for (ConsumerImplMap::iterator i = consumers.begin(); i != consumers.end(); i++) - i->second->requestDispatch(); -} - -void SemanticState::ConsumerImpl::requestDispatch() -{ - assertClusterSafe(); - if (blocked) { - parent->session.getConnection().outputTasks.addOutputTask(this); - parent->session.getConnection().outputTasks.activateOutput(); - blocked = false; - } -} - -bool SemanticState::complete(DeliveryRecord& delivery) -{ - ConsumerImplMap::iterator i = consumers.find(delivery.getTag()); - if (i != consumers.end()) { - i->second->complete(delivery); - } - return delivery.isRedundant(); -} - -void SemanticState::ConsumerImpl::complete(DeliveryRecord& delivery) -{ - if (!delivery.isComplete()) { - delivery.complete(); - if (windowing) { - if (msgCredit != 0xFFFFFFFF) msgCredit++; - if (byteCredit != 0xFFFFFFFF) byteCredit += delivery.getCredit(); - } - } -} - -void SemanticState::recover(bool requeue) -{ - if(requeue){ - //take copy and clear unacked as requeue may result in redelivery to this session - //which will in turn result in additions to unacked - DeliveryRecords copy = unacked; - unacked.clear(); - for_each(copy.rbegin(), copy.rend(), mem_fun_ref(&DeliveryRecord::requeue)); - }else{ - for_each(unacked.begin(), unacked.end(), boost::bind(&DeliveryRecord::redeliver, _1, this)); - //unconfirmed messages re redelivered and therefore have their - //id adjusted, confirmed messages are not and so the ordering - //w.r.t id is lost - sort(unacked.begin(), unacked.end()); - } -} - -void SemanticState::deliver(DeliveryRecord& msg, bool sync) -{ - return deliveryAdapter.deliver(msg, sync); -} - -SemanticState::ConsumerImpl& SemanticState::find(const std::string& destination) -{ - ConsumerImplMap::iterator i = consumers.find(destination); - if (i == consumers.end()) { - throw NotFoundException(QPID_MSG("Unknown destination " << destination)); - } else { - return *(i->second); - } -} - -void SemanticState::setWindowMode(const std::string& destination) -{ - find(destination).setWindowMode(); -} - -void SemanticState::setCreditMode(const std::string& destination) -{ - find(destination).setCreditMode(); -} - -void SemanticState::addByteCredit(const std::string& destination, uint32_t value) -{ - ConsumerImpl& c = find(destination); - c.addByteCredit(value); - c.requestDispatch(); -} - - -void SemanticState::addMessageCredit(const std::string& destination, uint32_t value) -{ - ConsumerImpl& c = find(destination); - c.addMessageCredit(value); - c.requestDispatch(); -} - -void SemanticState::flush(const std::string& destination) -{ - find(destination).flush(); -} - - -void SemanticState::stop(const std::string& destination) -{ - find(destination).stop(); -} - -void SemanticState::ConsumerImpl::setWindowMode() -{ - assertClusterSafe(); - windowing = true; - if (mgmtObject){ - mgmtObject->set_creditMode("WINDOW"); - } -} - -void SemanticState::ConsumerImpl::setCreditMode() -{ - assertClusterSafe(); - windowing = false; - if (mgmtObject){ - mgmtObject->set_creditMode("CREDIT"); - } -} - -void SemanticState::ConsumerImpl::addByteCredit(uint32_t value) -{ - assertClusterSafe(); - if (byteCredit != 0xFFFFFFFF) { - if (value == 0xFFFFFFFF) byteCredit = value; - else byteCredit += value; - } -} - -void SemanticState::ConsumerImpl::addMessageCredit(uint32_t value) -{ - assertClusterSafe(); - if (msgCredit != 0xFFFFFFFF) { - if (value == 0xFFFFFFFF) msgCredit = value; - else msgCredit += value; - } -} - -bool SemanticState::ConsumerImpl::haveCredit() -{ - if (msgCredit && byteCredit) { - return true; - } else { - blocked = true; - return false; - } -} - -void SemanticState::ConsumerImpl::flush() -{ - while(haveCredit() && queue->dispatch(shared_from_this())) - ; - stop(); -} - -void SemanticState::ConsumerImpl::stop() -{ - assertClusterSafe(); - msgCredit = 0; - byteCredit = 0; -} - -Queue::shared_ptr SemanticState::getQueue(const string& name) const { - Queue::shared_ptr queue; - if (name.empty()) { - throw NotAllowedException(QPID_MSG("No queue name specified.")); - } else { - queue = session.getBroker().getQueues().find(name); - if (!queue) - throw NotFoundException(QPID_MSG("Queue not found: "<<name)); - } - return queue; -} - -AckRange SemanticState::findRange(DeliveryId first, DeliveryId last) -{ - return DeliveryRecord::findRange(unacked, first, last); -} - -void SemanticState::acquire(DeliveryId first, DeliveryId last, DeliveryIds& acquired) -{ - AckRange range = findRange(first, last); - for_each(range.start, range.end, AcquireFunctor(acquired)); -} - -void SemanticState::release(DeliveryId first, DeliveryId last, bool setRedelivered) -{ - AckRange range = findRange(first, last); - //release results in the message being added to the head so want - //to release in reverse order to keep the original transfer order - DeliveryRecords::reverse_iterator start(range.end); - DeliveryRecords::reverse_iterator end(range.start); - for_each(start, end, boost::bind(&DeliveryRecord::release, _1, setRedelivered)); -} - -void SemanticState::reject(DeliveryId first, DeliveryId last) -{ - AckRange range = findRange(first, last); - for_each(range.start, range.end, mem_fun_ref(&DeliveryRecord::reject)); - //may need to remove the delivery records as well - for (DeliveryRecords::iterator i = range.start; i != unacked.end() && i->getId() <= last; ) { - if (i->isRedundant()) i = unacked.erase(i); - else i++; - } -} - -bool SemanticState::ConsumerImpl::doOutput() -{ - try { - return haveCredit() && queue->dispatch(shared_from_this()); - } catch (const SessionException& e) { - throw SessionOutputException(e, parent->session.getChannel()); - } -} - -void SemanticState::ConsumerImpl::enableNotify() -{ - Mutex::ScopedLock l(lock); - assertClusterSafe(); - notifyEnabled = true; -} - -void SemanticState::ConsumerImpl::disableNotify() -{ - Mutex::ScopedLock l(lock); - notifyEnabled = false; -} - -bool SemanticState::ConsumerImpl::isNotifyEnabled() const { - Mutex::ScopedLock l(lock); - return notifyEnabled; -} - -void SemanticState::ConsumerImpl::notify() -{ - Mutex::ScopedLock l(lock); - assertClusterSafe(); - if (notifyEnabled) { - parent->session.getConnection().outputTasks.addOutputTask(this); - parent->session.getConnection().outputTasks.activateOutput(); - } -} - - -// Test that a DeliveryRecord's ID is in a sequence set and some other -// predicate on DeliveryRecord holds. -template <class Predicate> struct IsInSequenceSetAnd { - IsInSequenceSet isInSet; - Predicate predicate; - IsInSequenceSetAnd(const SequenceSet& s, Predicate p) : isInSet(s), predicate(p) {} - bool operator()(DeliveryRecord& dr) { - return isInSet(dr.getId()) && predicate(dr); - } -}; - -template<class Predicate> IsInSequenceSetAnd<Predicate> -isInSequenceSetAnd(const SequenceSet& s, Predicate p) { - return IsInSequenceSetAnd<Predicate>(s,p); -} - -void SemanticState::accepted(const SequenceSet& commands) { - assertClusterSafe(); - if (txBuffer.get()) { - //in transactional mode, don't dequeue or remove, just - //maintain set of acknowledged messages: - accumulatedAck.add(commands); - - if (dtxBuffer.get()) { - //if enlisted in a dtx, copy the relevant slice from - //unacked and record it against that transaction - TxOp::shared_ptr txAck(new DtxAck(accumulatedAck, unacked)); - accumulatedAck.clear(); - dtxBuffer->enlist(txAck); - - //mark the relevant messages as 'ended' in unacked - //if the messages are already completed, they can be - //removed from the record - DeliveryRecords::iterator removed = - remove_if(unacked.begin(), unacked.end(), - isInSequenceSetAnd(commands, - bind(&DeliveryRecord::setEnded, _1))); - unacked.erase(removed, unacked.end()); - } - } else { - DeliveryRecords::iterator removed = - remove_if(unacked.begin(), unacked.end(), - isInSequenceSetAnd(commands, - bind(&DeliveryRecord::accept, _1, - (TransactionContext*) 0))); - unacked.erase(removed, unacked.end()); - } -} - -void SemanticState::completed(const SequenceSet& commands) { - DeliveryRecords::iterator removed = - remove_if(unacked.begin(), unacked.end(), - isInSequenceSetAnd(commands, - bind(&SemanticState::complete, this, _1))); - unacked.erase(removed, unacked.end()); - requestDispatch(); -} - -void SemanticState::attached() -{ - for (ConsumerImplMap::iterator i = consumers.begin(); i != consumers.end(); i++) { - i->second->enableNotify(); - session.getConnection().outputTasks.addOutputTask(i->second.get()); - } - session.getConnection().outputTasks.activateOutput(); -} - -void SemanticState::detached() -{ - for (ConsumerImplMap::iterator i = consumers.begin(); i != consumers.end(); i++) { - i->second->disableNotify(); - session.getConnection().outputTasks.removeOutputTask(i->second.get()); - } -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/SemanticState.h b/cpp/src/qpid/broker/SemanticState.h deleted file mode 100644 index 8c69d6b89b..0000000000 --- a/cpp/src/qpid/broker/SemanticState.h +++ /dev/null @@ -1,257 +0,0 @@ -#ifndef QPID_BROKER_SEMANTICSTATE_H -#define QPID_BROKER_SEMANTICSTATE_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/Consumer.h" -#include "qpid/broker/Deliverable.h" -#include "qpid/broker/DeliveryAdapter.h" -#include "qpid/broker/DeliveryRecord.h" -#include "qpid/broker/DtxBuffer.h" -#include "qpid/broker/DtxManager.h" -#include "qpid/broker/NameGenerator.h" -#include "qpid/broker/TxBuffer.h" - -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/SequenceSet.h" -#include "qpid/framing/Uuid.h" -#include "qpid/sys/AggregateOutput.h" -#include "qpid/sys/Mutex.h" -#include "qpid/sys/AtomicValue.h" -#include "qpid/broker/AclModule.h" -#include "qmf/org/apache/qpid/broker/Subscription.h" - -#include <list> -#include <map> -#include <vector> - -#include <boost/enable_shared_from_this.hpp> -#include <boost/intrusive_ptr.hpp> -#include <boost/cast.hpp> - -namespace qpid { -namespace broker { - -class SessionContext; - -/** - * - * SemanticState implements the behavior of a Session, especially the - * state of consumers subscribed to queues. The code for ConsumerImpl - * is also in SemanticState.cpp - * - * SemanticState holds the AMQP Execution and Model state of an open - * session, whether attached to a channel or suspended. It is not - * dependent on any specific AMQP version. - * - * Message delivery is driven by ConsumerImpl::doOutput(), which is - * called when a client's socket is ready to write data. - * - */ -class SemanticState : private boost::noncopyable { - public: - class ConsumerImpl : public Consumer, public sys::OutputTask, - public boost::enable_shared_from_this<ConsumerImpl>, - public management::Manageable - { - mutable qpid::sys::Mutex lock; - SemanticState* const parent; - const std::string name; - const boost::shared_ptr<Queue> queue; - const bool ackExpected; - const bool acquire; - bool blocked; - bool windowing; - bool exclusive; - std::string resumeId; - uint64_t resumeTtl; - framing::FieldTable arguments; - uint32_t msgCredit; - uint32_t byteCredit; - bool notifyEnabled; - const int syncFrequency; - int deliveryCount; - qmf::org::apache::qpid::broker::Subscription* mgmtObject; - - bool checkCredit(boost::intrusive_ptr<Message>& msg); - void allocateCredit(boost::intrusive_ptr<Message>& msg); - bool haveCredit(); - - public: - typedef boost::shared_ptr<ConsumerImpl> shared_ptr; - - ConsumerImpl(SemanticState* parent, - const std::string& name, boost::shared_ptr<Queue> queue, - bool ack, bool acquire, bool exclusive, - const std::string& resumeId, uint64_t resumeTtl, const framing::FieldTable& arguments); - ~ConsumerImpl(); - OwnershipToken* getSession(); - bool deliver(QueuedMessage& msg); - bool filter(boost::intrusive_ptr<Message> msg); - bool accept(boost::intrusive_ptr<Message> msg); - - void disableNotify(); - void enableNotify(); - void notify(); - bool isNotifyEnabled() const; - - void requestDispatch(); - - void setWindowMode(); - void setCreditMode(); - void addByteCredit(uint32_t value); - void addMessageCredit(uint32_t value); - void flush(); - void stop(); - void complete(DeliveryRecord&); - boost::shared_ptr<Queue> getQueue() const { return queue; } - bool isBlocked() const { return blocked; } - bool setBlocked(bool set) { std::swap(set, blocked); return set; } - - bool doOutput(); - - std::string getName() const { return name; } - - bool isAckExpected() const { return ackExpected; } - bool isAcquire() const { return acquire; } - bool isWindowing() const { return windowing; } - bool isExclusive() const { return exclusive; } - uint32_t getMsgCredit() const { return msgCredit; } - uint32_t getByteCredit() const { return byteCredit; } - std::string getResumeId() const { return resumeId; }; - uint64_t getResumeTtl() const { return resumeTtl; } - const framing::FieldTable& getArguments() const { return arguments; } - - SemanticState& getParent() { return *parent; } - const SemanticState& getParent() const { return *parent; } - // Manageable entry points - management::ManagementObject* GetManagementObject (void) const; - management::Manageable::status_t ManagementMethod (uint32_t methodId, management::Args& args, std::string& text); - }; - - private: - typedef std::map<std::string, ConsumerImpl::shared_ptr> ConsumerImplMap; - typedef std::map<std::string, DtxBuffer::shared_ptr> DtxBufferMap; - - SessionContext& session; - DeliveryAdapter& deliveryAdapter; - ConsumerImplMap consumers; - NameGenerator tagGenerator; - DeliveryRecords unacked; - TxBuffer::shared_ptr txBuffer; - DtxBuffer::shared_ptr dtxBuffer; - bool dtxSelected; - DtxBufferMap suspendedXids; - framing::SequenceSet accumulatedAck; - boost::shared_ptr<Exchange> cacheExchange; - AclModule* acl; - const bool authMsg; - const std::string userID; - const std::string userName; - const bool isDefaultRealm; - bool closeComplete; - - void route(boost::intrusive_ptr<Message> msg, Deliverable& strategy); - void checkDtxTimeout(); - - bool complete(DeliveryRecord&); - AckRange findRange(DeliveryId first, DeliveryId last); - void requestDispatch(); - void cancel(ConsumerImpl::shared_ptr); - void unsubscribe(ConsumerImpl::shared_ptr); - void disable(ConsumerImpl::shared_ptr); - - public: - SemanticState(DeliveryAdapter&, SessionContext&); - ~SemanticState(); - - SessionContext& getSession() { return session; } - const SessionContext& getSession() const { return session; } - - ConsumerImpl& find(const std::string& destination); - - /** - * Get named queue, never returns 0. - * @return: named queue - * @exception: ChannelException if no queue of that name is found. - * @exception: ConnectionException if name="" and session has no default. - */ - boost::shared_ptr<Queue> getQueue(const std::string& name) const; - - bool exists(const std::string& consumerTag); - - void consume(const std::string& destination, - boost::shared_ptr<Queue> queue, - bool ackRequired, bool acquire, bool exclusive, - const std::string& resumeId=std::string(), uint64_t resumeTtl=0, - const framing::FieldTable& = framing::FieldTable()); - - bool cancel(const std::string& tag); - - void setWindowMode(const std::string& destination); - void setCreditMode(const std::string& destination); - void addByteCredit(const std::string& destination, uint32_t value); - void addMessageCredit(const std::string& destination, uint32_t value); - void flush(const std::string& destination); - void stop(const std::string& destination); - - void startTx(); - void commit(MessageStore* const store); - void rollback(); - void selectDtx(); - void startDtx(const std::string& xid, DtxManager& mgr, bool join); - void endDtx(const std::string& xid, bool fail); - void suspendDtx(const std::string& xid); - void resumeDtx(const std::string& xid); - void recover(bool requeue); - void deliver(DeliveryRecord& message, bool sync); - void acquire(DeliveryId first, DeliveryId last, DeliveryIds& acquired); - void release(DeliveryId first, DeliveryId last, bool setRedelivered); - void reject(DeliveryId first, DeliveryId last); - void handle(boost::intrusive_ptr<Message> msg); - - void completed(const framing::SequenceSet& commands); - void accepted(const framing::SequenceSet& commands); - - void attached(); - void detached(); - void closed(); - - // Used by cluster to re-create sessions - template <class F> void eachConsumer(F f) { - for(ConsumerImplMap::iterator i = consumers.begin(); i != consumers.end(); ++i) - f(i->second); - } - DeliveryRecords& getUnacked() { return unacked; } - framing::SequenceSet getAccumulatedAck() const { return accumulatedAck; } - TxBuffer::shared_ptr getTxBuffer() const { return txBuffer; } - void setTxBuffer(const TxBuffer::shared_ptr& txb) { txBuffer = txb; } - void setAccumulatedAck(const framing::SequenceSet& s) { accumulatedAck = s; } - void record(const DeliveryRecord& delivery); -}; - -}} // namespace qpid::broker - - - - -#endif /*!QPID_BROKER_SEMANTICSTATE_H*/ diff --git a/cpp/src/qpid/broker/SessionAdapter.cpp b/cpp/src/qpid/broker/SessionAdapter.cpp deleted file mode 100644 index 63c4b660b2..0000000000 --- a/cpp/src/qpid/broker/SessionAdapter.cpp +++ /dev/null @@ -1,693 +0,0 @@ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ -#include "qpid/broker/SessionAdapter.h" -#include "qpid/broker/Connection.h" -#include "qpid/broker/Queue.h" -#include "qpid/Exception.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/enum.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/SequenceSet.h" -#include "qpid/management/ManagementAgent.h" -#include "qpid/broker/SessionState.h" -#include "qmf/org/apache/qpid/broker/EventExchangeDeclare.h" -#include "qmf/org/apache/qpid/broker/EventExchangeDelete.h" -#include "qmf/org/apache/qpid/broker/EventQueueDeclare.h" -#include "qmf/org/apache/qpid/broker/EventQueueDelete.h" -#include "qmf/org/apache/qpid/broker/EventBind.h" -#include "qmf/org/apache/qpid/broker/EventUnbind.h" -#include "qmf/org/apache/qpid/broker/EventSubscribe.h" -#include "qmf/org/apache/qpid/broker/EventUnsubscribe.h" -#include <boost/format.hpp> -#include <boost/cast.hpp> -#include <boost/bind.hpp> - -namespace qpid { -namespace broker { - -using namespace qpid; -using namespace qpid::framing; -using namespace qpid::framing::dtx; -using namespace qpid::management; -namespace _qmf = qmf::org::apache::qpid::broker; - -typedef std::vector<Queue::shared_ptr> QueueVector; - -SessionAdapter::SessionAdapter(SemanticState& s) : - HandlerImpl(s), - exchangeImpl(s), - queueImpl(s), - messageImpl(s), - executionImpl(s), - txImpl(s), - dtxImpl(s) -{} - -static const std::string _TRUE("true"); -static const std::string _FALSE("false"); - -void SessionAdapter::ExchangeHandlerImpl::declare(const string& exchange, const string& type, - const string& alternateExchange, - bool passive, bool durable, bool /*autoDelete*/, const FieldTable& args){ - - //TODO: implement autoDelete - Exchange::shared_ptr alternate; - if (!alternateExchange.empty()) { - alternate = getBroker().getExchanges().get(alternateExchange); - } - if(passive){ - AclModule* acl = getBroker().getAcl(); - if (acl) { - //TODO: why does a passive declare require create - //permission? The purpose of the passive flag is to state - //that the exchange should *not* created. For - //authorisation a passive declare is similar to - //exchange-query. - std::map<acl::Property, std::string> params; - params.insert(make_pair(acl::PROP_TYPE, type)); - params.insert(make_pair(acl::PROP_ALTERNATE, alternateExchange)); - params.insert(make_pair(acl::PROP_PASSIVE, _TRUE)); - params.insert(make_pair(acl::PROP_DURABLE, durable ? _TRUE : _FALSE)); - if (!acl->authorise(getConnection().getUserId(),acl::ACT_CREATE,acl::OBJ_EXCHANGE,exchange,¶ms) ) - throw framing::UnauthorizedAccessException(QPID_MSG("ACL denied exchange create request from " << getConnection().getUserId())); - } - Exchange::shared_ptr actual(getBroker().getExchanges().get(exchange)); - checkType(actual, type); - checkAlternate(actual, alternate); - }else{ - if(exchange.find("amq.") == 0 || exchange.find("qpid.") == 0) { - throw framing::NotAllowedException(QPID_MSG("Exchange names beginning with \"amq.\" or \"qpid.\" are reserved. (exchange=\"" << exchange << "\")")); - } - try{ - std::pair<Exchange::shared_ptr, bool> response = - getBroker().createExchange(exchange, type, durable, alternateExchange, args, - getConnection().getUserId(), getConnection().getUrl()); - if (!response.second) { - //exchange already there, not created - checkType(response.first, type); - checkAlternate(response.first, alternate); - ManagementAgent* agent = getBroker().getManagementAgent(); - if (agent) - agent->raiseEvent(_qmf::EventExchangeDeclare(getConnection().getUrl(), - getConnection().getUserId(), - exchange, - type, - alternateExchange, - durable, - false, - ManagementAgent::toMap(args), - "existing")); - } - }catch(UnknownExchangeTypeException& /*e*/){ - throw NotFoundException(QPID_MSG("Exchange type not implemented: " << type)); - } - } -} - -void SessionAdapter::ExchangeHandlerImpl::checkType(Exchange::shared_ptr exchange, const std::string& type) -{ - if (!type.empty() && exchange->getType() != type) { - throw NotAllowedException(QPID_MSG("Exchange declared to be of type " << exchange->getType() << ", requested " << type)); - } -} - -void SessionAdapter::ExchangeHandlerImpl::checkAlternate(Exchange::shared_ptr exchange, Exchange::shared_ptr alternate) -{ - if (alternate && ((exchange->getAlternate() && alternate != exchange->getAlternate()) - || !exchange->getAlternate())) - throw NotAllowedException(QPID_MSG("Exchange declared with alternate-exchange " - << (exchange->getAlternate() ? exchange->getAlternate()->getName() : "<nonexistent>") - << ", requested " - << alternate->getName())); -} - -void SessionAdapter::ExchangeHandlerImpl::delete_(const string& name, bool /*ifUnused*/) -{ - //TODO: implement if-unused - getBroker().deleteExchange(name, getConnection().getUserId(), getConnection().getUrl()); -} - -ExchangeQueryResult SessionAdapter::ExchangeHandlerImpl::query(const string& name) -{ - AclModule* acl = getBroker().getAcl(); - if (acl) { - if (!acl->authorise(getConnection().getUserId(),acl::ACT_ACCESS,acl::OBJ_EXCHANGE,name,NULL) ) - throw UnauthorizedAccessException(QPID_MSG("ACL denied exchange query request from " << getConnection().getUserId())); - } - - try { - Exchange::shared_ptr exchange(getBroker().getExchanges().get(name)); - return ExchangeQueryResult(exchange->getType(), exchange->isDurable(), false, exchange->getArgs()); - } catch (const NotFoundException& /*e*/) { - return ExchangeQueryResult("", false, true, FieldTable()); - } -} - -void SessionAdapter::ExchangeHandlerImpl::bind(const string& queueName, - const string& exchangeName, const string& routingKey, - const FieldTable& arguments) -{ - getBroker().bind(queueName, exchangeName, routingKey, arguments, - getConnection().getUserId(), getConnection().getUrl()); -} - -void SessionAdapter::ExchangeHandlerImpl::unbind(const string& queueName, - const string& exchangeName, - const string& routingKey) -{ - getBroker().unbind(queueName, exchangeName, routingKey, - getConnection().getUserId(), getConnection().getUrl()); -} - -ExchangeBoundResult SessionAdapter::ExchangeHandlerImpl::bound(const std::string& exchangeName, - const std::string& queueName, - const std::string& key, - const framing::FieldTable& args) -{ - AclModule* acl = getBroker().getAcl(); - if (acl) { - std::map<acl::Property, std::string> params; - params.insert(make_pair(acl::PROP_QUEUENAME, queueName)); - params.insert(make_pair(acl::PROP_ROUTINGKEY, key)); - if (!acl->authorise(getConnection().getUserId(),acl::ACT_ACCESS,acl::OBJ_EXCHANGE,exchangeName,¶ms) ) - throw UnauthorizedAccessException(QPID_MSG("ACL denied exchange bound request from " << getConnection().getUserId())); - } - - Exchange::shared_ptr exchange; - try { - exchange = getBroker().getExchanges().get(exchangeName); - } catch (const NotFoundException&) {} - - Queue::shared_ptr queue; - if (!queueName.empty()) { - queue = getBroker().getQueues().find(queueName); - } - - if (!exchange) { - return ExchangeBoundResult(true, (!queueName.empty() && !queue), false, false, false); - } else if (!queueName.empty() && !queue) { - return ExchangeBoundResult(false, true, false, false, false); - } else if (exchange->isBound(queue, key.empty() ? 0 : &key, args.count() > 0 ? &args : &args)) { - return ExchangeBoundResult(false, false, false, false, false); - } else { - //need to test each specified option individually - bool queueMatched = queueName.empty() || exchange->isBound(queue, 0, 0); - bool keyMatched = key.empty() || exchange->isBound(Queue::shared_ptr(), &key, 0); - bool argsMatched = args.count() == 0 || exchange->isBound(Queue::shared_ptr(), 0, &args); - - return ExchangeBoundResult(false, false, !queueMatched, !keyMatched, !argsMatched); - } -} - -SessionAdapter::QueueHandlerImpl::QueueHandlerImpl(SemanticState& session) : HandlerHelper(session), broker(getBroker()) -{} - - -SessionAdapter::QueueHandlerImpl::~QueueHandlerImpl() -{ - try { - destroyExclusiveQueues(); - } catch (std::exception& e) { - QPID_LOG(error, e.what()); - } -} - -void SessionAdapter::QueueHandlerImpl::destroyExclusiveQueues() -{ - while (!exclusiveQueues.empty()) { - Queue::shared_ptr q(exclusiveQueues.front()); - q->releaseExclusiveOwnership(); - if (q->canAutoDelete()) { - Queue::tryAutoDelete(broker, q); - } - exclusiveQueues.erase(exclusiveQueues.begin()); - } -} - -bool SessionAdapter::QueueHandlerImpl::isLocal(const ConnectionToken* t) const -{ - return session.isLocal(t); -} - - -QueueQueryResult SessionAdapter::QueueHandlerImpl::query(const string& name) -{ - AclModule* acl = getBroker().getAcl(); - if (acl) { - if (!acl->authorise(getConnection().getUserId(),acl::ACT_ACCESS,acl::OBJ_QUEUE,name,NULL) ) - throw UnauthorizedAccessException(QPID_MSG("ACL denied queue query request from " << getConnection().getUserId())); - } - - Queue::shared_ptr queue = session.getBroker().getQueues().find(name); - if (queue) { - - Exchange::shared_ptr alternateExchange = queue->getAlternateExchange(); - - return QueueQueryResult(queue->getName(), - alternateExchange ? alternateExchange->getName() : "", - queue->isDurable(), - queue->hasExclusiveOwner(), - queue->isAutoDelete(), - queue->getSettings(), - queue->getMessageCount(), - queue->getConsumerCount()); - } else { - return QueueQueryResult(); - } -} - -void SessionAdapter::QueueHandlerImpl::declare(const string& name, const string& alternateExchange, - bool passive, bool durable, bool exclusive, - bool autoDelete, const qpid::framing::FieldTable& arguments) -{ - Queue::shared_ptr queue; - if (passive && !name.empty()) { - AclModule* acl = getBroker().getAcl(); - if (acl) { - //TODO: why does a passive declare require create - //permission? The purpose of the passive flag is to state - //that the queue should *not* created. For - //authorisation a passive declare is similar to - //queue-query (or indeed a qmf query). - std::map<acl::Property, std::string> params; - params.insert(make_pair(acl::PROP_ALTERNATE, alternateExchange)); - params.insert(make_pair(acl::PROP_PASSIVE, _TRUE)); - params.insert(make_pair(acl::PROP_DURABLE, std::string(durable ? _TRUE : _FALSE))); - params.insert(make_pair(acl::PROP_EXCLUSIVE, std::string(exclusive ? _TRUE : _FALSE))); - params.insert(make_pair(acl::PROP_AUTODELETE, std::string(autoDelete ? _TRUE : _FALSE))); - params.insert(make_pair(acl::PROP_POLICYTYPE, arguments.getAsString("qpid.policy_type"))); - params.insert(make_pair(acl::PROP_MAXQUEUECOUNT, boost::lexical_cast<string>(arguments.getAsInt("qpid.max_count")))); - params.insert(make_pair(acl::PROP_MAXQUEUESIZE, boost::lexical_cast<string>(arguments.getAsInt64("qpid.max_size")))); - if (!acl->authorise(getConnection().getUserId(),acl::ACT_CREATE,acl::OBJ_QUEUE,name,¶ms) ) - throw UnauthorizedAccessException(QPID_MSG("ACL denied queue create request from " << getConnection().getUserId())); - } - queue = getQueue(name); - //TODO: check alternate-exchange is as expected - } else { - std::pair<Queue::shared_ptr, bool> queue_created = - getBroker().createQueue(name, durable, - autoDelete, - exclusive ? &session : 0, - alternateExchange, - arguments, - getConnection().getUserId(), - getConnection().getUrl()); - queue = queue_created.first; - assert(queue); - if (queue_created.second) { // This is a new queue - //handle automatic cleanup: - if (exclusive) { - exclusiveQueues.push_back(queue); - } - } else { - if (exclusive && queue->setExclusiveOwner(&session)) { - exclusiveQueues.push_back(queue); - } - ManagementAgent* agent = getBroker().getManagementAgent(); - if (agent) - agent->raiseEvent(_qmf::EventQueueDeclare(getConnection().getUrl(), getConnection().getUserId(), - name, durable, exclusive, autoDelete, ManagementAgent::toMap(arguments), - "existing")); - } - - } - - if (exclusive && !queue->isExclusiveOwner(&session)) - throw ResourceLockedException(QPID_MSG("Cannot grant exclusive access to queue " - << queue->getName())); -} - -void SessionAdapter::QueueHandlerImpl::purge(const string& queue){ - AclModule* acl = getBroker().getAcl(); - if (acl) - { - if (!acl->authorise(getConnection().getUserId(),acl::ACT_PURGE,acl::OBJ_QUEUE,queue,NULL) ) - throw UnauthorizedAccessException(QPID_MSG("ACL denied queue purge request from " << getConnection().getUserId())); - } - getQueue(queue)->purge(); -} - -void SessionAdapter::QueueHandlerImpl::checkDelete(Queue::shared_ptr queue, bool ifUnused, bool ifEmpty) -{ - if (queue->hasExclusiveOwner() && !queue->isExclusiveOwner(&session)) { - throw ResourceLockedException(QPID_MSG("Cannot delete queue " - << queue->getName() << "; it is exclusive to another session")); - } else if(ifEmpty && queue->getMessageCount() > 0) { - throw PreconditionFailedException(QPID_MSG("Cannot delete queue " - << queue->getName() << "; queue not empty")); - } else if(ifUnused && queue->getConsumerCount() > 0) { - throw PreconditionFailedException(QPID_MSG("Cannot delete queue " - << queue->getName() << "; queue in use")); - } else if (queue->isExclusiveOwner(&session)) { - //remove the queue from the list of exclusive queues if necessary - QueueVector::iterator i = std::find(exclusiveQueues.begin(), - exclusiveQueues.end(), - queue); - if (i < exclusiveQueues.end()) exclusiveQueues.erase(i); - } -} - -void SessionAdapter::QueueHandlerImpl::delete_(const string& queue, bool ifUnused, bool ifEmpty) -{ - getBroker().deleteQueue(queue, getConnection().getUserId(), getConnection().getUrl(), - boost::bind(&SessionAdapter::QueueHandlerImpl::checkDelete, this, _1, ifUnused, ifEmpty)); -} - -SessionAdapter::MessageHandlerImpl::MessageHandlerImpl(SemanticState& s) : - HandlerHelper(s), - releaseRedeliveredOp(boost::bind(&SemanticState::release, &state, _1, _2, true)), - releaseOp(boost::bind(&SemanticState::release, &state, _1, _2, false)), - rejectOp(boost::bind(&SemanticState::reject, &state, _1, _2)) - {} - -// -// Message class method handlers -// - -void SessionAdapter::MessageHandlerImpl::transfer(const string& /*destination*/, - uint8_t /*acceptMode*/, - uint8_t /*acquireMode*/) -{ - //not yet used (content containing assemblies treated differently at present - std::cout << "SessionAdapter::MessageHandlerImpl::transfer() called" << std::endl; -} - -void SessionAdapter::MessageHandlerImpl::release(const SequenceSet& transfers, bool setRedelivered) -{ - transfers.for_each(setRedelivered ? releaseRedeliveredOp : releaseOp); -} - -void -SessionAdapter::MessageHandlerImpl::subscribe(const string& queueName, - const string& destination, - uint8_t acceptMode, - uint8_t acquireMode, - bool exclusive, - const string& resumeId, - uint64_t resumeTtl, - const FieldTable& arguments) -{ - - AclModule* acl = getBroker().getAcl(); - if (acl) - { - if (!acl->authorise(getConnection().getUserId(),acl::ACT_CONSUME,acl::OBJ_QUEUE,queueName,NULL) ) - throw UnauthorizedAccessException(QPID_MSG("ACL denied Queue subscribe request from " << getConnection().getUserId())); - } - - Queue::shared_ptr queue = getQueue(queueName); - if(!destination.empty() && state.exists(destination)) - throw NotAllowedException(QPID_MSG("Consumer tags must be unique")); - - if (queue->hasExclusiveOwner() && !queue->isExclusiveOwner(&session) && acquireMode == 0) - throw ResourceLockedException(QPID_MSG("Cannot subscribe to exclusive queue " - << queue->getName())); - - state.consume(destination, queue, - acceptMode == 0, acquireMode == 0, exclusive, - resumeId, resumeTtl, arguments); - - ManagementAgent* agent = getBroker().getManagementAgent(); - if (agent) - agent->raiseEvent(_qmf::EventSubscribe(getConnection().getUrl(), getConnection().getUserId(), - queueName, destination, exclusive, ManagementAgent::toMap(arguments))); -} - -void -SessionAdapter::MessageHandlerImpl::cancel(const string& destination ) -{ - if (!state.cancel(destination)) { - throw NotFoundException(QPID_MSG("No such subscription: " << destination)); - } - - ManagementAgent* agent = getBroker().getManagementAgent(); - if (agent) - agent->raiseEvent(_qmf::EventUnsubscribe(getConnection().getUrl(), getConnection().getUserId(), destination)); -} - -void -SessionAdapter::MessageHandlerImpl::reject(const SequenceSet& transfers, uint16_t /*code*/, const string& /*text*/ ) -{ - transfers.for_each(rejectOp); -} - -void SessionAdapter::MessageHandlerImpl::flow(const std::string& destination, uint8_t unit, uint32_t value) -{ - if (unit == 0) { - //message - state.addMessageCredit(destination, value); - } else if (unit == 1) { - //bytes - state.addByteCredit(destination, value); - } else { - //unknown - throw InvalidArgumentException(QPID_MSG("Invalid value for unit " << unit)); - } - -} - -void SessionAdapter::MessageHandlerImpl::setFlowMode(const std::string& destination, uint8_t mode) -{ - if (mode == 0) { - //credit - state.setCreditMode(destination); - } else if (mode == 1) { - //window - state.setWindowMode(destination); - } else{ - throw InvalidArgumentException(QPID_MSG("Invalid value for mode " << mode)); - } -} - -void SessionAdapter::MessageHandlerImpl::flush(const std::string& destination) -{ - state.flush(destination); -} - -void SessionAdapter::MessageHandlerImpl::stop(const std::string& destination) -{ - state.stop(destination); -} - -void SessionAdapter::MessageHandlerImpl::accept(const framing::SequenceSet& commands) -{ - state.accepted(commands); -} - -framing::MessageAcquireResult SessionAdapter::MessageHandlerImpl::acquire(const framing::SequenceSet& transfers) -{ - // FIXME aconway 2008-05-12: create SequenceSet directly, no need for intermediate results vector. - SequenceNumberSet results; - RangedOperation f = boost::bind(&SemanticState::acquire, &state, _1, _2, boost::ref(results)); - transfers.for_each(f); - - results = results.condense(); - SequenceSet acquisitions; - RangedOperation g = boost::bind(&SequenceSet::add, &acquisitions, _1, _2); - results.processRanges(g); - - return MessageAcquireResult(acquisitions); -} - -framing::MessageResumeResult SessionAdapter::MessageHandlerImpl::resume(const std::string& /*destination*/, - const std::string& /*resumeId*/) -{ - throw NotImplementedException("resuming transfers not yet supported"); -} - - - -void SessionAdapter::ExecutionHandlerImpl::sync() -{ - session.addPendingExecutionSync(); - /** @todo KAG - need a generic mechanism to allow a command to returning "not completed" status back to SessionState */ - -} - -void SessionAdapter::ExecutionHandlerImpl::result(const SequenceNumber& /*commandId*/, const string& /*value*/) -{ - //TODO: but currently never used client->server -} - -void SessionAdapter::ExecutionHandlerImpl::exception(uint16_t /*errorCode*/, - const SequenceNumber& /*commandId*/, - uint8_t /*classCode*/, - uint8_t /*commandCode*/, - uint8_t /*fieldIndex*/, - const std::string& /*description*/, - const framing::FieldTable& /*errorInfo*/) -{ - //TODO: again, not really used client->server but may be important - //for inter-broker links -} - - - -void SessionAdapter::TxHandlerImpl::select() -{ - state.startTx(); -} - -void SessionAdapter::TxHandlerImpl::commit() -{ - state.commit(&getBroker().getStore()); -} - -void SessionAdapter::TxHandlerImpl::rollback() -{ - state.rollback(); -} - -std::string SessionAdapter::DtxHandlerImpl::convert(const framing::Xid& xid) -{ - std::string encoded; - encode(xid, encoded); - return encoded; -} - -void SessionAdapter::DtxHandlerImpl::select() -{ - state.selectDtx(); -} - -XaResult SessionAdapter::DtxHandlerImpl::end(const Xid& xid, - bool fail, - bool suspend) -{ - try { - if (fail) { - state.endDtx(convert(xid), true); - if (suspend) { - throw CommandInvalidException(QPID_MSG("End and suspend cannot both be set.")); - } else { - return XaResult(XA_STATUS_XA_RBROLLBACK); - } - } else { - if (suspend) { - state.suspendDtx(convert(xid)); - } else { - state.endDtx(convert(xid), false); - } - return XaResult(XA_STATUS_XA_OK); - } - } catch (const DtxTimeoutException& /*e*/) { - return XaResult(XA_STATUS_XA_RBTIMEOUT); - } -} - -XaResult SessionAdapter::DtxHandlerImpl::start(const Xid& xid, - bool join, - bool resume) -{ - if (join && resume) { - throw CommandInvalidException(QPID_MSG("Join and resume cannot both be set.")); - } - try { - if (resume) { - state.resumeDtx(convert(xid)); - } else { - state.startDtx(convert(xid), getBroker().getDtxManager(), join); - } - return XaResult(XA_STATUS_XA_OK); - } catch (const DtxTimeoutException& /*e*/) { - return XaResult(XA_STATUS_XA_RBTIMEOUT); - } -} - -XaResult SessionAdapter::DtxHandlerImpl::prepare(const Xid& xid) -{ - try { - bool ok = getBroker().getDtxManager().prepare(convert(xid)); - return XaResult(ok ? XA_STATUS_XA_OK : XA_STATUS_XA_RBROLLBACK); - } catch (const DtxTimeoutException& /*e*/) { - return XaResult(XA_STATUS_XA_RBTIMEOUT); - } -} - -XaResult SessionAdapter::DtxHandlerImpl::commit(const Xid& xid, - bool onePhase) -{ - try { - bool ok = getBroker().getDtxManager().commit(convert(xid), onePhase); - return XaResult(ok ? XA_STATUS_XA_OK : XA_STATUS_XA_RBROLLBACK); - } catch (const DtxTimeoutException& /*e*/) { - return XaResult(XA_STATUS_XA_RBTIMEOUT); - } -} - - -XaResult SessionAdapter::DtxHandlerImpl::rollback(const Xid& xid) -{ - try { - getBroker().getDtxManager().rollback(convert(xid)); - return XaResult(XA_STATUS_XA_OK); - } catch (const DtxTimeoutException& /*e*/) { - return XaResult(XA_STATUS_XA_RBTIMEOUT); - } -} - -DtxRecoverResult SessionAdapter::DtxHandlerImpl::recover() -{ - std::set<std::string> xids; - getBroker().getStore().collectPreparedXids(xids); - /* - * create array of long structs - */ - Array indoubt(0xAB); - for (std::set<std::string>::iterator i = xids.begin(); i != xids.end(); i++) { - boost::shared_ptr<FieldValue> xid(new Struct32Value(*i)); - indoubt.add(xid); - } - return DtxRecoverResult(indoubt); -} - -void SessionAdapter::DtxHandlerImpl::forget(const Xid& xid) -{ - //Currently no heuristic completion is supported, so this should never be used. - throw NotImplementedException(QPID_MSG("Forget not implemented. Branch with xid " << xid << " not heuristically completed!")); -} - -DtxGetTimeoutResult SessionAdapter::DtxHandlerImpl::getTimeout(const Xid& xid) -{ - uint32_t timeout = getBroker().getDtxManager().getTimeout(convert(xid)); - return DtxGetTimeoutResult(timeout); -} - - -void SessionAdapter::DtxHandlerImpl::setTimeout(const Xid& xid, - uint32_t timeout) -{ - getBroker().getDtxManager().setTimeout(convert(xid), timeout); -} - - -Queue::shared_ptr SessionAdapter::HandlerHelper::getQueue(const string& name) const { - Queue::shared_ptr queue; - if (name.empty()) { - throw framing::IllegalArgumentException(QPID_MSG("No queue name specified.")); - } else { - queue = session.getBroker().getQueues().find(name); - if (!queue) - throw framing::NotFoundException(QPID_MSG("Queue not found: "<<name)); - } - return queue; -} - -}} // namespace qpid::broker - - diff --git a/cpp/src/qpid/broker/SessionAdapter.h b/cpp/src/qpid/broker/SessionAdapter.h deleted file mode 100644 index 8987c4812f..0000000000 --- a/cpp/src/qpid/broker/SessionAdapter.h +++ /dev/null @@ -1,273 +0,0 @@ -#ifndef _broker_SessionAdapter_h -#define _broker_SessionAdapter_h - -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "qpid/broker/HandlerImpl.h" - -#include "qpid/broker/ConnectionToken.h" -#include "qpid/broker/OwnershipToken.h" -#include "qpid/Exception.h" -#include "qpid/framing/AMQP_ServerOperations.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/StructHelper.h" - -#include <algorithm> -#include <vector> -#include <boost/function.hpp> -#include <boost/shared_ptr.hpp> - -namespace qpid { -namespace broker { - -class Channel; -class Connection; -class Broker; -class Queue; - -/** - * SessionAdapter translates protocol-specific AMQP commands for one - * specific version of AMQP into calls on the core broker objects. It - * is a container for a collection of adapters. - * - * Each adapter class provides a client proxy to send methods to the - * peer broker or client. - * - */ - - class SessionAdapter : public HandlerImpl, public framing::AMQP_ServerOperations -{ - public: - SessionAdapter(SemanticState& session); - - framing::ProtocolVersion getVersion() const { return session.getConnection().getVersion();} - - MessageHandler* getMessageHandler(){ return &messageImpl; } - ExchangeHandler* getExchangeHandler(){ return &exchangeImpl; } - QueueHandler* getQueueHandler(){ return &queueImpl; } - ExecutionHandler* getExecutionHandler(){ return &executionImpl; } - TxHandler* getTxHandler(){ return &txImpl; } - DtxHandler* getDtxHandler(){ return &dtxImpl; } - - ConnectionHandler* getConnectionHandler() { throw framing::NotImplementedException("Class not implemented"); } - SessionHandler* getSessionHandler() { throw framing::NotImplementedException("Class not implemented"); } - FileHandler* getFileHandler() { throw framing::NotImplementedException("Class not implemented"); } - StreamHandler* getStreamHandler() { throw framing::NotImplementedException("Class not implemented"); } - - template <class F> void eachExclusiveQueue(F f) - { - queueImpl.eachExclusiveQueue(f); - } - - - private: - //common base for utility methods etc that are specific to this adapter - struct HandlerHelper : public HandlerImpl - { - HandlerHelper(SemanticState& s) : HandlerImpl(s) {} - - boost::shared_ptr<Queue> getQueue(const std::string& name) const; - }; - - - class ExchangeHandlerImpl : - public ExchangeHandler, - public HandlerHelper - { - public: - ExchangeHandlerImpl(SemanticState& session) : HandlerHelper(session) {} - - void declare(const std::string& exchange, const std::string& type, - const std::string& alternateExchange, - bool passive, bool durable, bool autoDelete, - const qpid::framing::FieldTable& arguments); - void delete_(const std::string& exchange, bool ifUnused); - framing::ExchangeQueryResult query(const std::string& name); - void bind(const std::string& queue, - const std::string& exchange, const std::string& routingKey, - const qpid::framing::FieldTable& arguments); - void unbind(const std::string& queue, - const std::string& exchange, - const std::string& routingKey); - framing::ExchangeBoundResult bound(const std::string& exchange, - const std::string& queue, - const std::string& routingKey, - const framing::FieldTable& arguments); - private: - void checkType(boost::shared_ptr<Exchange> exchange, const std::string& type); - - void checkAlternate(boost::shared_ptr<Exchange> exchange, - boost::shared_ptr<Exchange> alternate); - }; - - class QueueHandlerImpl : public QueueHandler, - public HandlerHelper - { - Broker& broker; - std::vector< boost::shared_ptr<Queue> > exclusiveQueues; - - public: - QueueHandlerImpl(SemanticState& session); - ~QueueHandlerImpl(); - - void declare(const std::string& queue, - const std::string& alternateExchange, - bool passive, bool durable, bool exclusive, - bool autoDelete, - const qpid::framing::FieldTable& arguments); - void delete_(const std::string& queue, - bool ifUnused, bool ifEmpty); - void purge(const std::string& queue); - framing::QueueQueryResult query(const std::string& queue); - bool isLocal(const ConnectionToken* t) const; - - void destroyExclusiveQueues(); - void checkDelete(boost::shared_ptr<Queue> queue, bool ifUnused, bool ifEmpty); - template <class F> void eachExclusiveQueue(F f) - { - std::for_each(exclusiveQueues.begin(), exclusiveQueues.end(), f); - } - }; - - class MessageHandlerImpl : - public MessageHandler, - public HandlerHelper - { - typedef boost::function<void(DeliveryId, DeliveryId)> RangedOperation; - RangedOperation releaseRedeliveredOp; - RangedOperation releaseOp; - RangedOperation rejectOp; - RangedOperation acceptOp; - - public: - MessageHandlerImpl(SemanticState& session); - void transfer(const std::string& destination, - uint8_t acceptMode, - uint8_t acquireMode); - - void accept(const framing::SequenceSet& commands); - - void reject(const framing::SequenceSet& commands, - uint16_t code, - const std::string& text); - - void release(const framing::SequenceSet& commands, - bool setRedelivered); - - framing::MessageAcquireResult acquire(const framing::SequenceSet&); - - void subscribe(const std::string& queue, - const std::string& destination, - uint8_t acceptMode, - uint8_t acquireMode, - bool exclusive, - const std::string& resumeId, - uint64_t resumeTtl, - const framing::FieldTable& arguments); - - void cancel(const std::string& destination); - - void setFlowMode(const std::string& destination, - uint8_t flowMode); - - void flow(const std::string& destination, - uint8_t unit, - uint32_t value); - - void flush(const std::string& destination); - - void stop(const std::string& destination); - - framing::MessageResumeResult resume(const std::string& destination, - const std::string& resumeId); - - }; - - class ExecutionHandlerImpl : public ExecutionHandler, public HandlerHelper - { - public: - ExecutionHandlerImpl(SemanticState& session) : HandlerHelper(session) {} - - void sync(); - void result(const framing::SequenceNumber& commandId, const std::string& value); - void exception(uint16_t errorCode, - const framing::SequenceNumber& commandId, - uint8_t classCode, - uint8_t commandCode, - uint8_t fieldIndex, - const std::string& description, - const framing::FieldTable& errorInfo); - - }; - - class TxHandlerImpl : public TxHandler, public HandlerHelper - { - public: - TxHandlerImpl(SemanticState& session) : HandlerHelper(session) {} - - void select(); - void commit(); - void rollback(); - }; - - class DtxHandlerImpl : public DtxHandler, public HandlerHelper, private framing::StructHelper - { - std::string convert(const framing::Xid& xid); - - public: - DtxHandlerImpl(SemanticState& session) : HandlerHelper(session) {} - - void select(); - - framing::XaResult start(const framing::Xid& xid, - bool join, - bool resume); - - framing::XaResult end(const framing::Xid& xid, - bool fail, - bool suspend); - - framing::XaResult commit(const framing::Xid& xid, - bool onePhase); - - void forget(const framing::Xid& xid); - - framing::DtxGetTimeoutResult getTimeout(const framing::Xid& xid); - - framing::XaResult prepare(const framing::Xid& xid); - - framing::DtxRecoverResult recover(); - - framing::XaResult rollback(const framing::Xid& xid); - - void setTimeout(const framing::Xid& xid, uint32_t timeout); - }; - - ExchangeHandlerImpl exchangeImpl; - QueueHandlerImpl queueImpl; - MessageHandlerImpl messageImpl; - ExecutionHandlerImpl executionImpl; - TxHandlerImpl txImpl; - DtxHandlerImpl dtxImpl; -}; -}} // namespace qpid::broker - - - -#endif /*!_broker_SessionAdapter_h*/ diff --git a/cpp/src/qpid/broker/SessionContext.h b/cpp/src/qpid/broker/SessionContext.h deleted file mode 100644 index 253ce8dcf2..0000000000 --- a/cpp/src/qpid/broker/SessionContext.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef QPID_BROKER_SESSIONCONTEXT_H -#define QPID_BROKER_SESSIONCONTEXT_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/AMQP_ClientProxy.h" -#include "qpid/framing/amqp_types.h" -#include "qpid/sys/OutputControl.h" -#include "qpid/broker/ConnectionState.h" -#include "qpid/broker/OwnershipToken.h" -#include "qpid/SessionId.h" - -#include <boost/noncopyable.hpp> - -namespace qpid { -namespace broker { - -class SessionContext : public OwnershipToken, public sys::OutputControl -{ - public: - virtual ~SessionContext(){} - virtual bool isLocal(const ConnectionToken* t) const = 0; - virtual bool isAttached() const = 0; - virtual ConnectionState& getConnection() = 0; - virtual framing::AMQP_ClientProxy& getProxy() = 0; - virtual Broker& getBroker() = 0; - virtual uint16_t getChannel() const = 0; - virtual const SessionId& getSessionId() const = 0; - virtual void addPendingExecutionSync() = 0; -}; - -}} // namespace qpid::broker - - - -#endif /*!QPID_BROKER_SESSIONCONTEXT_H*/ diff --git a/cpp/src/qpid/broker/SessionHandler.cpp b/cpp/src/qpid/broker/SessionHandler.cpp deleted file mode 100644 index 752fa55535..0000000000 --- a/cpp/src/qpid/broker/SessionHandler.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/SessionHandler.h" -#include "qpid/broker/SessionState.h" -#include "qpid/broker/Connection.h" -#include "qpid/log/Statement.h" - -#include <boost/bind.hpp> - -namespace qpid { -namespace broker { -using namespace framing; -using namespace std; -using namespace qpid::sys; - -SessionHandler::SessionHandler(Connection& c, ChannelId ch) - : amqp_0_10::SessionHandler(&c.getOutput(), ch), - connection(c), - proxy(out), - clusterOrderProxy(c.getClusterOrderOutput() ? new SetChannelProxy(ch, c.getClusterOrderOutput()) : 0) -{} - -SessionHandler::~SessionHandler() {} - -void SessionHandler::connectionException(framing::connection::CloseCode code, const std::string& msg) { - // NOTE: must tell the error listener _before_ calling connection.close() - if (connection.getErrorListener()) connection.getErrorListener()->connectionError(msg); - connection.close(code, msg); -} - -void SessionHandler::channelException(framing::session::DetachCode, const std::string& msg) { - if (connection.getErrorListener()) connection.getErrorListener()->sessionError(getChannel(), msg); -} - -void SessionHandler::executionException(framing::execution::ErrorCode, const std::string& msg) { - if (connection.getErrorListener()) connection.getErrorListener()->sessionError(getChannel(), msg); -} - -ConnectionState& SessionHandler::getConnection() { return connection; } - -const ConnectionState& SessionHandler::getConnection() const { return connection; } - -void SessionHandler::handleDetach() { - amqp_0_10::SessionHandler::handleDetach(); - assert(&connection.getChannel(channel.get()) == this); - if (session.get()) - connection.getBroker().getSessionManager().detach(session); - assert(!session.get()); - connection.closeChannel(channel.get()); -} - -void SessionHandler::setState(const std::string& name, bool force) { - assert(!session.get()); - SessionId id(connection.getUserId(), name); - session = connection.broker.getSessionManager().attach(*this, id, force); -} - -void SessionHandler::detaching() -{ - assert(session.get()); - session->disableOutput(); -} - -FrameHandler* SessionHandler::getInHandler() { return session.get() ? &session->in : 0; } -qpid::SessionState* SessionHandler::getState() { return session.get(); } - -void SessionHandler::readyToSend() { - if (session.get()) session->readyToSend(); -} - -/** - * Used by inter-broker bridges to set up session id and attach - */ -void SessionHandler::attachAs(const std::string& name) -{ - SessionId id(connection.getUserId(), name); - SessionState::Configuration config = connection.broker.getSessionManager().getSessionConfig(); - // Delay creating management object till attached(). In a cluster, - // only the active link broker calls attachAs but all brokers - // receive the subsequent attached() call. - session.reset(new SessionState(connection.getBroker(), *this, id, config, true)); - sendAttach(false); -} - -/** - * TODO: this is a little ugly, fix it; its currently still relied on - * for 'push' bridges - */ -void SessionHandler::attached(const std::string& name) -{ - if (session.get()) { - session->addManagementObject(); // Delayed from attachAs() - amqp_0_10::SessionHandler::attached(name); - } else { - SessionId id(connection.getUserId(), name); - SessionState::Configuration config = connection.broker.getSessionManager().getSessionConfig(); - session.reset(new SessionState(connection.getBroker(), *this, id, config)); - markReadyToSend(); - } -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/SessionHandler.h b/cpp/src/qpid/broker/SessionHandler.h deleted file mode 100644 index ca6d6bb193..0000000000 --- a/cpp/src/qpid/broker/SessionHandler.h +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef QPID_BROKER_SESSIONHANDLER_H -#define QPID_BROKER_SESSIONHANDLER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/amqp_0_10/SessionHandler.h" -#include "qpid/framing/AMQP_ClientProxy.h" - -namespace qpid { -class SessionState; - -namespace broker { - -class Connection; -class ConnectionState; -class SessionState; - -/** - * A SessionHandler is associated with each active channel. It - * receives incoming frames, handles session controls and manages the - * association between the channel and a session. - */ -class SessionHandler : public amqp_0_10::SessionHandler { - public: - SessionHandler(Connection&, framing::ChannelId); - ~SessionHandler(); - - /** Get broker::SessionState */ - SessionState* getSession() { return session.get(); } - const SessionState* getSession() const { return session.get(); } - - ConnectionState& getConnection(); - const ConnectionState& getConnection() const; - - framing::AMQP_ClientProxy& getProxy() { return proxy; } - const framing::AMQP_ClientProxy& getProxy() const { return proxy; } - - /** - * If commands are sent based on the local time (e.g. in timers), they don't have - * a well-defined ordering across cluster nodes. - * This proxy is for sending such commands. In a clustered broker it will take steps - * to synchronize command order across the cluster. In a stand-alone broker - * it is just a synonym for getProxy() - */ - framing::AMQP_ClientProxy& getClusterOrderProxy() { - return clusterOrderProxy.get() ? *clusterOrderProxy : proxy; - } - - virtual void handleDetach(); - void attached(const std::string& name);//used by 'pushing' inter-broker bridges - void attachAs(const std::string& name);//used by 'pulling' inter-broker bridges - - protected: - virtual void setState(const std::string& sessionName, bool force); - virtual qpid::SessionState* getState(); - virtual framing::FrameHandler* getInHandler(); - virtual void connectionException(framing::connection::CloseCode code, const std::string& msg); - virtual void channelException(framing::session::DetachCode, const std::string& msg); - virtual void executionException(framing::execution::ErrorCode, const std::string& msg); - virtual void detaching(); - virtual void readyToSend(); - - private: - struct SetChannelProxy : public framing::AMQP_ClientProxy { // Proxy that sets the channel. - framing::ChannelHandler setChannel; - SetChannelProxy(uint16_t ch, framing::FrameHandler* out) - : framing::AMQP_ClientProxy(setChannel), setChannel(ch, out) {} - }; - - Connection& connection; - framing::AMQP_ClientProxy proxy; - std::auto_ptr<SessionState> session; - std::auto_ptr<SetChannelProxy> clusterOrderProxy; -}; - -}} // namespace qpid::broker - - - -#endif /*!QPID_BROKER_SESSIONHANDLER_H*/ diff --git a/cpp/src/qpid/broker/SessionManager.cpp b/cpp/src/qpid/broker/SessionManager.cpp deleted file mode 100644 index 8cc58571af..0000000000 --- a/cpp/src/qpid/broker/SessionManager.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/SessionManager.h" -#include "qpid/broker/SessionState.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/log/Statement.h" -#include "qpid/log/Helpers.h" -#include "qpid/memory.h" - -#include <boost/bind.hpp> -#include <boost/range.hpp> - -#include <algorithm> -#include <functional> -#include <ostream> - -namespace qpid { -namespace broker { - -using boost::intrusive_ptr; -using namespace sys; -using namespace framing; - -SessionManager::SessionManager(const SessionState::Configuration& c, Broker& b) - : config(c), broker(b) {} - -SessionManager::~SessionManager() { - detached.clear(); // Must clear before destructor as session dtor will call forget() -} - -std::auto_ptr<SessionState> SessionManager::attach(SessionHandler& h, const SessionId& id, bool/*force*/) { - Mutex::ScopedLock l(lock); - eraseExpired(); // Clean up expired table - std::pair<Attached::iterator, bool> insert = attached.insert(id); - if (!insert.second) - throw SessionBusyException(QPID_MSG("Session already attached: " << id)); - Detached::iterator i = std::find(detached.begin(), detached.end(), id); - std::auto_ptr<SessionState> state; - if (i == detached.end()) - state.reset(new SessionState(broker, h, id, config)); - else { - state.reset(detached.release(i).release()); - state->attach(h); - } - return state; - // FIXME aconway 2008-04-29: implement force -} - -void SessionManager::detach(std::auto_ptr<SessionState> session) { - Mutex::ScopedLock l(lock); - attached.erase(session->getId()); - session->detach(); - if (session->getTimeout() > 0) { - session->expiry = AbsTime(now(),session->getTimeout()*TIME_SEC); - if (session->mgmtObject != 0) - session->mgmtObject->set_expireTime ((uint64_t) Duration (EPOCH, session->expiry)); - detached.push_back(session.release()); // In expiry order - eraseExpired(); -} -} - -void SessionManager::forget(const SessionId& id) { - Mutex::ScopedLock l(lock); - attached.erase(id); -} - -void SessionManager::eraseExpired() { - // Called with lock held. - if (!detached.empty()) { - // This used to use a more elegant invocation of std::lower_bound - // but violated the strict weak ordering rule which Visual Studio - // enforced. See QPID-1424 for more info should you be tempted to - // replace the loop with something more elegant. - AbsTime now = AbsTime::now(); - Detached::iterator keep = detached.begin(); - while ((keep != detached.end()) && ((*keep).expiry < now)) - keep++; - if (detached.begin() != keep) { - QPID_LOG(debug, "Expiring sessions: " << log::formatList(detached.begin(), keep)); - detached.erase(detached.begin(), keep); - } - } -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/SessionManager.h b/cpp/src/qpid/broker/SessionManager.h deleted file mode 100644 index db88e7ec10..0000000000 --- a/cpp/src/qpid/broker/SessionManager.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef QPID_BROKER_SESSIONMANAGER_H -#define QPID_BROKER_SESSIONMANAGER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include <qpid/SessionState.h> -#include <qpid/sys/Time.h> -#include <qpid/sys/Mutex.h> -#include <qpid/RefCounted.h> - -#include <set> -#include <vector> -#include <memory> - -#include <boost/noncopyable.hpp> -#include <boost/ptr_container/ptr_vector.hpp> -#include <boost/intrusive_ptr.hpp> - -namespace qpid { -namespace broker { -class Broker; -class SessionState; -class SessionHandler; - -/** - * Create and manage SessionState objects. - */ -class SessionManager : private boost::noncopyable { - public: - SessionManager(const qpid::SessionState::Configuration&, Broker&); - - ~SessionManager(); - - /** Open a new active session, caller takes ownership */ - std::auto_ptr<SessionState> attach(SessionHandler& h, const SessionId& id, bool/*force*/); - - /** Return a detached session to the manager, start the timeout counter. */ - void detach(std::auto_ptr<SessionState>); - - /** Forget about an attached session. Called by SessionState destructor. */ - void forget(const SessionId&); - - Broker& getBroker() const { return broker; } - - const qpid::SessionState::Configuration& getSessionConfig() const { return config; } - - private: - typedef boost::ptr_vector<SessionState> Detached; // Sorted in expiry order. - typedef std::set<SessionId> Attached; - - void eraseExpired(); - - sys::Mutex lock; - Detached detached; - Attached attached; - qpid::SessionState::Configuration config; - Broker& broker; -}; - - - -}} // namespace qpid::broker - - - - - -#endif /*!QPID_BROKER_SESSIONMANAGER_H*/ diff --git a/cpp/src/qpid/broker/SessionOutputException.h b/cpp/src/qpid/broker/SessionOutputException.h deleted file mode 100644 index 7c1c5de926..0000000000 --- a/cpp/src/qpid/broker/SessionOutputException.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef QPID_BROKER_SESSIONOUTPUTEXCEPTION_H -#define QPID_BROKER_SESSIONOUTPUTEXCEPTION_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/Exception.h" - -namespace qpid { -namespace broker { - -/** - * This exception is used to signal 'session' exceptions (aka - * execution exceptions in AMQP 0-10 terms) that occur during output - * processing. It simply allows the channel of the session to be - * specified in addition to the other details. Special treatment is - * required at present because the output processing chain is - * different from that which handles incoming commands (specifically - * AggregateOutput cannot reasonably handle exceptions as it has no - * context). - */ -struct SessionOutputException : qpid::SessionException -{ - const uint16_t channel; - SessionOutputException(const qpid::SessionException& e, uint16_t c) : qpid::SessionException(e.code, e.getMessage()), channel(c) {} -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_SESSIONOUTPUTEXCEPTION_H*/ diff --git a/cpp/src/qpid/broker/SessionState.cpp b/cpp/src/qpid/broker/SessionState.cpp deleted file mode 100644 index 957d5bd4d2..0000000000 --- a/cpp/src/qpid/broker/SessionState.cpp +++ /dev/null @@ -1,591 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/SessionState.h" -#include "qpid/broker/Broker.h" -#include "qpid/broker/ConnectionState.h" -#include "qpid/broker/DeliveryRecord.h" -#include "qpid/broker/SessionManager.h" -#include "qpid/broker/SessionHandler.h" -#include "qpid/broker/RateFlowcontrol.h" -#include "qpid/sys/Timer.h" -#include "qpid/framing/AMQContentBody.h" -#include "qpid/framing/AMQHeaderBody.h" -#include "qpid/framing/AMQMethodBody.h" -#include "qpid/framing/reply_exceptions.h" -#include "qpid/framing/ServerInvoker.h" -#include "qpid/log/Statement.h" -#include "qpid/management/ManagementAgent.h" -#include "qpid/framing/AMQP_ClientProxy.h" - -#include <boost/bind.hpp> -#include <boost/lexical_cast.hpp> - -namespace qpid { -namespace broker { - -using namespace framing; -using sys::Mutex; -using boost::intrusive_ptr; -using qpid::management::ManagementAgent; -using qpid::management::ManagementObject; -using qpid::management::Manageable; -using qpid::management::Args; -using qpid::sys::AbsTime; -//using qpid::sys::Timer; -namespace _qmf = qmf::org::apache::qpid::broker; - -SessionState::SessionState( - Broker& b, SessionHandler& h, const SessionId& id, - const SessionState::Configuration& config, bool delayManagement) - : qpid::SessionState(id, config), - broker(b), handler(&h), - semanticState(*this, *this), - adapter(semanticState), - msgBuilder(&broker.getStore()), - mgmtObject(0), - rateFlowcontrol(0), - asyncCommandCompleter(new AsyncCommandCompleter(this)) -{ - uint32_t maxRate = broker.getOptions().maxSessionRate; - if (maxRate) { - if (handler->getConnection().getClientThrottling()) { - rateFlowcontrol.reset(new RateFlowcontrol(maxRate)); - } else { - QPID_LOG(warning, getId() << ": Unable to flow control client - client doesn't support"); - } - } - if (!delayManagement) addManagementObject(); - attach(h); -} - -void SessionState::addManagementObject() { - if (GetManagementObject()) return; // Already added. - Manageable* parent = broker.GetVhostObject (); - if (parent != 0) { - ManagementAgent* agent = getBroker().getManagementAgent(); - if (agent != 0) { - mgmtObject = new _qmf::Session - (agent, this, parent, getId().getName()); - mgmtObject->set_attached (0); - mgmtObject->set_detachedLifespan (0); - mgmtObject->clr_expireTime(); - if (rateFlowcontrol) - mgmtObject->set_maxClientRate(rateFlowcontrol->getRate()); - agent->addObject(mgmtObject); - } - } -} - -SessionState::~SessionState() { - asyncCommandCompleter->cancel(); - semanticState.closed(); - if (mgmtObject != 0) - mgmtObject->resourceDestroy (); - - if (flowControlTimer) - flowControlTimer->cancel(); -} - -AMQP_ClientProxy& SessionState::getProxy() { - assert(isAttached()); - return handler->getProxy(); -} - -uint16_t SessionState::getChannel() const { - assert(isAttached()); - return handler->getChannel(); -} - -ConnectionState& SessionState::getConnection() { - assert(isAttached()); - return handler->getConnection(); -} - -bool SessionState::isLocal(const ConnectionToken* t) const -{ - return isAttached() && &(handler->getConnection()) == t; -} - -void SessionState::detach() { - QPID_LOG(debug, getId() << ": detached on broker."); - asyncCommandCompleter->detached(); - disableOutput(); - handler = 0; - if (mgmtObject != 0) - mgmtObject->set_attached (0); -} - -void SessionState::disableOutput() -{ - semanticState.detached(); //prevents further activateOutput calls until reattached -} - -void SessionState::attach(SessionHandler& h) { - QPID_LOG(debug, getId() << ": attached on broker."); - handler = &h; - if (mgmtObject != 0) - { - mgmtObject->set_attached (1); - mgmtObject->set_connectionRef (h.getConnection().GetManagementObject()->getObjectId()); - mgmtObject->set_channelId (h.getChannel()); - } - asyncCommandCompleter->attached(); -} - -void SessionState::abort() { - if (isAttached()) - getConnection().outputTasks.abort(); -} - -void SessionState::activateOutput() { - if (isAttached()) - getConnection().outputTasks.activateOutput(); -} - -void SessionState::giveReadCredit(int32_t credit) { - if (isAttached()) - getConnection().outputTasks.giveReadCredit(credit); -} - -ManagementObject* SessionState::GetManagementObject (void) const -{ - return (ManagementObject*) mgmtObject; -} - -Manageable::status_t SessionState::ManagementMethod (uint32_t methodId, - Args& /*args*/, - string& /*text*/) -{ - Manageable::status_t status = Manageable::STATUS_UNKNOWN_METHOD; - - switch (methodId) - { - case _qmf::Session::METHOD_DETACH : - if (handler != 0) { - handler->sendDetach(); - } - status = Manageable::STATUS_OK; - break; - - case _qmf::Session::METHOD_CLOSE : - /* - if (handler != 0) - { - handler->getConnection().closeChannel(handler->getChannel()); - } - status = Manageable::STATUS_OK; - break; - */ - - case _qmf::Session::METHOD_SOLICITACK : - case _qmf::Session::METHOD_RESETLIFESPAN : - status = Manageable::STATUS_NOT_IMPLEMENTED; - break; - } - - return status; -} - -void SessionState::handleCommand(framing::AMQMethodBody* method, const SequenceNumber& id) { - currentCommandComplete = true; // assumed, can be overridden by invoker method (this sucks). - Invoker::Result invocation = invoke(adapter, *method); - if (currentCommandComplete) receiverCompleted(id); - - if (!invocation.wasHandled()) { - throw NotImplementedException(QPID_MSG("Not implemented: " << *method)); - } else if (invocation.hasResult()) { - getProxy().getExecution().result(id, invocation.getResult()); - } - - if (method->isSync() && currentCommandComplete) { - sendAcceptAndCompletion(); - } -} - -struct ScheduledCreditTask : public sys::TimerTask { - sys::Timer& timer; - SessionState& sessionState; - ScheduledCreditTask(const qpid::sys::Duration& d, sys::Timer& t, - SessionState& s) : - TimerTask(d,"ScheduledCredit"), - timer(t), - sessionState(s) - {} - - void fire() { - // This is the best we can currently do to avoid a destruction/fire race - sessionState.getConnection().requestIOProcessing(boost::bind(&ScheduledCreditTask::sendCredit, this)); - } - - void sendCredit() { - if ( !sessionState.processSendCredit(0) ) { - QPID_LOG(warning, sessionState.getId() << ": Reschedule sending credit"); - setupNextFire(); - timer.add(this); - } - } -}; - -void SessionState::handleContent(AMQFrame& frame, const SequenceNumber& id) -{ - if (frame.getBof() && frame.getBos()) //start of frameset - msgBuilder.start(id); - intrusive_ptr<Message> msg(msgBuilder.getMessage()); - msgBuilder.handle(frame); - if (frame.getEof() && frame.getEos()) {//end of frameset - if (frame.getBof()) { - //i.e this is a just a command frame, add a dummy header - AMQFrame header((AMQHeaderBody())); - header.setBof(false); - header.setEof(false); - msg->getFrames().append(header); - } - msg->setPublisher(&getConnection()); - msg->getIngressCompletion().begin(); - semanticState.handle(msg); - msgBuilder.end(); - IncompleteIngressMsgXfer xfer(this, msg); - msg->getIngressCompletion().end(xfer); // allows msg to complete xfer - } - - // Handle producer session flow control - if (rateFlowcontrol && frame.getBof() && frame.getBos()) { - if ( !processSendCredit(1) ) { - QPID_LOG(debug, getId() << ": Schedule sending credit"); - sys::Timer& timer = getBroker().getTimer(); - // Use heuristic for scheduled credit of time for 50 messages, but not longer than 500ms - sys::Duration d = std::min(sys::TIME_SEC * 50 / rateFlowcontrol->getRate(), 500 * sys::TIME_MSEC); - flowControlTimer = new ScheduledCreditTask(d, timer, *this); - timer.add(flowControlTimer); - } - } -} - -bool SessionState::processSendCredit(uint32_t msgs) -{ - qpid::sys::ScopedLock<Mutex> l(rateLock); - // Check for violating flow control - if ( msgs > 0 && rateFlowcontrol->flowStopped() ) { - QPID_LOG(warning, getId() << ": producer throttling violation"); - // TODO: Probably do message.stop("") first time then disconnect - // See comment on getClusterOrderProxy() in .h file - getClusterOrderProxy().getMessage().stop(""); - return true; - } - AbsTime now = AbsTime::now(); - uint32_t sendCredit = rateFlowcontrol->receivedMessage(now, msgs); - if (mgmtObject) mgmtObject->dec_clientCredit(msgs); - if ( sendCredit>0 ) { - QPID_LOG(debug, getId() << ": send producer credit " << sendCredit); - getClusterOrderProxy().getMessage().flow("", 0, sendCredit); - rateFlowcontrol->sentCredit(now, sendCredit); - if (mgmtObject) mgmtObject->inc_clientCredit(sendCredit); - return true; - } else { - return !rateFlowcontrol->flowStopped() ; - } -} - -void SessionState::sendAcceptAndCompletion() -{ - if (!accepted.empty()) { - getProxy().getMessage().accept(accepted); - accepted.clear(); - } - sendCompletion(); -} - -/** Invoked when the given inbound message is finished being processed - * by all interested parties (eg. it is done being enqueued to all queues, - * its credit has been accounted for, etc). At this point, msg is considered - * by this receiver as 'completed' (as defined by AMQP 0_10) - */ -void SessionState::completeRcvMsg(SequenceNumber id, - bool requiresAccept, - bool requiresSync) -{ - bool callSendCompletion = false; - receiverCompleted(id); - if (requiresAccept) - // will cause msg's seq to appear in the next message.accept we send. - accepted.add(id); - - // Are there any outstanding Execution.Sync commands pending the - // completion of this msg? If so, complete them. - while (!pendingExecutionSyncs.empty() && - receiverGetIncomplete().front() >= pendingExecutionSyncs.front()) { - const SequenceNumber id = pendingExecutionSyncs.front(); - pendingExecutionSyncs.pop(); - QPID_LOG(debug, getId() << ": delayed execution.sync " << id << " is completed."); - receiverCompleted(id); - callSendCompletion = true; // likely peer is pending for this completion. - } - - // if the sender has requested immediate notification of the completion... - if (requiresSync) { - sendAcceptAndCompletion(); - } else if (callSendCompletion) { - sendCompletion(); - } -} - -void SessionState::handleIn(AMQFrame& frame) { - SequenceNumber commandId = receiverGetCurrent(); - //TODO: make command handling more uniform, regardless of whether - //commands carry content. - AMQMethodBody* m = frame.getMethod(); - if (m == 0 || m->isContentBearing()) { - handleContent(frame, commandId); - } else if (frame.getBof() && frame.getEof()) { - handleCommand(frame.getMethod(), commandId); - } else { - throw InternalErrorException("Cannot handle multi-frame command segments yet"); - } -} - -void SessionState::handleOut(AMQFrame& frame) { - assert(handler); - handler->out(frame); -} - -void SessionState::deliver(DeliveryRecord& msg, bool sync) -{ - uint32_t maxFrameSize = getConnection().getFrameMax(); - assert(senderGetCommandPoint().offset == 0); - SequenceNumber commandId = senderGetCommandPoint().command; - msg.deliver(getProxy().getHandler(), commandId, maxFrameSize); - assert(senderGetCommandPoint() == SessionPoint(commandId+1, 0)); // Delivery has moved sendPoint. - if (sync) { - AMQP_ClientProxy::Execution& p(getProxy().getExecution()); - Proxy::ScopedSync s(p); - p.sync(); - } -} - -void SessionState::sendCompletion() { - handler->sendCompletion(); -} - -void SessionState::senderCompleted(const SequenceSet& commands) { - qpid::SessionState::senderCompleted(commands); - semanticState.completed(commands); -} - -void SessionState::readyToSend() { - QPID_LOG(debug, getId() << ": ready to send, activating output."); - assert(handler); - semanticState.attached(); - if (rateFlowcontrol) { - qpid::sys::ScopedLock<Mutex> l(rateLock); - // Issue initial credit - use a heuristic here issue min of 300 messages or 1 secs worth - uint32_t credit = std::min(rateFlowcontrol->getRate(), 300U); - QPID_LOG(debug, getId() << ": Issuing producer message credit " << credit); - // See comment on getClusterOrderProxy() in .h file - getClusterOrderProxy().getMessage().setFlowMode("", 0); - getClusterOrderProxy().getMessage().flow("", 0, credit); - rateFlowcontrol->sentCredit(AbsTime::now(), credit); - if (mgmtObject) mgmtObject->inc_clientCredit(credit); - } -} - -Broker& SessionState::getBroker() { return broker; } - -// Session resume is not fully implemented so it is useless to set a -// non-0 timeout. Moreover it creates problems in a cluster because -// dead sessions are kept and interfere with failover. -void SessionState::setTimeout(uint32_t) { } - -framing::AMQP_ClientProxy& SessionState::getClusterOrderProxy() { - return handler->getClusterOrderProxy(); -} - - -// Current received command is an execution.sync command. -// Complete this command only when all preceding commands have completed. -// (called via the invoker() in handleCommand() above) -void SessionState::addPendingExecutionSync() -{ - SequenceNumber syncCommandId = receiverGetCurrent(); - if (receiverGetIncomplete().front() < syncCommandId) { - currentCommandComplete = false; - pendingExecutionSyncs.push(syncCommandId); - asyncCommandCompleter->flushPendingMessages(); - QPID_LOG(debug, getId() << ": delaying completion of execution.sync " << syncCommandId); - } -} - - -/** factory for creating a reference-counted IncompleteIngressMsgXfer object - * which will be attached to a message that will be completed asynchronously. - */ -boost::intrusive_ptr<AsyncCompletion::Callback> -SessionState::IncompleteIngressMsgXfer::clone() -{ - boost::intrusive_ptr<SessionState::IncompleteIngressMsgXfer> cb(new SessionState::IncompleteIngressMsgXfer(session, msg)); - - // Optimization: this routine is *only* invoked when the message needs to be asynchronously completed. - // If the client is pending the message.transfer completion, flush now to force immediate write to journal. - if (requiresSync) - msg->flush(); - else { - // otherwise, we need to track this message in order to flush it if an execution.sync arrives - // before it has been completed (see flushPendingMessages()) - pending = true; - completerContext->addPendingMessage(msg); - } - return cb; -} - - -/** Invoked by the asynchronous completer associated with a received - * msg that is pending Completion. May be invoked by the IO thread - * (sync == true), or some external thread (!sync). - */ -void SessionState::IncompleteIngressMsgXfer::completed(bool sync) -{ - if (pending) completerContext->deletePendingMessage(id); - if (!sync) { - /** note well: this path may execute in any thread. It is safe to access - * the scheduledCompleterContext, since *this has a shared pointer to it. - * but not session! - */ - session = 0; - QPID_LOG(debug, ": async completion callback scheduled for msg seq=" << id); - completerContext->scheduleMsgCompletion(id, requiresAccept, requiresSync); - } else { - // this path runs directly from the ac->end() call in handleContent() above, - // so *session is definately valid. - if (session->isAttached()) { - QPID_LOG(debug, ": receive completed for msg seq=" << id); - session->completeRcvMsg(id, requiresAccept, requiresSync); - } - } - completerContext = boost::intrusive_ptr<AsyncCommandCompleter>(); -} - - -/** Scheduled from an asynchronous command's completed callback to run on - * the IO thread. - */ -void SessionState::AsyncCommandCompleter::schedule(boost::intrusive_ptr<AsyncCommandCompleter> ctxt) -{ - ctxt->completeCommands(); -} - - -/** Track an ingress message that is pending completion */ -void SessionState::AsyncCommandCompleter::addPendingMessage(boost::intrusive_ptr<Message> msg) -{ - qpid::sys::ScopedLock<qpid::sys::Mutex> l(completerLock); - std::pair<SequenceNumber, boost::intrusive_ptr<Message> > item(msg->getCommandId(), msg); - bool unique = pendingMsgs.insert(item).second; - assert(unique); -} - - -/** pending message has completed */ -void SessionState::AsyncCommandCompleter::deletePendingMessage(SequenceNumber id) -{ - qpid::sys::ScopedLock<qpid::sys::Mutex> l(completerLock); - pendingMsgs.erase(id); -} - - -/** done when an execution.sync arrives */ -void SessionState::AsyncCommandCompleter::flushPendingMessages() -{ - std::map<SequenceNumber, boost::intrusive_ptr<Message> > copy; - { - qpid::sys::ScopedLock<qpid::sys::Mutex> l(completerLock); - pendingMsgs.swap(copy); // we've only tracked these in case a flush is needed, so nuke 'em now. - } - // drop lock, so it is safe to call "flush()" - for (std::map<SequenceNumber, boost::intrusive_ptr<Message> >::iterator i = copy.begin(); - i != copy.end(); ++i) { - i->second->flush(); - } -} - - -/** mark an ingress Message.Transfer command as completed. - * This method must be thread safe - it may run on any thread. - */ -void SessionState::AsyncCommandCompleter::scheduleMsgCompletion(SequenceNumber cmd, - bool requiresAccept, - bool requiresSync) -{ - qpid::sys::ScopedLock<qpid::sys::Mutex> l(completerLock); - - if (session && isAttached) { - MessageInfo msg(cmd, requiresAccept, requiresSync); - completedMsgs.push_back(msg); - if (completedMsgs.size() == 1) { - session->getConnection().requestIOProcessing(boost::bind(&schedule, - session->asyncCommandCompleter)); - } - } -} - - -/** Cause the session to complete all completed commands. - * Executes on the IO thread. - */ -void SessionState::AsyncCommandCompleter::completeCommands() -{ - qpid::sys::ScopedLock<qpid::sys::Mutex> l(completerLock); - - // when session is destroyed, it clears the session pointer via cancel(). - if (session && session->isAttached()) { - for (std::vector<MessageInfo>::iterator msg = completedMsgs.begin(); - msg != completedMsgs.end(); ++msg) { - session->completeRcvMsg(msg->cmd, msg->requiresAccept, msg->requiresSync); - } - } - completedMsgs.clear(); -} - - -/** cancel any pending calls to scheduleComplete */ -void SessionState::AsyncCommandCompleter::cancel() -{ - qpid::sys::ScopedLock<qpid::sys::Mutex> l(completerLock); - session = 0; -} - - -/** inform the completer that the session has attached, - * allows command completion scheduling from any thread */ -void SessionState::AsyncCommandCompleter::attached() -{ - qpid::sys::ScopedLock<qpid::sys::Mutex> l(completerLock); - isAttached = true; -} - - -/** inform the completer that the session has detached, - * disables command completion scheduling from any thread */ -void SessionState::AsyncCommandCompleter::detached() -{ - qpid::sys::ScopedLock<qpid::sys::Mutex> l(completerLock); - isAttached = false; -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/SessionState.h b/cpp/src/qpid/broker/SessionState.h deleted file mode 100644 index b43df0c0aa..0000000000 --- a/cpp/src/qpid/broker/SessionState.h +++ /dev/null @@ -1,284 +0,0 @@ -#ifndef QPID_BROKER_SESSION_H -#define QPID_BROKER_SESSION_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/SessionState.h" -#include "qpid/framing/FrameHandler.h" -#include "qpid/framing/SequenceSet.h" -#include "qpid/sys/Time.h" -#include "qpid/management/Manageable.h" -#include "qmf/org/apache/qpid/broker/Session.h" -#include "qpid/broker/SessionAdapter.h" -#include "qpid/broker/DeliveryAdapter.h" -#include "qpid/broker/AsyncCompletion.h" -#include "qpid/broker/MessageBuilder.h" -#include "qpid/broker/SessionContext.h" -#include "qpid/broker/SemanticState.h" -#include "qpid/sys/Monitor.h" - -#include <boost/noncopyable.hpp> -#include <boost/scoped_ptr.hpp> -#include <boost/intrusive_ptr.hpp> - -#include <set> -#include <vector> -#include <ostream> - -namespace qpid { - -namespace framing { -class AMQP_ClientProxy; -} - -namespace sys { -class TimerTask; -} - -namespace broker { - -class Broker; -class ConnectionState; -class Message; -class SessionHandler; -class SessionManager; -class RateFlowcontrol; - -/** - * Broker-side session state includes session's handler chains, which - * may themselves have state. - */ -class SessionState : public qpid::SessionState, - public SessionContext, - public DeliveryAdapter, - public management::Manageable, - public framing::FrameHandler::InOutHandler -{ - public: - SessionState(Broker&, SessionHandler&, const SessionId&, - const SessionState::Configuration&, bool delayManagement=false); - ~SessionState(); - bool isAttached() const { return handler; } - - void detach(); - void attach(SessionHandler& handler); - void disableOutput(); - - /** @pre isAttached() */ - framing::AMQP_ClientProxy& getProxy(); - - /** @pre isAttached() */ - uint16_t getChannel() const; - - /** @pre isAttached() */ - ConnectionState& getConnection(); - bool isLocal(const ConnectionToken* t) const; - - Broker& getBroker(); - - void setTimeout(uint32_t seconds); - - /** OutputControl **/ - void abort(); - void activateOutput(); - void giveReadCredit(int32_t); - - void senderCompleted(const framing::SequenceSet& ranges); - - void sendCompletion(); - - //delivery adapter methods: - void deliver(DeliveryRecord&, bool sync); - - // Manageable entry points - management::ManagementObject* GetManagementObject (void) const; - management::Manageable::status_t - ManagementMethod (uint32_t methodId, management::Args& args, std::string&); - - void readyToSend(); - - // Used by cluster to create replica sessions. - SemanticState& getSemanticState() { return semanticState; } - boost::intrusive_ptr<Message> getMessageInProgress() { return msgBuilder.getMessage(); } - SessionAdapter& getSessionAdapter() { return adapter; } - - bool processSendCredit(uint32_t msgs); - - const SessionId& getSessionId() const { return getId(); } - - // Used by ExecutionHandler sync command processing. Notifies - // the SessionState of a received Execution.Sync command. - void addPendingExecutionSync(); - - // Used to delay creation of management object for sessions - // belonging to inter-broker bridges - void addManagementObject(); - - private: - void handleCommand(framing::AMQMethodBody* method, const framing::SequenceNumber& id); - void handleContent(framing::AMQFrame& frame, const framing::SequenceNumber& id); - - // indicate that the given ingress msg has been completely received by the - // broker, and the msg's message.transfer command can be considered completed. - void completeRcvMsg(SequenceNumber id, bool requiresAccept, bool requiresSync); - - void handleIn(framing::AMQFrame& frame); - void handleOut(framing::AMQFrame& frame); - - // End of the input & output chains. - void handleInLast(framing::AMQFrame& frame); - void handleOutLast(framing::AMQFrame& frame); - - void sendAcceptAndCompletion(); - - /** - * If commands are sent based on the local time (e.g. in timers), they don't have - * a well-defined ordering across cluster nodes. - * This proxy is for sending such commands. In a clustered broker it will take steps - * to synchronize command order across the cluster. In a stand-alone broker - * it is just a synonym for getProxy() - */ - framing::AMQP_ClientProxy& getClusterOrderProxy(); - - Broker& broker; - SessionHandler* handler; - sys::AbsTime expiry; // Used by SessionManager. - SemanticState semanticState; - SessionAdapter adapter; - MessageBuilder msgBuilder; - qmf::org::apache::qpid::broker::Session* mgmtObject; - qpid::framing::SequenceSet accepted; - - // State used for producer flow control (rate limited) - qpid::sys::Mutex rateLock; - boost::scoped_ptr<RateFlowcontrol> rateFlowcontrol; - boost::intrusive_ptr<sys::TimerTask> flowControlTimer; - - // sequence numbers for pending received Execution.Sync commands - std::queue<SequenceNumber> pendingExecutionSyncs; - bool currentCommandComplete; - - /** This class provides a context for completing asynchronous commands in a thread - * safe manner. Asynchronous commands save their completion state in this class. - * This class then schedules the completeCommands() method in the IO thread. - * While running in the IO thread, completeCommands() may safely complete all - * saved commands without the risk of colliding with other operations on this - * SessionState. - */ - class AsyncCommandCompleter : public RefCounted { - private: - SessionState *session; - bool isAttached; - qpid::sys::Mutex completerLock; - - // special-case message.transfer commands for optimization - struct MessageInfo { - SequenceNumber cmd; // message.transfer command id - bool requiresAccept; - bool requiresSync; - MessageInfo(SequenceNumber c, bool a, bool s) - : cmd(c), requiresAccept(a), requiresSync(s) {} - }; - std::vector<MessageInfo> completedMsgs; - // If an ingress message does not require a Sync, we need to - // hold a reference to it in case an Execution.Sync command is received and we - // have to manually flush the message. - std::map<SequenceNumber, boost::intrusive_ptr<Message> > pendingMsgs; - - /** complete all pending commands, runs in IO thread */ - void completeCommands(); - - /** for scheduling a run of "completeCommands()" on the IO thread */ - static void schedule(boost::intrusive_ptr<AsyncCommandCompleter>); - - public: - AsyncCommandCompleter(SessionState *s) : session(s), isAttached(s->isAttached()) {}; - ~AsyncCommandCompleter() {}; - - /** track a message pending ingress completion */ - void addPendingMessage(boost::intrusive_ptr<Message> m); - void deletePendingMessage(SequenceNumber id); - void flushPendingMessages(); - /** schedule the processing of a completed ingress message.transfer command */ - void scheduleMsgCompletion(SequenceNumber cmd, - bool requiresAccept, - bool requiresSync); - void cancel(); // called by SessionState destructor. - void attached(); // called by SessionState on attach() - void detached(); // called by SessionState on detach() - }; - boost::intrusive_ptr<AsyncCommandCompleter> asyncCommandCompleter; - - /** Abstract class that represents a single asynchronous command that is - * pending completion. - */ - class AsyncCommandContext : public AsyncCompletion::Callback - { - public: - AsyncCommandContext( SessionState *ss, SequenceNumber _id ) - : id(_id), completerContext(ss->asyncCommandCompleter) {} - virtual ~AsyncCommandContext() {} - - protected: - SequenceNumber id; - boost::intrusive_ptr<AsyncCommandCompleter> completerContext; - }; - - /** incomplete Message.transfer commands - inbound to broker from client - */ - class IncompleteIngressMsgXfer : public SessionState::AsyncCommandContext - { - public: - IncompleteIngressMsgXfer( SessionState *ss, - boost::intrusive_ptr<Message> m ) - : AsyncCommandContext(ss, m->getCommandId()), - session(ss), - msg(m), - requiresAccept(m->requiresAccept()), - requiresSync(m->getFrames().getMethod()->isSync()), - pending(false) {} - virtual ~IncompleteIngressMsgXfer() {}; - - virtual void completed(bool); - virtual boost::intrusive_ptr<AsyncCompletion::Callback> clone(); - - private: - SessionState *session; // only valid if sync flag in callback is true - boost::intrusive_ptr<Message> msg; - bool requiresAccept; - bool requiresSync; - bool pending; // true if msg saved on pending list... - }; - - friend class SessionManager; -}; - - -inline std::ostream& operator<<(std::ostream& out, const SessionState& session) { - return out << session.getId(); -} - -}} // namespace qpid::broker - - - -#endif /*!QPID_BROKER_SESSION_H*/ diff --git a/cpp/src/qpid/broker/SignalHandler.cpp b/cpp/src/qpid/broker/SignalHandler.cpp deleted file mode 100644 index 16c141f21c..0000000000 --- a/cpp/src/qpid/broker/SignalHandler.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/SignalHandler.h" -#include "qpid/broker/Broker.h" -#include "qpid/sys/Mutex.h" -#include <signal.h> - -namespace qpid { -namespace broker { - -// Lock is to ensure that broker is not concurrently set to 0 and -// deleted while we are in a call to broker->shutdown() - -sys::Mutex brokerLock; -Broker* SignalHandler::broker; - -void SignalHandler::setBroker(Broker* b) { - sys::Mutex::ScopedLock l(brokerLock); - broker = b; - signal(SIGINT,shutdownHandler); - signal(SIGTERM, shutdownHandler); - signal(SIGHUP,SIG_IGN); - signal(SIGCHLD,SIG_IGN); -} - -void SignalHandler::shutdown() { shutdownHandler(0); } - -void SignalHandler::shutdownHandler(int) { - sys::Mutex::ScopedLock l(brokerLock); - if (broker) { - broker->shutdown(); - broker = 0; - } -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/SignalHandler.h b/cpp/src/qpid/broker/SignalHandler.h deleted file mode 100644 index 7bfa9ea630..0000000000 --- a/cpp/src/qpid/broker/SignalHandler.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef QPID_BROKER_SIGNALHANDLER_H -#define QPID_BROKER_SIGNALHANDLER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -namespace qpid { -namespace broker { - -class Broker; - -/** - * Handle signals e.g. to shut-down a broker. - */ -class SignalHandler -{ - public: - /** Set the broker to be shutdown on signals. - * Must be reset by calling setBroker(0) before the broker is deleted. - */ - static void setBroker(Broker* broker); - - /** Initiate shut-down of broker */ - static void shutdown(); - - private: - static void shutdownHandler(int); - static Broker* broker; -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_SIGNALHANDLER_H*/ diff --git a/cpp/src/qpid/broker/StatefulQueueObserver.h b/cpp/src/qpid/broker/StatefulQueueObserver.h deleted file mode 100644 index c682d460b7..0000000000 --- a/cpp/src/qpid/broker/StatefulQueueObserver.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef QPID_BROKER_STATEFULQUEUEOBSERVER_H -#define QPID_BROKER_STATEFULQUEUEOBSERVER_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/QueueObserver.h" -#include "qpid/framing/FieldTable.h" - -namespace qpid { -namespace broker { - -/** - * Specialized type of QueueObserver that maintains internal state that has to - * be replicated across clustered brokers. - */ -class StatefulQueueObserver : public QueueObserver -{ - public: - StatefulQueueObserver(std::string _id) : id(_id) {} - virtual ~StatefulQueueObserver() {} - - /** This identifier must uniquely identify this particular observer amoung - * all observers on a queue. For cluster replication, this id will be used - * to identify the peer queue observer for synchronization across - * brokers. - */ - const std::string& getId() const { return id; } - - /** This method should return the observer's internal state as an opaque - * map. - */ - virtual void getState(qpid::framing::FieldTable& state ) const = 0; - - /** The input map represents the internal state of the peer observer that - * this observer should synchonize to. - */ - virtual void setState(const qpid::framing::FieldTable&) = 0; - - - private: - std::string id; -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_STATEFULQUEUEOBSERVER_H*/ diff --git a/cpp/src/qpid/broker/System.cpp b/cpp/src/qpid/broker/System.cpp deleted file mode 100644 index 8cd2edda76..0000000000 --- a/cpp/src/qpid/broker/System.cpp +++ /dev/null @@ -1,84 +0,0 @@ -// -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -// - -#include "qpid/broker/System.h" -#include "qpid/broker/Broker.h" -#include "qpid/management/ManagementAgent.h" -#include "qpid/framing/Uuid.h" -#include "qpid/sys/SystemInfo.h" -#include "qpid/types/Uuid.h" -#include <iostream> -#include <fstream> - -using qpid::management::ManagementAgent; -using namespace qpid::broker; -using namespace std; -namespace _qmf = qmf::org::apache::qpid::broker; - -System::System (string _dataDir, Broker* broker) : mgmtObject(0) -{ - ManagementAgent* agent = broker ? broker->getManagementAgent() : 0; - - if (agent != 0) - { - framing::Uuid systemId; - - if (_dataDir.empty ()) - { - systemId.generate (); - } - else - { - string filename (_dataDir + "/systemId"); - ifstream inFile (filename.c_str ()); - - if (inFile.good ()) - { - inFile >> systemId; - inFile.close (); - } - else - { - systemId.generate (); - ofstream outFile (filename.c_str ()); - if (outFile.good ()) - { - outFile << systemId << endl; - outFile.close (); - } - } - } - - mgmtObject = new _qmf::System(agent, this, types::Uuid(systemId.c_array())); - std::string sysname, nodename, release, version, machine; - qpid::sys::SystemInfo::getSystemId (sysname, - nodename, - release, - version, - machine); - mgmtObject->set_osName (sysname); - mgmtObject->set_nodeName (nodename); - mgmtObject->set_release (release); - mgmtObject->set_version (version); - mgmtObject->set_machine (machine); - - agent->addObject(mgmtObject, 0, true); - } -} - diff --git a/cpp/src/qpid/broker/System.h b/cpp/src/qpid/broker/System.h deleted file mode 100644 index 0fc2c2bd88..0000000000 --- a/cpp/src/qpid/broker/System.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef _BrokerSystem_ -#define _BrokerSystem_ - -// -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -// - -#include "qpid/management/Manageable.h" -#include "qmf/org/apache/qpid/broker/System.h" -#include <boost/shared_ptr.hpp> -#include <string> - -namespace qpid { -namespace broker { - -class Broker; - -class System : public management::Manageable -{ - private: - - qmf::org::apache::qpid::broker::System* mgmtObject; - - public: - - typedef boost::shared_ptr<System> shared_ptr; - - System (std::string _dataDir, Broker* broker = 0); - - management::ManagementObject* GetManagementObject (void) const - { return mgmtObject; } -}; - -}} - -#endif /*!_BrokerSystem_*/ diff --git a/cpp/src/qpid/broker/ThresholdAlerts.cpp b/cpp/src/qpid/broker/ThresholdAlerts.cpp deleted file mode 100644 index 3c9e210d4d..0000000000 --- a/cpp/src/qpid/broker/ThresholdAlerts.cpp +++ /dev/null @@ -1,191 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/ThresholdAlerts.h" -#include "qpid/broker/Queue.h" -#include "qpid/broker/QueuedMessage.h" -#include "qpid/amqp_0_10/Codecs.h" -#include "qpid/log/Statement.h" -#include "qpid/management/ManagementAgent.h" -#include "qmf/org/apache/qpid/broker/EventQueueThresholdExceeded.h" - -namespace qpid { -namespace broker { -namespace { -const qmf::org::apache::qpid::broker::EventQueueThresholdExceeded EVENT("dummy", 0, 0); -bool isQMFv2(const boost::intrusive_ptr<Message> message) -{ - const qpid::framing::MessageProperties* props = message->getProperties<qpid::framing::MessageProperties>(); - return props && props->getAppId() == "qmf2"; -} - -bool isThresholdEvent(const boost::intrusive_ptr<Message> message) -{ - if (message->getIsManagementMessage()) { - //is this a qmf event? if so is it a threshold event? - if (isQMFv2(message)) { - const qpid::framing::FieldTable* headers = message->getApplicationHeaders(); - if (headers && headers->getAsString("qmf.content") == "_event") { - //decode as list - std::string content = message->getFrames().getContent(); - qpid::types::Variant::List list; - qpid::amqp_0_10::ListCodec::decode(content, list); - if (list.empty() || list.front().getType() != qpid::types::VAR_MAP) return false; - qpid::types::Variant::Map map = list.front().asMap(); - try { - std::string eventName = map["_schema_id"].asMap()["_class_name"].asString(); - return eventName == EVENT.getEventName(); - } catch (const std::exception& e) { - QPID_LOG(error, "Error checking for recursive threshold alert: " << e.what()); - } - } - } else { - std::string content = message->getFrames().getContent(); - qpid::framing::Buffer buffer(const_cast<char*>(content.data()), content.size()); - if (buffer.getOctet() == 'A' && buffer.getOctet() == 'M' && buffer.getOctet() == '2' && buffer.getOctet() == 'e') { - buffer.getLong();//sequence - std::string packageName; - buffer.getShortString(packageName); - if (packageName != EVENT.getPackageName()) return false; - std::string eventName; - buffer.getShortString(eventName); - return eventName == EVENT.getEventName(); - } - } - } - return false; -} -} - -ThresholdAlerts::ThresholdAlerts(const std::string& n, - qpid::management::ManagementAgent& a, - const uint32_t ct, - const uint64_t st, - const long repeat) - : name(n), agent(a), countThreshold(ct), sizeThreshold(st), - repeatInterval(repeat ? repeat*qpid::sys::TIME_SEC : 0), - count(0), size(0), lastAlert(qpid::sys::EPOCH) {} - -void ThresholdAlerts::enqueued(const QueuedMessage& m) -{ - size += m.payload->contentSize(); - ++count; - if ((countThreshold && count >= countThreshold) || (sizeThreshold && size >= sizeThreshold)) { - if ((repeatInterval == 0 && lastAlert == qpid::sys::EPOCH) - || qpid::sys::Duration(lastAlert, qpid::sys::now()) > repeatInterval) { - //Note: Raising an event may result in messages being - //enqueued on queues; it may even be that this event - //causes a message to be enqueued on the queue we are - //tracking, and so we need to avoid recursing - if (isThresholdEvent(m.payload)) return; - lastAlert = qpid::sys::now(); - agent.raiseEvent(qmf::org::apache::qpid::broker::EventQueueThresholdExceeded(name, count, size)); - QPID_LOG(info, "Threshold event triggered for " << name << ", count=" << count << ", size=" << size); - } - } -} - -void ThresholdAlerts::dequeued(const QueuedMessage& m) -{ - size -= m.payload->contentSize(); - --count; - if ((countThreshold && count < countThreshold) || (sizeThreshold && size < sizeThreshold)) { - lastAlert = qpid::sys::EPOCH; - } -} - - - -void ThresholdAlerts::observe(Queue& queue, qpid::management::ManagementAgent& agent, - const uint64_t countThreshold, - const uint64_t sizeThreshold, - const long repeatInterval) -{ - if (countThreshold || sizeThreshold) { - boost::shared_ptr<QueueObserver> observer( - new ThresholdAlerts(queue.getName(), agent, countThreshold, sizeThreshold, repeatInterval) - ); - queue.addObserver(observer); - } -} - -void ThresholdAlerts::observe(Queue& queue, qpid::management::ManagementAgent& agent, - const qpid::framing::FieldTable& settings, uint16_t limitRatio) - -{ - qpid::types::Variant::Map map; - qpid::amqp_0_10::translate(settings, map); - observe(queue, agent, map, limitRatio); -} - -template <class T> -class Option -{ - public: - Option(const std::string& name, T d) : defaultValue(d) { names.push_back(name); } - void addAlias(const std::string& name) { names.push_back(name); } - T get(const qpid::types::Variant::Map& settings) const - { - T value(defaultValue); - for (std::vector<std::string>::const_iterator i = names.begin(); i != names.end(); ++i) { - if (get(settings, *i, value)) break; - } - return value; - } - private: - std::vector<std::string> names; - T defaultValue; - - bool get(const qpid::types::Variant::Map& settings, const std::string& name, T& value) const - { - qpid::types::Variant::Map::const_iterator i = settings.find(name); - if (i != settings.end()) { - try { - value = (T) i->second; - } catch (const qpid::types::InvalidConversion&) { - QPID_LOG(warning, "Bad value for" << name << ": " << i->second); - } - return true; - } else { - return false; - } - } -}; - -void ThresholdAlerts::observe(Queue& queue, qpid::management::ManagementAgent& agent, - const qpid::types::Variant::Map& settings, uint16_t limitRatio) - -{ - //Note: aliases are keys defined by java broker - Option<int64_t> repeatInterval("qpid.alert_repeat_gap", 60); - repeatInterval.addAlias("x-qpid-minimum-alert-repeat-gap"); - - //If no explicit threshold settings were given use specified - //percentage of any limit from the policy. - const QueuePolicy* policy = queue.getPolicy(); - Option<uint32_t> countThreshold("qpid.alert_count", (uint32_t) (policy && limitRatio ? (policy->getMaxCount()*limitRatio/100) : 0)); - countThreshold.addAlias("x-qpid-maximum-message-count"); - Option<uint64_t> sizeThreshold("qpid.alert_size", (uint64_t) (policy && limitRatio ? (policy->getMaxSize()*limitRatio/100) : 0)); - sizeThreshold.addAlias("x-qpid-maximum-message-size"); - - observe(queue, agent, countThreshold.get(settings), sizeThreshold.get(settings), repeatInterval.get(settings)); -} - -}} diff --git a/cpp/src/qpid/broker/ThresholdAlerts.h b/cpp/src/qpid/broker/ThresholdAlerts.h deleted file mode 100644 index c77722e700..0000000000 --- a/cpp/src/qpid/broker/ThresholdAlerts.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef QPID_BROKER_THRESHOLDALERTS_H -#define QPID_BROKER_THRESHOLDALERTS_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/QueueObserver.h" -#include "qpid/sys/Time.h" -#include "qpid/types/Variant.h" -#include <string> - -namespace qpid { -namespace framing { -class FieldTable; -} -namespace management { -class ManagementAgent; -} -namespace broker { - -class Queue; -/** - * Class to manage generation of QMF alerts when particular thresholds - * are breached on a queue. - */ -class ThresholdAlerts : public QueueObserver -{ - public: - ThresholdAlerts(const std::string& name, - qpid::management::ManagementAgent& agent, - const uint32_t countThreshold, - const uint64_t sizeThreshold, - const long repeatInterval); - void enqueued(const QueuedMessage&); - void dequeued(const QueuedMessage&); - static void observe(Queue& queue, qpid::management::ManagementAgent& agent, - const uint64_t countThreshold, - const uint64_t sizeThreshold, - const long repeatInterval); - static void observe(Queue& queue, qpid::management::ManagementAgent& agent, - const qpid::framing::FieldTable& settings, uint16_t limitRatio); - static void observe(Queue& queue, qpid::management::ManagementAgent& agent, - const qpid::types::Variant::Map& settings, uint16_t limitRatio); - private: - const std::string name; - qpid::management::ManagementAgent& agent; - const uint32_t countThreshold; - const uint64_t sizeThreshold; - const qpid::sys::Duration repeatInterval; - uint64_t count; - uint64_t size; - qpid::sys::AbsTime lastAlert; -}; -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_THRESHOLDALERTS_H*/ diff --git a/cpp/src/qpid/broker/TopicExchange.cpp b/cpp/src/qpid/broker/TopicExchange.cpp deleted file mode 100644 index 644a3d628e..0000000000 --- a/cpp/src/qpid/broker/TopicExchange.cpp +++ /dev/null @@ -1,692 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/TopicExchange.h" -#include "qpid/broker/FedOps.h" -#include "qpid/log/Statement.h" -#include <algorithm> - - -namespace qpid { -namespace broker { - -using namespace qpid::framing; -using namespace qpid::sys; -using namespace std; -namespace _qmf = qmf::org::apache::qpid::broker; - - -// TODO aconway 2006-09-20: More efficient matching algorithm. -// Areas for improvement: -// - excessive string copying: should be 0 copy, match from original buffer. -// - match/lookup: use descision tree or other more efficient structure. - -namespace -{ -const std::string STAR("*"); -const std::string HASH("#"); -} - -// iterator for federation ReOrigin bind operation -class TopicExchange::ReOriginIter : public TopicExchange::BindingNode::TreeIterator { -public: - ReOriginIter() {}; - ~ReOriginIter() {}; - bool visit(BindingNode& node) { - if (node.bindings.fedBinding.hasLocal()) { - keys2prop.push_back(node.routePattern); - } - return true; - } - std::vector<std::string> keys2prop; -}; - - -// match iterator used by route(): builds BindingList of all unique queues -// that match the routing key. -class TopicExchange::BindingsFinderIter : public TopicExchange::BindingNode::TreeIterator { -public: - BindingsFinderIter(BindingList &bl) : b(bl) {}; - ~BindingsFinderIter() {}; - - BindingList& b; - std::set<std::string> qSet; - - bool visit(BindingNode& node) { - - Binding::vector& qv(node.bindings.bindingVector); - for (Binding::vector::iterator j = qv.begin(); j != qv.end(); j++) { - // do not duplicate queues on the binding list - if (qSet.insert(j->get()->queue->getName()).second) { - b->push_back(*j); - } - } - return true; - } -}; - - - -// Iterator to visit all bindings until a given queue is found -class TopicExchange::QueueFinderIter : public TopicExchange::BindingNode::TreeIterator { -public: - QueueFinderIter(Queue::shared_ptr queue) : queue(queue), found(false) {}; - ~QueueFinderIter() {}; - bool visit(BindingNode& node) { - - Binding::vector& qv(node.bindings.bindingVector); - Binding::vector::iterator q; - for (q = qv.begin(); q != qv.end(); q++) { - if ((*q)->queue == queue) { - found = true; - return false; // search done - } - } - return true; // continue search - } - - Queue::shared_ptr queue; - bool found; -}; - - -// Iterate over a string of '.'-separated tokens. -struct TopicExchange::TokenIterator { - typedef pair<const char*,const char*> Token; - - TokenIterator(const char* b, const char* e) : end(e), token(make_pair(b, find(b,e,'.'))) {} - - TokenIterator(const string& key) : end(&key[0]+key.size()), token(make_pair(&key[0], find(&key[0],end,'.'))) {} - - bool finished() const { return !token.first; } - - void next() { - if (token.second == end) - token.first = token.second = 0; - else { - token.first=token.second+1; - token.second=(find(token.first, end, '.')); - } - } - - void pop(string &top) { - ptrdiff_t l = len(); - if (l) { - top.assign(token.first, l); - } else top.clear(); - next(); - } - - bool match1(char c) const { - return token.second==token.first+1 && *token.first == c; - } - - bool match(const Token& token2) const { - ptrdiff_t l=len(); - return l == token2.second-token2.first && - strncmp(token.first, token2.first, l) == 0; - } - - bool match(const string& str) const { - ptrdiff_t l=len(); - return l == ptrdiff_t(str.size()) && - str.compare(0, l, token.first, l) == 0; - } - - ptrdiff_t len() const { return token.second - token.first; } - - - const char* end; - Token token; -}; - - -class TopicExchange::Normalizer : public TopicExchange::TokenIterator { - public: - Normalizer(string& p) - : TokenIterator(&p[0], &p[0]+p.size()), pattern(p) - { normalize(); } - - private: - // Apply 2 transformations: #.* -> *.# and #.# -> # - void normalize() { - while (!finished()) { - if (match1('#')) { - const char* hash1=token.first; - next(); - if (!finished()) { - if (match1('#')) { // Erase #.# -> # - pattern.erase(hash1-pattern.data(), 2); - token.first -= 2; - token.second -= 2; - end -= 2; - } - else if (match1('*')) { // Swap #.* -> *.# - swap(*const_cast<char*>(hash1), - *const_cast<char*>(token.first)); - } - } - } - else - next(); - } - } - - string& pattern; -}; - - - -// Convert sequences of * and # to a sequence of * followed by a single # -string TopicExchange::normalize(const string& pattern) { - string normal(pattern); - Normalizer n(normal); - return normal; -} - - -TopicExchange::TopicExchange(const string& _name, Manageable* _parent, Broker* b) - : Exchange(_name, _parent, b), - nBindings(0) -{ - if (mgmtExchange != 0) - mgmtExchange->set_type (typeName); -} - -TopicExchange::TopicExchange(const std::string& _name, bool _durable, - const FieldTable& _args, Manageable* _parent, Broker* b) : - Exchange(_name, _durable, _args, _parent, b), - nBindings(0) -{ - if (mgmtExchange != 0) - mgmtExchange->set_type (typeName); -} - -bool TopicExchange::bind(Queue::shared_ptr queue, const string& routingKey, const FieldTable* args) -{ - ClearCache cc(&cacheLock,&bindingCache); // clear the cache on function exit. - string fedOp(args ? args->getAsString(qpidFedOp) : fedOpBind); - string fedTags(args ? args->getAsString(qpidFedTags) : ""); - string fedOrigin(args ? args->getAsString(qpidFedOrigin) : ""); - bool propagate = false; - string routingPattern = normalize(routingKey); - - if (args == 0 || fedOp.empty() || fedOp == fedOpBind) { - RWlock::ScopedWlock l(lock); - BindingKey *bk = bindingTree.addBindingKey(routingPattern); - if (bk) { - Binding::vector& qv(bk->bindingVector); - Binding::vector::iterator q; - for (q = qv.begin(); q != qv.end(); q++) { - if ((*q)->queue == queue) { - // already bound, but may be from a different fedOrigin - bk->fedBinding.addOrigin(queue->getName(), fedOrigin); - return false; - } - } - - Binding::shared_ptr binding (new Binding (routingPattern, queue, this, FieldTable(), fedOrigin)); - binding->startManagement(); - bk->bindingVector.push_back(binding); - nBindings++; - propagate = bk->fedBinding.addOrigin(queue->getName(), fedOrigin); - if (mgmtExchange != 0) { - mgmtExchange->inc_bindingCount(); - } - QPID_LOG(debug, "Binding key [" << routingPattern << "] to queue " << queue->getName() - << " on exchange " << getName() << " (origin=" << fedOrigin << ")"); - } - } else if (fedOp == fedOpUnbind) { - RWlock::ScopedWlock l(lock); - BindingKey* bk = getQueueBinding(queue, routingPattern); - if (bk) { - QPID_LOG(debug, "FedOpUnbind [" << routingPattern << "] from exchange " << getName() - << " on queue=" << queue->getName() << " origin=" << fedOrigin); - propagate = bk->fedBinding.delOrigin(queue->getName(), fedOrigin); - // if this was the last binding for the queue, delete the binding - if (bk->fedBinding.countFedBindings(queue->getName()) == 0) { - deleteBinding(queue, routingPattern, bk); - } - } - } else if (fedOp == fedOpReorigin) { - /** gather up all the keys that need rebinding in a local vector - * while holding the lock. Then propagate once the lock is - * released - */ - ReOriginIter reOriginIter; - { - RWlock::ScopedRlock l(lock); - bindingTree.iterateAll( reOriginIter ); - } /* lock dropped */ - - for (std::vector<std::string>::const_iterator key = reOriginIter.keys2prop.begin(); - key != reOriginIter.keys2prop.end(); key++) { - propagateFedOp( *key, string(), fedOpBind, string()); - } - } - - cc.clearCache(); // clear the cache before we IVE route. - routeIVE(); - if (propagate) - propagateFedOp(routingKey, fedTags, fedOp, fedOrigin); - return true; -} - -bool TopicExchange::unbind(Queue::shared_ptr queue, const string& constRoutingKey, const FieldTable* args) -{ - string fedOrigin(args ? args->getAsString(qpidFedOrigin) : ""); - QPID_LOG(debug, "Unbinding key [" << constRoutingKey << "] from queue " << queue->getName() - << " on exchange " << getName() << " origin=" << fedOrigin << ")" ); - - ClearCache cc(&cacheLock,&bindingCache); // clear the cache on function exit. - RWlock::ScopedWlock l(lock); - string routingKey = normalize(constRoutingKey); - BindingKey* bk = getQueueBinding(queue, routingKey); - if (!bk) return false; - bool propagate = bk->fedBinding.delOrigin(queue->getName(), fedOrigin); - deleteBinding(queue, routingKey, bk); - if (propagate) - propagateFedOp(routingKey, string(), fedOpUnbind, string()); - return true; -} - - -bool TopicExchange::deleteBinding(Queue::shared_ptr queue, - const std::string& routingKey, - BindingKey *bk) -{ - // Note well: write lock held by caller - Binding::vector& qv(bk->bindingVector); - Binding::vector::iterator q; - for (q = qv.begin(); q != qv.end(); q++) - if ((*q)->queue == queue) - break; - if(q == qv.end()) return false; - qv.erase(q); - assert(nBindings > 0); - nBindings--; - - if(qv.empty()) { - bindingTree.removeBindingKey(routingKey); - } - if (mgmtExchange != 0) { - mgmtExchange->dec_bindingCount(); - } - QPID_LOG(debug, "Unbound key [" << routingKey << "] from queue " << queue->getName() - << " on exchange " << getName()); - return true; -} - -/** returns a pointer to the BindingKey if the given queue is bound to this - * exchange using the routing pattern. 0 if queue binding does not exist. - */ -TopicExchange::BindingKey *TopicExchange::getQueueBinding(Queue::shared_ptr queue, const string& pattern) -{ - // Note well: lock held by caller.... - BindingKey *bk = bindingTree.getBindingKey(pattern); // Exact match against binding pattern - if (!bk) return 0; - Binding::vector& qv(bk->bindingVector); - Binding::vector::iterator q; - for (q = qv.begin(); q != qv.end(); q++) - if ((*q)->queue == queue) - break; - return (q != qv.end()) ? bk : 0; -} - -void TopicExchange::route(Deliverable& msg, const string& routingKey, const FieldTable* /*args*/) -{ - // Note: PERFORMANCE CRITICAL!!! - BindingList b; - std::map<std::string, BindingList>::iterator it; - { // only lock the cache for read - RWlock::ScopedRlock cl(cacheLock); - it = bindingCache.find(routingKey); - if (it != bindingCache.end()) { - b = it->second; - } - } - PreRoute pr(msg, this); - if (!b.get()) // no cache hit - { - RWlock::ScopedRlock l(lock); - b = BindingList(new std::vector<boost::shared_ptr<qpid::broker::Exchange::Binding> >); - BindingsFinderIter bindingsFinder(b); - bindingTree.iterateMatch(routingKey, bindingsFinder); - RWlock::ScopedWlock cwl(cacheLock); - bindingCache[routingKey] = b; // update cache - } - doRoute(msg, b); -} - -bool TopicExchange::isBound(Queue::shared_ptr queue, const string* const routingKey, const FieldTable* const) -{ - RWlock::ScopedRlock l(lock); - if (routingKey && queue) { - string key(normalize(*routingKey)); - return getQueueBinding(queue, key) != 0; - } else if (!routingKey && !queue) { - return nBindings > 0; - } else if (routingKey) { - if (bindingTree.getBindingKey(*routingKey)) { - return true; - } - } else { - QueueFinderIter queueFinder(queue); - bindingTree.iterateAll( queueFinder ); - return queueFinder.found; - } - return false; -} - -TopicExchange::~TopicExchange() {} - -const std::string TopicExchange::typeName("topic"); - -// -// class BindingNode -// - -TopicExchange::BindingNode::~BindingNode() -{ - childTokens.clear(); -} - - -// Add a binding pattern to the tree. Return a pointer to the binding key -// of the node that matches the binding pattern. -TopicExchange::BindingKey* -TopicExchange::BindingNode::addBindingKey(const std::string& normalizedRoute) -{ - TokenIterator bKey(normalizedRoute); - return addBindingKey(bKey, normalizedRoute); -} - - -// Return a pointer to the binding key of the leaf node that matches the binding pattern. -TopicExchange::BindingKey* -TopicExchange::BindingNode::getBindingKey(const std::string& normalizedRoute) -{ - TokenIterator bKey(normalizedRoute); - return getBindingKey(bKey); -} - - -// Delete the binding associated with the given route. -void TopicExchange::BindingNode::removeBindingKey(const std::string& normalizedRoute) -{ - TokenIterator bKey2(normalizedRoute); - removeBindingKey(bKey2, normalizedRoute); -} - -// visit each node in the tree. Note: all nodes are visited, -// even non-leaf nodes (i.e. nodes without any bindings) -bool TopicExchange::BindingNode::iterateAll(TopicExchange::BindingNode::TreeIterator& iter) -{ - if (!iter.visit(*this)) return false; - - if (starChild && !starChild->iterateAll(iter)) return false; - - if (hashChild && !hashChild->iterateAll(iter)) return false; - - for (ChildMap::iterator ptr = childTokens.begin(); - ptr != childTokens.end(); ptr++) { - - if (!ptr->second->iterateAll(iter)) return false; - } - - return true; -} - -// applies iter against only matching nodes until iter returns false -// Note Well: the iter may match against the same node more than once -// if # wildcards are present! -bool TopicExchange::BindingNode::iterateMatch(const std::string& routingKey, TreeIterator& iter) -{ - TopicExchange::TokenIterator rKey(routingKey); - return iterateMatch( rKey, iter ); -} - - -// recurse over binding using token iterator. -// Note well: bkey is modified! -TopicExchange::BindingKey* -TopicExchange::BindingNode::addBindingKey(TokenIterator &bKey, - const string& fullPattern) -{ - if (bKey.finished()) { - // this node's binding - if (routePattern.empty()) { - routePattern = fullPattern; - } else assert(routePattern == fullPattern); - - return &bindings; - - } else { - // pop the topmost token & recurse... - - if (bKey.match(STAR)) { - if (!starChild) { - starChild.reset(new StarNode()); - } - bKey.next(); - return starChild->addBindingKey(bKey, fullPattern); - - } else if (bKey.match(HASH)) { - if (!hashChild) { - hashChild.reset(new HashNode()); - } - bKey.next(); - return hashChild->addBindingKey(bKey, fullPattern); - - } else { - ChildMap::iterator ptr; - std::string next_token; - bKey.pop(next_token); - ptr = childTokens.find(next_token); - if (ptr != childTokens.end()) { - return ptr->second->addBindingKey(bKey, fullPattern); - } else { - BindingNode::shared_ptr child(new BindingNode(next_token)); - childTokens[next_token] = child; - return child->addBindingKey(bKey, fullPattern); - } - } - } -} - - -// Remove a binding pattern from the tree. Return true if the current -// node becomes a leaf without any bindings (therefore can be deleted). -// Note Well: modifies parameter bKey's value! -bool -TopicExchange::BindingNode::removeBindingKey(TokenIterator &bKey, - const string& fullPattern) -{ - bool remove; - - if (!bKey.finished()) { - - if (bKey.match(STAR)) { - bKey.next(); - if (starChild) { - remove = starChild->removeBindingKey(bKey, fullPattern); - if (remove) { - starChild.reset(); - } - } - } else if (bKey.match(HASH)) { - bKey.next(); - if (hashChild) { - remove = hashChild->removeBindingKey(bKey, fullPattern); - if (remove) { - hashChild.reset(); - } - } - } else { - ChildMap::iterator ptr; - std::string next_token; - bKey.pop(next_token); - ptr = childTokens.find(next_token); - if (ptr != childTokens.end()) { - remove = ptr->second->removeBindingKey(bKey, fullPattern); - if (remove) { - childTokens.erase(ptr); - } - } - } - } - - // no bindings and no children == parent can delete this node. - return getChildCount() == 0 && bindings.bindingVector.empty(); -} - - -// find the binding key that matches the given binding pattern. -// Note Well: modifies key parameter! -TopicExchange::BindingKey* -TopicExchange::BindingNode::getBindingKey(TokenIterator &key) -{ - if (key.finished()) { - return &bindings; - } - - string next_token; - - key.pop(next_token); - - if (next_token == STAR) { - if (starChild) - return starChild->getBindingKey(key); - } else if (next_token == HASH) { - if (hashChild) - return hashChild->getBindingKey(key); - } else { - ChildMap::iterator ptr; - ptr = childTokens.find(next_token); - if (ptr != childTokens.end()) { - return ptr->second->getBindingKey(key); - } - } - - return 0; -} - - - -// iterate over all nodes that match the given key. Note well: the set of nodes -// that are visited includes matching non-leaf nodes. -// Note well: parameter key is modified! -bool TopicExchange::BindingNode::iterateMatch(TokenIterator& key, TreeIterator& iter) -{ - // invariant: key has matched all previous tokens up to this node. - if (key.finished()) { - // exact match this node: visit if bound - if (!bindings.bindingVector.empty()) - if (!iter.visit(*this)) return false; - } - - // check remaining key against children, even if empty. - return iterateMatchChildren(key, iter); -} - - -TopicExchange::StarNode::StarNode() - : BindingNode(STAR) {} - - -// See iterateMatch() above. -// Special case: this node must verify a token is available (match exactly one). -bool TopicExchange::StarNode::iterateMatch(TokenIterator& key, TreeIterator& iter) -{ - // must match one token: - if (key.finished()) - return true; // match failed, but continue iteration on siblings - - // pop the topmost token - key.next(); - - if (key.finished()) { - // exact match this node: visit if bound - if (!bindings.bindingVector.empty()) - if (!iter.visit(*this)) return false; - } - - return iterateMatchChildren(key, iter); -} - - -TopicExchange::HashNode::HashNode() - : BindingNode(HASH) {} - - -// See iterateMatch() above. -// Special case: can match zero or more tokens at the head of the key. -bool TopicExchange::HashNode::iterateMatch(TokenIterator& key, TreeIterator& iter) -{ - // consume each token and look for a match on the - // remaining key. - while (!key.finished()) { - if (!iterateMatchChildren(key, iter)) return false; - key.next(); - } - - if (!bindings.bindingVector.empty()) - return iter.visit(*this); - - return true; -} - - -// helper: iterate over current node's matching children -bool -TopicExchange::BindingNode::iterateMatchChildren(const TopicExchange::TokenIterator& key, - TopicExchange::BindingNode::TreeIterator& iter) -{ - // always try glob - it can match empty keys - if (hashChild) { - TokenIterator tmp(key); - if (!hashChild->iterateMatch(tmp, iter)) - return false; - } - - if (!key.finished()) { - - if (starChild) { - TokenIterator tmp(key); - if (!starChild->iterateMatch(tmp, iter)) - return false; - } - - if (!childTokens.empty()) { - TokenIterator newKey(key); - std::string next_token; - newKey.pop(next_token); - - ChildMap::iterator ptr = childTokens.find(next_token); - if (ptr != childTokens.end()) { - return ptr->second->iterateMatch(newKey, iter); - } - } - } - - return true; -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/TopicExchange.h b/cpp/src/qpid/broker/TopicExchange.h deleted file mode 100644 index 636918f8a1..0000000000 --- a/cpp/src/qpid/broker/TopicExchange.h +++ /dev/null @@ -1,208 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _TopicExchange_ -#define _TopicExchange_ - -#include <map> -#include <vector> -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/Exchange.h" -#include "qpid/framing/FieldTable.h" -#include "qpid/sys/Monitor.h" -#include "qpid/broker/Queue.h" - - -namespace qpid { -namespace broker { - -class TopicExchange : public virtual Exchange { - - struct TokenIterator; - class Normalizer; - - struct BindingKey { // binding for this node - Binding::vector bindingVector; - FedBinding fedBinding; - }; - - // Binding database: - // The dotted form of a binding key is broken up and stored in a directed tree graph. - // Common binding prefix are merged. This allows the route match alogrithm to quickly - // isolate those sub-trees that match a given routingKey. - // For example, given the routes: - // a.b.c.<...> - // a.b.d.<...> - // a.x.y.<...> - // The resulting tree would be: - // a-->b-->c-->... - // | +-->d-->... - // +-->x-->y-->... - // - class QPID_BROKER_CLASS_EXTERN BindingNode { - public: - - typedef boost::shared_ptr<BindingNode> shared_ptr; - - // for database transversal (visit a node). - class TreeIterator { - public: - TreeIterator() {}; - virtual ~TreeIterator() {}; - virtual bool visit(BindingNode& node) = 0; - }; - - BindingNode() {}; - BindingNode(const std::string& token) : token(token) {}; - QPID_BROKER_EXTERN virtual ~BindingNode(); - - // add normalizedRoute to tree, return associated BindingKey - QPID_BROKER_EXTERN BindingKey* addBindingKey(const std::string& normalizedRoute); - - // return BindingKey associated with normalizedRoute - QPID_BROKER_EXTERN BindingKey* getBindingKey(const std::string& normalizedRoute); - - // remove BindingKey associated with normalizedRoute - QPID_BROKER_EXTERN void removeBindingKey(const std::string& normalizedRoute); - - // applies iter against each node in tree until iter returns false - QPID_BROKER_EXTERN bool iterateAll(TreeIterator& iter); - - // applies iter against only matching nodes until iter returns false - QPID_BROKER_EXTERN bool iterateMatch(const std::string& routingKey, TreeIterator& iter); - - std::string routePattern; // normalized binding that matches this node - BindingKey bindings; // for matches against this node - - protected: - - std::string token; // portion of pattern represented by this node - - // children - typedef std::map<const std::string, BindingNode::shared_ptr> ChildMap; - ChildMap childTokens; - BindingNode::shared_ptr starChild; // "*" subtree - BindingNode::shared_ptr hashChild; // "#" subtree - - unsigned int getChildCount() { return childTokens.size() + - (starChild ? 1 : 0) + (hashChild ? 1 : 0); } - BindingKey* addBindingKey(TokenIterator& bKey, - const std::string& fullPattern); - bool removeBindingKey(TokenIterator& bKey, - const std::string& fullPattern); - BindingKey* getBindingKey(TokenIterator& bKey); - QPID_BROKER_EXTERN virtual bool iterateMatch(TokenIterator& rKey, TreeIterator& iter); - bool iterateMatchChildren(const TokenIterator& key, TreeIterator& iter); - }; - - // Special case: ("*" token) Node in the tree for a match exactly one wildcard - class StarNode : public BindingNode { - public: - StarNode(); - ~StarNode() {}; - - protected: - virtual bool iterateMatch(TokenIterator& key, TreeIterator& iter); - }; - - // Special case: ("#" token) Node in the tree for a match zero or more - class HashNode : public BindingNode { - public: - HashNode(); - ~HashNode() {}; - - protected: - virtual bool iterateMatch(TokenIterator& key, TreeIterator& iter); - }; - - BindingNode bindingTree; - unsigned long nBindings; - qpid::sys::RWlock lock; // protects bindingTree and nBindings - qpid::sys::RWlock cacheLock; // protects cache - std::map<std::string, BindingList> bindingCache; // cache of matched routes. - class ClearCache { - private: - qpid::sys::RWlock* cacheLock; - std::map<std::string, BindingList>* bindingCache; - bool cleared; - public: - ClearCache(qpid::sys::RWlock* l, std::map<std::string, BindingList>* bc): cacheLock(l), - bindingCache(bc),cleared(false) {}; - void clearCache() { - qpid::sys::RWlock::ScopedWlock l(*cacheLock); - if (!cleared) { - bindingCache->clear(); - cleared =true; - } - }; - ~ClearCache(){ - clearCache(); - }; - }; - BindingKey *getQueueBinding(Queue::shared_ptr queue, const std::string& pattern); - bool deleteBinding(Queue::shared_ptr queue, - const std::string& routingKey, - BindingKey *bk); - - class ReOriginIter; - class BindingsFinderIter; - class QueueFinderIter; - - public: - static const std::string typeName; - - static QPID_BROKER_EXTERN std::string normalize(const std::string& pattern); - - QPID_BROKER_EXTERN TopicExchange(const std::string& name, - management::Manageable* parent = 0, Broker* broker = 0); - QPID_BROKER_EXTERN TopicExchange(const std::string& _name, - bool _durable, - const qpid::framing::FieldTable& _args, - management::Manageable* parent = 0, Broker* broker = 0); - - virtual std::string getType() const { return typeName; } - - QPID_BROKER_EXTERN virtual bool bind(Queue::shared_ptr queue, - const std::string& routingKey, - const qpid::framing::FieldTable* args); - - virtual bool unbind(Queue::shared_ptr queue, const std::string& routingKey, const qpid::framing::FieldTable* args); - - QPID_BROKER_EXTERN virtual void route(Deliverable& msg, - const std::string& routingKey, - const qpid::framing::FieldTable* args); - - QPID_BROKER_EXTERN virtual bool isBound(Queue::shared_ptr queue, - const std::string* const routingKey, - const qpid::framing::FieldTable* const args); - - QPID_BROKER_EXTERN virtual ~TopicExchange(); - virtual bool supportsDynamicBinding() { return true; } - - class TopicExchangeTester; - friend class TopicExchangeTester; -}; - - - -} -} - -#endif diff --git a/cpp/src/qpid/broker/TransactionalStore.h b/cpp/src/qpid/broker/TransactionalStore.h deleted file mode 100644 index 2a2bac0c51..0000000000 --- a/cpp/src/qpid/broker/TransactionalStore.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _TransactionalStore_ -#define _TransactionalStore_ - -#include <memory> -#include <string> -#include <set> - -namespace qpid { -namespace broker { - -struct InvalidTransactionContextException : public std::exception {}; - -class TransactionContext { -public: - virtual ~TransactionContext(){} -}; - -class TPCTransactionContext : public TransactionContext { -public: - virtual ~TPCTransactionContext(){} -}; - -class TransactionalStore { -public: - virtual std::auto_ptr<TransactionContext> begin() = 0; - virtual std::auto_ptr<TPCTransactionContext> begin(const std::string& xid) = 0; - virtual void prepare(TPCTransactionContext& txn) = 0; - virtual void commit(TransactionContext& txn) = 0; - virtual void abort(TransactionContext& txn) = 0; - - virtual void collectPreparedXids(std::set<std::string>& xids) = 0; - - virtual ~TransactionalStore(){} -}; - -} -} - - -#endif diff --git a/cpp/src/qpid/broker/TxAccept.cpp b/cpp/src/qpid/broker/TxAccept.cpp deleted file mode 100644 index 928ac12c10..0000000000 --- a/cpp/src/qpid/broker/TxAccept.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/TxAccept.h" -#include "qpid/log/Statement.h" - -using std::bind1st; -using std::bind2nd; -using std::mem_fun_ref; -using namespace qpid::broker; -using qpid::framing::SequenceSet; -using qpid::framing::SequenceNumber; - -TxAccept::RangeOp::RangeOp(const AckRange& r) : range(r) {} - -void TxAccept::RangeOp::prepare(TransactionContext* ctxt) -{ - for_each(range.start, range.end, bind(&DeliveryRecord::dequeue, _1, ctxt)); -} - -void TxAccept::RangeOp::commit() -{ - for_each(range.start, range.end, bind(&DeliveryRecord::committed, _1)); - for_each(range.start, range.end, bind(&DeliveryRecord::setEnded, _1)); -} - -TxAccept::RangeOps::RangeOps(DeliveryRecords& u) : unacked(u) {} - -void TxAccept::RangeOps::operator()(SequenceNumber start, SequenceNumber end) -{ - ranges.push_back(RangeOp(DeliveryRecord::findRange(unacked, start, end))); -} - -void TxAccept::RangeOps::prepare(TransactionContext* ctxt) -{ - std::for_each(ranges.begin(), ranges.end(), bind(&RangeOp::prepare, _1, ctxt)); -} - -void TxAccept::RangeOps::commit() -{ - std::for_each(ranges.begin(), ranges.end(), bind(&RangeOp::commit, _1)); - //now remove if isRedundant(): - if (!ranges.empty()) { - DeliveryRecords::iterator begin = ranges.front().range.start; - DeliveryRecords::iterator end = ranges.back().range.end; - DeliveryRecords::iterator removed = remove_if(begin, end, mem_fun_ref(&DeliveryRecord::isRedundant)); - unacked.erase(removed, end); - } -} - -TxAccept::TxAccept(const SequenceSet& _acked, DeliveryRecords& _unacked) : - acked(_acked), unacked(_unacked), ops(unacked) -{ - //populate the ops - acked.for_each(ops); -} - -bool TxAccept::prepare(TransactionContext* ctxt) throw() -{ - try{ - ops.prepare(ctxt); - return true; - }catch(const std::exception& e){ - QPID_LOG(error, "Failed to prepare: " << e.what()); - return false; - }catch(...){ - QPID_LOG(error, "Failed to prepare"); - return false; - } -} - -void TxAccept::commit() throw() -{ - try { - ops.commit(); - } catch (const std::exception& e) { - QPID_LOG(error, "Failed to commit: " << e.what()); - } catch(...) { - QPID_LOG(error, "Failed to commit (unknown error)"); - } -} - -void TxAccept::rollback() throw() {} diff --git a/cpp/src/qpid/broker/TxAccept.h b/cpp/src/qpid/broker/TxAccept.h deleted file mode 100644 index 314a150176..0000000000 --- a/cpp/src/qpid/broker/TxAccept.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _TxAccept_ -#define _TxAccept_ - -#include <algorithm> -#include <functional> -#include <list> -#include "qpid/framing/SequenceSet.h" -#include "qpid/broker/DeliveryRecord.h" -#include "qpid/broker/TxOp.h" - -namespace qpid { - namespace broker { - /** - * Defines the transactional behaviour for accepts received by - * a transactional channel. - */ - class TxAccept : public TxOp { - struct RangeOp - { - AckRange range; - - RangeOp(const AckRange& r); - void prepare(TransactionContext* ctxt); - void commit(); - }; - - struct RangeOps - { - std::vector<RangeOp> ranges; - DeliveryRecords& unacked; - - RangeOps(DeliveryRecords& u); - - void operator()(framing::SequenceNumber start, framing::SequenceNumber end); - void prepare(TransactionContext* ctxt); - void commit(); - }; - - framing::SequenceSet acked; - DeliveryRecords& unacked; - RangeOps ops; - - public: - /** - * @param acked a representation of the accumulation of - * acks received - * @param unacked the record of delivered messages - */ - TxAccept(const framing::SequenceSet& acked, DeliveryRecords& unacked); - virtual bool prepare(TransactionContext* ctxt) throw(); - virtual void commit() throw(); - virtual void rollback() throw(); - virtual ~TxAccept(){} - virtual void accept(TxOpConstVisitor& visitor) const { visitor(*this); } - - // Used by cluster replication. - const framing::SequenceSet& getAcked() const { return acked; } - }; - } -} - - -#endif diff --git a/cpp/src/qpid/broker/TxBuffer.cpp b/cpp/src/qpid/broker/TxBuffer.cpp deleted file mode 100644 index b509778e89..0000000000 --- a/cpp/src/qpid/broker/TxBuffer.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/broker/TxBuffer.h" -#include "qpid/log/Statement.h" - -#include <boost/mem_fn.hpp> -#include <boost/bind.hpp> -using boost::mem_fn; -using namespace qpid::broker; - -bool TxBuffer::prepare(TransactionContext* const ctxt) -{ - for(op_iterator i = ops.begin(); i < ops.end(); i++){ - if(!(*i)->prepare(ctxt)){ - return false; - } - } - return true; -} - -void TxBuffer::commit() -{ - std::for_each(ops.begin(), ops.end(), mem_fn(&TxOp::commit)); - ops.clear(); -} - -void TxBuffer::rollback() -{ - std::for_each(ops.begin(), ops.end(), mem_fn(&TxOp::rollback)); - ops.clear(); -} - -void TxBuffer::enlist(TxOp::shared_ptr op) -{ - ops.push_back(op); -} - -bool TxBuffer::commitLocal(TransactionalStore* const store) -{ - if (!store) return false; - try { - std::auto_ptr<TransactionContext> ctxt = store->begin(); - if (prepare(ctxt.get())) { - store->commit(*ctxt); - commit(); - return true; - } else { - store->abort(*ctxt); - rollback(); - return false; - } - } catch (std::exception& e) { - QPID_LOG(error, "Commit failed with exception: " << e.what()); - } catch (...) { - QPID_LOG(error, "Commit failed with unknown exception"); - } - return false; -} - -void TxBuffer::accept(TxOpConstVisitor& v) const { - std::for_each(ops.begin(), ops.end(), boost::bind(&TxOp::accept, _1, boost::ref(v))); -} diff --git a/cpp/src/qpid/broker/TxBuffer.h b/cpp/src/qpid/broker/TxBuffer.h deleted file mode 100644 index d49c8ba16a..0000000000 --- a/cpp/src/qpid/broker/TxBuffer.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _TxBuffer_ -#define _TxBuffer_ - -#include <algorithm> -#include <functional> -#include <vector> -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/TransactionalStore.h" -#include "qpid/broker/TxOp.h" - -/** - * Represents a single transaction. As such, an instance of this class - * will hold a list of operations representing the workload of the - * transaction. This work can be committed or rolled back. Committing - * is a two-stage process: first all the operations should be - * prepared, then if that succeeds they can be committed. - * - * In the 2pc case, a successful prepare may be followed by either a - * commit or a rollback. - * - * Atomicity of prepare is ensured by using a lower level - * transactional facility. This saves explicitly rolling back all the - * successfully prepared ops when one of them fails. i.e. we do not - * use 2pc internally, we instead ensure that prepare is atomic at a - * lower level. This makes individual prepare operations easier to - * code. - * - * Transactions on a messaging broker effect three types of 'action': - * (1) updates to persistent storage (2) updates to transient storage - * or cached data (3) network writes. - * - * Of these, (1) should always occur atomically during prepare to - * ensure that if the broker crashes while a transaction is being - * completed the persistent state (which is all that then remains) is - * consistent. (3) can only be done on commit, after a successful - * prepare. There is a little more flexibility with (2) but any - * changes made during prepare should be subject to the control of the - * TransactionalStore in use. - */ -namespace qpid { - namespace broker { - class TxBuffer{ - typedef std::vector<TxOp::shared_ptr>::iterator op_iterator; - std::vector<TxOp::shared_ptr> ops; - protected: - - public: - typedef boost::shared_ptr<TxBuffer> shared_ptr; - /** - * Adds an operation to the transaction. - */ - QPID_BROKER_EXTERN void enlist(TxOp::shared_ptr op); - - /** - * Requests that all ops are prepared. This should - * primarily involve making sure that a persistent record - * of the operations is stored where necessary. - * - * Once prepared, a transaction can be committed (or in - * the 2pc case, rolled back). - * - * @returns true if all the operations prepared - * successfully, false if not. - */ - QPID_BROKER_EXTERN bool prepare(TransactionContext* const ctxt); - - /** - * Signals that the ops all prepared successfully and can - * now commit, i.e. the operation can now be fully carried - * out. - * - * Should only be called after a call to prepare() returns - * true. - */ - QPID_BROKER_EXTERN void commit(); - - /** - * Signals that all ops can be rolled back. - * - * Should only be called either after a call to prepare() - * returns true (2pc) or instead of a prepare call - * ('server-local') - */ - QPID_BROKER_EXTERN void rollback(); - - /** - * Helper method for managing the process of server local - * commit - */ - QPID_BROKER_EXTERN bool commitLocal(TransactionalStore* const store); - - // Used by cluster to replicate transaction status. - void accept(TxOpConstVisitor& v) const; - }; - } -} - - -#endif diff --git a/cpp/src/qpid/broker/TxOp.h b/cpp/src/qpid/broker/TxOp.h deleted file mode 100644 index a8fa1c2621..0000000000 --- a/cpp/src/qpid/broker/TxOp.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _TxOp_ -#define _TxOp_ - -#include "qpid/broker/TxOpVisitor.h" -#include "qpid/broker/TransactionalStore.h" -#include <boost/shared_ptr.hpp> - -namespace qpid { - namespace broker { - - class TxOp{ - public: - typedef boost::shared_ptr<TxOp> shared_ptr; - - virtual bool prepare(TransactionContext*) throw() = 0; - virtual void commit() throw() = 0; - virtual void rollback() throw() = 0; - virtual ~TxOp(){} - - virtual void accept(TxOpConstVisitor&) const = 0; - }; - -}} // namespace qpid::broker - - -#endif diff --git a/cpp/src/qpid/broker/TxOpVisitor.h b/cpp/src/qpid/broker/TxOpVisitor.h deleted file mode 100644 index ceb894896e..0000000000 --- a/cpp/src/qpid/broker/TxOpVisitor.h +++ /dev/null @@ -1,97 +0,0 @@ -#ifndef QPID_BROKER_TXOPVISITOR_H -#define QPID_BROKER_TXOPVISITOR_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -namespace qpid { -namespace broker { - -class DtxAck; -class RecoveredDequeue; -class RecoveredEnqueue; -class TxAccept; -class TxPublish; - -/** - * Visitor for TxOp familly of classes. - */ -struct TxOpConstVisitor -{ - virtual ~TxOpConstVisitor() {} - virtual void operator()(const DtxAck&) = 0; - virtual void operator()(const RecoveredDequeue&) = 0; - virtual void operator()(const RecoveredEnqueue&) = 0; - virtual void operator()(const TxAccept&) = 0; - virtual void operator()(const TxPublish&) = 0; -}; - -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_TXOPVISITOR_H*/ -#ifndef QPID_BROKER_TXOPVISITOR_H -#define QPID_BROKER_TXOPVISITOR_H - -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -namespace qpid { -namespace broker { - -class DtxAck; -class RecoveredDequeue; -class RecoveredEnqueue; -class TxAccept; -class TxPublish; - -/** - * Visitor for TxOp familly of classes. - */ -struct TxOpConstVisitor -{ - virtual ~TxOpConstVisitor() {} - virtual void operator()(const DtxAck&) = 0; - virtual void operator()(const RecoveredDequeue&) = 0; - virtual void operator()(const RecoveredEnqueue&) = 0; - virtual void operator()(const TxAccept&) = 0; - virtual void operator()(const TxPublish&) = 0; -}; - -}} // namespace qpid::broker - -#endif /*!QPID_BROKER_TXOPVISITOR_H*/ diff --git a/cpp/src/qpid/broker/TxPublish.cpp b/cpp/src/qpid/broker/TxPublish.cpp deleted file mode 100644 index 9c2cf4a467..0000000000 --- a/cpp/src/qpid/broker/TxPublish.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#include "qpid/log/Statement.h" -#include "qpid/broker/TxPublish.h" -#include "qpid/broker/Queue.h" - -using boost::intrusive_ptr; -using namespace qpid::broker; - -TxPublish::TxPublish(intrusive_ptr<Message> _msg) : msg(_msg) {} - -bool TxPublish::prepare(TransactionContext* ctxt) throw() -{ - try{ - while (!queues.empty()) { - prepare(ctxt, queues.front()); - prepared.push_back(queues.front()); - queues.pop_front(); - } - return true; - }catch(const std::exception& e){ - QPID_LOG(error, "Failed to prepare: " << e.what()); - }catch(...){ - QPID_LOG(error, "Failed to prepare (unknown error)"); - } - return false; -} - -void TxPublish::commit() throw() -{ - try { - for_each(prepared.begin(), prepared.end(), Commit(msg)); - if (msg->isContentReleaseRequested()) { - // NOTE: The log messages in this section are used for flow-to-disk testing (which checks the log for the - // presence of these messages). Do not change these without also checking these tests. - if (msg->isContentReleaseBlocked()) { - QPID_LOG(debug, "Message id=\"" << msg->getProperties<qpid::framing::MessageProperties>()->getMessageId() << "\"; pid=0x" << - std::hex << msg->getPersistenceId() << std::dec << ": Content release blocked on commit"); - } else { - msg->releaseContent(); - QPID_LOG(debug, "Message id=\"" << msg->getProperties<qpid::framing::MessageProperties>()->getMessageId() << "\"; pid=0x" << - std::hex << msg->getPersistenceId() << std::dec << ": Content released on commit"); - } - } - } catch (const std::exception& e) { - QPID_LOG(error, "Failed to commit: " << e.what()); - } catch(...) { - QPID_LOG(error, "Failed to commit (unknown error)"); - } -} - -void TxPublish::rollback() throw() -{ - try { - for_each(prepared.begin(), prepared.end(), Rollback(msg)); - } catch (const std::exception& e) { - QPID_LOG(error, "Failed to complete rollback: " << e.what()); - } catch(...) { - QPID_LOG(error, "Failed to complete rollback (unknown error)"); - } - -} - -void TxPublish::deliverTo(const boost::shared_ptr<Queue>& queue){ - if (!queue->isLocal(msg)) { - queues.push_back(queue); - delivered = true; - } else { - QPID_LOG(debug, "Won't enqueue local message for " << queue->getName()); - } -} - -void TxPublish::prepare(TransactionContext* ctxt, const boost::shared_ptr<Queue> queue) -{ - queue->enqueue(ctxt, msg); -} - -TxPublish::Commit::Commit(intrusive_ptr<Message>& _msg) : msg(_msg){} - -void TxPublish::Commit::operator()(const boost::shared_ptr<Queue>& queue){ - queue->process(msg); -} - -TxPublish::Rollback::Rollback(intrusive_ptr<Message>& _msg) : msg(_msg){} - -void TxPublish::Rollback::operator()(const boost::shared_ptr<Queue>& queue){ - queue->enqueueAborted(msg); -} - -uint64_t TxPublish::contentSize () -{ - return msg->contentSize (); -} diff --git a/cpp/src/qpid/broker/TxPublish.h b/cpp/src/qpid/broker/TxPublish.h deleted file mode 100644 index f0b9c0a302..0000000000 --- a/cpp/src/qpid/broker/TxPublish.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -#ifndef _TxPublish_ -#define _TxPublish_ - -#include "qpid/broker/BrokerImportExport.h" -#include "qpid/broker/Deliverable.h" -#include "qpid/broker/Message.h" -#include "qpid/broker/MessageStore.h" -#include "qpid/broker/TxOp.h" - -#include <algorithm> -#include <functional> -#include <list> - -#include <boost/intrusive_ptr.hpp> - -namespace qpid { - namespace broker { - /** - * Defines the behaviour for publish operations on a - * transactional channel. Messages are routed through - * exchanges when received but are not at that stage delivered - * to the matching queues, rather the queues are held in an - * instance of this class. On prepare() the message is marked - * enqueued to the relevant queues in the MessagesStore. On - * commit() the messages will be passed to the queue for - * dispatch or to be added to the in-memory queue. - */ - class QPID_BROKER_CLASS_EXTERN TxPublish : public TxOp, public Deliverable{ - - class Commit{ - boost::intrusive_ptr<Message>& msg; - public: - Commit(boost::intrusive_ptr<Message>& msg); - void operator()(const boost::shared_ptr<Queue>& queue); - }; - class Rollback{ - boost::intrusive_ptr<Message>& msg; - public: - Rollback(boost::intrusive_ptr<Message>& msg); - void operator()(const boost::shared_ptr<Queue>& queue); - }; - - boost::intrusive_ptr<Message> msg; - std::list<boost::shared_ptr<Queue> > queues; - std::list<boost::shared_ptr<Queue> > prepared; - - void prepare(TransactionContext* ctxt, boost::shared_ptr<Queue>); - - public: - QPID_BROKER_EXTERN TxPublish(boost::intrusive_ptr<Message> msg); - QPID_BROKER_EXTERN virtual bool prepare(TransactionContext* ctxt) throw(); - QPID_BROKER_EXTERN virtual void commit() throw(); - QPID_BROKER_EXTERN virtual void rollback() throw(); - - virtual Message& getMessage() { return *msg; }; - - QPID_BROKER_EXTERN virtual void deliverTo(const boost::shared_ptr<Queue>& queue); - - virtual ~TxPublish(){} - virtual void accept(TxOpConstVisitor& visitor) const { visitor(*this); } - - QPID_BROKER_EXTERN uint64_t contentSize(); - - boost::intrusive_ptr<Message> getMessage() const { return msg; } - const std::list<boost::shared_ptr<Queue> > getQueues() const { return queues; } - }; - } -} - - -#endif diff --git a/cpp/src/qpid/broker/Vhost.cpp b/cpp/src/qpid/broker/Vhost.cpp deleted file mode 100644 index a9ca3b42ab..0000000000 --- a/cpp/src/qpid/broker/Vhost.cpp +++ /dev/null @@ -1,49 +0,0 @@ -// -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -// - -#include "qpid/broker/Vhost.h" -#include "qpid/broker/Broker.h" -#include "qpid/management/ManagementAgent.h" - -using namespace qpid::broker; -using qpid::management::ManagementAgent; -namespace _qmf = qmf::org::apache::qpid::broker; - -namespace qpid { namespace management { -class Manageable; -}} - -Vhost::Vhost (qpid::management::Manageable* parentBroker, Broker* broker) : mgmtObject(0) -{ - if (parentBroker != 0 && broker != 0) - { - ManagementAgent* agent = broker->getManagementAgent(); - - if (agent != 0) - { - mgmtObject = new _qmf::Vhost(agent, this, parentBroker, "/"); - agent->addObject(mgmtObject, 0, true); - } - } -} - -void Vhost::setFederationTag(const std::string& tag) -{ - mgmtObject->set_federationTag(tag); -} diff --git a/cpp/src/qpid/broker/Vhost.h b/cpp/src/qpid/broker/Vhost.h deleted file mode 100644 index 9554d641c2..0000000000 --- a/cpp/src/qpid/broker/Vhost.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef _Vhost_ -#define _Vhost_ - -// -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -// - -#include "qpid/management/Manageable.h" -#include "qmf/org/apache/qpid/broker/Vhost.h" -#include <boost/shared_ptr.hpp> - -namespace qpid { -namespace broker { - -class Broker; -class Vhost : public management::Manageable -{ - private: - - qmf::org::apache::qpid::broker::Vhost* mgmtObject; - - public: - - typedef boost::shared_ptr<Vhost> shared_ptr; - - Vhost (management::Manageable* parentBroker, Broker* broker = 0); - - management::ManagementObject* GetManagementObject (void) const - { return mgmtObject; } - void setFederationTag(const std::string& tag); -}; - -}} - -#endif /*!_Vhost_*/ diff --git a/cpp/src/qpid/broker/posix/BrokerDefaults.cpp b/cpp/src/qpid/broker/posix/BrokerDefaults.cpp deleted file mode 100644 index 9e463fa32d..0000000000 --- a/cpp/src/qpid/broker/posix/BrokerDefaults.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/Broker.h" -#include <stdlib.h> - -namespace qpid { -namespace broker { - -const std::string Broker::Options::DEFAULT_DATA_DIR_LOCATION("/tmp"); -const std::string Broker::Options::DEFAULT_DATA_DIR_NAME("/.qpidd"); - -std::string -Broker::Options::getHome() { - std::string home; - char *home_c = ::getenv("HOME"); - if (home_c != 0) - home += home_c; - return home; -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/windows/BrokerDefaults.cpp b/cpp/src/qpid/broker/windows/BrokerDefaults.cpp deleted file mode 100644 index b65440b5ad..0000000000 --- a/cpp/src/qpid/broker/windows/BrokerDefaults.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/broker/Broker.h" -#include <stdlib.h> - -namespace qpid { -namespace broker { - -const std::string Broker::Options::DEFAULT_DATA_DIR_LOCATION("\\TEMP"); -const std::string Broker::Options::DEFAULT_DATA_DIR_NAME("\\QPIDD.DATA"); - -std::string -Broker::Options::getHome() { - std::string home; -#ifdef _MSC_VER - char home_c[MAX_PATH+1]; - size_t unused; - if (0 == getenv_s (&unused, home_c, sizeof(home_c), "HOME")) - home += home_c; -#else - char *home_c = getenv("HOME"); - if (home_c) - home += home_c; -#endif - return home; -} - -}} // namespace qpid::broker diff --git a/cpp/src/qpid/broker/windows/SaslAuthenticator.cpp b/cpp/src/qpid/broker/windows/SaslAuthenticator.cpp deleted file mode 100644 index 962877a471..0000000000 --- a/cpp/src/qpid/broker/windows/SaslAuthenticator.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -// This source is only used on Windows; SSPI is the Windows mechanism for -// accessing authentication mechanisms, analogous to Cyrus SASL. - -#include "qpid/broker/Connection.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/reply_exceptions.h" - -#include <windows.h> - -using namespace qpid::framing; -using qpid::sys::SecurityLayer; - -namespace qpid { -namespace broker { - -class NullAuthenticator : public SaslAuthenticator -{ - Connection& connection; - framing::AMQP_ClientProxy::Connection client; -public: - NullAuthenticator(Connection& connection); - ~NullAuthenticator(); - void getMechanisms(framing::Array& mechanisms); - void start(const std::string& mechanism, const std::string& response); - void step(const std::string&) {} - std::auto_ptr<SecurityLayer> getSecurityLayer(uint16_t maxFrameSize); -}; - -class SspiAuthenticator : public SaslAuthenticator -{ - HANDLE userToken; - Connection& connection; - framing::AMQP_ClientProxy::Connection client; - -public: - SspiAuthenticator(Connection& connection); - ~SspiAuthenticator(); - void getMechanisms(framing::Array& mechanisms); - void start(const std::string& mechanism, const std::string& response); - void step(const std::string& response); - std::auto_ptr<SecurityLayer> getSecurityLayer(uint16_t maxFrameSize); -}; - -bool SaslAuthenticator::available(void) -{ - return true; -} - -// Initialize the SASL mechanism; throw if it fails. -void SaslAuthenticator::init(const std::string& /*saslName*/, const std::string& /*saslConfig*/) -{ - return; -} - -void SaslAuthenticator::fini(void) -{ - return; -} - -std::auto_ptr<SaslAuthenticator> SaslAuthenticator::createAuthenticator(Connection& c, bool) -{ - if (c.getBroker().getOptions().auth) { - return std::auto_ptr<SaslAuthenticator>(new SspiAuthenticator(c)); - } else { - return std::auto_ptr<SaslAuthenticator>(new NullAuthenticator(c)); - } -} - -NullAuthenticator::NullAuthenticator(Connection& c) : connection(c), client(c.getOutput()) {} -NullAuthenticator::~NullAuthenticator() {} - -void NullAuthenticator::getMechanisms(Array& mechanisms) -{ - mechanisms.add(boost::shared_ptr<FieldValue>(new Str16Value("ANONYMOUS"))); -} - -void NullAuthenticator::start(const string& mechanism, const string& response) -{ - QPID_LOG(warning, "SASL: No Authentication Performed"); - if (mechanism == "PLAIN") { // Old behavior - if (response.size() > 0 && response[0] == (char) 0) { - string temp = response.substr(1); - string::size_type i = temp.find((char)0); - string uid = temp.substr(0, i); - string pwd = temp.substr(i + 1); - connection.setUserId(uid); - } - } else { - connection.setUserId("anonymous"); - } - client.tune(framing::CHANNEL_MAX, connection.getFrameMax(), 0, 0); -} - -std::auto_ptr<SecurityLayer> NullAuthenticator::getSecurityLayer(uint16_t) -{ - std::auto_ptr<SecurityLayer> securityLayer; - return securityLayer; -} - - -SspiAuthenticator::SspiAuthenticator(Connection& c) : userToken(INVALID_HANDLE_VALUE), connection(c), client(c.getOutput()) -{ -} - -SspiAuthenticator::~SspiAuthenticator() -{ - if (INVALID_HANDLE_VALUE != userToken) { - CloseHandle(userToken); - userToken = INVALID_HANDLE_VALUE; - } -} - -void SspiAuthenticator::getMechanisms(Array& mechanisms) -{ - mechanisms.add(boost::shared_ptr<FieldValue>(new Str16Value(string("ANONYMOUS")))); - mechanisms.add(boost::shared_ptr<FieldValue>(new Str16Value(string("PLAIN")))); - QPID_LOG(info, "SASL: Mechanism list: ANONYMOUS PLAIN"); -} - -void SspiAuthenticator::start(const string& mechanism, const string& response) -{ - QPID_LOG(info, "SASL: Starting authentication with mechanism: " << mechanism); - if (mechanism == "ANONYMOUS") { - connection.setUserId("anonymous"); - client.tune(framing::CHANNEL_MAX, connection.getFrameMax(), 0, 0); - return; - } - if (mechanism != "PLAIN") - throw ConnectionForcedException("Unsupported mechanism"); - - // PLAIN's response is composed of 3 strings separated by 0 bytes: - // authorization id, authentication id (user), clear-text password. - if (response.size() == 0) - throw ConnectionForcedException("Authentication failed"); - - string::size_type i = response.find((char)0); - string auth = response.substr(0, i); - string::size_type j = response.find((char)0, i+1); - string uid = response.substr(i+1, j-1); - string pwd = response.substr(j+1); - string dot("."); - int error = 0; - if (!LogonUser(const_cast<char*>(uid.c_str()), - const_cast<char*>(dot.c_str()), - const_cast<char*>(pwd.c_str()), - LOGON32_LOGON_NETWORK, - LOGON32_PROVIDER_DEFAULT, - &userToken)) - error = GetLastError(); - pwd.replace(0, string::npos, 1, (char)0); - if (error != 0) { - QPID_LOG(info, - "SASL: Auth failed [" << error << "]: " << qpid::sys::strError(error)); - throw ConnectionForcedException("Authentication failed"); - } - - connection.setUserId(uid); - client.tune(framing::CHANNEL_MAX, connection.getFrameMax(), 0, 0); -} - -void SspiAuthenticator::step(const string& /*response*/) -{ - QPID_LOG(info, "SASL: Need another step!!!"); -} - -std::auto_ptr<SecurityLayer> SspiAuthenticator::getSecurityLayer(uint16_t) -{ - std::auto_ptr<SecurityLayer> securityLayer; - return securityLayer; -} - -}} diff --git a/cpp/src/qpid/broker/windows/SslProtocolFactory.cpp b/cpp/src/qpid/broker/windows/SslProtocolFactory.cpp deleted file mode 100644 index fd0e537192..0000000000 --- a/cpp/src/qpid/broker/windows/SslProtocolFactory.cpp +++ /dev/null @@ -1,302 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/ProtocolFactory.h" - -#include "qpid/Plugin.h" -#include "qpid/broker/Broker.h" -#include "qpid/log/Statement.h" -#include "qpid/sys/AsynchIOHandler.h" -#include "qpid/sys/ConnectionCodec.h" -#include "qpid/sys/Socket.h" -#include "qpid/sys/SystemInfo.h" -#include "qpid/sys/windows/SslAsynchIO.h" -#include <boost/bind.hpp> -#include <memory> -// security.h needs to see this to distinguish from kernel use. -#define SECURITY_WIN32 -#include <security.h> -#include <Schnlsp.h> -#undef SECURITY_WIN32 - - -namespace qpid { -namespace sys { -namespace windows { - -struct SslServerOptions : qpid::Options -{ - std::string certStore; - std::string certName; - uint16_t port; - bool clientAuth; - - SslServerOptions() : qpid::Options("SSL Options"), - certStore("My"), port(5671), clientAuth(false) - { - qpid::Address me; - if (qpid::sys::SystemInfo::getLocalHostname(me)) - certName = me.host; - else - certName = "localhost"; - - addOptions() - ("ssl-cert-store", optValue(certStore, "NAME"), "Local store name from which to obtain certificate") - ("ssl-cert-name", optValue(certName, "NAME"), "Name of the certificate to use") - ("ssl-port", optValue(port, "PORT"), "Port on which to listen for SSL connections") - ("ssl-require-client-authentication", optValue(clientAuth), - "Forces clients to authenticate in order to establish an SSL connection"); - } -}; - -class SslProtocolFactory : public qpid::sys::ProtocolFactory { - qpid::sys::Socket listener; - const bool tcpNoDelay; - const uint16_t listeningPort; - std::string brokerHost; - const bool clientAuthSelected; - std::auto_ptr<qpid::sys::AsynchAcceptor> acceptor; - ConnectFailedCallback connectFailedCallback; - CredHandle credHandle; - - public: - SslProtocolFactory(const SslServerOptions&, int backlog, bool nodelay); - ~SslProtocolFactory(); - void accept(sys::Poller::shared_ptr, sys::ConnectionCodec::Factory*); - void connect(sys::Poller::shared_ptr, const std::string& host, int16_t port, - sys::ConnectionCodec::Factory*, - ConnectFailedCallback failed); - - uint16_t getPort() const; - std::string getHost() const; - bool supports(const std::string& capability); - - private: - void connectFailed(const qpid::sys::Socket&, - int err, - const std::string& msg); - void established(sys::Poller::shared_ptr, - const qpid::sys::Socket&, - sys::ConnectionCodec::Factory*, - bool isClient); -}; - -// Static instance to initialise plugin -static struct SslPlugin : public Plugin { - SslServerOptions options; - - Options* getOptions() { return &options; } - - void earlyInitialize(Target&) { - } - - void initialize(Target& target) { - broker::Broker* broker = dynamic_cast<broker::Broker*>(&target); - // Only provide to a Broker - if (broker) { - try { - const broker::Broker::Options& opts = broker->getOptions(); - ProtocolFactory::shared_ptr protocol(new SslProtocolFactory(options, - opts.connectionBacklog, - opts.tcpNoDelay)); - QPID_LOG(notice, "Listening for SSL connections on TCP port " << protocol->getPort()); - broker->registerProtocolFactory("ssl", protocol); - } catch (const std::exception& e) { - QPID_LOG(error, "Failed to initialise SSL listener: " << e.what()); - } - } - } -} sslPlugin; - -SslProtocolFactory::SslProtocolFactory(const SslServerOptions& options, - int backlog, - bool nodelay) - : tcpNoDelay(nodelay), - listeningPort(listener.listen(options.port, backlog)), - clientAuthSelected(options.clientAuth) { - - SecInvalidateHandle(&credHandle); - - // Get the certificate for this server. - HCERTSTORE certStoreHandle; - certStoreHandle = ::CertOpenStore(CERT_STORE_PROV_SYSTEM_A, - X509_ASN_ENCODING, - 0, - CERT_SYSTEM_STORE_LOCAL_MACHINE, - options.certStore.c_str()); - if (!certStoreHandle) - throw qpid::Exception(QPID_MSG("Opening store " << options.certStore << " " << qpid::sys::strError(GetLastError()))); - - PCCERT_CONTEXT certContext; - certContext = ::CertFindCertificateInStore(certStoreHandle, - X509_ASN_ENCODING, - 0, - CERT_FIND_SUBJECT_STR_A, - options.certName.c_str(), - NULL); - if (certContext == NULL) { - int err = ::GetLastError(); - ::CertCloseStore(certStoreHandle, 0); - throw qpid::Exception(QPID_MSG("Locating certificate " << options.certName << " in store " << options.certStore << " " << qpid::sys::strError(GetLastError()))); - throw QPID_WINDOWS_ERROR(err); - } - - SCHANNEL_CRED cred; - memset(&cred, 0, sizeof(cred)); - cred.dwVersion = SCHANNEL_CRED_VERSION; - cred.cCreds = 1; - cred.paCred = &certContext; - SECURITY_STATUS status = ::AcquireCredentialsHandle(NULL, - UNISP_NAME, - SECPKG_CRED_INBOUND, - NULL, - &cred, - NULL, - NULL, - &credHandle, - NULL); - if (status != SEC_E_OK) - throw QPID_WINDOWS_ERROR(status); - ::CertFreeCertificateContext(certContext); - ::CertCloseStore(certStoreHandle, 0); -} - -SslProtocolFactory::~SslProtocolFactory() { - ::FreeCredentialsHandle(&credHandle); -} - -void SslProtocolFactory::connectFailed(const qpid::sys::Socket&, - int err, - const std::string& msg) { - if (connectFailedCallback) - connectFailedCallback(err, msg); -} - -void SslProtocolFactory::established(sys::Poller::shared_ptr poller, - const qpid::sys::Socket& s, - sys::ConnectionCodec::Factory* f, - bool isClient) { - sys::AsynchIOHandler* async = new sys::AsynchIOHandler(s.getFullAddress(), f); - - if (tcpNoDelay) { - s.setTcpNoDelay(); - QPID_LOG(info, - "Set TCP_NODELAY on connection to " << s.getPeerAddress()); - } - - SslAsynchIO *aio; - if (isClient) { - async->setClient(); - aio = - new qpid::sys::windows::ClientSslAsynchIO(brokerHost, - s, - credHandle, - boost::bind(&AsynchIOHandler::readbuff, async, _1, _2), - boost::bind(&AsynchIOHandler::eof, async, _1), - boost::bind(&AsynchIOHandler::disconnect, async, _1), - boost::bind(&AsynchIOHandler::closedSocket, async, _1, _2), - boost::bind(&AsynchIOHandler::nobuffs, async, _1), - boost::bind(&AsynchIOHandler::idle, async, _1)); - } - else { - aio = - new qpid::sys::windows::ServerSslAsynchIO(clientAuthSelected, - s, - credHandle, - boost::bind(&AsynchIOHandler::readbuff, async, _1, _2), - boost::bind(&AsynchIOHandler::eof, async, _1), - boost::bind(&AsynchIOHandler::disconnect, async, _1), - boost::bind(&AsynchIOHandler::closedSocket, async, _1, _2), - boost::bind(&AsynchIOHandler::nobuffs, async, _1), - boost::bind(&AsynchIOHandler::idle, async, _1)); - } - - async->init(aio, 4); - aio->start(poller); -} - -uint16_t SslProtocolFactory::getPort() const { - return listeningPort; // Immutable no need for lock. -} - -std::string SslProtocolFactory::getHost() const { - return listener.getSockname(); -} - -void SslProtocolFactory::accept(sys::Poller::shared_ptr poller, - sys::ConnectionCodec::Factory* fact) { - acceptor.reset( - AsynchAcceptor::create(listener, - boost::bind(&SslProtocolFactory::established, this, poller, _1, fact, false))); - acceptor->start(poller); -} - -void SslProtocolFactory::connect(sys::Poller::shared_ptr poller, - const std::string& host, - int16_t port, - sys::ConnectionCodec::Factory* fact, - ConnectFailedCallback failed) -{ - SCHANNEL_CRED cred; - memset(&cred, 0, sizeof(cred)); - cred.dwVersion = SCHANNEL_CRED_VERSION; - SECURITY_STATUS status = ::AcquireCredentialsHandle(NULL, - UNISP_NAME, - SECPKG_CRED_OUTBOUND, - NULL, - &cred, - NULL, - NULL, - &credHandle, - NULL); - if (status != SEC_E_OK) - throw QPID_WINDOWS_ERROR(status); - - brokerHost = host; - // Note that the following logic does not cause a memory leak. - // The allocated Socket is freed either by the AsynchConnector - // upon connection failure or by the AsynchIO upon connection - // shutdown. The allocated AsynchConnector frees itself when it - // is no longer needed. - qpid::sys::Socket* socket = new qpid::sys::Socket(); - connectFailedCallback = failed; - AsynchConnector::create(*socket, - host, - port, - boost::bind(&SslProtocolFactory::established, - this, poller, _1, fact, true), - boost::bind(&SslProtocolFactory::connectFailed, - this, _1, _2, _3)); -} - -namespace -{ -const std::string SSL = "ssl"; -} - -bool SslProtocolFactory::supports(const std::string& capability) -{ - std::string s = capability; - transform(s.begin(), s.end(), s.begin(), tolower); - return s == SSL; -} - -}}} // namespace qpid::sys::windows |