summaryrefslogtreecommitdiff
path: root/indra/llxml/llxmlnode.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llxml/llxmlnode.cpp')
-rw-r--r--indra/llxml/llxmlnode.cpp78
1 files changed, 51 insertions, 27 deletions
diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp
index 9c7ac66f01..627e99a1e6 100644
--- a/indra/llxml/llxmlnode.cpp
+++ b/indra/llxml/llxmlnode.cpp
@@ -650,34 +650,56 @@ bool LLXMLNode::updateNode(
return true;
}
-// static
-bool LLXMLNode::parseFile(const std::string& filename, LLXMLNodePtr& node, LLXMLNode* defaults_tree)
+static std::map<std::string, LLXMLNodePtr> sXMLCache;
+static LLSharedMutex sXMLCacheMutex;
+
+static void saveToCache(const std::string& filename, LLXMLNodePtr& node)
{
- // Read file
- LL_DEBUGS("XMLNode") << "parsing XML file: " << filename << LL_ENDL;
- LLFILE* fp = LLFile::fopen(filename, "rb"); /* Flawfinder: ignore */
- if (fp == NULL)
- {
- node = NULL ;
- return false;
- }
- fseek(fp, 0, SEEK_END);
- U32 length = ftell(fp);
- fseek(fp, 0, SEEK_SET);
+ LLExclusiveMutexLock lock(&sXMLCacheMutex);
+ sXMLCache.emplace(filename, node.notNull() ? node->deepCopy() : nullptr);
+}
- U8* buffer = new U8[length+1];
- size_t nread = fread(buffer, 1, length, fp);
- buffer[nread] = 0;
- fclose(fp);
+static bool loadFromCache(const std::string& filename, LLXMLNodePtr& node)
+{
+ LLSharedMutexLock lock(&sXMLCacheMutex);
+ auto it = sXMLCache.find(filename);
+ if (it == sXMLCache.end())
+ return false;
+ node = it->second.notNull() ? it->second->deepCopy() : nullptr;
+ return node.notNull();
+}
- bool rv = parseBuffer(buffer, nread, node, defaults_tree);
- delete [] buffer;
- return rv;
+// static
+bool LLXMLNode::parseFile(const std::string& filename, LLXMLNodePtr& node, LLXMLNode* defaults_tree, bool cacheable)
+{
+ // Try to read from cache
+ if (cacheable)
+ {
+ if (loadFromCache(filename, node))
+ return true;
+ }
+
+ std::string xml = gDirUtilp->getFileContents(filename);
+ if (xml.empty())
+ {
+ LL_WARNS("XMLNode") << "no XML file: " << filename << LL_ENDL;
+ }
+ else if (parseBuffer(xml.data(), xml.size(), node, defaults_tree))
+ {
+ if (cacheable)
+ {
+ saveToCache(filename, node);
+ }
+ return true;
+ }
+
+ node = nullptr;
+ return false;
}
// static
bool LLXMLNode::parseBuffer(
- U8* buffer,
+ const char* buffer,
U32 length,
LLXMLNodePtr& node,
LLXMLNode* defaults)
@@ -696,7 +718,7 @@ bool LLXMLNode::parseBuffer(
XML_SetUserData(my_parser, (void *)file_node_ptr);
// Do the parsing
- if (XML_Parse(my_parser, (const char *)buffer, length, true) != XML_STATUS_OK)
+ if (XML_Parse(my_parser, buffer, length, true) != XML_STATUS_OK)
{
LL_WARNS() << "Error parsing xml error code: "
<< XML_ErrorString(XML_GetErrorCode(my_parser))
@@ -824,18 +846,20 @@ bool LLXMLNode::isFullyDefault()
}
// static
-bool LLXMLNode::getLayeredXMLNode(LLXMLNodePtr& root,
- const std::vector<std::string>& paths)
+bool LLXMLNode::getLayeredXMLNode(LLXMLNodePtr& root, const std::vector<std::string>& paths, bool cacheable)
{
- if (paths.empty()) return false;
+ if (paths.empty())
+ {
+ return false;
+ }
std::string filename = paths.front();
if (filename.empty())
{
return false;
}
-
- if (!LLXMLNode::parseFile(filename, root, NULL))
+
+ if (!LLXMLNode::parseFile(filename, root, nullptr, cacheable))
{
LL_WARNS() << "Problem reading UI description file: " << filename << LL_ENDL;
return false;