diff options
author | Cinder <cinder.roxley@phoenixviewer.com> | 2014-06-09 15:14:09 -0600 |
---|---|---|
committer | Cinder <cinder.roxley@phoenixviewer.com> | 2014-06-09 15:14:09 -0600 |
commit | 41f6c5ce4899b3ae57aefa564ee22ff84fa698ce (patch) | |
tree | 7f75bec5313e46a7afca5d264299163403865138 /indra/newview/llsyntaxid.cpp | |
parent | 58bf0dd580456f2df23c463f24791f6d580604b1 (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.cpp | 296 |
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); } |