Ru-BRD
5.4 The ACE_Service_Config Class Motivation Before a service can execute, it must be configured into an application's address space. One way to configure services into a networked application is to statically link the functionality provided by its various classes and functions into separate OS processes, and then manually instantiate or initialize them at run time. We used this approach in the logging server examples in Chapters 3 and 4 and throughout C NPv1, where the logging server program runs in a process that handles log records from client applications. Although our use of the ACE Reactor framework in earlier chapters improved the networked logging server's modularity and portability, the following drawbacks arose from statically configuring the Reactor_Logging_Server class with its main () program: before the service can be implemented, it must be configured into applications. One method is a static connection from a different class and a function to a separate OS process, then manually instantiate them at runtime. We use this method in Chapter 3, 4 of C NPV1, and Logging Server runs in a process of processing a customer log. Although we used the Ace Reactor framework to increase modular, portability, but in main () static configuration reactor_logging_server appears below the problem:
Service configuration decisions are made prematurely in the development cycle, which is undesirable if developers do not know the best way to collocate or distribute services in advance. Moreover, the "best" configuration may change as the computing context changes. For example, an application may write log records to a local file when it's running on a disconnected laptop computer. When the laptop is connected to a LAN, however, it may forward log records to a centralized logging server. Forcing networked applications to commit prematurely to a particular service configuration impedes their flexibility and can reduce their performance and functionality. It can also force costly redesign and reimplementation later in a project's life cycle. development cycle to make a premature decision service configuration, developers do not know the best configuration or distribution service. And the best configuration changes with the changes in the computer environment. Applications can write long records to a local file When the network is disconnected, the record can also forward the record to the log server when the network is connected. Premature submission configuration hinders flexibility to reduce functionality and efficiency. Strengthened the re-real expensive overhead.
Modifying a service may affect other services adversely if the implementation of a service is coupled tightly with its initial configuration. To enhance reuse, for example, a logging server may initially reside in the same program as other services, such as a name service. If the other services change, however, for example if the name service lookup algorithm changes, all existing code in the server would require modification, recompilation, and static relinking. moreover, terminating a running process to change some of its service code would also terminate the collocated logging service. This disruption in service may not be acceptable for highly available systems, such as telecommunication switches or customer care call centers [SS94]. If a service and his initial configuration are closely linked, modify a service may affect other services adversely. To enhance reuse, examples, a Logging Server may be in the same program, such as a name service, residing in the same program. If other services change, if the name service modifies the search algorithm, all the code in the service needs to be re-modified, edited, and static. And terminated a running process to change the code in the service, also ending the log service. This interrupt is unacceptable in some high reliability systems, such as Telecommunication Switches and Customer Care Call Center. System performance may scale poorly since associating a separate process with each service ties up OS resources, such as I / O handles, virtual memory, and process table slots. This design is particularly wasteful if services are often idle. Moreover, processes can be inefficient For Many Short-Lived Communication Tasks, Such As AsKing A Time Service For The Current Time Or Resolving a Host Address Request Via The Domain Name Service (DNS). System performance extension is small because of interrelated processes and each of its services System resources are closely linked, such as I / O Handle, virtual memory, and process slots. This design is very wasteful if the service is often processed. Moreover, the process may be inefficient to serve many short-libunication tasks, such as inquiry the Time Service to get the current time, or resolve a host address via DNS.
To address the drawbacks of purely static configurations, the ACE Service Configurator framework defines the ACE_Service_Config class. Class Capabilities ACE_Service_Config implements the Facade pattern [GoF] to integrate other classes in the ACE Service Configurator framework and coordinate the activities necessary to manage the services in an Application. this class provides the Following Capabilities: ACE_SERVICE_CONFIG implements Facade Pattern [GOF] combined with classes in other ACE Service Configurator Framework, adjust the required behavior to manage other services in the program. This class provides the following capabilities: It interprets a scripting language that allows applications or administrators to provide the ACE Service Configurator framework with commands, called directives, to locate and initialize a service's implementation at run time, as well as to suspend, resume, reinitialize, and / or shut down a component after it's been initialized Directives can be specified to ACE_Service_Config in either of two ways:. he explained the scripting language allows programs or administrator ACE Service Configurator framework command at runtime, call instruction to The implementation of positioning and initialization services, such as hang, recovery, reinitialization, SHUT DOWN a component after he is initialized. The instruction can be specified in two ways:
Using configuration files (named svc.conf by default) that contain one or more directives containing one or a plurality of the specified configuration file, default svc.conf Programmatically, by passing individual directives as strings Programmatically, by a separate command character string passed
It supports the management of services located in the application (the so-called static services), as well as those that must be linked dynamically (the so-called dynamic services) from separate shared libraries (DLLs). He supported service management.
IT Allows Service Reconfiguration At Run Time Using The Following Mechanisms:
On POSIX platforms, ACE_Service_Config can be integrated with the ACE Reactor framework to reprocess its configuration files upon receipt of a SIGHUP signal any other user-specified signal, such as SIGINT. By passing the "reconfigure" command via ACE_Service_Manager or, as described in Sidebar 31 (page 132). An application can request its ACE_Service_Config to reprocess its configuration files at any time. For example, a Windows directory change notification event can be used to help a program learn when its configuration file changes. This change event can then trigger reprocessing of the configuration. An application can also specify individual directives for its ACE_Service_Config to process at any time via the process_directive () method. program can specify any time individual instruction by process_directive method of ACE_Service_Config at any time. Figure 5.6 the ace_service_config class ace_service_config ace_service_config (ignore_static_svcs: int = 1,
Repository_size: size_t = max_services,
Signum: int = SIGHUP)
Open (argc: int, argv: ace_tchar * [],
Logger_key: const ace_tchar * = ace_default_logger_key,
Ignore_static_svcs: int = 1,
Ignore_Default_svc_conf: int = 0,
Ignore_debug_flag: INT = 0): INT
Close (): int
Process_Directives (): int
Process_directive (Directive: ACE_TCHAR []): INT
Reconfigure (): int
suspend (name: const ace_tchar []): int
Resume (name: const ACE_TCHAR []):.. Int The interface for ACE_Service_Config is shown in Figure 5.6 This class has a rich interface since it exports all the features in the ACE Service Configurator framework We therefore group the description of its methods into The Three Categories Described Below. 1. Service Configurator Life Cycle Management Methods. The Following Methods Initialize and Shut Down The Ace_Service_config: Lifecycle Management Method
ACE Class Description ACE_Service_Config () open () These methods create and initialize the ACE_Service_Config. Close () This method shuts down and finalizes all the configured services and deletes the resources allocated when the ACE_Service_Config was initialized. There's only one instance of ACE_Service_Config's state in a process. This class is a variant of the Monostate pattern [CB97], which ensures a unique state for its instances by declaring all data members to be static. moreover, the ACE_Service_Config methods are also declared as static. The ACE_Service_Config constructor, however, is the only way to set the maximum size of the ACE_Service_Repository. It's also the only programmatic way to change the signal number that can be registered with the reactor to trigger reconfigurations. Instantiating an instance of ACE_Service_Config therefore simply sets these parameters for the underlying monostate object and Does Not Create a Separate Configuration Object. thus, the ace_service_c Onfig Destructor is a no-op. ACE_SERVICE_CONFIG status is only one instance in the entire process. This class is a variant of the monostate pattern [cb97] guarantees the unique state of the instance by declaring all member variables as static. And the ACE_SERVICE_CONFIG method is also static. The constructor of the ACE_Service is the only way to set the size of the ACE_SERVICE_REPOSTORY. He can also change the Signal Number That Can Be Registered with Reactor to trigger the reconfiguration by programming methods. Simple Set the parameters of Monostate Object to install an ACE_SERVICE_CONFIG instance, do not create a separate configuration object, the ace_service_config becoming function is not operated. The open () method is the common way of initializing the ACE_Service_Config. It parses arguments passed in the argc and argv parameters, skipping the first parameter (argv [0]) since that's the name of the program. The options recognized by ACE_Service_Config are outlined In The Following Table: Open is a method that is usually initialized ACE_SERVICE_CONFIG.
He parsed the parameters introduced through the ARGC and Argv, skip Argv [0] because it is the name of the program. The following is an other option: option description '-b' Turn The Application Process Into a daemon (see Sidebar 5 on page 32). Transformation into a daemon. '-D' Display diagnostic information as directives are processed. Diagnostic Information '-f' display instruction processing Supply a file containing directives other than the default svc.conf file. This argument can be repeated to supply multiple configuration files. Configured to provide a file. '-N' Do not process static directives, which eliminates the need to initialize the ACE_Service_Repository statically. '-S' Designate the signal to be used to cause the ACE_Service_Config to reprocess its configuration file. By default, SIGHUP is used. To develop a The signal is used to resize the configuration file. '-S' supply a directive to the ace_service_config directly. This Argument CAN Be Repeated to Process Multiple Directives. A directive is provided to ACE_SERVICE_CONFIG. '-Y' Process static directives, which requires the static initialization of the ACE_Service_Repository. Static connection 2. Service configuration methods. After parsing all its argc / argv arguments, the ACE_Service_Config :: open () method calls one or both of the following methods To configure the application: Service configuration method. Open is configured by calling the following method.
Method Description process_directives () Process a sequence of directives that are stored in the designated script file (s). This method allows multiple directives to be stored persistently and processed iteratively in batch mode. Each service configuration directive in each configuration file is executed in the order they are specified. process_directive () Process a single directive passed as a string.This method allows directives to be created dynamically and processed interactively, such as via a GUI or a network connection. The following table summarizes the service configuration directives that can be Processed by these TWO ACE_SERVICE_CONFIG METHODS: The following is the service configuration instruction that ACE_SERVICE_CONFIG can process. Directive Description dynamic Dynamically link a service and initialize it by calling its init () hook method. Dynamic Link static Call the init () hook method to initialize a service that was linked statically. Statically linked remove Remove a service completely, that is, call its fini () hook method and unlink it from the application process when it's no longer used. to delete a service suspend Call a service's suspend () hook method to pause it without removing it. suspend service resume Call a service's resume () hook method to continue processing a service that was suspended earlier. resume service stream Initialize an ordered list of hierarchically related modules. We describe the syntax and semantics for the tokens in each of these directives below.
Dynamically link and initialize a service: dynamic svc-name svc-type DLL-name: factory_func () [ "argc / argv options"] The dynamic directive instructs the ACE Service Configurator framework to dynamically link and initialize a service object The svc-. name is the name assigned to the service. The svc-type designates the type of the service, which can be a Service_Object *, Module *, or Stream *. DLL-name is the name of the dynamic link library that contains the factory_func ( ) symbol. This symbol is the entry point for an extern "C" function that the ACE_Service_Config interpreter invokes to create an instance of a service. If the svc-type is Service_Object * then factory_func () must return a pointer to an object derived from ACE_Service_Object. The factory_func () symbol should have a leading underscore character since linkers add that character to externally visible symbols. DLL-name can be either a full pathname or a filename without a suffix. If it's a full pathname, the ACE_DLL :: open () Method Described in Sidebar 33 IS Used to DynamicalLink The Designated File Into The Application Process. if IT '
sa filename, however, ACE_DLL :: open () uses ACE :: ldfind () (also described in Sidebar 33) to locate the DLL and dynamically link it into the address space of the process via ACE_DLL :: open (). The dynamic directive can be used portably across operating systems since ACE encapsulates these platform details. The argc / argv options are an optional list of parameters that can be supplied to initialize a service object via its init () hook method. The ACE Service Configurator framework uses the ACE_ARGV class described in Sidebar 35 (page 148) to separate the string into arguments and substitute the values of environment variables that are included in the string Initialize a statically linked service:. static svc-name [ "argc / argv options"] Although ACE_Service_Config is commonly used to configure services dynamically, it can also be used to configure services statically via the static directive. The svc-name and optional argc / argv options are the same as those in the dynamic directive. The synta x is simpler, however, since the service object must already be linked into the executable program image statically. Thus, there's no need to either locate and link a DLL or call a factory function to create a service object. Static configuration trades flexibility for increased security, which may be useful for certain types of servers that must contain only trusted, statically linked services. Recall from Sidebar 31 (page 132) that static service loading is disabled by default. static service loading must therefore be enabled explicitly to use them, OR else the static directive will have no effect.sidebar 33: The ace_dll class application thing link and unlink Dlls Explicitly Can Encounter The Following Problems:
- A nonuniform programming interface that's even less portable than the Socket API described in Chapter 3 of C NPv1- Unsafe types that invite errors and misuse because the native OS DLL APIs return weakly typed handles that are passed to DLL functions, such as those Used to Locate Symbols and Unlink The DLL
- Potential Resource Leaks, Since It's Possible To Forget To Release DLL Handles
To address these problems, ACE defines the ACE_DLL wrapper facade class to encapsulate explicit linking / unlinking functionality. This class eliminates the need for applications to use error-prone, weakly typed handles and also ensures that resources are released properly by its destructor. In addition , IT Uses the ace :: ldfind () Method to Locate Dlls Via the Following Algorithms:
DLL filename expansion? ACE :: ldfind () determines the name of the DLL by adding the appropriate prefix and suffix. For example, it adds the lib prefix and .so suffix for Solaris and the .dll suffix for Windows. DLL search path? ACE :: ldfind () will also search for the designated DLL using the platform's DLL search path environment variable. for example, it searches for DLLs using LD_LIBRARY_PATH on many UNIX systems and pATH on Windows. The key methods in the ACE_DLL class are outlined in The following table.
ACE Class Description ACE_DLL () open () Opens and dynamically links a designated DLL ACE_DLL () close () Closes and optionally unlinks the DLL symbol () Returns a pointer to a function or object in the DLL error () Returns a string explaining which Failure Occurred The Interface of Ace_dll Is Shown In The Figure Below. ACE_DLL
- Handle_: ace_shlib_handle
Open (name: const ace_tchar *,
Mode: int = ace_default_shlib_mode, close_on_destruct: int = 1): int =
Close (): int
Symbol (Name: const a_tchar *): void *
Error (void): ACE_TCHAR * Remove a service completely:. Remove svc-name The remove directive causes the ACE_Service_Config interpreter to query the ACE_Service_Repository for the named service If this service is located, the interpreter invokes its fini () hook method, which performs the activities needed to clean up resources when the service shuts down. If a service destruction function pointer is associated with the service object, it's called to destroy the service object itself (the ACE_FACTORY_DEFINE macro defines this function automatically). Finally, if the service was linked dynamically from a DLL, it's unlinked via the ACE_DLL :: close () method. Since a DLL can be linked multiple times in a process, ACE_DLL :: close () ensures that the DLL is only unlinked when it's no longer in use Suspend A Service Without Removing It: Suspend SVC-Name The Suspend Directive Causes The ace_Service_config Interpreter To Query THE_SERVICE_REPOSTORY for The Designated SVC-Name Service. If T . His service is located, its suspend () hook method is invoked A service can override this method to implement the appropriate actions needed to suspend its processing Resume a previously suspended service:. Resume svc-name The resume directive causes the ACE_Service_Config interpreter to query the ACE_Service_Repository for the designated svc-name service. If this service is located, its resume () hook method is invoked. A service can override this method to implement the appropriate actions needed to resume its processing, which typically reverse the effects of the suspend () Method. Initialize An ORDERED LIST OF HIERARCHICLY Related Modules: Stream SVC-Name '{' Module-List '}'
The stream directive causes the ACE_Service_Config interpreter to initialize an ordered list of hierarchically related modules. Each module consists of a pair of services that are interconnected and communicate by passing ACE_Message_Block objects. The implementation of the stream directive uses the ACE Streams framework described in Chapter 9 . The complete Backus / Naur Format (BNF) syntax for svc.conf files parsed by the ACE_Service_Config is shown in Figure 5.7. Sidebar 34 (page 146) describes how to specify svc.conf files using the optional XML syntax. 3. Utility methods . ACE_Service_Config defines the following utility methods:.. Method Description reconfigure () Reprocess the current configuration file (s) suspend () Suspend a service, identified by name resume () Resume a suspended service, identified by name Figure 5.7 BNF for the. ACE_SERVICE_CONFIG SCRIPTING LANGUAGE
It statically configures an instance of Service_Reporter. It dynamically links and configures the Reactor_Logging_Server_Adapter template from the Example portion of Section 5.2 into the server's address space. We then show how to dynamically reconfigure the server to support a different implementation of a reactive logging service.
Sidebar 34: Using XML to Configure Services The ACE_Service_Config class can be configured to interpret an XML-based scripting language The Document Type Definition (DTD) for this language is shown below:
Status (Active | Inactive) "Active"
Type (Module | Service_Object | Stream)
#Required>
Path cdata #implied
Params CData #implied>
Params CData #implied>
The syntax of this XML-based configuration language is different from the one in Figure 5.5, but its semantics are the same. Although it's more verbose to compose, the ACE XML-based configuration file format is more flexible. For example, users can plug in customized XML event handlers to extend the behavior of the ACE Service Configurator framework without modifying the underlying ACE implementation. The XML configuration file format is relatively new (it was introduced in ACE 5.3). It's therefore not yet the default used by the ACE Service Configurator framework. Users can choose the XML-based Service Configurator by compiling ACE with the ACE_HAS_XML_SVC_CONF macro enabled. ACE provides the svcconf-convert.pl perl script to translate original format files into the new XML format THE Script is located in The $ ACE_ROOT / BIN / DIRECTORY. INITIAL SERVER Configuration. We start by Writing the Following Generic Main () Program in configurable_logging_se rver.cpp. This program configures the Service_Reporter and Reactor_Logging_Server_Adapter services into an application process and then runs the reactor's event loop. 1 #include "ace / OS.h" 2 #include "ace / Service_Config.h"
3 #include "ace / reactor.h"
4
5 INT ACE_TMAIN (int Argc, ACE_TCHAR * Argv []) {
6 ACE_STATIC_SVC_REGISTER (REPORTER);
Seduce
8 ace_service_config :: Open
9 (Argc, Argv, ACE_DEFAULT_LOGGGER_KEY, 0);
10
11 ace_reactor :: instance () -> Run_REACTOR_EVENT_LOOP ();
12 return 0;
13} Lines 1? There are no service-specific header files () program (or code) in the main. It's therefore completely generic, and can be reused for many programs that are configured using the ACE Service Configurator and Reactor frameworks. Line 5 Replace the main () entry point name with the ACE_TMAIN macro. This macro uses the alternate wmain () entry point on Windows when Unicode is enabled, and the usual main () in all other situations. Line 6 Register the static Reporter service with the ACE service Configurator framework. Although the framework now knows of the service, it is not activated unless a service configuration directive causes it to be. registering a static Reporter service to ACE_Service Configurator framework. Although the framework knows this service, he is not activated unless the service configuration instruction activates him.
#if defined (ACE_LACKS_STATIC_CONSTRUCTORS) # define ACE_STATIC_SVC_REQUIRE (SERVICE_CLASS) / class ACE_Static_Svc _ ## SERVICE_CLASS {/ public: / ACE_Static_Svc _ ## SERVICE_CLASS () {/ ACE_Service_Config :: static_svcs () -> insert (/ & ace_svc_desc _ ## SERVICE_CLASS); /} /}; # define ACE_STATIC_SVC_REGISTER (sERVICE_CLASS) / ACE_Static_Svc _ ## sERVICE_CLASS ace_static_svc _ ## sERVICE_CLASS #else / * ACE_LACKS_STATIC_CONSTRUCTORS * / # define ACE_STATIC_SVC_REQUIRE (sERVICE_CLASS) / class ACE_Static_Svc _ ## sERVICE_CLASS {/ public:! / ACE_Static_Svc _ ## sERVICE_CLASS () { / ACE_Service_Config :: static_svcs () -> insert (/ & ace_svc_desc _ ## sERVICE_CLASS); /} /}; / static ACE_Static_Svc _ ## sERVICE_CLASS ace_static_svc _ ## sERVICE_CLASS; #define ACE_STATIC_SVC_REGISTER (sERVICE_CLASS) do {} while (0) #endif / *! ACE_LACKS_STATIC_CONSTRUCTORS * / Lines 8? Call ACE_Service_Config :: open () to configure the application. All decisions about which service (s) to load, and all of the service parameters, are located in the service co Nfiguration File, Which Is External To The Binary Application Program. Weimle I / O Events from Clients. Calling ACE_SERVICE_CONFIG :: Open to configure programs, all service loads are located in binary Profile outside the program, then we handle the Reactor event loop to process I / O events from the client.
Since we know that our program will activate the static Service_Reporter service, we added the fourth argument (and by necessity, the third) to ACE_Service_Config :: open () to explicitly enable static service loading. If we instead decided to leave this decision to the User Or Administrator, That Argument Would NOT BE Suppl, And The User Would Choose To Enable or Disable Static Services BY SUPPLYING THE --Y Option On The Command Line. Because the program activates static service, the fourth parameter is set to 0 It is clear that the static service can be loaded. If we leave this decision to the user or administrator, they can load static services at the command line. When ace_service_config :: open () is called, it uses the ace_service_config :: process_directives () Method to interpret the svc.conf file below: 1 static service_reporter "-p $ service_reporter_port" 2
3 Dynamic Server_Logging_Daemon Service_Object *
4 SLD: _MAKE_SERVER_LOGGGING_DAEMON ()
5 "$ SERVER_LOGGING_DAEMON_PORT" Line 1 The Service_Reporter code, registration information, and factory function were all statically linked into the executable program. This directive therefore simply causes the Service Configurator framework to activate the service by calling Service_Reporter :: init () (page 132 ). The argc / argv arguments passed to init () are the string "-p" and an expansion of the SERVICE_REPORTER_PORT environment variable. The Service Configurator framework expands this environment variable automatically using the ACE_ARGV class described in Sidebar 35. ACE_ARGV recognizes SERVICE_REPORTER_PORT as an environment variable by its leading $ character and substitutes its associated value. The ACE_STATIC_SVC_REQUIRE macro used in Service_Reporter.cpp (page 135) ensures the Service_Reporter is registered with ACE_Service_Repository before the ACE_Service_Config :: open () method is called. The first line of The Service_Reporter Code, registration information, factory functions are static connection to executable. The instruction causes Service Configurator Framework to activate the service by calling service_reporter :: init (). The Argc / Argv parameter passes the expansion of the init () and service_reporter_port environment variables through -p. Service Configurator Framework is an ACE_ARGV class to extend environment variables. ACE-Argv identifies the environment variable through the $ previously variable, replaces the associated value. ACE_STATIC_SVCREQUIRE Macro guarantees that Service_Reporter is registered in ACE_SERVICE_REPOSTORY before the ACE_SERVICE_CONFIG :: Open () call. Sidebar 35: The ace_argv class the ace_argv class is a useful utility class what can
Transform a string into an argc / argv-style vector of strings Incrementally assemble a set of strings into an argc / argv vector Transform an argc / argv-style vector into a string During the transformation, the class can substitute environment variable values for each $ -delimited environment variable name encountered. ACE_ARGV provides an easy and efficient mechanism to create arbitrary command-line arguments. Consider its use whenever command-line processing is required, especially when environment variable substitution is desirable. ACE uses ACE_ARGV extensively, particularly in its Service .? Configurator framework Lines 3 This code configures the server logging daemon via the following steps:. Dynamically link the SLD DLL into the address space of the process Use the ACE_DLL class described in Sidebar 33 (page 143) to extract the _make_Server_Logging_Daemon () factory Function from the SLD DLL SYMBOL TABLE. The factory function is caled to allocate a server_logging_daemon object. The Seri vice Configurator framework calls the service object's Server_Logging_Daemon :: init () hook method, passing as its argc / argv arguments an expansion of the SERVER_LOGGING_DAEMON_PORT environment variable that designates the port number where the server logging daemon listens for client connection requests. If init () Succeeds, The Server_Logging_daemon Pointer Is Stored In The Ace_Service_Repository under the name "server_logging_daemon". Dynamically connect SLD.dll to process address space. Remove the factory function from the SLD.dll symbol mark _make_server_logging_daemon (), and call the factory function to create a Server_Logging_Daemon object. Service configurator frame call server_logging_daemon :: init (), pass server_logging_daemon_port as Argc / Argv.
Sidebar 36 Illustrates An XML Version of The Svc.conf File Shown Above.
Sidebar 36: An Xml Svc.conf File Example The XML Representation of The Svc.conf File Shown On Page 147 Is Shown Below: 1 3 params = '- p $ service_reporter_port' /> 4 5 6 TYPE = 'Service_Object'> 7 8 init = '_ make_server_logging_daemon' 9 params = $ server_logging_daemon_port '/> 10 dynamic> 11 ACE_Svc_Conf> The XML svc.conf file is more verbose than the original format since it specifies field names explicitly. However, the XML format allows svc.conf files to express expanded capabilities, since new sections and fields can be added without affecting . existing syntax There's also no threat to backwards compatibility, as might occur if fields were added to the original format or the field order changed The SLD_DLL is generated from the following SLD.cpp file:. #include "Reactor_Logging_Server_Adapter.h" #include "logging_acceptor.h" #include "SLD_EXPORT.H" TYPEDEF Reactor_logging_server_adapter Server_logging_daemon; ACE_FACTORY_DEFINE (SLD, Server_Logging_Daemon) The SLD.cpp file contains the Server_Logging_Daemon type definition that instantiates the Reactor_Logging_Server_Adapter template with the Logging_Acceptor class (page 54). The ACE_FACTORY_DEFINE macro generates the _make_Server_Logging_Daemon () factory function in the DLL containing the service code. If code outside the service DLL needs to refer to the factory function, it can use the ACE_FACTORY_DECLARE macro to declare the _make_Server_Logging_Daemon () factory function with the proper import declaration. SLD.CPP contains Server_Logging_Daemon type definition template class instantiation parameters Logging_Acceptor Reactor_Logging_Server_Adapter. The ACE_FACTORY_DEFINE macro generates the _make_server_logging_daemon factory function in the DLL containing the service code. If the code is outside the service DLL, Needs to Refer to Factory Function, it can use the ACE_FACTORY_DECLARE macro to declare _make_server_logging_daemon () Factory function via the appropriate import declaration. ACE's import / export helper macros are described in Sidebar 37 (page 150). These macros help to ensure that a DLL's externally visible symbols are exported properly from the DLL on all supported platforms, as well as allowing the DLL's users to import them properly. Applying the export macros within the ACE service macros allow the ACE Service Configurator framework to look up the factory function's entry point symbol when activating a service. ACE import and export in the macro described in Sidebar37. These macros ensure that the external visible symbols of the DLL are derived from the DLL to be exported to all supported platforms, and the use of the use of the DLL is equivalent to import them. When an service is activated, the application exports the macro ACE_SERVICE Configurator Framework to find the entry symbol of the factory function. Sidebar 37:. The ACE DLL Import / Export Macros Windows has specific rules for explicitly importing and exporting symbols in DLLs Developers with a UNIX background may not have encountered these rules in the past, but they are important for managing symbol usage in DLLs on Windows . ACE makes it easy to conform to these rules by supplying a script that generates the necessary import / export declarations and a set of guidelines for using them successfully to ease porting, the following procedure can be used on all platforms that ACE runs on.: Select a concise mnemonic for each DLL to be built. Run the $ ACE_ROOT / bin / generate_export_file.pl Perl script, specifying the DLL's mnemonic on the command line. The script will generate a platform-independent header file and write it to the standard output . _ _ E e in u u u 的 a e keyword Symbols decorated using the above guidelines will be declared using __declspec (dllexport) when built in their DLL When referenced from components outside the DLL, the symbols will be declared __declspec (dllimport). If you choose a separate mnemonic for each DLL and use them consistently , it will be straightforward to build and use DLLs across all OS platforms. The UML sequence diagram in Figure 5.8 illustrates the steps involved in configuring the server logging daemon based on the svc.conf file shown above. At program start time, the object generated by the ACE_STATIC_SVC_REQUIRE macro registers the Service_Reporter information created using the ACE_STATIC_SVC_DEFINE macro into ACE_Service_Config. When the ACE_Service_Config :: open () method is called it uses the specified factory function to instantiate a Service_Reporter object, but does not activate it. The open () Method dam (), Which Interprets the Directives in the svc.conf file. The first directive activity S The Static Service_reporter Service. The Second Directive Triggers The Following Actions: Figure 5.8. UML SEQUENCE DIAGRAGRAGRAGRAGRAGRAGRAGRAGRAM for Configuring The Logging Server The SLD DLL is linked dynamically The _make_Server_Logging_Daemon factory function is called to create an instance of Reactor_Logging_Server_Adapter The new service object's init () method is called to activate the service When all configuration activities are done, the main () program calls ACE_Reactor...: : run_reactor_event_loop () At that point, the services are running, just like the objects that were configured statically in previous examples Reconfiguring the server The ACE Service Configurator framework can reconfigure a server at run time in response to external events, such as... signals or commands. At this point, the framework rereads its svc.conf file (s) and performs the designated directives, such as inserting or removing service objects into or from a server, and suspending or resuming existing service objects. We now illustrate how To Use these features to reconfigure Our Server Logging Daemon Dynamical, ACE Service Configurator Framework By response external events can be configured in runtime reconfiguration Server such as Signals or Commands. At this time, the frame rereads the SVC.conf Configure the execution of the specified instruction, such as insert or delete the service object, hang, or restore the existing service object. Let me explain how to use these features to dynamically configure our logging daemon. The Initial Configuration of the Logging Server Has The Following Limitations: The initial configuration has the following limitations It uses the Logging_Acceptor implementation from Section 3.3 (page 54), which does not time out logging handlers that remain idle for long periods of time. He uses Logging_Acceptor achieve, logging handlers remain idle for a long time without a timeout. There is no way to shut down the run_reactor_event_loop () Method Called on the ace_reactor singleton. There is no way to turn off the run_reactor_event_loop () method. We can add these capabilities without affecting existing code or the Service_Reporter service in the process by defining a new svc.conf file and instructing the server to reconfigure itself by sending it a signal, such as SIGHUP or SIGINT. We add these properties does not affect the existence of The service_reporter service in the code or process is re-configured by defining a new SVC.conf file and by sending a signal such as SIGHUP or SIGINT. 1 Remove Server_Logging_Daemon2 3 Dynamic Server_Logging_Daemon Service_Object * 4 SLDEX: _MAKE_SERVER_LOGGING_DAEMON_EX () 5 "$ server_logging_daemon_port" 6 7 Dynamic Server_Shutdown Service_Object * 8 SLDex: _make_Server_Shutdown () This svc.conf file assumes the server process is currently running with the Server_Logging_Daemon already configured The ACE Service Configurator framework provides configuration mechanisms and assumes the policies that determine when and what to reconfigure are handled by an administrator or another. This file assumes that Server_Logging_Daemon has been configured in the service process. Line 1 Remove the existing server logging daemon from the ACE service repository and unlink it from the application's address space. Lines 3? Dynamically configure a different instantiation of the Reactor_Logging_Server_Adapter template into the address space of the server logging daemon. In particular, the _make_Server_Logging_Daemon_Ex ( ) factory function is created by the ACE_FACTORY_DEFINE macro shown below in the SLDex.cpp file, which is used to generate the SLDex DLL.typedef Reactor_Logging_Server_Adapter ACE_FACTORY_DEFINE (SLDEX, Server_Logging_Daemon_Ex) This macro instantiates the Reactor_Logging_Server_Adapter template with the Logging_Acceptor_Ex (page 67). Lines 7? Dynamically configure a Server_Shutdown service object that uses the controller () function (page 98) and Quit_Handler class (page 98) to wait for an administrator to shut down the server via a command on its standard input The Server_Shutdown class shown below inherits from ACE_Service_Object so that we can via manage its life cycle the ACE Service Configurator framework.class Server_Shutdown:. public ACE_Service_Object { PUBLIC: Server_shutdown :: init () spawns a thread to run the controller () function: Virtual int init (int, ACE_TCHAR * []) { Reactor_ = ace_reactor :: instance (); Return ACE_THREAD_MANAGER :: Instance () -> spawn (Controller, Reactor_, THR_Detached); } We pass the THR_DETACHED flag to spawn so that the controller's thread identifier and other resources are reclaimed by the OS automatically after the thread terminates The Server_Shutdown :: fini () method notifies the reactor to shut down:. Virtual int fini () { Quit_handler * quit_handler = 0; ACE_NEW_RETURN (Quit_Handler, Quit_handler (Reactor_), -1); Return Reactor_-> Notify (Quit_Handler); } // ... Other method OMIMITTED ... Private: ACE_REACTOR * Reactor_; }; We use ace_factory_define to generate the _make_server_shutdown () Factory function needed by the ace service configurator framework. We use ACE_FACTORY_DEFINE to generate the _make_server_shutdown () factory function. # Define ACE_FACTORY_DEFINE (CLS, SERVICE_CLASS) / void _gobble _ ## SERVICE_CLASS (void * p) {/ ACE_Service_Object * _p = static_cast Figure 5.9. UML SEQUENCE DIAGRAM for Reconfiguring The Logging Server The dynamic reconfiguration mechanism in the ACE Service Configurator framework enables developers to modify server functionality or fine-tune performance without extensive redevelopment and reinstallation effort. For example, debugging a faulty implementation of the logging service simply involves the dynamic reconfiguration of a functionally equivalent service that contains additional instrumentation to help identify the erroneous behavior. This reconfiguration process may be performed without modifying, recompiling, relinking, or restarting the currently executing server logging daemon. In particular, this reconfiguration does not affect the Service_Reporter that was configured statically. dynamic weight The configuration mechanism allows the developer to modify the feature or performance does not cost expensive re-developing costs. For example, debug a shortcoming of a Logging service Simple dynamic reproduction of a function equal to an identification error. This reconfiguration process does not need to be modified, compiled, connected, and restarted the current executed server logging daemon. A particularly configured service_reporter. Ru-BRD