mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2025-11-29 17:38:24 +08:00
523 lines
20 KiB
C++
523 lines
20 KiB
C++
// -*- C++ -*-
|
|
|
|
//====================================================================
|
|
/**
|
|
* @file Service_Gestalt.h
|
|
*
|
|
* @author Iliyan Jeliazkov <iliyan@ociweb.com>
|
|
*/
|
|
//====================================================================
|
|
|
|
#ifndef ACE_SERVICE_GESTALT_H
|
|
#define ACE_SERVICE_GESTALT_H
|
|
|
|
#include /**/ "ace/pre.h"
|
|
|
|
#include /**/ "ace/config-all.h"
|
|
#include "ace/Default_Constants.h"
|
|
|
|
#if !defined (ACE_LACKS_PRAGMA_ONCE)
|
|
# pragma once
|
|
#endif /* ACE_LACKS_PRAGMA_ONCE */
|
|
|
|
#include "ace/Auto_Ptr.h"
|
|
#include "ace/SString.h"
|
|
#include "ace/Unbounded_Queue.h"
|
|
#include "ace/Unbounded_Set.h"
|
|
#include "ace/Service_Repository.h"
|
|
#include "ace/Singleton.h"
|
|
#include "ace/OS_NS_signal.h"
|
|
#include "ace/Synch_Traits.h"
|
|
#include "ace/Atomic_Op.h"
|
|
#include "ace/Guard_T.h"
|
|
|
|
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
|
|
|
|
#if (ACE_USES_CLASSIC_SVC_CONF == 1)
|
|
class ACE_Service_Type_Factory;
|
|
class ACE_Location_Node;
|
|
#else
|
|
class ACE_XML_Svc_Conf;
|
|
class ACE_DLL;
|
|
#endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */
|
|
|
|
class ACE_Static_Svc_Descriptor;
|
|
class ACE_Svc_Conf_Param;
|
|
|
|
/**
|
|
* @class ACE_Service_Gestalt
|
|
*
|
|
* @brief Supplies common server operations for dynamic and static
|
|
* configuration of services.
|
|
*
|
|
* The Gestalt embodies the concept of configuration context. On one
|
|
* hand, it is a flat namespace, where names correspond to a Service
|
|
* Object instance. A Gestalt owns the Service Repository instance,
|
|
* which in turn owns the Service Object instances.
|
|
*
|
|
* Another aspect of a Gestalt is its responsibility for
|
|
* record-keeping and accounting for the meta-data, necessary for
|
|
* locating, removing or instantiating a service.
|
|
*
|
|
* A repository underlies an instance of a gestalt and its lifetime
|
|
* may or may not be bounded by the lifetime of the gestalt, that owns
|
|
* it. This feature is important for the derived classes and the
|
|
* Service Config in particular.
|
|
*/
|
|
class ACE_Export ACE_Service_Gestalt : private ACE_Copy_Disabled
|
|
{
|
|
public:
|
|
enum
|
|
{
|
|
MAX_SERVICES = ACE_DEFAULT_SERVICE_REPOSITORY_SIZE
|
|
};
|
|
|
|
enum
|
|
{
|
|
DEFAULT_SIZE = ACE_DEFAULT_SERVICE_GESTALT_SIZE
|
|
};
|
|
|
|
/// Constructor either associates the instance with the process-wide
|
|
/// singleton instance of ACE_Service_Repository, or creates and
|
|
/// manages its own instance of the specified size.
|
|
ACE_Service_Gestalt (size_t size = DEFAULT_SIZE,
|
|
bool svc_repo_is_owned = true,
|
|
bool no_static_svcs = true);
|
|
|
|
/// Perform user-specified close activities and remove dynamic
|
|
/// memory.
|
|
~ACE_Service_Gestalt (void);
|
|
|
|
/// Dump the state of an object.
|
|
void dump (void) const;
|
|
|
|
/**
|
|
* Performs an open without parsing command-line arguments. The
|
|
* @a logger_key indicates where to write the logging output, which
|
|
* is typically either a STREAM pipe or a socket address. If
|
|
* @a ignore_static_svcs is true then static services are not loaded,
|
|
* otherwise, they are loaded. If @a ignore_default_svc_conf_file is
|
|
* true then the @c svc.conf configuration file will be ignored.
|
|
* Returns zero upon success, -1 if the file is not found or cannot
|
|
* be opened (errno is set accordingly), otherwise returns the
|
|
* number of errors encountered loading the services in the
|
|
* specified svc.conf configuration file. If @a ignore_debug_flag is
|
|
* true then the application is responsible for setting the
|
|
* ACE_Log_Msg::priority_mask appropriately.
|
|
*/
|
|
int open (const ACE_TCHAR program_name[],
|
|
const ACE_TCHAR *logger_key = 0,
|
|
bool ignore_static_svcs = true,
|
|
bool ignore_default_svc_conf_file = false,
|
|
bool ignore_debug_flag = false);
|
|
|
|
/**
|
|
* This is the primary entry point into the ACE_Service_Config (the
|
|
* constructor just handles simple initializations). It parses
|
|
* arguments passed in from @a argc and @a argv parameters. The
|
|
* arguments that are valid in a call to this method include:
|
|
*
|
|
* - '-b' Option to indicate that we should be a daemon. Note that when
|
|
* this option is used, the process will be daemonized before the
|
|
* service configuration file(s) are read. During daemonization,
|
|
* (on POSIX systems) the current directory will be changed to "/"
|
|
* so the caller should either fully specify the file names, or
|
|
* execute a @c chroot() to the appropriate directory.
|
|
* @sa ACE::daemonize().
|
|
* - '-d' Turn on debugging mode
|
|
* - '-f' Specifies a configuration file name other than the default
|
|
* svc.conf. Can be specified multiple times to use multiple files.
|
|
* If any configuration file is provided with this option then
|
|
* the default svc.conf will be ignored.
|
|
* - '-k' Specifies the rendezvous point to use for the ACE distributed
|
|
* logger.
|
|
* - '-y' Explicitly enables the use of static services. This flag
|
|
* overrides the @a ignore_static_svcs parameter value.
|
|
* - '-n' Explicitly disables the use of static services. This flag
|
|
* overrides the @a ignore_static_svcs parameter value.
|
|
* - '-p' Specifies a pathname which is used to store the process id.
|
|
* - '-s' Specifies a signal number other than SIGHUP to trigger reprocessing
|
|
* of the configuration file(s). Ignored for platforms that do not
|
|
* have POSIX signals, such as Windows.
|
|
* - '-S' Specifies a service directive string. Enclose the string in quotes
|
|
* and escape any embedded quotes with a backslash. This option
|
|
* specifies service directives without the need for a configuration
|
|
* file. Can be specified multiple times.
|
|
*
|
|
* Note: Options '-f' and '-S' complement each other. Directives
|
|
* from files and from '-S' option are processed together in the
|
|
* following order. First, the default file "./svc.conf" is
|
|
* evaluated if not ignored, then all files are processed in the
|
|
* order they are specified in '-f' @a argv parameter. Finally, all
|
|
* '-S' directive strings are executed in the order the directives
|
|
* appear in @a argv parameter.
|
|
*
|
|
* If no files or directives are added via the '-f' and '-S'
|
|
* arguments, and the default file is not ignored, it will be
|
|
* evaluated whether it exists or not, possibly causing a failure
|
|
* return. If any other directives are added then the default file
|
|
* will be evaluated only if it exists.
|
|
*
|
|
* @param argc The number of commandline arguments.
|
|
* @param argv The array with commandline arguments
|
|
* @param logger_key Indicates where to write the logging output,
|
|
* which is typically either a STREAM pipe or a
|
|
* socket address.
|
|
* @param ignore_static_svcs If true then static services are not loaded,
|
|
* otherwise, they are loaded.
|
|
* @param ignore_default_svc_conf_file If false then the @c ./svc.conf
|
|
* configuration file will be ignored.
|
|
* @param ignore_debug_flag If false then the application is responsible
|
|
* for setting the @c ACE_Log_Msg::priority_mask
|
|
* appropriately.
|
|
*
|
|
* @retval -1 A configuration file is not found or cannot
|
|
* be opened (errno is set accordingly).
|
|
* @retval 0 Success.
|
|
* @retval >0 The number of directive errors encountered while processing
|
|
* the service configuration file(s).
|
|
*/
|
|
int open (int argc,
|
|
ACE_TCHAR *argv[],
|
|
const ACE_TCHAR *logger_key = 0,
|
|
bool ignore_static_svcs = true,
|
|
bool ignore_default_svc_conf_file = false,
|
|
bool ignore_debug_flag = false);
|
|
|
|
/// Has it been opened? Returns the difference between the times
|
|
/// open and close have been called on this instance
|
|
int is_opened (void);
|
|
|
|
/// Declare the dynamic allocation hooks.
|
|
ACE_ALLOC_HOOK_DECLARE;
|
|
|
|
/// Process one service configuration @a directive, which is passed as
|
|
/// a string. Returns the number of errors that occurred.
|
|
int process_directive (const ACE_TCHAR directive[]);
|
|
|
|
/// Process one static service definition.
|
|
/**
|
|
* Load a new static service.
|
|
*
|
|
* @param ssd Service descriptor, see the document of
|
|
* ACE_Static_Svc_Descriptor for more details.
|
|
*
|
|
* @param force_replace If set the new service descriptor replaces
|
|
* any previous instance in the repository.
|
|
*
|
|
* @return Returns -1 if the service cannot be 'loaded'.
|
|
*/
|
|
int process_directive (const ACE_Static_Svc_Descriptor &ssd,
|
|
bool force_replace = false);
|
|
|
|
/// Process a file containing a list of service configuration
|
|
/// directives.
|
|
int process_file (const ACE_TCHAR file[]);
|
|
|
|
/**
|
|
* Locate an entry with @a name in the table. If @a ignore_suspended
|
|
* is set then only consider services marked as resumed. If the
|
|
* caller wants the located entry, pass back a pointer to the
|
|
* located entry via @a srp. If @a name is not found, -1 is returned.
|
|
* If @a name is found, but it is suspended and the caller wants to
|
|
* ignore suspended services a -2 is returned.
|
|
*/
|
|
int find (const ACE_TCHAR name[],
|
|
const ACE_Service_Type **srp = 0,
|
|
bool ignore_suspended = true) const;
|
|
|
|
/**
|
|
* Handle the command-line options intended for the
|
|
* ACE_Service_Gestalt. Note that @c argv[0] is assumed to be the
|
|
* program name.
|
|
*
|
|
* The arguments that are valid in a call to this method are
|
|
* - '-d' Turn on debugging mode
|
|
* - '-f' Option to read in the list of svc.conf file names
|
|
* - '-k' Option to read a wide string where in the logger output can
|
|
* be written
|
|
* - '-y' Turn on the flag for a repository of statically
|
|
* linked services
|
|
* - '-n' Need not have a repository of statically linked services
|
|
* - '-S' Option to read in the list of services on the command-line
|
|
* Please observe the difference between options '-f' that looks
|
|
* for a list of files and here a list of services.
|
|
*/
|
|
int parse_args (int argc, ACE_TCHAR *argv[]);
|
|
|
|
/**
|
|
* Process (or re-process) service configuration requests that are
|
|
* provided in the svc.conf file(s). Returns the number of errors
|
|
* that occurred.
|
|
*/
|
|
int process_directives (bool defunct_option = false);
|
|
|
|
/// Tidy up and perform last rites when ACE_Service_Config is shut
|
|
/// down. This method calls @c close_svcs. Returns 0.
|
|
int close (void);
|
|
|
|
/// Registers a service descriptor for a static service object
|
|
int insert (ACE_Static_Svc_Descriptor *stsd);
|
|
|
|
// = Utility methods.
|
|
|
|
#if (ACE_USES_CLASSIC_SVC_CONF == 1)
|
|
/// Dynamically link the shared object file and retrieve a pointer to
|
|
/// the designated shared object in this file. Also account for the
|
|
/// possiblity to have static services registered when loading the DLL, by
|
|
/// ensuring that the dynamic sevice is registered before any of its
|
|
/// subordibnate static services. Thus avoiding any finalization order
|
|
/// problems.
|
|
int initialize (const ACE_Service_Type_Factory *,
|
|
const ACE_TCHAR *parameters);
|
|
#endif /* (ACE_USES_CLASSIC_SVC_CONF == 1) */
|
|
|
|
/// Dynamically link the shared object file and retrieve a pointer to
|
|
/// the designated shared object in this file.
|
|
/// @deprecated
|
|
/// @note This is error-prone in the presense of dynamic services,
|
|
/// which in turn initialize their own static services. This method
|
|
/// will allow those static services to register *before* the dynamic
|
|
/// service that owns them. Upon finalization of the static services
|
|
/// the process will typically crash, because the dynamic service's
|
|
/// DLL may have been already released, together with the memory in
|
|
/// which the static services reside. It may not crash, for
|
|
/// instance, when the first static service to register is the same
|
|
/// as the dynamic service being loaded. You should be so lucky!
|
|
int initialize (const ACE_Service_Type *,
|
|
const ACE_TCHAR *parameters);
|
|
|
|
/// Initialize and activate a statically @a svc_name service.
|
|
int initialize (const ACE_TCHAR *svc_name,
|
|
const ACE_TCHAR *parameters);
|
|
|
|
/// Resume a @a svc_name that was previously suspended or has not yet
|
|
/// been resumed (e.g., a static service).
|
|
int resume (const ACE_TCHAR svc_name[]);
|
|
|
|
/**
|
|
* Suspend @a svc_name. Note that this will not unlink the service
|
|
* from the daemon if it was dynamically linked, it will mark it as
|
|
* being suspended in the Service Repository and call the @c suspend()
|
|
* member function on the appropriate ACE_Service_Object. A
|
|
* service can be resumed later on by calling the @c resume() member
|
|
* function...
|
|
*/
|
|
int suspend (const ACE_TCHAR svc_name[]);
|
|
|
|
/// Totally remove @a svc_name from the daemon by removing it
|
|
/// from the ACE_Reactor, and unlinking it if necessary.
|
|
int remove (const ACE_TCHAR svc_name[]);
|
|
|
|
/**
|
|
* Using the supplied name, finds and (if needed) returns a pointer to a
|
|
* static service descriptor. Returns 0 for success and -1 for failure
|
|
*/
|
|
int find_static_svc_descriptor (const ACE_TCHAR* name,
|
|
ACE_Static_Svc_Descriptor **ssd = 0) const;
|
|
|
|
struct Processed_Static_Svc
|
|
{
|
|
Processed_Static_Svc (const ACE_Static_Svc_Descriptor *);
|
|
~Processed_Static_Svc (void);
|
|
ACE_TCHAR * name_;
|
|
const ACE_Static_Svc_Descriptor *assd_;
|
|
};
|
|
|
|
/// Get the current ACE_Service_Repository held by this object.
|
|
ACE_Service_Repository* current_service_repository (void);
|
|
|
|
protected:
|
|
|
|
int parse_args_i (int, ACE_TCHAR *argv[],
|
|
bool& ignore_default_svc_conf_file);
|
|
|
|
/**
|
|
* Performs an open without parsing command-line arguments. The @a
|
|
* logger_key indicates where to write the logging output, which is
|
|
* typically either a STREAM pipe or a socket address. If @a
|
|
* ignore_default_svc_conf_file is non-0 then the "svc.conf" file
|
|
* will not be added by default. If @a ignore_debug_flag is non-0
|
|
* then the application is responsible for setting the @c
|
|
* ACE_Log_Msg::priority_mask() appropriately. Returns number of
|
|
* errors that occurred on failure and 0 otherwise.
|
|
*/
|
|
int open_i (const ACE_TCHAR program_name[],
|
|
const ACE_TCHAR *logger_key = 0,
|
|
bool ignore_static_svcs = true,
|
|
bool ignore_default_svc_conf_file = false,
|
|
bool ignore_debug_flag = false);
|
|
|
|
/// Initialize the @c svc_conf_file_queue_ if necessary.
|
|
int init_svc_conf_file_queue (void);
|
|
|
|
/// Add the default statically-linked services to the
|
|
/// ACE_Service_Repository.
|
|
int load_static_svcs (void);
|
|
|
|
/// Process service configuration requests that were provided on the
|
|
/// command-line. Returns the number of errors that occurred.
|
|
int process_commandline_directives (void);
|
|
|
|
/// Process a static directive without also inserting its descriptor
|
|
/// the global table. This avoids multiple additions when processing
|
|
/// directives in non-global gestalts.
|
|
int process_directive_i (const ACE_Static_Svc_Descriptor &ssd,
|
|
bool force_replace = false);
|
|
|
|
#if (ACE_USES_CLASSIC_SVC_CONF == 1)
|
|
/// This is the implementation function that process_directives()
|
|
/// and process_directive() both call. Returns the number of errors
|
|
/// that occurred.
|
|
int process_directives_i (ACE_Svc_Conf_Param *param);
|
|
#else
|
|
/// Helper function to dynamically link in the XML Service Configurator
|
|
/// parser.
|
|
ACE_XML_Svc_Conf* get_xml_svc_conf (ACE_DLL &d);
|
|
#endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */
|
|
|
|
/// Dynamically link the shared object file and retrieve a pointer to
|
|
/// the designated shared object in this file.
|
|
int initialize_i (const ACE_Service_Type *sr, const ACE_TCHAR *parameters);
|
|
|
|
const ACE_Static_Svc_Descriptor* find_processed_static_svc (const ACE_TCHAR*);
|
|
void add_processed_static_svc (const ACE_Static_Svc_Descriptor *);
|
|
|
|
/// Performs the common initialization tasks for a new or previously
|
|
/// closed instance. Must not be virtual, as it is called from the
|
|
/// constructor.
|
|
int init_i (void);
|
|
|
|
protected:
|
|
|
|
/// Maintain a queue of services to be configured from the
|
|
/// command-line.
|
|
typedef ACE_Unbounded_Queue<ACE_TString> ACE_SVC_QUEUE;
|
|
typedef ACE_Unbounded_Queue_Iterator<ACE_TString> ACE_SVC_QUEUE_ITERATOR;
|
|
|
|
/// Maintain a set of the statically linked service descriptors.
|
|
typedef ACE_Unbounded_Set<ACE_Static_Svc_Descriptor *>
|
|
ACE_STATIC_SVCS;
|
|
|
|
typedef ACE_Unbounded_Set_Iterator<ACE_Static_Svc_Descriptor *>
|
|
ACE_STATIC_SVCS_ITERATOR;
|
|
|
|
typedef ACE_Unbounded_Set<Processed_Static_Svc *>
|
|
ACE_PROCESSED_STATIC_SVCS;
|
|
|
|
typedef ACE_Unbounded_Set_Iterator<Processed_Static_Svc *>
|
|
ACE_PROCESSED_STATIC_SVCS_ITERATOR;
|
|
|
|
friend class ACE_Dynamic_Service_Base;
|
|
friend class ACE_Service_Object;
|
|
friend class ACE_Service_Config;
|
|
friend class ACE_Service_Config_Guard;
|
|
|
|
protected:
|
|
|
|
/// Do we own the service repository instance, or have only been
|
|
/// given a ptr to the singleton?
|
|
bool svc_repo_is_owned_;
|
|
|
|
/// Repository size is necessary, so that we can close (which may
|
|
/// destroy the repository instance), and then re-open again.
|
|
size_t svc_repo_size_;
|
|
|
|
/// Keep track of the number of times the instance has been
|
|
/// initialized (opened). "If so, we can't allow <yyparse> to be called since
|
|
/// it's not reentrant" is the original motivation, but that does not seem
|
|
/// to be the case anymore. This variable is incremented by the
|
|
/// <ACE_Service_Gestalt::open> method and decremented by the
|
|
/// <ACE_Service_Gestalt::close> method.
|
|
int is_opened_;
|
|
|
|
/// Indicates where to write the logging output. This is typically
|
|
/// either a STREAM pipe or a socket
|
|
const ACE_TCHAR *logger_key_;
|
|
|
|
/// Should we avoid loading the static services?
|
|
bool no_static_svcs_;
|
|
|
|
/// Queue of services specified on the command-line.
|
|
ACE_SVC_QUEUE* svc_queue_;
|
|
|
|
/**
|
|
* Queue of svc.conf files specified on the command-line.
|
|
* @@ This should probably be made to handle unicode filenames...
|
|
*/
|
|
ACE_SVC_QUEUE* svc_conf_file_queue_;
|
|
|
|
/// The service repository to hold the services.
|
|
ACE_Service_Repository* repo_;
|
|
|
|
/// Repository of statically linked services.
|
|
ACE_STATIC_SVCS* static_svcs_;
|
|
|
|
/// Repository of statically linked services for which process
|
|
/// directive was called, but the service is not already a member of
|
|
/// the static_svcs_ list.
|
|
ACE_PROCESSED_STATIC_SVCS* processed_static_svcs_;
|
|
|
|
/// Support for intrusive reference counting
|
|
ACE_Atomic_Op<ACE_SYNCH_MUTEX, long> refcnt_;
|
|
|
|
public:
|
|
static void intrusive_add_ref (ACE_Service_Gestalt*);
|
|
static void intrusive_remove_ref (ACE_Service_Gestalt*);
|
|
|
|
}; /* class ACE_Service_Gestalt */
|
|
|
|
|
|
/**
|
|
* @class ACE_Service_Type_Dynamic_Guard
|
|
*
|
|
* @brief A forward service declaration guard.
|
|
*
|
|
* Helps to resolve an issue with hybrid services, i.e. dynamic
|
|
* services, accompanied by static services in the same DLL. Only
|
|
* automatic instances of this class are supposed to exist. Those are
|
|
* created during (dynamic) service initialization and serve to:
|
|
*
|
|
* (a) Ensure the service we are loading is ordered last in the
|
|
* repository, following any other services it may cause to register,
|
|
* as part of its own registration. This is a common case when
|
|
* loading dynamic services from DLLs - there are often static
|
|
* initializers, which register static services.
|
|
*
|
|
* (b) The SDG instance destructor detects if the dynamic service
|
|
* initialized successfully and "fixes-up" all the newly registered
|
|
* static services to hold a reference to the DLL, from which they
|
|
* have originated.
|
|
*/
|
|
class ACE_Export ACE_Service_Type_Dynamic_Guard
|
|
{
|
|
public:
|
|
ACE_Service_Type_Dynamic_Guard (ACE_Service_Repository &r,
|
|
ACE_TCHAR const *name);
|
|
|
|
~ACE_Service_Type_Dynamic_Guard (void);
|
|
|
|
private:
|
|
ACE_Service_Repository & repo_;
|
|
size_t repo_begin_;
|
|
ACE_TCHAR const * const name_;
|
|
|
|
#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
|
|
// FUZZ: disable check_for_ACE_Guard
|
|
ACE_Guard< ACE_Recursive_Thread_Mutex > repo_monitor_;
|
|
// FUZZ: enable check_for_ACE_Guard
|
|
#endif
|
|
};
|
|
|
|
|
|
ACE_END_VERSIONED_NAMESPACE_DECL
|
|
|
|
#if defined (__ACE_INLINE__)
|
|
#include "ace/Service_Gestalt.inl"
|
|
#endif /* __ACE_INLINE__ */
|
|
|
|
|
|
#include /**/ "ace/post.h"
|
|
|
|
#endif /* ACE_SERVICE_GESTALT_H */
|