From 804fe2d9b00e7e974600f17d64375fab8676ad11 Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Fri, 20 May 2011 12:52:09 +0300 Subject: [PATCH 01/26] Save the sun's position in OARs --- .../Serialization/External/RegionSettingsSerializer.cs | 8 ++++++-- .../CoreModules/World/Archiver/ArchiveReadRequest.cs | 3 +++ .../CoreModules/World/Archiver/Tests/ArchiverTests.cs | 2 ++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/OpenSim/Framework/Serialization/External/RegionSettingsSerializer.cs b/OpenSim/Framework/Serialization/External/RegionSettingsSerializer.cs index 6ba4c5a55e..931898ce10 100644 --- a/OpenSim/Framework/Serialization/External/RegionSettingsSerializer.cs +++ b/OpenSim/Framework/Serialization/External/RegionSettingsSerializer.cs @@ -182,6 +182,9 @@ namespace OpenSim.Framework.Serialization.External case "FixedSun": settings.FixedSun = bool.Parse(xtr.ReadElementContentAsString()); break; + case "SunPosition": + settings.SunPosition = double.Parse(xtr.ReadElementContentAsString()); + break; } } @@ -237,8 +240,9 @@ namespace OpenSim.Framework.Serialization.External xtw.WriteElementString("TerrainLowerLimit", settings.TerrainLowerLimit.ToString()); xtw.WriteElementString("UseEstateSun", settings.UseEstateSun.ToString()); xtw.WriteElementString("FixedSun", settings.FixedSun.ToString()); - // XXX: Need to expose interface to get sun phase information from sun module - // xtw.WriteStartElement("SunPhase", + xtw.WriteElementString("SunPosition", settings.SunPosition.ToString()); + // Note: 'SunVector' isn't saved because this value is owned by the Sun Module, which + // calculates it automatically according to the date and other factors. xtw.WriteEndElement(); xtw.WriteEndElement(); diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index 64616365f4..48130e7991 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -488,6 +488,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver currentRegionSettings.Elevation2SE = loadedRegionSettings.Elevation2SE; currentRegionSettings.Elevation2SW = loadedRegionSettings.Elevation2SW; currentRegionSettings.FixedSun = loadedRegionSettings.FixedSun; + currentRegionSettings.SunPosition = loadedRegionSettings.SunPosition; currentRegionSettings.ObjectBonus = loadedRegionSettings.ObjectBonus; currentRegionSettings.RestrictPushing = loadedRegionSettings.RestrictPushing; currentRegionSettings.TerrainLowerLimit = loadedRegionSettings.TerrainLowerLimit; @@ -500,6 +501,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver currentRegionSettings.WaterHeight = loadedRegionSettings.WaterHeight; currentRegionSettings.Save(); + + m_scene.TriggerEstateSunUpdate(); IEstateModule estateModule = m_scene.RequestModuleInterface(); diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index 34e2e23a01..6ba3459747 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs @@ -440,6 +440,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests rs.Elevation2SE = 9.2; rs.Elevation2SW = 2.1; rs.FixedSun = true; + rs.SunPosition = 12.0; rs.ObjectBonus = 1.4; rs.RestrictPushing = true; rs.TerrainLowerLimit = 0.4; @@ -485,6 +486,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests Assert.That(loadedRs.Elevation2SE, Is.EqualTo(9.2)); Assert.That(loadedRs.Elevation2SW, Is.EqualTo(2.1)); Assert.That(loadedRs.FixedSun, Is.True); + Assert.AreEqual(12.0, loadedRs.SunPosition); Assert.That(loadedRs.ObjectBonus, Is.EqualTo(1.4)); Assert.That(loadedRs.RestrictPushing, Is.True); Assert.That(loadedRs.TerrainLowerLimit, Is.EqualTo(0.4)); From c7bdb66a1f02c968f61f82333751e7f144fb59d8 Mon Sep 17 00:00:00 2001 From: Makopoppo Date: Thu, 9 Jun 2011 22:26:03 +0900 Subject: [PATCH 02/26] Added missing "Old Guids=true" to ConnectionString --- OpenSim/Tests/Clients/Presence/OpenSim.Server.ini | 2 +- OpenSim/Tests/Clients/UserAccounts/OpenSim.Server.ini | 2 +- bin/config-include/GridCommon.ini.example | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/OpenSim/Tests/Clients/Presence/OpenSim.Server.ini b/OpenSim/Tests/Clients/Presence/OpenSim.Server.ini index 47e73f9887..8610c78a63 100644 --- a/OpenSim/Tests/Clients/Presence/OpenSim.Server.ini +++ b/OpenSim/Tests/Clients/Presence/OpenSim.Server.ini @@ -29,5 +29,5 @@ port = 8003 [PresenceService] LocalServiceModule = "OpenSim.Services.PresenceService.dll:PresenceService" StorageProvider = "OpenSim.Data.MySQL.dll" - ConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=opensim123;" + ConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=opensim123;Old Guids=true;" diff --git a/OpenSim/Tests/Clients/UserAccounts/OpenSim.Server.ini b/OpenSim/Tests/Clients/UserAccounts/OpenSim.Server.ini index eb1f47346a..453e17e65c 100644 --- a/OpenSim/Tests/Clients/UserAccounts/OpenSim.Server.ini +++ b/OpenSim/Tests/Clients/UserAccounts/OpenSim.Server.ini @@ -29,5 +29,5 @@ port = 8003 [UserAccountService] LocalServiceModule = "OpenSim.Services.UserAccountService.dll:UserAccountService" StorageProvider = "OpenSim.Data.MySQL.dll" - ConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=opensim123;" + ConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=opensim123;Old Guids=true;" diff --git a/bin/config-include/GridCommon.ini.example b/bin/config-include/GridCommon.ini.example index e2e6459c58..27f262f374 100644 --- a/bin/config-include/GridCommon.ini.example +++ b/bin/config-include/GridCommon.ini.example @@ -10,9 +10,9 @@ ; Uncomment these lines if you want to use mysql storage ; Change the connection string to your db details ;StorageProvider = "OpenSim.Data.MySQL.dll" - ;ConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=***;" + ;ConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=***;Old Guids=true;" ; Uncomment this line if you are using MySQL and want to use a different database for estates - ;EstateConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=***;" + ;EstateConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=***;Old Guids=true;" ; MSSQL ; Uncomment these lines if you want to use MSSQL storage From fc7e17baf74a4b3ce4c47480f24266180dd4353d Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 10 Jun 2011 21:49:25 +0100 Subject: [PATCH 03/26] When serializing objects, stop accidentally using the green text colour value for alpha This addresses http://opensimulator.org/mantis/view.php?id=5111 --- .../Framework/Scenes/Serialization/SceneObjectSerializer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index 6ae4f3856d..fcf7e0cfec 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs @@ -1171,7 +1171,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization writer.WriteElementString("R", sop.Color.R.ToString(Utils.EnUsCulture)); writer.WriteElementString("G", sop.Color.G.ToString(Utils.EnUsCulture)); writer.WriteElementString("B", sop.Color.B.ToString(Utils.EnUsCulture)); - writer.WriteElementString("A", sop.Color.G.ToString(Utils.EnUsCulture)); + writer.WriteElementString("A", sop.Color.A.ToString(Utils.EnUsCulture)); writer.WriteEndElement(); writer.WriteElementString("Text", sop.Text); From b13b54c5268d8acada132b678946ceba925f6419 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 11 Jun 2011 00:04:21 +0100 Subject: [PATCH 04/26] Make the internal flotsam asset cache defaults match config-include/FlotsamCache.ini.example. Enable the flotsam console commands even if FlotsamCache.ini isn't present. For the most part, defaults are made to match those already in FlotsamCache.ini.example. The one exception is that the 48 hour file timeout from the code is used instead of the 0 hours that was in the example file. This can be tweaked if necessary. Most importantly, the default cache directory is now ./assetcache (as in FlotsamCache.ini.example) rather than ./FlotsamAssetCache (as was the internal code default). Therefore, if you were using flotasm without using the config file, then please rename your cache directory or start using the ini file and change the default there if you want to keep using your existing cache. --- .../CoreModules/Asset/FlotsamAssetCache.cs | 70 ++++++++++--------- bin/config-include/FlotsamCache.ini.example | 2 +- 2 files changed, 39 insertions(+), 33 deletions(-) diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index 9adb68bc0d..d9280c66e0 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -64,13 +64,13 @@ namespace Flotsam.RegionModules.AssetCache private bool m_Enabled; private const string m_ModuleName = "FlotsamAssetCache"; - private const string m_DefaultCacheDirectory = m_ModuleName; + private const string m_DefaultCacheDirectory = "./assetcache"; private string m_CacheDirectory = m_DefaultCacheDirectory; private readonly List m_InvalidChars = new List(); private int m_LogLevel = 0; - private ulong m_HitRateDisplay = 1; // How often to display hit statistics, given in requests + private ulong m_HitRateDisplay = 100; // How often to display hit statistics, given in requests private static ulong m_Requests; private static ulong m_RequestsForInprogress; @@ -87,14 +87,14 @@ namespace Flotsam.RegionModules.AssetCache #endif private ExpiringCache m_MemoryCache; - private bool m_MemoryCacheEnabled = true; + private bool m_MemoryCacheEnabled = false; // Expiration is expressed in hours. - private const double m_DefaultMemoryExpiration = 1.0; + private const double m_DefaultMemoryExpiration = 2; 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(m_DefaultFileExpiration); + private TimeSpan m_FileExpirationCleanupTimer = TimeSpan.FromHours(0.166); private static int m_CacheDirectoryTiers = 1; private static int m_CacheDirectoryTierLen = 3; @@ -141,26 +141,38 @@ namespace Flotsam.RegionModules.AssetCache IConfig assetConfig = source.Configs["AssetCache"]; if (assetConfig == null) { - 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_log.Warn( + "[FLOTSAM ASSET CACHE]: AssetCache section missing from config (not copied config-include/FlotsamCache.ini.example? Using defaults."); + } + else + { + m_CacheDirectory = assetConfig.GetString("CacheDirectory", m_DefaultCacheDirectory); + + m_MemoryCacheEnabled = assetConfig.GetBoolean("MemoryCacheEnabled", m_MemoryCacheEnabled); + m_MemoryExpiration = TimeSpan.FromHours(assetConfig.GetDouble("MemoryCacheTimeout", m_DefaultMemoryExpiration)); + + #if WAIT_ON_INPROGRESS_REQUESTS + m_WaitOnInprogressTimeout = assetConfig.GetInt("WaitOnInprogressTimeout", 3000); + #endif + + m_LogLevel = assetConfig.GetInt("LogLevel", m_LogLevel); + m_HitRateDisplay = (ulong)assetConfig.GetLong("HitRateDisplay", (long)m_HitRateDisplay); + + m_FileExpiration = TimeSpan.FromHours(assetConfig.GetDouble("FileCacheTimeout", m_DefaultFileExpiration)); + m_FileExpirationCleanupTimer + = TimeSpan.FromHours( + assetConfig.GetDouble("FileCleanupTimer", m_FileExpirationCleanupTimer.TotalHours)); + + m_CacheDirectoryTiers = assetConfig.GetInt("CacheDirectoryTiers", m_CacheDirectoryTiers); + m_CacheDirectoryTierLen = assetConfig.GetInt("CacheDirectoryTierLength", m_CacheDirectoryTierLen); + + m_CacheWarnAt = assetConfig.GetInt("CacheWarnAt", m_CacheWarnAt); + + m_DeepScanBeforePurge = assetConfig.GetBoolean("DeepScanBeforePurge", m_DeepScanBeforePurge); } - m_CacheDirectory = assetConfig.GetString("CacheDirectory", m_DefaultCacheDirectory); - m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory", m_CacheDirectory); + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory {0}", m_CacheDirectory); - m_MemoryCacheEnabled = assetConfig.GetBoolean("MemoryCacheEnabled", false); - m_MemoryExpiration = TimeSpan.FromHours(assetConfig.GetDouble("MemoryCacheTimeout", m_DefaultMemoryExpiration)); - -#if WAIT_ON_INPROGRESS_REQUESTS - m_WaitOnInprogressTimeout = assetConfig.GetInt("WaitOnInprogressTimeout", 3000); -#endif - - m_LogLevel = assetConfig.GetInt("LogLevel", 0); - m_HitRateDisplay = (ulong)assetConfig.GetInt("HitRateDisplay", 1000); - - m_FileExpiration = TimeSpan.FromHours(assetConfig.GetDouble("FileCacheTimeout", m_DefaultFileExpiration)); - m_FileExpirationCleanupTimer = TimeSpan.FromHours(assetConfig.GetDouble("FileCleanupTimer", m_DefaultFileExpiration)); if ((m_FileExpiration > TimeSpan.Zero) && (m_FileExpirationCleanupTimer > TimeSpan.Zero)) { m_CacheCleanTimer = new System.Timers.Timer(m_FileExpirationCleanupTimer.TotalMilliseconds); @@ -170,7 +182,6 @@ namespace Flotsam.RegionModules.AssetCache m_CacheCleanTimer.Start(); } - m_CacheDirectoryTiers = assetConfig.GetInt("CacheDirectoryTiers", 1); if (m_CacheDirectoryTiers < 1) { m_CacheDirectoryTiers = 1; @@ -180,7 +191,6 @@ namespace Flotsam.RegionModules.AssetCache m_CacheDirectoryTiers = 3; } - m_CacheDirectoryTierLen = assetConfig.GetInt("CacheDirectoryTierLength", 3); if (m_CacheDirectoryTierLen < 1) { m_CacheDirectoryTierLen = 1; @@ -190,14 +200,10 @@ namespace Flotsam.RegionModules.AssetCache m_CacheDirectoryTierLen = 4; } - m_CacheWarnAt = assetConfig.GetInt("CacheWarnAt", 30000); - - m_DeepScanBeforePurge = assetConfig.GetBoolean("DeepScanBeforePurge", false); - - MainConsole.Instance.Commands.AddCommand(this.Name, true, "fcache status", "fcache status", "Display cache status", HandleConsoleCommand); - MainConsole.Instance.Commands.AddCommand(this.Name, true, "fcache clear", "fcache clear [file] [memory]", "Remove all assets in the file and/or memory cache", HandleConsoleCommand); - MainConsole.Instance.Commands.AddCommand(this.Name, true, "fcache assets", "fcache assets", "Attempt a deep scan and cache of all assets in all scenes", HandleConsoleCommand); - MainConsole.Instance.Commands.AddCommand(this.Name, true, "fcache expire", "fcache expire ", "Purge cached assets older then the specified date/time", HandleConsoleCommand); + MainConsole.Instance.Commands.AddCommand(Name, true, "fcache status", "fcache status", "Display cache status", HandleConsoleCommand); + MainConsole.Instance.Commands.AddCommand(Name, true, "fcache clear", "fcache clear [file] [memory]", "Remove all assets in the file and/or memory cache", HandleConsoleCommand); + MainConsole.Instance.Commands.AddCommand(Name, true, "fcache assets", "fcache assets", "Attempt a deep scan and cache of all assets in all scenes", HandleConsoleCommand); + MainConsole.Instance.Commands.AddCommand(Name, true, "fcache expire", "fcache expire ", "Purge cached assets older then the specified date/time", HandleConsoleCommand); } } } diff --git a/bin/config-include/FlotsamCache.ini.example b/bin/config-include/FlotsamCache.ini.example index 026dee718d..1f2bf03162 100644 --- a/bin/config-include/FlotsamCache.ini.example +++ b/bin/config-include/FlotsamCache.ini.example @@ -29,7 +29,7 @@ ; 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 - FileCacheTimeout = 0 + FileCacheTimeout = 48 ; How often {in hours} should the disk be checked for expired filed ; Specify 0 to disable expiration checking From c7cef650db6bbbabfefa7a2fb47a028147b7e822 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 11 Jun 2011 00:10:40 +0100 Subject: [PATCH 05/26] Make it clear that WaitOnInprogressTimeout is currently a dead setting in FlotsamCache.ini.example --- bin/config-include/FlotsamCache.ini.example | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/config-include/FlotsamCache.ini.example b/bin/config-include/FlotsamCache.ini.example index 1f2bf03162..ad38ad15b5 100644 --- a/bin/config-include/FlotsamCache.ini.example +++ b/bin/config-include/FlotsamCache.ini.example @@ -38,6 +38,7 @@ ; If WAIT_ON_INPROGRESS_REQUESTS has been defined then this specifies how ; long (in miliseconds) to block a request thread while trying to complete ; an existing write to disk. + ; NOTE: THIS PARAMETER IS NOT CURRENTLY USED BY THE CACHE ; WaitOnInprogressTimeout = 3000 ; Number of tiers to use for cache directories (current valid From 39e878eb8f23cdae67b917d16f3dfc8709abcd9c Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 11 Jun 2011 00:35:31 +0100 Subject: [PATCH 06/26] Align CenomeCache.ini.example values with CenomeCache defaults. --- bin/config-include/CenomeCache.ini.example | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/bin/config-include/CenomeCache.ini.example b/bin/config-include/CenomeCache.ini.example index 8ef4e03bdc..4340493355 100644 --- a/bin/config-include/CenomeCache.ini.example +++ b/bin/config-include/CenomeCache.ini.example @@ -1,13 +1,14 @@ [AssetCache] ;; - ;; Options for CenmoeAssetCache + ;; Options for CenomeAssetCache ;; - ; 256 MB (default: 134217728) - MaxSize = 268435456 + ; Max size of the cache in bytes + ; 134217728 = 128 MB, 26843556 = 256 MB, etc (default: 134217728) + MaxSize = 134217728 - ; How many assets it is possible to store cache (default: 4096) - MaxCount = 16384 + ; How many assets it is possible to store in the cache (default: 4096) + MaxCount = 4096 - ; Expiration time - 1 hour (default: 30 minutes) - ExpirationTime = 60 + ; Expiration time in minutes (default: 30) + ExpirationTime = 30 From 9a62bfab0ea6c60ad2ce8b853b3dae95ef57ac69 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 11 Jun 2011 00:50:20 +0100 Subject: [PATCH 07/26] If the flotsam asset cache console command "fcache clear" is specified on its own, clear both memory and file caches --- .../CoreModules/Asset/FlotsamAssetCache.cs | 37 +++++++++++++------ 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index d9280c66e0..48ee277ae9 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -201,7 +201,7 @@ namespace Flotsam.RegionModules.AssetCache } MainConsole.Instance.Commands.AddCommand(Name, true, "fcache status", "fcache status", "Display cache status", HandleConsoleCommand); - MainConsole.Instance.Commands.AddCommand(Name, true, "fcache clear", "fcache clear [file] [memory]", "Remove all assets in the file and/or memory cache", HandleConsoleCommand); + MainConsole.Instance.Commands.AddCommand(Name, true, "fcache clear", "fcache clear [file] [memory]", "Remove all assets in the cache. If file or memory is specified then only this cache is cleared.", HandleConsoleCommand); MainConsole.Instance.Commands.AddCommand(Name, true, "fcache assets", "fcache assets", "Attempt a deep scan and cache of all assets in all scenes", HandleConsoleCommand); MainConsole.Instance.Commands.AddCommand(Name, true, "fcache expire", "fcache expire ", "Purge cached assets older then the specified date/time", HandleConsoleCommand); } @@ -729,24 +729,39 @@ namespace Flotsam.RegionModules.AssetCache break; case "clear": - if (cmdparams.Length < 3) + if (cmdparams.Length < 2) { - m_log.Warn("[FLOTSAM ASSET CACHE] Please specify memory and/or file cache."); + m_log.Warn("[FLOTSAM ASSET CACHE] Usage is fcache clear [file] [memory]"); break; } + + bool clearMemory = false, clearFile = false; + + if (cmdparams.Length == 2) + { + clearMemory = true; + clearFile = true; + } foreach (string s in cmdparams) { if (s.ToLower() == "memory") - { - m_MemoryCache.Clear(); - m_log.Info("[FLOTSAM ASSET CACHE] Memory cache cleared."); - } + clearMemory = true; else if (s.ToLower() == "file") - { - ClearFileCache(); - m_log.Info("[FLOTSAM ASSET CACHE] File cache cleared."); - } + clearFile = true; } + + if (clearMemory) + { + m_MemoryCache.Clear(); + m_log.Info("[FLOTSAM ASSET CACHE] Memory cache cleared."); + } + + if (clearFile) + { + ClearFileCache(); + m_log.Info("[FLOTSAM ASSET CACHE] File cache cleared."); + } + break; From 487cb51f69ac2f713797de03eb26a4b53afcfade Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 10 Jun 2011 17:22:17 -0700 Subject: [PATCH 08/26] 3rd way of reseting the HG Map. This time, don't use the grid service; instead keep track of which map blocks each client has seen in the region, and reset exactly those when the client closes. --- .../EntityTransfer/HGEntityTransferModule.cs | 25 ---- .../CoreModules/Hypergrid/HGWorldMapModule.cs | 121 ++++++++++-------- .../World/WorldMap/WorldMapModule.cs | 4 +- 3 files changed, 71 insertions(+), 79 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index 8df89adfdb..4d77ef478d 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -148,9 +148,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer base.AgentHasMovedAway(sp, logout); if (logout) { - // Reset the map - ResetMap(sp); - // Log them out of this grid m_aScene.PresenceService.LogoutAgent(sp.ControllingClient.SessionId); } @@ -285,28 +282,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } - protected void ResetMap(ScenePresence sp) - { - List regions = m_Scenes[0].GridService.GetRegionRange(m_Scenes[0].RegionInfo.ScopeID, 0, 17000 * (int)Constants.RegionSize, 0, 17000 * (int)Constants.RegionSize); - m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Resetting {0} tiles on the map", regions.Count); - if (regions != null) - { - List mapBlocks = new List(); - foreach (GridRegion r in regions) - { - MapBlockData mblock = new MapBlockData(); - mblock.X = (ushort)(r.RegionLocX / Constants.RegionSize); - mblock.Y = (ushort)(r.RegionLocY / Constants.RegionSize); - mblock.Name = ""; - mblock.Access = 254; // means 'simulator is offline'. We need this because the viewer ignores 255's - mblock.MapImageId = UUID.Zero; - mapBlocks.Add(mblock); - } - sp.ControllingClient.SendMapBlock(mapBlocks, 0); - } - - } - #endregion #region IUserAgentVerificationModule diff --git a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs index fd2cc20a1a..0c60391fe2 100644 --- a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs +++ b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs @@ -41,7 +41,10 @@ namespace OpenSim.Region.CoreModules.Hypergrid { public class HGWorldMapModule : WorldMapModule { - //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + // Remember the map area that each client has been exposed to in this region + private Dictionary> m_SeenMapBlocks = new Dictionary>(); #region INonSharedRegionModule Members @@ -52,6 +55,13 @@ namespace OpenSim.Region.CoreModules.Hypergrid m_Enabled = true; } + public override void AddRegion(Scene scene) + { + base.AddRegion(scene); + + scene.EventManager.OnClientClosed += new EventManager.ClientClosed(EventManager_OnClientClosed); + } + public override string Name { get { return "HGWorldMap"; } @@ -59,65 +69,70 @@ namespace OpenSim.Region.CoreModules.Hypergrid #endregion - //protected override void GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) - //{ - // List mapBlocks = new List(); - // List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, - // minX * (int)Constants.RegionSize, maxX * (int)Constants.RegionSize, - // minY * (int)Constants.RegionSize, maxY * (int)Constants.RegionSize); - - // foreach (GridRegion r in regions) - // { - // uint x = 0, y = 0; - // long handle = 0; - // if (r.RegionSecret != null && r.RegionSecret != string.Empty) - // { - // if (long.TryParse(r.RegionSecret, out handle)) - // { - // Utils.LongToUInts((ulong)handle, out x, out y); - // x = x / Constants.RegionSize; - // y = y / Constants.RegionSize; - // } - // } - - // if (handle == 0 || - // // Check the distance from the current region - // (handle != 0 && Math.Abs((int)(x - m_scene.RegionInfo.RegionLocX)) < 4096 && Math.Abs((int)(y - m_scene.RegionInfo.RegionLocY)) < 4096)) - // { - // MapBlockData block = new MapBlockData(); - // MapBlockFromGridRegion(block, r); - // mapBlocks.Add(block); - // } - // } - - // // Different from super - // //FillInMap(mapBlocks, minX, minY, maxX, maxY); - // // - - // remoteClient.SendMapBlock(mapBlocks, 0); - - //} - - - private void FillInMap(List mapBlocks, int minX, int minY, int maxX, int maxY) + void EventManager_OnClientClosed(UUID clientID, Scene scene) { - for (int x = minX; x <= maxX; x++) + ScenePresence sp = scene.GetScenePresence(clientID); + if (sp != null) { - for (int y = minY; y <= maxY; y++) + if (m_SeenMapBlocks.ContainsKey(clientID)) { - MapBlockData mblock = mapBlocks.Find(delegate(MapBlockData mb) { return ((mb.X == x) && (mb.Y == y)); }); - if (mblock == null) + List mapBlocks = m_SeenMapBlocks[clientID]; + foreach (MapBlockData b in mapBlocks) { - mblock = new MapBlockData(); - mblock.X = (ushort)x; - mblock.Y = (ushort)y; - mblock.Name = ""; - mblock.Access = 254; // means 'simulator is offline'. We need this because the viewer ignores 255's - mblock.MapImageId = UUID.Zero; - mapBlocks.Add(mblock); + b.Name = string.Empty; + b.Access = 254; // means 'simulator is offline'. We need this because the viewer ignores 255's } + + m_log.DebugFormat("[HG MAP]: Reseting {0} blocks", mapBlocks.Count); + sp.ControllingClient.SendMapBlock(mapBlocks, 0); + m_SeenMapBlocks.Remove(clientID); } } } + + protected override List GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) + { + List mapBlocks = base.GetAndSendBlocks(remoteClient, minX, minY, maxX, maxY, flag); + lock (m_SeenMapBlocks) + { + if (!m_SeenMapBlocks.ContainsKey(remoteClient.AgentId)) + { + m_SeenMapBlocks.Add(remoteClient.AgentId, mapBlocks); + } + else + { + List seen = m_SeenMapBlocks[remoteClient.AgentId]; + List newBlocks = new List(); + foreach (MapBlockData b in mapBlocks) + if (seen.Find(delegate(MapBlockData bdata) { return bdata.X == b.X && bdata.Y == b.Y; }) == null) + newBlocks.Add(b); + seen.AddRange(newBlocks); + } + } + + return mapBlocks; + } + + } + + class MapArea + { + public int minX; + public int minY; + public int maxX; + public int maxY; + + public MapArea(int mix, int miy, int max, int may) + { + minX = mix; + minY = miy; + maxX = max; + maxY = may; + } + + public void Print() + { + Console.WriteLine(String.Format(" --> Area is minX={0} minY={1} minY={2} maxY={3}", minX, minY, maxY, maxY)); + } } } diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index 69d300553c..3553c9af45 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -845,7 +845,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap } } - protected virtual void GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) + protected virtual List GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) { List mapBlocks = new List(); List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, @@ -860,6 +860,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap mapBlocks.Add(block); } remoteClient.SendMapBlock(mapBlocks, 0); + + return mapBlocks; } protected void MapBlockFromGridRegion(MapBlockData block, GridRegion r) From 0ae022d68822c05130f76a6e80bccd669a3d76ed Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 10 Jun 2011 20:59:57 -0700 Subject: [PATCH 09/26] Decreased timeout of HG StatusNotification to 4secs. http://opensimulator.org/mantis/view.php?id=5516 --- .../Services/Connectors/Hypergrid/UserAgentServiceConnector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs index 853e5243ab..b7e09e83d6 100644 --- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs @@ -427,7 +427,7 @@ namespace OpenSim.Services.Connectors.Hypergrid XmlRpcResponse response = null; try { - response = request.Send(m_ServerURL, 10000); + response = request.Send(m_ServerURL, 4000); } catch (Exception e) { From 5f311c91c781d09e266fb76cb7747550fe2afc16 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 10 Jun 2011 21:07:50 -0700 Subject: [PATCH 10/26] More tweaking on the UserAgentServiceConnector: add constructor that does not do DNS lookup, and use that for friends notification. --- .../Avatar/Friends/HGFriendsModule.cs | 2 +- .../Hypergrid/UserAgentServiceConnector.cs | 35 ++++++++++++------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs index b9d67193ab..b8342efdde 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs @@ -278,7 +278,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends List ids = new List(); foreach (FriendInfo f in kvp.Value) ids.Add(f.Friend); - UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key); + UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key, false); List friendsOnline = uConn.StatusNotification(ids, userID, online); // need to debug this here if (online) diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs index b7e09e83d6..2a5fb40475 100644 --- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs @@ -51,22 +51,31 @@ namespace OpenSim.Services.Connectors.Hypergrid MethodBase.GetCurrentMethod().DeclaringType); string m_ServerURL; - public UserAgentServiceConnector(string url) + + public UserAgentServiceConnector(string url) : this(url, true) + { + } + + public UserAgentServiceConnector(string url, bool dnsLookup) { m_ServerURL = url; - // Doing this here, because XML-RPC or mono have some strong ideas about - // caching DNS translations. - try + + if (dnsLookup) { - Uri m_Uri = new Uri(m_ServerURL); - IPAddress ip = Util.GetHostFromDNS(m_Uri.Host); - m_ServerURL = m_ServerURL.Replace(m_Uri.Host, ip.ToString()); - if (!m_ServerURL.EndsWith("/")) - m_ServerURL += "/"; - } - catch (Exception e) - { - m_log.DebugFormat("[USER AGENT CONNECTOR]: Malformed Uri {0}: {1}", m_ServerURL, e.Message); + // Doing this here, because XML-RPC or mono have some strong ideas about + // caching DNS translations. + try + { + Uri m_Uri = new Uri(m_ServerURL); + IPAddress ip = Util.GetHostFromDNS(m_Uri.Host); + m_ServerURL = m_ServerURL.Replace(m_Uri.Host, ip.ToString()); + if (!m_ServerURL.EndsWith("/")) + m_ServerURL += "/"; + } + catch (Exception e) + { + m_log.DebugFormat("[USER AGENT CONNECTOR]: Malformed Uri {0}: {1}", m_ServerURL, e.Message); + } } m_log.DebugFormat("[USER AGENT CONNECTOR]: new connector to {0} ({1})", url, m_ServerURL); } From e07d71d2982ac2c128035fee29991eda949bd8dd Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 10 Jun 2011 21:17:34 -0700 Subject: [PATCH 11/26] Added a Sleep in between each site call, to slow the xml-rpc requests down. --- .../Avatar/Friends/HGFriendsModule.cs | 77 ++++++++++--------- 1 file changed, 40 insertions(+), 37 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs index b8342efdde..40506a5aeb 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs @@ -29,6 +29,8 @@ using System; using System.Collections; using System.Collections.Generic; using System.Reflection; +using System.Threading; + using log4net; using Nini.Config; using Nwc.XmlRpc; @@ -194,46 +196,46 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends //} - private void CollectOnlineFriendsElsewhere(UUID userID, List foreignFriends) - { - // let's divide the friends on a per-domain basis - Dictionary> friendsPerDomain = new Dictionary>(); - foreach (string friend in foreignFriends) - { - UUID friendID; - if (!UUID.TryParse(friend, out friendID)) - { - // it's a foreign friend - string url = string.Empty, tmp = string.Empty; - if (Util.ParseUniversalUserIdentifier(friend, out friendID, out url, out tmp, out tmp, out tmp)) - { - if (!friendsPerDomain.ContainsKey(url)) - friendsPerDomain[url] = new List(); - friendsPerDomain[url].Add(friend); - } - } - } + //private void CollectOnlineFriendsElsewhere(UUID userID, List foreignFriends) + //{ + // // let's divide the friends on a per-domain basis + // Dictionary> friendsPerDomain = new Dictionary>(); + // foreach (string friend in foreignFriends) + // { + // UUID friendID; + // if (!UUID.TryParse(friend, out friendID)) + // { + // // it's a foreign friend + // string url = string.Empty, tmp = string.Empty; + // if (Util.ParseUniversalUserIdentifier(friend, out friendID, out url, out tmp, out tmp, out tmp)) + // { + // if (!friendsPerDomain.ContainsKey(url)) + // friendsPerDomain[url] = new List(); + // friendsPerDomain[url].Add(friend); + // } + // } + // } - // Now, call those worlds + // // Now, call those worlds - foreach (KeyValuePair> kvp in friendsPerDomain) - { - List ids = new List(); - foreach (string f in kvp.Value) - ids.Add(f); - UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key); - List online = uConn.GetOnlineFriends(userID, ids); - // Finally send the notifications to the user - // this whole process may take a while, so let's check at every - // iteration that the user is still here - IClientAPI client = LocateClientObject(userID); - if (client != null) - client.SendAgentOnline(online.ToArray()); - else - break; - } + // foreach (KeyValuePair> kvp in friendsPerDomain) + // { + // List ids = new List(); + // foreach (string f in kvp.Value) + // ids.Add(f); + // UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key); + // List online = uConn.GetOnlineFriends(userID, ids); + // // Finally send the notifications to the user + // // this whole process may take a while, so let's check at every + // // iteration that the user is still here + // IClientAPI client = LocateClientObject(userID); + // if (client != null) + // client.SendAgentOnline(online.ToArray()); + // else + // break; + // } - } + //} protected override void StatusNotify(List friendList, UUID userID, bool online) { @@ -280,6 +282,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends ids.Add(f.Friend); UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key, false); List friendsOnline = uConn.StatusNotification(ids, userID, online); + Thread.Sleep(100); // need to debug this here if (online) { From d99277939750247ad100395394720c73a3580c72 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 11 Jun 2011 09:36:57 -0700 Subject: [PATCH 12/26] Switched order of SQL statements in Friends migration -- resulted in the wrong key --- OpenSim/Data/MySQL/Resources/FriendsStore.migrations | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Data/MySQL/Resources/FriendsStore.migrations b/OpenSim/Data/MySQL/Resources/FriendsStore.migrations index 7848e49955..55d82eca73 100644 --- a/OpenSim/Data/MySQL/Resources/FriendsStore.migrations +++ b/OpenSim/Data/MySQL/Resources/FriendsStore.migrations @@ -25,8 +25,8 @@ COMMIT; BEGIN; +ALTER TABLE `Friends` MODIFY COLUMN PrincipalID varchar(255) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'; ALTER TABLE `Friends` DROP PRIMARY KEY; ALTER TABLE `Friends` ADD PRIMARY KEY(PrincipalID(36), Friend(36)); -ALTER TABLE `Friends` MODIFY COLUMN PrincipalID varchar(255) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'; COMMIT; From e1ca77a0dbc68431131b0505f03cf45dbfe5b7d9 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 11 Jun 2011 17:22:35 -0700 Subject: [PATCH 13/26] Only send AgentOnline to the client if the friendsOnline list has elements. Also, increased the timeout on UserAgentServiceConnector, StatusNotification again. --- OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs | 2 +- .../Services/Connectors/Hypergrid/UserAgentServiceConnector.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs index 40506a5aeb..2c915140fe 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs @@ -284,7 +284,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends List friendsOnline = uConn.StatusNotification(ids, userID, online); Thread.Sleep(100); // need to debug this here - if (online) + if (online && friendsOnline.Count > 0) { IClientAPI client = LocateClientObject(userID); if (client != null) diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs index 2a5fb40475..6265bcd3fc 100644 --- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs @@ -436,7 +436,7 @@ namespace OpenSim.Services.Connectors.Hypergrid XmlRpcResponse response = null; try { - response = request.Send(m_ServerURL, 4000); + response = request.Send(m_ServerURL, 6000); } catch (Exception e) { From 06e254c392c754bf7e7a1c80400a3ef5b1a82ca3 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sat, 11 Jun 2011 17:48:19 -0700 Subject: [PATCH 14/26] A few more cleanups on the way to close http://opensimulator.org/mantis/view.php?id=5516 once and for all. Moral of the story: don't send AgentOnline/Offline to viewers with a zero-length array. --- .../CoreModules/Avatar/Friends/HGFriendsModule.cs | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs index 2c915140fe..dda67f9c2b 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs @@ -280,10 +280,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends List ids = new List(); foreach (FriendInfo f in kvp.Value) ids.Add(f.Friend); - UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key, false); + UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key); List friendsOnline = uConn.StatusNotification(ids, userID, online); - Thread.Sleep(100); - // need to debug this here + if (online && friendsOnline.Count > 0) { IClientAPI client = LocateClientObject(userID); @@ -305,15 +304,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends if (Util.ParseUniversalUserIdentifier(fid, out agentID, out url, out first, out last, out tmp)) { IUserManagement userMan = m_Scenes[0].RequestModuleInterface(); - userMan.AddUser(agentID, url + ";" + first + " " + last); + userMan.AddUser(agentID, first, last, url); - try // our best - { - string[] parts = userMan.GetUserName(agentID).Split(); - first = parts[0]; - last = parts[1]; - } - catch { } return true; } return false; From fd57c91b4a10cf7ee1e94dc8fe4e81eb0d5bae3d Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 12 Jun 2011 15:37:42 -0700 Subject: [PATCH 15/26] First pass at making the V2 map work. Standalones only for now. There are some issues with the zoom level -- TBD. --- .../Servers/HttpServer/BaseHttpServer.cs | 4 +- .../MapImageServiceInConnectorModule.cs | 111 +++++++ .../MapImage/MapImageServiceModule.cs | 232 ++++++++++++++ .../World/WorldMap/WorldMapModule.cs | 8 +- .../Handlers/Map/MapAddServerConnector.cs | 61 ++++ .../Handlers/Map/MapGetServerConnector.cs | 105 +++++++ .../MapImage/MapImageServiceConnector.cs | 158 ++++++++++ .../{IMapService.cs => IMapImageService.cs} | 6 +- .../MapImageService/MapImageService.cs | 295 ++++++++++++++++++ bin/config-include/Standalone.ini | 7 + .../StandaloneCommon.ini.example | 3 + bin/config-include/StandaloneHypergrid.ini | 11 +- prebuild.xml | 30 ++ 13 files changed, 1021 insertions(+), 10 deletions(-) create mode 100644 OpenSim/Region/CoreModules/ServiceConnectorsIn/MapImage/MapImageServiceInConnectorModule.cs create mode 100644 OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs create mode 100644 OpenSim/Server/Handlers/Map/MapAddServerConnector.cs create mode 100644 OpenSim/Server/Handlers/Map/MapGetServerConnector.cs create mode 100644 OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs rename OpenSim/Services/Interfaces/{IMapService.cs => IMapImageService.cs} (86%) create mode 100644 OpenSim/Services/MapImageService/MapImageService.cs diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index 598e5d17cd..cb1117ae55 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs @@ -412,7 +412,7 @@ namespace OpenSim.Framework.Servers.HttpServer // OpenSim.Framework.WebUtil.OSHeaderRequestID if (request.Headers["opensim-request-id"] != null) reqnum = String.Format("{0}:{1}",request.RemoteIPEndPoint,request.Headers["opensim-request-id"]); - // m_log.DebugFormat("[BASE HTTP SERVER]: <{0}> handle request for {1}",reqnum,request.RawUrl); + //m_log.DebugFormat("[BASE HTTP SERVER]: <{0}> handle request for {1}",reqnum,request.RawUrl); Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", true); @@ -440,7 +440,7 @@ namespace OpenSim.Framework.Servers.HttpServer string path = request.RawUrl; string handlerKey = GetHandlerKey(request.HttpMethod, path); -// m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path); + //m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path); if (TryGetStreamHandler(handlerKey, out requestHandler)) { diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/MapImage/MapImageServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/MapImage/MapImageServiceInConnectorModule.cs new file mode 100644 index 0000000000..b570155048 --- /dev/null +++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/MapImage/MapImageServiceInConnectorModule.cs @@ -0,0 +1,111 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Reflection; +using System.Collections.Generic; +using log4net; +using Mono.Addins; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Server.Base; +using OpenSim.Server.Handlers.Base; +using OpenSim.Server.Handlers.MapImage; +using OpenSim.Services.Interfaces; + +namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.MapImage +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class MapImageServiceInConnectorModule : ISharedRegionModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static bool m_Enabled = false; + + private IConfigSource m_Config; + bool m_Registered = false; + + #region IRegionModule interface + + public void Initialise(IConfigSource config) + { + m_Config = config; + IConfig moduleConfig = config.Configs["Modules"]; + if (moduleConfig != null) + { + m_Enabled = moduleConfig.GetBoolean("MapImageServiceInConnector", false); + if (m_Enabled) + { + m_log.Info("[MAP SERVICE IN CONNECTOR]: MapImage Service In Connector enabled"); + new MapGetServiceConnector(m_Config, MainServer.Instance, "MapImageService"); + } + + } + + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public Type ReplaceableInterface + { + get { return null; } + } + + public string Name + { + get { return "MapImageServiceIn"; } + } + + public void AddRegion(Scene scene) + { + if (!m_Enabled) + return; + } + + public void RemoveRegion(Scene scene) + { + if (!m_Enabled) + return; + } + + public void RegionLoaded(Scene scene) + { + if (!m_Enabled) + return; + } + + #endregion + + } +} diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs new file mode 100644 index 0000000000..ee90859744 --- /dev/null +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs @@ -0,0 +1,232 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Net; +using System.IO; +using System.Timers; +using System.Drawing; +using System.Drawing.Imaging; + +using log4net; +using Mono.Addins; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using OpenSim.Server.Base; +using OpenMetaverse; +using OpenMetaverse.StructuredData; + +namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage +{ + /// + /// + /// + /// + + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class MapImageServiceModule : ISharedRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private bool m_enabled = false; + private IMapImageService m_MapService; + + private string m_serverUrl = String.Empty; + private Dictionary m_scenes = new Dictionary(); + + private int m_refreshtime = 0; + private int m_lastrefresh = 0; + private System.Timers.Timer m_refreshTimer = new System.Timers.Timer(); + + #region ISharedRegionModule + + public Type ReplaceableInterface { get { return null; } } + public string Name { get { return "MapImageServiceModule"; } } + public void RegionLoaded(Scene scene) { } + public void Close() { } + public void PostInitialise() { } + + + /// + /// + /// + public void Initialise(IConfigSource source) + { + IConfig moduleConfig = source.Configs["Modules"]; + if (moduleConfig != null) + { + string name = moduleConfig.GetString("MapImageService", ""); + if (name != Name) + return; + } + + IConfig config = source.Configs["MapImageService"]; + if (config == null) + return; + + int refreshminutes = Convert.ToInt32(config.GetString("RefreshTime")); + if (refreshminutes <= 0) + { + m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: No refresh time given in config. Module disabled."); + return; + } + + m_refreshtime = refreshminutes * 60 * 1000; // convert from minutes to ms + + string service = config.GetString("LocalServiceModule", string.Empty); + if (service == string.Empty) + { + m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: No service dll given in config. Unable to proceed."); + return; + } + + Object[] args = new Object[] { source }; + m_MapService = ServerUtils.LoadPlugin(service, args); + + m_refreshTimer.Enabled = true; + m_refreshTimer.AutoReset = true; + m_refreshTimer.Interval = m_refreshtime; + m_refreshTimer.Elapsed += new ElapsedEventHandler(HandleMaptileRefresh); + + m_log.InfoFormat("[MAP IMAGE SERVICE MODULE]: enabled with refresh time {0}min and service object {1}", + refreshminutes, service); + + m_enabled = true; + } + + /// + /// + /// + + + /// + /// + /// + public void AddRegion(Scene scene) + { + if (! m_enabled) + return; + + // Every shared region module has to maintain an indepedent list of + // currently running regions + lock (m_scenes) + m_scenes[scene.RegionInfo.RegionID] = scene; + + scene.EventManager.OnPrimsLoaded += new EventManager.PrimsLoaded(EventManager_OnPrimsLoaded); + } + + /// + /// + /// + public void RemoveRegion(Scene scene) + { + if (! m_enabled) + return; + + lock (m_scenes) + m_scenes.Remove(scene.RegionInfo.RegionID); + } + + #endregion ISharedRegionModule + + void EventManager_OnPrimsLoaded(Scene s) + { + UploadMapTile(s); + } + + + /// + /// + /// + private void HandleMaptileRefresh(object sender, EventArgs ea) + { + // this approach is a bit convoluted becase we want to wait for the + // first upload to happen on startup but after all the objects are + // loaded and initialized + if (m_lastrefresh > 0 && Util.EnvironmentTickCountSubtract(m_lastrefresh) < m_refreshtime) + return; + + m_log.DebugFormat("[MAP IMAGE SERVICE MODULE]: map refresh!"); + lock (m_scenes) + { + foreach (IScene scene in m_scenes.Values) + { + try + { + UploadMapTile(scene); + } + catch (Exception ex) + { + m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: something bad happened {0}", ex.Message); + } + } + } + + m_lastrefresh = Util.EnvironmentTickCount(); + } + + /// + /// + /// + private void UploadMapTile(IScene scene) + { + m_log.DebugFormat("[MAP IMAGE SERVICE MODULE]: upload maptile for {0}", scene.RegionInfo.RegionName); + + // Create a PNG map tile and upload it to the AddMapTile API + byte[] jpgData = Utils.EmptyBytes; + IMapImageGenerator tileGenerator = scene.RequestModuleInterface(); + if (tileGenerator == null) + { + m_log.Warn("[MAP IMAGE SERVICE MODULE]: Cannot upload PNG map tile without an ImageGenerator"); + return; + } + + using (Image mapTile = tileGenerator.CreateMapTile()) + { + using (MemoryStream stream = new MemoryStream()) + { + mapTile.Save(stream, ImageFormat.Jpeg); + jpgData = stream.ToArray(); + } + } + + string reason = string.Empty; + if (!m_MapService.AddMapTile((int)scene.RegionInfo.RegionLocX, (int)scene.RegionInfo.RegionLocY, jpgData, out reason)) + { + m_log.DebugFormat("[MAP IMAGE SERVICE MODULE]: Unable to upload tile image for {0} at {1}-{2}: {3}", + scene.RegionInfo.RegionName, scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY, reason); + } + + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index 3553c9af45..079b1c205d 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -849,10 +849,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap { List mapBlocks = new List(); List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, - (minX - 4) * (int)Constants.RegionSize, - (maxX + 4) * (int)Constants.RegionSize, - (minY - 4) * (int)Constants.RegionSize, - (maxY + 4) * (int)Constants.RegionSize); + (minX - 8) * (int)Constants.RegionSize, + (maxX + 8) * (int)Constants.RegionSize, + (minY - 8) * (int)Constants.RegionSize, + (maxY + 8) * (int)Constants.RegionSize); foreach (GridRegion r in regions) { MapBlockData block = new MapBlockData(); diff --git a/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs b/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs new file mode 100644 index 0000000000..a953cd7eaf --- /dev/null +++ b/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs @@ -0,0 +1,61 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using Nini.Config; +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Server.Handlers.Base; + +namespace OpenSim.Server.Handlers.MapImage +{ + public class MapAddServiceConnector : ServiceConnector + { + private IMapImageService m_MapService; + private string m_ConfigName = "MapImageService"; + + public MapAddServiceConnector(IConfigSource config, IHttpServer server, string configName) : + base(config, server, configName) + { + IConfig serverConfig = config.Configs[m_ConfigName]; + if (serverConfig == null) + throw new Exception(String.Format("No section {0} in config file", m_ConfigName)); + + string gridService = serverConfig.GetString("LocalServiceModule", + String.Empty); + + if (gridService == String.Empty) + throw new Exception("No LocalServiceModule in config file"); + + Object[] args = new Object[] { config }; + m_MapService = ServerUtils.LoadPlugin(gridService, args); + + //server.AddStreamHandler(new PresenceServerPostHandler(m_PresenceService)); + } + } +} diff --git a/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs new file mode 100644 index 0000000000..9448af743b --- /dev/null +++ b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs @@ -0,0 +1,105 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.IO; +using System.Net; +using System.Reflection; + +using Nini.Config; +using log4net; + +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Server.Handlers.Base; + +namespace OpenSim.Server.Handlers.MapImage +{ + public class MapGetServiceConnector : ServiceConnector + { + private IMapImageService m_MapService; + private string m_ConfigName = "MapImageService"; + + public MapGetServiceConnector(IConfigSource config, IHttpServer server, string configName) : + base(config, server, configName) + { + IConfig serverConfig = config.Configs[m_ConfigName]; + if (serverConfig == null) + throw new Exception(String.Format("No section {0} in config file", m_ConfigName)); + + string gridService = serverConfig.GetString("LocalServiceModule", + String.Empty); + + if (gridService == String.Empty) + throw new Exception("No LocalServiceModule in config file"); + + Object[] args = new Object[] { config }; + m_MapService = ServerUtils.LoadPlugin(gridService, args); + + server.AddStreamHandler(new MapServerGetHandler(m_MapService)); + } + } + + class MapServerGetHandler : BaseStreamHandler + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private IMapImageService m_MapService; + + public MapServerGetHandler(IMapImageService service) : + base("GET", "/map") + { + m_MapService = service; + } + + public override byte[] Handle(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + m_log.DebugFormat("[MAP SERVICE IMAGE HANDLER]: retrieving {0}", path); + byte[] result = new byte[0]; + + string format = string.Empty; + result = m_MapService.GetMapTile(path.Trim('/'), out format); + + if (result.Length > 0) + { + httpResponse.StatusCode = (int)HttpStatusCode.OK; + if (format.Equals("png")) + httpResponse.ContentType = "image/png"; + else if (format.Equals("jpg") || format.Equals("jpeg")) + httpResponse.ContentType = "image/jpeg"; + } + else + { + httpResponse.StatusCode = (int)HttpStatusCode.NotFound; + httpResponse.ContentType = "text/plain"; + } + + return result; + } + + } +} diff --git a/OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs b/OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs new file mode 100644 index 0000000000..ff0e9d9aee --- /dev/null +++ b/OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs @@ -0,0 +1,158 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using log4net; +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Reflection; + +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Framework.Communications; +using OpenSim.Services.Interfaces; +using OpenMetaverse; +using OpenMetaverse.StructuredData; + +namespace OpenSim.Services.Connectors +{ + public class MapImageServicesConnector : IMapImageService + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private string m_ServerURI = String.Empty; + private IImprovedAssetCache m_Cache = null; + + public MapImageServicesConnector() + { + } + + public MapImageServicesConnector(string serverURI) + { + m_ServerURI = serverURI.TrimEnd('/'); + } + + public MapImageServicesConnector(IConfigSource source) + { + Initialise(source); + } + + public virtual void Initialise(IConfigSource source) + { + IConfig config = source.Configs["MapImageService"]; + if (config == null) + { + m_log.Error("[MAP IMAGE CONNECTOR]: MapImageService missing"); + throw new Exception("MapImage connector init error"); + } + + string serviceURI = config.GetString("MapImageServerURI", + String.Empty); + + if (serviceURI == String.Empty) + { + m_log.Error("[MAP IMAGE CONNECTOR]: No Server URI named in section MapImageService"); + throw new Exception("MapImage connector init error"); + } + m_ServerURI = serviceURI; + } + + public bool AddMapTile(int x, int y, byte[] pngData, out string reason) + { + List postParameters = new List() + { + new MultipartForm.Parameter("X", x.ToString()), + new MultipartForm.Parameter("Y", y.ToString()), + new MultipartForm.File("Tile", "tile.png", "image/png", pngData) + }; + + reason = string.Empty; + int tickstart = Util.EnvironmentTickCount(); + + // Make the remote storage request + try + { + HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(m_ServerURI); + request.Timeout = 20000; + request.ReadWriteTimeout = 5000; + + using (HttpWebResponse response = MultipartForm.Post(request, postParameters)) + { + using (Stream responseStream = response.GetResponseStream()) + { + string responseStr = responseStream.GetStreamString(); + OSD responseOSD = OSDParser.Deserialize(responseStr); + if (responseOSD.Type == OSDType.Map) + { + OSDMap responseMap = (OSDMap)responseOSD; + if (responseMap["Success"].AsBoolean()) + return true; + + reason = "Upload failed: " + responseMap["Message"].AsString(); + } + else + { + reason = "Response format was invalid:\n" + responseStr; + } + } + } + } + catch (WebException we) + { + reason = we.Message; + if (we.Status == WebExceptionStatus.ProtocolError) + { + HttpWebResponse webResponse = (HttpWebResponse)we.Response; + reason = String.Format("[{0}] {1}", webResponse.StatusCode, webResponse.StatusDescription); + } + } + catch (Exception ex) + { + reason = ex.Message; + } + finally + { + // This just dumps a warning for any operation that takes more than 100 ms + int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); + m_log.DebugFormat("[MAP IMAGE CONNECTOR]: map tile uploaded in {0}ms", tickdiff); + } + + return false; + } + + public byte[] GetMapTile(string fileName, out string format) + { + format = string.Empty; + new Exception("GetMapTile method not Implemented"); + return null; + } + } +} diff --git a/OpenSim/Services/Interfaces/IMapService.cs b/OpenSim/Services/Interfaces/IMapImageService.cs similarity index 86% rename from OpenSim/Services/Interfaces/IMapService.cs rename to OpenSim/Services/Interfaces/IMapImageService.cs index c70f484f08..a7b2cf1dfd 100644 --- a/OpenSim/Services/Interfaces/IMapService.cs +++ b/OpenSim/Services/Interfaces/IMapImageService.cs @@ -31,8 +31,10 @@ using OpenMetaverse; namespace OpenSim.Services.Interfaces { - public interface IMapService + public interface IMapImageService { - List GetMapBlocks(UUID scopeID, int minX, int minY, int maxX, int maxY); + //List GetMapBlocks(UUID scopeID, int minX, int minY, int maxX, int maxY); + bool AddMapTile(int x, int y, byte[] imageData, out string reason); + byte[] GetMapTile(string fileName, out string format); } } diff --git a/OpenSim/Services/MapImageService/MapImageService.cs b/OpenSim/Services/MapImageService/MapImageService.cs new file mode 100644 index 0000000000..596c4a6f48 --- /dev/null +++ b/OpenSim/Services/MapImageService/MapImageService.cs @@ -0,0 +1,295 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Net; +using System.Reflection; + +using Nini.Config; +using log4net; +using OpenMetaverse; + +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Services.Interfaces; + + +namespace OpenSim.Services.MapImageService +{ + public class MapImageService : IMapImageService + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private const int ZOOM_LEVELS = 8; + private const int IMAGE_WIDTH = 256; + private const int HALF_WIDTH = 128; + private const int JPEG_QUALITY = 80; + + private static string m_TilesStoragePath = "maptiles"; + + private static object m_Sync = new object(); + private static bool m_Initialized = false; + private static string m_WaterTileFile = string.Empty; + private static Color m_Watercolor = Color.FromArgb(29, 71, 95); + + public MapImageService(IConfigSource config) + { + if (!m_Initialized) + { + m_Initialized = true; + m_log.Debug("[MAP IMAGE SERVICE]: Starting MapImage service"); + + IConfig serviceConfig = config.Configs["MapImageService"]; + if (serviceConfig != null) + { + m_TilesStoragePath = serviceConfig.GetString("TilesStoragePath", m_TilesStoragePath); + if (!Directory.Exists(m_TilesStoragePath)) + Directory.CreateDirectory(m_TilesStoragePath); + + + m_WaterTileFile = Path.Combine(m_TilesStoragePath, "water.jpg"); + if (!File.Exists(m_WaterTileFile)) + { + Bitmap waterTile = new Bitmap(IMAGE_WIDTH, IMAGE_WIDTH); + FillImage(waterTile, m_Watercolor); + waterTile.Save(m_WaterTileFile); + } + } + } + } + + #region IMapImageService + + public bool AddMapTile(int x, int y, byte[] imageData, out string reason) + { + reason = string.Empty; + string fileName = GetFileName(1, x, y); + + lock (m_Sync) + { + try + { + using (FileStream f = File.Open(fileName, FileMode.OpenOrCreate, FileAccess.Write)) + f.Write(imageData, 0, imageData.Length); + } + catch (Exception e) + { + m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to save image file {0}: {1}", fileName, e); + reason = e.Message; + return false; + } + + // Also save in png format? + + // Stitch seven more aggregate tiles together + for (uint zoomLevel = 2; zoomLevel <= ZOOM_LEVELS; zoomLevel++) + { + // Calculate the width (in full resolution tiles) and bottom-left + // corner of the current zoom level + int width = (int)Math.Pow(2, (double)(zoomLevel - 1)); + int x1 = x - (x % width); + int y1 = y - (y % width); + + if (!CreateTile(zoomLevel, x1, y1)) + { + m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to create tile for {0} at zoom level {1}", fileName, zoomLevel); + reason = string.Format("Map tile at zoom level {0} failed", zoomLevel); + return false; + } + } + } + + return true; + } + + public byte[] GetMapTile(string fileName, out string format) + { + format = "jpg"; + string fullName = Path.Combine(m_TilesStoragePath, fileName); + if (File.Exists(fullName)) + { + format = Path.GetExtension(fileName).ToLower(); + m_log.DebugFormat("[MAP IMAGE SERVICE]: Found file {0}, extension {1}", fileName, format); + return File.ReadAllBytes(fullName); + } + else if (File.Exists(m_WaterTileFile)) + { + m_log.DebugFormat("[MAP IMAGE SERVICE]: File not found {0}, sending water", fileName); + return File.ReadAllBytes(m_WaterTileFile); + } + else + { + m_log.DebugFormat("[MAP IMAGE SERVICE]: unable to get file {0}", fileName); + return new byte[0]; + } + } + + #endregion + + + private string GetFileName(uint zoomLevel, int x, int y) + { + string extension = "jpg"; + return Path.Combine(m_TilesStoragePath, string.Format("map-{0}-{1}-{2}-objects.{3}", zoomLevel, x, y, extension)); + } + + private Bitmap GetInputTileImage(string fileName) + { + try + { + if (File.Exists(fileName)) + return new Bitmap(fileName); + } + catch (Exception e) + { + m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to read image data from {0}: {1}", fileName, e); + } + + return null; + } + + private Bitmap GetOutputTileImage(string fileName) + { + try + { + if (File.Exists(fileName)) + return new Bitmap(fileName); + + else + { + // Create a new output tile with a transparent background + Bitmap bm = new Bitmap(IMAGE_WIDTH, IMAGE_WIDTH); + bm.MakeTransparent(); + return bm; + } + } + catch (Exception e) + { + m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to read image data from {0}: {1}", fileName, e); + } + + return null; + } + + private bool CreateTile(uint zoomLevel, int x, int y) + { + m_log.DebugFormat("[MAP IMAGE SERVICE]: Create tile for {0} {1}, zoom {2}", x, y, zoomLevel); + int prevWidth = (int)Math.Pow(2, (double)zoomLevel - 2); + int thisWidth = (int)Math.Pow(2, (double)zoomLevel - 1); + + // Convert x and y to the bottom left tile for this zoom level + int xIn = x - (x % prevWidth); + int yIn = y - (y % prevWidth); + + // Convert x and y to the bottom left tile for the next zoom level + int xOut = x - (x % thisWidth); + int yOut = y - (y % thisWidth); + + // Try to open the four input tiles from the previous zoom level + Bitmap inputBL = GetInputTileImage(GetFileName(zoomLevel - 1, xIn, yIn)); + Bitmap inputBR = GetInputTileImage(GetFileName(zoomLevel - 1, xIn + prevWidth, yIn)); + Bitmap inputTL = GetInputTileImage(GetFileName(zoomLevel - 1, xIn, yIn + prevWidth)); + Bitmap inputTR = GetInputTileImage(GetFileName(zoomLevel - 1, xIn + prevWidth, yIn + prevWidth)); + + // Open the output tile (current zoom level) + string outputFile = GetFileName(zoomLevel, xOut, yOut); + Bitmap output = GetOutputTileImage(outputFile); + if (output == null) + return false; + FillImage(output, m_Watercolor); + + if (inputBL != null) + { + ImageCopyResampled(output, inputBL, 0, HALF_WIDTH, 0, 0); + inputBL.Dispose(); + } + if (inputBR != null) + { + ImageCopyResampled(output, inputBR, HALF_WIDTH, HALF_WIDTH, 0, 0); + inputBR.Dispose(); + } + if (inputTL != null) + { + ImageCopyResampled(output, inputTL, 0, 0, 0, 0); + inputTL.Dispose(); + } + if (inputTR != null) + { + ImageCopyResampled(output, inputTR, HALF_WIDTH, 0, 0, 0); + inputTR.Dispose(); + } + + // Write the modified output + try + { + using (Bitmap final = new Bitmap(output)) + { + output.Dispose(); + final.Save(outputFile); + } + } + catch (Exception e) + { + m_log.WarnFormat("[MAP IMAGE SERVICE]: Oops on saving {0} {1}", outputFile, e); + } + + // Save also as png? + + return true; + } + + #region Image utilities + + private void FillImage(Bitmap bm, Color c) + { + for (int x = 0; x < bm.Width; x++) + for (int y = 0; y < bm.Height; y++) + bm.SetPixel(x, y, c); + } + + private void ImageCopyResampled(Bitmap output, Bitmap input, int destX, int destY, int srcX, int srcY) + { + int resamplingRateX = 2; // (input.Width - srcX) / (output.Width - destX); + int resamplingRateY = 2; // (input.Height - srcY) / (output.Height - destY); + + for (int x = destX; x < destX + HALF_WIDTH; x++) + for (int y = destY; y < destY + HALF_WIDTH; y++) + { + Color p = input.GetPixel(srcX + (x - destX) * resamplingRateX, srcY + (y - destY) * resamplingRateY); + output.SetPixel(x, y, p); + } + } + + #endregion + } +} diff --git a/bin/config-include/Standalone.ini b/bin/config-include/Standalone.ini index 4ff1a269bf..bf89d0bb9c 100644 --- a/bin/config-include/Standalone.ini +++ b/bin/config-include/Standalone.ini @@ -17,10 +17,12 @@ AvatarServices = "LocalAvatarServicesConnector" EntityTransferModule = "BasicEntityTransferModule" InventoryAccessModule = "BasicInventoryAccessModule" + MapImageService = "MapImageServiceModule" LibraryModule = true LLLoginServiceInConnector = true GridInfoServiceInConnector = true + MapImageServiceInConnector = true [Profile] Module = "BasicProfileModule" @@ -91,6 +93,11 @@ WelcomeMessage = "Welcome, Avatar!" +[MapImageService] + LocalServiceModule = "OpenSim.Services.MapImageService.dll:MapImageService" + ; in minutes + RefreshTime = 60 + ;; This should always be the very last thing on this file [Includes] Include-Common = "config-include/StandaloneCommon.ini" diff --git a/bin/config-include/StandaloneCommon.ini.example b/bin/config-include/StandaloneCommon.ini.example index 7359bba62f..69349d2b49 100644 --- a/bin/config-include/StandaloneCommon.ini.example +++ b/bin/config-include/StandaloneCommon.ini.example @@ -99,6 +99,9 @@ SRV_FriendsServerURI = "http://127.0.0.1:9000" SRV_IMServerURI = "http://127.0.0.1:9000" + ;; For Viewer 2 + MapTileURL = "http://127.0.0.1:9000" + ;; Regular expressions for controlling which client versions are accepted/denied. ;; An empty string means nothing is checked. ;; diff --git a/bin/config-include/StandaloneHypergrid.ini b/bin/config-include/StandaloneHypergrid.ini index 8480a77bbd..719df5c5c3 100644 --- a/bin/config-include/StandaloneHypergrid.ini +++ b/bin/config-include/StandaloneHypergrid.ini @@ -18,9 +18,10 @@ GridUserServices = "LocalGridUserServicesConnector" SimulationServices = "RemoteSimulationConnectorModule" AvatarServices = "LocalAvatarServicesConnector" + MapImageService = "MapImageServiceModule" EntityTransferModule = "HGEntityTransferModule" InventoryAccessModule = "HGInventoryAccessModule" - FriendsModule = "HGFriendsModule" + FriendsModule = "HGFriendsModule" InventoryServiceInConnector = true AssetServiceInConnector = true @@ -31,6 +32,7 @@ GridInfoServiceInConnector = true AuthenticationServiceInConnector = true SimulationServiceInConnector = true + MapImageServiceInConnector = true [Profile] Module = "BasicProfileModule" @@ -116,7 +118,12 @@ GridService = "OpenSim.Services.GridService.dll:GridService" AvatarService = "OpenSim.Services.AvatarService.dll:AvatarService" FriendsService = "OpenSim.Services.FriendsService.dll:FriendsService" - + +[MapImageService] + LocalServiceModule = "OpenSim.Services.MapImageService.dll:MapImageService" + ; in minutes + RefreshTime = 60 + [GatekeeperService] LocalServiceModule = "OpenSim.Services.HypergridService.dll:GatekeeperService" ;; for the service diff --git a/prebuild.xml b/prebuild.xml index 90f451d6a7..ed79b40c39 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -1269,6 +1269,36 @@ + + + + ../../../bin/ + + + + + ../../../bin/ + + + + ../../../bin/ + + + + + + + + + + + + + + + + + From 78c16da5444a2e363de50bc88c8d2b929dec0989 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 12 Jun 2011 17:05:45 -0700 Subject: [PATCH 16/26] A few bug fixes on map V2. Zoom level weirdness still there. --- .../World/WorldMap/WorldMapModule.cs | 18 ++++++++++++------ .../Handlers/Map/MapGetServerConnector.cs | 5 ++--- .../MapImageService/MapImageService.cs | 2 +- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index 079b1c205d..6e142bb2da 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -836,7 +836,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap block.Access = 254; // means 'simulator is offline' response.Add(block); } - remoteClient.SendMapBlock(response, 0); + if ((flag & 2) == 2) // V2 !!! + remoteClient.SendMapBlock(response, 2); + else + remoteClient.SendMapBlock(response, 0); } else { @@ -849,17 +852,20 @@ namespace OpenSim.Region.CoreModules.World.WorldMap { List mapBlocks = new List(); List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, - (minX - 8) * (int)Constants.RegionSize, - (maxX + 8) * (int)Constants.RegionSize, - (minY - 8) * (int)Constants.RegionSize, - (maxY + 8) * (int)Constants.RegionSize); + (minX - 4) * (int)Constants.RegionSize, + (maxX + 4) * (int)Constants.RegionSize, + (minY - 4) * (int)Constants.RegionSize, + (maxY + 4) * (int)Constants.RegionSize); foreach (GridRegion r in regions) { MapBlockData block = new MapBlockData(); MapBlockFromGridRegion(block, r); mapBlocks.Add(block); } - remoteClient.SendMapBlock(mapBlocks, 0); + if ((flag & 2) == 2) // V2 !!! + remoteClient.SendMapBlock(mapBlocks, 2); + else + remoteClient.SendMapBlock(mapBlocks, 0); return mapBlocks; } diff --git a/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs index 9448af743b..76dd695fe7 100644 --- a/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs +++ b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs @@ -83,13 +83,12 @@ namespace OpenSim.Server.Handlers.MapImage string format = string.Empty; result = m_MapService.GetMapTile(path.Trim('/'), out format); - if (result.Length > 0) { httpResponse.StatusCode = (int)HttpStatusCode.OK; - if (format.Equals("png")) + if (format.Equals(".png")) httpResponse.ContentType = "image/png"; - else if (format.Equals("jpg") || format.Equals("jpeg")) + else if (format.Equals(".jpg") || format.Equals(".jpeg")) httpResponse.ContentType = "image/jpeg"; } else diff --git a/OpenSim/Services/MapImageService/MapImageService.cs b/OpenSim/Services/MapImageService/MapImageService.cs index 596c4a6f48..ee424e14f3 100644 --- a/OpenSim/Services/MapImageService/MapImageService.cs +++ b/OpenSim/Services/MapImageService/MapImageService.cs @@ -134,7 +134,7 @@ namespace OpenSim.Services.MapImageService public byte[] GetMapTile(string fileName, out string format) { - format = "jpg"; + format = ".jpg"; string fullName = Path.Combine(m_TilesStoragePath, fileName); if (File.Exists(fullName)) { From 07d7c1cd2d0d5ccf6d40a3616ecaeb565e9bfab4 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 12 Jun 2011 18:29:44 -0700 Subject: [PATCH 17/26] Trailing / in MapTileURL must be there! --- bin/config-include/StandaloneCommon.ini.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/config-include/StandaloneCommon.ini.example b/bin/config-include/StandaloneCommon.ini.example index 69349d2b49..29c2af1f96 100644 --- a/bin/config-include/StandaloneCommon.ini.example +++ b/bin/config-include/StandaloneCommon.ini.example @@ -100,7 +100,7 @@ SRV_IMServerURI = "http://127.0.0.1:9000" ;; For Viewer 2 - MapTileURL = "http://127.0.0.1:9000" + MapTileURL = "http://127.0.0.1:9000/" ;; Regular expressions for controlling which client versions are accepted/denied. ;; An empty string means nothing is checked. From 2e77518c6dd5f06c965df758ebd0a20a39c96dc8 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 12 Jun 2011 21:51:26 -0700 Subject: [PATCH 18/26] bit depth: 24!!! begeez! -- zoom levels work now. --- OpenSim/Server/Handlers/Map/MapGetServerConnector.cs | 4 +++- OpenSim/Services/MapImageService/MapImageService.cs | 5 ++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs index 76dd695fe7..53d08faa3b 100644 --- a/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs +++ b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs @@ -42,11 +42,13 @@ namespace OpenSim.Server.Handlers.MapImage { public class MapGetServiceConnector : ServiceConnector { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private IMapImageService m_MapService; + private string m_ConfigName = "MapImageService"; public MapGetServiceConnector(IConfigSource config, IHttpServer server, string configName) : - base(config, server, configName) + base(config, server, configName) { IConfig serverConfig = config.Configs[m_ConfigName]; if (serverConfig == null) diff --git a/OpenSim/Services/MapImageService/MapImageService.cs b/OpenSim/Services/MapImageService/MapImageService.cs index ee424e14f3..736fa2ebac 100644 --- a/OpenSim/Services/MapImageService/MapImageService.cs +++ b/OpenSim/Services/MapImageService/MapImageService.cs @@ -144,7 +144,6 @@ namespace OpenSim.Services.MapImageService } else if (File.Exists(m_WaterTileFile)) { - m_log.DebugFormat("[MAP IMAGE SERVICE]: File not found {0}, sending water", fileName); return File.ReadAllBytes(m_WaterTileFile); } else @@ -188,7 +187,7 @@ namespace OpenSim.Services.MapImageService else { // Create a new output tile with a transparent background - Bitmap bm = new Bitmap(IMAGE_WIDTH, IMAGE_WIDTH); + Bitmap bm = new Bitmap(IMAGE_WIDTH, IMAGE_WIDTH, PixelFormat.Format24bppRgb); bm.MakeTransparent(); return bm; } @@ -255,7 +254,7 @@ namespace OpenSim.Services.MapImageService using (Bitmap final = new Bitmap(output)) { output.Dispose(); - final.Save(outputFile); + final.Save(outputFile, ImageFormat.Jpeg); } } catch (Exception e) From 95e050130c42c21ca4f26b31abce1c4a83194525 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 12 Jun 2011 22:10:16 -0700 Subject: [PATCH 19/26] People are bound to forget the '/' at the end of MapTileURL, so let's correct that from the inside. --- OpenSim/Services/LLLoginService/LLLoginService.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs index 5d1779a15c..2b15896d69 100644 --- a/OpenSim/Services/LLLoginService/LLLoginService.cs +++ b/OpenSim/Services/LLLoginService/LLLoginService.cs @@ -112,6 +112,14 @@ namespace OpenSim.Services.LLLoginService m_AllowedClients = m_LoginServerConfig.GetString("AllowedClients", string.Empty); m_DeniedClients = m_LoginServerConfig.GetString("DeniedClients", string.Empty); + // Clean up some of these vars + if (m_MapTileURL != String.Empty) + { + m_MapTileURL = m_MapTileURL.Trim(); + if (!m_MapTileURL.EndsWith("/")) + m_MapTileURL = m_MapTileURL + "/"; + } + // These are required; the others aren't if (accountService == string.Empty || authService == string.Empty) throw new Exception("LoginService is missing service specifications"); From 4b9de140ab9aa9312219610de68138c4288b840a Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 12 Jun 2011 22:25:30 -0700 Subject: [PATCH 20/26] Add credit and link to SimianGrid project. Thanks, guys! --- OpenSim/Services/MapImageService/MapImageService.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/OpenSim/Services/MapImageService/MapImageService.cs b/OpenSim/Services/MapImageService/MapImageService.cs index 736fa2ebac..27722bb4b7 100644 --- a/OpenSim/Services/MapImageService/MapImageService.cs +++ b/OpenSim/Services/MapImageService/MapImageService.cs @@ -23,6 +23,10 @@ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The design of this map service is based on SimianGrid's PHP-based + * map service. See this URL for the original PHP version: + * https://github.com/openmetaversefoundation/simiangrid/ */ using System; From dc978d02a723440a3860da0ad6a2b61b09769f39 Mon Sep 17 00:00:00 2001 From: Michael Cerquoni aka Nebadon Izumi Date: Mon, 13 Jun 2011 03:46:24 -0700 Subject: [PATCH 21/26] match water color for warp3d map tiler and adjust lighting --- .../CoreModules/World/Warp3DMap/MapImageModule.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs index 6eb57eb424..6163fd12fe 100644 --- a/OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs +++ b/OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs @@ -52,7 +52,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap public class Warp3DImageModule : IMapImageGenerator, INonSharedRegionModule { private static readonly UUID TEXTURE_METADATA_MAGIC = new UUID("802dc0e0-f080-4931-8b57-d1be8611c4f3"); - private static readonly Color4 WATER_COLOR = new Color4(29, 71, 95, 216); + private static readonly Color4 WATER_COLOR = new Color4(29, 72, 96, 216); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -61,7 +61,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap private IRendering m_primMesher; private IConfigSource m_config; private Dictionary m_colors = new Dictionary(); - private bool m_useAntiAliasing = true; // TODO: Make this a config option + private bool m_useAntiAliasing = false; // TODO: Make this a config option private bool m_Enabled = false; #region IRegionModule Members @@ -192,8 +192,8 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap #endregion Camera - renderer.Scene.addLight("Light1", new warp_Light(new warp_Vector(0.2f, 0.2f, 1f), 0xffffff, 320, 80)); - renderer.Scene.addLight("Light2", new warp_Light(new warp_Vector(-1f, -1f, 1f), 0xffffff, 100, 40)); + renderer.Scene.addLight("Light1", new warp_Light(new warp_Vector(1.0f, 0.5f, 1f), 0xffffff, 0, 320, 40)); + renderer.Scene.addLight("Light2", new warp_Light(new warp_Vector(-1f, -1f, 1f), 0xffffff, 0, 100, 40)); CreateWater(renderer); CreateTerrain(renderer, textureTerrain); @@ -237,6 +237,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap renderer.Scene.sceneobject("Water").setPos(127.5f, waterHeight, 127.5f); renderer.AddMaterial("WaterColor", ConvertColor(WATER_COLOR)); + renderer.Scene.material("WaterColor").setReflectivity(0); // match water color with standard map module thanks lkalif renderer.Scene.material("WaterColor").setTransparency((byte)((1f - WATER_COLOR.A) * 255f)); renderer.SetObjectMaterial("Water", "WaterColor"); } @@ -322,6 +323,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap warp_Material material = new warp_Material(texture); material.setReflectivity(50); renderer.Scene.addMaterial("TerrainColor", material); + renderer.Scene.material("TerrainColor").setReflectivity(0); // reduces tile seams a bit thanks lkalif renderer.SetObjectMaterial("Terrain", "TerrainColor"); } @@ -653,4 +655,4 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap return result; } } -} +} \ No newline at end of file From 0e4db3ca3911d8ac7080f51931ffe71b388e7180 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 13 Jun 2011 07:56:52 -0700 Subject: [PATCH 22/26] Added experimental new capability URL called MapImageService meant to work with Kokua viewer if devs are willing to do it. --- .../ClientStack/Linden/Caps/MiscCapsModule.cs | 119 ++++++++++++++++++ bin/OpenSim.ini.example | 5 + 2 files changed, 124 insertions(+) create mode 100644 OpenSim/Region/ClientStack/Linden/Caps/MiscCapsModule.cs diff --git a/OpenSim/Region/ClientStack/Linden/Caps/MiscCapsModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/MiscCapsModule.cs new file mode 100644 index 0000000000..d084a738d5 --- /dev/null +++ b/OpenSim/Region/ClientStack/Linden/Caps/MiscCapsModule.cs @@ -0,0 +1,119 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Reflection; +using log4net; +using Nini.Config; +using Mono.Addins; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using Caps = OpenSim.Framework.Capabilities.Caps; +using OpenSim.Capabilities.Handlers; + +namespace OpenSim.Region.ClientStack.Linden +{ + /// + /// A module to place miscellaneous capabilities + /// + /// + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class MiscCapsModule : INonSharedRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private Scene m_scene; + + private bool m_Enabled = false; + private string m_MapImageServerURL; + + #region ISharedRegionModule Members + + public void Initialise(IConfigSource source) + { + m_Enabled = true; + IConfig config = source.Configs["ClientStack.LindenCaps"]; + if (config == null) + return; + + m_MapImageServerURL = config.GetString("Cap_MapImageService", string.Empty); + } + + public void AddRegion(Scene s) + { + if (!m_Enabled) + return; + + m_scene = s; + } + + public void RemoveRegion(Scene s) + { + if (!m_Enabled) + return; + + m_scene.EventManager.OnRegisterCaps -= RegisterCaps; + m_scene = null; + } + + public void RegionLoaded(Scene s) + { + if (!m_Enabled) + return; + + m_scene.EventManager.OnRegisterCaps += RegisterCaps; + } + + public void PostInitialise() + { + } + + public void Close() { } + + public string Name { get { return "MiscCapsModule"; } } + + public Type ReplaceableInterface + { + get { return null; } + } + + #endregion + + public void RegisterCaps(UUID agentID, Caps caps) + { + m_log.InfoFormat("[MISC CAPS MODULE]: {0} in region {1}", m_MapImageServerURL, m_scene.RegionInfo.RegionName); + if (m_MapImageServerURL != string.Empty) + caps.RegisterHandler("MapImageService", m_MapImageServerURL); + } + + } +} diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 813c5b828c..a9ce2841fc 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -306,6 +306,11 @@ ; This is disabled by default. Change if you see fit. Note that ; serving this cap from the simulators may lead to poor performace. Cap_WebFetchInventoryDescendents = "" + ; Experimental new capability for Kokua viewers meant to override + ; the MapImage server url given at login, and varying switching on + ; a sim-basis (as it should). + ; Viewers that don't understand it, will ignore it + Cap_MapImageService = "http://127.0.0.1:9000/ [Chat] ;# {whisper_distance} {} {Distance at which a whisper is heard, in meters?} {} 10 From ab11835aeb341a34f479d9a6eb18de1ca9500c4a Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 13 Jun 2011 07:59:28 -0700 Subject: [PATCH 23/26] Same processing of the "/" in the MapImageService Cap as the one in the login service. --- OpenSim/Region/ClientStack/Linden/Caps/MiscCapsModule.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/OpenSim/Region/ClientStack/Linden/Caps/MiscCapsModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/MiscCapsModule.cs index d084a738d5..3dcd1e3a11 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/MiscCapsModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/MiscCapsModule.cs @@ -66,6 +66,12 @@ namespace OpenSim.Region.ClientStack.Linden return; m_MapImageServerURL = config.GetString("Cap_MapImageService", string.Empty); + if (m_MapImageServerURL != string.Empty) + { + m_MapImageServerURL = m_MapImageServerURL.Trim(); + if (!m_MapImageServerURL.EndsWith("/")) + m_MapImageServerURL = m_MapImageServerURL + "/"; + } } public void AddRegion(Scene s) From ecb28ae130d1fc212c72af887fc75ae2bf64ab97 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 13 Jun 2011 09:13:44 -0700 Subject: [PATCH 24/26] V2 map now working in grids too. WARNING: A few visible configuration variables added in order for this to work. See .ini.example changes --- .../Handlers/Map/MapAddServerConnector.cs | 124 +++++++++++++++++- .../Handlers/Map/MapGetServerConnector.cs | 1 - .../MapImage/MapImageServiceConnector.cs | 81 ++++++------ .../MapImageService/MapImageService.cs | 2 +- bin/Robust.HG.ini.example | 8 +- bin/Robust.ini.example | 9 +- bin/config-include/Grid.ini | 6 + bin/config-include/GridCommon.ini.example | 3 + bin/config-include/GridHypergrid.ini | 8 +- 9 files changed, 193 insertions(+), 49 deletions(-) diff --git a/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs b/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs index a953cd7eaf..99f98b60d7 100644 --- a/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs +++ b/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs @@ -26,7 +26,14 @@ */ using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Xml; + using Nini.Config; +using log4net; + using OpenSim.Server.Base; using OpenSim.Services.Interfaces; using OpenSim.Framework.Servers.HttpServer; @@ -55,7 +62,122 @@ namespace OpenSim.Server.Handlers.MapImage Object[] args = new Object[] { config }; m_MapService = ServerUtils.LoadPlugin(gridService, args); - //server.AddStreamHandler(new PresenceServerPostHandler(m_PresenceService)); + server.AddStreamHandler(new MapServerPostHandler(m_MapService)); + } + } + + class MapServerPostHandler : BaseStreamHandler + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private IMapImageService m_MapService; + + public MapServerPostHandler(IMapImageService service) : + base("POST", "/map") + { + m_MapService = service; + } + + public override byte[] Handle(string path, Stream requestData, OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + m_log.DebugFormat("[MAP SERVICE IMAGE HANDLER]: Received {0}", path); + StreamReader sr = new StreamReader(requestData); + string body = sr.ReadToEnd(); + sr.Close(); + body = body.Trim(); + + try + { + Dictionary request = ServerUtils.ParseQueryString(body); + + if (!request.ContainsKey("X") || !request.ContainsKey("Y") || !request.ContainsKey("DATA")) + { + httpResponse.StatusCode = (int)OSHttpStatusCode.ClientErrorBadRequest; + return FailureResult("Bad request."); + } + int x = 0, y = 0; + Int32.TryParse(request["X"].ToString(), out x); + Int32.TryParse(request["Y"].ToString(), out y); + string type = "image/jpeg"; + if (request.ContainsKey("TYPE")) + type = request["TYPE"].ToString(); + byte[] data = Convert.FromBase64String(request["DATA"].ToString()); + + string reason = string.Empty; + bool result = m_MapService.AddMapTile(x, y, data, out reason); + + if (result) + return SuccessResult(); + else + return FailureResult(reason); + + } + catch (Exception e) + { + m_log.ErrorFormat("[MAP SERVICE IMAGE HANDLER]: Exception {0} {1}", e.Message, e.StackTrace); + } + + return FailureResult("Unexpected server error"); + + } + + private byte[] SuccessResult() + { + XmlDocument doc = new XmlDocument(); + + XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration, + "", ""); + + doc.AppendChild(xmlnode); + + XmlElement rootElement = doc.CreateElement("", "ServerResponse", + ""); + + doc.AppendChild(rootElement); + + XmlElement result = doc.CreateElement("", "Result", ""); + result.AppendChild(doc.CreateTextNode("Success")); + + rootElement.AppendChild(result); + + return DocToBytes(doc); + } + + private byte[] FailureResult(string msg) + { + XmlDocument doc = new XmlDocument(); + + XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration, + "", ""); + + doc.AppendChild(xmlnode); + + XmlElement rootElement = doc.CreateElement("", "ServerResponse", + ""); + + doc.AppendChild(rootElement); + + XmlElement result = doc.CreateElement("", "Result", ""); + result.AppendChild(doc.CreateTextNode("Failure")); + + rootElement.AppendChild(result); + + XmlElement message = doc.CreateElement("", "Message", ""); + message.AppendChild(doc.CreateTextNode(msg)); + + rootElement.AppendChild(message); + + return DocToBytes(doc); + } + + private byte[] DocToBytes(XmlDocument doc) + { + MemoryStream ms = new MemoryStream(); + XmlTextWriter xw = new XmlTextWriter(ms, null); + xw.Formatting = Formatting.Indented; + doc.WriteTo(xw); + xw.Flush(); + + return ms.ToArray(); } } } diff --git a/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs index 53d08faa3b..e8a424f513 100644 --- a/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs +++ b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs @@ -80,7 +80,6 @@ namespace OpenSim.Server.Handlers.MapImage public override byte[] Handle(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse) { - m_log.DebugFormat("[MAP SERVICE IMAGE HANDLER]: retrieving {0}", path); byte[] result = new byte[0]; string format = string.Empty; diff --git a/OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs b/OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs index ff0e9d9aee..520d639ccf 100644 --- a/OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs +++ b/OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs @@ -36,6 +36,7 @@ using Nini.Config; using OpenSim.Framework; using OpenSim.Framework.Console; using OpenSim.Framework.Communications; +using OpenSim.Server.Base; using OpenSim.Services.Interfaces; using OpenMetaverse; using OpenMetaverse.StructuredData; @@ -83,60 +84,57 @@ namespace OpenSim.Services.Connectors throw new Exception("MapImage connector init error"); } m_ServerURI = serviceURI; + m_ServerURI = serviceURI.TrimEnd('/'); } - public bool AddMapTile(int x, int y, byte[] pngData, out string reason) + public bool AddMapTile(int x, int y, byte[] jpgData, out string reason) { - List postParameters = new List() - { - new MultipartForm.Parameter("X", x.ToString()), - new MultipartForm.Parameter("Y", y.ToString()), - new MultipartForm.File("Tile", "tile.png", "image/png", pngData) - }; - - reason = string.Empty; + reason = string.Empty; int tickstart = Util.EnvironmentTickCount(); + Dictionary sendData = new Dictionary(); + sendData["X"] = x.ToString(); + sendData["Y"] = y.ToString(); + sendData["TYPE"] = "image/jpeg"; + sendData["DATA"] = Convert.ToBase64String(jpgData); + + string reqString = ServerUtils.BuildQueryString(sendData); - // Make the remote storage request try { - HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(m_ServerURI); - request.Timeout = 20000; - request.ReadWriteTimeout = 5000; - - using (HttpWebResponse response = MultipartForm.Post(request, postParameters)) + string reply = SynchronousRestFormsRequester.MakeRequest("POST", + m_ServerURI + "/map", + reqString); + if (reply != string.Empty) { - using (Stream responseStream = response.GetResponseStream()) + Dictionary replyData = ServerUtils.ParseXmlResponse(reply); + + if (replyData.ContainsKey("Result") && (replyData["Result"].ToString().ToLower() == "success")) { - string responseStr = responseStream.GetStreamString(); - OSD responseOSD = OSDParser.Deserialize(responseStr); - if (responseOSD.Type == OSDType.Map) - { - OSDMap responseMap = (OSDMap)responseOSD; - if (responseMap["Success"].AsBoolean()) - return true; - - reason = "Upload failed: " + responseMap["Message"].AsString(); - } - else - { - reason = "Response format was invalid:\n" + responseStr; - } + return true; } + else if (replyData.ContainsKey("Result") && (replyData["Result"].ToString().ToLower() == "failure")) + { + m_log.DebugFormat("[MAP IMAGE CONNECTOR]: Registration failed: {0}", replyData["Message"].ToString()); + reason = replyData["Message"].ToString(); + return false; + } + else if (!replyData.ContainsKey("Result")) + { + m_log.DebugFormat("[MAP IMAGE CONNECTOR]: reply data does not contain result field"); + } + else + { + m_log.DebugFormat("[MAP IMAGE CONNECTOR]: unexpected result {0}", replyData["Result"].ToString()); + reason = "Unexpected result " + replyData["Result"].ToString(); + } + } + else + m_log.DebugFormat("[MAP IMAGE CONNECTOR]: RegisterRegion received null reply"); } - catch (WebException we) + catch (Exception e) { - reason = we.Message; - if (we.Status == WebExceptionStatus.ProtocolError) - { - HttpWebResponse webResponse = (HttpWebResponse)we.Response; - reason = String.Format("[{0}] {1}", webResponse.StatusCode, webResponse.StatusDescription); - } - } - catch (Exception ex) - { - reason = ex.Message; + m_log.DebugFormat("[MAP IMAGE CONNECTOR]: Exception when contacting grid server: {0}", e.Message); } finally { @@ -146,6 +144,7 @@ namespace OpenSim.Services.Connectors } return false; + } public byte[] GetMapTile(string fileName, out string format) diff --git a/OpenSim/Services/MapImageService/MapImageService.cs b/OpenSim/Services/MapImageService/MapImageService.cs index 27722bb4b7..7e7391c988 100644 --- a/OpenSim/Services/MapImageService/MapImageService.cs +++ b/OpenSim/Services/MapImageService/MapImageService.cs @@ -143,7 +143,7 @@ namespace OpenSim.Services.MapImageService if (File.Exists(fullName)) { format = Path.GetExtension(fileName).ToLower(); - m_log.DebugFormat("[MAP IMAGE SERVICE]: Found file {0}, extension {1}", fileName, format); + //m_log.DebugFormat("[MAP IMAGE SERVICE]: Found file {0}, extension {1}", fileName, format); return File.ReadAllBytes(fullName); } else if (File.Exists(m_WaterTileFile)) diff --git a/bin/Robust.HG.ini.example b/bin/Robust.HG.ini.example index 812d2659fa..00ece88025 100644 --- a/bin/Robust.HG.ini.example +++ b/bin/Robust.HG.ini.example @@ -21,7 +21,7 @@ ; * [[@]/][:] ; * [Startup] -ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003/OpenSim.Server.Handlers.dll:XInventoryInConnector,8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector,8003/OpenSim.Server.Handlers.dll:GridServiceConnector,8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector,8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector,8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector,8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector,8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector,8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector,8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector,8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector,8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector,8002/OpenSim.Server.Handlers.dll:GatekeeperServiceInConnector,8002/OpenSim.Server.Handlers.dll:UserAgentServerConnector,HGInventoryService@8002/OpenSim.Server.Handlers.dll:XInventoryInConnector,HGAssetService@8002/OpenSim.Server.Handlers.dll:AssetServiceConnector,8002/OpenSim.Server.Handlers.dll:HeloServiceInConnector,8002/OpenSim.Server.Handlers.dll:HGFriendsServerConnector,8002/OpenSim.Server.Handlers.dll:InstantMessageServerConnector" +ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003/OpenSim.Server.Handlers.dll:XInventoryInConnector,8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector,8003/OpenSim.Server.Handlers.dll:GridServiceConnector,8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector,8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector,8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector,8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector,8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector,8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector,8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector,8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector,8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector,8002/OpenSim.Server.Handlers.dll:GatekeeperServiceInConnector,8002/OpenSim.Server.Handlers.dll:UserAgentServerConnector,HGInventoryService@8002/OpenSim.Server.Handlers.dll:XInventoryInConnector,HGAssetService@8002/OpenSim.Server.Handlers.dll:AssetServiceConnector,8002/OpenSim.Server.Handlers.dll:HeloServiceInConnector,8002/OpenSim.Server.Handlers.dll:HGFriendsServerConnector,8002/OpenSim.Server.Handlers.dll:InstantMessageServerConnector,8003/OpenSim.Server.Handlers.dll:MapAddServiceConnector,8002/OpenSim.Server.Handlers.dll:MapGetServiceConnector" ; * This is common for all services, it's the network setup for the entire ; * server instance, if none is specified above @@ -206,6 +206,9 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 WelcomeMessage = "Welcome, Avatar!" AllowRemoteSetLoginLevel = "false" + ; For V2 map + ; MapTileURL = "http://127.0.0.1:8002"; + ; If you run this login server behind a proxy, set this to true ; HasProxy = false @@ -237,6 +240,9 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 ;AllowedClients = "" ;DeniedClients = "" +[MapImageService] + LocalServiceModule = "OpenSim.Services.MapImageService.dll:MapImageService" + [GridInfoService] ; These settings are used to return information on a get_grid_info call. ; Client launcher scripts and third-party clients make use of this to diff --git a/bin/Robust.ini.example b/bin/Robust.ini.example index 5d0ec09d7d..e29e9dbbc7 100644 --- a/bin/Robust.ini.example +++ b/bin/Robust.ini.example @@ -13,7 +13,7 @@ ; * [[@]/][:] ; * [Startup] -ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003/OpenSim.Server.Handlers.dll:XInventoryInConnector,8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector,8003/OpenSim.Server.Handlers.dll:GridServiceConnector,8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector,8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector,8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector,8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector,8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector,8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector,8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector,8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector,8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector" +ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003/OpenSim.Server.Handlers.dll:XInventoryInConnector,8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector,8003/OpenSim.Server.Handlers.dll:GridServiceConnector,8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector,8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector,8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector,8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector,8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector,8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector,8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector,8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector,8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector,8003/OpenSim.Server.Handlers.dll:MapAddServiceConnector,8002/OpenSim.Server.Handlers.dll:MapGetServiceConnector" ; * This is common for all services, it's the network setup for the entire ; * server instance, if none is specified above @@ -191,8 +191,8 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 WelcomeMessage = "Welcome, Avatar!" AllowRemoteSetLoginLevel = "false" - ; For snowglobe's web map - ; MapTileURL = ""; + ; For V2 map + ; MapTileURL = "http://127.0.0.1:8002"; ; If you run this login server behind a proxy, set this to true ; HasProxy = false @@ -214,6 +214,9 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 ;AllowedClients = "" ;DeniedClients = "" +[MapImageService] + LocalServiceModule = "OpenSim.Services.MapImageService.dll:MapImageService" + [GridInfoService] ; These settings are used to return information on a get_grid_info call. ; Client launcher scripts and third-party clients make use of this to diff --git a/bin/config-include/Grid.ini b/bin/config-include/Grid.ini index 52205732f0..da860c6859 100644 --- a/bin/config-include/Grid.ini +++ b/bin/config-include/Grid.ini @@ -21,6 +21,7 @@ EntityTransferModule = "BasicEntityTransferModule" InventoryAccessModule = "BasicInventoryAccessModule" LandServices = "RemoteLandServicesConnector" + MapImageService = "MapImageServiceModule" LandServiceInConnector = true NeighbourServiceInConnector = true @@ -50,3 +51,8 @@ [Friends] Connector = "OpenSim.Services.Connectors.dll:FriendsServicesConnector" + +[MapImageService] + LocalServiceModule = "OpenSim.Services.Connectors.dll:MapImageServicesConnector" + ; in minutes + RefreshTime = 60 diff --git a/bin/config-include/GridCommon.ini.example b/bin/config-include/GridCommon.ini.example index 27f262f374..4eb6fcf333 100644 --- a/bin/config-include/GridCommon.ini.example +++ b/bin/config-include/GridCommon.ini.example @@ -116,6 +116,9 @@ ; UserAgentServerURI = "http://mygridserver.com:8002" +[MapImageService] + MapImageServerURI = "http://mygridserver.com:8003" + [Modules] ;; Choose 0 or 1 cache modules, and the corresponding config file, if it exists. ;; Copy the config .example file into your own .ini file and change configs there diff --git a/bin/config-include/GridHypergrid.ini b/bin/config-include/GridHypergrid.ini index b8e66c2733..60a3c625f2 100644 --- a/bin/config-include/GridHypergrid.ini +++ b/bin/config-include/GridHypergrid.ini @@ -25,6 +25,7 @@ InventoryAccessModule = "HGInventoryAccessModule" LandServices = "RemoteLandServicesConnector" FriendsModule = "HGFriendsModule" + MapImageService = "MapImageServiceModule" LandServiceInConnector = true NeighbourServiceInConnector = true @@ -76,4 +77,9 @@ LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGInstantMessageService" GridService = "OpenSim.Services.Connectors.dll:GridServicesConnector" PresenceService = "OpenSim.Services.Connectors.dll:PresenceServicesConnector" - UserAgentService = "OpenSim.Services.Connectors.dll:UserAgentServiceConnector" \ No newline at end of file + UserAgentService = "OpenSim.Services.Connectors.dll:UserAgentServiceConnector" + +[MapImageService] + LocalServiceModule = "OpenSim.Services.Connectors.dll:MapImageServicesConnector" + ; in minutes + RefreshTime = 60 From 822b9e085fca9dcf04e61b29b98daeecf7893d85 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Mon, 13 Jun 2011 10:21:29 -0700 Subject: [PATCH 25/26] Added SimulatorFeatures capability. Thanks Aurora devs for the bootstrap on the contents of the response. Changed the experimental capability introduced a couple of commits ago: now sending that extra information as part of the response in the SimulatorFeatures cap. --- ...psModule.cs => SimulatorFeaturesModule.cs} | 71 +++++++++++++------ bin/OpenSim.ini.example | 11 +-- 2 files changed, 56 insertions(+), 26 deletions(-) rename OpenSim/Region/ClientStack/Linden/Caps/{MiscCapsModule.cs => SimulatorFeaturesModule.cs} (59%) diff --git a/OpenSim/Region/ClientStack/Linden/Caps/MiscCapsModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs similarity index 59% rename from OpenSim/Region/ClientStack/Linden/Caps/MiscCapsModule.cs rename to OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs index 3dcd1e3a11..9f78948df4 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/MiscCapsModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs @@ -32,71 +32,67 @@ using log4net; using Nini.Config; using Mono.Addins; using OpenMetaverse; +using OpenMetaverse.StructuredData; using OpenSim.Framework; using OpenSim.Framework.Servers.HttpServer; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; using Caps = OpenSim.Framework.Capabilities.Caps; -using OpenSim.Capabilities.Handlers; namespace OpenSim.Region.ClientStack.Linden { /// - /// A module to place miscellaneous capabilities + /// SimulatorFeatures capability. This is required for uploading Mesh. + /// Since is accepts an open-ended response, we also send more information + /// for viewers that care to interpret it. + /// + /// NOTE: Part of this code was adapted from the Aurora project, specifically + /// the normal part of the response in the capability handler. /// /// [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class MiscCapsModule : INonSharedRegionModule + public class SimulatorFeaturesModule : ISharedRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private Scene m_scene; - private bool m_Enabled = false; - private string m_MapImageServerURL; + private string m_MapImageServerURL = string.Empty; + private string m_SearchURL = string.Empty; #region ISharedRegionModule Members public void Initialise(IConfigSource source) { - m_Enabled = true; - IConfig config = source.Configs["ClientStack.LindenCaps"]; + IConfig config = source.Configs["SimulatorFeatures"]; if (config == null) return; - m_MapImageServerURL = config.GetString("Cap_MapImageService", string.Empty); + m_MapImageServerURL = config.GetString("MapImageServerURI", string.Empty); if (m_MapImageServerURL != string.Empty) { m_MapImageServerURL = m_MapImageServerURL.Trim(); if (!m_MapImageServerURL.EndsWith("/")) m_MapImageServerURL = m_MapImageServerURL + "/"; } + + m_SearchURL = config.GetString("SearchServerURI", string.Empty); } public void AddRegion(Scene s) { - if (!m_Enabled) - return; - m_scene = s; + m_scene.EventManager.OnRegisterCaps += RegisterCaps; } public void RemoveRegion(Scene s) { - if (!m_Enabled) - return; - m_scene.EventManager.OnRegisterCaps -= RegisterCaps; - m_scene = null; } public void RegionLoaded(Scene s) { - if (!m_Enabled) - return; - - m_scene.EventManager.OnRegisterCaps += RegisterCaps; } public void PostInitialise() @@ -105,7 +101,7 @@ namespace OpenSim.Region.ClientStack.Linden public void Close() { } - public string Name { get { return "MiscCapsModule"; } } + public string Name { get { return "SimulatorFeaturesModule"; } } public Type ReplaceableInterface { @@ -116,9 +112,40 @@ namespace OpenSim.Region.ClientStack.Linden public void RegisterCaps(UUID agentID, Caps caps) { - m_log.InfoFormat("[MISC CAPS MODULE]: {0} in region {1}", m_MapImageServerURL, m_scene.RegionInfo.RegionName); + IRequestHandler reqHandler = new RestHTTPHandler("GET", "/CAPS/" + UUID.Random(), SimulatorFeatures); + caps.RegisterHandler("SimulatorFeatures", reqHandler); + } + + private Hashtable SimulatorFeatures(Hashtable mDhttpMethod) + { + m_log.DebugFormat("[SIMULATOR FEATURES MODULE]: SimulatorFeatures request"); + OSDMap data = new OSDMap(); + data["MeshRezEnabled"] = true; + data["MeshUploadEnabled"] = true; + data["MeshXferEnabled"] = true; + data["PhysicsMaterialsEnabled"] = true; + + OSDMap typesMap = new OSDMap(); + typesMap["convex"] = true; + typesMap["none"] = true; + typesMap["prim"] = true; + data["PhysicsShapeTypes"] = typesMap; + + // Extra information for viewers that want to use it + OSDMap gridServicesMap = new OSDMap(); if (m_MapImageServerURL != string.Empty) - caps.RegisterHandler("MapImageService", m_MapImageServerURL); + gridServicesMap["map-server-url"] = m_MapImageServerURL; + if (m_SearchURL != string.Empty) + gridServicesMap["search"] = m_SearchURL; + data["GridServices"] = gridServicesMap; + + //Send back data + Hashtable responsedata = new Hashtable(); + responsedata["int_response_code"] = 200; + responsedata["content_type"] = "text/plain"; + responsedata["keepalive"] = false; + responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(data); + return responsedata; } } diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index a9ce2841fc..bab118fd63 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -306,11 +306,14 @@ ; This is disabled by default. Change if you see fit. Note that ; serving this cap from the simulators may lead to poor performace. Cap_WebFetchInventoryDescendents = "" - ; Experimental new capability for Kokua viewers meant to override - ; the MapImage server url given at login, and varying switching on - ; a sim-basis (as it should). + +[SimulatorFeatures] + ; Experimental new information sent in SimulatorFeatures cap for Kokua viewers + ; meant to override the MapImage and search server url given at login, and varying + ; on a sim-basis. ; Viewers that don't understand it, will ignore it - Cap_MapImageService = "http://127.0.0.1:9000/ + ;MapImageServerURI = "http://127.0.0.1:9000/ + ;SearchServerURI = "http://127.0.0.1:9000/ [Chat] ;# {whisper_distance} {} {Distance at which a whisper is heard, in meters?} {} 10 From 603dbea190de26dce5160f5ab9730ffc1375ec26 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 14 Jun 2011 00:51:18 +0100 Subject: [PATCH 26/26] tweak messages. Make verbose inventory item save message give the item name as well as item id and asset id --- .../Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs | 4 +++- OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index c2ad079536..36ecb3b7ee 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs @@ -147,7 +147,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver protected void SaveInvItem(InventoryItemBase inventoryItem, string path, Dictionary options, IUserAccountService userAccountService) { if (options.ContainsKey("verbose")) - m_log.InfoFormat("[INVENTORY ARCHIVER]: Saving item {0} with asset {1}", inventoryItem.ID, inventoryItem.AssetID); + m_log.InfoFormat( + "[INVENTORY ARCHIVER]: Saving item {0} {1} with asset {2}", + inventoryItem.ID, inventoryItem.Name, inventoryItem.AssetID); string filename = path + CreateArchiveItemName(inventoryItem); diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs index 3078ab384e..6a9c3d016d 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs @@ -198,11 +198,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver m_log.ErrorFormat( "[ARCHIVER]: (... {0} more not shown)", uuids.Count - MAX_UUID_DISPLAY_ON_TIMEOUT); - m_log.Error("[ARCHIVER]: OAR save aborted. PLEASE DO NOT USE THIS OAR, IT WILL BE INCOMPLETE."); + m_log.Error("[ARCHIVER]: Archive save aborted. PLEASE DO NOT USE THIS ARCHIVE, IT WILL BE INCOMPLETE."); } catch (Exception e) { - m_log.ErrorFormat("[ARCHIVER]: Timeout handler exception {0}", e); + m_log.ErrorFormat("[ARCHIVER]: Timeout handler exception {0}{1}", e.Message, e.StackTrace); } finally {