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 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 */

Generated on Sun Jan 27 12:05:37 2008 for ACE by doxygen 1.3.6