in src/windows/QpiddBroker.cpp [369:486]
int QpiddBroker::execute (QpiddOptions *options) {
// If running as a service, bump the status checkpoint to let SCM know
// we're still making progress.
if (svcStatusHandle != 0) {
svcStatus.dwCheckPoint++;
::SetServiceStatus(svcStatusHandle, &svcStatus);
}
// Options that affect a running daemon.
QpiddWindowsOptions *myOptions =
reinterpret_cast<QpiddWindowsOptions *>(options->platform.get());
if (myOptions == 0)
throw qpid::Exception("Internal error obtaining platform options");
if (myOptions->service.install) {
// Handle start type
DWORD startType;
if (myOptions->service.startType.compare("demand") == 0)
startType = SERVICE_DEMAND_START;
else if (myOptions->service.startType.compare("auto") == 0)
startType = SERVICE_AUTO_START;
else if (myOptions->service.startType.compare("disabled") == 0)
startType = SERVICE_DISABLED;
else if (!myOptions->service.startType.empty())
throw qpid::Exception("Invalid service start type: " +
myOptions->service.startType);
// Install service and exit
qpid::windows::SCM manager;
manager.install(svcName,
"Apache Qpid Message Broker",
myOptions->service.startArgs,
startType,
myOptions->service.account,
myOptions->service.password,
myOptions->service.depends);
return 0;
}
if (myOptions->service.start) {
qpid::windows::SCM manager;
manager.start(svcName);
return 0;
}
if (myOptions->service.stop) {
qpid::windows::SCM manager;
manager.stop(svcName);
return 0;
}
if (myOptions->service.uninstall) {
qpid::windows::SCM manager;
manager.uninstall(svcName);
return 0;
}
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));
int pid = info.get().pid;
if (pid < 0)
return 1;
if (myOptions->control.check)
std::cout << pid << std::endl;
if (myOptions->control.quit) {
ShutdownEvent shutter(options->broker.port);
shutter.open();
shutter.signal();
HANDLE brokerHandle = ::OpenProcess(SYNCHRONIZE, false, pid);
QPID_WINDOWS_CHECK_NULL(brokerHandle);
::WaitForSingleObject(brokerHandle, INFINITE);
::CloseHandle(brokerHandle);
}
return 0;
}
boost::intrusive_ptr<Broker> brokerPtr(new Broker(options->broker));
// 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);
BrokerInfo info;
info.pid = ::GetCurrentProcessId();
NamedSharedMemory<BrokerInfo> sharedInfo(brokerInfoName(options->broker.port));
sharedInfo.create() = info;
// Allow the broker to receive a shutdown request via a qpidd --quit
// command. Note that when the broker is run as a service this operation
// should not be allowed.
ourPort = options->broker.port;
ShutdownHandler waitShut(ourPort, brokerPtr);
waitShut.create();
qpid::sys::Thread waitThr(waitShut); // Wait for shutdown event
::SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE);
brokerPtr->accept();
std::cout << options->broker.port << std::endl;
// If running as a service, tell SCM we're up. There's still a chance
// that store recovery will drag out the time before the broker actually
// responds to requests, but integrating that mechanism with the SCM
// updating is probably more work than it's worth.
if (svcStatusHandle != 0) {
svcStatus.dwCheckPoint = 0;
svcStatus.dwWaitHint = 0;
svcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
svcStatus.dwCurrentState = SERVICE_RUNNING;
::SetServiceStatus(svcStatusHandle, &svcStatus);
}
brokerPtr->run();
waitShut.signal(); // In case we shut down some other way
waitThr.join();
return 0;
}