int QpiddBroker::execute()

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;
}