diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Framework/Location.cs | 16 | ||||
-rw-r--r-- | OpenSim/Framework/Tests/LocationTest.cs | 14 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | 5 | ||||
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | 102 | ||||
-rw-r--r-- | bin/OpenSimDefaults.ini | 7 |
5 files changed, 112 insertions, 32 deletions
diff --git a/OpenSim/Framework/Location.cs b/OpenSim/Framework/Location.cs index 9504e03..0b88834 100644 --- a/OpenSim/Framework/Location.cs +++ b/OpenSim/Framework/Location.cs | |||
@@ -33,10 +33,10 @@ namespace OpenSim.Framework | |||
33 | [Serializable] | 33 | [Serializable] |
34 | public class Location : ICloneable | 34 | public class Location : ICloneable |
35 | { | 35 | { |
36 | private readonly int m_x; | 36 | private readonly uint m_x; |
37 | private readonly int m_y; | 37 | private readonly uint m_y; |
38 | 38 | ||
39 | public Location(int x, int y) | 39 | public Location(uint x, uint y) |
40 | { | 40 | { |
41 | m_x = x; | 41 | m_x = x; |
42 | m_y = y; | 42 | m_y = y; |
@@ -44,21 +44,21 @@ namespace OpenSim.Framework | |||
44 | 44 | ||
45 | public Location(ulong regionHandle) | 45 | public Location(ulong regionHandle) |
46 | { | 46 | { |
47 | m_x = (int) regionHandle; | 47 | m_x = (uint)(regionHandle >> 32); |
48 | m_y = (int) (regionHandle >> 32); | 48 | m_y = (uint)(regionHandle & (ulong)uint.MaxValue); |
49 | } | 49 | } |
50 | 50 | ||
51 | public ulong RegionHandle | 51 | public ulong RegionHandle |
52 | { | 52 | { |
53 | get { return Utils.UIntsToLong((uint)m_x, (uint)m_y); } | 53 | get { return Utils.UIntsToLong(m_x, m_y); } |
54 | } | 54 | } |
55 | 55 | ||
56 | public int X | 56 | public uint X |
57 | { | 57 | { |
58 | get { return m_x; } | 58 | get { return m_x; } |
59 | } | 59 | } |
60 | 60 | ||
61 | public int Y | 61 | public uint Y |
62 | { | 62 | { |
63 | get { return m_y; } | 63 | get { return m_y; } |
64 | } | 64 | } |
diff --git a/OpenSim/Framework/Tests/LocationTest.cs b/OpenSim/Framework/Tests/LocationTest.cs index a56ecb4..af5f164 100644 --- a/OpenSim/Framework/Tests/LocationTest.cs +++ b/OpenSim/Framework/Tests/LocationTest.cs | |||
@@ -51,21 +51,21 @@ namespace OpenSim.Framework.Tests | |||
51 | [Test] | 51 | [Test] |
52 | public void locationXYRegionHandle() | 52 | public void locationXYRegionHandle() |
53 | { | 53 | { |
54 | Location TestLocation1 = new Location(256000,256000); | 54 | Location TestLocation1 = new Location(255000,256000); |
55 | Location TestLocation2 = new Location(1099511628032000); | 55 | Location TestLocation2 = new Location(1095216660736000); |
56 | Assert.That(TestLocation1 == TestLocation2); | 56 | Assert.That(TestLocation1 == TestLocation2); |
57 | 57 | ||
58 | Assert.That(TestLocation2.X == 256000 && TestLocation2.Y == 256000, "Test xy location doesn't match regionhandle provided"); | 58 | Assert.That(TestLocation2.X == 255000 && TestLocation2.Y == 256000, "Test xy location doesn't match regionhandle provided"); |
59 | 59 | ||
60 | Assert.That(TestLocation2.RegionHandle == 1099511628032000, | 60 | Assert.That(TestLocation2.RegionHandle == 1095216660736000, |
61 | "Location RegionHandle Property didn't match regionhandle provided in constructor"); | 61 | "Location RegionHandle Property didn't match regionhandle provided in constructor"); |
62 | 62 | ||
63 | 63 | ||
64 | TestLocation1 = new Location(256001, 256001); | 64 | TestLocation1 = new Location(255001, 256001); |
65 | TestLocation2 = new Location(1099511628032000); | 65 | TestLocation2 = new Location(1095216660736000); |
66 | Assert.That(TestLocation1 != TestLocation2); | 66 | Assert.That(TestLocation1 != TestLocation2); |
67 | 67 | ||
68 | Assert.That(TestLocation1.Equals(256001, 256001), "Equals(x,y) failed to match the position in the constructor"); | 68 | Assert.That(TestLocation1.Equals(255001, 256001), "Equals(x,y) failed to match the position in the constructor"); |
69 | 69 | ||
70 | Assert.That(TestLocation2.GetHashCode() == (TestLocation2.X.GetHashCode() ^ TestLocation2.Y.GetHashCode()), "GetHashCode failed to produce the expected hashcode"); | 70 | Assert.That(TestLocation2.GetHashCode() == (TestLocation2.X.GetHashCode() ^ TestLocation2.Y.GetHashCode()), "GetHashCode failed to produce the expected hashcode"); |
71 | 71 | ||
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 2a2c819..71b464b 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | |||
@@ -698,7 +698,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
698 | { | 698 | { |
699 | DefaultClientPacketDebugLevel = newDebug; | 699 | DefaultClientPacketDebugLevel = newDebug; |
700 | MainConsole.Instance.OutputFormat( | 700 | MainConsole.Instance.OutputFormat( |
701 | "Debug packet debug for new clients set to {0}", DefaultClientPacketDebugLevel); | 701 | "Debug packet debug for new clients set to {0} in {1}", DefaultClientPacketDebugLevel, m_scene.Name); |
702 | } | 702 | } |
703 | else | 703 | else |
704 | { | 704 | { |
@@ -1998,7 +1998,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1998 | // | 1998 | // |
1999 | // Instead, now wait for data present to be explicitly signalled. Evidence so far is that with | 1999 | // Instead, now wait for data present to be explicitly signalled. Evidence so far is that with |
2000 | // modern mono it reduces CPU base load since there is no more continuous polling. | 2000 | // modern mono it reduces CPU base load since there is no more continuous polling. |
2001 | m_dataPresentEvent.WaitOne(100); | 2001 | if (!m_packetSent) |
2002 | m_dataPresentEvent.WaitOne(100); | ||
2002 | 2003 | ||
2003 | Watchdog.UpdateThread(); | 2004 | Watchdog.UpdateThread(); |
2004 | } | 2005 | } |
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; |
diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index c9a79fc..286076da 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 |