diff --git a/OpenSim/Framework/IImprovedAssetCache.cs b/OpenSim/Framework/IImprovedAssetCache.cs index 251215a559..a0b8b55aaa 100644 --- a/OpenSim/Framework/IImprovedAssetCache.cs +++ b/OpenSim/Framework/IImprovedAssetCache.cs @@ -33,6 +33,7 @@ namespace OpenSim.Framework { void Cache(AssetBase asset); AssetBase Get(string id); + bool Check(string id); void Expire(string id); void Clear(); } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index ea3c6a4f81..edb1a9dabc 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -3992,7 +3992,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP const float TIME_DILATION = 1.0f; ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f); - if (terseAgentUpdateBlocks.IsValueCreated) { @@ -11695,14 +11694,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP cachedresp.WearableData = new AgentCachedTextureResponsePacket.WearableDataBlock[cachedtex.WearableData.Length]; - for (int i = 0; i < cachedtex.WearableData.Length; i++) + IImprovedAssetCache cache = m_scene.RequestModuleInterface(); + if (cache == null) { - cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); - cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; - cachedresp.WearableData[i].TextureID = UUID.Zero; - cachedresp.WearableData[i].HostName = new byte[0]; + for (int i = 0; i < cachedtex.WearableData.Length; i++) + { + cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); + cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; + cachedresp.WearableData[i].TextureID = UUID.Zero; + cachedresp.WearableData[i].HostName = new byte[0]; + } + } + else + { + for (int i = 0; i < cachedtex.WearableData.Length; i++) + { + cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); + cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; + if(cache.Check(cachedtex.WearableData[i].ID.ToString())) + cachedresp.WearableData[i].TextureID = UUID.Zero; + else + cachedresp.WearableData[i].TextureID = UUID.Zero; + cachedresp.WearableData[i].HostName = new byte[0]; + } } - cachedresp.Header.Zerocoded = true; OutPacket(cachedresp, ThrottleOutPacketType.Task); diff --git a/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs b/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs index e40caeca4d..f43305ff40 100644 --- a/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs @@ -194,6 +194,12 @@ namespace OpenSim.Region.CoreModules.Asset #region IImprovedAssetCache Members + + public bool Check(string id) + { + return false; + } + /// /// Cache asset. /// diff --git a/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs b/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs index 9742a5caa4..58ce61ac4e 100644 --- a/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs @@ -112,6 +112,10 @@ namespace OpenSim.Region.CoreModules.Asset //////////////////////////////////////////////////////////// // IImprovedAssetCache // + public bool Check(string id) + { + return false; + } public void Cache(AssetBase asset) { diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index b1bb56bb0b..a0f1e8c560 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -348,6 +348,17 @@ namespace OpenSim.Region.CoreModules.Asset return asset; } + private bool CheckFromMemoryCache(string id) + { + AssetBase asset = null; + + if (m_MemoryCache.TryGetValue(id, out asset)) + return true; + + return false; + } + + /// /// Try to get an asset from the file cache. /// @@ -420,6 +431,50 @@ namespace OpenSim.Region.CoreModules.Asset return asset; } + private bool CheckFromFileCache(string id) + { + bool found = false; + + string filename = GetFileName(id); + if (File.Exists(filename)) + { + // actually check if we can open it, and so update expire + FileStream stream = null; + try + { + stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read); + if (stream != null) + { + found = true; + stream.Close(); + } + + } + catch (System.Runtime.Serialization.SerializationException e) + { + found = false; + m_log.ErrorFormat( + "[FLOTSAM ASSET CACHE]: Failed to check file {0} for asset {1}. Exception {2} {3}", + filename, id, e.Message, e.StackTrace); + + // If there was a problem deserializing the asset, the asset may + // either be corrupted OR was serialized under an old format + // {different version of AssetBase} -- we should attempt to + // delete it and re-cache + File.Delete(filename); + } + catch (Exception e) + { + found = false; + m_log.ErrorFormat( + "[FLOTSAM ASSET CACHE]: Failed to check file {0} for asset {1}. Exception {2} {3}", + filename, id, e.Message, e.StackTrace); + } + } + + return found; + } + public AssetBase Get(string id) { m_Requests++; @@ -456,11 +511,26 @@ namespace OpenSim.Region.CoreModules.Asset return asset; } + public bool Check(string id) + { + if (m_MemoryCacheEnabled && CheckFromMemoryCache(id)) + return true; + + if (m_FileCacheEnabled && CheckFromFileCache(id)) + return true; + return false; + } + public AssetBase GetCached(string id) { return Get(id); } + public AssetBase CheckCached(string id) + { + return Get(id); + } + public void Expire(string id) { if (m_LogLevel >= 2) @@ -941,6 +1011,11 @@ namespace OpenSim.Region.CoreModules.Asset return asset.Data; } + public bool CheckData(string id) + { + return Check(id); ; + } + public bool Get(string id, object sender, AssetRetrieved handler) { AssetBase asset = Get(id); diff --git a/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs b/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs index 9592ca0019..ce9b5467f6 100644 --- a/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs @@ -115,6 +115,11 @@ namespace OpenSim.Region.CoreModules.Asset // IImprovedAssetCache // + public bool Check(string id) + { + return false; + } + public void Cache(AssetBase asset) { if (asset != null) diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index 4c42397cc5..3532b1dfe2 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -361,6 +361,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory public bool ValidateBakedTextureCache(IScenePresence sp) { bool defonly = true; // are we only using default textures + IImprovedAssetCache cache = m_scene.RequestModuleInterface(); // Process the texture entry for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) @@ -385,8 +386,16 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory defonly = false; // found a non-default texture reference - if (m_scene.AssetService.Get(face.TextureID.ToString()) == null) - return false; + if (cache != null) + { + if (!cache.Check(face.TextureID.ToString())) + return false; + } + else + { + if (m_scene.AssetService.Get(face.TextureID.ToString()) == null) + return false; + } } // m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0} {1}", sp.Name, sp.UUID); @@ -398,6 +407,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory public int RequestRebake(IScenePresence sp, bool missingTexturesOnly) { int texturesRebaked = 0; + IImprovedAssetCache cache = m_scene.RequestModuleInterface(); for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) { @@ -421,21 +431,36 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory if (missingTexturesOnly) { - if (m_scene.AssetService.Get(face.TextureID.ToString()) != null) + if (cache != null) { - continue; + if (cache.Check(face.TextureID.ToString())) + continue; + else + { + m_log.DebugFormat( + "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.", + face.TextureID, idx, sp.Name); + } } else { - // On inter-simulator teleports, this occurs if baked textures are not being stored by the - // grid asset service (which means that they are not available to the new region and so have - // to be re-requested from the client). - // - // The only available core OpenSimulator behaviour right now - // is not to store these textures, temporarily or otherwise. - m_log.DebugFormat( - "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.", - face.TextureID, idx, sp.Name); + if (m_scene.AssetService.Get(face.TextureID.ToString()) != null) + { + continue; + } + + else + { + // On inter-simulator teleports, this occurs if baked textures are not being stored by the + // grid asset service (which means that they are not available to the new region and so have + // to be re-requested from the client). + // + // The only available core OpenSimulator behaviour right now + // is not to store these textures, temporarily or otherwise. + m_log.DebugFormat( + "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.", + face.TextureID, idx, sp.Name); + } } } else