Skip to content

Commit

Permalink
LinkSet Data feature from SL (#64)
Browse files Browse the repository at this point in the history
* Manually applied the Linkset Data patch from zontreck (Aria) that had been posted  to OpenSim Core Mantis with permission.  I had to make a few small changes because this branch is still targetting Mono and only implements C# 7.3 and a few C# 8.0 features were used.  It's otherwise essentially as it was submitted.

* Add using around binary compression of linksetdata so that Dispose is called correctly on completion.   Remove the IsRoot check in BuildPrims for linksetdata.  At this stage we don't yet have a fully instantiated prim so the SOG is undefined.

* Declare and set linksetdata to null when updating prims table where there is no linkdata on a prim.  Previously it was left off an being explicitely set and the connector considers that an error.

* Update the script syntax XML

* Apparently forgot to add the Read and Delete protected methods

* Rewrite null checks for older dot net

* Update linkset data accounting on reset

* Rename ProtectedData to LinksetDataEntry

* Fix protected attribute not being set on new entries

* Add the new linkset data functions

* Finish adding remaining linkset data functions

* Fix a compile error due to typo

* Parity: Don't send value on write protected in event

* Do some code cleanup and fixes in multi-delete function

* Parity: When testing passwords, even for unsecured values, treat as secured

* Parity: Fix some return values

* Oops... compile error

* Fix up a few CodqQL scanner errors.

* For LinkSetData Find and returning a list of keys a count value of < 1 is an indication to return all available.   Adjust the code to behave that way. It was originally looking at -1 as an indication to do that.

* Reformat LinksetDataEntry to be consistent with coding standards. Function and Property names are MixedCase with Initial upper case letter.  Changed references to empty strings to use string.Empty and tests to use string.IsNullOrEmpty in the LinksetDataEntry data model class.

* Change the underlying storage to a SortedList so we return keys in alphabetic order as required.  This is a lightweight list with Dictionary behaviour added.  Mark the SOG dirty on operations that change the LinksetData field so persistence is reliable.  Rework the support functions to use string.Empty and string.IsNullOrEmpty where needed.   Cleaned up what should be the last of the CodeQL comments.

* Fix list handling in llLinksetDataDeleteFound, we can't delete keys from a list we are traversing.   Also a potential lock contention issue.

* Update LSL support for LinksetData to use string.Empty where appropriate

* Rework the scheme migration to use MEDIUMTEXT for the linksetdata field and to serialize/deserialize to/from JSON.  We calculate size based on the size of the serialization which means there is a little bit of overhead for each field.  We'll also let things go slightly over 128k to simplify the cost accounting but the field we're using can store well beyond 128k so thats not an issue.

* Revert to using a binary count for the space accounting for the linksetData field.  This way we match more closely SL semantics.   We'll still serialize in json text format when writing to the database.

* For llLinksetDeleteFound take a copy of the KVP's so we can delete as we iterate the copied list.   deleted and not_deleted only apply to matches, not all the entries. Thx to Aria for the review comments.

* Add missing stub functions

* Cleaned unused System.Text.Json references in Data namespaces.  Added it to Opensim.Region.Framework

---------

Co-authored-by: zontreck <[email protected]>
  • Loading branch information
mdickson and zontreck authored Nov 16, 2023
1 parent 4083fab commit 8c9ccc0
Show file tree
Hide file tree
Showing 23 changed files with 1,049 additions and 24 deletions.
20 changes: 18 additions & 2 deletions OpenSim/Data/MySQL/MySQLSimulationData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,8 @@ public virtual void StoreObject(SceneObjectGroup obj, UUID regionUUID)
"AttachedPosY, AttachedPosZ, " +
"PhysicsShapeType, Density, GravityModifier, " +
"Friction, Restitution, Vehicle, PhysInertia, DynAttrs, " +
"RotationAxisLocks, sopanims, sitactrange, pseudocrc" +
"RotationAxisLocks, sopanims, sitactrange, pseudocrc, " +
"linksetdata" +
") values (" + "?UUID, " +
"?CreationDate, ?Name, ?Text, " +
"?Description, ?SitName, ?TouchName, " +
Expand Down Expand Up @@ -216,7 +217,8 @@ public virtual void StoreObject(SceneObjectGroup obj, UUID regionUUID)
"?AttachedPosY, ?AttachedPosZ, " +
"?PhysicsShapeType, ?Density, ?GravityModifier, " +
"?Friction, ?Restitution, ?Vehicle, ?PhysInertia, ?DynAttrs," +
"?RotationAxisLocks, ?sopanims, ?sitactrange, ?pseudocrc)";
"?RotationAxisLocks, ?sopanims, ?sitactrange, ?pseudocrc, " +
"?linksetdata)";

FillPrimCommand(cmd, prim, obj.UUID, regionUUID);

Expand Down Expand Up @@ -1202,6 +1204,11 @@ private SceneObjectPart BuildPrim(IDataReader row)
if(pseudocrc != 0)
prim.PseudoCRC = pseudocrc;

if (!(row["linksetdata"] is DBNull))
{
prim.DeserializeLinksetData((string)row["linksetdata"]);
}

return prim;
}

