diff --git a/.gitignore b/.gitignore
index bf3ac37e0c..1e412437cd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,6 +30,10 @@ bin/*.db-journal
bin/addin-db-*
bin/*.dll
bin/OpenSim.vshost.exe.config
+bin/OpenSim.32BitLaunch.vshost.exe.config
+bin/OpenSim.32BitLaunch.log
+UpgradeLog.XML
+_UpgradeReport_Files/
bin/ScriptEngines/*-*-*-*-*
bin/ScriptEngines/*.dll
bin/ScriptEngines/*/*.dll
diff --git a/.nant/local.include b/.nant/local.include
index 6d3e97228f..35f00589e8 100644
--- a/.nant/local.include
+++ b/.nant/local.include
@@ -135,14 +135,25 @@
-
+
-
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/OpenSim/Data/IXInventoryData.cs b/OpenSim/Data/IXInventoryData.cs
index 85a5c08d37..e64a82820d 100644
--- a/OpenSim/Data/IXInventoryData.cs
+++ b/OpenSim/Data/IXInventoryData.cs
@@ -40,6 +40,11 @@ namespace OpenSim.Data
public UUID folderID;
public UUID agentID;
public UUID parentFolderID;
+
+ public XInventoryFolder Clone()
+ {
+ return (XInventoryFolder)MemberwiseClone();
+ }
}
public class XInventoryItem
@@ -64,6 +69,11 @@ namespace OpenSim.Data
public UUID avatarID;
public UUID parentFolderID;
public int inventoryGroupPermissions;
+
+ public XInventoryItem Clone()
+ {
+ return (XInventoryItem)MemberwiseClone();
+ }
}
public interface IXInventoryData
diff --git a/OpenSim/Framework/InventoryFolderBase.cs b/OpenSim/Framework/InventoryFolderBase.cs
index a12183c535..b3457a65b9 100644
--- a/OpenSim/Framework/InventoryFolderBase.cs
+++ b/OpenSim/Framework/InventoryFolderBase.cs
@@ -73,33 +73,27 @@ namespace OpenSim.Framework
{
}
- public InventoryFolderBase(UUID id)
+ public InventoryFolderBase(UUID id) : this()
{
ID = id;
}
- public InventoryFolderBase(UUID id, UUID owner)
+ public InventoryFolderBase(UUID id, UUID owner) : this(id)
{
- ID = id;
Owner = owner;
}
- public InventoryFolderBase(UUID id, string name, UUID owner, UUID parent)
+ public InventoryFolderBase(UUID id, string name, UUID owner, UUID parent) : this(id, owner)
{
- ID = id;
Name = name;
- Owner = owner;
ParentID = parent;
}
- public InventoryFolderBase(UUID id, string name, UUID owner, short type, UUID parent, ushort version)
+ public InventoryFolderBase(
+ UUID id, string name, UUID owner, short type, UUID parent, ushort version) : this(id, name, owner, parent)
{
- ID = id;
- Name = name;
- Owner = owner;
Type = type;
- ParentID = parent;
Version = version;
}
}
-}
+}
\ No newline at end of file
diff --git a/OpenSim/Framework/Serialization/External/OspResolver.cs b/OpenSim/Framework/Serialization/External/OspResolver.cs
index d31d27c4a6..fa7160f874 100644
--- a/OpenSim/Framework/Serialization/External/OspResolver.cs
+++ b/OpenSim/Framework/Serialization/External/OspResolver.cs
@@ -65,9 +65,14 @@ namespace OpenSim.Framework.Serialization
UserAccount account = userService.GetUserAccount(UUID.Zero, userId);
if (account != null)
+ {
return MakeOspa(account.FirstName, account.LastName);
+ }
// else
+// {
// m_log.WarnFormat("[OSP RESOLVER]: No user account for {0}", userId);
+// System.Console.WriteLine("[OSP RESOLVER]: No user account for {0}", userId);
+// }
return null;
}
@@ -79,10 +84,13 @@ namespace OpenSim.Framework.Serialization
///
public static string MakeOspa(string firstName, string lastName)
{
-// m_log.DebugFormat("[OSP RESOLVER]: Making OSPA for {0} {1}", firstName, lastName);
+ string ospa
+ = OSPA_PREFIX + OSPA_NAME_KEY + OSPA_PAIR_SEPARATOR + firstName + OSPA_NAME_VALUE_SEPARATOR + lastName;
+
+// m_log.DebugFormat("[OSP RESOLVER]: Made OSPA {0} for {1} {2}", ospa, firstName, lastName);
+// System.Console.WriteLine("[OSP RESOLVER]: Made OSPA {0} for {1} {2}", ospa, firstName, lastName);
- return
- OSPA_PREFIX + OSPA_NAME_KEY + OSPA_PAIR_SEPARATOR + firstName + OSPA_NAME_VALUE_SEPARATOR + lastName;
+ return ospa;
}
///
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
index b112b6db52..12a05b3df5 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
@@ -350,38 +350,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL1.PrincipalID));
}
- ///
- /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where
- /// an account exists with the same name as the creator, though not the same id.
- ///
- [Test]
- public void TestLoadIarV0_1SameNameCreator()
- {
- TestHelpers.InMethod();
-// log4net.Config.XmlConfigurator.Configure();
-
- UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood");
- UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire");
-
- m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream);
- InventoryItemBase foundItem1
- = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name);
-
- Assert.That(
- foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()),
- "Loaded item non-uuid creator doesn't match original");
- Assert.That(
- foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID),
- "Loaded item uuid creator doesn't match original");
- Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID),
- "Loaded item owner doesn't match inventory reciever");
-
- AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString());
- string xmlData = Utils.BytesToString(asset1.Data);
- SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
-
- Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID));
- }
+// ///
+// /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where
+// /// an account exists with the same name as the creator, though not the same id.
+// ///
+// [Test]
+// public void TestLoadIarV0_1SameNameCreator()
+// {
+// TestHelpers.InMethod();
+// TestHelpers.EnableLogging();
+//
+// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood");
+// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire");
+//
+// m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream);
+// InventoryItemBase foundItem1
+// = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name);
+//
+// Assert.That(
+// foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()),
+// "Loaded item non-uuid creator doesn't match original");
+// Assert.That(
+// foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID),
+// "Loaded item uuid creator doesn't match original");
+// Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID),
+// "Loaded item owner doesn't match inventory reciever");
+//
+// AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString());
+// string xmlData = Utils.BytesToString(asset1.Data);
+// SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
+//
+// Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID));
+// }
///
/// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where
diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
index 18bd0186b8..13b74983b1 100644
--- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
@@ -49,6 +49,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
public const int DISP_EXPIRE = 1;
public const int DISP_TEMP = 2;
+ ///
+ /// If true then where possible dynamic textures are reused.
+ ///
+ public bool ReuseTextures { get; set; }
+
private Dictionary RegisteredScenes = new Dictionary();
private Dictionary RenderPlugins =
@@ -56,6 +61,15 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
private Dictionary Updaters = new Dictionary();
+ ///
+ /// Record dynamic textures that we can reuse for a given data and parameter combination rather than
+ /// regenerate.
+ ///
+ ///
+ /// Key is string.Format("{0}{1}", data
+ ///
+ private Cache m_reuseableDynamicTextures;
+
#region IDynamicTextureManager Members
public void RegisterRender(string handleType, IDynamicTextureRender render)
@@ -71,7 +85,8 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
///
///
///
- public void ReturnData(UUID id, byte[] data)
+ /// True if the data generated can be reused for subsequent identical requests
+ public void ReturnData(UUID id, byte[] data, bool isReuseable)
{
DynamicTextureUpdater updater = null;
@@ -88,7 +103,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
if (RegisteredScenes.ContainsKey(updater.SimUUID))
{
Scene scene = RegisteredScenes[updater.SimUUID];
- updater.DataReceived(data, scene);
+ UUID newTextureID = updater.DataReceived(data, scene);
+
+ if (ReuseTextures && isReuseable && !updater.BlendWithOldTexture)
+ m_reuseableDynamicTextures.Store(
+ GenerateReusableTextureKey(updater.BodyData, updater.Params), newTextureID);
}
}
@@ -169,6 +188,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
{
if (RenderPlugins.ContainsKey(contentType))
{
+ // If we want to reuse dynamic textures then we have to ignore any request from the caller to expire
+ // them.
+ if (ReuseTextures)
+ disp = disp & ~DISP_EXPIRE;
+
DynamicTextureUpdater updater = new DynamicTextureUpdater();
updater.SimUUID = simID;
updater.PrimID = primID;
@@ -183,21 +207,49 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
updater.Url = "Local image";
updater.Disp = disp;
- lock (Updaters)
+ object reusableTextureUUID = null;
+
+ if (ReuseTextures)
+ reusableTextureUUID
+ = m_reuseableDynamicTextures.Get(GenerateReusableTextureKey(data, extraParams));
+
+ // We cannot reuse a dynamic texture if the data is going to be blended with something already there.
+ if (reusableTextureUUID == null || updater.BlendWithOldTexture)
{
- if (!Updaters.ContainsKey(updater.UpdaterID))
+ lock (Updaters)
{
- Updaters.Add(updater.UpdaterID, updater);
+ if (!Updaters.ContainsKey(updater.UpdaterID))
+ {
+ Updaters.Add(updater.UpdaterID, updater);
+ }
+ }
+
+ RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams);
+ }
+ else
+ {
+ // No need to add to updaters as the texture is always the same. Not that this functionality
+ // apppears to be implemented anyway.
+ if (RegisteredScenes.ContainsKey(updater.SimUUID))
+ {
+ SceneObjectPart part = RegisteredScenes[updater.SimUUID].GetSceneObjectPart(updater.PrimID);
+
+ if (part != null)
+ updater.UpdatePart(part, (UUID)reusableTextureUUID);
}
}
- RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams);
return updater.UpdaterID;
}
return UUID.Zero;
}
+ private string GenerateReusableTextureKey(string data, string extraParams)
+ {
+ return string.Format("{0}{1}", data, extraParams);
+ }
+
public void GetDrawStringSize(string contentType, string text, string fontName, int fontSize,
out double xSize, out double ySize)
{
@@ -224,6 +276,12 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
public void PostInitialise()
{
+// ReuseTextures = true;
+ if (ReuseTextures)
+ {
+ m_reuseableDynamicTextures = new Cache(CacheMedium.Memory, CacheStrategy.Conservative);
+ m_reuseableDynamicTextures.DefaultTTL = new TimeSpan(24, 0, 0);
+ }
}
public void Close()
@@ -268,10 +326,61 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
BodyData = null;
}
+ ///
+ /// Update the given part with the new texture.
+ ///
+ ///
+ /// The old texture UUID.
+ ///
+ public UUID UpdatePart(SceneObjectPart part, UUID textureID)
+ {
+ UUID oldID;
+
+ lock (part)
+ {
+ // mostly keep the values from before
+ Primitive.TextureEntry tmptex = part.Shape.Textures;
+
+ // FIXME: Need to return the appropriate ID if only a single face is replaced.
+ oldID = tmptex.DefaultTexture.TextureID;
+
+ if (Face == ALL_SIDES)
+ {
+ oldID = tmptex.DefaultTexture.TextureID;
+ tmptex.DefaultTexture.TextureID = textureID;
+ }
+ else
+ {
+ try
+ {
+ Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face);
+ texface.TextureID = textureID;
+ tmptex.FaceTextures[Face] = texface;
+ }
+ catch (Exception)
+ {
+ tmptex.DefaultTexture.TextureID = textureID;
+ }
+ }
+
+ // I'm pretty sure we always want to force this to true
+ // I'm pretty sure noone whats to set fullbright true if it wasn't true before.
+ // tmptex.DefaultTexture.Fullbright = true;
+
+ part.UpdateTextureEntry(tmptex.GetBytes());
+ }
+
+ return oldID;
+ }
+
///
/// Called once new texture data has been received for this updater.
///
- public void DataReceived(byte[] data, Scene scene)
+ ///
+ ///
+ /// True if the data given is reuseable.
+ /// The asset UUID given to the incoming data.
+ public UUID DataReceived(byte[] data, Scene scene)
{
SceneObjectPart part = scene.GetSceneObjectPart(PrimID);
@@ -281,7 +390,8 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url);
scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say,
0, part.ParentGroup.RootPart.AbsolutePosition, part.Name, part.UUID, false);
- return;
+
+ return UUID.Zero;
}
byte[] assetData = null;
@@ -323,52 +433,23 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
cacheLayerDecode = null;
}
- UUID oldID = UUID.Zero;
-
- lock (part)
- {
- // mostly keep the values from before
- Primitive.TextureEntry tmptex = part.Shape.Textures;
-
- // remove the old asset from the cache
- oldID = tmptex.DefaultTexture.TextureID;
-
- if (Face == ALL_SIDES)
- {
- tmptex.DefaultTexture.TextureID = asset.FullID;
- }
- else
- {
- try
- {
- Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face);
- texface.TextureID = asset.FullID;
- tmptex.FaceTextures[Face] = texface;
- }
- catch (Exception)
- {
- tmptex.DefaultTexture.TextureID = asset.FullID;
- }
- }
-
- // I'm pretty sure we always want to force this to true
- // I'm pretty sure noone whats to set fullbright true if it wasn't true before.
- // tmptex.DefaultTexture.Fullbright = true;
-
- part.UpdateTextureEntry(tmptex.GetBytes());
- }
+ UUID oldID = UpdatePart(part, asset.FullID);
if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0))
{
- if (oldAsset == null) oldAsset = scene.AssetService.Get(oldID.ToString());
+ if (oldAsset == null)
+ oldAsset = scene.AssetService.Get(oldID.ToString());
+
if (oldAsset != null)
{
- if (oldAsset.Temporary == true)
+ if (oldAsset.Temporary)
{
scene.AssetService.Delete(oldID.ToString());
}
}
}
+
+ return asset.FullID;
}
private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha)
diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
index 05d54f03a2..53a9679580 100644
--- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
@@ -84,6 +84,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
public string body;
public int responseCode;
public string responseBody;
+ public string responseType = "text/plain";
//public ManualResetEvent ev;
public bool requestDone;
public int startTime;
@@ -302,6 +303,22 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
}
}
+ public void HttpContentType(UUID request, string type)
+ {
+ lock (m_UrlMap)
+ {
+ if (m_RequestMap.ContainsKey(request))
+ {
+ UrlData urlData = m_RequestMap[request];
+ urlData.requests[request].responseType = type;
+ }
+ else
+ {
+ m_log.Info("[HttpRequestHandler] There is no http-in request with id " + request.ToString());
+ }
+ }
+ }
+
public void HttpResponse(UUID request, int status, string body)
{
lock (m_UrlMap)
@@ -504,7 +521,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
//put response
response["int_response_code"] = requestData.responseCode;
response["str_response_string"] = requestData.responseBody;
- response["content_type"] = "text/plain";
+ response["content_type"] = requestData.responseType;
+ // response["content_type"] = "text/plain";
response["keepalive"] = false;
response["reusecontext"] = false;
diff --git a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
index 6f839485ec..2b3a0f29ff 100644
--- a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
@@ -67,12 +67,18 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
return true;
}
+// public bool AlwaysIdenticalConversion(string bodyData, string extraParams)
+// {
+// // We don't support conversion of body data.
+// return false;
+// }
+
public byte[] ConvertUrl(string url, string extraParams)
{
return null;
}
- public byte[] ConvertStream(Stream data, string extraParams)
+ public byte[] ConvertData(string bodyData, string extraParams)
{
return null;
}
@@ -236,9 +242,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
stream.Close();
}
}
+
m_log.DebugFormat("[LOADIMAGEURLMODULE] Returning {0} bytes of image data for request {1}",
imageJ2000.Length, state.RequestID);
- m_textureManager.ReturnData(state.RequestID, imageJ2000);
+
+ m_textureManager.ReturnData(state.RequestID, imageJ2000, false);
}
#region Nested type: RequestState
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
index 9787c8c173..b50c0bd7cd 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
@@ -45,31 +45,250 @@ using OpenSim.Tests.Common.Mock;
namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
{
[TestFixture]
- public class VectorRenderModuleTests
+ public class VectorRenderModuleTests : OpenSimTestCase
{
+ Scene m_scene;
+ DynamicTextureModule m_dtm;
+ VectorRenderModule m_vrm;
+
+ private void SetupScene(bool reuseTextures)
+ {
+ m_scene = new SceneHelpers().SetupScene();
+
+ m_dtm = new DynamicTextureModule();
+ m_dtm.ReuseTextures = reuseTextures;
+
+ m_vrm = new VectorRenderModule();
+
+ SceneHelpers.SetupSceneModules(m_scene, m_dtm, m_vrm);
+ }
+
[Test]
public void TestDraw()
{
TestHelpers.InMethod();
- Scene scene = new SceneHelpers().SetupScene();
- DynamicTextureModule dtm = new DynamicTextureModule();
- VectorRenderModule vrm = new VectorRenderModule();
- SceneHelpers.SetupSceneModules(scene, dtm, vrm);
-
- SceneObjectGroup so = SceneHelpers.AddSceneObject(scene);
+ SetupScene(false);
+ SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
- dtm.AddDynamicTextureData(
- scene.RegionInfo.RegionID,
+ m_dtm.AddDynamicTextureData(
+ m_scene.RegionInfo.RegionID,
so.UUID,
- vrm.GetContentType(),
+ m_vrm.GetContentType(),
"PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;",
"",
0);
+ Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
+ }
+
+ [Test]
+ public void TestRepeatSameDraw()
+ {
+ TestHelpers.InMethod();
+
+ string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
+
+ SetupScene(false);
+ SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
+
+ m_dtm.AddDynamicTextureData(
+ m_scene.RegionInfo.RegionID,
+ so.UUID,
+ m_vrm.GetContentType(),
+ dtText,
+ "",
+ 0);
+
+ UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
+
+ m_dtm.AddDynamicTextureData(
+ m_scene.RegionInfo.RegionID,
+ so.UUID,
+ m_vrm.GetContentType(),
+ dtText,
+ "",
+ 0);
+
+ Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
+ }
+
+ [Test]
+ public void TestRepeatSameDrawDifferentExtraParams()
+ {
+ TestHelpers.InMethod();
+
+ string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
+
+ SetupScene(false);
+ SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
+
+ m_dtm.AddDynamicTextureData(
+ m_scene.RegionInfo.RegionID,
+ so.UUID,
+ m_vrm.GetContentType(),
+ dtText,
+ "",
+ 0);
+
+ UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
+
+ m_dtm.AddDynamicTextureData(
+ m_scene.RegionInfo.RegionID,
+ so.UUID,
+ m_vrm.GetContentType(),
+ dtText,
+ "alpha:250",
+ 0);
+
+ Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
+ }
+
+ [Test]
+ public void TestRepeatSameDrawContainingImage()
+ {
+ TestHelpers.InMethod();
+
+ string dtText
+ = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png";
+
+ SetupScene(false);
+ SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
+
+ m_dtm.AddDynamicTextureData(
+ m_scene.RegionInfo.RegionID,
+ so.UUID,
+ m_vrm.GetContentType(),
+ dtText,
+ "",
+ 0);
+
+ UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
+
+ m_dtm.AddDynamicTextureData(
+ m_scene.RegionInfo.RegionID,
+ so.UUID,
+ m_vrm.GetContentType(),
+ dtText,
+ "",
+ 0);
+
+ Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
+ }
+
+ [Test]
+ public void TestDrawReusingTexture()
+ {
+ TestHelpers.InMethod();
+
+ SetupScene(true);
+ SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
+ UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
+
+ m_dtm.AddDynamicTextureData(
+ m_scene.RegionInfo.RegionID,
+ so.UUID,
+ m_vrm.GetContentType(),
+ "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;",
+ "",
+ 0);
Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
}
+
+ [Test]
+ public void TestRepeatSameDrawReusingTexture()
+ {
+ TestHelpers.InMethod();
+
+ string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
+
+ SetupScene(true);
+ SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
+
+ m_dtm.AddDynamicTextureData(
+ m_scene.RegionInfo.RegionID,
+ so.UUID,
+ m_vrm.GetContentType(),
+ dtText,
+ "",
+ 0);
+
+ UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
+
+ m_dtm.AddDynamicTextureData(
+ m_scene.RegionInfo.RegionID,
+ so.UUID,
+ m_vrm.GetContentType(),
+ dtText,
+ "",
+ 0);
+
+ Assert.That(firstDynamicTextureID, Is.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
+ }
+
+ [Test]
+ public void TestRepeatSameDrawDifferentExtraParamsReusingTexture()
+ {
+ TestHelpers.InMethod();
+
+ string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
+
+ SetupScene(true);
+ SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
+
+ m_dtm.AddDynamicTextureData(
+ m_scene.RegionInfo.RegionID,
+ so.UUID,
+ m_vrm.GetContentType(),
+ dtText,
+ "",
+ 0);
+
+ UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
+
+ m_dtm.AddDynamicTextureData(
+ m_scene.RegionInfo.RegionID,
+ so.UUID,
+ m_vrm.GetContentType(),
+ dtText,
+ "alpha:250",
+ 0);
+
+ Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
+ }
+
+ [Test]
+ public void TestRepeatSameDrawContainingImageReusingTexture()
+ {
+ TestHelpers.InMethod();
+
+ string dtText
+ = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png";
+
+ SetupScene(true);
+ SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
+
+ m_dtm.AddDynamicTextureData(
+ m_scene.RegionInfo.RegionID,
+ so.UUID,
+ m_vrm.GetContentType(),
+ dtText,
+ "",
+ 0);
+
+ UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
+
+ m_dtm.AddDynamicTextureData(
+ m_scene.RegionInfo.RegionID,
+ so.UUID,
+ m_vrm.GetContentType(),
+ dtText,
+ "",
+ 0);
+
+ Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
+ }
}
}
\ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
index 018c190133..7c9c2446ab 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
@@ -30,6 +30,7 @@ using System.Drawing;
using System.Drawing.Imaging;
using System.Globalization;
using System.IO;
+using System.Linq;
using System.Net;
using Nini.Config;
using OpenMetaverse;
@@ -47,7 +48,6 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
- private string m_name = "VectorRenderModule";
private Scene m_scene;
private IDynamicTextureManager m_textureManager;
private Graphics m_graph;
@@ -61,12 +61,12 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
public string GetContentType()
{
- return ("vector");
+ return "vector";
}
public string GetName()
{
- return m_name;
+ return Name;
}
public bool SupportsAsynchronous()
@@ -74,14 +74,26 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
return true;
}
+// public bool AlwaysIdenticalConversion(string bodyData, string extraParams)
+// {
+// string[] lines = GetLines(bodyData);
+// return lines.Any((str, r) => str.StartsWith("Image"));
+// }
+
public byte[] ConvertUrl(string url, string extraParams)
{
return null;
}
- public byte[] ConvertStream(Stream data, string extraParams)
+ public byte[] ConvertData(string bodyData, string extraParams)
{
- return null;
+ bool reuseable;
+ return Draw(bodyData, extraParams, out reuseable);
+ }
+
+ private byte[] ConvertData(string bodyData, string extraParams, out bool reuseable)
+ {
+ return Draw(bodyData, extraParams, out reuseable);
}
public bool AsyncConvertUrl(UUID id, string url, string extraParams)
@@ -91,7 +103,12 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
public bool AsyncConvertData(UUID id, string bodyData, string extraParams)
{
- Draw(bodyData, id, extraParams);
+ // XXX: This isn't actually being done asynchronously!
+ bool reuseable;
+ byte[] data = ConvertData(bodyData, extraParams, out reuseable);
+
+ m_textureManager.ReturnData(id, data, reuseable);
+
return true;
}
@@ -152,7 +169,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
public string Name
{
- get { return m_name; }
+ get { return "VectorRenderModule"; }
}
public bool IsSharedModule
@@ -162,7 +179,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
#endregion
- private void Draw(string data, UUID id, string extraParams)
+ private byte[] Draw(string data, string extraParams, out bool reuseable)
{
// We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha
// we will now support multiple comma seperated params in the form width:256,height:512,alpha:255
@@ -343,7 +360,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
}
}
- GDIDraw(data, graph, altDataDelim);
+ GDIDraw(data, graph, altDataDelim, out reuseable);
}
byte[] imageJ2000 = new byte[0];
@@ -359,7 +376,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
e.Message, e.StackTrace);
}
- m_textureManager.ReturnData(id, imageJ2000);
+ return imageJ2000;
}
finally
{
@@ -434,8 +451,21 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
}
*/
- private void GDIDraw(string data, Graphics graph, char dataDelim)
+ ///
+ /// Split input data into discrete command lines.
+ ///
+ ///
+ ///
+ ///
+ private string[] GetLines(string data, char dataDelim)
{
+ char[] lineDelimiter = { dataDelim };
+ return data.Split(lineDelimiter);
+ }
+
+ private void GDIDraw(string data, Graphics graph, char dataDelim, out bool reuseable)
+ {
+ reuseable = true;
Point startPoint = new Point(0, 0);
Point endPoint = new Point(0, 0);
Pen drawPen = null;
@@ -450,11 +480,9 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
myFont = new Font(fontName, fontSize);
myBrush = new SolidBrush(Color.Black);
- char[] lineDelimiter = {dataDelim};
char[] partsDelimiter = {','};
- string[] lines = data.Split(lineDelimiter);
- foreach (string line in lines)
+ foreach (string line in GetLines(data, dataDelim))
{
string nextLine = line.Trim();
//replace with switch, or even better, do some proper parsing
@@ -485,6 +513,10 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
}
else if (nextLine.StartsWith("Image"))
{
+ // We cannot reuse any generated texture involving fetching an image via HTTP since that image
+ // can change.
+ reuseable = false;
+
float x = 0;
float y = 0;
GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y);
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
index 3f848ed1f7..4694b148b4 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
@@ -414,6 +414,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
private void LoadPlugins()
{
m_plugineffects = new Dictionary();
+ LoadPlugins(Assembly.GetCallingAssembly());
string plugineffectsPath = "Terrain";
// Load the files in the Terrain/ dir
@@ -427,32 +428,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
try
{
Assembly library = Assembly.LoadFrom(file);
- foreach (Type pluginType in library.GetTypes())
- {
- try
- {
- if (pluginType.IsAbstract || pluginType.IsNotPublic)
- continue;
-
- string typeName = pluginType.Name;
-
- if (pluginType.GetInterface("ITerrainEffect", false) != null)
- {
- ITerrainEffect terEffect = (ITerrainEffect) Activator.CreateInstance(library.GetType(pluginType.ToString()));
-
- InstallPlugin(typeName, terEffect);
- }
- else if (pluginType.GetInterface("ITerrainLoader", false) != null)
- {
- ITerrainLoader terLoader = (ITerrainLoader) Activator.CreateInstance(library.GetType(pluginType.ToString()));
- m_loaders[terLoader.FileExtension] = terLoader;
- m_log.Info("L ... " + typeName);
- }
- }
- catch (AmbiguousMatchException)
- {
- }
- }
+ LoadPlugins(library);
}
catch (BadImageFormatException)
{
@@ -460,6 +436,36 @@ namespace OpenSim.Region.CoreModules.World.Terrain
}
}
+ private void LoadPlugins(Assembly library)
+ {
+ foreach (Type pluginType in library.GetTypes())
+ {
+ try
+ {
+ if (pluginType.IsAbstract || pluginType.IsNotPublic)
+ continue;
+
+ string typeName = pluginType.Name;
+
+ if (pluginType.GetInterface("ITerrainEffect", false) != null)
+ {
+ ITerrainEffect terEffect = (ITerrainEffect)Activator.CreateInstance(library.GetType(pluginType.ToString()));
+
+ InstallPlugin(typeName, terEffect);
+ }
+ else if (pluginType.GetInterface("ITerrainLoader", false) != null)
+ {
+ ITerrainLoader terLoader = (ITerrainLoader)Activator.CreateInstance(library.GetType(pluginType.ToString()));
+ m_loaders[terLoader.FileExtension] = terLoader;
+ m_log.Info("L ... " + typeName);
+ }
+ }
+ catch (AmbiguousMatchException)
+ {
+ }
+ }
+ }
+
public void InstallPlugin(string pluginName, ITerrainEffect effect)
{
lock (m_plugineffects)
@@ -1176,7 +1182,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
private void InterfaceRunPluginEffect(Object[] args)
{
- if ((string) args[0] == "list")
+ string firstArg = (string)args[0];
+ if (firstArg == "list")
{
m_log.Info("List of loaded plugins");
foreach (KeyValuePair kvp in m_plugineffects)
@@ -1185,14 +1192,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain
}
return;
}
- if ((string) args[0] == "reload")
+ if (firstArg == "reload")
{
LoadPlugins();
return;
}
- if (m_plugineffects.ContainsKey((string) args[0]))
+ if (m_plugineffects.ContainsKey(firstArg))
{
- m_plugineffects[(string) args[0]].RunEffect(m_channel);
+ m_plugineffects[firstArg].RunEffect(m_channel);
CheckForTerrainUpdates();
}
else
diff --git a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs
index 8954513c06..1a3bcbbc71 100644
--- a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs
+++ b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs
@@ -33,7 +33,7 @@ namespace OpenSim.Region.Framework.Interfaces
public interface IDynamicTextureManager
{
void RegisterRender(string handleType, IDynamicTextureRender render);
- void ReturnData(UUID id, byte[] data);
+ void ReturnData(UUID id, byte[] data, bool isReuseable);
UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams,
int updateTimer);
@@ -113,8 +113,20 @@ namespace OpenSim.Region.Framework.Interfaces
string GetName();
string GetContentType();
bool SupportsAsynchronous();
+
+// ///
+// /// Return true if converting the input body and extra params data will always result in the same byte[] array
+// ///
+// ///
+// /// This method allows the caller to use a previously generated asset if it has one.
+// ///
+// ///
+// ///
+// ///
+// bool AlwaysIdenticalConversion(string bodyData, string extraParams);
+
byte[] ConvertUrl(string url, string extraParams);
- byte[] ConvertStream(Stream data, string extraParams);
+ byte[] ConvertData(string bodyData, string extraParams);
bool AsyncConvertUrl(UUID id, string url, string extraParams);
bool AsyncConvertData(UUID id, string bodyData, string extraParams);
void GetDrawStringSize(string text, string fontName, int fontSize,
diff --git a/OpenSim/Region/Framework/Interfaces/IUrlModule.cs b/OpenSim/Region/Framework/Interfaces/IUrlModule.cs
index 457444cd83..79e9f9d51e 100644
--- a/OpenSim/Region/Framework/Interfaces/IUrlModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IUrlModule.cs
@@ -39,6 +39,8 @@ namespace OpenSim.Region.Framework.Interfaces
UUID RequestSecureURL(IScriptModule engine, SceneObjectPart host, UUID itemID);
void ReleaseURL(string url);
void HttpResponse(UUID request, int status, string body);
+ void HttpContentType(UUID request, string type);
+
string GetHttpHeader(UUID request, string header);
int GetFreeUrls();
diff --git a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs
index 44d2d452d5..9457ebb374 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs
@@ -50,8 +50,40 @@ using OpenSim.Tests.Common.Mock;
namespace OpenSim.Region.Framework.Tests
{
[TestFixture]
- public class UserInventoryTests
+ public class UserInventoryTests : OpenSimTestCase
{
+ [Test]
+ public void TestCreateInventoryFolders()
+ {
+ TestHelpers.InMethod();
+// TestHelpers.EnableLogging();
+
+ // For this test both folders will have the same name which is legal in SL user inventories.
+ string foldersName = "f1";
+
+ Scene scene = new SceneHelpers().SetupScene();
+ UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001));
+
+ UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, user1.PrincipalID, foldersName);
+
+ List oneFolder
+ = UserInventoryHelpers.GetInventoryFolders(scene.InventoryService, user1.PrincipalID, foldersName);
+
+ Assert.That(oneFolder.Count, Is.EqualTo(1));
+ InventoryFolderBase firstRetrievedFolder = oneFolder[0];
+ Assert.That(firstRetrievedFolder.Name, Is.EqualTo(foldersName));
+
+ UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, user1.PrincipalID, foldersName);
+
+ List twoFolders
+ = UserInventoryHelpers.GetInventoryFolders(scene.InventoryService, user1.PrincipalID, foldersName);
+
+ Assert.That(twoFolders.Count, Is.EqualTo(2));
+ Assert.That(twoFolders[0].Name, Is.EqualTo(foldersName));
+ Assert.That(twoFolders[1].Name, Is.EqualTo(foldersName));
+ Assert.That(twoFolders[0].ID, Is.Not.EqualTo(twoFolders[1].ID));
+ }
+
[Test]
public void TestGiveInventoryItem()
{
@@ -83,7 +115,7 @@ namespace OpenSim.Region.Framework.Tests
public void TestGiveInventoryFolder()
{
TestHelpers.InMethod();
-// log4net.Config.XmlConfigurator.Configure();
+// TestHelpers.EnableLogging();
Scene scene = new SceneHelpers().SetupScene();
UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001));
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index b001c51606..45286c0135 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -7208,7 +7208,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
m_host.AddScriptLPS(1);
- setLinkPrimParams(ScriptBaseClass.LINK_THIS, rules);
+ setLinkPrimParams(ScriptBaseClass.LINK_THIS, rules, "llSetPrimitiveParams");
ScriptSleep(200);
}
@@ -7217,7 +7217,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
m_host.AddScriptLPS(1);
- setLinkPrimParams(linknumber, rules);
+ setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParams");
ScriptSleep(200);
}
@@ -7226,17 +7226,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
m_host.AddScriptLPS(1);
- setLinkPrimParams(linknumber, rules);
+ setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast");
}
- protected void setLinkPrimParams(int linknumber, LSL_List rules)
+ protected void setLinkPrimParams(int linknumber, LSL_List rules, string originFunc)
{
List parts = GetLinkParts(linknumber);
LSL_List remaining = null;
+ uint rulesParsed = 0;
foreach (SceneObjectPart part in parts)
- remaining = SetPrimParams(part, rules);
+ remaining = SetPrimParams(part, rules, originFunc, ref rulesParsed);
while (remaining != null && remaining.Length > 2)
{
@@ -7245,13 +7246,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
parts = GetLinkParts(linknumber);
foreach (SceneObjectPart part in parts)
- remaining = SetPrimParams(part, rules);
+ remaining = SetPrimParams(part, rules, originFunc, ref rulesParsed);
}
}
- protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules)
+ protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc, ref uint rulesParsed)
{
int idx = 0;
+ int idxStart = 0;
bool positionChanged = false;
LSL_Vector currentPosition = GetPartLocalPos(part);
@@ -7260,9 +7262,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
while (idx < rules.Length)
{
+ ++rulesParsed;
int code = rules.GetLSLIntegerItem(idx++);
int remain = rules.Length - idx;
+ idxStart = idx;
int face;
LSL_Vector v;
@@ -7639,7 +7643,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
catch (InvalidCastException e)
{
- ShoutError(e.Message);
+ ShoutError(string.Format(
+ "{0} error running rule #{1}: arg #{2} ",
+ originFunc, rulesParsed, idx - idxStart) + e.Message);
}
finally
{
@@ -10113,31 +10119,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public LSL_Float llListStatistics(int operation, LSL_List src)
{
m_host.AddScriptLPS(1);
- LSL_List nums = LSL_List.ToDoubleList(src);
switch (operation)
{
case ScriptBaseClass.LIST_STAT_RANGE:
- return nums.Range();
+ return src.Range();
case ScriptBaseClass.LIST_STAT_MIN:
- return nums.Min();
+ return src.Min();
case ScriptBaseClass.LIST_STAT_MAX:
- return nums.Max();
+ return src.Max();
case ScriptBaseClass.LIST_STAT_MEAN:
- return nums.Mean();
+ return src.Mean();
case ScriptBaseClass.LIST_STAT_MEDIAN:
- return nums.Median();
+ return LSL_List.ToDoubleList(src).Median();
case ScriptBaseClass.LIST_STAT_NUM_COUNT:
- return nums.NumericLength();
+ return src.NumericLength();
case ScriptBaseClass.LIST_STAT_STD_DEV:
- return nums.StdDev();
+ return src.StdDev();
case ScriptBaseClass.LIST_STAT_SUM:
- return nums.Sum();
+ return src.Sum();
case ScriptBaseClass.LIST_STAT_SUM_SQUARES:
- return nums.SumSqrs();
+ return src.SumSqrs();
case ScriptBaseClass.LIST_STAT_GEOMETRIC_MEAN:
- return nums.GeometricMean();
+ return src.GeometricMean();
case ScriptBaseClass.LIST_STAT_HARMONIC_MEAN:
- return nums.HarmonicMean();
+ return src.HarmonicMean();
default:
return 0.0;
}
@@ -10761,7 +10766,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return tid.ToString();
}
- public void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules)
+ public void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc)
{
SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim));
if (obj == null)
@@ -10770,14 +10775,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (obj.OwnerID != m_host.OwnerID)
return;
- LSL_List remaining = SetPrimParams(obj, rules);
+ uint rulesParsed = 0;
+ LSL_List remaining = SetPrimParams(obj, rules, originFunc, ref rulesParsed);
while ((object)remaining != null && remaining.Length > 2)
{
LSL_Integer newLink = remaining.GetLSLIntegerItem(0);
LSL_List newrules = remaining.GetSublist(1, -1);
foreach(SceneObjectPart part in GetLinkParts(obj, newLink)){
- remaining = SetPrimParams(part, newrules);
+ remaining = SetPrimParams(part, newrules, originFunc, ref rulesParsed);
}
}
}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 1afa4fbc20..e245684a43 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -140,12 +140,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
internal float m_ScriptDistanceFactor = 1.0f;
internal Dictionary m_FunctionPerms = new Dictionary();
+ protected IUrlModule m_UrlModule = null;
+
public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item)
{
m_ScriptEngine = ScriptEngine;
m_host = host;
m_item = item;
+ m_UrlModule = m_ScriptEngine.World.RequestModuleInterface();
+
if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false))
m_OSFunctionsEnabled = true;
@@ -2988,7 +2992,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.AddScriptLPS(1);
InitLSL();
- m_LSL_Api.SetPrimitiveParamsEx(prim, rules);
+ m_LSL_Api.SetPrimitiveParamsEx(prim, rules, "osSetPrimitiveParams");
}
///
@@ -3358,5 +3362,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return new LSL_Key(m_host.ParentGroup.FromPartID.ToString());
}
- }
+
+ ///
+ /// Sets the response type for an HTTP request/response
+ ///
+ ///
+ public void osSetContentType(LSL_Key id, string type)
+ {
+ CheckThreatLevel(ThreatLevel.High,"osSetResponseType");
+ if (m_UrlModule != null)
+ m_UrlModule.HttpContentType(new UUID(id),type);
+ }
+
+ }
}
\ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
index cd58614b58..e97ff9d1ba 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
@@ -424,7 +424,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
LSL_String llXorBase64StringsCorrect(string str1, string str2);
void print(string str);
- void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
+ void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc);
LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
}
}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
index 9ad1c22bd1..06729abe36 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -40,16 +40,75 @@ using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
{
+ ///
+ /// To permit region owners to enable the extended scripting functionality
+ /// of OSSL, without allowing malicious scripts to access potentially
+ /// troublesome functions, each OSSL function is assigned a threat level,
+ /// and access to the functions is granted or denied based on a default
+ /// threshold set in OpenSim.ini (which can be overridden for individual
+ /// functions on a case-by-case basis)
+ ///
public enum ThreatLevel
{
+ // Not documented, presumably means permanently disabled ?
NoAccess = -1,
+
+ ///
+ /// Function is no threat at all. It doesn't constitute a threat to
+ /// either users or the system and has no known side effects.
+ ///
None = 0,
+
+ ///
+ /// Abuse of this command can cause a nuisance to the region operator,
+ /// such as log message spew.
+ ///
Nuisance = 1,
+
+ ///
+ /// Extreme levels of abuse of this function can cause impaired
+ /// functioning of the region, or very gullible users can be tricked
+ /// into experiencing harmless effects.
+ ///
VeryLow = 2,
+
+ ///
+ /// Intentional abuse can cause crashes or malfunction under certain
+ /// circumstances, which can be easily rectified; or certain users can
+ /// be tricked into certain situations in an avoidable manner.
+ ///
Low = 3,
+
+ ///
+ /// Intentional abuse can cause denial of service and crashes with
+ /// potential of data or state loss; or trusting users can be tricked
+ /// into embarrassing or uncomfortable situations.
+ ///
Moderate = 4,
+
+ ///
+ /// Casual abuse can cause impaired functionality or temporary denial
+ /// of service conditions. Intentional abuse can easily cause crashes
+ /// with potential data loss, or can be used to trick experienced and
+ /// cautious users into unwanted situations, or changes global data
+ /// permanently and without undo ability.
+ ///
High = 5,
+
+ ///
+ /// Even normal use may, depending on the number of instances, or
+ /// frequency of use, result in severe service impairment or crash
+ /// with loss of data, or can be used to cause unwanted or harmful
+ /// effects on users without giving the user a means to avoid it.
+ ///
VeryHigh = 6,
+
+ ///
+ /// Even casual use is a danger to region stability, or function allows
+ /// console or OS command execution, or function allows taking money
+ /// without consent, or allows deletion or modification of user data,
+ /// or allows the compromise of sensitive data by design.
+ ///
Severe = 7
};
@@ -306,5 +365,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
///
/// Rezzing object key or NULL_KEY if rezzed by agent or otherwise unknown.
LSL_Key osGetRezzingObject();
+
+ ///
+ /// Sets the response type for an HTTP request/response
+ ///
+ ///
+ void osSetContentType(LSL_Key id, string type);
}
}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
index e9131e4655..ba1ade2285 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
@@ -955,5 +955,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
{
return m_OSSL_Functions.osGetRezzingObject();
}
+
+ public void osSetContentType(LSL_Key id, string type)
+ {
+ m_OSSL_Functions.osSetContentType(id,type);
+ }
}
}
diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
index 9d9df9c4e6..fcb98a5152 100644
--- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
@@ -1137,7 +1137,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
{
list ret = new list();
double entry;
- for (int i = 0; i < src.Data.Length - 1; i++)
+ for (int i = 0; i < src.Data.Length; i++)
{
if (double.TryParse(src.Data[i].ToString(), NumberStyles.Float, Culture.NumberFormatInfo, out entry))
{
diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs
index deacd5a4b4..309dab4501 100644
--- a/OpenSim/Services/InventoryService/XInventoryService.cs
+++ b/OpenSim/Services/InventoryService/XInventoryService.cs
@@ -94,6 +94,7 @@ namespace OpenSim.Services.InventoryService
m_Database = LoadPlugin(dllName,
new Object[] {connString, String.Empty});
+
if (m_Database == null)
throw new Exception("Could not find a storage interface in the given module");
}
@@ -326,7 +327,7 @@ namespace OpenSim.Services.InventoryService
if (check != null)
return false;
- if (folder.Type != (short)AssetType.Folder || folder.Type != (short)AssetType.Unknown)
+ if (folder.Type != (short)AssetType.Folder && folder.Type != (short)AssetType.Unknown)
{
InventoryFolderBase rootFolder = GetRootFolder(folder.Owner);
diff --git a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs
index 7598cc360e..fc49169c97 100644
--- a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs
+++ b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs
@@ -245,7 +245,7 @@ namespace OpenSim.Tests.Common
config.AddConfig("Modules");
config.AddConfig("InventoryService");
config.Configs["Modules"].Set("InventoryServices", "LocalInventoryServicesConnector");
- config.Configs["InventoryService"].Set("LocalServiceModule", "OpenSim.Services.InventoryService.dll:InventoryService");
+ config.Configs["InventoryService"].Set("LocalServiceModule", "OpenSim.Services.InventoryService.dll:XInventoryService");
config.Configs["InventoryService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
LocalInventoryServicesConnector inventoryService = new LocalInventoryServicesConnector();
diff --git a/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs b/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs
index b3a7c9eec3..87d9410f22 100644
--- a/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs
+++ b/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs
@@ -199,7 +199,9 @@ namespace OpenSim.Tests.Common
string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None);
InventoryFolderBase newFolder
- = new InventoryFolderBase(UUID.Random(), components[0], parentFolder.Owner, parentFolder.ID);
+ = new InventoryFolderBase(
+ UUID.Random(), components[0], parentFolder.Owner, (short)AssetType.Unknown, parentFolder.ID, 0);
+
inventoryService.AddFolder(newFolder);
if (components.Length > 1)
diff --git a/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs b/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs
new file mode 100644
index 0000000000..bca5979e50
--- /dev/null
+++ b/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSimulator Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using log4net;
+using OpenMetaverse;
+using OpenSim.Framework;
+using OpenSim.Data;
+
+namespace OpenSim.Tests.Common.Mock
+{
+ public class TestXInventoryDataPlugin : IXInventoryData
+ {
+ private Dictionary m_allFolders = new Dictionary();
+ private Dictionary m_allItems = new Dictionary();
+
+ public TestXInventoryDataPlugin(string conn, string realm) {}
+
+ public XInventoryItem[] GetItems(string[] fields, string[] vals)
+ {
+ List origItems = Get(fields, vals, m_allItems.Values.ToList());
+
+ return origItems.Select(i => i.Clone()).ToArray();
+ }
+
+ public XInventoryFolder[] GetFolders(string[] fields, string[] vals)
+ {
+ List origFolders
+ = Get(fields, vals, m_allFolders.Values.ToList());
+
+ return origFolders.Select(f => f.Clone()).ToArray();
+ }
+
+ private List Get(string[] fields, string[] vals, List inputEntities)
+ {
+ List entities = inputEntities;
+
+ for (int i = 0; i < fields.Length; i++)
+ {
+ entities
+ = entities.Where(
+ e =>
+ {
+ FieldInfo fi = typeof(T).GetField(fields[i]);
+ if (fi == null)
+ throw new NotImplementedException(string.Format("No field {0} for val {1}", fields[i], vals[i]));
+
+ return fi.GetValue(e).ToString() == vals[i];
+ }
+ ).ToList();
+ }
+
+ return entities;
+ }
+
+ public bool StoreFolder(XInventoryFolder folder)
+ {
+ m_allFolders[folder.folderID] = folder.Clone();
+
+// Console.WriteLine("Added folder {0} {1}", folder.folderName, folder.folderID);
+
+ return true;
+ }
+
+ public bool StoreItem(XInventoryItem item)
+ {
+ m_allItems[item.inventoryID] = item.Clone();
+
+// Console.WriteLine("Added item {0} {1}, creator {2}, owner {3}", item.inventoryName, item.inventoryID, item.creatorID, item.avatarID);
+
+ return true;
+ }
+
+ public bool DeleteFolders(string field, string val)
+ {
+ return DeleteFolders(new string[] { field }, new string[] { val });
+ }
+
+ public bool DeleteFolders(string[] fields, string[] vals)
+ {
+ XInventoryFolder[] foldersToDelete = GetFolders(fields, vals);
+ Array.ForEach(foldersToDelete, f => m_allFolders.Remove(f.folderID));
+
+ return true;
+ }
+
+ public bool DeleteItems(string field, string val)
+ {
+ return DeleteItems(new string[] { field }, new string[] { val });
+ }
+
+ public bool DeleteItems(string[] fields, string[] vals)
+ {
+ XInventoryItem[] itemsToDelete = GetItems(fields, vals);
+ Array.ForEach(itemsToDelete, i => m_allItems.Remove(i.inventoryID));
+
+ return true;
+ }
+
+ public bool MoveItem(string id, string newParent) { throw new NotImplementedException(); }
+ public XInventoryItem[] GetActiveGestures(UUID principalID) { throw new NotImplementedException(); }
+ public int GetAssetPermissions(UUID principalID, UUID assetID) { throw new NotImplementedException(); }
+ }
+}
\ No newline at end of file
diff --git a/OpenSim/Tests/Common/TestHelpers.cs b/OpenSim/Tests/Common/TestHelpers.cs
index 30121fef6a..57da802e6b 100644
--- a/OpenSim/Tests/Common/TestHelpers.cs
+++ b/OpenSim/Tests/Common/TestHelpers.cs
@@ -95,6 +95,7 @@ namespace OpenSim.Tests.Common
public static void EnableLogging()
{
log4net.Config.XmlConfigurator.Configure(EnableLoggingConfigStream);
+ EnableLoggingConfigStream.Position = 0;
}
///
diff --git a/OpenSim/Tests/Torture/NPCTortureTests.cs b/OpenSim/Tests/Performance/NPCPerformanceTests.cs
similarity index 98%
rename from OpenSim/Tests/Torture/NPCTortureTests.cs
rename to OpenSim/Tests/Performance/NPCPerformanceTests.cs
index 731df6808c..627765b325 100644
--- a/OpenSim/Tests/Torture/NPCTortureTests.cs
+++ b/OpenSim/Tests/Performance/NPCPerformanceTests.cs
@@ -47,10 +47,10 @@ using OpenSim.Services.AvatarService;
using OpenSim.Tests.Common;
using OpenSim.Tests.Common.Mock;
-namespace OpenSim.Tests.Torture
+namespace OpenSim.Tests.Performance
{
///
- /// NPC torture tests
+ /// NPC performance tests
///
///
/// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached,
@@ -58,7 +58,7 @@ namespace OpenSim.Tests.Torture
/// earlier tests.
///
[TestFixture]
- public class NPCTortureTests
+ public class NPCPerformanceTests
{
private TestScene scene;
private AvatarFactoryModule afm;
diff --git a/OpenSim/Tests/Torture/ObjectTortureTests.cs b/OpenSim/Tests/Performance/ObjectPerformanceTests.cs
similarity index 98%
rename from OpenSim/Tests/Torture/ObjectTortureTests.cs
rename to OpenSim/Tests/Performance/ObjectPerformanceTests.cs
index 195d47bd52..2264d86246 100644
--- a/OpenSim/Tests/Torture/ObjectTortureTests.cs
+++ b/OpenSim/Tests/Performance/ObjectPerformanceTests.cs
@@ -36,10 +36,10 @@ using OpenSim.Region.Framework.Scenes;
using OpenSim.Tests.Common;
using OpenSim.Tests.Common.Mock;
-namespace OpenSim.Tests.Torture
+namespace OpenSim.Tests.Performance
{
///
- /// Object torture tests
+ /// Object performance tests
///
///
/// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached,
@@ -47,7 +47,7 @@ namespace OpenSim.Tests.Torture
/// earlier tests.
///
[TestFixture]
- public class ObjectTortureTests
+ public class ObjectPerformanceTests
{
[TearDown]
public void TearDown()
diff --git a/OpenSim/Tests/Torture/ScriptTortureTests.cs b/OpenSim/Tests/Performance/ScriptPerformanceTests.cs
similarity index 98%
rename from OpenSim/Tests/Torture/ScriptTortureTests.cs
rename to OpenSim/Tests/Performance/ScriptPerformanceTests.cs
index 24f278f3f8..d708abd1f4 100644
--- a/OpenSim/Tests/Torture/ScriptTortureTests.cs
+++ b/OpenSim/Tests/Performance/ScriptPerformanceTests.cs
@@ -42,10 +42,10 @@ using OpenSim.Region.ScriptEngine.XEngine;
using OpenSim.Tests.Common;
using OpenSim.Tests.Common.Mock;
-namespace OpenSim.Tests.Torture
+namespace OpenSim.Tests.Performance
{
///
- /// Script torture tests
+ /// Script performance tests
///
///
/// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached,
@@ -53,7 +53,7 @@ namespace OpenSim.Tests.Torture
/// earlier tests.
///
[TestFixture]
- public class ScriptTortureTests
+ public class ScriptPerformanceTests
{
private TestScene m_scene;
private XEngine m_xEngine;
diff --git a/OpenSim/Tests/Stress/VectorRenderModuleStressTests.cs b/OpenSim/Tests/Stress/VectorRenderModuleStressTests.cs
new file mode 100644
index 0000000000..1f220c01ee
--- /dev/null
+++ b/OpenSim/Tests/Stress/VectorRenderModuleStressTests.cs
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSimulator Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Threading;
+using log4net.Config;
+using NUnit.Framework;
+using OpenMetaverse;
+using OpenMetaverse.Assets;
+using OpenSim.Framework;
+using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
+using OpenSim.Region.CoreModules.Scripting.VectorRender;
+using OpenSim.Region.Framework.Scenes;
+using OpenSim.Region.Framework.Scenes.Serialization;
+using OpenSim.Tests.Common;
+using OpenSim.Tests.Common.Mock;
+
+namespace OpenSim.Tests.Stress
+{
+ [TestFixture]
+ public class VectorRenderModuleStressTests : OpenSimTestCase
+ {
+ public Scene Scene { get; private set; }
+ public DynamicTextureModule Dtm { get; private set; }
+ public VectorRenderModule Vrm { get; private set; }
+
+ private void SetupScene(bool reuseTextures)
+ {
+ Scene = new SceneHelpers().SetupScene();
+
+ Dtm = new DynamicTextureModule();
+ Dtm.ReuseTextures = reuseTextures;
+
+ Vrm = new VectorRenderModule();
+
+ SceneHelpers.SetupSceneModules(Scene, Dtm, Vrm);
+ }
+
+ [Test]
+ public void TestConcurrentRepeatedDraw()
+ {
+ int threads = 4;
+ TestHelpers.InMethod();
+
+ SetupScene(false);
+
+ List drawers = new List();
+
+ for (int i = 0; i < threads; i++)
+ {
+ Drawer d = new Drawer(this, i);
+ drawers.Add(d);
+ Console.WriteLine("Starting drawer {0}", i);
+ Util.FireAndForget(o => d.Draw());
+ }
+
+ Thread.Sleep(10 * 60 * 1000);
+
+ drawers.ForEach(d => d.Ready = false);
+ drawers.ForEach(d => Console.WriteLine("Drawer {0} drew {1} textures", d.Number, d.Pass + 1));
+ }
+
+ class Drawer
+ {
+ public int Number { get; private set; }
+ public int Pass { get; private set; }
+ public bool Ready { get; set; }
+
+ private VectorRenderModuleStressTests m_tests;
+
+ public Drawer(VectorRenderModuleStressTests tests, int number)
+ {
+ m_tests = tests;
+ Number = number;
+ Ready = true;
+ }
+
+ public void Draw()
+ {
+ SceneObjectGroup so = SceneHelpers.AddSceneObject(m_tests.Scene);
+
+ while (Ready)
+ {
+ UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
+
+ // Ensure unique text
+ string text = string.Format("{0:D2}{1}", Number, Pass);
+
+ m_tests.Dtm.AddDynamicTextureData(
+ m_tests.Scene.RegionInfo.RegionID,
+ so.UUID,
+ m_tests.Vrm.GetContentType(),
+ string.Format("PenColour BLACK; MoveTo 40,220; FontSize 32; Text {0};", text),
+ "",
+ 0);
+
+ Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
+
+ Pass++;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/prebuild.xml b/prebuild.xml
index c626ae7493..ac03d2d383 100644
--- a/prebuild.xml
+++ b/prebuild.xml
@@ -3289,7 +3289,47 @@
-
+
+
+
+ ../../../bin/
+
+
+
+
+ ../../../bin/
+
+
+
+ ../../../bin/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
../../../bin/