Merge branch 'master' into careminster

avinationmerge
Melanie 2012-05-31 03:35:24 +01:00
commit e80161753f
8 changed files with 469 additions and 80 deletions

View File

@ -28,6 +28,7 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;

View File

@ -0,0 +1,189 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using log4net;
using Mono.Addins;
using NDesk.Options;
using Nini.Config;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Console;
using OpenSim.Framework.Statistics;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
namespace OpenSim.Region.CoreModules.Avatars.Commands
{
/// <summary>
/// A module that holds commands for manipulating objects in the scene.
/// </summary>
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UserCommandsModule")]
public class UserCommandsModule : ISharedRegionModule
{
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public const string TeleportUserCommandSyntax = "teleport user <first-name> <last-name> <destination>";
public static Regex InterRegionDestinationRegex
= new Regex(@"^(?<regionName>.+)/(?<x>\d+)/(?<y>\d+)/(?<z>\d+)$", RegexOptions.Compiled);
public static Regex WithinRegionDestinationRegex
= new Regex(@"^(?<x>\d+)/(?<y>\d+)/(?<z>\d+)$", RegexOptions.Compiled);
private Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>();
public string Name { get { return "User Commands Module"; } }
public Type ReplaceableInterface { get { return null; } }
public void Initialise(IConfigSource source)
{
// m_log.DebugFormat("[USER COMMANDS MODULE]: INITIALIZED MODULE");
}
public void PostInitialise()
{
// m_log.DebugFormat("[USER COMMANDS MODULE]: POST INITIALIZED MODULE");
}
public void Close()
{
// m_log.DebugFormat("[USER COMMANDS MODULE]: CLOSED MODULE");
}
public void AddRegion(Scene scene)
{
// m_log.DebugFormat("[USER COMMANDS MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName);
lock (m_scenes)
m_scenes[scene.RegionInfo.RegionID] = scene;
scene.AddCommand(
"Users",
this,
"teleport user",
TeleportUserCommandSyntax,
"Teleport a user in this simulator to the given destination",
"<destination> is in format [<region-name>]/<x>/<y>/<z>, e.g. regionone/20/30/40 or just 20/30/40 to teleport within same region."
+ "\nIf the region contains a space then the whole destination must be in quotes, e.g. \"region one/20/30/40\"",
HandleTeleportUser);
}
public void RemoveRegion(Scene scene)
{
// m_log.DebugFormat("[USER COMMANDS MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName);
lock (m_scenes)
m_scenes.Remove(scene.RegionInfo.RegionID);
}
public void RegionLoaded(Scene scene)
{
// m_log.DebugFormat("[USER COMMANDS MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName);
}
private ScenePresence GetUser(string firstName, string lastName)
{
ScenePresence userFound = null;
lock (m_scenes)
{
foreach (Scene scene in m_scenes.Values)
{
ScenePresence user = scene.GetScenePresence(firstName, lastName);
if (user != null && !user.IsChildAgent)
{
userFound = user;
break;
}
}
}
return userFound;
}
private void HandleTeleportUser(string module, string[] cmd)
{
if (cmd.Length < 5)
{
MainConsole.Instance.OutputFormat("Usage: " + TeleportUserCommandSyntax);
return;
}
string firstName = cmd[2];
string lastName = cmd[3];
string rawDestination = cmd[4];
ScenePresence user = GetUser(firstName, lastName);
if (user == null)
{
MainConsole.Instance.OutputFormat("No user found with name {0} {1}", firstName, lastName);
return;
}
// MainConsole.Instance.OutputFormat("rawDestination [{0}]", rawDestination);
Match m = WithinRegionDestinationRegex.Match(rawDestination);
if (!m.Success)
{
m = InterRegionDestinationRegex.Match(rawDestination);
if (!m.Success)
{
MainConsole.Instance.OutputFormat("Invalid destination {0}", rawDestination);
return;
}
}
string regionName
= m.Groups["regionName"].Success ? m.Groups["regionName"].Value : user.Scene.RegionInfo.RegionName;
MainConsole.Instance.OutputFormat(
"Teleporting {0} to {1},{2},{3} in {4}",
user.Name,
m.Groups["x"], m.Groups["y"], m.Groups["z"],
regionName);
user.Scene.RequestTeleportLocation(
user.ControllingClient,
regionName,
new Vector3(
float.Parse(m.Groups["x"].Value),
float.Parse(m.Groups["y"].Value),
float.Parse(m.Groups["z"].Value)),
user.Lookat,
(uint)TeleportFlags.ViaLocation);
}
}
}

View File

