diff options
author | Melanie Thielker | 2014-06-21 00:39:55 +0200 |
---|---|---|
committer | Melanie Thielker | 2014-06-21 00:39:55 +0200 |
commit | 159fcbf150b7da0e229b29aa7b94793484543d12 (patch) | |
tree | b8c0ff3b4c758a3fba8315b556c923ef4c02a185 /OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | |
parent | Merge commit '68c8633ba18f0a11cfc0ed04d1d0c7c59e6cec76' (diff) | |
parent | Merge branch 'master' into careminster (diff) | |
download | opensim-SC_OLD-159fcbf150b7da0e229b29aa7b94793484543d12.zip opensim-SC_OLD-159fcbf150b7da0e229b29aa7b94793484543d12.tar.gz opensim-SC_OLD-159fcbf150b7da0e229b29aa7b94793484543d12.tar.bz2 opensim-SC_OLD-159fcbf150b7da0e229b29aa7b94793484543d12.tar.xz |
Merge branch 'master' of ssh://3dhosting.de/var/git/careminster
Conflicts:
OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
Diffstat (limited to 'OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs')
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | 129 |
1 files changed, 109 insertions, 20 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 6495f3f..d47ca4b 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | |||
@@ -29,6 +29,7 @@ using System; | |||
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Reflection; | 30 | using System.Reflection; |
31 | using System.IO; | 31 | using System.IO; |
32 | using System.Threading; | ||
32 | using System.Xml; | 33 | using System.Xml; |
33 | using log4net; | 34 | using log4net; |
34 | using Mono.Addins; | 35 | using Mono.Addins; |
@@ -51,6 +52,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
51 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 52 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
52 | 53 | ||
53 | public int DebugLevel { get; set; } | 54 | public int DebugLevel { get; set; } |
55 | |||
56 | /// <summary> | ||
57 | /// Period to sleep per 100 prims in order to avoid CPU spikes when an avatar with many attachments logs in/changes | ||
58 | /// outfit or many avatars with a medium levels of attachments login/change outfit simultaneously. | ||
59 | /// </summary> | ||
60 | /// <remarks> | ||
61 | /// A value of 0 will apply no pause. The pause is specified in milliseconds. | ||
62 | /// </remarks> | ||
63 | public int ThrottlePer100PrimsRezzed { get; set; } | ||
54 | 64 | ||
55 | private Scene m_scene; | 65 | private Scene m_scene; |
56 | private IInventoryAccessModule m_invAccessModule; | 66 | private IInventoryAccessModule m_invAccessModule; |
@@ -67,18 +77,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
67 | { | 77 | { |
68 | IConfig config = source.Configs["Attachments"]; | 78 | IConfig config = source.Configs["Attachments"]; |
69 | if (config != null) | 79 | if (config != null) |
80 | { | ||
70 | Enabled = config.GetBoolean("Enabled", true); | 81 | Enabled = config.GetBoolean("Enabled", true); |
82 | |||
83 | ThrottlePer100PrimsRezzed = config.GetInt("ThrottlePer100PrimsRezzed", 0); | ||
84 | } | ||
71 | else | 85 | else |
86 | { | ||
72 | Enabled = true; | 87 | Enabled = true; |
88 | } | ||
73 | } | 89 | } |
74 | 90 | ||
75 | public void AddRegion(Scene scene) | 91 | public void AddRegion(Scene scene) |
76 | { | 92 | { |
77 | m_scene = scene; | 93 | m_scene = scene; |
78 | m_scene.RegisterModuleInterface<IAttachmentsModule>(this); | ||
79 | |||
80 | if (Enabled) | 94 | if (Enabled) |
81 | { | 95 | { |
96 | // Only register module with scene if it is enabled. All callers check for a null attachments module. | ||
97 | // Ideally, there should be a null attachments module for when this core attachments module has been | ||
98 | // disabled. Registering only when enabled allows for other attachments module implementations. | ||
99 | m_scene.RegisterModuleInterface<IAttachmentsModule>(this); | ||
82 | m_scene.EventManager.OnNewClient += SubscribeToClientEvents; | 100 | m_scene.EventManager.OnNewClient += SubscribeToClientEvents; |
83 | m_scene.EventManager.OnStartScript += (localID, itemID) => HandleScriptStateChange(localID, true); | 101 | m_scene.EventManager.OnStartScript += (localID, itemID) => HandleScriptStateChange(localID, true); |
84 | m_scene.EventManager.OnStopScript += (localID, itemID) => HandleScriptStateChange(localID, false); | 102 | m_scene.EventManager.OnStopScript += (localID, itemID) => HandleScriptStateChange(localID, false); |
@@ -86,24 +104,43 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
86 | MainConsole.Instance.Commands.AddCommand( | 104 | MainConsole.Instance.Commands.AddCommand( |
87 | "Debug", | 105 | "Debug", |
88 | false, | 106 | false, |
89 | "debug attachments", | 107 | "debug attachments log", |
90 | "debug attachments [0|1]", | 108 | "debug attachments log [0|1]", |
91 | "Turn on attachments debugging\n" | 109 | "Turn on attachments debug logging", |
92 | + " <= 0 - turns off debugging\n" | 110 | " <= 0 - turns off debug logging\n" |
93 | + " >= 1 - turns on attachment message logging\n", | 111 | + " >= 1 - turns on attachment message debug logging", |
94 | HandleDebugAttachments); | 112 | HandleDebugAttachmentsLog); |
113 | |||
114 | MainConsole.Instance.Commands.AddCommand( | ||
115 | "Debug", | ||
116 | false, | ||
117 | "debug attachments throttle", | ||
118 | "debug attachments throttle <ms>", | ||
119 | "Turn on attachments throttling.", | ||
120 | "This requires a millisecond value. " + | ||
121 | " == 0 - disable throttling.\n" | ||
122 | + " > 0 - sleeps for this number of milliseconds per 100 prims rezzed.", | ||
123 | HandleDebugAttachmentsThrottle); | ||
124 | |||
125 | MainConsole.Instance.Commands.AddCommand( | ||
126 | "Debug", | ||
127 | false, | ||
128 | "debug attachments status", | ||
129 | "debug attachments status", | ||
130 | "Show current attachments debug status", | ||
131 | HandleDebugAttachmentsStatus); | ||
95 | } | 132 | } |
96 | 133 | ||
97 | // TODO: Should probably be subscribing to CloseClient too, but this doesn't yet give us IClientAPI | 134 | // TODO: Should probably be subscribing to CloseClient too, but this doesn't yet give us IClientAPI |
98 | } | 135 | } |
99 | 136 | ||
100 | private void HandleDebugAttachments(string module, string[] args) | 137 | private void HandleDebugAttachmentsLog(string module, string[] args) |
101 | { | 138 | { |
102 | int debugLevel; | 139 | int debugLevel; |
103 | 140 | ||
104 | if (!(args.Length == 3 && int.TryParse(args[2], out debugLevel))) | 141 | if (!(args.Length == 4 && int.TryParse(args[3], out debugLevel))) |
105 | { | 142 | { |
106 | MainConsole.Instance.OutputFormat("Usage: debug attachments [0|1]"); | 143 | MainConsole.Instance.OutputFormat("Usage: debug attachments log [0|1]"); |
107 | } | 144 | } |
108 | else | 145 | else |
109 | { | 146 | { |
@@ -113,6 +150,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
113 | } | 150 | } |
114 | } | 151 | } |
115 | 152 | ||
153 | private void HandleDebugAttachmentsThrottle(string module, string[] args) | ||
154 | { | ||
155 | int ms; | ||
156 | |||
157 | if (args.Length == 4 && int.TryParse(args[3], out ms)) | ||
158 | { | ||
159 | ThrottlePer100PrimsRezzed = ms; | ||
160 | MainConsole.Instance.OutputFormat( | ||
161 | "Attachments rez throttle per 100 prims is now {0} in {1}", ThrottlePer100PrimsRezzed, m_scene.Name); | ||
162 | |||
163 | return; | ||
164 | } | ||
165 | |||
166 | MainConsole.Instance.OutputFormat("Usage: debug attachments throttle <ms>"); | ||
167 | } | ||
168 | |||
169 | private void HandleDebugAttachmentsStatus(string module, string[] args) | ||
170 | { | ||
171 | MainConsole.Instance.OutputFormat("Settings for {0}", m_scene.Name); | ||
172 | MainConsole.Instance.OutputFormat("Debug logging level: {0}", DebugLevel); | ||
173 | MainConsole.Instance.OutputFormat("Throttle per 100 prims: {0}ms", ThrottlePer100PrimsRezzed); | ||
174 | } | ||
175 | |||
116 | /// <summary> | 176 | /// <summary> |
117 | /// Listen for client triggered running state changes so that we can persist the script's object if necessary. | 177 | /// Listen for client triggered running state changes so that we can persist the script's object if necessary. |
118 | /// </summary> | 178 | /// </summary> |
@@ -273,7 +333,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
273 | List<AvatarAttachment> attachments = sp.Appearance.GetAttachments(); | 333 | List<AvatarAttachment> attachments = sp.Appearance.GetAttachments(); |
274 | foreach (AvatarAttachment attach in attachments) | 334 | foreach (AvatarAttachment attach in attachments) |
275 | { | 335 | { |
276 | uint p = (uint)attach.AttachPoint; | 336 | uint attachmentPt = (uint)attach.AttachPoint; |
277 | 337 | ||
278 | // m_log.DebugFormat( | 338 | // m_log.DebugFormat( |
279 | // "[ATTACHMENTS MODULE]: Doing initial rez of attachment with itemID {0}, assetID {1}, point {2} for {3} in {4}", | 339 | // "[ATTACHMENTS MODULE]: Doing initial rez of attachment with itemID {0}, assetID {1}, point {2} for {3} in {4}", |
@@ -302,13 +362,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
302 | // If we're an NPC then skip all the item checks and manipulations since we don't have an | 362 | // If we're an NPC then skip all the item checks and manipulations since we don't have an |
303 | // inventory right now. | 363 | // inventory right now. |
304 | RezSingleAttachmentFromInventoryInternal( | 364 | RezSingleAttachmentFromInventoryInternal( |
305 | sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, p, true, d); | 365 | sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, attachmentPt, true, d); |
306 | } | 366 | } |
307 | catch (Exception e) | 367 | catch (Exception e) |
308 | { | 368 | { |
309 | UUID agentId = (sp.ControllingClient == null) ? (UUID)null : sp.ControllingClient.AgentId; | 369 | UUID agentId = (sp.ControllingClient == null) ? default(UUID) : sp.ControllingClient.AgentId; |
310 | m_log.ErrorFormat("[ATTACHMENTS MODULE]: Unable to rez attachment with itemID {0}, assetID {1}, point {2} for {3}: {4}\n{5}", | 370 | m_log.ErrorFormat("[ATTACHMENTS MODULE]: Unable to rez attachment with itemID {0}, assetID {1}, point {2} for {3}: {4}\n{5}", |
311 | attach.ItemID, attach.AssetID, p, agentId, e.Message, e.StackTrace); | 371 | attach.ItemID, attach.AssetID, attachmentPt, agentId, e.Message, e.StackTrace); |
312 | } | 372 | } |
313 | } | 373 | } |
314 | } | 374 | } |
@@ -422,13 +482,28 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
422 | attachPos = Vector3.Zero; | 482 | attachPos = Vector3.Zero; |
423 | } | 483 | } |
424 | 484 | ||
425 | // AttachmentPt 0 (default) means the client chose to 'wear' the attachment. | 485 | // if the attachment point is the same as previous, make sure we get the saved |
486 | // position info. | ||
487 | if (attachmentPt != 0 && attachmentPt == group.RootPart.Shape.LastAttachPoint) | ||
488 | { | ||
489 | attachPos = group.RootPart.AttachedPos; | ||
490 | } | ||
491 | |||
492 | // AttachmentPt 0 means the client chose to 'wear' the attachment. | ||
426 | if (attachmentPt == (uint)AttachmentPoint.Default) | 493 | if (attachmentPt == (uint)AttachmentPoint.Default) |
427 | { | 494 | { |
428 | // Check object for stored attachment point | 495 | // Check object for stored attachment point |
429 | attachmentPt = group.AttachmentPoint; | 496 | attachmentPt = group.AttachmentPoint; |
430 | } | 497 | } |
431 | 498 | ||
499 | // if we didn't find an attach point, look for where it was last attached | ||
500 | if (attachmentPt == 0) | ||
501 | { | ||
502 | attachmentPt = (uint)group.RootPart.Shape.LastAttachPoint; | ||
503 | attachPos = group.RootPart.AttachedPos; | ||
504 | group.HasGroupChanged = true; | ||
505 | } | ||
506 | |||
432 | // if we still didn't find a suitable attachment point....... | 507 | // if we still didn't find a suitable attachment point....... |
433 | if (attachmentPt == 0) | 508 | if (attachmentPt == 0) |
434 | { | 509 | { |
@@ -610,6 +685,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
610 | if (changed && m_scene.AvatarFactory != null) | 685 | if (changed && m_scene.AvatarFactory != null) |
611 | m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); | 686 | m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); |
612 | 687 | ||
688 | so.RootPart.Shape.LastAttachPoint = (byte)so.AttachmentPoint; | ||
689 | |||
613 | sp.RemoveAttachment(so); | 690 | sp.RemoveAttachment(so); |
614 | so.FromItemID = UUID.Zero; | 691 | so.FromItemID = UUID.Zero; |
615 | 692 | ||
@@ -841,7 +918,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
841 | m_scene.ForEachClient( | 918 | m_scene.ForEachClient( |
842 | client => | 919 | client => |
843 | { if (client.AgentId != so.AttachedAvatar) | 920 | { if (client.AgentId != so.AttachedAvatar) |
844 | client.SendKillObject(m_scene.RegionInfo.RegionHandle, new List<uint>() { so.LocalId }); | 921 | client.SendKillObject(new List<uint>() { so.LocalId }); |
845 | }); | 922 | }); |
846 | } | 923 | } |
847 | 924 | ||
@@ -982,8 +1059,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
982 | 1059 | ||
983 | if (DebugLevel > 0) | 1060 | if (DebugLevel > 0) |
984 | m_log.DebugFormat( | 1061 | m_log.DebugFormat( |
985 | "[ATTACHMENTS MODULE]: Rezzed single object {0} for attachment to {1} on point {2} in {3}", | 1062 | "[ATTACHMENTS MODULE]: Rezzed single object {0} with {1} prims for attachment to {2} on point {3} in {4}", |
986 | objatt.Name, sp.Name, attachmentPt, m_scene.Name); | 1063 | objatt.Name, objatt.PrimCount, sp.Name, attachmentPt, m_scene.Name); |
987 | 1064 | ||
988 | // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. | 1065 | // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. |
989 | objatt.HasGroupChanged = false; | 1066 | objatt.HasGroupChanged = false; |
@@ -1020,7 +1097,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
1020 | } | 1097 | } |
1021 | 1098 | ||
1022 | if (tainted) | 1099 | if (tainted) |
1023 | objatt.HasGroupChanged = true; | 1100 | objatt.HasGroupChanged = true; |
1101 | |||
1102 | if (ThrottlePer100PrimsRezzed > 0) | ||
1103 | { | ||
1104 | int throttleMs = (int)Math.Round((float)objatt.PrimCount / 100 * ThrottlePer100PrimsRezzed); | ||
1105 | |||
1106 | if (DebugLevel > 0) | ||
1107 | m_log.DebugFormat( | ||
1108 | "[ATTACHMENTS MODULE]: Throttling by {0}ms after rez of {1} with {2} prims for attachment to {3} on point {4} in {5}", | ||
1109 | throttleMs, objatt.Name, objatt.PrimCount, sp.Name, attachmentPt, m_scene.Name); | ||
1110 | |||
1111 | Thread.Sleep(throttleMs); | ||
1112 | } | ||
1024 | 1113 | ||
1025 | return objatt; | 1114 | return objatt; |
1026 | } | 1115 | } |