If JobEngine is active, then use it to copy/rez attachments for an avatar entering the scene that isn't initially logging on. This will execute tasks consecutively rather than concurrently.

This has two aims
1) Reduce initial teleport failures when a foreign Hypergrid user enters a region by not holding up the teleport for attachment rez (this can be particularly costly when HG gets all assets in the object graph.
2) Reduce server load that may impact other simulator activities.
This complements existing JobEngine options that perform initial login attachment rez and appearance send in consecutive tasks.
ghosts
Justin Clark-Casey (justincc) 2014-10-14 16:57:58 +01:00
parent 275613ad83
commit b9b2f5686f
1 changed files with 62 additions and 22 deletions

View File

@ -1240,11 +1240,6 @@ namespace OpenSim.Region.Framework.Scenes
} }
else 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 need to restart scripts here so that they receive the correct changed events (CHANGED_TELEPORT // 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 // 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 // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are
@ -1258,22 +1253,21 @@ namespace OpenSim.Region.Framework.Scenes
// But XEngine starts all scripts unsuspended. Starting them suspended will not currently work because script rezzing // 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 // 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. // script is rezzed. This means the ResumeScripts() does absolutely nothing when using XEngine.
//
// One cannot simply iterate over attachments in a fire and forget thread because this would no longer
// be locked, allowing race conditions if other code changes the attachments list.
List<SceneObjectGroup> attachments = GetAttachments(); List<SceneObjectGroup> attachments = GetAttachments();
if (attachments.Count > 0) if (attachments.Count > 0)
{ {
m_log.DebugFormat( if (Watchdog.JobEngine.IsRunning)
"[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name);
// Resume scripts
foreach (SceneObjectGroup sog in attachments)
{ {
sog.ScheduleGroupForFullUpdate(); Watchdog.RunWhenPossible(
sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); "StartAttachmentScripts",
sog.ResumeScripts(); o => RestartAttachmentScripts(attachments),
string.Format("Start attachment scripts for {0} in {1}", Name, Scene.Name),
null);
}
else
{
RestartAttachmentScripts(attachments);
} }
} }
} }
@ -1298,6 +1292,20 @@ namespace OpenSim.Region.Framework.Scenes
return true; return true;
} }
private void RestartAttachmentScripts(List<SceneObjectGroup> attachments)
{
m_log.DebugFormat(
"[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name);
// Resume scripts
foreach (SceneObjectGroup sog in attachments)
{
sog.ScheduleGroupForFullUpdate();
sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
sog.ResumeScripts();
}
}
private static bool IsRealLogin(TeleportFlags teleportFlags) private static bool IsRealLogin(TeleportFlags teleportFlags)
{ {
return ((teleportFlags & TeleportFlags.ViaLogin) != 0) && ((teleportFlags & TeleportFlags.ViaHGLogin) == 0); return ((teleportFlags & TeleportFlags.ViaLogin) != 0) && ((teleportFlags & TeleportFlags.ViaHGLogin) == 0);
@ -1813,13 +1821,20 @@ namespace OpenSim.Region.Framework.Scenes
} }
// XXX: If we force an update here, then multiple attachments do appear correctly on a destination region // XXX: If we force an update after activity has completed, then multiple attachments do appear correctly on a destination region
// If we do it a little bit earlier (e.g. when converting the child to a root agent) then this does not work. // If we do it a little bit earlier (e.g. when converting the child to a root agent) then this does not work.
// This may be due to viewer code or it may be something we're not doing properly simulator side. // This may be due to viewer code or it may be something we're not doing properly simulator side.
lock (m_attachments) if (Watchdog.JobEngine.IsRunning)
{ {
foreach (SceneObjectGroup sog in m_attachments) Watchdog.RunWhenPossible(
sog.ScheduleGroupForFullUpdate(); "ScheduleAttachmentsForFullUpdate",
o => ScheduleAttachmentsForFullUpdate(),
string.Format("Schedule attachments for full update for {0} in {1}", Name, Scene.Name),
null);
}
else
{
ScheduleAttachmentsForFullUpdate();
} }
// m_log.DebugFormat( // m_log.DebugFormat(
@ -1832,6 +1847,15 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
private void ScheduleAttachmentsForFullUpdate()
{
lock (m_attachments)
{
foreach (SceneObjectGroup sog in m_attachments)
sog.ScheduleGroupForFullUpdate();
}
}
/// <summary> /// <summary>
/// Callback for the Camera view block check. Gets called with the results of the camera view block test /// Callback for the Camera view block check. Gets called with the results of the camera view block test
/// hitYN is true when there's something in the way. /// hitYN is true when there's something in the way.
@ -4039,9 +4063,25 @@ namespace OpenSim.Region.Framework.Scenes
Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero); Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero);
if (Scene.AttachmentsModule != null) if (Scene.AttachmentsModule != null)
{
// If the JobEngine is running we can schedule this job now and continue rather than waiting for all
// attachments to copy, which might take a long time in the Hypergrid case as the entire inventory
// graph is inspected for each attachments and assets possibly fetched.
//
// We don't need to worry about a race condition as the job to later start the scripts is also
// JobEngine scheduled and so will always occur after this task.
// XXX: This will not be true if JobEngine ever gets more than one thread.
if (Watchdog.JobEngine.IsRunning)
Watchdog.RunWhenPossible(
"CopyAttachments",
o => Scene.AttachmentsModule.CopyAttachments(cAgent, this),
string.Format("Copy attachments for {0} entering {1}", Name, Scene.Name),
null);
else
Scene.AttachmentsModule.CopyAttachments(cAgent, this); Scene.AttachmentsModule.CopyAttachments(cAgent, this);
}
// This must occur after attachments are copied, as it releases the CompleteMovement() calling thread // This must occur after attachments are copied or scheduled to be copied, as it releases the CompleteMovement() calling thread
// originating from the client completing a teleport. Otherwise, CompleteMovement() code to restart // originating from the client completing a teleport. Otherwise, CompleteMovement() code to restart
// script attachments can outrace this thread. // script attachments can outrace this thread.
lock (m_originRegionIDAccessLock) lock (m_originRegionIDAccessLock)