summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authordoccvs <doccvs@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2001-01-19 19:28:41 +0000
committerdoccvs <doccvs@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2001-01-19 19:28:41 +0000
commitab68d4c9cc337ae788e31441c14d16c6b4a9c3f4 (patch)
tree43b3749f8fd37ba4ded1eab72def6c97c8394400 /docs
parent138ab62d6cd7762ad41f23d634b2ffdf4476e01f (diff)
downloadATCD-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.cpp154
-rw-r--r--docs/tutorials/022/Acceptor_Service.h93
-rw-r--r--docs/tutorials/022/Makefile666
-rw-r--r--docs/tutorials/022/client/Makefile47
-rw-r--r--docs/tutorials/022/client/client.cpp216
-rw-r--r--docs/tutorials/022/client_handler.cpp225
-rw-r--r--docs/tutorials/022/client_handler.h100
-rw-r--r--docs/tutorials/022/page01.html43
-rw-r--r--docs/tutorials/022/page02.html98
-rw-r--r--docs/tutorials/022/page03.html122
-rw-r--r--docs/tutorials/022/page04.html176
-rw-r--r--docs/tutorials/022/page05.html130
-rw-r--r--docs/tutorials/022/server.cpp56
-rw-r--r--docs/tutorials/022/svc.conf9
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&lt;> 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&lt;> 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