From 0887be3c12f548539dd5a66d11c74a2f118cac5f Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 23 Dec 2016 03:42:50 +0000 Subject: [PATCH 1/8] replace the (hidden) GRID_GOD by a more usefull GOD so includes all types. This needs to be changed to current effective godlevel check (sp.GodLevel) when that is fixed. Automatic god powers need be (optionaly) removed --- .../ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | 8 +++++--- bin/config-include/osslEnable.ini | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 5638f01cba..6e6647911c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -310,7 +310,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api foreach (string id in ids) { string current = id.Trim(); - if (current.ToUpper() == "PARCEL_GROUP_MEMBER" || current.ToUpper() == "PARCEL_OWNER" || current.ToUpper() == "ESTATE_MANAGER" || current.ToUpper() == "ESTATE_OWNER" || current.ToUpper() == "GRID_GOD") + if (current.ToUpper() == "PARCEL_GROUP_MEMBER" || current.ToUpper() == "PARCEL_OWNER" || current.ToUpper() == "ESTATE_MANAGER" || current.ToUpper() == "ESTATE_OWNER" || current.ToUpper() == "GOD") { if (!perms.AllowedOwnerClasses.Contains(current)) perms.AllowedOwnerClasses.Add(current.ToUpper()); @@ -416,9 +416,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } //Only gods may use the function - if (m_FunctionPerms[function].AllowedOwnerClasses.Contains("GRID_GOD")) + if (m_FunctionPerms[function].AllowedOwnerClasses.Contains("GOD")) { - if (World.Permissions.IsGridGod(ownerID)) + // this should be replaced by sp.GodLevel > 200 to be effective requested power + // but that still needs fix + if (World.Permissions.IsGod(ownerID)) { return String.Empty; } diff --git a/bin/config-include/osslEnable.ini b/bin/config-include/osslEnable.ini index a064f0957f..21e14519e0 100644 --- a/bin/config-include/osslEnable.ini +++ b/bin/config-include/osslEnable.ini @@ -37,6 +37,7 @@ ; To enable for individuals or groups, set it to a comma separated list. This checks ; against the owner of the object containing the script. ; The comma separated entries in the list may be one of: + ; "GOD" -- enable for users with GOD rights ; "ESTATE_MANAGER" -- enable for estate manager ; "ESTATE_OWNER" -- enable for estate owner ; "PARCEL_OWNER" -- enable for parcel owner From b6266c6a1de9d78904aa01eb39f1da2979db06ca Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 23 Dec 2016 14:23:07 +0000 Subject: [PATCH 2/8] check if a parcelID is a encoded position data or a true UUID. This may fail, just reducing the odds. --- OpenSim/Framework/Util.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index b6225232db..89cf045716 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -1725,12 +1725,16 @@ namespace OpenSim.Framework return new UUID(bytes, 0); } - public static void ParseFakeParcelID(UUID parcelID, out ulong regionHandle, out uint x, out uint y) + public static bool ParseFakeParcelID(UUID parcelID, out ulong regionHandle, out uint x, out uint y) { byte[] bytes = parcelID.GetBytes(); regionHandle = Utils.BytesToUInt64(bytes); x = Utils.BytesToUInt(bytes, 8) & 0xffff; y = Utils.BytesToUInt(bytes, 12) & 0xffff; + // validation may fail, just reducing the odds of using a real UUID as encoded parcel + return ( bytes[0] == 0 && bytes[4] == 0 && // handler x,y multiples of 256 + bytes[9] < 64 && bytes[13] < 64 && // positions < 16km + bytes[14] == 0 && bytes[15] == 0); } public static void ParseFakeParcelID(UUID parcelID, out ulong regionHandle, out uint x, out uint y, out uint z) From 70475c676bbb9ed3a029a5c28c8e253e7df35d97 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 23 Dec 2016 14:25:22 +0000 Subject: [PATCH 3/8] dont try to use a parcelID as encoded position when it is not --- .../Region/CoreModules/World/Land/LandManagementModule.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index bec5322341..22bc49e3c1 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -1880,8 +1880,9 @@ namespace OpenSim.Region.CoreModules.World.Land UUID.TryParse(id, out parcel); // assume we've got the parcelID we just computed in RemoteParcelRequest ExtendedLandData extLandData = new ExtendedLandData(); - Util.ParseFakeParcelID(parcel, out extLandData.RegionHandle, - out extLandData.X, out extLandData.Y); + if(!Util.ParseFakeParcelID(parcel, out extLandData.RegionHandle, + out extLandData.X, out extLandData.Y)) + return null; m_log.DebugFormat("[LAND MANAGEMENT MODULE]: Got parcelinfo request for regionHandle {0}, x/y {1}/{2}", extLandData.RegionHandle, extLandData.X, extLandData.Y); From bfb1cb9f33ab4beb01661e7fb14678e8b009e384 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 23 Dec 2016 16:10:07 +0000 Subject: [PATCH 4/8] a few more changes on user profiles --- .../Avatar/UserProfiles/UserProfileModule.cs | 96 +++++++++++++++---- 1 file changed, 76 insertions(+), 20 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs index d232d82a84..3f7a8ee7a9 100644 --- a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs @@ -897,20 +897,36 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles else { // we have a proxy on map - // this is a fail on large regions - uint gtmp = (uint)globalPos.X >> 8; - globalPos.X -= (gtmp << 8); - globalPos.X += target.RegionLocX; + ulong oriHandle; + uint oriX; + uint oriY; + if(Util.ParseFakeParcelID(pick.ParcelId, out oriHandle, out oriX, out oriY)) + { + pick.ParcelId = Util.BuildFakeParcelID(target.RegionHandle, oriX, oriY); + globalPos.X = target.RegionLocX + oriX; + globalPos.Y = target.RegionLocY + oriY; + pick.GlobalPos = globalPos.ToString(); + } + else + { + // this is a fail on large regions + uint gtmp = (uint)globalPos.X >> 8; + globalPos.X -= (gtmp << 8); - gtmp = (uint)globalPos.Y >> 8; - globalPos.Y -= (gtmp << 8); - globalPos.Y += target.RegionLocY; + gtmp = (uint)globalPos.Y >> 8; + globalPos.Y -= (gtmp << 8); + + pick.ParcelId = Util.BuildFakeParcelID(target.RegionHandle, (uint)globalPos.X, (uint)globalPos.Y); + + globalPos.X += target.RegionLocX; + globalPos.Y += target.RegionLocY; + pick.GlobalPos = globalPos.ToString(); + } } } m_log.DebugFormat("[PROFILES]: PickInfoRequest: {0} : {1}", pick.Name.ToString(), pick.SnapshotId.ToString()); - pick.GlobalPos = globalPos.ToString(); lock(m_profilesCache) { if(!m_profilesCache.TryGetValue(targetID, out uce) || uce == null) @@ -1331,16 +1347,35 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles if(uce.props != null) { props = uce.props; - remoteClient.SendAvatarProperties(props.UserId, props.AboutText, - uce.born, uce.membershipType , props.FirstLifeText, uce.flags, - props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId); + uint cflags = uce.flags; + // if on same region force online + if(p != null && !p.IsDeleted) + cflags |= 0x10; + remoteClient.SendAvatarProperties(props.UserId, props.AboutText, + uce.born, uce.membershipType , props.FirstLifeText, cflags, + props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId); remoteClient.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, props.WantToText, (uint)props.SkillsMask, props.SkillsText, props.Language); - return; + return; } + else + { + if(uce.ClientsWaitingProps == null) + uce.ClientsWaitingProps = new HashSet(); + else if(uce.ClientsWaitingProps.Contains(remoteClient)) + return; + uce.ClientsWaitingProps.Add(remoteClient); + } + } + else + { + uce = new UserProfileCacheEntry(); + uce.ClientsWaitingProps = new HashSet(); + uce.ClientsWaitingProps.Add(remoteClient); + m_profilesCache.AddOrUpdate(avatarID, uce, PROFILECACHEEXPIRE); } } @@ -1402,14 +1437,11 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles { props.AboutText ="Profile not available at this time. User may still be unknown to this grid"; } - - // if on same region force online - if(p != null && !p.IsDeleted) - flags |= 0x10; if(!m_allowUserProfileWebURLs) props.WebUrl =""; + HashSet clients; lock(m_profilesCache) { if(!m_profilesCache.TryGetValue(props.UserId, out uce) || uce == null) @@ -1418,15 +1450,39 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles uce.born = born; uce.membershipType = membershipType; uce.flags = flags; - + clients = uce.ClientsWaitingProps; + uce.ClientsWaitingProps = null; m_profilesCache.AddOrUpdate(props.UserId, uce, PROFILECACHEEXPIRE); } - remoteClient.SendAvatarProperties(props.UserId, props.AboutText, born, membershipType , props.FirstLifeText, flags, + // if on same region force online + if(p != null && !p.IsDeleted) + flags |= 0x10; + + if(clients == null) + { + remoteClient.SendAvatarProperties(props.UserId, props.AboutText, born, membershipType , props.FirstLifeText, flags, props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId); - remoteClient.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, props.WantToText, (uint)props.SkillsMask, - props.SkillsText, props.Language); + remoteClient.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, props.WantToText, + (uint)props.SkillsMask, props.SkillsText, props.Language); + } + else + { + if(!clients.Contains(remoteClient)) + clients.Add(remoteClient); + foreach(IClientAPI cli in clients) + { + if(!cli.IsActive) + continue; + cli.SendAvatarProperties(props.UserId, props.AboutText, born, membershipType , props.FirstLifeText, flags, + props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId); + + cli.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, props.WantToText, + (uint)props.SkillsMask, props.SkillsText, props.Language); + + } + } } /// From 679d52ced69adecaa510b7b196a1d13c59fc836c Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Fri, 23 Dec 2016 19:41:57 +0000 Subject: [PATCH 5/8] add missing file --- OpenSim/Framework/UserProfiles.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/OpenSim/Framework/UserProfiles.cs b/OpenSim/Framework/UserProfiles.cs index 6d46fe9c2d..4ed890bc43 100644 --- a/OpenSim/Framework/UserProfiles.cs +++ b/OpenSim/Framework/UserProfiles.cs @@ -135,6 +135,7 @@ namespace OpenSim.Framework public string born; public byte[] membershipType; public uint flags; + public HashSet ClientsWaitingProps; } } From ba1ca67afef3640bd5fd0d1cee678d7bda79c97c Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 23 Dec 2016 19:48:03 +0000 Subject: [PATCH 6/8] Re-add GRID_GOD because in some cases an "employee-only" level is simply needed --- .../Shared/Api/Implementation/OSSL_Api.cs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 6e6647911c..ba5a46d1be 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -310,7 +310,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api foreach (string id in ids) { string current = id.Trim(); - if (current.ToUpper() == "PARCEL_GROUP_MEMBER" || current.ToUpper() == "PARCEL_OWNER" || current.ToUpper() == "ESTATE_MANAGER" || current.ToUpper() == "ESTATE_OWNER" || current.ToUpper() == "GOD") + if (current.ToUpper() == "PARCEL_GROUP_MEMBER" || current.ToUpper() == "PARCEL_OWNER" || current.ToUpper() == "ESTATE_MANAGER" || current.ToUpper() == "ESTATE_OWNER" || current.ToUpper() == "GOD" || current.ToUpper() == "GRID_GOD") { if (!perms.AllowedOwnerClasses.Contains(current)) perms.AllowedOwnerClasses.Add(current.ToUpper()); @@ -418,14 +418,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api //Only gods may use the function if (m_FunctionPerms[function].AllowedOwnerClasses.Contains("GOD")) { - // this should be replaced by sp.GodLevel > 200 to be effective requested power - // but that still needs fix if (World.Permissions.IsGod(ownerID)) { return String.Empty; } } + //Only grid gods may use the function + if (m_FunctionPerms[function].AllowedOwnerClasses.Contains("GRID_GOD")) + { + if (World.Permissions.IsGridGod(ownerID)) + { + return String.Empty; + } + } + if (!m_FunctionPerms[function].AllowedCreators.Contains(m_item.CreatorID)) return( String.Format("{0} permission denied. Script creator is not in the list of users allowed to execute this function and prim owner also has no permission.", From 8d0b592e5d3524cf57a1a12edd0eb6fd2ce25dff Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 23 Dec 2016 20:41:10 +0000 Subject: [PATCH 7/8] Add en explanation to osslEnable.ini for GRID_GOD --- bin/config-include/osslEnable.ini | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bin/config-include/osslEnable.ini b/bin/config-include/osslEnable.ini index 21e14519e0..b96688bafd 100644 --- a/bin/config-include/osslEnable.ini +++ b/bin/config-include/osslEnable.ini @@ -37,7 +37,8 @@ ; To enable for individuals or groups, set it to a comma separated list. This checks ; against the owner of the object containing the script. ; The comma separated entries in the list may be one of: - ; "GOD" -- enable for users with GOD rights + ; "GRID_GOD" -- enable for users with UserLevel >= 200 + ; "GOD" -- enable for users with any type of god rights ; "ESTATE_MANAGER" -- enable for estate manager ; "ESTATE_OWNER" -- enable for estate owner ; "PARCEL_OWNER" -- enable for parcel owner From 293b65ac82890f338b6ed420ca7e56f876e79f40 Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sun, 25 Dec 2016 05:46:16 +0000 Subject: [PATCH 8/8] FloatSamCache: dont use slideexpire on current libovm expirecache. Change example settings to use memory cache with short expire time. ( 20% to 40% mem cache hit rates observed --- .../CoreModules/Asset/FlotsamAssetCache.cs | 75 ++++++++++++------- bin/config-include/FlotsamCache.ini.example | 13 +++- 2 files changed, 58 insertions(+), 30 deletions(-) diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index 9413598de6..b6dd5652c7 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -62,7 +62,8 @@ namespace OpenSim.Region.CoreModules.Asset MethodBase.GetCurrentMethod().DeclaringType); private bool m_Enabled; - private bool m_Running; + private bool m_timerRunning; + private bool m_cleanupRunning; private const string m_ModuleName = "FlotsamAssetCache"; private const string m_DefaultCacheDirectory = "./assetcache"; @@ -91,9 +92,8 @@ namespace OpenSim.Region.CoreModules.Asset private bool m_MemoryCacheEnabled = false; // Expiration is expressed in hours. - private const double m_DefaultMemoryExpiration = 2; + private double m_MemoryExpiration = 0.001; private const double m_DefaultFileExpiration = 48; - private TimeSpan m_MemoryExpiration = TimeSpan.FromHours(m_DefaultMemoryExpiration); private TimeSpan m_FileExpiration = TimeSpan.FromHours(m_DefaultFileExpiration); private TimeSpan m_FileExpirationCleanupTimer = TimeSpan.FromHours(1.0); @@ -150,7 +150,8 @@ namespace OpenSim.Region.CoreModules.Asset m_CacheDirectory = assetConfig.GetString("CacheDirectory", m_DefaultCacheDirectory); m_MemoryCacheEnabled = assetConfig.GetBoolean("MemoryCacheEnabled", m_MemoryCacheEnabled); - m_MemoryExpiration = TimeSpan.FromHours(assetConfig.GetDouble("MemoryCacheTimeout", m_DefaultMemoryExpiration)); + m_MemoryExpiration = assetConfig.GetDouble("MemoryCacheTimeout", m_MemoryExpiration); + m_MemoryExpiration *= 3600.0; // config in hours to seconds #if WAIT_ON_INPROGRESS_REQUESTS m_WaitOnInprogressTimeout = assetConfig.GetInt("WaitOnInprogressTimeout", 3000); @@ -224,9 +225,9 @@ namespace OpenSim.Region.CoreModules.Asset m_Scenes.Remove(scene); lock(timerLock) { - if(m_Running && m_Scenes.Count <= 0) + if(m_timerRunning && m_Scenes.Count <= 0) { - m_Running = false; + m_timerRunning = false; m_CacheCleanTimer.Stop(); m_CacheCleanTimer.Close(); } @@ -242,7 +243,7 @@ namespace OpenSim.Region.CoreModules.Asset m_AssetService = scene.RequestModuleInterface(); lock(timerLock) { - if(!m_Running) + if(!m_timerRunning) { if (m_FileCacheEnabled && (m_FileExpiration > TimeSpan.Zero) && (m_FileExpirationCleanupTimer > TimeSpan.Zero)) { @@ -250,7 +251,7 @@ namespace OpenSim.Region.CoreModules.Asset m_CacheCleanTimer.AutoReset = false; m_CacheCleanTimer.Elapsed += CleanupExpiredFiles; m_CacheCleanTimer.Start(); - m_Running = true; + m_timerRunning = true; } } } @@ -263,6 +264,7 @@ namespace OpenSim.Region.CoreModules.Asset private void UpdateMemoryCache(string key, AssetBase asset) { + // NOTE DO NOT USE SLIDEEXPIRE option on current libomv m_MemoryCache.AddOrUpdate(key, asset, m_MemoryExpiration); } @@ -480,12 +482,10 @@ namespace OpenSim.Region.CoreModules.Asset asset = GetFromMemoryCache(id); if (asset == null && m_FileCacheEnabled) - { asset = GetFromFileCache(id); - if (m_MemoryCacheEnabled && asset != null) - UpdateMemoryCache(id, asset); - } + if (m_MemoryCacheEnabled && asset != null) + UpdateMemoryCache(id, asset); if (((m_LogLevel >= 1)) && (m_HitRateDisplay != 0) && (m_Requests % m_HitRateDisplay == 0)) { @@ -561,8 +561,12 @@ namespace OpenSim.Region.CoreModules.Asset if (m_LogLevel >= 2) m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Checking for expired files older then {0}.", m_FileExpiration); - if(!m_Running) - return; + lock(timerLock) + { + if(!m_timerRunning || m_cleanupRunning) + return; + m_cleanupRunning = true; + } // Purge all files last accessed prior to this point DateTime purgeLine = DateTime.Now - m_FileExpiration; @@ -578,8 +582,9 @@ namespace OpenSim.Region.CoreModules.Asset lock(timerLock) { - if(m_Running) + if(m_timerRunning) m_CacheCleanTimer.Start(); + m_cleanupRunning = false; } } @@ -816,13 +821,13 @@ namespace OpenSim.Region.CoreModules.Asset s.ForEachSOG(delegate(SceneObjectGroup e) { - if(!m_Running && !storeUncached) + if(!m_timerRunning && !storeUncached) return; gatherer.AddForInspection(e); gatherer.GatherAll(); - if(!m_Running && !storeUncached) + if(!m_timerRunning && !storeUncached) return; foreach (UUID assetID in gatherer.GatheredUuids.Keys) @@ -854,13 +859,13 @@ namespace OpenSim.Region.CoreModules.Asset } gatherer.GatheredUuids.Clear(); - if(!m_Running && !storeUncached) + if(!m_timerRunning && !storeUncached) return; if(!storeUncached) Thread.Sleep(50); }); - if(!m_Running && !storeUncached) + if(!m_timerRunning && !storeUncached) break; } @@ -905,16 +910,23 @@ namespace OpenSim.Region.CoreModules.Asset { List outputLines = new List(); - double fileHitRate = (double)m_DiskHits / m_Requests * 100.0; + double invReq = 100.0 / m_Requests; + + double fileHitRate = m_DiskHits * invReq; outputLines.Add( string.Format("File Hit Rate: {0}% for {1} requests", fileHitRate.ToString("0.00"), m_Requests)); if (m_MemoryCacheEnabled) { - double memHitRate = (double)m_MemoryHits / m_Requests * 100.0; + double HitRate = m_MemoryHits * invReq; outputLines.Add( - string.Format("Memory Hit Rate: {0}% for {1} requests", memHitRate.ToString("0.00"), m_Requests)); + string.Format("Memory Hit Rate: {0}% for {1} requests", HitRate.ToString("0.00"), m_Requests)); + + HitRate += fileHitRate; + + outputLines.Add( + string.Format("Total Hit Rate: {0}% for {1} requests", HitRate.ToString("0.00"), m_Requests)); } outputLines.Add( @@ -1019,17 +1031,27 @@ namespace OpenSim.Region.CoreModules.Asset break; case "assets": - con.Output("Ensuring assets are cached for all scenes."); + lock(timerLock) + { + if(m_cleanupRunning) + { + con.OutputFormat("FloatSam assets check already running"); + return; + } + m_cleanupRunning = true; + } + + con.Output("FloatSam Ensuring assets are cached for all scenes."); WorkManager.RunInThread(delegate { bool wasRunning= false; lock(timerLock) { - if(m_Running) + if(m_timerRunning) { m_CacheCleanTimer.Stop(); - m_Running = false; + m_timerRunning = false; wasRunning = true; Thread.Sleep(100); } @@ -1041,8 +1063,9 @@ namespace OpenSim.Region.CoreModules.Asset if(wasRunning) { m_CacheCleanTimer.Start(); - m_Running = true; + m_timerRunning = true; } + m_cleanupRunning = false; } con.OutputFormat("Completed check with {0} assets.", assetReferenceTotal); }, null, "TouchAllSceneAssets"); diff --git a/bin/config-include/FlotsamCache.ini.example b/bin/config-include/FlotsamCache.ini.example index db8d4db01a..666681211d 100644 --- a/bin/config-include/FlotsamCache.ini.example +++ b/bin/config-include/FlotsamCache.ini.example @@ -20,15 +20,20 @@ HitRateDisplay = 100 ; Set to false for no memory cache - MemoryCacheEnabled = false + ; assets can be requested several times in short periods + ; so even a small memory cache is usefull + MemoryCacheEnabled = true ; Set to false for no file cache FileCacheEnabled = true ; How long {in hours} to keep assets cached in memory, .5 == 30 minutes - ; Optimization: for VPS or limited memory system installs set Timeout to .016 (1 minute) - ; increases performance without large memory impact - MemoryCacheTimeout = 2 + ; even a few minutes may mean many assets loaded to memory, if not all. + ; this is good if memory is not a problem. + ; if memory is a problem then a few seconds may actually save same. + ; reducing duplications. + ; see hit rates with console comand: fcache status + MemoryCacheTimeout = .001 // 3.6s ie around 4s (1s resolution) ; 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