This directory provides a number of network services that utilize the ACE wrapper features. . Logging_Strategy -- Controls the output of all services that are invoked along with the Logging_Strategy service. Please see below for details on how to control the output. . [Thr_]Server_Logging_Handler.* -- Implements server portion of the ACE distributed logging service. Both multi-threaded and single-threaded implementations are provided. . Client_Logging_Handler.* -- Implements the client portion of the ACE distributed logging service. . Name_Handler.* -- Implements a distributed name service that allows applications to bind, find, and unbind names in a distributed system. . Token_Handler.* -- Implements a distributed token service that allows applications to acquire and release locks in a distributed system. . Time_Handler.* -- Implements a distributed time service that allows distributed applications to synchronize their time. The remainder of this README file explains how these services work. ==================== Logging_Strategy Service ==================== The Logging_Strategy Service can be used to control the output of all the network services. It can be invoked with certain flags that determine where the output of all the services should go. The Logging_Strategy Service sets the flags in ACE_Log_Msg which in turn controls all the streams through macros such as ACE_DEBUG, ACE_ERROR, and ACE_ERROR_RETURN. If default behavior is required, the Logging_Strategy Service need not be invoked or it can be invoked with no paramaters. Here are the command line arguments that can be given to the Logging_Strategy Service: -f || (etc...) where a flag can be any of the following: STDERR -- Write messages to stderr. LOGGER -- Write messages to the local client logger deamon. OSTREAM -- Write messages to the ostream that gets created by specifying a filename (see below) VERBOSE -- Display messages in a verbose manner SILENT -- Do not print messages at all Note: If more than one flag is specified, the flags need to be 'OR'ed as above syntax shows. Make sure there is no space in between the flag and '|'. -s filename If the OSTREAM flag is set, this can be used to specify the filename where the output should be directed. Note that if the OSTREAM flag is set and no filename is specified, ACE_DEFAULT_LOGFILE will be used to write the output to. Examples: To direct output only to STDERR, specify command line arguments as: "-f STDERR" To direct output to both STDERR and a file called "mylog", specify command line arguments as: "-f STDERR|OSTREAM -s mylog" ==================== Name Service ==================== This file describes the principles of the Name_Server server test application. 1. Startup configuration --------------------- To communicate with the server process, a client needs to know the INET_Addr, where the server offers its service. Class Name_Options holds all the configuration information of the Name Service. This consists of : - nameserver_port : Port number where the server process expects requests - nameserver_host : hostname where the server process resides - namespace_dir : directory that holds the NameBinding databases - process_name : name of the client process (argv[0]), NameBindings of a ProcessLocal namespace are stored in file "namespace_dir/process_name". NameBindings of NodeGlobal namespace are stored in "namespace_dir/localnames". NameBindings of Net_Local namespace are stored in file "namespace_dir/globalnames" on the server host. These configuration parameters are passed to the process as commandline arguments to main: -p nameserver port -h nameserver host -l namespace directory The main program _must_ initialize an instance of Name_Options with name name_options (since the shared libraries depend on this). Main should look like : #include "ace/Name_Options.h" Name_Options name_options; int main(int argc, char **argv) { name_options.process_name(argv[0]); name_options.parse_args (argc, argv); ...... } See the examples in the tests subdirectory of ...Name_Server/Client-Server/client and ...Name_Server/Client-Server/server 2. Class Naming_Context ------------------- This is the main workhorse of the Name Service. It is used by client processes as well as by the server process. It manages all accesses to the appropriate NameBinding database (that is the file where NameBindings are stored) and it also manages the communication between a client process and the server (by using class Name_Proxy, which is a private member of Naming_Context). (Note: no IPC is necessary, if a client process runs on the same host as the server). The strategy for all public methods of Naming_Context is common : 1. Transform the format of the arguments to ACE_SString (which is internally used) if necessary. 2. check if work can be done locally : -> call the appropriate local_* method otherwise call the appropriate global_* method. Removing Name_Bindings from the database (either with unbind or rebind) uses the ACE_Malloc class configured with the ACE_MMAP_Memory_Pool. This allows memory to be reclaimed when name/value tuples are unbound. 3. Class Name_Server ---------------- The Name_Server registers in its run method its Name_Acceptor (instantiated with the INET_Addr) at the Reactor, to receive incoming requests. 4. Class Name_Acceptor ------------------ The Name_Acceptor allocates in its handle_input routine a new instance of class Name_Handler on the heap, and accepts connections into this Name_Handler. 5. Class Name_Handler ----------------- The Name_Handler represents the server side of communication between client and server. It interprets incoming requests to the Net_Local namespace and dele- gates the requests to its own Naming_Context (which is the Net_Local namespace on the current host). For communication it uses the helper classes Name_Request (which up to now needs not only contain the request from the client, but also the appropriate reply from the server) and Name_Reply. Note that I want to change the usage of these classes to make the structure of the software clearer. 6. Dependencies ------------ As the Name service must be able to handle wide character strings, it uses ACE_WString String classes. ==================== Time Service ==================== The following is a description of the Time Server clerk and server services: 1. Startup configuration --------------------- Configuring a server requires specifying the port number of the server. This can be specified as a command line argument as follows: -p A clerk communicates with one or more server processes. To communicate with the server process, a client needs to know the INET_Addr, where the server offers its service. The configuration parameters namely the server port and server host are passed as command line arguments when starting up the clerk service as follows: -h : -h : ... Note that multiple servers can be specified in this manner for the clerk to connect to when it starts up. The server name and the port number need to be concatenated and separated by a ":". In addition, the timeout value can also be specified as a command line argument as follows: -t timeout The timeout value specifies the time interval at which the clerk should query the servers for time updates. By default a Clerk does a non-blocking connect to a server. This can be overridden and a Clerk can be made to do a blocking connect by using the -b flag. Here is what a config file would look like for starting up a server at port 20202: dynamic Time_Service Service_Object * ../lib/netsvcs:_make_ACE_TS_Server_Acceptor() "-p 20202" Here is what a config file would look like for starting up a clerk that needs to connect to two servers, one at tango and one at lambada: dynamic Time_Server_test Service_Object *../lib/netsvcs:_make_ACE_TS_Clerk_Processor () "-h tango:20202 -h lambada:20202 -t 4" 2. Class TS_Server_Handler ----------------------- TS_Server_Handler represents the server side of communication between clerk and server. It interprets incoming requests for time updates, gets the system time, creates a reply in response to the request and then sends the reply to the clerk from which it received the request. For communication it uses the helper class Time_Request. 3. Class TS_Server_Acceptor ------------------------ TS_Server_Acceptor allocates in its handle_input routine a new instance of class TS_Server_Handler on the heap, and accepts connections into this TS_Server_Handler. 4. Class TS_Clerk_Handler ---------------------- TS_Clerk_Handler represents the clerk side of communication between clerk and server. It generates requests for time updates every timeout period and then sends these requests to all the servers it is connected to asynchronously. It receives the replies to these requests from the servers through its handle_input method and then adjusts the time using the roundtrip estimate. It caches this time which is later retrieved by TS_Clerk_Processor. 5. Class TS_Clerk_Processor ------------------------ TS_Clerk_Processor creates a new instance of TS_Clerk_Handler for every server connection it needs to create. It periodically calls send_request() of every TS_Clerk_Handler to send a request for time update to all the servers. In the process, it retrieves the latest time cached by each TS_Clerk_Handler and then uses it to compute its notion of the local system time. 6. Algorithms ---------- Currently, updating the system time involves taking the average of all the times received from the servers.