Here is what you can do in C++.

Each server listens on 2 ports:

- The admin port. That is where administrative requests (like 'shutdown') come 
in.

- The service port. That is where the requests for the 'real' service come in.

So.... Note this is all pseudo code ;-).

1 - Create a service called 'ServerControl'. It has a function like:

service ServerControl {
  void shutdown();
  ...
}

2 - The implementation of shutdown() is:

typedef void (*shutdownhandler_t)(void);

void ServerControlHandler::shutdown()
{
    std::vector<shutdownhandler_t>::const_iterator iter = handlers.begin();
    while (iter != handlers.end()) {
        (*iter)();
        iter++;
    }
}

So my code can register shutdown handlers that get called when a 'shutdown' 
request comes in.

3 - When creating my server binary I do something like the following.

SimpleServer* ctrlServer = NULL;
ThreadpoolServer* theServer = NULL;
...
void shutdownHandler()
{
   theServer->stop();
   ctrlServer->stop();
}
...
void setupServerControl()
{
    int port = "get the admin port from some config file";

    boost::shared_ptr<ProtocolFactory> protocolFactory(new 
BinaryProtocolFactory());
    boost::shared_ptr<ServerControlHandler> handler(new ServerControlHandler());
    boost::shared_ptr<Processor> processor(new ServerControlProcessor(handler));
    boost::shared_ptr<ServerTransport> serverTransport(new 
TCPServerSocket(port));
    boost::shared_ptr<TransportFactory> transportFactory(new 
BufferedTransportFactory());

    ctrlServer = new SimpleServer(processor, serverTransport, transportFactory, 
protocolFactory);

    handler->addShutdownHandler(shutdownHandler);
}
...
void setupServer()
{
    int port = "get the service port from some config file";

    boost::shared_ptr<ProtocolFactory> protocolFactory(new 
BinaryProtocolFactory());
    boost::shared_ptr<EventHandler> handler(new XXXHandler());
    boost::shared_ptr<Processor> processor(new XXXProcessor(handler));
    boost::shared_ptr<ServerTransport> serverTransport(new 
TCPServerSocket(port));
    boost::shared_ptr<TransportFactory> transportFactory(new 
BufferedTransportFactory());

    theThreadManager =
        boost::shared_ptr<StaticThreadManager>(new 
StaticThreadManager(threadFactory,
                                               threadPoolSize));
    theThreadManager->start();
    theServer = new ThreadpoolServer(processor, serverTransport, 
transportFactory,
        protocolFactory, theThreadManager);

    boost::shared_ptr<Runnable> runnable = 
boost::shared_ptr<Runnable>(theServer);

    boost::shared_ptr<Thread> thread = 
boost::shared_ptr<Thread>(threadFactory->newThread(runnable));

    thread->start();
}
...
int main(int argc, const char* argv[])
{
    setupServerControl();
    setupServer();

    ctrlServer->serve();

    return 0;
}

After calling 'setupServerControl()', the real service is listening on the 
service port runnng in a separate thread. And 'ctrlServer->serve()' will block 
until a 'shutdown' request comes in.

This can be boilerplate code for all your servers. There are a few race 
conditions here but that's an exercise for the reader ;-).

And so now I can just write a simple commandline utility, that looks up the 
admin port for the server I want to shut down, and it sends the 'shutdown' 
request to that admin port.

Thanks.

Samir


On May 4, 2011, at 8:01 AM, Bryan Duxbury wrote:

> If your server is in Java or Ruby, then there are methods for stopping the
> server gracefully.
> 
> On Wed, May 4, 2011 at 2:43 AM, Jaonary Rabarisoa <[email protected]> wrote:
> 
>> Hi all,
>> 
>> I'm trying to use thrift for testing purpose. In my project, I need to
>> start
>> and stop the service for every test case. Starting the service is simple as
>> doing "server.serve()" but I can't find how to stop it. So, how a thrift
>> service is supposed to be stopped ? Is is possible to stop it from the
>> client ?
>> 
>> 
>> Regards,
>> 
>> 
>> Jaonary
>> 

Reply via email to