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