diff options
Diffstat (limited to 'ACE/ace/Service_Gestalt.cpp')
-rw-r--r-- | ACE/ace/Service_Gestalt.cpp | 1281 |
1 files changed, 0 insertions, 1281 deletions
diff --git a/ACE/ace/Service_Gestalt.cpp b/ACE/ace/Service_Gestalt.cpp deleted file mode 100644 index c644ec6ef72..00000000000 --- a/ACE/ace/Service_Gestalt.cpp +++ /dev/null @@ -1,1281 +0,0 @@ -// $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_string.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 - -ACE_Service_Type_Dynamic_Guard::ACE_Service_Type_Dynamic_Guard - (ACE_Service_Repository &r, const ACE_TCHAR *name) - : repo_ (r) - , repo_begin_ (r.current_size ()) - , name_ (name) -# if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) - // On this thread (for the duration of the initialize() method), - // we're about to do two things that require locking: (1) fiddle - // with the repository and (2) load a DLL and hence lock the - // DLL_Manager. - // - // Now if we don't lock the repo here, it is possible that two - // threads may deadlock on initialization because they can acquire - // locks (1) and (2) in different order, for instance: - // - // T1: loads a DLL (2) and registers a service (1); - // - // T2: may be relocating a service (1), which could lead to a - // (re)opening or uping the ref count on a DLL (2); - // - // To prevent this, we lock the repo here, using the repo_monitor_ - // member guard. - , repo_monitor_ (r.lock_) -#endif -{ - 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 - ACE_DLL (), // ... bogus ACE_DLL - 0)); // ... no type_impl - - ACE_ASSERT (this->dummy_ != 0); // No memory? - - if (ACE::debug ()) - ACE_DEBUG ((LM_DEBUG, - ACE_TEXT ("ACE (%P|%t) STDG::<ctor>, repo=%@ [%d], ") - ACE_TEXT ("name=%s, type=%@, impl=%@, object=%@, active=%d - inserting dummy forward\n"), - &this->repo_, this->repo_begin_, this->name_, this->dummy_, - this->dummy_->type (), - (this->dummy_->type () != 0) ? this->dummy_->type ()->object () : 0, - this->dummy_->active ())); - - // Note that the dummy_'s memory may be deallocated between invoking - // the ctor and dtor, if the expected ("real") dynamic service is - // inserted in the repository. See how this affects the destructor's - // behavior, below. - this->repo_.insert (this->dummy_); -} - - -/// Destructor - -ACE_Service_Type_Dynamic_Guard::~ACE_Service_Type_Dynamic_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 - size_t slot = 0; - int const ret = this->repo_.find_i (this->name_, slot, &tmp, false); - - // We inserted it (as inactive), so we expect to find it, right? - if (ret < 0 && ret != -2) - { - if (ACE::debug ()) - ACE_ERROR ((LM_WARNING, - ACE_TEXT ("ACE (%P|%t) STDG::<dtor> - Failed (%d) to find %s\n"), - ret, this->name_)); - return; - } - - if (tmp != 0 && tmp->type () != 0) - { - // Something has registered a proper (non-forward-decl) service with - // the same name as our dummy. - - if (ACE::debug ()) - ACE_DEBUG ((LM_DEBUG, - ACE_TEXT ("ACE (%P|%t) STDG::<dtor>, repo=%@, name=%s - updating [%d - %d]\n"), - &this->repo_, - this->name_, - this->repo_begin_, - this->repo_.current_size ())); - - // Relocate any static services. If any have been registered in - // the context of this guard, those really aren't static - // services because their code is in the DLL's code segment - this->repo_.relocate_i (this->repo_begin_, this->repo_.current_size (), tmp->dll()); - - // The ACE_Service_Gestalt::insert() modifies the memory for the - // original ACE_Service_Type instance. It deletes our dummy - // instance when replacing it with the actual implementation, so - // we are hereby simply giving up ownership. - this->dummy_ = 0; - - if (ACE::debug ()) - ACE_DEBUG ((LM_DEBUG, - ACE_TEXT ("ACE (%P|%t) STDG::<dtor>, repo=%@ [%d], ") - ACE_TEXT ("name=%s, type=%@, impl=%@, object=%@, active=%d - loaded\n"), - &this->repo_, this->repo_begin_, this->name_, tmp, tmp->type (), - (tmp->type () != 0) ? tmp->type ()->object () : 0, - tmp->active ())); - } - else - { - if (ACE::debug ()) - ACE_DEBUG ((LM_DEBUG, - ACE_TEXT ("ACE (%P|%t) STDG::<dtor>, repo=%@, ") - ACE_TEXT ("name=%s, type=%@, impl=%@, object=%@, active=%d - removing dummy forward\n"), - &this->repo_, this->name_, this->dummy_, this->dummy_->type (), - (this->dummy_->type () != 0) ? this->dummy_->type ()->object () : 0, - this->dummy_->active ())); - - // 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_i (this->name_, - const_cast< ACE_Service_Type**> (&this->dummy_)) == 0) - { - // If it is a dummy then deleting it while holding the repo lock is okay. There will be no - // call to service object's fini() and no possibility for deadlocks. - delete this->dummy_; - } - else - { - ACE_ERROR ((LM_WARNING, - ACE_TEXT ("ACE (%P|%t) STDG::<dtor>, repo=%@, name=%s, ") - ACE_TEXT ("type=%@, impl=%@, object=%@, active=%d - dummy remove failed\n"), - &this->repo_, this->name_, this->dummy_, this->dummy_->type (), - (this->dummy_->type () != 0) ? this->dummy_->type ()->object () : 0, - this->dummy_->active ())); - } - } - - // Clean up - this->dummy_ = 0; -} - - - -// ---------------------------------------- - -ACE_Service_Gestalt::Processed_Static_Svc:: -Processed_Static_Svc (const ACE_Static_Svc_Descriptor *assd) - :name_(0), - assd_(assd) -{ - ACE_NEW_NORETURN (name_, ACE_TCHAR[ACE_OS::strlen(assd->name_)+1]); - ACE_OS::strcpy(name_,assd->name_); -} - -ACE_Service_Gestalt::Processed_Static_Svc::~Processed_Static_Svc (void) -{ - delete [] name_; -} - -// ---------------------------------------- - -ACE_Service_Gestalt::~ACE_Service_Gestalt (void) -{ - if (this->svc_repo_is_owned_) - delete this->repo_; - - this->repo_ =0; - - delete this->static_svcs_; - this->static_svcs_ = 0; - - // Delete the dynamically allocated static_svcs instance. -#ifndef ACE_NLOGGING - if (ACE::debug ()) - ACE_DEBUG ((LM_DEBUG, - ACE_TEXT ("ACE (%P|%t) SG::dtor - this=%@, pss = %@\n"), - this, this->processed_static_svcs_)); -#endif - - if (this->processed_static_svcs_ && - !this->processed_static_svcs_->is_empty()) - { - Processed_Static_Svc **pss = 0; - for (ACE_PROCESSED_STATIC_SVCS_ITERATOR iter (*this->processed_static_svcs_); - iter.next (pss) != 0; - iter.advance ()) - { - delete *pss; - } - } - delete this->processed_static_svcs_; - this->processed_static_svcs_ = 0; -} - -ACE_Service_Gestalt::ACE_Service_Gestalt (size_t size, - bool svc_repo_is_owned, - bool no_static_svcs) - : svc_repo_is_owned_ (svc_repo_is_owned) - , svc_repo_size_ (size) - , is_opened_ (0) - , logger_key_ (ACE_DEFAULT_LOGGER_KEY) - , no_static_svcs_ (no_static_svcs) - , svc_queue_ (0) - , svc_conf_file_queue_ (0) - , repo_ (0) - , static_svcs_ (0) - , processed_static_svcs_ (0) -{ - (void)this->init_i (); - -#ifndef ACE_NLOGGING - if (ACE::debug ()) - ACE_DEBUG ((LM_DEBUG, - ACE_TEXT ("ACE (%P|%t) SG::ctor - this = %@, pss = %@\n"), - this, this->processed_static_svcs_)); -#endif -} - -/// Performs the common initialization tasks for a new or previously -/// closed instance. Must not be virtual, as it is also called from -/// the constructor. -int -ACE_Service_Gestalt::init_i (void) -{ - // Only initialize the repo_ if (a) we are being constructed, or; - // (b) we're being open()-ed, perhaps after previously having been - // close()-ed. In both cases: repo_ == 0 and we need a repository. - if (this->repo_ == 0) - { - if (this->svc_repo_is_owned_) - { - ACE_NEW_RETURN (this->repo_, - ACE_Service_Repository (this->svc_repo_size_), - -1); - } - else - { - this->repo_ = - ACE_Service_Repository::instance (this->svc_repo_size_); - } - } - - return 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; -} - -/// @brief - -const ACE_Static_Svc_Descriptor* -ACE_Service_Gestalt::find_processed_static_svc (const ACE_TCHAR* name) -{ - if (this->processed_static_svcs_ == 0 || name == 0) - return 0; - - Processed_Static_Svc **pss = 0; - for (ACE_PROCESSED_STATIC_SVCS_ITERATOR iter (*this->processed_static_svcs_); - iter.next (pss) != 0; - iter.advance ()) - { - if (ACE_OS::strcmp ((*pss)->name_, name) == 0) - return (*pss)->assd_; - } - return 0; -} - - - -/// @brief Captures a list of the direcives processed (explicitely) for this -/// Gestalt so that services can be replicated in other repositories -/// upon their first initialization. -/// -/// This is part of the mechanism ensuring distinct local instances -/// for static service objects, loaded in another repository. - -void -ACE_Service_Gestalt::add_processed_static_svc - (const ACE_Static_Svc_Descriptor *assd) -{ - - /// When process_directive(Static_Svc_Descriptor&) is called, it - /// associates a service object with the Gestalt and makes the - /// resource (a Service Object) local to the repository. This is but - /// the first step in using such SO. The next is the - /// "initialization" step. It is typicaly done through a "static" - /// service configuration directive. - /// - /// In contrast a "dynamic" directive, when processed through the - /// overloaded process_directives(string) both creates the SO - /// locally and initializes it, where the statics directive must - /// first locate the SO and then calls the init() method. This means - /// that durig the "static" initialization there's no specific - /// information about the hosting repository and the gestalt must - /// employ some lookup strategy to find it elsewhere. - - if (this->processed_static_svcs_ == 0) - ACE_NEW (this->processed_static_svcs_, - ACE_PROCESSED_STATIC_SVCS); - - Processed_Static_Svc **pss = 0; - for (ACE_PROCESSED_STATIC_SVCS_ITERATOR iter (*this->processed_static_svcs_); - iter.next (pss) != 0; - iter.advance ()) - { - if (ACE_OS::strcmp ((*pss)->name_, assd->name_) == 0) - { - (*pss)->assd_ = assd; - return; - } - } - Processed_Static_Svc *tmp = 0; - ACE_NEW (tmp,Processed_Static_Svc(assd)); - this->processed_static_svcs_->insert(tmp); - - if (ACE::debug ()) - ACE_DEBUG ((LM_DEBUG, - ACE_TEXT ("ACE (%P|%t) SG::add_processed_static_svc, ") - ACE_TEXT ("repo=%@ - %s\n"), - this->repo_, - assd->name_)); -} - - -/// Queues a static service object descriptor which, during open() -/// will be given to process_directive() to create the Service -/// Object. Normally, only called from static initializers, prior to -/// calling open() but loading a service from a DLL can cause it too. - -int -ACE_Service_Gestalt::insert (ACE_Static_Svc_Descriptor *stsd) -{ - if (this->static_svcs_ == 0) - ACE_NEW_RETURN (this->static_svcs_, - ACE_STATIC_SVCS, - -1); - - 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 */ -} - - - -/// - -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); - -#ifndef ACE_NLOGGING - if (ACE::debug ()) - { - ACE_DEBUG ((LM_DEBUG, - ACE_TEXT ("ACE (%P|%t) SG::initialize - () repo=%@, ") - ACE_TEXT ("looking up static ") - ACE_TEXT ("service \'%s\' to initialize\n"), - this->repo_, - svc_name)); - } -#endif - - const ACE_Service_Type *srp = 0; - for (int i = 0; this->find (svc_name, &srp) == -1 && i < 2; i++) - // if (this->repo_->find (svc_name, &srp) == -1) - { - const ACE_Static_Svc_Descriptor *assd = - ACE_Service_Config::global()->find_processed_static_svc(svc_name); - if (assd != 0) - { - this->process_directive_i(*assd, 0); - } - else - { - ACE_ERROR_RETURN ((LM_ERROR, - ACE_TEXT ("ACE (%P|%t) ERROR: SG::initialize - service \'%s\'") - ACE_TEXT (" was not located.\n"), - svc_name), - -1); - } - } - if (srp == 0) - ACE_ERROR_RETURN ((LM_ERROR, - ACE_TEXT ("ACE (%P|%t) ERROR: SG::initialize - service \'%s\'") - ACE_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_TEXT ("ACE (%P|%t) ERROR: SG::initialize - static init of \'%s\'") - ACE_TEXT (" failed (%p)\n"), - svc_name, ACE_TEXT ("error"))); - this->repo_->remove (svc_name); - return -1; - } - - // If everything is ok, activate it - const_cast<ACE_Service_Type *>(srp)->active (1); - return 0; -} - - -#if (ACE_USES_CLASSIC_SVC_CONF == 1) -int -ACE_Service_Gestalt::initialize (const ACE_Service_Type_Factory *stf, - const ACE_TCHAR *parameters) -{ - ACE_TRACE ("ACE_Service_Gestalt::initialize"); - -#ifndef ACE_NLOGGING - if (ACE::debug ()) - ACE_DEBUG ((LM_DEBUG, - ACE_TEXT ("ACE (%P|%t) SG::initialize - repo=%@, looking up dynamic ") - ACE_TEXT ("service \'%s\' to initialize\n"), - this->repo_, - stf->name ())); -#endif - - ACE_Service_Type *srp = 0; - int const 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. - // IJ: This used to be the behavior, before allowing multiple - // independent service repositories. Should that still be required? - if (retv >= 0) - { -#ifndef ACE_NLOGGING - if (ACE::debug ()) - ACE_ERROR_RETURN ((LM_WARNING, - ACE_TEXT ("ACE (%P|%t) SG::initialize - repo=%@,") - ACE_TEXT (" %s is already initialized.") - ACE_TEXT (" Remove before re-initializing.\n"), - this->repo_, - stf->name ()), - 0); -#endif - return 0; - } - - // If there is an inactive service by that name it may have been - // either inactivated, or just a forward declaration for a service, - // that is in the process of being initialized. If it is 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_TEXT ("ACE (%P|%t) SG::initialize - repo=%@,") - ACE_TEXT (" %s is forward-declared.") - ACE_TEXT (" Recursive initialization requests are") - ACE_TEXT (" not supported.\n"), - this->repo_, - 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 (a forward declaration). This declaration - // ensures maintaining the proper partial ordering of the services - // with respect to their finalization. For example, 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_Dynamic_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. Tthe ACE_Service_Type instance is now owned by the - // repository and we should make sure it is not destroyed upon - // exit from this method. - tmp.release (); - return 0; - } - - return -1; -} -#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. -// @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_TEXT ("ACE (%P|%t) SG::initialize - looking up dynamic ") - ACE_TEXT (" service %s to initialize, repo=%@\n"), - sr->name (), this->repo_)); - - ACE_Service_Type *srp = 0; - if (this->repo_->find (sr->name (), - (const ACE_Service_Type **) &srp) >= 0) - ACE_ERROR_RETURN ((LM_WARNING, - ACE_TEXT ("ACE (%P|%t) SG::initialize - \'%s\' ") - ACE_TEXT ("has already been installed. ") - ACE_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) - { - // We just get ps to avoid having remove() delete it. - ACE_Service_Type *ps = 0; - this->repo_->remove (sr->name (), &ps); - -#ifndef ACE_NLOGGING - // Not using LM_ERROR here to avoid confusing the test harness - if (ACE::debug ()) - ACE_ERROR_RETURN ((LM_WARNING, - ACE_TEXT ("ACE (%P|%t) SG::initialize_i ") - ACE_TEXT ("failed for %s: %m\n"), - sr->name ()), - -1); -#endif - return -1; - } - - if (this->repo_->insert (sr) == -1) - { -#ifndef ACE_NLOGGING - // Not using LM_ERROR here to avoid confusing the test harness - if (ACE::debug ()) - ACE_ERROR_RETURN ((LM_WARNING, - ACE_TEXT ("ACE (%P|%t) SG - repository insert ") - ACE_TEXT ("failed for %s: %m\n"), - sr->name ()), - -1); -#endif - return -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"); - if (this->repo_ == 0) - return -1; - - 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"); - if (this->repo_ == 0) - return -1; - - 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"); - if (this->repo_ == 0) - return -1; - - return this->repo_->resume (svc_name); -} - - -int -ACE_Service_Gestalt::process_directive (const ACE_Static_Svc_Descriptor &ssd, - bool force_replace) -{ - int const result = process_directive_i (ssd, force_replace); - if (result == 0) - { - this->add_processed_static_svc(&ssd); - } - return result; -} - -int -ACE_Service_Gestalt::process_directive_i (const ACE_Static_Svc_Descriptor &ssd, - bool force_replace) -{ - if (this->repo_ == 0) - return -1; - - 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 = 0; - - // This is just a temporary to force the compiler to use the right - // constructor in ACE_Service_Type. Note that, in cases where we are - // called from a static initializer which is part of a DLL, there is - // not enough information about the actuall DLL in this context. - ACE_DLL tmp_dll; - - ACE_NEW_RETURN (service_type, - ACE_Service_Type (ssd.name_, - stp, - tmp_dll, - ssd.active_), - -1); - -#ifndef ACE_NLOGGING - if (ACE::debug ()) - ACE_DEBUG ((LM_DEBUG, - ACE_TEXT ("ACE (%P|%t) SG::process_directive_i, ") - ACE_TEXT ("repo=%@ - %s, dll=%s, force=%d\n"), - this->repo_, - ssd.name_, - (tmp_dll.dll_name_ == 0) ? ACE_TEXT ("<null>") : tmp_dll.dll_name_, - force_replace)); -#endif - - 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); - -#ifndef ACE_NLOGGING - if (ACE::debug ()) - ACE_DEBUG ((LM_DEBUG, - ACE_TEXT ("ACE (%P|%t) SG::process_directives_i, ") - ACE_TEXT ("repo=%@ - %s\n"), - this->repo_, - (param->type == ACE_Svc_Conf_Param::SVC_CONF_FILE) - ? ACE_TEXT ("<from file>") - : param->source.directive)); -#endif - - ::ace_yyparse (param); - - // This is a hack, better errors should be provided... - if (param->yyerrno > 0) - { - // Always set the last error if ace_yyparse() fails. - // Other code may use errno to determine the type - // of problem that occurred from processing directives. - ACE_OS::last_error (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_TEXT ("ACEXML_XML_Svc_Conf_Parser")) == -1) - ACE_ERROR_RETURN ((LM_ERROR, - ACE_TEXT ("ACE (%P|%t) Failure to open ACEXML_XML_Svc_Conf_Parser: %p\n"), - "ACE_Service_Config::get_xml_svc_conf"), - 0); - - void * foo = - xmldll.symbol (ACE_TEXT ("_ACEXML_create_XML_Svc_Conf_Object")); - - ACE_XML_Svc_Conf::Factory factory = - reinterpret_cast<ACE_XML_Svc_Conf::Factory> (foo); - if (factory == 0) - ACE_ERROR_RETURN ((LM_ERROR, - ACE_TEXT ("ACE (%P|%t) 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 ("ACE (%P|%t) Configuration file %s is currently") - ACE_TEXT (" being processed. Ignoring recursive process_file().\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_Dynamic_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_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_TEXT ("ACE (%P|%t): %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 (this->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"); - -#ifndef ACE_NLOGGING - if (ACE::debug ()) - ACE_DEBUG ((LM_DEBUG, - ACE_TEXT ("ACE (%P|%t) SG::process_directive, repo=%@ - %s\n"), - this->repo_, - directive)); -#endif - -#if (ACE_USES_CLASSIC_SVC_CONF == 1) - ACE_UNUSED_ARG (directive); - - ACE_Svc_Conf_Param d (this, directive); - - return this->process_directives_i (&d); -#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; - - // 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); - - 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; - } - -#ifndef ACE_NLOGGING - if (ACE::debug ()) - ACE_DEBUG ((LM_DEBUG, - ACE_TEXT ("ACE (%P|%t) SG::init_svc_conf_file_queue ") - ACE_TEXT ("- this=%@, repo=%@\n"), - this, this->repo_)); -#endif - - 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); - -#ifndef ACE_NLOGGING - if (ACE::debug ()) - ACE_DEBUG ((LM_DEBUG, - ACE_TEXT ("ACE (%P|%t) SG::open_i - this=%@, ") - ACE_TEXT ("opened=%d, loadstatics=%d\n"), - this, this->is_opened_, this->no_static_svcs_)); -#endif - - // 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 (this->init_i () != 0) - return -1; - - if (!ignore_debug_flag) - { - // 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) - { - 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_TEXT ("ACE (%P|%t) %p\n"), - ACE_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"); - //FUZZ: disable check_for_lack_ACE_OS - ACE_Get_Opt getopt (argc, - argv, - ACE_TEXT ("df:k:nyS:"), - 1); // Start at argv[1]. - //FUZZ: enable check_for_lack_ACE_OS - - if (this->init_svc_conf_file_queue () == -1) - return -1; - - //FUZZ: disable check_for_lack_ACE_OS - for (int c; (argc != 0) && ((c = getopt ()) != -1); ) - //FUZZ: enable check_for_lack_ACE_OS - 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_TEXT ("%p\n"), - ACE_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_TEXT ("%p\n"), - ACE_TEXT ("enqueue_tail")), - -1); - break; - default: - if (ACE::debug ()) - ACE_DEBUG ((LM_DEBUG, - ACE_TEXT ("ACE (%P|%t) %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 (!this->is_opened_ || --this->is_opened_ != 0) - return 0; - - // Delete the list fo svc.conf files - delete this->svc_conf_file_queue_; - this->svc_conf_file_queue_ = 0; - - if (this->processed_static_svcs_ && - !this->processed_static_svcs_->is_empty()) - { - Processed_Static_Svc **pss = 0; - for (ACE_PROCESSED_STATIC_SVCS_ITERATOR iter (*this->processed_static_svcs_); - iter.next (pss) != 0; - iter.advance ()) - { - delete *pss; - } - } - delete this->processed_static_svcs_; - this->processed_static_svcs_ = 0; - -#ifndef ACE_NLOGGING - if (ACE::debug ()) - ACE_DEBUG ((LM_DEBUG, - ACE_TEXT ("ACE (%P|%t) SG::close - complete this=%@, repo=%@, owned=%d\n"), - this, this->repo_, this->svc_repo_is_owned_)); -#endif - - if (this->svc_repo_is_owned_) - delete this->repo_; - - this->repo_ = 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) |