Expand Down Expand Up @@ -1620,6 +1627,15 @@ private void FillPrimCommand(MySqlCommand cmd, SceneObjectPart prim, UUID sceneG

cmd.Parameters.AddWithValue("sitactrange", prim.SitActiveRange);
cmd.Parameters.AddWithValue("pseudocrc", prim.PseudoCRC);

if (prim.HasLinksetData)
{
cmd.Parameters.AddWithValue("linksetdata", prim.SerializeLinksetData());
}
else
{
cmd.Parameters.AddWithValue("linksetdata", null);
}
}

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion OpenSim/Data/MySQL/OpenSim.Data.MySQL.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
<EmbeddedResource Include="Resources\os_groups_Store.migrations" />
<EmbeddedResource Include="Resources\Presence.migrations" />
<EmbeddedResource Include="Resources\RegionStore.migrations" />
<EmbeddedResource Include="Resources\UserAlias.migrations" />
<EmbeddedResource Include="Resources\UserAlias.migrations" />
<EmbeddedResource Include="Resources\UserAccount.migrations" />
<EmbeddedResource Include="Resources\UserProfiles.migrations" />
<EmbeddedResource Include="Resources\XAssetStore.migrations" />
Expand Down
8 changes: 8 additions & 0 deletions OpenSim/Data/MySQL/Resources/RegionStore.migrations
Original file line number Diff line number Diff line change
Expand Up @@ -550,3 +550,11 @@ BEGIN;
ALTER TABLE `land` ADD COLUMN `environment` MEDIUMTEXT default NULL;
COMMIT;

:VERSION 64 #----- material overrides
ALTER TABLE `primshapes` ADD COLUMN `MatOvrd` blob default NULL;
COMMIT;

