diff options
Merge branch 'master' into careminster
Conflicts:
OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
Diffstat (limited to 'OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs')
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | 102 |
1 files changed, 87 insertions, 15 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 505bb53..7b12c81 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 | ||
58 | /// or many avatars with a medium levels of attachments login 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,9 +77,15 @@ 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) |
@@ -88,24 +104,43 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
88 | MainConsole.Instance.Commands.AddCommand( | 104 | MainConsole.Instance.Commands.AddCommand( |
89 | "Debug", | 105 | "Debug", |
90 | false, | 106 | false, |
91 | "debug attachments", | 107 | "debug attachments log", |
92 | "debug attachments [0|1]", | 108 | "debug attachments log [0|1]", |
93 | "Turn on attachments debugging\n" | 109 | "Turn on attachments debug logging", |
94 | + " <= 0 - turns off debugging\n" | 110 | " <= 0 - turns off debug logging\n" |
95 | + " >= 1 - turns on attachment message logging\n", | 111 | + " >= 1 - turns on attachment message debug logging", |
96 | 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); | ||
97 | } | 132 | } |
98 | 133 | ||
99 | // 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 |
100 | } | 135 | } |
101 | 136 | ||
102 | private void HandleDebugAttachments(string module, string[] args) | 137 | private void HandleDebugAttachmentsLog(string module, string[] args) |
103 | { | 138 | { |
104 | int debugLevel; | 139 | int debugLevel; |
105 | 140 | ||
106 | if (!(args.Length == 3 && int.TryParse(args[2], out debugLevel))) | 141 | if (!(args.Length == 4 && int.TryParse(args[3], out debugLevel))) |
107 | { | 142 | { |
108 | MainConsole.Instance.OutputFormat("Usage: debug attachments [0|1]"); | 143 | MainConsole.Instance.OutputFormat("Usage: debug attachments log [0|1]"); |
109 | } | 144 | } |
110 | else | 145 | else |
111 | { | 146 | { |
@@ -115,6 +150,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
115 | } | 150 | } |
116 | } | 151 | } |
117 | 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 | |||
118 | /// <summary> | 176 | /// <summary> |
119 | /// 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. |
120 | /// </summary> | 178 | /// </summary> |
@@ -275,7 +333,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
275 | List<AvatarAttachment> attachments = sp.Appearance.GetAttachments(); | 333 | List<AvatarAttachment> attachments = sp.Appearance.GetAttachments(); |
276 | foreach (AvatarAttachment attach in attachments) | 334 | foreach (AvatarAttachment attach in attachments) |
277 | { | 335 | { |
278 | uint p = (uint)attach.AttachPoint; | 336 | uint attachmentPt = (uint)attach.AttachPoint; |
279 | 337 | ||
280 | // m_log.DebugFormat( | 338 | // m_log.DebugFormat( |
281 | // "[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}", |
@@ -303,14 +361,28 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
303 | 361 | ||
304 | // 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 |
305 | // inventory right now. | 363 | // inventory right now. |
306 | RezSingleAttachmentFromInventoryInternal( | 364 | SceneObjectGroup objatt |
307 | sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, p, true, null); | 365 | = RezSingleAttachmentFromInventoryInternal( |
366 | sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, attachmentPt, true, null); | ||
367 | |||
368 | |||
369 | if (ThrottlePer100PrimsRezzed > 0) | ||
370 | { | ||
371 | int throttleMs = (int)Math.Round((float)objatt.PrimCount / 100 * ThrottlePer100PrimsRezzed); | ||
372 | |||
373 | if (DebugLevel > 0) | ||
374 | m_log.DebugFormat( | ||
375 | "[ATTACHMENTS MODULE]: Throttling by {0}ms after rez of {1} with {2} prims for attachment to {3} on point {4} in {5}", | ||
376 | throttleMs, objatt.Name, objatt.PrimCount, sp.Name, attachmentPt, m_scene.Name); | ||
377 | |||
378 | Thread.Sleep(throttleMs); | ||
379 | } | ||
308 | } | 380 | } |
309 | catch (Exception e) | 381 | catch (Exception e) |
310 | { | 382 | { |
311 | UUID agentId = (sp.ControllingClient == null) ? (UUID)null : sp.ControllingClient.AgentId; | 383 | UUID agentId = (sp.ControllingClient == null) ? (UUID)null : sp.ControllingClient.AgentId; |
312 | m_log.ErrorFormat("[ATTACHMENTS MODULE]: Unable to rez attachment with itemID {0}, assetID {1}, point {2} for {3}: {4}\n{5}", | 384 | m_log.ErrorFormat("[ATTACHMENTS MODULE]: Unable to rez attachment with itemID {0}, assetID {1}, point {2} for {3}: {4}\n{5}", |
313 | attach.ItemID, attach.AssetID, p, agentId, e.Message, e.StackTrace); | 385 | attach.ItemID, attach.AssetID, attachmentPt, agentId, e.Message, e.StackTrace); |
314 | } | 386 | } |
315 | } | 387 | } |
316 | } | 388 | } |
@@ -984,8 +1056,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
984 | 1056 | ||
985 | if (DebugLevel > 0) | 1057 | if (DebugLevel > 0) |
986 | m_log.DebugFormat( | 1058 | m_log.DebugFormat( |
987 | "[ATTACHMENTS MODULE]: Rezzed single object {0} for attachment to {1} on point {2} in {3}", | 1059 | "[ATTACHMENTS MODULE]: Rezzed single object {0} with {1} prims for attachment to {2} on point {3} in {4}", |
988 | objatt.Name, sp.Name, attachmentPt, m_scene.Name); | 1060 | objatt.Name, objatt.PrimCount, sp.Name, attachmentPt, m_scene.Name); |
989 | 1061 | ||
990 | // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. | 1062 | // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. |
991 | objatt.HasGroupChanged = false; | 1063 | objatt.HasGroupChanged = false; |