aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs102
-rw-r--r--bin/OpenSimDefaults.ini7
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;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using System.IO; 31using System.IO;
32using System.Threading;
32using System.Xml; 33using System.Xml;
33using log4net; 34using log4net;
34using Mono.Addins; 35using 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