Service_Gestalt.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 //====================================================================
00004 /**
00005  *  @file    Service_Gestalt.h
00006  *
00007  *  $Id: Service_Gestalt.h 81624 2008-05-06 17:14:57Z wotte $
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   /// Constructor either associates the instance with the process-wide
00086   /// singleton instance of ACE_Service_Repository, or creates and
00087   /// manages its own instance of the specified size.
00088   ACE_Service_Gestalt (size_t size = 1024,
00089                        bool svc_repo_is_owned = true,
00090                        bool no_static_svcs = true);
00091 
00092   /// Perform user-specified close activities and remove dynamic
00093   /// memory.
00094   ~ACE_Service_Gestalt (void);
00095 
00096   /// Dump the state of an object.
00097   void dump (void) const;
00098 
00099    /**
00100    * Performs an open without parsing command-line arguments.  The
00101    * @a logger_key indicates where to write the logging output, which
00102    * is typically either a STREAM pipe or a socket address.  If
00103    * @a ignore_static_svcs is true then static services are not loaded,
00104    * otherwise, they are loaded.  If @a ignore_default_svc_conf_file is
00105    * true then the <svc.conf> configuration file will be ignored.
00106    * Returns zero upon success, -1 if the file is not found or cannot
00107    * be opened (errno is set accordingly), otherwise returns the
00108    * number of errors encountered loading the services in the
00109    * specified svc.conf configuration file.  If @a ignore_debug_flag is
00110    * true then the application is responsible for setting the
00111    * <ACE_Log_Msg::priority_mask> appropriately.
00112    */
00113   int open (const ACE_TCHAR program_name[],
00114             const ACE_TCHAR *logger_key = ACE_DEFAULT_LOGGER_KEY,
00115             bool ignore_static_svcs = true,
00116             bool ignore_default_svc_conf_file = false,
00117             bool ignore_debug_flag = false);
00118 
00119   /**
00120    * This is the primary entry point into the ACE_Service_Config (the
00121    * constructor just handles simple initializations).  It parses
00122    * arguments passed in from @a argc and @a argv parameters.  The
00123    * arguments that are valid in a call to this method include:
00124    *
00125    * - '-b' Option to indicate that we should be a daemon. Note that when
00126    *        this option is used, the process will be daemonized before the
00127    *        service configuration file(s) are read. During daemonization,
00128    *        (on POSIX systems) the current directory will be changed to "/"
00129    *        so the caller should either fully specify the file names, or
00130    *        execute a @c chroot() to the appropriate directory.
00131    *        @sa ACE::daemonize().
00132    * - '-d' Turn on debugging mode
00133    * - '-f' Specifies a configuration file name other than the default
00134    *        svc.conf. Can be specified multiple times to use multiple files.
00135    * - '-k' Specifies the rendezvous point to use for the ACE distributed
00136    *        logger.
00137    * - '-y' Explicitly enables the use of static services. This flag
00138    *        overrides the @a ignore_static_svcs parameter value.
00139    * - '-n' Explicitly disables the use of static services. This flag
00140    *        overrides the @a ignore_static_svcs parameter value.
00141    * - '-p' Specifies a pathname which is used to store the process id.
00142    * - '-s' Specifies a signal number other than SIGHUP to trigger reprocessing
00143    *        of the configuration file(s). Ignored for platforms that do not
00144    *        have POSIX signals, such as Windows.
00145    * - '-S' Specifies a service directive string. Enclose the string in quotes
00146    *        and escape any embedded quotes with a backslash. This option
00147    *        specifies service directives without the need for a configuration
00148    *        file.
00149    *
00150    * @param argc The number of commandline arguments.
00151    * @param argv The array with commandline arguments
00152    * @param logger_key   Indicates where to write the logging output,
00153    *                     which is typically either a STREAM pipe or a
00154    *                     socket address.
00155    * @param ignore_static_svcs   If true then static services are not loaded,
00156    *                             otherwise, they are loaded.
00157    * @param ignore_default_svc_conf_file  If false then the @c svc.conf
00158    *                                      configuration file will be ignored.
00159    * @param ignore_debug_flag If false then the application is responsible
00160    *                          for setting the @c ACE_Log_Msg::priority_mask
00161    *                          appropriately.
00162    *
00163    * @retval -1   The configuration file is not found or cannot
00164    *              be opened (errno is set accordingly).
00165    * @retval  0   Success.
00166    * @retval  >0  The number of errors encountered while processing
00167    *              the service configuration file(s).
00168    */
00169   int open (int argc,
00170             ACE_TCHAR *argv[],
00171             const ACE_TCHAR *logger_key = ACE_DEFAULT_LOGGER_KEY,
00172             bool ignore_static_svcs = true,
00173             bool ignore_default_svc_conf_file = false,
00174             bool ignore_debug_flag = false);
00175 
00176   /// Has it been opened?  Returns the difference between the times
00177   /// open and close have been called on this instance
00178   int is_opened (void);
00179 
00180   /// Declare the dynamic allocation hooks.
00181   ACE_ALLOC_HOOK_DECLARE;
00182 
00183   /// Process one service configuration @a directive, which is passed as
00184   /// a string.  Returns the number of errors that occurred.
00185   int process_directive (const ACE_TCHAR directive[]);
00186 
00187   /// Process one static service definition.
00188   /**
00189    * Load a new static service.
00190    *
00191    * @param ssd Service descriptor, see the document of
00192    *        ACE_Static_Svc_Descriptor for more details.
00193    *
00194    * @param force_replace If set the new service descriptor replaces
00195    *        any previous instance in the repository.
00196    *
00197    * @return Returns -1 if the service cannot be 'loaded'.
00198    */
00199   int process_directive (const ACE_Static_Svc_Descriptor &ssd,
00200                          bool force_replace = false);
00201 
00202   /// Process a file containing a list of service configuration
00203   /// directives.
00204   int process_file (const ACE_TCHAR file[]);
00205 
00206   /**
00207    * Locate an entry with @a name in the table.  If @a ignore_suspended
00208    * is set then only consider services marked as resumed.  If the
00209    * caller wants the located entry, pass back a pointer to the
00210    * located entry via @a srp.  If @a name is not found, -1 is returned.
00211    * If @a name is found, but it is suspended and the caller wants to
00212    * ignore suspended services a -2 is returned.
00213    */
00214   int find (const ACE_TCHAR name[],
00215             const ACE_Service_Type **srp = 0,
00216             bool ignore_suspended = true) const;
00217 
00218   /**
00219    * Handle the command-line options intended for the
00220    * ACE_Service_Gestalt.  Note that <argv[0]> is assumed to be the
00221    * program name.
00222    *
00223    * The arguments that are valid in a call to this method are
00224    * - '-d' Turn on debugging mode
00225    * - '-f' Option to read in the list of svc.conf file names
00226    * - '-k' Option to read a wide string where in the logger output can
00227    *        be written
00228    * - '-y' Turn on the flag for a  repository of statically
00229    *        linked services
00230    * - '-n' Need not have a repository of statically linked services
00231    * - '-S' Option to read in the list of services on the command-line
00232    *        Please observe the difference between options '-f' that looks
00233    *        for a list of files and here a list of services.
00234    */
00235    int parse_args (int, ACE_TCHAR *argv[]);
00236 
00237   /**
00238    * Process (or re-process) service configuration requests that are
00239    * provided in the svc.conf file(s).  Returns the number of errors
00240    * that occurred.
00241    */
00242    int process_directives (bool ignore_default_svc_conf_file);
00243 
00244   /// Tidy up and perform last rites when ACE_Service_Config is shut
00245   /// down.  This method calls <close_svcs>.  Returns 0.
00246   int close (void);
00247 
00248 
00249   // Registers a service descriptor for a static service object
00250   int insert (ACE_Static_Svc_Descriptor *stsd);
00251 
00252   // = Utility methods.
00253 
00254 #if (ACE_USES_CLASSIC_SVC_CONF == 1)
00255   /// Dynamically link the shared object file and retrieve a pointer to
00256   /// the designated shared object in this file. Also account for the
00257   /// possiblity to have static services registered when loading the DLL, by
00258   /// ensuring that the dynamic sevice is registered before any of its
00259   /// subordibnate static services. Thus avoiding any finalization order
00260   /// problems.
00261   int initialize (const ACE_Service_Type_Factory *,
00262                   const ACE_TCHAR *parameters);
00263 #endif /* (ACE_USES_CLASSIC_SVC_CONF == 1) */
00264 
00265   /// Dynamically link the shared object file and retrieve a pointer to
00266   /// the designated shared object in this file.
00267   /// @deprecated
00268   /// @note This is error-prone in the presense of dynamic services,
00269   /// which in turn initialize their own static services. This method
00270   /// will allow those static services to register *before* the dynamic
00271   /// service that owns them.  Upon finalization of the static services
00272   /// the process will typically crash, because the dynamic service's
00273   /// DLL may have been already released, together with the memory in
00274   /// which the static services reside.  It may not crash, for
00275   /// instance, when the first static service to register is the same
00276   /// as the dynamic service being loaded. You should be so lucky!
00277   int initialize (const ACE_Service_Type *,
00278                   const ACE_TCHAR *parameters);
00279 
00280   /// Initialize and activate a statically @a svc_name service.
00281   int initialize (const ACE_TCHAR *svc_name,
00282                   const ACE_TCHAR *parameters);
00283 
00284   /// Resume a @a svc_name that was previously suspended or has not yet
00285   /// been resumed (e.g., a static service).
00286   int resume (const ACE_TCHAR svc_name[]);
00287 
00288   /**
00289    * Suspend @a svc_name.  Note that this will not unlink the service
00290    * from the daemon if it was dynamically linked, it will mark it as
00291    * being suspended in the Service Repository and call the <suspend>
00292    * member function on the appropriate ACE_Service_Object.  A
00293    * service can be resumed later on by calling the <RESUME> member
00294    * function...
00295    */
00296   int suspend (const ACE_TCHAR svc_name[]);
00297 
00298   /// Totally remove @a svc_name from the daemon by removing it
00299   /// from the ACE_Reactor, and unlinking it if necessary.
00300   int remove (const ACE_TCHAR svc_name[]);
00301 
00302   /**
00303    * Using the supplied name, finds and (if needed) returns a pointer to a
00304    * static service descriptor. Returns 0 for success and -1 for failure
00305    */
00306   int find_static_svc_descriptor (const ACE_TCHAR* name,
00307                                   ACE_Static_Svc_Descriptor **ssd = 0) const;
00308 
00309   struct Processed_Static_Svc
00310   {
00311     Processed_Static_Svc (const ACE_Static_Svc_Descriptor *);
00312     ~Processed_Static_Svc (void);
00313     ACE_TCHAR * name_;
00314     const ACE_Static_Svc_Descriptor *assd_;
00315   };
00316 
00317   /// Get the current ACE_Service_Repository held by this object.
00318   ACE_Service_Repository* current_service_repository (void);
00319 
00320 protected:
00321 
00322   int parse_args_i (int, ACE_TCHAR *argv[],
00323                     bool& ignore_default_svc_conf_file);
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   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                            bool force_replace = false);
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 protected:
00382 
00383   // Maintain a queue of services to be configured from the
00384   // command-line.
00385   typedef ACE_Unbounded_Queue<ACE_TString> ACE_SVC_QUEUE;
00386   typedef ACE_Unbounded_Queue_Iterator<ACE_TString> ACE_SVC_QUEUE_ITERATOR;
00387 
00388   // Maintain a set of the statically linked service descriptors.
00389   typedef ACE_Unbounded_Set<ACE_Static_Svc_Descriptor *>
00390     ACE_STATIC_SVCS;
00391 
00392   typedef ACE_Unbounded_Set_Iterator<ACE_Static_Svc_Descriptor *>
00393     ACE_STATIC_SVCS_ITERATOR;
00394 
00395   typedef ACE_Unbounded_Set<Processed_Static_Svc *>
00396     ACE_PROCESSED_STATIC_SVCS;
00397 
00398   typedef ACE_Unbounded_Set_Iterator<Processed_Static_Svc *>
00399     ACE_PROCESSED_STATIC_SVCS_ITERATOR;
00400 
00401   friend class ACE_Dynamic_Service_Base;
00402   friend class ACE_Service_Object;
00403   friend class ACE_Service_Config;
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   /// Support for intrusive reference counting
00451   ACE_Atomic_Op<ACE_SYNCH_MUTEX, long> refcnt_;
00452 
00453  public:
00454   static void intrusive_add_ref (ACE_Service_Gestalt*);
00455   static void intrusive_remove_ref (ACE_Service_Gestalt*);
00456 
00457 }; /* class ACE_Service_Gestalt */
00458 
00459 
00460 /**
00461  * @class ACE_Service_Type_Dynamic_Guard
00462  *
00463  * @brief A forward service declaration guard.
00464  *
00465  * Helps to resolve an issue with hybrid services, i.e. dynamic
00466  * services, accompanied by static services in the same DLL.  Only
00467  * automatic instances of this class are supposed to exist. Those are
00468  * created during (dynamic) service initialization and serve to:
00469  *
00470  * (a) Ensure the service we are loading is ordered last in the
00471  * repository, following any other services it may cause to register,
00472  * as part of its own registration. This is a common case when
00473  * loading dynamic services from DLLs - there are often static
00474  * initializers, which register static services.
00475  *
00476  * (b) The SDG instance destructor detects if the dynamic service
00477  * initialized successfully and "fixes-up" all the newly registered
00478  * static services to hold a reference to the DLL, from which they
00479  * have originated.
00480  */
00481 class ACE_Export ACE_Service_Type_Dynamic_Guard
00482 {
00483 public:
00484   ACE_Service_Type_Dynamic_Guard (ACE_Service_Repository &r,
00485                                   ACE_TCHAR const *name);
00486 
00487   ~ACE_Service_Type_Dynamic_Guard (void);
00488 
00489 private:
00490   ACE_Service_Repository & repo_;
00491   size_t repo_begin_;
00492   ACE_TCHAR const * const name_;
00493 
00494 
00495 # if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
00496   ACE_Guard< ACE_Recursive_Thread_Mutex > repo_monitor_;
00497 #endif
00498 };
00499 
00500 
00501 ACE_END_VERSIONED_NAMESPACE_DECL
00502 
00503 #if defined (__ACE_INLINE__)
00504 #include "ace/Service_Gestalt.inl"
00505 #endif /* __ACE_INLINE__ */
00506 
00507 
00508 #include /**/ "ace/post.h"
00509 
00510 #endif /* ACE_SERVICE_GESTALT_H */

Generated on Tue Feb 2 17:18:42 2010 for ACE by  doxygen 1.4.7