diff options
author | Justin Clark-Casey (justincc) | 2014-11-06 01:15:22 +0000 |
---|---|---|
committer | Justin Clark-Casey (justincc) | 2014-11-25 23:23:11 +0000 |
commit | aeae34505f5f306bbf4d9f3db19db8a26ac5e63d (patch) | |
tree | 1a6afdaeb024dc9ffa60cf98e9f53afc1f992c96 /OpenSim | |
parent | Introduce an IteratingUuidGatherer where each fetch from the asset service (i... (diff) | |
download | opensim-SC_OLD-aeae34505f5f306bbf4d9f3db19db8a26ac5e63d.zip opensim-SC_OLD-aeae34505f5f306bbf4d9f3db19db8a26ac5e63d.tar.gz opensim-SC_OLD-aeae34505f5f306bbf4d9f3db19db8a26ac5e63d.tar.bz2 opensim-SC_OLD-aeae34505f5f306bbf4d9f3db19db8a26ac5e63d.tar.xz |
When processing incoming attachments via HG, if a request for uuid gathering or final asset import takes too long remove remaining requests from same user to prevent hold up of other user's incoming attachments.
This improves upon the earlier naive simply queueing immplementation.
Threshold is 30 seconds. If this happens to a user they can relog and fetch will be reattempted.
Diffstat (limited to 'OpenSim')
4 files changed, 121 insertions, 29 deletions
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index be409bb..7e356ea 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs | |||
@@ -546,6 +546,31 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
546 | } | 546 | } |
547 | } | 547 | } |
548 | 548 | ||
549 | private void RemoveIncomingSceneObjectJobs(string commonIdToRemove) | ||
550 | { | ||
551 | List<Job> jobsToReinsert = new List<Job>(); | ||
552 | int jobsRemoved = 0; | ||
553 | |||
554 | Job job; | ||
555 | while ((job = m_incomingSceneObjectEngine.RemoveNextRequest()) != null) | ||
556 | { | ||
557 | if (job.CommonId != commonIdToRemove) | ||
558 | jobsToReinsert.Add(job); | ||
559 | else | ||
560 | jobsRemoved++; | ||
561 | } | ||
562 | |||
563 | m_log.DebugFormat( | ||
564 | "[HG ENTITY TRANSFER]: Removing {0} jobs with common ID {1} and reinserting {2} other jobs", | ||
565 | jobsRemoved, commonIdToRemove, jobsToReinsert.Count); | ||
566 | |||
567 | if (jobsToReinsert.Count > 0) | ||
568 | { | ||
569 | foreach (Job jobToReinsert in jobsToReinsert) | ||
570 | m_incomingSceneObjectEngine.QueueRequest(jobToReinsert); | ||
571 | } | ||
572 | } | ||
573 | |||
549 | public override bool HandleIncomingSceneObject(SceneObjectGroup so, Vector3 newPosition) | 574 | public override bool HandleIncomingSceneObject(SceneObjectGroup so, Vector3 newPosition) |
550 | { | 575 | { |
551 | // FIXME: We must make it so that we can use SOG.IsAttachment here. At the moment it is always null! | 576 | // FIXME: We must make it so that we can use SOG.IsAttachment here. At the moment it is always null! |
@@ -564,38 +589,73 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
564 | { | 589 | { |
565 | m_incomingSceneObjectEngine.QueueRequest( | 590 | m_incomingSceneObjectEngine.QueueRequest( |
566 | string.Format("HG UUID Gather for attachment {0} for {1}", so.Name, aCircuit.Name), | 591 | string.Format("HG UUID Gather for attachment {0} for {1}", so.Name, aCircuit.Name), |
592 | so.OwnerID.ToString(), | ||
567 | o => | 593 | o => |
568 | { | 594 | { |
569 | string url = aCircuit.ServiceURLs["AssetServerURI"].ToString(); | 595 | string url = aCircuit.ServiceURLs["AssetServerURI"].ToString(); |
570 | m_log.DebugFormat( | 596 | // m_log.DebugFormat( |
571 | "[HG ENTITY TRANSFER MODULE]: Incoming attachment {0} for HG user {1} with asset server {2}", | 597 | // "[HG ENTITY TRANSFER MODULE]: Incoming attachment {0} for HG user {1} with asset service {2}", |
572 | so.Name, so.AttachedAvatar, url); | 598 | // so.Name, so.AttachedAvatar, url); |
573 | 599 | ||
574 | IteratingHGUuidGatherer uuidGatherer = new IteratingHGUuidGatherer(Scene.AssetService, url); | 600 | IteratingHGUuidGatherer uuidGatherer = new IteratingHGUuidGatherer(Scene.AssetService, url); |
575 | uuidGatherer.RecordAssetUuids(so); | 601 | uuidGatherer.RecordAssetUuids(so); |
576 | 602 | ||
577 | // XXX: We will shortly use this iterating mechanism to check if a fetch is taking too long | 603 | while (!uuidGatherer.Complete) |
578 | // but just for now we will simply fetch everything. If this was permanent could use | 604 | { |
579 | // GatherAll() | 605 | int tickStart = Util.EnvironmentTickCount(); |
580 | while (uuidGatherer.GatherNext()) | 606 | |
581 | m_log.DebugFormat( | 607 | UUID? nextUuid = uuidGatherer.NextUuidToInspect; |
582 | "[HG ENTITY TRANSFER]: Gathered attachment {0} for HG user {1} with asset server {2}", | 608 | uuidGatherer.GatherNext(); |
583 | so.Name, so.OwnerID, url); | 609 | |
610 | // m_log.DebugFormat( | ||
611 | // "[HG ENTITY TRANSFER]: Gathered attachment asset uuid {0} for object {1} for HG user {2} took {3} ms with asset service {4}", | ||
612 | // nextUuid, so.Name, so.OwnerID, Util.EnvironmentTickCountSubtract(tickStart), url); | ||
613 | |||
614 | int ticksElapsed = Util.EnvironmentTickCountSubtract(tickStart); | ||
615 | |||
616 | if (ticksElapsed > 30000) | ||
617 | { | ||
618 | m_log.WarnFormat( | ||
619 | "[HG ENTITY TRANSFER]: Removing incoming scene object jobs for HG user {0} as gather of {1} from {2} took {3} ms to respond (> {4} ms)", | ||
620 | so.OwnerID, so.Name, url, ticksElapsed, 30000); | ||
621 | |||
622 | RemoveIncomingSceneObjectJobs(so.OwnerID.ToString()); | ||
623 | |||
624 | return; | ||
625 | } | ||
626 | } | ||
584 | 627 | ||
585 | IDictionary<UUID, sbyte> ids = uuidGatherer.GetGatheredUuids(); | 628 | IDictionary<UUID, sbyte> ids = uuidGatherer.GetGatheredUuids(); |
586 | 629 | ||
587 | m_log.DebugFormat( | 630 | // m_log.DebugFormat( |
588 | "[HG ENTITY TRANSFER]: Fetching {0} assets for attachment {1} for HG user {2} with asset server {3}", | 631 | // "[HG ENTITY TRANSFER]: Fetching {0} assets for attachment {1} for HG user {2} with asset service {3}", |
589 | ids.Count, so.Name, so.OwnerID, url); | 632 | // ids.Count, so.Name, so.OwnerID, url); |
590 | 633 | ||
591 | foreach (KeyValuePair<UUID, sbyte> kvp in ids) | 634 | foreach (KeyValuePair<UUID, sbyte> kvp in ids) |
592 | uuidGatherer.FetchAsset(kvp.Key); | 635 | { |
636 | int tickStart = Util.EnvironmentTickCount(); | ||
637 | |||
638 | uuidGatherer.FetchAsset(kvp.Key); | ||
639 | |||
640 | int ticksElapsed = Util.EnvironmentTickCountSubtract(tickStart); | ||
641 | |||
642 | if (ticksElapsed > 30000) | ||
643 | { | ||
644 | m_log.WarnFormat( | ||
645 | "[HG ENTITY TRANSFER]: Removing incoming scene object jobs for HG user {0} as fetch of {1} from {2} took {3} ms to respond (> {4} ms)", | ||
646 | so.OwnerID, kvp.Key, url, ticksElapsed, 30000); | ||
647 | |||
648 | RemoveIncomingSceneObjectJobs(so.OwnerID.ToString()); | ||
649 | |||
650 | return; | ||
651 | } | ||
652 | } | ||
593 | 653 | ||
594 | base.HandleIncomingSceneObject(so, newPosition); | 654 | base.HandleIncomingSceneObject(so, newPosition); |
595 | 655 | ||
596 | m_log.DebugFormat( | 656 | // m_log.DebugFormat( |
597 | "[HG ENTITY TRANSFER MODULE]: Completed incoming attachment {0} for HG user {1} with asset server {2}", | 657 | // "[HG ENTITY TRANSFER MODULE]: Completed incoming attachment {0} for HG user {1} with asset server {2}", |
598 | so.Name, so.OwnerID, url); | 658 | // so.Name, so.OwnerID, url); |
599 | }, | 659 | }, |
600 | null); | 660 | null); |
601 | } | 661 | } |
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGIncomingSceneObjectEngine.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGIncomingSceneObjectEngine.cs index 718db31..ce6cdc9 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGIncomingSceneObjectEngine.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGIncomingSceneObjectEngine.cs | |||
@@ -38,13 +38,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
38 | { | 38 | { |
39 | public class Job | 39 | public class Job |
40 | { | 40 | { |
41 | public string Name; | 41 | public string Name { get; private set; } |
42 | public WaitCallback Callback; | 42 | public string CommonId { get; private set; } |
43 | public object O; | 43 | public WaitCallback Callback { get; private set; } |
44 | public object O { get; private set; } | ||
44 | 45 | ||
45 | public Job(string name, WaitCallback callback, object o) | 46 | public Job(string name, string commonId, WaitCallback callback, object o) |
46 | { | 47 | { |
47 | Name = name; | 48 | Name = name; |
49 | CommonId = commonId; | ||
48 | Callback = callback; | 50 | Callback = callback; |
49 | O = o; | 51 | O = o; |
50 | } | 52 | } |
@@ -90,6 +92,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
90 | 92 | ||
91 | public HGIncomingSceneObjectEngine(string name) | 93 | public HGIncomingSceneObjectEngine(string name) |
92 | { | 94 | { |
95 | // LogLevel = 1; | ||
93 | Name = name; | 96 | Name = name; |
94 | RequestProcessTimeoutOnStop = 5000; | 97 | RequestProcessTimeoutOnStop = 5000; |
95 | 98 | ||
@@ -192,10 +195,24 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
192 | } | 195 | } |
193 | } | 196 | } |
194 | 197 | ||
195 | public bool QueueRequest(string name, WaitCallback req, object o) | 198 | public Job RemoveNextRequest() |
199 | { | ||
200 | Job nextRequest; | ||
201 | m_requestQueue.TryTake(out nextRequest); | ||
202 | |||
203 | return nextRequest; | ||
204 | } | ||
205 | |||
206 | public bool QueueRequest(string name, string commonId, WaitCallback req, object o) | ||
207 | { | ||
208 | return QueueRequest(new Job(name, commonId, req, o)); | ||
209 | } | ||
210 | |||
211 | public bool QueueRequest(Job job) | ||
196 | { | 212 | { |
197 | if (LogLevel >= 1) | 213 | if (LogLevel >= 1) |
198 | m_log.DebugFormat("[HG INCOMING SCENE OBJECT ENGINE]: Queued job {0}", name); | 214 | m_log.DebugFormat( |
215 | "[HG INCOMING SCENE OBJECT ENGINE]: Queued job {0}, common ID {1}", job.Name, job.CommonId); | ||
199 | 216 | ||
200 | if (m_requestQueue.Count < m_requestQueue.BoundedCapacity) | 217 | if (m_requestQueue.Count < m_requestQueue.BoundedCapacity) |
201 | { | 218 | { |
@@ -203,7 +220,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
203 | // "[OUTGOING QUEUE REFILL ENGINE]: Adding request for categories {0} for {1} in {2}", | 220 | // "[OUTGOING QUEUE REFILL ENGINE]: Adding request for categories {0} for {1} in {2}", |
204 | // categories, client.AgentID, m_udpServer.Scene.Name); | 221 | // categories, client.AgentID, m_udpServer.Scene.Name); |
205 | 222 | ||
206 | m_requestQueue.Add(new Job(name, req, o)); | 223 | m_requestQueue.Add(job); |
207 | 224 | ||
208 | if (!m_warnOverMaxQueue) | 225 | if (!m_warnOverMaxQueue) |
209 | m_warnOverMaxQueue = true; | 226 | m_warnOverMaxQueue = true; |
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs index 9c4e4c0..2450cdb 100644 --- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs +++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs | |||
@@ -655,7 +655,22 @@ namespace OpenSim.Region.Framework.Scenes | |||
655 | /// <summary> | 655 | /// <summary> |
656 | /// Is gathering complete? | 656 | /// Is gathering complete? |
657 | /// </summary> | 657 | /// </summary> |
658 | public bool GatheringComplete { get { return m_assetUuidsToInspect.Count <= 0; } } | 658 | public bool Complete { get { return m_assetUuidsToInspect.Count <= 0; } } |
659 | |||
660 | /// <summary> | ||
661 | /// Gets the next UUID to inspect. | ||
662 | /// </summary> | ||
663 | /// <value>If there is no next UUID then returns null</value> | ||
664 | public UUID? NextUuidToInspect | ||
665 | { | ||
666 | get | ||
667 | { | ||
668 | if (Complete) | ||
669 | return null; | ||
670 | else | ||
671 | return m_assetUuidsToInspect.Peek(); | ||
672 | } | ||
673 | } | ||
659 | 674 | ||
660 | protected IAssetService m_assetService; | 675 | protected IAssetService m_assetService; |
661 | 676 | ||
@@ -693,7 +708,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
693 | /// <returns>false if gathering is already complete, true otherwise</returns> | 708 | /// <returns>false if gathering is already complete, true otherwise</returns> |
694 | public bool GatherNext() | 709 | public bool GatherNext() |
695 | { | 710 | { |
696 | if (GatheringComplete) | 711 | if (Complete) |
697 | return false; | 712 | return false; |
698 | 713 | ||
699 | GetAssetUuids(m_assetUuidsToInspect.Dequeue()); | 714 | GetAssetUuids(m_assetUuidsToInspect.Dequeue()); |
@@ -707,7 +722,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
707 | /// <returns>false if gathering is already complete, true otherwise</returns> | 722 | /// <returns>false if gathering is already complete, true otherwise</returns> |
708 | public bool GatherAll() | 723 | public bool GatherAll() |
709 | { | 724 | { |
710 | if (GatheringComplete) | 725 | if (Complete) |
711 | return false; | 726 | return false; |
712 | 727 | ||
713 | while (GatherNext()); | 728 | while (GatherNext()); |
diff --git a/OpenSim/Services/HypergridService/HGAssetService.cs b/OpenSim/Services/HypergridService/HGAssetService.cs index 5c804d4..b57f8d8 100644 --- a/OpenSim/Services/HypergridService/HGAssetService.cs +++ b/OpenSim/Services/HypergridService/HGAssetService.cs | |||
@@ -100,7 +100,7 @@ namespace OpenSim.Services.HypergridService | |||
100 | return null; | 100 | return null; |
101 | 101 | ||
102 | if (asset.Metadata.Type == (sbyte)AssetType.Object) | 102 | if (asset.Metadata.Type == (sbyte)AssetType.Object) |
103 | asset.Data = AdjustIdentifiers(asset.Data); ; | 103 | asset.Data = AdjustIdentifiers(asset.Data); |
104 | 104 | ||
105 | AdjustIdentifiers(asset.Metadata); | 105 | AdjustIdentifiers(asset.Metadata); |
106 | 106 | ||