diff --git a/.gitignore b/.gitignore index 9d2d692cf0..b6b5582b0d 100644 --- a/.gitignore +++ b/.gitignore @@ -38,13 +38,21 @@ bin/config-include/CenomeCache.ini bin/config-include/FlotsamCache.ini bin/config-include/GridCommon.ini bin/config-include/StandaloneCommon.ini +bin/OpenSim.Grid.AssetInventoryServer.log +bin/OpenSim.Grid.AssetServer.log +bin/OpenSim.Grid.GridServer.log +bin/OpenSim.Grid.InventoryServer.log +bin/OpenSim.Grid.MessagingServer.log +bin/OpenSim.Grid.UserServer.log +bin/OpenSim.log +bin/crashes/ Examples/*.dll OpenSim.build OpenSim.sln OpenSim.suo Prebuild/Prebuild.build Prebuild/Prebuild.sln -bin/OpenSim.log +TestResult.xml cov/* OpenSim/OpenSim.userprefs OpenSim/OpenSim.usertasks @@ -53,3 +61,4 @@ TAGS Makefile.local bin/.version compile.bat + diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index 53b8ebc185..c5203566d5 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -129,18 +129,18 @@ namespace Flotsam.RegionModules.AssetCache if (name == Name) { m_Enabled = true; - m_log.InfoFormat("[ASSET CACHE]: {0} enabled", this.Name); + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0} enabled", this.Name); IConfig assetConfig = source.Configs["AssetCache"]; if (assetConfig == null) { - m_log.Warn("[ASSET CACHE]: AssetCache missing from OpenSim.ini, using defaults."); - m_log.InfoFormat("[ASSET CACHE]: Cache Directory", m_DefaultCacheDirectory); + m_log.Warn("[FLOTSAM ASSET CACHE]: AssetCache missing from OpenSim.ini, using defaults."); + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory", m_DefaultCacheDirectory); return; } m_CacheDirectory = assetConfig.GetString("CacheDirectory", m_DefaultCacheDirectory); - m_log.InfoFormat("[ASSET CACHE]: Cache Directory", m_DefaultCacheDirectory); + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory", m_DefaultCacheDirectory); m_MemoryCacheEnabled = assetConfig.GetBoolean("MemoryCacheEnabled", true); m_MemoryExpiration = TimeSpan.FromHours(assetConfig.GetDouble("MemoryCacheTimeout", m_DefaultMemoryExpiration)); @@ -188,6 +188,8 @@ namespace Flotsam.RegionModules.AssetCache } m_CacheWarnAt = assetConfig.GetInt("CacheWarnAt", 30000); + + } } } @@ -203,7 +205,14 @@ namespace Flotsam.RegionModules.AssetCache public void AddRegion(Scene scene) { if (m_Enabled) + { scene.RegisterModuleInterface(this); + + //scene.AddCommand(this, "flotsamcache", "", "Display a list of console commands for the Flotsam Asset Cache", HandleConsoleCommand); + scene.AddCommand(this, "flotsamcache counts", "flotsamcache counts", "Display the number of cached assets", HandleConsoleCommand); + scene.AddCommand(this, "flotsamcache clearmem", "flotsamcache clearmem", "Remove all assets cached in memory", HandleConsoleCommand); + scene.AddCommand(this, "flotsamcache clearfile", "flotsamcache clearfile", "Remove all assets cached on disk", HandleConsoleCommand); + } } public void RemoveRegion(Scene scene) @@ -365,16 +374,16 @@ namespace Flotsam.RegionModules.AssetCache { m_HitRateFile = (double)m_DiskHits / m_Requests * 100.0; - m_log.InfoFormat("[ASSET CACHE]: Cache Get :: {0} :: {1}", id, asset == null ? "Miss" : "Hit"); - m_log.InfoFormat("[ASSET CACHE]: File Hit Rate {0}% for {1} requests", m_HitRateFile.ToString("0.00"), m_Requests); + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Get :: {0} :: {1}", id, asset == null ? "Miss" : "Hit"); + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File Hit Rate {0}% for {1} requests", m_HitRateFile.ToString("0.00"), m_Requests); if (m_MemoryCacheEnabled) { m_HitRateMemory = (double)m_MemoryHits / m_Requests * 100.0; - m_log.InfoFormat("[ASSET CACHE]: Memory Hit Rate {0}% for {1} requests", m_HitRateMemory.ToString("0.00"), m_Requests); + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Memory Hit Rate {0}% for {1} requests", m_HitRateMemory.ToString("0.00"), m_Requests); } - m_log.InfoFormat("[ASSET CACHE]: {0} unnessesary requests due to requests for assets that are currently downloading.", m_RequestsForInprogress); + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0} unnessesary requests due to requests for assets that are currently downloading.", m_RequestsForInprogress); } @@ -384,7 +393,7 @@ namespace Flotsam.RegionModules.AssetCache public void Expire(string id) { if (m_LogLevel >= 2) - m_log.DebugFormat("[ASSET CACHE]: Expiring Asset {0}.", id); + m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Expiring Asset {0}.", id); try { @@ -406,7 +415,7 @@ namespace Flotsam.RegionModules.AssetCache public void Clear() { if (m_LogLevel >= 2) - m_log.Debug("[ASSET CACHE]: Clearing Cache."); + m_log.Debug("[FLOTSAM ASSET CACHE]: Clearing Cache."); foreach (string dir in Directory.GetDirectories(m_CacheDirectory)) { @@ -420,31 +429,44 @@ namespace Flotsam.RegionModules.AssetCache private void CleanupExpiredFiles(object source, ElapsedEventArgs e) { if (m_LogLevel >= 2) - m_log.DebugFormat("[ASSET CACHE]: Checking for expired files older then {0}.", m_FileExpiration.ToString()); + m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Checking for expired files older then {0}.", m_FileExpiration.ToString()); foreach (string dir in Directory.GetDirectories(m_CacheDirectory)) { - foreach (string file in Directory.GetFiles(dir)) - { - if (DateTime.Now - File.GetLastAccessTime(file) > m_FileExpiration) - { - File.Delete(file); - } - } - - int dirSize = Directory.GetFiles(dir).Length; - if (dirSize == 0) - { - Directory.Delete(dir); - } - else if (dirSize >= m_CacheWarnAt) - { - m_log.WarnFormat("[ASSET CACHE]: Cache folder exceeded CacheWarnAt limit {0} {1}. Suggest increasing tiers, tier length, or reducing cache expiration", dir, dirSize); - } - + CleanExpiredFiles(dir); } } + /// + /// Recurses through specified directory checking for expired asset files and deletes them. Also removes empty directories. + /// + /// + private void CleanExpiredFiles(string dir) + { + foreach (string file in Directory.GetFiles(dir)) + { + if (DateTime.Now - File.GetLastAccessTime(file) > m_FileExpiration) + { + File.Delete(file); + } + } + + foreach (string subdir in Directory.GetDirectories(dir)) + { + CleanExpiredFiles(subdir); + } + + int dirSize = Directory.GetFiles(dir).Length + Directory.GetDirectories(dir).Length; + if (dirSize == 0) + { + Directory.Delete(dir); + } + else if (dirSize >= m_CacheWarnAt) + { + m_log.WarnFormat("[FLOTSAM ASSET CACHE]: Cache folder exceeded CacheWarnAt limit {0} {1}. Suggest increasing tiers, tier length, or reducing cache expiration", dir, dirSize); + } + } + private string GetFileName(string id) { // Would it be faster to just hash the darn thing? @@ -486,7 +508,7 @@ namespace Flotsam.RegionModules.AssetCache File.Move(tempname, filename); if (m_LogLevel >= 2) - m_log.DebugFormat("[ASSET CACHE]: Cache Stored :: {0}", asset.ID); + m_log.DebugFormat("[FLOTSAM ASSET CACHE]: Cache Stored :: {0}", asset.ID); } catch (Exception e) { @@ -522,8 +544,88 @@ namespace Flotsam.RegionModules.AssetCache string[] text = e.ToString().Split(new char[] { '\n' }); foreach (string t in text) { - m_log.ErrorFormat("[ASSET CACHE]: {0} ", t); + m_log.ErrorFormat("[FLOTSAM ASSET CACHE]: {0} ", t); } } + + private int GetFileCacheCount(string dir) + { + int count = Directory.GetFiles(dir).Length; + + foreach (string subdir in Directory.GetDirectories(dir)) + { + count += GetFileCacheCount(subdir); + } + + return count; + } + + #region Console Commands + private void HandleConsoleCommand(string module, string[] cmdparams) + { + if (cmdparams.Length == 2) + { + string cmd = cmdparams[1]; + switch (cmd) + { + case "count": + case "counts": + m_log.InfoFormat("[FLOTSAM ASSET CACHE] Memory Cache : {0}", m_MemoryCache.Count); + + int fileCount = GetFileCacheCount(m_CacheDirectory); + m_log.InfoFormat("[FLOTSAM ASSET CACHE] File Cache : {0}", fileCount); + + break; + + case "clearmem": + m_MemoryCache.Clear(); + m_log.InfoFormat("[FLOTSAM ASSET CACHE] Memory Cache Cleared, there are now {0} items in the memory cache", m_MemoryCache.Count); + break; + + case "clearfile": + foreach (string dir in Directory.GetDirectories(m_CacheDirectory)) + { + try + { + Directory.Delete(dir, true); + } + catch (Exception e) + { + LogException(e); + } + } + + foreach (string file in Directory.GetFiles(m_CacheDirectory)) + { + try + { + File.Delete(file); + } + catch (Exception e) + { + LogException(e); + } + } + + break; + + default: + m_log.InfoFormat("[FLOTSAM ASSET CACHE] Unknown command {0}", cmd); + break; + } + } + else if (cmdparams.Length == 1) + { + m_log.InfoFormat("[FLOTSAM ASSET CACHE] flotsamcache counts - Display the number of cached assets"); + m_log.InfoFormat("[FLOTSAM ASSET CACHE] flotsamcache clearmem - Remove all assets cached in memory"); + m_log.InfoFormat("[FLOTSAM ASSET CACHE] flotsamcache clearfile - Remove all assets cached on disk"); + + } + + + } + + #endregion + } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index f261c16d32..02befda49c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -9477,8 +9477,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return; } - System.Text.ASCIIEncoding enc = - new System.Text.ASCIIEncoding(); + System.Text.UTF8Encoding enc = + new System.Text.UTF8Encoding(); string data = enc.GetString(a.Data); //m_log.Debug(data); NotecardCache.Cache(id, data); @@ -9524,29 +9524,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (NotecardCache.IsCached(assetID)) { - AsyncCommands. - DataserverPlugin.DataserverReply(assetID.ToString(), - NotecardCache.GetLine(assetID, line, m_notecardLineReadCharsMax)); + AsyncCommands.DataserverPlugin.DataserverReply(assetID.ToString(), + NotecardCache.GetLine(assetID, line, m_notecardLineReadCharsMax)); ConditionalScriptSleep(100); return tid.ToString(); } WithNotecard(assetID, delegate (UUID id, AssetBase a) - { - if (a == null || a.Type != 7) - { - ShoutError("Notecard '" + name + "' could not be found."); - return; - } + { + if (a == null || a.Type != 7) + { + ShoutError("Notecard '" + name + "' could not be found."); + return; + } - System.Text.ASCIIEncoding enc = - new System.Text.ASCIIEncoding(); - string data = enc.GetString(a.Data); - //m_log.Debug(data); - NotecardCache.Cache(id, data); - AsyncCommands.DataserverPlugin.DataserverReply(id.ToString(), - NotecardCache.GetLine(id, line, m_notecardLineReadCharsMax)); - }); + System.Text.UTF8Encoding enc = + new System.Text.UTF8Encoding(); + string data = enc.GetString(a.Data); + //m_log.Debug(data); + NotecardCache.Cache(id, data); + AsyncCommands.DataserverPlugin.DataserverReply(id.ToString(), + NotecardCache.GetLine(id, line, m_notecardLineReadCharsMax)); + }); ConditionalScriptSleep(100); return tid.ToString(); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index bca019b72d..726b37a077 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -1457,7 +1457,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api notecardData = "Linden text version 2\n{\nLLEmbeddedItems version 1\n{\ncount 0\n}\nText length " + textLength.ToString() + "\n" + notecardData + "}\n"; - asset.Data = Encoding.ASCII.GetBytes(notecardData); + asset.Data = Encoding.UTF8.GetBytes(notecardData); World.AssetService.Store(asset); // Create Task Entry @@ -1522,7 +1522,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api AssetBase a = World.AssetService.Get(assetID.ToString()); if (a != null) { - System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); + System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding(); string data = enc.GetString(a.Data); NotecardCache.Cache(assetID, data); } @@ -1575,7 +1575,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api AssetBase a = World.AssetService.Get(assetID.ToString()); if (a != null) { - System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); + System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding(); string data = enc.GetString(a.Data); NotecardCache.Cache(assetID, data); } @@ -1632,7 +1632,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api AssetBase a = World.AssetService.Get(assetID.ToString()); if (a != null) { - System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); + System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding(); string data = enc.GetString(a.Data); NotecardCache.Cache(assetID, data); }