From ff429a259b41f1205a6b153bb6da383d9a9f5daf Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 23 May 2012 01:58:10 +0100 Subject: [PATCH 01/10] Fix bug where an avatar that had an object they owned attached through llAttachToAvatar() or osForceAttachToAvatar() would wrongly have next permissions come into play when they detached that object and rezzed it in scene. This is because the attachments module code was setting the 'object slam' bit by using PermissionMask.All Solution here is to route the attachment item creation call through the existing inventory code in BasicInventoryAccessModule rather than copy/pasted code in AttachmentsModule itself. --- .../Avatar/Attachments/AttachmentsModule.cs | 206 ++++++------------ .../Tests/AttachmentsModuleTests.cs | 13 +- .../InventoryAccess/InventoryAccessModule.cs | 59 +++-- .../Interfaces/IInventoryAccessModule.cs | 10 +- .../Scenes/AsyncSceneObjectGroupDeleter.cs | 2 +- .../Scenes/SceneObjectPartInventory.cs | 7 + .../CoalescedSceneObjectsSerializer.cs | 20 +- OpenSim/Tests/Common/Helpers/SceneHelpers.cs | 7 +- 8 files changed, 155 insertions(+), 169 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 2e1948d231..d099511e8e 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -49,6 +49,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments private Scene m_scene; private IDialogModule m_dialogModule; + private IInventoryAccessModule m_invAccessModule; /// /// Are attachments enabled? @@ -87,7 +88,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments m_scene.EventManager.OnNewClient -= SubscribeToClientEvents; } - public void RegionLoaded(Scene scene) {} + public void RegionLoaded(Scene scene) + { + m_invAccessModule = m_scene.RequestModuleInterface(); + } public void Close() { @@ -578,90 +582,23 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments /// The user inventory item created that holds the attachment. private InventoryItemBase AddSceneObjectAsNewAttachmentInInv(IScenePresence sp, SceneObjectGroup grp) { + if (m_invAccessModule == null) + return null; + // m_log.DebugFormat( // "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}", // grp.Name, grp.LocalId, remoteClient.Name); - Vector3 inventoryStoredPosition = new Vector3 - (((grp.AbsolutePosition.X > (int)Constants.RegionSize) - ? Constants.RegionSize - 6 - : grp.AbsolutePosition.X) - , - (grp.AbsolutePosition.Y > (int)Constants.RegionSize) - ? Constants.RegionSize - 6 - : grp.AbsolutePosition.Y, - grp.AbsolutePosition.Z); - - Vector3 originalPosition = grp.AbsolutePosition; - - grp.AbsolutePosition = inventoryStoredPosition; - - // If we're being called from a script, then trying to serialize that same script's state will not complete - // in any reasonable time period. Therefore, we'll avoid it. The worst that can happen is that if - // the client/server crashes rather than logging out normally, the attachment's scripts will resume - // without state on relog. Arguably, this is what we want anyway. - string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, false); - - grp.AbsolutePosition = originalPosition; - - AssetBase asset = m_scene.CreateAsset( - grp.GetPartName(grp.LocalId), - grp.GetPartDescription(grp.LocalId), - (sbyte)AssetType.Object, - Utils.StringToBytes(sceneObjectXml), - sp.UUID); - - m_scene.AssetService.Store(asset); - - InventoryItemBase item = new InventoryItemBase(); - item.CreatorId = grp.RootPart.CreatorID.ToString(); - item.CreatorData = grp.RootPart.CreatorData; - item.Owner = sp.UUID; - item.ID = UUID.Random(); - item.AssetID = asset.FullID; - item.Description = asset.Description; - item.Name = asset.Name; - item.AssetType = asset.Type; - item.InvType = (int)InventoryType.Object; - - InventoryFolderBase folder = m_scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object); - if (folder != null) - item.Folder = folder.ID; - else // oopsies - item.Folder = UUID.Zero; - - if ((sp.UUID != grp.RootPart.OwnerID) && m_scene.Permissions.PropagatePermissions()) - { - item.BasePermissions = grp.RootPart.NextOwnerMask; - item.CurrentPermissions = grp.RootPart.NextOwnerMask; - item.NextPermissions = grp.RootPart.NextOwnerMask; - item.EveryOnePermissions = grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask; - item.GroupPermissions = grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask; - } - else - { - item.BasePermissions = grp.RootPart.BaseMask; - item.CurrentPermissions = grp.RootPart.OwnerMask; - item.NextPermissions = grp.RootPart.NextOwnerMask; - item.EveryOnePermissions = grp.RootPart.EveryoneMask; - item.GroupPermissions = grp.RootPart.GroupMask; - } - item.CreationDate = Util.UnixTimeSinceEpoch(); + InventoryItemBase newItem = m_invAccessModule.CopyToInventory( + DeRezAction.TakeCopy, + m_scene.InventoryService.GetFolderForType(sp.UUID, AssetType.Object).ID, + new List { grp }, + sp.ControllingClient, true)[0]; // sets itemID so client can show item as 'attached' in inventory - grp.FromItemID = item.ID; + grp.FromItemID = newItem.ID; - if (m_scene.AddInventoryItem(item)) - { - sp.ControllingClient.SendInventoryItemCreateUpdate(item, 0); - } - else - { - if (m_dialogModule != null) - m_dialogModule.SendAlertToUser(sp.ControllingClient, "Operation failed"); - } - - return item; + return newItem; } // What makes this method odd and unique is it tries to detach using an UUID.... Yay for standards. @@ -709,70 +646,69 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments private SceneObjectGroup RezSingleAttachmentFromInventoryInternal( IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt) { - IInventoryAccessModule invAccess = m_scene.RequestModuleInterface(); - if (invAccess != null) + if (m_invAccessModule == null) + return null; + + lock (sp.AttachmentsSyncLock) { - lock (sp.AttachmentsSyncLock) + SceneObjectGroup objatt; + + if (itemID != UUID.Zero) + objatt = m_invAccessModule.RezObject(sp.ControllingClient, + itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, + false, false, sp.UUID, true); + else + objatt = m_invAccessModule.RezObject(sp.ControllingClient, + null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, + false, false, sp.UUID, true); + + // m_log.DebugFormat( + // "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}", + // objatt.Name, remoteClient.Name, AttachmentPt); + + if (objatt != null) { - SceneObjectGroup objatt; + // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. + objatt.HasGroupChanged = false; + bool tainted = false; + if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint) + tainted = true; - if (itemID != UUID.Zero) - objatt = invAccess.RezObject(sp.ControllingClient, - itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, - false, false, sp.UUID, true); - else - objatt = invAccess.RezObject(sp.ControllingClient, - null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, - false, false, sp.UUID, true); - - // m_log.DebugFormat( - // "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}", - // objatt.Name, remoteClient.Name, AttachmentPt); - - if (objatt != null) + // This will throw if the attachment fails + try { - // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. - objatt.HasGroupChanged = false; - bool tainted = false; - if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint) - tainted = true; - - // This will throw if the attachment fails - try - { - AttachObject(sp, objatt, attachmentPt, false); - } - catch (Exception e) - { - m_log.ErrorFormat( - "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}", - objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace); - - // Make sure the object doesn't stick around and bail - sp.RemoveAttachment(objatt); - m_scene.DeleteSceneObject(objatt, false); - return null; - } - - if (tainted) - objatt.HasGroupChanged = true; - - // Fire after attach, so we don't get messy perms dialogs - // 4 == AttachedRez - objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4); - objatt.ResumeScripts(); - - // Do this last so that event listeners have access to all the effects of the attachment - m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID); - - return objatt; + AttachObject(sp, objatt, attachmentPt, false); } - else + catch (Exception e) { - m_log.WarnFormat( - "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}", - itemID, sp.Name, attachmentPt); + m_log.ErrorFormat( + "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}", + objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace); + + // Make sure the object doesn't stick around and bail + sp.RemoveAttachment(objatt); + m_scene.DeleteSceneObject(objatt, false); + return null; } + + if (tainted) + objatt.HasGroupChanged = true; + + // Fire after attach, so we don't get messy perms dialogs + // 4 == AttachedRez + objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4); + objatt.ResumeScripts(); + + // Do this last so that event listeners have access to all the effects of the attachment + m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID); + + return objatt; + } + else + { + m_log.WarnFormat( + "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}", + itemID, sp.Name, attachmentPt); } } diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs index 42d07fd2d6..5e89eec25d 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs @@ -99,12 +99,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests public void TestAddAttachmentFromGround() { TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); +// TestHelpers.EnableLogging(); AddPresence(); string attName = "att"; - SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName).ParentGroup; + SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, m_presence.UUID).ParentGroup; m_attMod.AttachObject(m_presence, so, (uint)AttachmentPoint.Chest, false); @@ -123,6 +123,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That( m_presence.Appearance.GetAttachpoint(attSo.FromItemID), Is.EqualTo((int)AttachmentPoint.Chest)); + + InventoryItemBase attachmentItem = scene.InventoryService.GetItem(new InventoryItemBase(attSo.FromItemID)); + Assert.That(attachmentItem, Is.Not.Null); + Assert.That(attachmentItem.Name, Is.EqualTo(attName)); + + InventoryFolderBase targetFolder = scene.InventoryService.GetFolderForType(m_presence.UUID, AssetType.Object); + Assert.That(attachmentItem.Folder, Is.EqualTo(targetFolder.ID)); + +// TestHelpers.DisableLogging(); } [Test] diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 8171487545..f219d4c914 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -295,9 +295,12 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess return UUID.Zero; } - public virtual UUID CopyToInventory(DeRezAction action, UUID folderID, - List objectGroups, IClientAPI remoteClient) + public virtual List CopyToInventory( + DeRezAction action, UUID folderID, + List objectGroups, IClientAPI remoteClient, bool asAttachment) { + List copiedItems = new List(); + Dictionary> bundlesToCopy = new Dictionary>(); if (CoalesceMultipleObjectsToInventory) @@ -324,16 +327,16 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess } } - // This is method scoped and will be returned. It will be the - // last created asset id - UUID assetID = UUID.Zero; +// m_log.DebugFormat( +// "[INVENTORY ACCESS MODULE]: Copying {0} object bundles to folder {1} action {2} for {3}", +// bundlesToCopy.Count, folderID, action, remoteClient.Name); // Each iteration is really a separate asset being created, // with distinct destinations as well. foreach (List bundle in bundlesToCopy.Values) - assetID = CopyBundleToInventory(action, folderID, bundle, remoteClient); + copiedItems.Add(CopyBundleToInventory(action, folderID, bundle, remoteClient, asAttachment)); - return assetID; + return copiedItems; } /// @@ -344,12 +347,13 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess /// /// /// - /// - protected UUID CopyBundleToInventory( - DeRezAction action, UUID folderID, List objlist, IClientAPI remoteClient) + /// Should be true if the bundle is being copied as an attachment. This prevents + /// attempted serialization of any script state which would abort any operating scripts. + /// The inventory item created by the copy + protected InventoryItemBase CopyBundleToInventory( + DeRezAction action, UUID folderID, List objlist, IClientAPI remoteClient, + bool asAttachment) { - UUID assetID = UUID.Zero; - CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero); Dictionary originalPositions = new Dictionary(); @@ -385,18 +389,27 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess string itemXml; + // If we're being called from a script, then trying to serialize that same script's state will not complete + // in any reasonable time period. Therefore, we'll avoid it. The worst that can happen is that if + // the client/server crashes rather than logging out normally, the attachment's scripts will resume + // without state on relog. Arguably, this is what we want anyway. if (objlist.Count > 1) - itemXml = CoalescedSceneObjectsSerializer.ToXml(coa); + itemXml = CoalescedSceneObjectsSerializer.ToXml(coa, !asAttachment); else - itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0]); + itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0], !asAttachment); // Restore the position of each group now that it has been stored to inventory. foreach (SceneObjectGroup objectGroup in objlist) objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID]; InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID); + +// m_log.DebugFormat( +// "[INVENTORY ACCESS MODULE]: Created item is {0}", +// item != null ? item.ID.ToString() : "NULL"); + if (item == null) - return UUID.Zero; + return null; // Can't know creator is the same, so null it in inventory if (objlist.Count > 1) @@ -406,7 +419,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess } else { - item.CreatorId = objlist[0].RootPart.CreatorID.ToString(); + item.CreatorId = objlist[0].RootPart.CreatorID.ToString(); + item.CreatorData = objlist[0].RootPart.CreatorData; item.SaleType = objlist[0].RootPart.ObjectSaleType; item.SalePrice = objlist[0].RootPart.SalePrice; } @@ -419,8 +433,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess objlist[0].OwnerID.ToString()); m_Scene.AssetService.Store(asset); - item.AssetID = asset.FullID; - assetID = asset.FullID; + item.AssetID = asset.FullID; if (DeRezAction.SaveToExistingUserInventoryItem == action) { @@ -453,9 +466,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess // This is a hook to do some per-asset post-processing for subclasses that need that if (remoteClient != null) - ExportAsset(remoteClient.AgentId, assetID); + ExportAsset(remoteClient.AgentId, asset.FullID); - return assetID; + return item; } protected virtual void ExportAsset(UUID agentID, UUID assetID) @@ -643,7 +656,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess { // Catch all. Use lost & found // - folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); } } @@ -964,8 +976,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess so.FromFolderID = item.Folder; -// Console.WriteLine("rootPart.OwnedID {0}, item.Owner {1}, item.CurrentPermissions {2:X}", -// rootPart.OwnerID, item.Owner, item.CurrentPermissions); +// m_log.DebugFormat( +// "[INVENTORY ACCESS MODULE]: rootPart.OwnedID {0}, item.Owner {1}, item.CurrentPermissions {2:X}", +// rootPart.OwnerID, item.Owner, item.CurrentPermissions); if ((rootPart.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0) diff --git a/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs b/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs index 1904011b17..3576e35798 100644 --- a/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs @@ -49,11 +49,15 @@ namespace OpenSim.Region.Framework.Interfaces /// /// /// + /// + /// Should be true if the object(s) are begin taken as attachments. False otherwise. + /// /// - /// Returns the UUID of the newly created item asset (not the item itself). - /// FIXME: This is not very useful. It would be far more useful to return a list of items instead. + /// A list of the items created. If there was more than one object and objects are not being coaleseced in + /// inventory, then the order of items is in the same order as the input objects. /// - UUID CopyToInventory(DeRezAction action, UUID folderID, List objectGroups, IClientAPI remoteClient); + List CopyToInventory( + DeRezAction action, UUID folderID, List objectGroups, IClientAPI remoteClient, bool asAttachment); /// /// Rez an object into the scene from the user's inventory diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs index 834464b2c8..f555b49f58 100644 --- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs +++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs @@ -155,7 +155,7 @@ namespace OpenSim.Region.Framework.Scenes { IInventoryAccessModule invAccess = m_scene.RequestModuleInterface(); if (invAccess != null) - invAccess.CopyToInventory(x.action, x.folderID, x.objectGroups, x.remoteClient); + invAccess.CopyToInventory(x.action, x.folderID, x.objectGroups, x.remoteClient, false); if (x.permissionToDelete) { diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 3734e03994..d27d9e1dad 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -1027,10 +1027,16 @@ namespace OpenSim.Region.Framework.Scenes public void ApplyNextOwnerPermissions() { + Util.PrintCallStack(); + lock (m_items) { foreach (TaskInventoryItem item in m_items.Values) { +// m_log.DebugFormat ( +// "[SCENE OBJECT PART INVENTORY]: Applying next permissions {0} to {1} in {2} with current {3}, base {4}, everyone {5}", +// item.NextPermissions, item.Name, m_part.Name, item.CurrentPermissions, item.BasePermissions, item.EveryonePermissions); + if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) { if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) @@ -1040,6 +1046,7 @@ namespace OpenSim.Region.Framework.Scenes if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0) item.CurrentPermissions &= ~(uint)PermissionMask.Modify; } + item.CurrentPermissions &= item.NextPermissions; item.BasePermissions &= item.NextPermissions; item.EveryonePermissions &= item.NextPermissions; diff --git a/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs index 55455cc434..a4f730d375 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs @@ -47,14 +47,30 @@ namespace OpenSim.Region.Framework.Scenes.Serialization /// public class CoalescedSceneObjectsSerializer { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); /// /// Serialize coalesced objects to Xml /// /// + /// + /// If true then serialize script states. This will halt any running scripts + /// /// public static string ToXml(CoalescedSceneObjects coa) + { + return ToXml(coa, true); + } + + /// + /// Serialize coalesced objects to Xml + /// + /// + /// + /// If true then serialize script states. This will halt any running scripts + /// + /// + public static string ToXml(CoalescedSceneObjects coa, bool doScriptStates) { using (StringWriter sw = new StringWriter()) { @@ -91,7 +107,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization writer.WriteAttributeString("offsety", offsets[i].Y.ToString()); writer.WriteAttributeString("offsetz", offsets[i].Z.ToString()); - SceneObjectSerializer.ToOriginalXmlFormat(obj, writer, true); + SceneObjectSerializer.ToOriginalXmlFormat(obj, writer, doScriptStates); writer.WriteEndElement(); // SceneObjectGroup } diff --git a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs index 59829d994f..239afc0aee 100644 --- a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs +++ b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs @@ -566,7 +566,7 @@ namespace OpenSim.Tests.Common /// public static SceneObjectPart AddSceneObject(Scene scene) { - return AddSceneObject(scene, "Test Object"); + return AddSceneObject(scene, "Test Object", UUID.Zero); } /// @@ -574,10 +574,11 @@ namespace OpenSim.Tests.Common /// /// /// + /// /// - public static SceneObjectPart AddSceneObject(Scene scene, string name) + public static SceneObjectPart AddSceneObject(Scene scene, string name, UUID ownerId) { - SceneObjectPart part = CreateSceneObjectPart(name, UUID.Random(), UUID.Zero); + SceneObjectPart part = CreateSceneObjectPart(name, UUID.Random(), ownerId); //part.UpdatePrimFlags(false, false, true); //part.ObjectFlags |= (uint)PrimFlags.Phantom; From ec8745cf511de3a452a882a44034c55baf2350a1 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 23 May 2012 02:05:48 +0100 Subject: [PATCH 02/10] minor: Make log class names in InventoryAccessModule uniform --- .../InventoryAccess/InventoryAccessModule.cs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index f219d4c914..69767c1b99 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -175,7 +175,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess sbyte assetType, byte wearableType, uint nextOwnerMask, int creationDate) { - m_log.DebugFormat("[AGENT INVENTORY]: Received request to create inventory item {0} in folder {1}", name, folderID); + m_log.DebugFormat("[INVENTORY ACCESS MODULE]: Received request to create inventory item {0} in folder {1}", name, folderID); if (!m_Scene.Permissions.CanCreateUserInventory(invType, remoteClient.AgentId)) return; @@ -210,7 +210,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess else { m_log.ErrorFormat( - "ScenePresence for agent uuid {0} unexpectedly not found in CreateNewInventoryItem", + "[INVENTORY ACCESS MODULE]: ScenePresence for agent uuid {0} unexpectedly not found in CreateNewInventoryItem", remoteClient.AgentId); } } @@ -288,7 +288,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess else { m_log.ErrorFormat( - "[AGENT INVENTORY]: Could not find item {0} for caps inventory update", + "[INVENTORY ACCESS MODULE]: Could not find item {0} for caps inventory update", itemID); } @@ -605,7 +605,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess if (null == item) { m_log.DebugFormat( - "[AGENT INVENTORY]: Object {0} {1} scheduled for save to inventory has already been deleted.", + "[INVENTORY ACCESS MODULE]: Object {0} {1} scheduled for save to inventory has already been deleted.", so.Name, so.UUID); return null; @@ -706,7 +706,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess if (item == null) { m_log.WarnFormat( - "[InventoryAccessModule]: Could not find item {0} for {1} in RezObject()", + "[INVENTORY ACCESS MODULE]: Could not find item {0} for {1} in RezObject()", itemID, remoteClient.Name); return null; @@ -738,7 +738,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess else { m_log.WarnFormat( - "[InventoryAccessModule]: Could not find asset {0} for {1} in RezObject()", + "[INVENTORY ACCESS MODULE]: Could not find asset {0} for {1} in RezObject()", assetID, remoteClient.Name); } @@ -815,7 +815,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess group = objlist[i]; // m_log.DebugFormat( -// "[InventoryAccessModule]: Preparing to rez {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}", +// "[INVENTORY ACCESS MODULE]: Preparing to rez {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}", // group.Name, group.LocalId, group.UUID, // group.RootPart.OwnerMask, group.RootPart.NextOwnerMask, group.RootPart.GroupMask, group.RootPart.EveryoneMask, // remoteClient.Name); @@ -823,7 +823,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess // Vector3 storedPosition = group.AbsolutePosition; if (group.UUID == UUID.Zero) { - m_log.Debug("[InventoryAccessModule]: Object has UUID.Zero! Position 3"); + m_log.Debug("[INVENTORY ACCESS MODULE]: Object has UUID.Zero! Position 3"); } foreach (SceneObjectPart part in group.Parts) @@ -886,7 +886,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess } // m_log.DebugFormat( -// "[InventoryAccessModule]: Rezzed {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}", +// "[INVENTORY ACCESS MODULE]: Rezzed {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}", // group.Name, group.LocalId, group.UUID, // group.RootPart.OwnerMask, group.RootPart.NextOwnerMask, group.RootPart.GroupMask, group.RootPart.EveryoneMask, // remoteClient.Name); @@ -1101,7 +1101,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess if (assetRequestItem.AssetID != requestID) { m_log.WarnFormat( - "[CLIENT]: {0} requested asset {1} from item {2} but this does not match item's asset {3}", + "[INVENTORY ACCESS MODULE]: {0} requested asset {1} from item {2} but this does not match item's asset {3}", Name, requestID, itemID, assetRequestItem.AssetID); return false; From 68918d632f0521941f67fe2c7b9c87ed048e2b92 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 23 May 2012 02:09:31 +0100 Subject: [PATCH 03/10] Fetch the dialog module reference in AttachmentsModule in RegionLoaded() not AddRegion() The reference is not guaranteed to be there when AddRegion() is called but will definitely be present at RegionLoaded() if it's going to be present at all. --- .../Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index d099511e8e..510b483ed1 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -71,7 +71,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments public void AddRegion(Scene scene) { m_scene = scene; - m_dialogModule = m_scene.RequestModuleInterface(); m_scene.RegisterModuleInterface(this); if (Enabled) @@ -90,6 +89,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments public void RegionLoaded(Scene scene) { + m_dialogModule = m_scene.RequestModuleInterface(); m_invAccessModule = m_scene.RequestModuleInterface(); } From 050007b44da97bf155fca95cadc32cb27924e263 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 23 May 2012 02:30:16 +0100 Subject: [PATCH 04/10] Lay out "show region" information in an easier to read line by line format --- OpenSim/Services/GridService/GridService.cs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/OpenSim/Services/GridService/GridService.cs b/OpenSim/Services/GridService/GridService.cs index 3dc87bc5d5..b17fca799a 100644 --- a/OpenSim/Services/GridService/GridService.cs +++ b/OpenSim/Services/GridService/GridService.cs @@ -509,19 +509,21 @@ namespace OpenSim.Services.GridService return; } - MainConsole.Instance.Output("Region Name Region UUID"); - MainConsole.Instance.Output("Location URI"); - MainConsole.Instance.Output("Owner ID Flags"); - MainConsole.Instance.Output("-------------------------------------------------------------------------------"); + ICommandConsole con = MainConsole.Instance; + foreach (RegionData r in regions) { OpenSim.Data.RegionFlags flags = (OpenSim.Data.RegionFlags)Convert.ToInt32(r.Data["flags"]); - MainConsole.Instance.Output(String.Format("{0,-20} {1}\n{2,-20} {3}\n{4,-39} {5}\n\n", - r.RegionName, r.RegionID, - String.Format("{0},{1}", r.posX / Constants.RegionSize, r.posY / Constants.RegionSize), - r.Data["serverURI"], - r.Data["owner_uuid"], flags)); + + con.OutputFormat("{0,-11}: {1}", "Region Name", r.RegionName); + con.OutputFormat("{0,-11}: {1}", "Region ID", r.RegionID); + con.OutputFormat("{0,-11}: {1}", "Location", r.coordX, r.coordY); + con.OutputFormat("{0,-11}: {1}", "URI", r.Data["serverURI"]); + con.OutputFormat("{0,-11}: {1}", "Owner ID", r.Data["owner_uuid"]); + con.OutputFormat("{0,-11}: {1}", "Flags", flags); + con.Output("\n"); } + return; } From c6ce41bfbab310eae2366ad494a0dbb42cebc070 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 23 May 2012 02:31:53 +0100 Subject: [PATCH 05/10] Add missing Y co-ord in "show region" console command information --- OpenSim/Services/GridService/GridService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Services/GridService/GridService.cs b/OpenSim/Services/GridService/GridService.cs index b17fca799a..9d81eb5355 100644 --- a/OpenSim/Services/GridService/GridService.cs +++ b/OpenSim/Services/GridService/GridService.cs @@ -517,7 +517,7 @@ namespace OpenSim.Services.GridService con.OutputFormat("{0,-11}: {1}", "Region Name", r.RegionName); con.OutputFormat("{0,-11}: {1}", "Region ID", r.RegionID); - con.OutputFormat("{0,-11}: {1}", "Location", r.coordX, r.coordY); + con.OutputFormat("{0,-11}: {1},{2}", "Location", r.coordX, r.coordY); con.OutputFormat("{0,-11}: {1}", "URI", r.Data["serverURI"]); con.OutputFormat("{0,-11}: {1}", "Owner ID", r.Data["owner_uuid"]); con.OutputFormat("{0,-11}: {1}", "Flags", flags); From 2222d979cc723ee2f3bad92ffe4991d074b2403a Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 23 May 2012 02:37:38 +0100 Subject: [PATCH 06/10] refactor: rename ConsoleTable -> ConsoleDisplayTable for clarity --- .../Console/{ConsoleTable.cs => ConsoleDisplayTable.cs} | 4 ++-- .../Avatar/Attachments/AttachmentsCommandModule.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename OpenSim/Framework/Console/{ConsoleTable.cs => ConsoleDisplayTable.cs} (98%) diff --git a/OpenSim/Framework/Console/ConsoleTable.cs b/OpenSim/Framework/Console/ConsoleDisplayTable.cs similarity index 98% rename from OpenSim/Framework/Console/ConsoleTable.cs rename to OpenSim/Framework/Console/ConsoleDisplayTable.cs index be3025be7f..49d5a179d0 100644 --- a/OpenSim/Framework/Console/ConsoleTable.cs +++ b/OpenSim/Framework/Console/ConsoleDisplayTable.cs @@ -38,7 +38,7 @@ namespace OpenSim.Framework.Console /// /// Currently subject to change. If you use this, be prepared to change your code when this class changes. /// - public class ConsoleTable + public class ConsoleDisplayTable { /// /// Default number of spaces between table columns. @@ -65,7 +65,7 @@ namespace OpenSim.Framework.Console /// public int TableSpacing { get; set; } - public ConsoleTable() + public ConsoleDisplayTable() { TableSpacing = DefaultTableSpacing; Columns = new List(); diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs index a95514c642..df32a1d623 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs @@ -145,7 +145,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments { sb.AppendFormat("Attachments for {0}\n", sp.Name); - ConsoleTable ct = new ConsoleTable() { Indent = 2 }; + ConsoleDisplayTable ct = new ConsoleDisplayTable() { Indent = 2 }; ct.Columns.Add(new ConsoleTableColumn("Attachment Name", 36)); ct.Columns.Add(new ConsoleTableColumn("Local ID", 10)); ct.Columns.Add(new ConsoleTableColumn("Item ID", 36)); From 059a1e90b92c3c1ca027c0ec59f3628d87a954a6 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 23 May 2012 03:19:25 +0100 Subject: [PATCH 07/10] Add ConsoleDisplayList for more consistent formatting of console output in list form. Convert "show region" to use this structure rather than hand-constructing --- .../Framework/Console/ConsoleDisplayList.cs | 112 ++++++++++++++++++ OpenSim/Services/GridService/GridService.cs | 18 +-- 2 files changed, 121 insertions(+), 9 deletions(-) create mode 100644 OpenSim/Framework/Console/ConsoleDisplayList.cs diff --git a/OpenSim/Framework/Console/ConsoleDisplayList.cs b/OpenSim/Framework/Console/ConsoleDisplayList.cs new file mode 100644 index 0000000000..68855091d4 --- /dev/null +++ b/OpenSim/Framework/Console/ConsoleDisplayList.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.Generic; +using System.Linq; +using System.Text; + +namespace OpenSim.Framework.Console +{ + /// + /// Used to generated a formatted table for the console. + /// + /// + /// Currently subject to change. If you use this, be prepared to change your code when this class changes. + /// + public class ConsoleDisplayList + { + /// + /// The default divider between key and value for a list item. + /// + public const string DefaultKeyValueDivider = " : "; + + /// + /// The divider used between key and value for a list item. + /// + public string KeyValueDivider { get; set; } + + /// + /// Table rows + /// + public List> Rows { get; private set; } + + /// + /// Number of spaces to indent the list. + /// + public int Indent { get; set; } + + public ConsoleDisplayList() + { + Rows = new List>(); + KeyValueDivider = DefaultKeyValueDivider; + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + AddToStringBuilder(sb); + return sb.ToString(); + } + + public void AddToStringBuilder(StringBuilder sb) + { + string formatString = GetFormatString(); +// System.Console.WriteLine("FORMAT STRING [{0}]", formatString); + + // rows + foreach (KeyValuePair row in Rows) + sb.AppendFormat(formatString, row.Key, row.Value); + } + + /// + /// Gets the format string for the table. + /// + private string GetFormatString() + { + StringBuilder formatSb = new StringBuilder(); + + int longestKey = -1; + + foreach (KeyValuePair row in Rows) + if (row.Key.Length > longestKey) + longestKey = row.Key.Length; + + formatSb.Append(' ', Indent); + + // Can only do left formatting for now + formatSb.AppendFormat("{{0,-{0}}}{1}{{1}}\n", longestKey, KeyValueDivider); + + return formatSb.ToString(); + } + + public void AddRow(object key, object value) + { + Rows.Add(new KeyValuePair(key.ToString(), value.ToString())); + } + } +} \ No newline at end of file diff --git a/OpenSim/Services/GridService/GridService.cs b/OpenSim/Services/GridService/GridService.cs index 9d81eb5355..8a60ca5467 100644 --- a/OpenSim/Services/GridService/GridService.cs +++ b/OpenSim/Services/GridService/GridService.cs @@ -509,19 +509,19 @@ namespace OpenSim.Services.GridService return; } - ICommandConsole con = MainConsole.Instance; - foreach (RegionData r in regions) { OpenSim.Data.RegionFlags flags = (OpenSim.Data.RegionFlags)Convert.ToInt32(r.Data["flags"]); - con.OutputFormat("{0,-11}: {1}", "Region Name", r.RegionName); - con.OutputFormat("{0,-11}: {1}", "Region ID", r.RegionID); - con.OutputFormat("{0,-11}: {1},{2}", "Location", r.coordX, r.coordY); - con.OutputFormat("{0,-11}: {1}", "URI", r.Data["serverURI"]); - con.OutputFormat("{0,-11}: {1}", "Owner ID", r.Data["owner_uuid"]); - con.OutputFormat("{0,-11}: {1}", "Flags", flags); - con.Output("\n"); + ConsoleDisplayList dispList = new ConsoleDisplayList(); + dispList.AddRow("Region Name", r.RegionName); + dispList.AddRow("Region ID", r.RegionID); + dispList.AddRow("Location", string.Format("{0},{1}", r.coordX, r.coordY)); + dispList.AddRow("URI", r.Data["serverURI"]); + dispList.AddRow("Owner ID", r.Data["owner_uuid"]); + dispList.AddRow("Flags", flags); + + MainConsole.Instance.Output(dispList.ToString()); } return; From 8f88c17df969b1fd3e4a93747201e9436c9a1fcd Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 23 May 2012 03:23:37 +0100 Subject: [PATCH 08/10] refactor: Rename ConsoleTableRow and ConsoleTableColumn to ConsoleDisplayTableRow and ConsoleDisplayTableColumn --- .../Framework/Console/ConsoleDisplayTable.cs | 18 +++++++++--------- .../Attachments/AttachmentsCommandModule.cs | 12 ++++++------ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/OpenSim/Framework/Console/ConsoleDisplayTable.cs b/OpenSim/Framework/Console/ConsoleDisplayTable.cs index 49d5a179d0..e9d1628b1d 100644 --- a/OpenSim/Framework/Console/ConsoleDisplayTable.cs +++ b/OpenSim/Framework/Console/ConsoleDisplayTable.cs @@ -48,12 +48,12 @@ namespace OpenSim.Framework.Console /// /// Table columns. /// - public List Columns { get; private set; } + public List Columns { get; private set; } /// /// Table rows /// - public List Rows { get; private set; } + public List Rows { get; private set; } /// /// Number of spaces to indent the table. @@ -68,8 +68,8 @@ namespace OpenSim.Framework.Console public ConsoleDisplayTable() { TableSpacing = DefaultTableSpacing; - Columns = new List(); - Rows = new List(); + Columns = new List(); + Rows = new List(); } public override string ToString() @@ -88,7 +88,7 @@ namespace OpenSim.Framework.Console sb.AppendFormat(formatString, Columns.ConvertAll(c => c.Header).ToArray()); // rows - foreach (ConsoleTableRow row in Rows) + foreach (ConsoleDisplayTableRow row in Rows) sb.AppendFormat(formatString, row.Cells.ToArray()); } @@ -115,23 +115,23 @@ namespace OpenSim.Framework.Console } } - public struct ConsoleTableColumn + public struct ConsoleDisplayTableColumn { public string Header { get; set; } public int Width { get; set; } - public ConsoleTableColumn(string header, int width) : this() + public ConsoleDisplayTableColumn(string header, int width) : this() { Header = header; Width = width; } } - public struct ConsoleTableRow + public struct ConsoleDisplayTableRow { public List Cells { get; private set; } - public ConsoleTableRow(List cells) : this() + public ConsoleDisplayTableRow(List cells) : this() { Cells = cells; } diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs index df32a1d623..1b9e3ace5c 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs @@ -146,11 +146,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments sb.AppendFormat("Attachments for {0}\n", sp.Name); ConsoleDisplayTable ct = new ConsoleDisplayTable() { Indent = 2 }; - ct.Columns.Add(new ConsoleTableColumn("Attachment Name", 36)); - ct.Columns.Add(new ConsoleTableColumn("Local ID", 10)); - ct.Columns.Add(new ConsoleTableColumn("Item ID", 36)); - ct.Columns.Add(new ConsoleTableColumn("Attach Point", 14)); - ct.Columns.Add(new ConsoleTableColumn("Position", 15)); + ct.Columns.Add(new ConsoleDisplayTableColumn("Attachment Name", 36)); + ct.Columns.Add(new ConsoleDisplayTableColumn("Local ID", 10)); + ct.Columns.Add(new ConsoleDisplayTableColumn("Item ID", 36)); + ct.Columns.Add(new ConsoleDisplayTableColumn("Attach Point", 14)); + ct.Columns.Add(new ConsoleDisplayTableColumn("Position", 15)); // sb.AppendFormat( // " {0,-36} {1,-10} {2,-36} {3,-14} {4,-15}\n", @@ -176,7 +176,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments // attachmentObject.Name, attachmentObject.LocalId, attachmentObject.FromItemID, // (AttachmentPoint)attachmentObject.AttachmentPoint, attachmentObject.RootPart.AttachedPos); ct.Rows.Add( - new ConsoleTableRow( + new ConsoleDisplayTableRow( new List() { attachmentObject.Name, From ee98b9c394900f55684e33829be1c182e84b2cab Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 23 May 2012 04:10:45 +0100 Subject: [PATCH 09/10] Add "show scene" command which lists stats for the currently selected console scene(s) This includes prim count, script count, avatar count, etc. Information is currently the same as "show stats", though show stats can only show one scene at a time because it listens for the latest outgoing stats packet (a bad approach that needs to change). Might be better to tie this module into the other stats module to display arbitrary stats rather than fetching directly from scene.SimStatsReporter. Console command is "show scene" because "show region" already exists for the grid service, which is unfortunate. Might need to make a distinction between "scene" relating to a live scene and "region" relating to more static region data (url, coords, etc.) --- .../World/Region/RegionCommandsModule.cs | 155 ++++++++++++++++++ OpenSim/Region/Framework/Scenes/Scene.cs | 7 +- 2 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs diff --git a/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs b/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs new file mode 100644 index 0000000000..be4f497360 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs @@ -0,0 +1,155 @@ +/* + * 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.Text; +using System.Text.RegularExpressions; +using log4net; +using Mono.Addins; +using NDesk.Options; +using Nini.Config; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Framework.Statistics; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.Objects.Commands +{ + /// + /// A module that holds commands for manipulating objects in the scene. + /// + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RegionCommandsModule")] + public class RegionCommandsModule : INonSharedRegionModule + { + private Scene m_scene; + private ICommandConsole m_console; + + public string Name { get { return "Region Commands Module"; } } + + public Type ReplaceableInterface { get { return null; } } + + public void Initialise(IConfigSource source) + { +// m_log.DebugFormat("[OBJECT COMMANDS MODULE]: INITIALIZED MODULE"); + } + + public void PostInitialise() + { +// m_log.DebugFormat("[OBJECT COMMANDS MODULE]: POST INITIALIZED MODULE"); + } + + public void Close() + { +// m_log.DebugFormat("[OBJECT COMMANDS MODULE]: CLOSED MODULE"); + } + + public void AddRegion(Scene scene) + { +// m_log.DebugFormat("[OBJECT COMMANDS MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName); + + m_scene = scene; + m_console = MainConsole.Instance; + + m_console.Commands.AddCommand( + "Regions", false, "show scene", + "show scene", + "Show live scene information for the currently selected region.", HandleShowScene); + } + + public void RemoveRegion(Scene scene) + { +// m_log.DebugFormat("[OBJECTS COMMANDS MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName); + } + + public void RegionLoaded(Scene scene) + { +// m_log.DebugFormat("[OBJECTS COMMANDS MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName); + } + + private void HandleShowScene(string module, string[] cmd) + { + if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_scene)) + return; + + SimStatsReporter r = m_scene.StatsReporter; + float[] stats = r.LastReportedSimStats; + + float timeDilation = stats[0]; + float simFps = stats[1]; + float physicsFps = stats[2]; + float agentUpdates = stats[3]; + float rootAgents = stats[4]; + float childAgents = stats[5]; + float totalPrims = stats[6]; + float activePrims = stats[7]; + float totalFrameTime = stats[8]; +// float netFrameTime = stats.StatsBlock[9].StatValue; // Ignored - not used by OpenSimulator + float physicsFrameTime = stats[10]; + float otherFrameTime = stats[11]; +// float imageFrameTime = stats.StatsBlock[12].StatValue; // Ignored + float inPacketsPerSecond = stats[13]; + float outPacketsPerSecond = stats[14]; + float unackedBytes = stats[15]; +// float agentFrameTime = stats.StatsBlock[16].StatValue; // Not really used + float pendingDownloads = stats[17]; + float pendingUploads = stats[18]; + float activeScripts = stats[19]; + float scriptLinesPerSecond = stats[20]; + + StringBuilder sb = new StringBuilder(); + sb.AppendFormat("Scene statistics for {0}\n", m_scene.RegionInfo.RegionName); + + ConsoleDisplayList dispList = new ConsoleDisplayList(); + dispList.AddRow("Time Dilation", timeDilation); + dispList.AddRow("Sim FPS", simFps); + dispList.AddRow("Physics FPS", physicsFps); + dispList.AddRow("Avatars", rootAgents); + dispList.AddRow("Child agents", childAgents); + dispList.AddRow("Total prims", totalPrims); + dispList.AddRow("Scripts", activeScripts); + dispList.AddRow("Script lines processed per second", scriptLinesPerSecond); + dispList.AddRow("Physics enabled prims", activePrims); + dispList.AddRow("Total frame time", totalFrameTime); + dispList.AddRow("Physics frame time", physicsFrameTime); + dispList.AddRow("Other frame time", otherFrameTime); + dispList.AddRow("Agent Updates per second", agentUpdates); + dispList.AddRow("Packets processed from clients per second", inPacketsPerSecond); + dispList.AddRow("Packets sent to clients per second", outPacketsPerSecond); + dispList.AddRow("Bytes unacknowledged by clients", unackedBytes); + dispList.AddRow("Pending asset downloads to clients", pendingDownloads); + dispList.AddRow("Pending asset uploads from clients", pendingUploads); + + dispList.AddToStringBuilder(sb); + + MainConsole.Instance.Output(sb.ToString()); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 5a0f56441f..fbe56f6b36 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -77,7 +77,12 @@ namespace OpenSim.Region.Framework.Scenes public bool DebugUpdates { get; private set; } public SynchronizeSceneHandler SynchronizeScene; - public SimStatsReporter StatsReporter; + + /// + /// Statistical information for this scene. + /// + public SimStatsReporter StatsReporter { get; private set; } + public List NorthBorders = new List(); public List EastBorders = new List(); public List SouthBorders = new List(); From 4d1986c0e480466383fa0a79a1305fe108430d68 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 23 May 2012 04:20:54 +0100 Subject: [PATCH 10/10] minor: Change [OBJECT COMMANDS MODULE] log strings to [REGION COMMANDS MODULE] strings, though all these are currently commented out anyway --- .../CoreModules/World/Region/RegionCommandsModule.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs b/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs index be4f497360..2838e0c356 100644 --- a/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs @@ -58,22 +58,22 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands public void Initialise(IConfigSource source) { -// m_log.DebugFormat("[OBJECT COMMANDS MODULE]: INITIALIZED MODULE"); +// m_log.DebugFormat("[REGION COMMANDS MODULE]: INITIALIZED MODULE"); } public void PostInitialise() { -// m_log.DebugFormat("[OBJECT COMMANDS MODULE]: POST INITIALIZED MODULE"); +// m_log.DebugFormat("[REGION COMMANDS MODULE]: POST INITIALIZED MODULE"); } public void Close() { -// m_log.DebugFormat("[OBJECT COMMANDS MODULE]: CLOSED MODULE"); +// m_log.DebugFormat("[REGION COMMANDS MODULE]: CLOSED MODULE"); } public void AddRegion(Scene scene) { -// m_log.DebugFormat("[OBJECT COMMANDS MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName); +// m_log.DebugFormat("[REGION COMMANDS MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName); m_scene = scene; m_console = MainConsole.Instance; @@ -86,12 +86,12 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands public void RemoveRegion(Scene scene) { -// m_log.DebugFormat("[OBJECTS COMMANDS MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName); +// m_log.DebugFormat("[REGION COMMANDS MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName); } public void RegionLoaded(Scene scene) { -// m_log.DebugFormat("[OBJECTS COMMANDS MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName); +// m_log.DebugFormat("[REGION COMMANDS MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName); } private void HandleShowScene(string module, string[] cmd)