• No results found

The ACE Service Object Class

In document c++ Ntw Programming (Page 106-111)

The ACE Service Configurator Framework

4.2 The ACE Service Object Class

Motivation

Enforcing a uniform interface across all networked services enables them to be configured and managed consistently. In turn, this consistency sim-plifies application development and deployment by simplifying the cre-ation of reusable administrative configurcre-ation tools and promoting the

“principle of least surprise.” To provide a uniform interface between the ACE Service Configurator framework and the application-supplied ser-vices, each service must be a descendant of a common base class called ACE_Service_Object.

Class Capabilities

The ACE_Service_Object class provides a uniform interface that allows all service implementations to be configured and managed by the ACE

Ser-Section 4.2 The ACE Service Object Class 95

Figure 4.2: The ACE Service Object Class

vice Configurator framework. This class provides the following capabilities:

 It provides hook methods that initialize a service and shut down a service and clean up its resources.

 It provides hook methods to suspend service execution temporarily and to resume execution of a suspended service.

 It provides a hook method that reports key information about the service, such as its purpose and the port number where it listens for client connections.

The interface for theACE_Service_Objectclass is shown in Figure 4.2.

By inheriting from ACE_Event_Handler and ACE_Shared_Object, sub-classes of ACE_Service_Object can be dispatched by the ACE Reactor framework and can be linked/unlinked dynamically from a DLL, respec-tively. The key methods of ACE_Service_Objectare outlined in the fol-lowing table:

Method Description

init() A hook method used by the Service Configurator framework to in-struct a service to initialize itself. A pair of “argc/argv”-style pa-rameters can be passed to init()and used to control the initial-ization of a service.

fini() A hook method used by the Service Configurator framework to instruct a service to terminate itself. This method typically per-forms termination operations that release dynamically allocated resources, such as memory, synchronization locks, or I/O descrip-tors.

suspend() resume()

Hook methods used by the Service Configurator framework to in-struct a service to suspend and resume its execution.

info() A hook method used by the Service Configurator framework to query a service for certain information about itself, such as its name, purpose, and network address. Clients can query a server to retrieve this information and use it to contact a particular service running in a server.

These hook methods collectively impose a uniform contract between the ACE Service Configurator framework and the services that it manages.

Application services that inherit from ACE_Service_Objectcan selec-tively override its hook methods, which are called back at the appropriate

96 Section 4.2 The ACE Service Object Class

time by the ACE Service Configurator framework in accordance to various events. This highly extensible technique allows applications to defer the se-lection of a particular service implementation until late in the design cycle, i.e., at installation-time or even during run-time. Developers can there-fore concentrate on a service’s functionality and other design dimensions without committing themselves prematurely to a particular service config-uration. Developers can also configure complete applications by compos-ing multiple services that are developed independently and therefore don’t require a priori global knowledge of each other, yet can still collaborate effectively.

Example

To illustrate theACE_Service_Objectclass, we reimplement our Reactor-based logging server from the Example portion in Section 3.5. This revi-sion can be configured dynamically by the ACE Service Configurator frame-work, rather than configured statically into themain()program shown on page 3.5. To accomplish this, we’ll create the followingReactor_Logging_

Server_Adaptertemplate:

template <class ACCEPTOR>

class Reactor_Logging_Server_Adapter : public ACE_Service_Object {

public:

// Hook methods inherited from <ACE_Service_Object>.

virtual int init (int argc, char *argv[]);

virtual int fini ();

virtual int info (ACE_TCHAR **, size_t) const;

virtual int suspend ();

virtual int resume ();

private:

Reactor_Logging_Server<ACCEPTOR> *server_;

};

This template inherits from ACE_Service_Objectand contains a pointer to the Reactor_Logging_Servertemplate defined on page 71. We’ve in-stantiated this template with the ACCEPTOR parameter to defer our choice of acceptor until later in the design cycle.

Section 4.2 The ACE Service Object Class 97

When an instance ofReactor_Logging_Server_Adapteris configured dynamically, the ACE Service Configurator framework invokes its init() method:

template <class ACCEPTOR> int

Reactor_Logging_Server_Adapter<ACCEPTOR>::init (int argc, char *argv[])

{

server_ = new Reactor_Logging_Server<ACCEPTOR>

(argc, argv,

ACE_Reactor::instance ());

return 0;

}

This method creates an instance of Reactor_Logging_Serverand keeps track of it with theserver_pointer.

When instructed to remove the Reactor_Logging_Server_Adapter, the ACE Service Configurator framework invokes itsfini()method:

template <class ACCEPTOR> int

Reactor_Logging_Server_Adapter<ACCEPTOR>::fini () {

delete server_;

return 0;

}

This method deletes the instance of Reactor_Logging_Servercreated in init().

Theinfo()method is shown next:

1 template <class ACCEPTOR> int

2 Reactor_Logging_Server_Adapter<ACCEPTOR>::info 3 (ACE_TCHAR **bufferp, size_t length) const { 4 ACE_INET_Addr sa;

5 server_->acceptor ().get_local_addr (sa);

6

7 ACE_TCHAR buf[BUFSIZ];

8 sprintf (buf,

9 "%d/%s %s",

10 sa.get_port_number (), 11 "tcp",

12 "# Reactor-based logging server\n");

98 Section 4.2 The ACE Service Object Class

13 *bufferp = ACE_OS::strnew (buf);

14 ACE_OS::strcpy (*bufferp, buf);

15 return ACE_OS::strlen (buf);

16 }

Lines 1–5 Obtain the network address object from the instance of ACE_

SOCK_Acceptorthat’s used by theReactor_Logging_Server.

Lines 7–12 Format an informative message that explains what the ser-vice does and how to contact it.

Lines 13–15 Allocate a new memory buffer dynamically, store the for-matted description string into this buffer, and return the buffer’s length.

The caller is responsible for deleting the buffer.

The suspend() and resume() methods are similar to each other, as shown below:

template <class ACCEPTOR> int

Reactor_Logging_Server_Adapter<ACCEPTOR>::suspend () {

return ACE_Reactor::instance ()->suspend_handler (server_);

}

template <class ACCEPTOR> int

Reactor_Logging_Server_Adapter<ACCEPTOR>::resume () {

return ACE_Reactor::instance ()->resume_handler (server_);

}

SinceReactor_Logging_Serveris a descendant of ACE_Event_Handler, the server_ object can be passed to the singleton reactor’s suspend_

handler() and resume_handler() methods, which double-dispatch to Reactor_Logging_Server::get_handle()to extract the underlying passive-mode socket handle. These methods then use this socket handle to tem-porarily remove or resume the Reactor_Logging_Serverfrom the list of socket handles handled by the singleton reactor.

The Example portion of Section 4.4 shows how theReactor_Logging_

Server_Adaptercan be configured into and out of a generic server appli-cation dynamically.

Section 4.3 The ACE Service Repository and ACE Service Repository Iterator Classes 99

Figure 4.3: TheACE Service RepositoryClass

4.3 The ACE Service Repository and ACE Service

In document c++ Ntw Programming (Page 106-111)