qpid-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From acon...@apache.org
Subject svn commit: r611823 - in /incubator/qpid/trunk/qpid/cpp/src: ./ qpid/ qpid/broker/ qpid/cluster/
Date Mon, 14 Jan 2008 14:55:50 GMT
Author: aconway
Date: Mon Jan 14 06:55:46 2008
New Revision: 611823

URL: http://svn.apache.org/viewvc?rev=611823&view=rev
Log:

Apply patch from QPID-732 by Ted Ross.

 The attached patch provides support for plugin modules in the C++ broker.

  - Plugins are supported (--load <lib>, --load-dir <dir> options provided)
  - Command options may be extended by plugins.
  - A workaround was added to make config-file parsing tolerant of unregistered options.
  - Store-specific options were removed so they can be supplied by a plugin
  - A pre-log facility was introduced so log messages can be generated prior to the initialization
of the logging module.

File-by-file details:

M cpp/src/qpidd.cpp

    Added support for loadable plugin modules. This involves a
    two-phased handling of command line/config options. Phase-1
    determines which modules to load and phase-2 is based on all of
    the command-line options supplied by qpidd and the loaded
    plugins.

M cpp/src/Makefile.am

    Added dependency for boost_filesystem library.

M cpp/src/qpid/Plugin.h

    Added 'earlyInitialize' method. Plugins are now initialized at
    two points: earlyInitialize is called prior to broker
    initialization and initialize is called at the end of broker
    init. This allows modules like the store to be hooked in early
    and other modules to be able to assume that the broker target is
    fully functional.

M cpp/src/qpid/cluster/ClusterPlugin.cpp

    Added stub for the new pure-virtual earlyInitialize method.

M cpp/src/qpid/Options.h
M cpp/src/qpid/Options.cpp

    Added 'allowUnknown' option in the parse method. This is needed
    in phase-1 command processing when there are options for
    not-yet-loaded plugin modules.

    Because the stable version of boost does not permit 'allowUnknown'
    for config files, a workaround has been implemented in this module
    to pre-filter the config file text removing lines that represent
    unknown options.

M cpp/src/qpid/broker/Broker.h
M cpp/src/qpid/broker/Broker.cpp

    Removed all store-specific command options. Updated logic to
    allow the store to be a plugin module.

M cpp/src/qpid/broker/DtxManager.h
M cpp/src/qpid/broker/DtxManager.cpp
M cpp/src/qpid/broker/QueueRegistry.h
M cpp/src/qpid/broker/QueueRegistry.cpp

    Changed API to these classes such that the store is no longer
    supplied in the constructor but is supplied later, before any
    operations are called for.

M cpp/src/qpid/broker/MessageStoreModule.h
M cpp/src/qpid/broker/MessageStoreModule.cpp

    This module is still needed to provide "exception transfer"
    service. It was changed to not load the store module but rather
    use the already-loaded plugin store.

Modified:
    incubator/qpid/trunk/qpid/cpp/src/Makefile.am
    incubator/qpid/trunk/qpid/cpp/src/qpid/Options.cpp
    incubator/qpid/trunk/qpid/cpp/src/qpid/Options.h
    incubator/qpid/trunk/qpid/cpp/src/qpid/Plugin.h
    incubator/qpid/trunk/qpid/cpp/src/qpid/broker/Broker.cpp
    incubator/qpid/trunk/qpid/cpp/src/qpid/broker/DtxManager.cpp
    incubator/qpid/trunk/qpid/cpp/src/qpid/broker/DtxManager.h
    incubator/qpid/trunk/qpid/cpp/src/qpid/broker/MessageStoreModule.cpp
    incubator/qpid/trunk/qpid/cpp/src/qpid/broker/MessageStoreModule.h
    incubator/qpid/trunk/qpid/cpp/src/qpid/broker/QueueRegistry.cpp
    incubator/qpid/trunk/qpid/cpp/src/qpid/broker/QueueRegistry.h
    incubator/qpid/trunk/qpid/cpp/src/qpid/cluster/ClusterPlugin.cpp
    incubator/qpid/trunk/qpid/cpp/src/qpidd.cpp

Modified: incubator/qpid/trunk/qpid/cpp/src/Makefile.am
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/Makefile.am?rev=611823&r1=611822&r2=611823&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/Makefile.am (original)
+++ incubator/qpid/trunk/qpid/cpp/src/Makefile.am Mon Jan 14 06:55:46 2008
@@ -92,6 +92,7 @@
 
 libqpidcommon_la_LIBADD = \
   -lboost_program_options \
