diff options
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | 102 | ||||
-rw-r--r-- | bin/OpenSimDefaults.ini | 7 |
2 files changed, 94 insertions, 15 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 2f5a76f..97477d4 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; |
@@ -50,6 +51,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
50 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 51 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
51 | 52 | ||
52 | public int DebugLevel { get; set; } | 53 | public int DebugLevel { get; set; } |
54 | |||
55 | /// <summary> | ||
56 | /// Period to sleep per 100 prims in order to avoid CPU spikes when an avatar with many attachments logs in | ||
57 | /// or many avatars with a medium levels of attachments login simultaneously. | ||
58 | /// </summary> | ||
59 | /// <remarks> | ||
60 | /// A value of 0 will apply no pause. The pause is specified in milliseconds. | ||
61 | /// </remarks> | ||
62 | public int ThrottlePer100PrimsRezzed { get; set; } | ||
53 | 63 | ||
54 | private Scene m_scene; | 64 | private Scene m_scene; |
55 | private IInventoryAccessModule m_invAccessModule; | 65 | private IInventoryAccessModule m_invAccessModule; |
@@ -66,9 +76,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
66 | { | 76 | { |
67 | IConfig config = source.Configs["Attachments"]; | 77 | IConfig config = source.Configs["Attachments"]; |
68 | if (config != null) | 78 | if (config != null) |
79 | { | ||
69 | Enabled = config.GetBoolean("Enabled", true); | 80 | Enabled = config.GetBoolean("Enabled", true); |
81 | |||
82 | ThrottlePer100PrimsRezzed = config.GetInt("ThrottlePer100PrimsRezzed", 0); | ||
83 | } | ||
70 | else | 84 | else |
85 | { | ||
71 | Enabled = true; | 86 | Enabled = true; |
87 | } | ||
72 | } | 88 | } |
73 | 89 | ||
74 | public void AddRegion(Scene scene) | 90 | public void AddRegion(Scene scene) |
@@ -87,24 +103,43 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
87 | MainConsole.Instance.Commands.AddCommand( | 103 | MainConsole.Instance.Commands.AddCommand( |
88 | "Debug", | 104 | "Debug", |
89 | false, | 105 | false, |
90 | "debug attachments", | 106 | "debug attachments log", |
91 | "debug attachments [0|1]", | 107 | "debug attachments log [0|1]", |
92 | "Turn on attachments debugging\n" | 108 | "Turn on attachments debug logging", |
93 | + " <= 0 - turns off debugging\n" | 109 | " <= 0 - turns off debug logging\n" |
94 | + " >= 1 - turns on attachment message logging\n", | 110 | + " >= 1 - turns on attachment message debug logging", |
95 | HandleDebugAttachments); | 111 | HandleDebugAttachmentsLog); |
112 | |||
113 | MainConsole.Instance.Commands.AddCommand( | ||
114 | "Debug", | ||
115 | false, | ||
116 | "debug attachments throttle", | ||
117 | "debug attachments throttle <ms>", | ||
118 | "Turn on attachments throttling.", | ||
119 | "This requires a millisecond value. " + | ||
120 | " == 0 - disable throttling.\n" | ||
121 | + " > 0 - sleeps for this number of milliseconds per 100 prims rezzed.", | ||
122 | HandleDebugAttachmentsThrottle); | ||
123 | |||
124 | MainConsole.Instance.Commands.AddCommand( | ||
125 | "Debug", | ||
126 | false, | ||
127 | "debug attachments status", | ||
128 | "debug attachments status", | ||
129 | "Show current attachments debug status", | ||
130 | HandleDebugAttachmentsStatus); | ||
96 | } | 131 | } |
97 | 132 | ||
98 | // TODO: Should probably be subscribing to CloseClient too, but this doesn't yet give us IClientAPI | 133 | // TODO: Should probably be subscribing to CloseClient too, but this doesn't yet give us IClientAPI |
99 | } | 134 | } |
100 | 135 | ||
101 | private void HandleDebugAttachments(string module, string[] args) | 136 | private void HandleDebugAttachmentsLog(string module, string[] args) |
102 | { | 137 | { |
103 | int debugLevel; | 138 | int debugLevel; |
104 | 139 | ||
105 | if (!(args.Length == 3 && int.TryParse(args[2], out debugLevel))) | 140 | if (!(args.Length == 4 && int.TryParse(args[3], out debugLevel))) |
106 | { | 141 | { |
107 | MainConsole.Instance.OutputFormat("Usage: debug attachments [0|1]"); | 142 | MainConsole.Instance.OutputFormat("Usage: debug attachments log [0|1]"); |
108 | } | 143 | } |
109 | else | 144 | else |
110 | { | 145 | { |
@@ -114,6 +149,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
114 | } | 149 | } |
115 | } | 150 | } |
116 | 151 | ||
152 | private void HandleDebugAttachmentsThrottle(string module, string[] args) | ||
153 | { | ||
154 | int ms; | ||
155 | |||
156 | if (args.Length == 4 && int.TryParse(args[3], out ms)) | ||
157 | { | ||
158 | ThrottlePer100PrimsRezzed = ms; | ||
159 | MainConsole.Instance.OutputFormat( | ||
160 | "Attachments rez throttle per 100 prims is now {0} in {1}", ThrottlePer100PrimsRezzed, m_scene.Name); | ||
161 | |||
162 | return; | ||
163 | } | ||
164 | |||
165 | MainConsole.Instance.OutputFormat("Usage: debug attachments throttle <ms>"); | ||
166 | } | ||
167 | |||
168 | private void HandleDebugAttachmentsStatus(string module, string[] args) | ||
169 | { | ||
170 | MainConsole.Instance.OutputFormat("Settings for {0}", m_scene.Name); | ||
171 | MainConsole.Instance.OutputFormat("Debug logging level: {0}", DebugLevel); | ||
172 | MainConsole.Instance.OutputFormat("Throttle per 100 prims: {0}ms", ThrottlePer100PrimsRezzed); | ||
173 | } | ||
174 | |||
117 | /// <summary> | 175 | /// <summary> |
118 | /// Listen for client triggered running state changes so that we can persist the script's object if necessary. | 176 | /// Listen for client triggered running state changes so that we can persist the script's object if necessary. |
119 | /// </summary> | 177 | /// </summary> |
@@ -240,7 +298,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
240 | List<AvatarAttachment> attachments = sp.Appearance.GetAttachments(); | 298 | List<AvatarAttachment> attachments = sp.Appearance.GetAttachments(); |
241 | foreach (AvatarAttachment attach in attachments) | 299 | foreach (AvatarAttachment attach in attachments) |
242 | { | 300 | { |
243 | uint p = (uint)attach.AttachPoint; | 301 | uint attachmentPt = (uint)attach.AttachPoint; |
244 | 302 | ||
245 | // m_log.DebugFormat( | 303 | // m_log.DebugFormat( |
246 | // "[ATTACHMENTS MODULE]: Doing initial rez of attachment with itemID {0}, assetID {1}, point {2} for {3} in {4}", | 304 | // "[ATTACHMENTS MODULE]: Doing initial rez of attachment with itemID {0}, assetID {1}, point {2} for {3} in {4}", |
@@ -258,14 +316,28 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
258 | { | 316 | { |
259 | // If we're an NPC then skip all the item checks and manipulations since we don't have an | 317 | // If we're an NPC then skip all the item checks and manipulations since we don't have an |
260 | // inventory right now. | 318 | // inventory right now. |
261 | RezSingleAttachmentFromInventoryInternal( | 319 | SceneObjectGroup objatt |
262 | sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, p, true); | 320 | = RezSingleAttachmentFromInventoryInternal( |
321 | sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, attachmentPt, true); | ||
322 | |||
323 | |||
324 | if (ThrottlePer100PrimsRezzed > 0) | ||
325 | { | ||
326 | int throttleMs = (int)Math.Round((float)objatt.PrimCount / 100 * ThrottlePer100PrimsRezzed); | ||
327 | |||
328 | if (DebugLevel > 0) | ||
329 | m_log.DebugFormat( | ||
330 | "[ATTACHMENTS MODULE]: Throttling by {0}ms after rez of {1} with {2} prims for attachment to {3} on point {4} in {5}", | ||
331 | throttleMs, objatt.Name, objatt.PrimCount, sp.Name, attachmentPt, m_scene.Name); | ||
332 | |||
333 | Thread.Sleep(throttleMs); | ||
334 | } | ||
263 | } | 335 | } |
264 | catch (Exception e) | 336 | catch (Exception e) |
265 | { | 337 | { |
266 | UUID agentId = (sp.ControllingClient == null) ? (UUID)null : sp.ControllingClient.AgentId; | 338 | UUID agentId = (sp.ControllingClient == null) ? (UUID)null : sp.ControllingClient.AgentId; |
267 | m_log.ErrorFormat("[ATTACHMENTS MODULE]: Unable to rez attachment with itemID {0}, assetID {1}, point {2} for {3}: {4}\n{5}", | 339 | m_log.ErrorFormat("[ATTACHMENTS MODULE]: Unable to rez attachment with itemID {0}, assetID {1}, point {2} for {3}: {4}\n{5}", |
268 | attach.ItemID, attach.AssetID, p, agentId, e.Message, e.StackTrace); | 340 | attach.ItemID, attach.AssetID, attachmentPt, agentId, e.Message, e.StackTrace); |
269 | } | 341 | } |
270 | } | 342 | } |
271 | } | 343 | } |
@@ -919,8 +991,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
919 | 991 | ||
920 | if (DebugLevel > 0) | 992 | if (DebugLevel > 0) |
921 | m_log.DebugFormat( | 993 | m_log.DebugFormat( |
922 | "[ATTACHMENTS MODULE]: Rezzed single object {0} for attachment to {1} on point {2} in {3}", | 994 | "[ATTACHMENTS MODULE]: Rezzed single object {0} with {1} prims for attachment to {2} on point {3} in {4}", |
923 | objatt.Name, sp.Name, attachmentPt, m_scene.Name); | 995 | objatt.Name, objatt.PrimCount, sp.Name, attachmentPt, m_scene.Name); |
924 | 996 | ||
925 | // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. | 997 | // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. |
926 | objatt.HasGroupChanged = false; | 998 | objatt.HasGroupChanged = false; |
diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index dbafd5c..2488bf1 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini | |||
@@ -703,11 +703,18 @@ | |||
703 | ; on every login | 703 | ; on every login |
704 | ReuseTextures = false | 704 | ReuseTextures = false |
705 | 705 | ||
706 | |||
706 | [Attachments] | 707 | [Attachments] |
707 | ; Controls whether avatar attachments are enabled. | 708 | ; Controls whether avatar attachments are enabled. |
708 | ; Defaults to true - only set to false for debugging purposes | 709 | ; Defaults to true - only set to false for debugging purposes |
709 | Enabled = true | 710 | Enabled = true |
710 | 711 | ||
712 | ; Controls the number of milliseconds that are slept per 100 prims rezzed in attachments | ||
713 | ; Experimental setting to control CPU spiking when avatars with many attachments login | ||
714 | ; or when multiple avatars with medium level attachments login simultaneously. | ||
715 | ; If 0 then no throttling is performed. | ||
716 | ThrottlePer100PrimsRezzed = 0; | ||
717 | |||
711 | 718 | ||
712 | [Mesh] | 719 | [Mesh] |
713 | ; enable / disable Collada mesh support | 720 | ; enable / disable Collada mesh support |