diff options
author | Alan Conway <aconway@apache.org> | 2007-04-26 16:01:04 +0000 |
---|---|---|
committer | Alan Conway <aconway@apache.org> | 2007-04-26 16:01:04 +0000 |
commit | 0a90e5db613b035e15af3b7358205ed1f7960d2c (patch) | |
tree | c4b1ec81e60a3b93e414ddf725985d1a9ff5d291 | |
parent | 4473eb5d9e9da37e515be063952d284034adbec3 (diff) | |
download | qpid-python-0a90e5db613b035e15af3b7358205ed1f7960d2c.tar.gz |
Merged revisions 532430 by hand from
https://svn.apache.org/repos/asf/incubator/qpid/branches/trunk/qpid/cpp
------------------------------------------------------------------------
r532430 | aconway | 2007-04-25 14:06:14 -0400 (Wed, 25 Apr 2007) | 10 lines
* qpid/CommonOptions.h:
- Convenience classs/functions to use boost::program_options.
- CommonOptions class for options common to client/broker.
* qpid/broker/Broker.h:
- Replaced broker::Configuration with class Broker::Options,
derived from CommonOptions.
* qpidd.cpp: Updated options handling.
* qpid/Exception.h: Added strError function to get std::string from errno.
------------------------------------------------------------------------
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/branches/M2@532787 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | cpp/lib/CommonOptions.cpp | 36 | ||||
-rw-r--r-- | cpp/lib/CommonOptions.h | 91 | ||||
-rw-r--r-- | cpp/lib/broker/Broker.cpp | 51 | ||||
-rw-r--r-- | cpp/lib/broker/Broker.h | 19 | ||||
-rw-r--r-- | cpp/lib/broker/Configuration.cpp | 252 | ||||
-rw-r--r-- | cpp/lib/broker/Configuration.h | 170 | ||||
-rw-r--r-- | cpp/lib/broker/Makefile.am | 2 | ||||
-rw-r--r-- | cpp/lib/common/CommonOptions.cpp | 36 | ||||
-rw-r--r-- | cpp/lib/common/CommonOptions.h | 91 | ||||
-rw-r--r-- | cpp/lib/common/Exception.cpp | 8 | ||||
-rw-r--r-- | cpp/lib/common/Exception.h | 4 | ||||
-rw-r--r-- | cpp/lib/common/Makefile.am | 17 | ||||
-rw-r--r-- | cpp/src/Makefile.am | 18 | ||||
-rw-r--r-- | cpp/src/qpidd.cpp | 100 | ||||
-rw-r--r-- | cpp/tests/ConfigurationTest.cpp | 98 | ||||
-rw-r--r-- | cpp/tests/Makefile.am | 5 |
16 files changed, 405 insertions, 593 deletions
diff --git a/cpp/lib/CommonOptions.cpp b/cpp/lib/CommonOptions.cpp new file mode 100644 index 0000000000..8efb3a6baa --- /dev/null +++ b/cpp/lib/CommonOptions.cpp @@ -0,0 +1,36 @@ +/* + * + * 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 "CommonOptions.h" + +namespace qpid { + +const int CommonOptions::DEFAULT_PORT=5672; + +CommonOptions::CommonOptions() : trace(false), port(DEFAULT_PORT) {} + +void CommonOptions::addTo(po::options_description& desc) +{ + using namespace po; + desc.add_options() + ("trace,t", optValue(trace), "Enable debug tracing" ) + ("port,p", optValue(port,"PORT"), "Use PORT for AMQP connections."); +} + +} // namespace qpid + diff --git a/cpp/lib/CommonOptions.h b/cpp/lib/CommonOptions.h new file mode 100644 index 0000000000..2a4b9798cd --- /dev/null +++ b/cpp/lib/CommonOptions.h @@ -0,0 +1,91 @@ +#ifndef QPID_COMMONOPTIONS_H +#define QPID_COMMONOPTIONS_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/program_options.hpp> +#include <boost/format.hpp> + +namespace qpid { + +/**@Qpid extensions to boost::program_options */ +namespace program_options { + +using namespace boost::program_options; + +/** @internal Normally only constructed by optValue() */ +template <class T> +class OptionValue : public typed_value<T> { + public: + OptionValue(T& value, const std::string& arg) + : typed_value<T>(&value), argName(arg) {} + std::string name() const { return argName; } + private: + std::string argName; +}; + +/** + * Like boost::program_options::value() with more convenient signature + * for updating a value by reference and nicer help formatting. + * + *@param value displayed as default in help, updated from options. + * Must support ostream << operator. + *@param arg name for arguments in help. + * + *@see CommonOptions.cpp for example of use. + */ +template<class T> +value_semantic* optValue(T& value, const char* arg) { + std::string val(boost::lexical_cast<std::string>(value)); + std::string argName( + val.empty() ? std::string(arg) : + (boost::format("%s (=%s) ") % arg % val).str()); + return new OptionValue<T>(value, argName); +} + +/** + * Like boost::program_options::bool_switch but takes reference, not pointer. + */ +inline value_semantic* optValue(bool& value) { return bool_switch(&value); } + +} // namespace program_options + +namespace po=program_options; // Convenience alias. + +/** + * Common options for client and broker + */ +struct CommonOptions { + static const int DEFAULT_PORT; + + CommonOptions(); + + bool trace; + int port; + + /** Add members to program_options to be updated */ + void addTo(po::options_description&); +}; + +} // namespace qpid + +#endif /*!QPID_COMMONOPTIONS_H*/ diff --git a/cpp/lib/broker/Broker.cpp b/cpp/lib/broker/Broker.cpp index 6c0d7a3f3f..806127bf43 100644 --- a/cpp/lib/broker/Broker.cpp +++ b/cpp/lib/broker/Broker.cpp @@ -22,38 +22,63 @@ #include <memory> #include <Broker.h> - using namespace qpid::broker; using namespace qpid::sys; -Broker::Broker(const Configuration& config) : - acceptor(Acceptor::create(config.getPort(), - config.getConnectionBacklog(), - config.getWorkerThreads(), - config.isTrace())), - factory(config.getStore()) +Broker::Options::Options() : + workerThreads(5), + maxConnections(500), + connectionBacklog(10), + store(), + stagingThreshold(5000000) +{} + +void Broker::Options::addTo(po::options_description& desc) +{ + using namespace po; + CommonOptions::addTo(desc); + desc.add_options() + ("worker-threads", optValue(workerThreads, "N"), + "Broker thread pool size") + ("max-connections", optValue(maxConnections, "N"), + "Maximum allowed connections") + ("connection-backlog", optValue(connectionBacklog, "N"), + "Connection backlog limit for server socket.") + ("staging-threshold", optValue(stagingThreshold, "N"), + "Messages over N bytes are staged to disk.") + ("store", optValue(store,"LIBNAME"), + "Name of message store shared library."); +} + + +Broker::Broker(const Options& config) : + acceptor(Acceptor::create(config.port, + config.connectionBacklog, + config.workerThreads, + config.trace)), + factory(config.store) { } Broker::shared_ptr Broker::create(int16_t port) { - Configuration config; - config.setPort(port); + Options config; + config.port=port; return create(config); } -Broker::shared_ptr Broker::create(const Configuration& config) { +Broker::shared_ptr Broker::create(const Options& config) { return Broker::shared_ptr(new Broker(config)); } - + void Broker::run() { acceptor->run(&factory); } void Broker::shutdown() { - acceptor->shutdown(); + if (acceptor) + acceptor->shutdown(); } Broker::~Broker() { } -const int16_t Broker::DEFAULT_PORT(5672); diff --git a/cpp/lib/broker/Broker.h b/cpp/lib/broker/Broker.h index 8ea1a57c27..8b54bd592b 100644 --- a/cpp/lib/broker/Broker.h +++ b/cpp/lib/broker/Broker.h @@ -22,7 +22,7 @@ * */ -#include <Configuration.h> +#include <CommonOptions.h> #include <SessionHandlerFactoryImpl.h> #include <sys/Runnable.h> #include <sys/Acceptor.h> @@ -37,7 +37,15 @@ class Broker : public qpid::sys::Runnable, public qpid::SharedObject<Broker> { public: - static const int16_t DEFAULT_PORT; + struct Options : public CommonOptions { + Options(); + void addTo(po::options_description&); + int workerThreads; + int maxConnections; + int connectionBacklog; + std::string store; + long stagingThreshold; + }; virtual ~Broker(); @@ -45,12 +53,12 @@ class Broker : public qpid::sys::Runnable, * Create a broker. * @param port Port to listen on or 0 to pick a port dynamically. */ - static shared_ptr create(int16_t port = DEFAULT_PORT); + static shared_ptr create(int16_t port = Options::DEFAULT_PORT); /** * Create a broker using a Configuration. */ - static shared_ptr create(const Configuration& config); + static shared_ptr create(const Options& config); /** * Return listening port. If called before bind this is @@ -70,7 +78,8 @@ class Broker : public qpid::sys::Runnable, virtual void shutdown(); private: - Broker(const Configuration& config); + Broker(const Options& config); + Options config; qpid::sys::Acceptor::shared_ptr acceptor; SessionHandlerFactoryImpl factory; }; diff --git a/cpp/lib/broker/Configuration.cpp b/cpp/lib/broker/Configuration.cpp deleted file mode 100644 index e83c359f2d..0000000000 --- a/cpp/lib/broker/Configuration.cpp +++ /dev/null @@ -1,252 +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 <Configuration.h> -#include <string.h> -#include <config.h> - -using namespace qpid::broker; -using namespace std; - -Configuration::Configuration() : - daemon('d', "daemon", "Run as system daemon, detached from terminal.", false), - trace('t', "trace", "Print incoming & outgoing frames to the console", false), - port('p', "port", "Set the port to listen on (default=5672)", 5672), - workerThreads("worker-threads", "Set the number of worker threads to use (default=5).", 5), - maxConnections("max-connections", "Set the maximum number of connections the broker can accept (default=500).", 500), - connectionBacklog("connection-backlog", "Set the connection backlog for the servers socket (default=10)", 10), - store('s', "store", "Set the message store module to use (default='' which implies no store)", ""), - stagingThreshold("staging-threshold", "Set the message size threshold above which messages will be written to disk as they arrive (default=5,000,000)", 5000000), - help("help", "Print usage information", false), - version("version", "Print version information", false) -{ - options.push_back(&daemon); - options.push_back(&trace); - options.push_back(&port); - options.push_back(&workerThreads); - options.push_back(&maxConnections); - options.push_back(&connectionBacklog); - options.push_back(&store); - options.push_back(&stagingThreshold); - options.push_back(&help); - options.push_back(&version); -} - -Configuration::~Configuration(){} - -void Configuration::parse(char const *progName, int argc, char** argv){ - programName = progName; - int position = 1; - while(position < argc){ - bool matched(false); - for(op_iterator i = options.begin(); i < options.end() && !matched; i++){ - matched = (*i)->parse(position, argv, argc); - } - if(!matched) { - throw BadOptionException( - std::string("Unrecognised option: ")+argv[position]); - } - } -} - -void Configuration::usage(){ - std::cout << "Usage: " << programName << " [OPTION]..." << std::endl - << "Start the Qpid AMQP broker daemon." << std::endl << std::endl - << "Options:" << std::endl; - for(op_iterator i = options.begin(); i < options.end(); i++){ - (*i)->print(std::cout); - } - - std::cout << std::endl << "Report bugs to <" << PACKAGE_BUGREPORT << ">." - << std::endl; -} - -bool Configuration::isHelp() const { - return help.getValue(); -} - -bool Configuration::isVersion() const { - return version.getValue(); -} - -bool Configuration::isDaemon() const { - return daemon.getValue(); -} - -bool Configuration::isTrace() const { - return trace.getValue(); -} - -int Configuration::getPort() const { - return port.getValue(); -} - -int Configuration::getWorkerThreads() const { - return workerThreads.getValue(); -} - -int Configuration::getMaxConnections() const { - return maxConnections.getValue(); -} - -int Configuration::getConnectionBacklog() const { - return connectionBacklog.getValue(); -} - -const std::string& Configuration::getStore() const { - return store.getValue(); -} - -long Configuration::getStagingThreshold() const { - return stagingThreshold.getValue(); -} - - -Configuration::Option::Option(const char _flag, const string& _name, const string& _desc) : - flag(string("-") + _flag), name("--" +_name), desc(_desc) {} - -Configuration::Option::Option(const string& _name, const string& _desc) : - flag(""), name("--" + _name), desc(_desc) {} - -Configuration::Option::~Option(){} - -bool Configuration::Option::match(const string& arg){ - return flag == arg || name == arg; -} - -bool Configuration::Option::parse(int& i, char** argv, int argc){ - const string arg(argv[i]); - if(match(arg)){ - if(needsValue()){ - if(++i < argc) setValue(argv[i]); - else throw ParseException("Argument " + arg + " requires a value!"); - }else{ - setValue(""); - } - i++; - return true; - }else{ - return false; - } -} - -void Configuration::Option::print(ostream& out) const { - out << " "; - if(flag.length() > 0){ - out << flag << ", "; - } else { - out << " "; - } - out << name; - if(needsValue()) out << " <value>"; - out << std::endl; - out << " " << desc << std::endl; -} - - -// String Option: - -Configuration::StringOption::StringOption(const char _flag, const string& _name, const string& _desc, const string _value) : - Option(_flag,_name,_desc), defaultValue(_value), value(_value) {} - -Configuration::StringOption::StringOption(const string& _name, const string& _desc, const string _value) : - Option(_name,_desc), defaultValue(_value), value(_value) {} - -Configuration::StringOption::~StringOption(){} - -const string& Configuration::StringOption::getValue() const { - return value; -} - -bool Configuration::StringOption::needsValue() const { - return true; -} - -void Configuration::StringOption::setValue(const std::string& _value){ - value = _value; -} - -// Int Option: - -Configuration::IntOption::IntOption(const char _flag, const string& _name, const string& _desc, const int _value) : - Option(_flag,_name,_desc), defaultValue(_value), value(_value) {} - -Configuration::IntOption::IntOption(const string& _name, const string& _desc, const int _value) : - Option(_name,_desc), defaultValue(_value), value(_value) {} - -Configuration::IntOption::~IntOption(){} - -int Configuration::IntOption::getValue() const { - return value; -} - -bool Configuration::IntOption::needsValue() const { - return true; -} - -void Configuration::IntOption::setValue(const std::string& _value){ - value = atoi(_value.c_str()); -} - -// Long Option: - -Configuration::LongOption::LongOption(const char _flag, const string& _name, const string& _desc, const long _value) : - Option(_flag,_name,_desc), defaultValue(_value), value(_value) {} - -Configuration::LongOption::LongOption(const string& _name, const string& _desc, const long _value) : - Option(_name,_desc), defaultValue(_value), value(_value) {} - -Configuration::LongOption::~LongOption(){} - -long Configuration::LongOption::getValue() const { - return value; -} - -bool Configuration::LongOption::needsValue() const { - return true; -} - -void Configuration::LongOption::setValue(const std::string& _value){ - value = atol(_value.c_str()); -} - -// Bool Option: - -Configuration::BoolOption::BoolOption(const char _flag, const string& _name, const string& _desc, const bool _value) : - Option(_flag,_name,_desc), defaultValue(_value), value(_value) {} - -Configuration::BoolOption::BoolOption(const string& _name, const string& _desc, const bool _value) : - Option(_name,_desc), defaultValue(_value), value(_value) {} - -Configuration::BoolOption::~BoolOption(){} - -bool Configuration::BoolOption::getValue() const { - return value; -} - -bool Configuration::BoolOption::needsValue() const { - return false; -} - -void Configuration::BoolOption::setValue(const std::string& /*not required*/){ - //BoolOptions have no value. The fact that the option is specified - //implies the value is true. - value = true; -} diff --git a/cpp/lib/broker/Configuration.h b/cpp/lib/broker/Configuration.h deleted file mode 100644 index 15f2117f5e..0000000000 --- a/cpp/lib/broker/Configuration.h +++ /dev/null @@ -1,170 +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 _Configuration_ -#define _Configuration_ - -#include <cstdlib> -#include <iostream> -#include <vector> -#include <Exception.h> - -namespace qpid { -namespace broker { -class Configuration{ - - class Option { - const std::string flag; - const std::string name; - const std::string desc; - - bool match(const std::string& arg); - - protected: - virtual bool needsValue() const = 0; - virtual void setValue(const std::string& value) = 0; - - public: - Option(const char flag, const std::string& name, const std::string& desc); - Option(const std::string& name, const std::string& desc); - virtual ~Option(); - - bool parse(int& i, char** argv, int argc); - void print(std::ostream& out) const; - }; - - class IntOption : public Option{ - const int defaultValue; - int value; - public: - IntOption(char flag, const std::string& name, const std::string& desc, const int value = 0); - IntOption(const std::string& name, const std::string& desc, const int value = 0); - virtual ~IntOption(); - - int getValue() const; - virtual bool needsValue() const; - virtual void setValue(const std::string& value); - virtual void setValue(int _value) { value = _value; } - }; - - class LongOption : public Option{ - const long defaultValue; - int value; - public: - LongOption(char flag, const std::string& name, const std::string& desc, const long value = 0); - LongOption(const std::string& name, const std::string& desc, const long value = 0); - virtual ~LongOption(); - - long getValue() const; - virtual bool needsValue() const; - virtual void setValue(const std::string& value); - virtual void setValue(int _value) { value = _value; } - }; - - class StringOption : public Option{ - const std::string defaultValue; - std::string value; - public: - StringOption(char flag, const std::string& name, const std::string& desc, const std::string value = ""); - StringOption(const std::string& name, const std::string& desc, const std::string value = ""); - virtual ~StringOption(); - - const std::string& getValue() const; - virtual bool needsValue() const; - virtual void setValue(const std::string& value); - }; - - class BoolOption : public Option{ - const bool defaultValue; - bool value; - public: - BoolOption(char flag, const std::string& name, const std::string& desc, const bool value = 0); - BoolOption(const std::string& name, const std::string& desc, const bool value = 0); - virtual ~BoolOption(); - - bool getValue() const; - virtual bool needsValue() const; - virtual void setValue(const std::string& value); - virtual void setValue(bool _value) { value = _value; } - }; - - BoolOption daemon; - BoolOption trace; - IntOption port; - IntOption workerThreads; - IntOption maxConnections; - IntOption connectionBacklog; - StringOption store; - LongOption stagingThreshold; - BoolOption help; - BoolOption version; - char const *programName; - - typedef std::vector<Option*>::iterator op_iterator; - std::vector<Option*> options; - - public: - - struct BadOptionException : public qpid::Exception { - BadOptionException(const std::string& msg) - : qpid::Exception(msg) {} - }; - - - class ParseException : public Exception { - public: - ParseException(const std::string& msg) : Exception(msg) {} - }; - - - Configuration(); - ~Configuration(); - - void parse(char const*, int argc, char** argv); - - bool isHelp() const; - bool isVersion() const; - bool isDaemon() const; - bool isTrace() const; - int getPort() const; - int getWorkerThreads() const; - int getMaxConnections() const; - int getConnectionBacklog() const; - const std::string& getStore() const; - long getStagingThreshold() const; - - void setHelp(bool b) { help.setValue(b); } - void setVersion(bool b) { version.setValue(b); } - void setDaemon(bool b) { daemon.setValue(b); } - void setTrace(bool b) { trace.setValue(b); } - void setPort(int i) { port.setValue(i); } - void setWorkerThreads(int i) { workerThreads.setValue(i); } - void setMaxConnections(int i) { maxConnections.setValue(i); } - void setConnectionBacklog(int i) { connectionBacklog.setValue(i); } - void setStore(const std::string& s) { store.setValue(s); } - void setStagingThreshold(long l) { stagingThreshold.setValue(l); } - - void usage(); -}; -} -} - - -#endif diff --git a/cpp/lib/broker/Makefile.am b/cpp/lib/broker/Makefile.am index b093d13ea9..dfc0315902 100644 --- a/cpp/lib/broker/Makefile.am +++ b/cpp/lib/broker/Makefile.am @@ -24,8 +24,6 @@ libqpidbroker_la_SOURCES = \ BrokerMessage.h \ BrokerQueue.cpp \ BrokerQueue.h \ - Configuration.cpp \ - Configuration.h \ ConnectionToken.h \ Consumer.h \ Content.h \ diff --git a/cpp/lib/common/CommonOptions.cpp b/cpp/lib/common/CommonOptions.cpp new file mode 100644 index 0000000000..8efb3a6baa --- /dev/null +++ b/cpp/lib/common/CommonOptions.cpp @@ -0,0 +1,36 @@ +/* + * + * 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 "CommonOptions.h" + +namespace qpid { + +const int CommonOptions::DEFAULT_PORT=5672; + +CommonOptions::CommonOptions() : trace(false), port(DEFAULT_PORT) {} + +void CommonOptions::addTo(po::options_description& desc) +{ + using namespace po; + desc.add_options() + ("trace,t", optValue(trace), "Enable debug tracing" ) + ("port,p", optValue(port,"PORT"), "Use PORT for AMQP connections."); +} + +} // namespace qpid + diff --git a/cpp/lib/common/CommonOptions.h b/cpp/lib/common/CommonOptions.h new file mode 100644 index 0000000000..2a4b9798cd --- /dev/null +++ b/cpp/lib/common/CommonOptions.h @@ -0,0 +1,91 @@ +#ifndef QPID_COMMONOPTIONS_H +#define QPID_COMMONOPTIONS_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/program_options.hpp> +#include <boost/format.hpp> + +namespace qpid { + +/**@Qpid extensions to boost::program_options */ +namespace program_options { + +using namespace boost::program_options; + +/** @internal Normally only constructed by optValue() */ +template <class T> +class OptionValue : public typed_value<T> { + public: + OptionValue(T& value, const std::string& arg) + : typed_value<T>(&value), argName(arg) {} + std::string name() const { return argName; } + private: + std::string argName; +}; + +/** + * Like boost::program_options::value() with more convenient signature + * for updating a value by reference and nicer help formatting. + * + *@param value displayed as default in help, updated from options. + * Must support ostream << operator. + *@param arg name for arguments in help. + * + *@see CommonOptions.cpp for example of use. + */ +template<class T> +value_semantic* optValue(T& value, const char* arg) { + std::string val(boost::lexical_cast<std::string>(value)); + std::string argName( + val.empty() ? std::string(arg) : + (boost::format("%s (=%s) ") % arg % val).str()); + return new OptionValue<T>(value, argName); +} + +/** + * Like boost::program_options::bool_switch but takes reference, not pointer. + */ +inline value_semantic* optValue(bool& value) { return bool_switch(&value); } + +} // namespace program_options + +namespace po=program_options; // Convenience alias. + +/** + * Common options for client and broker + */ +struct CommonOptions { + static const int DEFAULT_PORT; + + CommonOptions(); + + bool trace; + int port; + + /** Add members to program_options to be updated */ + void addTo(po::options_description&); +}; + +} // namespace qpid + +#endif /*!QPID_COMMONOPTIONS_H*/ diff --git a/cpp/lib/common/Exception.cpp b/cpp/lib/common/Exception.cpp index 0161518011..64d88af1b4 100644 --- a/cpp/lib/common/Exception.cpp +++ b/cpp/lib/common/Exception.cpp @@ -19,10 +19,16 @@ * */ -#include <Exception.h> +#include "Exception.h" +#include <cerrno> namespace qpid { +std::string strError(int err) { + char buf[512]; + return std::string(strerror_r(err, buf, sizeof(buf))); +} + Exception::Exception() throw() {} Exception::Exception(const std::string& str) throw() : whatStr(str) {} diff --git a/cpp/lib/common/Exception.h b/cpp/lib/common/Exception.h index f35d427bb0..4e26ad42e3 100644 --- a/cpp/lib/common/Exception.h +++ b/cpp/lib/common/Exception.h @@ -29,6 +29,10 @@ namespace qpid { + +/** Get the error message for error number err. */ +std::string strError(int err); + /** * Exception base class for all Qpid exceptions. */ diff --git a/cpp/lib/common/Makefile.am b/cpp/lib/common/Makefile.am index fe05498b97..e90dacb605 100644 --- a/cpp/lib/common/Makefile.am +++ b/cpp/lib/common/Makefile.am @@ -44,13 +44,14 @@ framing = framing gen = $(srcdir)/../../gen lib_LTLIBRARIES = libqpidcommon.la -libqpidcommon_la_LIBADD = \ - $(APR_LIBS) \ - $(LIB_DLOPEN) \ - $(LIB_CLOCK_GETTIME) +libqpidcommon_la_LIBADD = \ + $(APR_LIBS) \ + $(LIB_DLOPEN) \ + $(LIB_CLOCK_GETTIME) \ + -lboost_program_options -libqpidcommon_la_LDFLAGS = \ - -version-info \ +libqpidcommon_la_LDFLAGS = \ + -version-info \ $(LIBTOOL_VERSION_INFO_ARG) libqpidcommon_la_SOURCES = \ @@ -72,12 +73,13 @@ libqpidcommon_la_SOURCES = \ $(framing)/ProtocolVersionException.cpp \ $(framing)/Value.cpp \ $(gen)/AMQP_ClientProxy.cpp \ - $(gen)/AMQP_HighestVersion.h \ + $(gen)/AMQP_HighestVersion.h \ $(gen)/AMQP_MethodVersionMap.cpp \ $(gen)/AMQP_ServerProxy.cpp \ Exception.cpp \ ExceptionHolder.cpp \ QpidError.cpp \ + CommonOptions.cpp \ sys/Runnable.cpp \ sys/Time.cpp @@ -109,6 +111,7 @@ nobase_pkginclude_HEADERS = \ ExceptionHolder.h \ QpidError.h \ SharedObject.h \ + CommonOptions.cpp \ sys/Acceptor.h \ sys/AtomicCount.h \ sys/Module.h \ diff --git a/cpp/src/Makefile.am b/cpp/src/Makefile.am index 40398eb2c9..42b86f98e6 100644 --- a/cpp/src/Makefile.am +++ b/cpp/src/Makefile.am @@ -1,14 +1,16 @@ AM_CXXFLAGS = $(WARNING_CFLAGS) -INCLUDES = \ - -I$(top_srcdir)/gen \ - -I$(top_srcdir)/lib/broker \ - -I$(top_srcdir)/lib/common \ - -I$(top_srcdir)/lib/common/framing \ + +INCLUDES = \ + -I$(top_srcdir)/gen \ + -I$(top_srcdir)/lib/broker \ + -I$(top_srcdir)/lib/common \ + -I$(top_srcdir)/lib/common/framing \ -I$(top_srcdir)/lib/common/sys -LDADD = \ - ../lib/broker/libqpidbroker.la \ - ../lib/common/libqpidcommon.la +LDADD = \ + ../lib/broker/libqpidbroker.la \ + ../lib/common/libqpidcommon.la \ + -lboost_program_options sbin_PROGRAMS = qpidd qpidd_SOURCES = qpidd.cpp diff --git a/cpp/src/qpidd.cpp b/cpp/src/qpidd.cpp index 9f658ebf74..532636602e 100644 --- a/cpp/src/qpidd.cpp +++ b/cpp/src/qpidd.cpp @@ -19,62 +19,92 @@ * */ #include <Broker.h> -#include <Configuration.h> #include <signal.h> #include <iostream> #include <memory> -#include <cerrno> #include <config.h> #include <unistd.h> -static char const* programName = "qpidd"; +using namespace qpid; using namespace qpid::broker; using namespace qpid::sys; +using namespace std; -Broker::shared_ptr broker; +/** Command line options */ +struct QpiddOptions : public Broker::Options +{ + bool help; + bool version; + bool daemon; + po::options_description desc; + + QpiddOptions() : + help(false), version(false), daemon(false), desc("Options") + { + using namespace po; + desc.add_options() + ("daemon,d", optValue(daemon), "Run as a daemon"); + Broker::Options::addTo(desc); + desc.add_options() + ("help,h", optValue(help), "Print help message") + ("version,v", optValue(version), "Print version information"); + } + + void parse(int argc, char* argv[]) { + po::variables_map vm; + po::store(po::parse_command_line(argc, argv, desc), vm); + po::notify(vm); + }; + + void usage(std::ostream& out) const { + out << "Usage: qpidd [OPTIONS]" << endl + << "Start the Qpid AMQP broker." << endl << endl + << desc << endl; + }; +}; + +std::ostream& operator<<(std::ostream& out, const QpiddOptions& config) { + config.usage(out); return out; +} + +Broker::shared_ptr brokerPtr; void handle_signal(int /*signal*/){ - std::cerr << "Shutting down..." << std::endl; - broker->shutdown(); + if (brokerPtr) { + cerr << "Shutting down..." << endl; + brokerPtr->shutdown(); + } } -int main(int argc, char** argv) +int main(int argc, char* argv[]) { - Configuration config; + QpiddOptions config; try { - config.parse(programName, argc, argv); - - if(config.isHelp()){ - config.usage(); - }else if(config.isVersion()){ - std::cout << programName << " (" << PACKAGE_NAME << ") version " - << PACKAGE_VERSION << std::endl; - }else{ - broker = Broker::create(config); + config.parse(argc, argv); + if(config.help) { + config.usage(cout); + } + else if (config.version) { + cout << "qpidd (" << PACKAGE_NAME << ") version " + << PACKAGE_VERSION << endl; + } + else { + brokerPtr=Broker::create(config); signal(SIGINT, handle_signal); - if (config.isDaemon()) { - // Detach & run as daemon. - int chdirRoot = 0; // 0 means chdir to root. - int closeStd = 0; // 0 means close stdin/out/err - if (daemon(chdirRoot, closeStd) < 0) { - char buf[512]; - - std::cerr << "Failed to detach as daemon: " - << strerror_r(errno, buf, sizeof(buf)) - << std::endl;; - return 1; - } + if (config.daemon) { + if (daemon(0, 0) < 0) // daemon(nochdir, noclose) + throw QPID_ERROR( + INTERNAL_ERROR, + "Failed to detach as daemon: "+ strError(errno)); } - broker->run(); + brokerPtr->run(); } return 0; } - catch (const Configuration::BadOptionException& e) { - std::cerr << e.what() << std::endl << std::endl; - config.usage(); - } catch(const std::exception& e) { - std::cerr << e.what() << std::endl; + catch(const exception& e) { + cerr << "Error: " << e.what() << endl + << "Type 'qpidd --help' for usage." << endl; } return 1; } diff --git a/cpp/tests/ConfigurationTest.cpp b/cpp/tests/ConfigurationTest.cpp deleted file mode 100644 index 3a1d5ba85d..0000000000 --- a/cpp/tests/ConfigurationTest.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 <Configuration.h> -#include <qpid_test_plugin.h> -#include <iostream> - -using namespace std; -using namespace qpid::broker; - -class ConfigurationTest : public CppUnit::TestCase -{ - CPPUNIT_TEST_SUITE(ConfigurationTest); - CPPUNIT_TEST(testIsHelp); - CPPUNIT_TEST(testPortLongForm); - CPPUNIT_TEST(testPortShortForm); - CPPUNIT_TEST(testStore); - CPPUNIT_TEST(testStagingThreshold); - CPPUNIT_TEST(testVarious); - CPPUNIT_TEST_SUITE_END(); - - public: - - void testIsHelp() - { - Configuration conf; - char* argv[] = {"ignore", "--help"}; - conf.parse("ignore", 2, argv); - CPPUNIT_ASSERT(conf.isHelp()); - } - - void testPortLongForm() - { - Configuration conf; - char* argv[] = {"ignore", "--port", "6789"}; - conf.parse("ignore", 3, argv); - CPPUNIT_ASSERT_EQUAL(6789, conf.getPort()); - } - - void testPortShortForm() - { - Configuration conf; - char* argv[] = {"ignore", "-p", "6789"}; - conf.parse("ignore", 3, argv); - CPPUNIT_ASSERT_EQUAL(6789, conf.getPort()); - } - - void testStore() - { - Configuration conf; - char* argv[] = {"ignore", "--store", "my-store-module.so"}; - conf.parse("ignore", 3, argv); - std::string expected("my-store-module.so"); - CPPUNIT_ASSERT_EQUAL(expected, conf.getStore()); - } - - void testStagingThreshold() - { - Configuration conf; - char* argv[] = {"ignore", "--staging-threshold", "123456789"}; - conf.parse("ignore", 3, argv); - long expected = 123456789; - CPPUNIT_ASSERT_EQUAL(expected, conf.getStagingThreshold()); - } - - void testVarious() - { - Configuration conf; - char* argv[] = {"ignore", "-t", "--worker-threads", "10"}; - conf.parse("ignore", 4, argv); - CPPUNIT_ASSERT_EQUAL(5672, conf.getPort());//default - CPPUNIT_ASSERT_EQUAL(10, conf.getWorkerThreads()); - CPPUNIT_ASSERT(conf.isTrace()); - CPPUNIT_ASSERT(!conf.isHelp()); - } -}; - -// Make this test suite a plugin. -CPPUNIT_PLUGIN_IMPLEMENT(); -CPPUNIT_TEST_SUITE_REGISTRATION(ConfigurationTest); - diff --git a/cpp/tests/Makefile.am b/cpp/tests/Makefile.am index 7764d79721..7f6de0d28e 100644 --- a/cpp/tests/Makefile.am +++ b/cpp/tests/Makefile.am @@ -29,7 +29,6 @@ client_tests = \ broker_tests = \ AccumulatedAckTest \ ChannelTest \ - ConfigurationTest \ ExchangeTest \ HeadersExchangeTest \ InMemoryContentTest \ @@ -66,6 +65,9 @@ unit_tests = \ noinst_PROGRAMS = $(client_tests) +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ + TESTS_ENVIRONMENT = \ VALGRIND=$(VALGRIND) \ abs_builddir='$(abs_builddir)' \ @@ -80,7 +82,6 @@ DISTCLEANFILES=gen.mk include gen.mk -abs_builddir = @abs_builddir@ extra_libs = $(CPPUNIT_LIBS) lib_client = $(abs_builddir)/../lib/client/libqpidclient.la lib_common = $(abs_builddir)/../lib/common/libqpidcommon.la |