Files
Beq 0d25562014 FIRE-34977 - Reduce Sim crossing overhead causing pauses
The purge thread should be the only thread recalculating cache usage. This removes the directory scan from the critial path where it would occasionally trigger due to aligned timers (exacerbated by high rates of region crossing)
2025-05-19 19:53:44 +01:00

132 lines
3.8 KiB
C++

#include "linden_common.h"
#include "bugsplatattributes.h"
#include <filesystem>
std::string BugSplatAttributes::mCrashContextFileName;
BugSplatAttributes& BugSplatAttributes::instance()
{
static BugSplatAttributes sInstance;
return sInstance;
}
#include <string>
#include <cctype>
std::string BugSplatAttributes::to_xml_token(const std::string& input)
{
// Example usage:
// std::string token = to_xml_token("Bandwidth (kbit/s)");
// The result should be: "Bandwidth_kbit_per_s"
std::string result;
result.reserve(input.size() * 2); // Reserve some space, since we might insert more chars for "/"
for (char ch : input)
{
if (ch == '/')
{
// Replace '/' with "_per_"
result.append("_per_");
}
else if (std::isalnum(ch) || ch == '_' || ch == '-')
{
// Letters, digits, underscore, and hyphen are okay
result.push_back(ch);
}
else if (ch == ' ' || ch == '(' || ch == ')')
{
// Replace spaces and parentheses with underscore
result.push_back('_');
}
else
{
// Other characters map to underscore
result.push_back('_');
}
}
// Ensure the first character is a letter or underscore:
// If not, prepend underscore.
if (result.empty() || !(std::isalpha(result.front()) || result.front() == '_'))
{
result.insert(result.begin(), '_');
}
// trim trailing underscores
while (!result.empty() && result.back() == '_')
{
result.pop_back();
}
return result;
}
bool BugSplatAttributes::writeToFile(const std::string& file_path)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_LOGGING;
std::lock_guard<std::mutex> lock(mMutex);
// Write to a temporary file first
std::string tmp_file = file_path + ".tmp";
{
llofstream ofs(tmp_file.c_str(), std::ios::out | std::ios::trunc);
if (!ofs.good())
{
return false;
}
ofs << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
ofs << "<XmlCrashContext>\n";
// First, write out attributes that have an empty category (top-level)
auto empty_category_it = mAttributes.find("");
if (empty_category_it != mAttributes.end())
{
for (const auto& kv : empty_category_it->second)
{
const std::string& key = kv.first;
const std::string& val = kv.second;
ofs << " <" << key << ">" << val << "</" << key << ">\n";
}
}
// Write out all other categories
// BugSplat chaanged the XML format and there is no strict category support now. For now we'll prefix the category to each attribute
for (const auto& cat_pair : mAttributes)
{
const std::string& category = cat_pair.first;
// Skip empty category since we already handled it above
if (category.empty())
{
continue;
}
for (const auto& kv : cat_pair.second)
{
const std::string& key = kv.first;
const std::string& val = kv.second;
ofs << " <" << category << "-" << key << ">" << val << "</" << category << "-" << key << ">\n";
}
}
ofs << "</XmlCrashContext>\n";
// Close the file before renaming
ofs.close();
}
// Rename the temp file to the final file. If rename fails, leave the old file intact.
std::error_code ec;
std::filesystem::rename(tmp_file, file_path, ec);
if (ec)
{
// Rename failed, remove the temp file and return false
std::filesystem::remove(tmp_file, ec);
return false;
}
return true;
}