//---------------------------------------------------------------------------- // // Copyright (C) Intel Corporation, 2007 - 2008. // // File: Options.h // // Contents: Parses a static and dynamic configuration file. // Provides access to its elements, with the actual type // of the element obtained from the configuration file. // // Notes: //---------------------------------------------------------------------------- #ifndef OPTIONS_H #define OPTIONS_H //------------------ // Includes //------------------ #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ #include #include #include #include #include #include "ConfigFormat.h" #include "ConfigElement.h" //------------------ // Classes //------------------ /************************************************************* * * Singleton class that consolidates all Options for the MPS. * Parses a static and dynamic configuration file. * Provides access to its elements, with the actual type * of the element obtained from the configuration file. * *************************************************************/ class Options { public: //------------------ // Public Functions //------------------ /* * Creates the Options Singleton. * Requires the filenames to parse, and the type of formats that are * allowed and needed. * staticFileName - Pointer to the name of the static file to parse. * dynamicFileName - Pointer to the name of the dynamic file to parse. * format_static_mandatory - Pointer to the static mandatory format. * format_static_optional - Pointer to the static optional format. * format_dynamic_mandatory - Pointer to the dynamic mandatory format. * format_dynamic_optional - Pointer to the dynamic optional format. * Returns STATUS_FAILURE on failure. * Returns STATUS_SUCCESS on success. */ static STATUS createInstance(const ACE_TCHAR * staticFileName, const ACE_TCHAR * dynamicFileName, const Format * format_static_mandatory, const Format * format_static_optional, const Format * format_dynamic_mandatory, const Format * format_dynamic_optional); /* * Return Singleton of Options. * Must be called only after createInstance was called. * On error throws MPSConfigurationException. */ static Options * instance (void); /* * Default destructor. * If error occurs at any point that can not be recovered than * destruction is stopped and not all elements are deleted */ ~Options (void); /* * Reads the static files and parses its elements. * After successful usage, the static elements may be received. * Returns STATUS_FAILURE on failure. * Returns STATUS_SUCCESS on success. */ STATUS read_static_file(); /* * Reads the dynamic files and parses its elements. * After successful usage, the dynamic elements may be received. * Returns -1 on failure. * Returns 0 if none of the files were changed, and therefore not read. * Returns 1 on read of only the dynamic config file. * Returns 2 on read of the dynamic config file and at least one of the external files. * Returns 3 on read of at least one of the external files. (no read of the dynamic config file). */ int read_dynamic_file(void); // The following functions are implemented in the header file: /* * Indicates if the class was init successfully. * Returns true if it was init successfully. * Returns false otherwise. */ bool isInit() { return _init; } /* * Returns a const pointer to the value of the element in the given section and element name. * section - An ACE_TCHAR pointer to the section name from which to retrieve the value. * element - An ACE_TCHAR pointer to the element name (in the above section) * from which to retrieve the value. * Example for a regular call: * ACE_TString ip = getValue("Network", "AMTListenIP"); * * If an element was added to the Files section, than the data structure which holds * the data contained in the referenced file has the same section and element name * as was stated in the Files section. * Example: * if in config file: * [Files] * MCSubscribersList = MCSubscribersList.config * than to obtain the data: * MCList mcList = getValue("MCSubscribersList", "MCSubscribersList"); * * Uses a mutex so no return of values will be done while ctor the Options */ template const T * getValue(const ACE_TCHAR * section, const ACE_TCHAR * element) { T * ret = NULL; Element * elem; ACE_GUARD_REACTION(ACE_Recursive_Thread_Mutex, locker1, _mutex, return NULL); BaseElement * base = NULL; if (_element_hash.getValue(ACE_TString(section), ACE_TString(element), &base) != STATUS_SUCCESS) { ACE_DEBUG((MY_ERROR ACE_TEXT("Element %s is not found.\n"), element)); return NULL; } elem = dynamic_cast< Element * >(base); if (elem != NULL) { ret = elem->getElement(); } else { ACE_DEBUG((MY_ERROR ACE_TEXT("Element %s is NULL.\n"), element)); return NULL; } return ret; } /* * Returns a pointer to the value of the element in the given section and element name * On error returns NULL * Uses a mutex so no return of values will be done while ctor the Options */ template T * getValueChangable(const ACE_TCHAR * section, const ACE_TCHAR * element) { T * ret = NULL; ACE_GUARD_REACTION(ACE_Recursive_Thread_Mutex, locker1, _mutex, return NULL); BaseElement * base = NULL; if (_element_hash.getValue(ACE_TString(section), ACE_TString(element), &base) == -1) { return ret; } Element * elem = dynamic_cast< Element * >(base); if (elem != NULL) { ret = elem->getElement(); } return ret; } private: //------------------ // Private Typedefs //------------------ typedef Canonical_Hash < ACE_TString, ACE_TString, BaseElement *, ACE_TString_compare, ACE_TString_compare > ElementHash; typedef Canonical_Hash < ACE_TString, ACE_TString, ACE_TString, ACE_TString_compare, ACE_TString_compare > ACE_TStringHash; //------------------ // Private functions //------------------ /* * Default constructor. * Is private so it won't be called outside. * Does nothing */ Options():_lastModification(), _format_static_mandatory(), _format_static_optional(), _format_dynamic_mandatory(), _format_dynamic_optional(){} // The following functions are implemented in the source file: /* * Constructor. * Requires the filenames to parse, and the type of formats that are * allowed and needed. * staticFileName - Pointer to the name of the static file to parse. * dynamicFileName - Pointer to the name of the dynamic file to parse. * format_static_mandatory - Pointer to the static mandatory format. * format_static_optional - Pointer to the static optional format. * format_dynamic_mandatory - Pointer to the dynamic mandatory format. * format_dynamic_optional - Pointer to the dynamic optional format. */ Options(const ACE_TCHAR * staticFileName, const ACE_TCHAR * dynamicFileName, const Format * format_static_mandatory, const Format * format_static_optional, const Format * format_dynamic_mandatory, const Format * format_dynamic_optional); /* * Reads the file and parses its elements according to the formats given. * This is the main bulk function, after which the static file is parsed. * fileName - filename to be read * format_mandatory - mandatory format to use * format_optional - optional format to use * Returns STATUS_FAILURE on failure. * Returns STATUS_SUCCESS on success. */ STATUS read_file(const ACE_TCHAR * fileName, const Format * format_mandatory, const Format * format_optional); /* * Builds the element hash according to previously entered parsing data to the * string hash. * Builds it according to the given formats - * If an element parsed is missing from the mandatory and optional format than an error is ensued. * Returns STATUS_FAILURE on failure. * Returns STATUS_SUCCESS on success. */ STATUS build_element_hash(const Format * mandatory_format, const Format * optional_format); /* * Adds an element to the element hash, putting it in the correct section, and element in the section, * and providing it with the correct type (using elemType). The element value is obtained from * elementValue. * sectionName - section to put the element in * elementName - element name in the section to put the element in * elemType - the type of the element according which the needed type for the element is decided. * elementValue- the value of the element. * Returns STATUS_FAILURE on failure. * Returns STATUS_SUCCESS on success. */ STATUS addToElementHash(const ACE_TString §ionName, const ACE_TString &elementName, const ELEMENT_TYPES_ENUM &elemType, ACE_TString &elementValue); /* * Adds a single element with the given sectionName, elementName and elemValue to the hash. * If it already exists, than its value is changed. * sectionName - section to put the element in * elementName - element name in the section to put the element in * elementValue- the value of the element. * Returns STATUS_FAILURE on failure. * Returns STATUS_SUCCESS on success. */ template STATUS addSingleElement(const ACE_TString §ionName, const ACE_TString &elementName, T &elemValue) { STATUS status = STATUS_FAILURE; if (!_element_hash.hasInner(sectionName, elementName)) { Element * element = new Element(elemValue); if (element == NULL) { return status; } _element_hash.addInner(sectionName, elementName, element); } // Has element, change it then with the new value. else { T * oldValue = getValueChangable(sectionName.c_str(), elementName.c_str()); if (oldValue == NULL) { return status; } *oldValue = elemValue; } status = STATUS_SUCCESS; return status; } /* * Adds an INET type element to the hash according to the given sectionName and elementName. * isPort indicates if the given element indicates a port or an ip, by which the indication * of the INET is recognized. It may be that an INET object is not currently possible to add, in which * case, this is not considered as error (such as in the example that only the port is known) * Returns STATUS_FAILURE on failure. * Returns STATUS_SUCCESS on success. */ /*STATUS addINET(const ACE_TString §ionName, const ACE_TString &elementName, bool isPort);*/ /* * Checks that the format given (mandatory or optional set by isMandatory), fits the inner hash. * i.e: if the hash holding all the data has all the elements it is required off according to * the formats (if it does not hold an element that is in the optional format, than its * default value is added) * This is done after the inner hash is filled. * Returns STATUS_FAILURE on failure. * Returns STATUS_SUCCESS on success. */ STATUS checkFormat(const Format * format, bool isMandatory); /* * Reads and parses all external files, and enters them to the element hash according * their data. * Returns -1 on failure. * Otherwise, returns the amount of files that were read (files that were changed). */ int read_all_external_files(); /* * Adds an element to the element hash according to an external file which was parsed to a vector. * The vector reference is the vector which holds the parsed information. * The section name indicates which section the new element is supposed to be in. * The element type indicates the needed element type * Note: A single element (in the final hash) is provided per file (usually a list or a hash) * Returns STATUS_FAILURE on failure. * Returns STATUS_SUCCESS on success. */ STATUS build_element_hash_ext_from_vector(const vector &vec, const ACE_TString §ionName, Element_Type_Enum * elementType); /* * Adds an element to the element hash according to an external file which was parsed to a canonical hash. * The section name indicates which section the new element is supposed to be in. * The element type indicates the needed element type * Note: A single element is provided per file (usually a list or a hash) * Returns STATUS_FAILURE on failure. * Returns STATUS_SUCCESS on success. */ //STATUS build_element_hash_ext_from_hash(const ACE_TString §ionName, Element_Type_Enum * elementType); /* * Obtains a single elements' type according to the given formats. Puts a pointer to the * element type in **elementType. * Returns STATUS_FAILURE on failure. * Returns STATUS_SUCCESS on success. */ STATUS obtainElementType(const Format * mandatory_format, const Format * optional_format, const ACE_TString §ionName, const ACE_TString &elementName, Element_Type_Enum ** elementType); /* * Deletes an element from the element hash (deleting the element itself and removing * it from the canonical element hash). * Returns STATUS_FAILURE on failure. * Returns STATUS_SUCCESS on success. */ STATUS deleteElement(const ACE_TString §ionName, const ACE_TString &elementName); /* * Deletes an element from the element hash (deleting the element itself but not removing * it from the canonical element hash). * Returns STATUS_FAILURE on failure. * Returns STATUS_SUCCESS on success. */ STATUS deleteElementContent(const ACE_TString §ionName, const ACE_TString &elementName); //-------------- // Data Members //-------------- // Options Singleton instance. static Options * _instance; static bool _init; static ACE_Mutex _ctor_mutex; ACE_Recursive_Thread_Mutex _mutex; time_t _lastModification; const Format * _format_static_mandatory; const Format * _format_static_optional; const Format * _format_dynamic_mandatory; const Format * _format_dynamic_optional; ElementHash _element_hash; ACE_TStringHash _temp_String_Hash; map< ACE_TString, time_t, ACE_TString_compare_no_toUpper > _extModifTimeMap; ACE_TCHAR _static_config_file[MAXPATHLEN + 1]; ACE_TCHAR _dynamic_config_file[MAXPATHLEN + 1]; }; #endif /* OPTIONS_H */