@@ -92,7 +92,7 @@ class LLDispatchEmptyMuteList : public LLDispatchHandler
9292 const LLUUID& invoice,
9393 const sparam_t & strings)
9494 {
95- LLMuteList::getInstance ()->setLoaded ();
95+ LLMuteList::getInstance ()->setLoaded (LLMuteList::MLS_SERVER_EMPTY );
9696 return true ;
9797 }
9898};
@@ -155,7 +155,9 @@ std::string LLMute::getDisplayType() const
155155// -----------------------------------------------------------------------------
156156LLMuteList::LLMuteList () :
157157 mLoadState(ML_INITIAL),
158- mRequestStartTime(0 .f)
158+ mLoadSource(MLS_NONE),
159+ mRequestStartTime(0 .f),
160+ mTriedCacheFallback(false )
159161{
160162 gGenericDispatcher .addHandler (" emptymutelist" , &sDispatchEmptyMuteList );
161163
@@ -210,7 +212,7 @@ bool LLMuteList::isLinden(const std::string& name)
210212 return last_name == " linden" ;
211213}
212214
213- bool LLMuteList::getLoadFailed () const
215+ bool LLMuteList::getLoadFailed ()
214216{
215217 if (mLoadState == ML_FAILED)
216218 {
@@ -221,12 +223,78 @@ bool LLMuteList::getLoadFailed() const
221223 constexpr F64 WAIT_SECONDS = 30 ;
222224 if (mRequestStartTime + WAIT_SECONDS < LLTimer::getTotalSeconds ())
223225 {
224- return true ;
226+ LL_WARNS () << " Mute list request timed out; trying cache fallback once" << LL_ENDL;
227+ tryLoadCacheFallback (gAgent .getID (), " request timeout" );
228+ return mLoadState == ML_FAILED;
225229 }
226230 }
227231 return false ;
228232}
229233
234+ const char * LLMuteList::sourceToString (EMuteListSource source)
235+ {
236+ switch (source)
237+ {
238+ case MLS_NONE:
239+ return " none" ;
240+ case MLS_SERVER:
241+ return " server" ;
242+ case MLS_SERVER_EMPTY:
243+ return " server-empty" ;
244+ case MLS_SERVER_CACHE:
245+ return " server-cached" ;
246+ case MLS_FALLBACK_CACHE:
247+ return " fallback-cache" ;
248+ default :
249+ return " unknown" ;
250+ }
251+ }
252+
253+ std::string LLMuteList::getCacheFilename (const LLUUID& agent_id) const
254+ {
255+ std::string agent_id_string;
256+ agent_id.toString (agent_id_string);
257+ return gDirUtilp ->getExpandedFilename (LL_PATH_CACHE, agent_id_string) + " .cached_mute" ;
258+ }
259+
260+ void LLMuteList::setFailed (const std::string& reason)
261+ {
262+ mLoadState = ML_FAILED;
263+ if (mLoadSource == MLS_NONE)
264+ {
265+ LL_WARNS () << " Mute list unavailable: " << reason << LL_ENDL;
266+ }
267+ else
268+ {
269+ LL_WARNS () << " Mute list unavailable: " << reason << " (last source=" << sourceToString (mLoadSource ) << " )" << LL_ENDL;
270+ }
271+ }
272+
273+ bool LLMuteList::tryLoadCacheFallback (const LLUUID& agent_id, const std::string& reason)
274+ {
275+ if (mTriedCacheFallback )
276+ {
277+ if (!isLoaded ())
278+ {
279+ setFailed (" cache fallback already attempted before " + reason);
280+ }
281+ return isLoaded ();
282+ }
283+
284+ mTriedCacheFallback = true ;
285+ const std::string filename = getCacheFilename (agent_id);
286+ LL_INFOS () << " Trying mute list cache fallback due to " << reason << " : " << filename << LL_ENDL;
287+
288+ if (loadFromFile (filename, MLS_FALLBACK_CACHE))
289+ {
290+ LL_WARNS () << " Loaded mute list from cache fallback due to " << reason << LL_ENDL;
291+ return true ;
292+ }
293+
294+ setFailed (" cache fallback failed after " + reason);
295+ return false ;
296+ }
297+
230298static LLVOAvatar* find_avatar (const LLUUID& id)
231299{
232300 LLViewerObject *obj = gObjectList .findObject (id);
@@ -580,25 +648,29 @@ std::vector<LLMute> LLMuteList::getMutes() const
580648// -----------------------------------------------------------------------------
581649// loadFromFile()
582650// -----------------------------------------------------------------------------
583- bool LLMuteList::loadFromFile (const std::string& filename)
651+ bool LLMuteList::loadFromFile (const std::string& filename, EMuteListSource source )
584652{
585653 LL_PROFILE_ZONE_SCOPED;
586654
587655 if (!filename.size ())
588656 {
589657 LL_WARNS () << " Mute List Filename is Empty!" << LL_ENDL;
590- mLoadState = ML_FAILED ;
658+ setFailed ( " empty filename " ) ;
591659 return false ;
592660 }
593661
594662 LLFILE* fp = LLFile::fopen (filename, " rb" ); /* Flawfinder: ignore*/
595663 if (!fp)
596664 {
597665 LL_WARNS () << " Couldn't open mute list " << filename << LL_ENDL;
598- mLoadState = ML_FAILED ;
666+ setFailed ( " cannot open " + filename) ;
599667 return false ;
600668 }
601669
670+ // Replace previous server-backed state so fallback can be superseded by authoritative data.
671+ mMutes .clear ();
672+ mLegacyMutes .clear ();
673+
602674 // *NOTE: Changing the size of these buffers will require changes
603675 // in the scanf below.
604676 char id_buffer[MAX_STRING]; /* Flawfinder: ignore*/
@@ -627,7 +699,7 @@ bool LLMuteList::loadFromFile(const std::string& filename)
627699 }
628700 }
629701 fclose (fp);
630- setLoaded ();
702+ setLoaded (source );
631703
632704 // server does not maintain up-to date account names (not display names!)
633705 // in this list, so it falls to viewer.
@@ -737,12 +809,11 @@ bool LLMuteList::isMuted(const std::string& username, U32 flags) const
737809// -----------------------------------------------------------------------------
738810void LLMuteList::requestFromServer (const LLUUID& agent_id)
739811{
740- std::string agent_id_string;
741- std::string filename;
742- agent_id.toString (agent_id_string);
743- filename = gDirUtilp ->getExpandedFilename (LL_PATH_CACHE,agent_id_string) + " .cached_mute" ;
812+ const std::string filename = getCacheFilename (agent_id);
744813 LLCRC crc;
745814 crc.update (filename);
815+ mTriedCacheFallback = false ;
816+ mLoadSource = MLS_NONE;
746817
747818 LLMessageSystem* msg = gMessageSystem ;
748819 msg->newMessageFast (_PREHASH_MuteListRequest);
@@ -755,17 +826,17 @@ void LLMuteList::requestFromServer(const LLUUID& agent_id)
755826 if (gDisconnected )
756827 {
757828 LL_WARNS () << " Trying to request mute list when disconnected!" << LL_ENDL;
758- mLoadState = ML_FAILED ;
829+ tryLoadCacheFallback (agent_id, " disconnected before request " ) ;
759830 return ;
760831 }
761832 if (!gAgent .getRegion ())
762833 {
763834 LL_WARNS () << " No region for agent yet, skipping mute list request!" << LL_ENDL;
764- mLoadState = ML_FAILED ;
835+ tryLoadCacheFallback (agent_id, " no region for request " ) ;
765836 return ;
766837 }
767838 mLoadState = ML_REQUESTED;
768- mRequestStartTime = LLTimer::getElapsedSeconds ();
839+ mRequestStartTime = LLTimer::getTotalSeconds ();
769840 // Double amount of retries due to this request happening during busy stage
770841 // Ideally this should be turned into a capability
771842 gMessageSystem ->sendReliable (gAgent .getRegionHost (), LL_DEFAULT_RELIABLE_RETRIES * 2 , true , LL_PING_BASED_TIMEOUT_DUMMY, NULL , NULL );
@@ -777,15 +848,16 @@ void LLMuteList::requestFromServer(const LLUUID& agent_id)
777848
778849void LLMuteList::cache (const LLUUID& agent_id)
779850{
780- // Write to disk even if empty.
781- if (isLoaded ())
851+ // Write to disk even if empty, but never from degraded fallback state .
852+ if (isLoaded () && mLoadSource != MLS_FALLBACK_CACHE )
782853 {
783- std::string agent_id_string;
784- std::string filename;
785- agent_id.toString (agent_id_string);
786- filename = gDirUtilp ->getExpandedFilename (LL_PATH_CACHE,agent_id_string) + " .cached_mute" ;
854+ const std::string filename = getCacheFilename (agent_id);
787855 saveToFile (filename);
788856 }
857+ else if (isLoaded ())
858+ {
859+ LL_WARNS () << " Skipping mute list cache write from fallback-only state" << LL_ENDL;
860+ }
789861}
790862
791863// -----------------------------------------------------------------------------
@@ -812,7 +884,7 @@ void LLMuteList::processMuteListUpdate(LLMessageSystem* msg, void**)
812884
813885 LLMuteList* mute_list = getInstance ();
814886 mute_list->mLoadState = ML_REQUESTED;
815- mute_list->mRequestStartTime = LLTimer::getElapsedSeconds ();
887+ mute_list->mRequestStartTime = LLTimer::getTotalSeconds ();
816888
817889 // Todo: Based of logs and testing, there is no callback
818890 // from server if file doesn't exist server side.
@@ -831,12 +903,7 @@ void LLMuteList::processMuteListUpdate(LLMessageSystem* msg, void**)
831903void LLMuteList::processUseCachedMuteList (LLMessageSystem* msg, void **)
832904{
833905 LL_INFOS () << " LLMuteList::processUseCachedMuteList()" << LL_ENDL;
834-
835- std::string agent_id_string;
836- gAgent .getID ().toString (agent_id_string);
837- std::string filename;
838- filename = gDirUtilp ->getExpandedFilename (LL_PATH_CACHE,agent_id_string) + " .cached_mute" ;
839- LLMuteList::getInstance ()->loadFromFile (filename);
906+ LLMuteList::getInstance ()->loadFromFile (LLMuteList::getInstance ()->getCacheFilename (gAgent .getID ()), MLS_SERVER_CACHE);
840907}
841908
842909void LLMuteList::onFileMuteList (void ** user_data, S32 error_code, LLExtStat ext_status)
@@ -845,13 +912,13 @@ void LLMuteList::onFileMuteList(void** user_data, S32 error_code, LLExtStat ext_
845912 if (local_filename_and_path && !local_filename_and_path->empty () && (error_code == 0 ))
846913 {
847914 LL_INFOS () << " Received mute list from server" << LL_ENDL;
848- LLMuteList::getInstance ()->loadFromFile (*local_filename_and_path);
915+ LLMuteList::getInstance ()->loadFromFile (*local_filename_and_path, MLS_SERVER );
849916 LLFile::remove (*local_filename_and_path);
850917 }
851918 else
852919 {
853920 LL_INFOS () << " LLMuteList xfer failed with code " << error_code << LL_ENDL;
854- LLMuteList::getInstance ()->mLoadState = ML_FAILED ;
921+ LLMuteList::getInstance ()->tryLoadCacheFallback ( gAgent . getID (), " xfer failure " ) ;
855922 }
856923 delete local_filename_and_path;
857924}
@@ -908,9 +975,10 @@ void LLMuteList::removeObserver(LLMuteListObserver* observer)
908975 mObservers .erase (observer);
909976}
910977
911- void LLMuteList::setLoaded ()
978+ void LLMuteList::setLoaded (EMuteListSource source )
912979{
913980 mLoadState = ML_LOADED;
981+ mLoadSource = source;
914982 notifyObservers ();
915983}
916984
0 commit comments