diff --git a/OpenSim/Framework/Console/ConsoleUtil.cs b/OpenSim/Framework/Console/ConsoleUtil.cs new file mode 100644 index 0000000000..2612a50425 --- /dev/null +++ b/OpenSim/Framework/Console/ConsoleUtil.cs @@ -0,0 +1,114 @@ +/* + * 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.Linq; +using System.Reflection; +using log4net; +using OpenMetaverse; + +public class ConsoleUtil +{ + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + public const string MinRawConsoleVectorValue = "-~"; + public const string MaxRawConsoleVectorValue = "~"; + + public const string VectorSeparator = ","; + public static char[] VectorSeparatorChars = VectorSeparator.ToCharArray(); + + /// + /// Convert a minimum vector input from the console to an OpenMetaverse.Vector3 + /// + /// /param> + /// + /// + public static bool TryParseConsoleMinVector(string rawConsoleVector, out Vector3 vector) + { + return TryParseConsoleVector(rawConsoleVector, c => float.MinValue.ToString(), out vector); + } + + /// + /// Convert a maximum vector input from the console to an OpenMetaverse.Vector3 + /// + /// /param> + /// + /// + public static bool TryParseConsoleMaxVector(string rawConsoleVector, out Vector3 vector) + { + return TryParseConsoleVector(rawConsoleVector, c => float.MaxValue.ToString(), out vector); + } + + /// + /// Convert a vector input from the console to an OpenMetaverse.Vector3 + /// + /// + /// A string in the form ,, where there is no space between values. + /// Any component can be missing (e.g. ,,40). blankComponentFunc is invoked to replace the blank with a suitable value + /// Also, if the blank component is at the end, then the comma can be missed off entirely (e.g. 40,30 or 40) + /// The strings "~" and "-~" are valid in components. The first substitutes float.MaxValue whilst the second is float.MinValue + /// Other than that, component values must be numeric. + /// + /// + /// + /// + public static bool TryParseConsoleVector( + string rawConsoleVector, Func blankComponentFunc, out Vector3 vector) + { + List components = rawConsoleVector.Split(VectorSeparatorChars).ToList(); + + if (components.Count < 1 || components.Count > 3) + { + vector = Vector3.Zero; + return false; + } + + for (int i = components.Count; i < 3; i++) + components.Add(""); + + List semiDigestedComponents + = components.ConvertAll( + c => + { + if (c == "") + return blankComponentFunc.Invoke(c); + else if (c == MaxRawConsoleVectorValue) + return float.MaxValue.ToString(); + else if (c == MinRawConsoleVectorValue) + return float.MinValue.ToString(); + else + return c; + }); + + string semiDigestedConsoleVector = string.Join(VectorSeparator, semiDigestedComponents.ToArray()); + + m_log.DebugFormat("[CONSOLE UTIL]: Parsing {0} into OpenMetaverse.Vector3", semiDigestedConsoleVector); + + return Vector3.TryParse(semiDigestedConsoleVector, out vector); + } +} \ No newline at end of file diff --git a/OpenSim/Framework/GridInstantMessage.cs b/OpenSim/Framework/GridInstantMessage.cs index a6bf6e3c32..6ae0488fc2 100644 --- a/OpenSim/Framework/GridInstantMessage.cs +++ b/OpenSim/Framework/GridInstantMessage.cs @@ -44,7 +44,6 @@ namespace OpenSim.Framework public Vector3 Position; public byte[] binaryBucket; - public uint ParentEstateID; public Guid RegionID; public uint timestamp; @@ -58,7 +57,7 @@ namespace OpenSim.Framework string _fromAgentName, UUID _toAgentID, byte _dialog, bool _fromGroup, string _message, UUID _imSessionID, bool _offline, Vector3 _position, - byte[] _binaryBucket) + byte[] _binaryBucket, bool addTimestamp) { fromAgentID = _fromAgentID.Guid; fromAgentName = _fromAgentName; @@ -79,7 +78,9 @@ namespace OpenSim.Framework ParentEstateID = scene.RegionInfo.EstateSettings.ParentEstateID; RegionID = scene.RegionInfo.RegionSettings.RegionUUID.Guid; } - timestamp = (uint)Util.UnixTimeSinceEpoch(); + + if (addTimestamp) + timestamp = (uint)Util.UnixTimeSinceEpoch(); } public GridInstantMessage(IScene scene, UUID _fromAgentID, @@ -87,7 +88,7 @@ namespace OpenSim.Framework string _message, bool _offline, Vector3 _position) : this(scene, _fromAgentID, _fromAgentName, _toAgentID, _dialog, false, _message, - _fromAgentID ^ _toAgentID, _offline, _position, new byte[0]) + _fromAgentID ^ _toAgentID, _offline, _position, new byte[0], true) { } } diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index a26e9308db..74551ea3f2 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -545,6 +545,19 @@ namespace OpenSim.Framework return (x + y - (min >> 1) - (min >> 2) + (min >> 4)); } + /// + /// Determines whether a point is inside a bounding box. + /// + /// /param> + /// + /// + /// + public static bool IsInsideBox(Vector3 v, Vector3 min, Vector3 max) + { + return v.X >= min.X & v.Y >= min.Y && v.Z >= min.Z + && v.X <= max.X && v.Y <= max.Y && v.Z <= max.Z; + } + /// /// Are the co-ordinates of the new region visible from the old region? /// diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 6f00957743..6ccabf153b 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5962,7 +5962,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP msgpack.MessageBlock.ID, msgpack.MessageBlock.Offline != 0 ? true : false, msgpack.MessageBlock.Position, - msgpack.MessageBlock.BinaryBucket); + msgpack.MessageBlock.BinaryBucket, + true); handlerInstantMessage(this, im); } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 60ab70edb0..b3db0644c4 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -227,6 +227,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_pausedAckTimeout = 1000 * 300; // 5 minutes } + // FIXME: This actually only needs to be done once since the PacketPool is shared across all servers. + // However, there is no harm in temporarily doing it multiple times. + IConfig packetConfig = configSource.Configs["PacketPool"]; + if (packetConfig != null) + { + PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true); + PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true); + } + #region BinaryStats config = configSource.Configs["Statistics.Binary"]; m_shouldCollectStats = false; diff --git a/OpenSim/Framework/PacketPool.cs b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs similarity index 98% rename from OpenSim/Framework/PacketPool.cs rename to OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs index 41d17c54f2..fc9406b88d 100644 --- a/OpenSim/Framework/PacketPool.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs @@ -32,9 +32,8 @@ using OpenMetaverse; using OpenMetaverse.Packets; using log4net; -namespace OpenSim.Framework +namespace OpenSim.Region.ClientStack.LindenUDP { - public sealed class PacketPool { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -44,6 +43,9 @@ namespace OpenSim.Framework private bool packetPoolEnabled = true; private bool dataBlockPoolEnabled = true; + /// + /// Pool of packets available for reuse. + /// private readonly Dictionary> pool = new Dictionary>(); private static Dictionary> DataBlocks = @@ -244,4 +246,4 @@ namespace OpenSim.Framework } } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs index d942e8742a..5ec0ea94b4 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs @@ -141,7 +141,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends client.FirstName+" "+client.LastName, destID, (byte)211, false, String.Empty, - transactionID, false, new Vector3(), new byte[0]), + transactionID, false, new Vector3(), new byte[0], true), delegate(bool success) {} ); } } diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs index c14cb1791b..21dff4bfee 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs @@ -313,6 +313,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer m_TransferModule.SendInstantMessage(im, delegate(bool success) {}); } } + + // XXX: This code was placed here to try and accomdate RLV which moves given folders named #RLV/~ + // to a folder called name in #RLV. However, this approach may not be ultimately correct - from analysis + // of Firestorm 4.2.2 on sending an InventoryOffered instead of TaskInventoryOffered (as was previously + // done), the viewer itself would appear to move and rename the folder, rather than the simulator doing it here. else if (im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted) { UUID destinationFolderID = UUID.Zero; @@ -324,6 +329,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer if (destinationFolderID != UUID.Zero) { + InventoryFolderBase destinationFolder = new InventoryFolderBase(destinationFolderID, client.AgentId); + if (destinationFolder == null) + { + m_log.WarnFormat( + "[INVENTORY TRANSFER]: TaskInventoryAccepted message from {0} in {1} specified folder {2} which does not exist", + client.Name, scene.Name, destinationFolderID); + + return; + } + IInventoryService invService = scene.InventoryService; UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip @@ -331,9 +346,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId); item = invService.GetItem(item); InventoryFolderBase folder = null; + UUID? previousParentFolderID = null; if (item != null) // It's an item { + previousParentFolderID = item.Folder; item.Folder = destinationFolderID; invService.DeleteItems(item.Owner, new List() { item.ID }); @@ -346,10 +363,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer if (folder != null) // It's a folder { + previousParentFolderID = folder.ParentID; folder.ParentID = destinationFolderID; invService.MoveFolder(folder); } } + + // Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code). + if (previousParentFolderID != null) + { + InventoryFolderBase previousParentFolder + = new InventoryFolderBase((UUID)previousParentFolderID, client.AgentId); + previousParentFolder = invService.GetFolder(previousParentFolder); + scene.SendInventoryUpdate(client, previousParentFolder, true, true); + + scene.SendInventoryUpdate(client, destinationFolder, true, true); + } } } else if ( @@ -370,9 +399,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId); item = invService.GetItem(item); InventoryFolderBase folder = null; + UUID? previousParentFolderID = null; if (item != null && trashFolder != null) { + previousParentFolderID = item.Folder; item.Folder = trashFolder.ID; // Diva comment: can't we just update this item??? @@ -388,6 +419,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer if (folder != null & trashFolder != null) { + previousParentFolderID = folder.ParentID; folder.ParentID = trashFolder.ID; invService.MoveFolder(folder); client.SendBulkUpdateInventory(folder); @@ -408,6 +440,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer client.SendAgentAlertMessage("Unable to delete "+ "received inventory" + reason, false); } + // Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code). + else if (previousParentFolderID != null) + { + InventoryFolderBase previousParentFolder + = new InventoryFolderBase((UUID)previousParentFolderID, client.AgentId); + previousParentFolder = invService.GetFolder(previousParentFolder); + scene.SendInventoryUpdate(client, previousParentFolder, true, true); + + scene.SendInventoryUpdate(client, trashFolder, true, true); + } ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID)); diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs index 92cf9d1616..9c369f6060 100644 --- a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs @@ -186,7 +186,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure client.FirstName+" "+client.LastName, targetid, (byte)InstantMessageDialog.RequestTeleport, false, message, sessionID, false, presence.AbsolutePosition, - new Byte[0]); + new Byte[0], true); m.RegionID = client.Scene.RegionInfo.RegionID.Guid; m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", m.imSessionID, m.RegionID, m.message); diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index c5bb9a5080..e355ebf1fe 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -1028,6 +1028,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer Scene initiatingScene) { Thread.Sleep(10000); + IMessageTransferModule im = initiatingScene.RequestModuleInterface(); if (im != null) { @@ -1040,11 +1041,22 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer (uint)(int)position.X, (uint)(int)position.Y, (uint)(int)position.Z); - GridInstantMessage m = new GridInstantMessage(initiatingScene, UUID.Zero, - "Region", agent.UUID, - (byte)InstantMessageDialog.GodLikeRequestTeleport, false, - "", gotoLocation, false, new Vector3(127, 0, 0), - new Byte[0]); + + GridInstantMessage m + = new GridInstantMessage( + initiatingScene, + UUID.Zero, + "Region", + agent.UUID, + (byte)InstantMessageDialog.GodLikeRequestTeleport, + false, + "", + gotoLocation, + false, + new Vector3(127, 0, 0), + new Byte[0], + false); + im.SendInstantMessage(m, delegate(bool success) { m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Client Initiating Teleport sending IM success = {0}", success); diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index 36c84c7bc6..b4811dadce 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs @@ -31,6 +31,7 @@ using System.Reflection; using OpenSim.Framework; using OpenSim.Framework.Console; +using OpenSim.Region.ClientStack.LindenUDP; using OpenSim.Region.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index 09f6758ba4..6e39e9acc9 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -123,6 +123,25 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands "If --regex is specified then the name is treatead as a regular expression", HandleShowObjectByName); + m_console.Commands.AddCommand( + "Objects", + false, + "show object pos", + "show object pos to ", + "Show details of scene objects within the given area.", + "Each component of the coord is comma separated. There must be no spaces between the commas.\n" + + "If you don't care about the z component you can simply omit it.\n" + + "If you don't care about the x or y components then you can leave them blank (though a comma is still required)\n" + + "If you want to specify the maxmimum value of a component then you can use ~ instead of a number\n" + + "If you want to specify the minimum value of a component then you can use -~ instead of a number\n" + + "e.g.\n" + + "show object pos 20,20,20 to 40,40,40\n" + + "show object pos 20,20 to 40,40\n" + + "show object pos ,20,20 to ,40,40\n" + + "show object pos ,,30 to ,,~\n" + + "show object pos ,,-~ to ,,30", + HandleShowObjectByPos); + m_console.Commands.AddCommand( "Objects", false, @@ -138,6 +157,25 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands "Show details of scene object parts with the given name.", "If --regex is specified then the name is treatead as a regular expression", HandleShowPartByName); + + m_console.Commands.AddCommand( + "Objects", + false, + "show part pos", + "show part pos to ", + "Show details of scene object parts within the given area.", + "Each component of the coord is comma separated. There must be no spaces between the commas.\n" + + "If you don't care about the z component you can simply omit it.\n" + + "If you don't care about the x or y components then you can leave them blank (though a comma is still required)\n" + + "If you want to specify the maxmimum value of a component then you can use ~ instead of a number\n" + + "If you want to specify the minimum value of a component then you can use -~ instead of a number\n" + + "e.g.\n" + + "show object pos 20,20,20 to 40,40,40\n" + + "show object pos 20,20 to 40,40\n" + + "show object pos ,20,20 to ,40,40\n" + + "show object pos ,,30 to ,,~\n" + + "show object pos ,,-~ to ,,30", + HandleShowPartByPos); } public void RemoveRegion(Scene scene) @@ -150,6 +188,43 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands // m_log.DebugFormat("[OBJECTS COMMANDS MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName); } + private void OutputSogsToConsole(Predicate searchPredicate) + { + List sceneObjects = m_scene.GetSceneObjectGroups().FindAll(searchPredicate); + + StringBuilder sb = new StringBuilder(); + + foreach (SceneObjectGroup so in sceneObjects) + { + AddSceneObjectReport(sb, so); + sb.Append("\n"); + } + + sb.AppendFormat("{0} object(s) found in {1}\n", sceneObjects.Count, m_scene.Name); + + m_console.OutputFormat(sb.ToString()); + } + + private void OutputSopsToConsole(Predicate searchPredicate) + { + List sceneObjects = m_scene.GetSceneObjectGroups(); + List parts = new List(); + + sceneObjects.ForEach(so => parts.AddRange(Array.FindAll(so.Parts, searchPredicate))); + + StringBuilder sb = new StringBuilder(); + + foreach (SceneObjectPart part in parts) + { + AddScenePartReport(sb, part); + sb.Append("\n"); + } + + sb.AppendFormat("{0} parts found in {1}\n", parts.Count, m_scene.Name); + + m_console.OutputFormat(sb.ToString()); + } + private void HandleShowObjectByUuid(string module, string[] cmd) { if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) @@ -200,36 +275,54 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands string name = mainParams[3]; - List sceneObjects = new List(); - Action searchAction; + Predicate searchPredicate; if (useRegex) { Regex nameRegex = new Regex(name); - searchAction = so => { if (nameRegex.IsMatch(so.Name)) { sceneObjects.Add(so); }}; + searchPredicate = so => nameRegex.IsMatch(so.Name); } else { - searchAction = so => { if (so.Name == name) { sceneObjects.Add(so); }}; + searchPredicate = so => so.Name == name; } - m_scene.ForEachSOG(searchAction); + OutputSogsToConsole(searchPredicate); + } - if (sceneObjects.Count == 0) + private void HandleShowObjectByPos(string module, string[] cmdparams) + { + if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) + return; + + if (cmdparams.Length < 5) { - m_console.OutputFormat("No objects with name {0} found in {1}", name, m_scene.RegionInfo.RegionName); + m_console.OutputFormat("Usage: show object pos to "); return; } - StringBuilder sb = new StringBuilder(); + string rawConsoleStartVector = cmdparams[3]; + Vector3 startVector; - foreach (SceneObjectGroup so in sceneObjects) + if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector)) { - AddSceneObjectReport(sb, so); - sb.Append("\n"); + m_console.OutputFormat("Error: Start vector {0} does not have a valid format", rawConsoleStartVector); + return; } - m_console.OutputFormat(sb.ToString()); + string rawConsoleEndVector = cmdparams[5]; + Vector3 endVector; + + if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector)) + { + m_console.OutputFormat("Error: End vector {0} does not have a valid format", rawConsoleEndVector); + return; + } + + Predicate searchPredicate + = so => Util.IsInsideBox(so.AbsolutePosition, startVector, endVector); + + OutputSogsToConsole(searchPredicate); } private void HandleShowPartByUuid(string module, string[] cmd) @@ -264,6 +357,38 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands m_console.OutputFormat(sb.ToString()); } + private void HandleShowPartByPos(string module, string[] cmdparams) + { + if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) + return; + + if (cmdparams.Length < 5) + { + m_console.OutputFormat("Usage: show part pos to "); + return; + } + + string rawConsoleStartVector = cmdparams[3]; + Vector3 startVector; + + if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector)) + { + m_console.OutputFormat("Error: Start vector {0} does not have a valid format", rawConsoleStartVector); + return; + } + + string rawConsoleEndVector = cmdparams[5]; + Vector3 endVector; + + if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector)) + { + m_console.OutputFormat("Error: End vector {0} does not have a valid format", rawConsoleEndVector); + return; + } + + OutputSopsToConsole(sop => Util.IsInsideBox(sop.AbsolutePosition, startVector, endVector)); + } + private void HandleShowPartByName(string module, string[] cmdparams) { if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) @@ -282,37 +407,19 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands string name = mainParams[3]; - List parts = new List(); - - Action searchAction; + Predicate searchPredicate; if (useRegex) { Regex nameRegex = new Regex(name); - searchAction = so => so.ForEachPart(sop => { if (nameRegex.IsMatch(sop.Name)) { parts.Add(sop); } }); + searchPredicate = sop => nameRegex.IsMatch(sop.Name); } else { - searchAction = so => so.ForEachPart(sop => { if (sop.Name == name) { parts.Add(sop); } }); + searchPredicate = sop => sop.Name == name; } - m_scene.ForEachSOG(searchAction); - - if (parts.Count == 0) - { - m_console.OutputFormat("No parts with name {0} found in {1}", name, m_scene.RegionInfo.RegionName); - return; - } - - StringBuilder sb = new StringBuilder(); - - foreach (SceneObjectPart part in parts) - { - AddScenePartReport(sb, part); - sb.Append("\n"); - } - - m_console.OutputFormat(sb.ToString()); + OutputSopsToConsole(searchPredicate); } private StringBuilder AddSceneObjectReport(StringBuilder sb, SceneObjectGroup so) diff --git a/OpenSim/Region/Framework/Interfaces/IUserManagement.cs b/OpenSim/Region/Framework/Interfaces/IUserManagement.cs index 24cd06978e..f8088c3d3c 100644 --- a/OpenSim/Region/Framework/Interfaces/IUserManagement.cs +++ b/OpenSim/Region/Framework/Interfaces/IUserManagement.cs @@ -1,4 +1,31 @@ -using System; +/* + * 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 OpenMetaverse; diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 35df85c750..30bf7441ac 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1469,7 +1469,7 @@ namespace OpenSim.Region.Framework.Scenes return newFolderID; } - private void SendInventoryUpdate(IClientAPI client, InventoryFolderBase folder, bool fetchFolders, bool fetchItems) + public void SendInventoryUpdate(IClientAPI client, InventoryFolderBase folder, bool fetchFolders, bool fetchItems) { if (folder == null) return; diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index bb3748ec29..66fc216913 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -148,7 +148,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC OnInstantMessage(this, new GridInstantMessage(m_scene, m_uuid, m_firstname + " " + m_lastname, target, 0, false, message, - UUID.Zero, false, Position, new byte[0])); + UUID.Zero, false, Position, new byte[0], true)); } public void SendAgentOffline(UUID[] agentIDs) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index d8da173b1c..49f0ef7b8b 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -4326,7 +4326,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api World.RegionInfo.RegionName+" "+ m_host.AbsolutePosition.ToString(), agentItem.ID, true, m_host.AbsolutePosition, - bucket); + bucket, true); ScenePresence sp; @@ -6912,16 +6912,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (m_TransferModule != null) { byte[] bucket = new byte[] { (byte)AssetType.Folder }; - + + Vector3 pos = m_host.AbsolutePosition; + GridInstantMessage msg = new GridInstantMessage(World, - m_host.UUID, m_host.Name + ", an object owned by " + - resolveName(m_host.OwnerID) + ",", destID, + m_host.OwnerID, m_host.Name, destID, (byte)InstantMessageDialog.TaskInventoryOffered, - false, category + "\n" + m_host.Name + " is located at " + - World.RegionInfo.RegionName + " " + - m_host.AbsolutePosition.ToString(), - folderID, true, m_host.AbsolutePosition, - bucket); + false, string.Format("'{0}'"), +// We won't go so far as to add a SLURL, but this is the format used by LL as of 2012-10-06 +// false, string.Format("'{0}' ( http://slurl.com/secondlife/{1}/{2}/{3}/{4} )", category, World.Name, (int)pos.X, (int)pos.Y, (int)pos.Z), + folderID, false, pos, + bucket, false); m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); } diff --git a/OpenSim/Region/UserStatistics/WebStatsModule.cs b/OpenSim/Region/UserStatistics/WebStatsModule.cs index c11ea0225a..625eba4b0a 100644 --- a/OpenSim/Region/UserStatistics/WebStatsModule.cs +++ b/OpenSim/Region/UserStatistics/WebStatsModule.cs @@ -61,7 +61,7 @@ namespace OpenSim.Region.UserStatistics /// /// User statistics sessions keyed by agent ID /// - private Dictionary m_sessions = new Dictionary(); + private Dictionary m_sessions = new Dictionary(); private List m_scenes = new List(); private Dictionary reports = new Dictionary(); @@ -319,14 +319,18 @@ namespace OpenSim.Region.UserStatistics private void OnMakeRootAgent(ScenePresence agent) { +// m_log.DebugFormat( +// "[WEB STATS MODULE]: Looking for session {0} for {1} in {2}", +// agent.ControllingClient.SessionId, agent.Name, agent.Scene.Name); + lock (m_sessions) { - UserSessionID uid; + UserSession uid; if (!m_sessions.ContainsKey(agent.UUID)) { UserSessionData usd = UserSessionUtil.newUserSessionData(); - uid = new UserSessionID(); + uid = new UserSession(); uid.name_f = agent.Firstname; uid.name_l = agent.Lastname; uid.session_data = usd; @@ -411,9 +415,9 @@ namespace OpenSim.Region.UserStatistics return String.Empty; } - private UserSessionID ParseViewerStats(string request, UUID agentID) + private UserSession ParseViewerStats(string request, UUID agentID) { - UserSessionID uid = new UserSessionID(); + UserSession uid = new UserSession(); UserSessionData usd; OSD message = OSDParser.DeserializeLLSDXml(request); OSDMap mmap; @@ -425,22 +429,25 @@ namespace OpenSim.Region.UserStatistics if (!m_sessions.ContainsKey(agentID)) { m_log.WarnFormat("[WEB STATS MODULE]: no session for stat disclosure for agent {0}", agentID); - return new UserSessionID(); + return new UserSession(); } + uid = m_sessions[agentID]; + +// m_log.DebugFormat("[WEB STATS MODULE]: Got session {0} for {1}", uid.session_id, agentID); } else { // parse through the beginning to locate the session if (message.Type != OSDType.Map) - return new UserSessionID(); + return new UserSession(); mmap = (OSDMap)message; { UUID sessionID = mmap["session_id"].AsUUID(); if (sessionID == UUID.Zero) - return new UserSessionID(); + return new UserSession(); // search through each session looking for the owner @@ -459,7 +466,7 @@ namespace OpenSim.Region.UserStatistics // can't find a session if (agentID == UUID.Zero) { - return new UserSessionID(); + return new UserSession(); } } } @@ -468,12 +475,12 @@ namespace OpenSim.Region.UserStatistics usd = uid.session_data; if (message.Type != OSDType.Map) - return new UserSessionID(); + return new UserSession(); mmap = (OSDMap)message; { if (mmap["agent"].Type != OSDType.Map) - return new UserSessionID(); + return new UserSession(); OSDMap agent_map = (OSDMap)mmap["agent"]; usd.agent_id = agentID; usd.name_f = uid.name_f; @@ -493,17 +500,18 @@ namespace OpenSim.Region.UserStatistics (float)agent_map["fps"].AsReal()); if (mmap["downloads"].Type != OSDType.Map) - return new UserSessionID(); + return new UserSession(); OSDMap downloads_map = (OSDMap)mmap["downloads"]; usd.d_object_kb = (float)downloads_map["object_kbytes"].AsReal(); usd.d_texture_kb = (float)downloads_map["texture_kbytes"].AsReal(); usd.d_world_kb = (float)downloads_map["workd_kbytes"].AsReal(); +// m_log.DebugFormat("[WEB STATS MODULE]: mmap[\"session_id\"] = [{0}]", mmap["session_id"].AsUUID()); usd.session_id = mmap["session_id"].AsUUID(); if (mmap["system"].Type != OSDType.Map) - return new UserSessionID(); + return new UserSession(); OSDMap system_map = (OSDMap)mmap["system"]; usd.s_cpu = system_map["cpu"].AsString(); @@ -512,13 +520,13 @@ namespace OpenSim.Region.UserStatistics usd.s_ram = system_map["ram"].AsInteger(); if (mmap["stats"].Type != OSDType.Map) - return new UserSessionID(); + return new UserSession(); OSDMap stats_map = (OSDMap)mmap["stats"]; { if (stats_map["failures"].Type != OSDType.Map) - return new UserSessionID(); + return new UserSession(); OSDMap stats_failures = (OSDMap)stats_map["failures"]; usd.f_dropped = stats_failures["dropped"].AsInteger(); usd.f_failed_resends = stats_failures["failed_resends"].AsInteger(); @@ -527,18 +535,18 @@ namespace OpenSim.Region.UserStatistics usd.f_send_packet = stats_failures["send_packet"].AsInteger(); if (stats_map["net"].Type != OSDType.Map) - return new UserSessionID(); + return new UserSession(); OSDMap stats_net = (OSDMap)stats_map["net"]; { if (stats_net["in"].Type != OSDType.Map) - return new UserSessionID(); + return new UserSession(); OSDMap net_in = (OSDMap)stats_net["in"]; usd.n_in_kb = (float)net_in["kbytes"].AsReal(); usd.n_in_pk = net_in["packets"].AsInteger(); if (stats_net["out"].Type != OSDType.Map) - return new UserSessionID(); + return new UserSession(); OSDMap net_out = (OSDMap)stats_net["out"]; usd.n_out_kb = (float)net_out["kbytes"].AsReal(); @@ -549,11 +557,18 @@ namespace OpenSim.Region.UserStatistics uid.session_data = usd; m_sessions[agentID] = uid; + +// m_log.DebugFormat( +// "[WEB STATS MODULE]: Parse data for {0} {1}, session {2}", uid.name_f, uid.name_l, uid.session_id); + return uid; } - private void UpdateUserStats(UserSessionID uid, SqliteConnection db) + private void UpdateUserStats(UserSession uid, SqliteConnection db) { +// m_log.DebugFormat( +// "[WEB STATS MODULE]: Updating user stats for {0} {1}, session {2}", uid.name_f, uid.name_l, uid.session_id); + if (uid.session_id == UUID.Zero) return; @@ -740,7 +755,6 @@ VALUES s.min_ping = ArrayMin_f(__ping); s.max_ping = ArrayMax_f(__ping); s.mode_ping = ArrayMode_f(__ping); - } #region Statistics @@ -985,7 +999,7 @@ VALUES } #region structs - public struct UserSessionID + public class UserSession { public UUID session_id; public UUID region_id; diff --git a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs index 9d6d9ad69c..88a3026aa2 100644 --- a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs +++ b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs @@ -52,6 +52,8 @@ namespace OpenSim.Services.Connectors private int m_retryCounter; private Dictionary> m_retryQueue = new Dictionary>(); private System.Timers.Timer m_retryTimer; + private int m_maxAssetRequestConcurrency = 30; + private delegate void AssetRetrievedEx(AssetBase asset); // Keeps track of concurrent requests for the same asset, so that it's only loaded once. @@ -80,6 +82,10 @@ namespace OpenSim.Services.Connectors public virtual void Initialise(IConfigSource source) { + IConfig netconfig = source.Configs["Network"]; + if (netconfig != null) + m_maxAssetRequestConcurrency = netconfig.GetInt("MaxRequestConcurrency",m_maxAssetRequestConcurrency); + IConfig assetConfig = source.Configs["AssetService"]; if (assetConfig == null) { @@ -204,7 +210,7 @@ namespace OpenSim.Services.Connectors if (asset == null || asset.Data == null || asset.Data.Length == 0) { asset = SynchronousRestObjectRequester. - MakeRequest("GET", uri, 0, 30); + MakeRequest("GET", uri, 0, m_maxAssetRequestConcurrency); if (m_Cache != null) m_Cache.Cache(asset); @@ -311,7 +317,7 @@ namespace OpenSim.Services.Connectors h.Invoke(a); if (handlers != null) handlers.Clear(); - }, 30); + }, m_maxAssetRequestConcurrency); success = true; } diff --git a/OpenSim/Services/Connectors/GridUser/GridUserServicesConnector.cs b/OpenSim/Services/Connectors/GridUser/GridUserServicesConnector.cs index 20d7eaf301..94bda82d14 100644 --- a/OpenSim/Services/Connectors/GridUser/GridUserServicesConnector.cs +++ b/OpenSim/Services/Connectors/GridUser/GridUserServicesConnector.cs @@ -207,7 +207,7 @@ namespace OpenSim.Services.Connectors if ((replyData != null) && replyData.ContainsKey("result") && (replyData["result"] != null)) { if (replyData["result"] is Dictionary) - guinfo = new GridUserInfo((Dictionary)replyData["result"]); + guinfo = Create((Dictionary)replyData["result"]); } return guinfo; @@ -273,7 +273,7 @@ namespace OpenSim.Services.Connectors { if (griduser is Dictionary) { - GridUserInfo pinfo = new GridUserInfo((Dictionary)griduser); + GridUserInfo pinfo = Create((Dictionary)griduser); rinfos.Add(pinfo); } else @@ -286,5 +286,10 @@ namespace OpenSim.Services.Connectors return rinfos.ToArray(); } + + protected virtual GridUserInfo Create(Dictionary griduser) + { + return new GridUserInfo(griduser); + } } } diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index 042fd3a612..f4d9021888 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -423,6 +423,10 @@ ; " (Mozilla Compatible)" to the text where there are problems with a web server ;user_agent = "OpenSim LSL (Mozilla Compatible)" + ; OpenSim can send multiple simultaneous requests for services such as asset + ; retrieval. However, some versions of mono appear to hang when there are too + ; many simultaneous requests, default is 30 and is currently applied only to assets + ;MaxRequestConcurrency = 30 [XMLRPC] ; ## diff --git a/prebuild.xml b/prebuild.xml index d149010d06..eae85bb4c8 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -1497,110 +1497,6 @@ - - - - ../../../bin/ - true - - - - - ../../../bin/ - true - - - - ../../../bin/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ../../../bin/ - - - - - ../../../bin/ - - - - ../../../bin/ - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1723,6 +1619,111 @@ + + + + ../../../bin/ + true + + + + + ../../../bin/ + true + + + + ../../../bin/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ../../../bin/ + + + + + ../../../bin/ + + + + ../../../bin/ + + + + + + + + + + + + + + + + + + + + + + + + +