414 lines
14 KiB
C++

//----------------------------------------------------------------------------
//
// 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 <ace/SString.h>
#include <ace/Synch.h>
#include <ace/INET_Addr.h>
#include <ace/Guard_T.h>
#include <vector>
#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<ACE_TString>("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<MCList>("MCSubscribersList", "MCSubscribersList");
*
* Uses a mutex so no return of values will be done while ctor the Options
*/
template <class T>
const T * getValue(const ACE_TCHAR * section, const ACE_TCHAR * element) {
T * ret = NULL;
Element<T> * 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<T> * >(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 <class T>
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<T> * elem = dynamic_cast< Element<T> * >(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 &sectionName,
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 <class T>
STATUS addSingleElement(const ACE_TString &sectionName, const ACE_TString &elementName, T &elemValue)
{
STATUS status = STATUS_FAILURE;
if (!_element_hash.hasInner(sectionName, elementName))
{
Element<T> * element = new Element<T>(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<T>(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 &sectionName,
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<ACE_TString> &vec,
const ACE_TString &sectionName,
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 &sectionName, 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 &sectionName, 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 &sectionName, 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 &sectionName, 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 */