summaryrefslogtreecommitdiff
path: root/indra/newview/llsyntaxid.cpp
diff options
context:
space:
mode:
authorCinder <cinder.roxley@phoenixviewer.com>2014-06-09 15:14:09 -0600
committerCinder <cinder.roxley@phoenixviewer.com>2014-06-09 15:14:09 -0600
commit41f6c5ce4899b3ae57aefa564ee22ff84fa698ce (patch)
tree7f75bec5313e46a7afca5d264299163403865138 /indra/newview/llsyntaxid.cpp
parent58bf0dd580456f2df23c463f24791f6d580604b1 (diff)
Greatly simplify LLSyntaxIdLSL:
* Move file fetched callback to the singleton and handle all syntax id changes within the singleton * Remove a fair number of bool checks and method relying more on callbacks to drive syntax changes. * Don't pretty print the cache file to conserve space and to speed up xml to llsd parsing * Clean up includes
Diffstat (limited to 'indra/newview/llsyntaxid.cpp')
-rw-r--r--indra/newview/llsyntaxid.cpp296
1 files changed, 123 insertions, 173 deletions
diff --git a/indra/newview/llsyntaxid.cpp b/indra/newview/llsyntaxid.cpp
index 0ef5993ac1..5b5bab85d0 100644
--- a/indra/newview/llsyntaxid.cpp
+++ b/indra/newview/llsyntaxid.cpp
@@ -1,8 +1,8 @@
/**
* @file LLSyntaxId
- * @author Ima Mechanique
* @brief Handles downloading, saving, and checking of LSL keyword/syntax files
* for each region.
+ * @author Ima Mechanique, Cinder Roxley
*
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
* Second Life Viewer Source Code
@@ -28,189 +28,149 @@
#include "llviewerprecompiledheaders.h"
+#include "llsyntaxid.h"
#include "llagent.h"
#include "llappviewer.h"
#include "llhttpclient.h"
#include "llsdserialize.h"
-#include "llsyntaxid.h"
+#include "llviewerregion.h"
//-----------------------------------------------------------------------------
// fetchKeywordsFileResponder
//-----------------------------------------------------------------------------
-fetchKeywordsFileResponder::fetchKeywordsFileResponder(const std::string& filespec)
-: mFileSpec(filespec)
+class fetchKeywordsFileResponder : public LLHTTPClient::Responder
{
- LL_DEBUGS("SyntaxLSL") << "Instantiating with file saving to: '" << filespec << "'" << LL_ENDL;
-}
+public:
+ fetchKeywordsFileResponder(const std::string& filespec)
+ : mFileSpec(filespec)
+ {
+ LL_DEBUGS("SyntaxLSL") << "Instantiating with file saving to: '" << filespec << "'" << LL_ENDL;
+ }
-void fetchKeywordsFileResponder::errorWithContent(U32 status,
- const std::string& reason,
- const LLSD& content)
-{
- LLSyntaxIdLSL::getInstance()->mLoadFailed = true;
- LL_WARNS("SyntaxLSL") << "fetchKeywordsFileResponder error [status:" << status << "]: " << content << LL_ENDL;
-}
+ virtual void errorWithContent(U32 status,
+ const std::string& reason,
+ const LLSD& content)
+ {
+ LL_WARNS("SyntaxLSL") << "failed to fetch syntax file [status:" << status << "]: " << content << LL_ENDL;
+ }
-void fetchKeywordsFileResponder::result(const LLSD& content_ref)
-{
+ virtual void result(const LLSD& content_ref)
+ {
// Continue only if a valid LLSD object was returned.
if (content_ref.isMap())
{
- LL_DEBUGS("SyntaxLSL") << "content_ref isMap so assuming valid XML." << LL_ENDL;
-
if (LLSyntaxIdLSL::getInstance()->isSupportedVersion(content_ref))
{
- LL_DEBUGS("SyntaxLSL") << "Supported verson of syntax file." << LL_ENDL;
-
LLSyntaxIdLSL::getInstance()->setKeywordsXml(content_ref);
- LLSyntaxIdLSL::getInstance()->mInitialized = true;
- LLSyntaxIdLSL::getInstance()->mLoaded = true;
- LLSyntaxIdLSL::getInstance()->mLoadFailed = false;
cacheFile(content_ref);
+ LLSyntaxIdLSL::getInstance()->handleFileFetched(mFileSpec);
}
else
{
- LLSyntaxIdLSL::getInstance()->mLoaded = false;
- LLSyntaxIdLSL::getInstance()->mLoadFailed = true;
LL_WARNS("SyntaxLSL") << "Unknown or unsupported version of syntax file." << LL_ENDL;
}
}
else
{
- LLSyntaxIdLSL::getInstance()->mLoaded = false;
- LLSyntaxIdLSL::getInstance()->mLoadFailed = true;
LL_WARNS("SyntaxLSL") << "Syntax file '" << mFileSpec << "' contains invalid LLSD." << LL_ENDL;
}
-
- LLSyntaxIdLSL::getInstance()->mFileFetchedSignal();
}
-void fetchKeywordsFileResponder::cacheFile(const LLSD& content_ref)
-{
- std::stringstream str;
- LLSDSerialize::toPrettyXML(content_ref, str);
- const std::string xml = str.str();
-
- // save the str to disc, usually to the cache.
- llofstream file(mFileSpec, std::ios_base::out);
- file.write(xml.c_str(), str.str().size());
- file.close();
+ void cacheFile(const LLSD& content_ref)
+ {
+ std::stringstream str;
+ LLSDSerialize::toXML(content_ref, str);
+ const std::string xml = str.str();
- LL_DEBUGS("SyntaxLSL") << "Syntax file received, saving as: '" << mFileSpec << "'" << LL_ENDL;
-}
+ // save the str to disk, usually to the cache.
+ llofstream file(mFileSpec, std::ios_base::out);
+ file.write(xml.c_str(), str.str().size());
+ file.close();
+ LL_DEBUGS("SyntaxLSL") << "Syntax file received, saving as: '" << mFileSpec << "'" << LL_ENDL;
+ }
+
+private:
+ std::string mFileSpec;
+};
+
//-----------------------------------------------------------------------------
// LLSyntaxIdLSL
//-----------------------------------------------------------------------------
-const std::string LLSyntaxIdLSL::CAPABILITY_NAME = "LSLSyntax";
-const std::string LLSyntaxIdLSL::FILENAME_DEFAULT = "keywords_lsl_default.xml";
-const std::string LLSyntaxIdLSL::SIMULATOR_FEATURE = "LSLSyntaxId";
+const std::string SYNTAX_ID_CAPABILITY_NAME = "LSLSyntax";
+const std::string SYNTAX_ID_SIMULATOR_FEATURE = "LSLSyntaxId";
+const std::string FILENAME_DEFAULT = "keywords_lsl_default.xml";
/**
* @brief LLSyntaxIdLSL constructor
*/
-LLSyntaxIdLSL::LLSyntaxIdLSL() :
- mInitialized(false),
- mKeywordsXml(LLSD()),
- mLoaded(false),
- mLoadFailed(false),
- mVersionChanged(false),
- mCapabilityName(CAPABILITY_NAME),
- mCapabilityURL(""),
- mFileNameCurrent(FILENAME_DEFAULT),
- mFileNameDefault(FILENAME_DEFAULT),
- mFileNameNew(""),
- mFilePath(LL_PATH_APP_SETTINGS),
- mSimulatorFeature(SIMULATOR_FEATURE),
- mSyntaxIdCurrent(LLUUID()),
- mSyntaxIdNew(LLUUID())
+LLSyntaxIdLSL::LLSyntaxIdLSL()
+: mKeywordsXml(LLSD())
+, mCapabilityURL(std::string())
+, mFilePath(LL_PATH_APP_SETTINGS)
+, mSyntaxId(LLUUID())
{
+ mRegionChangedCallback = gAgent.addRegionChangedCallback(boost::bind(&LLSyntaxIdLSL::handleRegionChanged, this));
+ handleRegionChanged(); // Kick off an initial caps query and fetch
}
void LLSyntaxIdLSL::buildFullFileSpec()
{
- ELLPath path = mSyntaxIdNew.isNull() ? LL_PATH_APP_SETTINGS : LL_PATH_CACHE;
- mFileNameNew = mSyntaxIdNew.isNull() ? mFileNameDefault : "keywords_lsl_" + mSyntaxIdNew.asString() + ".llsd.xml";
- mFullFileSpec = gDirUtilp->getExpandedFilename(path, mFileNameNew);
+ ELLPath path = mSyntaxId.isNull() ? LL_PATH_APP_SETTINGS : LL_PATH_CACHE;
+ const std::string filename = mSyntaxId.isNull() ? FILENAME_DEFAULT : "keywords_lsl_" + mSyntaxId.asString() + ".llsd.xml";
+ mFullFileSpec = gDirUtilp->getExpandedFilename(path, filename);
}
//-----------------------------------------------------------------------------
-// checkSyntaxIdChange()
+// syntaxIdChange()
//-----------------------------------------------------------------------------
-bool LLSyntaxIdLSL::checkSyntaxIdChanged()
+bool LLSyntaxIdLSL::syntaxIdChanged()
{
- mVersionChanged = false;
+ bool version_changed = false;
LLViewerRegion* region = gAgent.getRegion();
if (region)
{
- if (!region->capabilitiesReceived())
- { // Shouldn't be possible, but experience shows that it may be needed.
- mLoadFailed = true;
- LL_INFOS("SyntaxLSL") << "Region '" << region->getName() << "' has not received capabilities yet. Cannot process SyntaxId." << LL_ENDL;
- }
- else
+ if (region->capabilitiesReceived())
{
- LLSD simFeatures;
- region->getSimulatorFeatures(simFeatures);
+ LLSD sim_features;
+ region->getSimulatorFeatures(sim_features);
- // Does the sim have the required feature
- if (simFeatures.has(mSimulatorFeature))
+ if (sim_features.has(SYNTAX_ID_SIMULATOR_FEATURE))
{
// get and check the hash
- mSyntaxIdNew = simFeatures[mSimulatorFeature].asUUID();
- mCapabilityURL = region->getCapability(mCapabilityName);
- if (mSyntaxIdCurrent != mSyntaxIdNew)
- {
- LL_DEBUGS("SyntaxLSL") << "Region has LSLSyntaxId capability, and the new hash is '" << mSyntaxIdNew.asString() << "'" << LL_ENDL;
-
- mVersionChanged = true;
- }
- else
- {
- LL_DEBUGS("SyntaxLSL") << "Region has the same LSLSyntaxId! Leaving hash as '" << mSyntaxIdCurrent.asString() << "'" << LL_ENDL;
- }
- }
- else
- {
- if ( mSyntaxIdCurrent.isNull() && isInitialized())
+ LLUUID new_syntax_id = sim_features[SYNTAX_ID_SIMULATOR_FEATURE].asUUID();
+ mCapabilityURL = region->getCapability(SYNTAX_ID_CAPABILITY_NAME);
+ LL_DEBUGS("SyntaxLSL") << SYNTAX_ID_SIMULATOR_FEATURE << " capability URL: " << mCapabilityURL << LL_ENDL;
+ if (new_syntax_id != mSyntaxId)
{
- LL_DEBUGS("SyntaxLSL") << "Region does not have LSLSyntaxId capability, remaining with default keywords." << LL_ENDL;
+ LL_DEBUGS("SyntaxLSL") << "New SyntaxID '" << new_syntax_id << "' found." << LL_ENDL;
+ mSyntaxId = new_syntax_id;
+ version_changed = true;
}
else
- {
- // The hash is set to NULL_KEY to indicate use of default keywords file
- mSyntaxIdNew = LLUUID();
- LL_DEBUGS("SyntaxLSL") << "Region does not have LSLSyntaxId capability, using default keywords." << LL_ENDL;
- mVersionChanged = true;
- }
+ LL_DEBUGS("SyntaxLSL") << "SyntaxID matches what we have." << LL_ENDL;
}
}
+ else
+ {
+ LL_WARNS("SyntaxLSL") << "Region '" << region->getName() << "' has not received capabilities. Cannot process SyntaxId." << LL_ENDL;
+ }
}
- return mVersionChanged;
-}
-
-/**
- * @brief LLSyntaxIdLSL::fetching
- * If the XML has not loaded yet and it hasn't failed, then we're still fetching it.
- * @return bool Whether the file fetch is still in process.
- */
-bool LLSyntaxIdLSL::fetching()
-{
- return !(mLoaded || mLoadFailed);
+ return version_changed;
}
//-----------------------------------------------------------------------------
// fetchKeywordsFile
//-----------------------------------------------------------------------------
-void LLSyntaxIdLSL::fetchKeywordsFile()
+void LLSyntaxIdLSL::fetchKeywordsFile(const std::string& filespec)
{
+ mInflightFetches.push_back(filespec);
LLHTTPClient::get(mCapabilityURL,
- new fetchKeywordsFileResponder(mFullFileSpec),
- LLSD(), 30.f
- );
- LL_DEBUGS("SyntaxLSL") << "LSLSyntaxId capability URL is: " << mCapabilityURL << ". Filename to use is: '" << mFullFileSpec << "'." << LL_ENDL;
+ new fetchKeywordsFileResponder(filespec),
+ LLSD(), 30.f);
+ LL_DEBUGS("SyntaxLSL") << "LSLSyntaxId capability URL is: " << mCapabilityURL << ". Filename to use is: '" << filespec << "'." << LL_ENDL;
}
@@ -219,55 +179,40 @@ void LLSyntaxIdLSL::fetchKeywordsFile()
//-----------------------------------------------------------------------------
void LLSyntaxIdLSL::initialize()
{
- mFileNameNew = mFileNameCurrent;
- mSyntaxIdNew = mSyntaxIdCurrent;
-
- if (checkSyntaxIdChanged())
+ if (mSyntaxId.isNull())
{
- mKeywordsXml = LLSD();
- mLoaded = mLoadFailed = false;
+ loadDefaultKeywordsIntoLLSD();
+ }
+ else if (!mCapabilityURL.empty())
+ {
+ LL_DEBUGS("SyntaxLSL") << "LSL version has changed, getting appropriate file." << LL_ENDL;
- if (mSyntaxIdNew.isNull())
- { // Need to open the default
- loadDefaultKeywordsIntoLLSD();
- }
- else if (!mCapabilityURL.empty() )
+ // Need a full spec regardless of file source, so build it now.
+ buildFullFileSpec();
+ if (mSyntaxId.notNull())
{
- LL_DEBUGS("SyntaxLSL") << "LSL version has changed, getting appropriate file." << LL_ENDL;
-
- // Need a full spec regardless of file source, so build it now.
- buildFullFileSpec();
- if ( !mSyntaxIdNew.isNull())
- {
- if ( !gDirUtilp->fileExists(mFullFileSpec) )
- { // Does not exist, so fetch it from the capability
- LL_INFOS("SyntaxLSL") << "LSL syntax not cached, attempting download." << LL_ENDL;
- fetchKeywordsFile();
- }
- else
- {
- loadKeywordsIntoLLSD();
- }
+ if (!gDirUtilp->fileExists(mFullFileSpec))
+ { // Does not exist, so fetch it from the capability
+ LL_DEBUGS("SyntaxLSL") << "LSL syntax not cached, attempting download." << LL_ENDL;
+ fetchKeywordsFile(mFullFileSpec);
}
else
- { // Need to open the default
- loadDefaultKeywordsIntoLLSD();
+ {
+ LL_DEBUGS("SyntaxLSL") << "Found cached Syntax file: " << mFullFileSpec << " Loading keywords." << LL_ENDL;
+ loadKeywordsIntoLLSD();
}
}
else
{
- mLoadFailed = true;
- LL_WARNS("SyntaxLSL") << "LSLSyntaxId capability URL is empty." << LL_ENDL;
+ LL_DEBUGS("SyntaxLSL") << "LSLSyntaxId is null. Loading default values" << LL_ENDL;
loadDefaultKeywordsIntoLLSD();
}
}
- else if (!isInitialized())
+ else
{
+ LL_DEBUGS("SyntaxLSL") << "LSLSyntaxId capability URL is empty." << LL_ENDL;
loadDefaultKeywordsIntoLLSD();
}
-
- mFileNameCurrent = mFileNameNew;
- mSyntaxIdCurrent = mSyntaxIdNew;
}
//-----------------------------------------------------------------------------
@@ -278,7 +223,7 @@ const std::string LLSD_SYNTAX_LSL_VERSION_KEY("llsd-lsl-syntax-version");
bool LLSyntaxIdLSL::isSupportedVersion(const LLSD& content)
{
- bool isValid = false;
+ bool is_valid = false;
/*
* If the schema used to store LSL keywords and hints changes, this value is incremented
* Note that it should _not_ be changed if the keywords and hints _content_ changes.
@@ -290,15 +235,15 @@ bool LLSyntaxIdLSL::isSupportedVersion(const LLSD& content)
if (content[LLSD_SYNTAX_LSL_VERSION_KEY].asInteger() == LLSD_SYNTAX_LSL_VERSION_EXPECTED)
{
- isValid = true;
+ is_valid = true;
}
}
else
{
- LL_DEBUGS("SyntaxLSL") << "No LSL syntax version key." << LL_ENDL;
+ LL_DEBUGS("SyntaxLSL") << "Missing LSL syntax version key." << LL_ENDL;
}
- return isValid;
+ return is_valid;
}
//-----------------------------------------------------------------------------
@@ -306,8 +251,7 @@ bool LLSyntaxIdLSL::isSupportedVersion(const LLSD& content)
//-----------------------------------------------------------------------------
void LLSyntaxIdLSL::loadDefaultKeywordsIntoLLSD()
{
- LL_DEBUGS("SyntaxLSL") << "LSLSyntaxId is null so we will use the default file." << LL_ENDL;
- mSyntaxIdNew = LLUUID();
+ mSyntaxId.setNull();
buildFullFileSpec();
loadKeywordsIntoLLSD();
}
@@ -323,46 +267,52 @@ void LLSyntaxIdLSL::loadDefaultKeywordsIntoLLSD()
*/
void LLSyntaxIdLSL::loadKeywordsIntoLLSD()
{
- LL_DEBUGS("SyntaxLSL") << "Trying to open cached or default keyword file" << LL_ENDL;
-
- // Is this the right thing to do, or should we leave the old content
- // even if it isn't entirely accurate anymore?
- mKeywordsXml = LLSD().emptyMap();
-
LLSD content;
llifstream file;
file.open(mFullFileSpec);
if (file.is_open())
{
- mLoaded = (bool)LLSDSerialize::fromXML(content, file);
- if (!mLoaded)
- {
- LL_WARNS("SyntaxLSL") << "Unable to deserialise: " << mFullFileSpec << LL_ENDL;
- }
- else
+ if (LLSDSerialize::fromXML(content, file) != LLSDParser::PARSE_FAILURE)
{
if (isSupportedVersion(content))
{
- mKeywordsXml = content;
- mLoaded = true;
- mInitialized = true;
LL_DEBUGS("SyntaxLSL") << "Deserialised: " << mFullFileSpec << LL_ENDL;
}
else
{
- mLoaded = false;
LL_WARNS("SyntaxLSL") << "Unknown or unsupported version of syntax file." << LL_ENDL;
}
}
}
else
{
- LL_WARNS("SyntaxLSL") << "Unable to open: " << mFullFileSpec << LL_ENDL;
+ LL_WARNS("SyntaxLSL") << "Failed to open: " << mFullFileSpec << LL_ENDL;
+ }
+ mKeywordsXml = content;
+ mSyntaxIDChangedSignal();
+}
+
+bool LLSyntaxIdLSL::keywordFetchInProgress()
+{
+ return !mInflightFetches.empty();
+}
+
+void LLSyntaxIdLSL::handleRegionChanged()
+{
+ if (syntaxIdChanged())
+ {
+ buildFullFileSpec();
+ fetchKeywordsFile(mFullFileSpec);
}
- mLoadFailed = !mLoaded;
}
-boost::signals2::connection LLSyntaxIdLSL::addFileFetchedCallback(const file_fetched_signal_t::slot_type& cb)
+void LLSyntaxIdLSL::handleFileFetched(const std::string& filepath)
+{
+ mInflightFetches.remove(filepath);
+ loadKeywordsIntoLLSD();
+}
+
+boost::signals2::connection LLSyntaxIdLSL::addSyntaxIDCallback(const syntax_id_changed_signal_t::slot_type& cb)
{
- return mFileFetchedSignal.connect(cb);
+ return mSyntaxIDChangedSignal.connect(cb);
}