aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
authorDiva Canto2014-12-25 08:01:50 -0800
committerDiva Canto2014-12-25 08:01:50 -0800
commit27c34b69bf5960e02b087f9f298dcbe19f03b142 (patch)
treef299009958858da9db464dcbc84bd03beae0ca15 /OpenSim/Region
parentRevert "Update libomv to grab latest bug fixes for Collada upload." (diff)
parentIf a moap entry has EnableWhiteList but WhiteList == null, then properly bloc... (diff)
downloadopensim-SC-27c34b69bf5960e02b087f9f298dcbe19f03b142.zip
opensim-SC-27c34b69bf5960e02b087f9f298dcbe19f03b142.tar.gz
opensim-SC-27c34b69bf5960e02b087f9f298dcbe19f03b142.tar.bz2
opensim-SC-27c34b69bf5960e02b087f9f298dcbe19f03b142.tar.xz
Merge branch 'master' of ssh://opensimulator.org/var/git/opensim
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs75
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs23
-rw-r--r--OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs109
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs8
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs15
-rw-r--r--OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs3
-rw-r--r--OpenSim/Region/Framework/Interfaces/INPCModule.cs11
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs11
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs61
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs265
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs9
-rw-r--r--OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs49
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs73
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineBasicTests.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineCrossingTests.cs195
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs148
18 files changed, 675 insertions, 390 deletions
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index fe9a17d..6564b4d 100644
--- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
@@ -256,20 +256,7 @@ namespace OpenSim.Region.CoreModules.Asset
256 // If the file is already cached, don't cache it, just touch it so access time is updated 256 // If the file is already cached, don't cache it, just touch it so access time is updated
257 if (File.Exists(filename)) 257 if (File.Exists(filename))
258 { 258 {
259 // We don't really want to know about sharing 259 UpdateFileLastAccessTime(filename);
260 // violations here. If the file is locked, then
261 // the other thread has updated the time for us.
262 try
263 {
264 lock (m_CurrentlyWriting)
265 {
266 if (!m_CurrentlyWriting.Contains(filename))
267 File.SetLastAccessTime(filename, DateTime.Now);
268 }
269 }
270 catch
271 {
272 }
273 } 260 }
274 else 261 else
275 { 262 {
@@ -329,6 +316,24 @@ namespace OpenSim.Region.CoreModules.Asset
329 } 316 }
330 317
331 /// <summary> 318 /// <summary>
319 /// Updates the cached file with the current time.
320 /// </summary>
321 /// <param name="filename">Filename.</param>
322 /// <returns><c>true</c>, if the update was successful, false otherwise.</returns>
323 private bool UpdateFileLastAccessTime(string filename)
324 {
325 try
326 {
327 File.SetLastAccessTime(filename, DateTime.Now);
328 return true;
329 }
330 catch
331 {
332 return false;
333 }
334 }
335
336 /// <summary>
332 /// Try to get an asset from the in-memory cache. 337 /// Try to get an asset from the in-memory cache.
333 /// </summary> 338 /// </summary>
334 /// <param name="id"></param> 339 /// <param name="id"></param>
@@ -771,8 +776,8 @@ namespace OpenSim.Region.CoreModules.Asset
771 { 776 {
772 UuidGatherer gatherer = new UuidGatherer(m_AssetService); 777 UuidGatherer gatherer = new UuidGatherer(m_AssetService);
773 778
774 HashSet<UUID> uniqueUuids = new HashSet<UUID>(); 779 Dictionary<UUID, sbyte> assetIdsToCheck = new Dictionary<UUID, sbyte>();
775 Dictionary<UUID, sbyte> assets = new Dictionary<UUID, sbyte>(); 780 Dictionary<UUID, bool> assetsFound = new Dictionary<UUID, bool>();
776 781
777 foreach (Scene s in m_Scenes) 782 foreach (Scene s in m_Scenes)
778 { 783 {
@@ -780,34 +785,40 @@ namespace OpenSim.Region.CoreModules.Asset
780 785
781 s.ForEachSOG(delegate(SceneObjectGroup e) 786 s.ForEachSOG(delegate(SceneObjectGroup e)
782 { 787 {
783 gatherer.GatherAssetUuids(e, assets); 788 gatherer.GatherAssetUuids(e, assetIdsToCheck);
784 789
785 foreach (UUID assetID in assets.Keys) 790 foreach (UUID assetID in assetIdsToCheck.Keys)
786 { 791 {
787 uniqueUuids.Add(assetID); 792 if (!assetsFound.ContainsKey(assetID))
788
789 string filename = GetFileName(assetID.ToString());
790
791 if (File.Exists(filename))
792 { 793 {
793 File.SetLastAccessTime(filename, DateTime.Now); 794 string filename = GetFileName(assetID.ToString());
795
796 if (File.Exists(filename))
797 {
798 UpdateFileLastAccessTime(filename);
799 }
800 else if (storeUncached)
801 {
802 AssetBase cachedAsset = m_AssetService.Get(assetID.ToString());
803 if (cachedAsset == null && assetIdsToCheck[assetID] != (sbyte)AssetType.Unknown)
804 assetsFound[assetID] = false;
805 else
806 assetsFound[assetID] = true;
807 }
794 } 808 }
795 else if (storeUncached) 809 else if (!assetsFound[assetID])
796 { 810 {
797 AssetBase cachedAsset = m_AssetService.Get(assetID.ToString()); 811 m_log.DebugFormat(
798 if (cachedAsset == null && assets[assetID] != (sbyte)AssetType.Unknown)
799 m_log.DebugFormat(
800 "[FLOTSAM ASSET CACHE]: Could not find asset {0}, type {1} referenced by object {2} at {3} in scene {4} when pre-caching all scene assets", 812 "[FLOTSAM ASSET CACHE]: Could not find asset {0}, type {1} referenced by object {2} at {3} in scene {4} when pre-caching all scene assets",
801 assetID, assets[assetID], e.Name, e.AbsolutePosition, s.Name); 813 assetID, assetIdsToCheck[assetID], e.Name, e.AbsolutePosition, s.Name);
802 } 814 }
803 } 815 }
804 816
805 assets.Clear(); 817 assetIdsToCheck.Clear();
806 }); 818 });
807 } 819 }
808 820
809 821 return assetsFound.Count;
810 return uniqueUuids.Count;
811 } 822 }
812 823
813 /// <summary> 824 /// <summary>
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index a3368fb..4af4ddb 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -255,6 +255,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
255 255
256 public void CopyAttachments(AgentData ad, IScenePresence sp) 256 public void CopyAttachments(AgentData ad, IScenePresence sp)
257 { 257 {
258// m_log.DebugFormat("[ATTACHMENTS MODULE]: Copying attachment data into {0} in {1}", sp.Name, m_scene.Name);
259
258 if (ad.AttachmentObjects != null && ad.AttachmentObjects.Count > 0) 260 if (ad.AttachmentObjects != null && ad.AttachmentObjects.Count > 0)
259 { 261 {
260 lock (sp.AttachmentsSyncLock) 262 lock (sp.AttachmentsSyncLock)
@@ -265,6 +267,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
265 { 267 {
266 ((SceneObjectGroup)so).LocalId = 0; 268 ((SceneObjectGroup)so).LocalId = 0;
267 ((SceneObjectGroup)so).RootPart.ClearUpdateSchedule(); 269 ((SceneObjectGroup)so).RootPart.ClearUpdateSchedule();
270
271// m_log.DebugFormat(
272// "[ATTACHMENTS MODULE]: Copying script state with {0} bytes for object {1} for {2} in {3}",
273// ad.AttachmentObjectStates[i].Length, so.Name, sp.Name, m_scene.Name);
274
268 so.SetState(ad.AttachmentObjectStates[i++], m_scene); 275 so.SetState(ad.AttachmentObjectStates[i++], m_scene);
269 m_scene.IncomingCreateObject(Vector3.Zero, so); 276 m_scene.IncomingCreateObject(Vector3.Zero, so);
270 } 277 }
@@ -334,11 +341,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
334 if (!Enabled) 341 if (!Enabled)
335 return; 342 return;
336 343
337 if (DebugLevel > 0)
338 m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name);
339
340 List<SceneObjectGroup> attachments = sp.GetAttachments(); 344 List<SceneObjectGroup> attachments = sp.GetAttachments();
341 345
346 if (DebugLevel > 0)
347 m_log.DebugFormat(
348 "[ATTACHMENTS MODULE]: Saving for {0} attachments for {1} in {2}",
349 attachments.Count, sp.Name, m_scene.Name);
350
342 if (attachments.Count <= 0) 351 if (attachments.Count <= 0)
343 return; 352 return;
344 353
@@ -352,6 +361,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
352 // This must be done outside the sp.AttachmentSyncLock so that there is no risk of a deadlock from 361 // This must be done outside the sp.AttachmentSyncLock so that there is no risk of a deadlock from
353 // scripts performing attachment operations at the same time. Getting object states stops the scripts. 362 // scripts performing attachment operations at the same time. Getting object states stops the scripts.
354 scriptStates[so] = PrepareScriptInstanceForSave(so, false); 363 scriptStates[so] = PrepareScriptInstanceForSave(so, false);
364
365// m_log.DebugFormat(
366// "[ATTACHMENTS MODULE]: For object {0} for {1} in {2} got saved state {3}",
367// so.Name, sp.Name, m_scene.Name, scriptStates[so]);
355 } 368 }
356 369
357 lock (sp.AttachmentsSyncLock) 370 lock (sp.AttachmentsSyncLock)
@@ -819,8 +832,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
819 { 832 {
820 if (DebugLevel > 0) 833 if (DebugLevel > 0)
821 m_log.DebugFormat( 834 m_log.DebugFormat(
822 "[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}", 835 "[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} at pt {2} pos {3} {4} in {5}",
823 so.Name, sp.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos); 836 so.Name, sp.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos, m_scene.Name);
824 837
825 // Remove from database and parcel prim count 838 // Remove from database and parcel prim count
826 m_scene.DeleteFromStorage(so.UUID); 839 m_scene.DeleteFromStorage(so.UUID);
diff --git a/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs b/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs
index 5e35135..7d2cad6 100644
--- a/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs
@@ -103,48 +103,51 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
103 return null; 103 return null;
104 104
105 int size = 0; 105 int size = 0;
106 RestClient rc = new RestClient(m_URL);
107 List<WearableCacheItem> ret = new List<WearableCacheItem>();
108 rc.AddResourcePath("bakes");
109 rc.AddResourcePath(id.ToString());
110
111 rc.RequestMethod = "GET";
112 106
113 try 107 using (RestClient rc = new RestClient(m_URL))
114 { 108 {
115 Stream s = rc.Request(m_Auth); 109 List<WearableCacheItem> ret = new List<WearableCacheItem>();
116 XmlTextReader sr = new XmlTextReader(s); 110 rc.AddResourcePath("bakes");
111 rc.AddResourcePath(id.ToString());
117 112
118 sr.ReadStartElement("BakedAppearance"); 113 rc.RequestMethod = "GET";
119 while (sr.LocalName == "BakedTexture") 114
115 try
120 { 116 {
121 string sTextureIndex = sr.GetAttribute("TextureIndex"); 117 Stream s = rc.Request(m_Auth);
122 int lTextureIndex = Convert.ToInt32(sTextureIndex); 118
123 string sCacheId = sr.GetAttribute("CacheId"); 119 using (XmlTextReader sr = new XmlTextReader(s))
124 UUID lCacheId = UUID.Zero;
125 if (!(UUID.TryParse(sCacheId, out lCacheId)))
126 { 120 {
127 // ?? Nothing here 121 sr.ReadStartElement("BakedAppearance");
122 while (sr.LocalName == "BakedTexture")
123 {
124 string sTextureIndex = sr.GetAttribute("TextureIndex");
125 int lTextureIndex = Convert.ToInt32(sTextureIndex);
126 string sCacheId = sr.GetAttribute("CacheId");
127 UUID lCacheId = UUID.Zero;
128 if (!(UUID.TryParse(sCacheId, out lCacheId)))
129 {
130 // ?? Nothing here
131 }
132
133 ++size;
134
135 sr.ReadStartElement("BakedTexture");
136 AssetBase a = (AssetBase)m_serializer.Deserialize(sr);
137 ret.Add(new WearableCacheItem() { CacheId = lCacheId, TextureIndex = (uint)lTextureIndex, TextureAsset = a, TextureID = a.FullID });
138
139 sr.ReadEndElement();
140 }
141
142 m_log.DebugFormat("[XBakes]: read {0} textures for user {1}", ret.Count, id);
128 } 143 }
129 144
130 ++size; 145 return ret.ToArray();
131 146 }
132 sr.ReadStartElement("BakedTexture"); 147 catch (XmlException)
133 AssetBase a = (AssetBase)m_serializer.Deserialize(sr); 148 {
134 ret.Add(new WearableCacheItem() { CacheId = lCacheId, TextureIndex = (uint)lTextureIndex, TextureAsset = a, TextureID = a.FullID }); 149 return null;
135
136 sr.ReadEndElement();
137 } 150 }
138 m_log.DebugFormat("[XBakes]: read {0} textures for user {1}", ret.Count, id);
139 sr.Close();
140 s.Close();
141
142
143 return ret.ToArray();
144 }
145 catch (XmlException)
146 {
147 return null;
148 } 151 }
149 } 152 }
150 153
@@ -153,27 +156,32 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
153 if (m_URL == String.Empty) 156 if (m_URL == String.Empty)
154 return; 157 return;
155 158
156 MemoryStream bakeStream = new MemoryStream(); 159 MemoryStream reqStream;
157 XmlTextWriter bakeWriter = new XmlTextWriter(bakeStream, null);
158 160
159 bakeWriter.WriteStartElement(String.Empty, "BakedAppearance", String.Empty); 161 using (MemoryStream bakeStream = new MemoryStream())
160 162 using (XmlTextWriter bakeWriter = new XmlTextWriter(bakeStream, null))
161 for (int i = 0; i < data.Length; i++)
162 { 163 {
163 if (data[i] != null) 164 bakeWriter.WriteStartElement(String.Empty, "BakedAppearance", String.Empty);
165
166 for (int i = 0; i < data.Length; i++)
164 { 167 {
165 bakeWriter.WriteStartElement(String.Empty, "BakedTexture", String.Empty); 168 if (data[i] != null)
166 bakeWriter.WriteAttributeString(String.Empty, "TextureIndex", String.Empty, data[i].TextureIndex.ToString()); 169 {
167 bakeWriter.WriteAttributeString(String.Empty, "CacheId", String.Empty, data[i].CacheId.ToString()); 170 bakeWriter.WriteStartElement(String.Empty, "BakedTexture", String.Empty);
168 if (data[i].TextureAsset != null) 171 bakeWriter.WriteAttributeString(String.Empty, "TextureIndex", String.Empty, data[i].TextureIndex.ToString());
169 m_serializer.Serialize(bakeWriter, data[i].TextureAsset); 172 bakeWriter.WriteAttributeString(String.Empty, "CacheId", String.Empty, data[i].CacheId.ToString());
173 if (data[i].TextureAsset != null)
174 m_serializer.Serialize(bakeWriter, data[i].TextureAsset);
170 175
171 bakeWriter.WriteEndElement(); 176 bakeWriter.WriteEndElement();
177 }
172 } 178 }
173 }
174 179
175 bakeWriter.WriteEndElement(); 180 bakeWriter.WriteEndElement();
176 bakeWriter.Flush(); 181 bakeWriter.Flush();
182
183 reqStream = new MemoryStream(bakeStream.ToArray());
184 }
177 185
178 RestClient rc = new RestClient(m_URL); 186 RestClient rc = new RestClient(m_URL);
179 rc.AddResourcePath("bakes"); 187 rc.AddResourcePath("bakes");
@@ -181,7 +189,6 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
181 189
182 rc.RequestMethod = "POST"; 190 rc.RequestMethod = "POST";
183 191
184 MemoryStream reqStream = new MemoryStream(bakeStream.ToArray());
185 Util.FireAndForget( 192 Util.FireAndForget(
186 delegate 193 delegate
187 { 194 {
@@ -191,4 +198,4 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
191 ); 198 );
192 } 199 }
193 } 200 }
194} 201} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
index 97267c1..2ddb599 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
@@ -604,8 +604,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
604 // "[HG ENTITY TRANSFER MODULE]: Incoming attachment {0} for HG user {1} with asset service {2}", 604 // "[HG ENTITY TRANSFER MODULE]: Incoming attachment {0} for HG user {1} with asset service {2}",
605 // so.Name, so.AttachedAvatar, url); 605 // so.Name, so.AttachedAvatar, url);
606 606
607 IteratingHGUuidGatherer uuidGatherer = new IteratingHGUuidGatherer(Scene.AssetService, url); 607 IDictionary<UUID, sbyte> ids = new Dictionary<UUID, sbyte>();
608 uuidGatherer.RecordAssetUuids(so); 608 IteratingHGUuidGatherer uuidGatherer
609 = new IteratingHGUuidGatherer(Scene.AssetService, url, ids);
610 uuidGatherer.AddForInspection(so);
609 611
610 while (!uuidGatherer.Complete) 612 while (!uuidGatherer.Complete)
611 { 613 {
@@ -632,8 +634,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
632 } 634 }
633 } 635 }
634 636
635 IDictionary<UUID, sbyte> ids = uuidGatherer.GetGatheredUuids();
636
637 // m_log.DebugFormat( 637 // m_log.DebugFormat(
638 // "[HG ENTITY TRANSFER]: Fetching {0} assets for attachment {1} for HG user {2} with asset service {3}", 638 // "[HG ENTITY TRANSFER]: Fetching {0} assets for attachment {1} for HG user {2} with asset service {3}",
639 // ids.Count, so.Name, so.OwnerID, url); 639 // ids.Count, so.Name, so.OwnerID, url);
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
index 9bf7885..6479430 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
@@ -680,6 +680,21 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
680 "Show the bindings between user UUIDs and user names", 680 "Show the bindings between user UUIDs and user names",
681 String.Empty, 681 String.Empty,
682 HandleShowUsers); 682 HandleShowUsers);
683
684 MainConsole.Instance.Commands.AddCommand("Users", true,
685 "reset user cache",
686 "reset user cache",
687 "reset user cache to allow changed settings to be applied",
688 String.Empty,
689 HandleResetUserCache);
690 }
691
692 private void HandleResetUserCache(string module, string[] cmd)
693 {
694 lock(m_UserCache)
695 {
696 m_UserCache.Clear();
697 }
683 } 698 }
684 699
685 private void HandleShowUser(string module, string[] cmd) 700 private void HandleShowUser(string module, string[] cmd)
diff --git a/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs b/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs
index 601e81e..46b0470 100644
--- a/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs
+++ b/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs
@@ -595,6 +595,9 @@ namespace OpenSim.Region.CoreModules.World.Media.Moap
595 /// <returns>true if the url matches an entry on the whitelist, false otherwise</returns> 595 /// <returns>true if the url matches an entry on the whitelist, false otherwise</returns>
596 protected bool CheckUrlAgainstWhitelist(string rawUrl, string[] whitelist) 596 protected bool CheckUrlAgainstWhitelist(string rawUrl, string[] whitelist)
597 { 597 {
598 if (whitelist == null)
599 return false;
600
598 Uri url = new Uri(rawUrl); 601 Uri url = new Uri(rawUrl);
599 602
600 foreach (string origWlUrl in whitelist) 603 foreach (string origWlUrl in whitelist)
diff --git a/OpenSim/Region/Framework/Interfaces/INPCModule.cs b/OpenSim/Region/Framework/Interfaces/INPCModule.cs
index d5dcddd..478833e 100644
--- a/OpenSim/Region/Framework/Interfaces/INPCModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/INPCModule.cs
@@ -122,6 +122,17 @@ namespace OpenSim.Region.Framework.Interfaces
122 /// <summary> 122 /// <summary>
123 /// Check if the caller has permission to manipulate the given NPC. 123 /// Check if the caller has permission to manipulate the given NPC.
124 /// </summary> 124 /// </summary>
125 /// <remarks>
126 /// A caller has permission if
127 /// * An NPC exists with the given npcID.
128 /// * The caller UUID given is UUID.Zero.
129 /// * The avatar is unowned (owner is UUID.Zero).
130 /// * The avatar is owned and the owner and callerID match.
131 /// * The avatar is owned and the callerID matches its agentID.
132 /// </remarks>
133 /// <param name="av"></param>
134 /// <param name="callerID"></param>
135 /// <returns>true if they do, false if they don't.</returns>
125 /// <param name="npcID"></param> 136 /// <param name="npcID"></param>
126 /// <param name="callerID"></param> 137 /// <param name="callerID"></param>
127 /// <returns> 138 /// <returns>
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index f7c12d6..21d47aa 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -823,7 +823,6 @@ namespace OpenSim.Region.Framework.Scenes
823 m_sceneGridService = sceneGridService; 823 m_sceneGridService = sceneGridService;
824 m_SimulationDataService = simDataService; 824 m_SimulationDataService = simDataService;
825 m_EstateDataService = estateDataService; 825 m_EstateDataService = estateDataService;
826 m_regionHandle = RegionInfo.RegionHandle;
827 826
828 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this); 827 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this);
829 m_asyncSceneObjectDeleter.Enabled = true; 828 m_asyncSceneObjectDeleter.Enabled = true;
@@ -2042,11 +2041,11 @@ namespace OpenSim.Region.Framework.Scenes
2042 2041
2043 GridRegion region = new GridRegion(RegionInfo); 2042 GridRegion region = new GridRegion(RegionInfo);
2044 string error = GridService.RegisterRegion(RegionInfo.ScopeID, region); 2043 string error = GridService.RegisterRegion(RegionInfo.ScopeID, region);
2045 m_log.DebugFormat("{0} RegisterRegionWithGrid. name={1},id={2},loc=<{3},{4}>,size=<{5},{6}>", 2044// m_log.DebugFormat("[SCENE]: RegisterRegionWithGrid. name={0},id={1},loc=<{2},{3}>,size=<{4},{5}>",
2046 LogHeader, m_regionName, 2045// m_regionName,
2047 RegionInfo.RegionID, 2046// RegionInfo.RegionID,
2048 RegionInfo.RegionLocX, RegionInfo.RegionLocY, 2047// RegionInfo.RegionLocX, RegionInfo.RegionLocY,
2049 RegionInfo.RegionSizeX, RegionInfo.RegionSizeY); 2048// RegionInfo.RegionSizeX, RegionInfo.RegionSizeY);
2050 2049
2051 if (error != String.Empty) 2050 if (error != String.Empty)
2052 throw new Exception(error); 2051 throw new Exception(error);
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index aaddce6..6f172e7 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -145,10 +145,6 @@ namespace OpenSim.Region.Framework.Scenes
145 get { return 1.0f; } 145 get { return 1.0f; }
146 } 146 }
147 147
148 protected ulong m_regionHandle;
149 protected string m_regionName;
150 protected RegionInfo m_regInfo;
151
152 public ITerrainChannel Heightmap; 148 public ITerrainChannel Heightmap;
153 149
154 /// <value> 150 /// <value>
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 93dfd00..0414f89 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -1228,45 +1228,27 @@ namespace OpenSim.Region.Framework.Scenes
1228 1228
1229 m_scene.SwapRootAgentCount(false); 1229 m_scene.SwapRootAgentCount(false);
1230 1230
1231 // The initial login scene presence is already root when it gets here 1231 if (Scene.AttachmentsModule != null)
1232 // and it has already rezzed the attachments and started their scripts. 1232 {
1233 // We do the following only for non-login agents, because their scripts 1233 // The initial login scene presence is already root when it gets here
1234 // haven't started yet. 1234 // and it has already rezzed the attachments and started their scripts.
1235 if (PresenceType == PresenceType.Npc || IsRealLogin(m_teleportFlags)) 1235 // We do the following only for non-login agents, because their scripts
1236 { 1236 // haven't started yet.
1237 // Viewers which have a current outfit folder will actually rez their own attachments. However, 1237 if (PresenceType == PresenceType.Npc || IsRealLogin(m_teleportFlags))
1238 // viewers without (e.g. v1 viewers) will not, so we still need to make this call.
1239 if (Scene.AttachmentsModule != null)
1240 { 1238 {
1239 // Viewers which have a current outfit folder will actually rez their own attachments. However,
1240 // viewers without (e.g. v1 viewers) will not, so we still need to make this call.
1241 WorkManager.RunJob( 1241 WorkManager.RunJob(
1242 "RezAttachments", 1242 "RezAttachments",
1243 o => Scene.AttachmentsModule.RezAttachments(this), 1243 o => Scene.AttachmentsModule.RezAttachments(this),
1244 null, 1244 null,
1245 string.Format("Rez attachments for {0} in {1}", Name, Scene.Name)); 1245 string.Format("Rez attachments for {0} in {1}", Name, Scene.Name));
1246 } 1246 }
1247 } 1247 else
1248 else
1249 {
1250 // We need to restart scripts here so that they receive the correct changed events (CHANGED_TELEPORT
1251 // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently
1252 // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are
1253 // not transporting the required data.
1254 //
1255 // We must take a copy of the attachments list here (rather than locking) to avoid a deadlock where a script in one of
1256 // the attachments may start processing an event (which locks ScriptInstance.m_Script) that then calls a method here
1257 // which needs to lock m_attachments. ResumeScripts() needs to take a ScriptInstance.m_Script lock to try to unset the Suspend status.
1258 //
1259 // FIXME: In theory, this deadlock should not arise since scripts should not be processing events until ResumeScripts().
1260 // But XEngine starts all scripts unsuspended. Starting them suspended will not currently work because script rezzing
1261 // is placed in an asynchronous queue in XEngine and so the ResumeScripts() call will almost certainly execute before the
1262 // script is rezzed. This means the ResumeScripts() does absolutely nothing when using XEngine.
1263 List<SceneObjectGroup> attachments = GetAttachments();
1264
1265 if (attachments.Count > 0)
1266 { 1248 {
1267 WorkManager.RunJob( 1249 WorkManager.RunJob(
1268 "StartAttachmentScripts", 1250 "StartAttachmentScripts",
1269 o => RestartAttachmentScripts(attachments), 1251 o => RestartAttachmentScripts(),
1270 null, 1252 null,
1271 string.Format("Start attachment scripts for {0} in {1}", Name, Scene.Name), 1253 string.Format("Start attachment scripts for {0} in {1}", Name, Scene.Name),
1272 true); 1254 true);
@@ -1292,10 +1274,25 @@ namespace OpenSim.Region.Framework.Scenes
1292 return true; 1274 return true;
1293 } 1275 }
1294 1276
1295 private void RestartAttachmentScripts(List<SceneObjectGroup> attachments) 1277 private void RestartAttachmentScripts()
1296 { 1278 {
1279 // We need to restart scripts here so that they receive the correct changed events (CHANGED_TELEPORT
1280 // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently
1281 // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are
1282 // not transporting the required data.
1283 //
1284 // We must take a copy of the attachments list here (rather than locking) to avoid a deadlock where a script in one of
1285 // the attachments may start processing an event (which locks ScriptInstance.m_Script) that then calls a method here
1286 // which needs to lock m_attachments. ResumeScripts() needs to take a ScriptInstance.m_Script lock to try to unset the Suspend status.
1287 //
1288 // FIXME: In theory, this deadlock should not arise since scripts should not be processing events until ResumeScripts().
1289 // But XEngine starts all scripts unsuspended. Starting them suspended will not currently work because script rezzing
1290 // is placed in an asynchronous queue in XEngine and so the ResumeScripts() call will almost certainly execute before the
1291 // script is rezzed. This means the ResumeScripts() does absolutely nothing when using XEngine.
1292 List<SceneObjectGroup> attachments = GetAttachments();
1293
1297 m_log.DebugFormat( 1294 m_log.DebugFormat(
1298 "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name); 1295 "[SCENE PRESENCE]: Restarting scripts in {0} attachments for {1} in {2}", attachments.Count, Name, Scene.Name);
1299 1296
1300 // Resume scripts 1297 // Resume scripts
1301 foreach (SceneObjectGroup sog in attachments) 1298 foreach (SceneObjectGroup sog in attachments)
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index 2450cdb..2c5353f 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -648,6 +648,15 @@ namespace OpenSim.Region.Framework.Scenes
648 } 648 }
649 } 649 }
650 650
651 /// <summary>
652 /// Gather uuids for a given entity.
653 /// </summary>
654 /// <remarks>
655 /// This does a deep inspection of the entity to retrieve all the assets it uses (whether as textures, as scripts
656 /// contained in inventory, as scripts contained in objects contained in another object's inventory, etc. Assets
657 /// are only retrieved when they are necessary to carry out the inspection (i.e. a serialized object needs to be
658 /// retrieved to work out which assets it references).
659 /// </remarks>
651 public class IteratingUuidGatherer 660 public class IteratingUuidGatherer
652 { 661 {
653 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 662 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -678,21 +687,31 @@ namespace OpenSim.Region.Framework.Scenes
678 687
679 protected Queue<UUID> m_assetUuidsToInspect; 688 protected Queue<UUID> m_assetUuidsToInspect;
680 689
681 public IteratingUuidGatherer(IAssetService assetService) 690 /// <summary>
691 /// Initializes a new instance of the <see cref="OpenSim.Region.Framework.Scenes.UuidGatherer"/> class.
692 /// </summary>
693 /// <param name="assetService">
694 /// Asset service.
695 /// </param>
696 /// <param name="collector">
697 /// Gathered UUIDs will be collected in this dictinaory.
698 /// It can be pre-populated if you want to stop the gatherer from analyzing assets that have already been fetched and inspected.
699 /// </param>
700 public IteratingUuidGatherer(IAssetService assetService, IDictionary<UUID, sbyte> collector)
682 { 701 {
683 m_assetService = assetService; 702 m_assetService = assetService;
684 m_gatheredAssetUuids = new Dictionary<UUID, sbyte>(); 703 m_gatheredAssetUuids = collector;
685 704
686 // FIXME: Not efficient for searching, can improve. 705 // FIXME: Not efficient for searching, can improve.
687 m_assetUuidsToInspect = new Queue<UUID>(); 706 m_assetUuidsToInspect = new Queue<UUID>();
688 } 707 }
689 708
690 public IDictionary<UUID, sbyte> GetGatheredUuids() 709 /// <summary>
691 { 710 /// Adds the asset uuid for inspection during the gathering process.
692 return new Dictionary<UUID, sbyte>(m_gatheredAssetUuids); 711 /// </summary>
693 } 712 /// <returns><c>true</c>, if for inspection was added, <c>false</c> otherwise.</returns>
694 713 /// <param name="uuid">UUID.</param>
695 public bool AddAssetUuidToInspect(UUID uuid) 714 public bool AddForInspection(UUID uuid)
696 { 715 {
697 if (m_assetUuidsToInspect.Contains(uuid)) 716 if (m_assetUuidsToInspect.Contains(uuid))
698 return false; 717 return false;
@@ -701,6 +720,107 @@ namespace OpenSim.Region.Framework.Scenes
701 720
702 return true; 721 return true;
703 } 722 }
723
724 /// <summary>
725 /// Gather all the asset uuids associated with a given object.
726 /// </summary>
727 /// <remarks>
728 /// This includes both those directly associated with
729 /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained
730 /// within this object).
731 /// </remarks>
732 /// <param name="sceneObject">The scene object for which to gather assets</param>
733 public void AddForInspection(SceneObjectGroup sceneObject)
734 {
735 // m_log.DebugFormat(
736 // "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID);
737
738 SceneObjectPart[] parts = sceneObject.Parts;
739 for (int i = 0; i < parts.Length; i++)
740 {
741 SceneObjectPart part = parts[i];
742
743 // m_log.DebugFormat(
744 // "[ARCHIVER]: Getting part {0}, {1} for object {2}", part.Name, part.UUID, sceneObject.UUID);
745
746 try
747 {
748 Primitive.TextureEntry textureEntry = part.Shape.Textures;
749 if (textureEntry != null)
750 {
751 // Get the prim's default texture. This will be used for faces which don't have their own texture
752 if (textureEntry.DefaultTexture != null)
753 RecordTextureEntryAssetUuids(textureEntry.DefaultTexture);
754
755 if (textureEntry.FaceTextures != null)
756 {
757 // Loop through the rest of the texture faces (a non-null face means the face is different from DefaultTexture)
758 foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures)
759 {
760 if (texture != null)
761 RecordTextureEntryAssetUuids(texture);
762 }
763 }
764 }
765
766 // If the prim is a sculpt then preserve this information too
767 if (part.Shape.SculptTexture != UUID.Zero)
768 m_gatheredAssetUuids[part.Shape.SculptTexture] = (sbyte)AssetType.Texture;
769
770 if (part.Shape.ProjectionTextureUUID != UUID.Zero)
771 m_gatheredAssetUuids[part.Shape.ProjectionTextureUUID] = (sbyte)AssetType.Texture;
772
773 if (part.CollisionSound != UUID.Zero)
774 m_gatheredAssetUuids[part.CollisionSound] = (sbyte)AssetType.Sound;
775
776 if (part.ParticleSystem.Length > 0)
777 {
778 try
779 {
780 Primitive.ParticleSystem ps = new Primitive.ParticleSystem(part.ParticleSystem, 0);
781 if (ps.Texture != UUID.Zero)
782 m_gatheredAssetUuids[ps.Texture] = (sbyte)AssetType.Texture;
783 }
784 catch (Exception)
785 {
786 m_log.WarnFormat(
787 "[UUID GATHERER]: Could not check particle system for part {0} {1} in object {2} {3} since it is corrupt. Continuing.",
788 part.Name, part.UUID, sceneObject.Name, sceneObject.UUID);
789 }
790 }
791
792 TaskInventoryDictionary taskDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone();
793
794 // Now analyze this prim's inventory items to preserve all the uuids that they reference
795 foreach (TaskInventoryItem tii in taskDictionary.Values)
796 {
797 // m_log.DebugFormat(
798 // "[ARCHIVER]: Analysing item {0} asset type {1} in {2} {3}",
799 // tii.Name, tii.Type, part.Name, part.UUID);
800
801 if (!m_gatheredAssetUuids.ContainsKey(tii.AssetID))
802 AddForInspection(tii.AssetID, (sbyte)tii.Type);
803 }
804
805 // FIXME: We need to make gathering modular but we cannot yet, since gatherers are not guaranteed
806 // to be called with scene objects that are in a scene (e.g. in the case of hg asset mapping and
807 // inventory transfer. There needs to be a way for a module to register a method without assuming a
808 // Scene.EventManager is present.
809 // part.ParentGroup.Scene.EventManager.TriggerGatherUuids(part, assetUuids);
810
811
812 // still needed to retrieve textures used as materials for any parts containing legacy materials stored in DynAttrs
813 RecordMaterialsUuids(part);
814 }
815 catch (Exception e)
816 {
817 m_log.ErrorFormat("[UUID GATHERER]: Failed to get part - {0}", e);
818 m_log.DebugFormat(
819 "[UUID GATHERER]: Texture entry length for prim was {0} (min is 46)",
820 part.Shape.TextureEntry.Length);
821 }
822 }
823 }
704 824
705 /// <summary> 825 /// <summary>
706 /// Gathers the next set of assets returned by the next uuid to get from the asset service. 826 /// Gathers the next set of assets returned by the next uuid to get from the asset service.
@@ -790,7 +910,7 @@ namespace OpenSim.Region.Framework.Scenes
790 } 910 }
791 } 911 }
792 912
793 private void RecordAssetUuids(UUID assetUuid, sbyte assetType) 913 private void AddForInspection(UUID assetUuid, sbyte assetType)
794 { 914 {
795 // Here, we want to collect uuids which require further asset fetches but mark the others as gathered 915 // Here, we want to collect uuids which require further asset fetches but mark the others as gathered
796 try 916 try
@@ -799,27 +919,27 @@ namespace OpenSim.Region.Framework.Scenes
799 919
800 if ((sbyte)AssetType.Bodypart == assetType || (sbyte)AssetType.Clothing == assetType) 920 if ((sbyte)AssetType.Bodypart == assetType || (sbyte)AssetType.Clothing == assetType)
801 { 921 {
802 AddAssetUuidToInspect(assetUuid); 922 AddForInspection(assetUuid);
803 } 923 }
804 else if ((sbyte)AssetType.Gesture == assetType) 924 else if ((sbyte)AssetType.Gesture == assetType)
805 { 925 {
806 AddAssetUuidToInspect(assetUuid); 926 AddForInspection(assetUuid);
807 } 927 }
808 else if ((sbyte)AssetType.Notecard == assetType) 928 else if ((sbyte)AssetType.Notecard == assetType)
809 { 929 {
810 AddAssetUuidToInspect(assetUuid); 930 AddForInspection(assetUuid);
811 } 931 }
812 else if ((sbyte)AssetType.LSLText == assetType) 932 else if ((sbyte)AssetType.LSLText == assetType)
813 { 933 {
814 AddAssetUuidToInspect(assetUuid); 934 AddForInspection(assetUuid);
815 } 935 }
816 else if ((sbyte)OpenSimAssetType.Material == assetType) 936 else if ((sbyte)OpenSimAssetType.Material == assetType)
817 { 937 {
818 AddAssetUuidToInspect(assetUuid); 938 AddForInspection(assetUuid);
819 } 939 }
820 else if ((sbyte)AssetType.Object == assetType) 940 else if ((sbyte)AssetType.Object == assetType)
821 { 941 {
822 AddAssetUuidToInspect(assetUuid); 942 AddForInspection(assetUuid);
823 } 943 }
824 } 944 }
825 catch (Exception) 945 catch (Exception)
@@ -832,107 +952,6 @@ namespace OpenSim.Region.Framework.Scenes
832 } 952 }
833 953
834 /// <summary> 954 /// <summary>
835 /// Gather all the asset uuids associated with a given object.
836 /// </summary>
837 /// <remarks>
838 /// This includes both those directly associated with
839 /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained
840 /// within this object).
841 /// </remarks>
842 /// <param name="sceneObject">The scene object for which to gather assets</param>
843 public void RecordAssetUuids(SceneObjectGroup sceneObject)
844 {
845 // m_log.DebugFormat(
846 // "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID);
847
848 SceneObjectPart[] parts = sceneObject.Parts;
849 for (int i = 0; i < parts.Length; i++)
850 {
851 SceneObjectPart part = parts[i];
852
853 // m_log.DebugFormat(
854 // "[ARCHIVER]: Getting part {0}, {1} for object {2}", part.Name, part.UUID, sceneObject.UUID);
855
856 try
857 {
858 Primitive.TextureEntry textureEntry = part.Shape.Textures;
859 if (textureEntry != null)
860 {
861 // Get the prim's default texture. This will be used for faces which don't have their own texture
862 if (textureEntry.DefaultTexture != null)
863 RecordTextureEntryAssetUuids(textureEntry.DefaultTexture);
864
865 if (textureEntry.FaceTextures != null)
866 {
867 // Loop through the rest of the texture faces (a non-null face means the face is different from DefaultTexture)
868 foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures)
869 {
870 if (texture != null)
871 RecordTextureEntryAssetUuids(texture);
872 }
873 }
874 }
875
876 // If the prim is a sculpt then preserve this information too
877 if (part.Shape.SculptTexture != UUID.Zero)
878 m_gatheredAssetUuids[part.Shape.SculptTexture] = (sbyte)AssetType.Texture;
879
880 if (part.Shape.ProjectionTextureUUID != UUID.Zero)
881 m_gatheredAssetUuids[part.Shape.ProjectionTextureUUID] = (sbyte)AssetType.Texture;
882
883 if (part.CollisionSound != UUID.Zero)
884 m_gatheredAssetUuids[part.CollisionSound] = (sbyte)AssetType.Sound;
885
886 if (part.ParticleSystem.Length > 0)
887 {
888 try
889 {
890 Primitive.ParticleSystem ps = new Primitive.ParticleSystem(part.ParticleSystem, 0);
891 if (ps.Texture != UUID.Zero)
892 m_gatheredAssetUuids[ps.Texture] = (sbyte)AssetType.Texture;
893 }
894 catch (Exception)
895 {
896 m_log.WarnFormat(
897 "[UUID GATHERER]: Could not check particle system for part {0} {1} in object {2} {3} since it is corrupt. Continuing.",
898 part.Name, part.UUID, sceneObject.Name, sceneObject.UUID);
899 }
900 }
901
902 TaskInventoryDictionary taskDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone();
903
904 // Now analyze this prim's inventory items to preserve all the uuids that they reference
905 foreach (TaskInventoryItem tii in taskDictionary.Values)
906 {
907 // m_log.DebugFormat(
908 // "[ARCHIVER]: Analysing item {0} asset type {1} in {2} {3}",
909 // tii.Name, tii.Type, part.Name, part.UUID);
910
911 if (!m_gatheredAssetUuids.ContainsKey(tii.AssetID))
912 RecordAssetUuids(tii.AssetID, (sbyte)tii.Type);
913 }
914
915 // FIXME: We need to make gathering modular but we cannot yet, since gatherers are not guaranteed
916 // to be called with scene objects that are in a scene (e.g. in the case of hg asset mapping and
917 // inventory transfer. There needs to be a way for a module to register a method without assuming a
918 // Scene.EventManager is present.
919 // part.ParentGroup.Scene.EventManager.TriggerGatherUuids(part, assetUuids);
920
921
922 // still needed to retrieve textures used as materials for any parts containing legacy materials stored in DynAttrs
923 RecordMaterialsUuids(part);
924 }
925 catch (Exception e)
926 {
927 m_log.ErrorFormat("[UUID GATHERER]: Failed to get part - {0}", e);
928 m_log.DebugFormat(
929 "[UUID GATHERER]: Texture entry length for prim was {0} (min is 46)",
930 part.Shape.TextureEntry.Length);
931 }
932 }
933 }
934
935 /// <summary>
936 /// Collect all the asset uuids found in one face of a Texture Entry. 955 /// Collect all the asset uuids found in one face of a Texture Entry.
937 /// </summary> 956 /// </summary>
938 private void RecordTextureEntryAssetUuids(Primitive.TextureEntryFace texture) 957 private void RecordTextureEntryAssetUuids(Primitive.TextureEntryFace texture)
@@ -940,7 +959,7 @@ namespace OpenSim.Region.Framework.Scenes
940 m_gatheredAssetUuids[texture.TextureID] = (sbyte)AssetType.Texture; 959 m_gatheredAssetUuids[texture.TextureID] = (sbyte)AssetType.Texture;
941 960
942 if (texture.MaterialID != UUID.Zero) 961 if (texture.MaterialID != UUID.Zero)
943 AddAssetUuidToInspect(texture.MaterialID); 962 AddForInspection(texture.MaterialID);
944 } 963 }
945 964
946 /// <summary> 965 /// <summary>
@@ -948,7 +967,7 @@ namespace OpenSim.Region.Framework.Scenes
948 /// stored in legacy format in part.DynAttrs 967 /// stored in legacy format in part.DynAttrs
949 /// </summary> 968 /// </summary>
950 /// <param name="part"></param> 969 /// <param name="part"></param>
951 public void RecordMaterialsUuids(SceneObjectPart part) 970 private void RecordMaterialsUuids(SceneObjectPart part)
952 { 971 {
953 // scan thru the dynAttrs map of this part for any textures used as materials 972 // scan thru the dynAttrs map of this part for any textures used as materials
954 OSD osdMaterials = null; 973 OSD osdMaterials = null;
@@ -1039,7 +1058,7 @@ namespace OpenSim.Region.Framework.Scenes
1039 UUID uuid = new UUID(uuidMatch.Value); 1058 UUID uuid = new UUID(uuidMatch.Value);
1040 // m_log.DebugFormat("[ARCHIVER]: Recording {0} in text", uuid); 1059 // m_log.DebugFormat("[ARCHIVER]: Recording {0} in text", uuid);
1041 1060
1042 AddAssetUuidToInspect(uuid); 1061 AddForInspection(uuid);
1043 } 1062 }
1044 } 1063 }
1045 1064
@@ -1074,14 +1093,14 @@ namespace OpenSim.Region.Framework.Scenes
1074 if (CoalescedSceneObjectsSerializer.TryFromXml(xml, out coa)) 1093 if (CoalescedSceneObjectsSerializer.TryFromXml(xml, out coa))
1075 { 1094 {
1076 foreach (SceneObjectGroup sog in coa.Objects) 1095 foreach (SceneObjectGroup sog in coa.Objects)
1077 RecordAssetUuids(sog); 1096 AddForInspection(sog);
1078 } 1097 }
1079 else 1098 else
1080 { 1099 {
1081 SceneObjectGroup sog = SceneObjectSerializer.FromOriginalXmlFormat(xml); 1100 SceneObjectGroup sog = SceneObjectSerializer.FromOriginalXmlFormat(xml);
1082 1101
1083 if (null != sog) 1102 if (null != sog)
1084 RecordAssetUuids(sog); 1103 AddForInspection(sog);
1085 } 1104 }
1086 } 1105 }
1087 1106
@@ -1147,8 +1166,8 @@ namespace OpenSim.Region.Framework.Scenes
1147 1166
1148 protected string m_assetServerURL; 1167 protected string m_assetServerURL;
1149 1168
1150 public IteratingHGUuidGatherer(IAssetService assetService, string assetServerURL) 1169 public IteratingHGUuidGatherer(IAssetService assetService, string assetServerURL, IDictionary<UUID, sbyte> collector)
1151 : base(assetService) 1170 : base(assetService, collector)
1152 { 1171 {
1153 m_assetServerURL = assetServerURL; 1172 m_assetServerURL = assetServerURL;
1154 if (!m_assetServerURL.EndsWith("/") && !m_assetServerURL.EndsWith("=")) 1173 if (!m_assetServerURL.EndsWith("/") && !m_assetServerURL.EndsWith("="))
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
index 95e59ab..b834619 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
@@ -441,13 +441,20 @@ namespace OpenSim.Region.OptionalModules.World.NPC
441 /// <summary> 441 /// <summary>
442 /// Check if the caller has permission to manipulate the given NPC. 442 /// Check if the caller has permission to manipulate the given NPC.
443 /// </summary> 443 /// </summary>
444 /// <remarks>
445 /// A caller has permission if
446 /// * The caller UUID given is UUID.Zero.
447 /// * The avatar is unowned (owner is UUID.Zero).
448 /// * The avatar is owned and the owner and callerID match.
449 /// * The avatar is owned and the callerID matches its agentID.
450 /// </remarks>
444 /// <param name="av"></param> 451 /// <param name="av"></param>
445 /// <param name="callerID"></param> 452 /// <param name="callerID"></param>
446 /// <returns>true if they do, false if they don't.</returns> 453 /// <returns>true if they do, false if they don't.</returns>
447 private bool CheckPermissions(NPCAvatar av, UUID callerID) 454 private bool CheckPermissions(NPCAvatar av, UUID callerID)
448 { 455 {
449 return callerID == UUID.Zero || av.OwnerID == UUID.Zero || 456 return callerID == UUID.Zero || av.OwnerID == UUID.Zero ||
450 av.OwnerID == callerID; 457 av.OwnerID == callerID || av.AgentId == callerID;
451 } 458 }
452 } 459 }
453} \ No newline at end of file 460} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
index b9a217b..1097efb 100644
--- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
@@ -222,7 +222,7 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
222 void SetVars(Dictionary<string, object> vars); 222 void SetVars(Dictionary<string, object> vars);
223 DetectParams GetDetectParams(int idx); 223 DetectParams GetDetectParams(int idx);
224 UUID GetDetectID(int idx); 224 UUID GetDetectID(int idx);
225 void SaveState(string assembly); 225 void SaveState();
226 void DestroyScriptInstance(); 226 void DestroyScriptInstance();
227 227
228 IScriptApi GetApi(string name); 228 IScriptApi GetApi(string name);
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
index 9379f8f..de5f92d 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
@@ -663,9 +663,8 @@ namespace SecondLife
663 663
664 try 664 try
665 { 665 {
666 FileStream fs = File.Open(assembly, FileMode.Open, FileAccess.Read); 666 using (FileStream fs = File.Open(assembly, FileMode.Open, FileAccess.Read))
667 fs.Read(data, 0, data.Length); 667 fs.Read(data, 0, data.Length);
668 fs.Close();
669 } 668 }
670 catch (Exception) 669 catch (Exception)
671 { 670 {
@@ -680,9 +679,8 @@ namespace SecondLife
680 679
681 Byte[] buf = Encoding.ASCII.GetBytes(filetext); 680 Byte[] buf = Encoding.ASCII.GetBytes(filetext);
682 681
683 FileStream sfs = File.Create(assembly + ".text"); 682 using (FileStream sfs = File.Create(assembly + ".text"))
684 sfs.Write(buf, 0, buf.Length); 683 sfs.Write(buf, 0, buf.Length);
685 sfs.Close();
686 684
687 return assembly; 685 return assembly;
688 } 686 }
@@ -775,7 +773,6 @@ namespace SecondLife
775 return message; 773 return message;
776 } 774 }
777 775
778
779 private static void WriteMapFile(string filename, Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> linemap) 776 private static void WriteMapFile(string filename, Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> linemap)
780 { 777 {
781 string mapstring = String.Empty; 778 string mapstring = String.Empty;
@@ -787,40 +784,42 @@ namespace SecondLife
787 } 784 }
788 785
789 Byte[] mapbytes = Encoding.ASCII.GetBytes(mapstring); 786 Byte[] mapbytes = Encoding.ASCII.GetBytes(mapstring);
790 FileStream mfs = File.Create(filename);
791 mfs.Write(mapbytes, 0, mapbytes.Length);
792 mfs.Close();
793 }
794 787
788 using (FileStream mfs = File.Create(filename))
789 mfs.Write(mapbytes, 0, mapbytes.Length);
790 }
795 791
796 private static Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> ReadMapFile(string filename) 792 private static Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> ReadMapFile(string filename)
797 { 793 {
798 Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> linemap; 794 Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> linemap;
799 try 795 try
800 { 796 {
801 StreamReader r = File.OpenText(filename); 797 using (StreamReader r = File.OpenText(filename))
802 linemap = new Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>>();
803
804 string line;
805 while ((line = r.ReadLine()) != null)
806 { 798 {
807 String[] parts = line.Split(new Char[] { ',' }); 799 linemap = new Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>>();
808 int kk = System.Convert.ToInt32(parts[0]);
809 int kv = System.Convert.ToInt32(parts[1]);
810 int vk = System.Convert.ToInt32(parts[2]);
811 int vv = System.Convert.ToInt32(parts[3]);
812 800
813 KeyValuePair<int, int> k = new KeyValuePair<int, int>(kk, kv); 801 string line;
814 KeyValuePair<int, int> v = new KeyValuePair<int, int>(vk, vv); 802 while ((line = r.ReadLine()) != null)
803 {
804 String[] parts = line.Split(new Char[] { ',' });
805 int kk = System.Convert.ToInt32(parts[0]);
806 int kv = System.Convert.ToInt32(parts[1]);
807 int vk = System.Convert.ToInt32(parts[2]);
808 int vv = System.Convert.ToInt32(parts[3]);
809
810 KeyValuePair<int, int> k = new KeyValuePair<int, int>(kk, kv);
811 KeyValuePair<int, int> v = new KeyValuePair<int, int>(vk, vv);
815 812
816 linemap[k] = v; 813 linemap[k] = v;
814 }
817 } 815 }
818 } 816 }
819 catch 817 catch
820 { 818 {
821 linemap = new Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>>(); 819 linemap = new Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>>();
822 } 820 }
821
823 return linemap; 822 return linemap;
824 } 823 }
825 } 824 }
826} 825} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
index 9da2168..b983be9 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
@@ -71,7 +71,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
71 private bool m_TimerQueued; 71 private bool m_TimerQueued;
72 private DateTime m_EventStart; 72 private DateTime m_EventStart;
73 private bool m_InEvent; 73 private bool m_InEvent;
74 private string m_Assembly; 74 private string m_assemblyPath;
75 private string m_dataPath;
75 private string m_CurrentEvent = String.Empty; 76 private string m_CurrentEvent = String.Empty;
76 private bool m_InSelfDelete; 77 private bool m_InSelfDelete;
77 private int m_MaxScriptQueue; 78 private int m_MaxScriptQueue;
@@ -244,12 +245,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
244 /// </summary> 245 /// </summary>
245 /// <param name='dom'></param> 246 /// <param name='dom'></param>
246 /// <param name='assembly'></param> 247 /// <param name='assembly'></param>
248 /// <param name='dataPath'>
249 /// Path for all script associated data (state, etc.). In a multi-region set up
250 /// with all scripts loading into the same AppDomain this may not be the same place as the DLL itself.
251 /// </param>
247 /// <param name='stateSource'></param> 252 /// <param name='stateSource'></param>
248 /// <returns>false if load failed, true if suceeded</returns> 253 /// <returns>false if load failed, true if suceeded</returns>
249 public bool Load(AppDomain dom, Assembly scriptAssembly, StateSource stateSource) 254 public bool Load(AppDomain dom, Assembly scriptAssembly, string dataPath, StateSource stateSource)
250 { 255 {
251 //m_Assembly = scriptAssembly.CodeBase; 256 m_assemblyPath = scriptAssembly.Location;
252 m_Assembly = scriptAssembly.Location; 257 m_dataPath = dataPath;
253 m_stateSource = stateSource; 258 m_stateSource = stateSource;
254 259
255 try 260 try
@@ -270,14 +275,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
270 constructorParams = null; 275 constructorParams = null;
271 } 276 }
272 277
273// m_log.DebugFormat(
274// "[SCRIP
275// scriptType.FullName, m_Assembly, Engine.World.Name);
276
277 if (dom != System.AppDomain.CurrentDomain) 278 if (dom != System.AppDomain.CurrentDomain)
278 m_Script 279 m_Script
279 = (IScript)dom.CreateInstanceAndUnwrap( 280 = (IScript)dom.CreateInstanceAndUnwrap(
280 Path.GetFileNameWithoutExtension(m_Assembly), 281 Path.GetFileNameWithoutExtension(m_assemblyPath),
281 scriptType.FullName, 282 scriptType.FullName,
282 false, 283 false,
283 BindingFlags.Default, 284 BindingFlags.Default,
@@ -305,7 +306,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
305 { 306 {
306 m_log.ErrorFormat( 307 m_log.ErrorFormat(
307 "[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}. Error loading assembly {6}. Exception {7}{8}", 308 "[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}. Error loading assembly {6}. Exception {7}{8}",
308 ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, m_Assembly, e.Message, e.StackTrace); 309 ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, scriptAssembly.Location, e.Message, e.StackTrace);
309 310
310 return false; 311 return false;
311 } 312 }
@@ -340,10 +341,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
340 341
341 m_SaveState = true; 342 m_SaveState = true;
342 343
343 string savedState = Path.Combine(Path.GetDirectoryName(m_Assembly), ItemID.ToString() + ".state"); 344 string savedState = Path.Combine(m_dataPath, ItemID.ToString() + ".state");
344 345
345 if (File.Exists(savedState)) 346 if (File.Exists(savedState))
346 { 347 {
348// m_log.DebugFormat(
349// "[SCRIPT INSTANCE]: Found state for script {0} for {1} ({2}) at {3} in {4}",
350// ItemID, savedState, Part.Name, Part.ParentGroup.Name, Part.ParentGroup.Scene.Name);
351
347 string xml = String.Empty; 352 string xml = String.Empty;
348 353
349 try 354 try
@@ -385,12 +390,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
385 m_startedFromSavedState = true; 390 m_startedFromSavedState = true;
386 } 391 }
387 } 392 }
388 else 393// else
389 { 394// {
390 m_log.WarnFormat( 395// m_log.WarnFormat(
391 "[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}. Unable to load script state file {6}. Memory limit exceeded.", 396// "[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}. Unable to load script state file {6}. Memory limit exceeded.",
392 ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, savedState); 397// ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, savedState);
393 } 398// }
394 } 399 }
395 catch (Exception e) 400 catch (Exception e)
396 { 401 {
@@ -401,11 +406,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
401 } 406 }
402// else 407// else
403// { 408// {
404// ScenePresence presence = Engine.World.GetScenePresence(part.OwnerID); 409// m_log.DebugFormat(
405 410// "[SCRIPT INSTANCE]: Did not find state for script {0} for {1} ({2}) at {3} in {4}",
406// if (presence != null && (!postOnRez)) 411// ItemID, savedState, Part.Name, Part.ParentGroup.Name, Part.ParentGroup.Scene.Name);
407// presence.ControllingClient.SendAgentAlertMessage("Compile successful", false);
408
409// } 412// }
410 413
411 return true; 414 return true;
@@ -498,8 +501,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
498 501
499 public void RemoveState() 502 public void RemoveState()
500 { 503 {
501 string savedState = Path.Combine(Path.GetDirectoryName(m_Assembly), 504 string savedState = Path.Combine(m_dataPath, ItemID.ToString() + ".state");
502 ItemID.ToString() + ".state"); 505
506// m_log.DebugFormat(
507// "[SCRIPT INSTANCE]: Deleting state {0} for script {1} (id {2}) in part {3} (id {4}) in object {5} in {6}.",
508// savedState, ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name);
503 509
504 try 510 try
505 { 511 {
@@ -822,8 +828,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
822 if (Engine.World.PipeEventsForScript(LocalID) || 828 if (Engine.World.PipeEventsForScript(LocalID) ||
823 data.EventName == "control") // Don't freeze avies! 829 data.EventName == "control") // Don't freeze avies!
824 { 830 {
825 // m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}", 831// m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}",
826 // PrimName, ScriptName, data.EventName, State); 832// PrimName, ScriptName, data.EventName, State);
827 833
828 try 834 try
829 { 835 {
@@ -849,7 +855,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
849 // This will be the very first event we deliver 855 // This will be the very first event we deliver
850 // (state_entry) in default state 856 // (state_entry) in default state
851 // 857 //
852 SaveState(m_Assembly); 858 SaveState();
853 859
854 m_SaveState = false; 860 m_SaveState = false;
855 } 861 }
@@ -1043,7 +1049,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
1043 return m_DetectParams[idx].Key; 1049 return m_DetectParams[idx].Key;
1044 } 1050 }
1045 1051
1046 public void SaveState(string assembly) 1052 public void SaveState()
1047 { 1053 {
1048 // If we're currently in an event, just tell it to save upon return 1054 // If we're currently in an event, just tell it to save upon return
1049 // 1055 //
@@ -1065,10 +1071,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
1065 { 1071 {
1066 try 1072 try
1067 { 1073 {
1068 FileStream fs = File.Create(Path.Combine(Path.GetDirectoryName(assembly), ItemID.ToString() + ".state")); 1074 using (FileStream fs = File.Create(Path.Combine(m_dataPath, ItemID.ToString() + ".state")))
1069 Byte[] buf = Util.UTF8NoBomEncoding.GetBytes(xml); 1075 {
1070 fs.Write(buf, 0, buf.Length); 1076 Byte[] buf = Util.UTF8NoBomEncoding.GetBytes(xml);
1071 fs.Close(); 1077 fs.Write(buf, 0, buf.Length);
1078 }
1072 } 1079 }
1073 catch(Exception) 1080 catch(Exception)
1074 { 1081 {
@@ -1148,7 +1155,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
1148 1155
1149 public string GetAssemblyName() 1156 public string GetAssemblyName()
1150 { 1157 {
1151 return m_Assembly; 1158 return m_assemblyPath;
1152 } 1159 }
1153 1160
1154 public string GetXMLState() 1161 public string GetXMLState()
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineBasicTests.cs b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineBasicTests.cs
index fe15157..878e571 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineBasicTests.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineBasicTests.cs
@@ -40,10 +40,10 @@ using OpenSim.Tests.Common;
40namespace OpenSim.Region.ScriptEngine.XEngine.Tests 40namespace OpenSim.Region.ScriptEngine.XEngine.Tests
41{ 41{
42 /// <summary> 42 /// <summary>
43 /// XEngine tests. 43 /// Basic XEngine tests.
44 /// </summary> 44 /// </summary>
45 [TestFixture] 45 [TestFixture]
46 public class XEngineTest : OpenSimTestCase 46 public class XEngineBasicTests : OpenSimTestCase
47 { 47 {
48 private TestScene m_scene; 48 private TestScene m_scene;
49 private XEngine m_xEngine; 49 private XEngine m_xEngine;
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineCrossingTests.cs b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineCrossingTests.cs
new file mode 100644
index 0000000..587695f
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineCrossingTests.cs
@@ -0,0 +1,195 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Threading;
30using Nini.Config;
31using NUnit.Framework;
32using OpenMetaverse;
33using OpenSim.Framework;
34using OpenSim.Region.CoreModules.Framework.EntityTransfer;
35using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
36using OpenSim.Region.Framework.Scenes;
37using OpenSim.Region.ScriptEngine.Shared;
38using OpenSim.Tests.Common;
39
40namespace OpenSim.Region.ScriptEngine.XEngine.Tests
41{
42 /// <summary>
43 /// XEngine tests connected with crossing scripts between regions.
44 /// </summary>
45 [TestFixture]
46 public class XEngineCrossingTests : OpenSimTestCase
47 {
48 [TestFixtureSetUp]
49 public void FixtureInit()
50 {
51 // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread.
52 Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest;
53 }
54
55 [TestFixtureTearDown]
56 public void TearDown()
57 {
58 // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple
59 // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression
60 // tests really shouldn't).
61 Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
62 }
63
64 /// <summary>
65 /// Test script state preservation when a script crosses between regions on the same simulator.
66 /// </summary>
67 [Test]
68 public void TestScriptCrossOnSameSimulator()
69 {
70 TestHelpers.InMethod();
71// TestHelpers.EnableLogging();
72
73 UUID userId = TestHelpers.ParseTail(0x1);
74 int sceneObjectIdTail = 0x2;
75
76 EntityTransferModule etmA = new EntityTransferModule();
77 EntityTransferModule etmB = new EntityTransferModule();
78 LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
79 XEngine xEngineA = new XEngine();
80 XEngine xEngineB = new XEngine();
81 xEngineA.DebugLevel = 1;
82 xEngineB.DebugLevel = 1;
83
84 IConfigSource configSource = new IniConfigSource();
85
86 IConfig startupConfig = configSource.AddConfig("Startup");
87 startupConfig.Set("DefaultScriptEngine", "XEngine");
88
89 IConfig xEngineConfig = configSource.AddConfig("XEngine");
90 xEngineConfig.Set("Enabled", "true");
91 xEngineConfig.Set("StartDelay", "0");
92
93 // These tests will not run with AppDomainLoading = true, at least on mono. For unknown reasons, the call
94 // to AssemblyResolver.OnAssemblyResolve fails.
95 xEngineConfig.Set("AppDomainLoading", "false");
96
97 IConfig modulesConfig = configSource.AddConfig("Modules");
98 modulesConfig.Set("EntityTransferModule", etmA.Name);
99 modulesConfig.Set("SimulationServices", lscm.Name);
100
101 SceneHelpers sh = new SceneHelpers();
102 TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000, configSource);
103 TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1000, 999, configSource);
104
105 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, configSource, lscm);
106 SceneHelpers.SetupSceneModules(sceneA, configSource, etmA, xEngineA);
107 SceneHelpers.SetupSceneModules(sceneB, configSource, etmB, xEngineB);
108 sceneA.StartScripts();
109 sceneB.StartScripts();
110
111 SceneObjectGroup soSceneA = SceneHelpers.AddSceneObject(sceneA, 1, userId, "so1-", sceneObjectIdTail);
112 soSceneA.AbsolutePosition = new Vector3(128, 10, 20);
113
114 // CREATE SCRIPT TODO
115 InventoryItemBase scriptItemSceneA = new InventoryItemBase();
116 // itemTemplate.ID = itemId;
117 scriptItemSceneA.Name = "script1";
118 scriptItemSceneA.Folder = soSceneA.UUID;
119 scriptItemSceneA.InvType = (int)InventoryType.LSL;
120
121 AutoResetEvent chatEvent = new AutoResetEvent(false);
122 OSChatMessage messageReceived = null;
123 sceneA.EventManager.OnChatFromWorld += (s, m) => { messageReceived = m; chatEvent.Set(); };
124
125 sceneA.RezNewScript(userId, scriptItemSceneA,
126@"integer c = 0;
127
128default
129{
130 state_entry()
131 {
132 llSay(0, ""Script running"");
133 }
134
135 changed(integer change)
136 {
137 llSay(0, ""Changed"");
138 }
139
140 touch_start(integer n)
141 {
142 c = c + 1;
143 llSay(0, (string)c);
144 }
145}");
146
147 chatEvent.WaitOne(60000);
148
149 Assert.That(messageReceived, Is.Not.Null, "No chat message received.");
150 Assert.That(messageReceived.Message, Is.EqualTo("Script running"));
151
152 {
153 // XXX: Should not be doing this so directly. Should call some variant of EventManager.touch() instead.
154 DetectParams[] det = new DetectParams[1];
155 det[0] = new DetectParams();
156 det[0].Key = userId;
157 det[0].Populate(sceneA);
158
159 EventParams ep = new EventParams("touch_start", new Object[] { new LSL_Types.LSLInteger(1) }, det);
160
161 xEngineA.PostObjectEvent(soSceneA.LocalId, ep);
162 chatEvent.WaitOne(60000);
163
164 Assert.That(messageReceived.Message, Is.EqualTo("1"));
165 }
166
167 sceneB.EventManager.OnChatFromWorld += (s, m) => { messageReceived = m; chatEvent.Set(); };
168
169 // Cross with a negative value
170 soSceneA.AbsolutePosition = new Vector3(128, -10, 20);
171
172 chatEvent.WaitOne(60000);
173 Assert.That(messageReceived.Message, Is.EqualTo("Changed"));
174
175 // TEST sending event to moved prim and output
176 {
177 SceneObjectGroup soSceneB = sceneB.GetSceneObjectGroup(soSceneA.Name);
178 TaskInventoryItem scriptItemSceneB = soSceneB.RootPart.Inventory.GetInventoryItem(scriptItemSceneA.Name);
179
180 // XXX: Should not be doing this so directly. Should call some variant of EventManager.touch() instead.
181 DetectParams[] det = new DetectParams[1];
182 det[0] = new DetectParams();
183 det[0].Key = userId;
184 det[0].Populate(sceneB);
185
186 EventParams ep = new EventParams("touch_start", new Object[] { new LSL_Types.LSLInteger(1) }, det);
187
188 xEngineB.PostObjectEvent(soSceneB.LocalId, ep);
189 chatEvent.WaitOne(60000);
190
191 Assert.That(messageReceived.Message, Is.EqualTo("2"));
192 }
193 }
194 }
195} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index a4113d6..906c6ee 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -70,7 +70,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
70 /// <remarks> 70 /// <remarks>
71 /// If DebugLevel >= 1, then we log every time that a script is started. 71 /// If DebugLevel >= 1, then we log every time that a script is started.
72 /// </remarks> 72 /// </remarks>
73// public int DebugLevel { get; set; } 73 public int DebugLevel { get; set; }
74 74
75 private SmartThreadPool m_ThreadPool; 75 private SmartThreadPool m_ThreadPool;
76 private int m_MaxScriptQueue; 76 private int m_MaxScriptQueue;
@@ -101,7 +101,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine
101 private bool m_InitialStartup = true; 101 private bool m_InitialStartup = true;
102 private int m_ScriptFailCount; // Number of script fails since compile queue was last empty 102 private int m_ScriptFailCount; // Number of script fails since compile queue was last empty
103 private string m_ScriptErrorMessage; 103 private string m_ScriptErrorMessage;
104 private Dictionary<string, string> m_uniqueScripts = new Dictionary<string, string>();
105 private bool m_AppDomainLoading; 104 private bool m_AppDomainLoading;
106 private Dictionary<UUID,ArrayList> m_ScriptErrors = 105 private Dictionary<UUID,ArrayList> m_ScriptErrors =
107 new Dictionary<UUID,ArrayList>(); 106 new Dictionary<UUID,ArrayList>();
@@ -403,12 +402,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
403 + "Level >= 2, log event invocations.\n", 402 + "Level >= 2, log event invocations.\n",
404 HandleDebugScriptLogCommand); 403 HandleDebugScriptLogCommand);
405 404
406// MainConsole.Instance.Commands.AddCommand( 405 MainConsole.Instance.Commands.AddCommand(
407// "Debug", false, "debug xengine", "debug xengine [<level>]", 406 "Debug", false, "debug xengine log", "debug xengine log [<level>]",
408// "Turn on detailed xengine debugging.", 407 "Turn on detailed xengine debugging.",
409// "If level <= 0, then no extra logging is done.\n" 408 "If level <= 0, then no extra logging is done.\n"
410// + "If level >= 1, then we log every time that a script is started.", 409 + "If level >= 1, then we log every time that a script is started.",
411// HandleDebugLevelCommand); 410 HandleDebugLevelCommand);
412 } 411 }
413 412
414 private void HandleDebugScriptLogCommand(string module, string[] args) 413 private void HandleDebugScriptLogCommand(string module, string[] args)
@@ -451,26 +450,26 @@ namespace OpenSim.Region.ScriptEngine.XEngine
451 /// </summary> 450 /// </summary>
452 /// <param name="module"></param> 451 /// <param name="module"></param>
453 /// <param name="args"></param> 452 /// <param name="args"></param>
454// private void HandleDebugLevelCommand(string module, string[] args) 453 private void HandleDebugLevelCommand(string module, string[] args)
455// { 454 {
456// if (args.Length == 3) 455 if (args.Length <= 4)
457// { 456 {
458// int newDebug; 457 int newDebug;
459// if (int.TryParse(args[2], out newDebug)) 458 if (ConsoleUtil.TryParseConsoleNaturalInt(MainConsole.Instance, args[3], out newDebug))
460// { 459 {
461// DebugLevel = newDebug; 460 DebugLevel = newDebug;
462// MainConsole.Instance.OutputFormat("Debug level set to {0}", newDebug); 461 MainConsole.Instance.OutputFormat("Debug level set to {0} in XEngine for region {1}", newDebug, m_Scene.Name);
463// } 462 }
464// } 463 }
465// else if (args.Length == 2) 464 else if (args.Length == 3)
466// { 465 {
467// MainConsole.Instance.OutputFormat("Current debug level is {0}", DebugLevel); 466 MainConsole.Instance.OutputFormat("Current debug level is {0}", DebugLevel);
468// } 467 }
469// else 468 else
470// { 469 {
471// MainConsole.Instance.Output("Usage: debug xengine 0..1"); 470 MainConsole.Instance.Output("Usage: debug xengine log <level>");
472// } 471 }
473// } 472 }
474 473
475 /// <summary> 474 /// <summary>
476 /// Parse the raw item id into a script instance from the command params if it's present. 475 /// Parse the raw item id into a script instance from the command params if it's present.
@@ -570,7 +569,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine
570 } 569 }
571 570
572 sb.AppendFormat("Scripts loaded : {0}\n", scriptsLoaded); 571 sb.AppendFormat("Scripts loaded : {0}\n", scriptsLoaded);
573 sb.AppendFormat("Unique scripts : {0}\n", m_uniqueScripts.Count);
574 sb.AppendFormat("Scripts waiting for load : {0}\n", m_CompileQueue.Count); 572 sb.AppendFormat("Scripts waiting for load : {0}\n", m_CompileQueue.Count);
575 sb.AppendFormat("Max threads : {0}\n", m_ThreadPool.MaxThreads); 573 sb.AppendFormat("Max threads : {0}\n", m_ThreadPool.MaxThreads);
576 sb.AppendFormat("Min threads : {0}\n", m_ThreadPool.MinThreads); 574 sb.AppendFormat("Min threads : {0}\n", m_ThreadPool.MinThreads);
@@ -716,22 +714,17 @@ namespace OpenSim.Region.ScriptEngine.XEngine
716 { 714 {
717 // Force a final state save 715 // Force a final state save
718 // 716 //
719 if (m_Assemblies.ContainsKey(instance.AssetID)) 717 try
720 { 718 {
721 string assembly = m_Assemblies[instance.AssetID]; 719 instance.SaveState();
722 720 }
723 try 721 catch (Exception e)
724 { 722 {
725 instance.SaveState(assembly); 723 m_log.Error(
726 } 724 string.Format(
727 catch (Exception e) 725 "[XEngine]: Failed final state save for script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ",
728 { 726 instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name)
729 m_log.Error( 727 , e);
730 string.Format(
731 "[XEngine]: Failed final state save for script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ",
732 instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name)
733 , e);
734 }
735 } 728 }
736 729
737 // Clear the event queue and abort the instance thread 730 // Clear the event queue and abort the instance thread
@@ -840,18 +833,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
840 833
841 foreach (IScriptInstance i in instances) 834 foreach (IScriptInstance i in instances)
842 { 835 {
843 string assembly = String.Empty;
844
845 lock (m_Scripts)
846 {
847 if (!m_Assemblies.ContainsKey(i.AssetID))
848 continue;
849 assembly = m_Assemblies[i.AssetID];
850 }
851
852 try 836 try
853 { 837 {
854 i.SaveState(assembly); 838 i.SaveState();
855 } 839 }
856 catch (Exception e) 840 catch (Exception e)
857 { 841 {
@@ -1001,12 +985,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1001 if (engine != ScriptEngineName) 985 if (engine != ScriptEngineName)
1002 return; 986 return;
1003 987
1004 // If we've seen this exact script text before, use that reference instead
1005 if (m_uniqueScripts.ContainsKey(script))
1006 script = m_uniqueScripts[script];
1007 else
1008 m_uniqueScripts[script] = script;
1009
1010 Object[] parms = new Object[]{localID, itemID, script, startParam, postOnRez, (StateSource)stateSource}; 988 Object[] parms = new Object[]{localID, itemID, script, startParam, postOnRez, (StateSource)stateSource};
1011 989
1012 if (stateSource == (int)StateSource.ScriptedRez) 990 if (stateSource == (int)StateSource.ScriptedRez)
@@ -1020,11 +998,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1020 } 998 }
1021 else 999 else
1022 { 1000 {
1023 m_CompileQueue.Enqueue(parms);
1024 lock (m_CompileDict) 1001 lock (m_CompileDict)
1025 {
1026 m_CompileDict[itemID] = 0; 1002 m_CompileDict[itemID] = 0;
1027 } 1003
1004 // This must occur after the m_CompileDict so that an existing compile thread cannot hit the check
1005 // in DoOnRezScript() before m_CompileDict has been updated.
1006 m_CompileQueue.Enqueue(parms);
1028 1007
1029// m_log.DebugFormat("[XEngine]: Added script {0} to compile queue", itemID); 1008// m_log.DebugFormat("[XEngine]: Added script {0} to compile queue", itemID);
1030 1009
@@ -1100,7 +1079,15 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1100 // due to a race condition 1079 // due to a race condition
1101 // 1080 //
1102 lock (m_CompileQueue) 1081 lock (m_CompileQueue)
1082 {
1103 m_CurrentCompile = null; 1083 m_CurrentCompile = null;
1084
1085 // This is to avoid a situation where the m_CompileQueue while loop above could complete but
1086 // OnRezScript() place a new script on the queue and check m_CurrentCompile = null before we hit
1087 // this section.
1088 if (m_CompileQueue.Count > 0)
1089 m_CurrentCompile = m_ThreadPool.QueueWorkItem(DoOnRezScriptQueue, null);
1090 }
1104 } 1091 }
1105 1092
1106 return null; 1093 return null;
@@ -1148,10 +1135,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1148 return false; 1135 return false;
1149 } 1136 }
1150 1137
1151 m_log.DebugFormat( 1138 if (DebugLevel > 0)
1152 "[XEngine]: Loading script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", 1139 m_log.DebugFormat(
1153 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, 1140 "[XEngine]: Loading script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}",
1154 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); 1141 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID,
1142 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1155 1143
1156 UUID assetID = item.AssetID; 1144 UUID assetID = item.AssetID;
1157 1145
@@ -1170,7 +1158,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1170 lock (m_AddingAssemblies) 1158 lock (m_AddingAssemblies)
1171 { 1159 {
1172 m_Compiler.PerformScriptCompile(script, assetID.ToString(), item.OwnerID, out assemblyPath, out linemap); 1160 m_Compiler.PerformScriptCompile(script, assetID.ToString(), item.OwnerID, out assemblyPath, out linemap);
1173 1161
1162// m_log.DebugFormat(
1163// "[XENGINE]: Found assembly path {0} onrez {1} in {2}",
1164// assemblyPath, item.ItemID, World.Name);
1165
1174 if (!m_AddingAssemblies.ContainsKey(assemblyPath)) { 1166 if (!m_AddingAssemblies.ContainsKey(assemblyPath)) {
1175 m_AddingAssemblies[assemblyPath] = 1; 1167 m_AddingAssemblies[assemblyPath] = 1;
1176 } else { 1168 } else {
@@ -1348,14 +1340,24 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1348 // simulator session if the script halt strategy has been changed. Instead, we'll continue with 1340 // simulator session if the script halt strategy has been changed. Instead, we'll continue with
1349 // the existing DLL and the new one will be used in the next simulator session. 1341 // the existing DLL and the new one will be used in the next simulator session.
1350 if (recompile) 1342 if (recompile)
1343 {
1344 m_log.DebugFormat(
1345 "[XEngine]: Recompiling script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5} to switch it to {6} termination. Will be active on next restart.",
1346 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID,
1347 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.Name,
1348 m_coopTermination ? "co-op" : "abort");
1349
1351 m_Compiler.PerformScriptCompile(script, assetID.ToString(), item.OwnerID, true, out assemblyPath, out linemap); 1350 m_Compiler.PerformScriptCompile(script, assetID.ToString(), item.OwnerID, true, out assemblyPath, out linemap);
1351 }
1352 1352
1353 instance = new ScriptInstance(this, part, 1353 instance = new ScriptInstance(this, part,
1354 item, 1354 item,
1355 startParam, postOnRez, 1355 startParam, postOnRez,
1356 m_MaxScriptQueue); 1356 m_MaxScriptQueue);
1357 1357
1358 if (!instance.Load(m_AppDomains[appDomain], scriptAssembly, stateSource)) 1358 if (!instance.Load(
1359 m_AppDomains[appDomain], scriptAssembly,
1360 Path.Combine(ScriptEnginePath, World.RegionInfo.RegionID.ToString()), stateSource))
1359 return false; 1361 return false;
1360 1362
1361// if (DebugLevel >= 1) 1363// if (DebugLevel >= 1)
@@ -1586,7 +1588,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1586 1588
1587 IScriptInstance instance = (ScriptInstance) parms; 1589 IScriptInstance instance = (ScriptInstance) parms;
1588 1590
1589 //m_log.DebugFormat("[XEngine]: Processing event for {0}", instance); 1591// m_log.DebugFormat("[XEngine]: Processing event for {0}", instance);
1590 1592
1591 return instance.EventProcessor(); 1593 return instance.EventProcessor();
1592 } 1594 }
@@ -2155,7 +2157,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
2155 catch (IOException ex) 2157 catch (IOException ex)
2156 { 2158 {
2157 // if there already exists a file at that location, it may be locked. 2159 // if there already exists a file at that location, it may be locked.
2158 m_log.ErrorFormat("[XEngine]: Linemap file {0} already exists! {1}", mappath, ex.Message); 2160 m_log.Error(
2161 string.Format("[XEngine]: Linemap file {0} could not be written. Exception ", mappath), ex);
2159 } 2162 }
2160 } 2163 }
2161 } 2164 }
@@ -2181,6 +2184,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
2181 m_log.ErrorFormat("[XEngine]: Error whilst writing state file {0}, {1}", statepath, ex.Message); 2184 m_log.ErrorFormat("[XEngine]: Error whilst writing state file {0}, {1}", statepath, ex.Message);
2182 } 2185 }
2183 2186
2187// m_log.DebugFormat(
2188// "[XEngine]: Wrote state for script item with ID {0} at {1} in {2}", itemID, statepath, m_Scene.Name);
2189
2184 return true; 2190 return true;
2185 } 2191 }
2186 2192