PageRenderTime 55ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/dep/acelite/ace/Service_Gestalt.cpp

https://github.com/chucho/FaceCore
C++ | 1331 lines | 933 code | 209 blank | 189 comment | 207 complexity | ed09d089280b311caa7d3a99f605f9b6 MD5 | raw file
  1. // $Id: Service_Gestalt.cpp 92357 2010-10-25 14:11:44Z mesnier_p $
  2. #include "ace/Svc_Conf.h"
  3. #include "ace/Get_Opt.h"
  4. #include "ace/ARGV.h"
  5. #include "ace/Malloc.h"
  6. #include "ace/Service_Manager.h"
  7. #include "ace/Service_Types.h"
  8. #include "ace/Containers.h"
  9. #include "ace/Auto_Ptr.h"
  10. #include "ace/Reactor.h"
  11. #include "ace/Thread_Manager.h"
  12. #include "ace/DLL.h"
  13. #include "ace/XML_Svc_Conf.h"
  14. #include "ace/SString.h"
  15. #ifndef ACE_LACKS_UNIX_SIGNALS
  16. # include "ace/Signal.h"
  17. #endif /* !ACE_LACKS_UNIX_SIGNALS */
  18. #include "ace/OS_NS_stdio.h"
  19. #include "ace/OS_NS_string.h"
  20. #include "ace/OS_NS_time.h"
  21. #include "ace/OS_NS_unistd.h"
  22. #include "ace/OS_NS_sys_stat.h"
  23. #include "ace/TSS_T.h"
  24. #include "ace/Service_Gestalt.h"
  25. #include "ace/Svc_Conf_Param.h"
  26. ACE_BEGIN_VERSIONED_NAMESPACE_DECL
  27. ACE_Service_Type_Dynamic_Guard::ACE_Service_Type_Dynamic_Guard
  28. (ACE_Service_Repository &r, const ACE_TCHAR *name)
  29. : repo_ (r)
  30. // Relocation starts where the next service will be inserted (if any)
  31. , repo_begin_ (r.current_size ())
  32. , name_ (name)
  33. # if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
  34. // On this thread (for the duration of the initialize() method),
  35. // we're about to do two things that require locking: (1) fiddle
  36. // with the repository and (2) load a DLL and hence lock the
  37. // DLL_Manager.
  38. //
  39. // Now if we don't lock the repo here, it is possible that two
  40. // threads may deadlock on initialization because they can acquire
  41. // locks (1) and (2) in different order, for instance:
  42. //
  43. // T1: loads a DLL (2) and registers a service (1);
  44. //
  45. // T2: may be relocating a service (1), which could lead to a
  46. // (re)opening or uping the ref count on a DLL (2);
  47. //
  48. // To prevent this, we lock the repo here, using the repo_monitor_
  49. // member guard.
  50. , repo_monitor_ (r.lock_)
  51. #endif
  52. {
  53. if (ACE::debug ())
  54. ACE_DEBUG ((LM_DEBUG,
  55. ACE_TEXT ("ACE (%P|%t) STDG::<ctor>, repo=%@")
  56. ACE_TEXT(", name=%s - begining at [%d]\n"),
  57. &this->repo_,
  58. this->name_,
  59. this->repo_begin_));
  60. ACE_ASSERT (this->name_ != 0); // No name?
  61. }
  62. /// Destructor
  63. ACE_Service_Type_Dynamic_Guard::~ACE_Service_Type_Dynamic_Guard (void)
  64. {
  65. const ACE_Service_Type *tmp = 0;
  66. // Lookup without ignoring suspended services. Making sure
  67. // not to ignore any inactive services, since those may be forward
  68. // declarations
  69. size_t slot = 0;
  70. int const ret = this->repo_.find_i (this->name_, slot, &tmp, false);
  71. // We inserted it (as inactive), so we expect to find it, right?
  72. if ((ret < 0 && ret != -2) || tmp == 0)
  73. {
  74. if (ACE::debug ())
  75. ACE_ERROR ((LM_WARNING,
  76. ACE_TEXT ("ACE (%P|%t) STDG::<dtor> - Failed (%d) to find %s -> %@\n"),
  77. ret, this->name_, tmp));
  78. return;
  79. }
  80. if (tmp->type () != 0)
  81. {
  82. // Something has registered a proper (non-forward-decl) service with
  83. // the same name as our dummy.
  84. if (ACE::debug ())
  85. ACE_DEBUG ((LM_DEBUG,
  86. ACE_TEXT ("ACE (%P|%t) STDG::<dtor>, repo=%@ [%d], ")
  87. ACE_TEXT ("name=%s - updating dependents [%d - %d)\n"),
  88. &this->repo_,
  89. slot,
  90. this->name_,
  91. this->repo_begin_,
  92. this->repo_.current_size ()));
  93. // Relocate any services inserted since we were created.
  94. // Any (static, i.e. DLL = 0) services registered in
  95. // the context of this guard aren't really static because
  96. // their code belongs in the DLL's code segment
  97. this->repo_.relocate_i (this->repo_begin_, this->repo_.current_size (), tmp->dll());
  98. if (ACE::debug ())
  99. ACE_DEBUG ((LM_DEBUG,
  100. ACE_TEXT ("ACE (%P|%t) STDG::<dtor>, repo=%@ [%d], ")
  101. ACE_TEXT ("name=%s - loaded (type=%@, impl=%@, object=%@, active=%d)\n"),
  102. &this->repo_,
  103. slot,
  104. this->name_,
  105. tmp,
  106. tmp->type (),
  107. tmp->type ()->object (),
  108. tmp->active ()));
  109. }
  110. }
  111. // ----------------------------------------
  112. ACE_Service_Gestalt::Processed_Static_Svc::
  113. Processed_Static_Svc (const ACE_Static_Svc_Descriptor *assd)
  114. :name_(0),
  115. assd_(assd)
  116. {
  117. ACE_NEW_NORETURN (name_, ACE_TCHAR[ACE_OS::strlen(assd->name_)+1]);
  118. ACE_OS::strcpy(name_,assd->name_);
  119. }
  120. ACE_Service_Gestalt::Processed_Static_Svc::~Processed_Static_Svc (void)
  121. {
  122. delete [] name_;
  123. }
  124. void
  125. ACE_Service_Gestalt::intrusive_add_ref (ACE_Service_Gestalt* g)
  126. {
  127. if (g != 0)
  128. {
  129. ++g->refcnt_;
  130. ACE_ASSERT (g->refcnt_ > 0);
  131. }
  132. }
  133. void
  134. ACE_Service_Gestalt::intrusive_remove_ref (ACE_Service_Gestalt* g)
  135. {
  136. if (g != 0)
  137. {
  138. long tmp = --g->refcnt_;
  139. if (tmp <= 0) delete g;
  140. ACE_ASSERT (tmp >= 0);
  141. }
  142. }
  143. ACE_Service_Gestalt::~ACE_Service_Gestalt (void)
  144. {
  145. if (this->svc_repo_is_owned_)
  146. delete this->repo_;
  147. this->repo_ =0;
  148. delete this->static_svcs_;
  149. this->static_svcs_ = 0;
  150. // Delete the dynamically allocated static_svcs instance.
  151. #ifndef ACE_NLOGGING
  152. if (ACE::debug ())
  153. ACE_DEBUG ((LM_DEBUG,
  154. ACE_TEXT ("ACE (%P|%t) SG::~SG - this=%@, pss = %@\n"),
  155. this, this->processed_static_svcs_));
  156. #endif
  157. if (this->processed_static_svcs_ &&
  158. !this->processed_static_svcs_->is_empty())
  159. {
  160. Processed_Static_Svc **pss = 0;
  161. for (ACE_PROCESSED_STATIC_SVCS_ITERATOR iter (*this->processed_static_svcs_);
  162. iter.next (pss) != 0;
  163. iter.advance ())
  164. {
  165. delete *pss;
  166. }
  167. }
  168. delete this->processed_static_svcs_;
  169. this->processed_static_svcs_ = 0;
  170. delete this->svc_conf_file_queue_;
  171. this->svc_conf_file_queue_ = 0;
  172. delete this->svc_queue_;
  173. this->svc_queue_ = 0;
  174. }
  175. ACE_Service_Gestalt::ACE_Service_Gestalt (size_t size,
  176. bool svc_repo_is_owned,
  177. bool no_static_svcs)
  178. : svc_repo_is_owned_ (svc_repo_is_owned)
  179. , svc_repo_size_ (size)
  180. , is_opened_ (0)
  181. , logger_key_ (ACE_DEFAULT_LOGGER_KEY)
  182. , no_static_svcs_ (no_static_svcs)
  183. , svc_queue_ (0)
  184. , svc_conf_file_queue_ (0)
  185. , repo_ (0)
  186. , static_svcs_ (0)
  187. , processed_static_svcs_ (0)
  188. , refcnt_ (0)
  189. {
  190. (void)this->init_i ();
  191. #ifndef ACE_NLOGGING
  192. if (ACE::debug ())
  193. ACE_DEBUG ((LM_DEBUG,
  194. ACE_TEXT ("ACE (%P|%t) SG::ctor - this = %@, pss = %@\n"),
  195. this, this->processed_static_svcs_));
  196. #endif
  197. }
  198. /// Performs the common initialization tasks for a new or previously
  199. /// closed instance. Must not be virtual, as it is also called from
  200. /// the constructor.
  201. int
  202. ACE_Service_Gestalt::init_i (void)
  203. {
  204. // Only initialize the repo_ if (a) we are being constructed, or;
  205. // (b) we're being open()-ed, perhaps after previously having been
  206. // close()-ed. In both cases: repo_ == 0 and we need a repository.
  207. if (this->repo_ == 0)
  208. {
  209. if (this->svc_repo_is_owned_)
  210. {
  211. ACE_NEW_RETURN (this->repo_,
  212. ACE_Service_Repository (this->svc_repo_size_),
  213. -1);
  214. }
  215. else
  216. {
  217. this->repo_ =
  218. ACE_Service_Repository::instance (this->svc_repo_size_);
  219. }
  220. }
  221. if (init_svc_conf_file_queue () == -1)
  222. return -1;
  223. return 0;
  224. }
  225. /// Add the default statically-linked services to the Service
  226. /// Repository.
  227. int
  228. ACE_Service_Gestalt::load_static_svcs (void)
  229. {
  230. ACE_TRACE ("ACE_Service_Gestalt::load_static_svcs");
  231. if (this->static_svcs_ == 0)
  232. return 0; // Nothing to do
  233. ACE_Static_Svc_Descriptor **ssdp = 0;
  234. for (ACE_STATIC_SVCS_ITERATOR iter (*this->static_svcs_);
  235. iter.next (ssdp) != 0;
  236. iter.advance ())
  237. {
  238. ACE_Static_Svc_Descriptor *ssd = *ssdp;
  239. if (this->process_directive (*ssd, 1) == -1)
  240. return -1;
  241. }
  242. return 0;
  243. } /* load_static_svcs () */
  244. /// Find a static service descriptor by name
  245. int
  246. ACE_Service_Gestalt::find_static_svc_descriptor (const ACE_TCHAR* name,
  247. ACE_Static_Svc_Descriptor **ssd) const
  248. {
  249. ACE_TRACE ("ACE_Service_Gestalt::find_static_svc_descriptor");
  250. if (this->static_svcs_ == 0)
  251. return -1;
  252. ACE_Static_Svc_Descriptor **ssdp = 0;
  253. for (ACE_STATIC_SVCS_ITERATOR iter ( *this->static_svcs_);
  254. iter.next (ssdp) != 0;
  255. iter.advance ())
  256. {
  257. if (ACE_OS::strcmp ((*ssdp)->name_, name) == 0)
  258. {
  259. if (ssd != 0)
  260. *ssd = *ssdp;
  261. return 0;
  262. }
  263. }
  264. return -1;
  265. }
  266. /// @brief
  267. const ACE_Static_Svc_Descriptor*
  268. ACE_Service_Gestalt::find_processed_static_svc (const ACE_TCHAR* name)
  269. {
  270. if (this->processed_static_svcs_ == 0 || name == 0)
  271. return 0;
  272. Processed_Static_Svc **pss = 0;
  273. for (ACE_PROCESSED_STATIC_SVCS_ITERATOR iter (*this->processed_static_svcs_);
  274. iter.next (pss) != 0;
  275. iter.advance ())
  276. {
  277. if (ACE_OS::strcmp ((*pss)->name_, name) == 0)
  278. return (*pss)->assd_;
  279. }
  280. return 0;
  281. }
  282. /// @brief Captures a list of the direcives processed (explicitely) for this
  283. /// Gestalt so that services can be replicated in other repositories
  284. /// upon their first initialization.
  285. ///
  286. /// This is part of the mechanism ensuring distinct local instances
  287. /// for static service objects, loaded in another repository.
  288. void
  289. ACE_Service_Gestalt::add_processed_static_svc
  290. (const ACE_Static_Svc_Descriptor *assd)
  291. {
  292. /// When process_directive(Static_Svc_Descriptor&) is called, it
  293. /// associates a service object with the Gestalt and makes the
  294. /// resource (a Service Object) local to the repository. This is but
  295. /// the first step in using such SO. The next is the
  296. /// "initialization" step. It is typicaly done through a "static"
  297. /// service configuration directive.
  298. ///
  299. /// In contrast a "dynamic" directive, when processed through the
  300. /// overloaded process_directives(string) both creates the SO
  301. /// locally and initializes it, where the statics directive must
  302. /// first locate the SO and then calls the init() method. This means
  303. /// that durig the "static" initialization there's no specific
  304. /// information about the hosting repository and the gestalt must
  305. /// employ some lookup strategy to find it elsewhere.
  306. if (this->processed_static_svcs_ == 0)
  307. ACE_NEW (this->processed_static_svcs_,
  308. ACE_PROCESSED_STATIC_SVCS);
  309. Processed_Static_Svc **pss = 0;
  310. for (ACE_PROCESSED_STATIC_SVCS_ITERATOR iter (*this->processed_static_svcs_);
  311. iter.next (pss) != 0;
  312. iter.advance ())
  313. {
  314. if (ACE_OS::strcmp ((*pss)->name_, assd->name_) == 0)
  315. {
  316. (*pss)->assd_ = assd;
  317. return;
  318. }
  319. }
  320. Processed_Static_Svc *tmp = 0;
  321. ACE_NEW (tmp,Processed_Static_Svc(assd));
  322. this->processed_static_svcs_->insert(tmp);
  323. if (ACE::debug ())
  324. ACE_DEBUG ((LM_DEBUG,
  325. ACE_TEXT ("ACE (%P|%t) SG::add_processed_static_svc, ")
  326. ACE_TEXT ("repo=%@ - %s\n"),
  327. this->repo_,
  328. assd->name_));
  329. }
  330. /// Queues a static service object descriptor which, during open()
  331. /// will be given to process_directive() to create the Service
  332. /// Object. Normally, only called from static initializers, prior to
  333. /// calling open() but loading a service from a DLL can cause it too.
  334. int
  335. ACE_Service_Gestalt::insert (ACE_Static_Svc_Descriptor *stsd)
  336. {
  337. if (this->static_svcs_ == 0)
  338. ACE_NEW_RETURN (this->static_svcs_,
  339. ACE_STATIC_SVCS,
  340. -1);
  341. return this->static_svcs_->insert (stsd);
  342. }
  343. ACE_ALLOC_HOOK_DEFINE (ACE_Service_Gestalt)
  344. void
  345. ACE_Service_Gestalt::dump (void) const
  346. {
  347. #if defined (ACE_HAS_DUMP)
  348. ACE_TRACE ("ACE_Service_Gestalt::dump");
  349. #endif /* ACE_HAS_DUMP */
  350. }
  351. int
  352. ACE_Service_Gestalt::initialize (const ACE_TCHAR *svc_name,
  353. const ACE_TCHAR *parameters)
  354. {
  355. ACE_TRACE ("ACE_Service_Gestalt_Base::initialize (repo)");
  356. ACE_ARGV args (parameters);
  357. #ifndef ACE_NLOGGING
  358. if (ACE::debug ())
  359. {
  360. ACE_DEBUG ((LM_DEBUG,
  361. ACE_TEXT ("ACE (%P|%t) SG::initialize - () repo=%@, ")
  362. ACE_TEXT ("looking up static ")
  363. ACE_TEXT ("service \'%s\' to initialize\n"),
  364. this->repo_,
  365. svc_name));
  366. }
  367. #endif
  368. const ACE_Service_Type *srp = 0;
  369. for (int i = 0; this->find (svc_name, &srp) == -1 && i < 2; i++)
  370. // if (this->repo_->find (svc_name, &srp) == -1)
  371. {
  372. const ACE_Static_Svc_Descriptor *assd =
  373. ACE_Service_Config::global()->find_processed_static_svc(svc_name);
  374. if (assd != 0)
  375. {
  376. this->process_directive_i(*assd, 0);
  377. }
  378. else
  379. {
  380. ACE_ERROR_RETURN ((LM_ERROR,
  381. ACE_TEXT ("ACE (%P|%t) ERROR: SG::initialize - service \'%s\'")
  382. ACE_TEXT (" was not located.\n"),
  383. svc_name),
  384. -1);
  385. }
  386. }
  387. if (srp == 0)
  388. ACE_ERROR_RETURN ((LM_ERROR,
  389. ACE_TEXT ("ACE (%P|%t) ERROR: SG::initialize - service \'%s\'")
  390. ACE_TEXT (" was not located.\n"),
  391. svc_name),
  392. -1);
  393. /// If initialization fails ...
  394. if (srp->type ()->init (args.argc (),
  395. args.argv ()) == -1)
  396. {
  397. // ... report and remove this entry.
  398. ACE_ERROR ((LM_ERROR,
  399. ACE_TEXT ("ACE (%P|%t) ERROR: SG::initialize - static init of \'%s\'")
  400. ACE_TEXT (" failed (%p)\n"),
  401. svc_name, ACE_TEXT ("error")));
  402. this->repo_->remove (svc_name);
  403. return -1;
  404. }
  405. // If everything is ok, activate it
  406. const_cast<ACE_Service_Type *>(srp)->active (1);
  407. return 0;
  408. }
  409. #if (ACE_USES_CLASSIC_SVC_CONF == 1)
  410. int
  411. ACE_Service_Gestalt::initialize (const ACE_Service_Type_Factory *stf,
  412. const ACE_TCHAR *parameters)
  413. {
  414. ACE_TRACE ("ACE_Service_Gestalt::initialize");
  415. #ifndef ACE_NLOGGING
  416. if (ACE::debug ())
  417. ACE_DEBUG ((LM_DEBUG,
  418. ACE_TEXT ("ACE (%P|%t) SG::initialize - repo=%@, name=%s")
  419. ACE_TEXT (" - looking up in the repo\n"),
  420. this->repo_,
  421. stf->name ()));
  422. #endif
  423. ACE_Service_Type *srp = 0;
  424. int const retv = this->repo_->find (stf->name (),
  425. (const ACE_Service_Type **) &srp);
  426. // If there is an active service already, remove it first
  427. // before it can be re-installed.
  428. if (retv >= 0)
  429. {
  430. #ifndef ACE_NLOGGING
  431. if (ACE::debug ())
  432. ACE_DEBUG ((LM_WARNING,
  433. ACE_TEXT ("ACE (%P|%t) SG::initialize - repo=%@,")
  434. ACE_TEXT (" name=%s - removing a pre-existing namesake.\n"),
  435. this->repo_,
  436. stf->name ()));
  437. #endif
  438. this->repo_->remove (stf->name ());
  439. }
  440. // If there is an inactive service by that name it may have been
  441. // either inactivated, or just a forward declaration for a service,
  442. // that is in the process of being initialized. If it is the latter,
  443. // then we have detected an attempt to initialize the same dynamic
  444. // service while still processing previous attempt. This can lock up
  445. // the process, because the ACE_DLL_Manager::open () is not
  446. // re-entrant - it uses a Singleton lock to serialize concurent
  447. // invocations. This use case must be handled here, because if the
  448. // DLL_Manager was re-entrant we would have entered an infinite
  449. // recursion here.
  450. if (retv == -2 && srp->type () == 0)
  451. ACE_ERROR_RETURN ((LM_WARNING,
  452. ACE_TEXT ("ACE (%P|%t) SG::initialize - repo=%@,")
  453. ACE_TEXT (" name=%s - forward-declared; ")
  454. ACE_TEXT (" recursive initialization requests are")
  455. ACE_TEXT (" ignored.\n"),
  456. this->repo_,
  457. stf->name ()),
  458. -1);
  459. // Reserve a spot for the dynamic service by inserting an incomplete
  460. // service declaration, i.e. one that can not produce a service
  461. // object if asked (a forward declaration). This declaration
  462. // ensures maintaining the proper partial ordering of the services
  463. // with respect to their finalization. For example, dependent static
  464. // services must be registered *after* the dynamic service that
  465. // loads them, so that their finalization is complete *before*
  466. // finalizing the dynamic service.
  467. ACE_Service_Type_Dynamic_Guard dummy (*this->repo_,
  468. stf->name ());
  469. // make_service_type() is doing the dynamic loading and also runs
  470. // any static initializers
  471. ACE_Auto_Ptr<ACE_Service_Type> tmp (stf->make_service_type (this));
  472. if (tmp.get () != 0 &&
  473. this->initialize_i (tmp.get (), parameters) == 0)
  474. {
  475. // All good. Tthe ACE_Service_Type instance is now owned by the
  476. // repository and we should make sure it is not destroyed upon
  477. // exit from this method.
  478. tmp.release ();
  479. return 0;
  480. }
  481. return -1;
  482. }
  483. #endif /* (ACE_USES_CLASSIC_SVC_CONF == 1) */
  484. /// Dynamically link the shared object file and retrieve a pointer to
  485. /// the designated shared object in this file.
  486. /// @note This is obsolete (and error-prone) in the presense of dynamic
  487. /// services with their own static services. This method will allow those
  488. /// static services to register *before* the dynamic service that owns them.
  489. /// Upon finalization of the static services the process may crash, because
  490. /// the dynamic service's DLL may have been already released, together with
  491. /// the memory in which the static services reside.
  492. /// It may not crash, for instance, when the first static service to register
  493. /// is the same as the dynamic service being loaded. You should be so lucky! ..
  494. int
  495. ACE_Service_Gestalt::initialize (const ACE_Service_Type *sr,
  496. const ACE_TCHAR *parameters)
  497. {
  498. ACE_TRACE ("ACE_Service_Gestalt::initialize");
  499. if (ACE::debug ())
  500. ACE_DEBUG ((LM_DEBUG,
  501. ACE_TEXT ("ACE (%P|%t) SG::initialize - repo=%@, name=%s")
  502. ACE_TEXT (" - looking up in the repo\n"),
  503. this->repo_,
  504. sr->name ()));
  505. ACE_Service_Type *srp = 0;
  506. if (this->repo_->find (sr->name (),
  507. (const ACE_Service_Type **) &srp) >= 0)
  508. {
  509. #ifndef ACE_NLOGGING
  510. ACE_DEBUG ((LM_WARNING,
  511. ACE_TEXT ("ACE (%P|%t) SG::initialize - repo=%@, name=%s")
  512. ACE_TEXT (" - removing a pre-existing namesake.\n"),
  513. this->repo_,
  514. sr->name ()));
  515. #endif
  516. this->repo_->remove (sr->name ());
  517. }
  518. return this->initialize_i (sr, parameters);
  519. }
  520. /// Dynamically link the shared object file and retrieve a pointer to
  521. /// the designated shared object in this file.
  522. int
  523. ACE_Service_Gestalt::initialize_i (const ACE_Service_Type *sr,
  524. const ACE_TCHAR *parameters)
  525. {
  526. ACE_TRACE ("ACE_Service_Gestalt::initialize_i");
  527. ACE_ARGV args (parameters);
  528. if (sr->type ()->init (args.argc (),
  529. args.argv ()) == -1)
  530. {
  531. // We just get ps to avoid having remove() delete it.
  532. ACE_Service_Type *ps = 0;
  533. this->repo_->remove (sr->name (), &ps);
  534. #ifndef ACE_NLOGGING
  535. // Not using LM_ERROR here to avoid confusing the test harness
  536. if (ACE::debug ())
  537. ACE_ERROR_RETURN ((LM_WARNING,
  538. ACE_TEXT ("ACE (%P|%t) SG::initialize_i -")
  539. ACE_TEXT (" repo=%@, name=%s - remove failed: %m\n"),
  540. this->repo_,
  541. sr->name ()),
  542. -1);
  543. #endif
  544. return -1;
  545. }
  546. if (this->repo_->insert (sr) == -1)
  547. {
  548. #ifndef ACE_NLOGGING
  549. // Not using LM_ERROR here to avoid confusing the test harness
  550. if (ACE::debug ())
  551. ACE_ERROR_RETURN ((LM_WARNING,
  552. ACE_TEXT ("ACE (%P|%t) SG::initialize_i -")
  553. ACE_TEXT (" repo=%@, name=%s - insert failed: %m\n"),
  554. this->repo_,
  555. sr->name ()),
  556. -1);
  557. #endif
  558. return -1;
  559. }
  560. return 0;
  561. }
  562. // Totally remove <svc_name> from the daemon by removing it from the
  563. // ACE_Reactor, and unlinking it if necessary.
  564. int
  565. ACE_Service_Gestalt::remove (const ACE_TCHAR svc_name[])
  566. {
  567. ACE_TRACE ("ACE_Service_Gestalt::remove");
  568. if (this->repo_ == 0)
  569. return -1;
  570. return this->repo_->remove (svc_name);
  571. }
  572. /// Suspend @a svc_name. Note that this will not unlink the service
  573. /// from the daemon if it was dynamically linked, it will mark it as
  574. /// being suspended in the Service Repository and call the <suspend>
  575. /// member function on the appropriate <ACE_Service_Object>. A service
  576. /// can be resumed later on by calling the <resume> method...
  577. int
  578. ACE_Service_Gestalt::suspend (const ACE_TCHAR svc_name[])
  579. {
  580. ACE_TRACE ("ACE_Service_Gestalt::suspend");
  581. if (this->repo_ == 0)
  582. return -1;
  583. return this->repo_->suspend (svc_name);
  584. }
  585. // Resume a SVC_NAME that was previously suspended or has not yet
  586. // been resumed (e.g., a static service).
  587. int
  588. ACE_Service_Gestalt::resume (const ACE_TCHAR svc_name[])
  589. {
  590. ACE_TRACE ("ACE_Service_Gestalt::resume");
  591. if (this->repo_ == 0)
  592. return -1;
  593. return this->repo_->resume (svc_name);
  594. }
  595. int
  596. ACE_Service_Gestalt::process_directive (const ACE_Static_Svc_Descriptor &ssd,
  597. bool force_replace)
  598. {
  599. int const result = process_directive_i (ssd, force_replace);
  600. if (result == 0)
  601. {
  602. this->add_processed_static_svc(&ssd);
  603. }
  604. return result;
  605. }
  606. int
  607. ACE_Service_Gestalt::process_directive_i (const ACE_Static_Svc_Descriptor &ssd,
  608. bool force_replace)
  609. {
  610. if (this->repo_ == 0)
  611. return -1;
  612. if (!force_replace)
  613. {
  614. if (this->repo_->find (ssd.name_, 0, 0) >= 0)
  615. {
  616. // The service is already there, just return
  617. return 0;
  618. }
  619. }
  620. ACE_Service_Object_Exterminator gobbler;
  621. void *sym = (ssd.alloc_)(&gobbler);
  622. ACE_Service_Type_Impl *stp =
  623. ACE_Service_Config::create_service_type_impl (ssd.name_,
  624. ssd.type_,
  625. sym,
  626. ssd.flags_,
  627. gobbler);
  628. if (stp == 0)
  629. return 0;
  630. ACE_Service_Type *service_type = 0;
  631. // This is just a temporary to force the compiler to use the right
  632. // constructor in ACE_Service_Type. Note that, in cases where we are
  633. // called from a static initializer which is part of a DLL, there is
  634. // not enough information about the actuall DLL in this context.
  635. ACE_DLL tmp_dll;
  636. ACE_NEW_RETURN (service_type,
  637. ACE_Service_Type (ssd.name_,
  638. stp,
  639. tmp_dll,
  640. ssd.active_),
  641. -1);
  642. #ifndef ACE_NLOGGING
  643. if (ACE::debug ())
  644. ACE_DEBUG ((LM_DEBUG,
  645. ACE_TEXT ("ACE (%P|%t) SG::process_directive_i, ")
  646. ACE_TEXT ("repo=%@ - %s, dll=%s, force=%d\n"),
  647. this->repo_,
  648. ssd.name_,
  649. (tmp_dll.dll_name_ == 0) ? ACE_TEXT ("<null>") : tmp_dll.dll_name_,
  650. force_replace));
  651. #endif
  652. return this->repo_->insert (service_type);
  653. }
  654. #if (ACE_USES_CLASSIC_SVC_CONF == 1)
  655. int
  656. ACE_Service_Gestalt::process_directives_i (ACE_Svc_Conf_Param *param)
  657. {
  658. #ifndef ACE_NLOGGING
  659. if (ACE::debug ())
  660. ACE_DEBUG ((LM_DEBUG,
  661. ACE_TEXT ("ACE (%P|%t) SG::process_directives_i, ")
  662. ACE_TEXT ("repo=%@ - %s\n"),
  663. this->repo_,
  664. (param->type == ACE_Svc_Conf_Param::SVC_CONF_FILE)
  665. ? ACE_TEXT ("<from file>")
  666. : param->source.directive));
  667. #endif
  668. // AC 970827 Skip the heap check because yacc allocates a buffer
  669. // here which will be reported as a memory leak for some reason.
  670. ACE_NO_HEAP_CHECK
  671. // Were we called in the context of the current instance?
  672. ACE_ASSERT (this == param->config);
  673. // Temporarily (for the duration of this call) make sure that *any*
  674. // static service registrations will happen with this instance. Such
  675. // registrations are possible as a side-effect of dynamically
  676. // loading a DLL, which has other static services registered. Thus
  677. // this instance will own both the DLL and those static services,
  678. // which implies that their finalization will be performed in the
  679. // correct order, i.e. prior to finalizing the DLL
  680. ACE_Service_Config_Guard guard (this);
  681. ::ace_yyparse (param);
  682. // This is a hack, better errors should be provided...
  683. if (param->yyerrno > 0)
  684. {
  685. // Always set the last error if ace_yyparse() fails.
  686. // Other code may use errno to determine the type
  687. // of problem that occurred from processing directives.
  688. ACE_OS::last_error (EINVAL);
  689. return param->yyerrno;
  690. }
  691. else
  692. return 0;
  693. }
  694. #else
  695. ACE_XML_Svc_Conf *
  696. ACE_Service_Gestalt::get_xml_svc_conf (ACE_DLL &xmldll)
  697. {
  698. if (xmldll.open (ACE_TEXT ("ACEXML_XML_Svc_Conf_Parser")) == -1)
  699. ACE_ERROR_RETURN ((LM_ERROR,
  700. ACE_TEXT ("ACE (%P|%t) Failure to open ACEXML_XML_Svc_Conf_Parser: %p\n"),
  701. ACE_TEXT("ACE_Service_Config::get_xml_svc_conf")),
  702. 0);
  703. void * foo =
  704. xmldll.symbol (ACE_TEXT ("_ACEXML_create_XML_Svc_Conf_Object"));
  705. #if defined (ACE_OPENVMS) && (!defined (__INITIAL_POINTER_SIZE) || (__INITIAL_POINTER_SIZE < 64))
  706. int const temp_p = reinterpret_cast<int> (foo);
  707. #else
  708. intptr_t const temp_p = reinterpret_cast<intptr_t> (foo);
  709. #endif
  710. ACE_XML_Svc_Conf::Factory factory = reinterpret_cast<ACE_XML_Svc_Conf::Factory> (temp_p);
  711. if (factory == 0)
  712. ACE_ERROR_RETURN ((LM_ERROR,
  713. ACE_TEXT ("ACE (%P|%t) Unable to resolve factory: %p\n"),
  714. xmldll.error ()),
  715. 0);
  716. return factory ();
  717. }
  718. #endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */
  719. int
  720. ACE_Service_Gestalt::process_file (const ACE_TCHAR file[])
  721. {
  722. ACE_TRACE ("ACE_Service_Gestalt::process_file");
  723. // To avoid recursive processing of the same file and the same repository
  724. // we maintain an implicit stack of dummy "services" named after the file
  725. // being processed. Anytime we have to open a new file, we then can check
  726. // to see if it is not already being processed by searching for a dummy
  727. // service with a matching name.
  728. if (this->repo_->find (file, 0, 0) >=0)
  729. {
  730. ACE_DEBUG ((LM_WARNING,
  731. ACE_TEXT ("ACE (%P|%t) Configuration file %s is currently")
  732. ACE_TEXT (" being processed. Ignoring recursive process_file().\n"),
  733. file));
  734. return 0;
  735. }
  736. // Register a dummy service as a forward decl, using the file name as name.
  737. // The entry will be automaticaly removed once the thread exits this block.
  738. ACE_Service_Type_Dynamic_Guard recursion_guard (*this->repo_,
  739. file);
  740. /*
  741. * @TODO: Test with ACE_USES_CLASSIC_SVC_CONF turned off!
  742. */
  743. #if (ACE_USES_CLASSIC_SVC_CONF == 1)
  744. int result = 0;
  745. FILE *fp = ACE_OS::fopen (file,
  746. ACE_TEXT ("r"));
  747. if (fp == 0)
  748. {
  749. // Invalid svc.conf file. We'll report it here and break out of
  750. // the method.
  751. if (ACE::debug ())
  752. ACE_DEBUG ((LM_ERROR,
  753. ACE_TEXT ("ACE (%P|%t): %p\n"),
  754. file));
  755. // Use stat to find out if the file exists. I didn't use access()
  756. // because stat is better supported on most non-unix platforms.
  757. ACE_stat exists;
  758. if (ACE_OS::stat (file, &exists) == 0)
  759. // If it exists, but we couldn't open it for reading then we
  760. // must not have permission to read it.
  761. errno = EPERM;
  762. else
  763. errno = ENOENT;
  764. result = -1;
  765. }
  766. else
  767. {
  768. ACE_Svc_Conf_Param f (this, fp);
  769. // Keep track of the number of errors.
  770. result = this->process_directives_i (&f);
  771. (void) ACE_OS::fclose (fp);
  772. }
  773. return result;
  774. #else
  775. ACE_DLL dll;
  776. auto_ptr<ACE_XML_Svc_Conf> xml_svc_conf (this->get_xml_svc_conf (dll));
  777. if (xml_svc_conf.get () == 0)
  778. return -1;
  779. return xml_svc_conf->parse_file (file);
  780. #endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */
  781. }
  782. int
  783. ACE_Service_Gestalt::process_directive (const ACE_TCHAR directive[])
  784. {
  785. ACE_TRACE ("ACE_Service_Gestalt::process_directive");
  786. #ifndef ACE_NLOGGING
  787. if (ACE::debug ())
  788. ACE_DEBUG ((LM_DEBUG,
  789. ACE_TEXT ("ACE (%P|%t) SG::process_directive, repo=%@ - %s\n"),
  790. this->repo_,
  791. directive));
  792. #endif
  793. #if (ACE_USES_CLASSIC_SVC_CONF == 1)
  794. ACE_UNUSED_ARG (directive);
  795. ACE_Svc_Conf_Param d (this, directive);
  796. return this->process_directives_i (&d);
  797. #else
  798. ACE_DLL dll;
  799. auto_ptr<ACE_XML_Svc_Conf>
  800. xml_svc_conf (this->get_xml_svc_conf (dll));
  801. if (xml_svc_conf.get () == 0)
  802. return -1;
  803. // Temporarily (for the duration of this call) make sure that *any* static
  804. // service registrations will happen with this instance. Such registrations
  805. // are possible as a side-effect of dynamically loading a DLL, which has
  806. // other static services registered. Thus this instance will own both the
  807. // DLL and those static services, which implies that their finalization
  808. // will be performed in the correct order, i.e. prior to finalizing the DLL
  809. ACE_Service_Config_Guard guard (this);
  810. return xml_svc_conf->parse_string (directive);
  811. #endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */
  812. } /* process_directive () */
  813. int
  814. ACE_Service_Gestalt::init_svc_conf_file_queue (void)
  815. {
  816. if (this->svc_conf_file_queue_ == 0)
  817. {
  818. ACE_SVC_QUEUE *tmp = 0;
  819. ACE_NEW_RETURN (tmp,
  820. ACE_SVC_QUEUE,
  821. -1);
  822. this->svc_conf_file_queue_ = tmp;
  823. }
  824. #ifndef ACE_NLOGGING
  825. if (ACE::debug ())
  826. ACE_DEBUG ((LM_DEBUG,
  827. ACE_TEXT ("ACE (%P|%t) SG::init_svc_conf_file_queue ")
  828. ACE_TEXT ("- this=%@, repo=%@\n"),
  829. this, this->repo_));
  830. #endif
  831. return 0;
  832. } /* init_svc_conf_file_queue () */
  833. int
  834. ACE_Service_Gestalt::open_i (const ACE_TCHAR program_name[],
  835. const ACE_TCHAR* logger_key,
  836. bool ignore_static_svcs,
  837. bool ignore_default_svc_conf_file,
  838. bool ignore_debug_flag)
  839. {
  840. ACE_TRACE ("ACE_Service_Gestalt::open_i");
  841. int result = 0;
  842. ACE_Log_Msg *log_msg = ACE_LOG_MSG;
  843. this->no_static_svcs_ = ignore_static_svcs;
  844. // Record the current log setting upon entering this thread.
  845. u_long old_process_mask = log_msg->priority_mask
  846. (ACE_Log_Msg::PROCESS);
  847. u_long old_thread_mask = log_msg->priority_mask
  848. (ACE_Log_Msg::THREAD);
  849. #ifndef ACE_NLOGGING
  850. if (ACE::debug ())
  851. ACE_DEBUG ((LM_DEBUG,
  852. ACE_TEXT ("ACE (%P|%t) SG::open_i - this=%@, ")
  853. ACE_TEXT ("opened=%d, loadstatics=%d\n"),
  854. this, this->is_opened_, this->no_static_svcs_));
  855. #endif
  856. // Guard against reentrant processing. For example,
  857. // if the singleton gestalt (ubergestalt) was already open,
  858. // do not open it again...
  859. if (this->is_opened_++ != 0)
  860. return 0;
  861. if (this->init_i () != 0)
  862. return -1;
  863. u_long flags = log_msg->flags ();
  864. // Only use STDERR if the caller hasn't already set the flags.
  865. if (flags == 0)
  866. flags = (u_long) ACE_Log_Msg::STDERR;
  867. const ACE_TCHAR *key = logger_key;
  868. if (key == 0 || ACE_OS::strcmp (key, ACE_DEFAULT_LOGGER_KEY) == 0)
  869. {
  870. // Only use the static <logger_key_> if the caller doesn't
  871. // override it in the parameter list or if the key supplied is
  872. // equal to the default static logger key.
  873. key = this->logger_key_;
  874. }
  875. else
  876. {
  877. ACE_SET_BITS (flags, ACE_Log_Msg::LOGGER);
  878. }
  879. if (log_msg->open (program_name,
  880. flags,
  881. key) == -1)
  882. return -1;
  883. if (!ignore_debug_flag)
  884. {
  885. // If -d was included as a startup parameter, the user wants debug
  886. // information printed during service initialization.
  887. if (ACE::debug ())
  888. ACE_Log_Msg::enable_debug_messages ();
  889. else
  890. // The user has requested no debugging info.
  891. ACE_Log_Msg::disable_debug_messages ();
  892. }
  893. if (!ignore_default_svc_conf_file)
  894. {
  895. bool add_default = true;
  896. bool has_files = this->svc_conf_file_queue_ &&
  897. !this->svc_conf_file_queue_->is_empty ();
  898. bool has_cmdline = this->svc_queue_ && !this->svc_queue_->is_empty ();
  899. if (has_files || has_cmdline)
  900. {
  901. // check if default file is already listed
  902. ACE_TString *sptr = 0;
  903. ACE_TString default_svc_conf (ACE_DEFAULT_SVC_CONF);
  904. for (ACE_SVC_QUEUE_ITERATOR iter (*this->svc_conf_file_queue_);
  905. iter.next (sptr) != 0 && add_default;
  906. iter.advance ())
  907. {
  908. add_default = (*sptr != default_svc_conf);
  909. }
  910. if (add_default)
  911. {
  912. FILE *fp = ACE_OS::fopen (ACE_DEFAULT_SVC_CONF, ACE_TEXT ("r"));
  913. if (fp != 0)
  914. ACE_OS::fclose(fp);
  915. else
  916. add_default = false;
  917. }
  918. }
  919. // Load the default "svc.conf" entry. here if there weren't
  920. // overriding -f arguments in <parse_args>.
  921. if (add_default && svc_conf_file_queue_->enqueue_head
  922. (ACE_TString (ACE_DEFAULT_SVC_CONF)) == -1)
  923. {
  924. errno = ENOENT;
  925. ACE_ERROR_RETURN ((LM_ERROR,
  926. ACE_TEXT ("%p\n"),
  927. ACE_TEXT ("enqueuing ")
  928. ACE_DEFAULT_SVC_CONF
  929. ACE_TEXT(" file")),
  930. -1);
  931. }
  932. }
  933. // See if we need to load the static services.
  934. if (this->no_static_svcs_ == 0
  935. && this->load_static_svcs () == -1)
  936. result = -1;
  937. else
  938. {
  939. result = this->process_directives ();
  940. if (result != -1)
  941. {
  942. int temp = this->process_commandline_directives ();
  943. if (temp == -1)
  944. result = -1;
  945. else result += temp;
  946. }
  947. }
  948. // Reset debugging back to the way it was when we came into
  949. // into <open_i>.
  950. {
  951. // Make sure to save/restore errno properly.
  952. ACE_Errno_Guard error (errno);
  953. if (!ignore_debug_flag)
  954. {
  955. log_msg->priority_mask (old_process_mask, ACE_Log_Msg::PROCESS);
  956. log_msg->priority_mask (old_thread_mask, ACE_Log_Msg::THREAD);
  957. }
  958. }
  959. return result;
  960. } /* open_i () */
  961. int
  962. ACE_Service_Gestalt::is_opened (void)
  963. {
  964. return this->is_opened_;
  965. }
  966. int
  967. ACE_Service_Gestalt::process_commandline_directives (void)
  968. {
  969. int result = 0;
  970. if (this->svc_queue_ != 0)
  971. {
  972. ACE_TString *sptr = 0;
  973. for (ACE_SVC_QUEUE_ITERATOR iter (*this->svc_queue_);
  974. iter.next (sptr) != 0;
  975. iter.advance ())
  976. {
  977. // Process just a single directive.
  978. if (this->process_directive ((sptr->fast_rep ())) != 0)
  979. {
  980. ACE_ERROR ((LM_ERROR,
  981. ACE_TEXT ("ACE (%P|%t) %p\n"),
  982. ACE_TEXT ("process_directive")));
  983. result = -1;
  984. }
  985. }
  986. delete this->svc_queue_;
  987. this->svc_queue_ = 0;
  988. }
  989. return result;
  990. } /* process_commandline_directives () */
  991. int
  992. ACE_Service_Gestalt::parse_args (int argc, ACE_TCHAR *argv[])
  993. {
  994. ACE_TRACE ("ACE_Service_Gestalt::parse_args");
  995. bool unused_ignore_default_svc_conf = true;
  996. return parse_args_i (argc, argv, unused_ignore_default_svc_conf);
  997. }
  998. int
  999. ACE_Service_Gestalt::parse_args_i (int argc,
  1000. ACE_TCHAR *argv[],
  1001. bool &ignore_default_svc_conf_file)
  1002. {
  1003. ACE_TRACE ("ACE_Service_Gestalt::parse_args_i");
  1004. ACE_Get_Opt get_opt (argc,
  1005. argv,
  1006. ACE_TEXT ("df:k:nyS:"),
  1007. 1); // Start at argv[1].
  1008. if (this->init_svc_conf_file_queue () == -1)
  1009. return -1;
  1010. for (int c; (argc != 0) && ((c = get_opt ()) != -1); )
  1011. switch (c)
  1012. {
  1013. case 'd':
  1014. ACE::debug (1);
  1015. break;
  1016. case 'f':
  1017. if (this->svc_conf_file_queue_->enqueue_tail (ACE_TString (get_opt.opt_arg ())) == -1)
  1018. ACE_ERROR_RETURN ((LM_ERROR,
  1019. ACE_TEXT ("%p\n"),
  1020. ACE_TEXT ("enqueue_tail")),
  1021. -1);
  1022. ignore_default_svc_conf_file = true;
  1023. break;
  1024. case 'k':
  1025. /*
  1026. * @TODO: Is this always a static storage? Shouldn't we copy
  1027. * & gain ownership of the value?
  1028. */
  1029. this->logger_key_ = get_opt.opt_arg ();
  1030. break;
  1031. case 'n':
  1032. this->no_static_svcs_ = 1;
  1033. break;
  1034. case 'y':
  1035. this->no_static_svcs_ = 0;
  1036. break;
  1037. case 'S':
  1038. if (this->svc_queue_ == 0)
  1039. {
  1040. ACE_NEW_RETURN (this->svc_queue_,
  1041. ACE_SVC_QUEUE,
  1042. -1);
  1043. }
  1044. if (this->svc_queue_->enqueue_tail (ACE_TString (get_opt.opt_arg ())) == -1)
  1045. ACE_ERROR_RETURN ((LM_ERROR,
  1046. ACE_TEXT ("%p\n"),
  1047. ACE_TEXT ("enqueue_tail")),
  1048. -1);
  1049. break;
  1050. default:
  1051. if (ACE::debug ())
  1052. ACE_DEBUG ((LM_DEBUG,
  1053. ACE_TEXT ("ACE (%P|%t) %c is not a ACE_Service_Config option\n"),
  1054. c));
  1055. }
  1056. return 0;
  1057. } /* parse_args_i () */
  1058. // Process service configuration directives from the files queued for
  1059. // processing
  1060. int
  1061. ACE_Service_Gestalt::process_directives (bool )
  1062. {
  1063. ACE_TRACE ("ACE_Service_Gestalt::process_directives");
  1064. if (this->svc_conf_file_queue_ == 0
  1065. || this->svc_conf_file_queue_->is_empty ())
  1066. {
  1067. return 0;
  1068. }
  1069. ACE_TString *sptr = 0;
  1070. int failed = 0;
  1071. // Iterate through all the svc.conf files.
  1072. for (ACE_SVC_QUEUE_ITERATOR iter (*this->svc_conf_file_queue_);
  1073. iter.next (sptr) != 0;
  1074. iter.advance ())
  1075. {
  1076. int result = this->process_file (sptr->fast_rep ());
  1077. if (result < 0)
  1078. return result;
  1079. failed += result;
  1080. }
  1081. return failed;
  1082. } /* process_directives () */
  1083. // Tidy up and perform last rites on a terminating ACE_Service_Gestalt.
  1084. int
  1085. ACE_Service_Gestalt::close (void)
  1086. {
  1087. ACE_TRACE ("ACE_Service_Gestalt::close");
  1088. if (!this->is_opened_ || --this->is_opened_ != 0)
  1089. return 0;
  1090. // Delete the list fo svc.conf files
  1091. delete this->svc_conf_file_queue_;
  1092. this->svc_conf_file_queue_ = 0;
  1093. if (this->processed_static_svcs_ &&
  1094. !this->processed_static_svcs_->is_empty())
  1095. {
  1096. Processed_Static_Svc **pss = 0;
  1097. for (ACE_PROCESSED_STATIC_SVCS_ITERATOR iter (*this->processed_static_svcs_);
  1098. iter.next (pss) != 0;
  1099. iter.advance ())
  1100. {
  1101. delete *pss;
  1102. }
  1103. }
  1104. delete this->processed_static_svcs_;
  1105. this->processed_static_svcs_ = 0;
  1106. #ifndef ACE_NLOGGING
  1107. if (ACE::debug ())
  1108. ACE_DEBUG ((LM_DEBUG,
  1109. ACE_TEXT ("ACE (%P|%t) SG::close - complete this=%@, repo=%@, owned=%d\n"),
  1110. this, this->repo_, this->svc_repo_is_owned_));
  1111. #endif
  1112. if (this->svc_repo_is_owned_)
  1113. delete this->repo_;
  1114. this->repo_ = 0;
  1115. return 0;
  1116. } /* close () */
  1117. ACE_END_VERSIONED_NAMESPACE_DECL
  1118. #if !defined (__ACE_INLINE__)
  1119. #include "ace/Service_Gestalt.inl"
  1120. #endif /* __ACE_INLINE__ */
  1121. // Allocate a Service Manager.
  1122. ACE_FACTORY_DEFINE (ACE, ACE_Service_Manager)