blob: 81d10b2dd18f9e8c0cad0bd3ff6083fe4614d87b [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "CacheXmlParser.hpp"
#include <chrono>
#include <geode/PoolFactory.hpp>
#include <geode/PoolManager.hpp>
#include <geode/internal/chrono/duration.hpp>
#include "AutoDelete.hpp"
#include "CacheImpl.hpp"
#include "CacheRegionHelper.hpp"
#if defined(_WIN32)
#include <windows.h>
#else
#include <dlfcn.h>
#endif
namespace apache {
namespace geode {
namespace client {
namespace impl {
void* getFactoryFunc(const std::string& lib, const std::string& funcName);
} // namespace impl
namespace {
using apache::geode::client::impl::getFactoryFunc;
std::vector<std::pair<std::string, int>> parseEndPoints(
const std::string& str) {
std::vector<std::pair<std::string, int>> endPoints;
std::string::size_type start = 0;
std::string::size_type pos = str.find_first_of(',');
while (std::string::npos != pos) {
const std::string endPoint(str.substr(start, pos - start));
const std::string::size_type split = endPoint.find_last_of(':');
if (std::string::npos == split) {
endPoints.push_back(std::pair<std::string, int>(endPoint, 0));
} else {
int port = 0;
try {
port = std::stoi(endPoint.substr(split + 1));
} catch (...) {
// NOP
}
endPoints.push_back(
std::pair<std::string, int>(endPoint.substr(0, split), port));
}
start = pos + 1;
pos = str.find_first_of(',', start);
}
return endPoints;
}
} // namespace
/////////////////XML Parser Callback functions////////////////////////
extern "C" void startElementSAX2Function(void* ctx, const xmlChar* name,
const xmlChar** atts) {
CacheXmlParser* parser = (CacheXmlParser*)ctx;
if (!parser) {
Log::error("CacheXmlParser::startElementSAX2Function:Parser is nullptr");
return;
}
if ((!parser->isCacheXmlException()) &&
(!parser->isIllegalStateException()) &&
(!parser->isAnyOtherException())) {
try {
auto uname =
reinterpret_cast<const char*>(const_cast<unsigned char*>(name));
if (std::strcmp(uname, parser->CACHE) == 0) {
parser->startCache(ctx, atts);
} else if (strcmp(uname, parser->CLIENT_CACHE) == 0) {
parser->startCache(ctx, atts);
} else if (strcmp(uname, parser->PDX) == 0) {
parser->startPdx(atts);
} else if (strcmp(uname, parser->REGION) == 0) {
parser->incNesting();
parser->startRegion(atts, parser->isRootLevel());
} else if (strcmp(uname, parser->ROOT_REGION) == 0) {
parser->incNesting();
parser->startRegion(atts, parser->isRootLevel());
} else if (strcmp(uname, parser->REGION_ATTRIBUTES) == 0) {
parser->startRegionAttributes(atts);
} else if (strcmp(uname, parser->REGION_TIME_TO_LIVE) == 0) {
} else if (strcmp(uname, parser->REGION_IDLE_TIME) == 0) {
} else if (strcmp(uname, parser->ENTRY_TIME_TO_LIVE) == 0) {
} else if (strcmp(uname, parser->ENTRY_IDLE_TIME) == 0) {
} else if (strcmp(uname, parser->EXPIRATION_ATTRIBUTES) == 0) {
parser->startExpirationAttributes(atts);
} else if (strcmp(uname, parser->CACHE_LOADER) == 0) {
parser->startCacheLoader(atts);
} else if (strcmp(uname, parser->CACHE_WRITER) == 0) {
parser->startCacheWriter(atts);
} else if (strcmp(uname, parser->CACHE_LISTENER) == 0) {
parser->startCacheListener(atts);
} else if (strcmp(uname, parser->PARTITION_RESOLVER) == 0) {
parser->startPartitionResolver(atts);
} else if (strcmp(uname, parser->PERSISTENCE_MANAGER) == 0) {
parser->startPersistenceManager(atts);
} else if (strcmp(uname, parser->PROPERTIES) == 0) {
} else if (strcmp(uname, parser->PROPERTY) == 0) {
parser->startPersistenceProperties(atts);
} else if (strcmp(uname, parser->POOL) == 0) {
parser->startPool(atts);
} else if (strcmp(uname, parser->LOCATOR) == 0) {
parser->startLocator(atts);
} else if (strcmp(uname, parser->SERVER) == 0) {
parser->startServer(atts);
} else {
throw CacheXmlException("XML:Unknown XML element \"" +
std::string(uname) + "\"");
}
} catch (const CacheXmlException& e) {
parser->setCacheXmlException();
std::string s = e.what();
parser->setError(s);
} catch (const IllegalStateException& ex) {
parser->setIllegalStateException();
std::string s = ex.what();
parser->setError(s);
} catch (const Exception& ex) {
parser->setAnyOtherException();
std::string s = ex.what();
parser->setError(s);
}
} // flag
}
extern "C" void endElementSAX2Function(void* ctx, const xmlChar* name) {
CacheXmlParser* parser = (CacheXmlParser*)ctx;
if (!parser) {
Log::error(
"Error occured while xml parsing: "
"CacheXmlParser:startElementSAX2Function:Parser is nullptr");
return;
}
if ((!parser->isCacheXmlException()) &&
(!parser->isIllegalStateException()) &&
(!parser->isAnyOtherException())) {
try {
auto uname =
reinterpret_cast<const char*>(const_cast<unsigned char*>(name));
if (strcmp(uname, parser->CACHE) == 0) {
parser->endCache();
} else if (strcmp(uname, parser->CLIENT_CACHE) == 0) {
parser->endCache();
} else if (strcmp(uname, parser->PDX) == 0) {
parser->endPdx();
} else if (strcmp(uname, parser->REGION) == 0) {
parser->endRegion(parser->isRootLevel());
parser->decNesting();
} else if (strcmp(uname, parser->ROOT_REGION) == 0) {
parser->endRegion(parser->isRootLevel());
parser->decNesting();
} else if (strcmp(uname, parser->REGION_ATTRIBUTES) == 0) {
parser->endRegionAttributes();
} else if (strcmp(uname, parser->REGION_TIME_TO_LIVE) == 0) {
parser->endRegionTimeToLive();
} else if (strcmp(uname, parser->REGION_IDLE_TIME) == 0) {
parser->endRegionIdleTime();
} else if (strcmp(uname, parser->ENTRY_TIME_TO_LIVE) == 0) {
parser->endEntryTimeToLive();
} else if (strcmp(uname, parser->ENTRY_IDLE_TIME) == 0) {
parser->endEntryIdleTime();
} else if (strcmp(uname, parser->EXPIRATION_ATTRIBUTES) == 0) {
} else if (strcmp(uname, parser->CACHE_LOADER) == 0) {
} else if (strcmp(uname, parser->CACHE_WRITER) == 0) {
} else if (strcmp(uname, parser->CACHE_LISTENER) == 0) {
} else if (strcmp(uname, parser->PARTITION_RESOLVER) == 0) {
} else if (strcmp(uname, parser->PERSISTENCE_MANAGER) == 0) {
parser->endPersistenceManager();
} else if (strcmp(uname, parser->PROPERTIES) == 0) {
} else if (strcmp(uname, parser->PROPERTY) == 0) {
} else if (strcmp(uname, parser->POOL) == 0) {
parser->endPool();
} else if (strcmp(uname, parser->LOCATOR) == 0) {
// parser->endLocator();
} else if (strcmp(uname, parser->SERVER) == 0) {
// parser->endServer();
} else {
throw CacheXmlException("XML:Unknown XML element \"" +
std::string(uname) + "\"");
}
} catch (CacheXmlException& e) {
parser->setCacheXmlException();
std::string s = e.what();
parser->setError(s);
} catch (IllegalStateException& ex) {
parser->setIllegalStateException();
std::string s = ex.what();
parser->setError(s);
} catch (Exception& ex) {
parser->setAnyOtherException();
std::string s = ex.what();
parser->setError(s);
}
} // flag
}
/**
* warningDebug:
* @ctxt: An XML parser context
* @msg: the message to display/transmit
* @...: extra parameters for the message display
*
* Display and format a warning messages, gives file, line, position and
* extra parameters.
*/
extern "C" void warningDebug(void*, const char* msg, ...) {
char logmsg[2048];
va_list args;
va_start(args, msg);
vsprintf(logmsg, msg, args);
va_end(args);
LOGWARN("SAX.warning during XML declarative client initialization: %s",
logmsg);
}
/**
* fatalErrorDebug:
* @ctxt: An XML parser context
* @msg: the message to display/transmit
* @...: extra parameters for the message display
*
* Display and format a fatalError messages, gives file, line, position and
* extra parameters.
*/
extern "C" void fatalErrorDebug(void* ctx, const char* msg, ...) {
char buf[1024];
va_list args;
va_start(args, msg);
CacheXmlParser* parser = (CacheXmlParser*)ctx;
vsprintf(buf, msg, args);
std::string stringMsg(buf);
parser->setParserMessage(parser->getParserMessage() + stringMsg);
va_end(args);
}
/////////////End of XML Parser Cackllback functions///////////////
///////////////static variables of the class////////////////////////
LibraryCacheLoaderFn CacheXmlParser::managedCacheLoaderFn = nullptr;
LibraryCacheListenerFn CacheXmlParser::managedCacheListenerFn = nullptr;
LibraryPartitionResolverFn CacheXmlParser::managedPartitionResolverFn = nullptr;
LibraryCacheWriterFn CacheXmlParser::managedCacheWriterFn = nullptr;
LibraryPersistenceManagerFn CacheXmlParser::managedPersistenceManagerFn =
nullptr;
//////////////////////////////////////////////////////////////////
CacheXmlParser::CacheXmlParser(Cache* cache)
: m_cacheCreation(nullptr),
m_nestedRegions(0),
m_config(nullptr),
m_parserMessage(""),
m_flagCacheXmlException(false),
m_flagIllegalStateException(false),
m_flagAnyOtherException(false),
m_flagExpirationAttribute(false),
m_poolFactory(nullptr),
m_cache(cache) {
static xmlSAXHandler saxHandler = {
nullptr, /* internalSubset */
nullptr, /* isStandalone */
nullptr, /* hasInternalSubset */
nullptr, /* hasExternalSubset */
nullptr, /* resolveEntity */
nullptr, /* getEntity */
nullptr, /* entityDecl */
nullptr, /* notationDecl */
nullptr, /* attributeDecl */
nullptr, /* elementDecl */
nullptr, /* unparsedEntityDecl */
nullptr, /* setDocumentLocator */
nullptr, /* startDocument */
nullptr, /* endDocument */
startElementSAX2Function, /* startElement */
endElementSAX2Function, /* endElement */
nullptr, /* reference */
nullptr, /* characters */
nullptr, /* ignorableWhitespace */
nullptr, /* processingInstruction */
nullptr, // commentDebug, /* comment */
warningDebug, /* xmlParserWarning */
fatalErrorDebug, /* xmlParserError */
nullptr, /* xmlParserError */
nullptr, /* getParameterEntity */
nullptr, /* cdataBlock; */
nullptr, /* externalSubset; */
XML_SAX2_MAGIC,
nullptr,
nullptr, /* startElementNs */
nullptr, /* endElementNs */
nullptr /* xmlStructuredErrorFunc */
};
m_saxHandler = saxHandler;
namedRegions = CacheImpl::getRegionShortcut();
}
void CacheXmlParser::parseFile(const char* filename) {
int res = 0;
res = xmlSAXUserParseFile(&this->m_saxHandler, this, filename);
if (res == -1) {
throw CacheXmlException("Xml file " + std::string(filename) + " not found");
}
handleParserErrors(res);
}
void CacheXmlParser::parseMemory(const char* buffer, int size) {
int res = 0;
res = xmlSAXUserParseMemory(&this->m_saxHandler, this, buffer, size);
if (res == -1) {
throw CacheXmlException("Unable to read buffer.");
}
handleParserErrors(res);
}
void CacheXmlParser::handleParserErrors(int res) {
if (res != 0) // xml file is not well-formed
{
char buf[256];
ACE_OS::snprintf(buf, 256, "Error code returned by xml parser is : %d ",
res);
Log::error(buf);
throw CacheXmlException("Xml file is not well formed. Error _stack: \n" +
std::string(this->m_parserMessage));
}
std::string temp = this->getError();
if (temp.empty()) {
Log::info("Xml file parsed successfully");
} else {
// well formed, but not according to our specs(dtd errors thrown manually)
if (this->m_flagCacheXmlException) {
throw CacheXmlException(temp);
} else if (this->m_flagIllegalStateException) {
throw IllegalStateException(temp);
} else if (this->m_flagAnyOtherException) {
throw UnknownException(temp);
}
this->setError("");
}
}
////////////////////// Static Methods //////////////////////
/**
* Parses XML data and from it creates an instance of
* <code>CacheXmlParser</code> that can be used to create
* the {@link Cache}, etc.
*
* @param cacheXml
* The xml file
*
* @throws CacheXmlException
* Something went wrong while parsing the XML
* @throws OutOfMemoryException
* @throws CacheXmlException
* If xml file is not well-formed or
* Something went wrong while parsing the XML
* @throws IllegalStateException
* If xml file is well-flrmed but not valid
* @throws UnknownException otherwise
*/
CacheXmlParser* CacheXmlParser::parse(const char* cacheXml, Cache* cache) {
CacheXmlParser* handler;
_GEODE_NEW(handler, CacheXmlParser(cache));
// use RAII to delete the handler object in case of exceptions
DeleteObject<CacheXmlParser> delHandler(handler);
{
handler->parseFile(cacheXml);
delHandler.noDelete();
return handler;
}
}
void CacheXmlParser::setAttributes(Cache*) {}
/**
* Creates cache artifacts ({@link Cache}s, etc.) based upon the XML
* parsed by this parser.
*
* @param cache
* The cachewhcih is to be populated
* @throws OutOfMemoryException if the memory allocation failed
* @throws NotConnectedException if the cache is not connected
* @throws InvalidArgumentException if the attributePtr is nullptr.
* or if RegionAttributes is null or if regionName is null,
* the empty string, or contains a '/'
* @throws RegionExistsException
* @throws CacheClosedException if the cache is closed
* at the time of region creation
* @throws UnknownException otherwise
*
*/
void CacheXmlParser::create(Cache* cache) {
// use DeleteObject class to delete m_cacheCreation in case of exceptions
DeleteObject<CacheXmlCreation> delCacheCreation(m_cacheCreation);
if (cache == nullptr) {
throw IllegalArgumentException(
"XML:No cache specified for performing configuration");
}
if (!m_cacheCreation) {
throw CacheXmlException("XML: Element <cache> was not provided in the xml");
}
m_cacheCreation->create(cache);
delCacheCreation.noDelete();
Log::info("Declarative configuration of cache completed successfully");
}
void CacheXmlParser::startCache(void*, const xmlChar** atts) {
if (atts) {
for (size_t i = 0; atts[i] && atts[i + 1]; i += 2) {
auto name = std::string(reinterpret_cast<const char*>(atts[i]));
auto value = std::string(reinterpret_cast<const char*>(atts[i + 1]));
if (value.empty()) {
throw CacheXmlException("XML: No value provided for attribute: " +
name);
}
if (ENDPOINTS == name) {
if (m_poolFactory) {
for (auto&& endPoint : parseEndPoints(value)) {
m_poolFactory->addServer(endPoint.first, endPoint.second);
}
}
} else if (REDUNDANCY_LEVEL == name) {
m_poolFactory->setSubscriptionRedundancy(std::stoi(value));
}
}
}
_GEODE_NEW(m_cacheCreation, CacheXmlCreation());
}
void CacheXmlParser::startPdx(const xmlChar** atts) {
if (!atts) {
return;
}
for (size_t i = 0; atts[i] && atts[i + 1]; i += 2) {
auto name = std::string(reinterpret_cast<const char*>(atts[i]));
auto value = std::string(reinterpret_cast<const char*>(atts[i + 1]));
if (value.empty()) {
throw CacheXmlException("XML: No value provided for attribute: " + name);
}
if (IGNORE_UNREAD_FIELDS == name) {
bool flag = false;
std::transform(value.begin(), value.end(), value.begin(), ::tolower);
if ("false" == value) {
flag = false;
} else if ("true" == value) {
flag = true;
} else {
throw CacheXmlException(
"XML: " + value +
" is not a valid value for the attribute <ignore-unread-fields>");
}
m_cacheCreation->setPdxIgnoreUnreadField(flag);
} else if (READ_SERIALIZED == name) {
bool flag = false;
std::transform(value.begin(), value.end(), value.begin(), ::tolower);
if ("false" == value) {
flag = false;
} else if ("true" == value) {
flag = true;
} else {
throw CacheXmlException(
"XML: " + value +
" is not a valid value for the attribute <ignore-unread-fields>");
}
m_cacheCreation->setPdxReadSerialized(flag);
} else {
throw CacheXmlException("XML:Unrecognized pdx attribute " + name);
}
}
}
void CacheXmlParser::endPdx() {}
void CacheXmlParser::startLocator(const xmlChar** atts) {
if (!atts) {
throw CacheXmlException(
"XML:No attributes provided for <locator>. A locator requires a host "
"and port");
}
m_poolFactory = std::static_pointer_cast<PoolFactory>(_stack.top());
std::string host;
std::string port;
int attrsCount = 0;
for (size_t i = 0; atts[i] && atts[i + 1]; i += 2) {
auto name = std::string(reinterpret_cast<const char*>(atts[i]));
auto value = std::string(reinterpret_cast<const char*>(atts[i + 1]));
if (value.empty()) {
throw CacheXmlException("XML: No value provided for attribute: " + name);
}
if (HOST == name) {
host = std::move(value);
} else if (PORT == name) {
port = std::move(value);
} else {
throw CacheXmlException("XML:Unrecognized locator attribute");
}
++attrsCount;
}
if (attrsCount < 2) {
throw CacheXmlException(
"XML:Not enough attributes provided for a <locator> - host and port "
"required");
}
m_poolFactory->addLocator(host, std::stoi(port));
}
void CacheXmlParser::startServer(const xmlChar** atts) {
if (!atts) {
throw CacheXmlException(
"XML:No attributes provided for <server>. A server requires a host and "
"port");
}
auto factory = std::static_pointer_cast<PoolFactory>(_stack.top());
std::string host;
std::string port;
int attrsCount = 0;
for (size_t i = 0; atts[i] && atts[i + 1]; i += 2) {
auto name = std::string(reinterpret_cast<const char*>(atts[i]));
auto value = std::string(reinterpret_cast<const char*>(atts[i + 1]));
if (value.empty()) {
throw CacheXmlException("XML: No value provided for attribute: " + name);
}
if (HOST == name) {
host = std::move(value);
} else if (PORT == name) {
port = std::move(value);
} else {
throw CacheXmlException("XML:Unrecognized server attribute");
}
++attrsCount;
}
if (attrsCount < 2) {
throw CacheXmlException(
"XML:Not enough attributes provided for a <server> - host and port "
"required");
}
factory->addServer(host, std::stoi(port));
}
void CacheXmlParser::startPool(const xmlChar** atts) {
if (!atts) {
throw CacheXmlException(
"XML:No attributes provided for <pool>. A pool cannot be created "
"without a name");
}
auto factory =
std::make_shared<PoolFactory>(m_cache->getPoolManager().createFactory());
std::string poolName;
for (size_t i = 0; atts[i] && atts[i + 1]; i += 2) {
auto name = std::string(reinterpret_cast<const char*>(atts[i]));
auto value = std::string(reinterpret_cast<const char*>(atts[i + 1]));
if (value.empty()) {
throw CacheXmlException("XML: No value provided for attribute: " + name);
}
if (NAME == name) {
poolName = std::move(value);
} else {
setPoolInfo(factory.get(), name.c_str(), value.c_str());
}
}
if (poolName.empty()) {
throw CacheXmlException(
"XML:No attributes provided for a <pool> - at least the name is "
"required");
}
auto poolxml = std::make_shared<PoolXmlCreation>(poolName, factory);
_stack.push(poolxml);
_stack.push(factory);
}
void CacheXmlParser::endPool() {
_stack.pop(); // remove factory
auto poolxml = std::static_pointer_cast<PoolXmlCreation>(_stack.top());
_stack.pop(); // remove pool
m_cacheCreation->addPool(poolxml);
}
void CacheXmlParser::setPoolInfo(PoolFactory* factory, const char* name,
const char* value) {
using apache::geode::internal::chrono::duration::from_string;
if (strcmp(name, FREE_CONNECTION_TIMEOUT) == 0) {
factory->setFreeConnectionTimeout(
from_string<std::chrono::milliseconds>(std::string(value)));
} else if (strcmp(name, MULTIUSER_SECURE_MODE) == 0) {
if (ACE_OS::strcasecmp(value, "true") == 0) {
factory->setMultiuserAuthentication(true);
} else {
factory->setMultiuserAuthentication(false);
}
} else if (strcmp(name, IDLE_TIMEOUT) == 0) {
factory->setIdleTimeout(
from_string<std::chrono::milliseconds>(std::string(value)));
} else if (strcmp(name, LOAD_CONDITIONING_INTERVAL) == 0) {
factory->setLoadConditioningInterval(
from_string<std::chrono::milliseconds>(std::string(value)));
} else if (strcmp(name, MAX_CONNECTIONS) == 0) {
factory->setMaxConnections(atoi(value));
} else if (strcmp(name, MIN_CONNECTIONS) == 0) {
factory->setMinConnections(atoi(value));
} else if (strcmp(name, PING_INTERVAL) == 0) {
factory->setPingInterval(
from_string<std::chrono::milliseconds>(std::string(value)));
} else if (strcmp(name, UPDATE_LOCATOR_LIST_INTERVAL) == 0) {
factory->setUpdateLocatorListInterval(
from_string<std::chrono::milliseconds>(std::string(value)));
} else if (strcmp(name, READ_TIMEOUT) == 0) {
factory->setReadTimeout(
from_string<std::chrono::milliseconds>(std::string(value)));
} else if (strcmp(name, RETRY_ATTEMPTS) == 0) {
factory->setRetryAttempts(atoi(value));
} else if (strcmp(name, SERVER_GROUP) == 0) {
factory->setServerGroup(value);
} else if (strcmp(name, SOCKET_BUFFER_SIZE) == 0) {
factory->setSocketBufferSize(atoi(value));
} else if (strcmp(name, STATISTIC_INTERVAL) == 0) {
factory->setStatisticInterval(
from_string<std::chrono::milliseconds>(std::string(value)));
} else if (strcmp(name, SUBSCRIPTION_ACK_INTERVAL) == 0) {
factory->setSubscriptionAckInterval(
from_string<std::chrono::milliseconds>(std::string(value)));
} else if (strcmp(name, SUBSCRIPTION_ENABLED) == 0) {
if (ACE_OS::strcasecmp(value, "true") == 0) {
factory->setSubscriptionEnabled(true);
} else {
factory->setSubscriptionEnabled(false);
}
} else if (strcmp(name, SUBSCRIPTION_MTT) == 0) {
factory->setSubscriptionMessageTrackingTimeout(
from_string<std::chrono::milliseconds>(std::string(value)));
} else if (strcmp(name, SUBSCRIPTION_REDUNDANCY) == 0) {
factory->setSubscriptionRedundancy(atoi(value));
} else if (strcmp(name, THREAD_LOCAL_CONNECTIONS) == 0) {
if (ACE_OS::strcasecmp(value, "true") == 0) {
factory->setThreadLocalConnections(true);
} else {
factory->setThreadLocalConnections(false);
}
} else if (strcmp(name, PR_SINGLE_HOP_ENABLED) == 0) {
if (ACE_OS::strcasecmp(value, "true") == 0) {
factory->setPRSingleHopEnabled(true);
} else {
factory->setPRSingleHopEnabled(false);
}
} else {
throw CacheXmlException("XML:Unrecognized pool attribute " +
std::string(name));
}
}
/**
* When a <code>region</code> element is first encountered, we
* create a {@link RegionCreation} and push it on the _stack.
* An {@link RegionAttributesFactory }is also created and puhed on _stack.
*/
void CacheXmlParser::startRegion(const xmlChar** atts, bool isRoot) {
int attrsCount = 0;
if (!atts) {
throw CacheXmlException(
"XML:No attributes provided for <region>. A region cannot be created "
"without a name");
}
while (atts[attrsCount]) ++attrsCount;
if (attrsCount < 2 || attrsCount > 4) {
throw CacheXmlException(
"XML:Incorrect number of attributes provided for a <region>");
}
std::string regionName;
std::string refid;
for (size_t i = 0; atts[i] && atts[i + 1]; i += 2) {
auto name = std::string(reinterpret_cast<const char*>(atts[i]));
auto value = std::string(reinterpret_cast<const char*>(atts[i + 1]));
if ("name" == name) {
regionName = value;
} else if ("refid" == name) {
refid = value;
} else {
throw CacheXmlException("XML:<region> does not contain the attribute :" +
name);
}
}
if (regionName.empty()) {
throw CacheXmlException(
"XML:The attribute name of <region> should be specified and cannot be "
"empty");
}
auto region = std::make_shared<RegionXmlCreation>(regionName, isRoot);
if (!region) {
throw UnknownException("CacheXmlParser::startRegion:Out of memeory");
}
_stack.push(region);
RegionAttributesFactory regionAttributesFactory;
if (!refid.empty()) {
if (namedRegions.find(refid) != namedRegions.end()) {
regionAttributesFactory = RegionAttributesFactory(namedRegions[refid]);
} else {
throw CacheXmlException("XML:referenced named attribute '" + refid +
"' does not exist.");
}
}
region->setAttributes(regionAttributesFactory.create());
}
void CacheXmlParser::startSubregion(const xmlChar** atts) {
startRegion(atts, false);
}
void CacheXmlParser::startRootRegion(const xmlChar** atts) {
startRegion(atts, true);
}
void CacheXmlParser::startRegionAttributes(const xmlChar** atts) {
bool isDistributed = false;
bool isTCR = false;
std::shared_ptr<RegionAttributesFactory> regionAttributesFactory = nullptr;
if (atts) {
int attrsCount = 0;
while (atts[attrsCount]) ++attrsCount;
if (attrsCount > 24) // Remember to change this when the number changes
{
throw CacheXmlException(
"XML:Number of attributes provided for <region-attributes> are more");
}
std::string refid;
for (size_t i = 0; atts[i] && atts[i + 1]; i += 2) {
auto name = std::string(reinterpret_cast<const char*>(atts[i]));
auto value = std::string(reinterpret_cast<const char*>(atts[i + 1]));
if (value.empty()) {
throw CacheXmlException(
"XML:In the <region-attributes> element attribute " + name +
" can be set to empty string. It should either have a "
"value or the attribute should be removed. In the latter case "
"the default value will be set");
}
if (ID == name) {
auto region = std::static_pointer_cast<RegionXmlCreation>(_stack.top());
region->setAttrId(value);
} else if (REFID == name) {
refid = std::move(value);
}
}
if (refid.empty()) {
auto region = std::static_pointer_cast<RegionXmlCreation>(_stack.top());
regionAttributesFactory =
std::make_shared<RegionAttributesFactory>(region->getAttributes());
} else {
if (namedRegions.find(refid) != namedRegions.end()) {
regionAttributesFactory =
std::make_shared<RegionAttributesFactory>(namedRegions[refid]);
} else {
throw CacheXmlException("XML:referenced named attribute '" + refid +
"' does not exist.");
}
}
if (!regionAttributesFactory) {
throw UnknownException(
"CacheXmlParser::startRegionAttributes:Out of memeory");
}
_stack.push(regionAttributesFactory);
for (size_t i = 0; atts[i] && atts[i + 1]; i += 2) {
auto name = std::string(reinterpret_cast<const char*>(atts[i]));
auto value = std::string(reinterpret_cast<const char*>(atts[i + 1]));
if (ID == name || REFID == name) {
continue;
} else if (CLIENT_NOTIFICATION_ENABLED == name) {
bool flag = false;
std::transform(value.begin(), value.end(), value.begin(), ::tolower);
if ("false" == value) {
flag = false;
} else if ("true" == value) {
flag = true;
} else {
throw CacheXmlException(
"XML: " + value +
" is not a valid name for the attribute <client-notification>");
}
if (m_poolFactory) {
m_poolFactory->setSubscriptionEnabled(flag);
}
} else if (INITIAL_CAPACITY == name) {
regionAttributesFactory->setInitialCapacity(std::stoi(value));
} else if (CONCURRENCY_LEVEL == name) {
regionAttributesFactory->setConcurrencyLevel(std::stoi(value));
} else if (LOAD_FACTOR == name) {
regionAttributesFactory->setLoadFactor(std::stof(value));
} else if (CACHING_ENABLED == name) {
bool flag = false;
std::transform(value.begin(), value.end(), value.begin(), ::tolower);
if ("false" == value) {
flag = false;
} else if ("true" == value) {
flag = true;
} else {
throw CacheXmlException(
"XML: " + value +
" is not a valid name for the attribute <caching-enabled>");
}
regionAttributesFactory->setCachingEnabled(flag);
} else if (LRU_ENTRIES_LIMIT == name) {
regionAttributesFactory->setLruEntriesLimit(std::stoi(value));
} else if (DISK_POLICY == name) {
auto diskPolicy = apache::geode::client::DiskPolicyType::NONE;
if (OVERFLOWS == value) {
diskPolicy = apache::geode::client::DiskPolicyType::OVERFLOWS;
} else if (PERSIST == value) {
throw IllegalStateException("Persistence feature is not supported");
} else if (NONE == value) {
diskPolicy = apache::geode::client::DiskPolicyType::NONE;
} else {
throw CacheXmlException(
"XML: " + value +
" is not a valid name for the attribute <disk-policy>");
}
regionAttributesFactory->setDiskPolicy(diskPolicy);
} else if (ENDPOINTS == name) {
if (m_poolFactory) {
for (auto&& endPoint : parseEndPoints(name)) {
m_poolFactory->addServer(endPoint.first, endPoint.second);
}
}
isTCR = true;
} else if (POOL_NAME == name) {
regionAttributesFactory->setPoolName(value);
isTCR = true;
} else if (CLONING_ENABLED == name) {
bool flag = false;
std::transform(value.begin(), value.end(), value.begin(), ::tolower);
if ("false" == value) {
flag = false;
} else if ("true" == value) {
flag = true;
} else {
throw CacheXmlException(
"XML: " + value +
" is not a valid value for the attribute <cloning-enabled>");
}
regionAttributesFactory->setCloningEnabled(flag);
isTCR = true;
} else if (CONCURRENCY_CHECKS_ENABLED == name) {
bool flag = false;
std::transform(value.begin(), value.end(), value.begin(), ::tolower);
if ("false" == value) {
flag = false;
} else if ("true" == value) {
flag = true;
} else {
throw CacheXmlException("XML: " + value +
" is not a valid value for the attribute "
"<concurrency-checks-enabled>");
}
regionAttributesFactory->setConcurrencyChecksEnabled(flag);
}
} // for loop
} // atts is nullptr
else {
auto region = std::static_pointer_cast<RegionXmlCreation>(_stack.top());
regionAttributesFactory =
std::make_shared<RegionAttributesFactory>(region->getAttributes());
_stack.push(regionAttributesFactory);
}
if (isDistributed && isTCR) {
/* we don't allow DR+TCR at current stage according to sudhir */
throw CacheXmlException(
"XML:endpoints cannot be defined for distributed region.\n");
}
}
void CacheXmlParser::endRegionAttributes() {
auto regionAttributesFactory =
std::static_pointer_cast<RegionAttributesFactory>(_stack.top());
_stack.pop();
if (!regionAttributesFactory) {
throw UnknownException(
"CacheXmlParser::endRegion:RegionAttributesFactory is null");
}
auto regionAttributes = regionAttributesFactory->create();
auto regionPtr = std::static_pointer_cast<RegionXmlCreation>(_stack.top());
if (!regionPtr) {
throw UnknownException("CacheXmlParser::endRegion:Region is null");
}
std::string id = regionPtr->getAttrId();
if (id != "") {
namedRegions[id] = regionAttributes;
}
regionPtr->setAttributes(regionAttributes);
}
/**
* When a <code>expiration-attributes</code> element is first
* encountered, we create an {@link ExpirationAttibutes} object from
* the element's attributes and push it on the _stack.
*/
void CacheXmlParser::startExpirationAttributes(const xmlChar** atts) {
using apache::geode::internal::chrono::duration::from_string;
if (!atts) {
throw CacheXmlException(
"XML:No attributes provided for <expiration-attributes> ");
}
m_flagExpirationAttribute = true;
size_t attrsCount = 0;
while (atts[attrsCount]) ++attrsCount;
if (attrsCount > 4) {
throw CacheXmlException(
"XML:Incorrect number of attributes provided for "
"<expirartion-attributes>");
}
std::string timeOut;
ExpirationAction expire = ExpirationAction::INVALID_ACTION;
for (size_t i = 0; atts[i] && atts[i + 1]; i += 2) {
auto name = std::string(reinterpret_cast<const char*>(atts[i]));
auto value = std::string(reinterpret_cast<const char*>(atts[i + 1]));
if (TIMEOUT == name) {
if (value.empty()) {
throw CacheXmlException(
"XML:Value for attribute <timeout> needs to be specified");
}
timeOut = value;
} else if (ACTION == name) {
if (value.empty()) {
throw CacheXmlException(
"XML:The attribute <action> of <expiration-attributes> cannot be "
"set to empty string. It should either have a value or the "
"attribute should be removed. In the latter case the default value "
"will be set");
} else if (INVALIDATE == value) {
expire = ExpirationAction::INVALIDATE;
} else if (DESTROY == value) {
expire = ExpirationAction::DESTROY;
} else if (LOCAL_INVALIDATE == value) {
expire = ExpirationAction::LOCAL_INVALIDATE;
} else if (LOCAL_DESTROY == value) {
expire = ExpirationAction::LOCAL_DESTROY;
} else {
throw CacheXmlException(
"XML: " + value +
" is not a valid value for the attribute <action>");
}
} else {
throw CacheXmlException(
"XML:Incorrect attribute name specified in "
"<expiration-attributes>: " +
value);
}
}
if (timeOut.empty()) {
throw CacheXmlException(
"XML:The attribute <timeout> not specified in "
"<expiration-attributes>.");
}
auto timeOutSeconds = from_string<std::chrono::seconds>(timeOut);
auto expireAttr =
std::make_shared<ExpirationAttributes>(timeOutSeconds, expire);
if (!expireAttr) {
throw UnknownException(
"CacheXmlParser::startExpirationAttributes:Out of memory");
}
expireAttr->setAction(expire);
_stack.push(expireAttr);
}
void CacheXmlParser::startPersistenceManager(const xmlChar** atts) {
int attrsCount = 0;
if (!atts) {
throw CacheXmlException(
"XML:No attributes provided for <persistence-manager>");
}
while (atts[attrsCount]) ++attrsCount;
if (attrsCount > 4) {
throw CacheXmlException(
"XML:Incorrect number of attributes provided for "
"<persistence-manager>");
}
std::string libraryName;
std::string libraryFunctionName;
for (size_t i = 0; atts[i] && atts[i + 1]; i += 2) {
auto name = std::string(reinterpret_cast<const char*>(atts[i]));
auto value = std::string(reinterpret_cast<const char*>(atts[i + 1]));
if (value.empty()) {
throw CacheXmlException("XML:Value for attribute <" + name +
"> needs to be specified in the "
"<persistence-manager>");
}
if (LIBRARY_NAME == name) {
libraryName = std::move(value);
} else if (LIBRARY_FUNCTION_NAME == name) {
libraryFunctionName = std::move(value);
} else {
throw CacheXmlException(
"XML:Incorrect attribute name specified in <persistence-manager>: " +
value);
}
}
if (libraryFunctionName.empty()) {
throw CacheXmlException(
"XML:Library function name not specified in the <persistence-manager>");
}
try {
if (managedPersistenceManagerFn &&
libraryFunctionName.find('.') != std::string::npos) {
// this is a managed library
(*managedPersistenceManagerFn)(libraryName.c_str(),
libraryFunctionName.c_str());
} else {
getFactoryFunc(libraryName, libraryFunctionName);
}
} catch (IllegalArgumentException& ex) {
throw CacheXmlException(ex.what());
}
_stack.emplace(std::make_shared<std::string>(std::move(libraryName)));
_stack.emplace(std::make_shared<std::string>(std::move(libraryFunctionName)));
}
void CacheXmlParser::startPersistenceProperties(const xmlChar** atts) {
if (!atts) {
throw CacheXmlException("XML:No attributes provided for <property>");
}
int attrsCount = 0;
while (atts[attrsCount]) ++attrsCount;
if (attrsCount > 4) {
throw CacheXmlException(
"XML:Incorrect number of attributes provided for <property>");
} else {
if (m_config == nullptr) {
m_config = Properties::create();
}
}
std::string propName;
std::string propValue;
for (size_t i = 0; atts[i] && atts[i + 1]; i += 2) {
auto name = std::string(reinterpret_cast<const char*>(atts[i]));
auto value = std::string(reinterpret_cast<const char*>(atts[i + 1]));
if (value.empty()) {
throw CacheXmlException("XML:Value for attribute <" + name +
"> needs to be specified in the "
"<property>");
}
if ("name" == name) {
propName = value;
} else if ("value" == name) {
propValue = value;
} else {
throw CacheXmlException(
"XML:Incorrect attribute name specified in <property>: " + name);
}
}
if (propName.empty()) {
throw CacheXmlException(
"XML:attribute <name> needs to be specified in the <property>");
}
if (propValue.empty()) {
throw CacheXmlException(
"XML:attribute <value> needs to be specified in the <property>");
}
m_config->insert(propName, propValue);
}
void CacheXmlParser::startCacheLoader(const xmlChar** atts) {
std::string libraryName;
std::string libraryFunctionName;
int attrsCount = 0;
if (!atts) {
throw CacheXmlException("XML:No attributes provided for <cache-loader>");
}
while (atts[attrsCount]) ++attrsCount;
if (attrsCount > 4) {
throw CacheXmlException(
"XML:Incorrect number of attributes provided for <cache-loader>");
}
for (size_t i = 0; atts[i] && atts[i + 1]; i += 2) {
auto name = std::string(reinterpret_cast<const char*>(atts[i]));
auto value = std::string(reinterpret_cast<const char*>(atts[i + 1]));
if (value.empty()) {
throw CacheXmlException("XML:Value for attribute <" + name +
"> needs to be specified in the "
"<cache-loader>");
}
if (LIBRARY_NAME == name) {
libraryName = std::move(value);
} else if (LIBRARY_FUNCTION_NAME == name) {
libraryFunctionName = std::move(value);
} else {
throw CacheXmlException(
"XML:Incorrect attribute name specified in <cache-loader> : " + name);
}
}
if (libraryFunctionName.empty()) {
throw CacheXmlException(
"XML:<library-function-name> not specified in <cache-loader>");
}
try {
if (managedCacheLoaderFn &&
libraryFunctionName.find('.') != std::string::npos) {
// this is a managed library
(*managedCacheLoaderFn)(libraryName.c_str(), libraryFunctionName.c_str());
} else {
getFactoryFunc(libraryName, libraryFunctionName);
}
} catch (IllegalArgumentException& ex) {
throw CacheXmlException(ex.what());
}
auto regionAttributesFactory =
std::static_pointer_cast<RegionAttributesFactory>(_stack.top());
regionAttributesFactory->setCacheLoader(libraryName, libraryFunctionName);
}
void CacheXmlParser::startCacheListener(const xmlChar** atts) {
std::string libraryName;
std::string libraryFunctionName;
int attrsCount = 0;
if (!atts) {
throw CacheXmlException("XML:No attributes provided for <cache-listener>");
}
while (atts[attrsCount]) ++attrsCount;
if (attrsCount > 4) {
throw CacheXmlException(
"XML:Incorrect number of attributes provided for <cache-listener>");
}
for (size_t i = 0; atts[i] && atts[i + 1]; i += 2) {
auto name = std::string(reinterpret_cast<const char*>(atts[i]));
auto value = std::string(reinterpret_cast<const char*>(atts[i + 1]));
if (value.empty()) {
throw CacheXmlException("XML:Value for attribute <" + name +
"> needs to be specified in the "
"<cache-listener>");
}
if (LIBRARY_NAME == name) {
libraryName = std::move(value);
} else if (LIBRARY_FUNCTION_NAME == name) {
libraryFunctionName = std::move(value);
} else {
throw CacheXmlException(
"XML:Incorrect attribute name specified in <cache-listener> : " +
name);
}
}
if (libraryFunctionName.empty()) {
throw CacheXmlException(
"XML:Library function name not specified in <cache-listener>");
}
try {
if (managedCacheListenerFn &&
libraryFunctionName.find('.') != std::string::npos) {
// this is a managed library
(*managedCacheListenerFn)(libraryName.c_str(),
libraryFunctionName.c_str());
} else {
getFactoryFunc(libraryName, libraryFunctionName);
}
} catch (IllegalArgumentException& ex) {
throw CacheXmlException(ex.what());
}
auto regionAttributesFactory =
std::static_pointer_cast<RegionAttributesFactory>(_stack.top());
regionAttributesFactory->setCacheListener(libraryName, libraryFunctionName);
}
void CacheXmlParser::startPartitionResolver(const xmlChar** atts) {
if (!atts) {
throw CacheXmlException(
"XML:No attributes provided for <partition-resolver> ");
}
int attrsCount = 0;
while (atts[attrsCount]) ++attrsCount;
if (attrsCount > 4) {
throw CacheXmlException(
"XML:Incorrect number of attributes provided for "
"<partition-resolver>");
}
std::string libraryName;
std::string libraryFunctionName;
for (size_t i = 0; atts[i] && atts[i + 1]; i += 2) {
auto name = std::string(reinterpret_cast<const char*>(atts[i]));
auto value = std::string(reinterpret_cast<const char*>(atts[i + 1]));
if (value.empty()) {
throw CacheXmlException("XML:Value for attribute <" + name +
"> needs to be specified in the "
"<cache-listener>");
}
if (LIBRARY_NAME == name) {
libraryName = std::move(value);
} else if (LIBRARY_FUNCTION_NAME == name) {
libraryFunctionName = std::move(value);
} else {
throw CacheXmlException(
"XML:Incorrect attribute name specified in <partition-resolver>: " +
value);
}
}
if (libraryFunctionName.empty()) {
throw CacheXmlException(
"XML:Library function name not specified in <partition-resolver> ");
}
try {
if (managedPartitionResolverFn != nullptr &&
libraryFunctionName.find('.') != std::string::npos) {
// this is a managed library
(*managedPartitionResolverFn)(libraryName.c_str(),
libraryFunctionName.c_str());
} else {
getFactoryFunc(libraryName, libraryFunctionName);
}
} catch (IllegalArgumentException& ex) {
throw CacheXmlException(ex.what());
}
auto regionAttributesFactory =
std::static_pointer_cast<RegionAttributesFactory>(_stack.top());
regionAttributesFactory->setPartitionResolver(libraryName,
libraryFunctionName);
}
void CacheXmlParser::startCacheWriter(const xmlChar** atts) {
if (!atts) {
throw CacheXmlException("XML:No attributes provided for <cache-writer>");
}
int attrsCount = 0;
while (atts[attrsCount] != nullptr) ++attrsCount;
if (attrsCount > 4) {
throw CacheXmlException(
"XML:Incorrect number of attributes provided for <cache-writer>");
}
std::string libraryName;
std::string libraryFunctionName;
for (size_t i = 0; atts[i] && atts[i + 1]; i += 2) {
auto name = std::string(reinterpret_cast<const char*>(atts[i]));
auto value = std::string(reinterpret_cast<const char*>(atts[i + 1]));
if (value.empty()) {
throw CacheXmlException("XML:Value for attribute <" + name +
"> needs to be specified in the <cache-writer>");
}
if (LIBRARY_NAME == name) {
libraryName = std::move(value);
} else if (LIBRARY_FUNCTION_NAME == name) {
libraryFunctionName = std::move(value);
} else {
throw CacheXmlException(
"XML:Incorrect attribute name specified in <cache-writer>: " + value);
}
}
if (libraryFunctionName.empty()) {
throw CacheXmlException(
"XML:Library function name not specified in the <cache-writer>");
}
try {
if (managedCacheWriterFn &&
libraryFunctionName.find('.') != std::string::npos) {
// this is a managed library
(*managedCacheWriterFn)(libraryName.c_str(), libraryFunctionName.c_str());
} else {
getFactoryFunc(libraryName, libraryFunctionName);
}
} catch (IllegalArgumentException& ex) {
throw CacheXmlException(ex.what());
}
auto regionAttributesFactory =
std::static_pointer_cast<RegionAttributesFactory>(_stack.top());
regionAttributesFactory->setCacheWriter(libraryName, libraryFunctionName);
}
/**
* After popping the current <code>RegionXmlCreation</code> off the
* _stack, if the element on top of the _stack is a
* <code>RegionXmlCreation</code>, then it is the parent region.
*/
void CacheXmlParser::endRegion(bool isRoot) {
auto regionPtr = std::static_pointer_cast<RegionXmlCreation>(_stack.top());
_stack.pop();
if (isRoot) {
if (!_stack.empty()) {
throw CacheXmlException("Xml file has incorrectly nested region tags");
}
if (!m_cacheCreation) {
throw CacheXmlException(
"XML: Element <cache> was not provided in the xml");
}
m_cacheCreation->addRootRegion(regionPtr);
} else {
if (_stack.empty()) {
throw CacheXmlException("Xml file has incorrectly nested region tags");
}
auto parent = std::static_pointer_cast<RegionXmlCreation>(_stack.top());
parent->addSubregion(regionPtr);
}
}
void CacheXmlParser::endSubregion() { endRegion(false); }
void CacheXmlParser::endRootRegion() { endRegion(true); }
/**
* When a <code>cache</code> element is finished
*/
void CacheXmlParser::endCache() {}
/**
* When a <code>region-time-to-live</code> element is finished, the
* {@link ExpirationAttributes} are on top of the _stack followed by
* the {@link RegionAttributesFactory} to which the expiration
* attributes are assigned.
*/
void CacheXmlParser::endRegionTimeToLive() {
if (!m_flagExpirationAttribute) {
throw CacheXmlException(
"XML: <region-time-to-live> cannot be without a "
"<expiration-attributes>");
}
auto expireAttr =
std::static_pointer_cast<ExpirationAttributes>(_stack.top());
_stack.pop();
auto regionAttributesFactory =
std::static_pointer_cast<RegionAttributesFactory>(_stack.top());
regionAttributesFactory->setRegionTimeToLive(expireAttr->getAction(),
expireAttr->getTimeout());
m_flagExpirationAttribute = false;
}
/**
* When a <code>region-idle-time</code> element is finished, the
* {@link ExpirationAttributes} are on top of the _stack followed by
* the {@link RegionAttributesFactory} to which the expiration
* attributes are assigned.
*/
void CacheXmlParser::endRegionIdleTime() {
if (!m_flagExpirationAttribute) {
throw CacheXmlException(
"XML: <region-idle-time> cannot be without <expiration-attributes>");
}
auto expireAttr =
std::static_pointer_cast<ExpirationAttributes>(_stack.top());
_stack.pop();
auto regionAttributesFactory =
std::static_pointer_cast<RegionAttributesFactory>(_stack.top());
regionAttributesFactory->setRegionIdleTimeout(expireAttr->getAction(),
expireAttr->getTimeout());
m_flagExpirationAttribute = false;
}
/**
* When a <code>entry-time-to-live</code> element is finished, the
* {@link ExpirationAttributes} are on top of the _stack followed by
* the {@link RegionAttributesFactory} to which the expiration
* attributes are assigned.
*/
void CacheXmlParser::endEntryTimeToLive() {
if (!m_flagExpirationAttribute) {
throw CacheXmlException(
"XML: <entry-time-to-live> cannot be without <expiration-attributes>");
}
auto expireAttr =
std::static_pointer_cast<ExpirationAttributes>(_stack.top());
_stack.pop();
auto regionAttributesFactory =
std::static_pointer_cast<RegionAttributesFactory>(_stack.top());
regionAttributesFactory->setEntryTimeToLive(expireAttr->getAction(),
expireAttr->getTimeout());
m_flagExpirationAttribute = false;
}
/**
* When a <code>entry-idle-time</code> element is finished, the
* {@link ExpirationAttributes} are on top of the _stack followed by
* the {@link RegionAttributesFactory} to which the expiration
* attributes are assigned.
*/
void CacheXmlParser::endEntryIdleTime() {
if (!m_flagExpirationAttribute) {
throw CacheXmlException(
"XML: <entry-idle-time> cannot be without <expiration-attributes>");
}
auto expireAttr =
std::static_pointer_cast<ExpirationAttributes>(_stack.top());
_stack.pop();
auto regionAttributesFactory =
std::static_pointer_cast<RegionAttributesFactory>(_stack.top());
// TODO GEODE-3136: consider string parser here.
regionAttributesFactory->setEntryIdleTimeout(expireAttr->getAction(),
expireAttr->getTimeout());
m_flagExpirationAttribute = false;
}
/**
* When persistence-manager attributes is finished, it will set the attribute
* factory.
*/
void CacheXmlParser::endPersistenceManager() {
std::shared_ptr<std::string> libraryFunctionName =
std::static_pointer_cast<std::string>(_stack.top());
_stack.pop();
std::shared_ptr<std::string> libraryName =
std::static_pointer_cast<std::string>(_stack.top());
_stack.pop();
auto regionAttributesFactory =
std::static_pointer_cast<RegionAttributesFactory>(_stack.top());
if (m_config != nullptr) {
regionAttributesFactory->setPersistenceManager(
libraryName->c_str(), libraryFunctionName->c_str(), m_config);
m_config = nullptr;
} else {
regionAttributesFactory->setPersistenceManager(
libraryName->c_str(), libraryFunctionName->c_str());
}
}
CacheXmlParser::~CacheXmlParser() { _GEODE_SAFE_DELETE(m_cacheCreation); }
void CacheXmlParser::setError(const std::string& err) { m_error = err; }
const std::string& CacheXmlParser::getError() const { return m_error; }
} // namespace client
} // namespace geode
} // namespace apache