+  -lboost_filesystem \
   -luuid \
   libLogger.la \
   $(LIB_DLOPEN) \

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/Options.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/Options.cpp?rev=611823&r1=611822&r2=611823&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/Options.cpp (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/Options.cpp Mon Jan 14 06:55:46 2008
@@ -40,6 +40,10 @@
         return std::equal(env.begin(), env.end(), desc->long_name().begin(), &matchChar);
     }
             
+    static bool matchCase(const string& env, boost::shared_ptr<po::option_description>
desc) {
+        return env == desc->long_name();
+    }
+            
     EnvOptMapper(const Options& o) : opts(o) {}
     
     string operator()(const string& envVar) {
@@ -54,6 +58,20 @@
         }
         return string();
     }
+
+    string configFileLine (string& line) {
+        size_t pos = line.find ('=');
+        if (pos == string::npos)
+            return string();
+        string key = line.substr (0, pos);
+        typedef const std::vector< boost::shared_ptr<po::option_description> >
OptDescs;
+        OptDescs::const_iterator i = 
+            find_if(opts.options().begin(), opts.options().end(), boost::bind(matchCase,
key, _1));
+        if (i != opts.options().end())
+            return string (line) + "\n";
+        return string ();
+    }
+
     const Options& opts;
 };
 
@@ -64,23 +82,52 @@
 
 Options::Options(const string& name) : po::options_description(name) {}
 