@ -49,7 +49,16 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
public bool Enabled { get; private set; } public bool Enabled { get; private set; }
private Scene m_scene; private Scene m_scene;
private readonly List<IMonitor> m_monitors = new List<IMonitor>();
/// <summary>
/// These are monitors where we know the static details in advance.
/// </summary>
/// <remarks>
/// Dynamic monitors also exist (we don't know any of the details of what stats we get back here)
/// but these are currently hardcoded.
/// </remarks>
private readonly List<IMonitor> m_staticMonitors = new List<IMonitor>();
private readonly List<IAlert> m_alerts = new List<IAlert>(); private readonly List<IAlert> m_alerts = new List<IAlert>();
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@ -84,9 +93,18 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
public void DebugMonitors(string module, string[] args) public void DebugMonitors(string module, string[] args)
{ {
foreach (IMonitor monitor in m_monitors) foreach (IMonitor monitor in m_staticMonitors)
{ {
m_log.Info("[MonitorModule]: " + m_scene.RegionInfo.RegionName + " reports " + monitor.GetFriendlyName() + " = " + monitor.GetFriendlyValue()); m_log.InfoFormat(
"[MONITOR MODULE]: {0} reports {1} = {2}",
m_scene.RegionInfo.RegionName, monitor.GetFriendlyName(), monitor.GetFriendlyValue());
}
foreach (KeyValuePair<string, float> tuple in m_scene.StatsReporter.GetExtraSimStats())
{
m_log.InfoFormat(
"[MONITOR MODULE]: {0} reports {1} = {2}",
m_scene.RegionInfo.RegionName, tuple.Key, tuple.Value);
} }
} }
@ -106,11 +124,12 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
{ {
string monID = (string) request["monitor"]; string monID = (string) request["monitor"];
foreach (IMonitor monitor in m_monitors) foreach (IMonitor monitor in m_staticMonitors)
{ {
string elemName = monitor.ToString(); string elemName = monitor.ToString();
if (elemName.StartsWith(monitor.GetType().Namespace)) if (elemName.StartsWith(monitor.GetType().Namespace))
elemName = elemName.Substring(monitor.GetType().Namespace.Length + 1); elemName = elemName.Substring(monitor.GetType().Namespace.Length + 1);
if (elemName == monID || monitor.ToString() == monID) if (elemName == monID || monitor.ToString() == monID)
{ {
Hashtable ereply3 = new Hashtable(); Hashtable ereply3 = new Hashtable();
@ -123,6 +142,9 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
} }
} }
// FIXME: Arguably this should also be done with dynamic monitors but I'm not sure what the above code
// is even doing. Why are we inspecting the type of the monitor???
// No monitor with that name // No monitor with that name
Hashtable ereply2 = new Hashtable(); Hashtable ereply2 = new Hashtable();
@ -134,12 +156,18 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
} }
string xml = "<data>"; string xml = "<data>";
foreach (IMonitor monitor in m_monitors) foreach (IMonitor monitor in m_staticMonitors)
{ {
string elemName = monitor.GetName(); string elemName = monitor.GetName();
xml += "<" + elemName + ">" + monitor.GetValue().ToString() + "</" + elemName + ">"; xml += "<" + elemName + ">" + monitor.GetValue().ToString() + "</" + elemName + ">";
// m_log.DebugFormat("[MONITOR MODULE]: {0} = {1}", elemName, monitor.GetValue()); // m_log.DebugFormat("[MONITOR MODULE]: {0} = {1}", elemName, monitor.GetValue());
} }
foreach (KeyValuePair<string, float> tuple in m_scene.StatsReporter.GetExtraSimStats())
{
xml += "<" + tuple.Key + ">" + tuple.Value + "</" + tuple.Key + ">";
}
xml += "</data>"; xml += "</data>";
Hashtable ereply = new Hashtable(); Hashtable ereply = new Hashtable();
@ -156,20 +184,20 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
if (!Enabled) if (!Enabled)
return; return;
m_monitors.Add(new AgentCountMonitor(m_scene)); m_staticMonitors.Add(new AgentCountMonitor(m_scene));
m_monitors.Add(new ChildAgentCountMonitor(m_scene)); m_staticMonitors.Add(new ChildAgentCountMonitor(m_scene));
m_monitors.Add(new GCMemoryMonitor()); m_staticMonitors.Add(new GCMemoryMonitor());
m_monitors.Add(new ObjectCountMonitor(m_scene)); m_staticMonitors.Add(new ObjectCountMonitor(m_scene));
m_monitors.Add(new PhysicsFrameMonitor(m_scene)); m_staticMonitors.Add(new PhysicsFrameMonitor(m_scene));
m_monitors.Add(new PhysicsUpdateFrameMonitor(m_scene)); m_staticMonitors.Add(new PhysicsUpdateFrameMonitor(m_scene));
m_monitors.Add(new PWSMemoryMonitor()); m_staticMonitors.Add(new PWSMemoryMonitor());
m_monitors.Add(new ThreadCountMonitor()); m_staticMonitors.Add(new ThreadCountMonitor());
m_monitors.Add(new TotalFrameMonitor(m_scene)); m_staticMonitors.Add(new TotalFrameMonitor(m_scene));
m_monitors.Add(new EventFrameMonitor(m_scene)); m_staticMonitors.Add(new EventFrameMonitor(m_scene));
m_monitors.Add(new LandFrameMonitor(m_scene)); m_staticMonitors.Add(new LandFrameMonitor(m_scene));
m_monitors.Add(new LastFrameTimeMonitor(m_scene)); m_staticMonitors.Add(new LastFrameTimeMonitor(m_scene));
m_monitors.Add( m_staticMonitors.Add(
new GenericMonitor( new GenericMonitor(
m_scene, m_scene,
"TimeDilationMonitor", "TimeDilationMonitor",
@ -177,7 +205,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[0], m => m.Scene.StatsReporter.LastReportedSimStats[0],
m => m.GetValue().ToString())); m => m.GetValue().ToString()));
m_monitors.Add( m_staticMonitors.Add(
new GenericMonitor( new GenericMonitor(
m_scene, m_scene,
"SimFPSMonitor", "SimFPSMonitor",
@ -185,7 +213,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[1], m => m.Scene.StatsReporter.LastReportedSimStats[1],
m => string.Format("{0}", m.GetValue()))); m => string.Format("{0}", m.GetValue())));
m_monitors.Add( m_staticMonitors.Add(
new GenericMonitor( new GenericMonitor(
m_scene, m_scene,
"PhysicsFPSMonitor", "PhysicsFPSMonitor",
@ -193,7 +221,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[2], m => m.Scene.StatsReporter.LastReportedSimStats[2],
m => string.Format("{0}", m.GetValue()))); m => string.Format("{0}", m.GetValue())));
m_monitors.Add( m_staticMonitors.Add(
new GenericMonitor( new GenericMonitor(
m_scene, m_scene,
"AgentUpdatesPerSecondMonitor", "AgentUpdatesPerSecondMonitor",
@ -201,15 +229,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[3], m => m.Scene.StatsReporter.LastReportedSimStats[3],
m => string.Format("{0} per second", m.GetValue()))); m => string.Format("{0} per second", m.GetValue())));
m_monitors.Add( m_staticMonitors.Add(
new GenericMonitor(
m_scene,
"ObjectUpdatesPerSecondMonitor",
"Object Updates",
m => m.Scene.StatsReporter.LastReportedObjectUpdates,
m => string.Format("{0} per second", m.GetValue())));
m_monitors.Add(
new GenericMonitor( new GenericMonitor(
m_scene, m_scene,
"ActiveObjectCountMonitor", "ActiveObjectCountMonitor",
@ -217,7 +237,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[7], m => m.Scene.StatsReporter.LastReportedSimStats[7],
m => string.Format("{0}", m.GetValue()))); m => string.Format("{0}", m.GetValue())));
m_monitors.Add( m_staticMonitors.Add(
new GenericMonitor( new GenericMonitor(
m_scene, m_scene,
"ActiveScriptsMonitor", "ActiveScriptsMonitor",
@ -225,7 +245,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[19], m => m.Scene.StatsReporter.LastReportedSimStats[19],
m => string.Format("{0}", m.GetValue()))); m => string.Format("{0}", m.GetValue())));
m_monitors.Add( m_staticMonitors.Add(
new GenericMonitor( new GenericMonitor(
m_scene, m_scene,
"ScriptEventsPerSecondMonitor", "ScriptEventsPerSecondMonitor",
@ -233,7 +253,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[20], m => m.Scene.StatsReporter.LastReportedSimStats[20],
m => string.Format("{0} per second", m.GetValue()))); m => string.Format("{0} per second", m.GetValue())));
m_monitors.Add( m_staticMonitors.Add(
new GenericMonitor( new GenericMonitor(
m_scene, m_scene,
"InPacketsPerSecondMonitor", "InPacketsPerSecondMonitor",
@ -241,7 +261,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[13], m => m.Scene.StatsReporter.LastReportedSimStats[13],
m => string.Format("{0} per second", m.GetValue()))); m => string.Format("{0} per second", m.GetValue())));
m_monitors.Add( m_staticMonitors.Add(
new GenericMonitor( new GenericMonitor(
m_scene, m_scene,
"OutPacketsPerSecondMonitor", "OutPacketsPerSecondMonitor",
@ -249,7 +269,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[14], m => m.Scene.StatsReporter.LastReportedSimStats[14],
m => string.Format("{0} per second", m.GetValue()))); m => string.Format("{0} per second", m.GetValue())));
m_monitors.Add( m_staticMonitors.Add(
new GenericMonitor( new GenericMonitor(
m_scene, m_scene,
"UnackedBytesMonitor", "UnackedBytesMonitor",
@ -257,7 +277,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[15], m => m.Scene.StatsReporter.LastReportedSimStats[15],
m => string.Format("{0}", m.GetValue()))); m => string.Format("{0}", m.GetValue())));
m_monitors.Add( m_staticMonitors.Add(
new GenericMonitor( new GenericMonitor(
m_scene, m_scene,
"PendingDownloadsMonitor", "PendingDownloadsMonitor",
@ -265,7 +285,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[17], m => m.Scene.StatsReporter.LastReportedSimStats[17],
m => string.Format("{0}", m.GetValue()))); m => string.Format("{0}", m.GetValue())));
m_monitors.Add( m_staticMonitors.Add(
new GenericMonitor( new GenericMonitor(
m_scene, m_scene,
"PendingUploadsMonitor", "PendingUploadsMonitor",
@ -273,7 +293,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[18], m => m.Scene.StatsReporter.LastReportedSimStats[18],
m => string.Format("{0}", m.GetValue()))); m => string.Format("{0}", m.GetValue())));
m_monitors.Add( m_staticMonitors.Add(
new GenericMonitor( new GenericMonitor(
m_scene, m_scene,
"TotalFrameTimeMonitor", "TotalFrameTimeMonitor",
@ -281,7 +301,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[8], m => m.Scene.StatsReporter.LastReportedSimStats[8],
m => string.Format("{0} ms", m.GetValue()))); m => string.Format("{0} ms", m.GetValue())));
m_monitors.Add( m_staticMonitors.Add(
new GenericMonitor( new GenericMonitor(
m_scene, m_scene,
"NetFrameTimeMonitor", "NetFrameTimeMonitor",
@ -289,7 +309,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[9], m => m.Scene.StatsReporter.LastReportedSimStats[9],
m => string.Format("{0} ms", m.GetValue()))); m => string.Format("{0} ms", m.GetValue())));
m_monitors.Add( m_staticMonitors.Add(
new GenericMonitor( new GenericMonitor(
m_scene, m_scene,
"PhysicsFrameTimeMonitor", "PhysicsFrameTimeMonitor",
@ -297,7 +317,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[10], m => m.Scene.StatsReporter.LastReportedSimStats[10],
m => string.Format("{0} ms", m.GetValue()))); m => string.Format("{0} ms", m.GetValue())));
m_monitors.Add( m_staticMonitors.Add(
new GenericMonitor( new GenericMonitor(
m_scene, m_scene,
"SimulationFrameTimeMonitor", "SimulationFrameTimeMonitor",
@ -305,7 +325,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[12], m => m.Scene.StatsReporter.LastReportedSimStats[12],
m => string.Format("{0} ms", m.GetValue()))); m => string.Format("{0} ms", m.GetValue())));
m_monitors.Add( m_staticMonitors.Add(
new GenericMonitor( new GenericMonitor(
m_scene, m_scene,
"AgentFrameTimeMonitor", "AgentFrameTimeMonitor",
@ -313,7 +333,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[16], m => m.Scene.StatsReporter.LastReportedSimStats[16],
m => string.Format("{0} ms", m.GetValue()))); m => string.Format("{0} ms", m.GetValue())));
m_monitors.Add( m_staticMonitors.Add(
new GenericMonitor( new GenericMonitor(
m_scene, m_scene,
"ImagesFrameTimeMonitor", "ImagesFrameTimeMonitor",
@ -321,7 +341,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
m => m.Scene.StatsReporter.LastReportedSimStats[11], m => m.Scene.StatsReporter.LastReportedSimStats[11],
m => string.Format("{0} ms", m.GetValue()))); m => string.Format("{0} ms", m.GetValue())));
m_alerts.Add(new DeadlockAlert(m_monitors.Find(x => x is LastFrameTimeMonitor) as LastFrameTimeMonitor)); m_alerts.Add(new DeadlockAlert(m_staticMonitors.Find(x => x is LastFrameTimeMonitor) as LastFrameTimeMonitor));
foreach (IAlert alert in m_alerts) foreach (IAlert alert in m_alerts)
{ {

View File

@ -2509,21 +2509,21 @@ namespace OpenSim.Region.Framework.Scenes
{ {
} }
private bool CollisionFilteredOut(SceneObjectPart dest, UUID objectID, string objectName) public bool CollisionFilteredOut(UUID objectID, string objectName)
{ {
if(dest.CollisionFilter.Count == 0) if(CollisionFilter.Count == 0)
return false; return false;
if (dest.CollisionFilter.ContainsValue(objectID.ToString()) || if (CollisionFilter.ContainsValue(objectID.ToString()) ||
dest.CollisionFilter.ContainsValue(objectID.ToString() + objectName) || CollisionFilter.ContainsValue(objectID.ToString() + objectName) ||
dest.CollisionFilter.ContainsValue(UUID.Zero.ToString() + objectName)) CollisionFilter.ContainsValue(UUID.Zero.ToString() + objectName))
{ {
if (dest.CollisionFilter.ContainsKey(1)) if (CollisionFilter.ContainsKey(1))
return false; return false;
return true; return true;
} }
if (dest.CollisionFilter.ContainsKey(1)) if (CollisionFilter.ContainsKey(1))
return true; return true;
return false; return false;
@ -2586,7 +2586,7 @@ namespace OpenSim.Region.Framework.Scenes
SceneObjectPart obj = ParentGroup.Scene.GetSceneObjectPart(localId); SceneObjectPart obj = ParentGroup.Scene.GetSceneObjectPart(localId);
if (obj != null) if (obj != null)
{ {
if (!dest.CollisionFilteredOut(this, obj.UUID, obj.Name)) if (!dest.CollisionFilteredOut(obj.UUID, obj.Name))
colliding.Add(CreateDetObject(obj)); colliding.Add(CreateDetObject(obj));
} }
else else
@ -2594,7 +2594,7 @@ namespace OpenSim.Region.Framework.Scenes
ScenePresence av = ParentGroup.Scene.GetScenePresence(localId); ScenePresence av = ParentGroup.Scene.GetScenePresence(localId);
if (av != null && (!av.IsChildAgent)) if (av != null && (!av.IsChildAgent))
{ {
if (!dest.CollisionFilteredOut(this, av.UUID, av.Name)) if (!dest.CollisionFilteredOut(av.UUID, av.Name))
colliding.Add(CreateDetObject(av)); colliding.Add(CreateDetObject(av));
} }
} }

View File

@ -26,7 +26,7 @@
*/ */
using System; using System;
//using System.Collections.Generic; using System.Collections.Generic;
using System.Timers; using System.Timers;
using OpenMetaverse.Packets; using OpenMetaverse.Packets;
using OpenSim.Framework; using OpenSim.Framework;
@ -35,10 +35,18 @@ using OpenSim.Region.Framework.Interfaces;
namespace OpenSim.Region.Framework.Scenes namespace OpenSim.Region.Framework.Scenes
{ {
/// <summary>
/// Collect statistics from the scene to send to the client and for access by other monitoring tools.
/// </summary>
/// <remarks>
/// FIXME: This should be a monitoring region module
/// </remarks>
public class SimStatsReporter public class SimStatsReporter
{ {
// private static readonly log4net.ILog m_log private static readonly log4net.ILog m_log
// = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public const string LastReportedObjectUpdateStatName = "LastReportedObjectUpdates";
public delegate void SendStatResult(SimStats stats); public delegate void SendStatResult(SimStats stats);
@ -113,6 +121,14 @@ namespace OpenSim.Region.Framework.Scenes
get { return lastReportedSimStats; } get { return lastReportedSimStats; }
} }
/// <summary>
/// Extra sim statistics that are used by monitors but not sent to the client.
/// </summary>
/// <value>
/// The keys are the stat names.
/// </value>
private Dictionary<string, float> m_lastReportedExtraSimStats = new Dictionary<string, float>();
// Sending a stats update every 3 seconds- // Sending a stats update every 3 seconds-
private int statsUpdatesEveryMS = 3000; private int statsUpdatesEveryMS = 3000;
private float statsUpdateFactor = 0; private float statsUpdateFactor = 0;
@ -387,7 +403,20 @@ namespace OpenSim.Region.Framework.Scenes
} }
// Extra statistics that aren't currently sent to clients // Extra statistics that aren't currently sent to clients
LastReportedObjectUpdates = m_objectUpdates / statsUpdateFactor; lock (m_lastReportedExtraSimStats)
{
m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates / statsUpdateFactor;
Dictionary<string, float> physicsStats = m_scene.PhysicsScene.GetStats();
if (physicsStats != null)
{
foreach (KeyValuePair<string, float> tuple in physicsStats)
{
m_lastReportedExtraSimStats[tuple.Key] = tuple.Value / statsUpdateFactor;
}
}
}
resetvalues(); resetvalues();
} }
@ -546,7 +575,10 @@ namespace OpenSim.Region.Framework.Scenes
public void AddPendingDownloads(int count) public void AddPendingDownloads(int count)
{ {
m_pendingDownloads += count; m_pendingDownloads += count;
if (m_pendingDownloads < 0) m_pendingDownloads = 0;
if (m_pendingDownloads < 0)
m_pendingDownloads = 0;
//m_log.InfoFormat("[stats]: Adding {0} to pending downloads to make {1}", count, m_pendingDownloads); //m_log.InfoFormat("[stats]: Adding {0} to pending downloads to make {1}", count, m_pendingDownloads);
} }
@ -568,5 +600,11 @@ namespace OpenSim.Region.Framework.Scenes
} }
#endregion #endregion
public Dictionary<string, float> GetExtraSimStats()
{
lock (m_lastReportedExtraSimStats)
return new Dictionary<string, float>(m_lastReportedExtraSimStats);
}
} }
} }

