From ab48caad0804728ad939470a7120978a2566ee1e Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 28 Jan 2011 04:31:21 +0100 Subject: [PATCH 01/12] Make the new style stuff compatible with the older revision --- .../Simulation/SimulationServiceConnector.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs index 775bded4f5..c5313fc8b9 100644 --- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs +++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs @@ -223,7 +223,20 @@ namespace OpenSim.Services.Connectors.Simulation try { OSDMap result = WebUtil.ServiceOSDRequest(uri, request, "QUERYACCESS", 10000); - return result["Success"].AsBoolean(); + bool success = result["Success"].AsBoolean(); + if (!success) + { + if (result.ContainsKey("Message")) + { + string message = result["Message"].AsString(); + if (message == "Service request failed: [MethodNotAllowed] MethodNotAllowed") // Old style region + { + m_log.Info("[REMOTE SIMULATION CONNECTOR]: The above web util error was caused by a TP to a sim that doesn't support QUERYACCESS and can be ignored"); + return true; + } + } + } + return success; } catch (Exception e) { From 9798b044fe92df6bd1b3f18c04937bd99a4d98cb Mon Sep 17 00:00:00 2001 From: Kevin Cozens Date: Wed, 26 Jan 2011 20:53:21 -0500 Subject: [PATCH 02/12] Added loading and saving of terrain files using Terragen format (Mantis #1564) Terrain files can now be loaded and saved using the Terragen (.ter) format. Selection of the terrain file loader to use is now based on the extension of the filename being loaded and the data is loaded using a memory stream instead of writing it to a file and then loading it from the file. --- .../World/Estate/EstateManagementModule.cs | 35 +-- .../World/Terrain/FileLoaders/Terragen.cs | 239 ++++++++++++++++-- 2 files changed, 224 insertions(+), 50 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs index b0563c5ff1..01f04d93d3 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs @@ -555,37 +555,12 @@ namespace OpenSim.Region.CoreModules.World.Estate try { + MemoryStream terrainStream = new MemoryStream(terrainData); + terr.LoadFromStream(filename, terrainStream); + terrainStream.Close(); - string localfilename = "terrain.raw"; - - if (terrainData.Length == 851968) - { - localfilename = Path.Combine(Util.dataDir(),"terrain.raw"); // It's a .LLRAW - } - - if (terrainData.Length == 196662) // 24-bit 256x256 Bitmap - localfilename = Path.Combine(Util.dataDir(), "terrain.bmp"); - - if (terrainData.Length == 256 * 256 * 4) // It's a .R32 - localfilename = Path.Combine(Util.dataDir(), "terrain.r32"); - - if (terrainData.Length == 256 * 256 * 8) // It's a .R64 - localfilename = Path.Combine(Util.dataDir(), "terrain.r64"); - - if (File.Exists(localfilename)) - { - File.Delete(localfilename); - } - - FileStream input = new FileStream(localfilename, FileMode.CreateNew); - input.Write(terrainData, 0, terrainData.Length); - input.Close(); - - FileInfo x = new FileInfo(localfilename); - - terr.LoadFromFile(localfilename); - remoteClient.SendAlertMessage("Your terrain was loaded as a ." + x.Extension + " file. It may take a few moments to appear."); - + FileInfo x = new FileInfo(filename); + remoteClient.SendAlertMessage("Your terrain was loaded as a " + x.Extension + " file. It may take a few moments to appear."); } catch (IOException e) { diff --git a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs index 3ee20ae48f..2919897153 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/FileLoaders/Terragen.cs @@ -30,6 +30,7 @@ using System.IO; using System.Text; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; +using OpenSim.Framework; namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders { @@ -53,17 +54,120 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders return retval; } + public ITerrainChannel LoadFile(string filename, int offsetX, int offsetY, int fileWidth, int fileHeight, int sectionWidth, int sectionHeight) + { + TerrainChannel retval = new TerrainChannel(sectionWidth, sectionHeight); + + FileInfo file = new FileInfo(filename); + FileStream s = file.Open(FileMode.Open, FileAccess.Read); + BinaryReader bs = new BinaryReader(s); + + bool eof = false; + + int fileXPoints = 0; + int fileYPoints = 0; + + // Terragen file + while (eof == false) + { + string tmp = Encoding.ASCII.GetString(bs.ReadBytes(4)); + switch (tmp) + { + case "SIZE": + fileXPoints = bs.ReadInt16() + 1; + fileYPoints = fileXPoints; + bs.ReadInt16(); + break; + case "XPTS": + fileXPoints = bs.ReadInt16(); + bs.ReadInt16(); + break; + case "YPTS": + fileYPoints = bs.ReadInt16(); + bs.ReadInt16(); + break; + case "ALTW": + eof = true; + Int16 heightScale = bs.ReadInt16(); + Int16 baseHeight = bs.ReadInt16(); + + int currFileYOffset = 0; + + // if our region isn't on the first X section of the areas to be landscaped, then + // advance to our section of the file + while (currFileYOffset < offsetY) + { + // read a whole strip of regions + int heightsToRead = sectionHeight * fileXPoints; + bs.ReadBytes(heightsToRead * 2); // because the shorts are 2 bytes in the file + currFileYOffset++; + } + + for (int y = 0; y < sectionHeight; y++) + { + int currFileXOffset = 0; + + // if our region isn't the first X section of the areas to be landscaped, then + // advance the stream to the X start pos of our section in the file + // i.e. eat X upto where we start + while (currFileXOffset < offsetX) + { + bs.ReadBytes(sectionWidth * 2); // 2 bytes = short + currFileXOffset++; + } + + // got to our X offset, so write our regions X line + for (int x = 0; x < sectionWidth; x++) + { + // Read a strip and continue + retval[x, y] = baseHeight + bs.ReadInt16() * (double)heightScale / 65536.0; + } + // record that we wrote it + currFileXOffset++; + + // if our region isn't the last X section of the areas to be landscaped, then + // advance the stream to the end of this Y column + while (currFileXOffset < fileWidth) + { + // eat the next regions x line + bs.ReadBytes(sectionWidth * 2); // 2 bytes = short + currFileXOffset++; + } + //eat the last additional point + bs.ReadInt16(); + } + + + break; + default: + bs.ReadInt32(); + break; + } + } + + bs.Close(); + s.Close(); + + return retval; + } + public ITerrainChannel LoadStream(Stream s) { - TerrainChannel retval = new TerrainChannel(); + + int w = (int)Constants.RegionSize; + int h = (int)Constants.RegionSize; + + TerrainChannel retval = new TerrainChannel(w, h); BinaryReader bs = new BinaryReader(s); bool eof = false; if (Encoding.ASCII.GetString(bs.ReadBytes(16)) == "TERRAGENTERRAIN ") { - int w = 256; - int h = 256; + + int fileWidth = w; + int fileHeight = h; + // Terragen file while (eof == false) @@ -73,30 +177,27 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders { case "SIZE": int sztmp = bs.ReadInt16() + 1; - w = sztmp; - h = sztmp; + fileWidth = sztmp; + fileHeight = sztmp; bs.ReadInt16(); break; case "XPTS": - w = bs.ReadInt16(); + fileWidth = bs.ReadInt16(); bs.ReadInt16(); break; case "YPTS": - h = bs.ReadInt16(); + fileHeight = bs.ReadInt16(); bs.ReadInt16(); break; case "ALTW": eof = true; Int16 heightScale = bs.ReadInt16(); Int16 baseHeight = bs.ReadInt16(); - retval = new TerrainChannel(w, h); - int x; - for (x = 0; x < w; x++) + for (int y = 0; y < h; y++) { - int y; - for (y = 0; y < h; y++) + for (int x = 0; x < w; x++) { - retval[x, y] = baseHeight + bs.ReadInt16() * (double) heightScale / 65536.0; + retval[x, y] = baseHeight + bs.ReadInt16() * (double)heightScale / 65536.0; } } break; @@ -114,12 +215,92 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders public void SaveFile(string filename, ITerrainChannel map) { - throw new NotImplementedException(); + FileInfo file = new FileInfo(filename); + FileStream s = file.Open(FileMode.Create, FileAccess.Write); + SaveStream(s, map); + + s.Close(); } public void SaveStream(Stream stream, ITerrainChannel map) { - throw new NotImplementedException(); + BinaryWriter bs = new BinaryWriter(stream); + + //find the max and min heights on the map + double heightMax = map[0,0]; + double heightMin = map[0,0]; + + for (int y = 0; y < map.Height; y++) + { + for (int x = 0; x < map.Width; x++) + { + double current = map[x,y]; + if (heightMax < current) + heightMax = current; + if (heightMin > current) + heightMin = current; + } + } + + double baseHeight = Math.Floor( (heightMax + heightMin) / 2d ); + + double horizontalScale = Math.Ceiling((heightMax - heightMin)); + + // if we are completely flat add 1cm range to avoid NaN divisions + if (horizontalScale < 0.01d) + horizontalScale = 0.01d; + + System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); + + bs.Write(enc.GetBytes("TERRAGENTERRAIN ")); + + bs.Write(enc.GetBytes("SIZE")); + bs.Write(Convert.ToInt16(Constants.RegionSize)); + bs.Write(Convert.ToInt16(0)); // necessary padding + + //The XPTS and YPTS chunks are not needed for square regions + //but L3DT won't load the terrain file properly without them. + bs.Write(enc.GetBytes("XPTS")); + bs.Write(Convert.ToInt16(Constants.RegionSize)); + bs.Write(Convert.ToInt16(0)); // necessary padding + + bs.Write(enc.GetBytes("YPTS")); + bs.Write(Convert.ToInt16(Constants.RegionSize)); + bs.Write(Convert.ToInt16(0)); // necessary padding + + bs.Write(enc.GetBytes("SCAL")); + bs.Write(ToLittleEndian(1f)); //we're going to say that 1 terrain unit is 1 metre + bs.Write(ToLittleEndian(1f)); + bs.Write(ToLittleEndian(1f)); + + // as we are square and not projected on a sphere then the other + // header blocks are not required + + // now write the elevation data + bs.Write(enc.GetBytes("ALTW")); + bs.Write(Convert.ToInt16(horizontalScale)); // range between max and min + bs.Write(Convert.ToInt16(baseHeight)); // base height or mid point + + for (int y = 0; y < map.Height; y++) + { + for (int x = 0; x < map.Width; x++) + { + float elevation = (float)((map[x,y] - baseHeight) * 65536 ) / (float)horizontalScale; // see LoadStream for inverse + + // clamp rounding issues + if (elevation > Int16.MaxValue) + elevation = Int16.MaxValue; + else if (elevation < Int16.MinValue) + elevation = Int16.MinValue; + + bs.Write(Convert.ToInt16(elevation)); + } + } + + //This is only necessary for older versions of Terragen. + bs.Write(enc.GetBytes("EOF ")); + + bs.Close(); } public string FileExtension @@ -127,16 +308,34 @@ namespace OpenSim.Region.CoreModules.World.Terrain.FileLoaders get { return ".ter"; } } - public ITerrainChannel LoadFile(string filename, int x, int y, int fileWidth, int fileHeight, int w, int h) - { - throw new NotImplementedException(); - } - #endregion public override string ToString() { return "Terragen"; } + + /// + /// terragen SCAL floats need to be written intel ordered regardless of + /// big or little endian system + /// + /// + /// + private byte[] ToLittleEndian( float number) + { + byte[] retVal = BitConverter.GetBytes(number); + if (BitConverter.IsLittleEndian == false) + { + byte[] tmp = new byte[4]; + for (int i = 0; i < 4; i++) + { + tmp[i] = retVal[3 - i]; + } + retVal = tmp; + + } + return retVal ; + } + } } From a0380af18ff7b383333f38d81a25a668154eb5c2 Mon Sep 17 00:00:00 2001 From: Kevin Cozens Date: Thu, 27 Jan 2011 22:57:08 -0500 Subject: [PATCH 03/12] Display supported file extensions/formats in "terrain load help" (Mantis #5349) --- .../Region/CoreModules/World/Terrain/TerrainModule.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs index 25d73c2c0f..8a79d78b22 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs @@ -131,7 +131,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain m_scene.EventManager.OnNewClient += EventManager_OnNewClient; m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole; m_scene.EventManager.OnTerrainTick += EventManager_OnTerrainTick; - InstallInterfaces(); } InstallDefaultEffects(); @@ -140,6 +139,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain public void RegionLoaded(Scene scene) { + //Do this here to give file loaders time to initialize and + //register their supported file extensions and file formats. + InstallInterfaces(); } public void RemoveRegion(Scene scene) @@ -1082,8 +1084,12 @@ namespace OpenSim.Region.CoreModules.World.Terrain { // Load / Save string supportedFileExtensions = ""; + string supportedFilesSeparator = ""; foreach (KeyValuePair loader in m_loaders) - supportedFileExtensions += " " + loader.Key + " (" + loader.Value + ")"; + { + supportedFileExtensions += supportedFilesSeparator + loader.Key + " (" + loader.Value + ")"; + supportedFilesSeparator = ", "; + } Command loadFromFileCommand = new Command("load", CommandIntentions.COMMAND_HAZARDOUS, InterfaceLoadFile, "Loads a terrain from a specified file."); From ab1ec3c3cccf30ab61379b700129ca3284578274 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 28 Jan 2011 21:51:25 +0000 Subject: [PATCH 04/12] minor: remove a few mono compiler warnings --- .../Assets/NewFileAgentInventoryVariablePriceModule.cs | 4 ++-- .../ServiceConnectorsOut/UserAccounts/UserAccountCache.cs | 7 ++++--- OpenSim/Region/CoreModules/World/Region/RestartModule.cs | 4 ++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Assets/NewFileAgentInventoryVariablePriceModule.cs b/OpenSim/Region/CoreModules/Avatar/Assets/NewFileAgentInventoryVariablePriceModule.cs index 542af25b87..4a42c938d5 100644 --- a/OpenSim/Region/CoreModules/Avatar/Assets/NewFileAgentInventoryVariablePriceModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Assets/NewFileAgentInventoryVariablePriceModule.cs @@ -54,7 +54,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets // LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private Scene m_scene; - private IAssetService m_assetService; +// private IAssetService m_assetService; private bool m_dumpAssetsToFile = false; #region IRegionModuleBase Members @@ -85,7 +85,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Assets public void RegionLoaded(Scene scene) { - m_assetService = m_scene.RequestModuleInterface(); +// m_assetService = m_scene.RequestModuleInterface(); m_scene.EventManager.OnRegisterCaps += RegisterCaps; } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs index 155335bded..ddef75f616 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs @@ -38,9 +38,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts { private const double CACHE_EXPIRATION_SECONDS = 120000.0; // 33 hours! - private static readonly ILog m_log = - LogManager.GetLogger( - MethodBase.GetCurrentMethod().DeclaringType); +// private static readonly ILog m_log = +// LogManager.GetLogger( +// MethodBase.GetCurrentMethod().DeclaringType); + private ExpiringCache m_UUIDCache; private ExpiringCache m_NameCache; diff --git a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs index c65aa6a8bd..ab6a598ace 100644 --- a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs +++ b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs @@ -45,8 +45,8 @@ namespace OpenSim.Region.CoreModules.World.Region [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RestartModule")] public class RestartModule : INonSharedRegionModule, IRestartModule { - private static readonly ILog m_log = - LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); +// private static readonly ILog m_log = +// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); protected Scene m_Scene; protected Timer m_CountdownTimer = null; From 810f4b9835e3e5432ad8819793ac2ed5e964dac5 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 28 Jan 2011 22:07:35 +0000 Subject: [PATCH 05/12] Add groups cache timeout setting for Flotsam Groups back to OpenSimDefaults.ini --- bin/OpenSimDefaults.ini | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index 90284530f4..475d4a0c53 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -1186,6 +1186,11 @@ ; This makes the Groups modules very chatty on the console. DebugEnabled = false + ; Groups data is cached for this number of seconds before another request is made to the groups service + ; Set to 0 to disable the cache. + ; Default is 30 seconds + GroupsCacheTimeout = 30 + ; Specify which messaging module to use for groups messaging and if it's enabled ;MessagingModule = GroupsMessagingModule ;MessagingEnabled = true From 1fcb919798f8ff132353d447e6dfb81bedd3bc44 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 28 Jan 2011 22:46:29 +0000 Subject: [PATCH 06/12] If a non-globbed included file from config cannot be found then warn the user --- .../Region/Application/ConfigurationLoader.cs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/Application/ConfigurationLoader.cs b/OpenSim/Region/Application/ConfigurationLoader.cs index 6e3d6af57c..d246181926 100644 --- a/OpenSim/Region/Application/ConfigurationLoader.cs +++ b/OpenSim/Region/Application/ConfigurationLoader.cs @@ -180,6 +180,7 @@ namespace OpenSim { if (ReadConfig(sources[i])) iniFileExists = true; + AddIncludes(sources); } @@ -235,10 +236,19 @@ namespace OpenSim string path = Path.Combine(basepath, chunkWithoutWildcards); path = Path.GetFullPath(path) + chunkWithWildcards; string[] paths = Util.Glob(path); - foreach (string p in paths) + + // If the include path contains no wildcards, then warn the user that it wasn't found. + if (wildcardIndex == -1 && paths.Length == 0) { - if (!sources.Contains(p)) - sources.Add(p); + m_log.WarnFormat("[CONFIG]: Could not find include file {0}", path); + } + else + { + foreach (string p in paths) + { + if (!sources.Contains(p)) + sources.Add(p); + } } } } From a4acf485d7332ff6c22a2e0dffdbd1409e4b2dcb Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 28 Jan 2011 22:50:49 +0000 Subject: [PATCH 07/12] minor: don't bother reparsing the sources for includes if ReadConfig() was unsuccessful --- OpenSim/Region/Application/ConfigurationLoader.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Application/ConfigurationLoader.cs b/OpenSim/Region/Application/ConfigurationLoader.cs index d246181926..40ab76571e 100644 --- a/OpenSim/Region/Application/ConfigurationLoader.cs +++ b/OpenSim/Region/Application/ConfigurationLoader.cs @@ -179,9 +179,10 @@ namespace OpenSim for (int i = 0 ; i < sources.Count ; i++) { if (ReadConfig(sources[i])) + { iniFileExists = true; - - AddIncludes(sources); + AddIncludes(sources); + } } if (!iniFileExists) From 933f47e89df69200fd4cf03a9f48c465a0434e05 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 28 Jan 2011 22:59:07 +0000 Subject: [PATCH 08/12] Comment out unused call to GridService in TeleportAgent() --- .../Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index bca08fb771..c0c790dd28 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -702,7 +702,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // and convert the regionName to the target region if (regionName.Contains(".") && regionName.Contains(":")) { - List regions = World.GridService.GetRegionsByName(World.RegionInfo.ScopeID, regionName, 1); +// List regions = World.GridService.GetRegionsByName(World.RegionInfo.ScopeID, regionName, 1); string[] parts = regionName.Split(new char[] { ':' }); if (parts.Length > 2) regionName = parts[0] + ':' + parts[1] + "/ " + parts[2]; From 5942385d0e95697dda1aac99e40d998b9bf8a2f4 Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 28 Jan 2011 23:21:41 +0000 Subject: [PATCH 09/12] Add the prim count interfaces --- .../Framework/Interfaces/IPrimCountModule.cs | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 OpenSim/Region/Framework/Interfaces/IPrimCountModule.cs diff --git a/OpenSim/Region/Framework/Interfaces/IPrimCountModule.cs b/OpenSim/Region/Framework/Interfaces/IPrimCountModule.cs new file mode 100644 index 0000000000..7b77b305c8 --- /dev/null +++ b/OpenSim/Region/Framework/Interfaces/IPrimCountModule.cs @@ -0,0 +1,53 @@ +/* + * 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 OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Region.Framework.Interfaces +{ + public interface IPrimCountModule + { + void TaintPrimCount(ILandObject land); + void TaintPrimCount(int x, int y); + void TaintPrimCount(); + } + + public interface IPrimCounts + { + int Owner { get; } + int Group { get; } + int Others { get; } + int Simulator { get; } + IUserPrimCounts Users { get; } + } + + public interface IUserPrimCounts + { + int this[UUID agentID] { get; } + } +} From 0936455725d8945db217ab662998cca66c977ed7 Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 28 Jan 2011 23:44:17 +0000 Subject: [PATCH 10/12] Adding the prim count module skeleton --- .../Resources/CoreModulePlugin.addin.xml | 1 + .../CoreModules/World/Land/PrimCountModule.cs | 112 ++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs diff --git a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml index cfa41095c8..43de2abd15 100644 --- a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml +++ b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml @@ -14,6 +14,7 @@ + diff --git a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs new file mode 100644 index 0000000000..c39ac73237 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs @@ -0,0 +1,112 @@ +/* + * 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.Collections.Generic; +using System.Diagnostics; +using System.Reflection; +using log4net; +using Nini.Config; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; + +namespace OpenSim.Region.CoreModules.World.Land +{ + public class PrimCountModule : IPrimCountModule, INonSharedRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private Scene m_Scene; + + public Type ReplaceableInterface + { + get { return null; } + } + + public void Initialise(IConfigSource source) + { + } + + public void AddRegion(Scene scene) + { + m_Scene = scene; + + m_Scene.EventManager.OnParcelPrimCountAdd += + OnParcelPrimCountAdd; + m_Scene.EventManager.OnObjectBeingRemovedFromScene += + OnObjectBeingRemovedFromScene; + m_Scene.EventManager.OnParcelPrimCountTainted += + OnParcelPrimCountTainted; + } + + public void RegionLoaded(Scene scene) + { + } + + public void RemoveRegion(Scene scene) + { + } + + public void Close() + { + } + + public string Name + { + get { return "PrimCountModule"; } + } + + private void OnParcelPrimCountAdd(SceneObjectGroup obj) + { + } + + private void OnObjectBeingRemovedFromScene(SceneObjectGroup obj) + { + } + + private void OnParcelPrimCountTainted() + { + } + + public void TaintPrimCount(ILandObject land) + { + } + + public void TaintPrimCount(int x, int y) + { + } + + public void TaintPrimCount() + { + } + } +} From e7d5ff9bd27dd8ff891a0182bec83a33b6e7d7a5 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 29 Jan 2011 02:24:27 +0000 Subject: [PATCH 11/12] Create the structure of classes and interfaces to replace the cruft that is in the land management module today --- .../CoreModules/World/Land/PrimCountModule.cs | 120 ++++++++++++++++++ .../Framework/Interfaces/IPrimCountModule.cs | 2 + 2 files changed, 122 insertions(+) diff --git a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs index c39ac73237..9689e04037 100644 --- a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs @@ -46,6 +46,8 @@ namespace OpenSim.Region.CoreModules.World.Land LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private Scene m_Scene; + private Dictionary m_PrimCounts = + new Dictionary(); public Type ReplaceableInterface { @@ -108,5 +110,123 @@ namespace OpenSim.Region.CoreModules.World.Land public void TaintPrimCount() { } + + public IPrimCounts GetPrimCounts(UUID parcelID) + { + PrimCounts primCounts; + + lock (m_PrimCounts) + { + if (m_PrimCounts.TryGetValue(parcelID, out primCounts)) + return primCounts; + + primCounts = new PrimCounts(parcelID, this); + m_PrimCounts[parcelID] = primCounts; + } + return primCounts; + } + + public int GetOwnerCount(UUID parcelID) + { + return 0; + } + + public int GetGroupCount(UUID parcelID) + { + return 0; + } + + public int GetOthersCount(UUID parcelID) + { + return 0; + } + + public int GetSimulatorCount(UUID parcelID) + { + return 0; + } + + public int GetUserCount(UUID parcelID, UUID userID) + { + return 0; + } + } + + public class PrimCounts : IPrimCounts + { + private PrimCountModule m_Parent; + private UUID m_ParcelID; + private UserPrimCounts m_UserPrimCounts; + + public PrimCounts (UUID parcelID, PrimCountModule parent) + { + m_ParcelID = parcelID; + m_Parent = parent; + + m_UserPrimCounts = new UserPrimCounts(this); + } + + public int Owner + { + get + { + return m_Parent.GetOwnerCount(m_ParcelID); + } + } + + public int Group + { + get + { + return m_Parent.GetGroupCount(m_ParcelID); + } + } + + public int Others + { + get + { + return m_Parent.GetOthersCount(m_ParcelID); + } + } + + public int Simulator + { + get + { + return m_Parent.GetSimulatorCount(m_ParcelID); + } + } + + public IUserPrimCounts Users + { + get + { + return m_UserPrimCounts; + } + } + + public int GetUserCount(UUID userID) + { + return m_Parent.GetUserCount(m_ParcelID, userID); + } + } + + public class UserPrimCounts : IUserPrimCounts + { + private PrimCounts m_Parent; + + public UserPrimCounts(PrimCounts parent) + { + m_Parent = parent; + } + + public int this[UUID userID] + { + get + { + return m_Parent.GetUserCount(userID); + } + } } } diff --git a/OpenSim/Region/Framework/Interfaces/IPrimCountModule.cs b/OpenSim/Region/Framework/Interfaces/IPrimCountModule.cs index 7b77b305c8..65158e1c80 100644 --- a/OpenSim/Region/Framework/Interfaces/IPrimCountModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IPrimCountModule.cs @@ -35,6 +35,8 @@ namespace OpenSim.Region.Framework.Interfaces void TaintPrimCount(ILandObject land); void TaintPrimCount(int x, int y); void TaintPrimCount(); + + IPrimCounts GetPrimCounts(UUID parcelID); } public interface IPrimCounts From 8f008f394d22ada3c1017371cd8fbef06c0846c0 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 29 Jan 2011 04:27:20 +0000 Subject: [PATCH 12/12] Flash out the prim count module --- .../CoreModules/World/Land/PrimCountModule.cs | 174 ++++++++++++++++++ 1 file changed, 174 insertions(+) diff --git a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs index 9689e04037..34ef67f10b 100644 --- a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs @@ -40,6 +40,15 @@ using OpenSim.Services.Interfaces; namespace OpenSim.Region.CoreModules.World.Land { + public class ParcelCounts + { + public int Owner = 0; + public int Group = 0; + public int Others = 0; + public Dictionary Users = + new Dictionary (); + } + public class PrimCountModule : IPrimCountModule, INonSharedRegionModule { private static readonly ILog m_log = @@ -48,6 +57,18 @@ namespace OpenSim.Region.CoreModules.World.Land private Scene m_Scene; private Dictionary m_PrimCounts = new Dictionary(); + private Dictionary m_OwnerMap = + new Dictionary(); + private Dictionary m_SimwideCounts = + new Dictionary(); + private Dictionary m_ParcelCounts = + new Dictionary(); + + // For now, a simple simwide taint to get this up. Later parcel based + // taint to allow recounting a parcel if only ownership has changed + // without recounting the whole sim. + private bool m_Tainted = true; + private Object m_TaintLock = new Object(); public Type ReplaceableInterface { @@ -89,25 +110,96 @@ namespace OpenSim.Region.CoreModules.World.Land private void OnParcelPrimCountAdd(SceneObjectGroup obj) { + // If we're tainted already, don't bother to add. The next + // access will cause a recount anyway + lock (m_TaintLock) + { + if (!m_Tainted) + AddObject(obj); + } } private void OnObjectBeingRemovedFromScene(SceneObjectGroup obj) { + // Don't bother to update tainted counts + lock (m_TaintLock) + { + if (!m_Tainted) + RemoveObject(obj); + } } private void OnParcelPrimCountTainted() { + lock (m_TaintLock) + m_Tainted = true; } public void TaintPrimCount(ILandObject land) { + lock (m_TaintLock) + m_Tainted = true; } public void TaintPrimCount(int x, int y) { + lock (m_TaintLock) + m_Tainted = true; } public void TaintPrimCount() + { + lock (m_TaintLock) + m_Tainted = true; + } + + // NOTE: Call under Taint Lock + private void AddObject(SceneObjectGroup obj) + { + if (obj.IsAttachment) + return; + if (((obj.RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)) + return; + + Vector3 pos = obj.AbsolutePosition; + ILandObject landObject = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y); + LandData landData = landObject.LandData; + + ParcelCounts parcelCounts; + if (m_ParcelCounts.TryGetValue(landData.GlobalID, out parcelCounts)) + { + UUID landOwner = landData.OwnerID; + int partCount = obj.Parts.Length; + + m_SimwideCounts[landOwner] += partCount; + if (parcelCounts.Users.ContainsKey(obj.OwnerID)) + parcelCounts.Users[obj.OwnerID] += partCount; + else + parcelCounts.Users[obj.OwnerID] = partCount; + + if (landData.IsGroupOwned) + { + if (obj.OwnerID == landData.GroupID) + parcelCounts.Owner += partCount; + else if (obj.GroupID == landData.GroupID) + parcelCounts.Group += partCount; + else + parcelCounts.Others += partCount; + } + else + { + if (obj.OwnerID == landData.OwnerID) + parcelCounts.Owner += partCount; + else if (obj.GroupID == landData.GroupID) + parcelCounts.Group += partCount; + else + parcelCounts.Others += partCount; + } + } + } + + // NOTE: Call under Taint Lock + private void RemoveObject(SceneObjectGroup obj) { } @@ -128,28 +220,110 @@ namespace OpenSim.Region.CoreModules.World.Land public int GetOwnerCount(UUID parcelID) { + lock (m_TaintLock) + { + if (m_Tainted) + Recount(); + + ParcelCounts counts; + if (m_ParcelCounts.TryGetValue(parcelID, out counts)) + return counts.Owner; + } return 0; } public int GetGroupCount(UUID parcelID) { + lock (m_TaintLock) + { + if (m_Tainted) + Recount(); + + ParcelCounts counts; + if (m_ParcelCounts.TryGetValue(parcelID, out counts)) + return counts.Group; + } return 0; } public int GetOthersCount(UUID parcelID) { + lock (m_TaintLock) + { + if (m_Tainted) + Recount(); + + ParcelCounts counts; + if (m_ParcelCounts.TryGetValue(parcelID, out counts)) + return counts.Others; + } return 0; } public int GetSimulatorCount(UUID parcelID) { + lock (m_TaintLock) + { + if (m_Tainted) + Recount(); + + UUID owner; + if (m_OwnerMap.TryGetValue(parcelID, out owner)) + { + int val; + if (m_SimwideCounts.TryGetValue(owner, out val)) + return val; + } + } return 0; } public int GetUserCount(UUID parcelID, UUID userID) { + lock (m_TaintLock) + { + if (m_Tainted) + Recount(); + + ParcelCounts counts; + if (m_ParcelCounts.TryGetValue(parcelID, out counts)) + { + int val; + if (counts.Users.TryGetValue(userID, out val)) + return val; + } + } return 0; } + + // NOTE: This method MUST be called while holding the taint lock! + private void Recount() + { + m_OwnerMap.Clear(); + m_SimwideCounts.Clear(); + m_ParcelCounts.Clear(); + + List land = m_Scene.LandChannel.AllParcels(); + + foreach (ILandObject l in land) + { + LandData landData = l.LandData; + + m_OwnerMap[landData.GlobalID] = landData.OwnerID; + m_SimwideCounts[landData.OwnerID] = 0; + m_ParcelCounts[landData.GlobalID] = new ParcelCounts(); + } + + m_Scene.ForEachSOG(AddObject); + + List primcountKeys = new List(m_PrimCounts.Keys); + foreach (UUID k in primcountKeys) + { + if (!m_OwnerMap.ContainsKey(k)) + m_PrimCounts.Remove(k); + } + m_Tainted = false; + } } public class PrimCounts : IPrimCounts