[6916] Fixed typos in spell checking code.
[getmangos.git] / dep / ACE_wrappers / ace / Service_Gestalt.cpp
blob6ceeb15260f2b81d007c25cce9c88c180bac062b
1 // $Id: Service_Gestalt.cpp 81673 2008-05-09 19:09:43Z iliyan $
3 #include "ace/Svc_Conf.h"
4 #include "ace/Get_Opt.h"
5 #include "ace/ARGV.h"
6 #include "ace/Malloc.h"
7 #include "ace/Service_Manager.h"
8 #include "ace/Service_Types.h"
9 #include "ace/Containers.h"
10 #include "ace/Auto_Ptr.h"
11 #include "ace/Reactor.h"
12 #include "ace/Thread_Manager.h"
13 #include "ace/DLL.h"
14 #include "ace/XML_Svc_Conf.h"
15 #include "ace/SString.h"
17 #ifndef ACE_LACKS_UNIX_SIGNALS
18 # include "ace/Signal.h"
19 #endif /* !ACE_LACKS_UNIX_SIGNALS */
21 #include "ace/OS_NS_stdio.h"
22 #include "ace/OS_NS_string.h"
23 #include "ace/OS_NS_time.h"
24 #include "ace/OS_NS_unistd.h"
25 #include "ace/OS_NS_sys_stat.h"
27 #include "ace/TSS_T.h"
28 #include "ace/Service_Gestalt.h"
30 #include "ace/Svc_Conf_Param.h"
32 ACE_RCSID (ace,
33 Service_Gestalt,
34 "$Id: Service_Gestalt.cpp 81673 2008-05-09 19:09:43Z iliyan $")
36 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
38 ACE_Service_Type_Dynamic_Guard::ACE_Service_Type_Dynamic_Guard
39 (ACE_Service_Repository &r, const ACE_TCHAR *name)
40 : repo_ (r)
41 // Relocation starts where the next service will be inserted (if any)
42 , repo_begin_ (r.current_size ())
43 , name_ (name)
44 # if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
45 // On this thread (for the duration of the initialize() method),
46 // we're about to do two things that require locking: (1) fiddle
47 // with the repository and (2) load a DLL and hence lock the
48 // DLL_Manager.
50 // Now if we don't lock the repo here, it is possible that two
51 // threads may deadlock on initialization because they can acquire
52 // locks (1) and (2) in different order, for instance:
54 // T1: loads a DLL (2) and registers a service (1);
56 // T2: may be relocating a service (1), which could lead to a
57 // (re)opening or uping the ref count on a DLL (2);
59 // To prevent this, we lock the repo here, using the repo_monitor_
60 // member guard.
61 , repo_monitor_ (r.lock_)
62 #endif
64 if (ACE::debug ())
65 ACE_DEBUG ((LM_DEBUG,
66 ACE_TEXT ("ACE (%P|%t) STDG::<ctor>, repo=%@")
67 ACE_TEXT(", name=%s - begining at [%d]\n"),
68 &this->repo_,
69 this->name_,
70 this->repo_begin_));
72 ACE_ASSERT (this->name_ != 0); // No name?
76 /// Destructor
78 ACE_Service_Type_Dynamic_Guard::~ACE_Service_Type_Dynamic_Guard (void)
80 const ACE_Service_Type *tmp = 0;
82 // Lookup without ignoring suspended services. Making sure
83 // not to ignore any inactive services, since those may be forward
84 // declarations
85 size_t slot = 0;
86 int const ret = this->repo_.find_i (this->name_, slot, &tmp, false);
88 // We inserted it (as inactive), so we expect to find it, right?
89 if ((ret < 0 && ret != -2) || tmp == 0)
91 if (ACE::debug ())
92 ACE_ERROR ((LM_WARNING,
93 ACE_TEXT ("ACE (%P|%t) STDG::<dtor> - Failed (%d) to find %s -> %@\n"),
94 ret, this->name_, tmp));
95 return;
98 if (tmp->type () != 0)
100 // Something has registered a proper (non-forward-decl) service with
101 // the same name as our dummy.
103 if (ACE::debug ())
104 ACE_DEBUG ((LM_DEBUG,
105 ACE_TEXT ("ACE (%P|%t) STDG::<dtor>, repo=%@ [%d], ")
106 ACE_TEXT ("name=%s - updating dependents [%d - %d)\n"),
107 &this->repo_,
108 slot,
109 this->name_,
110 this->repo_begin_,
111 this->repo_.current_size ()));
113 // Relocate any services inserted since we were created.
114 // Any (static, i.e. DLL = 0) services registered in
115 // the context of this guard aren't really static because
116 // their code belongs in the DLL's code segment
117 this->repo_.relocate_i (this->repo_begin_, this->repo_.current_size (), tmp->dll());
119 if (ACE::debug ())
120 ACE_DEBUG ((LM_DEBUG,
121 ACE_TEXT ("ACE (%P|%t) STDG::<dtor>, repo=%@ [%d], ")
122 ACE_TEXT ("name=%s - loaded (type=%@, impl=%@, object=%@, active=%d)\n"),
123 &this->repo_,
124 slot,
125 this->name_,
126 tmp,
127 tmp->type (),
128 tmp->type ()->object (),
129 tmp->active ()));
135 // ----------------------------------------
137 ACE_Service_Gestalt::Processed_Static_Svc::
138 Processed_Static_Svc (const ACE_Static_Svc_Descriptor *assd)
139 :name_(0),
140 assd_(assd)
142 ACE_NEW_NORETURN (name_, ACE_TCHAR[ACE_OS::strlen(assd->name_)+1]);
143 ACE_OS::strcpy(name_,assd->name_);
146 ACE_Service_Gestalt::Processed_Static_Svc::~Processed_Static_Svc (void)
148 delete [] name_;
151 void
152 ACE_Service_Gestalt::intrusive_add_ref (ACE_Service_Gestalt* g)
154 if (g != 0)
156 ++g->refcnt_;
157 ACE_ASSERT (g->refcnt_ > 0);
161 void
162 ACE_Service_Gestalt::intrusive_remove_ref (ACE_Service_Gestalt* g)
164 if (g != 0)
166 long tmp = --g->refcnt_;
167 if (tmp <= 0) delete g;
168 ACE_ASSERT (tmp >= 0);
173 ACE_Service_Gestalt::~ACE_Service_Gestalt (void)
176 if (this->svc_repo_is_owned_)
177 delete this->repo_;
179 this->repo_ =0;
181 delete this->static_svcs_;
182 this->static_svcs_ = 0;
184 // Delete the dynamically allocated static_svcs instance.
185 #ifndef ACE_NLOGGING
186 if (ACE::debug ())
187 ACE_DEBUG ((LM_DEBUG,
188 ACE_TEXT ("ACE (%P|%t) SG::~SG - this=%@, pss = %@\n"),
189 this, this->processed_static_svcs_));
190 #endif
192 if (this->processed_static_svcs_ &&
193 !this->processed_static_svcs_->is_empty())
195 Processed_Static_Svc **pss = 0;
196 for (ACE_PROCESSED_STATIC_SVCS_ITERATOR iter (*this->processed_static_svcs_);
197 iter.next (pss) != 0;
198 iter.advance ())
200 delete *pss;
204 delete this->processed_static_svcs_;
205 this->processed_static_svcs_ = 0;
207 delete this->svc_conf_file_queue_;
208 this->svc_conf_file_queue_ = 0;
211 ACE_Service_Gestalt::ACE_Service_Gestalt (size_t size,
212 bool svc_repo_is_owned,
213 bool no_static_svcs)
214 : svc_repo_is_owned_ (svc_repo_is_owned)
215 , svc_repo_size_ (size)
216 , is_opened_ (0)
217 , logger_key_ (ACE_DEFAULT_LOGGER_KEY)
218 , no_static_svcs_ (no_static_svcs)
219 , svc_queue_ (0)
220 , svc_conf_file_queue_ (0)
221 , repo_ (0)
222 , static_svcs_ (0)
223 , processed_static_svcs_ (0)
224 , refcnt_ (0)
226 (void)this->init_i ();
228 #ifndef ACE_NLOGGING
229 if (ACE::debug ())
230 ACE_DEBUG ((LM_DEBUG,
231 ACE_TEXT ("ACE (%P|%t) SG::ctor - this = %@, pss = %@\n"),
232 this, this->processed_static_svcs_));
233 #endif
236 /// Performs the common initialization tasks for a new or previously
237 /// closed instance. Must not be virtual, as it is also called from
238 /// the constructor.
240 ACE_Service_Gestalt::init_i (void)
242 // Only initialize the repo_ if (a) we are being constructed, or;
243 // (b) we're being open()-ed, perhaps after previously having been
244 // close()-ed. In both cases: repo_ == 0 and we need a repository.
245 if (this->repo_ == 0)
247 if (this->svc_repo_is_owned_)
249 ACE_NEW_RETURN (this->repo_,
250 ACE_Service_Repository (this->svc_repo_size_),
251 -1);
253 else
255 this->repo_ =
256 ACE_Service_Repository::instance (this->svc_repo_size_);
260 if (init_svc_conf_file_queue () == -1)
261 return -1;
263 if ( svc_conf_file_queue_->is_empty ())
265 // Check if the default file exists before attempting to queue it
266 // for processing
267 FILE *fp = ACE_OS::fopen (ACE_DEFAULT_SVC_CONF,
268 ACE_TEXT ("r"));
269 bool skip_static_svcs = (fp == 0);
270 if (fp != 0)
271 ACE_OS::fclose (fp);
273 if (!skip_static_svcs) {
274 // Load the default "svc.conf" entry here if there weren't
275 // overriding -f arguments in <parse_args>.
276 if (svc_conf_file_queue_->enqueue_tail
277 (ACE_TString (ACE_DEFAULT_SVC_CONF)) == -1)
279 ACE_ERROR_RETURN ((LM_ERROR,
280 ACE_TEXT ("%p\n"),
281 ACE_TEXT ("enqueuing ")
282 ACE_DEFAULT_SVC_CONF
283 ACE_TEXT(" file")),
284 -1);
289 return 0;
293 // Add the default statically-linked services to the Service
294 // Repository.
297 ACE_Service_Gestalt::load_static_svcs (void)
299 ACE_TRACE ("ACE_Service_Gestalt::load_static_svcs");
301 if (this->static_svcs_ == 0)
302 return 0; // Nothing to do
304 ACE_Static_Svc_Descriptor **ssdp = 0;
305 for (ACE_STATIC_SVCS_ITERATOR iter (*this->static_svcs_);
306 iter.next (ssdp) != 0;
307 iter.advance ())
309 ACE_Static_Svc_Descriptor *ssd = *ssdp;
311 if (this->process_directive (*ssd, 1) == -1)
312 return -1;
314 return 0;
316 } /* load_static_svcs () */
320 /// Find a static service descriptor by name
323 ACE_Service_Gestalt::find_static_svc_descriptor (const ACE_TCHAR* name,
324 ACE_Static_Svc_Descriptor **ssd) const
326 ACE_TRACE ("ACE_Service_Gestalt::find_static_svc_descriptor");
328 if (this->static_svcs_ == 0)
329 return -1;
331 ACE_Static_Svc_Descriptor **ssdp = 0;
332 for (ACE_STATIC_SVCS_ITERATOR iter ( *this->static_svcs_);
333 iter.next (ssdp) != 0;
334 iter.advance ())
336 if (ACE_OS::strcmp ((*ssdp)->name_, name) == 0)
338 if (ssd != 0)
339 *ssd = *ssdp;
341 return 0;
345 return -1;
348 /// @brief
350 const ACE_Static_Svc_Descriptor*
351 ACE_Service_Gestalt::find_processed_static_svc (const ACE_TCHAR* name)
353 if (this->processed_static_svcs_ == 0 || name == 0)
354 return 0;
356 Processed_Static_Svc **pss = 0;
357 for (ACE_PROCESSED_STATIC_SVCS_ITERATOR iter (*this->processed_static_svcs_);
358 iter.next (pss) != 0;
359 iter.advance ())
361 if (ACE_OS::strcmp ((*pss)->name_, name) == 0)
362 return (*pss)->assd_;
364 return 0;
369 /// @brief Captures a list of the direcives processed (explicitely) for this
370 /// Gestalt so that services can be replicated in other repositories
371 /// upon their first initialization.
373 /// This is part of the mechanism ensuring distinct local instances
374 /// for static service objects, loaded in another repository.
376 void
377 ACE_Service_Gestalt::add_processed_static_svc
378 (const ACE_Static_Svc_Descriptor *assd)
381 /// When process_directive(Static_Svc_Descriptor&) is called, it
382 /// associates a service object with the Gestalt and makes the
383 /// resource (a Service Object) local to the repository. This is but
384 /// the first step in using such SO. The next is the
385 /// "initialization" step. It is typicaly done through a "static"
386 /// service configuration directive.
388 /// In contrast a "dynamic" directive, when processed through the
389 /// overloaded process_directives(string) both creates the SO
390 /// locally and initializes it, where the statics directive must
391 /// first locate the SO and then calls the init() method. This means
392 /// that durig the "static" initialization there's no specific
393 /// information about the hosting repository and the gestalt must
394 /// employ some lookup strategy to find it elsewhere.
396 if (this->processed_static_svcs_ == 0)
397 ACE_NEW (this->processed_static_svcs_,
398 ACE_PROCESSED_STATIC_SVCS);
400 Processed_Static_Svc **pss = 0;
401 for (ACE_PROCESSED_STATIC_SVCS_ITERATOR iter (*this->processed_static_svcs_);
402 iter.next (pss) != 0;
403 iter.advance ())
405 if (ACE_OS::strcmp ((*pss)->name_, assd->name_) == 0)
407 (*pss)->assd_ = assd;
408 return;
411 Processed_Static_Svc *tmp = 0;
412 ACE_NEW (tmp,Processed_Static_Svc(assd));
413 this->processed_static_svcs_->insert(tmp);
415 if (ACE::debug ())
416 ACE_DEBUG ((LM_DEBUG,
417 ACE_TEXT ("ACE (%P|%t) SG::add_processed_static_svc, ")
418 ACE_TEXT ("repo=%@ - %s\n"),
419 this->repo_,
420 assd->name_));
424 /// Queues a static service object descriptor which, during open()
425 /// will be given to process_directive() to create the Service
426 /// Object. Normally, only called from static initializers, prior to
427 /// calling open() but loading a service from a DLL can cause it too.
430 ACE_Service_Gestalt::insert (ACE_Static_Svc_Descriptor *stsd)
432 if (this->static_svcs_ == 0)
433 ACE_NEW_RETURN (this->static_svcs_,
434 ACE_STATIC_SVCS,
435 -1);
437 return this->static_svcs_->insert (stsd);
441 ACE_ALLOC_HOOK_DEFINE (ACE_Service_Gestalt)
444 void
445 ACE_Service_Gestalt::dump (void) const
447 #if defined (ACE_HAS_DUMP)
448 ACE_TRACE ("ACE_Service_Gestalt::dump");
449 #endif /* ACE_HAS_DUMP */
457 ACE_Service_Gestalt::initialize (const ACE_TCHAR *svc_name,
458 const ACE_TCHAR *parameters)
460 ACE_TRACE ("ACE_Service_Gestalt_Base::initialize (repo)");
461 ACE_ARGV args (parameters);
463 #ifndef ACE_NLOGGING
464 if (ACE::debug ())
466 ACE_DEBUG ((LM_DEBUG,
467 ACE_TEXT ("ACE (%P|%t) SG::initialize - () repo=%@, ")
468 ACE_TEXT ("looking up static ")
469 ACE_TEXT ("service \'%s\' to initialize\n"),
470 this->repo_,
471 svc_name));
473 #endif
475 const ACE_Service_Type *srp = 0;
476 for (int i = 0; this->find (svc_name, &srp) == -1 && i < 2; i++)
477 // if (this->repo_->find (svc_name, &srp) == -1)
479 const ACE_Static_Svc_Descriptor *assd =
480 ACE_Service_Config::global()->find_processed_static_svc(svc_name);
481 if (assd != 0)
483 this->process_directive_i(*assd, 0);
485 else
487 ACE_ERROR_RETURN ((LM_ERROR,
488 ACE_TEXT ("ACE (%P|%t) ERROR: SG::initialize - service \'%s\'")
489 ACE_TEXT (" was not located.\n"),
490 svc_name),
491 -1);
494 if (srp == 0)
495 ACE_ERROR_RETURN ((LM_ERROR,
496 ACE_TEXT ("ACE (%P|%t) ERROR: SG::initialize - service \'%s\'")
497 ACE_TEXT (" was not located.\n"),
498 svc_name),
499 -1);
501 /// If initialization fails ...
502 if (srp->type ()->init (args.argc (),
503 args.argv ()) == -1)
505 // ... report and remove this entry.
506 ACE_ERROR ((LM_ERROR,
507 ACE_TEXT ("ACE (%P|%t) ERROR: SG::initialize - static init of \'%s\'")
508 ACE_TEXT (" failed (%p)\n"),
509 svc_name, ACE_TEXT ("error")));
510 this->repo_->remove (svc_name);
511 return -1;
514 // If everything is ok, activate it
515 const_cast<ACE_Service_Type *>(srp)->active (1);
516 return 0;
520 #if (ACE_USES_CLASSIC_SVC_CONF == 1)
522 ACE_Service_Gestalt::initialize (const ACE_Service_Type_Factory *stf,
523 const ACE_TCHAR *parameters)
525 ACE_TRACE ("ACE_Service_Gestalt::initialize");
527 #ifndef ACE_NLOGGING
528 if (ACE::debug ())
529 ACE_DEBUG ((LM_DEBUG,
530 ACE_TEXT ("ACE (%P|%t) SG::initialize - repo=%@, name=%s")
531 ACE_TEXT (" - looking up in the repo\n"),
532 this->repo_,
533 stf->name ()));
534 #endif
536 ACE_Service_Type *srp = 0;
537 int const retv = this->repo_->find (stf->name (),
538 (const ACE_Service_Type **) &srp);
540 // If there is an active service already, remove it first
541 // before it can be re-installed.
542 if (retv >= 0)
544 #ifndef ACE_NLOGGING
545 if (ACE::debug ())
546 ACE_DEBUG ((LM_WARNING,
547 ACE_TEXT ("ACE (%P|%t) SG::initialize - repo=%@,")
548 ACE_TEXT (" name=%s - removing a pre-existing namesake.\n"),
549 this->repo_,
550 stf->name ()));
551 #endif
552 this->repo_->remove (stf->name ());
555 // If there is an inactive service by that name it may have been
556 // either inactivated, or just a forward declaration for a service,
557 // that is in the process of being initialized. If it is the latter,
558 // then we have detected an attempt to initialize the same dynamic
559 // service while still processing previous attempt. This can lock up
560 // the process, because the ACE_DLL_Manager::open () is not
561 // re-entrant - it uses a Singleton lock to serialize concurent
562 // invocations. This use case must be handled here, because if the
563 // DLL_Manager was re-entrant we would have entered an infinite
564 // recursion here.
565 if (retv == -2 && srp->type () == 0)
566 ACE_ERROR_RETURN ((LM_WARNING,
567 ACE_TEXT ("ACE (%P|%t) SG::initialize - repo=%@,")
568 ACE_TEXT (" name=%s - forward-declared; ")
569 ACE_TEXT (" recursive initialization requests are")
570 ACE_TEXT (" ignored.\n"),
571 this->repo_,
572 stf->name ()),
573 -1);
575 // Reserve a spot for the dynamic service by inserting an incomplete
576 // service declaration, i.e. one that can not produce a service
577 // object if asked (a forward declaration). This declaration
578 // ensures maintaining the proper partial ordering of the services
579 // with respect to their finalization. For example, dependent static
580 // services must be registered *after* the dynamic service that
581 // loads them, so that their finalization is complete *before*
582 // finalizing the dynamic service.
583 ACE_Service_Type_Dynamic_Guard dummy (*this->repo_,
584 stf->name ());
586 // make_service_type() is doing the dynamic loading and also runs
587 // any static initializers
588 ACE_Auto_Ptr<ACE_Service_Type> tmp (stf->make_service_type (this));
590 if (tmp.get () != 0 &&
591 this->initialize_i (tmp.get (), parameters) == 0)
593 // All good. Tthe ACE_Service_Type instance is now owned by the
594 // repository and we should make sure it is not destroyed upon
595 // exit from this method.
596 tmp.release ();
597 return 0;
600 return -1;
602 #endif /* (ACE_USES_CLASSIC_SVC_CONF == 1) */
605 // Dynamically link the shared object file and retrieve a pointer to
606 // the designated shared object in this file.
607 // @note This is obsolete (and error-prone) in the presense of dynamic
608 // services with their own static services. This method will allow those
609 // static services to register *before* the dynamic service that owns them.
610 // Upon finalization of the static services the process may crash, because
611 // the dynamic service's DLL may have been already released, together with
612 // the memory in which the static services reside.
613 // It may not crash, for instance, when the first static service to register
614 // is the same as the dynamic service being loaded. You should be so lucky! ..
617 ACE_Service_Gestalt::initialize (const ACE_Service_Type *sr,
618 const ACE_TCHAR *parameters)
620 ACE_TRACE ("ACE_Service_Gestalt::initialize");
622 if (ACE::debug ())
623 ACE_DEBUG ((LM_DEBUG,
624 ACE_TEXT ("ACE (%P|%t) SG::initialize - repo=%@, name=%s")
625 ACE_TEXT (" - looking up in the repo\n"),
626 this->repo_,
627 sr->name ()));
629 ACE_Service_Type *srp = 0;
630 if (this->repo_->find (sr->name (),
631 (const ACE_Service_Type **) &srp) >= 0)
633 #ifndef ACE_NLOGGING
634 ACE_DEBUG ((LM_WARNING,
635 ACE_TEXT ("ACE (%P|%t) SG::initialize - repo=%@, name=%s")
636 ACE_TEXT (" - removing a pre-existing namesake.\n"),
637 this->repo_,
638 sr->name ()));
639 #endif
640 this->repo_->remove (sr->name ());
643 return this->initialize_i (sr, parameters);
647 // Dynamically link the shared object file and retrieve a pointer to
648 // the designated shared object in this file.
650 ACE_Service_Gestalt::initialize_i (const ACE_Service_Type *sr,
651 const ACE_TCHAR *parameters)
653 ACE_TRACE ("ACE_Service_Gestalt::initialize_i");
654 ACE_ARGV args (parameters);
655 if (sr->type ()->init (args.argc (),
656 args.argv ()) == -1)
658 // We just get ps to avoid having remove() delete it.
659 ACE_Service_Type *ps = 0;
660 this->repo_->remove (sr->name (), &ps);
662 #ifndef ACE_NLOGGING
663 // Not using LM_ERROR here to avoid confusing the test harness
664 if (ACE::debug ())
665 ACE_ERROR_RETURN ((LM_WARNING,
666 ACE_TEXT ("ACE (%P|%t) SG::initialize_i -")
667 ACE_TEXT (" repo=%@, name=%s - remove failed: %m\n"),
668 this->repo_,
669 sr->name ()),
670 -1);
671 #endif
672 return -1;
675 if (this->repo_->insert (sr) == -1)
677 #ifndef ACE_NLOGGING
678 // Not using LM_ERROR here to avoid confusing the test harness
679 if (ACE::debug ())
680 ACE_ERROR_RETURN ((LM_WARNING,
681 ACE_TEXT ("ACE (%P|%t) SG::initialize_i -")
682 ACE_TEXT (" repo=%@, name=%s - insert failed: %m\n"),
683 this->repo_,
684 sr->name ()),
685 -1);
686 #endif
687 return -1;
690 return 0;
693 // Totally remove <svc_name> from the daemon by removing it from the
694 // ACE_Reactor, and unlinking it if necessary.
697 ACE_Service_Gestalt::remove (const ACE_TCHAR svc_name[])
699 ACE_TRACE ("ACE_Service_Gestalt::remove");
700 if (this->repo_ == 0)
701 return -1;
703 return this->repo_->remove (svc_name);
706 // Suspend <svc_name>. Note that this will not unlink the service
707 // from the daemon if it was dynamically linked, it will mark it as
708 // being suspended in the Service Repository and call the <suspend>
709 // member function on the appropriate <ACE_Service_Object>. A service
710 // can be resumed later on by calling the <resume> method...
713 ACE_Service_Gestalt::suspend (const ACE_TCHAR svc_name[])
715 ACE_TRACE ("ACE_Service_Gestalt::suspend");
716 if (this->repo_ == 0)
717 return -1;
719 return this->repo_->suspend (svc_name);
722 // Resume a SVC_NAME that was previously suspended or has not yet
723 // been resumed (e.g., a static service).
726 ACE_Service_Gestalt::resume (const ACE_TCHAR svc_name[])
728 ACE_TRACE ("ACE_Service_Gestalt::resume");
729 if (this->repo_ == 0)
730 return -1;
732 return this->repo_->resume (svc_name);
737 ACE_Service_Gestalt::process_directive (const ACE_Static_Svc_Descriptor &ssd,
738 bool force_replace)
740 int const result = process_directive_i (ssd, force_replace);
741 if (result == 0)
743 this->add_processed_static_svc(&ssd);
745 return result;
749 ACE_Service_Gestalt::process_directive_i (const ACE_Static_Svc_Descriptor &ssd,
750 bool force_replace)
752 if (this->repo_ == 0)
753 return -1;
755 if (!force_replace)
757 if (this->repo_->find (ssd.name_, 0, 0) >= 0)
759 // The service is already there, just return
760 return 0;
765 ACE_Service_Object_Exterminator gobbler;
766 void *sym = (ssd.alloc_)(&gobbler);
768 ACE_Service_Type_Impl *stp =
769 ACE_Service_Config::create_service_type_impl (ssd.name_,
770 ssd.type_,
771 sym,
772 ssd.flags_,
773 gobbler);
774 if (stp == 0)
775 return 0;
777 ACE_Service_Type *service_type = 0;
779 // This is just a temporary to force the compiler to use the right
780 // constructor in ACE_Service_Type. Note that, in cases where we are
781 // called from a static initializer which is part of a DLL, there is
782 // not enough information about the actuall DLL in this context.
783 ACE_DLL tmp_dll;
785 ACE_NEW_RETURN (service_type,
786 ACE_Service_Type (ssd.name_,
787 stp,
788 tmp_dll,
789 ssd.active_),
790 -1);
792 #ifndef ACE_NLOGGING
793 if (ACE::debug ())
794 ACE_DEBUG ((LM_DEBUG,
795 ACE_TEXT ("ACE (%P|%t) SG::process_directive_i, ")
796 ACE_TEXT ("repo=%@ - %s, dll=%s, force=%d\n"),
797 this->repo_,
798 ssd.name_,
799 (tmp_dll.dll_name_ == 0) ? ACE_TEXT ("<null>") : tmp_dll.dll_name_,
800 force_replace));
801 #endif
803 return this->repo_->insert (service_type);
806 #if (ACE_USES_CLASSIC_SVC_CONF == 1)
809 ACE_Service_Gestalt::process_directives_i (ACE_Svc_Conf_Param *param)
811 #ifndef ACE_NLOGGING
812 if (ACE::debug ())
813 ACE_DEBUG ((LM_DEBUG,
814 ACE_TEXT ("ACE (%P|%t) SG::process_directives_i, ")
815 ACE_TEXT ("repo=%@ - %s\n"),
816 this->repo_,
817 (param->type == ACE_Svc_Conf_Param::SVC_CONF_FILE)
818 ? ACE_TEXT ("<from file>")
819 : param->source.directive));
820 #endif
822 // AC 970827 Skip the heap check because yacc allocates a buffer
823 // here which will be reported as a memory leak for some reason.
824 ACE_NO_HEAP_CHECK
826 // Were we called in the context of the current instance?
827 ACE_ASSERT (this == param->config);
829 // Temporarily (for the duration of this call) make sure that *any*
830 // static service registrations will happen with this instance. Such
831 // registrations are possible as a side-effect of dynamically
832 // loading a DLL, which has other static services registered. Thus
833 // this instance will own both the DLL and those static services,
834 // which implies that their finalization will be performed in the
835 // correct order, i.e. prior to finalizing the DLL
836 ACE_Service_Config_Guard guard (this);
838 ::ace_yyparse (param);
840 // This is a hack, better errors should be provided...
841 if (param->yyerrno > 0)
843 // Always set the last error if ace_yyparse() fails.
844 // Other code may use errno to determine the type
845 // of problem that occurred from processing directives.
846 ACE_OS::last_error (EINVAL);
847 return param->yyerrno;
849 else
850 return 0;
853 #else
855 ACE_XML_Svc_Conf *
856 ACE_Service_Gestalt::get_xml_svc_conf (ACE_DLL &xmldll)
858 if (xmldll.open (ACE_TEXT ("ACEXML_XML_Svc_Conf_Parser")) == -1)
859 ACE_ERROR_RETURN ((LM_ERROR,
860 ACE_TEXT ("ACE (%P|%t) Failure to open ACEXML_XML_Svc_Conf_Parser: %p\n"),
861 "ACE_Service_Config::get_xml_svc_conf"),
864 void * foo =
865 xmldll.symbol (ACE_TEXT ("_ACEXML_create_XML_Svc_Conf_Object"));
867 ACE_XML_Svc_Conf::Factory factory =
868 reinterpret_cast<ACE_XML_Svc_Conf::Factory> (foo);
869 if (factory == 0)
870 ACE_ERROR_RETURN ((LM_ERROR,
871 ACE_TEXT ("ACE (%P|%t) Unable to resolve factory: %p\n"),
872 xmldll.error ()),
875 return factory ();
877 #endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */
880 ACE_Service_Gestalt::process_file (const ACE_TCHAR file[])
882 ACE_TRACE ("ACE_Service_Gestalt::process_file");
884 // To avoid recursive processing of the same file and the same repository
885 // we maintain an implicit stack of dummy "services" named after the file
886 // being processed. Anytime we have to open a new file, we then can check
887 // to see if it is not already being processed by searching for a dummy
888 // service with a matching name.
889 if (this->repo_->find (file, 0, 0) >=0)
891 ACE_DEBUG ((LM_WARNING,
892 ACE_TEXT ("ACE (%P|%t) Configuration file %s is currently")
893 ACE_TEXT (" being processed. Ignoring recursive process_file().\n"),
894 file));
895 return 0;
898 // Register a dummy service as a forward decl, using the file name as name.
899 // The entry will be automaticaly removed once the thread exits this block.
900 ACE_Service_Type_Dynamic_Guard recursion_guard (*this->repo_,
901 file);
904 * @TODO: Test with ACE_USES_CLASSIC_SVC_CONF turned off!
906 #if (ACE_USES_CLASSIC_SVC_CONF == 1)
907 int result = 0;
909 FILE *fp = ACE_OS::fopen (file,
910 ACE_TEXT ("r"));
912 if (fp == 0)
914 // Invalid svc.conf file. We'll report it here and break out of
915 // the method.
916 if (ACE::debug ())
917 ACE_DEBUG ((LM_ERROR,
918 ACE_TEXT ("ACE (%P|%t): %p\n"),
919 file));
921 // Use stat to find out if the file exists. I didn't use access()
922 // because stat is better supported on most non-unix platforms.
923 ACE_stat exists;
924 if (ACE_OS::stat (file, &exists) == 0)
925 // If it exists, but we couldn't open it for reading then we
926 // must not have permission to read it.
927 errno = EPERM;
928 else
929 errno = ENOENT;
930 result = -1;
932 else
934 ACE_Svc_Conf_Param f (this, fp);
936 // Keep track of the number of errors.
937 result = this->process_directives_i (&f);
939 (void) ACE_OS::fclose (fp);
941 return result;
942 #else
943 ACE_DLL dll;
945 auto_ptr<ACE_XML_Svc_Conf>
946 xml_svc_conf (this->get_xml_svc_conf (dll));
948 if (xml_svc_conf.get () == 0)
949 return -1;
951 return xml_svc_conf->parse_file (file);
952 #endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */
956 ACE_Service_Gestalt::process_directive (const ACE_TCHAR directive[])
958 ACE_TRACE ("ACE_Service_Gestalt::process_directive");
960 #ifndef ACE_NLOGGING
961 if (ACE::debug ())
962 ACE_DEBUG ((LM_DEBUG,
963 ACE_TEXT ("ACE (%P|%t) SG::process_directive, repo=%@ - %s\n"),
964 this->repo_,
965 directive));
966 #endif
968 #if (ACE_USES_CLASSIC_SVC_CONF == 1)
969 ACE_UNUSED_ARG (directive);
971 ACE_Svc_Conf_Param d (this, directive);
973 return this->process_directives_i (&d);
974 #else
975 ACE_DLL dll;
977 auto_ptr<ACE_XML_Svc_Conf>
978 xml_svc_conf (this->get_xml_svc_conf (dll));
980 if (xml_svc_conf.get () == 0)
981 return -1;
983 // Temporarily (for the duration of this call) make sure that *any* static
984 // service registrations will happen with this instance. Such registrations
985 // are possible as a side-effect of dynamically loading a DLL, which has
986 // other static services registered. Thus this instance will own both the
987 // DLL and those static services, which implies that their finalization
988 // will be performed in the correct order, i.e. prior to finalizing the DLL
989 ACE_Service_Config_Guard guard (this);
991 return xml_svc_conf->parse_string (directive);
992 #endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */
994 } /* process_directive () */
998 ACE_Service_Gestalt::init_svc_conf_file_queue (void)
1000 if (this->svc_conf_file_queue_ == 0)
1002 ACE_SVC_QUEUE *tmp = 0;
1003 ACE_NEW_RETURN (tmp,
1004 ACE_SVC_QUEUE,
1005 -1);
1006 this->svc_conf_file_queue_ = tmp;
1009 #ifndef ACE_NLOGGING
1010 if (ACE::debug ())
1011 ACE_DEBUG ((LM_DEBUG,
1012 ACE_TEXT ("ACE (%P|%t) SG::init_svc_conf_file_queue ")
1013 ACE_TEXT ("- this=%@, repo=%@\n"),
1014 this, this->repo_));
1015 #endif
1017 return 0;
1019 } /* init_svc_conf_file_queue () */
1023 ACE_Service_Gestalt::open_i (const ACE_TCHAR /*program_name*/[],
1024 const ACE_TCHAR* /*logger_key*/,
1025 bool ignore_static_svcs,
1026 bool ignore_default_svc_conf_file,
1027 bool ignore_debug_flag)
1029 ACE_TRACE ("ACE_Service_Gestalt::open_i");
1030 int result = 0;
1031 ACE_Log_Msg *log_msg = ACE_LOG_MSG;
1033 no_static_svcs_ = ignore_static_svcs;
1035 // Record the current log setting upon entering this thread.
1036 u_long old_process_mask = log_msg->priority_mask
1037 (ACE_Log_Msg::PROCESS);
1039 u_long old_thread_mask = log_msg->priority_mask
1040 (ACE_Log_Msg::THREAD);
1042 #ifndef ACE_NLOGGING
1043 if (ACE::debug ())
1044 ACE_DEBUG ((LM_DEBUG,
1045 ACE_TEXT ("ACE (%P|%t) SG::open_i - this=%@, ")
1046 ACE_TEXT ("opened=%d, loadstatics=%d\n"),
1047 this, this->is_opened_, this->no_static_svcs_));
1048 #endif
1050 // Guard against reentrant processing. For example,
1051 // if the singleton gestalt (ubergestalt) was already open,
1052 // do not open it again...
1053 if (this->is_opened_++ != 0)
1054 return 0;
1056 if (this->init_i () != 0)
1057 return -1;
1059 if (!ignore_debug_flag)
1061 // If -d was included as a startup parameter, the user wants debug
1062 // information printed during service initialization.
1063 if (ACE::debug ())
1064 ACE_Log_Msg::enable_debug_messages ();
1065 else
1066 // The user has requested no debugging info.
1067 ACE_Log_Msg::disable_debug_messages ();
1070 // See if we need to load the static services.
1071 if (this->no_static_svcs_ == 0
1072 && this->load_static_svcs () == -1)
1073 result = -1;
1074 else
1076 if (this->process_commandline_directives () == -1)
1077 result = -1;
1078 else
1079 result = this->process_directives (ignore_default_svc_conf_file);
1083 // Reset debugging back to the way it was when we came into
1084 // into <open_i>.
1086 // Make sure to save/restore errno properly.
1087 ACE_Errno_Guard error (errno);
1089 if (!ignore_debug_flag)
1091 log_msg->priority_mask (old_process_mask, ACE_Log_Msg::PROCESS);
1092 log_msg->priority_mask (old_thread_mask, ACE_Log_Msg::THREAD);
1096 return result;
1097 } /* open_i () */
1101 ACE_Service_Gestalt::is_opened (void)
1103 return this->is_opened_;
1107 ACE_Service_Gestalt::process_commandline_directives (void)
1109 int result = 0;
1110 if (this->svc_queue_ != 0)
1112 ACE_TString *sptr = 0;
1113 for (ACE_SVC_QUEUE_ITERATOR iter (*this->svc_queue_);
1114 iter.next (sptr) != 0;
1115 iter.advance ())
1117 // Process just a single directive.
1118 if (this->process_directive ((sptr->fast_rep ())) != 0)
1120 ACE_ERROR ((LM_ERROR,
1121 ACE_TEXT ("ACE (%P|%t) %p\n"),
1122 ACE_TEXT ("process_directive")));
1123 result = -1;
1127 delete this->svc_queue_;
1128 this->svc_queue_ = 0;
1131 return result;
1133 } /* process_commandline_directives () */
1137 ACE_Service_Gestalt::parse_args (int argc, ACE_TCHAR *argv[])
1139 ACE_TRACE ("ACE_Service_Gestalt::parse_args");
1140 bool unused_ignore_default_svc_conf = true;
1141 return parse_args_i (argc, argv, unused_ignore_default_svc_conf);
1145 ACE_Service_Gestalt::parse_args_i (int argc,
1146 ACE_TCHAR *argv[],
1147 bool &ignore_default_svc_conf_file)
1149 ACE_TRACE ("ACE_Service_Gestalt::parse_args_i");
1150 //FUZZ: disable check_for_lack_ACE_OS
1151 ACE_Get_Opt getopt (argc,
1152 argv,
1153 ACE_TEXT ("df:k:nyS:"),
1154 1); // Start at argv[1].
1155 //FUZZ: enable check_for_lack_ACE_OS
1157 if (this->init_svc_conf_file_queue () == -1)
1158 return -1;
1160 //FUZZ: disable check_for_lack_ACE_OS
1161 for (int c; (argc != 0) && ((c = getopt ()) != -1); )
1162 //FUZZ: enable check_for_lack_ACE_OS
1163 switch (c)
1165 case 'd':
1166 ACE::debug (1);
1167 break;
1168 case 'f':
1169 if (this->svc_conf_file_queue_->enqueue_tail (ACE_TString (getopt.opt_arg ())) == -1)
1170 ACE_ERROR_RETURN ((LM_ERROR,
1171 ACE_TEXT ("%p\n"),
1172 ACE_TEXT ("enqueue_tail")),
1173 -1);
1174 ignore_default_svc_conf_file = true;
1175 break;
1176 case 'k':
1178 * @TODO: Is this always a static storage? Shouldn't we copy
1179 * & gain ownership of the value?
1181 this->logger_key_ = getopt.opt_arg ();
1182 break;
1183 case 'n':
1184 this->no_static_svcs_ = 1;
1185 break;
1186 case 'y':
1187 this->no_static_svcs_ = 0;
1188 break;
1189 case 'S':
1190 if (this->svc_queue_ == 0)
1192 ACE_NEW_RETURN (this->svc_queue_,
1193 ACE_SVC_QUEUE,
1194 -1);
1197 if (this->svc_queue_->enqueue_tail (ACE_TString (getopt.opt_arg ())) == -1)
1198 ACE_ERROR_RETURN ((LM_ERROR,
1199 ACE_TEXT ("%p\n"),
1200 ACE_TEXT ("enqueue_tail")),
1201 -1);
1202 break;
1203 default:
1204 if (ACE::debug ())
1205 ACE_DEBUG ((LM_DEBUG,
1206 ACE_TEXT ("ACE (%P|%t) %c is not a ACE_Service_Config option\n"),
1207 c));
1210 return 0;
1211 } /* parse_args_i () */
1215 // Process service configuration directives from the files queued for
1216 // processing
1218 ACE_Service_Gestalt::process_directives (bool ignore_default_svc_conf_file)
1220 ACE_TRACE ("ACE_Service_Gestalt::process_directives");
1222 if (this->svc_conf_file_queue_ == 0
1223 || this->svc_conf_file_queue_->is_empty ())
1224 return 0;
1226 ACE_TString *sptr = 0;
1227 ACE_TString default_svc_conf (ACE_DEFAULT_SVC_CONF);
1229 // Iterate through all the svc.conf files.
1230 for (ACE_SVC_QUEUE_ITERATOR iter (*this->svc_conf_file_queue_);
1231 iter.next (sptr) != 0;
1232 iter.advance ())
1234 if (*sptr == default_svc_conf && ignore_default_svc_conf_file)
1235 continue;
1237 int result = this->process_file (sptr->fast_rep ());
1238 if (result < 0)
1239 return result;
1242 return 0;
1244 } /* process_directives () */
1246 // Tidy up and perform last rites on a terminating ACE_Service_Gestalt.
1248 ACE_Service_Gestalt::close (void)
1250 ACE_TRACE ("ACE_Service_Gestalt::close");
1252 if (!this->is_opened_ || --this->is_opened_ != 0)
1253 return 0;
1255 // Delete the list fo svc.conf files
1256 delete this->svc_conf_file_queue_;
1257 this->svc_conf_file_queue_ = 0;
1259 if (this->processed_static_svcs_ &&
1260 !this->processed_static_svcs_->is_empty())
1262 Processed_Static_Svc **pss = 0;
1263 for (ACE_PROCESSED_STATIC_SVCS_ITERATOR iter (*this->processed_static_svcs_);
1264 iter.next (pss) != 0;
1265 iter.advance ())
1267 delete *pss;
1270 delete this->processed_static_svcs_;
1271 this->processed_static_svcs_ = 0;
1273 #ifndef ACE_NLOGGING
1274 if (ACE::debug ())
1275 ACE_DEBUG ((LM_DEBUG,
1276 ACE_TEXT ("ACE (%P|%t) SG::close - complete this=%@, repo=%@, owned=%d\n"),
1277 this, this->repo_, this->svc_repo_is_owned_));
1278 #endif
1280 if (this->svc_repo_is_owned_)
1281 delete this->repo_;
1283 this->repo_ = 0;
1285 return 0;
1286 } /* close () */
1289 ACE_END_VERSIONED_NAMESPACE_DECL
1291 #if !defined (__ACE_INLINE__)
1292 #include "ace/Service_Gestalt.inl"
1293 #endif /* __ACE_INLINE__ */
1295 // Allocate a Service Manager.
1296 ACE_FACTORY_DEFINE (ACE, ACE_Service_Manager)