diff options
author | Alan Conway <aconway@apache.org> | 2007-06-11 16:05:06 +0000 |
---|---|---|
committer | Alan Conway <aconway@apache.org> | 2007-06-11 16:05:06 +0000 |
commit | b59a0092f12a07f925bc0b1c7f8cf4949dd374e7 (patch) | |
tree | c6c188962552bac59bb96b8b7b00d791ae9e4be1 /cpp/src/qpidd.cpp | |
parent | 4c88e1be1c96cf27b8418df2a60c3cbbefd92fcc (diff) | |
download | qpid-python-b59a0092f12a07f925bc0b1c7f8cf4949dd374e7.tar.gz |
QPID-504: Print bound port if --port 0 is specified. Not yet used by tests.
* qpidd.cpp:
- With --port 0 print the bound port number to stdout.
- Removed --ppid, --check now prints pid.
* Daemon.cpp/h: Move pid-file generation to caller (qpidd.cpp)
* Exception.cpp: Log a debug message in exception constructors.
Helps to show what exceptions were thrown even if they aren't
logged at a higher level.
* daemon_test: Test new daemon options.
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@546180 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/src/qpidd.cpp')
-rw-r--r-- | cpp/src/qpidd.cpp | 160 |
1 files changed, 94 insertions, 66 deletions
diff --git a/cpp/src/qpidd.cpp b/cpp/src/qpidd.cpp index 2f4d16f0a7..3378fcdc96 100644 --- a/cpp/src/qpidd.cpp +++ b/cpp/src/qpidd.cpp @@ -25,23 +25,18 @@ #include "qpid/log/Options.h" #include "qpid/log/Logger.h" #include "config.h" +#include <boost/filesystem/path.hpp> +#include <boost/filesystem/operations.hpp> #include <iostream> #include <fstream> #include <signal.h> +#include <unistd.h> using namespace qpid; using namespace qpid::broker; using namespace qpid::sys; using namespace std; -Broker::shared_ptr brokerPtr; - -void handle_signal(int /*signal*/){ - QPID_LOG(notice, "Shutting down..."); - brokerPtr->shutdown(); -} - - /** Command line options */ struct QpiddOptions : public Broker::Options, public log::Options { @@ -52,39 +47,42 @@ struct QpiddOptions : public Broker::Options, public log::Options bool quit; bool kill; bool check; - bool ppid; int wait; string config; po::options_description mainOpts; po::options_description allOpts; - po::options_description logOpts; QpiddOptions() : help(false), version(false), daemon(false), - quit(false), kill(false), check(false), ppid(false), wait(10), + quit(false), check(false), + wait(10), config("/etc/qpidd.conf"), - mainOpts("Options"), - logOpts("Logging Options") + mainOpts("Broker Options") { using namespace po; - mainOpts.add_options() - ("daemon,d", optValue(daemon), "Run as a daemon.") - ("quit,q", optValue(quit), "Stop the running daemon politely.") - ("kill,k", optValue(kill), "Kill the running daemon harshly.") - ("check,c", optValue(check), "If daemon is running return 0.") - ("wait", optValue(wait, "SECONDS"), - "Maximum wait for daemon response.") - ("ppid", optValue(ppid), "Print daemon pid to stdout." ); - po::options_description brokerOpts; + // First set up the sub-option groups. + options_description daemonOpts("Daemon Options"); + daemonOpts.add_options() + ("daemon,d", optValue(daemon), "Run as a daemon. With --port 0 print actual listening port.") + ("wait,w", optValue(wait, "SECONDS"), "Maximum wait for daemon response.") + ("check,c", optValue(check), "If a daemon is running print its pid to stdout and return 0.") + ("quit,q", optValue(quit), "Stop the running daemon politely."); + + options_description logOpts("Logging Options"); + log::Options::addTo(logOpts); + + // Populate the main options group for --help Broker::Options::addTo(mainOpts); mainOpts.add_options() ("config", optValue(config, "FILE"), "Configuation file.") ("help,h", optValue(help), "Print help message.") ("long-help", optValue(longHelp), "Show complete list of options.") ("version,v", optValue(version), "Print version information."); + mainOpts.add(daemonOpts); - log::Options::addTo(logOpts); + // Populate the all options group allOpts.add(mainOpts).add(logOpts); + } void parse(int argc, char* argv[]) { @@ -97,19 +95,62 @@ struct QpiddOptions : public Broker::Options, public log::Options }; }; +// Globals +Broker::shared_ptr brokerPtr; +QpiddOptions config; + +void handle_signal(int /*signal*/){ + QPID_LOG(notice, "Shutting down..."); + brokerPtr->shutdown(); +} + +/** Compute a name for the pid file */ +std::string pidFileFn() { + uint16_t port=brokerPtr ? brokerPtr->getPort() : config.port; + string file=(boost::format("qpidd.%d.pid") % port).str(); + string pidPath; + if (getuid() == 0) // Use standard pid file for root. + pidPath=Daemon::defaultPidFile(file); + else { // Use $HOME/.qpidd for non-root. + const char* home=getenv("HOME"); + if (!home) + throw(Exception("$HOME is not set, cant create $HOME/.qpidd.")); + namespace fs=boost::filesystem; + fs::path dir = fs::path(home,fs::native) / fs::path(".qpidd", fs::native); + fs::create_directory(dir); + dir /= file; + pidPath=dir.string(); + } + QPID_LOG(debug, "PID file name=" << pidPath); + return pidPath; +} + +/** Code for forked parent */ +void parent(Daemon& demon) { + uint16_t realPort = demon.wait(); + if (config.port == 0) + cout << realPort << endl; +} + +/** Code for forked child */ +void child(Daemon& demon) { + brokerPtr=Broker::create(config); + uint16_t realPort=brokerPtr->getPort(); + demon.ready(realPort); // Notify parent. + brokerPtr->run(); +} + + int main(int argc, char* argv[]) { - QpiddOptions config; + // Spelled 'demon' to avoid clash with daemon.h function. + Daemon demon(pidFileFn, config.wait); + try { config.parse(argc, argv); if (config.trace) config.selectors.push_back("trace+"); log::Logger::instance().configure(config, argv[0]); - string name=(boost::format("%s.%d") - % Daemon::nameFromArgv0(argv[0]) - % (config.port)).str(); - // Spelled 'demon' to avoid clash with daemon.h function. - Daemon demon(name, config.wait); // Options that just print information. if(config.help || config.longHelp || config.version) { @@ -123,46 +164,32 @@ int main(int argc, char* argv[]) return 0; } - // Options that act on an already running daemon. - if (config.quit || config.kill || config.check) { + // Stop running daemon + if (config.quit) { + demon.quit(); + return 0; + } + + // Query running daemon + if (config.check) { pid_t pid = demon.check(); - if (config.ppid && pid > 0) - cout << pid << endl; - if (config.kill) - demon.kill(); - else if (config.quit) - demon.quit(); - if (config.check && pid <= 0) + if (pid < 0) return 1; - return 0; + else { + cout << pid << endl; + return 0; + } } // Starting the broker: signal(SIGINT, handle_signal); - if (config.daemon) { - pid_t pid = demon.fork(); - if (pid == 0) { // Child - try { - brokerPtr=Broker::create(config); - demon.ready(); // Notify parent we're ready. - brokerPtr->run(); - } catch (const exception& e) { - QPID_LOG(critical, "Broker daemon startup failed: " << e.what()); - demon.failed(); // Notify parent we failed. - return 1; - } - } - else if (pid > 0) { // Parent - if (config.ppid) - cout << pid << endl; - return 0; - } - else { // pid < 0 - throw Exception("fork failed"+strError(errno)); - } - } // Non-daemon broker. - else { + if (config.daemon) { // Daemon broker + demon.fork(parent, child); + } + else { // Non-daemon broker. brokerPtr = Broker::create(config); + if (config.port == 0) + cout << uint16_t(brokerPtr->getPort()) << endl; brokerPtr->run(); } return 0; @@ -170,12 +197,13 @@ int main(int argc, char* argv[]) catch(const po::error& e) { // Command line parsing error. cerr << "Error: " << e.what() << endl - << "Type 'qpidd --help' for usage." << endl; + << "Type 'qpidd --long-help' for full usage." << endl; } catch(const exception& e) { - // Could be child or parent so log and print. - QPID_LOG(error, e.what()); - cerr << "Error: " << e.what() << endl; + if (demon.isParent()) + cerr << "Error: " << e.what() << endl; + else + QPID_LOG(critical, e.what()); } return 1; } |