diff --git a/OpenSim/Framework/Communications/RestClient.cs b/OpenSim/Framework/Communications/RestClient.cs
index 72018e46e0..6f517b6f87 100644
--- a/OpenSim/Framework/Communications/RestClient.cs
+++ b/OpenSim/Framework/Communications/RestClient.cs
@@ -90,7 +90,7 @@ namespace OpenSim.Framework.Communications
private byte[] _readbuf;
///
- /// MemoryStream representing the resultiong resource
+ /// MemoryStream representing the resulting resource
///
private Stream _resource;
@@ -352,42 +352,46 @@ namespace OpenSim.Framework.Communications
m_log.DebugFormat("[LOGHTTP]: HTTP OUT {0} REST {1} to {2}", reqnum, _request.Method, _request.RequestUri);
// IAsyncResult responseAsyncResult = _request.BeginGetResponse(new AsyncCallback(ResponseIsReadyDelegate), _request);
+
try
{
- _response = (HttpWebResponse) _request.GetResponse();
+ using (_response = (HttpWebResponse) _request.GetResponse())
+ {
+ using (Stream src = _response.GetResponseStream())
+ {
+ int length = src.Read(_readbuf, 0, BufferSize);
+ while (length > 0)
+ {
+ _resource.Write(_readbuf, 0, length);
+ length = src.Read(_readbuf, 0, BufferSize);
+ }
+
+ // TODO! Implement timeout, without killing the server
+ // this line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted
+ //ThreadPool.RegisterWaitForSingleObject(responseAsyncResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), _request, DefaultTimeout, true);
+
+ // _allDone.WaitOne();
+ }
+ }
}
catch (WebException e)
{
- HttpWebResponse errorResponse = e.Response as HttpWebResponse;
- if (null != errorResponse && HttpStatusCode.NotFound == errorResponse.StatusCode)
+ using (HttpWebResponse errorResponse = e.Response as HttpWebResponse)
{
- // This is often benign. E.g., requesting a missing asset will return 404.
- m_log.DebugFormat("[REST CLIENT] Resource not found (404): {0}", _request.Address.ToString());
- }
- else
- {
- m_log.Error(string.Format("[REST CLIENT] Error fetching resource from server: {0} ", _request.Address.ToString()), e);
+ if (null != errorResponse && HttpStatusCode.NotFound == errorResponse.StatusCode)
+ {
+ // This is often benign. E.g., requesting a missing asset will return 404.
+ m_log.DebugFormat("[REST CLIENT] Resource not found (404): {0}", _request.Address.ToString());
+ }
+ else
+ {
+ m_log.Error(string.Format("[REST CLIENT] Error fetching resource from server: {0} ", _request.Address.ToString()), e);
+ }
}
return null;
}
- Stream src = _response.GetResponseStream();
- int length = src.Read(_readbuf, 0, BufferSize);
- while (length > 0)
- {
- _resource.Write(_readbuf, 0, length);
- length = src.Read(_readbuf, 0, BufferSize);
- }
-
-
- // TODO! Implement timeout, without killing the server
- // this line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted
- //ThreadPool.RegisterWaitForSingleObject(responseAsyncResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), _request, DefaultTimeout, true);
-
-// _allDone.WaitOne();
- if (_response != null)
- _response.Close();
if (_asyncException != null)
throw _asyncException;
@@ -515,4 +519,4 @@ namespace OpenSim.Framework.Communications
#endregion Async Invocation
}
-}
+}
\ No newline at end of file
diff --git a/OpenSim/Framework/ISceneObject.cs b/OpenSim/Framework/ISceneObject.cs
index afac9b84f2..754b77b4a2 100644
--- a/OpenSim/Framework/ISceneObject.cs
+++ b/OpenSim/Framework/ISceneObject.cs
@@ -32,6 +32,8 @@ namespace OpenSim.Framework
{
public interface ISceneObject
{
+ string Name { get; }
+
UUID UUID { get; }
///
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index fe9a17d264..6564b4d22f 100644
--- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
@@ -256,20 +256,7 @@ namespace OpenSim.Region.CoreModules.Asset
// If the file is already cached, don't cache it, just touch it so access time is updated
if (File.Exists(filename))
{
- // We don't really want to know about sharing
- // violations here. If the file is locked, then
- // the other thread has updated the time for us.
- try
- {
- lock (m_CurrentlyWriting)
- {
- if (!m_CurrentlyWriting.Contains(filename))
- File.SetLastAccessTime(filename, DateTime.Now);
- }
- }
- catch
- {
- }
+ UpdateFileLastAccessTime(filename);
}
else
{
@@ -328,6 +315,24 @@ namespace OpenSim.Region.CoreModules.Asset
}
}
+ ///
+ /// Updates the cached file with the current time.
+ ///
+ /// Filename.
+ /// true, if the update was successful, false otherwise.
+ private bool UpdateFileLastAccessTime(string filename)
+ {
+ try
+ {
+ File.SetLastAccessTime(filename, DateTime.Now);
+ return true;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+
///
/// Try to get an asset from the in-memory cache.
///
@@ -771,8 +776,8 @@ namespace OpenSim.Region.CoreModules.Asset
{
UuidGatherer gatherer = new UuidGatherer(m_AssetService);
- HashSet uniqueUuids = new HashSet();
- Dictionary assets = new Dictionary();
+ Dictionary assetIdsToCheck = new Dictionary();
+ Dictionary assetsFound = new Dictionary();
foreach (Scene s in m_Scenes)
{
@@ -780,34 +785,40 @@ namespace OpenSim.Region.CoreModules.Asset
s.ForEachSOG(delegate(SceneObjectGroup e)
{
- gatherer.GatherAssetUuids(e, assets);
+ gatherer.GatherAssetUuids(e, assetIdsToCheck);
- foreach (UUID assetID in assets.Keys)
+ foreach (UUID assetID in assetIdsToCheck.Keys)
{
- uniqueUuids.Add(assetID);
-
- string filename = GetFileName(assetID.ToString());
-
- if (File.Exists(filename))
+ if (!assetsFound.ContainsKey(assetID))
{
- File.SetLastAccessTime(filename, DateTime.Now);
+ string filename = GetFileName(assetID.ToString());
+
+ if (File.Exists(filename))
+ {
+ UpdateFileLastAccessTime(filename);
+ }
+ else if (storeUncached)
+ {
+ AssetBase cachedAsset = m_AssetService.Get(assetID.ToString());
+ if (cachedAsset == null && assetIdsToCheck[assetID] != (sbyte)AssetType.Unknown)
+ assetsFound[assetID] = false;
+ else
+ assetsFound[assetID] = true;
+ }
}
- else if (storeUncached)
+ else if (!assetsFound[assetID])
{
- AssetBase cachedAsset = m_AssetService.Get(assetID.ToString());
- if (cachedAsset == null && assets[assetID] != (sbyte)AssetType.Unknown)
- m_log.DebugFormat(
+ m_log.DebugFormat(
"[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",
- assetID, assets[assetID], e.Name, e.AbsolutePosition, s.Name);
+ assetID, assetIdsToCheck[assetID], e.Name, e.AbsolutePosition, s.Name);
}
}
- assets.Clear();
+ assetIdsToCheck.Clear();
});
}
-
- return uniqueUuids.Count;
+ return assetsFound.Count;
}
///
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index a3368fbb1c..4af4ddb32c 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
public void CopyAttachments(AgentData ad, IScenePresence sp)
{
+// m_log.DebugFormat("[ATTACHMENTS MODULE]: Copying attachment data into {0} in {1}", sp.Name, m_scene.Name);
+
if (ad.AttachmentObjects != null && ad.AttachmentObjects.Count > 0)
{
lock (sp.AttachmentsSyncLock)
@@ -265,6 +267,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
{
((SceneObjectGroup)so).LocalId = 0;
((SceneObjectGroup)so).RootPart.ClearUpdateSchedule();
+
+// m_log.DebugFormat(
+// "[ATTACHMENTS MODULE]: Copying script state with {0} bytes for object {1} for {2} in {3}",
+// ad.AttachmentObjectStates[i].Length, so.Name, sp.Name, m_scene.Name);
+
so.SetState(ad.AttachmentObjectStates[i++], m_scene);
m_scene.IncomingCreateObject(Vector3.Zero, so);
}
@@ -334,11 +341,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
if (!Enabled)
return;
- if (DebugLevel > 0)
- m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name);
-
List attachments = sp.GetAttachments();
+ if (DebugLevel > 0)
+ m_log.DebugFormat(
+ "[ATTACHMENTS MODULE]: Saving for {0} attachments for {1} in {2}",
+ attachments.Count, sp.Name, m_scene.Name);
+
if (attachments.Count <= 0)
return;
@@ -352,6 +361,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
// This must be done outside the sp.AttachmentSyncLock so that there is no risk of a deadlock from
// scripts performing attachment operations at the same time. Getting object states stops the scripts.
scriptStates[so] = PrepareScriptInstanceForSave(so, false);
+
+// m_log.DebugFormat(
+// "[ATTACHMENTS MODULE]: For object {0} for {1} in {2} got saved state {3}",
+// so.Name, sp.Name, m_scene.Name, scriptStates[so]);
}
lock (sp.AttachmentsSyncLock)
@@ -819,8 +832,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
{
if (DebugLevel > 0)
m_log.DebugFormat(
- "[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}",
- so.Name, sp.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos);
+ "[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} at pt {2} pos {3} {4} in {5}",
+ so.Name, sp.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos, m_scene.Name);
// Remove from database and parcel prim count
m_scene.DeleteFromStorage(so.UUID);
diff --git a/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs b/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs
index 5e35135c5f..7d2cad67c3 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
return null;
int size = 0;
- RestClient rc = new RestClient(m_URL);
- List ret = new List();
- rc.AddResourcePath("bakes");
- rc.AddResourcePath(id.ToString());
- rc.RequestMethod = "GET";
-
- try
+ using (RestClient rc = new RestClient(m_URL))
{
- Stream s = rc.Request(m_Auth);
- XmlTextReader sr = new XmlTextReader(s);
+ List ret = new List();
+ rc.AddResourcePath("bakes");
+ rc.AddResourcePath(id.ToString());
- sr.ReadStartElement("BakedAppearance");
- while (sr.LocalName == "BakedTexture")
+ rc.RequestMethod = "GET";
+
+ try
{
- string sTextureIndex = sr.GetAttribute("TextureIndex");
- int lTextureIndex = Convert.ToInt32(sTextureIndex);
- string sCacheId = sr.GetAttribute("CacheId");
- UUID lCacheId = UUID.Zero;
- if (!(UUID.TryParse(sCacheId, out lCacheId)))
+ Stream s = rc.Request(m_Auth);
+
+ using (XmlTextReader sr = new XmlTextReader(s))
{
- // ?? Nothing here
+ sr.ReadStartElement("BakedAppearance");
+ while (sr.LocalName == "BakedTexture")
+ {
+ string sTextureIndex = sr.GetAttribute("TextureIndex");
+ int lTextureIndex = Convert.ToInt32(sTextureIndex);
+ string sCacheId = sr.GetAttribute("CacheId");
+ UUID lCacheId = UUID.Zero;
+ if (!(UUID.TryParse(sCacheId, out lCacheId)))
+ {
+ // ?? Nothing here
+ }
+
+ ++size;
+
+ sr.ReadStartElement("BakedTexture");
+ AssetBase a = (AssetBase)m_serializer.Deserialize(sr);
+ ret.Add(new WearableCacheItem() { CacheId = lCacheId, TextureIndex = (uint)lTextureIndex, TextureAsset = a, TextureID = a.FullID });
+
+ sr.ReadEndElement();
+ }
+
+ m_log.DebugFormat("[XBakes]: read {0} textures for user {1}", ret.Count, id);
}
- ++size;
-
- sr.ReadStartElement("BakedTexture");
- AssetBase a = (AssetBase)m_serializer.Deserialize(sr);
- ret.Add(new WearableCacheItem() { CacheId = lCacheId, TextureIndex = (uint)lTextureIndex, TextureAsset = a, TextureID = a.FullID });
-
- sr.ReadEndElement();
+ return ret.ToArray();
+ }
+ catch (XmlException)
+ {
+ return null;
}
- m_log.DebugFormat("[XBakes]: read {0} textures for user {1}", ret.Count, id);
- sr.Close();
- s.Close();
-
-
- return ret.ToArray();
- }
- catch (XmlException)
- {
- return null;
}
}
@@ -153,27 +156,32 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
if (m_URL == String.Empty)
return;
- MemoryStream bakeStream = new MemoryStream();
- XmlTextWriter bakeWriter = new XmlTextWriter(bakeStream, null);
+ MemoryStream reqStream;
- bakeWriter.WriteStartElement(String.Empty, "BakedAppearance", String.Empty);
-
- for (int i = 0; i < data.Length; i++)
+ using (MemoryStream bakeStream = new MemoryStream())
+ using (XmlTextWriter bakeWriter = new XmlTextWriter(bakeStream, null))
{
- if (data[i] != null)
+ bakeWriter.WriteStartElement(String.Empty, "BakedAppearance", String.Empty);
+
+ for (int i = 0; i < data.Length; i++)
{
- bakeWriter.WriteStartElement(String.Empty, "BakedTexture", String.Empty);
- bakeWriter.WriteAttributeString(String.Empty, "TextureIndex", String.Empty, data[i].TextureIndex.ToString());
- bakeWriter.WriteAttributeString(String.Empty, "CacheId", String.Empty, data[i].CacheId.ToString());
- if (data[i].TextureAsset != null)
- m_serializer.Serialize(bakeWriter, data[i].TextureAsset);
+ if (data[i] != null)
+ {
+ bakeWriter.WriteStartElement(String.Empty, "BakedTexture", String.Empty);
+ bakeWriter.WriteAttributeString(String.Empty, "TextureIndex", String.Empty, data[i].TextureIndex.ToString());
+ bakeWriter.WriteAttributeString(String.Empty, "CacheId", String.Empty, data[i].CacheId.ToString());
+ if (data[i].TextureAsset != null)
+ m_serializer.Serialize(bakeWriter, data[i].TextureAsset);
- bakeWriter.WriteEndElement();
+ bakeWriter.WriteEndElement();
+ }
}
- }
- bakeWriter.WriteEndElement();
- bakeWriter.Flush();
+ bakeWriter.WriteEndElement();
+ bakeWriter.Flush();
+
+ reqStream = new MemoryStream(bakeStream.ToArray());
+ }
RestClient rc = new RestClient(m_URL);
rc.AddResourcePath("bakes");
@@ -181,7 +189,6 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
rc.RequestMethod = "POST";
- MemoryStream reqStream = new MemoryStream(bakeStream.ToArray());
Util.FireAndForget(
delegate
{
@@ -191,4 +198,4 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures
);
}
}
-}
+}
\ 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 97267c1cd7..2ddb599af4 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
// "[HG ENTITY TRANSFER MODULE]: Incoming attachment {0} for HG user {1} with asset service {2}",
// so.Name, so.AttachedAvatar, url);
- IteratingHGUuidGatherer uuidGatherer = new IteratingHGUuidGatherer(Scene.AssetService, url);
- uuidGatherer.RecordAssetUuids(so);
+ IDictionary ids = new Dictionary();
+ IteratingHGUuidGatherer uuidGatherer
+ = new IteratingHGUuidGatherer(Scene.AssetService, url, ids);
+ uuidGatherer.AddForInspection(so);
while (!uuidGatherer.Complete)
{
@@ -632,8 +634,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
}
}
- IDictionary ids = uuidGatherer.GetGatheredUuids();
-
// m_log.DebugFormat(
// "[HG ENTITY TRANSFER]: Fetching {0} assets for attachment {1} for HG user {2} with asset service {3}",
// 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 9bf788545e..647943062e 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
"Show the bindings between user UUIDs and user names",
String.Empty,
HandleShowUsers);
+
+ MainConsole.Instance.Commands.AddCommand("Users", true,
+ "reset user cache",
+ "reset user cache",
+ "reset user cache to allow changed settings to be applied",
+ String.Empty,
+ HandleResetUserCache);
+ }
+
+ private void HandleResetUserCache(string module, string[] cmd)
+ {
+ lock(m_UserCache)
+ {
+ m_UserCache.Clear();
+ }
}
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 601e81e587..46b0470600 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
/// true if the url matches an entry on the whitelist, false otherwise
protected bool CheckUrlAgainstWhitelist(string rawUrl, string[] whitelist)
{
+ if (whitelist == null)
+ return false;
+
Uri url = new Uri(rawUrl);
foreach (string origWlUrl in whitelist)
diff --git a/OpenSim/Region/Framework/Interfaces/INPCModule.cs b/OpenSim/Region/Framework/Interfaces/INPCModule.cs
index d5dcdddf6a..478833ea70 100644
--- a/OpenSim/Region/Framework/Interfaces/INPCModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/INPCModule.cs
@@ -122,6 +122,17 @@ namespace OpenSim.Region.Framework.Interfaces
///
/// Check if the caller has permission to manipulate the given NPC.
///
+ ///
+ /// A caller has permission if
+ /// * An NPC exists with the given npcID.
+ /// * The caller UUID given is UUID.Zero.
+ /// * The avatar is unowned (owner is UUID.Zero).
+ /// * The avatar is owned and the owner and callerID match.
+ /// * The avatar is owned and the callerID matches its agentID.
+ ///
+ ///
+ ///
+ /// true if they do, false if they don't.
///
///
///
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index f7c12d6f99..21d47aa15a 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -823,7 +823,6 @@ namespace OpenSim.Region.Framework.Scenes
m_sceneGridService = sceneGridService;
m_SimulationDataService = simDataService;
m_EstateDataService = estateDataService;
- m_regionHandle = RegionInfo.RegionHandle;
m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this);
m_asyncSceneObjectDeleter.Enabled = true;
@@ -2042,11 +2041,11 @@ namespace OpenSim.Region.Framework.Scenes
GridRegion region = new GridRegion(RegionInfo);
string error = GridService.RegisterRegion(RegionInfo.ScopeID, region);
- m_log.DebugFormat("{0} RegisterRegionWithGrid. name={1},id={2},loc=<{3},{4}>,size=<{5},{6}>",
- LogHeader, m_regionName,
- RegionInfo.RegionID,
- RegionInfo.RegionLocX, RegionInfo.RegionLocY,
- RegionInfo.RegionSizeX, RegionInfo.RegionSizeY);
+// m_log.DebugFormat("[SCENE]: RegisterRegionWithGrid. name={0},id={1},loc=<{2},{3}>,size=<{4},{5}>",
+// m_regionName,
+// RegionInfo.RegionID,
+// RegionInfo.RegionLocX, RegionInfo.RegionLocY,
+// RegionInfo.RegionSizeX, RegionInfo.RegionSizeY);
if (error != String.Empty)
throw new Exception(error);
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index aaddce6050..6f172e7611 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -145,10 +145,6 @@ namespace OpenSim.Region.Framework.Scenes
get { return 1.0f; }
}
- protected ulong m_regionHandle;
- protected string m_regionName;
- protected RegionInfo m_regInfo;
-
public ITerrainChannel Heightmap;
///
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 93dfd005d2..0414f893c3 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -1228,45 +1228,27 @@ namespace OpenSim.Region.Framework.Scenes
m_scene.SwapRootAgentCount(false);
- // The initial login scene presence is already root when it gets here
- // and it has already rezzed the attachments and started their scripts.
- // We do the following only for non-login agents, because their scripts
- // haven't started yet.
- if (PresenceType == PresenceType.Npc || IsRealLogin(m_teleportFlags))
+ if (Scene.AttachmentsModule != null)
{
- // Viewers which have a current outfit folder will actually rez their own attachments. However,
- // viewers without (e.g. v1 viewers) will not, so we still need to make this call.
- if (Scene.AttachmentsModule != null)
+ // The initial login scene presence is already root when it gets here
+ // and it has already rezzed the attachments and started their scripts.
+ // We do the following only for non-login agents, because their scripts
+ // haven't started yet.
+ if (PresenceType == PresenceType.Npc || IsRealLogin(m_teleportFlags))
{
+ // Viewers which have a current outfit folder will actually rez their own attachments. However,
+ // viewers without (e.g. v1 viewers) will not, so we still need to make this call.
WorkManager.RunJob(
"RezAttachments",
o => Scene.AttachmentsModule.RezAttachments(this),
null,
string.Format("Rez attachments for {0} in {1}", Name, Scene.Name));
}
- }
- else
- {
- // We need to restart scripts here so that they receive the correct changed events (CHANGED_TELEPORT
- // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently
- // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are
- // not transporting the required data.
- //
- // We must take a copy of the attachments list here (rather than locking) to avoid a deadlock where a script in one of
- // the attachments may start processing an event (which locks ScriptInstance.m_Script) that then calls a method here
- // which needs to lock m_attachments. ResumeScripts() needs to take a ScriptInstance.m_Script lock to try to unset the Suspend status.
- //
- // FIXME: In theory, this deadlock should not arise since scripts should not be processing events until ResumeScripts().
- // But XEngine starts all scripts unsuspended. Starting them suspended will not currently work because script rezzing
- // is placed in an asynchronous queue in XEngine and so the ResumeScripts() call will almost certainly execute before the
- // script is rezzed. This means the ResumeScripts() does absolutely nothing when using XEngine.
- List attachments = GetAttachments();
-
- if (attachments.Count > 0)
+ else
{
WorkManager.RunJob(
- "StartAttachmentScripts",
- o => RestartAttachmentScripts(attachments),
+ "StartAttachmentScripts",
+ o => RestartAttachmentScripts(),
null,
string.Format("Start attachment scripts for {0} in {1}", Name, Scene.Name),
true);
@@ -1292,10 +1274,25 @@ namespace OpenSim.Region.Framework.Scenes
return true;
}
- private void RestartAttachmentScripts(List attachments)
+ private void RestartAttachmentScripts()
{
+ // We need to restart scripts here so that they receive the correct changed events (CHANGED_TELEPORT
+ // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently
+ // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are
+ // not transporting the required data.
+ //
+ // We must take a copy of the attachments list here (rather than locking) to avoid a deadlock where a script in one of
+ // the attachments may start processing an event (which locks ScriptInstance.m_Script) that then calls a method here
+ // which needs to lock m_attachments. ResumeScripts() needs to take a ScriptInstance.m_Script lock to try to unset the Suspend status.
+ //
+ // FIXME: In theory, this deadlock should not arise since scripts should not be processing events until ResumeScripts().
+ // But XEngine starts all scripts unsuspended. Starting them suspended will not currently work because script rezzing
+ // is placed in an asynchronous queue in XEngine and so the ResumeScripts() call will almost certainly execute before the
+ // script is rezzed. This means the ResumeScripts() does absolutely nothing when using XEngine.
+ List attachments = GetAttachments();
+
m_log.DebugFormat(
- "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name);
+ "[SCENE PRESENCE]: Restarting scripts in {0} attachments for {1} in {2}", attachments.Count, Name, Scene.Name);
// Resume scripts
foreach (SceneObjectGroup sog in attachments)
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index 2450cdbb84..2c5353fc6b 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -648,6 +648,15 @@ namespace OpenSim.Region.Framework.Scenes
}
}
+ ///
+ /// Gather uuids for a given entity.
+ ///
+ ///
+ /// This does a deep inspection of the entity to retrieve all the assets it uses (whether as textures, as scripts
+ /// contained in inventory, as scripts contained in objects contained in another object's inventory, etc. Assets
+ /// are only retrieved when they are necessary to carry out the inspection (i.e. a serialized object needs to be
+ /// retrieved to work out which assets it references).
+ ///
public class IteratingUuidGatherer
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -678,21 +687,31 @@ namespace OpenSim.Region.Framework.Scenes
protected Queue m_assetUuidsToInspect;
- public IteratingUuidGatherer(IAssetService assetService)
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// Asset service.
+ ///
+ ///
+ /// Gathered UUIDs will be collected in this dictinaory.
+ /// It can be pre-populated if you want to stop the gatherer from analyzing assets that have already been fetched and inspected.
+ ///
+ public IteratingUuidGatherer(IAssetService assetService, IDictionary collector)
{
m_assetService = assetService;
- m_gatheredAssetUuids = new Dictionary();
+ m_gatheredAssetUuids = collector;
// FIXME: Not efficient for searching, can improve.
m_assetUuidsToInspect = new Queue();
}
- public IDictionary GetGatheredUuids()
- {
- return new Dictionary(m_gatheredAssetUuids);
- }
-
- public bool AddAssetUuidToInspect(UUID uuid)
+ ///
+ /// Adds the asset uuid for inspection during the gathering process.
+ ///
+ /// true, if for inspection was added, false otherwise.
+ /// UUID.
+ public bool AddForInspection(UUID uuid)
{
if (m_assetUuidsToInspect.Contains(uuid))
return false;
@@ -701,6 +720,107 @@ namespace OpenSim.Region.Framework.Scenes
return true;
}
+
+ ///
+ /// Gather all the asset uuids associated with a given object.
+ ///
+ ///
+ /// This includes both those directly associated with
+ /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained
+ /// within this object).
+ ///
+ /// The scene object for which to gather assets
+ public void AddForInspection(SceneObjectGroup sceneObject)
+ {
+ // m_log.DebugFormat(
+ // "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID);
+
+ SceneObjectPart[] parts = sceneObject.Parts;
+ for (int i = 0; i < parts.Length; i++)
+ {
+ SceneObjectPart part = parts[i];
+
+ // m_log.DebugFormat(
+ // "[ARCHIVER]: Getting part {0}, {1} for object {2}", part.Name, part.UUID, sceneObject.UUID);
+
+ try
+ {
+ Primitive.TextureEntry textureEntry = part.Shape.Textures;
+ if (textureEntry != null)
+ {
+ // Get the prim's default texture. This will be used for faces which don't have their own texture
+ if (textureEntry.DefaultTexture != null)
+ RecordTextureEntryAssetUuids(textureEntry.DefaultTexture);
+
+ if (textureEntry.FaceTextures != null)
+ {
+ // Loop through the rest of the texture faces (a non-null face means the face is different from DefaultTexture)
+ foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures)
+ {
+ if (texture != null)
+ RecordTextureEntryAssetUuids(texture);
+ }
+ }
+ }
+
+ // If the prim is a sculpt then preserve this information too
+ if (part.Shape.SculptTexture != UUID.Zero)
+ m_gatheredAssetUuids[part.Shape.SculptTexture] = (sbyte)AssetType.Texture;
+
+ if (part.Shape.ProjectionTextureUUID != UUID.Zero)
+ m_gatheredAssetUuids[part.Shape.ProjectionTextureUUID] = (sbyte)AssetType.Texture;
+
+ if (part.CollisionSound != UUID.Zero)
+ m_gatheredAssetUuids[part.CollisionSound] = (sbyte)AssetType.Sound;
+
+ if (part.ParticleSystem.Length > 0)
+ {
+ try
+ {
+ Primitive.ParticleSystem ps = new Primitive.ParticleSystem(part.ParticleSystem, 0);
+ if (ps.Texture != UUID.Zero)
+ m_gatheredAssetUuids[ps.Texture] = (sbyte)AssetType.Texture;
+ }
+ catch (Exception)
+ {
+ m_log.WarnFormat(
+ "[UUID GATHERER]: Could not check particle system for part {0} {1} in object {2} {3} since it is corrupt. Continuing.",
+ part.Name, part.UUID, sceneObject.Name, sceneObject.UUID);
+ }
+ }
+
+ TaskInventoryDictionary taskDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone();
+
+ // Now analyze this prim's inventory items to preserve all the uuids that they reference
+ foreach (TaskInventoryItem tii in taskDictionary.Values)
+ {
+ // m_log.DebugFormat(
+ // "[ARCHIVER]: Analysing item {0} asset type {1} in {2} {3}",
+ // tii.Name, tii.Type, part.Name, part.UUID);
+
+ if (!m_gatheredAssetUuids.ContainsKey(tii.AssetID))
+ AddForInspection(tii.AssetID, (sbyte)tii.Type);
+ }
+
+ // FIXME: We need to make gathering modular but we cannot yet, since gatherers are not guaranteed
+ // to be called with scene objects that are in a scene (e.g. in the case of hg asset mapping and
+ // inventory transfer. There needs to be a way for a module to register a method without assuming a
+ // Scene.EventManager is present.
+ // part.ParentGroup.Scene.EventManager.TriggerGatherUuids(part, assetUuids);
+
+
+ // still needed to retrieve textures used as materials for any parts containing legacy materials stored in DynAttrs
+ RecordMaterialsUuids(part);
+ }
+ catch (Exception e)
+ {
+ m_log.ErrorFormat("[UUID GATHERER]: Failed to get part - {0}", e);
+ m_log.DebugFormat(
+ "[UUID GATHERER]: Texture entry length for prim was {0} (min is 46)",
+ part.Shape.TextureEntry.Length);
+ }
+ }
+ }
///
/// 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
}
}
- private void RecordAssetUuids(UUID assetUuid, sbyte assetType)
+ private void AddForInspection(UUID assetUuid, sbyte assetType)
{
// Here, we want to collect uuids which require further asset fetches but mark the others as gathered
try
@@ -799,27 +919,27 @@ namespace OpenSim.Region.Framework.Scenes
if ((sbyte)AssetType.Bodypart == assetType || (sbyte)AssetType.Clothing == assetType)
{
- AddAssetUuidToInspect(assetUuid);
+ AddForInspection(assetUuid);
}
else if ((sbyte)AssetType.Gesture == assetType)
{
- AddAssetUuidToInspect(assetUuid);
+ AddForInspection(assetUuid);
}
else if ((sbyte)AssetType.Notecard == assetType)
{
- AddAssetUuidToInspect(assetUuid);
+ AddForInspection(assetUuid);
}
else if ((sbyte)AssetType.LSLText == assetType)
{
- AddAssetUuidToInspect(assetUuid);
+ AddForInspection(assetUuid);
}
else if ((sbyte)OpenSimAssetType.Material == assetType)
{
- AddAssetUuidToInspect(assetUuid);
+ AddForInspection(assetUuid);
}
else if ((sbyte)AssetType.Object == assetType)
{
- AddAssetUuidToInspect(assetUuid);
+ AddForInspection(assetUuid);
}
}
catch (Exception)
@@ -831,107 +951,6 @@ namespace OpenSim.Region.Framework.Scenes
}
}
- ///
- /// Gather all the asset uuids associated with a given object.
- ///
- ///
- /// This includes both those directly associated with
- /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained
- /// within this object).
- ///
- /// The scene object for which to gather assets
- public void RecordAssetUuids(SceneObjectGroup sceneObject)
- {
- // m_log.DebugFormat(
- // "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID);
-
- SceneObjectPart[] parts = sceneObject.Parts;
- for (int i = 0; i < parts.Length; i++)
- {
- SceneObjectPart part = parts[i];
-
- // m_log.DebugFormat(
- // "[ARCHIVER]: Getting part {0}, {1} for object {2}", part.Name, part.UUID, sceneObject.UUID);
-
- try
- {
- Primitive.TextureEntry textureEntry = part.Shape.Textures;
- if (textureEntry != null)
- {
- // Get the prim's default texture. This will be used for faces which don't have their own texture
- if (textureEntry.DefaultTexture != null)
- RecordTextureEntryAssetUuids(textureEntry.DefaultTexture);
-
- if (textureEntry.FaceTextures != null)
- {
- // Loop through the rest of the texture faces (a non-null face means the face is different from DefaultTexture)
- foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures)
- {
- if (texture != null)
- RecordTextureEntryAssetUuids(texture);
- }
- }
- }
-
- // If the prim is a sculpt then preserve this information too
- if (part.Shape.SculptTexture != UUID.Zero)
- m_gatheredAssetUuids[part.Shape.SculptTexture] = (sbyte)AssetType.Texture;
-
- if (part.Shape.ProjectionTextureUUID != UUID.Zero)
- m_gatheredAssetUuids[part.Shape.ProjectionTextureUUID] = (sbyte)AssetType.Texture;
-
- if (part.CollisionSound != UUID.Zero)
- m_gatheredAssetUuids[part.CollisionSound] = (sbyte)AssetType.Sound;
-
- if (part.ParticleSystem.Length > 0)
- {
- try
- {
- Primitive.ParticleSystem ps = new Primitive.ParticleSystem(part.ParticleSystem, 0);
- if (ps.Texture != UUID.Zero)
- m_gatheredAssetUuids[ps.Texture] = (sbyte)AssetType.Texture;
- }
- catch (Exception)
- {
- m_log.WarnFormat(
- "[UUID GATHERER]: Could not check particle system for part {0} {1} in object {2} {3} since it is corrupt. Continuing.",
- part.Name, part.UUID, sceneObject.Name, sceneObject.UUID);
- }
- }
-
- TaskInventoryDictionary taskDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone();
-
- // Now analyze this prim's inventory items to preserve all the uuids that they reference
- foreach (TaskInventoryItem tii in taskDictionary.Values)
- {
- // m_log.DebugFormat(
- // "[ARCHIVER]: Analysing item {0} asset type {1} in {2} {3}",
- // tii.Name, tii.Type, part.Name, part.UUID);
-
- if (!m_gatheredAssetUuids.ContainsKey(tii.AssetID))
- RecordAssetUuids(tii.AssetID, (sbyte)tii.Type);
- }
-
- // FIXME: We need to make gathering modular but we cannot yet, since gatherers are not guaranteed
- // to be called with scene objects that are in a scene (e.g. in the case of hg asset mapping and
- // inventory transfer. There needs to be a way for a module to register a method without assuming a
- // Scene.EventManager is present.
- // part.ParentGroup.Scene.EventManager.TriggerGatherUuids(part, assetUuids);
-
-
- // still needed to retrieve textures used as materials for any parts containing legacy materials stored in DynAttrs
- RecordMaterialsUuids(part);
- }
- catch (Exception e)
- {
- m_log.ErrorFormat("[UUID GATHERER]: Failed to get part - {0}", e);
- m_log.DebugFormat(
- "[UUID GATHERER]: Texture entry length for prim was {0} (min is 46)",
- part.Shape.TextureEntry.Length);
- }
- }
- }
-
///
/// Collect all the asset uuids found in one face of a Texture Entry.
///
@@ -940,7 +959,7 @@ namespace OpenSim.Region.Framework.Scenes
m_gatheredAssetUuids[texture.TextureID] = (sbyte)AssetType.Texture;
if (texture.MaterialID != UUID.Zero)
- AddAssetUuidToInspect(texture.MaterialID);
+ AddForInspection(texture.MaterialID);
}
///
@@ -948,7 +967,7 @@ namespace OpenSim.Region.Framework.Scenes
/// stored in legacy format in part.DynAttrs
///
///
- public void RecordMaterialsUuids(SceneObjectPart part)
+ private void RecordMaterialsUuids(SceneObjectPart part)
{
// scan thru the dynAttrs map of this part for any textures used as materials
OSD osdMaterials = null;
@@ -1039,7 +1058,7 @@ namespace OpenSim.Region.Framework.Scenes
UUID uuid = new UUID(uuidMatch.Value);
// m_log.DebugFormat("[ARCHIVER]: Recording {0} in text", uuid);
- AddAssetUuidToInspect(uuid);
+ AddForInspection(uuid);
}
}
@@ -1074,14 +1093,14 @@ namespace OpenSim.Region.Framework.Scenes
if (CoalescedSceneObjectsSerializer.TryFromXml(xml, out coa))
{
foreach (SceneObjectGroup sog in coa.Objects)
- RecordAssetUuids(sog);
+ AddForInspection(sog);
}
else
{
SceneObjectGroup sog = SceneObjectSerializer.FromOriginalXmlFormat(xml);
if (null != sog)
- RecordAssetUuids(sog);
+ AddForInspection(sog);
}
}
@@ -1147,8 +1166,8 @@ namespace OpenSim.Region.Framework.Scenes
protected string m_assetServerURL;
- public IteratingHGUuidGatherer(IAssetService assetService, string assetServerURL)
- : base(assetService)
+ public IteratingHGUuidGatherer(IAssetService assetService, string assetServerURL, IDictionary collector)
+ : base(assetService, collector)
{
m_assetServerURL = assetServerURL;
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 95e59ab38e..b834619d2c 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
///
/// Check if the caller has permission to manipulate the given NPC.
///
+ ///
+ /// A caller has permission if
+ /// * The caller UUID given is UUID.Zero.
+ /// * The avatar is unowned (owner is UUID.Zero).
+ /// * The avatar is owned and the owner and callerID match.
+ /// * The avatar is owned and the callerID matches its agentID.
+ ///
///
///
/// true if they do, false if they don't.
private bool CheckPermissions(NPCAvatar av, UUID callerID)
{
return callerID == UUID.Zero || av.OwnerID == UUID.Zero ||
- av.OwnerID == callerID;
+ av.OwnerID == callerID || av.AgentId == callerID;
}
}
}
\ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
index b9a217b649..1097efb856 100644
--- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
@@ -222,7 +222,7 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
void SetVars(Dictionary vars);
DetectParams GetDetectParams(int idx);
UUID GetDetectID(int idx);
- void SaveState(string assembly);
+ void SaveState();
void DestroyScriptInstance();
IScriptApi GetApi(string name);
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
index 9379f8fe74..de5f92df4a 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
@@ -663,9 +663,8 @@ namespace SecondLife
try
{
- FileStream fs = File.Open(assembly, FileMode.Open, FileAccess.Read);
- fs.Read(data, 0, data.Length);
- fs.Close();
+ using (FileStream fs = File.Open(assembly, FileMode.Open, FileAccess.Read))
+ fs.Read(data, 0, data.Length);
}
catch (Exception)
{
@@ -680,9 +679,8 @@ namespace SecondLife
Byte[] buf = Encoding.ASCII.GetBytes(filetext);
- FileStream sfs = File.Create(assembly + ".text");
- sfs.Write(buf, 0, buf.Length);
- sfs.Close();
+ using (FileStream sfs = File.Create(assembly + ".text"))
+ sfs.Write(buf, 0, buf.Length);
return assembly;
}
@@ -775,7 +773,6 @@ namespace SecondLife
return message;
}
-
private static void WriteMapFile(string filename, Dictionary, KeyValuePair> linemap)
{
string mapstring = String.Empty;
@@ -787,40 +784,42 @@ namespace SecondLife
}
Byte[] mapbytes = Encoding.ASCII.GetBytes(mapstring);
- FileStream mfs = File.Create(filename);
- mfs.Write(mapbytes, 0, mapbytes.Length);
- mfs.Close();
- }
+ using (FileStream mfs = File.Create(filename))
+ mfs.Write(mapbytes, 0, mapbytes.Length);
+ }
private static Dictionary, KeyValuePair> ReadMapFile(string filename)
{
Dictionary, KeyValuePair> linemap;
try
{
- StreamReader r = File.OpenText(filename);
- linemap = new Dictionary, KeyValuePair>();
-
- string line;
- while ((line = r.ReadLine()) != null)
+ using (StreamReader r = File.OpenText(filename))
{
- String[] parts = line.Split(new Char[] { ',' });
- int kk = System.Convert.ToInt32(parts[0]);
- int kv = System.Convert.ToInt32(parts[1]);
- int vk = System.Convert.ToInt32(parts[2]);
- int vv = System.Convert.ToInt32(parts[3]);
+ linemap = new Dictionary, KeyValuePair>();
- KeyValuePair k = new KeyValuePair(kk, kv);
- KeyValuePair v = new KeyValuePair(vk, vv);
+ string line;
+ while ((line = r.ReadLine()) != null)
+ {
+ String[] parts = line.Split(new Char[] { ',' });
+ int kk = System.Convert.ToInt32(parts[0]);
+ int kv = System.Convert.ToInt32(parts[1]);
+ int vk = System.Convert.ToInt32(parts[2]);
+ int vv = System.Convert.ToInt32(parts[3]);
- linemap[k] = v;
+ KeyValuePair k = new KeyValuePair(kk, kv);
+ KeyValuePair v = new KeyValuePair(vk, vv);
+
+ linemap[k] = v;
+ }
}
}
catch
{
linemap = new Dictionary, KeyValuePair>();
}
+
return linemap;
}
}
-}
+}
\ 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 9da2168585..b983be93b6 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
private bool m_TimerQueued;
private DateTime m_EventStart;
private bool m_InEvent;
- private string m_Assembly;
+ private string m_assemblyPath;
+ private string m_dataPath;
private string m_CurrentEvent = String.Empty;
private bool m_InSelfDelete;
private int m_MaxScriptQueue;
@@ -244,12 +245,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
///
///
///
+ ///
+ /// Path for all script associated data (state, etc.). In a multi-region set up
+ /// with all scripts loading into the same AppDomain this may not be the same place as the DLL itself.
+ ///
///
/// false if load failed, true if suceeded
- public bool Load(AppDomain dom, Assembly scriptAssembly, StateSource stateSource)
+ public bool Load(AppDomain dom, Assembly scriptAssembly, string dataPath, StateSource stateSource)
{
- //m_Assembly = scriptAssembly.CodeBase;
- m_Assembly = scriptAssembly.Location;
+ m_assemblyPath = scriptAssembly.Location;
+ m_dataPath = dataPath;
m_stateSource = stateSource;
try
@@ -270,14 +275,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
constructorParams = null;
}
-// m_log.DebugFormat(
-// "[SCRIP
-// scriptType.FullName, m_Assembly, Engine.World.Name);
-
if (dom != System.AppDomain.CurrentDomain)
m_Script
= (IScript)dom.CreateInstanceAndUnwrap(
- Path.GetFileNameWithoutExtension(m_Assembly),
+ Path.GetFileNameWithoutExtension(m_assemblyPath),
scriptType.FullName,
false,
BindingFlags.Default,
@@ -305,7 +306,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
{
m_log.ErrorFormat(
"[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}",
- ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, m_Assembly, e.Message, e.StackTrace);
+ ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, scriptAssembly.Location, e.Message, e.StackTrace);
return false;
}
@@ -340,10 +341,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
m_SaveState = true;
- string savedState = Path.Combine(Path.GetDirectoryName(m_Assembly), ItemID.ToString() + ".state");
+ string savedState = Path.Combine(m_dataPath, ItemID.ToString() + ".state");
if (File.Exists(savedState))
{
+// m_log.DebugFormat(
+// "[SCRIPT INSTANCE]: Found state for script {0} for {1} ({2}) at {3} in {4}",
+// ItemID, savedState, Part.Name, Part.ParentGroup.Name, Part.ParentGroup.Scene.Name);
+
string xml = String.Empty;
try
@@ -385,12 +390,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
m_startedFromSavedState = true;
}
}
- else
- {
- m_log.WarnFormat(
- "[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.",
- ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, savedState);
- }
+// else
+// {
+// m_log.WarnFormat(
+// "[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.",
+// ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, savedState);
+// }
}
catch (Exception e)
{
@@ -401,11 +406,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
}
// else
// {
-// ScenePresence presence = Engine.World.GetScenePresence(part.OwnerID);
-
-// if (presence != null && (!postOnRez))
-// presence.ControllingClient.SendAgentAlertMessage("Compile successful", false);
-
+// m_log.DebugFormat(
+// "[SCRIPT INSTANCE]: Did not find state for script {0} for {1} ({2}) at {3} in {4}",
+// ItemID, savedState, Part.Name, Part.ParentGroup.Name, Part.ParentGroup.Scene.Name);
// }
return true;
@@ -498,8 +501,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
public void RemoveState()
{
- string savedState = Path.Combine(Path.GetDirectoryName(m_Assembly),
- ItemID.ToString() + ".state");
+ string savedState = Path.Combine(m_dataPath, ItemID.ToString() + ".state");
+
+// m_log.DebugFormat(
+// "[SCRIPT INSTANCE]: Deleting state {0} for script {1} (id {2}) in part {3} (id {4}) in object {5} in {6}.",
+// savedState, ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name);
try
{
@@ -822,8 +828,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
if (Engine.World.PipeEventsForScript(LocalID) ||
data.EventName == "control") // Don't freeze avies!
{
- // m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}",
- // PrimName, ScriptName, data.EventName, State);
+// m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}",
+// PrimName, ScriptName, data.EventName, State);
try
{
@@ -849,7 +855,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
// This will be the very first event we deliver
// (state_entry) in default state
//
- SaveState(m_Assembly);
+ SaveState();
m_SaveState = false;
}
@@ -1043,7 +1049,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
return m_DetectParams[idx].Key;
}
- public void SaveState(string assembly)
+ public void SaveState()
{
// If we're currently in an event, just tell it to save upon return
//
@@ -1065,10 +1071,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
{
try
{
- FileStream fs = File.Create(Path.Combine(Path.GetDirectoryName(assembly), ItemID.ToString() + ".state"));
- Byte[] buf = Util.UTF8NoBomEncoding.GetBytes(xml);
- fs.Write(buf, 0, buf.Length);
- fs.Close();
+ using (FileStream fs = File.Create(Path.Combine(m_dataPath, ItemID.ToString() + ".state")))
+ {
+ Byte[] buf = Util.UTF8NoBomEncoding.GetBytes(xml);
+ fs.Write(buf, 0, buf.Length);
+ }
}
catch(Exception)
{
@@ -1148,7 +1155,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
public string GetAssemblyName()
{
- return m_Assembly;
+ return m_assemblyPath;
}
public string GetXMLState()
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineBasicTests.cs b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineBasicTests.cs
index fe15157af5..878e571617 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;
namespace OpenSim.Region.ScriptEngine.XEngine.Tests
{
///
- /// XEngine tests.
+ /// Basic XEngine tests.
///
[TestFixture]
- public class XEngineTest : OpenSimTestCase
+ public class XEngineBasicTests : OpenSimTestCase
{
private TestScene m_scene;
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 0000000000..587695fc1a
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineCrossingTests.cs
@@ -0,0 +1,195 @@
+/*
+ * 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.Threading;
+using Nini.Config;
+using NUnit.Framework;
+using OpenMetaverse;
+using OpenSim.Framework;
+using OpenSim.Region.CoreModules.Framework.EntityTransfer;
+using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
+using OpenSim.Region.Framework.Scenes;
+using OpenSim.Region.ScriptEngine.Shared;
+using OpenSim.Tests.Common;
+
+namespace OpenSim.Region.ScriptEngine.XEngine.Tests
+{
+ ///
+ /// XEngine tests connected with crossing scripts between regions.
+ ///
+ [TestFixture]
+ public class XEngineCrossingTests : OpenSimTestCase
+ {
+ [TestFixtureSetUp]
+ public void FixtureInit()
+ {
+ // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread.
+ Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest;
+ }
+
+ [TestFixtureTearDown]
+ public void TearDown()
+ {
+ // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple
+ // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression
+ // tests really shouldn't).
+ Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
+ }
+
+ ///
+ /// Test script state preservation when a script crosses between regions on the same simulator.
+ ///
+ [Test]
+ public void TestScriptCrossOnSameSimulator()
+ {
+ TestHelpers.InMethod();
+// TestHelpers.EnableLogging();
+
+ UUID userId = TestHelpers.ParseTail(0x1);
+ int sceneObjectIdTail = 0x2;
+
+ EntityTransferModule etmA = new EntityTransferModule();
+ EntityTransferModule etmB = new EntityTransferModule();
+ LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
+ XEngine xEngineA = new XEngine();
+ XEngine xEngineB = new XEngine();
+ xEngineA.DebugLevel = 1;
+ xEngineB.DebugLevel = 1;
+
+ IConfigSource configSource = new IniConfigSource();
+
+ IConfig startupConfig = configSource.AddConfig("Startup");
+ startupConfig.Set("DefaultScriptEngine", "XEngine");
+
+ IConfig xEngineConfig = configSource.AddConfig("XEngine");
+ xEngineConfig.Set("Enabled", "true");
+ xEngineConfig.Set("StartDelay", "0");
+
+ // These tests will not run with AppDomainLoading = true, at least on mono. For unknown reasons, the call
+ // to AssemblyResolver.OnAssemblyResolve fails.
+ xEngineConfig.Set("AppDomainLoading", "false");
+
+ IConfig modulesConfig = configSource.AddConfig("Modules");
+ modulesConfig.Set("EntityTransferModule", etmA.Name);
+ modulesConfig.Set("SimulationServices", lscm.Name);
+
+ SceneHelpers sh = new SceneHelpers();
+ TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000, configSource);
+ TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1000, 999, configSource);
+
+ SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, configSource, lscm);
+ SceneHelpers.SetupSceneModules(sceneA, configSource, etmA, xEngineA);
+ SceneHelpers.SetupSceneModules(sceneB, configSource, etmB, xEngineB);
+ sceneA.StartScripts();
+ sceneB.StartScripts();
+
+ SceneObjectGroup soSceneA = SceneHelpers.AddSceneObject(sceneA, 1, userId, "so1-", sceneObjectIdTail);
+ soSceneA.AbsolutePosition = new Vector3(128, 10, 20);
+
+ // CREATE SCRIPT TODO
+ InventoryItemBase scriptItemSceneA = new InventoryItemBase();
+ // itemTemplate.ID = itemId;
+ scriptItemSceneA.Name = "script1";
+ scriptItemSceneA.Folder = soSceneA.UUID;
+ scriptItemSceneA.InvType = (int)InventoryType.LSL;
+
+ AutoResetEvent chatEvent = new AutoResetEvent(false);
+ OSChatMessage messageReceived = null;
+ sceneA.EventManager.OnChatFromWorld += (s, m) => { messageReceived = m; chatEvent.Set(); };
+
+ sceneA.RezNewScript(userId, scriptItemSceneA,
+@"integer c = 0;
+
+default
+{
+ state_entry()
+ {
+ llSay(0, ""Script running"");
+ }
+
+ changed(integer change)
+ {
+ llSay(0, ""Changed"");
+ }
+
+ touch_start(integer n)
+ {
+ c = c + 1;
+ llSay(0, (string)c);
+ }
+}");
+
+ chatEvent.WaitOne(60000);
+
+ Assert.That(messageReceived, Is.Not.Null, "No chat message received.");
+ Assert.That(messageReceived.Message, Is.EqualTo("Script running"));
+
+ {
+ // XXX: Should not be doing this so directly. Should call some variant of EventManager.touch() instead.
+ DetectParams[] det = new DetectParams[1];
+ det[0] = new DetectParams();
+ det[0].Key = userId;
+ det[0].Populate(sceneA);
+
+ EventParams ep = new EventParams("touch_start", new Object[] { new LSL_Types.LSLInteger(1) }, det);
+
+ xEngineA.PostObjectEvent(soSceneA.LocalId, ep);
+ chatEvent.WaitOne(60000);
+
+ Assert.That(messageReceived.Message, Is.EqualTo("1"));
+ }
+
+ sceneB.EventManager.OnChatFromWorld += (s, m) => { messageReceived = m; chatEvent.Set(); };
+
+ // Cross with a negative value
+ soSceneA.AbsolutePosition = new Vector3(128, -10, 20);
+
+ chatEvent.WaitOne(60000);
+ Assert.That(messageReceived.Message, Is.EqualTo("Changed"));
+
+ // TEST sending event to moved prim and output
+ {
+ SceneObjectGroup soSceneB = sceneB.GetSceneObjectGroup(soSceneA.Name);
+ TaskInventoryItem scriptItemSceneB = soSceneB.RootPart.Inventory.GetInventoryItem(scriptItemSceneA.Name);
+
+ // XXX: Should not be doing this so directly. Should call some variant of EventManager.touch() instead.
+ DetectParams[] det = new DetectParams[1];
+ det[0] = new DetectParams();
+ det[0].Key = userId;
+ det[0].Populate(sceneB);
+
+ EventParams ep = new EventParams("touch_start", new Object[] { new LSL_Types.LSLInteger(1) }, det);
+
+ xEngineB.PostObjectEvent(soSceneB.LocalId, ep);
+ chatEvent.WaitOne(60000);
+
+ Assert.That(messageReceived.Message, Is.EqualTo("2"));
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index a4113d66a9..906c6ee298 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -70,7 +70,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
///
/// If DebugLevel >= 1, then we log every time that a script is started.
///
-// public int DebugLevel { get; set; }
+ public int DebugLevel { get; set; }
private SmartThreadPool m_ThreadPool;
private int m_MaxScriptQueue;
@@ -101,7 +101,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine
private bool m_InitialStartup = true;
private int m_ScriptFailCount; // Number of script fails since compile queue was last empty
private string m_ScriptErrorMessage;
- private Dictionary m_uniqueScripts = new Dictionary();
private bool m_AppDomainLoading;
private Dictionary m_ScriptErrors =
new Dictionary();
@@ -403,12 +402,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
+ "Level >= 2, log event invocations.\n",
HandleDebugScriptLogCommand);
-// MainConsole.Instance.Commands.AddCommand(
-// "Debug", false, "debug xengine", "debug xengine []",
-// "Turn on detailed xengine debugging.",
-// "If level <= 0, then no extra logging is done.\n"
-// + "If level >= 1, then we log every time that a script is started.",
-// HandleDebugLevelCommand);
+ MainConsole.Instance.Commands.AddCommand(
+ "Debug", false, "debug xengine log", "debug xengine log []",
+ "Turn on detailed xengine debugging.",
+ "If level <= 0, then no extra logging is done.\n"
+ + "If level >= 1, then we log every time that a script is started.",
+ HandleDebugLevelCommand);
}
private void HandleDebugScriptLogCommand(string module, string[] args)
@@ -451,26 +450,26 @@ namespace OpenSim.Region.ScriptEngine.XEngine
///
///
///
-// private void HandleDebugLevelCommand(string module, string[] args)
-// {
-// if (args.Length == 3)
-// {
-// int newDebug;
-// if (int.TryParse(args[2], out newDebug))
-// {
-// DebugLevel = newDebug;
-// MainConsole.Instance.OutputFormat("Debug level set to {0}", newDebug);
-// }
-// }
-// else if (args.Length == 2)
-// {
-// MainConsole.Instance.OutputFormat("Current debug level is {0}", DebugLevel);
-// }
-// else
-// {
-// MainConsole.Instance.Output("Usage: debug xengine 0..1");
-// }
-// }
+ private void HandleDebugLevelCommand(string module, string[] args)
+ {
+ if (args.Length <= 4)
+ {
+ int newDebug;
+ if (ConsoleUtil.TryParseConsoleNaturalInt(MainConsole.Instance, args[3], out newDebug))
+ {
+ DebugLevel = newDebug;
+ MainConsole.Instance.OutputFormat("Debug level set to {0} in XEngine for region {1}", newDebug, m_Scene.Name);
+ }
+ }
+ else if (args.Length == 3)
+ {
+ MainConsole.Instance.OutputFormat("Current debug level is {0}", DebugLevel);
+ }
+ else
+ {
+ MainConsole.Instance.Output("Usage: debug xengine log ");
+ }
+ }
///
/// 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
}
sb.AppendFormat("Scripts loaded : {0}\n", scriptsLoaded);
- sb.AppendFormat("Unique scripts : {0}\n", m_uniqueScripts.Count);
sb.AppendFormat("Scripts waiting for load : {0}\n", m_CompileQueue.Count);
sb.AppendFormat("Max threads : {0}\n", m_ThreadPool.MaxThreads);
sb.AppendFormat("Min threads : {0}\n", m_ThreadPool.MinThreads);
@@ -716,22 +714,17 @@ namespace OpenSim.Region.ScriptEngine.XEngine
{
// Force a final state save
//
- if (m_Assemblies.ContainsKey(instance.AssetID))
+ try
{
- string assembly = m_Assemblies[instance.AssetID];
-
- try
- {
- instance.SaveState(assembly);
- }
- catch (Exception e)
- {
- m_log.Error(
- string.Format(
- "[XEngine]: Failed final state save for script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ",
- instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name)
- , e);
- }
+ instance.SaveState();
+ }
+ catch (Exception e)
+ {
+ m_log.Error(
+ string.Format(
+ "[XEngine]: Failed final state save for script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ",
+ instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name)
+ , e);
}
// Clear the event queue and abort the instance thread
@@ -840,18 +833,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
foreach (IScriptInstance i in instances)
{
- string assembly = String.Empty;
-
- lock (m_Scripts)
- {
- if (!m_Assemblies.ContainsKey(i.AssetID))
- continue;
- assembly = m_Assemblies[i.AssetID];
- }
-
try
{
- i.SaveState(assembly);
+ i.SaveState();
}
catch (Exception e)
{
@@ -1001,12 +985,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine
if (engine != ScriptEngineName)
return;
- // If we've seen this exact script text before, use that reference instead
- if (m_uniqueScripts.ContainsKey(script))
- script = m_uniqueScripts[script];
- else
- m_uniqueScripts[script] = script;
-
Object[] parms = new Object[]{localID, itemID, script, startParam, postOnRez, (StateSource)stateSource};
if (stateSource == (int)StateSource.ScriptedRez)
@@ -1020,11 +998,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
}
else
{
- m_CompileQueue.Enqueue(parms);
lock (m_CompileDict)
- {
m_CompileDict[itemID] = 0;
- }
+
+ // This must occur after the m_CompileDict so that an existing compile thread cannot hit the check
+ // in DoOnRezScript() before m_CompileDict has been updated.
+ m_CompileQueue.Enqueue(parms);
// m_log.DebugFormat("[XEngine]: Added script {0} to compile queue", itemID);
@@ -1100,7 +1079,15 @@ namespace OpenSim.Region.ScriptEngine.XEngine
// due to a race condition
//
lock (m_CompileQueue)
+ {
m_CurrentCompile = null;
+
+ // This is to avoid a situation where the m_CompileQueue while loop above could complete but
+ // OnRezScript() place a new script on the queue and check m_CurrentCompile = null before we hit
+ // this section.
+ if (m_CompileQueue.Count > 0)
+ m_CurrentCompile = m_ThreadPool.QueueWorkItem(DoOnRezScriptQueue, null);
+ }
}
return null;
@@ -1148,10 +1135,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine
return false;
}
- m_log.DebugFormat(
- "[XEngine]: Loading script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}",
- part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID,
- part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
+ if (DebugLevel > 0)
+ m_log.DebugFormat(
+ "[XEngine]: Loading script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}",
+ part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID,
+ part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
UUID assetID = item.AssetID;
@@ -1170,7 +1158,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine
lock (m_AddingAssemblies)
{
m_Compiler.PerformScriptCompile(script, assetID.ToString(), item.OwnerID, out assemblyPath, out linemap);
-
+
+// m_log.DebugFormat(
+// "[XENGINE]: Found assembly path {0} onrez {1} in {2}",
+// assemblyPath, item.ItemID, World.Name);
+
if (!m_AddingAssemblies.ContainsKey(assemblyPath)) {
m_AddingAssemblies[assemblyPath] = 1;
} else {
@@ -1348,14 +1340,24 @@ namespace OpenSim.Region.ScriptEngine.XEngine
// simulator session if the script halt strategy has been changed. Instead, we'll continue with
// the existing DLL and the new one will be used in the next simulator session.
if (recompile)
+ {
+ m_log.DebugFormat(
+ "[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.",
+ part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID,
+ part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.Name,
+ m_coopTermination ? "co-op" : "abort");
+
m_Compiler.PerformScriptCompile(script, assetID.ToString(), item.OwnerID, true, out assemblyPath, out linemap);
+ }
instance = new ScriptInstance(this, part,
item,
startParam, postOnRez,
m_MaxScriptQueue);
- if (!instance.Load(m_AppDomains[appDomain], scriptAssembly, stateSource))
+ if (!instance.Load(
+ m_AppDomains[appDomain], scriptAssembly,
+ Path.Combine(ScriptEnginePath, World.RegionInfo.RegionID.ToString()), stateSource))
return false;
// if (DebugLevel >= 1)
@@ -1586,7 +1588,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
IScriptInstance instance = (ScriptInstance) parms;
- //m_log.DebugFormat("[XEngine]: Processing event for {0}", instance);
+// m_log.DebugFormat("[XEngine]: Processing event for {0}", instance);
return instance.EventProcessor();
}
@@ -2155,7 +2157,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
catch (IOException ex)
{
// if there already exists a file at that location, it may be locked.
- m_log.ErrorFormat("[XEngine]: Linemap file {0} already exists! {1}", mappath, ex.Message);
+ m_log.Error(
+ string.Format("[XEngine]: Linemap file {0} could not be written. Exception ", mappath), ex);
}
}
}
@@ -2181,6 +2184,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
m_log.ErrorFormat("[XEngine]: Error whilst writing state file {0}, {1}", statepath, ex.Message);
}
+// m_log.DebugFormat(
+// "[XEngine]: Wrote state for script item with ID {0} at {1} in {2}", itemID, statepath, m_Scene.Name);
+
return true;
}
diff --git a/OpenSim/Server/Handlers/BakedTextures/XBakes.cs b/OpenSim/Server/Handlers/BakedTextures/XBakes.cs
index d1b2e124d8..4e554336ae 100644
--- a/OpenSim/Server/Handlers/BakedTextures/XBakes.cs
+++ b/OpenSim/Server/Handlers/BakedTextures/XBakes.cs
@@ -107,11 +107,9 @@ namespace OpenSim.Server.Handlers.BakedTextures
File.Delete(diskFile);
byte[] data = utf8encoding.GetBytes(sdata);
- FileStream fs = File.Create(diskFile);
- fs.Write(data, 0, data.Length);
-
- fs.Close();
+ using (FileStream fs = File.Create(diskFile))
+ fs.Write(data, 0, data.Length);
}
private void HandleDeleteBakes(string module, string[] args)
diff --git a/OpenSim/Services/GridService/GridService.cs b/OpenSim/Services/GridService/GridService.cs
index e8a545cf10..29723d8329 100644
--- a/OpenSim/Services/GridService/GridService.cs
+++ b/OpenSim/Services/GridService/GridService.cs
@@ -317,8 +317,10 @@ namespace OpenSim.Services.GridService
m_log.DebugFormat("[GRID SERVICE]: Database exception: {0}", e);
}
- m_log.DebugFormat("[GRID SERVICE]: Region {0} ({1}) registered successfully at {2}-{3} with flags {4}",
- regionInfos.RegionName, regionInfos.RegionID, regionInfos.RegionCoordX, regionInfos.RegionCoordY,
+ m_log.DebugFormat
+ ("[GRID SERVICE]: Region {0} ({1}, {2}x{3}) registered at {4},{5} with flags {6}",
+ regionInfos.RegionName, regionInfos.RegionID, regionInfos.RegionSizeX, regionInfos.RegionSizeY,
+ regionInfos.RegionCoordX, regionInfos.RegionCoordY,
(OpenSim.Framework.RegionFlags)flags);
return String.Empty;
diff --git a/OpenSim/Services/UserAccountService/UserAccountService.cs b/OpenSim/Services/UserAccountService/UserAccountService.cs
index ec6118b3f6..4705445675 100644
--- a/OpenSim/Services/UserAccountService/UserAccountService.cs
+++ b/OpenSim/Services/UserAccountService/UserAccountService.cs
@@ -98,7 +98,12 @@ namespace OpenSim.Services.UserAccountService
MainConsole.Instance.Commands.AddCommand("Users", false,
"reset user password",
"reset user password [ [ []]]",
- "Reset a user password", HandleResetUserPassword);
+ "Reset a user password", HandleResetUserPassword);
+
+ MainConsole.Instance.Commands.AddCommand("Users", false,
+ "reset user email",
+ "reset user email [ [ []]]",
+ "Reset a user email address", HandleResetUserEmail);
MainConsole.Instance.Commands.AddCommand("Users", false,
"set user level",
@@ -420,6 +425,43 @@ namespace OpenSim.Services.UserAccountService
MainConsole.Instance.OutputFormat("Password reset for user {0} {1}", firstName, lastName);
}
+ protected void HandleResetUserEmail(string module, string[] cmdparams)
+ {
+ string firstName;
+ string lastName;
+ string newEmail;
+
+ if (cmdparams.Length < 4)
+ firstName = MainConsole.Instance.CmdPrompt("First name");
+ else firstName = cmdparams[3];
+
+ if (cmdparams.Length < 5)
+ lastName = MainConsole.Instance.CmdPrompt("Last name");
+ else lastName = cmdparams[4];
+
+ if (cmdparams.Length < 6)
+ newEmail = MainConsole.Instance.PasswdPrompt("New Email");
+ else newEmail = cmdparams[5];
+
+ UserAccount account = GetUserAccount(UUID.Zero, firstName, lastName);
+ if (account == null)
+ {
+ MainConsole.Instance.OutputFormat("No such user as {0} {1}", firstName, lastName);
+ return;
+ }
+
+ bool success = false;
+
+ account.Email = newEmail;
+
+ success = StoreUserAccount(account);
+ if (!success)
+ MainConsole.Instance.OutputFormat("Unable to set Email for account {0} {1}.", firstName, lastName);
+ else
+ MainConsole.Instance.OutputFormat("User Email set for user {0} {1} to {2}", firstName, lastName, account.Email);
+ }
+
+
protected void HandleSetUserLevel(string module, string[] cmdparams)
{
string firstName;
diff --git a/bin/OpenMetaverse.dll b/bin/OpenMetaverse.dll
index f1f5ed66a3..97aaba45ed 100755
Binary files a/bin/OpenMetaverse.dll and b/bin/OpenMetaverse.dll differ
diff --git a/bin/OpenSim.exe.config b/bin/OpenSim.exe.config
index 31f1064068..e19a47a4a4 100755
--- a/bin/OpenSim.exe.config
+++ b/bin/OpenSim.exe.config
@@ -57,11 +57,6 @@
-
-
-
-
-
diff --git a/bin/Robust.HG.ini.example b/bin/Robust.HG.ini.example
index 9a6371b3af..4d4ebde14f 100644
--- a/bin/Robust.HG.ini.example
+++ b/bin/Robust.HG.ini.example
@@ -208,6 +208,10 @@
[InventoryService]
LocalServiceModule = "OpenSim.Services.InventoryService.dll:XInventoryService"
+ ; Will calls to purge folders (empty trash) and immediately delete/update items or folders (not move to trash first) succeed?
+ ; If this is set to false then some other arrangement must be made to perform these operations if necessary.
+ AllowDelete = true
+
; * This is the new style grid service.
; * "Realm" is the table that is used for user lookup.
diff --git a/bin/Robust.ini.example b/bin/Robust.ini.example
index 0ce16ba47f..a7b39a36aa 100644
--- a/bin/Robust.ini.example
+++ b/bin/Robust.ini.example
@@ -179,6 +179,10 @@
[InventoryService]
LocalServiceModule = "OpenSim.Services.InventoryService.dll:XInventoryService"
+ ; Will calls to purge folders (empty trash) and immediately delete/update items or folders (not move to trash first) succeed?
+ ; If this is set to false then some other arrangement must be made to perform these operations if necessary.
+ AllowDelete = true
+
; * This is the new style grid service.
; * "Realm" is the table that is used for user lookup.
diff --git a/prebuild.xml b/prebuild.xml
index 90997cf1b4..a9a7cfcf73 100644
--- a/prebuild.xml
+++ b/prebuild.xml
@@ -2926,7 +2926,6 @@
-