Merge branch 'master' into careminster

Conflicts:
	OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
avinationmerge
Melanie 2013-08-01 23:42:19 +01:00
commit 6fc03c7e6e
5 changed files with 112 additions and 32 deletions

View File

@ -33,10 +33,10 @@ namespace OpenSim.Framework
[Serializable] [Serializable]
public class Location : ICloneable public class Location : ICloneable
{ {
private readonly int m_x; private readonly uint m_x;
private readonly int m_y; private readonly uint m_y;
public Location(int x, int y) public Location(uint x, uint y)
{ {
m_x = x; m_x = x;
m_y = y; m_y = y;
@ -44,21 +44,21 @@ namespace OpenSim.Framework
public Location(ulong regionHandle) public Location(ulong regionHandle)
{ {
m_x = (int) regionHandle; m_x = (uint)(regionHandle >> 32);
m_y = (int) (regionHandle >> 32); m_y = (uint)(regionHandle & (ulong)uint.MaxValue);
} }
public ulong RegionHandle public ulong RegionHandle
{ {
get { return Utils.UIntsToLong((uint)m_x, (uint)m_y); } get { return Utils.UIntsToLong(m_x, m_y); }
} }
public int X public uint X
{ {
get { return m_x; } get { return m_x; }
} }
public int Y public uint Y
{ {
get { return m_y; } get { return m_y; }
} }

View File

@ -51,21 +51,21 @@ namespace OpenSim.Framework.Tests
[Test] [Test]
public void locationXYRegionHandle() public void locationXYRegionHandle()
{ {
Location TestLocation1 = new Location(256000,256000); Location TestLocation1 = new Location(255000,256000);
Location TestLocation2 = new Location(1099511628032000); Location TestLocation2 = new Location(1095216660736000);
Assert.That(TestLocation1 == TestLocation2); Assert.That(TestLocation1 == TestLocation2);
Assert.That(TestLocation2.X == 256000 && TestLocation2.Y == 256000, "Test xy location doesn't match regionhandle provided"); Assert.That(TestLocation2.X == 255000 && TestLocation2.Y == 256000, "Test xy location doesn't match regionhandle provided");
Assert.That(TestLocation2.RegionHandle == 1099511628032000, Assert.That(TestLocation2.RegionHandle == 1095216660736000,
"Location RegionHandle Property didn't match regionhandle provided in constructor"); "Location RegionHandle Property didn't match regionhandle provided in constructor");
TestLocation1 = new Location(256001, 256001); TestLocation1 = new Location(255001, 256001);
TestLocation2 = new Location(1099511628032000); TestLocation2 = new Location(1095216660736000);
Assert.That(TestLocation1 != TestLocation2); Assert.That(TestLocation1 != TestLocation2);
Assert.That(TestLocation1.Equals(256001, 256001), "Equals(x,y) failed to match the position in the constructor"); Assert.That(TestLocation1.Equals(255001, 256001), "Equals(x,y) failed to match the position in the constructor");
Assert.That(TestLocation2.GetHashCode() == (TestLocation2.X.GetHashCode() ^ TestLocation2.Y.GetHashCode()), "GetHashCode failed to produce the expected hashcode"); Assert.That(TestLocation2.GetHashCode() == (TestLocation2.X.GetHashCode() ^ TestLocation2.Y.GetHashCode()), "GetHashCode failed to produce the expected hashcode");

View File

@ -698,7 +698,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{ {
DefaultClientPacketDebugLevel = newDebug; DefaultClientPacketDebugLevel = newDebug;
MainConsole.Instance.OutputFormat( MainConsole.Instance.OutputFormat(
"Debug packet debug for new clients set to {0}", DefaultClientPacketDebugLevel); "Debug packet debug for new clients set to {0} in {1}", DefaultClientPacketDebugLevel, m_scene.Name);
} }
else else
{ {
@ -1998,7 +1998,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// //
// Instead, now wait for data present to be explicitly signalled. Evidence so far is that with // Instead, now wait for data present to be explicitly signalled. Evidence so far is that with
// modern mono it reduces CPU base load since there is no more continuous polling. // modern mono it reduces CPU base load since there is no more continuous polling.
m_dataPresentEvent.WaitOne(100); if (!m_packetSent)
m_dataPresentEvent.WaitOne(100);
Watchdog.UpdateThread(); Watchdog.UpdateThread();
} }

View File

@ -29,6 +29,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using System.IO; using System.IO;
using System.Threading;
using System.Xml; using System.Xml;
using log4net; using log4net;
using Mono.Addins; using Mono.Addins;
@ -51,6 +52,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public int DebugLevel { get; set; } public int DebugLevel { get; set; }
/// <summary>
/// Period to sleep per 100 prims in order to avoid CPU spikes when an avatar with many attachments logs in
/// or many avatars with a medium levels of attachments login simultaneously.
/// </summary>
/// <remarks>
/// A value of 0 will apply no pause. The pause is specified in milliseconds.
/// </remarks>
public int ThrottlePer100PrimsRezzed { get; set; }
private Scene m_scene; private Scene m_scene;
private IInventoryAccessModule m_invAccessModule; private IInventoryAccessModule m_invAccessModule;
@ -67,9 +77,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
{ {
IConfig config = source.Configs["Attachments"]; IConfig config = source.Configs["Attachments"];
if (config != null) if (config != null)
{
Enabled = config.GetBoolean("Enabled", true); Enabled = config.GetBoolean("Enabled", true);
ThrottlePer100PrimsRezzed = config.GetInt("ThrottlePer100PrimsRezzed", 0);
}
else else
{
Enabled = true; Enabled = true;
}
} }
public void AddRegion(Scene scene) public void AddRegion(Scene scene)
@ -88,24 +104,43 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
MainConsole.Instance.Commands.AddCommand( MainConsole.Instance.Commands.AddCommand(
"Debug", "Debug",
false, false,
"debug attachments", "debug attachments log",
"debug attachments [0|1]", "debug attachments log [0|1]",
"Turn on attachments debugging\n" "Turn on attachments debug logging",
+ " <= 0 - turns off debugging\n" " <= 0 - turns off debug logging\n"
+ " >= 1 - turns on attachment message logging\n", + " >= 1 - turns on attachment message debug logging",
HandleDebugAttachments); HandleDebugAttachmentsLog);
MainConsole.Instance.Commands.AddCommand(
"Debug",
false,
"debug attachments throttle",
"debug attachments throttle <ms>",
"Turn on attachments throttling.",
"This requires a millisecond value. " +
" == 0 - disable throttling.\n"
+ " > 0 - sleeps for this number of milliseconds per 100 prims rezzed.",
HandleDebugAttachmentsThrottle);
MainConsole.Instance.Commands.AddCommand(
"Debug",
false,
"debug attachments status",
"debug attachments status",
"Show current attachments debug status",
HandleDebugAttachmentsStatus);
} }
// TODO: Should probably be subscribing to CloseClient too, but this doesn't yet give us IClientAPI // TODO: Should probably be subscribing to CloseClient too, but this doesn't yet give us IClientAPI
} }
private void HandleDebugAttachments(string module, string[] args) private void HandleDebugAttachmentsLog(string module, string[] args)
{ {
int debugLevel; int debugLevel;
if (!(args.Length == 3 && int.TryParse(args[2], out debugLevel))) if (!(args.Length == 4 && int.TryParse(args[3], out debugLevel)))
{ {
MainConsole.Instance.OutputFormat("Usage: debug attachments [0|1]"); MainConsole.Instance.OutputFormat("Usage: debug attachments log [0|1]");
} }
else else
{ {
@ -115,6 +150,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
} }
} }
private void HandleDebugAttachmentsThrottle(string module, string[] args)
{
int ms;
if (args.Length == 4 && int.TryParse(args[3], out ms))
{
ThrottlePer100PrimsRezzed = ms;
MainConsole.Instance.OutputFormat(
"Attachments rez throttle per 100 prims is now {0} in {1}", ThrottlePer100PrimsRezzed, m_scene.Name);
return;
}
MainConsole.Instance.OutputFormat("Usage: debug attachments throttle <ms>");
}
private void HandleDebugAttachmentsStatus(string module, string[] args)
{
MainConsole.Instance.OutputFormat("Settings for {0}", m_scene.Name);
MainConsole.Instance.OutputFormat("Debug logging level: {0}", DebugLevel);
MainConsole.Instance.OutputFormat("Throttle per 100 prims: {0}ms", ThrottlePer100PrimsRezzed);
}
/// <summary> /// <summary>
/// Listen for client triggered running state changes so that we can persist the script's object if necessary. /// Listen for client triggered running state changes so that we can persist the script's object if necessary.
/// </summary> /// </summary>
@ -275,7 +333,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
List<AvatarAttachment> attachments = sp.Appearance.GetAttachments(); List<AvatarAttachment> attachments = sp.Appearance.GetAttachments();
foreach (AvatarAttachment attach in attachments) foreach (AvatarAttachment attach in attachments)
{ {
uint p = (uint)attach.AttachPoint; uint attachmentPt = (uint)attach.AttachPoint;
// m_log.DebugFormat( // m_log.DebugFormat(
// "[ATTACHMENTS MODULE]: Doing initial rez of attachment with itemID {0}, assetID {1}, point {2} for {3} in {4}", // "[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
// If we're an NPC then skip all the item checks and manipulations since we don't have an // If we're an NPC then skip all the item checks and manipulations since we don't have an
// inventory right now. // inventory right now.
RezSingleAttachmentFromInventoryInternal( SceneObjectGroup objatt
sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, p, true, null); = RezSingleAttachmentFromInventoryInternal(
sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, attachmentPt, true, null);
if (ThrottlePer100PrimsRezzed > 0)
{
int throttleMs = (int)Math.Round((float)objatt.PrimCount / 100 * ThrottlePer100PrimsRezzed);
if (DebugLevel > 0)
m_log.DebugFormat(
"[ATTACHMENTS MODULE]: Throttling by {0}ms after rez of {1} with {2} prims for attachment to {3} on point {4} in {5}",
throttleMs, objatt.Name, objatt.PrimCount, sp.Name, attachmentPt, m_scene.Name);
Thread.Sleep(throttleMs);
}
} }
catch (Exception e) catch (Exception e)
{ {
UUID agentId = (sp.ControllingClient == null) ? (UUID)null : sp.ControllingClient.AgentId; UUID agentId = (sp.ControllingClient == null) ? (UUID)null : sp.ControllingClient.AgentId;
m_log.ErrorFormat("[ATTACHMENTS MODULE]: Unable to rez attachment with itemID {0}, assetID {1}, point {2} for {3}: {4}\n{5}", m_log.ErrorFormat("[ATTACHMENTS MODULE]: Unable to rez attachment with itemID {0}, assetID {1}, point {2} for {3}: {4}\n{5}",
attach.ItemID, attach.AssetID, p, agentId, e.Message, e.StackTrace); attach.ItemID, attach.AssetID, attachmentPt, agentId, e.Message, e.StackTrace);
} }
} }
} }
@ -984,8 +1056,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
if (DebugLevel > 0) if (DebugLevel > 0)
m_log.DebugFormat( m_log.DebugFormat(
"[ATTACHMENTS MODULE]: Rezzed single object {0} for attachment to {1} on point {2} in {3}", "[ATTACHMENTS MODULE]: Rezzed single object {0} with {1} prims for attachment to {2} on point {3} in {4}",
objatt.Name, sp.Name, attachmentPt, m_scene.Name); objatt.Name, objatt.PrimCount, sp.Name, attachmentPt, m_scene.Name);
// HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller.
objatt.HasGroupChanged = false; objatt.HasGroupChanged = false;

View File

@ -703,11 +703,18 @@
; on every login ; on every login
ReuseTextures = false ReuseTextures = false
[Attachments] [Attachments]
; Controls whether avatar attachments are enabled. ; Controls whether avatar attachments are enabled.
; Defaults to true - only set to false for debugging purposes ; Defaults to true - only set to false for debugging purposes
Enabled = true Enabled = true
; Controls the number of milliseconds that are slept per 100 prims rezzed in attachments
; Experimental setting to control CPU spiking when avatars with many attachments login
; or when multiple avatars with medium level attachments login simultaneously.
; If 0 then no throttling is performed.
ThrottlePer100PrimsRezzed = 0;
[Mesh] [Mesh]
; enable / disable Collada mesh support ; enable / disable Collada mesh support