diff options
author | doccvs <doccvs@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2001-01-19 19:28:41 +0000 |
---|---|---|
committer | doccvs <doccvs@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2001-01-19 19:28:41 +0000 |
commit | ab68d4c9cc337ae788e31441c14d16c6b4a9c3f4 (patch) | |
tree | 43b3749f8fd37ba4ded1eab72def6c97c8394400 /docs | |
parent | 138ab62d6cd7762ad41f23d634b2ffdf4476e01f (diff) | |
download | ATCD-ab68d4c9cc337ae788e31441c14d16c6b4a9c3f4.tar.gz |
ChangeLogTag: Fri Jan 19 11:22:42 2001 Priyanka Gontla <pgontla@ece.uci.edu>
Diffstat (limited to 'docs')
-rw-r--r-- | docs/tutorials/022/Acceptor_Service.cpp | 154 | ||||
-rw-r--r-- | docs/tutorials/022/Acceptor_Service.h | 93 | ||||
-rw-r--r-- | docs/tutorials/022/Makefile | 666 | ||||
-rw-r--r-- | docs/tutorials/022/client/Makefile | 47 | ||||
-rw-r--r-- | docs/tutorials/022/client/client.cpp | 216 | ||||
-rw-r--r-- | docs/tutorials/022/client_handler.cpp | 225 | ||||
-rw-r--r-- | docs/tutorials/022/client_handler.h | 100 | ||||
-rw-r--r-- | docs/tutorials/022/page01.html | 43 | ||||
-rw-r--r-- | docs/tutorials/022/page02.html | 98 | ||||
-rw-r--r-- | docs/tutorials/022/page03.html | 122 | ||||
-rw-r--r-- | docs/tutorials/022/page04.html | 176 | ||||
-rw-r--r-- | docs/tutorials/022/page05.html | 130 | ||||
-rw-r--r-- | docs/tutorials/022/server.cpp | 56 | ||||
-rw-r--r-- | docs/tutorials/022/svc.conf | 9 |
14 files changed, 2135 insertions, 0 deletions
diff --git a/docs/tutorials/022/Acceptor_Service.cpp b/docs/tutorials/022/Acceptor_Service.cpp new file mode 100644 index 00000000000..aa4976cc228 --- /dev/null +++ b/docs/tutorials/022/Acceptor_Service.cpp @@ -0,0 +1,154 @@ +// $Id$ + +#include "Acceptor_Service.h" +#include "ace/Dynamic_Service.h" + +#include "client_handler.h" + +/* A server has to listen for clients at a known TCP/IP port. The + default ACE port is 10002 (at least on my system) and that's good + enough for what we want to do here. Obviously, a more robust + application would take a command line parameter or read from a + configuration file or do some other clever thing. Just like the + signal handler above, though, that's not what we want to focus on, + so we're taking the easy way out. */ + +static const u_short PORT = ACE_DEFAULT_SERVER_PORT; + +/* As in all our simple tutorials, our contructor also does nothing */ +Acceptor_Service::Acceptor_Service (void) +{ + // Constructor +} + +/* Same in the destructor case */ +Acceptor_Service::~Acceptor_Service (void) +{ + // Constructor +} + +/* This is the virtual method inherited from ACE_Service_Object. This + method is called to initialize the service. In a generic sense, we + initialize everything that is needed to initialize our service + here. Ofcourse we need to do that only if there are not already + initialized. One important point to note here is that we have to + make sure that everything that is initialized here is actually + removed when the service is shutdown */ +int +Acceptor_Service::init (int argc, char *argv[]) +{ + /* As you will see, we will not be using argc and argv here and + hence declare them to be unused variables. This helps us from the + complaints from the picky compilers about unused variables. */ + ACE_UNUSED_ARG (argc); + ACE_UNUSED_ARG (argv); + + /* Lets have a debug statement so that we can know that our + Acceptor_Service will be initialized soon */ + ACE_DEBUG ((LM_DEBUG, + "Starting the Acceptor_Service\n")); + + /* Create an ACE_INET_Addr that represents our endpoint of a + connection. We then open our acceptor object with that Addr. + Doing so tells the acceptor where to listen for connections. + Servers generally listen at "well known" addresses. If not, there + must be some mechanism by which the client is informed of the + server's address. */ + if (this->open (ACE_INET_Addr (PORT), + ACE_Reactor::instance ()) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n", + "open"), + -1); + return 0; +} + +/* This virtual method will be invoked when we pass a directive to the + service configurator framework to remove our service. Remember the + threads and anything else that are initialized in the init + method and remove each of them. If we leave anything that we + initialized still running after this method is invoked ...well .. you + know what happens :-) */ +int +Acceptor_Service::fini (void) +{ + /* Lets have another debug statement to inform us the state of the + service. */ + ACE_DEBUG ((LM_DEBUG, + "Closing down the Acceptor_Service\n")); + + /* Now, lets see what did we start or initialize during the + initialization process. The only thing that we did was opening + our Acceptor to start listening for requests. So, lets close it + down. */ + this->close (); + + return 0; +} + +/* Now, lets see how we can suspend the service that we initialized + and is running. By suspension, we mean that the Reactor still knows + about the service and receives the requests. But, it just keeps + quite even if there are any requests. It actually queues the + requests and sends them to the service once it is resumed. */ +int +Acceptor_Service::suspend (void) +{ +/* You must be wondering, as I did, how we can simply suspend this + service without any complex method invocations. Thanks to our + ACE_Reactor class, we can actually suspend the service by just + invoking the following method and passing a pointer to ourself. + This method actually takes care of all the particulars for + suspending the services and keeps us happy. */ + ACE_Reactor::instance ()->suspend_handler (this); + return 0; +} + +int +Acceptor_Service::resume (void) +{ + /* I had the same question again ... how do I do this ?? As before, + our ACE_Reactor class came to a help with this method. ACE + classes do make life simpler .. don't they !! */ + ACE_Reactor::instance ()->resume_handler (this); + + return 0; +} + +/* The macro to be used to define the factory method and destructor + for our dynamically loadable service. */ +ACE_SVC_FACTORY_DEFINE (Acceptor_Service) + +/* This macro helps to register a statically linked service into the + service configurator. It is defined in ace/OS.h. All the parameters + needed by the service configurator to build and control the + statically linked servuce are configured in a single structure. An + instance of this structure is statically initialized using this + macro. The First parameter is SERVICE_CLASS i.e. the name of the + class that implements the service. As we did implicitly, this class + must derive from ACE_Service_Configurator. The second parameter is + the NAME of the service. This name is used by the service + configurator to match the configuration options provided in the + svc.conf file. The third parameter is the type of the object which + could be either streams or service objects. The next parameter is + the name of the factory function which we defined in our header + file and above using the macros ACE_FACTORY_DECLARE and + ACE_FACTORY_DEFINE. The fifth parameter are a set of options or + flags which are used to control the ownership and life cycle of the + object. The final argument helps us to choose if we want a new + thread for this service. If the argument is not 0, a thread will be + dedicated to this service. .. lots of parameters .. Huh !! */ +ACE_STATIC_SVC_DEFINE (Acceptor_Service, + ACE_TEXT ("Acceptor_Service"), + ACE_SVC_OBJ_T, + &ACE_SVC_NAME (Acceptor_Service), + ACE_Service_Type::DELETE_THIS | ACE_Service_Type::DELETE_OBJ, + 0) + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) +template class ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR>; +template class ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>; +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) +#pragma instantiate ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR> +#pragma instantiate ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ diff --git a/docs/tutorials/022/Acceptor_Service.h b/docs/tutorials/022/Acceptor_Service.h new file mode 100644 index 00000000000..d21bd70a42d --- /dev/null +++ b/docs/tutorials/022/Acceptor_Service.h @@ -0,0 +1,93 @@ +//$Id$ + +#ifndef ACCEPTOR_SERVICE_H +#define ACCEPTOR_SERVICE_H +#include "ace/pre.h" + +/* The ACE_Acceptor<> template lives in the ace/Acceptor.h header + file. */ +#include "ace/Acceptor.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +/* Since we want to work with sockets, we'll need a SOCK_Acceptor to + allow the clients to connect to us. */ +#include "ace/SOCK_Acceptor.h" + +/* The Client_Handler object we develop will be used to handle clients + once they're connected. The ACE_Acceptor<> template's first + parameter requires such an object. In some cases, you can get by + with just a forward declaration on the class, in others you have to + have the whole thing. */ +#include "client_handler.h" + +/* In our original simple server, we instantiated a + ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR> object. We can + make it much simpler and efficient by inheriting our + Acceptor_Service from ACE_Acceptor itself. + + Our Acceptor_Service class also needs to inherit from + ACE_Service_Object. ACE_Service_Object is an abstract class which + includes methods called by the Service Configurator framework to + start, remove, suspend or resume our service. + + You might have noticed that we didnt explicitly inherit from + ACE_Service_Object here. That is because, ACE_Acceptor derives from + ACE_Service_Object and hence there is no need to specify it again. */ + + /* TO Do: Describe what/why ACE_Svc_Export */ + +class ACE_Svc_Export Acceptor_Service : public ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR> +{ + public: + // Constructor + Acceptor_Service (void); + + // Destructor + ~Acceptor_Service (void); + + /* This method is the one which is called by the Service + Configurator Framework to initialize or start the service. */ + virtual int init (int argc, char *argv[]); + + /* Called by the Service Configurator framework to remove this + Service. */ + virtual int fini (void); + + /* You could easily guess that this method is called to suspend the + service by the same Service Configurator Framework. When in the + suspend mode, the service is not removed completely and is *still + there*. The difference is that the service is not in a active + state and doesnot accept requests.*/ + virtual int suspend (void); + + /* And your guess that this method is called to resume the service + is also not wrong. This call brings the service back to the + active state and the service is all ready to accept requests */ + virtual int resume (void); + +}; + +/* The following macros and similar macros which we will use in the + implementation file later are used to define helper functions for + the Service Configurator. As we can easily guess, these macros are + intended to dynamically load ancd configure services using the + svc.conf file. These macros will also help to dynamically configure + even the statically linked services. */ + +/* This macro is used to declare a data structure required to register a + statically linked service into the service configurator. As you can + see it has only one argument which is the name of the class that + implements this service... so Acceptor_Service in our case. */ +ACE_STATIC_SVC_DECLARE (Acceptor_Service) + +/* Once the service implementation is dynamically loaded, the Service + Configurator uses a factory method to create the object. This + macro declares such a factory function with the proper interface + and export macros. */ +ACE_SVC_FACTORY_DECLARE (Acceptor_Service) + +#include "ace/post.h" +#endif /* ACCEPTOR_SERVICE_H */ diff --git a/docs/tutorials/022/Makefile b/docs/tutorials/022/Makefile new file mode 100644 index 00000000000..cee2ab65686 --- /dev/null +++ b/docs/tutorials/022/Makefile @@ -0,0 +1,666 @@ +#---------------------------------------------------------------------------- +# $Id$ +#---------------------------------------------------------------------------- + +#---------------------------------------------------------------------------- +# Local macros +#---------------------------------------------------------------------------- + +# You can generally find a Makefile in the ACE examples, tests or the library +# itself that will satisfy our application needs. This one was taken from +# one of the examples. + + # Define the name of the binary we want to create. There has to be + # a CPP file $(BIN).cpp but it doesn't necessarily have to have your + # main() in it. Most of the time, though, it will. +MAKEFILE = Makefile +BIN = server +LIBNAME = libAcceptor_Server +LIB = $(LIBNAME).a +SHLIB = $(LIBNAME).$(SOEXT) + # Few applications will have a single source file. We use the FILES + # macro to build up a list of additional files to compile. Notice + # that we leave off the extension just as with BIN +FILES = +FILES += Acceptor_Service client_handler + + # Here we use some GNU make extensions to build the SRC macro. Basically, + # we're just adding .cpp to the value of BIN and for each entry of the + # FILES macro. +PSRC = $(addsuffix .cpp,$(BIN)) +LSRC = $(addsuffix .cpp,$(FILES)) + +LDLIBS = + +LIBS += $(ACELIB) + + # The BUILD macro is used by the ACE makefiles. Basically, it tells + # the system what to build. I don't really know what VBIN is other + # than it is constructed from the value of BIN. Just go with it... +BUILD = $(VLIB) $(VSHLIB) $(SHLIBA) $(VBIN) + +#---------------------------------------------------------------------------- +# Include macros and targets +#---------------------------------------------------------------------------- + + # This is where the real power lies! These included makefile components + # are similar to the C++ templates in ACE. That is, they do a tremendous + # amount of work for you and all you have to do is include them. + # As a matter of fact, in our project, I created a single file named + # "app.mk" that includes all of these. Our project makefiles then just + # need to include app.mk to get everything they need. + +include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU +include $(ACE_ROOT)/include/makeinclude/macros.GNU +include $(ACE_ROOT)/include/makeinclude/rules.common.GNU +include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU +include $(ACE_ROOT)/include/makeinclude/rules.lib.GNU +include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU +include $(ACE_ROOT)/include/makeinclude/rules.local.GNU + +#---------------------------------------------------------------------------- +# Local targets +#---------------------------------------------------------------------------- + + # Sometimes I like to reformat my code to make it more readable. This is + # more useful for the comments than anything else. Unfortunately, the + # "indent" program doesn't quite grok C++ so I have to post-process it's + # output just a bit. +Indent : # + for i in $(SRC) $(HDR) ; do \ + indent -npsl -l80 -fca -fc1 -cli0 -cdb < $$i | \ + sed -e 's/: :/::/g' \ + -e 's/^.*\(public:\)/\1/' \ + -e 's/^.*\(protected:\)/\1/' \ + -e 's/^.*\(private:\)/\1/' \ + -e 's/:\(public\)/ : \1/' \ + -e 's/:\(protected\)/ : \1/' \ + -e 's/:\(private\)/ : \1/' \ + > $$i~ ;\ + mv $$i~ $$i ;\ + done + + # One of the targets in the ACE makefiles is "depend". It will invoke + # your compiler in a way that will generate a list of dependencies for + # you. This is a great thing! Unfortunately, it puts all of that mess + # directly into the Makefile. I prefer my Makefile to stay clean and + # uncluttered. The perl script referenced here pulls the dependency + # stuff back out of the Makefile and into a file ".depend" which we then + # include just like the makefile components above. + # + # NOTE: The 'depend' target expects to have GCC available. + # You can do the same thing with other compilers but the ACE + # makefiles and utilities are only wired up to work with GCC. +Depend : depend + perl ../fix.Makefile + +CLEAN : realclean + $(RM) hdr bodies *.pre *.pst .depend + +#---------------------------------------------------------------------------- +# Dependencies +#---------------------------------------------------------------------------- + + # Don't put anything below here. Between the "depend" target and fix.Makefile + # it's guaranteed to be lost! + + # This is inserted by the fix.Makefile script +include .depend +# DO NOT DELETE THIS LINE -- g++dep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. + + +.obj/Acceptor_Service.o .obj/Acceptor_Service.so .shobj/Acceptor_Service.o .shobj/Acceptor_Service.so: Acceptor_Service.cpp Acceptor_Service.h \ + $(ACE_ROOT)/ace/pre.h \ + $(ACE_ROOT)/ace/Service_Config.h \ + $(ACE_ROOT)/ace/Service_Object.h \ + $(ACE_ROOT)/ace/Shared_Object.h \ + $(ACE_ROOT)/ace/ACE.h \ + $(ACE_ROOT)/ace/OS.h \ + $(ACE_ROOT)/ace/post.h \ + $(ACE_ROOT)/ace/ACE_export.h \ + $(ACE_ROOT)/ace/svc_export.h \ + $(ACE_ROOT)/ace/ace_wchar.h \ + $(ACE_ROOT)/ace/ace_wchar.inl \ + $(ACE_ROOT)/ace/OS_Errno.h \ + $(ACE_ROOT)/ace/OS_Export.h \ + $(ACE_ROOT)/ace/OS_Errno.inl \ + $(ACE_ROOT)/ace/OS_Dirent.h \ + $(ACE_ROOT)/ace/OS_Dirent.inl \ + $(ACE_ROOT)/ace/OS_String.h \ + $(ACE_ROOT)/ace/OS_String.inl \ + $(ACE_ROOT)/ace/OS_Memory.h \ + $(ACE_ROOT)/ace/OS_Memory.inl \ + $(ACE_ROOT)/ace/OS_TLI.h \ + $(ACE_ROOT)/ace/OS_TLI.inl \ + $(ACE_ROOT)/ace/Min_Max.h \ + $(ACE_ROOT)/ace/streams.h \ + $(ACE_ROOT)/ace/Basic_Types.h \ + $(ACE_ROOT)/ace/Basic_Types.i \ + $(ACE_ROOT)/ace/Trace.h \ + $(ACE_ROOT)/ace/OS.i \ + $(ACE_ROOT)/ace/Flag_Manip.h \ + $(ACE_ROOT)/ace/Flag_Manip.i \ + $(ACE_ROOT)/ace/Handle_Ops.h \ + $(ACE_ROOT)/ace/Handle_Ops.i \ + $(ACE_ROOT)/ace/Lib_Find.h \ + $(ACE_ROOT)/ace/Lib_Find.i \ + $(ACE_ROOT)/ace/Init_ACE.h \ + $(ACE_ROOT)/ace/Init_ACE.i \ + $(ACE_ROOT)/ace/Sock_Connect.h \ + $(ACE_ROOT)/ace/Sock_Connect.i \ + $(ACE_ROOT)/ace/ACE.i \ + $(ACE_ROOT)/ace/Shared_Object.i \ + $(ACE_ROOT)/ace/Event_Handler.h \ + $(ACE_ROOT)/ace/Event_Handler.i \ + $(ACE_ROOT)/ace/Service_Object.i \ + $(ACE_ROOT)/ace/Signal.h \ + $(ACE_ROOT)/ace/Synch.h \ + $(ACE_ROOT)/ace/Synch.i \ + $(ACE_ROOT)/ace/Synch_T.h \ + $(ACE_ROOT)/ace/Synch_T.i \ + $(ACE_ROOT)/ace/Thread.h \ + $(ACE_ROOT)/ace/Thread_Adapter.h \ + $(ACE_ROOT)/ace/Base_Thread_Adapter.h \ + $(ACE_ROOT)/ace/OS_Log_Msg_Attributes.h \ + $(ACE_ROOT)/ace/OS_Log_Msg_Attributes.inl \ + $(ACE_ROOT)/ace/Base_Thread_Adapter.inl \ + $(ACE_ROOT)/ace/Thread_Adapter.inl \ + $(ACE_ROOT)/ace/Thread.i \ + $(ACE_ROOT)/ace/Atomic_Op.i \ + $(ACE_ROOT)/ace/Synch_T.cpp \ + $(ACE_ROOT)/ace/Log_Msg.h \ + $(ACE_ROOT)/ace/Log_Record.h \ + $(ACE_ROOT)/ace/Log_Priority.h \ + $(ACE_ROOT)/ace/Log_Record.i \ + $(ACE_ROOT)/ace/Containers.h \ + $(ACE_ROOT)/ace/Malloc_Base.h \ + $(ACE_ROOT)/ace/Containers.i \ + $(ACE_ROOT)/ace/Containers_T.h \ + $(ACE_ROOT)/ace/Containers_T.i \ + $(ACE_ROOT)/ace/Containers_T.cpp \ + $(ACE_ROOT)/ace/Malloc.h \ + $(ACE_ROOT)/ace/Malloc.i \ + $(ACE_ROOT)/ace/Malloc_T.h \ + $(ACE_ROOT)/ace/Malloc_Allocator.h \ + $(ACE_ROOT)/ace/Malloc_Allocator.i \ + $(ACE_ROOT)/ace/Free_List.h \ + $(ACE_ROOT)/ace/Free_List.i \ + $(ACE_ROOT)/ace/Free_List.cpp \ + $(ACE_ROOT)/ace/Malloc_T.i \ + $(ACE_ROOT)/ace/Malloc_T.cpp \ + $(ACE_ROOT)/ace/Memory_Pool.h \ + $(ACE_ROOT)/ace/Mem_Map.h \ + $(ACE_ROOT)/ace/Mem_Map.i \ + $(ACE_ROOT)/ace/SV_Semaphore_Complex.h \ + $(ACE_ROOT)/ace/SV_Semaphore_Simple.h \ + $(ACE_ROOT)/ace/SV_Semaphore_Simple.i \ + $(ACE_ROOT)/ace/SV_Semaphore_Complex.i \ + $(ACE_ROOT)/ace/Memory_Pool.i \ + $(ACE_ROOT)/ace/Signal.i \ + $(ACE_ROOT)/ace/SString.h \ + $(ACE_ROOT)/ace/SString.i \ + $(ACE_ROOT)/ace/Service_Config.i \ + $(ACE_ROOT)/ace/Reactor.h \ + $(ACE_ROOT)/ace/Handle_Set.h \ + $(ACE_ROOT)/ace/Handle_Set.i \ + $(ACE_ROOT)/ace/Timer_Queue.h \ + $(ACE_ROOT)/ace/Timer_Queue_T.h \ + $(ACE_ROOT)/ace/Test_and_Set.h \ + $(ACE_ROOT)/ace/Test_and_Set.i \ + $(ACE_ROOT)/ace/Test_and_Set.cpp \ + $(ACE_ROOT)/ace/Timer_Queue_T.i \ + $(ACE_ROOT)/ace/Timer_Queue_T.cpp \ + $(ACE_ROOT)/ace/Reactor.i \ + $(ACE_ROOT)/ace/Reactor_Impl.h \ + $(ACE_ROOT)/ace/Svc_Conf_Tokens.h \ + $(ACE_ROOT)/ace/Acceptor.h \ + $(ACE_ROOT)/ace/Svc_Handler.h \ + $(ACE_ROOT)/ace/Synch_Options.h \ + $(ACE_ROOT)/ace/Synch_Options.i \ + $(ACE_ROOT)/ace/Task.h \ + $(ACE_ROOT)/ace/Thread_Manager.h \ + $(ACE_ROOT)/ace/Singleton.h \ + $(ACE_ROOT)/ace/Singleton.i \ + $(ACE_ROOT)/ace/Singleton.cpp \ + $(ACE_ROOT)/ace/Object_Manager.h \ + $(ACE_ROOT)/ace/Object_Manager.i \ + $(ACE_ROOT)/ace/Managed_Object.h \ + $(ACE_ROOT)/ace/Managed_Object.i \ + $(ACE_ROOT)/ace/Managed_Object.cpp \ + $(ACE_ROOT)/ace/Thread_Manager.i \ + $(ACE_ROOT)/ace/Task.i \ + $(ACE_ROOT)/ace/Task_T.h \ + $(ACE_ROOT)/ace/Message_Queue.h \ + $(ACE_ROOT)/ace/Message_Block.h \ + $(ACE_ROOT)/ace/Message_Block.i \ + $(ACE_ROOT)/ace/Message_Block_T.h \ + $(ACE_ROOT)/ace/Message_Block_T.i \ + $(ACE_ROOT)/ace/Message_Block_T.cpp \ + $(ACE_ROOT)/ace/IO_Cntl_Msg.h \ + $(ACE_ROOT)/ace/Message_Queue_T.h \ + $(ACE_ROOT)/ace/Message_Queue_T.i \ + $(ACE_ROOT)/ace/Message_Queue_T.cpp \ + $(ACE_ROOT)/ace/Strategies.h \ + $(ACE_ROOT)/ace/Strategies_T.h \ + $(ACE_ROOT)/ace/Hash_Map_Manager.h \ + $(ACE_ROOT)/ace/Functor.h \ + $(ACE_ROOT)/ace/Functor.i \ + $(ACE_ROOT)/ace/Functor_T.h \ + $(ACE_ROOT)/ace/Functor_T.i \ + $(ACE_ROOT)/ace/Functor_T.cpp \ + $(ACE_ROOT)/ace/Hash_Map_Manager_T.h \ + $(ACE_ROOT)/ace/Hash_Map_Manager_T.i \ + $(ACE_ROOT)/ace/Hash_Map_Manager_T.cpp \ + $(ACE_ROOT)/ace/Strategies_T.i \ + $(ACE_ROOT)/ace/Strategies_T.cpp \ + $(ACE_ROOT)/ace/Service_Repository.h \ + $(ACE_ROOT)/ace/Service_Types.h \ + $(ACE_ROOT)/ace/Service_Types.i \ + $(ACE_ROOT)/ace/Service_Repository.i \ + $(ACE_ROOT)/ace/WFMO_Reactor.h \ + $(ACE_ROOT)/ace/Process_Mutex.h \ + $(ACE_ROOT)/ace/Process_Mutex.inl \ + $(ACE_ROOT)/ace/WFMO_Reactor.i \ + $(ACE_ROOT)/ace/Strategies.i \ + $(ACE_ROOT)/ace/Message_Queue.i \ + $(ACE_ROOT)/ace/Task_T.i \ + $(ACE_ROOT)/ace/Task_T.cpp \ + $(ACE_ROOT)/ace/Module.h \ + $(ACE_ROOT)/ace/Module.i \ + $(ACE_ROOT)/ace/Module.cpp \ + $(ACE_ROOT)/ace/Stream_Modules.h \ + $(ACE_ROOT)/ace/Stream_Modules.cpp \ + $(ACE_ROOT)/ace/Svc_Handler.cpp \ + $(ACE_ROOT)/ace/Dynamic.h \ + $(ACE_ROOT)/ace/Dynamic.i \ + $(ACE_ROOT)/ace/Acceptor.cpp \ + $(ACE_ROOT)/ace/SOCK_Acceptor.h \ + $(ACE_ROOT)/ace/SOCK_Stream.h \ + $(ACE_ROOT)/ace/SOCK_IO.h \ + $(ACE_ROOT)/ace/SOCK.h \ + $(ACE_ROOT)/ace/Addr.h \ + $(ACE_ROOT)/ace/Addr.i \ + $(ACE_ROOT)/ace/IPC_SAP.h \ + $(ACE_ROOT)/ace/IPC_SAP.i \ + $(ACE_ROOT)/ace/QoS_Session.h \ + $(ACE_ROOT)/ace/INET_Addr.h \ + $(ACE_ROOT)/ace/INET_Addr.i \ + $(ACE_ROOT)/ace/SOCK.i \ + $(ACE_ROOT)/ace/SOCK_IO.i \ + $(ACE_ROOT)/ace/SOCK_Stream.i \ + $(ACE_ROOT)/ace/Time_Value.h \ + $(ACE_ROOT)/ace/SOCK_Acceptor.i client_handler.h \ + $(ACE_ROOT)/ace/Dynamic_Service.h \ + $(ACE_ROOT)/ace/Dynamic_Service_Base.h \ + $(ACE_ROOT)/ace/Dynamic_Service.i \ + $(ACE_ROOT)/ace/Dynamic_Service.cpp + +.obj/client_handler.o .obj/client_handler.so .shobj/client_handler.o .shobj/client_handler.so: client_handler.cpp client_acceptor.h \ + $(ACE_ROOT)/ace/Acceptor.h \ + $(ACE_ROOT)/ace/pre.h \ + $(ACE_ROOT)/ace/Service_Config.h \ + $(ACE_ROOT)/ace/Service_Object.h \ + $(ACE_ROOT)/ace/Shared_Object.h \ + $(ACE_ROOT)/ace/ACE.h \ + $(ACE_ROOT)/ace/OS.h \ + $(ACE_ROOT)/ace/post.h \ + $(ACE_ROOT)/ace/ACE_export.h \ + $(ACE_ROOT)/ace/svc_export.h \ + $(ACE_ROOT)/ace/ace_wchar.h \ + $(ACE_ROOT)/ace/ace_wchar.inl \ + $(ACE_ROOT)/ace/OS_Errno.h \ + $(ACE_ROOT)/ace/OS_Export.h \ + $(ACE_ROOT)/ace/OS_Errno.inl \ + $(ACE_ROOT)/ace/OS_Dirent.h \ + $(ACE_ROOT)/ace/OS_Dirent.inl \ + $(ACE_ROOT)/ace/OS_String.h \ + $(ACE_ROOT)/ace/OS_String.inl \ + $(ACE_ROOT)/ace/OS_Memory.h \ + $(ACE_ROOT)/ace/OS_Memory.inl \ + $(ACE_ROOT)/ace/OS_TLI.h \ + $(ACE_ROOT)/ace/OS_TLI.inl \ + $(ACE_ROOT)/ace/Min_Max.h \ + $(ACE_ROOT)/ace/streams.h \ + $(ACE_ROOT)/ace/Basic_Types.h \ + $(ACE_ROOT)/ace/Basic_Types.i \ + $(ACE_ROOT)/ace/Trace.h \ + $(ACE_ROOT)/ace/OS.i \ + $(ACE_ROOT)/ace/Flag_Manip.h \ + $(ACE_ROOT)/ace/Flag_Manip.i \ + $(ACE_ROOT)/ace/Handle_Ops.h \ + $(ACE_ROOT)/ace/Handle_Ops.i \ + $(ACE_ROOT)/ace/Lib_Find.h \ + $(ACE_ROOT)/ace/Lib_Find.i \ + $(ACE_ROOT)/ace/Init_ACE.h \ + $(ACE_ROOT)/ace/Init_ACE.i \ + $(ACE_ROOT)/ace/Sock_Connect.h \ + $(ACE_ROOT)/ace/Sock_Connect.i \ + $(ACE_ROOT)/ace/ACE.i \ + $(ACE_ROOT)/ace/Shared_Object.i \ + $(ACE_ROOT)/ace/Event_Handler.h \ + $(ACE_ROOT)/ace/Event_Handler.i \ + $(ACE_ROOT)/ace/Service_Object.i \ + $(ACE_ROOT)/ace/Signal.h \ + $(ACE_ROOT)/ace/Synch.h \ + $(ACE_ROOT)/ace/Synch.i \ + $(ACE_ROOT)/ace/Synch_T.h \ + $(ACE_ROOT)/ace/Synch_T.i \ + $(ACE_ROOT)/ace/Thread.h \ + $(ACE_ROOT)/ace/Thread_Adapter.h \ + $(ACE_ROOT)/ace/Base_Thread_Adapter.h \ + $(ACE_ROOT)/ace/OS_Log_Msg_Attributes.h \ + $(ACE_ROOT)/ace/OS_Log_Msg_Attributes.inl \ + $(ACE_ROOT)/ace/Base_Thread_Adapter.inl \ + $(ACE_ROOT)/ace/Thread_Adapter.inl \ + $(ACE_ROOT)/ace/Thread.i \ + $(ACE_ROOT)/ace/Atomic_Op.i \ + $(ACE_ROOT)/ace/Synch_T.cpp \ + $(ACE_ROOT)/ace/Log_Msg.h \ + $(ACE_ROOT)/ace/Log_Record.h \ + $(ACE_ROOT)/ace/Log_Priority.h \ + $(ACE_ROOT)/ace/Log_Record.i \ + $(ACE_ROOT)/ace/Containers.h \ + $(ACE_ROOT)/ace/Malloc_Base.h \ + $(ACE_ROOT)/ace/Containers.i \ + $(ACE_ROOT)/ace/Containers_T.h \ + $(ACE_ROOT)/ace/Containers_T.i \ + $(ACE_ROOT)/ace/Containers_T.cpp \ + $(ACE_ROOT)/ace/Malloc.h \ + $(ACE_ROOT)/ace/Malloc.i \ + $(ACE_ROOT)/ace/Malloc_T.h \ + $(ACE_ROOT)/ace/Malloc_Allocator.h \ + $(ACE_ROOT)/ace/Malloc_Allocator.i \ + $(ACE_ROOT)/ace/Free_List.h \ + $(ACE_ROOT)/ace/Free_List.i \ + $(ACE_ROOT)/ace/Free_List.cpp \ + $(ACE_ROOT)/ace/Malloc_T.i \ + $(ACE_ROOT)/ace/Malloc_T.cpp \ + $(ACE_ROOT)/ace/Memory_Pool.h \ + $(ACE_ROOT)/ace/Mem_Map.h \ + $(ACE_ROOT)/ace/Mem_Map.i \ + $(ACE_ROOT)/ace/SV_Semaphore_Complex.h \ + $(ACE_ROOT)/ace/SV_Semaphore_Simple.h \ + $(ACE_ROOT)/ace/SV_Semaphore_Simple.i \ + $(ACE_ROOT)/ace/SV_Semaphore_Complex.i \ + $(ACE_ROOT)/ace/Memory_Pool.i \ + $(ACE_ROOT)/ace/Signal.i \ + $(ACE_ROOT)/ace/SString.h \ + $(ACE_ROOT)/ace/SString.i \ + $(ACE_ROOT)/ace/Service_Config.i \ + $(ACE_ROOT)/ace/Reactor.h \ + $(ACE_ROOT)/ace/Handle_Set.h \ + $(ACE_ROOT)/ace/Handle_Set.i \ + $(ACE_ROOT)/ace/Timer_Queue.h \ + $(ACE_ROOT)/ace/Timer_Queue_T.h \ + $(ACE_ROOT)/ace/Test_and_Set.h \ + $(ACE_ROOT)/ace/Test_and_Set.i \ + $(ACE_ROOT)/ace/Test_and_Set.cpp \ + $(ACE_ROOT)/ace/Timer_Queue_T.i \ + $(ACE_ROOT)/ace/Timer_Queue_T.cpp \ + $(ACE_ROOT)/ace/Reactor.i \ + $(ACE_ROOT)/ace/Reactor_Impl.h \ + $(ACE_ROOT)/ace/Svc_Conf_Tokens.h \ + $(ACE_ROOT)/ace/Svc_Handler.h \ + $(ACE_ROOT)/ace/Synch_Options.h \ + $(ACE_ROOT)/ace/Synch_Options.i \ + $(ACE_ROOT)/ace/Task.h \ + $(ACE_ROOT)/ace/Thread_Manager.h \ + $(ACE_ROOT)/ace/Singleton.h \ + $(ACE_ROOT)/ace/Singleton.i \ + $(ACE_ROOT)/ace/Singleton.cpp \ + $(ACE_ROOT)/ace/Object_Manager.h \ + $(ACE_ROOT)/ace/Object_Manager.i \ + $(ACE_ROOT)/ace/Managed_Object.h \ + $(ACE_ROOT)/ace/Managed_Object.i \ + $(ACE_ROOT)/ace/Managed_Object.cpp \ + $(ACE_ROOT)/ace/Thread_Manager.i \ + $(ACE_ROOT)/ace/Task.i \ + $(ACE_ROOT)/ace/Task_T.h \ + $(ACE_ROOT)/ace/Message_Queue.h \ + $(ACE_ROOT)/ace/Message_Block.h \ + $(ACE_ROOT)/ace/Message_Block.i \ + $(ACE_ROOT)/ace/Message_Block_T.h \ + $(ACE_ROOT)/ace/Message_Block_T.i \ + $(ACE_ROOT)/ace/Message_Block_T.cpp \ + $(ACE_ROOT)/ace/IO_Cntl_Msg.h \ + $(ACE_ROOT)/ace/Message_Queue_T.h \ + $(ACE_ROOT)/ace/Message_Queue_T.i \ + $(ACE_ROOT)/ace/Message_Queue_T.cpp \ + $(ACE_ROOT)/ace/Strategies.h \ + $(ACE_ROOT)/ace/Strategies_T.h \ + $(ACE_ROOT)/ace/Hash_Map_Manager.h \ + $(ACE_ROOT)/ace/Functor.h \ + $(ACE_ROOT)/ace/Functor.i \ + $(ACE_ROOT)/ace/Functor_T.h \ + $(ACE_ROOT)/ace/Functor_T.i \ + $(ACE_ROOT)/ace/Functor_T.cpp \ + $(ACE_ROOT)/ace/Hash_Map_Manager_T.h \ + $(ACE_ROOT)/ace/Hash_Map_Manager_T.i \ + $(ACE_ROOT)/ace/Hash_Map_Manager_T.cpp \ + $(ACE_ROOT)/ace/Strategies_T.i \ + $(ACE_ROOT)/ace/Strategies_T.cpp \ + $(ACE_ROOT)/ace/Service_Repository.h \ + $(ACE_ROOT)/ace/Service_Types.h \ + $(ACE_ROOT)/ace/Service_Types.i \ + $(ACE_ROOT)/ace/Service_Repository.i \ + $(ACE_ROOT)/ace/WFMO_Reactor.h \ + $(ACE_ROOT)/ace/Process_Mutex.h \ + $(ACE_ROOT)/ace/Process_Mutex.inl \ + $(ACE_ROOT)/ace/WFMO_Reactor.i \ + $(ACE_ROOT)/ace/Strategies.i \ + $(ACE_ROOT)/ace/Message_Queue.i \ + $(ACE_ROOT)/ace/Task_T.i \ + $(ACE_ROOT)/ace/Task_T.cpp \ + $(ACE_ROOT)/ace/Module.h \ + $(ACE_ROOT)/ace/Module.i \ + $(ACE_ROOT)/ace/Module.cpp \ + $(ACE_ROOT)/ace/Stream_Modules.h \ + $(ACE_ROOT)/ace/Stream_Modules.cpp \ + $(ACE_ROOT)/ace/Svc_Handler.cpp \ + $(ACE_ROOT)/ace/Dynamic.h \ + $(ACE_ROOT)/ace/Dynamic.i \ + $(ACE_ROOT)/ace/Acceptor.cpp \ + $(ACE_ROOT)/ace/SOCK_Acceptor.h \ + $(ACE_ROOT)/ace/SOCK_Stream.h \ + $(ACE_ROOT)/ace/SOCK_IO.h \ + $(ACE_ROOT)/ace/SOCK.h \ + $(ACE_ROOT)/ace/Addr.h \ + $(ACE_ROOT)/ace/Addr.i \ + $(ACE_ROOT)/ace/IPC_SAP.h \ + $(ACE_ROOT)/ace/IPC_SAP.i \ + $(ACE_ROOT)/ace/QoS_Session.h \ + $(ACE_ROOT)/ace/INET_Addr.h \ + $(ACE_ROOT)/ace/INET_Addr.i \ + $(ACE_ROOT)/ace/SOCK.i \ + $(ACE_ROOT)/ace/SOCK_IO.i \ + $(ACE_ROOT)/ace/SOCK_Stream.i \ + $(ACE_ROOT)/ace/Time_Value.h \ + $(ACE_ROOT)/ace/SOCK_Acceptor.i client_handler.h + +.obj/server.o .obj/server.so .shobj/server.o .shobj/server.so: server.cpp $(ACE_ROOT)/ace/Service_Config.h \ + $(ACE_ROOT)/ace/pre.h \ + $(ACE_ROOT)/ace/Service_Object.h \ + $(ACE_ROOT)/ace/Shared_Object.h \ + $(ACE_ROOT)/ace/ACE.h \ + $(ACE_ROOT)/ace/OS.h \ + $(ACE_ROOT)/ace/post.h \ + $(ACE_ROOT)/ace/ACE_export.h \ + $(ACE_ROOT)/ace/svc_export.h \ + $(ACE_ROOT)/ace/ace_wchar.h \ + $(ACE_ROOT)/ace/ace_wchar.inl \ + $(ACE_ROOT)/ace/OS_Errno.h \ + $(ACE_ROOT)/ace/OS_Export.h \ + $(ACE_ROOT)/ace/OS_Errno.inl \ + $(ACE_ROOT)/ace/OS_Dirent.h \ + $(ACE_ROOT)/ace/OS_Dirent.inl \ + $(ACE_ROOT)/ace/OS_String.h \ + $(ACE_ROOT)/ace/OS_String.inl \ + $(ACE_ROOT)/ace/OS_Memory.h \ + $(ACE_ROOT)/ace/OS_Memory.inl \ + $(ACE_ROOT)/ace/OS_TLI.h \ + $(ACE_ROOT)/ace/OS_TLI.inl \ + $(ACE_ROOT)/ace/Min_Max.h \ + $(ACE_ROOT)/ace/streams.h \ + $(ACE_ROOT)/ace/Basic_Types.h \ + $(ACE_ROOT)/ace/Basic_Types.i \ + $(ACE_ROOT)/ace/Trace.h \ + $(ACE_ROOT)/ace/OS.i \ + $(ACE_ROOT)/ace/Flag_Manip.h \ + $(ACE_ROOT)/ace/Flag_Manip.i \ + $(ACE_ROOT)/ace/Handle_Ops.h \ + $(ACE_ROOT)/ace/Handle_Ops.i \ + $(ACE_ROOT)/ace/Lib_Find.h \ + $(ACE_ROOT)/ace/Lib_Find.i \ + $(ACE_ROOT)/ace/Init_ACE.h \ + $(ACE_ROOT)/ace/Init_ACE.i \ + $(ACE_ROOT)/ace/Sock_Connect.h \ + $(ACE_ROOT)/ace/Sock_Connect.i \ + $(ACE_ROOT)/ace/ACE.i \ + $(ACE_ROOT)/ace/Shared_Object.i \ + $(ACE_ROOT)/ace/Event_Handler.h \ + $(ACE_ROOT)/ace/Event_Handler.i \ + $(ACE_ROOT)/ace/Service_Object.i \ + $(ACE_ROOT)/ace/Signal.h \ + $(ACE_ROOT)/ace/Synch.h \ + $(ACE_ROOT)/ace/Synch.i \ + $(ACE_ROOT)/ace/Synch_T.h \ + $(ACE_ROOT)/ace/Synch_T.i \ + $(ACE_ROOT)/ace/Thread.h \ + $(ACE_ROOT)/ace/Thread_Adapter.h \ + $(ACE_ROOT)/ace/Base_Thread_Adapter.h \ + $(ACE_ROOT)/ace/OS_Log_Msg_Attributes.h \ + $(ACE_ROOT)/ace/OS_Log_Msg_Attributes.inl \ + $(ACE_ROOT)/ace/Base_Thread_Adapter.inl \ + $(ACE_ROOT)/ace/Thread_Adapter.inl \ + $(ACE_ROOT)/ace/Thread.i \ + $(ACE_ROOT)/ace/Atomic_Op.i \ + $(ACE_ROOT)/ace/Synch_T.cpp \ + $(ACE_ROOT)/ace/Log_Msg.h \ + $(ACE_ROOT)/ace/Log_Record.h \ + $(ACE_ROOT)/ace/Log_Priority.h \ + $(ACE_ROOT)/ace/Log_Record.i \ + $(ACE_ROOT)/ace/Containers.h \ + $(ACE_ROOT)/ace/Malloc_Base.h \ + $(ACE_ROOT)/ace/Containers.i \ + $(ACE_ROOT)/ace/Containers_T.h \ + $(ACE_ROOT)/ace/Containers_T.i \ + $(ACE_ROOT)/ace/Containers_T.cpp \ + $(ACE_ROOT)/ace/Malloc.h \ + $(ACE_ROOT)/ace/Malloc.i \ + $(ACE_ROOT)/ace/Malloc_T.h \ + $(ACE_ROOT)/ace/Malloc_Allocator.h \ + $(ACE_ROOT)/ace/Malloc_Allocator.i \ + $(ACE_ROOT)/ace/Free_List.h \ + $(ACE_ROOT)/ace/Free_List.i \ + $(ACE_ROOT)/ace/Free_List.cpp \ + $(ACE_ROOT)/ace/Malloc_T.i \ + $(ACE_ROOT)/ace/Malloc_T.cpp \ + $(ACE_ROOT)/ace/Memory_Pool.h \ + $(ACE_ROOT)/ace/Mem_Map.h \ + $(ACE_ROOT)/ace/Mem_Map.i \ + $(ACE_ROOT)/ace/SV_Semaphore_Complex.h \ + $(ACE_ROOT)/ace/SV_Semaphore_Simple.h \ + $(ACE_ROOT)/ace/SV_Semaphore_Simple.i \ + $(ACE_ROOT)/ace/SV_Semaphore_Complex.i \ + $(ACE_ROOT)/ace/Memory_Pool.i \ + $(ACE_ROOT)/ace/Signal.i \ + $(ACE_ROOT)/ace/SString.h \ + $(ACE_ROOT)/ace/SString.i \ + $(ACE_ROOT)/ace/Service_Config.i \ + $(ACE_ROOT)/ace/Reactor.h \ + $(ACE_ROOT)/ace/Handle_Set.h \ + $(ACE_ROOT)/ace/Handle_Set.i \ + $(ACE_ROOT)/ace/Timer_Queue.h \ + $(ACE_ROOT)/ace/Timer_Queue_T.h \ + $(ACE_ROOT)/ace/Test_and_Set.h \ + $(ACE_ROOT)/ace/Test_and_Set.i \ + $(ACE_ROOT)/ace/Test_and_Set.cpp \ + $(ACE_ROOT)/ace/Timer_Queue_T.i \ + $(ACE_ROOT)/ace/Timer_Queue_T.cpp \ + $(ACE_ROOT)/ace/Reactor.i \ + $(ACE_ROOT)/ace/Reactor_Impl.h \ + $(ACE_ROOT)/ace/Svc_Conf_Tokens.h Acceptor_Service.h \ + $(ACE_ROOT)/ace/Acceptor.h \ + $(ACE_ROOT)/ace/Svc_Handler.h \ + $(ACE_ROOT)/ace/Synch_Options.h \ + $(ACE_ROOT)/ace/Synch_Options.i \ + $(ACE_ROOT)/ace/Task.h \ + $(ACE_ROOT)/ace/Thread_Manager.h \ + $(ACE_ROOT)/ace/Singleton.h \ + $(ACE_ROOT)/ace/Singleton.i \ + $(ACE_ROOT)/ace/Singleton.cpp \ + $(ACE_ROOT)/ace/Object_Manager.h \ + $(ACE_ROOT)/ace/Object_Manager.i \ + $(ACE_ROOT)/ace/Managed_Object.h \ + $(ACE_ROOT)/ace/Managed_Object.i \ + $(ACE_ROOT)/ace/Managed_Object.cpp \ + $(ACE_ROOT)/ace/Thread_Manager.i \ + $(ACE_ROOT)/ace/Task.i \ + $(ACE_ROOT)/ace/Task_T.h \ + $(ACE_ROOT)/ace/Message_Queue.h \ + $(ACE_ROOT)/ace/Message_Block.h \ + $(ACE_ROOT)/ace/Message_Block.i \ + $(ACE_ROOT)/ace/Message_Block_T.h \ + $(ACE_ROOT)/ace/Message_Block_T.i \ + $(ACE_ROOT)/ace/Message_Block_T.cpp \ + $(ACE_ROOT)/ace/IO_Cntl_Msg.h \ + $(ACE_ROOT)/ace/Message_Queue_T.h \ + $(ACE_ROOT)/ace/Message_Queue_T.i \ + $(ACE_ROOT)/ace/Message_Queue_T.cpp \ + $(ACE_ROOT)/ace/Strategies.h \ + $(ACE_ROOT)/ace/Strategies_T.h \ + $(ACE_ROOT)/ace/Hash_Map_Manager.h \ + $(ACE_ROOT)/ace/Functor.h \ + $(ACE_ROOT)/ace/Functor.i \ + $(ACE_ROOT)/ace/Functor_T.h \ + $(ACE_ROOT)/ace/Functor_T.i \ + $(ACE_ROOT)/ace/Functor_T.cpp \ + $(ACE_ROOT)/ace/Hash_Map_Manager_T.h \ + $(ACE_ROOT)/ace/Hash_Map_Manager_T.i \ + $(ACE_ROOT)/ace/Hash_Map_Manager_T.cpp \ + $(ACE_ROOT)/ace/Strategies_T.i \ + $(ACE_ROOT)/ace/Strategies_T.cpp \ + $(ACE_ROOT)/ace/Service_Repository.h \ + $(ACE_ROOT)/ace/Service_Types.h \ + $(ACE_ROOT)/ace/Service_Types.i \ + $(ACE_ROOT)/ace/Service_Repository.i \ + $(ACE_ROOT)/ace/WFMO_Reactor.h \ + $(ACE_ROOT)/ace/Process_Mutex.h \ + $(ACE_ROOT)/ace/Process_Mutex.inl \ + $(ACE_ROOT)/ace/WFMO_Reactor.i \ + $(ACE_ROOT)/ace/Strategies.i \ + $(ACE_ROOT)/ace/Message_Queue.i \ + $(ACE_ROOT)/ace/Task_T.i \ + $(ACE_ROOT)/ace/Task_T.cpp \ + $(ACE_ROOT)/ace/Module.h \ + $(ACE_ROOT)/ace/Module.i \ + $(ACE_ROOT)/ace/Module.cpp \ + $(ACE_ROOT)/ace/Stream_Modules.h \ + $(ACE_ROOT)/ace/Stream_Modules.cpp \ + $(ACE_ROOT)/ace/Svc_Handler.cpp \ + $(ACE_ROOT)/ace/Dynamic.h \ + $(ACE_ROOT)/ace/Dynamic.i \ + $(ACE_ROOT)/ace/Acceptor.cpp \ + $(ACE_ROOT)/ace/SOCK_Acceptor.h \ + $(ACE_ROOT)/ace/SOCK_Stream.h \ + $(ACE_ROOT)/ace/SOCK_IO.h \ + $(ACE_ROOT)/ace/SOCK.h \ + $(ACE_ROOT)/ace/Addr.h \ + $(ACE_ROOT)/ace/Addr.i \ + $(ACE_ROOT)/ace/IPC_SAP.h \ + $(ACE_ROOT)/ace/IPC_SAP.i \ + $(ACE_ROOT)/ace/QoS_Session.h \ + $(ACE_ROOT)/ace/INET_Addr.h \ + $(ACE_ROOT)/ace/INET_Addr.i \ + $(ACE_ROOT)/ace/SOCK.i \ + $(ACE_ROOT)/ace/SOCK_IO.i \ + $(ACE_ROOT)/ace/SOCK_Stream.i \ + $(ACE_ROOT)/ace/Time_Value.h \ + $(ACE_ROOT)/ace/SOCK_Acceptor.i client_handler.h \ + $(ACE_ROOT)/ace/Dynamic_Service.h \ + $(ACE_ROOT)/ace/Dynamic_Service_Base.h \ + $(ACE_ROOT)/ace/Dynamic_Service.i \ + $(ACE_ROOT)/ace/Dynamic_Service.cpp + +# IF YOU PUT ANYTHING HERE IT WILL GO AWAY diff --git a/docs/tutorials/022/client/Makefile b/docs/tutorials/022/client/Makefile new file mode 100644 index 00000000000..0bfc82e3bd5 --- /dev/null +++ b/docs/tutorials/022/client/Makefile @@ -0,0 +1,47 @@ +#---------------------------------------------------------------------------- +# $Id$ +# +# Makefile for client logging applications +#---------------------------------------------------------------------------- + +#---------------------------------------------------------------------------- +# Local macros +#---------------------------------------------------------------------------- + +BIN = client + +LSRC = $(addsuffix .cpp,$(BIN)) + +VLDLIBS = $(LDLIBS:%=%$(VAR)) + +BUILD = $(VBIN) + +#---------------------------------------------------------------------------- +# Include macros and targets +#---------------------------------------------------------------------------- + +include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU +include $(ACE_ROOT)/include/makeinclude/macros.GNU +include $(ACE_ROOT)/include/makeinclude/rules.common.GNU +include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU +include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU +include $(ACE_ROOT)/include/makeinclude/rules.local.GNU + + +HTML : # + [ -f hdr ] || $(MAKE) UNSHAR + perl ../combine *.pre ; chmod +r *.html + +SHAR : # + [ ! -f combine.shar ] || exit 1 + shar -T hdr bodies *.pre *.pst > combine.shar && $(RM) hdr bodies *.pre *.pst + +UNSHAR : # + sh combine.shar + +CLEAN : realclean + $(RM) hdr bodies *.pre *.pst .depend + +#---------------------------------------------------------------------------- +# Local targets +#---------------------------------------------------------------------------- diff --git a/docs/tutorials/022/client/client.cpp b/docs/tutorials/022/client/client.cpp new file mode 100644 index 00000000000..54bcbc04fa0 --- /dev/null +++ b/docs/tutorials/022/client/client.cpp @@ -0,0 +1,216 @@ +// $Id$ + +/* We need the connector object & we also bring in a simple string + class. */ +#include "ace/Log_Msg.h" +#include "ace/SOCK_Connector.h" +#include "ace/SString.h" + +/* In this tutorial, we extend SOCK_Stream by adding a few wrappers + around the send_n() method. */ +class Client : public ACE_SOCK_Stream +{ +public: + // Basic constructor + Client (void); + + /* Construct and open() in one call. This isn't generally a good + idea because you don't have a clean way to inform the caller when + open() fails. (Unless you use C++ exceptions.) */ + Client (const char *server, + u_short port); + + /* Open the connection to the server. Notice that this mirrors the + use of ACE_SOCK_Connector. By providing our own open(), we can + hide the connector from our caller & make it's interaction easier. */ + int open (const char *server, + u_short port); + + /* These are necessary if you're going to use the constructor that + invokes open(). */ + int initialized (void) { return initialized_; } + int error (void) { return error_; } + + /* This is where the coolness lies. Most C++ folks are familiar + with "cout << some-data." It's a very handy and easy way to toss + data around. By adding these method calls, we're able to do the + same thing with a socket connection. */ + Client &operator<< (ACE_SString &str); + Client &operator<< (char *str); + Client &operator<< (int n); + +protected: + u_char initialized_; + u_char error_; +}; + +/* The basic constructor just sets our flags to reasonable values. */ +Client::Client(void) +{ + initialized_ = 0; + error_ = 0; +} + +/* This constructor also sets the flags but then calls open(). If the + open() fails, the flags will be set appropriately. Use the two + inline method calls initialized() and error() to check the object + state after using this constructor. */ +Client::Client (const char *server, + u_short port) +{ + initialized_ = 0; + error_ = 0; + this->open (server, port); +} + +/* Open a connection to the server. This hides the use of + ACE_SOCK_Connector from our caller. Since our caller probably + doesn't care *how* we connect, this is a good thing. */ +int +Client::open (const char *server, + u_short port) +{ + /* This is right out of Tutorial 3. The only thing we've added is + to set the initialized_ member variable on success. */ + + ACE_SOCK_Connector connector; + ACE_INET_Addr addr (port, server); + + if (connector.connect (*this, addr) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n", + "open"), + -1); + initialized_ = 1; + return 0; +} + +/* The first of our put operators sends a simple string object to the + peer. */ +Client & +Client::operator<< (ACE_SString &str) +{ + /* We have to be able to allow: server << foo << bar << stuff; + + To accomplish that, every << operator must check that the object + is in a valid state before doing work. */ + + if (initialized () && !error ()) + { + /* Get the actual data held in the string object */ + const char *cp = str.fast_rep (); + + /* Send that data to the peer using send_n() as before. If we + have a problem, we'll set error_ so that subsequent << + operations won't try to use a broken stream. */ + if (this->send_n (cp, + ACE_OS::strlen (cp)) == -1) + error_ = 1; + } + else + /* Be sure that error_ is set if somebody tries to use us when + we're not initialized. */ + error_ = 1; + + /* We have to return a reference to ourselves to allow chaining of + put operations (eg -- "server << foo << bar"). Without the + reference, you would have to do each put operation as a statement. + That's OK but doesn't have the same feel as standard C++ + iostreams. */ + return *this ; +} + +/* How do you put a char*? We'll take an easy way out and construct +an ACE_SString from the char* and then put that. It would have been +more efficient to implement this with the body of the +operator<<(ACE_SString&) method and then express that method in terms +of this one. There's always more than one way to do things! */ + +Client & +Client::operator<< (char *str) +{ + ACE_SString newStr (str); + + *this << newStr; + + return *this ; + + /* Notice that we could have been really clever and done: + + return *this << ACE_SString (str); + + That kind of thing just makes debugging a pain though! */ +} + +/* ACE_SString and char* are both about the same thing. What do you + do about different datatypes though? + + Do the same thing we did with char* and convert it to ACE_SString + where we already have a << operator defined. */ +Client & +Client::operator<< (int n) +{ + /* Create a character buffer large enough for the largest number. + That's a tough call but BUFSIZ should be quite enough. */ + char buf[BUFSIZ]; + + /* Put the number into our buffer... */ + ACE_OS::sprintf (buf, + "(%d)\n", + n); + + /* And create the ACE_SString that we know how to put. */ + ACE_SString newStr (buf); + + /* Send it and... */ + *this << newStr; + + /* return ourselves as usual. */ + return *this; +} + +/* Now we pull it all together. Like Tutorial 3, we'll allow command + line options. */ +int +main (int argc, char *argv[]) +{ + const char *server_host = argc > 1 ? argv[1] : ACE_DEFAULT_SERVER_HOST; + u_short server_port = argc > 2 ? ACE_OS::atoi (argv[2]) : ACE_DEFAULT_SERVER_PORT; + int max_iterations = argc > 3 ? ACE_OS::atoi (argv[3]) : 4; + + /* Use the basic constructor since the other isn't really very safe. */ + Client peer; + + /* Open the server connection. Notice how this is simpler than + Tutorial 3 since we only have to provide a host name and port + value. */ + if (peer.open (server_host, + server_port) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n", + "open"), + -1); + + for (int i = 0; i < max_iterations; i++) + { + /* Tell the server which iteration we're on. No more mucking + aroudn with sprintf at this level! It's all hidden from us. */ + peer << "message = " << i+1; + + /* Everything OK? */ + if (peer.error ()) + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n", + "send"), + -1); + else + ACE_OS::sleep (1); + } + + if (peer.close () == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n", + "close"), + -1); + return 0; +} diff --git a/docs/tutorials/022/client_handler.cpp b/docs/tutorials/022/client_handler.cpp new file mode 100644 index 00000000000..d1e51f0833c --- /dev/null +++ b/docs/tutorials/022/client_handler.cpp @@ -0,0 +1,225 @@ +// $Id$ + +/* In client_handler.h I alluded to the fact that we'll mess around + with a Client_Acceptor pointer. To do so, we need the + Client_Acceptor object declaration. + + We know that including client_handler.h is redundant because + client_acceptor.h includes it. Still, the sentry prevents + double-inclusion from causing problems and it's sometimes good to + be explicit about what we're using. + + On the other hand, we don't directly include any ACE header files + here. */ +#include "client_acceptor.h" +#include "client_handler.h" + +/* Our constructor doesn't do anything. That's generally a good idea. + Unless you want to start throwing exceptions, there isn't a really + good way to indicate that a constructor has failed. If I had my + way, I'd have a boolean return code from it that would cause new to + return 0 if I failed. Oh well... */ +Client_Handler::Client_Handler (void) +{ +} + +/* Our destructor doesn't do anything either. That is also by design. + Remember, we really want folks to use destroy() to get rid of us. + If that's so, then there's nothing left to do when the destructor + gets invoked. */ +Client_Handler::~Client_Handler (void) +{ + // Make sure that our peer closes when we're deleted. This + // will probably happened when the peer is deleted but it + // doesn't hurt to be explicit. + this->peer ().close (); +} + +/* The much talked about destroy() method! The reason I keep going on + about this is because it's just a Bad Idea (TM) to do real work + inside of a destructor. Although this method is void, it really + should return int so that it can tell the caller there was a + problem. Even as void you could at least throw an exception which + you would never want to do in a destructor. */ +void +Client_Handler::destroy (void) +{ + /* Tell the reactor to forget all about us. Notice that we use the + same args here that we use in the open() method to register + ourselves. In addition, we use the DONT_CALL flag to prevent + handle_close() being called. Since we likely got here due to + handle_close(), that could cause a bit of nasty recursion! */ + this->reactor ()->remove_handler (this, + ACE_Event_Handler:: READ_MASK | ACE_Event_Handler::DONT_CALL); + + /* This is how we're able to tell folks not to use delete. By + deleting our own instance, we take care of memory leaks after + ensuring that the object is shut down correctly. */ + delete this; +} + +/* As mentioned before, the open() method is called by the + Client_Acceptor when a new client connection has been accepted. + The Client_Acceptor instance pointer is cast to a void* and given + to us here. We'll use that to avoid some global data... */ +int +Client_Handler::open (void *_acceptor) +{ + /* Convert the void* to a Client_Acceptor*. You should probably use + those fancy ACE_*_cast macros but I can never remember how/when + to do so. Since you can cast just about anything around a void* + without compiler warnings be very sure of what you're doing when + you do this kind of thing. That's where the new-style cast + operators can save you. */ + Client_Acceptor *acceptor = (Client_Acceptor *) _acceptor; + + /* Our reactor reference will be set when we register ourselves but + I decided to go ahead and set it here. No good reason really... */ + this->reactor (acceptor->reactor ()); + + /* We need this to store the address of the client that we are now + connected to. We'll use it later to display a debug message. */ + ACE_INET_Addr addr; + + /* Our ACE_Svc_Handler baseclass gives us the peer() method as a way + to access our underlying ACE_SOCK_Stream. On that object, we can + invoke the get_remote_addr() method to get an ACE_INET_Addr + having our client's address information. As with most ACE + methods, we'll get back (and return) a -1 if there was any kind + of error. Once we have the ACE_INET_Addr, we can query it to + find out the clien's host name, TCP/IP address, TCP/IP port value + and so forth. One word of warning: the get_host_name() method of + ACE_INET_Addr may return you an empty string if your name server + can't resolve it. On the other hand, get_host_addr() will always + give you the dotted-decimal string representing the TCP/IP + address. */ + if (this->peer ().get_remote_addr (addr) == -1) + return -1; + + /* If we managed to get the client's address then we're connected to + a real and valid client. I suppose that in some cases, the + client may connect and disconnect so quickly that it is invalid + by the time we get here. In any case, the test above should + always be done to ensure that the connection is worth keeping. + + Now, register ourselves with a reactor and tell that reactor that + we want to be notified when there is something to read. + Remember, we took our reactor value from the acceptor which + created us in the first place. Since we're exploring a + single-threaded implementation, this is the correct thing to do. */ + if (this->reactor ()->register_handler (this, + ACE_Event_Handler::READ_MASK) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "(%P|%t) can't register with reactor\n"), + -1); + + /* Here, we use the ACE_INET_Addr object to print a message with the + name of the client we're connected to. Again, it is possible + that you'll get an empty string for the host name if your DNS + isn't configured correctly or if there is some other reason that + a TCP/IP addreess cannot be converted into a host name. */ + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) connected with %s\n", + addr.get_host_name ())); + + /* Always return zero on success. */ + return 0; +} + +/* In the open() method, we registered with the reactor and requested + to be notified when there is data to be read. When the reactor + sees that activity it will invoke this handle_input() method on us. + As I mentioned, the _handle parameter isn't useful to us but it + narrows the list of methods the reactor has to worry about and the + list of possible virtual functions we would have to override. */ +int +Client_Handler::handle_input (ACE_HANDLE handle) +{ + /* Some compilers don't like it when you fail to use a parameter. + This macro will keep 'em quiet for you. */ + ACE_UNUSED_ARG (handle); + + /* Now, we create and initialize a buffer for receiving the data. + Since this is just a simple test app, we'll use a small buffer + size. */ + char buf[BUFSIZ]; + + /* Invoke the process() method with a pointer to our data area. + We'll let that method worry about interfacing with the data. You + might choose to go ahead and read the data and then pass the + result to process(). However, application logic may require that + you read a few bytes to determine what else to read... It's best + if we push that all into the application-logic level. */ + return this->process (buf, sizeof (buf)); +} + +/* If we return -1 out of handle_input() or if the reactor sees other + problems with us then handle_close() will be called. The reactor + framework will take care of removing us (due to the -1), so we + don't need to use the destroy() method. Instead, we just delete + ourselves directly. */ +int +Client_Handler::handle_close (ACE_HANDLE handle, + ACE_Reactor_Mask mask) +{ + ACE_UNUSED_ARG (handle); + ACE_UNUSED_ARG (mask); + + delete this; + return 0; +} + +/* And, at last, we get to the application-logic level. Out of + everything we've done so far, this is the only thing that really + has anything to do with what your application will do. In this + method we will read and process the client's data. In a real + appliation, you will probably have a bit more in main() to deal + with command line options but after that point, all of the action + takes place here. */ +int +Client_Handler::process (char *rdbuf, + int rdbuf_len) +{ + ssize_t bytes_read = -1; + + /* Using the buffer provided for us, we read the data from the + client. If there is a read error (eg -- recv() returns -1) then + it's a pretty good bet that the connection is gone. Likewise, if + we read zero bytes then something wrong has happened. The + reactor wouldn't have called us if there wasn't some kind of read + activity but there wouldn't be activity if there were no bytes to + read... + + On the other hand, if we got some data then we can display it in + a debug message for everyone to see. */ + switch ( (bytes_read = this->peer ().recv (rdbuf, rdbuf_len)) ) + { + case -1: // Complain and leave + ACE_ERROR_RETURN ((LM_ERROR, + "(%P|%t) %p bad read\n", + "client"), + -1); + case 0: // Complain and leave + ACE_ERROR_RETURN ((LM_ERROR, + "(%P|%t) closing daemon (fd = %d)\n", + this->get_handle ()), + -1); + default: // Show the data + // NULL-terminate the string before printing it. + rdbuf[bytes_read] = 0; + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) from client: %s", + rdbuf)); + } + + /* It's also worth mentioning that recv() has a cousin: recv_n(). + recv_n() will receive exactly the number of bytes you provide it. + This is very good when you know exactly how much you expect to + receive. For the application here, unfortunately, we don't have + any idea how much the client will be sending. recv() will read + up-to-but-not-more-than the number of bytes we specify (e.g. -- + _rdbuf_len). That works well when we don't know how much the + client will provide. */ + + return 0; +} diff --git a/docs/tutorials/022/client_handler.h b/docs/tutorials/022/client_handler.h new file mode 100644 index 00000000000..03d3b1a8e10 --- /dev/null +++ b/docs/tutorials/022/client_handler.h @@ -0,0 +1,100 @@ +// $Id$ + +#ifndef CLIENT_HANDLER_H +#define CLIENT_HANDLER_H + +/* Our client handler must exist somewhere in the ACE_Event_Handler + object hierarchy. This is a requirement of the ACE_Reactor because + it maintains ACE_Event_Handler pointers for each registered event + handler. You could derive our Client_Handler directly from + ACE_Event_Handler but you still have to have an ACE_SOCK_Stream for + the actual connection. With a direct derivative of + ACE_Event_Handler, you'll have to contain and maintain an + ACE_SOCK_Stream instance yourself. With ACE_Svc_Handler (which is + a derivative of ACE_Event_Handler) some of those details are + handled for you. */ + +#include "ace/Svc_Handler.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/SOCK_Stream.h" + +/* Another feature of ACE_Svc_Handler is it's ability to present the + ACE_Task<> interface as well. That's what the ACE_NULL_SYNCH + parameter below is all about. That's beyond our scope here but + we'll come back to it in the next tutorial when we start looking at + concurrency options. */ +class Client_Handler : public ACE_Svc_Handler <ACE_SOCK_STREAM, ACE_NULL_SYNCH> +{ +public: + // Constructor... + Client_Handler (void); + + /* The destroy() method is our preferred method of destruction. We + could have overloaded the delete operator but that is neither easy + nor intuitive (at least to me). Instead, we provide a new method + of destruction and we make our destructor protected so that only + ourselves, our derivatives and our friends can delete us. It's a + nice compromise. */ + void destroy (void); + + /* Most ACE objects have an open() method. That's how you make them + ready to do work. ACE_Event_Handler has a virtual open() method + which allows us to create an override. ACE_Acceptor<> will invoke + this method after creating a new Client_Handler when a client + connects. Notice that the parameter to open() is a void*. It just + so happens that the pointer points to the acceptor which created + us. You would like for the parameter to be an ACE_Acceptor<>* but + since ACE_Event_Handler is generic, that would tie it too closely + to the ACE_Acceptor<> set of objects. In our definition of open() + you'll see how we get around that. */ + int open (void *acceptor); + + /* When there is activity on a registered handler, the + handle_input() method of the handler will be invoked. If that + method returns an error code (eg -- -1) then the reactor will + invoke handle_close() to allow the object to clean itself + up. Since an event handler can be registered for more than one + type of callback, the callback mask is provided to inform + handle_close() exactly which method failed. That way, you don't + have to maintain state information between your handle_* method + calls. The <handle> parameter is explained below... As a + side-effect, the reactor will also invoke remove_handler() for the + object on the mask that caused the -1 return. This means that we + don't have to do that ourselves! */ + int handle_close (ACE_HANDLE handle, + ACE_Reactor_Mask mask); + +protected: + + /* When we register with the reactor, we're going to tell it that we + want to be notified of READ events. When the reactor sees that + there is read activity for us, our handle_input() will be + invoked. The _handle provided is the handle (file descriptor in + Unix) of the actual connection causing the activity. Since we're + derived from ACE_Svc_Handler<> and it maintains its own peer + (ACE_SOCK_Stream) object, this is redundant for us. However, if + we had been derived directly from ACE_Event_Handler, we may have + chosen not to contain the peer. In that case, the <handle> would + be important to us for reading the client's data. */ + int handle_input (ACE_HANDLE handle); + + /* This has nothing at all to do with ACE. I've added this here as + a worker function which I will call from handle_input(). That + allows me to introduce concurrency in later tutorials with no + changes to the worker function. You can think of process() as + application-level code and everything else as + application-framework code. */ + int process (char *rdbuf, int rdbuf_len); + + /* We don't really do anything in our destructor but we've declared + it to be protected to prevent casual deletion of this object. As + I said above, I really would prefer that everyone goes through the + destroy() method to get rid of us. */ + ~Client_Handler (void); +}; + +#endif /* CLIENT_HANDLER_H */ diff --git a/docs/tutorials/022/page01.html b/docs/tutorials/022/page01.html new file mode 100644 index 00000000000..43db6475144 --- /dev/null +++ b/docs/tutorials/022/page01.html @@ -0,0 +1,43 @@ +<!-- $Id$ --> +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> + <head> + <title>ACE Tutorial 022</title> + </head> + + <body> + <h1>ACE Tutorial 022</h1> + <h1>Using Service Configurator Framework</h1> + + <P>Talking about distributed systems, almost means that + there will be several processes or services running at all + times. And it is a common scenario that only some or even just + one of these services needs to be suspended or stopped + altogether. In this scenario, how good it would be if we can + configure just that service or services instead of affecting all + the services leading to an overkill. And, how much convenient it + would be if we can configure the services dynamically so that the + services just need to reconfigured and not recompiled or + shutdown completely.</P> + + <P>Service Configurator pattern helps in all these cases by + enabling a service to be started, removed, suspended or resumed + dynamically. It decouples the implementation and configuration + of a service. New services can be added or unnecessary services + can be removed or suspended.</P> + + <P>In this tutorial, we will use the simple server and client + which we developed and used in our tutorial 005 as the base and + modify as needed.</P> + <P> + <P><HR WIDTH="100%"> + <CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page02.html">Continue This Tutorial</A>]</CENTER> + + <hr> + <address><a href="mailto:pgontla@ece.uci.edu">Priyanka Gontla</a></address> +<!-- Created: Thu Dec 28 14:19:26 PST 2000 --> +<!-- hhmts start --> +Last modified: Fri Jan 19 11:27:55 PST 2001 +<!-- hhmts end --> + </body> +</html> diff --git a/docs/tutorials/022/page02.html b/docs/tutorials/022/page02.html new file mode 100644 index 00000000000..9a478b20ddb --- /dev/null +++ b/docs/tutorials/022/page02.html @@ -0,0 +1,98 @@ +<!-- $Id$ --> +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> + <head> + <title>ACE Tutorial 022</title> + </head> + + <body> + <h1>ACE Tutorial 022</h1> + We begin with <a href="server.cpp">server.cpp</a> + <UL> + <P>Abstraction: + + We begin with the server and the acceptor which we developed in + our ACE Tutorial 005. We modify these and add new + implementation files so as to make the acceptor service dynamically + (un)loadable. What we want to do is separate the implementation + of the service from its configuration. So, our server will + now just act as a daemon waiting for requests. + + We again enroll the services of the ACE_Reactor to handle + events. Everything occurs in a single thread. + + This tutorial helps us learn apply the service configurator + pattern and make services dynamically configurable. In that + process, we are trying to make the acceptor we have developed + previously as a dynamically configurable service. + </UL> + <P> + <HR WIDTH="100%"> + <P> + <PRE> + <font color=red>/* We try to keep the server much simpler than before and + remove any thing related to the acceptor from the main (). + This lets keep the server running irrespective of the + state of the acceptor service. */ + </font> + <font color=red>/* As always, we would need the + ACE_Service_Config to help run the server as a daemon. */ </font> + <font color=blue>#include </font><font color=green>"ace/Service_Config.h"</font> + + <font color=red>/* Since we are seperating the acceptor service class from the + server, we need to declare our Acceptor_Service */ </font> + <font color=blue>#include </font><font color=green>"Acceptor_Service.h"</font> + + int + main (int argc, char *argv []) + { + <font color=red> + /* Perform daemon services update ... this opens the svc.conf + file and reads the entries present in the svc.conf + file. We will later learn the syntax of making an entry + into a svc.conf file. But for now, remember that this is a + file which has the entries to load or unload a service + dynamically or statically. */ + + In case, the function call returns a (-1), which is + indicative of an error, we print out a debug statement + and return (-1) to indicate an failure.</font> + if (ACE_Service_Config::open (argc, + argv, + ACE_DEFAULT_LOGGER_KEY, + 0) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n", + "ACE_Service_Config::open"), + -1); + + <font color=red> + /* Install our signal handler. As we already know, you can actually + register signal handlers with the reactor. You might do that + when the signal handler is responsible for performing "real" + work. Our simple flag-setter doesn't justify deriving from + ACE_Event_Handler and providing a callback function + though. */ </font> + ACE_Sig_Action sa ((ACE_SignalHandler) handler, SIGHUP); + + <font color=red> + /* Start running the event loop so that it + listens for events and acts accordingly. This event loop will run + either the event loop is ended explicitly or an error + occurs. */ </font> + ACE_Reactor::run_event_loop (); + + <font color=red>/* NOT REACHED */</font> + } +</PRE> +<P><HR WIDTH="100%"> +<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page03.html">Continue This Tutorial</A>]</CENTER> + + <hr> + <address><a href="mailto:pgontla@ece.uci.edu">Priyanka Gontla</a></address> +<!-- Created: Thu Dec 28 15:17:34 PST 2000 --> +<!-- hhmts start --> +Last modified: Fri Jan 19 11:28:04 PST 2001 +<!-- hhmts end --> + </body> +</html> diff --git a/docs/tutorials/022/page03.html b/docs/tutorials/022/page03.html new file mode 100644 index 00000000000..634415e1510 --- /dev/null +++ b/docs/tutorials/022/page03.html @@ -0,0 +1,122 @@ +<!-- $Id$ --> +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> + <head> + <title>ACE Tutorial 022</title> + </head> + + <body> + <h1>ACE Tutorial 022</h1> + Now, lets implement the Acceptor Service. As the first step, let + us take a look at <I><A HREF="Acceptor_Service.h">Acceptor_Service.h</A></I>. + +<P> +<HR WIDTH="100%"> +<PRE> +<font color=red>// $Id$</font> + +<font color=blue>#ifndef</font> <font color=purple>ACCEPTOR_SERVICE_H</font> +<font color=blue>#define</font> <font color=purple>ACCEPTOR_SERVICE_H</font> + +<font color=red>/* The ACE_Acceptor<> template lives in the ace/Acceptor.h header + file. */</font> + +<font color=blue>#include</font> "<A HREF="../../../ace/Acceptor.h">ace/Acceptor.h</A>" + +<font color=blue>#if !defined</font> (<font color=purple>ACE_LACKS_PRAGMA_ONCE</font>) +<font color=blue># pragma</font> <font color=purple>once</font> +<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_PRAGMA_ONCE */</font> + +<font color=red>/* Since we want to work with sockets, we'll need a SOCK_Acceptor to + allow the clients to connect to us. */</font> +<font color=blue>#include</font> "<A HREF="../../../ace/SOCK_Acceptor.h">ace/SOCK_Acceptor.h</A>" + +<font color=red>/* The Client_Handler object we develop will be used to handle clients + once they're connected. The ACE_Acceptor<> template's first + parameter requires such an object. In some cases, you can get by + with just a forward declaration on the class, in others you have to + have the whole thing. */</font> +<font color=blue>#include</font> "<font color=green>client_handler.h</font>" + +<font color=red>/* In our original simple server, we instantiated a + ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR> object. We can + make it much simpler and efficient by inheriting our + Acceptor_Service from ACE_Acceptor itself. + + Our Acceptor_Service class also needs to inherit from + ACE_Service_Object. ACE_Service_Object is an abstract class which + includes methods called by the Service Configurator framework to + start, remove, suspend or resume our service. + + You might have noticed that we didnt explicitly inherit from + ACE_Service_Object here. That is because, ACE_Acceptor derives from + ACE_Service_Object and hence there is no explicitly specify it. */ + + /* TO Do: Describe what/why ACE_Svc_Export */ + We use the ACE_Svc_Export macro to export the symbols from the +library on Win.</font> +class ACE_Svc_Export Acceptor_Service : public ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR> +{ + public: + <font color=red> // Constructor </font> + Acceptor_Service (void); + + <font color=red> // Destructor </font> + ~Acceptor_Service (void); + + <font color=red>/* This method is the one which is called by the Service + Configurator Framework to initialize or start the service. */ </font> + virtual int init (int argc, char *argv[]); + + <font color=red>/* Called by the Service Configurator framework to remove this + Service. */ </font> + virtual int fini (void); + + <font color=red>/* You could easily guess that this method is called to suspend the + service by the same Service Configurator Framework. When in the + suspend mode, the service is not removed completely and is *still + there*. The difference is that the service is not in a active + state and doesnot accept requests.*/ </font> + virtual int suspend (void); + + <font color=red> /* And your guess that this method is called to resume the service + is also right. This call brings the service back to the + active state and the service is all ready to accept requests */ </font> + virtual int resume (void); + +}; + +<font color=red>/* The following macros and similar macros which we + will use in the implementation file later are used to define helper + functions for the Service Configurator. As we can easily guess, these + macros are intended to dynamically load ancd configure services using + the svc.conf file. These macros will also help to dynamically configure + even the statically linked services. */</font> + +<font color=red>/* This macro is used to declare a data structure + required to register a statically linked service into the service + configurator. As you can see it has only one argument which is the + name of the class that implements this service... so + Acceptor_Service in our case. */</font> +ACE_STATIC_SVC_DECLARE (Acceptor_Service) + +<font color=red>/* Once the service implementation is dynamically loaded, the Service + Configurator uses a factory method to create the object. This + macro declares such a factory function with the proper interface + and export macros. */</font> +ACE_SVC_FACTORY_DECLARE (Acceptor_Service) + +#include "ace/post.h" +<font color=blue>#endif</font> <<font color=red> /* ACCEPTOR_SERVICE_H */</font> +</PRE> +<P><HR WIDTH="100%"> +<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page04.html">Continue This Tutorial</A>]</CENTER> + + <hr> + <address><a href="mailto:pgontla@ece.uci.edu">Priyanka Gontla</a></address> +<!-- Created: Thu Jan 18 17:46:58 PST 2001 --> +<!-- hhmts start --> +Last modified: Fri Jan 19 11:28:11 PST 2001 +<!-- hhmts end --> + </body> +</html> diff --git a/docs/tutorials/022/page04.html b/docs/tutorials/022/page04.html new file mode 100644 index 00000000000..06fefc677c5 --- /dev/null +++ b/docs/tutorials/022/page04.html @@ -0,0 +1,176 @@ +<!-- $Id$ --> +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> + <head> + <title>ACE Tutorial 022</title> + </head> + + <body> + <h1>ACE Tutorial 022</h1> +<font color=red>/* Now that we know the interface, lets proceed to its + implementation. */</font> +<font color=red>/* We obviosuly want to include the corresponding header + file. */</font> +<font color=blue>#include</font> "<A + HREF="Acceptor_Service.h">Acceptor_Service.h</A>" + +<font color=red>/* A server has to listen for clients at a known TCP/IP port. The + default ACE port is 10002 (at least on my system) and that's good + enough for what we want to do here. Obviously, a more robust + application would take a command line parameter or read from a + configuration file or do some other clever thing. Just like the + signal handler above, though, that's not what we want to focus on, + so we're taking the easy way out. */</font> + +static const u_short PORT = ACE_DEFAULT_SERVER_PORT; + +<PRE> +<font color=red>/* As in all our simple tutorials, our contructor also does nothing */</font> +Acceptor_Service::Acceptor_Service (void) +{ + <font color=red>// Constructor</font> +} + +<font color=red>/* Same in the destructor case */</font> +Acceptor_Service::~Acceptor_Service (void) +{ + <font color=red>// Destructor</font> +} + +<font color=red>/* This is the virtual method inherited from ACE_Service_Object. This + method is called to initialize the service. In a generic sense, we + initialize everything that is needed to initialize our service + here. Ofcourse we need to do that only if there are not already + initialized. One important point to note here is that we have to + make sure that everything that is initialized here is actually + removed when the service is shutdown */</font> +int +Acceptor_Service::init (int argc, char *argv[]) +{ + <font color=red>/* As you will see, we will not be using argc and + argv here and hence declare them to be unused variables. This + helps us from the complaints from the picky compilers about + unused variables. */</font> + ACE_UNUSED_ARG (argc); + ACE_UNUSED_ARG (argv); + + <font color=red>/* Lets have a debug statement so that we can know that our + Acceptor_Service will be initialized soon */</font> + ACE_DEBUG ((LM_DEBUG, + "Starting the Acceptor_Service\n")); + + <font color=red>/* Create an ACE_INET_Addr that represents our endpoint of a + connection. We then open our acceptor object with that Addr. + Doing so tells the acceptor where to listen for connections. + Servers generally listen at "well known" addresses. If not, there + must be some mechanism by which the client is informed of the + server's address. */</font> + if (this->open (ACE_INET_Addr (PORT), + ACE_Reactor::instance ()) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n", + "open"), + -1); + return 0; +} + +<font color=red>/* This virtual method will be invoked when we pass + a directive to the service configurator framework to remove + our service. Remember the threads and anything else that are + initialized in the init method and remove each of them. If we + leave anything that we initialized still running after this + method is invoked ...well .. you know what happens :-) */ </font> +int +Acceptor_Service::fini (void) +{ + <font color=red> /* Lets have another debug statement to inform us the state of the + service. */</font> + ACE_DEBUG ((LM_DEBUG, + "Closing down the Acceptor_Service\n")); + + <font color=red> /* Now, lets see what did we start or initialize during the + initialization process. The only thing that we did was opening + our Acceptor to start listening for requests. So, lets close it + down. */</font> + this->close (); + + return 0; +} + + <font color=red>/* Now, lets see how we can suspend the service that we initialized + and is running. By suspension, we mean that the Reactor still knows + about the service and receives the requests. But, it just keeps + quite even if there are any requests. It actually queues the + requests and sends them to the service once it is resumed.*/</font> +int +Acceptor_Service::suspend (void) +{ + <font color=red>/* You must be wondering, as I did, how we can simply suspend this + service without any complex method invocations. Thanks to our + ACE_Reactor class, we can actually suspend the service by just + invoking the following method and passing a pointer to ourself. + This method actually takes care of all the particulars for + suspending the services and keeps us happy. */</font> + ACE_Reactor::instance ()->suspend_handler (this); + return 0; +} + +int +Acceptor_Service::resume (void) +{ + <font color=red> /* I had the same question again ... how do I do this ?? As before, + our ACE_Reactor class came to a help with this method. ACE + classes do make life simpler .. don't they !! */</font> + ACE_Reactor::instance ()->resume_handler (this); + + return 0; +} + +<font color=red>/* The macro to be used to define the factory method + and destructor for our dynamically loadable service. */</font> +ACE_SVC_FACTORY_DEFINE (Acceptor_Service) + +</font color=red>/* This macro helps to register a statically linked + service into the service configurator. It is defined in ace/OS.h. All + the parameters needed by the service configurator to build and control the + statically linked servuce are configured in a single structure. An + instance of this structure is statically initialized using this + macro. The First parameter is SERVICE_CLASS i.e. the name of the + class that implements the service. As we did implicitly, this class + must derive from ACE_Service_Configurator. The second parameter is + the NAME of the service. This name is used by the service + configurator to match the configuration options provided in the + svc.conf file. The third parameter is the type of the object which + could be either streams or service objects. The next parameter is + the name of the factory function which we defined in our header + file and above using the macros ACE_FACTORY_DECLARE and + ACE_FACTORY_DEFINE. The fifth parameter are a set of options or + flags which are used to control the ownership and life cycle of the + object. The final argument helps us to choose if we want a new + thread for this service. If the argument is not 0, a thread will be + dedicated to this service. .. lots of parameters .. Huh !! */ </font> +ACE_STATIC_SVC_DEFINE (Acceptor_Service, + ACE_TEXT ("Acceptor_Service"), + ACE_SVC_OBJ_T, + &ACE_SVC_NAME (Acceptor_Service), + ACE_Service_Type::DELETE_THIS | ACE_Service_Type::DELETE_OBJ, + 0) + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) +template class ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR>; +template class ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>; +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) +#pragma instantiate ACE_Acceptor <Client_Handler, ACE_SOCK_ACCEPTOR> +#pragma instantiate ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ +</PRE> +<P><HR WIDTH="100%"> +<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page05.html">Continue This Tutorial</A>]</CENTER> + <hr> + <address><a href="mailto:pgontla@ece.uci.edu">Priyanka Gontla</a></address> +<!-- Created: Thu Jan 18 18:24:15 PST 2001 --> +<!-- hhmts start --> +Last modified: Fri Jan 19 11:28:20 PST 2001 +<!-- hhmts end --> + </body> +</html> diff --git a/docs/tutorials/022/page05.html b/docs/tutorials/022/page05.html new file mode 100644 index 00000000000..a615e287853 --- /dev/null +++ b/docs/tutorials/022/page05.html @@ -0,0 +1,130 @@ +<!-- $Id$ --> +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> + <head> + <title>ACE Tutorial 022</title> + </head> + + <body> + <h1>ACE Tutorial 022</h1> + <p>So, by now we have implemented our Acceptor Service: known how to + initialize, remove, suspend and resume our service. We have the + server daemon set up to run to accept requests. The only thing + that is left is the client_handler. We need to declare and define + the Client_Handler object. We will use the same <I><A + HREF="../005/Client_Handler.h">Client_Handler.h</A></I> and + <I><A HREF="../005/Client_Hander.cpp">Client_Handler.cpp</A></I> + that we used in our ACE Tutorial 005.</p> + + <p>With this, we are done with everything that we want to get our + Acceptor Service dynamically configurable in addition to the + actual functionality of the Acceptor.</p> + + <p>To compile, we can use the same <I><A + HREF="../005/Makefile">Makefile</A></I> that we used + previously and make appropriate changes for the new files that + we added. You could use this <I><A HREF="Makefile">Makefile</A></I> + + <p>Now, lets compile it and be all set to configure our Acceptor + Service. Let us run our server to start acting as a daemon and + accept requests.</p> + + <pre>$ ./server </pre> + + <p>Obviously, we will want to load our service dynamically and see + if our Acceptor Service is running as we want it to. For this, + we need to make an entry in the svc.conf file. + + <p>The Service Configurator framework reads the entries in the + svc.conf file in the working directory by default. According to + the entries in the svc.con file, the framework does the + needful. You could use a different name for the file like + server.conf but in that case, we need to explicitly specify to + the application the configuration file that has to be read using + the <I>-ORBSvcconf</I> option. + + <p>Coming back to where we were, now we want to make an entry in + this svc.conf file to load our service. I will show you the + general format for this entry and then we will make our entry.</p> + + A dynamic service could be initialized as: + <pre>dynamic service_name type_of_service * location_of_shared_lib:name_of_object "parameters" + + and a static service is initialized as: +<pre> static service_name "parameters_sent_to_service_object" </pre> + + <p>Lets start making our entry. The first keyword specifies if this + is a dynamic service or a static one. Since we want our service + to be a dynamically configurable one, the first parameter in our + entry will be <I>dynamic</I>. The next parameter is the name of + the service that we want to be loaded. This is the same name + that we specified in the ACE_STATIC_SVC_DEFINE macro. Since our + service name is Acceptor_Service, that becomes the second + parameter of our entry. The next argument is the type of the + service .. as we know already, there are two options: + Stream or Service_Object. And, we declared our service to be a + <I>Service_Object</I> in the ACE_STATIC_SVC_DEFINE macro. So, that + becomes the next parameter. The next entry is the location of + the shared library which has our service and that is + Acceptor_Server according to our Makefile. The next parameter is + the name of the object and finally the list of parameters that + we want to pass to our service. So, we are now erady to make our + entry in the svc.conf file to initialize our service. + +<pre> dynamic Acceptor_Service Service_Object * ./Acceptor_Server:_make_Acceptor_Service () "" </pre> + + <p>Now, we want to reconfigure so that our service will be + initialized. This could be done by sending a signal which would + be received eventually by the Reactor listening for requests and + it would invoke the ACE_Service::reconfigure () method which + does the reconfiguration of the services. + + <pre>$ kill -1 PID_of_our_server </pre> + + Now, that we know how to initialize our service and actually + initialized the service .. we could check if our service is + working good. Ofcourse, the debug statements we left in the init + method would help .. but to double check !! For this purpose, we + can use the simple client which we used in our ACE Tutorial + 005. Just compile the <I><A + HREF="client/client.cpp">client.cpp</A></I> using this <A + HREF="client/Makefile">Makefile</A> and run it. You can see the + responses from the service. + + <p>Now, we can check if we can suspend and resume and finally + remove the service. The entries for these functionalities are + very simple unlike the initialization entry. + + <pre>$ suspend Acceptor_Service + $ resume Acceptor_Service + $ remove Acceptor_Service + </pre> + + <p>Lets first suspend the service by commenting out the entry for + the initialization and making the new entry for suspension in + the svc.conf file. Now, send a signal as before. The Reactor + will receive this event and suspend the service. Just to double + check, you could run our client again and see the response. </p> + + <p>Now, to resume the service, the procedure is the same. Comment + out other entries and make the entry for the resumption of the + service. And finally, send a signal. Again, you could run the + client and see what is happening. But, even before running the + client, you must have noticed that as soon as you resumed the + service, you saw some response from the Acceptor_Service. This + is because, as I explained before, the Reactor will queue the + request when the service is in suspension mode and send the + service the queued requests as and when it is active again. + + <p>Finally, lets remove our service. + + <p>So, now we know how to implement a dynamically configurable + service and how to dynamically configure the service. </p> + <hr> + <address><a href="mailto:pgontla@ece.uci.edu">Priyanka Gontla</a></address> +<!-- Created: Fri Jan 19 10:19:46 PST 2001 --> +<!-- hhmts start --> +Last modified: Fri Jan 19 11:28:26 PST 2001 +<!-- hhmts end --> + </body> +</html> diff --git a/docs/tutorials/022/server.cpp b/docs/tutorials/022/server.cpp new file mode 100644 index 00000000000..5c3bce4601e --- /dev/null +++ b/docs/tutorials/022/server.cpp @@ -0,0 +1,56 @@ +// $Id$ + +/* We try to keep the server much simpler than before and + remove any thing related to the acceptor or the handler + from the main (). This lets keep the server running irrespective of + the state of the acceptor service, in our case and any service in + the general case. */ + +/* We would need the ACE_Service_Config class as it provides an + application developers interface to the entire Service + Configuration Framework */ +#include "ace/Service_Config.h" + +/* Since we are seperating the acceptor service class from the + server, we need to declare our Acceptor_Service */ +#include "Acceptor_Service.h" + +extern "C" void handler (int) +{ + ACE_Service_Config::reconfig_occurred (1); +} + +int +main (int argc, char *argv[]) +{ + /* Perform daemon services update ... this opens the svc.conf + file and reads the entries present in the svc.conf + file. We will later learn the syntax of making an entry + into a svc.conf file. But for now, remember that this is a + file which has the entries to load or unload a service + dynamically or statically. */ + if (ACE_Service_Config::open (argc, + argv, + ACE_DEFAULT_LOGGER_KEY, + 0) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n", + "ACE_Service_Config::open"), + -1); + + /* Install our signal handler. As we already know, you can actually + register signal handlers with the reactor. You might do that + when the signal handler is responsible for performing "real" + work. Our simple flag-setter doesn't justify deriving from + ACE_Event_Handler and providing a callback function though. */ + ACE_Sig_Action sa ((ACE_SignalHandler) handler, SIGHUP); + + /* Start running the event loop so that it + listens for events and acts accordingly. This event loop will run + until either the event loop is ended explicitly or an error + occurs. */ + ACE_Reactor::run_event_loop (); + + /* NOT REACHED */ + +} diff --git a/docs/tutorials/022/svc.conf b/docs/tutorials/022/svc.conf new file mode 100644 index 00000000000..1c3ae8eb8ce --- /dev/null +++ b/docs/tutorials/022/svc.conf @@ -0,0 +1,9 @@ +# $Id$ + + +#dynamic Acceptor_Service Service_Object * ./Acceptor_Server:_make_Acceptor_Service () "" + +#remove Acceptor_Service + +#suspend Acceptor_Service +#resume Acceptor_Service |