From e20cf3789bc8bbcda86c8e9067fbe8ecdb3046ac Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 25 Jan 2012 19:31:50 +0000 Subject: Serialize calls to ODE Collide() function across OdeScene instances to prevent ODE crashes on simulators running more than one region. It turns out that calls to Collide() are not thread-safe even for objects in different ODE physics worlds due to ODE static caches. For simulators running multiple regions, not serializing calls from different scene loops will sooner or later cause OpenSim to crash with a native stack trace referencing OBBCollider. This affects the default OPCODE collider but not GIMPACT. However, GIMPACT fails for other reasons under some current simulator loads. ODE provides a thread local storage option, but as of ODE r1755 (and r1840) DLLs compiled with this crash OpenSim immediately. --- OpenSim/Region/Physics/OdePlugin/ODECharacter.cs | 3 +++ OpenSim/Region/Physics/OdePlugin/OdeScene.cs | 30 +++++++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs index c6e8286..7c1c046 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs @@ -1048,6 +1048,7 @@ namespace OpenSim.Region.Physics.OdePlugin CAPSULE_RADIUS = 0.01f; } +// lock (OdeScene.UniversalColliderSyncObject) Shell = d.CreateCapsule(_parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH); d.GeomSetCategoryBits(Shell, (int)m_collisionCategories); @@ -1179,7 +1180,9 @@ namespace OpenSim.Region.Physics.OdePlugin if (Shell != IntPtr.Zero) { +// lock (OdeScene.UniversalColliderSyncObject) d.GeomDestroy(Shell); + _parent_scene.geom_name_map.Remove(Shell); _parent_scene.actor_name_map.Remove(Shell); diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs index 37daf46..4530c09 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs @@ -105,6 +105,32 @@ namespace OpenSim.Region.Physics.OdePlugin private readonly ILog m_log; // private Dictionary m_storedCollisions = new Dictionary(); + /// + /// Provide a sync object so that only one thread calls d.Collide() at a time across all OdeScene instances. + /// + /// + /// With ODE as of r1755 (though also tested on r1860), only one thread can call d.Collide() at a + /// time, even where physics objects are in entirely different ODE worlds. This is because generating contacts + /// uses a static cache at the ODE level. + /// + /// Without locking, simulators running multiple regions will eventually crash with a native stack trace similar + /// to + /// + /// mono() [0x489171] + /// mono() [0x4d154f] + /// /lib/x86_64-linux-gnu/libpthread.so.0(+0xfc60) [0x7f6ded592c60] + /// .../opensim/bin/libode-x86_64.so(_ZN6Opcode11OBBCollider8_CollideEPKNS_14AABBNoLeafNodeE+0xd7a) [0x7f6dd822628a] + /// + /// ODE provides an experimental option to cache in thread local storage but compiling ODE with this option + /// causes OpenSimulator to immediately crash with a native stack trace similar to + /// + /// mono() [0x489171] + /// mono() [0x4d154f] + /// /lib/x86_64-linux-gnu/libpthread.so.0(+0xfc60) [0x7f03c9849c60] + /// .../opensim/bin/libode-x86_64.so(_Z12dCollideCCTLP6dxGeomS0_iP12dContactGeomi+0x92) [0x7f03b44bcf82] + /// + internal static Object UniversalColliderSyncObject = new Object(); + private Random fluidRandomizer = new Random(Environment.TickCount); private const uint m_regionWidth = Constants.RegionSize; @@ -799,7 +825,9 @@ namespace OpenSim.Region.Physics.OdePlugin if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact)) return; - count = d.Collide(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf); + lock (OdeScene.UniversalColliderSyncObject) + count = d.Collide(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf); + if (count > contacts.Length) m_log.Error("[ODE SCENE]: Got " + count + " contacts when we asked for a maximum of " + contacts.Length); } -- cgit v1.1 From 82c3d0cf89427b2ed3be892b7b9af3ee06d65e52 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 25 Jan 2012 20:36:51 +0000 Subject: minor: stop the WebStatsModule logging UPDATE or INSERT every time it updates bin/LocalUserStatistics.db --- OpenSim/Region/UserStatistics/WebStatsModule.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/UserStatistics/WebStatsModule.cs b/OpenSim/Region/UserStatistics/WebStatsModule.cs index fca9fd0..24a9418 100644 --- a/OpenSim/Region/UserStatistics/WebStatsModule.cs +++ b/OpenSim/Region/UserStatistics/WebStatsModule.cs @@ -442,7 +442,7 @@ namespace OpenSim.Region.UserStatistics public string ViewerStatsReport(string request, string path, string param, UUID agentID, Caps caps) { - //m_log.Debug(request); +// m_log.DebugFormat("[WEB STATS MODULE]: Received viewer starts report from {0}", agentID); UpdateUserStats(ParseViewerStats(request,agentID), dbConn); @@ -655,13 +655,13 @@ namespace OpenSim.Region.UserStatistics updatecmd.Parameters.Add(new SqliteParameter(":session_key", uid.session_data.session_id.ToString())); updatecmd.Parameters.Add(new SqliteParameter(":agent_key", uid.session_data.agent_id.ToString())); updatecmd.Parameters.Add(new SqliteParameter(":region_key", uid.session_data.region_id.ToString())); - m_log.Debug("UPDATE"); +// m_log.Debug("UPDATE"); int result = updatecmd.ExecuteNonQuery(); if (result == 0) { - m_log.Debug("INSERT"); +// m_log.Debug("INSERT"); updatecmd.CommandText = SQL_STATS_TABLE_INSERT; try { -- cgit v1.1 From 8f53c768f53478ff3e0c27198b257bb27be16259 Mon Sep 17 00:00:00 2001 From: Pixel Tomsen Date: Wed, 25 Jan 2012 21:31:18 +0100 Subject: llGetParcelMusicURL implementation http://wiki.secondlife.com/wiki/LlGetParcelMusicURL Signed-off-by: BlueWall --- OpenSim/Framework/ILandObject.cs | 6 ++++++ OpenSim/Region/CoreModules/World/Land/LandObject.cs | 11 ++++++++++- .../Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 12 ++++++++++++ OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs | 1 + OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs | 5 +++++ 5 files changed, 34 insertions(+), 1 deletion(-) diff --git a/OpenSim/Framework/ILandObject.cs b/OpenSim/Framework/ILandObject.cs index 0316944..f75a990 100644 --- a/OpenSim/Framework/ILandObject.cs +++ b/OpenSim/Framework/ILandObject.cs @@ -130,5 +130,11 @@ namespace OpenSim.Framework /// /// void SetMusicUrl(string url); + + /// + /// Get the music url for this land parcel + /// + /// The music url. + string GetMusicUrl(); } } diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index 0da0de3..79b13c3 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -1094,7 +1094,16 @@ namespace OpenSim.Region.CoreModules.World.Land LandData.MusicURL = url; SendLandUpdateToAvatarsOverMe(); } - + + /// + /// Get the music url for this land parcel + /// + /// The music url. + public string GetMusicUrl() + { + return LandData.MusicURL; + } + #endregion } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index fb930e0..330c65d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -7566,6 +7566,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScriptSleep(2000); } + public LSL_String llGetParcelMusicURL() + { + m_host.AddScriptLPS(1); + + ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); + + if (land.LandData.OwnerID != m_host.OwnerID) + return String.Empty; + + return land.GetMusicUrl(); + } + public LSL_Vector llGetRootPosition() { m_host.AddScriptLPS(1); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs index 62e2854..282443b 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs @@ -161,6 +161,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces LSL_List llGetParcelDetails(LSL_Vector pos, LSL_List param); LSL_Integer llGetParcelFlags(LSL_Vector pos); LSL_Integer llGetParcelMaxPrims(LSL_Vector pos, int sim_wide); + LSL_String llGetParcelMusicURL(); LSL_Integer llGetParcelPrimCount(LSL_Vector pos, int category, int sim_wide); LSL_List llGetParcelPrimOwners(LSL_Vector pos); LSL_Integer llGetPermissions(); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs index 508f33b..9733683 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs @@ -649,6 +649,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase return m_LSL_Functions.llGetParcelMaxPrims(pos, sim_wide); } + public LSL_String llGetParcelMusicURL() + { + return m_LSL_Functions.llGetParcelMusicURL(); + } + public LSL_Integer llGetParcelPrimCount(LSL_Vector pos, int category, int sim_wide) { return m_LSL_Functions.llGetParcelPrimCount(pos, category, sim_wide); -- cgit v1.1 From e9de7e7107f4a52a944a06e20db0f29d0d6d37d3 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 25 Jan 2012 14:40:38 -0800 Subject: Update BulletSim.dll with some interface changes and tuning (see opensim-libs). Change BSScene to use new interface. --- OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 33 +++++++++++++++++---- .../Region/Physics/BulletSPlugin/BulletSimAPI.cs | 4 +++ bin/BulletSim-x86_64.dll | Bin 784384 -> 768000 bytes bin/BulletSim.dll | Bin 676352 -> 562176 bytes bin/OpenSimDefaults.ini | 5 ++-- bin/libBulletSim-x86_64.so | Bin 2005396 -> 977886 bytes bin/libBulletSim.so | Bin 1857855 -> 864751 bytes 7 files changed, 34 insertions(+), 8 deletions(-) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 7704002..e9a849c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -72,6 +72,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters private bool m_initialized = false; + private int m_detailedStatsStep = 0; + public IMesher mesher; private float m_meshLOD; public float MeshLOD @@ -192,6 +194,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters m_meshLOD = 8f; m_sculptLOD = 32f; + m_detailedStatsStep = 0; // disabled + m_maxSubSteps = 10; m_fixedTimeStep = 1f / 60f; m_maxCollisionsPerFrame = 2048; @@ -209,8 +213,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters parms.deactivationTime = 0.2f; parms.linearSleepingThreshold = 0.8f; parms.angularSleepingThreshold = 1.0f; - parms.ccdMotionThreshold = 0.5f; // set to zero to disable - parms.ccdSweptSphereRadius = 0.2f; + parms.ccdMotionThreshold = 0.0f; // set to zero to disable + parms.ccdSweptSphereRadius = 0.0f; + parms.contactProcessingThreshold = 0.1f; parms.terrainFriction = 0.5f; parms.terrainHitFraction = 0.8f; @@ -231,6 +236,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters _meshSculptedPrim = pConfig.GetBoolean("MeshSculptedPrim", _meshSculptedPrim); _forceSimplePrimMeshing = pConfig.GetBoolean("ForceSimplePrimMeshing", _forceSimplePrimMeshing); + m_detailedStatsStep = pConfig.GetInt("DetailedStatsStep", m_detailedStatsStep); m_meshLOD = pConfig.GetFloat("MeshLevelOfDetail", m_meshLOD); m_sculptLOD = pConfig.GetFloat("SculptLevelOfDetail", m_sculptLOD); @@ -253,6 +259,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters parms.angularSleepingThreshold = pConfig.GetFloat("AngularSleepingThreshold", parms.angularSleepingThreshold); parms.ccdMotionThreshold = pConfig.GetFloat("CcdMotionThreshold", parms.ccdMotionThreshold); parms.ccdSweptSphereRadius = pConfig.GetFloat("CcdSweptSphereRadius", parms.ccdSweptSphereRadius); + parms.contactProcessingThreshold = pConfig.GetFloat("ContactProcessingThreshold", parms.contactProcessingThreshold); parms.terrainFriction = pConfig.GetFloat("TerrainFriction", parms.terrainFriction); parms.terrainHitFraction = pConfig.GetFloat("TerrainHitFraction", parms.terrainHitFraction); @@ -398,6 +405,14 @@ public class BSScene : PhysicsScene, IPhysicsParameters } } + if (m_detailedStatsStep > 0) + { + if ((m_simulationStep % m_detailedStatsStep) == 0) + { + BulletSimAPI.DumpBulletStatistics(); + } + } + // TODO: FIX THIS: fps calculation wrong. This calculation always returns about 1 in normal operation. return timeStep / (numSubSteps * m_fixedTimeStep) * 1000f; } @@ -671,6 +686,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters new PhysParameterEntry("MaxSubStep", "In simulation step, maximum number of substeps"), new PhysParameterEntry("FixedTimeStep", "In simulation step, seconds of one substep (1/60)"), new PhysParameterEntry("MaxObjectMass", "Maximum object mass (10000.01)"), + new PhysParameterEntry("DetailedStats", "Frames between outputting detailed phys stats. Zero is off"), new PhysParameterEntry("DefaultFriction", "Friction factor used on new objects"), new PhysParameterEntry("DefaultDensity", "Density for new objects" ), @@ -685,6 +701,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters new PhysParameterEntry("AngularSleepingThreshold", "Seconds to measure angular movement before considering static" ), // new PhysParameterEntry("CcdMotionThreshold", "" ), // new PhysParameterEntry("CcdSweptSphereRadius", "" ), + new PhysParameterEntry("ContactProcessingThreshold", "Distance between contacts before doing collision check" ), new PhysParameterEntry("TerrainFriction", "Factor to reduce movement against terrain surface" ), new PhysParameterEntry("TerrainHitFraction", "Distance to measure hit collisions" ), @@ -715,6 +732,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters string lparm = parm.ToLower(); switch (lparm) { + case "detailedstats": m_detailedStatsStep = (int)val; break; case "meshlod": m_meshLOD = (int)val; break; case "sculptlod": m_sculptLOD = (int)val; break; case "maxsubstep": m_maxSubSteps = (int)val; break; @@ -725,7 +743,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters case "defaultdensity": m_params[0].defaultDensity = val; break; case "defaultrestitution": m_params[0].defaultRestitution = val; break; case "collisionmargin": m_params[0].collisionMargin = val; break; - case "gravity": m_params[0].gravity = val; TaintedUpdateParameter(lparm, PhysParameterEntry.APPLY_TO_NONE, val); break; + case "gravity": m_params[0].gravity = val; TaintedUpdateParameter(lparm, PhysParameterEntry.APPLY_TO_NONE, val); break; case "lineardamping": UpdateParameterPrims(ref m_params[0].linearDamping, lparm, localID, val); break; case "angulardamping": UpdateParameterPrims(ref m_params[0].angularDamping, lparm, localID, val); break; @@ -734,6 +752,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters case "angularsleepingthreshold": UpdateParameterPrims(ref m_params[0].angularDamping, lparm, localID, val); break; case "ccdmotionthreshold": UpdateParameterPrims(ref m_params[0].ccdMotionThreshold, lparm, localID, val); break; case "ccdsweptsphereradius": UpdateParameterPrims(ref m_params[0].ccdSweptSphereRadius, lparm, localID, val); break; + case "contactprocessingthreshold": UpdateParameterPrims(ref m_params[0].contactProcessingThreshold, lparm, localID, val); break; // set a terrain physical feature and cause terrain to be recalculated case "terrainfriction": m_params[0].terrainFriction = val; TaintedUpdateParameter("terrain", 0, val); break; @@ -741,10 +760,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters case "terrainrestitution": m_params[0].terrainRestitution = val; TaintedUpdateParameter("terrain", 0, val); break; // set an avatar physical feature and cause avatar(s) to be recalculated case "avatarfriction": UpdateParameterAvatars(ref m_params[0].avatarFriction, "avatar", localID, val); break; - case "avatardensity": UpdateParameterAvatars(ref m_params[0].avatarDensity, "avatar", localID, val); break; + case "avatardensity": UpdateParameterAvatars(ref m_params[0].avatarDensity, "avatar", localID, val); break; case "avatarrestitution": UpdateParameterAvatars(ref m_params[0].avatarRestitution, "avatar", localID, val); break; - case "avatarcapsuleradius": UpdateParameterAvatars(ref m_params[0].avatarCapsuleRadius, "avatar", localID, val); break; - case "avatarcapsuleheight": UpdateParameterAvatars(ref m_params[0].avatarCapsuleHeight, "avatar", localID, val); break; + case "avatarcapsuleradius": UpdateParameterAvatars(ref m_params[0].avatarCapsuleRadius, "avatar", localID, val); break; + case "avatarcapsuleheight": UpdateParameterAvatars(ref m_params[0].avatarCapsuleHeight, "avatar", localID, val); break; default: ret = false; break; } @@ -816,6 +835,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters bool ret = true; switch (parm.ToLower()) { + case "detailedstats": val = (int)m_detailedStatsStep; break; case "meshlod": val = (float)m_meshLOD; break; case "sculptlod": val = (float)m_sculptLOD; break; case "maxsubstep": val = (float)m_maxSubSteps; break; @@ -835,6 +855,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters case "angularsleepingthreshold": val = m_params[0].angularDamping; break; case "ccdmotionthreshold": val = m_params[0].ccdMotionThreshold; break; case "ccdsweptsphereradius": val = m_params[0].ccdSweptSphereRadius; break; + case "contactprocessingthreshold": val = m_params[0].contactProcessingThreshold; break; case "terrainfriction": val = m_params[0].terrainFriction; break; case "terrainhitfraction": val = m_params[0].terrainHitFraction; break; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index a610c8d..d12bd7d 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -122,6 +122,7 @@ public struct ConfigurationParameters public float angularSleepingThreshold; public float ccdMotionThreshold; public float ccdSweptSphereRadius; + public float contactProcessingThreshold; public float terrainFriction; public float terrainHitFraction; @@ -248,6 +249,9 @@ public static extern RaycastHit RayTest(uint worldID, uint id, Vector3 from, Vec [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern Vector3 RecoverFromPenetration(uint worldID, uint id); +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void DumpBulletStatistics(); + // Log a debug message [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg); diff --git a/bin/BulletSim-x86_64.dll b/bin/BulletSim-x86_64.dll index 6620759..ec21dfe 100755 Binary files a/bin/BulletSim-x86_64.dll and b/bin/BulletSim-x86_64.dll differ diff --git a/bin/BulletSim.dll b/bin/BulletSim.dll index ffb5380..d1571cf 100755 Binary files a/bin/BulletSim.dll and b/bin/BulletSim.dll differ diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index c226fb3..25a8da6 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -842,8 +842,9 @@ DeactivationTime = 0.2 LinearSleepingThreshold = 0.8 AngularSleepingThreshold = 1.0 - CcdMotionThreshold = 0.5 - CcdSweptSphereRadius = 0.2 + CcdMotionThreshold = 0.0 + CcdSweptSphereRadius = 0.0 + ContactProcessingThreshold = 0.1 ; Whether to mesh sculpties MeshSculptedPrim = true diff --git a/bin/libBulletSim-x86_64.so b/bin/libBulletSim-x86_64.so index cd2db40..527eda5 100755 Binary files a/bin/libBulletSim-x86_64.so and b/bin/libBulletSim-x86_64.so differ diff --git a/bin/libBulletSim.so b/bin/libBulletSim.so index 44afb5e..9f91bfd 100755 Binary files a/bin/libBulletSim.so and b/bin/libBulletSim.so differ -- cgit v1.1 From d0536256635008bdeb1a5ded1b06c5f84f02975e Mon Sep 17 00:00:00 2001 From: nebadon Date: Wed, 25 Jan 2012 15:59:07 -0700 Subject: Update save oar and save iar help responses to reflect new -h|--home switches which replace -p|--profile ie: "save oar --home=http://hg.osgrid.org:80 region.oar" --- OpenSim/Region/Application/OpenSim.cs | 4 ++-- .../CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index 832d93c..8683476 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -291,10 +291,10 @@ namespace OpenSim m_console.Commands.AddCommand("region", false, "save oar", //"save oar [-v|--version=] [-p|--profile=] []", - "save oar [-p|--profile=] [--noassets] [--perm=] []", + "save oar [-h|--home=] [--noassets] [--perm=] []", "Save a region's data to an OAR archive.", // "-v|--version= generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine - "-p|--profile= adds the url of the profile service to the saved user information." + Environment.NewLine + "-h|--home= adds the url of the profile service to the saved user information." + Environment.NewLine + "--noassets stops assets being saved to the OAR." + Environment.NewLine + "--perm stops objects with insufficient permissions from being saved to the OAR." + Environment.NewLine + " can contain one or more of these characters: \"C\" = Copy, \"T\" = Transfer" + Environment.NewLine diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs index e0b02aa..150d913 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs @@ -122,12 +122,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver scene.AddCommand( this, "save iar", - "save iar [--p|-profile=] [--noassets] [] [--v|-verbose]", + "save iar [-h|--home=] [--noassets] [] [--v|-verbose]", "Save user inventory archive (IAR).", " is the user's first name." + Environment.NewLine + " is the user's last name." + Environment.NewLine + " is the path inside the user's inventory for the folder/item to be saved." + Environment.NewLine - + "-p|--profile= adds the url of the profile service to the saved user information." + Environment.NewLine + + "-h|--home= adds the url of the profile service to the saved user information." + Environment.NewLine + "-c|--creators preserves information about foreign creators." + Environment.NewLine + "-v|--verbose extra debug messages." + Environment.NewLine + "--noassets stops assets being saved to the IAR." -- cgit v1.1 From 2de3a1b9dad25855cb18a29f2c43ad67cfb0730c Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 25 Jan 2012 23:22:07 +0000 Subject: refactor: decompose most of RezScript() into RezScriptFromAgentInventory(), RezNewScript() and rename one RezScript() to RezScriptFromPrim() --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 174 +++++++++++---------- .../Shared/Api/Implementation/LSL_Api.cs | 3 +- 2 files changed, 97 insertions(+), 80 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 2444367..f4f37ac 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1560,104 +1560,120 @@ namespace OpenSim.Region.Framework.Scenes /// Rez a script into a prim's inventory, either ex nihilo or from an existing avatar inventory /// /// - /// + /// + /// /// public void RezScript(IClientAPI remoteClient, InventoryItemBase itemBase, UUID transactionID, uint localID) { - UUID itemID = itemBase.ID; + if (itemBase.ID != UUID.Zero) + RezScriptFromAgentInventory(remoteClient, itemBase.ID, localID); + else + RezNewScript(remoteClient, itemBase); + } + + /// + /// Rez a script into a prim from an agent inventory. + /// + /// + /// + /// + public void RezScriptFromAgentInventory(IClientAPI remoteClient, UUID fromItemID, uint localID) + { UUID copyID = UUID.Random(); + InventoryItemBase item = new InventoryItemBase(fromItemID, remoteClient.AgentId); + item = InventoryService.GetItem(item); - if (itemID != UUID.Zero) // transferred from an avatar inventory to the prim's inventory + // Try library + // XXX clumsy, possibly should be one call + if (null == item && LibraryService != null && LibraryService.LibraryRootFolder != null) { - InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); - item = InventoryService.GetItem(item); - - // Try library - // XXX clumsy, possibly should be one call - if (null == item && LibraryService != null && LibraryService.LibraryRootFolder != null) - { - item = LibraryService.LibraryRootFolder.FindItem(itemID); - } + item = LibraryService.LibraryRootFolder.FindItem(fromItemID); + } - if (item != null) + if (item != null) + { + SceneObjectPart part = GetSceneObjectPart(localID); + if (part != null) { - SceneObjectPart part = GetSceneObjectPart(localID); - if (part != null) - { - if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId)) - return; + if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId)) + return; - part.ParentGroup.AddInventoryItem(remoteClient, localID, item, copyID); - // TODO: switch to posting on_rez here when scripts - // have state in inventory - part.Inventory.CreateScriptInstance(copyID, 0, false, DefaultScriptEngine, 0); + part.ParentGroup.AddInventoryItem(remoteClient, localID, item, copyID); + // TODO: switch to posting on_rez here when scripts + // have state in inventory + part.Inventory.CreateScriptInstance(copyID, 0, false, DefaultScriptEngine, 0); - // m_log.InfoFormat("[PRIMINVENTORY]: " + - // "Rezzed script {0} into prim local ID {1} for user {2}", - // item.inventoryName, localID, remoteClient.Name); - part.SendPropertiesToClient(remoteClient); - part.ParentGroup.ResumeScripts(); - } - else - { - m_log.ErrorFormat( - "[PRIM INVENTORY]: " + - "Could not rez script {0} into prim local ID {1} for user {2}" - + " because the prim could not be found in the region!", - item.Name, localID, remoteClient.Name); - } + // m_log.InfoFormat("[PRIMINVENTORY]: " + + // "Rezzed script {0} into prim local ID {1} for user {2}", + // item.inventoryName, localID, remoteClient.Name); + part.SendPropertiesToClient(remoteClient); + part.ParentGroup.ResumeScripts(); } else { m_log.ErrorFormat( - "[PRIM INVENTORY]: Could not find script inventory item {0} to rez for {1}!", - itemID, remoteClient.Name); + "[PRIM INVENTORY]: " + + "Could not rez script {0} into prim local ID {1} for user {2}" + + " because the prim could not be found in the region!", + item.Name, localID, remoteClient.Name); } } - else // script has been rezzed directly into a prim's inventory + else { - SceneObjectPart part = GetSceneObjectPart(itemBase.Folder); - if (part == null) - return; + m_log.ErrorFormat( + "[PRIM INVENTORY]: Could not find script inventory item {0} to rez for {1}!", + fromItemID, remoteClient.Name); + } + } - if (!Permissions.CanCreateObjectInventory( - itemBase.InvType, part.UUID, remoteClient.AgentId)) - return; + /// + /// Rez a new script from nothing. + /// + /// + /// + public void RezNewScript(IClientAPI remoteClient, InventoryItemBase itemBase) + { + SceneObjectPart part = GetSceneObjectPart(itemBase.Folder); + if (part == null) + return; - AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, - Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), - remoteClient.AgentId); - AssetService.Store(asset); - - TaskInventoryItem taskItem = new TaskInventoryItem(); - - taskItem.ResetIDs(itemBase.Folder); - taskItem.ParentID = itemBase.Folder; - taskItem.CreationDate = (uint)itemBase.CreationDate; - taskItem.Name = itemBase.Name; - taskItem.Description = itemBase.Description; - taskItem.Type = itemBase.AssetType; - taskItem.InvType = itemBase.InvType; - taskItem.OwnerID = itemBase.Owner; - taskItem.CreatorID = itemBase.CreatorIdAsUuid; - taskItem.BasePermissions = itemBase.BasePermissions; - taskItem.CurrentPermissions = itemBase.CurrentPermissions; - taskItem.EveryonePermissions = itemBase.EveryOnePermissions; - taskItem.GroupPermissions = itemBase.GroupPermissions; - taskItem.NextPermissions = itemBase.NextPermissions; - taskItem.GroupID = itemBase.GroupID; - taskItem.GroupPermissions = 0; - taskItem.Flags = itemBase.Flags; - taskItem.PermsGranter = UUID.Zero; - taskItem.PermsMask = 0; - taskItem.AssetID = asset.FullID; - - part.Inventory.AddInventoryItem(taskItem, false); - part.SendPropertiesToClient(remoteClient); + if (!Permissions.CanCreateObjectInventory( + itemBase.InvType, part.UUID, remoteClient.AgentId)) + return; - part.Inventory.CreateScriptInstance(taskItem, 0, false, DefaultScriptEngine, 0); - part.ParentGroup.ResumeScripts(); - } + AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, + Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), + remoteClient.AgentId); + AssetService.Store(asset); + + TaskInventoryItem taskItem = new TaskInventoryItem(); + + taskItem.ResetIDs(itemBase.Folder); + taskItem.ParentID = itemBase.Folder; + taskItem.CreationDate = (uint)itemBase.CreationDate; + taskItem.Name = itemBase.Name; + taskItem.Description = itemBase.Description; + taskItem.Type = itemBase.AssetType; + taskItem.InvType = itemBase.InvType; + taskItem.OwnerID = itemBase.Owner; + taskItem.CreatorID = itemBase.CreatorIdAsUuid; + taskItem.BasePermissions = itemBase.BasePermissions; + taskItem.CurrentPermissions = itemBase.CurrentPermissions; + taskItem.EveryonePermissions = itemBase.EveryOnePermissions; + taskItem.GroupPermissions = itemBase.GroupPermissions; + taskItem.NextPermissions = itemBase.NextPermissions; + taskItem.GroupID = itemBase.GroupID; + taskItem.GroupPermissions = 0; + taskItem.Flags = itemBase.Flags; + taskItem.PermsGranter = UUID.Zero; + taskItem.PermsMask = 0; + taskItem.AssetID = asset.FullID; + + part.Inventory.AddInventoryItem(taskItem, false); + part.SendPropertiesToClient(remoteClient); + + part.Inventory.CreateScriptInstance(taskItem, 0, false, DefaultScriptEngine, 0); + part.ParentGroup.ResumeScripts(); } /// @@ -1666,7 +1682,7 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// - public void RezScript(UUID srcId, SceneObjectPart srcPart, UUID destId, int pin, int running, int start_param) + public void RezScriptFromPrim(UUID srcId, SceneObjectPart srcPart, UUID destId, int pin, int running, int start_param) { TaskInventoryItem srcTaskItem = srcPart.Inventory.GetInventoryItem(srcId); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 330c65d..6fa812d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -6603,7 +6603,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } // the rest of the permission checks are done in RezScript, so check the pin there as well - World.RezScript(srcId, m_host, destId, pin, running, start_param); + World.RezScriptFromPrim(srcId, m_host, destId, pin, running, start_param); + // this will cause the delay even if the script pin or permissions were wrong - seems ok ScriptSleep(3000); } -- cgit v1.1 From 55c6cbabfd04599030548983f376f60acdf607e7 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 26 Jan 2012 00:10:37 +0000 Subject: refactor: change RezScriptFromAgentInventory(), RezNewScript() and AddInventoryItem() to accept an agent id rather than a full IClientAPI. This stops some code having to make spurious client == null checks and reduces regression test complexity. --- OpenSim/Data/Tests/RegionTests.cs | 12 +++--- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 50 +++++++++++++--------- .../Framework/Scenes/SceneObjectGroup.Inventory.cs | 15 ++----- 3 files changed, 40 insertions(+), 37 deletions(-) diff --git a/OpenSim/Data/Tests/RegionTests.cs b/OpenSim/Data/Tests/RegionTests.cs index 1b93176..1d806fc 100644 --- a/OpenSim/Data/Tests/RegionTests.cs +++ b/OpenSim/Data/Tests/RegionTests.cs @@ -685,7 +685,7 @@ namespace OpenSim.Data.Tests SceneObjectGroup sog = GetMySOG("object1"); InventoryItemBase i = NewItem(item1, zero, zero, itemname1, zero); - Assert.That(sog.AddInventoryItem(null, sog.RootPart.LocalId, i, zero), Is.True); + Assert.That(sog.AddInventoryItem(zero, sog.RootPart.LocalId, i, zero), Is.True); TaskInventoryItem t = sog.GetInventoryItem(sog.RootPart.LocalId, item1); Assert.That(t.Name, Is.EqualTo(itemname1), "Assert.That(t.Name, Is.EqualTo(itemname1))"); @@ -762,7 +762,7 @@ namespace OpenSim.Data.Tests i.CreationDate = creationd; SceneObjectGroup sog = GetMySOG("object1"); - Assert.That(sog.AddInventoryItem(null, sog.RootPart.LocalId, i, zero), Is.True); + Assert.That(sog.AddInventoryItem(zero, sog.RootPart.LocalId, i, zero), Is.True); TaskInventoryItem t = sog.GetInventoryItem(sog.RootPart.LocalId, id); Assert.That(t.Name, Is.EqualTo(name), "Assert.That(t.Name, Is.EqualTo(name))"); @@ -807,10 +807,10 @@ namespace OpenSim.Data.Tests SceneObjectGroup sog = FindSOG("object1", region1); - Assert.That(sog.AddInventoryItem(null, sog.RootPart.LocalId, ib1, zero), Is.True); - Assert.That(sog.AddInventoryItem(null, sog.RootPart.LocalId, ib2, zero), Is.True); - Assert.That(sog.AddInventoryItem(null, sog.RootPart.LocalId, ib3, zero), Is.True); - Assert.That(sog.AddInventoryItem(null, sog.RootPart.LocalId, ib4, zero), Is.True); + Assert.That(sog.AddInventoryItem(zero, sog.RootPart.LocalId, ib1, zero), Is.True); + Assert.That(sog.AddInventoryItem(zero, sog.RootPart.LocalId, ib2, zero), Is.True); + Assert.That(sog.AddInventoryItem(zero, sog.RootPart.LocalId, ib3, zero), Is.True); + Assert.That(sog.AddInventoryItem(zero, sog.RootPart.LocalId, ib4, zero), Is.True); TaskInventoryItem t1 = sog.GetInventoryItem(sog.RootPart.LocalId, i1); Assert.That(t1.Name, Is.EqualTo(ib1.Name), "Assert.That(t1.Name, Is.EqualTo(ib1.Name))"); diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index f4f37ac..9293aeb 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1444,7 +1444,7 @@ namespace OpenSim.Region.Framework.Scenes // If we've found the item in the user's inventory or in the library if (item != null) { - part.ParentGroup.AddInventoryItem(remoteClient, primLocalID, item, copyID); + part.ParentGroup.AddInventoryItem(remoteClient.AgentId, primLocalID, item, copyID); m_log.InfoFormat( "[PRIM INVENTORY]: Update with item {0} requested of prim {1} for {2}", item.Name, primLocalID, remoteClient.Name); @@ -1565,22 +1565,28 @@ namespace OpenSim.Region.Framework.Scenes /// public void RezScript(IClientAPI remoteClient, InventoryItemBase itemBase, UUID transactionID, uint localID) { + SceneObjectPart partWhereRezzed; + if (itemBase.ID != UUID.Zero) - RezScriptFromAgentInventory(remoteClient, itemBase.ID, localID); + partWhereRezzed = RezScriptFromAgentInventory(remoteClient.AgentId, itemBase.ID, localID); else - RezNewScript(remoteClient, itemBase); + partWhereRezzed = RezNewScript(remoteClient.AgentId, itemBase); + + if (partWhereRezzed != null) + partWhereRezzed.SendPropertiesToClient(remoteClient); } /// /// Rez a script into a prim from an agent inventory. /// - /// + /// /// /// - public void RezScriptFromAgentInventory(IClientAPI remoteClient, UUID fromItemID, uint localID) + /// The part where the script was rezzed if successful. False otherwise. + public SceneObjectPart RezScriptFromAgentInventory(UUID agentID, UUID fromItemID, uint localID) { UUID copyID = UUID.Random(); - InventoryItemBase item = new InventoryItemBase(fromItemID, remoteClient.AgentId); + InventoryItemBase item = new InventoryItemBase(fromItemID, agentID); item = InventoryService.GetItem(item); // Try library @@ -1595,10 +1601,10 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart part = GetSceneObjectPart(localID); if (part != null) { - if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId)) - return; + if (!Permissions.CanEditObjectInventory(part.UUID, agentID)) + return null; - part.ParentGroup.AddInventoryItem(remoteClient, localID, item, copyID); + part.ParentGroup.AddInventoryItem(agentID, localID, item, copyID); // TODO: switch to posting on_rez here when scripts // have state in inventory part.Inventory.CreateScriptInstance(copyID, 0, false, DefaultScriptEngine, 0); @@ -1606,8 +1612,9 @@ namespace OpenSim.Region.Framework.Scenes // m_log.InfoFormat("[PRIMINVENTORY]: " + // "Rezzed script {0} into prim local ID {1} for user {2}", // item.inventoryName, localID, remoteClient.Name); - part.SendPropertiesToClient(remoteClient); part.ParentGroup.ResumeScripts(); + + return part; } else { @@ -1615,15 +1622,17 @@ namespace OpenSim.Region.Framework.Scenes "[PRIM INVENTORY]: " + "Could not rez script {0} into prim local ID {1} for user {2}" + " because the prim could not be found in the region!", - item.Name, localID, remoteClient.Name); + item.Name, localID, agentID); } } else { m_log.ErrorFormat( "[PRIM INVENTORY]: Could not find script inventory item {0} to rez for {1}!", - fromItemID, remoteClient.Name); + fromItemID, agentID); } + + return null; } /// @@ -1631,19 +1640,20 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// - public void RezNewScript(IClientAPI remoteClient, InventoryItemBase itemBase) + /// The part where the script was rezzed if successful. False otherwise. + public SceneObjectPart RezNewScript(UUID agentID, InventoryItemBase itemBase) { + // The part ID is the folder ID! SceneObjectPart part = GetSceneObjectPart(itemBase.Folder); if (part == null) - return; + return null; - if (!Permissions.CanCreateObjectInventory( - itemBase.InvType, part.UUID, remoteClient.AgentId)) - return; + if (!Permissions.CanCreateObjectInventory(itemBase.InvType, part.UUID, agentID)) + return null; AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), - remoteClient.AgentId); + agentID); AssetService.Store(asset); TaskInventoryItem taskItem = new TaskInventoryItem(); @@ -1670,10 +1680,10 @@ namespace OpenSim.Region.Framework.Scenes taskItem.AssetID = asset.FullID; part.Inventory.AddInventoryItem(taskItem, false); - part.SendPropertiesToClient(remoteClient); - part.Inventory.CreateScriptInstance(taskItem, 0, false, DefaultScriptEngine, 0); part.ParentGroup.ResumeScripts(); + + return part; } /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs index 905ecc9..f173c95 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs @@ -83,13 +83,12 @@ namespace OpenSim.Region.Framework.Scenes /// /// Add an inventory item from a user's inventory to a prim in this scene object. /// - /// The client adding the item. + /// The agent adding the item. /// The local ID of the part receiving the add. /// The user inventory item being added. /// The item UUID that should be used by the new item. /// - public bool AddInventoryItem(IClientAPI remoteClient, uint localID, - InventoryItemBase item, UUID copyItemID) + public bool AddInventoryItem(UUID agentID, uint localID, InventoryItemBase item, UUID copyItemID) { // m_log.DebugFormat( // "[PRIM INVENTORY]: Adding inventory item {0} from {1} to part with local ID {2}", @@ -111,9 +110,7 @@ namespace OpenSim.Region.Framework.Scenes taskItem.Type = item.AssetType; taskItem.InvType = item.InvType; - if (remoteClient != null && - remoteClient.AgentId != part.OwnerID && - m_scene.Permissions.PropagatePermissions()) + if (agentID != part.OwnerID && m_scene.Permissions.PropagatePermissions()) { taskItem.BasePermissions = item.BasePermissions & item.NextPermissions; @@ -148,11 +145,7 @@ namespace OpenSim.Region.Framework.Scenes // taskItem.SaleType = item.SaleType; taskItem.CreationDate = (uint)item.CreationDate; - bool addFromAllowedDrop = false; - if (remoteClient != null) - { - addFromAllowedDrop = remoteClient.AgentId != part.OwnerID; - } + bool addFromAllowedDrop = agentID != part.OwnerID; part.Inventory.AddInventoryItem(taskItem, addFromAllowedDrop); -- cgit v1.1