//---------------------------------------------------------------------------- // // Copyright (C) Intel Corporation, 2007 - 2008. // // File: Options.cpp // // 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: //---------------------------------------------------------------------------- //------------------ // Includes //------------------ #include "Options.h" #include #include "TypeValidationsExtraction.h" #include "DataStructures.h" #include "CFParser.h" #include "ListParser.h" #include using namespace std; //------------------ // Defines //------------------ #define FILES "FILES" #define PORT "PORT" #define IP "IP" #define INET "INET" #define ZERO_TIME 0 //------------------ // Statics init //------------------ Options * Options::_instance = NULL; bool Options::_init = false; ACE_Mutex Options::_ctor_mutex; //---------------------------------------- // Options public functions implementation //---------------------------------------- /* * 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. */ STATUS Options::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) { STATUS status = STATUS_FAILURE; // init is set to false. if a construction is // performed successfully than init will become true if (Options::_instance == NULL) { // do not allow two constructions simultaneously Options::_ctor_mutex.acquire(); // do not allow more than one construction at all if (!_init) { Options::_instance = new Options(staticFileName, dynamicFileName, format_static_mandatory, format_static_optional, format_dynamic_mandatory, format_dynamic_optional); } Options::_ctor_mutex.release(); if (!_init) { ACE_ERROR ((MY_ERROR ACE_TEXT ("Creating Options instance failed.\n"))); delete Options::_instance; Options::_instance = NULL; return status; } } status = STATUS_SUCCESS; return status; } /* * Return pointer to singleton of Options. * Must be called only after createInstance was called. * Returns NULL if no such object exist. */ Options * Options::instance (void) { return Options::_instance; } /* * Default destructor. * If error occurs at any point that can not be recovered than * destruction is stopped and not all elements are deleted */ Options::~Options (void) { ACE_TString sectionName, elementName; auto_ptr hashOuterP_begin(_element_hash.beginOuters()); auto_ptr hashOuterP_end(_element_hash.endOuters()); if ((hashOuterP_begin.get() == NULL) || (hashOuterP_end.get() == NULL)) { return; } ElementHash::constOuterIter hashOuterIter = * hashOuterP_begin; for (; hashOuterIter != *hashOuterP_end; hashOuterIter++) { auto_ptr hashInnerIterP_begin (_element_hash.beginInners(hashOuterIter->first)); auto_ptr hashInnerIterP_end (_element_hash.endInners(hashOuterIter->first)); sectionName = hashOuterIter->first; // Do not exit, it may happen that next iteration will work if ((hashInnerIterP_begin.get() != NULL) && (hashInnerIterP_end.get() != NULL)) { ElementHash::constInnerIter hashInnerIter = * hashInnerIterP_begin; for (; hashInnerIter != *hashInnerIterP_end; hashInnerIter++) { elementName = hashInnerIter->first; deleteElementContent(sectionName, elementName); } } } _element_hash.cleanHash(); _temp_String_Hash.cleanHash(); } /* * Reads the static file and parses its elements. * After successful usage, the static elements may be received. * Returns STATUS_FAILURE on failure. * Returns STATUS_SUCCESS on success. */ STATUS Options::read_static_file(void) { STATUS status = STATUS_FAILURE; // Sanity check if (_static_config_file == NULL || _format_static_mandatory == NULL || _format_static_optional == NULL) { return status; } if (read_file(_static_config_file, _format_static_mandatory, _format_static_optional)) { return status; } if (read_all_external_files() == STATUS_FAILURE) { return status; } status = STATUS_SUCCESS; return status; } /* * 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 Options::read_dynamic_file(void) { int ret = 0; bool readConfigFile = false; bool readExternalFiles = false; // Sanity check if (_dynamic_config_file == NULL || _format_dynamic_mandatory == NULL || _format_dynamic_optional == NULL) { return STATUS_FAILURE; } ACE_stat fileStats; ACE_OS::stat(_dynamic_config_file, &fileStats); if (_lastModification != fileStats.st_mtime) { if (read_file(_dynamic_config_file, _format_dynamic_mandatory, _format_dynamic_optional) != STATUS_SUCCESS) { return STATUS_FAILURE; } _lastModification = fileStats.st_mtime; readConfigFile = true; } int externalFilesRead = read_all_external_files(); if (externalFilesRead == STATUS_FAILURE) { return STATUS_FAILURE; } if (externalFilesRead > 0) { readExternalFiles = true; } if (readConfigFile) { if (readExternalFiles) { ret = 2; } else { ret = 1; } } else { if (readExternalFiles) { ret = 3; } } return ret; } //---------------------------------------- // Options private functions implementation //---------------------------------------- /* * 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::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) : _lastModification(ZERO_TIME), _format_static_mandatory(), _format_static_optional(), _format_dynamic_mandatory(), _format_dynamic_optional() { if ( (staticFileName == NULL) || (dynamicFileName == NULL) ) { return; } if ( (format_static_mandatory == NULL) || (format_static_optional == NULL) || (format_dynamic_mandatory == NULL) || (format_dynamic_optional == NULL) ) { return; } if ((ACE_OS::strlen(staticFileName) <= MAXPATHLEN + 1) || (ACE_OS::strlen(dynamicFileName) <= MAXPATHLEN + 1)) { ACE_OS::strcpy (this->_static_config_file, staticFileName); ACE_OS::strcpy (this->_dynamic_config_file, dynamicFileName); } else { return; } _format_static_mandatory = format_static_mandatory; _format_static_optional = format_static_optional; _format_dynamic_mandatory = format_dynamic_mandatory; _format_dynamic_optional = format_dynamic_optional; _init = true; } /* * 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 Options::read_file(const ACE_TCHAR * fileName, const Format * format_mandatory, const Format * format_optional) { STATUS status = STATUS_FAILURE; ACE_GUARD_RETURN(ACE_Recursive_Thread_Mutex, locker1, _mutex, STATUS_FAILURE); // Sanity check after mutex if (fileName == NULL || format_mandatory == NULL || format_optional == NULL) { return status; } CF_Parser parser; if (parser.parseToCanonicalStringHash(fileName, _temp_String_Hash) != PARSER_STATUS_SUCCESS) { return status; } if (build_element_hash(format_mandatory, format_optional) != STATUS_SUCCESS) { return status; } // Finished building the hash. // Now it should be checked that all the mandatory values were entered if (checkFormat(format_mandatory, true) != STATUS_SUCCESS) { return status; } if (checkFormat(format_optional, false) != STATUS_SUCCESS) { return status; } status = STATUS_SUCCESS; return status; } /* * 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 Options::build_element_hash(const Format * mandatory_format, const Format * optional_format) { STATUS status = STATUS_FAILURE; if (mandatory_format == NULL || optional_format == NULL) { return status; } ACE_TString sectionName, elementName, elementValue; Element_Type_Enum * elementType = NULL; ACE_TStringHash::constInnerIter hashInnerIter; ACE_TStringHash::constOuterIter hashOuterIter; auto_ptr hashOuterP_begin(_temp_String_Hash.beginOuters()); auto_ptr hashOuterP_end(_temp_String_Hash.endOuters()); if ((hashOuterP_begin.get() == NULL) || (hashOuterP_end.get() == NULL)) { return status; } hashOuterIter = * hashOuterP_begin; for (; hashOuterIter != *hashOuterP_end; hashOuterIter++) { auto_ptr hashInnerIterP_begin (_temp_String_Hash.beginInners(hashOuterIter->first)); auto_ptr hashInnerIterP_end (_temp_String_Hash.endInners(hashOuterIter->first)); if ((hashInnerIterP_begin.get() == NULL) || (hashInnerIterP_end.get() == NULL)) { return status; } hashInnerIter = * hashInnerIterP_begin; for (; hashInnerIter != *hashInnerIterP_end; hashInnerIter++) { sectionName = hashOuterIter->first; elementName = hashInnerIter->first; elementValue= hashInnerIter->second; // obtain element type if (obtainElementType(mandatory_format, optional_format, sectionName, elementName, &elementType) != STATUS_SUCCESS) { return status; } if (addToElementHash(sectionName, elementName, elementType->getElementType(), elementValue) != STATUS_SUCCESS) { return status; } } } // Clean up temp hash - there were no New's in it. Can simply clear hash _temp_String_Hash.cleanHash(); status = STATUS_SUCCESS; return status; } /* * 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 Options::addToElementHash(const ACE_TString §ionName, const ACE_TString &elementName, const ELEMENT_TYPES_ENUM &elemType, ACE_TString &elementValue) { STATUS status = STATUS_FAILURE; //Authentication_Param authParam; LogMasks mask; time_t timeVal; URL_Wrapper * mc_data = NULL; MCList * mc_list = NULL; ServerData * as_data = NULL; AuthServerHash * as_hash = NULL; // check if in FILE section ACE_TString sectionNameUpper = toUpper(sectionName); if (sectionNameUpper.compare(FILES) == STATUS_SUCCESS) { ACE_TString fullFileName; fullFileName += absolutePath; fullFileName += elementValue; if (addSingleElement(sectionName, elementName, fullFileName) != STATUS_SUCCESS) { return status; } status = STATUS_SUCCESS; return status; } switch(elemType) { case BOOL_TYPE: bool cond; if (validateAndGetElement(elementValue, cond) != STATUS_SUCCESS) { ACE_ERROR ((MY_ERROR ACE_TEXT ("Invalid parameter: %s. Must be boolean.\n"), elementValue.c_str())); return status; } if (addSingleElement(sectionName, elementName, cond) != STATUS_SUCCESS) { return status; } break; case UNSIGNED_INT_TYPE: unsigned int num; if (validateAndGetElement(elementValue, num) != STATUS_SUCCESS) { ACE_ERROR ((MY_ERROR ACE_TEXT ("Invalid parameter: %s. Must be unsigned int.\n"), elementValue.c_str())); return status; } if (addSingleElement(sectionName, elementName, num) != STATUS_SUCCESS) { return status; } break; case STRING_TYPE: if (addSingleElement(sectionName, elementName, elementValue) != STATUS_SUCCESS) { return status; } break; case PORT_TYPE: unsigned short port; if ((validateAndGetElement(elementValue, port) != STATUS_SUCCESS) || (validatePort(port) != STATUS_SUCCESS)) { ACE_ERROR ((MY_ERROR ACE_TEXT ("Invalid parameter: %s. Must be unsigned short.\n"), elementValue.c_str())); return status; } if (addSingleElement(sectionName, elementName, port) != STATUS_SUCCESS) { return status; } // try to add INET if possible /*if (addINET(sectionName, elementName, true) != STATUS_SUCCESS) { return status; }*/ break; case LOG_LEVELS_TYPE: unsigned long maskVal; if (validateAndGetElement(elementValue, mask) != STATUS_SUCCESS) { ACE_ERROR ((MY_ERROR ACE_TEXT ("Invalid log level: %s.\n"), elementValue.c_str())); return status; } maskVal = mask.getMask(); if (addSingleElement(sectionName, elementName, maskVal) != STATUS_SUCCESS) { return status; } break; case TIME_T_TYPE: unsigned int temp; if (validateAndGetElement(elementValue, temp) != STATUS_SUCCESS) { ACE_ERROR ((MY_ERROR ACE_TEXT ("Invalid time type: %s.\n"), elementValue.c_str())); return status; } // Loss of information is not expected since the information is supposed to be short. // But this should be checked. timeVal = (time_t) temp; if (addSingleElement(sectionName, elementName, timeVal) != STATUS_SUCCESS) { return status; } break; case IP_TYPE: if (validateIP(elementValue) != STATUS_SUCCESS) { ACE_ERROR ((MY_ERROR ACE_TEXT ("Invalid host name: %s.\n"), elementValue.c_str())); return status; } if (addSingleElement(sectionName, elementName, elementValue) != STATUS_SUCCESS) { return status; } // try to add INET if possible /*if (addINET(sectionName, elementName, false) != STATUS_SUCCESS) { return status; }*/ break; case MC_LIST_TYPE: mc_list = getValueChangable(sectionName.c_str(), sectionName.c_str()); if (mc_list == NULL) { return status; } if (mc_list->size() >= MAX_NOTIFICATIONS) { ACE_ERROR ((MY_DEBUG ACE_TEXT ("Notification list cannot exceed maximum size of %d entries. Skipping notification entry: %s\n"), MAX_NOTIFICATIONS , elementValue.c_str())); } else { mc_data = new URL_Wrapper(); if (mc_data == NULL) { return status; } if (validateAndGetElement(elementValue, *mc_data) != STATUS_SUCCESS) { ACE_ERROR ((MY_ERROR ACE_TEXT ("Skipping invalid notification entry: %s.\n"), elementValue.c_str())); delete mc_data; } else { TRY_ACQUIRE_WRITE_GUARD( ACE_RW_Thread_Mutex , lock, mc_list->guard()); if (lock.locked () == 0) { delete mc_data; ACE_ERROR_RETURN((MY_DEBUG ACE_TEXT ("Unable to acquire write mutex on notification list.\n")), status); } mc_list->push_back(mc_data); } } break; case AUTHERIZED_SERVERS_LIST_TYPE: as_data = new ServerData(); if (as_data == NULL) { return status; } if (validateAndGetElement(elementValue, *as_data) != STATUS_SUCCESS) { ACE_ERROR ((MY_ERROR ACE_TEXT ("Skipping invalid authorized server entry: %s\n"), elementValue.c_str())); delete as_data; } else { as_hash = getValueChangable(sectionName.c_str(), sectionName.c_str()); if (as_hash == NULL) { delete as_data; return status; } // Element value is intentionally inserted here. // This means that the TESTED host:port are entered as the key in the hash, // while the value holds the needed data about them, including the relevant INET TRY_ACQUIRE_WRITE_GUARD( ACE_RW_Thread_Mutex , lock, as_hash->guard()); if (lock.locked () == 0) { delete as_data; ACE_ERROR_RETURN((MY_DEBUG ACE_TEXT ("Unable to acquire write mutex on authorized servers hash.\n")), status); } as_hash->insert(make_pair(elementValue, as_data)); } break; default: return status; break; } 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 Options::addINET(const ACE_TString §ionName, // const ACE_TString &elementName, // bool isPort) //{ // STATUS status = STATUS_FAILURE; // // // Check to see if this is indeed a port and if there is an ip corresponding to it yet // // if there is, also add an INET object // ACE_TString addition, otherAddition, IPName, IP2Name,PortName,otherAddition2; // ACE_TString ipv4 = IPv4; // ACE_TString ipv6 = IPv6; // if (isPort) // { // /* // if ((elementName.substr(elementName.length() - ipv4.length())).compare(ipv4) == 0) // otherAddition = IPv4; // else if ((elementName.substr(elementName.length() - ipv6.length())).compare(ipv6) == 0) // otherAddition = IPv6; // else*/ // addition = PORT; // otherAddition = IPv4; // otherAddition2 = IPv6; // } // else // { // if ((elementName.substr(elementName.length() - ipv4.length())).compare(ipv4) == 0) // addition = IPv4; // else if ((elementName.substr(elementName.length() - ipv6.length())).compare(ipv6) == 0) // addition = IPv6; // else // addition = ""; // addition2 = ""; // otherAddition = PORT; // } // // if (elementName.length() - addition.length() < 0) // { // return status; // } // if ((!addition.is_empty()) && (!otherAddition.is_empty())) // { // ACE_TString baseName = elementName.substr(STATUS_SUCCESS, elementName.length() - addition.length()); // ACE_TString otherName = baseName; // otherName += otherAddition; // if (_element_hash.hasInner(sectionName, otherName)) // { // ACE_INET_Addr address; // IPName = baseName; // IPName += IPv4; // IP2Name = baseName; // IP2Name += IPv6; // PortName = baseName; // PortName += PORT; // // const unsigned short &port = *getValue(sectionName.c_str(), PortName.c_str()); // const ACE_TString &ipv4 = *getValue(sectionName.c_str(), IPName.c_str()); // const ACE_TString &ipv6 = *getValue(sectionName.c_str(), IP2Name.c_str()); // if (address.set(port, ipv4.c_str()) != STATUS_SUCCESS) // { // return status; // } // if (addSingleElement(sectionName, baseName + INET4, address) != STATUS_SUCCESS) // { // return status; // } // if (address.set(port, ipv6.c_str()) != STATUS_SUCCESS) // { // return status; // } // if (addSingleElement(sectionName, baseName + INET6, address) != STATUS_SUCCESS) // { // return status; // } // } // } // // status = STATUS_SUCCESS; // // return status; //} /* * 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 Options::checkFormat(const Format * format, bool isMandatory) { STATUS status = STATUS_FAILURE; if (format == NULL) { return status; } Format::constOuterIter formatIter; auto_ptr formatIterP_begin(format -> beginOuters()); auto_ptr formatIterP_end(format -> endOuters()); if ((formatIterP_begin.get() == NULL) || (formatIterP_end.get() == NULL)) { return status; } formatIter = * formatIterP_begin; for (; formatIter != *formatIterP_end; formatIter++) { if (!_element_hash.hasOuter(formatIter->first)) { if (isMandatory) { ACE_ERROR ((MY_ERROR ACE_TEXT ("Static config file is missing mandatory section: %s.\n"), formatIter->first.c_str())); return status; } else { _element_hash.addOuter(formatIter->first); } } auto_ptr formatInnerIterP_begin(format -> beginInners(formatIter->first)); auto_ptr formatInnerIterP_end(format -> endInners(formatIter->first)); if ((formatInnerIterP_begin.get() == NULL) || (formatInnerIterP_end.get() == NULL)) { return status; } Format::constInnerIter formatInnerIter = * formatInnerIterP_begin; for (; formatInnerIter != *formatInnerIterP_end; formatInnerIter++) { if (!_element_hash.hasInner(formatIter->first, formatInnerIter->first)) { if (isMandatory) { ACE_ERROR ((MY_ERROR ACE_TEXT ("Static config file is missing mandatory element: %s in section: %s.\n"), formatInnerIter->first.c_str(), formatIter->first.c_str())); return status; } else { Element_Type_Enum_and_Default_Val * element = (Element_Type_Enum_and_Default_Val *) formatInnerIter ->second; ACE_TString typeVal = element->getTypeVal(); if (addToElementHash(formatIter->first, formatInnerIter->first, element->getElementType(), typeVal) != STATUS_SUCCESS) { ACE_ERROR ((MY_ERROR ACE_TEXT ("Default element used for element: %s in section: %s is incompatible with expected type.\n"), formatInnerIter->first.c_str(), formatIter->first.c_str())); return status; } } } } } status = STATUS_SUCCESS; return status; } /* * 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 Options::read_all_external_files() { int ret = 0; ElementHash::constInnerIter hashInnerIter; Element_Type_Enum * elementType = NULL; // Iterate on Files section auto_ptr hashInnerIterP_begin(_element_hash.beginInners(FILES)); auto_ptr hashInnerIterP_end(_element_hash.endInners(FILES)); if ((hashInnerIterP_begin.get() == NULL) || (hashInnerIterP_end.get() == NULL)) { return STATUS_FAILURE; } hashInnerIter = * hashInnerIterP_begin; for (; hashInnerIter != *hashInnerIterP_end; hashInnerIter++) { const ACE_TString * fileName = getValue(FILES, hashInnerIter->first.c_str()); if (fileName == NULL) { return STATUS_FAILURE; } ACE_stat fileStats; ACE_OS::stat(fileName->c_str(), &fileStats); map< ACE_TString, time_t, ACE_TString_compare_no_toUpper >::const_iterator iter = _extModifTimeMap.find(*fileName); // If it is the first time, then the file name is not in the map, and should // be entered with the proper value. // If it is, than its last changed date should be checked. if ((iter == _extModifTimeMap.end()) || (_extModifTimeMap[*fileName] != fileStats.st_mtime)) { if (obtainElementType(_format_static_mandatory, _format_static_optional, FILES, hashInnerIter->first, &elementType) != STATUS_SUCCESS) { return STATUS_FAILURE; } List_Parser parser; vector vec; if (parser.parseItemList(fileName -> c_str(), vec) != PARSER_STATUS_SUCCESS) { return STATUS_FAILURE; } STATUS tempStat; if ((tempStat = build_element_hash_ext_from_vector(vec, hashInnerIter->first, elementType)) != STATUS_SUCCESS) { if (tempStat == STATUS_LOCK_FAILURE) { continue; } return STATUS_FAILURE; } // If reading the file was successful, than set a new change time. _extModifTimeMap[*fileName] = fileStats.st_mtime; ++ret; } } return ret; } /* * 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 Options::build_element_hash_ext_from_vector(const vector &vec, const ACE_TString §ionName, Element_Type_Enum * elementType) { STATUS status = STATUS_FAILURE; if (elementType == NULL) { return status; } // First, delete the previous element that may exist in that location if (!_element_hash.hasInner(sectionName, sectionName)) { BaseElement * elem; switch(elementType->getElementType()) { case MC_LIST_TYPE: elem = new Element(); if (elem == NULL) { return status; } break; case AUTHERIZED_SERVERS_LIST_TYPE: elem = new Element(); if (elem == NULL) { return status; } break; default: return status; } _element_hash.addInner(sectionName, sectionName, elem); } else // If it does exist, than clear its values // (since every time we read the external files again, we start from scratch). { switch(elementType->getElementType()) { case MC_LIST_TYPE: { MCList * mc_list = NULL; mc_list = getValueChangable(sectionName.c_str(), sectionName.c_str()); if (mc_list == NULL) { return status; } TRY_ACQUIRE_WRITE_GUARD( ACE_RW_Thread_Mutex , lock, mc_list->guard()); if (lock.locked () == 0) { ACE_ERROR_RETURN((MY_DEBUG ACE_TEXT ("Unable to acquire write mutex on notification list.\n")), STATUS_LOCK_FAILURE); } mc_list->clearList(); } break; case AUTHERIZED_SERVERS_LIST_TYPE: { AuthServerHash * authHash = NULL; authHash = getValueChangable(sectionName.c_str(), sectionName.c_str()); if (authHash == NULL) { return status; } TRY_ACQUIRE_WRITE_GUARD( ACE_RW_Thread_Mutex , lock, authHash->guard()); if (lock.locked () == 0) { ACE_ERROR_RETURN((MY_DEBUG ACE_TEXT ("Unable to acquire write mutex on authorized servers hash.\n")), STATUS_LOCK_FAILURE); } authHash->clearHash(); } break; default: return status; } } ACE_TString elementName, elementValue; vector< ACE_TString >::const_iterator iter; for (iter = vec.begin(); iter != vec.end(); iter++) { // The element name does not matter => just leave it blank elementValue = *iter; if (addToElementHash(sectionName, elementName, elementType->getElementType(), elementValue) != STATUS_SUCCESS) { return status; } } status = STATUS_SUCCESS; return status; } /* * 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 Options::obtainElementType(const Format * mandatory_format, const Format * optional_format, const ACE_TString §ionName, const ACE_TString &elementName, Element_Type_Enum ** elementType) { STATUS status = STATUS_FAILURE; if (mandatory_format == NULL || optional_format == NULL || elementType == NULL) { return status; } // Check if element is in mandatory first if (mandatory_format -> hasInner(sectionName, elementName)) { mandatory_format -> getValue(sectionName, elementName, elementType); } // Now check with optional else { if (optional_format -> hasInner(sectionName, elementName)) { optional_format -> getValue(sectionName, elementName, elementType); } // Not in optional or mandatory - considered an error else { ACE_ERROR ((MY_ERROR ACE_TEXT ("Element: %s in section: %s does not appear in accepted formats\n"), elementName.c_str(), sectionName.c_str())); return status; } } status = STATUS_SUCCESS; return status; } /* * 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 Options::deleteElement(const ACE_TString §ionName, const ACE_TString &elementName) { STATUS status = STATUS_FAILURE; if (deleteElementContent(sectionName, elementName) != STATUS_SUCCESS) { return status; } if (_element_hash.deleteElement(sectionName, elementName) != STATUS_SUCCESS) { return status; } status = STATUS_SUCCESS; return status; } /* * 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 Options::deleteElementContent(const ACE_TString §ionName, const ACE_TString &elementName) { STATUS status = STATUS_FAILURE; BaseElement * base = NULL; if ((_element_hash.getValue(sectionName, elementName, &base) != STATUS_SUCCESS) || (base == NULL)) { return status; } delete base; status = STATUS_SUCCESS; return status; }