-void Options::parse(int argc, char** argv, const std::string& configFile)
+void Options::parse(int argc, char** argv, const std::string& configFile, bool allowUnknown)
 {
     string defaultConfigFile = configFile; // May be changed by env/cmdline
     string parsing;
     try {
         po::variables_map vm;
         parsing="command line options";
-        if (argc > 0 && argv != 0)
-            po::store(po::parse_command_line(argc, argv, *this), vm);
+        if (argc > 0 && argv != 0) {
+            if (allowUnknown) {
+                // This hideous workaround is required because boost 1.33 has a bug
+                // that causes 'allow_unregistered' to not work.
+                po::command_line_parser clp = po::command_line_parser(argc, argv).
+                    options(*this).allow_unregistered();
+                po::parsed_options opts     = clp.run();
+                po::parsed_options filtopts = clp.run();
+                filtopts.options.clear ();
+                for (std::vector< po::basic_option<char> >::iterator i = opts.options.begin();
+                     i != opts.options.end(); i++)
+                    if (!i->unregistered)
+                        filtopts.options.push_back (*i);
+                po::store(filtopts, vm);
+            }
+            else
+                po::store(po::parse_command_line(argc, argv, *this), vm);
+        }
         parsing="environment variables";
         po::store(po::parse_environment(*this, EnvOptMapper(*this)), vm);
         po::notify(vm); // configFile may be updated from arg/env options.
         if (!configFile.empty()) {
             parsing="configuration file "+configFile;
             ifstream conf(configFile.c_str());
-            if (conf.good())
-                po::store(po::parse_config_file(conf, *this), vm);
+            if (conf.good()) {
+                // Remove this hack when we get a stable version of boost that
+                // can allow unregistered options in config files.
+                EnvOptMapper mapper(*this);
+                stringstream filtered;
+
+                while (!conf.eof()) {
+                    string line;
+                    getline (conf, line);
+                    filtered << mapper.configFileLine (line);
+                }
+
+                po::store(po::parse_config_file(filtered, *this), vm);
+                // End of hack
+            }
             else {
                 // No error if default configfile is missing/unreadable
                 // but complain for non-default config file.

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/Options.h
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/Options.h?rev=611823&r1=611822&r2=611823&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/Options.h (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/Options.h Mon Jan 14 06:55:46 2008
@@ -130,7 +130,8 @@
      * is updated by argc/argv or environment variable parsing.
      */
     void parse(int argc, char** argv,
-               const std::string& configfile=std::string());
+               const std::string& configfile=std::string(),
+               bool  allowUnknown = false);
 };
 
 /**

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/Plugin.h
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/Plugin.h?rev=611823&r1=611822&r2=611823&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/Plugin.h (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/Plugin.h Mon Jan 14 06:55:46 2008
@@ -73,6 +73,13 @@
      * 
      * Plugins should ignore targets they don't recognize.
      */
+    virtual void earlyInitialize(Target&) = 0;
+
+    /**
+     * Initialize Plugin functionality on a Target.
+     * 
+     * Plugins should ignore targets they don't recognize.
+     */
     virtual void initialize(Target&) = 0;
 
     /** List of registered Plugin objects.

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/broker/Broker.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/broker/Broker.cpp?rev=611823&r1=611822&r2=611823&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/broker/Broker.cpp (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/broker/Broker.cpp Mon Jan 14 06:55:46 2008
@@ -67,13 +67,7 @@
     workerThreads(5),
     maxConnections(500),
     connectionBacklog(10),
-    store(),
     stagingThreshold(5000000),
-    storeDir("/var"),
-    storeAsync(false),
-    storeForce(false),
-    numJrnlFiles(8),
-    jrnlFsizePgs(24),
     enableMgmt(0),
     mgmtPubInterval(10),
     ack(0)
@@ -91,20 +85,6 @@
          "Sets the connection backlog limit for the server socket")
         ("staging-threshold", optValue(stagingThreshold, "N"),
          "Stages messages over N bytes to disk")
-// TODO: These options need to come from within the store module
-        ("store-lib,s", optValue(store,"LIBNAME"),
-         "Tells the broker to use the message store shared library LIBNAME for persistence")
-        ("store-directory", optValue(storeDir,"DIR"),
-         "Store directory location for persistence.")
-        ("store-async", optValue(storeAsync,"yes|no"),
-         "Use async persistence storage - if store supports it, enables AIO O_DIRECT.")
-        ("store-force", optValue(storeForce,"yes|no"),
-         "Force changing modes of store, will delete all existing data if mode is changed.
Be SURE you want to do this!")
-        ("num-jfiles", qpid::optValue(numJrnlFiles, "N"),
-         "Number of files in persistence journal")
-        ("jfile-size-pgs", qpid::optValue(jrnlFsizePgs, "N"),
-         "Size of each journal file in multiples of read pages (1 read page = 64kiB)")
-// End of store module options
         ("mgmt,m", optValue(enableMgmt,"yes|no"),
          "Enable Management")
         ("mgmt-pub-interval", optValue(mgmtPubInterval, "SECONDS"),
@@ -122,29 +102,36 @@
 
 Broker::Broker(const Broker::Options& conf) :
     config(conf),
-    store(createStore(conf)),
-    queues(store.get()),
+    store(0),
     factory(*this),
-    dtxManager(store.get()),
     sessionManager(conf.ack)
 {
+    // Early-Initialize plugins
+    const Plugin::Plugins& plugins=Plugin::getPlugins();
+    for (Plugin::Plugins::const_iterator i = plugins.begin();
+         i != plugins.end();
+         i++)
+        (*i)->earlyInitialize(*this);
+
+    // If no plugin store module registered itself, set up the null store.
+    if (store == 0)
+        setStore (new NullMessageStore (false));
+
+    queues.setStore     (store);
+    dtxManager.setStore (store);
+
     if(conf.enableMgmt){
         ManagementAgent::enableManagement ();
         managementAgent = ManagementAgent::getAgent ();
         managementAgent->setInterval (conf.mgmtPubInterval);
 
         mgmtObject = management::Broker::shared_ptr (new management::Broker (this, 0, 0,
conf.port));
-        mgmtObject->set_workerThreads        (conf.workerThreads);
-        mgmtObject->set_maxConns             (conf.maxConnections);
-        mgmtObject->set_connBacklog          (conf.connectionBacklog);
-        mgmtObject->set_stagingThreshold     (conf.stagingThreshold);
-        mgmtObject->set_storeLib             (conf.store);
-        mgmtObject->set_asyncStore           (conf.storeAsync);
-        mgmtObject->set_mgmtPubInterval      (conf.mgmtPubInterval);
-        mgmtObject->set_initialDiskPageSize  (0);
-        mgmtObject->set_initialPagesPerQueue (0);
-        mgmtObject->set_clusterName          ("");
-        mgmtObject->set_version              (PACKAGE_VERSION);
+        mgmtObject->set_workerThreads    (conf.workerThreads);
+        mgmtObject->set_maxConns         (conf.maxConnections);
+        mgmtObject->set_connBacklog      (conf.connectionBacklog);
+        mgmtObject->set_stagingThreshold (conf.stagingThreshold);
+        mgmtObject->set_mgmtPubInterval  (conf.mgmtPubInterval);
+        mgmtObject->set_version          (PACKAGE_VERSION);
         
         managementAgent->addObject (mgmtObject, 1, 0);
 
@@ -160,16 +147,12 @@
 
     exchanges.declare(empty, DirectExchange::typeName); // Default exchange.
     
-    if(store.get()) {
-        if (!store->init(&conf)){
-              throw Exception( "Existing Journal in different mode, backup/move existing
data \
-			  before changing modes. Or use --store-force yes to blow existing data away.");
-		}else{
-             RecoveryManagerImpl recoverer(queues, exchanges, dtxManager, 
+    if (store != 0) {
+        RecoveryManagerImpl recoverer(queues, exchanges, dtxManager, 
                                       conf.stagingThreshold);
-             store->recover(recoverer);
-        }
+        store->recover(recoverer);
     }
+
     //ensure standard exchanges exist (done after recovery from store)
     declareStandardExchange(amq_direct, DirectExchange::typeName);
     declareStandardExchange(amq_topic, TopicExchange::typeName);
@@ -188,7 +171,6 @@
         QPID_LOG(info, "Management not enabled");
 
     // Initialize plugins
-    const Plugin::Plugins& plugins=Plugin::getPlugins();
     for (Plugin::Plugins::const_iterator i = plugins.begin();
          i != plugins.end();
          i++)
@@ -197,7 +179,7 @@
 
 void Broker::declareStandardExchange(const std::string& name, const std::string&
type)
 {
-    bool storeEnabled = store.get();
+    bool storeEnabled = store != NULL;
     std::pair<Exchange::shared_ptr, bool> status = exchanges.declare(name, type, storeEnabled);
     if (status.second && storeEnabled) {
         store->create(*status.first);
@@ -217,13 +199,13 @@
     return shared_ptr<Broker>(new Broker(opts));
 }
 
-MessageStore* Broker::createStore(const Options& config) {
-    if (config.store.empty())
-        return new NullMessageStore(false);
-    else
-        return new MessageStoreModule(config.store);
+void Broker::setStore (MessageStore* _store)
+{
+    assert (store == 0 && _store != 0);
+    if (store == 0 && _store != 0)
+        store = new MessageStoreModule (_store);
 }
-        
+
 void Broker::run() {
     getAcceptor().run(&factory);
 }
@@ -236,6 +218,7 @@
 
 Broker::~Broker() {
     shutdown();
+    delete store;    
 }
 
 uint16_t Broker::getPort() const  { return getAcceptor().getPort(); }

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/broker/DtxManager.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/broker/DtxManager.cpp?rev=611823&r1=611822&r2=611823&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/broker/DtxManager.cpp (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/broker/DtxManager.cpp Mon Jan 14 06:55:46 2008
@@ -32,7 +32,7 @@
 using namespace qpid::broker;
 using namespace qpid::framing;
 
-DtxManager::DtxManager(TransactionalStore* const _store) : store(_store) {}
+DtxManager::DtxManager() : store(0) {}
 
 DtxManager::~DtxManager() {}
 
@@ -159,4 +159,10 @@
     } catch (ConnectionException& e) {
         //assume it was explicitly cleaned up after a call to prepare, commit or rollback
     }
+}
+
+void DtxManager::setStore (TransactionalStore* _store)
+{
+    assert (store == 0 && _store != 0);
+    store = _store;
 }

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/broker/DtxManager.h
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/broker/DtxManager.h?rev=611823&r1=611822&r2=611823&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/broker/DtxManager.h (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/broker/DtxManager.h Mon Jan 14 06:55:46 2008
@@ -45,7 +45,7 @@
     };
 
     WorkMap work;
-    TransactionalStore* const store;
+    TransactionalStore* store;
     qpid::sys::Mutex lock;
     Timer timer;
 
@@ -54,7 +54,7 @@
     DtxWorkRecord* createWork(std::string xid);
 
 public:
-    DtxManager(TransactionalStore* const store);
+    DtxManager();
     ~DtxManager();
     void start(const std::string& xid, DtxBuffer::shared_ptr work);
     void join(const std::string& xid, DtxBuffer::shared_ptr work);
@@ -65,6 +65,7 @@
     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);
 };
 
 }

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/broker/MessageStoreModule.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/broker/MessageStoreModule.cpp?rev=611823&r1=611822&r2=611823&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/broker/MessageStoreModule.cpp (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/broker/MessageStoreModule.cpp Mon Jan 14 06:55:46
2008
@@ -27,14 +27,14 @@
 
 using namespace qpid::broker;
 
-MessageStoreModule::MessageStoreModule(const std::string& name) : store(name)
-{
-}
+MessageStoreModule::MessageStoreModule(MessageStore* _store) : store(_store) {}
 
-bool MessageStoreModule::init(const Options* options)
+MessageStoreModule::~MessageStoreModule()
 {
-	TRANSFER_EXCEPTION(return store->init(options));
+    delete store;
 }
+
+bool MessageStoreModule::init(const Options*) { return true; }
 
 void MessageStoreModule::create(PersistableQueue& queue)
 {

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/broker/MessageStoreModule.h
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/broker/MessageStoreModule.h?rev=611823&r1=611822&r2=611823&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/broker/MessageStoreModule.h (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/broker/MessageStoreModule.h Mon Jan 14 06:55:46
2008
@@ -34,9 +34,9 @@
  */
 class MessageStoreModule : public MessageStore
 {
-    qpid::sys::Module<MessageStore> store;
+    MessageStore* store;
 public:
-    MessageStoreModule(const std::string& name);
+    MessageStoreModule(MessageStore* store);
 
 	bool init(const Options* options);
     std::auto_ptr<TransactionContext> begin();
@@ -69,7 +69,7 @@
     u_int32_t outstandingQueueAIO(const PersistableQueue& queue);
     void flush(const qpid::broker::PersistableQueue& queue);
 	 
-    ~MessageStoreModule(){}
+    ~MessageStoreModule();
 };
 
 }

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/broker/QueueRegistry.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/broker/QueueRegistry.cpp?rev=611823&r1=611822&r2=611823&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/broker/QueueRegistry.cpp (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/broker/QueueRegistry.cpp Mon Jan 14 06:55:46 2008
@@ -26,8 +26,8 @@
 using namespace qpid::broker;
 using namespace qpid::sys;
 
-QueueRegistry::QueueRegistry(MessageStore* const _store) :
-    counter(1), store(_store), parent(0) {}
+QueueRegistry::QueueRegistry() :
+    counter(1), store(0), parent(0) {}
 
 QueueRegistry::~QueueRegistry(){}
 
@@ -82,6 +82,12 @@
     return name;
 }
 
-MessageStore* const QueueRegistry::getStore() const {
+void QueueRegistry::setStore (MessageStore* _store)
+{
+    assert (store == 0 && _store != 0);
+    store = _store;
+}
+
+MessageStore* QueueRegistry::getStore() const {
     return store;
 }

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/broker/QueueRegistry.h
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/broker/QueueRegistry.h?rev=611823&r1=611822&r2=611823&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/broker/QueueRegistry.h (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/broker/QueueRegistry.h Mon Jan 14 06:55:46 2008
@@ -38,7 +38,7 @@
  */
 class QueueRegistry{
   public:
-    QueueRegistry(MessageStore* const store = 0);
+    QueueRegistry();
     ~QueueRegistry();
 
     /**
@@ -86,9 +86,14 @@
     string generateName();
 
     /**
+     * Set the store to use.  May only be called once.
+     */
+    void setStore (MessageStore*);
+
+    /**
      * Return the message store used.
      */
-    MessageStore* const getStore() const;
+    MessageStore* getStore() const;
 
     /**
      * Register the manageable parent for declared queues
@@ -100,7 +105,7 @@
     QueueMap queues;
     qpid::sys::RWlock lock;
     int counter;
-    MessageStore* const store;
+    MessageStore* store;
     management::Manageable* parent;
 };
 

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/cluster/ClusterPlugin.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/cluster/ClusterPlugin.cpp?rev=611823&r1=611822&r2=611823&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/cluster/ClusterPlugin.cpp (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/cluster/ClusterPlugin.cpp Mon Jan 14 06:55:46 2008
@@ -47,6 +47,8 @@
 
     Options* getOptions() { return &options; }
 
+    void earlyInitialize(Plugin::Target&) {}
+
     void initialize(Plugin::Target& target) {
         broker::Broker* broker = dynamic_cast<broker::Broker*>(&target);
         // Only provide to a Broker, and only if the --cluster config is set.

Modified: incubator/qpid/trunk/qpid/cpp/src/qpidd.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpidd.cpp?rev=611823&r1=611822&r2=611823&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpidd.cpp (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpidd.cpp Mon Jan 14 06:55:46 2008
@@ -27,6 +27,7 @@
 #include "qpid/Plugin.h"
 #include "qpid/sys/Shlib.h"
 #include "config.h"
+#include <boost/filesystem/operations.hpp>
 #include <boost/filesystem/path.hpp>
 #include <iostream>
 #include <fstream>
@@ -36,7 +37,23 @@
 using namespace qpid;
 using namespace qpid::broker;
 using namespace qpid::sys;
+using namespace qpid::log;
 using namespace std;
+namespace fs=boost::filesystem;
+
+struct ModuleOptions : public qpid::Options {
+    string         loadDir;
+    vector<string> load;
+    bool           noLoad;
+    ModuleOptions() : qpid::Options("Module options"), loadDir("/usr/lib/qpidd"), noLoad(false)
+    {
+        addOptions()
+            ("load-dir",   optValue(loadDir, "DIR"),  "Load all modules from this directory")
+            ("load",       optValue(load,    "FILE"), "Specifies additional module(s) to
be loaded")
+            ("no-modules", optValue(noLoad),          "Don't load any modules");
+    }
+};
+
 
 struct DaemonOptions : public qpid::Options {
     bool daemon;
@@ -57,12 +74,14 @@
 
 struct QpiddOptions : public qpid::Options {
     CommonOptions common;
+    ModuleOptions module;
     Broker::Options broker;
     DaemonOptions daemon;
     qpid::log::Options log;
     
     QpiddOptions() : qpid::Options("Options"), common("", "/etc/qpidd.conf") {
         add(common);
+        add(module);
         add(broker);
         add(daemon);
         add(log);
@@ -79,6 +98,23 @@
     };
 };
 
+// BootstrapOptions is a minimal subset of options used for a pre-parse
+// of the command line to discover which plugin modules need to be loaded.
+// The pre-parse is necessary because plugin modules may supply their own
+// set of options.  CommonOptions is needed to properly support loading
+// from a configuration file.
+struct BootstrapOptions : public qpid::Options {
+    CommonOptions common;
+    ModuleOptions module;
+    qpid::log::Options log;
+
+    BootstrapOptions() : qpid::Options("Options"), common("", "/etc/qpidd.conf") {
+        add(common);
+        add(module);
+        add(log);
+    }
+};
+
 // Globals
 shared_ptr<Broker> brokerPtr;
 auto_ptr<QpiddOptions> options;
@@ -108,24 +144,59 @@
 void tryShlib(const char* libname) {
     try {
         Shlib shlib(libname);
+        QPID_LOG (info, "Loaded Module: " << libname);
+    }
+    catch (const exception& e) {}
+}
+
+void loadModuleDir (string dirname, bool isDefault)
+{
+    fs::path dirPath (dirname);
+
+    if (!fs::exists (dirPath))
+    {
+        if (isDefault)
+            return;
+        throw Exception ("Directory not found: " + dirname);
     }
-    catch (const exception& e) {
-        // TODO aconway 2007-07-09: Should log failures as INFO
-        // at least, but we try shlibs before logging is configured.
+
+    fs::directory_iterator endItr;
+    for (fs::directory_iterator itr (dirPath); itr != endItr; ++itr)
+    {
+        if (!fs::is_directory(*itr) &&
+            itr->string().find (".so") == itr->string().length() - 3)
+            tryShlib (itr->string().data());
     }
 }
   
 
 int main(int argc, char* argv[])
 {
-    try {
-        // Load optional modules
-        tryShlib("libqpidcluster.so.0");
+    try
+    {
+        {
+            BootstrapOptions bootOptions;
+            string           defaultPath (bootOptions.module.loadDir);
+
+            // Parse only the common, load, and log options to see which modules need
+            // to be loaded.  Once the modules are loaded, the command line will
+            // be re-parsed with all of the module-supplied options.
+            bootOptions.parse (argc, argv, bootOptions.common.config, true);
+            qpid::log::Logger::instance().configure(bootOptions.log, argv[0]);
+            if (!bootOptions.module.noLoad) {
+                for (vector<string>::iterator iter = bootOptions.module.load.begin();
+                     iter != bootOptions.module.load.end();
+                     iter++)
+                    tryShlib (iter->data());
+
+                bool isDefault = defaultPath == bootOptions.module.loadDir;
+                loadModuleDir (bootOptions.module.loadDir, isDefault);
+            }
+        }
 
         // Parse options
         options.reset(new QpiddOptions());
         options->parse(argc, argv, options->common.config);
-        qpid::log::Logger::instance().configure(options->log, argv[0]);
 
         // Options that just print information.
         if(options->common.help || options->common.version) {



Mime
View raw message