diff --git a/OpenSim/Framework/EstateSettings.cs b/OpenSim/Framework/EstateSettings.cs index 98604f27ba..a92abbf026 100644 --- a/OpenSim/Framework/EstateSettings.cs +++ b/OpenSim/Framework/EstateSettings.cs @@ -322,7 +322,7 @@ namespace OpenSim.Framework l_EstateManagers.Remove(avatarID); } - public bool IsEstateManager(UUID avatarID) + public bool IsEstateManagerOrOwner(UUID avatarID) { if (IsEstateOwner(avatarID)) return true; @@ -368,7 +368,7 @@ namespace OpenSim.Framework public bool HasAccess(UUID user) { - if (IsEstateManager(user)) + if (IsEstateManagerOrOwner(user)) return true; return l_EstateAccess.Contains(user); diff --git a/OpenSim/Framework/Tests/MundaneFrameworkTests.cs b/OpenSim/Framework/Tests/MundaneFrameworkTests.cs index 76de6be267..672847dfed 100644 --- a/OpenSim/Framework/Tests/MundaneFrameworkTests.cs +++ b/OpenSim/Framework/Tests/MundaneFrameworkTests.cs @@ -227,10 +227,10 @@ namespace OpenSim.Framework.Tests es.AddEstateManager(UUID.Zero); es.AddEstateManager(bannedUserId); - Assert.IsTrue(es.IsEstateManager(bannedUserId), "bannedUserId should be EstateManager but isn't."); + Assert.IsTrue(es.IsEstateManagerOrOwner(bannedUserId), "bannedUserId should be EstateManager but isn't."); es.RemoveEstateManager(bannedUserId); - Assert.IsFalse(es.IsEstateManager(bannedUserId), "bannedUserID is estateManager but shouldn't be"); + Assert.IsFalse(es.IsEstateManagerOrOwner(bannedUserId), "bannedUserID is estateManager but shouldn't be"); Assert.IsFalse(es.HasAccess(bannedUserId), "bannedUserID has access but shouldn't"); diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs index 124f01c9e5..58bbd2405a 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs @@ -967,7 +967,7 @@ namespace OpenSim.Region.CoreModules.World.Estate { RegionHandshakeArgs args = new RegionHandshakeArgs(); - args.isEstateManager = Scene.RegionInfo.EstateSettings.IsEstateManager(remoteClient.AgentId); + args.isEstateManager = Scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(remoteClient.AgentId); if (Scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero && Scene.RegionInfo.EstateSettings.EstateOwner == remoteClient.AgentId) args.isEstateManager = true; diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index 7f44613d5e..0536f6ec6e 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -469,7 +469,7 @@ namespace OpenSim.Region.CoreModules.World.Land if (m_scene.Permissions.IsAdministrator(avatar)) return false; - if (m_scene.RegionInfo.EstateSettings.IsEstateManager(avatar)) + if (m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(avatar)) return false; if (avatar == LandData.OwnerID) @@ -499,7 +499,7 @@ namespace OpenSim.Region.CoreModules.World.Land if (m_scene.Permissions.IsAdministrator(avatar)) return false; - if (m_scene.RegionInfo.EstateSettings.IsEstateManager(avatar)) + if (m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(avatar)) return false; if (avatar == LandData.OwnerID) diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index f5a5c92c4a..06fea58ea3 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -282,7 +282,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands sb.AppendFormat("Location: {0} @ {1}\n", sop.AbsolutePosition, sop.ParentGroup.Scene.RegionInfo.RegionName); sb.AppendFormat("Parent: {0}", sop.IsRoot ? "Is Root\n" : string.Format("{0} {1}\n", sop.ParentGroup.Name, sop.ParentGroup.UUID)); - sb.AppendFormat("Parts: {0}\n", !sop.IsRoot ? "1" : sop.ParentGroup.PrimCount.ToString());; + sb.AppendFormat("Link number: {0}\n", sop.LinkNum); return sb; } diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index 64759a7e12..2032905c5f 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -503,7 +503,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions { if (user == UUID.Zero) return false; - return m_scene.RegionInfo.EstateSettings.IsEstateManager(user); + return m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(user); } #endregion diff --git a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs new file mode 100644 index 0000000000..baac6e827f --- /dev/null +++ b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs @@ -0,0 +1,48 @@ +/* + * Copyright (c) Contributors + * 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 OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Reflection; +using OpenMetaverse; + +namespace OpenSim.Region.Framework.Interfaces +{ + public delegate void TakeValueCallback(string s); + + public interface IJsonStoreModule + { + bool CreateStore(string value, out UUID result); + bool DestroyStore(UUID storeID); + bool TestPath(UUID storeID, string path, bool useJson); + bool SetValue(UUID storeID, string path, string value, bool useJson); + bool RemoveValue(UUID storeID, string path); + bool GetValue(UUID storeID, string path, bool useJson, out string value); + + void TakeValue(UUID storeID, string path, bool useJson, TakeValueCallback cback); + void ReadValue(UUID storeID, string path, bool useJson, TakeValueCallback cback); + } +} diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 0098addb42..67eb0fe128 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -91,6 +91,9 @@ namespace OpenSim.Region.Framework.Scenes /// protected internal Dictionary SceneObjectGroupsByLocalPartID = new Dictionary(); + /// + /// Lock to prevent object group update, linking and delinking operations from running concurrently. + /// private Object m_updateLock = new Object(); #endregion diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index a49ed13ed2..8e786c150e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1962,6 +1962,10 @@ namespace OpenSim.Region.Framework.Scenes /// /// Link the prims in a given group to this group /// + /// + /// Do not call this method directly - use Scene.LinkObjects() instead to avoid races between threads. + /// FIXME: There are places where scripts call these methods directly without locking. This is a potential race condition. + /// /// The group of prims which should be linked to this group public void LinkToGroup(SceneObjectGroup objectGroup) { @@ -2045,6 +2049,11 @@ namespace OpenSim.Region.Framework.Scenes /// Delink the given prim from this group. The delinked prim is established as /// an independent SceneObjectGroup. /// + /// + /// FIXME: This method should not be called directly since it bypasses update locking, allowing a potential race + /// condition. But currently there is no + /// alternative method that does take a lonk to delink a single prim. + /// /// /// The object group of the newly delinked prim. Null if part could not be found public SceneObjectGroup DelinkFromGroup(uint partID) @@ -2056,6 +2065,11 @@ namespace OpenSim.Region.Framework.Scenes /// Delink the given prim from this group. The delinked prim is established as /// an independent SceneObjectGroup. /// + /// + /// FIXME: This method should not be called directly since it bypasses update locking, allowing a potential race + /// condition. But currently there is no + /// alternative method that does take a lonk to delink a single prim. + /// /// /// /// The object group of the newly delinked prim. Null if part could not be found @@ -2081,6 +2095,11 @@ namespace OpenSim.Region.Framework.Scenes /// Delink the given prim from this group. The delinked prim is established as /// an independent SceneObjectGroup. /// + /// + /// FIXME: This method should not be called directly since it bypasses update locking, allowing a potential race + /// condition. But currently there is no + /// alternative method that does take a lonk to delink a single prim. + /// /// /// /// The object group of the newly delinked prim. diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 641d742f95..b5f789b52a 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -3832,7 +3832,7 @@ namespace OpenSim.Region.Framework.Scenes land.LandData.UserLocation != Vector3.Zero && land.LandData.OwnerID != m_uuid && (!m_scene.Permissions.IsGod(m_uuid)) && - (!m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid))) + (!m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid))) { float curr = Vector3.Distance(AbsolutePosition, pos); if (Vector3.Distance(land.LandData.UserLocation, pos) < curr) @@ -3852,7 +3852,7 @@ namespace OpenSim.Region.Framework.Scenes { if (GodLevel < 200 && ((!m_scene.Permissions.IsGod(m_uuid) && - !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid)) || + !m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid)) || (m_teleportFlags & TeleportFlags.ViaLocation) != 0 || (m_teleportFlags & Constants.TeleportFlags.ViaHGLogin) != 0)) { @@ -3920,7 +3920,7 @@ namespace OpenSim.Region.Framework.Scenes GodLevel < 200 && ((land.LandData.OwnerID != m_uuid && !m_scene.Permissions.IsGod(m_uuid) && - !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid)) || + !m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid)) || (m_teleportFlags & TeleportFlags.ViaLocation) != 0 || (m_teleportFlags & Constants.TeleportFlags.ViaHGLogin) != 0)) { diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs index 19526c02fb..9fea3c63a7 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs @@ -44,24 +44,111 @@ namespace OpenSim.Region.Framework.Scenes.Tests [TestFixture] public class SceneObjectSpatialTests { + TestScene m_scene; + UUID m_ownerId = TestHelpers.ParseTail(0x1); + + [SetUp] + public void SetUp() + { + m_scene = SceneHelpers.SetupScene(); + } + + [Test] + public void TestGetSceneObjectGroupPosition() + { + TestHelpers.InMethod(); + + Vector3 position = new Vector3(10, 20, 30); + + SceneObjectGroup so + = SceneHelpers.CreateSceneObject(1, m_ownerId, "obj1", 0x10); + so.AbsolutePosition = position; + m_scene.AddNewSceneObject(so, false); + + Assert.That(so.AbsolutePosition, Is.EqualTo(position)); + } + [Test] public void TestGetRootPartPosition() { TestHelpers.InMethod(); - Scene scene = SceneHelpers.SetupScene(); - UUID ownerId = TestHelpers.ParseTail(0x1); Vector3 partPosition = new Vector3(10, 20, 30); SceneObjectGroup so - = SceneHelpers.CreateSceneObject(1, ownerId, "obj1", 0x10); + = SceneHelpers.CreateSceneObject(1, m_ownerId, "obj1", 0x10); so.AbsolutePosition = partPosition; - scene.AddNewSceneObject(so, false); + m_scene.AddNewSceneObject(so, false); - Assert.That(so.AbsolutePosition, Is.EqualTo(partPosition)); Assert.That(so.RootPart.AbsolutePosition, Is.EqualTo(partPosition)); - Assert.That(so.RootPart.OffsetPosition, Is.EqualTo(Vector3.Zero)); + Assert.That(so.RootPart.GroupPosition, Is.EqualTo(partPosition)); + Assert.That(so.RootPart.GetWorldPosition(), Is.EqualTo(partPosition)); Assert.That(so.RootPart.RelativePosition, Is.EqualTo(partPosition)); + Assert.That(so.RootPart.OffsetPosition, Is.EqualTo(Vector3.Zero)); + } + + [Test] + public void TestGetChildPartPosition() + { + TestHelpers.InMethod(); + + Vector3 rootPartPosition = new Vector3(10, 20, 30); + Vector3 childOffsetPosition = new Vector3(2, 3, 4); + + SceneObjectGroup so + = SceneHelpers.CreateSceneObject(2, m_ownerId, "obj1", 0x10); + so.AbsolutePosition = rootPartPosition; + so.Parts[1].OffsetPosition = childOffsetPosition; + + m_scene.AddNewSceneObject(so, false); + + // Calculate child absolute position. + Vector3 childPosition = new Vector3(rootPartPosition + childOffsetPosition); + + SceneObjectPart childPart = so.Parts[1]; + Assert.That(childPart.AbsolutePosition, Is.EqualTo(childPosition)); + Assert.That(childPart.GroupPosition, Is.EqualTo(rootPartPosition)); + Assert.That(childPart.GetWorldPosition(), Is.EqualTo(childPosition)); + Assert.That(childPart.RelativePosition, Is.EqualTo(childOffsetPosition)); + Assert.That(childPart.OffsetPosition, Is.EqualTo(childOffsetPosition)); + } + + [Test] + public void TestGetChildPartPositionAfterObjectRotation() + { + TestHelpers.InMethod(); + + Vector3 rootPartPosition = new Vector3(10, 20, 30); + Vector3 childOffsetPosition = new Vector3(2, 3, 4); + + SceneObjectGroup so + = SceneHelpers.CreateSceneObject(2, m_ownerId, "obj1", 0x10); + so.AbsolutePosition = rootPartPosition; + so.Parts[1].OffsetPosition = childOffsetPosition; + + m_scene.AddNewSceneObject(so, false); + + so.UpdateGroupRotationR(Quaternion.CreateFromEulers(0, 0, -90 * Utils.DEG_TO_RAD)); + + // Calculate child absolute position. + Vector3 rotatedChildOffsetPosition + = new Vector3(childOffsetPosition.Y, -childOffsetPosition.X, childOffsetPosition.Z); + + Vector3 childPosition = new Vector3(rootPartPosition + rotatedChildOffsetPosition); + + SceneObjectPart childPart = so.Parts[1]; + + // FIXME: Should be childPosition after rotation? + Assert.That(childPart.AbsolutePosition, Is.EqualTo(rootPartPosition + childOffsetPosition)); + + Assert.That(childPart.GroupPosition, Is.EqualTo(rootPartPosition)); + Assert.That(childPart.GetWorldPosition(), Is.EqualTo(childPosition)); + + // Relative to root part as (0, 0, 0) + Assert.That(childPart.RelativePosition, Is.EqualTo(childOffsetPosition)); + + // Relative to root part as (0, 0, 0) + Assert.That(childPart.OffsetPosition, Is.EqualTo(childOffsetPosition)); } } } \ No newline at end of file diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs new file mode 100644 index 0000000000..34894badf7 --- /dev/null +++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs @@ -0,0 +1,500 @@ +/* + * Copyright (c) Contributors + * 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 OpenSim 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 Mono.Addins; + +using System; +using System.Reflection; +using System.Threading; +using System.Text; +using System.Net; +using System.Net.Sockets; +using log4net; +using Nini.Config; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using System.Collections.Generic; +using System.Text.RegularExpressions; + +namespace OpenSim.Region.OptionalModules.Scripting.JsonStore +{ + public class JsonStore + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private OSD m_ValueStore; + + protected class TakeValueCallbackClass + { + public string Path { get; set; } + public bool UseJson { get; set; } + public TakeValueCallback Callback { get; set; } + + public TakeValueCallbackClass(string spath, bool usejson, TakeValueCallback cback) + { + Path = spath; + UseJson = usejson; + Callback = cback; + } + } + + protected List m_TakeStore; + protected List m_ReadStore; + + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + public JsonStore() : this("") {} + + public JsonStore(string value) + { + m_TakeStore = new List(); + m_ReadStore = new List(); + + if (String.IsNullOrEmpty(value)) + m_ValueStore = new OSDMap(); + else + m_ValueStore = OSDParser.DeserializeJson(value); + } + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + public bool TestPath(string expr, bool useJson) + { + Stack path = ParsePathExpression(expr); + OSD result = ProcessPathExpression(m_ValueStore,path); + + if (result == null) + return false; + + if (useJson || result.Type == OSDType.String) + return true; + + return false; + } + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + public bool GetValue(string expr, out string value, bool useJson) + { + Stack path = ParsePathExpression(expr); + OSD result = ProcessPathExpression(m_ValueStore,path); + return ConvertOutputValue(result,out value,useJson); + } + + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + public bool RemoveValue(string expr) + { + return SetValueFromExpression(expr,null); + } + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + public bool SetValue(string expr, string value, bool useJson) + { + OSD ovalue = useJson ? OSDParser.DeserializeJson(value) : new OSDString(value); + return SetValueFromExpression(expr,ovalue); + } + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + public bool TakeValue(string expr, bool useJson, TakeValueCallback cback) + { + Stack path = ParsePathExpression(expr); + string pexpr = PathExpressionToKey(path); + + OSD result = ProcessPathExpression(m_ValueStore,path); + if (result == null) + { + m_TakeStore.Add(new TakeValueCallbackClass(pexpr,useJson,cback)); + return false; + } + + string value = String.Empty; + if (! ConvertOutputValue(result,out value,useJson)) + { + // the structure does not match the request so i guess we'll wait + m_TakeStore.Add(new TakeValueCallbackClass(pexpr,useJson,cback)); + return false; + } + + SetValueFromExpression(expr,null); + cback(value); + + return true; + } + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + public bool ReadValue(string expr, bool useJson, TakeValueCallback cback) + { + Stack path = ParsePathExpression(expr); + string pexpr = PathExpressionToKey(path); + + OSD result = ProcessPathExpression(m_ValueStore,path); + if (result == null) + { + m_ReadStore.Add(new TakeValueCallbackClass(pexpr,useJson,cback)); + return false; + } + + string value = String.Empty; + if (! ConvertOutputValue(result,out value,useJson)) + { + // the structure does not match the request so i guess we'll wait + m_ReadStore.Add(new TakeValueCallbackClass(pexpr,useJson,cback)); + return false; + } + + cback(value); + + return true; + } + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + protected bool SetValueFromExpression(string expr, OSD ovalue) + { + Stack path = ParsePathExpression(expr); + if (path.Count == 0) + { + m_ValueStore = ovalue; + return true; + } + + string pkey = path.Pop(); + string pexpr = PathExpressionToKey(path); + if (pexpr != "") + pexpr += "."; + + OSD result = ProcessPathExpression(m_ValueStore,path); + if (result == null) + return false; + + Regex aPattern = new Regex("\\[([0-9]+|\\+)\\]"); + MatchCollection amatches = aPattern.Matches(pkey,0); + + if (amatches.Count > 0) + { + if (result.Type != OSDType.Array) + return false; + + OSDArray amap = result as OSDArray; + + Match match = amatches[0]; + GroupCollection groups = match.Groups; + string akey = groups[1].Value; + + if (akey == "+") + { + string npkey = String.Format("[{0}]",amap.Count); + + amap.Add(ovalue); + InvokeNextCallback(pexpr + npkey); + return true; + } + + int aval = Convert.ToInt32(akey); + if (0 <= aval && aval < amap.Count) + { + if (ovalue == null) + amap.RemoveAt(aval); + else + { + amap[aval] = ovalue; + InvokeNextCallback(pexpr + pkey); + } + return true; + } + + return false; + } + + Regex hPattern = new Regex("{([^}]+)}"); + MatchCollection hmatches = hPattern.Matches(pkey,0); + + if (hmatches.Count > 0) + { + Match match = hmatches[0]; + GroupCollection groups = match.Groups; + string hkey = groups[1].Value; + + if (result is OSDMap) + { + OSDMap hmap = result as OSDMap; + if (ovalue != null) + { + hmap[hkey] = ovalue; + InvokeNextCallback(pexpr + pkey); + } + else if (hmap.ContainsKey(hkey)) + hmap.Remove(hkey); + + return true; + } + + return false; + } + + // Shouldn't get here if the path was checked correctly + m_log.WarnFormat("[JsonStore] invalid path expression"); + return false; + } + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + protected bool InvokeNextCallback(string pexpr) + { + // Process all of the reads that match the expression first + List reads = + m_ReadStore.FindAll(delegate(TakeValueCallbackClass tb) { return pexpr.StartsWith(tb.Path); }); + + foreach (TakeValueCallbackClass readcb in reads) + { + m_ReadStore.Remove(readcb); + ReadValue(readcb.Path,readcb.UseJson,readcb.Callback); + } + + // Process one take next + TakeValueCallbackClass takecb = + m_TakeStore.Find(delegate(TakeValueCallbackClass tb) { return pexpr.StartsWith(tb.Path); }); + + if (takecb != null) + { + m_TakeStore.Remove(takecb); + TakeValue(takecb.Path,takecb.UseJson,takecb.Callback); + + return true; + } + + return false; + } + + // ----------------------------------------------------------------- + /// + /// Parse the path expression and put the components into a stack. We + /// use a stack because we process the path in inverse order later + /// + // ----------------------------------------------------------------- + protected static Stack ParsePathExpression(string path) + { + Stack m_path = new Stack(); + + // add front and rear separators + path = "." + path + "."; + + // add separators for quoted paths + Regex pass1 = new Regex("{[^}]+}"); + path = pass1.Replace(path,".$0.",-1,0); + + // add separators for array references + Regex pass2 = new Regex("(\\[[0-9]+\\]|\\[\\+\\])"); + path = pass2.Replace(path,".$0.",-1,0); + + // add quotes to bare identifier + Regex pass3 = new Regex("\\.([a-zA-Z]+)"); + path = pass3.Replace(path,".{$1}",-1,0); + + // remove extra separators + Regex pass4 = new Regex("\\.+"); + path = pass4.Replace(path,".",-1,0); + + Regex validate = new Regex("^\\.(({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])\\.)+$"); + if (validate.IsMatch(path)) + { + Regex parser = new Regex("\\.({[^}]+}|\\[[0-9]+\\]|\\[\\+\\]+)"); + MatchCollection matches = parser.Matches(path,0); + foreach (Match match in matches) + m_path.Push(match.Groups[1].Value); + } + + return m_path; + } + + // ----------------------------------------------------------------- + /// + /// + /// + /// path is a stack where the top level of the path is at the bottom of the stack + // ----------------------------------------------------------------- + protected static OSD ProcessPathExpression(OSD map, Stack path) + { + if (path.Count == 0) + return map; + + string pkey = path.Pop(); + + OSD rmap = ProcessPathExpression(map,path); + if (rmap == null) + return null; + + // ---------- Check for an array index ---------- + Regex aPattern = new Regex("\\[([0-9]+)\\]"); + MatchCollection amatches = aPattern.Matches(pkey,0); + + if (amatches.Count > 0) + { + if (rmap.Type != OSDType.Array) + { + m_log.WarnFormat("[JsonStore] wrong type for key {2}, expecting {0}, got {1}",OSDType.Array,rmap.Type,pkey); + return null; + } + + OSDArray amap = rmap as OSDArray; + + Match match = amatches[0]; + GroupCollection groups = match.Groups; + string akey = groups[1].Value; + int aval = Convert.ToInt32(akey); + + if (aval < amap.Count) + return (OSD) amap[aval]; + + return null; + } + + // ---------- Check for a hash index ---------- + Regex hPattern = new Regex("{([^}]+)}"); + MatchCollection hmatches = hPattern.Matches(pkey,0); + + if (hmatches.Count > 0) + { + if (rmap.Type != OSDType.Map) + { + m_log.WarnFormat("[JsonStore] wrong type for key {2}, expecting {0}, got {1}",OSDType.Map,rmap.Type,pkey); + return null; + } + + OSDMap hmap = rmap as OSDMap; + + Match match = hmatches[0]; + GroupCollection groups = match.Groups; + string hkey = groups[1].Value; + + if (hmap.ContainsKey(hkey)) + return (OSD) hmap[hkey]; + + return null; + } + + // Shouldn't get here if the path was checked correctly + m_log.WarnFormat("[JsonStore] Path type (unknown) does not match the structure"); + return null; + } + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + protected static bool ConvertOutputValue(OSD result, out string value, bool useJson) + { + value = String.Empty; + + // If we couldn't process the path + if (result == null) + return false; + + if (useJson) + { + // The path pointed to an intermediate hash structure + if (result.Type == OSDType.Map) + { + value = OSDParser.SerializeJsonString(result as OSDMap); + return true; + } + + // The path pointed to an intermediate hash structure + if (result.Type == OSDType.Array) + { + value = OSDParser.SerializeJsonString(result as OSDArray); + return true; + } + + value = "'" + result.AsString() + "'"; + return true; + } + + if (result.Type == OSDType.String) + { + value = result.AsString(); + return true; + } + + return false; + } + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + protected static string PathExpressionToKey(Stack path) + { + if (path.Count == 0) + return ""; + + string pkey = ""; + foreach (string k in path) + pkey = (pkey == "") ? k : (k + "." + pkey); + + return pkey; + } + } +} diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs new file mode 100644 index 0000000000..311531c8d4 --- /dev/null +++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs @@ -0,0 +1,430 @@ +/* + * Copyright (c) Contributors + * 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 OpenSim 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 Mono.Addins; + +using System; +using System.Reflection; +using System.Threading; +using System.Text; +using System.Net; +using System.Net.Sockets; +using log4net; +using Nini.Config; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using System.Collections.Generic; +using System.Text.RegularExpressions; + + +namespace OpenSim.Region.OptionalModules.Scripting.JsonStore +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "JsonStoreModule")] + + public class JsonStoreModule : INonSharedRegionModule, IJsonStoreModule + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private IConfig m_config = null; + private bool m_enabled = false; + private Scene m_scene = null; + + private Dictionary m_JsonValueStore; + private UUID m_sharedStore; + +#region IRegionModule Members + + // ----------------------------------------------------------------- + /// + /// Name of this shared module is it's class name + /// + // ----------------------------------------------------------------- + public string Name + { + get { return this.GetType().Name; } + } + + // ----------------------------------------------------------------- + /// + /// Initialise this shared module + /// + /// this region is getting initialised + /// nini config, we are not using this + // ----------------------------------------------------------------- + public void Initialise(IConfigSource config) + { + try + { + if ((m_config = config.Configs["JsonStore"]) == null) + { + // There is no configuration, the module is disabled + // m_log.InfoFormat("[JsonStore] no configuration info"); + return; + } + + m_enabled = m_config.GetBoolean("Enabled", m_enabled); + } + catch (Exception e) + { + m_log.ErrorFormat("[JsonStore] initialization error: {0}",e.Message); + return; + } + + if (m_enabled) + m_log.DebugFormat("[JsonStore] module is enabled"); + } + + // ----------------------------------------------------------------- + /// + /// everything is loaded, perform post load configuration + /// + // ----------------------------------------------------------------- + public void PostInitialise() + { + } + + // ----------------------------------------------------------------- + /// + /// Nothing to do on close + /// + // ----------------------------------------------------------------- + public void Close() + { + } + + // ----------------------------------------------------------------- + /// + /// + // ----------------------------------------------------------------- + public void AddRegion(Scene scene) + { + if (m_enabled) + { + m_scene = scene; + m_scene.RegisterModuleInterface(this); + + m_sharedStore = UUID.Zero; + m_JsonValueStore = new Dictionary(); + m_JsonValueStore.Add(m_sharedStore,new JsonStore("")); + } + } + + // ----------------------------------------------------------------- + /// + /// + // ----------------------------------------------------------------- + public void RemoveRegion(Scene scene) + { + // need to remove all references to the scene in the subscription + // list to enable full garbage collection of the scene object + } + + // ----------------------------------------------------------------- + /// + /// Called when all modules have been added for a region. This is + /// where we hook up events + /// + // ----------------------------------------------------------------- + public void RegionLoaded(Scene scene) + { + if (m_enabled) {} + } + + /// ----------------------------------------------------------------- + /// + /// + // ----------------------------------------------------------------- + public Type ReplaceableInterface + { + get { return null; } + } + +#endregion + +#region ScriptInvocationInteface + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + public bool CreateStore(string value, out UUID result) + { + result = UUID.Zero; + + if (! m_enabled) return false; + + UUID uuid = UUID.Random(); + JsonStore map = null; + + try + { + map = new JsonStore(value); + } + catch (Exception e) + { + m_log.InfoFormat("[JsonStore] Unable to initialize store from {0}; {1}",value,e.Message); + return false; + } + + lock (m_JsonValueStore) + m_JsonValueStore.Add(uuid,map); + + result = uuid; + return true; + } + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + public bool DestroyStore(UUID storeID) + { + if (! m_enabled) return false; + + lock (m_JsonValueStore) + m_JsonValueStore.Remove(storeID); + + return true; + } + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + public bool TestPath(UUID storeID, string path, bool useJson) + { + if (! m_enabled) return false; + + JsonStore map = null; + lock (m_JsonValueStore) + { + if (! m_JsonValueStore.TryGetValue(storeID,out map)) + { + m_log.InfoFormat("[JsonStore] Missing store {0}",storeID); + return true; + } + } + + try + { + lock (map) + return map.TestPath(path,useJson); + } + catch (Exception e) + { + m_log.InfoFormat("[JsonStore] Path test failed for {0} in {1}; {2}",path,storeID,e.Message); + } + + return false; + } + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + public bool SetValue(UUID storeID, string path, string value, bool useJson) + { + if (! m_enabled) return false; + + JsonStore map = null; + lock (m_JsonValueStore) + { + if (! m_JsonValueStore.TryGetValue(storeID,out map)) + { + m_log.InfoFormat("[JsonStore] Missing store {0}",storeID); + return false; + } + } + + try + { + lock (map) + if (map.SetValue(path,value,useJson)) + return true; + } + catch (Exception e) + { + m_log.InfoFormat("[JsonStore] Unable to assign {0} to {1} in {2}; {3}",value,path,storeID,e.Message); + } + + return false; + } + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + public bool RemoveValue(UUID storeID, string path) + { + if (! m_enabled) return false; + + JsonStore map = null; + lock (m_JsonValueStore) + { + if (! m_JsonValueStore.TryGetValue(storeID,out map)) + { + m_log.InfoFormat("[JsonStore] Missing store {0}",storeID); + return false; + } + } + + try + { + lock (map) + if (map.RemoveValue(path)) + return true; + } + catch (Exception e) + { + m_log.InfoFormat("[JsonStore] Unable to remove {0} in {1}; {2}",path,storeID,e.Message); + } + + return false; + } + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + public bool GetValue(UUID storeID, string path, bool useJson, out string value) + { + value = String.Empty; + + if (! m_enabled) return false; + + JsonStore map = null; + lock (m_JsonValueStore) + { + if (! m_JsonValueStore.TryGetValue(storeID,out map)) + return false; + } + + try + { + lock (map) + { + return map.GetValue(path, out value, useJson); + } + } + catch (Exception e) + { + m_log.InfoFormat("[JsonStore] unable to retrieve value; {0}",e.Message); + } + + return false; + } + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + public void TakeValue(UUID storeID, string path, bool useJson, TakeValueCallback cback) + { + if (! m_enabled) + { + cback(String.Empty); + return; + } + + JsonStore map = null; + lock (m_JsonValueStore) + { + if (! m_JsonValueStore.TryGetValue(storeID,out map)) + { + cback(String.Empty); + return; + } + } + + try + { + lock (map) + { + map.TakeValue(path, useJson, cback); + return; + } + } + catch (Exception e) + { + m_log.InfoFormat("[JsonStore] unable to retrieve value; {0}",e.ToString()); + } + + cback(String.Empty); + } + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + public void ReadValue(UUID storeID, string path, bool useJson, TakeValueCallback cback) + { + if (! m_enabled) + { + cback(String.Empty); + return; + } + + JsonStore map = null; + lock (m_JsonValueStore) + { + if (! m_JsonValueStore.TryGetValue(storeID,out map)) + { + cback(String.Empty); + return; + } + } + + try + { + lock (map) + { + map.ReadValue(path, useJson, cback); + return; + } + } + catch (Exception e) + { + m_log.InfoFormat("[JsonStore] unable to retrieve value; {0}",e.ToString()); + } + + cback(String.Empty); + } + +#endregion + } +} diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs new file mode 100644 index 0000000000..eda2aef9ed --- /dev/null +++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs @@ -0,0 +1,490 @@ +/* + * Copyright (c) Contributors + * 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 OpenSim 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 Mono.Addins; + +using System; +using System.Reflection; +using System.Threading; +using System.Text; +using System.Net; +using System.Net.Sockets; +using log4net; +using Nini.Config; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using System.Collections.Generic; +using System.Text.RegularExpressions; + +namespace OpenSim.Region.OptionalModules.Scripting.JsonStore +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "JsonStoreScriptModule")] + + public class JsonStoreScriptModule : INonSharedRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private IConfig m_config = null; + private bool m_enabled = false; + private Scene m_scene = null; + + private IScriptModuleComms m_comms; + private IJsonStoreModule m_store; + +#region IRegionModule Members + + // ----------------------------------------------------------------- + /// + /// Name of this shared module is it's class name + /// + // ----------------------------------------------------------------- + public string Name + { + get { return this.GetType().Name; } + } + + // ----------------------------------------------------------------- + /// + /// Initialise this shared module + /// + /// this region is getting initialised + /// nini config, we are not using this + // ----------------------------------------------------------------- + public void Initialise(IConfigSource config) + { + try + { + if ((m_config = config.Configs["JsonStore"]) == null) + { + // There is no configuration, the module is disabled + // m_log.InfoFormat("[JsonStoreScripts] no configuration info"); + return; + } + + m_enabled = m_config.GetBoolean("Enabled", m_enabled); + } + catch (Exception e) + { + m_log.ErrorFormat("[JsonStoreScripts] initialization error: {0}",e.Message); + return; + } + + if (m_enabled) + m_log.DebugFormat("[JsonStoreScripts] module is enabled"); + } + + // ----------------------------------------------------------------- + /// + /// everything is loaded, perform post load configuration + /// + // ----------------------------------------------------------------- + public void PostInitialise() + { + } + + // ----------------------------------------------------------------- + /// + /// Nothing to do on close + /// + // ----------------------------------------------------------------- + public void Close() + { + } + + // ----------------------------------------------------------------- + /// + /// + // ----------------------------------------------------------------- + public void AddRegion(Scene scene) + { + } + + // ----------------------------------------------------------------- + /// + /// + // ----------------------------------------------------------------- + public void RemoveRegion(Scene scene) + { + // need to remove all references to the scene in the subscription + // list to enable full garbage collection of the scene object + } + + // ----------------------------------------------------------------- + /// + /// Called when all modules have been added for a region. This is + /// where we hook up events + /// + // ----------------------------------------------------------------- + public void RegionLoaded(Scene scene) + { + if (m_enabled) + { + m_scene = scene; + m_comms = m_scene.RequestModuleInterface(); + if (m_comms == null) + { + m_log.ErrorFormat("[JsonStoreScripts] ScriptModuleComms interface not defined"); + m_enabled = false; + return; + } + + m_store = m_scene.RequestModuleInterface(); + if (m_store == null) + { + m_log.ErrorFormat("[JsonStoreScripts] JsonModule interface not defined"); + m_enabled = false; + return; + } + + m_comms.RegisterScriptInvocation(this,"JsonCreateStore"); + m_comms.RegisterScriptInvocation(this,"JsonDestroyStore"); + + m_comms.RegisterScriptInvocation(this,"JsonReadNotecard"); + m_comms.RegisterScriptInvocation(this,"JsonWriteNotecard"); + + m_comms.RegisterScriptInvocation(this,"JsonTestPath"); + m_comms.RegisterScriptInvocation(this,"JsonTestPathJson"); + + m_comms.RegisterScriptInvocation(this,"JsonGetValue"); + m_comms.RegisterScriptInvocation(this,"JsonGetValueJson"); + + m_comms.RegisterScriptInvocation(this,"JsonTakeValue"); + m_comms.RegisterScriptInvocation(this,"JsonTakeValueJson"); + + m_comms.RegisterScriptInvocation(this,"JsonReadValue"); + m_comms.RegisterScriptInvocation(this,"JsonReadValueJson"); + + m_comms.RegisterScriptInvocation(this,"JsonSetValue"); + m_comms.RegisterScriptInvocation(this,"JsonSetValueJson"); + + m_comms.RegisterScriptInvocation(this,"JsonRemoveValue"); + } + } + + /// ----------------------------------------------------------------- + /// + /// + // ----------------------------------------------------------------- + public Type ReplaceableInterface + { + get { return null; } + } + +#endregion + +#region ScriptInvocationInteface + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + protected void GenerateRuntimeError(string msg) + { + throw new Exception("JsonStore Runtime Error: " + msg); + } + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + protected UUID JsonCreateStore(UUID hostID, UUID scriptID, string value) + { + UUID uuid = UUID.Zero; + if (! m_store.CreateStore(value, out uuid)) + GenerateRuntimeError("Failed to create Json store"); + + return uuid; + } + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + protected int JsonDestroyStore(UUID hostID, UUID scriptID, UUID storeID) + { + return m_store.DestroyStore(storeID) ? 1 : 0; + } + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + protected UUID JsonReadNotecard(UUID hostID, UUID scriptID, UUID storeID, string path, UUID assetID) + { + UUID reqID = UUID.Random(); + Util.FireAndForget(delegate(object o) { DoJsonReadNotecard(reqID,hostID,scriptID,storeID,path,assetID); }); + return reqID; + } + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + protected UUID JsonWriteNotecard(UUID hostID, UUID scriptID, UUID storeID, string path, string name) + { + UUID reqID = UUID.Random(); + Util.FireAndForget(delegate(object o) { DoJsonWriteNotecard(reqID,hostID,scriptID,storeID,path,name); }); + return reqID; + } + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + protected int JsonTestPath(UUID hostID, UUID scriptID, UUID storeID, string path) + { + return m_store.TestPath(storeID,path,false) ? 1 : 0; + } + + protected int JsonTestPathJson(UUID hostID, UUID scriptID, UUID storeID, string path) + { + return m_store.TestPath(storeID,path,true) ? 1 : 0; + } + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + protected int JsonSetValue(UUID hostID, UUID scriptID, UUID storeID, string path, string value) + { + return m_store.SetValue(storeID,path,value,false) ? 1 : 0; + } + + protected int JsonSetValueJson(UUID hostID, UUID scriptID, UUID storeID, string path, string value) + { + return m_store.SetValue(storeID,path,value,true) ? 1 : 0; + } + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + protected int JsonRemoveValue(UUID hostID, UUID scriptID, UUID storeID, string path) + { + return m_store.RemoveValue(storeID,path) ? 1 : 0; + } + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + protected string JsonGetValue(UUID hostID, UUID scriptID, UUID storeID, string path) + { + string value = String.Empty; + m_store.GetValue(storeID,path,false,out value); + return value; + } + + protected string JsonGetValueJson(UUID hostID, UUID scriptID, UUID storeID, string path) + { + string value = String.Empty; + m_store.GetValue(storeID,path,true, out value); + return value; + } + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + protected UUID JsonTakeValue(UUID hostID, UUID scriptID, UUID storeID, string path) + { + UUID reqID = UUID.Random(); + Util.FireAndForget(delegate(object o) { DoJsonTakeValue(scriptID,reqID,storeID,path,false); }); + return reqID; + } + + protected UUID JsonTakeValueJson(UUID hostID, UUID scriptID, UUID storeID, string path) + { + UUID reqID = UUID.Random(); + Util.FireAndForget(delegate(object o) { DoJsonTakeValue(scriptID,reqID,storeID,path,true); }); + return reqID; + } + + private void DoJsonTakeValue(UUID scriptID, UUID reqID, UUID storeID, string path, bool useJson) + { + try + { + m_store.TakeValue(storeID,path,useJson,delegate(string value) { DispatchValue(scriptID,reqID,value); }); + return; + } + catch (Exception e) + { + m_log.InfoFormat("[JsonStoreScripts] unable to retrieve value; {0}",e.ToString()); + } + + DispatchValue(scriptID,reqID,String.Empty); + } + + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + protected UUID JsonReadValue(UUID hostID, UUID scriptID, UUID storeID, string path) + { + UUID reqID = UUID.Random(); + Util.FireAndForget(delegate(object o) { DoJsonReadValue(scriptID,reqID,storeID,path,false); }); + return reqID; + } + + protected UUID JsonReadValueJson(UUID hostID, UUID scriptID, UUID storeID, string path) + { + UUID reqID = UUID.Random(); + Util.FireAndForget(delegate(object o) { DoJsonReadValue(scriptID,reqID,storeID,path,true); }); + return reqID; + } + + private void DoJsonReadValue(UUID scriptID, UUID reqID, UUID storeID, string path, bool useJson) + { + try + { + m_store.ReadValue(storeID,path,useJson,delegate(string value) { DispatchValue(scriptID,reqID,value); }); + return; + } + catch (Exception e) + { + m_log.InfoFormat("[JsonStoreScripts] unable to retrieve value; {0}",e.ToString()); + } + + DispatchValue(scriptID,reqID,String.Empty); + } + +#endregion + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + protected void DispatchValue(UUID scriptID, UUID reqID, string value) + { + m_comms.DispatchReply(scriptID,1,value,reqID.ToString()); + } + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + private void DoJsonReadNotecard(UUID reqID, UUID hostID, UUID scriptID, UUID storeID, string path, UUID assetID) + { + AssetBase a = m_scene.AssetService.Get(assetID.ToString()); + if (a == null) + GenerateRuntimeError(String.Format("Unable to find notecard asset {0}",assetID)); + + if (a.Type != (sbyte)AssetType.Notecard) + GenerateRuntimeError(String.Format("Invalid notecard asset {0}",assetID)); + + m_log.DebugFormat("[JsonStoreScripts] read notecard in context {0}",storeID); + + try + { + System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding(); + string jsondata = SLUtil.ParseNotecardToString(enc.GetString(a.Data)); + int result = m_store.SetValue(storeID,path,jsondata,true) ? 1 : 0; + m_comms.DispatchReply(scriptID,result,"",reqID.ToString()); + return; + } + catch (Exception e) + { + m_log.WarnFormat("[JsonStoreScripts] Json parsing failed; {0}",e.Message); + } + + GenerateRuntimeError(String.Format("Json parsing failed for {0}",assetID.ToString())); + m_comms.DispatchReply(scriptID,0,"",reqID.ToString()); + } + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + private void DoJsonWriteNotecard(UUID reqID, UUID hostID, UUID scriptID, UUID storeID, string path, string name) + { + string data; + if (! m_store.GetValue(storeID,path,true, out data)) + { + m_comms.DispatchReply(scriptID,0,UUID.Zero.ToString(),reqID.ToString()); + return; + } + + SceneObjectPart host = m_scene.GetSceneObjectPart(hostID); + + // Create new asset + UUID assetID = UUID.Random(); + AssetBase asset = new AssetBase(assetID, name, (sbyte)AssetType.Notecard, host.OwnerID.ToString()); + asset.Description = "Json store"; + + int textLength = data.Length; + data = "Linden text version 2\n{\nLLEmbeddedItems version 1\n{\ncount 0\n}\nText length " + + textLength.ToString() + "\n" + data + "}\n"; + + asset.Data = Util.UTF8.GetBytes(data); + m_scene.AssetService.Store(asset); + + // Create Task Entry + TaskInventoryItem taskItem = new TaskInventoryItem(); + + taskItem.ResetIDs(host.UUID); + taskItem.ParentID = host.UUID; + taskItem.CreationDate = (uint)Util.UnixTimeSinceEpoch(); + taskItem.Name = asset.Name; + taskItem.Description = asset.Description; + taskItem.Type = (int)AssetType.Notecard; + taskItem.InvType = (int)InventoryType.Notecard; + taskItem.OwnerID = host.OwnerID; + taskItem.CreatorID = host.OwnerID; + taskItem.BasePermissions = (uint)PermissionMask.All; + taskItem.CurrentPermissions = (uint)PermissionMask.All; + taskItem.EveryonePermissions = 0; + taskItem.NextPermissions = (uint)PermissionMask.All; + taskItem.GroupID = host.GroupID; + taskItem.GroupPermissions = 0; + taskItem.Flags = 0; + taskItem.PermsGranter = UUID.Zero; + taskItem.PermsMask = 0; + taskItem.AssetID = asset.FullID; + + host.Inventory.AddInventoryItem(taskItem, false); + + m_comms.DispatchReply(scriptID,1,assetID.ToString(),reqID.ToString()); + } + } +} diff --git a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs index cab30dec25..74a85e2cd5 100644 --- a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs @@ -38,7 +38,7 @@ using OpenMetaverse; using System.Linq; using System.Linq.Expressions; -namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms +namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms { [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ScriptModuleCommsModule")] class ScriptModuleCommsModule : INonSharedRegionModule, IScriptModuleComms diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index a19427da73..36c9d5e74e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -9255,7 +9255,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // child agents have a mass of 1.0 return 1; else - return (double)avatar.PhysicsActor.Mass; + return (double)avatar.GetMass(); } catch (KeyNotFoundException) { @@ -10887,7 +10887,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api bool isAccount = false; bool isGroup = false; - if (!estate.IsEstateOwner(m_host.OwnerID) || !estate.IsEstateManager(m_host.OwnerID)) + if (!estate.IsEstateOwner(m_host.OwnerID) || !estate.IsEstateManagerOrOwner(m_host.OwnerID)) return 0; UUID id = new UUID(); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs index 77a784d077..df20126ff2 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs @@ -449,7 +449,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api LSShoutError("LightShare functions are not enabled."); return 0; } - if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) + if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) { LSShoutError("lsSetWindlightScene can only be used by estate managers or owners."); return 0; @@ -477,7 +477,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api LSShoutError("LightShare functions are not enabled."); return; } - if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) + if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) { LSShoutError("lsSetWindlightScene can only be used by estate managers or owners."); return; @@ -500,7 +500,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api LSShoutError("LightShare functions are not enabled."); return 0; } - if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) + if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) { LSShoutError("lsSetWindlightSceneTargeted can only be used by estate managers or owners."); return 0; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 2680ad0667..fe94b79b74 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -369,7 +369,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (m_FunctionPerms[function].AllowedOwnerClasses.Contains("ESTATE_MANAGER")) { //Only Estate Managers may use the function - if (World.RegionInfo.EstateSettings.IsEstateManager(ownerID) && World.RegionInfo.EstateSettings.EstateOwner != ownerID) + if (World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(ownerID) && World.RegionInfo.EstateSettings.EstateOwner != ownerID) { return; } diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index b7903d5a20..ad2f12e2ed 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -1021,11 +1021,18 @@ namespace OpenSim.Region.ScriptEngine.XEngine AppDomain sandbox; if (m_AppDomainLoading) + { sandbox = AppDomain.CreateDomain( m_Scene.RegionInfo.RegionID.ToString(), evidence, appSetup); + m_AppDomains[appDomain].AssemblyResolve += + new ResolveEventHandler( + AssemblyResolver.OnAssemblyResolve); + } else + { sandbox = AppDomain.CurrentDomain; + } //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); @@ -1037,9 +1044,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine m_AppDomains[appDomain] = sandbox; - m_AppDomains[appDomain].AssemblyResolve += - new ResolveEventHandler( - AssemblyResolver.OnAssemblyResolve); m_DomainScripts[appDomain] = new List(); } catch (Exception e) @@ -1984,4 +1988,4 @@ namespace OpenSim.Region.ScriptEngine.XEngine // m_log.DebugFormat("[XEngine]: Could not find script with ID {0} to resume", itemID); } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/UserStatistics/WebStatsModule.cs b/OpenSim/Region/UserStatistics/WebStatsModule.cs index b9ba4bc797..4248035904 100644 --- a/OpenSim/Region/UserStatistics/WebStatsModule.cs +++ b/OpenSim/Region/UserStatistics/WebStatsModule.cs @@ -90,7 +90,7 @@ namespace OpenSim.Region.UserStatistics dbConn = new SqliteConnection("URI=file:LocalUserStatistics.db,version=3"); dbConn.Open(); - CheckAndUpdateDatabase(dbConn); + CreateTables(dbConn); Prototype_distributor protodep = new Prototype_distributor(); Updater_distributor updatedep = new Updater_distributor(); @@ -131,7 +131,7 @@ namespace OpenSim.Region.UserStatistics } } - public void ReceiveClassicSimStatsPacket(SimStats stats) + private void ReceiveClassicSimStatsPacket(SimStats stats) { if (!enabled) { @@ -163,7 +163,7 @@ namespace OpenSim.Region.UserStatistics } } - public Hashtable HandleUnknownCAPSRequest(Hashtable request) + private Hashtable HandleUnknownCAPSRequest(Hashtable request) { //string regpath = request["uri"].ToString(); int response_code = 200; @@ -178,7 +178,7 @@ namespace OpenSim.Region.UserStatistics return responsedata; } - public Hashtable HandleStatsRequest(Hashtable request) + private Hashtable HandleStatsRequest(Hashtable request) { lastHit = System.Environment.TickCount; Hashtable responsedata = new Hashtable(); @@ -237,36 +237,12 @@ namespace OpenSim.Region.UserStatistics return responsedata; } - - public void CheckAndUpdateDatabase(SqliteConnection db) - { - lock (db) - { - // TODO: FIXME: implement stats migrations - const string SQL = @"SELECT * FROM migrations LIMIT 1"; - using (SqliteCommand cmd = new SqliteCommand(SQL, db)) - { - try - { - cmd.ExecuteNonQuery(); - } - catch (SqliteSyntaxException) - { - CreateTables(db); - } - } - } - } - - public void CreateTables(SqliteConnection db) + private void CreateTables(SqliteConnection db) { using (SqliteCommand createcmd = new SqliteCommand(SQL_STATS_TABLE_CREATE, db)) { createcmd.ExecuteNonQuery(); - - createcmd.CommandText = SQL_MIGRA_TABLE_CREATE; - createcmd.ExecuteNonQuery(); } } @@ -301,7 +277,7 @@ namespace OpenSim.Region.UserStatistics get { return true; } } - public void OnRegisterCaps(UUID agentID, Caps caps) + private void OnRegisterCaps(UUID agentID, Caps caps) { // m_log.DebugFormat("[WEB STATS MODULE]: OnRegisterCaps: agentID {0} caps {1}", agentID, caps); @@ -316,7 +292,7 @@ namespace OpenSim.Region.UserStatistics })); } - public void OnDeRegisterCaps(UUID agentID, Caps caps) + private void OnDeRegisterCaps(UUID agentID, Caps caps) { } @@ -336,7 +312,7 @@ namespace OpenSim.Region.UserStatistics } } - public void OnMakeRootAgent(ScenePresence agent) + private void OnMakeRootAgent(ScenePresence agent) { UUID regionUUID = GetRegionUUIDFromHandle(agent.RegionHandle); @@ -365,11 +341,11 @@ namespace OpenSim.Region.UserStatistics } } - public void OnMakeChildAgent(ScenePresence agent) + private void OnMakeChildAgent(ScenePresence agent) { } - public void OnClientClosed(UUID agentID, Scene scene) + private void OnClientClosed(UUID agentID, Scene scene) { lock (m_sessions) { @@ -380,7 +356,7 @@ namespace OpenSim.Region.UserStatistics } } - public string readLogLines(int amount) + private string readLogLines(int amount) { Encoding encoding = Encoding.ASCII; int sizeOfChar = encoding.GetByteCount("\n"); @@ -418,7 +394,7 @@ namespace OpenSim.Region.UserStatistics return encoding.GetString(buffer); } - public UUID GetRegionUUIDFromHandle(ulong regionhandle) + private UUID GetRegionUUIDFromHandle(ulong regionhandle) { lock (m_scenes) { @@ -441,17 +417,17 @@ namespace OpenSim.Region.UserStatistics /// /// /// - public string ViewerStatsReport(string request, string path, string param, + private string ViewerStatsReport(string request, string path, string param, UUID agentID, Caps caps) { // m_log.DebugFormat("[WEB STATS MODULE]: Received viewer starts report from {0}", agentID); - UpdateUserStats(ParseViewerStats(request,agentID), dbConn); + UpdateUserStats(ParseViewerStats(request, agentID), dbConn); return String.Empty; } - public UserSessionID ParseViewerStats(string request, UUID agentID) + private UserSessionID ParseViewerStats(string request, UUID agentID) { UserSessionID uid = new UserSessionID(); UserSessionData usd; @@ -592,14 +568,14 @@ namespace OpenSim.Region.UserStatistics return uid; } - public void UpdateUserStats(UserSessionID uid, SqliteConnection db) + private void UpdateUserStats(UserSessionID uid, SqliteConnection db) { if (uid.session_id == UUID.Zero) return; lock (db) { - using (SqliteCommand updatecmd = new SqliteCommand(SQL_STATS_TABLE_UPDATE, db)) + using (SqliteCommand updatecmd = new SqliteCommand(SQL_STATS_TABLE_INSERT, db)) { updatecmd.Parameters.Add(new SqliteParameter(":session_id", uid.session_data.session_id.ToString())); updatecmd.Parameters.Add(new SqliteParameter(":agent_id", uid.session_data.agent_id.ToString())); @@ -648,44 +624,26 @@ namespace OpenSim.Region.UserStatistics updatecmd.Parameters.Add(new SqliteParameter(":f_dropped", uid.session_data.f_dropped)); updatecmd.Parameters.Add(new SqliteParameter(":f_failed_resends", uid.session_data.f_failed_resends)); updatecmd.Parameters.Add(new SqliteParameter(":f_invalid", uid.session_data.f_invalid)); - updatecmd.Parameters.Add(new SqliteParameter(":f_off_circuit", uid.session_data.f_off_circuit)); updatecmd.Parameters.Add(new SqliteParameter(":f_resent", uid.session_data.f_resent)); updatecmd.Parameters.Add(new SqliteParameter(":f_send_packet", uid.session_data.f_send_packet)); - - 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())); + +// StringBuilder parameters = new StringBuilder(); +// SqliteParameterCollection spc = updatecmd.Parameters; +// foreach (SqliteParameter sp in spc) +// parameters.AppendFormat("{0}={1},", sp.ParameterName, sp.Value); +// +// m_log.DebugFormat("[WEB STATS MODULE]: Parameters {0}", parameters); // m_log.DebugFormat("[WEB STATS MODULE]: Database stats update for {0}", uid.session_data.agent_id); - int result = updatecmd.ExecuteNonQuery(); - - if (result == 0) - { -// m_log.DebugFormat("[WEB STATS MODULE]: Database stats insert for {0}", uid.session_data.agent_id); - - updatecmd.CommandText = SQL_STATS_TABLE_INSERT; - - try - { - updatecmd.ExecuteNonQuery(); - } - catch (Exception e) - { - m_log.WarnFormat( - "[WEB STATS MODULE]: failed to write stats for {0}, storage Execution Exception {1}{2}", - uid.session_data.agent_id, e.Message, e.StackTrace); - } - } + updatecmd.ExecuteNonQuery(); } } } #region SQL - private const string SQL_MIGRA_TABLE_CREATE = @"create table migrations(name varchar(100), version int)"; - - private const string SQL_STATS_TABLE_CREATE = @"CREATE TABLE stats_session_data ( + private const string SQL_STATS_TABLE_CREATE = @"CREATE TABLE IF NOT EXISTS stats_session_data ( session_id VARCHAR(36) NOT NULL PRIMARY KEY, agent_id VARCHAR(36) NOT NULL DEFAULT '', region_id VARCHAR(36) NOT NULL DEFAULT '', @@ -735,11 +693,11 @@ namespace OpenSim.Region.UserStatistics f_send_packet INT NOT NULL DEFAULT '0' );"; - private const string SQL_STATS_TABLE_INSERT = @"INSERT INTO stats_session_data ( + private const string SQL_STATS_TABLE_INSERT = @"INSERT OR REPLACE INTO stats_session_data ( session_id, agent_id, region_id, last_updated, remote_ip, name_f, name_l, avg_agents_in_view, min_agents_in_view, max_agents_in_view, mode_agents_in_view, avg_fps, min_fps, max_fps, mode_fps, a_language, mem_use, meters_traveled, avg_ping, min_ping, max_ping, mode_ping, regions_visited, run_time, avg_sim_fps, min_sim_fps, max_sim_fps, mode_sim_fps, start_time, client_version, s_cpu, s_gpu, s_os, s_ram, -d_object_kb, d_texture_kb, n_in_kb, n_in_pk, n_out_kb, n_out_pk, f_dropped, f_failed_resends, f_invalid, f_invalid, f_off_circuit, +d_object_kb, d_texture_kb, d_world_kb, n_in_kb, n_in_pk, n_out_kb, n_out_pk, f_dropped, f_failed_resends, f_invalid, f_off_circuit, f_resent, f_send_packet ) VALUES @@ -747,62 +705,13 @@ VALUES :session_id, :agent_id, :region_id, :last_updated, :remote_ip, :name_f, :name_l, :avg_agents_in_view, :min_agents_in_view, :max_agents_in_view, :mode_agents_in_view, :avg_fps, :min_fps, :max_fps, :mode_fps, :a_language, :mem_use, :meters_traveled, :avg_ping, :min_ping, :max_ping, :mode_ping, :regions_visited, :run_time, :avg_sim_fps, :min_sim_fps, :max_sim_fps, :mode_sim_fps, :start_time, :client_version, :s_cpu, :s_gpu, :s_os, :s_ram, -:d_object_kb, :d_texture_kb, :n_in_kb, :n_in_pk, :n_out_kb, :n_out_pk, :f_dropped, :f_failed_resends, :f_invalid, :f_invalid, :f_off_circuit, +:d_object_kb, :d_texture_kb, :d_world_kb, :n_in_kb, :n_in_pk, :n_out_kb, :n_out_pk, :f_dropped, :f_failed_resends, :f_invalid, :f_off_circuit, :f_resent, :f_send_packet ) "; - private const string SQL_STATS_TABLE_UPDATE = @" -UPDATE stats_session_data -set session_id=:session_id, - agent_id=:agent_id, - region_id=:region_id, - last_updated=:last_updated, - remote_ip=:remote_ip, - name_f=:name_f, - name_l=:name_l, - avg_agents_in_view=:avg_agents_in_view, - min_agents_in_view=:min_agents_in_view, - max_agents_in_view=:max_agents_in_view, - mode_agents_in_view=:mode_agents_in_view, - avg_fps=:avg_fps, - min_fps=:min_fps, - max_fps=:max_fps, - mode_fps=:mode_fps, - a_language=:a_language, - mem_use=:mem_use, - meters_traveled=:meters_traveled, - avg_ping=:avg_ping, - min_ping=:min_ping, - max_ping=:max_ping, - mode_ping=:mode_ping, - regions_visited=:regions_visited, - run_time=:run_time, - avg_sim_fps=:avg_sim_fps, - min_sim_fps=:min_sim_fps, - max_sim_fps=:max_sim_fps, - mode_sim_fps=:mode_sim_fps, - start_time=:start_time, - client_version=:client_version, - s_cpu=:s_cpu, - s_gpu=:s_gpu, - s_os=:s_os, - s_ram=:s_ram, - d_object_kb=:d_object_kb, - d_texture_kb=:d_texture_kb, - d_world_kb=:d_world_kb, - n_in_kb=:n_in_kb, - n_in_pk=:n_in_pk, - n_out_kb=:n_out_kb, - n_out_pk=:n_out_pk, - f_dropped=:f_dropped, - f_failed_resends=:f_failed_resends, - f_invalid=:f_invalid, - f_off_circuit=:f_off_circuit, - f_resent=:f_resent, - f_send_packet=:f_send_packet -WHERE session_id=:session_key AND agent_id=:agent_key AND region_id=:region_key"; - #endregion + #endregion + } public static class UserSessionUtil diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index 68a2ea307f..3f2f1318ac 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -1560,6 +1560,12 @@ MaptileURL = "http://www.mygrid.com/Grid/" RefreshTime = 3600 +;; +;; JsonStore module provides structured store for scripts +;; +[JsonStore] +Enabled = False + ;; ;; These are defaults that are overwritten below in [Architecture]. ;; These defaults allow OpenSim to work out of the box with