:VERSION 65 #----- add linkset data storage column
BEGIN;
ALTER TABLE `prims` ADD COLUMN `linksetdata` MEDIUMTEXT default NULL;
COMMIT;
2 changes: 1 addition & 1 deletion OpenSim/Data/OpenSim.Data.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
<Compile Remove="MySQL\MySQLRegionData.cs" />
<Compile Remove="MySQL\MySQLSimulationData.cs" />
<Compile Remove="MySQL\MySQLUserAccountData.cs" />
<Compile Remove="MySQL\MySQLUserAliasData.cs" />
<Compile Remove="MySQL\MySQLUserAliasData.cs" />
<Compile Remove="MySQL\MySQLUserProfilesData.cs" />
<Compile Remove="MySQL\MySQLXAssetData.cs" />
<Compile Remove="MySQL\MySQLXInventoryData.cs" />
Expand Down
17 changes: 12 additions & 5 deletions OpenSim/Data/PGSQL/PGSQLSimulationData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -355,9 +355,9 @@ UPDATE prims SET
""ClickAction"" = :ClickAction, ""Material"" = :Material, ""CollisionSound"" = :CollisionSound, ""CollisionSoundVolume"" = :CollisionSoundVolume, ""PassTouches"" = :PassTouches,
""LinkNumber"" = :LinkNumber, ""MediaURL"" = :MediaURL, ""DynAttrs"" = :DynAttrs, ""Vehicle"" = :Vehicle,
""PhysInertia"" = :PhysInertia, ""standtargetx"" =:standtargetx, ""standtargety"" =:standtargety, ""standtargetz"" =:standtargetz,
""sitactrange"" =:sitactrange, ""pseudocrc"" = :pseudocrc, ""sopanims"" = :sopanims
WHERE ""UUID"" = :UUID ;
""sitactrange"" =:sitactrange, ""pseudocrc"" = :pseudocrc, ""sopanims"" = :sopanims,
""linksetdata"" =:linksetdata
WHERE ""UUID"" = :UUID ;
INSERT INTO
prims (
Expand All @@ -371,7 +371,7 @@ INSERT INTO
""ForceMouselook"", ""ScriptAccessPin"", ""AllowedDrop"", ""DieAtEdge"", ""SalePrice"", ""SaleType"", ""ColorR"", ""ColorG"", ""ColorB"", ""ColorA"",
""ParticleSystem"", ""ClickAction"", ""Material"", ""CollisionSound"", ""CollisionSoundVolume"", ""PassTouches"", ""LinkNumber"", ""MediaURL"", ""DynAttrs"",
""PhysicsShapeType"", ""Density"", ""GravityModifier"", ""Friction"", ""Restitution"", ""PassCollisions"", ""RotationAxisLocks"", ""RezzerID"" , ""Vehicle"", ""PhysInertia"",
""standtargetx"", ""standtargety"", ""standtargetz"", ""sitactrange"", ""pseudocrc"", ""sopanims""
""standtargetx"", ""standtargety"", ""standtargetz"", ""sitactrange"", ""pseudocrc"", ""sopanims"", ""linksetdata""
) Select
:UUID, :CreationDate, :Name, :Text, :Description, :SitName, :TouchName, :ObjectFlags, :OwnerMask, :NextOwnerMask, :GroupMask,
:EveryoneMask, :BaseMask, :PositionX, :PositionY, :PositionZ, :GroupPositionX, :GroupPositionY, :GroupPositionZ, :VelocityX,
Expand All @@ -383,7 +383,7 @@ INSERT INTO
:ForceMouselook, :ScriptAccessPin, :AllowedDrop, :DieAtEdge, :SalePrice, :SaleType, :ColorR, :ColorG, :ColorB, :ColorA,
:ParticleSystem, :ClickAction, :Material, :CollisionSound, :CollisionSoundVolume, :PassTouches, :LinkNumber, :MediaURL, :DynAttrs,
:PhysicsShapeType, :Density, :GravityModifier, :Friction, :Restitution, :PassCollisions, :RotationAxisLocks, :RezzerID, :Vehicle, :PhysInertia,
:standtargetx, :standtargety, :standtargetz,:sitactrange, :pseudocrc, :sopanims
:standtargetx, :standtargety, :standtargetz,:sitactrange, :pseudocrc, :sopanims, :LinksetData
where not EXISTS (SELECT ""UUID"" FROM prims WHERE ""UUID"" = :UUID);
";

Expand Down Expand Up @@ -1406,6 +1406,11 @@ private static SceneObjectPart BuildPrim(IDataRecord primRow)
prim.Animations = null;
}

if ((primRow["LinksetData"] is DBNull) == false)
{
prim.DeserializeLinksetData(((string)primRow["linksetdata"]));
}

return prim;
}

Expand Down Expand Up @@ -1870,6 +1875,8 @@ private NpgsqlParameter[] CreatePrimParameters(SceneObjectPart prim, UUID sceneG
else
parameters.Add(_Database.CreateParameter("sopanims", null));

parameters.Add(_Database.CreateParameter("linksetdata", prim.SerializeLinksetData()));

return parameters.ToArray();
}

Expand Down
5 changes: 5 additions & 0 deletions OpenSim/Data/PGSQL/Resources/RegionStore.migrations
Original file line number Diff line number Diff line change
Expand Up @@ -1261,3 +1261,8 @@ BEGIN;
ALTER TABLE `prims` ADD COLUMN `sopanims` bytea NULL;
ALTER TABLE `primshapes` ADD COLUMN `MatOvrd` bytea NULL;
COMMIT;

