diff options
| author | Stephen D. Huston <shuston@apache.org> | 2011-02-23 00:48:56 +0000 |
|---|---|---|
| committer | Stephen D. Huston <shuston@apache.org> | 2011-02-23 00:48:56 +0000 |
| commit | d07e9a0a24eeab9b16706c8a001864af1f181182 (patch) | |
| tree | 20b2f989350a538a66c078657056e84758ef4087 /cpp/src/windows/QpiddBroker.cpp | |
| parent | 30996cba9f2588c379adad15b3f2c5c3137c6f55 (diff) | |
| download | qpid-python-d07e9a0a24eeab9b16706c8a001864af1f181182.tar.gz | |
Initial commit of patches applied from QPID-2519, formatted mostly for Qpid guidelines. Hasn't been built, will need more changes. Checking in for Kerry's use.
git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/QPID-2519@1073566 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/src/windows/QpiddBroker.cpp')
| -rw-r--r-- | cpp/src/windows/QpiddBroker.cpp | 120 |
1 files changed, 119 insertions, 1 deletions
diff --git a/cpp/src/windows/QpiddBroker.cpp b/cpp/src/windows/QpiddBroker.cpp index e221551575..9432cbc077 100644 --- a/cpp/src/windows/QpiddBroker.cpp +++ b/cpp/src/windows/QpiddBroker.cpp @@ -42,6 +42,11 @@ const char *QPIDD_MODULE_DIR = "."; using namespace qpid::broker; +// Service support +#include "Service.h" +Service s_service( "qpidd" ); + + BootstrapOptions::BootstrapOptions(const char* argv0) : qpid::Options("Options"), common("", QPIDD_CONF_FILE), @@ -225,9 +230,39 @@ struct ProcessControlOptions : public qpid::Options { } }; +struct DaemonOptions : public qpid::Options { + bool install; + bool start; + bool stop; + bool uninstall; + bool daemon; + string startType; + string account; + string password; + string depends; + + DaemonOptions() + : qpid::Options("Service options"), install(false), start(false), stop(false), uninstall(false), daemon(false), + startType("demand") + { + addOptions() + ("install", qpid::optValue(install), "Install as service") + ("start-type", qpid::optValue(startType,"auto|demand|disabled"), "Service start type\nApplied at install time only.") + ("account", qpid::optValue(account,"(LocalService)"), "Account to run as, default is LocalService\nApplied at install time only.") + ("password", qpid::optValue(password,"PASSWORD"), "Account password, if needed\nApplied at install time only.") + ("depends", qpid::optValue(depends,"(comma delimited list)"), "Names of services that must start before this service\nApplied at install time only.") + ("start", qpid::optValue(start), "Start the service.") + ("stop", qpid::optValue(stop), "Stop the service.") + ("uninstall", qpid::optValue(uninstall), "Uninstall the service.") + ("daemon", qpid::optValue(daemon), "Run as a daemon service (internal use only"); + } +}; + struct QpiddWindowsOptions : public QpiddOptionsPrivate { ProcessControlOptions control; + DaemonOptions daemon; QpiddWindowsOptions(QpiddOptions *parent) : QpiddOptionsPrivate(parent) { + parent->add(daemon); parent->add(control); } }; @@ -252,6 +287,19 @@ void QpiddOptions::usage() const { << *this << std::endl; } +void WINAPI ShutdownProc( void *pContext ) +{ + if( pContext ) + reinterpret_cast<Broker*>(pContext)->shutdown(); +} + +int __cdecl main(int argc, char* argv[]); + +void WINAPI main2( DWORD argc, char* argv[] ) +{ + (void)main( argc, argv ); +} + int QpiddBroker::execute (QpiddOptions *options) { // Options that affect a running daemon. QpiddWindowsOptions *myOptions = @@ -259,6 +307,69 @@ int QpiddBroker::execute (QpiddOptions *options) { if (myOptions == 0) throw qpid::Exception("Internal error obtaining platform options"); + if( myOptions->daemon.install ) + { + size_t p; + + // Handle start type + DWORD startType; + if( myOptions->daemon.startType.compare( "demand" ) == 0 ) + startType = SERVICE_DEMAND_START; + else if( myOptions->daemon.startType.compare( "auto" ) == 0 ) + startType = SERVICE_AUTO_START; + else if( myOptions->daemon.startType.compare( "disabled" ) == 0 ) + startType = SERVICE_DISABLED; + else if( ! myOptions->daemon.startType.empty() ) + throw qpid::Exception( "Invalid service start type: " + myOptions->daemon.startType ); + + // Get original command line arguments and substitute daemon for install... + string args( ::GetCommandLineA() ); + if( args[0] == '\"' ) // if OS prepended w/ fully qualified path + { + if( ( p = args.find_first_of( "\"", 1 ) ) != args.npos ) + args = args.substr( p + 2 ); // trim .exe + } + else + { + if( ( p = args.find_first_of( " ", 1 ) ) != args.npos ) + args = args.substr( p + 1 ); // trim .exe + } + if( ( p = args.find( "install" ) ) == args.npos ) + throw qpid::Exception("Internal error relocating install argument for service"); + string args2 = args.substr( 0, p ); + args2 += "daemon"; + args2 += args.substr( p + 7 ); + + // Install service and exit + WinService::install( "qpidd", args2, startType, myOptions->daemon.account, myOptions->daemon.password, myOptions->daemon.depends ); + return 0; + } + + if( myOptions->daemon.start ) + { + WinService::start( "qpidd" ); + return 0; + } + + else if( myOptions->daemon.stop ) + { + WinService::stop( "qpidd" ); + return 0; + } + + else if( myOptions->daemon.uninstall ) + { + WinService::uninstall( "qpidd" ); + return 0; + } + + // Detect daemon special argument + else if( myOptions->daemon.daemon ) + { + WinService::getInstance()->run( main2 ); + return 1; + } + if (myOptions->control.check || myOptions->control.quit) { // Relies on port number being set via --port or QPID_PORT env variable. NamedSharedMemory<BrokerInfo> info(brokerInfoName(options->broker.port)); @@ -281,6 +392,9 @@ int QpiddBroker::execute (QpiddOptions *options) { boost::intrusive_ptr<Broker> brokerPtr(new Broker(options->broker)); + // Enable shutdown + s_service.setShutdownProc( ShutdownProc, brokerPtr.get() ); + // Need the correct port number to use in the pid file name. if (options->broker.port == 0) options->broker.port = brokerPtr->getPort(myOptions->control.transport); @@ -302,7 +416,11 @@ int QpiddBroker::execute (QpiddOptions *options) { brokerPtr->accept(); std::cout << options->broker.port << std::endl; brokerPtr->run(); - waitShut.signal(); // In case we shut down some other way + + // Now disable shutdown + s_service.setShutdownProc(0,0); + + waitShut.signal(); // In case we shut down some other way waitThr.join(); // CloseHandle(h); |
