diff --git a/OpenSim/Framework/IImprovedAssetCache.cs b/OpenSim/Framework/IAssetCache.cs
similarity index 92%
rename from OpenSim/Framework/IImprovedAssetCache.cs
rename to OpenSim/Framework/IAssetCache.cs
index a853e9015d..8477116403 100644
--- a/OpenSim/Framework/IImprovedAssetCache.cs
+++ b/OpenSim/Framework/IAssetCache.cs
@@ -29,7 +29,7 @@ using OpenSim.Framework;
namespace OpenSim.Framework
{
- public interface IImprovedAssetCache
+ public interface IAssetCache
{
///
/// Cache the specified asset.
@@ -38,6 +38,12 @@ namespace OpenSim.Framework
void Cache(AssetBase asset);
///
+ /// Cache that the specified asset wasn't found.
+ ///
+ ///
+ ///
+ void CacheNegative(string id);
+
/// Get an asset by its id.
///
///
@@ -61,4 +67,4 @@ namespace OpenSim.Framework
///
void Clear();
}
-}
\ No newline at end of file
+}
diff --git a/OpenSim/Framework/WearableCacheItem.cs b/OpenSim/Framework/WearableCacheItem.cs
index af28abc74c..966a6bc290 100644
--- a/OpenSim/Framework/WearableCacheItem.cs
+++ b/OpenSim/Framework/WearableCacheItem.cs
@@ -50,7 +50,7 @@ namespace OpenSim.Framework
return retitems;
}
- public static WearableCacheItem[] FromOSD(OSD pInput, IImprovedAssetCache dataCache)
+ public static WearableCacheItem[] FromOSD(OSD pInput, IAssetCache dataCache)
{
List ret = new List();
if (pInput.Type == OSDType.Array)
@@ -100,7 +100,7 @@ namespace OpenSim.Framework
}
- public static OSD ToOSD(WearableCacheItem[] pcacheItems, IImprovedAssetCache dataCache)
+ public static OSD ToOSD(WearableCacheItem[] pcacheItems, IAssetCache dataCache)
{
OSDArray arr = new OSDArray();
foreach (WearableCacheItem item in pcacheItems)
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index 3cb999bee5..d9fdcde732 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -206,6 +206,7 @@ namespace OpenSim
MainServer.Instance.AddStreamHandler(new OpenSim.XSimStatusHandler(this));
if (userStatsURI != String.Empty)
MainServer.Instance.AddStreamHandler(new OpenSim.UXSimStatusHandler(this));
+ MainServer.Instance.AddStreamHandler(new OpenSim.SimRobotsHandler());
if (managedStatsURI != String.Empty)
{
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs
index 90505e193f..b8363ab789 100644
--- a/OpenSim/Region/Application/OpenSimBase.cs
+++ b/OpenSim/Region/Application/OpenSimBase.cs
@@ -898,6 +898,26 @@ namespace OpenSim
}
}
+ ///
+ /// handler to supply serving http://domainname:port/robots.txt
+ ///
+ public class SimRobotsHandler : BaseStreamHandler
+ {
+ public SimRobotsHandler() : base("GET", "/robots.txt", "SimRobots.txt", "Simulator Robots.txt") {}
+
+ protected override byte[] ProcessRequest(string path, Stream request,
+ IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
+ {
+ string robots = "# go away\nUser-agent: *\nDisallow: /\n";
+ return Util.UTF8.GetBytes(robots);
+ }
+
+ public override string ContentType
+ {
+ get { return "text/plain"; }
+ }
+ }
+
#endregion
///
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index a69b670cd7..55050d9de4 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -621,7 +621,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
GroupsInView.Clear();
if(m_scene.GetNumberOfClients() == 0)
- GC.Collect();
+ {
+ GC.Collect();
+ GC.WaitForPendingFinalizers();
+ GC.Collect();
+ }
}
public void Kick(string message)
diff --git a/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs b/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs
index 47dcbcd3ff..6d1f0c2ab1 100644
--- a/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs
+++ b/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs
@@ -57,13 +57,13 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender
/// List of client methods to notify of results of decode
private readonly Dictionary> m_notifyList = new Dictionary>();
/// Cache that will store decoded JPEG2000 layer boundary data
- private IImprovedAssetCache m_cache;
- private IImprovedAssetCache Cache
+ private IAssetCache m_cache;
+ private IAssetCache Cache
{
get
{
if (m_cache == null)
- m_cache = m_scene.RequestModuleInterface();
+ m_cache = m_scene.RequestModuleInterface();
return m_cache;
}
diff --git a/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs b/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs
index ebec9d2d74..14b0280cd5 100644
--- a/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs
@@ -91,7 +91,7 @@ namespace OpenSim.Region.CoreModules.Asset
///
///
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "CenomeMemoryAssetCache")]
- public class CenomeMemoryAssetCache : IImprovedAssetCache, ISharedRegionModule
+ public class CenomeMemoryAssetCache : IAssetCache, ISharedRegionModule
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -192,7 +192,7 @@ namespace OpenSim.Region.CoreModules.Asset
expirationTime);
}
- #region IImprovedAssetCache Members
+ #region IAssetCache Members
public bool Check(string id)
{
@@ -221,6 +221,11 @@ namespace OpenSim.Region.CoreModules.Asset
}
+ public void CacheNegative(string id)
+ {
+ // We don't do negative caching
+ }
+
///
/// Clear asset cache.
///
@@ -308,7 +313,7 @@ namespace OpenSim.Region.CoreModules.Asset
public void AddRegion(Scene scene)
{
if (m_enabled)
- scene.RegisterModuleInterface(this);
+ scene.RegisterModuleInterface(this);
}
///
diff --git a/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs b/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs
index f72074851e..82bc5ccebb 100644
--- a/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs
@@ -40,7 +40,7 @@ using OpenSim.Services.Interfaces;
namespace OpenSim.Region.CoreModules.Asset
{
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "CoreAssetCache")]
- public class CoreAssetCache : ISharedRegionModule, IImprovedAssetCache
+ public class CoreAssetCache : ISharedRegionModule, IAssetCache
{
private static readonly ILog m_log =
LogManager.GetLogger(
@@ -98,7 +98,7 @@ namespace OpenSim.Region.CoreModules.Asset
public void AddRegion(Scene scene)
{
if (m_Enabled)
- scene.RegisterModuleInterface(this);
+ scene.RegisterModuleInterface(this);
}
public void RemoveRegion(Scene scene)
@@ -110,7 +110,7 @@ namespace OpenSim.Region.CoreModules.Asset
}
////////////////////////////////////////////////////////////
- // IImprovedAssetCache
+ // IAssetCache
//
public bool Check(string id)
{
@@ -124,6 +124,11 @@ namespace OpenSim.Region.CoreModules.Asset
m_Cache.Store(asset.ID, asset);
}
+ public void CacheNegative(string id)
+ {
+ // We don't do negative caching
+ }
+
public AssetBase Get(string id)
{
return (AssetBase)m_Cache.Get(id);
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index b6dd5652c7..84e13a0d9d 100644
--- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
@@ -55,7 +55,7 @@ using OpenSim.Services.Interfaces;
namespace OpenSim.Region.CoreModules.Asset
{
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "FlotsamAssetCache")]
- public class FlotsamAssetCache : ISharedRegionModule, IImprovedAssetCache, IAssetService
+ public class FlotsamAssetCache : ISharedRegionModule, IAssetCache, IAssetService
{
private static readonly ILog m_log =
LogManager.GetLogger(
@@ -78,6 +78,7 @@ namespace OpenSim.Region.CoreModules.Asset
private static ulong m_RequestsForInprogress;
private static ulong m_DiskHits;
private static ulong m_MemoryHits;
+ private static ulong m_weakRefHits;
#if WAIT_ON_INPROGRESS_REQUESTS
private Dictionary m_CurrentlyWriting = new Dictionary();
@@ -91,9 +92,15 @@ namespace OpenSim.Region.CoreModules.Asset
private ExpiringCache m_MemoryCache;
private bool m_MemoryCacheEnabled = false;
+ private ExpiringCache m_negativeCache;
+ private bool m_negativeCacheEnabled = true;
+ private bool m_negativeCacheSliding = false;
+
// Expiration is expressed in hours.
- private double m_MemoryExpiration = 0.001;
+ private double m_MemoryExpiration = 0.016;
private const double m_DefaultFileExpiration = 48;
+ // Negative cache is in seconds
+ private int m_negativeExpiration = 120;
private TimeSpan m_FileExpiration = TimeSpan.FromHours(m_DefaultFileExpiration);
private TimeSpan m_FileExpirationCleanupTimer = TimeSpan.FromHours(1.0);
@@ -107,6 +114,10 @@ namespace OpenSim.Region.CoreModules.Asset
private List m_Scenes = new List();
private object timerLock = new object();
+ private Dictionary weakAssetReferences = new Dictionary();
+ private object weakAssetReferencesLock = new object();
+ private bool m_updateFileTimeOnCacheHit = false;
+
public FlotsamAssetCache()
{
m_InvalidChars.AddRange(Path.GetInvalidPathChars());
@@ -134,6 +145,7 @@ namespace OpenSim.Region.CoreModules.Asset
if (name == Name)
{
m_MemoryCache = new ExpiringCache();
+ m_negativeCache = new ExpiringCache();
m_Enabled = true;
m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0} enabled", this.Name);
@@ -152,6 +164,11 @@ namespace OpenSim.Region.CoreModules.Asset
m_MemoryCacheEnabled = assetConfig.GetBoolean("MemoryCacheEnabled", m_MemoryCacheEnabled);
m_MemoryExpiration = assetConfig.GetDouble("MemoryCacheTimeout", m_MemoryExpiration);
m_MemoryExpiration *= 3600.0; // config in hours to seconds
+
+ m_negativeCacheEnabled = assetConfig.GetBoolean("NegativeCacheEnabled", m_negativeCacheEnabled);
+ m_negativeExpiration = assetConfig.GetInt("NegativeCacheTimeout", m_negativeExpiration);
+ m_negativeCacheSliding = assetConfig.GetBoolean("NegativeCacheSliding", m_negativeCacheSliding);
+ m_updateFileTimeOnCacheHit = assetConfig.GetBoolean("UpdateFileTimeOnCacheHit", m_updateFileTimeOnCacheHit);
#if WAIT_ON_INPROGRESS_REQUESTS
m_WaitOnInprogressTimeout = assetConfig.GetInt("WaitOnInprogressTimeout", 3000);
@@ -212,7 +229,7 @@ namespace OpenSim.Region.CoreModules.Asset
{
if (m_Enabled)
{
- scene.RegisterModuleInterface(this);
+ scene.RegisterModuleInterface(this);
m_Scenes.Add(scene);
}
}
@@ -221,7 +238,7 @@ namespace OpenSim.Region.CoreModules.Asset
{
if (m_Enabled)
{
- scene.UnregisterModuleInterface(this);
+ scene.UnregisterModuleInterface(this);
m_Scenes.Remove(scene);
lock(timerLock)
{
@@ -255,12 +272,23 @@ namespace OpenSim.Region.CoreModules.Asset
}
}
}
+ if (m_MemoryCacheEnabled)
+ m_MemoryCache = new ExpiringCache();
+
+ lock(weakAssetReferencesLock)
+ weakAssetReferences = new Dictionary();
}
}
////////////////////////////////////////////////////////////
- // IImprovedAssetCache
+ // IAssetCache
//
+ private void UpdateWeakReference(string key, AssetBase asset)
+ {
+ WeakReference aref = new WeakReference(asset);
+ lock(weakAssetReferencesLock)
+ weakAssetReferences[key] = aref;
+ }
private void UpdateMemoryCache(string key, AssetBase asset)
{
@@ -327,6 +355,7 @@ namespace OpenSim.Region.CoreModules.Asset
if (asset != null)
{
//m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Caching asset with id {0}", asset.ID);
+ UpdateWeakReference(asset.ID, asset);
if (m_MemoryCacheEnabled)
UpdateMemoryCache(asset.ID, asset);
@@ -336,6 +365,17 @@ namespace OpenSim.Region.CoreModules.Asset
}
}
+ public void CacheNegative(string id)
+ {
+ if (m_negativeCacheEnabled)
+ {
+ if (m_negativeCacheSliding)
+ m_negativeCache.AddOrUpdate(id, null, TimeSpan.FromSeconds(m_negativeExpiration));
+ else
+ m_negativeCache.AddOrUpdate(id, null, m_negativeExpiration);
+ }
+ }
+
///
/// Updates the cached file with the current time.
///
@@ -354,6 +394,25 @@ namespace OpenSim.Region.CoreModules.Asset
}
}
+ private AssetBase GetFromWeakReference(string id)
+ {
+ AssetBase asset = null;
+ WeakReference aref;
+
+ lock(weakAssetReferencesLock)
+ {
+ if (weakAssetReferences.TryGetValue(id, out aref))
+ {
+ asset = aref.Target as AssetBase;
+ if(asset == null)
+ weakAssetReferences.Remove(id);
+ else
+ m_weakRefHits++;
+ }
+ }
+ return asset;
+ }
+
///
/// Try to get an asset from the in-memory cache.
///
@@ -476,13 +535,38 @@ namespace OpenSim.Region.CoreModules.Asset
{
m_Requests++;
- AssetBase asset = null;
+ object dummy;
+ if (m_negativeCache.TryGetValue(id, out dummy))
+ return null;
- if (m_MemoryCacheEnabled)
+ AssetBase asset = null;
+ asset = GetFromWeakReference(id);
+ if (asset != null && m_updateFileTimeOnCacheHit)
+ {
+ string filename = GetFileName(id);
+ UpdateFileLastAccessTime(filename);
+ }
+
+ if (m_MemoryCacheEnabled && asset == null)
+ {
asset = GetFromMemoryCache(id);
+ if(asset != null)
+ {
+ UpdateWeakReference(id,asset);
+ if (m_updateFileTimeOnCacheHit)
+ {
+ string filename = GetFileName(id);
+ UpdateFileLastAccessTime(filename);
+ }
+ }
+ }
if (asset == null && m_FileCacheEnabled)
+ {
asset = GetFromFileCache(id);
+ if(asset != null)
+ UpdateWeakReference(id,asset);
+ }
if (m_MemoryCacheEnabled && asset != null)
UpdateMemoryCache(id, asset);
@@ -494,6 +578,12 @@ namespace OpenSim.Region.CoreModules.Asset
GenerateCacheHitReport().ForEach(l => m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0}", l));
}
+ if(asset == null)
+ {
+
+
+ }
+
return asset;
}
@@ -530,6 +620,9 @@ namespace OpenSim.Region.CoreModules.Asset
if (m_MemoryCacheEnabled)
m_MemoryCache.Remove(id);
+
+ lock(weakAssetReferencesLock)
+ weakAssetReferences.Remove(id);
}
catch (Exception e)
{
@@ -553,7 +646,12 @@ namespace OpenSim.Region.CoreModules.Asset
}
if (m_MemoryCacheEnabled)
- m_MemoryCache.Clear();
+ m_MemoryCache = new ExpiringCache();
+ if (m_negativeCacheEnabled)
+ m_negativeCache = new ExpiringCache();
+
+ lock(weakAssetReferencesLock)
+ weakAssetReferences = new Dictionary();
}
private void CleanupExpiredFiles(object source, ElapsedEventArgs e)
@@ -911,28 +1009,34 @@ namespace OpenSim.Region.CoreModules.Asset
List outputLines = new List();
double invReq = 100.0 / m_Requests;
+
+ double weakHitRate = m_weakRefHits * invReq;
+ int weakEntries = weakAssetReferences.Count;
double fileHitRate = m_DiskHits * invReq;
+ double TotalHitRate = weakHitRate + fileHitRate;
+
outputLines.Add(
- string.Format("File Hit Rate: {0}% for {1} requests", fileHitRate.ToString("0.00"), m_Requests));
+ string.Format("Total requests: {0}", m_Requests));
+ outputLines.Add(
+ string.Format("unCollected Hit Rate: {0}% ({1} entries)", weakHitRate.ToString("0.00"),weakEntries));
+ outputLines.Add(
+ string.Format("File Hit Rate: {0}%", fileHitRate.ToString("0.00")));
if (m_MemoryCacheEnabled)
{
double HitRate = m_MemoryHits * invReq;
-
outputLines.Add(
- string.Format("Memory Hit Rate: {0}% for {1} requests", HitRate.ToString("0.00"), m_Requests));
+ string.Format("Memory Hit Rate: {0}%", HitRate.ToString("0.00")));
- HitRate += fileHitRate;
-
- outputLines.Add(
- string.Format("Total Hit Rate: {0}% for {1} requests", HitRate.ToString("0.00"), m_Requests));
+ TotalHitRate += HitRate;
}
+ outputLines.Add(
+ string.Format("Total Hit Rate: {0}%", TotalHitRate.ToString("0.00")));
outputLines.Add(
string.Format(
- "Unnecessary requests due to requests for assets that are currently downloading: {0}",
- m_RequestsForInprogress));
+ "Requests overlap during file writing: {0}", m_RequestsForInprogress));
return outputLines;
}
diff --git a/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs b/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs
index 5f76ac2c9e..195bdaa43f 100644
--- a/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs
@@ -41,7 +41,7 @@ using OpenSim.Services.Interfaces;
namespace OpenSim.Region.CoreModules.Asset
{
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GlynnTuckerAssetCache")]
- public class GlynnTuckerAssetCache : ISharedRegionModule, IImprovedAssetCache
+ public class GlynnTuckerAssetCache : ISharedRegionModule, IAssetCache
{
private static readonly ILog m_log =
LogManager.GetLogger(
@@ -100,7 +100,7 @@ namespace OpenSim.Region.CoreModules.Asset
public void AddRegion(Scene scene)
{
if (m_Enabled)
- scene.RegisterModuleInterface(this);
+ scene.RegisterModuleInterface(this);
}
public void RemoveRegion(Scene scene)
@@ -112,7 +112,7 @@ namespace OpenSim.Region.CoreModules.Asset
}
////////////////////////////////////////////////////////////
- // IImprovedAssetCache
+ // IAssetCache
//
public bool Check(string id)
@@ -126,6 +126,11 @@ namespace OpenSim.Region.CoreModules.Asset
m_Cache.AddOrUpdate(asset.ID, asset);
}
+ public void CacheNegative(string id)
+ {
+ // We don't do negative caching
+ }
+
public AssetBase Get(string id)
{
Object asset = null;
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index 41a3f5239e..67256ee685 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -288,7 +288,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
if (bakedTextures.Count == 0)
return false;
- IImprovedAssetCache cache = sp.Scene.RequestModuleInterface();
+ IAssetCache cache = sp.Scene.RequestModuleInterface();
if(cache == null)
return true; // no baked local caching so nothing to do
@@ -705,7 +705,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
return 0;
int texturesRebaked = 0;
-// IImprovedAssetCache cache = m_scene.RequestModuleInterface();
+// IAssetCache cache = m_scene.RequestModuleInterface();
for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++)
{
diff --git a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
index 3f7a8ee7a9..df5265cbe8 100644
--- a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
@@ -69,7 +69,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
Dictionary m_classifiedCache = new Dictionary();
Dictionary m_classifiedInterest = new Dictionary();
ExpiringCache m_profilesCache = new ExpiringCache();
- IImprovedAssetCache m_assetCache;
+ IAssetCache m_assetCache;
private JsonRpcRequestManager rpc = new JsonRpcRequestManager();
private bool m_allowUserProfileWebURLs = true;
@@ -221,7 +221,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
{
if(!Enabled)
return;
- m_assetCache = Scene.RequestModuleInterface();
+ m_assetCache = Scene.RequestModuleInterface();
}
///
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
index 9eb41f94f6..31d112925f 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
@@ -48,7 +48,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
LogManager.GetLogger(
MethodBase.GetCurrentMethod().DeclaringType);
- private IImprovedAssetCache m_Cache = null;
+ private IAssetCache m_Cache = null;
private IAssetService m_GridService;
private IAssetService m_HGService;
@@ -176,7 +176,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
if (m_Cache == null)
{
- m_Cache = scene.RequestModuleInterface();
+ m_Cache = scene.RequestModuleInterface();
if (!(m_Cache is ISharedRegionModule))
m_Cache = null;
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
index 5f3445068b..d5d6667504 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
@@ -44,7 +44,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
- private IImprovedAssetCache m_Cache = null;
+ private IAssetCache m_Cache = null;
private IAssetService m_AssetService;
@@ -128,7 +128,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
if (m_Cache == null)
{
- m_Cache = scene.RequestModuleInterface();
+ m_Cache = scene.RequestModuleInterface();
if (!(m_Cache is ISharedRegionModule))
m_Cache = null;
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/RemoteAssetServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/RemoteAssetServiceConnector.cs
index e6eeacfaf6..ff04f9d66e 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/RemoteAssetServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/RemoteAssetServiceConnector.cs
@@ -48,7 +48,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
MethodBase.GetCurrentMethod().DeclaringType);
private bool m_Enabled = false;
- private IImprovedAssetCache m_Cache;
+ private IAssetCache m_Cache;
public Type ReplaceableInterface
{
@@ -111,7 +111,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
if (m_Cache == null)
{
- m_Cache = scene.RequestModuleInterface();
+ m_Cache = scene.RequestModuleInterface();
// Since we are a shared module and scene data is not
// available for every method, the cache must be shared, too
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index e44f11a54e..d7a4ca46aa 100755
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -1581,6 +1581,8 @@ namespace OpenSim.Region.Framework.Scenes
m_heartbeatThread = null;
}
+ GC.Collect();
+ GC.WaitForPendingFinalizers();
GC.Collect();
// tell physics to finish building actor
m_sceneGraph.ProcessPhysicsPreSimulation();
@@ -1856,13 +1858,9 @@ namespace OpenSim.Region.Framework.Scenes
if (!LoginsEnabled && Frame == 20)
{
- // m_log.DebugFormat("{0} {1} {2}", LoginsDisabled, m_sceneGraph.GetActiveScriptsCount(), LoginLock);
-
- // In 99.9% of cases it is a bad idea to manually force garbage collection. However,
- // this is a rare case where we know we have just went through a long cycle of heap
- // allocations, and there is no more work to be done until someone logs in
GC.Collect();
-
+ GC.WaitForPendingFinalizers();
+ GC.Collect();
if (!LoginLock)
{
if (!StartDisabled)
@@ -1887,6 +1885,7 @@ namespace OpenSim.Region.Framework.Scenes
// LoginLock can currently only be set by a region module implementation.
// If somehow this hasn't been done then the quickest way to bugfix is to see the
// NullReferenceException
+
IRegionReadyModule rrm = RequestModuleInterface();
rrm.TriggerRegionReady(this);
}
diff --git a/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
index 7312bc39a8..b259f52f8f 100644
--- a/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
+++ b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
@@ -63,7 +63,7 @@ namespace OpenSim.Region.OptionalModules.Materials
public Type ReplaceableInterface { get { return null; } }
- IImprovedAssetCache m_cache;
+ IAssetCache m_cache;
private Scene m_scene = null;
private bool m_enabled = false;
private int m_maxMaterialsPerTransaction = 50;
@@ -207,7 +207,7 @@ namespace OpenSim.Region.OptionalModules.Materials
{
if (!m_enabled) return;
- m_cache = scene.RequestModuleInterface();
+ m_cache = scene.RequestModuleInterface();
ISimulatorFeaturesModule featuresModule = scene.RequestModuleInterface();
if (featuresModule != null)
featuresModule.OnSimulatorFeaturesRequest += OnSimulatorFeaturesRequest;
diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
index 870c0bbce9..1725eb4f0c 100644
--- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
@@ -214,6 +214,10 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
m_scene.EventManager.OnEmptyScriptCompileQueue -= OnEmptyScriptCompileQueue;
m_scene.LoginLock = false;
+ GC.Collect();
+ GC.WaitForPendingFinalizers();
+ GC.Collect();
+
if (!m_scene.StartDisabled)
{
m_scene.LoginsEnabled = true;
diff --git a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
index a6e8eb424b..bdc3befb08 100644
--- a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
+++ b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
@@ -49,7 +49,7 @@ namespace OpenSim.Services.Connectors
const int MAXSENDRETRIESLEN = 30;
private string m_ServerURI = String.Empty;
- private IImprovedAssetCache m_Cache = null;
+ private IAssetCache m_Cache = null;
private int m_retryCounter;
private bool m_inRetries;
private List[] m_sendRetries = new List[MAXSENDRETRIESLEN];
@@ -233,7 +233,7 @@ namespace OpenSim.Services.Connectors
}
}
- protected void SetCache(IImprovedAssetCache cache)
+ protected void SetCache(IAssetCache cache)
{
m_Cache = cache;
}
@@ -260,8 +260,13 @@ namespace OpenSim.Services.Connectors
asset = SynchronousRestObjectRequester.MakeRequest("GET", uri, 0, m_Auth);
- if (asset != null && m_Cache != null)
- m_Cache.Cache(asset);
+ if (m_Cache != null)
+ {
+ if (asset != null)
+ m_Cache.Cache(asset);
+ else
+ m_Cache.CacheNegative(id);
+ }
}
return asset;
}
diff --git a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs
index d80e660553..2ddd7a2f55 100644
--- a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs
+++ b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs
@@ -54,6 +54,8 @@ namespace OpenSim.Services.Connectors
private string m_ServerURI = String.Empty;
+ private int m_maxRetries = 0;
+
///
/// Timeout for remote requests.
///
@@ -100,6 +102,7 @@ namespace OpenSim.Services.Connectors
m_ServerURI = serviceURI;
m_requestTimeoutSecs = config.GetInt("RemoteRequestTimeout", m_requestTimeoutSecs);
+ m_maxRetries = config.GetInt("MaxRetries", m_maxRetries);
StatsManager.RegisterStat(
new Stat(
@@ -700,10 +703,20 @@ namespace OpenSim.Services.Connectors
RequestsMade++;
- string reply
- = SynchronousRestFormsRequester.MakeRequest(
+ string reply = String.Empty;
+ int retries = 0;
+
+ do
+ {
+ reply = SynchronousRestFormsRequester.MakeRequest(
"POST", m_ServerURI + "/xinventory",
ServerUtils.BuildQueryString(sendData), m_requestTimeoutSecs, m_Auth);
+
+ if (reply != String.Empty)
+ break;
+
+ retries++;
+ } while (retries <= m_maxRetries);
Dictionary replyData = ServerUtils.ParseXmlResponse(
reply);
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs
index 9ad4a7a56f..531939f2cc 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs
@@ -55,7 +55,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
private static string ZeroID = UUID.Zero.ToString();
private string m_serverUrl = String.Empty;
- private IImprovedAssetCache m_cache;
+ private IAssetCache m_cache;
private bool m_Enabled = false;
#region ISharedRegionModule
@@ -65,7 +65,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
{
if (m_cache == null)
{
- IImprovedAssetCache cache = scene.RequestModuleInterface();
+ IAssetCache cache = scene.RequestModuleInterface();
if (cache is ISharedRegionModule)
m_cache = cache;
}
diff --git a/bin/config-include/FlotsamCache.ini.example b/bin/config-include/FlotsamCache.ini.example
index c0d743093b..2b5d37e0e0 100644
--- a/bin/config-include/FlotsamCache.ini.example
+++ b/bin/config-include/FlotsamCache.ini.example
@@ -22,7 +22,44 @@
; Set to false for no memory cache
; assets can be requested several times in short periods
; so even a small memory cache is useful
- MemoryCacheEnabled = true
+ MemoryCacheEnabled = false
+
+ ; If a memory cache hit happens, or the asset is still in memory
+ ; due to other causes, update the timestamp on the disk file anyway.
+ ; Don't turn this on unless you share your asset cache between simulators
+ ; AND use an external process, e.g. cron job, to clean it up.
+ UpdateFileTimeOnCacheHit = false
+
+ ; Enabling this will cache negative fetches. If an asset is negative-cached
+ ; it will not be re-requested from the asset server again for a while.
+ ; Generally, this is a good thing.
+ ;
+ ; Regular expiration settings (non-sliding) mean that the asset will be
+ ; retried after the time has expired. Sliding expiration means that
+ ; the time the negative cache will keep the asset is refreshed each
+ ; time a fetch is attempted. Use sliding expiration if you have rogue
+ ; scripts hammering the asset server with requests for nonexistent
+ ; assets.
+ ;
+ ; There are two cases where negative caching may cause issues:
+ ;
+ ; 1 - If an invalid asset is repeatedly requested by a script and that asset is
+ ; subsequently created, it will not be seen until fcache clear
+ ; is used. This is a very theoretical scenario since UUID collisions
+ ; are deemed to be not occuring in practice.
+ ; This can only become an issue with sliding expiration time.
+ ;
+ ; 2 - If the asset service is clustered, an asset may not have propagated
+ ; to all cluster members when it is first attempted to fetch it.
+ ; This may theoretically occur with networked vendor systems and
+ ; would lead to an asset not found message. However, after the
+ ; expiration time has elapsed, the asset will the be fetchable.
+ ;
+ ; The defaults below are suitable for all small to medium installations
+ ; including grids.
+ NegativeCacheEnabled = true
+ NegativeCacheTimeout = 120
+ NegativeCacheSliding = false
; Set to false for no file cache
FileCacheEnabled = true
@@ -32,7 +69,7 @@
; this is good if memory is not a problem.
; if memory is a problem then a few seconds may actually save same.
; see hit rates with console comand: fcache status
- MemoryCacheTimeout = .001 ; 3.6s ie around 4s (1s resolution)
+ MemoryCacheTimeout = .016 // one minute
; How long {in hours} to keep assets cached on disk, .5 == 30 minutes
; Specify 0 if you do not want your disk cache to expire
diff --git a/bin/config-include/GridCommon.ini.example b/bin/config-include/GridCommon.ini.example
index 0922cf5a4a..10a5b474d9 100644
--- a/bin/config-include/GridCommon.ini.example
+++ b/bin/config-include/GridCommon.ini.example
@@ -85,6 +85,7 @@
; Change this to your grid-wide inventory server
;
InventoryServerURI = "${Const|BaseURL}:${Const|PrivatePort}"
+ ;MaxRetries = 0
[GridInfo]
;