00001 // -*- C++ -*- 00002 00003 //==================================================================== 00004 /** 00005 * @file Service_Gestalt.h 00006 * 00007 * $Id: Service_Gestalt.h 91158 2010-07-21 15:54:12Z mesnier_p $ 00008 * 00009 * @author Iliyan Jeliazkov <iliyan@ociweb.com> 00010 */ 00011 //==================================================================== 00012 00013 #ifndef ACE_SERVICE_GESTALT_H 00014 #define ACE_SERVICE_GESTALT_H 00015 00016 #include /**/ "ace/pre.h" 00017 00018 #include /**/ "ace/config-all.h" 00019 #include "ace/Default_Constants.h" 00020 00021 #if !defined (ACE_LACKS_PRAGMA_ONCE) 00022 # pragma once 00023 #endif /* ACE_LACKS_PRAGMA_ONCE */ 00024 00025 #include "ace/Auto_Ptr.h" 00026 #include "ace/SString.h" 00027 #include "ace/Unbounded_Queue.h" 00028 #include "ace/Unbounded_Set.h" 00029 #include "ace/Service_Repository.h" 00030 #include "ace/Singleton.h" 00031 #include "ace/OS_NS_signal.h" 00032 #include "ace/Synch_Traits.h" 00033 #include "ace/Atomic_Op.h" 00034 #include "ace/Guard_T.h" 00035 00036 ACE_BEGIN_VERSIONED_NAMESPACE_DECL 00037 00038 #if (ACE_USES_CLASSIC_SVC_CONF == 1) 00039 class ACE_Service_Type_Factory; 00040 class ACE_Location_Node; 00041 #else 00042 class ACE_XML_Svc_Conf; 00043 class ACE_DLL; 00044 #endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */ 00045 00046 class ACE_Static_Svc_Descriptor; 00047 class ACE_Svc_Conf_Param; 00048 00049 /** 00050 * @class ACE_Service_Gestalt 00051 * 00052 * @brief Supplies common server operations for dynamic and static 00053 * configuration of services. 00054 * 00055 * The Gestalt embodies the concept of configuration context. On one 00056 * hand, it is a flat namespace, where names correspond to a Service 00057 * Object instance. A Gestalt owns the Service Repository instance, 00058 * which in turn owns the Service Object instances. 00059 * 00060 * Another aspect of a Gestalt is its responsibility for 00061 * record-keeping and accounting for the meta-data, necessary for 00062 * locating, removing or instantiating a service. 00063 * 00064 * A repository underlies an instance of a gestalt and its lifetime 00065 * may or may not be bounded by the lifetime of the gestalt, that owns 00066 * it. This feature is important for the derived classes and the 00067 * Service Config in particular. 00068 * 00069 */ 00070 class ACE_Export ACE_Service_Gestalt 00071 { 00072 private: 00073 /// 00074 /// Not implemented to enforce no copying 00075 // 00076 ACE_UNIMPLEMENTED_FUNC (ACE_Service_Gestalt(const ACE_Service_Gestalt&)) 00077 ACE_UNIMPLEMENTED_FUNC (ACE_Service_Gestalt& operator=(const ACE_Service_Gestalt&)) 00078 00079 public: 00080 enum 00081 { 00082 MAX_SERVICES = ACE_DEFAULT_SERVICE_REPOSITORY_SIZE 00083 }; 00084 00085 enum 00086 { 00087 DEFAULT_SIZE = ACE_DEFAULT_SERVICE_GESTALT_SIZE 00088 }; 00089 00090 /// Constructor either associates the instance with the process-wide 00091 /// singleton instance of ACE_Service_Repository, or creates and 00092 /// manages its own instance of the specified size. 00093 ACE_Service_Gestalt (size_t size = DEFAULT_SIZE, 00094 bool svc_repo_is_owned = true, 00095 bool no_static_svcs = true); 00096 00097 /// Perform user-specified close activities and remove dynamic 00098 /// memory. 00099 ~ACE_Service_Gestalt (void); 00100 00101 /// Dump the state of an object. 00102 void dump (void) const; 00103 00104 /** 00105 * Performs an open without parsing command-line arguments. The 00106 * @a logger_key indicates where to write the logging output, which 00107 * is typically either a STREAM pipe or a socket address. If 00108 * @a ignore_static_svcs is true then static services are not loaded, 00109 * otherwise, they are loaded. If @a ignore_default_svc_conf_file is 00110 * true then the @c svc.conf configuration file will be ignored. 00111 * Returns zero upon success, -1 if the file is not found or cannot 00112 * be opened (errno is set accordingly), otherwise returns the 00113 * number of errors encountered loading the services in the 00114 * specified svc.conf configuration file. If @a ignore_debug_flag is 00115 * true then the application is responsible for setting the 00116 * ACE_Log_Msg::priority_mask appropriately. 00117 */ 00118 int open (const ACE_TCHAR program_name[], 00119 const ACE_TCHAR *logger_key = 0, 00120 bool ignore_static_svcs = true, 00121 bool ignore_default_svc_conf_file = false, 00122 bool ignore_debug_flag = false); 00123 00124 /** 00125 * This is the primary entry point into the ACE_Service_Config (the 00126 * constructor just handles simple initializations). It parses 00127 * arguments passed in from @a argc and @a argv parameters. The 00128 * arguments that are valid in a call to this method include: 00129 * 00130 * - '-b' Option to indicate that we should be a daemon. Note that when 00131 * this option is used, the process will be daemonized before the 00132 * service configuration file(s) are read. During daemonization, 00133 * (on POSIX systems) the current directory will be changed to "/" 00134 * so the caller should either fully specify the file names, or 00135 * execute a @c chroot() to the appropriate directory. 00136 * @sa ACE::daemonize(). 00137 * - '-d' Turn on debugging mode 00138 * - '-f' Specifies a configuration file name other than the default 00139 * svc.conf. Can be specified multiple times to use multiple files. 00140 * If any configuration file is provided with this option then 00141 * the default svc.conf will be ignored. 00142 * - '-k' Specifies the rendezvous point to use for the ACE distributed 00143 * logger. 00144 * - '-y' Explicitly enables the use of static services. This flag 00145 * overrides the @a ignore_static_svcs parameter value. 00146 * - '-n' Explicitly disables the use of static services. This flag 00147 * overrides the @a ignore_static_svcs parameter value. 00148 * - '-p' Specifies a pathname which is used to store the process id. 00149 * - '-s' Specifies a signal number other than SIGHUP to trigger reprocessing 00150 * of the configuration file(s). Ignored for platforms that do not 00151 * have POSIX signals, such as Windows. 00152 * - '-S' Specifies a service directive string. Enclose the string in quotes 00153 * and escape any embedded quotes with a backslash. This option 00154 * specifies service directives without the need for a configuration 00155 * file. Can be specified multiple times. 00156 * 00157 * Note: Options '-f' and '-S' complement each other. Directives 00158 * from files and from '-S' option are processed together in the 00159 * following order. First, the default file "./svc.conf" is 00160 * evaluated if not ignored, then all files are processed in the 00161 * order they are specified in '-f' @a argv parameter. Finally, all 00162 * '-S' directive strings are executed in the order the directives 00163 * appear in @a argv parameter. 00164 * 00165 * If no files or directives are added via the '-f' and '-S' 00166 * arguments, and the default file is not ignored, it will be 00167 * evaluated whether it exists or not, possibly causing a failure 00168 * return. If any other directives are added then the default file 00169 * will be evaluated only if it exists. 00170 * 00171 * @param argc The number of commandline arguments. 00172 * @param argv The array with commandline arguments 00173 * @param logger_key Indicates where to write the logging output, 00174 * which is typically either a STREAM pipe or a 00175 * socket address. 00176 * @param ignore_static_svcs If true then static services are not loaded, 00177 * otherwise, they are loaded. 00178 * @param ignore_default_svc_conf_file If false then the @c ./svc.conf 00179 * configuration file will be ignored. 00180 * @param ignore_debug_flag If false then the application is responsible 00181 * for setting the @c ACE_Log_Msg::priority_mask 00182 * appropriately. 00183 * 00184 * @retval -1 A configuration file is not found or cannot 00185 * be opened (errno is set accordingly). 00186 * @retval 0 Success. 00187 * @retval >0 The number of directive errors encountered while processing 00188 * the service configuration file(s). 00189 */ 00190 int open (int argc, 00191 ACE_TCHAR *argv[], 00192 const ACE_TCHAR *logger_key = 0, 00193 bool ignore_static_svcs = true, 00194 bool ignore_default_svc_conf_file = false, 00195 bool ignore_debug_flag = false); 00196 00197 /// Has it been opened? Returns the difference between the times 00198 /// open and close have been called on this instance 00199 int is_opened (void); 00200 00201 /// Declare the dynamic allocation hooks. 00202 ACE_ALLOC_HOOK_DECLARE; 00203 00204 /// Process one service configuration @a directive, which is passed as 00205 /// a string. Returns the number of errors that occurred. 00206 int process_directive (const ACE_TCHAR directive[]); 00207 00208 /// Process one static service definition. 00209 /** 00210 * Load a new static service. 00211 * 00212 * @param ssd Service descriptor, see the document of 00213 * ACE_Static_Svc_Descriptor for more details. 00214 * 00215 * @param force_replace If set the new service descriptor replaces 00216 * any previous instance in the repository. 00217 * 00218 * @return Returns -1 if the service cannot be 'loaded'. 00219 */ 00220 int process_directive (const ACE_Static_Svc_Descriptor &ssd, 00221 bool force_replace = false); 00222 00223 /// Process a file containing a list of service configuration 00224 /// directives. 00225 int process_file (const ACE_TCHAR file[]); 00226 00227 /** 00228 * Locate an entry with @a name in the table. If @a ignore_suspended 00229 * is set then only consider services marked as resumed. If the 00230 * caller wants the located entry, pass back a pointer to the 00231 * located entry via @a srp. If @a name is not found, -1 is returned. 00232 * If @a name is found, but it is suspended and the caller wants to 00233 * ignore suspended services a -2 is returned. 00234 */ 00235 int find (const ACE_TCHAR name[], 00236 const ACE_Service_Type **srp = 0, 00237 bool ignore_suspended = true) const; 00238 00239 /** 00240 * Handle the command-line options intended for the 00241 * ACE_Service_Gestalt. Note that @c argv[0] is assumed to be the 00242 * program name. 00243 * 00244 * The arguments that are valid in a call to this method are 00245 * - '-d' Turn on debugging mode 00246 * - '-f' Option to read in the list of svc.conf file names 00247 * - '-k' Option to read a wide string where in the logger output can 00248 * be written 00249 * - '-y' Turn on the flag for a repository of statically 00250 * linked services 00251 * - '-n' Need not have a repository of statically linked services 00252 * - '-S' Option to read in the list of services on the command-line 00253 * Please observe the difference between options '-f' that looks 00254 * for a list of files and here a list of services. 00255 */ 00256 int parse_args (int argc, ACE_TCHAR *argv[]); 00257 00258 /** 00259 * Process (or re-process) service configuration requests that are 00260 * provided in the svc.conf file(s). Returns the number of errors 00261 * that occurred. 00262 */ 00263 int process_directives (bool defunct_option = false); 00264 00265 /// Tidy up and perform last rites when ACE_Service_Config is shut 00266 /// down. This method calls @c close_svcs. Returns 0. 00267 int close (void); 00268 00269 /// Registers a service descriptor for a static service object 00270 int insert (ACE_Static_Svc_Descriptor *stsd); 00271 00272 // = Utility methods. 00273 00274 #if (ACE_USES_CLASSIC_SVC_CONF == 1) 00275 /// Dynamically link the shared object file and retrieve a pointer to 00276 /// the designated shared object in this file. Also account for the 00277 /// possiblity to have static services registered when loading the DLL, by 00278 /// ensuring that the dynamic sevice is registered before any of its 00279 /// subordibnate static services. Thus avoiding any finalization order 00280 /// problems. 00281 int initialize (const ACE_Service_Type_Factory *, 00282 const ACE_TCHAR *parameters); 00283 #endif /* (ACE_USES_CLASSIC_SVC_CONF == 1) */ 00284 00285 /// Dynamically link the shared object file and retrieve a pointer to 00286 /// the designated shared object in this file. 00287 /// @deprecated 00288 /// @note This is error-prone in the presense of dynamic services, 00289 /// which in turn initialize their own static services. This method 00290 /// will allow those static services to register *before* the dynamic 00291 /// service that owns them. Upon finalization of the static services 00292 /// the process will typically crash, because the dynamic service's 00293 /// DLL may have been already released, together with the memory in 00294 /// which the static services reside. It may not crash, for 00295 /// instance, when the first static service to register is the same 00296 /// as the dynamic service being loaded. You should be so lucky! 00297 int initialize (const ACE_Service_Type *, 00298 const ACE_TCHAR *parameters); 00299 00300 /// Initialize and activate a statically @a svc_name service. 00301 int initialize (const ACE_TCHAR *svc_name, 00302 const ACE_TCHAR *parameters); 00303 00304 /// Resume a @a svc_name that was previously suspended or has not yet 00305 /// been resumed (e.g., a static service). 00306 int resume (const ACE_TCHAR svc_name[]); 00307 00308 /** 00309 * Suspend @a svc_name. Note that this will not unlink the service 00310 * from the daemon if it was dynamically linked, it will mark it as 00311 * being suspended in the Service Repository and call the @c suspend() 00312 * member function on the appropriate ACE_Service_Object. A 00313 * service can be resumed later on by calling the @c resume() member 00314 * function... 00315 */ 00316 int suspend (const ACE_TCHAR svc_name[]); 00317 00318 /// Totally remove @a svc_name from the daemon by removing it 00319 /// from the ACE_Reactor, and unlinking it if necessary. 00320 int remove (const ACE_TCHAR svc_name[]); 00321 00322 /** 00323 * Using the supplied name, finds and (if needed) returns a pointer to a 00324 * static service descriptor. Returns 0 for success and -1 for failure 00325 */ 00326 int find_static_svc_descriptor (const ACE_TCHAR* name, 00327 ACE_Static_Svc_Descriptor **ssd = 0) const; 00328 00329 struct Processed_Static_Svc 00330 { 00331 Processed_Static_Svc (const ACE_Static_Svc_Descriptor *); 00332 ~Processed_Static_Svc (void); 00333 ACE_TCHAR * name_; 00334 const ACE_Static_Svc_Descriptor *assd_; 00335 }; 00336 00337 /// Get the current ACE_Service_Repository held by this object. 00338 ACE_Service_Repository* current_service_repository (void); 00339 00340 protected: 00341 00342 int parse_args_i (int, ACE_TCHAR *argv[], 00343 bool& ignore_default_svc_conf_file); 00344 00345 /** 00346 * Performs an open without parsing command-line arguments. The @a 00347 * logger_key indicates where to write the logging output, which is 00348 * typically either a STREAM pipe or a socket address. If @a 00349 * ignore_default_svc_conf_file is non-0 then the "svc.conf" file 00350 * will not be added by default. If @a ignore_debug_flag is non-0 00351 * then the application is responsible for setting the @c 00352 * ACE_Log_Msg::priority_mask() appropriately. Returns number of 00353 * errors that occurred on failure and 0 otherwise. 00354 */ 00355 int open_i (const ACE_TCHAR program_name[], 00356 const ACE_TCHAR *logger_key = 0, 00357 bool ignore_static_svcs = true, 00358 bool ignore_default_svc_conf_file = false, 00359 bool ignore_debug_flag = false); 00360 00361 /// Initialize the @c svc_conf_file_queue_ if necessary. 00362 int init_svc_conf_file_queue (void); 00363 00364 /// Add the default statically-linked services to the 00365 /// ACE_Service_Repository. 00366 int load_static_svcs (void); 00367 00368 /// Process service configuration requests that were provided on the 00369 /// command-line. Returns the number of errors that occurred. 00370 int process_commandline_directives (void); 00371 00372 /// Process a static directive without also inserting its descriptor 00373 /// the global table. This avoids multiple additions when processing 00374 /// directives in non-global gestalts. 00375 int process_directive_i (const ACE_Static_Svc_Descriptor &ssd, 00376 bool force_replace = false); 00377 00378 #if (ACE_USES_CLASSIC_SVC_CONF == 1) 00379 /// This is the implementation function that process_directives() 00380 /// and process_directive() both call. Returns the number of errors 00381 /// that occurred. 00382 int process_directives_i (ACE_Svc_Conf_Param *param); 00383 #else 00384 /// Helper function to dynamically link in the XML Service Configurator 00385 /// parser. 00386 ACE_XML_Svc_Conf* get_xml_svc_conf (ACE_DLL &d); 00387 #endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */ 00388 00389 /// Dynamically link the shared object file and retrieve a pointer to 00390 /// the designated shared object in this file. 00391 int initialize_i (const ACE_Service_Type *sr, const ACE_TCHAR *parameters); 00392 00393 const ACE_Static_Svc_Descriptor* find_processed_static_svc (const ACE_TCHAR*); 00394 void add_processed_static_svc (const ACE_Static_Svc_Descriptor *); 00395 00396 /// Performs the common initialization tasks for a new or previously 00397 /// closed instance. Must not be virtual, as it is called from the 00398 /// constructor. 00399 int init_i (void); 00400 00401 protected: 00402 00403 /// Maintain a queue of services to be configured from the 00404 /// command-line. 00405 typedef ACE_Unbounded_Queue<ACE_TString> ACE_SVC_QUEUE; 00406 typedef ACE_Unbounded_Queue_Iterator<ACE_TString> ACE_SVC_QUEUE_ITERATOR; 00407 00408 /// Maintain a set of the statically linked service descriptors. 00409 typedef ACE_Unbounded_Set<ACE_Static_Svc_Descriptor *> 00410 ACE_STATIC_SVCS; 00411 00412 typedef ACE_Unbounded_Set_Iterator<ACE_Static_Svc_Descriptor *> 00413 ACE_STATIC_SVCS_ITERATOR; 00414 00415 typedef ACE_Unbounded_Set<Processed_Static_Svc *> 00416 ACE_PROCESSED_STATIC_SVCS; 00417 00418 typedef ACE_Unbounded_Set_Iterator<Processed_Static_Svc *> 00419 ACE_PROCESSED_STATIC_SVCS_ITERATOR; 00420 00421 friend class ACE_Dynamic_Service_Base; 00422 friend class ACE_Service_Object; 00423 friend class ACE_Service_Config; 00424 friend class ACE_Service_Config_Guard; 00425 00426 protected: 00427 00428 /// Do we own the service repository instance, or have only been 00429 /// given a ptr to the singleton? 00430 bool svc_repo_is_owned_; 00431 00432 /// Repository size is necessary, so that we can close (which may 00433 /// destroy the repository instance), and then re-open again. 00434 size_t svc_repo_size_; 00435 00436 /// Keep track of the number of times the instance has been 00437 /// initialized (opened). "If so, we can't allow <yyparse> to be called since 00438 /// it's not reentrant" is the original motivation, but that does not seem 00439 /// to be the case anymore. This variable is incremented by the 00440 /// <ACE_Service_Gestalt::open> method and decremented by the 00441 /// <ACE_Service_Gestalt::close> method. 00442 int is_opened_; 00443 00444 /// Indicates where to write the logging output. This is typically 00445 /// either a STREAM pipe or a socket 00446 const ACE_TCHAR *logger_key_; 00447 00448 /// Should we avoid loading the static services? 00449 bool no_static_svcs_; 00450 00451 /// Queue of services specified on the command-line. 00452 ACE_SVC_QUEUE* svc_queue_; 00453 00454 /** 00455 * Queue of svc.conf files specified on the command-line. 00456 * @@ This should probably be made to handle unicode filenames... 00457 */ 00458 ACE_SVC_QUEUE* svc_conf_file_queue_; 00459 00460 /// The service repository to hold the services. 00461 ACE_Service_Repository* repo_; 00462 00463 /// Repository of statically linked services. 00464 ACE_STATIC_SVCS* static_svcs_; 00465 00466 /// Repository of statically linked services for which process 00467 /// directive was called, but the service is not already a member of 00468 /// the static_svcs_ list. 00469 ACE_PROCESSED_STATIC_SVCS* processed_static_svcs_; 00470 00471 /// Support for intrusive reference counting 00472 ACE_Atomic_Op<ACE_SYNCH_MUTEX, long> refcnt_; 00473 00474 public: 00475 static void intrusive_add_ref (ACE_Service_Gestalt*); 00476 static void intrusive_remove_ref (ACE_Service_Gestalt*); 00477 00478 }; /* class ACE_Service_Gestalt */ 00479 00480 00481 /** 00482 * @class ACE_Service_Type_Dynamic_Guard 00483 * 00484 * @brief A forward service declaration guard. 00485 * 00486 * Helps to resolve an issue with hybrid services, i.e. dynamic 00487 * services, accompanied by static services in the same DLL. Only 00488 * automatic instances of this class are supposed to exist. Those are 00489 * created during (dynamic) service initialization and serve to: 00490 * 00491 * (a) Ensure the service we are loading is ordered last in the 00492 * repository, following any other services it may cause to register, 00493 * as part of its own registration. This is a common case when 00494 * loading dynamic services from DLLs - there are often static 00495 * initializers, which register static services. 00496 * 00497 * (b) The SDG instance destructor detects if the dynamic service 00498 * initialized successfully and "fixes-up" all the newly registered 00499 * static services to hold a reference to the DLL, from which they 00500 * have originated. 00501 */ 00502 class ACE_Export ACE_Service_Type_Dynamic_Guard 00503 { 00504 public: 00505 ACE_Service_Type_Dynamic_Guard (ACE_Service_Repository &r, 00506 ACE_TCHAR const *name); 00507 00508 ~ACE_Service_Type_Dynamic_Guard (void); 00509 00510 private: 00511 ACE_Service_Repository & repo_; 00512 size_t repo_begin_; 00513 ACE_TCHAR const * const name_; 00514 00515 # if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) 00516 ACE_Guard< ACE_Recursive_Thread_Mutex > repo_monitor_; 00517 #endif 00518 }; 00519 00520 00521 ACE_END_VERSIONED_NAMESPACE_DECL 00522 00523 #if defined (__ACE_INLINE__) 00524 #include "ace/Service_Gestalt.inl" 00525 #endif /* __ACE_INLINE__ */ 00526 00527 00528 #include /**/ "ace/post.h" 00529 00530 #endif /* ACE_SERVICE_GESTALT_H */