View File

@ -241,8 +241,22 @@ namespace OpenSim.Region.Physics.Manager
public abstract void AddPhysicsActorTaint(PhysicsActor prim); public abstract void AddPhysicsActorTaint(PhysicsActor prim);
/// <summary>
/// Perform a simulation of the current physics scene over the given timestep.
/// </summary>
/// <param name="timeStep"></param>
/// <returns>The number of frames simulated over that period.</returns>
public abstract float Simulate(float timeStep); public abstract float Simulate(float timeStep);
/// <summary>
/// Get statistics about this scene.
/// </summary>
/// <remarks>This facility is currently experimental and subject to change.</remarks>
/// <returns>
/// A dictionary where the key is the statistic name. If no statistics are supplied then returns null.
/// </returns>
public virtual Dictionary<string, float> GetStats() { return null; }
public abstract void GetResults(); public abstract void GetResults();
public abstract void SetTerrain(float[] heightMap); public abstract void SetTerrain(float[] heightMap);

View File

@ -131,6 +131,41 @@ namespace OpenSim.Region.Physics.OdePlugin
/// </remarks> /// </remarks>
internal static Object UniversalColliderSyncObject = new Object(); internal static Object UniversalColliderSyncObject = new Object();
/// <summary>
/// Is stats collecting enabled for this ODE scene?
/// </summary>
public bool CollectStats { get; set; }
/// <summary>
/// Statistics for this scene.
/// </summary>
private Dictionary<string, float> m_stats = new Dictionary<string, float>();
/// <summary>
/// Stat name for recording the number of milliseconds that ODE spends in native collision code.
/// </summary>
public const string ODENativeCollisionFrameMsStatName = "ODENativeCollisionFrameMS";
/// <summary>
/// Used to hold tick numbers for stat collection purposes.
/// </summary>
private int m_nativeCollisionTickRecorder;
/// <summary>
/// A messy way to tell if we need to avoid adding a collision time because this was already done in the callback.
/// </summary>
private bool m_inCollisionTiming;
/// <summary>
/// Used in calculating physics frame time dilation
/// </summary>
private int tickCountFrameRun;
/// <summary>
/// Used in calculating physics frame time dilation
/// </summary>
private int latertickcount;
private Random fluidRandomizer = new Random(Environment.TickCount); private Random fluidRandomizer = new Random(Environment.TickCount);
private const uint m_regionWidth = Constants.RegionSize; private const uint m_regionWidth = Constants.RegionSize;
@ -345,9 +380,6 @@ namespace OpenSim.Region.Physics.OdePlugin
private OdePrim cp1; private OdePrim cp1;
private OdeCharacter cc2; private OdeCharacter cc2;
private OdePrim cp2; private OdePrim cp2;
private int tickCountFrameRun;
private int latertickcount=0;
//private int cStartStop = 0; //private int cStartStop = 0;
//private string cDictKey = ""; //private string cDictKey = "";
@ -440,6 +472,8 @@ namespace OpenSim.Region.Physics.OdePlugin
// Initialize the mesh plugin // Initialize the mesh plugin
public override void Initialise(IMesher meshmerizer, IConfigSource config) public override void Initialise(IMesher meshmerizer, IConfigSource config)
{ {
m_stats[ODENativeCollisionFrameMsStatName] = 0;
mesher = meshmerizer; mesher = meshmerizer;
m_config = config; m_config = config;
// Defaults // Defaults
@ -464,6 +498,8 @@ namespace OpenSim.Region.Physics.OdePlugin
IConfig physicsconfig = m_config.Configs["ODEPhysicsSettings"]; IConfig physicsconfig = m_config.Configs["ODEPhysicsSettings"];
if (physicsconfig != null) if (physicsconfig != null)
{ {
CollectStats = physicsconfig.GetBoolean("collect_stats", false);
gravityx = physicsconfig.GetFloat("world_gravityx", 0f); gravityx = physicsconfig.GetFloat("world_gravityx", 0f);
gravityy = physicsconfig.GetFloat("world_gravityy", 0f); gravityy = physicsconfig.GetFloat("world_gravityy", 0f);
gravityz = physicsconfig.GetFloat("world_gravityz", -9.8f); gravityz = physicsconfig.GetFloat("world_gravityz", -9.8f);
@ -764,6 +800,62 @@ namespace OpenSim.Region.Physics.OdePlugin
#region Collision Detection #region Collision Detection
/// <summary>
/// Collides two geometries.
/// </summary>
/// <returns></returns>
/// <param name='geom1'></param>
/// <param name='geom2'>/param>
/// <param name='maxContacts'></param>
/// <param name='contactsArray'></param>
/// <param name='contactGeomSize'></param>
private int CollideGeoms(
IntPtr geom1, IntPtr geom2, int maxContacts, Ode.NET.d.ContactGeom[] contactsArray, int contactGeomSize)
{
int count;
lock (OdeScene.UniversalColliderSyncObject)
{
// We do this inside the lock so that we don't count any delay in acquiring it
if (CollectStats)
m_nativeCollisionTickRecorder = Util.EnvironmentTickCount();
count = d.Collide(geom1, geom2, maxContacts, contactsArray, contactGeomSize);
}
// We do this outside the lock so that any waiting threads aren't held up, though the effect is probably
// negligable
if (CollectStats)
m_stats[ODENativeCollisionFrameMsStatName]
+= Util.EnvironmentTickCountSubtract(m_nativeCollisionTickRecorder);
return count;
}
/// <summary>
/// Collide two spaces or a space and a geometry.
/// </summary>
/// <param name='space1'></param>
/// <param name='space2'>/param>
/// <param name='data'></param>
private void CollideSpaces(IntPtr space1, IntPtr space2, IntPtr data)
{
if (CollectStats)
{
m_inCollisionTiming = true;
m_nativeCollisionTickRecorder = Util.EnvironmentTickCount();
}
d.SpaceCollide2(space1, space2, data, nearCallback);
if (CollectStats && m_inCollisionTiming)
{
m_stats[ODENativeCollisionFrameMsStatName]
+= Util.EnvironmentTickCountSubtract(m_nativeCollisionTickRecorder);
m_inCollisionTiming = false;
}
}
/// <summary> /// <summary>
/// This is our near callback. A geometry is near a body /// This is our near callback. A geometry is near a body
/// </summary> /// </summary>
@ -772,6 +864,13 @@ namespace OpenSim.Region.Physics.OdePlugin
/// <param name="g2">another geometry or space</param> /// <param name="g2">another geometry or space</param>
private void near(IntPtr space, IntPtr g1, IntPtr g2) private void near(IntPtr space, IntPtr g1, IntPtr g2)
{ {
if (CollectStats && m_inCollisionTiming)
{
m_stats[ODENativeCollisionFrameMsStatName]
+= Util.EnvironmentTickCountSubtract(m_nativeCollisionTickRecorder);
m_inCollisionTiming = false;
}
// m_log.DebugFormat("[PHYSICS]: Colliding {0} and {1} in {2}", g1, g2, space); // m_log.DebugFormat("[PHYSICS]: Colliding {0} and {1} in {2}", g1, g2, space);
// no lock here! It's invoked from within Simulate(), which is thread-locked // no lock here! It's invoked from within Simulate(), which is thread-locked
@ -789,7 +888,7 @@ namespace OpenSim.Region.Physics.OdePlugin
// contact points in the space // contact points in the space
try try
{ {
d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback); CollideSpaces(g1, g2, IntPtr.Zero);
} }
catch (AccessViolationException) catch (AccessViolationException)
{ {
@ -832,6 +931,7 @@ namespace OpenSim.Region.Physics.OdePlugin
// Figure out how many contact points we have // Figure out how many contact points we have
int count = 0; int count = 0;
try try
{ {
// Colliding Geom To Geom // Colliding Geom To Geom
@ -843,8 +943,7 @@ namespace OpenSim.Region.Physics.OdePlugin
if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact)) if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
return; return;
lock (OdeScene.UniversalColliderSyncObject) count = CollideGeoms(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf);
count = d.Collide(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf);
if (count > contacts.Length) if (count > contacts.Length)
m_log.Error("[ODE SCENE]: Got " + count + " contacts when we asked for a maximum of " + contacts.Length); m_log.Error("[ODE SCENE]: Got " + count + " contacts when we asked for a maximum of " + contacts.Length);
@ -1578,7 +1677,7 @@ namespace OpenSim.Region.Physics.OdePlugin
// and we'll run it again on all of them. // and we'll run it again on all of them.
try try
{ {
d.SpaceCollide2(space, chr.Shell, IntPtr.Zero, nearCallback); CollideSpaces(space, chr.Shell, IntPtr.Zero);
} }
catch (AccessViolationException) catch (AccessViolationException)
{ {
@ -1593,6 +1692,9 @@ namespace OpenSim.Region.Physics.OdePlugin
//} //}
} }
// if (framecount % 55 == 0)
// m_log.DebugFormat("Processed {0} collisions", _perloopContact.Count);
List<OdePrim> removeprims = null; List<OdePrim> removeprims = null;
foreach (OdePrim chr in _activeprims) foreach (OdePrim chr in _activeprims)
{ {
@ -1604,7 +1706,7 @@ namespace OpenSim.Region.Physics.OdePlugin
{ {
if (space != IntPtr.Zero && chr.prim_geom != IntPtr.Zero && chr.m_taintremove == false) if (space != IntPtr.Zero && chr.prim_geom != IntPtr.Zero && chr.m_taintremove == false)
{ {
d.SpaceCollide2(space, chr.prim_geom, IntPtr.Zero, nearCallback); CollideSpaces(space, chr.prim_geom, IntPtr.Zero);
} }
else else
{ {
@ -2689,7 +2791,7 @@ namespace OpenSim.Region.Physics.OdePlugin
/// It calls the methods that report back to the object owners.. (scenepresence, SceneObjectGroup) /// It calls the methods that report back to the object owners.. (scenepresence, SceneObjectGroup)
/// </summary> /// </summary>
/// <param name="timeStep"></param> /// <param name="timeStep"></param>
/// <returns></returns> /// <returns>The number of frames simulated over that period.</returns>
public override float Simulate(float timeStep) public override float Simulate(float timeStep)
{ {
if (framecount >= int.MaxValue) if (framecount >= int.MaxValue)
@ -3190,7 +3292,7 @@ namespace OpenSim.Region.Physics.OdePlugin
public override bool IsThreaded public override bool IsThreaded
{ {
// for now we won't be multithreaded // for now we won't be multithreaded
get { return (false); } get { return false; }
} }
#region ODE Specific Terrain Fixes #region ODE Specific Terrain Fixes
@ -3955,5 +4057,22 @@ namespace OpenSim.Region.Physics.OdePlugin
ds.SetViewpoint(ref xyz, ref hpr); ds.SetViewpoint(ref xyz, ref hpr);
} }
#endif #endif
public override Dictionary<string, float> GetStats()
{
if (!CollectStats)
return null;
Dictionary<string, float> returnStats;
lock (OdeLock)
{
returnStats = new Dictionary<string, float>(m_stats);
m_stats[ODENativeCollisionFrameMsStatName] = 0;
}
return returnStats;
}
} }
} }

View File

@ -675,6 +675,25 @@
[ODEPhysicsSettings] [ODEPhysicsSettings]
; ##
; ## Physics stats settings
;
; If collect_stats is enabled, then extra stat information is collected which is accessible via the MonitorModule
; (see http://opensimulator.org/wiki/Monitoring_Module for more details).
collect_stats = false
; ##
; ## Physics logging settings - logfiles are saved to *.DIF files
; ##
; default is false
;physics_logging = true
;; every n simulation iterations, the physics snapshot file is updated
;physics_logging_interval = 50
;; append to existing physics logfile, or overwrite existing logfiles?
;physics_logging_append_existing_logfile = true
;## ;##
;## World Settings ;## World Settings
;## ;##
@ -823,17 +842,6 @@
; number^2 physical level of detail of the sculpt texture. 16x16 - 256 verticies ; number^2 physical level of detail of the sculpt texture. 16x16 - 256 verticies
mesh_physical_lod = 16 mesh_physical_lod = 16
; ##
; ## Physics logging settings - logfiles are saved to *.DIF files
; ##
; default is false
;physics_logging = true
;; every n simulation iterations, the physics snapshot file is updated
;physics_logging_interval = 50
;; append to existing physics logfile, or overwrite existing logfiles?
;physics_logging_append_existing_logfile = true
; ## ; ##
; ## Joint support ; ## Joint support
; ## ; ##