summaryrefslogtreecommitdiff
path: root/ace
diff options
context:
space:
mode:
authornobody <nobody@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2006-04-27 20:45:26 +0000
committernobody <nobody@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2006-04-27 20:45:26 +0000
commit317d8c1ce78436f0107f056418c0c5f5b4231069 (patch)
treed432edf6760c4d9b42f941ba9453db96cd3fa75e /ace
parent664244e804da11536f2712a61116204e8042f312 (diff)
downloadATCD-317d8c1ce78436f0107f056418c0c5f5b4231069.tar.gz
This commit was manufactured by cvs2svn to create branch
'oci_dave_wchar_refactor_branch'.
Diffstat (limited to 'ace')
-rw-r--r--ace/Dynamic_Service_Dependency.cpp48
-rw-r--r--ace/Dynamic_Service_Dependency.h70
-rw-r--r--ace/Service_Gestalt.cpp1114
-rw-r--r--ace/Service_Gestalt.h438
-rw-r--r--ace/Service_Gestalt.inl64
-rw-r--r--ace/Svc_Conf_Param.h140
6 files changed, 1874 insertions, 0 deletions
diff --git a/ace/Dynamic_Service_Dependency.cpp b/ace/Dynamic_Service_Dependency.cpp
new file mode 100644
index 00000000000..cfb556f3e1c
--- /dev/null
+++ b/ace/Dynamic_Service_Dependency.cpp
@@ -0,0 +1,48 @@
+#include "ace/DLL_Manager.h"
+#include "ace/Dynamic_Service_Dependency.h"
+#include "ace/Service_Config.h"
+
+ACE_RCSID (ace,
+ Dynamic_Service_Dependency,
+ "$Id$")
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+
+ACE_Dynamic_Service_Dependency::ACE_Dynamic_Service_Dependency (const ACE_TCHAR *principal)
+{
+ this->init (ACE_Service_Config::current (), principal);
+}
+
+ACE_Dynamic_Service_Dependency::ACE_Dynamic_Service_Dependency (const ACE_Service_Gestalt *cfg,
+ const ACE_TCHAR *principal)
+{
+ this->init (cfg, principal);
+}
+
+
+ACE_Dynamic_Service_Dependency::~ACE_Dynamic_Service_Dependency (void)
+{
+ if (ACE::debug () > 1)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) DSD, this=%@ - destroying dependency\n"),
+ this));
+}
+
+void
+ACE_Dynamic_Service_Dependency::init (const ACE_Service_Gestalt *cfg,
+ const ACE_TCHAR *principal)
+{
+ const ACE_Service_Type* st = ACE_Dynamic_Service_Base::find_i (cfg, principal);
+ if (ACE::debug () > 1)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) DSD, this=%@ - creating dependency on "), this));
+ st->dump ();
+ }
+ this->tracker_ = st->dll ();
+}
+
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ace/Dynamic_Service_Dependency.h b/ace/Dynamic_Service_Dependency.h
new file mode 100644
index 00000000000..8f4b3b3cd18
--- /dev/null
+++ b/ace/Dynamic_Service_Dependency.h
@@ -0,0 +1,70 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Dynamic_Service_Dependency.h
+ *
+ * $Id$
+ *
+ * @author Iliyan Jeliazkov <iliyan@ociweb.com>
+ */
+//=============================================================================
+
+#ifndef ACE_DYNAMIC_SERVICE_DEPENDENCY_H
+#define ACE_DYNAMIC_SERVICE_DEPENDENCY_H
+
+#include /**/ "ace/pre.h"
+
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Dynamic_Service_Base.h"
+#include "ace/Service_Object.h"
+#include "ace/DLL.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+/**
+ * @class ACE_Dynamic_Service_Dependency
+ *
+ * @brief Provides a way to declare dependency on specific service,
+ * thus helping to avoid order of initialization issues with instances
+ * of an objects whose implementation code resides in dynamically loaded
+ * services.
+ *
+ * It is disastrous to have dynamically loadable services create and give away
+ * ownership of objects and then ending up being unloaded before all those
+ * instances have been deleted. Normally the code for such objects classes
+ * resides within the TEXT segment of the DLL, which implements the service.
+ * If a service gets removed, its DLL may be unmapped from memory and then
+ * any attempt to invoke a method on the said objects will cause SEGV.
+ *
+ * Such instances must contain a member of @code ACE_Dynamic_Service_Dependency
+ * initialized with the service they depend on.
+ * @code ACE_Dynamic_Service_Dependency's constructor and destructor are
+ * "magical" - they work by maintaining the underlying dynamic service's
+ * DLL reference count.
+ */
+class ACE_Export ACE_Dynamic_Service_Dependency
+{
+public:
+ ACE_Dynamic_Service_Dependency (const ACE_Service_Gestalt *cfg,
+ const ACE_TCHAR *principal);
+ ACE_Dynamic_Service_Dependency (const ACE_TCHAR *principal);
+ ~ACE_Dynamic_Service_Dependency (void);
+
+private:
+ void init (const ACE_Service_Gestalt *cfg, const ACE_TCHAR *principal);
+
+private:
+ ACE_DLL tracker_;
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_DYNAMIC_SERVICE_DEPENDENCY_H */
diff --git a/ace/Service_Gestalt.cpp b/ace/Service_Gestalt.cpp
new file mode 100644
index 00000000000..456958ac732
--- /dev/null
+++ b/ace/Service_Gestalt.cpp
@@ -0,0 +1,1114 @@
+// $Id$
+
+#include "ace/Svc_Conf.h"
+#include "ace/Get_Opt.h"
+#include "ace/ARGV.h"
+#include "ace/Malloc.h"
+#include "ace/Service_Manager.h"
+#include "ace/Service_Types.h"
+#include "ace/Containers.h"
+#include "ace/Auto_Ptr.h"
+#include "ace/Reactor.h"
+#include "ace/Thread_Manager.h"
+#include "ace/DLL.h"
+#include "ace/XML_Svc_Conf.h"
+#include "ace/SString.h"
+
+#ifndef ACE_LACKS_UNIX_SIGNALS
+# include "ace/Signal.h"
+#endif /* !ACE_LACKS_UNIX_SIGNALS */
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_time.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_sys_stat.h"
+
+#include "ace/TSS_T.h"
+#include "ace/Service_Gestalt.h"
+
+#include "ace/Svc_Conf_Param.h"
+
+ACE_RCSID (ace,
+ Service_Gestalt,
+ "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// This is here, in the implementation, because it depends on the ACE_DLL type,
+// which would be unnecessary to introduuce all over the place, had we declared
+// this in the header file.
+
+// A forward service declaration guard. Used to declare a Service Type with a
+// specific name in a Service Repository, which may later be replaced by the
+// "real" Service Type. The only application is in the implementation of
+// ACE_Service_Gestalt::initialize (), hence the declaration scoping in
+// this file.
+class ACE_Service_Type_Forward_Declaration_Guard
+{
+public:
+ ACE_Service_Type_Forward_Declaration_Guard (ACE_Service_Repository *r,
+ ACE_TCHAR const *name);
+
+ ~ACE_Service_Type_Forward_Declaration_Guard (void);
+
+private:
+ const ACE_DLL dummy_dll_;
+ ACE_Service_Repository *repo_;
+ ACE_TCHAR const * const name_;
+ ACE_Service_Type const * dummy_;
+};
+
+ACE_Service_Type_Forward_Declaration_Guard::ACE_Service_Type_Forward_Declaration_Guard
+(ACE_Service_Repository *r, const ACE_TCHAR *name)
+ : repo_ (r)
+ , name_ (name)
+{
+ ACE_ASSERT (this->repo_ != 0); // No repository specified?
+ ACE_ASSERT (this->name_ != 0); // No name?
+
+ ACE_NEW_NORETURN (this->dummy_, // Allocate the forward declaration ...
+ ACE_Service_Type (this->name_, // ... use the same name
+ 0, // ... inactive
+ this->dummy_dll_, // ... bogus ACE_DLL
+ 0)); // ... no type_impl
+
+ ACE_ASSERT (this->dummy_ != 0); // No memory?
+
+ if(ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("(%P|%t) FWDCL::start, repo=%@, \'%s\' ")
+ ACE_LIB_TEXT ("- type=%@ (impl=(nil))\n"),
+ this->repo_,
+ this->name_,
+ this->dummy_));
+
+ // Note that the dummy_'s memory can disaper between invoking
+ // the ctor and dtor, if the expected "real" dynamic service is
+ // inserted in the repository.
+ this->repo_->insert (this->dummy_);
+}
+
+ACE_Service_Type_Forward_Declaration_Guard::~ACE_Service_Type_Forward_Declaration_Guard (void)
+{
+ const ACE_Service_Type *tmp = 0;
+
+ // Lookup without ignoring suspended services. Making sure
+ // not to ignore any inactive services, since those may be forward
+ // declarations
+ int ret = this->repo_->find (this->name_, &tmp, 0);
+
+ // We inserted it (as inactive), so we expect to find it, right?
+ if (ret < 0 && ret != -2)
+ {
+ ACE_ERROR ((LM_WARNING,
+ ACE_LIB_TEXT ("(%P|%t) FWDCL::end - Failed (%d) to find %s\n"),
+ ret, this->name_));
+ ACE_ASSERT (ret == -2 || ret >= 0);
+ }
+
+ if (tmp != 0 && tmp->type () != 0)
+ {
+ // Something has registered a proper (non-forward-decl) service with
+ // the same name as our dummy. The ACE_Service_Gestalt::insert() modifies
+ // the memory for the previous ACE_Service_Type instance. It has in fact
+ // taken ownership and deleted the instance when it replaced it with the
+ // actual implementation, so nothing is left to do. We are hereby giving
+ // up any ownership claims.
+ this->dummy_ = 0;
+
+ if(ACE::debug ())
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("(%P|%t) FWDCL::end, repo=%@ - ")
+ ACE_LIB_TEXT ("Found different decl - "),
+ this->repo_,
+ this->name_));
+ tmp->dump ();
+ }
+
+ }
+ else
+ {
+ if(ACE::debug ())
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("(%P|%t) FWDCL::end, repo=%@ - ")
+ ACE_LIB_TEXT ("Removing incomplete decl - "),
+ this->repo_,
+ this->name_));
+ this->dummy_->dump ();
+ }
+
+ // The (dummy) forward declaration is still there and is
+ // the same, which means that no actual declaration was
+ // provided inside the guarded scope. Therefore, the forward
+ // declaration is no longer necessary.
+ if (this->repo_->remove (this->name_,
+ const_cast< ACE_Service_Type**> (&this->dummy_)) == 0)
+ {
+ delete this->dummy_;
+ }
+ else
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("(%P|%t) FWDCL::end, repo=%@ - ")
+ ACE_LIB_TEXT ("Failed to remove incomplete decl"),
+ this->repo_,
+ this->name_));
+ this->dummy_->dump ();
+ }
+ }
+
+
+ // Clean up
+ this->dummy_ = 0;
+ this->repo_ = 0;
+}
+
+
+
+// ----------------------------------------
+
+ACE_Service_Gestalt::~ACE_Service_Gestalt (void)
+{
+ ACE_ASSERT (this->repo_ != 0);
+
+ if (this->repo_is_owned_)
+ delete this->repo_;
+}
+
+ACE_Service_Gestalt::ACE_Service_Gestalt (size_t size)
+ : repo_ (new ACE_Service_Repository (size))
+ , repo_is_owned_ (true)
+ , is_opened_ (0)
+ , svc_conf_file_queue_ (0)
+ , static_svcs_ (new ACE_STATIC_SVCS)
+ , svc_queue_ (0)
+ , logger_key_ (ACE_DEFAULT_LOGGER_KEY)
+ , no_static_svcs_ (1)
+{
+ ACE_ASSERT (this->repo_ != 0);
+}
+
+ACE_Service_Gestalt::ACE_Service_Gestalt (void)
+ : repo_ (ACE_Service_Repository::instance ())
+ , repo_is_owned_ (false)
+ , is_opened_ (0)
+ , svc_conf_file_queue_ (0)
+ , static_svcs_ (new ACE_STATIC_SVCS)
+ , svc_queue_ (0)
+ , logger_key_ (ACE_DEFAULT_LOGGER_KEY)
+ , no_static_svcs_ (1)
+{
+ ACE_ASSERT (this->repo_ != 0);
+}
+
+
+
+// Add the default statically-linked services to the Service
+// Repository.
+
+int
+ACE_Service_Gestalt::load_static_svcs (void)
+{
+ ACE_TRACE ("ACE_Service_Gestalt::load_static_svcs");
+
+ if (this->static_svcs_ == 0)
+ return 0; // Nothing to do
+
+ ACE_Static_Svc_Descriptor **ssdp = 0;
+ for (ACE_STATIC_SVCS_ITERATOR iter (*this->static_svcs_);
+ iter.next (ssdp) != 0;
+ iter.advance ())
+ {
+ ACE_Static_Svc_Descriptor *ssd = *ssdp;
+
+ if (this->process_directive (*ssd, 1) == -1)
+ return -1;
+ }
+ return 0;
+
+} /* load_static_svcs () */
+
+
+
+/// Find a static service descriptor by name
+
+int
+ACE_Service_Gestalt::find_static_svc_descriptor (const ACE_TCHAR* name,
+ ACE_Static_Svc_Descriptor **ssd) const
+{
+ ACE_TRACE ("ACE_Service_Gestalt::find_static_svc_descriptor");
+
+ if (this->static_svcs_ == 0)
+ return -1;
+
+ ACE_Static_Svc_Descriptor **ssdp = 0;
+ for (ACE_STATIC_SVCS_ITERATOR iter ( *this->static_svcs_);
+ iter.next (ssdp) != 0;
+ iter.advance ())
+ {
+ if (ACE_OS::strcmp ((*ssdp)->name_, name) == 0)
+ {
+ if (ssd != 0)
+ *ssd = *ssdp;
+
+ return 0;
+ }
+ }
+ return -1;
+
+} /* find_static_svc_descriptor () */
+
+
+int
+ACE_Service_Gestalt::insert (ACE_Static_Svc_Descriptor *stsd)
+{
+ if (ACE::debug () > 1)
+ {
+ // If called during static initialization ACE_Log_Msg may not have
+ // been initialized yet, so use printf intead.
+ ACE_OS::fprintf (stderr,
+ "// (%d|0) SG::insert"
+ " repo=%p, name=%s - Static_Svc_Descriptor: active=%d, opened=%d.\n",
+ ACE_OS::getpid (),
+ this->repo_,
+ stsd->name_,
+ stsd->active_,
+ this->is_opened_);
+ }
+
+ // Inserting a service after teh Gestalt has been opened makes it
+ // impossible to activate it later. Perhaps open came too soon?
+ //ACE_ASSERT (this->is_opened_ == 0);
+
+ return this->static_svcs_->insert (stsd);
+}
+
+
+ACE_ALLOC_HOOK_DEFINE (ACE_Service_Gestalt)
+
+
+void
+ACE_Service_Gestalt::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Service_Gestalt::dump");
+#endif /* ACE_HAS_DUMP */
+}
+
+
+
+ACE_ALLOC_HOOK_DEFINE (ACE_Service_Type_Factory)
+
+ACE_Service_Type_Factory::ACE_Service_Type_Factory (ACE_TCHAR const *name,
+ int type,
+ ACE_Location_Node *location,
+ int active)
+ : name_ (name)
+ , type_ (type)
+ , location_ (location)
+ , is_active_ (active)
+{
+ ACE_TRACE ("ACE_Service_Type_Factory::ACE_Service_Type_Factory");
+};
+
+ACE_Service_Type_Factory::~ACE_Service_Type_Factory (void)
+{
+ ACE_TRACE ("ACE_Service_Type_Factory::~ACE_Service_Type_Factory");
+}
+
+
+ACE_Service_Type *
+ACE_Service_Type_Factory::make_service_type (ACE_Service_Gestalt *cfg) const
+{
+ ACE_TRACE ("ACE_Service_Type_Factory::make_service_type");
+
+ u_int flags = ACE_Service_Type::DELETE_THIS
+ | (this->location_->dispose () == 0 ? 0 : ACE_Service_Type::DELETE_OBJ);
+
+ ACE_Service_Object_Exterminator gobbler = 0;
+
+ int yyerrno = 0;
+ void *sym = this->location_->symbol (cfg, yyerrno, &gobbler);
+
+ if (sym != 0)
+ {
+ ACE_Service_Type_Impl *stp
+ = ACE_Service_Config::create_service_type_impl (this->name (),
+ this->type_,
+ sym,
+ flags,
+ gobbler);
+ if (stp == 0)
+ ++yyerrno;
+
+ return new ACE_Service_Type (this->name (),
+ stp,
+ this->location_->dll (),
+ this->is_active_);
+ }
+ else
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("Unable to find service: %s\n"),
+ this->name ()));
+ ++yyerrno;
+ return 0;
+ }
+}
+
+ACE_TCHAR const*
+ACE_Service_Type_Factory::name (void) const
+{
+ return name_.c_str ();
+}
+
+
+///
+
+int
+ACE_Service_Gestalt::initialize (const ACE_TCHAR *svc_name,
+ const ACE_TCHAR *parameters)
+{
+ ACE_TRACE ("ACE_Service_Gestalt_Base::initialize (repo)");
+ ACE_ARGV args (parameters);
+
+ if (ACE::debug () > 1)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("(%P|%t) SG::initialize - () repo=%@, looking up static ")
+ ACE_LIB_TEXT ("service \'%s\' to initialize\n"),
+ this->repo_,
+ svc_name));
+ }
+
+ const ACE_Service_Type *srp = 0;
+ if (this->repo_->find (svc_name, &srp) == -1)
+ {
+ // Since we're searching by name, the service may be in the
+ // process-wide repository, so check that before reporting
+ // failure.
+ if (this->repo_ == ACE_Service_Repository::instance ()
+ || ACE_Service_Repository::instance ()->find (svc_name, &srp) == -1)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("(%P|%t) SG::initialize - service \'%s\'")
+ ACE_LIB_TEXT (" was not located.\n"),
+ svc_name),
+ -1);
+ }
+ }
+
+ /// If initialization fails ...
+ if (srp->type ()->init (args.argc (),
+ args.argv ()) == -1)
+ {
+ // ... report and remove this entry.
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("(%P|%t) SG::initialize - static init of \'%s\'")
+ ACE_LIB_TEXT (" failed (%p)\n"),
+ svc_name));
+ this->repo_->remove (svc_name);
+ return -1;
+ }
+
+ // If everything is ok, activate it
+ const_cast<ACE_Service_Type *>(srp)->active (1);
+ return 0;
+}
+
+
+int
+ACE_Service_Gestalt::initialize (const ACE_Service_Type_Factory *stf,
+ const ACE_TCHAR *parameters)
+{
+ ACE_TRACE ("ACE_Service_Gestalt::initialize");
+
+ if (ACE::debug () > 1)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("(%P|%t) SG::initialize - repo=%@, looking up dynamic ")
+ ACE_LIB_TEXT ("service \'%s\' to initialize\n"),
+ this->repo_,
+ stf->name ()));
+
+ ACE_Service_Type *srp = 0;
+ int retv = this->repo_->find (stf->name (),
+ (const ACE_Service_Type **) &srp);
+
+ // If there is an active service already, it must first be removed,
+ // before it could be re-installed.
+ if (retv >= 0)
+ ACE_ERROR_RETURN ((LM_WARNING,
+ ACE_LIB_TEXT ("(%P|%t) \'%s\' already installed.")
+ ACE_LIB_TEXT (" Must be removes before re-installing\n"),
+ stf->name ()),
+ 0);
+
+ // There is an inactive service by that name, so it may have been
+ // either inactivated, or just a forward declaration for a service,
+ // that is in the process of being loaded. If the latter, then we
+ // have detected an attempt to initialize the same dynamic service
+ // while still processing previous attempt. This can lock up the
+ // process, because the ACE_DLL_Manager::open () is not re-entrant -
+ // it uses a Singleton lock to serialize concurent invocations. This
+ // use case must be handled here, because if the DLL_Manager was
+ // re-entrant we would have entered an infinite recursion here.
+ if (retv == -2 && srp->type () == 0)
+ ACE_ERROR_RETURN ((LM_WARNING,
+ ACE_LIB_TEXT ("(%P|%t) \'%s\' has not been ")
+ ACE_LIB_TEXT ("completely defined. Recursive ")
+ ACE_LIB_TEXT ("initialization request while ")
+ ACE_LIB_TEXT ("already performing one.\n"),
+ stf->name ()),
+ -1);
+
+ // Reserve a spot for the dynamic service by inserting an incomplete
+ // service declaration, i.e. one that can not produce a service
+ // object if asked. Having this incomplete declaration works
+ // similar to C++'s forward declaration to allow, in this case
+ // proper partial ordering of the loaded services in respect to
+ // their finalization. I.e. dependent static services must be
+ // registered *after* the dynamic service that loads them, so that
+ // their finalization is complete *before* finalizing the dynamic
+ // service.
+ ACE_Service_Type_Forward_Declaration_Guard dummy (this->repo_,
+ stf->name ());
+
+ // make_service_type() is doing the dynamic loading and also runs
+ // any static initializers
+ ACE_Auto_Ptr<ACE_Service_Type> tmp (stf->make_service_type (this));
+
+ if (tmp.get () != 0 &&
+ this->initialize_i (tmp.get (), parameters) == 0)
+ {
+ // All good the ACE_Service_Type instance is now owned by the repository
+ // and we should make sure it is not destroyed upon exit from this method.
+ (void)tmp.release ();
+ return 0;
+ }
+
+ // Something went wrong ...
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("(%P|%t) Error initializing \'%s\'\n"),
+ stf->name()),
+ -1);
+}
+
+
+// Dynamically link the shared object file and retrieve a pointer to
+// the designated shared object in this file.
+// @note This is obsolete (and error-prone) in the presense of dynamic
+// services with their own static services. This method will allow those
+// static services to register *before* the dynamic service that owns them.
+// Upon finalization of the static services the process may crash, because
+// the dynamic service's DLL may have been already released, together with
+// the memory in which the static services reside.
+// It may not crash, for instance, when the first static service to register
+// is the same as the dynamic service being loaded. You should be so lucky! ..
+
+int
+ACE_Service_Gestalt::initialize (const ACE_Service_Type *sr,
+ const ACE_TCHAR *parameters)
+{
+ ACE_TRACE ("ACE_Service_Gestalt::initialize");
+
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("(%P|%t) SG::initialize - looking up dynamic ")
+ ACE_LIB_TEXT (" service \'%s\' to initialize\n"),
+ sr->name ()));
+
+ ACE_Service_Type *srp = 0;
+ if (this->repo_->find (sr->name (),
+ (const ACE_Service_Type **) &srp) >= 0)
+ ACE_ERROR_RETURN ((LM_WARNING,
+ ACE_LIB_TEXT ("(%P|%t) SG::initialize - \'%s\' ")
+ ACE_LIB_TEXT ("has already been installed. ")
+ ACE_LIB_TEXT ("Remove before reinstalling\n"),
+ sr->name ()),
+ 0);
+
+ return this->initialize_i (sr, parameters);
+
+}
+
+// Dynamically link the shared object file and retrieve a pointer to
+// the designated shared object in this file.
+int
+ACE_Service_Gestalt::initialize_i (const ACE_Service_Type *sr,
+ const ACE_TCHAR *parameters)
+{
+ ACE_TRACE ("ACE_Service_Gestalt::initialize_i");
+ ACE_ARGV args (parameters);
+
+ if (sr->type ()->init (args.argc (),
+ args.argv ()) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("(%P|%t) SG - dynamic initialization ")
+ ACE_LIB_TEXT ("failed for \'%s\'\n"),
+ sr->name ()));
+
+ ACE_Service_Type *ps = 0;
+ this->repo_->remove (sr->name (), &ps);
+
+ // We just get ps to avoid having remove() delete it.
+ return -1;
+ }
+
+ if (this->repo_->insert (sr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("(%P|%t) SG - inserting service")
+ ACE_LIB_TEXT (" description failed, %p\n"),
+ sr->name ()),
+ -1);
+ return 0;
+}
+
+// Totally remove <svc_name> from the daemon by removing it from the
+// ACE_Reactor, and unlinking it if necessary.
+
+int
+ACE_Service_Gestalt::remove (const ACE_TCHAR svc_name[])
+{
+ ACE_TRACE ("ACE_Service_Gestalt::remove");
+ return this->repo_->remove (svc_name);
+}
+
+// Suspend <svc_name>. Note that this will not unlink the service
+// from the daemon if it was dynamically linked, it will mark it as
+// being suspended in the Service Repository and call the <suspend>
+// member function on the appropriate <ACE_Service_Object>. A service
+// can be resumed later on by calling the <resume> method...
+
+int
+ACE_Service_Gestalt::suspend (const ACE_TCHAR svc_name[])
+{
+ ACE_TRACE ("ACE_Service_Gestalt::suspend");
+ return this->repo_->suspend (svc_name);
+}
+
+// Resume a SVC_NAME that was previously suspended or has not yet
+// been resumed (e.g., a static service).
+
+int
+ACE_Service_Gestalt::resume (const ACE_TCHAR svc_name[])
+{
+ ACE_TRACE ("ACE_Service_Gestalt::resume");
+ return this->repo_->resume (svc_name);
+}
+
+
+int
+ACE_Service_Gestalt::process_directive (const ACE_Static_Svc_Descriptor &ssd,
+ int force_replace)
+{
+ if (ACE::debug () > 2)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("(%P|%t) SG::process_directive, ")
+ ACE_LIB_TEXT ("repo=%@, replace=%d - %s\n"),
+ this->repo_,
+ force_replace,
+ ssd.name_));
+
+ if (!force_replace)
+ {
+ if (this->repo_->find (ssd.name_, 0, 0) >= 0)
+ {
+ // The service is already there, just return
+ return 0;
+ }
+ }
+
+ ACE_Service_Object_Exterminator gobbler;
+ void *sym = (ssd.alloc_)(&gobbler);
+
+ ACE_Service_Type_Impl *stp =
+ ACE_Service_Config::create_service_type_impl (ssd.name_,
+ ssd.type_,
+ sym,
+ ssd.flags_,
+ gobbler);
+ if (stp == 0)
+ return 0;
+
+
+ ACE_Service_Type *service_type;
+
+ // This is just a temporary to force the compiler to use the right
+ // constructor in ACE_Service_Type
+ ACE_DLL tmp_dll;
+
+ ACE_NEW_RETURN (service_type,
+ ACE_Service_Type (ssd.name_,
+ stp,
+ tmp_dll,
+ ssd.active_),
+ -1);
+
+ return this->repo_->insert (service_type);
+}
+
+
+#if (ACE_USES_CLASSIC_SVC_CONF == 1)
+
+int
+ACE_Service_Gestalt::process_directives_i (ACE_Svc_Conf_Param *param)
+{
+ // AC 970827 Skip the heap check because yacc allocates a buffer
+ // here which will be reported as a memory leak for some reason.
+ ACE_NO_HEAP_CHECK
+
+ // Were we called in the context of the current instance?
+ ACE_ASSERT (this == param->config);
+
+ // Temporarily (for the duration of this call) make sure that *any* static
+ // service registrations will happen with this instance. Such registrations
+ // are possible as a side-effect of dynamically loading a DLL, which has
+ // other static services registered. Thus this instance will own both the
+ // DLL and those static services, which implies that their finalization
+ // will be performed in the correct order, i.e. prior to finalizing the DLL
+ ACE_Service_Config_Guard guard (this);
+
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("(%P|%t) SG::process_directives_i, ")
+ ACE_LIB_TEXT ("repo=%@ - %s\n"),
+ this->repo_,
+ (param->type == ACE_Svc_Conf_Param::SVC_CONF_FILE)
+ ? ACE_TEXT ("<from file>")
+ : param->source.directive));
+
+
+ ::ace_yyparse (param);
+
+ if (param->yyerrno > 0)
+ {
+ // This is a hack, better errors should be provided...
+ errno = EINVAL;
+ return param->yyerrno;
+ }
+ else
+ return 0;
+}
+
+#else
+
+ACE_XML_Svc_Conf *
+ACE_Service_Gestalt::get_xml_svc_conf (ACE_DLL &xmldll)
+{
+ if (xmldll.open (ACE_LIB_TEXT ("ACEXML_XML_Svc_Conf_Parser")) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("Fail to open ACEXML_XML_Svc_Conf_Parser: %p\n"),
+ "ACE_Service_Config::get_xml_svc_conf"),
+ 0);
+
+ void *foo;
+ foo = xmldll.symbol (ACE_LIB_TEXT ("_ACEXML_create_XML_Svc_Conf_Object"));
+
+ // Cast the void* to long first.
+ long tmp = reinterpret_cast<long> (foo);
+ ACE_XML_Svc_Conf::Factory factory =
+ reinterpret_cast<ACE_XML_Svc_Conf::Factory> (tmp);
+ if (factory == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("Unable to resolve factory: %p\n"),
+ xmldll.error ()),
+ 0);
+
+ return factory ();
+}
+#endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */
+
+int
+ACE_Service_Gestalt::process_file (const ACE_TCHAR file[])
+{
+ ACE_TRACE ("ACE_Service_Gestalt::process_file");
+
+ // To avoid recursive processing of the same file and the same repository
+ // we maintain an implicit stack of dummy "services" named after the file
+ // being processed. Anytime we have to open a new file, we then can check
+ // to see if it is not already being processed by searching for a dummy
+ // service with a matching name.
+ if (this->repo_->find (file, 0, 0) >=0)
+ {
+ ACE_DEBUG ((LM_WARNING,
+ ACE_TEXT ("(%P|%t) Configuration file %s has not finished")
+ ACE_TEXT (" processing yet. Ignoring.\n"),
+ file));
+ return 0;
+ }
+
+ // Register a dummy service as a forward decl, using the file name as name.
+ // The entry will be automaticaly removed once the thread exits this block.
+ ACE_Service_Type_Forward_Declaration_Guard recursion_guard (this->repo_, file);
+
+ /*
+ * @TODO: Test with ACE_USES_CLASSIC_SVC_CONF turned off!
+ */
+#if (ACE_USES_CLASSIC_SVC_CONF == 1)
+ int result = 0;
+
+ FILE *fp = ACE_OS::fopen (file,
+ ACE_LIB_TEXT ("r"));
+
+ if (fp == 0)
+ {
+ // Invalid svc.conf file. We'll report it here and break out of
+ // the method.
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ file));
+
+ // Use stat to find out if the file exists. I didn't use access()
+ // because stat is better supported on most non-unix platforms.
+ ACE_stat exists;
+ if (ACE_OS::stat (file, &exists) == 0)
+ // If it exists, but we couldn't open it for reading then we
+ // must not have permission to read it.
+ errno = EPERM;
+ else
+ errno = ENOENT;
+ result = -1;
+ }
+ else
+ {
+ ACE_Svc_Conf_Param f (this, fp);
+
+ // Keep track of the number of errors.
+ result = this->process_directives_i (&f);
+
+ (void) ACE_OS::fclose (fp);
+ }
+ return result;
+#else
+ ACE_DLL dll;
+
+ auto_ptr<ACE_XML_Svc_Conf>
+ xml_svc_conf (ACE_Service_Config::get_xml_svc_conf (dll));
+
+ if (xml_svc_conf.get () == 0)
+ return -1;
+
+ return xml_svc_conf->parse_file (file);
+#endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */
+}
+
+int
+ACE_Service_Gestalt::process_directive (const ACE_TCHAR directive[])
+{
+ ACE_TRACE ("ACE_Service_Gestalt::process_directive");
+
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("(%P|%t) SG::process_directive, repo=%@ - %s\n"),
+ this->repo_,
+ directive));
+
+#if (ACE_USES_CLASSIC_SVC_CONF == 1)
+ ACE_UNUSED_ARG (directive);
+
+ ACE_Svc_Conf_Param d (this, directive);
+
+ int result = this->process_directives_i (&d);
+
+ return result;
+#else
+ ACE_DLL dll;
+
+ auto_ptr<ACE_XML_Svc_Conf>
+ xml_svc_conf (this->get_xml_svc_conf (dll));
+
+ if (xml_svc_conf.get () == 0)
+ return -1;
+
+ return xml_svc_conf->parse_string (directive);
+#endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */
+
+} /* process_directive () */
+
+
+int
+ACE_Service_Gestalt::init_svc_conf_file_queue (void)
+{
+ if (this->svc_conf_file_queue_ == 0)
+ {
+ ACE_SVC_QUEUE *tmp = 0;
+ ACE_NEW_RETURN (tmp,
+ ACE_SVC_QUEUE,
+ -1);
+ delete this->svc_conf_file_queue_;
+ this->svc_conf_file_queue_ = tmp;
+ }
+
+ if (ACE::debug () > 1)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("(%P|%t) SG::init_svc_conf_file_queue ")
+ ACE_LIB_TEXT ("- this=%@, repo=%@\n"),
+ this, this->repo_));
+ return 0;
+
+} /* init_svc_conf_file_queue () */
+
+
+int
+ACE_Service_Gestalt::open_i (const ACE_TCHAR /*program_name*/[],
+ const ACE_TCHAR* /*logger_key*/,
+ bool /*ignore_static_svcs*/,
+ bool /*ignore_default_svc_conf_file*/,
+ bool ignore_debug_flag)
+{
+ ACE_TRACE ("ACE_Service_Gestalt::open_i");
+ int result = 0;
+ ACE_Log_Msg *log_msg = ACE_LOG_MSG;
+
+ // Record the current log setting upon entering this thread.
+ u_long old_process_mask = log_msg->priority_mask
+ (ACE_Log_Msg::PROCESS);
+ u_long old_thread_mask = log_msg->priority_mask
+ (ACE_Log_Msg::THREAD);
+
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) SG::open_i - this=%@, ")
+ ACE_TEXT ("opened=%d, loadstatics=%d\n"),
+ this, this->is_opened_, this->no_static_svcs_));
+
+ // Guard against reentrant processing. For example,
+ // if the singleton gestalt (ubergestalt) was already open,
+ // do not open it again...
+ if (this->is_opened_++ != 0)
+ return 0;
+
+ if (ignore_debug_flag == 0)
+ {
+ // If -d was included as a startup parameter, the user wants debug
+ // information printed during service initialization.
+ if (ACE::debug ())
+ ACE_Log_Msg::enable_debug_messages ();
+ else
+ // The user has requested no debugging info.
+ ACE_Log_Msg::disable_debug_messages ();
+ }
+
+ // See if we need to load the static services.
+ if (this->no_static_svcs_ == 0
+ && this->load_static_svcs () == -1)
+ result = -1;
+ else
+ {
+ if (this->process_commandline_directives () == -1)
+ result = -1;
+ else
+ result = this->process_directives ();
+ }
+
+
+ // Reset debugging back to the way it was when we came into
+ // into <open_i>.
+ {
+ // Make sure to save/restore errno properly.
+ ACE_Errno_Guard error (errno);
+
+ if (ignore_debug_flag == 0)
+ {
+ log_msg->priority_mask (old_process_mask, ACE_Log_Msg::PROCESS);
+ log_msg->priority_mask (old_thread_mask, ACE_Log_Msg::THREAD);
+ }
+ }
+
+ return result;
+} /* open_i () */
+
+
+int
+ACE_Service_Gestalt::is_opened (void)
+{
+ return this->is_opened_;
+}
+
+int
+ACE_Service_Gestalt::process_commandline_directives (void)
+{
+ int result = 0;
+ if (this->svc_queue_ != 0)
+ {
+ ACE_TString *sptr = 0;
+ for (ACE_SVC_QUEUE_ITERATOR iter (*this->svc_queue_);
+ iter.next (sptr) != 0;
+ iter.advance ())
+ {
+ // Process just a single directive.
+ if (this->process_directive ((sptr->fast_rep ())) != 0)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("process_directive")));
+ result = -1;
+ }
+ }
+
+ delete this->svc_queue_;
+ this->svc_queue_ = 0;
+ }
+
+ return result;
+
+} /* process_commandline_directives () */
+
+
+int
+ACE_Service_Gestalt::parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_TRACE ("ACE_Service_Gestalt::parse_args");
+ return parse_args_i (argc, argv);
+}
+
+int
+ACE_Service_Gestalt::parse_args_i (int argc, ACE_TCHAR *argv[])
+{
+ ACE_TRACE ("ACE_Service_Gestalt::parse_args_i");
+ ACE_Get_Opt getopt (argc,
+ argv,
+ ACE_LIB_TEXT ("df:k:nyp:s:S:"),
+ 1); // Start at argv[1].
+
+ if (this->init_svc_conf_file_queue () == -1)
+ return -1;
+
+ for (int c; (c = getopt ()) != -1; )
+ switch (c)
+ {
+ case 'd':
+ ACE::debug (1);
+ break;
+ case 'f':
+ if (this->svc_conf_file_queue_->enqueue_tail (ACE_TString (getopt.opt_arg ())) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("enqueue_tail")),
+ -1);
+ break;
+ case 'k':
+ /*
+ * @TODO: Is this always a static storage? Shouldn't we copy
+ * & gain ownership of the value?
+ */
+ this->logger_key_ = getopt.opt_arg ();
+ break;
+ case 'n':
+ this->no_static_svcs_ = 1;
+ break;
+ case 'y':
+ this->no_static_svcs_ = 0;
+ break;
+ case 'S':
+ if (this->svc_queue_ == 0)
+ {
+ ACE_NEW_RETURN (this->svc_queue_,
+ ACE_SVC_QUEUE,
+ -1);
+ }
+
+ if (this->svc_queue_->enqueue_tail (ACE_TString (getopt.opt_arg ())) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_LIB_TEXT ("%p\n"),
+ ACE_LIB_TEXT ("enqueue_tail")),
+ -1);
+ break;
+ default:
+ if (ACE::debug () > 0)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("%c is not a ACE_Service_Config option\n"),
+ c));
+ }
+
+ return 0;
+} /* parse_args_i () */
+
+
+
+// Process service configuration requests as indicated in the queue of
+// svc.conf files.
+int
+ACE_Service_Gestalt::process_directives (void)
+{
+ ACE_TRACE ("ACE_Service_Gestalt::process_directives");
+
+ int result = 0;
+
+ if (this->svc_conf_file_queue_ != 0)
+ {
+ ACE_TString *sptr = 0;
+
+ // Iterate through all the svc.conf files.
+ for (ACE_SVC_QUEUE_ITERATOR iter (*this->svc_conf_file_queue_);
+ iter.next (sptr) != 0;
+ iter.advance ())
+ {
+ int r = this->process_file (sptr->fast_rep ());
+
+ if (r < 0)
+ {
+ result = r;
+ break;
+ }
+
+ result += r;
+ }
+ }
+
+ return result;
+
+} /* process_directives () */
+
+
+
+// Tidy up and perform last rites on a terminating ACE_Service_Gestalt.
+int
+ACE_Service_Gestalt::close (void)
+{
+ ACE_TRACE ("ACE_Service_Gestalt::close");
+
+ if (ACE::debug () > 1)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("(%P|%t) SG::close - this=%@, repo=%@, is_opened=%d\n"),
+ this, this->repo_, this->is_opened_));
+
+ this->is_opened_--;
+ if (this->is_opened_ > 0)
+ return 0;
+
+ // Delete the service repository. All the objects inside the
+ // service repository should already have been finalized.
+ // ACE_Service_Config::close_svcs ();
+
+ // Delete the list fo svc.conf files
+ delete this->svc_conf_file_queue_;
+ this->svc_conf_file_queue_ = 0;
+
+ // Delete the dynamically allocated static_svcs instance.
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("(%P|%t) SG::close - this=%@, repo=%@\n"),
+ this, this->repo_));
+
+ delete this->static_svcs_;
+ this->static_svcs_ = 0;
+
+ return 0;
+
+} /* close () */
+
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Service_Gestalt.inl"
+#endif /* __ACE_INLINE__ */
+
+
+// Allocate a Service Manager.
+ACE_FACTORY_DEFINE (ACE, ACE_Service_Manager)
diff --git a/ace/Service_Gestalt.h b/ace/Service_Gestalt.h
new file mode 100644
index 00000000000..39618b402d6
--- /dev/null
+++ b/ace/Service_Gestalt.h
@@ -0,0 +1,438 @@
+// -*- C++ -*-
+
+//====================================================================
+/**
+ * @file Service_Gestalt.h
+ *
+ * $Id$
+ *
+ * @author Iliyan Jeliazkov <iliyan@ociweb.com>
+ */
+//====================================================================
+
+#ifndef ACE_SERVICE_GESTALT_H
+#define ACE_SERVICE_GESTALT_H
+
+#include /**/ "ace/pre.h"
+
+#include "ace/config-all.h"
+#include "ace/Default_Constants.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/SString.h"
+#include "ace/Unbounded_Queue.h"
+#include "ace/Service_Repository.h"
+#include "ace/Singleton.h"
+#include "ace/OS_NS_signal.h"
+#include "ace/Synch_Traits.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+class ACE_Service_Type_Factory;
+class ACE_Static_Svc_Descriptor;
+class ACE_Svc_Conf_Param;
+
+class ACE_Service_Gestalt;
+
+/**
+ * @class ACE_Service_Gestalt
+ *
+ * @brief Supplies common server operations for dynamic and static
+ * configuration of services.
+ */
+class ACE_Export ACE_Service_Gestalt
+{
+private:
+ /**
+ * Not implemented to enforce no copying
+ */
+ ACE_UNIMPLEMENTED_FUNC (ACE_Service_Gestalt(const ACE_Service_Gestalt&))
+ ACE_UNIMPLEMENTED_FUNC (ACE_Service_Gestalt& operator=(const ACE_Service_Gestalt&))
+
+public:
+ enum
+ {
+ MAX_SERVICES = ACE_DEFAULT_SERVICE_REPOSITORY_SIZE
+ };
+
+ /// Default constructor - associates the instance with the process-wide
+ /// singleton instance of ACE_Service_Repository.
+ ACE_Service_Gestalt (void);
+
+ /// Creates an instance with a specified repository size. Takes ownership
+ /// of the repository.
+ ACE_Service_Gestalt (size_t size);
+
+ /// Perform user-specified close activities and remove dynamic
+ /// memory.
+ virtual ~ACE_Service_Gestalt (void);
+
+ /// Dump the state of an object.
+ void dump (void) const;
+
+ /**
+ * Performs an open without parsing command-line arguments. The
+ * @a logger_key indicates where to write the logging output, which
+ * is typically either a STREAM pipe or a socket address. If
+ * @a ignore_static_svcs is 1 then static services are not loaded,
+ * otherwise, they are loaded. If @a ignore_default_svc_conf_file is
+ * non-0 then the <svc.conf> configuration file will be ignored.
+ * Returns zero upon success, -1 if the file is not found or cannot
+ * be opened (errno is set accordingly), otherwise returns the
+ * number of errors encountered loading the services in the
+ * specified svc.conf configuration file. If @a ignore_debug_flag is
+ * non-0 then the application is responsible for setting the
+ * <ACE_Log_Msg::priority_mask> appropriately.
+ */
+ int open (const ACE_TCHAR program_name[],
+ const ACE_TCHAR *logger_key = ACE_DEFAULT_LOGGER_KEY,
+ int ignore_static_svcs = 1,
+ int ignore_default_svc_conf_file = 0,
+ int ignore_debug_flag = 0);
+
+ /**
+ * This is the primary entry point into the ACE_Service_Config (the
+ * constructor just handles simple initializations). It parses
+ * arguments passed in from @a argc and @a argv parameters. The
+ * arguments that are valid in a call to this method include:
+ *
+ * - '-b' Option to indicate that we should be a daemon. Note that when
+ * this option is used, the process will be daemonized before the
+ * service configuration file(s) are read. During daemonization,
+ * (on POSIX systems) the current directory will be changed to "/"
+ * so the caller should either fully specify the file names, or
+ * execute a @c chroot() to the appropriate directory.
+ * @sa ACE::daemonize().
+ * - '-d' Turn on debugging mode
+ * - '-f' Specifies a configuration file name other than the default
+ * svc.conf. Can be specified multiple times to use multiple files.
+ * - '-k' Specifies the rendezvous point to use for the ACE distributed
+ * logger.
+ * - '-y' Explicitly enables the use of static services. This flag
+ * overrides the @a ignore_static_svcs parameter value.
+ * - '-n' Explicitly disables the use of static services. This flag
+ * overrides the @a ignore_static_svcs parameter value.
+ * - '-p' Specifies a pathname which is used to store the process id.
+ * - '-s' Specifies a signal number other than SIGHUP to trigger reprocessing
+ * of the configuration file(s). Ignored for platforms that do not
+ * have POSIX signals, such as Windows.
+ * - '-S' Specifies a service directive string. Enclose the string in quotes
+ * and escape any embedded quotes with a backslash. This option
+ * specifies service directives without the need for a configuration
+ * file.
+ *
+ * @param argc The number of commandline arguments.
+ * @param argv The array with commandline arguments
+ * @param logger_key Indicates where to write the logging output,
+ * which is typically either a STREAM pipe or a
+ * socket address.
+ * @param ignore_static_svcs If 1 then static services are not loaded,
+ * otherwise, they are loaded.
+ * @param ignore_default_svc_conf_file If non-0 then the @c svc.conf
+ * configuration file will be ignored.
+ * @param ignore_debug_flag If non-0 then the application is responsible
+ * for setting the @c ACE_Log_Msg::priority_mask
+ * appropriately.
+ *
+ * @retval -1 The configuration file is not found or cannot
+ * be opened (errno is set accordingly).
+ * @retval 0 Success.
+ * @retval >0 The number of errors encountered while processing
+ * the service configuration file(s).
+ */
+ int open (int argc,
+ ACE_TCHAR *argv[],
+ const ACE_TCHAR *logger_key = ACE_DEFAULT_LOGGER_KEY,
+ int ignore_static_svcs = 1,
+ int ignore_default_svc_conf_file = 0,
+ int ignore_debug_flag = 0);
+
+ /// Has it been opened? Returns the difference between the times
+ /// open and close have been called on this instance
+ int is_opened (void);
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+ /// Process one service configuration @a directive, which is passed as
+ /// a string. Returns the number of errors that occurred.
+ int process_directive (const ACE_TCHAR directive[]);
+
+ /// Process one static service definition.
+ /**
+ * Load a new static service.
+ *
+ * @param ssd Service descriptor, see the document of
+ * ACE_Static_Svc_Descriptor for more details.
+ *
+ * @param force_replace If set the new service descriptor replaces
+ * any previous instance in the repository.
+ *
+ * @return Returns -1 if the service cannot be 'loaded'.
+ */
+ int process_directive (const ACE_Static_Svc_Descriptor &ssd,
+ int force_replace = 0);
+
+ /// Process a file containing a list of service configuration
+ /// directives.
+ int process_file (const ACE_TCHAR file[]);
+
+ /**
+ * Locate an entry with <name> in the table. If <ignore_suspended>
+ * is set then only consider services marked as resumed. If the
+ * caller wants the located entry, pass back a pointer to the
+ * located entry via <srp>. If <name> is not found, -1 is returned.
+ * If <name> is found, but it is suspended and the caller wants to
+ * ignore suspended services a -2 is returned.
+ */
+ int find (const ACE_TCHAR name[],
+ const ACE_Service_Type **srp = 0,
+ int ignore_suspended = 1) const;
+
+ /**
+ * Handle the command-line options intended for the
+ * <ACE_Service_Config>. Note that <argv[0]> is assumed to be the
+ * program name.
+ * The arguments that are valid in a call to this method are
+ * - '-b' Option to indicate that we should be a daemon
+ * - '-d' Turn on debugging mode
+ * - '-f' Option to read in the list of svc.conf file names
+ * - '-k' Option to read a wide string where in the logger output can
+ * be written
+ * - '-y' Turn on the flag for a repository of statically
+ * linked services
+ * - '-n' Need not have a repository of statically linked services
+ * - '-S' Option to read in the list of services on the command-line
+ * Please observe the difference between options '-f' that looks
+ * for a list of files and here a list of services.
+ */
+ int parse_args (int, ACE_TCHAR *argv[]);
+
+ /**
+ * Process (or re-process) service configuration requests that are
+ * provided in the svc.conf file(s). Returns the number of errors
+ * that occurred.
+ */
+ int process_directives (void);
+
+ /// Tidy up and perform last rites when ACE_Service_Config is shut
+ /// down. This method calls <close_svcs>. Returns 0.
+ int close (void);
+
+
+ // Registers a service descriptor for a static service object
+ int insert (ACE_Static_Svc_Descriptor *stsd);
+
+ // = Utility methods.
+ /// Dynamically link the shared object file and retrieve a pointer to
+ /// the designated shared object in this file. Also account for the
+ /// possiblity to have static services registered when loading the DLL, by
+ /// ensuring that the dynamic sevice is registered before any of its
+ /// subordibnate static services. Thus avoiding any finalization order
+ /// problems.
+ int initialize (const ACE_Service_Type_Factory *,
+ const ACE_TCHAR *parameters);
+
+ // Dynamically link the shared object file and retrieve a pointer to
+ // the designated shared object in this file.
+ // @obsolete
+ // @note This is error-prone in the presense of dynamic
+ // services with their own static services. This method will allow those
+ // static services to register *before* the dynamic service that owns them.
+ // Upon finalization of the static services the process may crash, because
+ // the dynamic service's DLL may have been already released, together with
+ // the memory in which the static services reside.
+ // It may not crash, for instance, when the first static service to register
+ // is the same as the dynamic service being loaded. You should be so lucky!
+ int initialize (const ACE_Service_Type *,
+ const ACE_TCHAR *parameters);
+
+ /// Initialize and activate a statically @a svc_name service.
+ int initialize (const ACE_TCHAR *svc_name,
+ const ACE_TCHAR *parameters);
+
+ /// Resume a @a svc_name that was previously suspended or has not yet
+ /// been resumed (e.g., a static service).
+ int resume (const ACE_TCHAR svc_name[]);
+
+ /**
+ * Suspend @a svc_name. Note that this will not unlink the service
+ * from the daemon if it was dynamically linked, it will mark it as
+ * being suspended in the Service Repository and call the <suspend>
+ * member function on the appropriate <ACE_Service_Object>. A
+ * service can be resumed later on by calling the <RESUME> member
+ * function...
+ */
+ int suspend (const ACE_TCHAR svc_name[]);
+
+ /// Totally remove @a svc_name from the daemon by removing it
+ /// from the ACE_Reactor, and unlinking it if necessary.
+ int remove (const ACE_TCHAR svc_name[]);
+
+ /**
+ * Using the supplied name, finds and (if needed) returns a pointer to a
+ * static service descriptor. Returns 0 for success and -1 for failure
+ */
+ int find_static_svc_descriptor (const ACE_TCHAR* name,
+ ACE_Static_Svc_Descriptor **ssd = 0) const;
+
+protected:
+
+ /**
+ *
+ */
+ virtual int parse_args_i (int, ACE_TCHAR *argv[]);
+
+ /**
+ * Performs an open without parsing command-line arguments. The
+ * @a logger_key indicates where to write the logging output, which
+ * is typically either a STREAM pipe or a socket address. If
+ * @a ignore_default_svc_conf_file is non-0 then the "svc.conf" file
+ * will be ignored. If @a ignore_debug_flag is non-0 then the
+ * application is responsible for setting the
+ * @c ACE_Log_Msg::priority_mask() appropriately. Returns number of
+ * errors that occurred on failure and 0 otherwise.
+ */
+ virtual int open_i (const ACE_TCHAR program_name[],
+ const ACE_TCHAR *logger_key = ACE_DEFAULT_LOGGER_KEY,
+ bool ignore_static_svcs = true,
+ bool ignore_default_svc_conf_file = false,
+ bool ignore_debug_flag = false);
+
+ /// Initialize the <svc_conf_file_queue_> if necessary.
+ int init_svc_conf_file_queue (void);
+
+ /// Add the default statically-linked services to the
+ /// ACE_Service_Repository.
+ int load_static_svcs (void);
+
+ /// Process service configuration requests that were provided on the
+ /// command-line. Returns the number of errors that occurred.
+ int process_commandline_directives (void);
+
+#if (ACE_USES_CLASSIC_SVC_CONF == 1)
+ /// This is the implementation function that process_directives()
+ /// and process_directive() both call. Returns the number of errors
+ /// that occurred.
+ int process_directives_i (ACE_Svc_Conf_Param *param);
+#else
+ /// Helper function to dynamically link in the XML Service Configurator
+ /// parser.
+ ACE_XML_Svc_Conf *get_xml_svc_conf (ACE_DLL &d);
+#endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */
+
+ // Dynamically link the shared object file and retrieve a pointer to
+ // the designated shared object in this file.
+ int initialize_i (const ACE_Service_Type *sr, const ACE_TCHAR *parameters);
+
+
+protected:
+
+ // Maintain a queue of services to be configured from the
+ // command-line.
+ typedef ACE_Unbounded_Queue<ACE_TString> ACE_SVC_QUEUE;
+ typedef ACE_Unbounded_Queue_Iterator<ACE_TString> ACE_SVC_QUEUE_ITERATOR;
+
+ // Maintain a set of the statically linked service descriptors.
+ typedef ACE_Unbounded_Set<ACE_Static_Svc_Descriptor *>
+ ACE_STATIC_SVCS;
+
+ typedef ACE_Unbounded_Set_Iterator<ACE_Static_Svc_Descriptor *>
+ ACE_STATIC_SVCS_ITERATOR;
+
+ friend class ACE_Dynamic_Service_Base;
+ friend class ACE_Service_Object;
+ friend class ACE_Service_Config_Guard;
+
+protected:
+
+ /// The service repository to hold the services.
+ ACE_Service_Repository* const repo_;
+
+ /// Do we own the service repository instance or have only been given a ptr
+ /// to the singleton one?
+ bool repo_is_owned_;
+
+ /// Keep track of the number of times the instance has been
+ /// initialized (opened). "If so, we can't allow <yyparse> to be called since
+ /// it's not reentrant" is the original motivation, but that does not seem
+ /// to be the case anymore. This variable is incremented by the
+ /// <ACE_Service_Gestalt::open> method and decremented by the
+ /// <ACE_Service_Gestalt::close> method.
+ int is_opened_;
+
+ /** Queue of svc.conf files specified on the command-line.
+ * @@ This should probably be made to handle unicode filenames...
+ */
+ ACE_SVC_QUEUE* svc_conf_file_queue_;
+
+ /// Repository of statically linked services.
+ ACE_STATIC_SVCS* static_svcs_;
+
+ /// Queue of services specified on the command-line.
+ ACE_SVC_QUEUE* svc_queue_;
+
+ /// Indicates where to write the logging output. This is typically
+ /// either a STREAM pipe or a socket
+ const ACE_TCHAR *logger_key_;
+
+ /// Should we avoid loading the static services?
+ int no_static_svcs_;
+
+}; /* class ACE_Service_Gestalt */
+
+
+class ACE_Location_Node;
+
+// A helper class used to safely register dynamic services, which may contains
+// subordinate static services. It is used to capture the necessary data during
+// the parsing, but perform the actuall instantiation later.
+class ACE_Service_Type_Factory
+{
+public:
+ ACE_Service_Type_Factory (ACE_TCHAR const *name,
+ int type,
+ ACE_Location_Node *location,
+ int active);
+
+ ~ACE_Service_Type_Factory (void);
+
+ ACE_Service_Type *make_service_type (ACE_Service_Gestalt *pcfg) const;
+
+ ACE_TCHAR const* name (void) const;
+
+ /// Declare the dynamic allocation hooks.
+ ACE_ALLOC_HOOK_DECLARE;
+
+private:
+
+ /**
+ * Not implemented to enforce no copying
+ */
+ ACE_UNIMPLEMENTED_FUNC
+ (ACE_Service_Type_Factory(const ACE_Service_Type_Factory&));
+
+ ACE_UNIMPLEMENTED_FUNC
+ (ACE_Service_Type_Factory& operator=(const ACE_Service_Type_Factory&));
+
+private:
+ ACE_TString name_;
+ int type_;
+ ACE_Auto_Ptr<ACE_Location_Node> location_;
+ int is_active_;
+};
+
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#if defined (__ACE_INLINE__)
+#include "ace/Service_Gestalt.inl"
+#endif /* __ACE_INLINE__ */
+
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SERVICE_GESTALT_H */
diff --git a/ace/Service_Gestalt.inl b/ace/Service_Gestalt.inl
new file mode 100644
index 00000000000..9897b83c681
--- /dev/null
+++ b/ace/Service_Gestalt.inl
@@ -0,0 +1,64 @@
+// -*- C++ -*-
+//
+// $Id$
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+
+// This is the primary entry point into the ACE_Service_Config (the
+// constructor just handles simple initializations).
+
+ACE_INLINE int
+ACE_Service_Gestalt::open (const ACE_TCHAR program_name[],
+ const ACE_TCHAR *logger_key,
+ int ignore_static_svcs,
+ int ignore_default_svc_conf,
+ int ignore_debug_flag)
+{
+ ACE_TRACE ("ACE_Service_Gestalt::open");
+ this->no_static_svcs_ = ignore_static_svcs;
+
+ return this->open_i (program_name,
+ logger_key,
+ ignore_static_svcs,
+ ignore_default_svc_conf,
+ ignore_debug_flag);
+}
+
+ACE_INLINE int
+ACE_Service_Gestalt::open (int argc,
+ ACE_TCHAR *argv[],
+ const ACE_TCHAR *logger_key,
+ int ignore_static_svcs,
+ int ignore_default_svc_conf,
+ int ignore_debug_flag)
+{
+ ACE_TRACE ("ACE_Service_Gestalt::open");
+ this->no_static_svcs_ = ignore_static_svcs;
+
+ if (this->parse_args_i (argc,
+ argv) == -1)
+ return -1;
+ else
+ return this->open_i (argv == 0 ? 0 : argv[0],
+ logger_key,
+ ignore_static_svcs,
+ ignore_default_svc_conf,
+ ignore_debug_flag);
+}
+
+/// Searches for a service object declaration in the local repo, only
+
+ACE_INLINE int
+ACE_Service_Gestalt::find (const ACE_TCHAR name[],
+ const ACE_Service_Type **srp,
+ int ignore_suspended) const
+{
+ ACE_ASSERT (this->repo_ != 0);
+ return this->repo_->find (name, srp, ignore_suspended);
+}
+
+
+
+ACE_END_VERSIONED_NAMESPACE_DECL
diff --git a/ace/Svc_Conf_Param.h b/ace/Svc_Conf_Param.h
new file mode 100644
index 00000000000..898b3b5cd07
--- /dev/null
+++ b/ace/Svc_Conf_Param.h
@@ -0,0 +1,140 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Svc_Conf_Param.h
+ *
+ * $Id$
+ *
+ * @author Iliyan Jeliazkov <iliyan@ociweb.com>
+ */
+//=============================================================================
+
+
+#ifndef ACE_SVC_CONF_PARAM_H
+#define ACE_SVC_CONF_PARAM_H
+
+#include /**/ "ace/pre.h"
+
+// Globally visible macros, type decls, and extern var decls for
+// Service Configurator utility.
+
+#include "ace/Obstack.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Forward declarations.
+struct ace_yy_buffer_state;
+class ACE_Service_Gestalt;
+
+extern void ace_yy_delete_buffer (ace_yy_buffer_state *buffer);
+
+/**
+ * @class ACE_Svc_Conf_Param
+ *
+ * @brief An instance of this object will be passed down to the
+ * yyparse() and yylex() functions.
+ *
+ * This is intended for internal use within ACE service configuration
+ * framework only.
+ *
+ * This class retains the state for a given parse/scan. It primarily
+ * makes it possible to hold the static object lock in the scanner
+ * for as short a period of time as possible. The resulting finer
+ * grained locking prevents deadlocks from occuring when scanning a
+ * `svc.conf' file and activating an ACE_Task, for example, as a
+ * result of processing the directives in that file.
+ */
+class ACE_Svc_Conf_Param
+{
+public:
+
+ enum SVC_CONF_PARAM_TYPE
+ {
+ /// The lexer will scan a file containing one or more directives.
+ SVC_CONF_FILE,
+
+ /// The lexer will scan a string containing a directive.
+ SVC_CONF_DIRECTIVE
+ };
+
+ /// Constructor
+ ACE_Svc_Conf_Param (ACE_Service_Gestalt* config, FILE *file)
+ : type (SVC_CONF_FILE),
+ yyerrno (0),
+ yylineno (1),
+ buffer (0),
+ obstack (),
+ config (config)
+ {
+ source.file = file;
+ }
+
+ /// Constructor
+ ACE_Svc_Conf_Param (ACE_Service_Gestalt* config, const ACE_TCHAR *directive)
+ : type (SVC_CONF_DIRECTIVE),
+ yyerrno (0),
+ yylineno (1),
+ buffer (0),
+ obstack (),
+ config (config)
+ {
+ source.directive = directive;
+ }
+
+ ~ACE_Svc_Conf_Param (void)
+ {
+ ace_yy_delete_buffer (this->buffer);
+ }
+
+public:
+
+ union
+ {
+ /// FILE stream from which directives will be scanned and parsed.
+ FILE *file;
+
+ /// String containing directive that will be scanned and parsed.
+ const ACE_TCHAR *directive;
+
+ } source;
+
+ /// Discriminant use to determine which union member to use.
+ SVC_CONF_PARAM_TYPE type;
+
+ /// Keeps track of the number of errors encountered so far.
+ int yyerrno;
+
+ /// Keeps track of the current line number for error-handling routine.
+ int yylineno;
+
+ /// Lexer buffer that corresponds to the current Service
+ /// Configurator file/direct scan.
+ ace_yy_buffer_state *buffer;
+
+ /// Obstack used for efficient memory allocation when
+ /// parsing/scanning a service configurator directive.
+ ACE_Obstack_T<ACE_TCHAR> obstack;
+
+ /// A reference to the configuration
+ ACE_Service_Gestalt *config;
+};
+
+
+// Parameter that is passed down to the yyparse() function, and
+// eventually to yylex().
+#define ACE_YYPARSE_PARAM ace_svc_conf_parameter
+
+#define ACE_YYLEX_PARAM ACE_YYPARSE_PARAM
+
+#define ACE_SVC_CONF_PARAM (static_cast<ACE_Svc_Conf_Param *> (ACE_YYLEX_PARAM))
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SVC_CONF_PARAM_H */