:VERSION 53 #----- add linkset data storage column
BEGIN;
ALTER TABLE `prims` ADD COLUMN `linksetdata` varchar default NULL;
COMMIT;
5 changes: 5 additions & 0 deletions OpenSim/Data/SQLite/Resources/RegionStore.migrations
Original file line number Diff line number Diff line change
Expand Up @@ -406,3 +406,8 @@ BEGIN;
ALTER TABLE `prims` ADD COLUMN `sopanims` blob default NULL;
ALTER TABLE `primshapes` ADD COLUMN `MatOvrd` blob default NULL;
COMMIT;

:VERSION 41 #----- add linkset data storage column
BEGIN;
ALTER TABLE `prims` ADD COLUMN `linksetdata` TEXT default NULL;
COMMIT;
9 changes: 9 additions & 0 deletions OpenSim/Data/SQLite/SQLiteSimulationData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1251,6 +1251,8 @@ private static DataTable createPrimTable()
createCol(prims, "pseudocrc", typeof(int));
createCol(prims, "sopanims", typeof(byte[]));

createCol(prims, "linksetdata", typeof(string));

// Add in contraints
prims.PrimaryKey = new DataColumn[] { prims.Columns["UUID"] };

Expand Down Expand Up @@ -1810,6 +1812,11 @@ private SceneObjectPart buildPrim(DataRow row)
prim.Animations = null;
}

if (!(row["linksetdata"] is DBNull))
{
prim.DeserializeLinksetData((string)row["LinksetData"]);
}

return prim;
}

Expand Down Expand Up @@ -2199,6 +2206,8 @@ private static void fillPrimRow(DataRow row, SceneObjectPart prim, UUID sceneGro

row["pseudocrc"] = prim.PseudoCRC;
row["sopanims"] = prim.SerializeAnimations();

row["linksetdata"] = prim.SerializeLinksetData();
}

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion OpenSim/Framework/VersionInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public class VersionInfo
{
public const string VersionNumber = "0.9.2.2";
public const string AssemblyVersionNumber = "0.9.2.2";
public const string Release = "8688";
public const string Release = "8719";

public static string Version
{
Expand Down
1 change: 1 addition & 0 deletions OpenSim/Region/Framework/OpenSim.Region.Framework.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -82,5 +82,6 @@
<PackageReference Include="log4net" Version="2.0.15" />
<PackageReference Include="Mono.Addins" Version="1.4.1" />
<PackageReference Include="System.Drawing.Common" Version="6.0.0" />
<PackageReference Include="System.Text.Json" Version="6.0.9" />
</ItemGroup>
</Project>
39 changes: 39 additions & 0 deletions OpenSim/Region/Framework/Scenes/LinksetDataEntry.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System;
using System.IO;

namespace OpenSim.Region.Framework.Scenes
{
public class LinksetDataEntry
{
public LinksetDataEntry(string value, string password)
{
this.Value = value;
this.Password = password;
}

public string Value { get; private set; }
public string Password { get; private set; } = string.Empty;

public bool IsProtected()
{
return (string.IsNullOrEmpty(this.Password) == false);
}

public bool CheckPassword(string pass)
{
// A undocumented caveat for LinksetData appears to be that even for unprotected values, if a pass is provided, it is still treated as protected
if (this.Password == pass)
return true;
else
return false;
}

public string CheckPasswordAndGetValue(string pass)
{
if (string.IsNullOrEmpty(this.Password) || (this.Password == pass))
return this.Value;
else
return string.Empty;
}
}
}
7 changes: 5 additions & 2 deletions OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,10 @@ public enum ScriptEventCode : int
http_request = 38,

path_update = 40,
linkset_data = 41,

// marks highest numbered event
Size = 41
Size = 42
}

// this is not the right place for this
Expand Down Expand Up @@ -145,7 +146,9 @@ public enum scriptEvents : ulong
anytouch = touch | touch_end | touch_start,
anyTarget = at_target | not_at_target | at_rot_target | not_at_rot_target,
anyobjcollision = collision | collision_end | collision_start,
anylandcollision = land_collision | land_collision_end | land_collision_start
anylandcollision = land_collision | land_collision_end | land_collision_start,

linkset_data = 1UL << 41
}

public struct scriptPosTarget
Expand Down
Loading

0 comments on commit 8c9ccc0

Please sign in to comment.