Merge branch 'master' of melanie@opensimulator.org:/var/git/opensim

cpu-performance
Melanie 2013-06-23 01:49:45 +01:00
commit 936700bda3
38 changed files with 967 additions and 961 deletions

View File

@ -46,7 +46,7 @@ namespace OpenSim.OfflineIM
{
public class OfflineIMService : OfflineIMServiceBase, IOfflineIMService
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private const int MAX_IM = 25;
private XmlSerializer m_serializer;

View File

@ -46,7 +46,7 @@ namespace OpenSim.Capabilities.Handlers
{
public class FetchInventory2Handler
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private IInventoryService m_inventoryService;
@ -121,4 +121,4 @@ namespace OpenSim.Capabilities.Handlers
return llsdItem;
}
}
}
}

View File

@ -1,4 +1,4 @@
/*
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
@ -45,16 +45,16 @@ namespace OpenSim.Framework.Monitoring
sb.Append(Environment.NewLine);
sb.AppendFormat(
"Allocated to OpenSim objects: {0} MB\n",
"Heap allocated to OpenSim : {0} MB\n",
Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0));
sb.AppendFormat(
"OpenSim last object memory churn : {0} MB/s\n",
Math.Round((MemoryWatchdog.LastMemoryChurn * 1000) / 1024.0 / 1024, 3));
"Last heap allocation rate : {0} MB/s\n",
Math.Round((MemoryWatchdog.LastHeapAllocationRate * 1000) / 1024.0 / 1024, 3));
sb.AppendFormat(
"OpenSim average object memory churn : {0} MB/s\n",
Math.Round((MemoryWatchdog.AverageMemoryChurn * 1000) / 1024.0 / 1024, 3));
"Average heap allocation rate: {0} MB/s\n",
Math.Round((MemoryWatchdog.AverageHeapAllocationRate * 1000) / 1024.0 / 1024, 3));
sb.AppendFormat(
"Process memory : {0} MB\n",

View File

@ -60,17 +60,17 @@ namespace OpenSim.Framework.Monitoring
private static bool m_enabled;
/// <summary>
/// Last memory churn in bytes per millisecond.
/// Average heap allocation rate in bytes per millisecond.
/// </summary>
public static double AverageMemoryChurn
public static double AverageHeapAllocationRate
{
get { if (m_samples.Count > 0) return m_samples.Average(); else return 0; }
}
/// <summary>
/// Average memory churn in bytes per millisecond.
/// Last heap allocation in bytes
/// </summary>
public static double LastMemoryChurn
public static double LastHeapAllocationRate
{
get { if (m_samples.Count > 0) return m_samples.Last(); else return 0; }
}

View File

@ -0,0 +1,349 @@
/*
* 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.Diagnostics;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading;
using log4net;
using Nini.Config;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
namespace OpenSim.Framework.Monitoring
{
public class ServerStatsCollector
{
private readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private readonly string LogHeader = "[SERVER STATS]";
public bool Enabled = false;
private static Dictionary<string, Stat> RegisteredStats = new Dictionary<string, Stat>();
public readonly string CategoryServer = "server";
public readonly string ContainerThreadpool = "threadpool";
public readonly string ContainerProcessor = "processor";
public readonly string ContainerMemory = "memory";
public readonly string ContainerNetwork = "network";
public readonly string ContainerProcess = "process";
public string NetworkInterfaceTypes = "Ethernet";
readonly int performanceCounterSampleInterval = 500;
// int lastperformanceCounterSampleTime = 0;
private class PerfCounterControl
{
public PerformanceCounter perfCounter;
public int lastFetch;
public string name;
public PerfCounterControl(PerformanceCounter pPc)
: this(pPc, String.Empty)
{
}
public PerfCounterControl(PerformanceCounter pPc, string pName)
{
perfCounter = pPc;
lastFetch = 0;
name = pName;
}
}
PerfCounterControl processorPercentPerfCounter = null;
// IRegionModuleBase.Initialize
public void Initialise(IConfigSource source)
{
IConfig cfg = source.Configs["Monitoring"];
if (cfg != null)
Enabled = cfg.GetBoolean("ServerStatsEnabled", true);
if (Enabled)
{
NetworkInterfaceTypes = cfg.GetString("NetworkInterfaceTypes", "Ethernet");
}
}
public void Start()
{
if (RegisteredStats.Count == 0)
RegisterServerStats();
}
public void Close()
{
if (RegisteredStats.Count > 0)
{
foreach (Stat stat in RegisteredStats.Values)
{
StatsManager.DeregisterStat(stat);
stat.Dispose();
}
RegisteredStats.Clear();
}
}
private void MakeStat(string pName, string pDesc, string pUnit, string pContainer, Action<Stat> act)
{
MakeStat(pName, pDesc, pUnit, pContainer, act, MeasuresOfInterest.None);
}
private void MakeStat(string pName, string pDesc, string pUnit, string pContainer, Action<Stat> act, MeasuresOfInterest moi)
{
string desc = pDesc;
if (desc == null)
desc = pName;
Stat stat = new Stat(pName, pName, desc, pUnit, CategoryServer, pContainer, StatType.Pull, moi, act, StatVerbosity.Debug);
StatsManager.RegisterStat(stat);
RegisteredStats.Add(pName, stat);
}
public void RegisterServerStats()
{
// lastperformanceCounterSampleTime = Util.EnvironmentTickCount();
PerformanceCounter tempPC;
Stat tempStat;
string tempName;
try
{
tempName = "CPUPercent";
tempPC = new PerformanceCounter("Processor", "% Processor Time", "_Total");
processorPercentPerfCounter = new PerfCounterControl(tempPC);
// A long time bug in mono is that CPU percent is reported as CPU percent idle. Windows reports CPU percent busy.
tempStat = new Stat(tempName, tempName, "", "percent", CategoryServer, ContainerProcessor,
StatType.Pull, (s) => { GetNextValue(s, processorPercentPerfCounter, Util.IsWindows() ? 1 : -1); },
StatVerbosity.Info);
StatsManager.RegisterStat(tempStat);
RegisteredStats.Add(tempName, tempStat);
MakeStat("TotalProcessorTime", null, "sec", ContainerProcessor,
(s) => { s.Value = Process.GetCurrentProcess().TotalProcessorTime.TotalSeconds; });
MakeStat("UserProcessorTime", null, "sec", ContainerProcessor,
(s) => { s.Value = Process.GetCurrentProcess().UserProcessorTime.TotalSeconds; });
MakeStat("PrivilegedProcessorTime", null, "sec", ContainerProcessor,
(s) => { s.Value = Process.GetCurrentProcess().PrivilegedProcessorTime.TotalSeconds; });
MakeStat("Threads", null, "threads", ContainerProcessor,
(s) => { s.Value = Process.GetCurrentProcess().Threads.Count; });
}
catch (Exception e)
{
m_log.ErrorFormat("{0} Exception creating 'Process': {1}", LogHeader, e);
}
MakeStat("BuiltinThreadpoolWorkerThreadsAvailable", null, "threads", ContainerThreadpool,
s =>
{
int workerThreads, iocpThreads;
ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads);
s.Value = workerThreads;
});
MakeStat("BuiltinThreadpoolIOCPThreadsAvailable", null, "threads", ContainerThreadpool,
s =>
{
int workerThreads, iocpThreads;
ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads);
s.Value = iocpThreads;
});
if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool && Util.GetSmartThreadPoolInfo() != null)
{
MakeStat("STPMaxThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MaxThreads);
MakeStat("STPMinThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MinThreads);
MakeStat("STPConcurrency", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MaxConcurrentWorkItems);
MakeStat("STPActiveThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().ActiveThreads);
MakeStat("STPInUseThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().InUseThreads);
MakeStat("STPWorkItemsWaiting", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().WaitingCallbacks);
}
MakeStat(
"HTTPRequestsMade",
"Number of outbound HTTP requests made",
"requests",
ContainerNetwork,
s => s.Value = WebUtil.RequestNumber,
MeasuresOfInterest.AverageChangeOverTime);
try
{
List<string> okInterfaceTypes = new List<string>(NetworkInterfaceTypes.Split(','));
IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces();
foreach (NetworkInterface nic in nics)
{
if (nic.OperationalStatus != OperationalStatus.Up)
continue;
string nicInterfaceType = nic.NetworkInterfaceType.ToString();
if (!okInterfaceTypes.Contains(nicInterfaceType))
{
m_log.DebugFormat("{0} Not including stats for network interface '{1}' of type '{2}'.",
LogHeader, nic.Name, nicInterfaceType);
m_log.DebugFormat("{0} To include, add to comma separated list in [Monitoring]NetworkInterfaceTypes={1}",
LogHeader, NetworkInterfaceTypes);
continue;
}
if (nic.Supports(NetworkInterfaceComponent.IPv4))
{
IPv4InterfaceStatistics nicStats = nic.GetIPv4Statistics();
if (nicStats != null)
{
MakeStat("BytesRcvd/" + nic.Name, nic.Name, "KB", ContainerNetwork,
(s) => { LookupNic(s, (ns) => { return ns.BytesReceived; }, 1024.0); });
MakeStat("BytesSent/" + nic.Name, nic.Name, "KB", ContainerNetwork,
(s) => { LookupNic(s, (ns) => { return ns.BytesSent; }, 1024.0); });
MakeStat("TotalBytes/" + nic.Name, nic.Name, "KB", ContainerNetwork,
(s) => { LookupNic(s, (ns) => { return ns.BytesSent + ns.BytesReceived; }, 1024.0); });
}
}
// TODO: add IPv6 (it may actually happen someday)
}
}
catch (Exception e)
{
m_log.ErrorFormat("{0} Exception creating 'Network Interface': {1}", LogHeader, e);
}
MakeStat("ProcessMemory", null, "MB", ContainerMemory,
(s) => { s.Value = Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024d / 1024d, 3); });
MakeStat("HeapMemory", null, "MB", ContainerMemory,
(s) => { s.Value = Math.Round(GC.GetTotalMemory(false) / 1024d / 1024d, 3); });
MakeStat("LastHeapAllocationRate", null, "MB/sec", ContainerMemory,
(s) => { s.Value = Math.Round(MemoryWatchdog.LastHeapAllocationRate * 1000d / 1024d / 1024d, 3); });
MakeStat("AverageHeapAllocationRate", null, "MB/sec", ContainerMemory,
(s) => { s.Value = Math.Round(MemoryWatchdog.AverageHeapAllocationRate * 1000d / 1024d / 1024d, 3); });
}
// Notes on performance counters:
// "How To Read Performance Counters": http://blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx
// "How to get the CPU Usage in C#": http://stackoverflow.com/questions/278071/how-to-get-the-cpu-usage-in-c
// "Mono Performance Counters": http://www.mono-project.com/Mono_Performance_Counters
private delegate double PerfCounterNextValue();
private void GetNextValue(Stat stat, PerfCounterControl perfControl)
{
GetNextValue(stat, perfControl, 1.0);
}
private void GetNextValue(Stat stat, PerfCounterControl perfControl, double factor)
{
if (Util.EnvironmentTickCountSubtract(perfControl.lastFetch) > performanceCounterSampleInterval)
{
if (perfControl != null && perfControl.perfCounter != null)
{
try
{
// Kludge for factor to run double duty. If -1, subtract the value from one
if (factor == -1)
stat.Value = 1 - perfControl.perfCounter.NextValue();
else
stat.Value = perfControl.perfCounter.NextValue() / factor;
}
catch (Exception e)
{
m_log.ErrorFormat("{0} Exception on NextValue fetching {1}: {2}", LogHeader, stat.Name, e);
}
perfControl.lastFetch = Util.EnvironmentTickCount();
}
}
}
// Lookup the nic that goes with this stat and set the value by using a fetch action.
// Not sure about closure with delegates inside delegates.
private delegate double GetIPv4StatValue(IPv4InterfaceStatistics interfaceStat);
private void LookupNic(Stat stat, GetIPv4StatValue getter, double factor)
{
// Get the one nic that has the name of this stat
IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces().Where(
(network) => network.Name == stat.Description);
try
{
foreach (NetworkInterface nic in nics)
{
IPv4InterfaceStatistics intrStats = nic.GetIPv4Statistics();
if (intrStats != null)
{
double newVal = Math.Round(getter(intrStats) / factor, 3);
stat.Value = newVal;
}
break;
}
}
catch
{
// There are times interfaces go away so we just won't update the stat for this
m_log.ErrorFormat("{0} Exception fetching stat on interface '{1}'", LogHeader, stat.Description);
}
}
}
public class ServerStatsAggregator : Stat
{
public ServerStatsAggregator(
string shortName,
string name,
string description,
string unitName,
string category,
string container
)
: base(
shortName,
name,
description,
unitName,
category,
container,
StatType.Push,
MeasuresOfInterest.None,
null,
StatVerbosity.Info)
{
}
public override string ToConsoleString()
{
StringBuilder sb = new StringBuilder();
return sb.ToString();
}
public override OSDMap ToOSDMap()
{
OSDMap ret = new OSDMap();
return ret;
}
}
}

View File

@ -27,8 +27,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using log4net;
using OpenMetaverse.StructuredData;
namespace OpenSim.Framework.Monitoring
@ -38,6 +40,10 @@ namespace OpenSim.Framework.Monitoring
/// </summary>
public class Stat : IDisposable
{
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public static readonly char[] DisallowedShortNameCharacters = { '.' };
/// <summary>
/// Category of this stat (e.g. cache, scene, etc).
/// </summary>
@ -95,7 +101,7 @@ namespace OpenSim.Framework.Monitoring
/// <remarks>
/// Will be null if no measures of interest require samples.
/// </remarks>
private static Queue<double> m_samples;
private Queue<double> m_samples;
/// <summary>
/// Maximum number of statistical samples.
@ -162,6 +168,12 @@ namespace OpenSim.Framework.Monitoring
throw new Exception(
string.Format("Stat cannot be in category '{0}' since this is reserved for a subcommand", category));
foreach (char c in DisallowedShortNameCharacters)
{
if (shortName.IndexOf(c) != -1)
throw new Exception(string.Format("Stat name {0} cannot contain character {1}", shortName, c));
}
ShortName = shortName;
Name = name;
Description = description;
@ -204,6 +216,8 @@ namespace OpenSim.Framework.Monitoring
if (m_samples.Count >= m_maxSamples)
m_samples.Dequeue();
// m_log.DebugFormat("[STAT]: Recording value {0} for {1}", newValue, Name);
m_samples.Enqueue(newValue);
}
}
@ -242,6 +256,10 @@ namespace OpenSim.Framework.Monitoring
lock (m_samples)
{
// m_log.DebugFormat(
// "[STAT]: Samples for {0} are {1}",
// Name, string.Join(",", m_samples.Select(s => s.ToString()).ToArray()));
foreach (double s in m_samples)
{
if (lastSample != null)
@ -253,7 +271,7 @@ namespace OpenSim.Framework.Monitoring
int divisor = m_samples.Count <= 1 ? 1 : m_samples.Count - 1;
sb.AppendFormat(", {0:0.##}{1}/s", totalChange / divisor / (Watchdog.WATCHDOG_INTERVAL_MS / 1000), UnitName);
sb.AppendFormat(", {0:0.##} {1}/s", totalChange / divisor / (Watchdog.WATCHDOG_INTERVAL_MS / 1000), UnitName);
}
}
}

View File

@ -27,6 +27,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OpenSim.Framework.Monitoring
@ -54,13 +55,13 @@ namespace OpenSim.Framework.Monitoring
public static SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>> RegisteredStats
= new SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>>();
private static AssetStatsCollector assetStats;
private static UserStatsCollector userStats;
private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector();
// private static AssetStatsCollector assetStats;
// private static UserStatsCollector userStats;
// private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector();
public static AssetStatsCollector AssetStats { get { return assetStats; } }
public static UserStatsCollector UserStats { get { return userStats; } }
public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } }
// public static AssetStatsCollector AssetStats { get { return assetStats; } }
// public static UserStatsCollector UserStats { get { return userStats; } }
public static SimExtraStatsCollector SimExtraStats { get; set; }
public static void RegisterConsoleCommands(ICommandConsole console)
{
@ -68,12 +69,14 @@ namespace OpenSim.Framework.Monitoring
"General",
false,
"show stats",
"show stats [list|all|<category>]",
"show stats [list|all|(<category>[.<container>])+",
"Show statistical information for this server",
"If no final argument is specified then legacy statistics information is currently shown.\n"
+ "If list is specified then statistic categories are shown.\n"
+ "If all is specified then all registered statistics are shown.\n"
+ "If a category name is specified then only statistics from that category are shown.\n"
+ "'list' argument will show statistic categories.\n"
+ "'all' will show all statistics.\n"
+ "A <category> name will show statistics from that category.\n"
+ "A <category>.<container> name will show statistics from that category in that container.\n"
+ "More than one name can be given separated by spaces.\n"
+ "THIS STATS FACILITY IS EXPERIMENTAL AND DOES NOT YET CONTAIN ALL STATS",
HandleShowStatsCommand);
}
@ -84,43 +87,47 @@ namespace OpenSim.Framework.Monitoring
if (cmd.Length > 2)
{
var categoryName = cmd[2];
var containerName = cmd.Length > 3 ? cmd[3] : String.Empty;
foreach (string name in cmd.Skip(2))
{
string[] components = name.Split('.');
if (categoryName == AllSubCommand)
{
foreach (var category in RegisteredStats.Values)
string categoryName = components[0];
string containerName = components.Length > 1 ? components[1] : null;
if (categoryName == AllSubCommand)
{
OutputCategoryStatsToConsole(con, category);
OutputAllStatsToConsole(con);
}
}
else if (categoryName == ListSubCommand)
{
con.Output("Statistic categories available are:");
foreach (string category in RegisteredStats.Keys)
con.OutputFormat(" {0}", category);
}
else
{
SortedDictionary<string, SortedDictionary<string, Stat>> category;
if (!RegisteredStats.TryGetValue(categoryName, out category))
else if (categoryName == ListSubCommand)
{
con.OutputFormat("No such category as {0}", categoryName);
con.Output("Statistic categories available are:");
foreach (string category in RegisteredStats.Keys)
con.OutputFormat(" {0}", category);
}
else
{
if (String.IsNullOrEmpty(containerName))
OutputCategoryStatsToConsole(con, category);
SortedDictionary<string, SortedDictionary<string, Stat>> category;
if (!RegisteredStats.TryGetValue(categoryName, out category))
{
con.OutputFormat("No such category as {0}", categoryName);
}
else
{
SortedDictionary<string, Stat> container;
if (category.TryGetValue(containerName, out container))
if (String.IsNullOrEmpty(containerName))
{
OutputContainerStatsToConsole(con, container);
OutputCategoryStatsToConsole(con, category);
}
else
{
con.OutputFormat("No such container {0} in category {1}", containerName, categoryName);
SortedDictionary<string, Stat> container;
if (category.TryGetValue(containerName, out container))
{
OutputContainerStatsToConsole(con, container);
}
else
{
con.OutputFormat("No such container {0} in category {1}", containerName, categoryName);
}
}
}
}
@ -129,7 +136,18 @@ namespace OpenSim.Framework.Monitoring
else
{
// Legacy
con.Output(SimExtraStats.Report());
if (SimExtraStats != null)
con.Output(SimExtraStats.Report());
else
OutputAllStatsToConsole(con);
}
}
private static void OutputAllStatsToConsole(ICommandConsole con)
{
foreach (var category in RegisteredStats.Values)
{
OutputCategoryStatsToConsole(con, category);
}
}
@ -150,27 +168,27 @@ namespace OpenSim.Framework.Monitoring
}
}
/// <summary>
/// Start collecting statistics related to assets.
/// Should only be called once.
/// </summary>
public static AssetStatsCollector StartCollectingAssetStats()
{
assetStats = new AssetStatsCollector();
return assetStats;
}
/// <summary>
/// Start collecting statistics related to users.
/// Should only be called once.
/// </summary>
public static UserStatsCollector StartCollectingUserStats()
{
userStats = new UserStatsCollector();
return userStats;
}
// /// <summary>
// /// Start collecting statistics related to assets.
// /// Should only be called once.
// /// </summary>
// public static AssetStatsCollector StartCollectingAssetStats()
// {
// assetStats = new AssetStatsCollector();
//
// return assetStats;
// }
//
// /// <summary>
// /// Start collecting statistics related to users.
// /// Should only be called once.
// /// </summary>
// public static UserStatsCollector StartCollectingUserStats()
// {
// userStats = new UserStatsCollector();
//
// return userStats;
// }
/// <summary>
/// Registers a statistic.

View File

@ -86,25 +86,22 @@ namespace OpenSim.Framework.Servers
/// </summary>
protected virtual void StartupSpecific()
{
if (m_console == null)
return;
StatsManager.SimExtraStats = new SimExtraStatsCollector();
RegisterCommonCommands();
m_console.Commands.AddCommand("General", false, "quit",
"quit",
"Quit the application", HandleQuit);
RegisterCommonComponents(Config);
}
m_console.Commands.AddCommand("General", false, "shutdown",
"shutdown",
"Quit the application", HandleQuit);
protected override void ShutdownSpecific()
{
m_log.Info("[SHUTDOWN]: Shutdown processing on main thread complete. Exiting...");
RemovePIDFile();
base.ShutdownSpecific();
Environment.Exit(0);
}
/// <summary>
/// Should be overriden and referenced by descendents if they need to perform extra shutdown processing
/// </summary>
public virtual void ShutdownSpecific() {}
/// <summary>
/// Provides a list of help topics that are available. Overriding classes should append their topics to the
/// information returned when the base method is called.
@ -143,25 +140,8 @@ namespace OpenSim.Framework.Servers
timeTaken.Minutes, timeTaken.Seconds);
}
/// <summary>
/// Should be overriden and referenced by descendents if they need to perform extra shutdown processing
/// </summary>
public virtual void Shutdown()
public string osSecret
{
ShutdownSpecific();
m_log.Info("[SHUTDOWN]: Shutdown processing on main thread complete. Exiting...");
RemovePIDFile();
Environment.Exit(0);
}
private void HandleQuit(string module, string[] args)
{
Shutdown();
}
public string osSecret {
// Secret uuid for the simulator
get { return m_osSecret; }
}

View File

@ -54,7 +54,6 @@ namespace OpenSim.Framework.Servers.HttpServer
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private HttpServerLogWriter httpserverlog = new HttpServerLogWriter();
/// <summary>
/// This is a pending websocket request before it got an sucessful upgrade response.
/// The consumer must call handler.HandshakeAndUpgrade() to signal to the handler to
@ -81,6 +80,11 @@ namespace OpenSim.Framework.Servers.HttpServer
/// </remarks>
public int RequestNumber { get; private set; }
/// <summary>
/// Statistic for holding number of requests processed.
/// </summary>
private Stat m_requestsProcessedStat;
private volatile int NotSocketErrors = 0;
public volatile bool HTTPDRunning = false;
@ -436,9 +440,8 @@ namespace OpenSim.Framework.Servers.HttpServer
}
}
public void OnHandleRequestIOThread(IHttpClientContext context, IHttpRequest request)
private void OnHandleRequestIOThread(IHttpClientContext context, IHttpRequest request)
{
OSHttpRequest req = new OSHttpRequest(context, request);
WebSocketRequestDelegate dWebSocketRequestDelegate = null;
lock (m_WebSocketHandlers)
@ -454,8 +457,7 @@ namespace OpenSim.Framework.Servers.HttpServer
OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context);
resp.ReuseContext = true;
HandleRequest(req, resp);
HandleRequest(req, resp);
// !!!HACK ALERT!!!
// There seems to be a bug in the underlying http code that makes subsequent requests
@ -1824,6 +1826,21 @@ namespace OpenSim.Framework.Servers.HttpServer
// useful without inbound HTTP.
throw e;
}
m_requestsProcessedStat
= new Stat(
"HTTPRequestsServed",
"Number of inbound HTTP requests processed",
"",
"requests",
"httpserver",
Port.ToString(),
StatType.Pull,
MeasuresOfInterest.AverageChangeOverTime,
stat => stat.Value = RequestNumber,
StatVerbosity.Debug);
StatsManager.RegisterStat(m_requestsProcessedStat);
}
public void httpServerDisconnectMonitor(IHttpClientContext source, SocketError err)
@ -1854,6 +1871,9 @@ namespace OpenSim.Framework.Servers.HttpServer
public void Stop()
{
HTTPDRunning = false;
StatsManager.DeregisterStat(m_requestsProcessedStat);
try
{
m_PollServiceManager.Stop();

View File

@ -75,7 +75,7 @@ namespace OpenSim.Framework.Servers.HttpServer
/// <summary>
/// This is a regular HTTP Request... This may be removed in the future.
/// </summary>
public event RegularHttpRequestDelegate OnRegularHttpRequest;
// public event RegularHttpRequestDelegate OnRegularHttpRequest;
/// <summary>
/// When the upgrade from a HTTP request to a Websocket is completed, this will be fired
@ -304,15 +304,14 @@ namespace OpenSim.Framework.Servers.HttpServer
if (d != null)
d(this, new UpgradeCompletedEventArgs());
}
catch (IOException fail)
catch (IOException)
{
Close(string.Empty);
}
catch (ObjectDisposedException fail)
catch (ObjectDisposedException)
{
Close(string.Empty);
}
}
}
/// <summary>
@ -414,8 +413,6 @@ namespace OpenSim.Framework.Servers.HttpServer
_socketState.Header = pheader;
}
if (_socketState.FrameComplete)
{
ProcessFrame(_socketState);
@ -424,7 +421,6 @@ namespace OpenSim.Framework.Servers.HttpServer
_socketState.ExpectedBytes = 0;
}
}
}
else
@ -457,8 +453,7 @@ namespace OpenSim.Framework.Servers.HttpServer
_socketState.ReceivedBytes.Clear();
_socketState.ExpectedBytes = 0;
// do some processing
}
}
}
}
if (offset > 0)
@ -477,13 +472,12 @@ namespace OpenSim.Framework.Servers.HttpServer
{
// We can't read the stream anymore...
}
}
catch (IOException fail)
catch (IOException)
{
Close(string.Empty);
}
catch (ObjectDisposedException fail)
catch (ObjectDisposedException)
{
Close(string.Empty);
}

View File

@ -62,6 +62,8 @@ namespace OpenSim.Framework.Servers
protected string m_pidFile = String.Empty;
protected ServerStatsCollector m_serverStatsCollector;
/// <summary>
/// Server version information. Usually VersionInfo + information about git commit, operating system, etc.
/// </summary>
@ -259,6 +261,25 @@ namespace OpenSim.Framework.Servers
"force gc",
"Manually invoke runtime garbage collection. For debugging purposes",
HandleForceGc);
m_console.Commands.AddCommand(
"General", false, "quit",
"quit",
"Quit the application", (mod, args) => Shutdown());
m_console.Commands.AddCommand(
"General", false, "shutdown",
"shutdown",
"Quit the application", (mod, args) => Shutdown());
StatsManager.RegisterConsoleCommands(m_console);
}
public void RegisterCommonComponents(IConfigSource configSource)
{
m_serverStatsCollector = new ServerStatsCollector();
m_serverStatsCollector.Initialise(configSource);
m_serverStatsCollector.Start();
}
private void HandleForceGc(string module, string[] args)
@ -646,7 +667,68 @@ namespace OpenSim.Framework.Servers
sb.AppendFormat("Total threads active: {0}\n\n", totalThreads);
sb.Append("Main threadpool (excluding script engine pools)\n");
sb.Append(Util.GetThreadPoolReport());
sb.Append(GetThreadPoolReport());
return sb.ToString();
}
/// <summary>
/// Get a thread pool report.
/// </summary>
/// <returns></returns>
public static string GetThreadPoolReport()
{
string threadPoolUsed = null;
int maxThreads = 0;
int minThreads = 0;
int allocatedThreads = 0;
int inUseThreads = 0;
int waitingCallbacks = 0;
int completionPortThreads = 0;
StringBuilder sb = new StringBuilder();
if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
{
STPInfo stpi = Util.GetSmartThreadPoolInfo();
// ROBUST currently leaves this the FireAndForgetMethod but never actually initializes the threadpool.
if (stpi != null)
{
threadPoolUsed = "SmartThreadPool";
maxThreads = stpi.MaxThreads;
minThreads = stpi.MinThreads;
inUseThreads = stpi.InUseThreads;
allocatedThreads = stpi.ActiveThreads;
waitingCallbacks = stpi.WaitingCallbacks;
}
}
else if (
Util.FireAndForgetMethod == FireAndForgetMethod.QueueUserWorkItem
|| Util.FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem)
{
threadPoolUsed = "BuiltInThreadPool";
ThreadPool.GetMaxThreads(out maxThreads, out completionPortThreads);
ThreadPool.GetMinThreads(out minThreads, out completionPortThreads);
int availableThreads;
ThreadPool.GetAvailableThreads(out availableThreads, out completionPortThreads);
inUseThreads = maxThreads - availableThreads;
allocatedThreads = -1;
waitingCallbacks = -1;
}
if (threadPoolUsed != null)
{
sb.AppendFormat("Thread pool used : {0}\n", threadPoolUsed);
sb.AppendFormat("Max threads : {0}\n", maxThreads);
sb.AppendFormat("Min threads : {0}\n", minThreads);
sb.AppendFormat("Allocated threads : {0}\n", allocatedThreads < 0 ? "not applicable" : allocatedThreads.ToString());
sb.AppendFormat("In use threads : {0}\n", inUseThreads);
sb.AppendFormat("Work items waiting : {0}\n", waitingCallbacks < 0 ? "not available" : waitingCallbacks.ToString());
}
else
{
sb.AppendFormat("Thread pool not used\n");
}
return sb.ToString();
}
@ -698,5 +780,16 @@ namespace OpenSim.Framework.Servers
if (m_console != null)
m_console.OutputFormat(format, components);
}
public virtual void Shutdown()
{
m_serverStatsCollector.Close();
ShutdownSpecific();
}
/// <summary>
/// Should be overriden and referenced by descendents if they need to perform extra shutdown processing
/// </summary>
protected virtual void ShutdownSpecific() {}
}
}

View File

@ -88,10 +88,31 @@ namespace OpenSim.Framework
Thread,
}
/// <summary>
/// Class for delivering SmartThreadPool statistical information
/// </summary>
/// <remarks>
/// We do it this way so that we do not directly expose STP.
/// </remarks>
public class STPInfo
{
public string Name { get; set; }
public STPStartInfo STPStartInfo { get; set; }
public WIGStartInfo WIGStartInfo { get; set; }
public bool IsIdle { get; set; }
public bool IsShuttingDown { get; set; }
public int MaxThreads { get; set; }
public int MinThreads { get; set; }
public int InUseThreads { get; set; }
public int ActiveThreads { get; set; }
public int WaitingCallbacks { get; set; }
public int MaxConcurrentWorkItems { get; set; }
}
/// <summary>
/// Miscellaneous utility functions
/// </summary>
public class Util
public static class Util
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@ -1852,74 +1873,31 @@ namespace OpenSim.Framework
}
/// <summary>
/// Get a thread pool report.
/// Get information about the current state of the smart thread pool.
/// </summary>
/// <returns></returns>
public static string GetThreadPoolReport()
/// <returns>
/// null if this isn't the pool being used for non-scriptengine threads.
/// </returns>
public static STPInfo GetSmartThreadPoolInfo()
{
string threadPoolUsed = null;
int maxThreads = 0;
int minThreads = 0;
int allocatedThreads = 0;
int inUseThreads = 0;
int waitingCallbacks = 0;
int completionPortThreads = 0;
if (m_ThreadPool == null)
return null;
StringBuilder sb = new StringBuilder();
if (FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
{
// ROBUST currently leaves this the FireAndForgetMethod but never actually initializes the threadpool.
if (m_ThreadPool != null)
{
threadPoolUsed = "SmartThreadPool";
maxThreads = m_ThreadPool.MaxThreads;
minThreads = m_ThreadPool.MinThreads;
inUseThreads = m_ThreadPool.InUseThreads;
allocatedThreads = m_ThreadPool.ActiveThreads;
waitingCallbacks = m_ThreadPool.WaitingCallbacks;
}
}
else if (
FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem
|| FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem)
{
threadPoolUsed = "BuiltInThreadPool";
ThreadPool.GetMaxThreads(out maxThreads, out completionPortThreads);
ThreadPool.GetMinThreads(out minThreads, out completionPortThreads);
int availableThreads;
ThreadPool.GetAvailableThreads(out availableThreads, out completionPortThreads);
inUseThreads = maxThreads - availableThreads;
allocatedThreads = -1;
waitingCallbacks = -1;
}
STPInfo stpi = new STPInfo();
stpi.Name = m_ThreadPool.Name;
stpi.STPStartInfo = m_ThreadPool.STPStartInfo;
stpi.IsIdle = m_ThreadPool.IsIdle;
stpi.IsShuttingDown = m_ThreadPool.IsShuttingdown;
stpi.MaxThreads = m_ThreadPool.MaxThreads;
stpi.MinThreads = m_ThreadPool.MinThreads;
stpi.InUseThreads = m_ThreadPool.InUseThreads;
stpi.ActiveThreads = m_ThreadPool.ActiveThreads;
stpi.WaitingCallbacks = m_ThreadPool.WaitingCallbacks;
stpi.MaxConcurrentWorkItems = m_ThreadPool.Concurrency;
if (threadPoolUsed != null)
{
sb.AppendFormat("Thread pool used : {0}\n", threadPoolUsed);
sb.AppendFormat("Max threads : {0}\n", maxThreads);
sb.AppendFormat("Min threads : {0}\n", minThreads);
sb.AppendFormat("Allocated threads : {0}\n", allocatedThreads < 0 ? "not applicable" : allocatedThreads.ToString());
sb.AppendFormat("In use threads : {0}\n", inUseThreads);
sb.AppendFormat("Work items waiting : {0}\n", waitingCallbacks < 0 ? "not available" : waitingCallbacks.ToString());
}
else
{
sb.AppendFormat("Thread pool not used\n");
}
return sb.ToString();
return stpi;
}
// private static object SmartThreadPoolCallback(object o)
// {
// object[] array = (object[])o;
// WaitCallback callback = (WaitCallback)array[0];
// object obj = array[1];
//
// callback(obj);
// return null;
// }
#endregion FireAndForget Threading Pattern
/// <summary>

View File

@ -124,6 +124,7 @@ namespace OpenSim
workerThreads = workerThreadsMax;
m_log.InfoFormat("[OPENSIM MAIN]: Limiting worker threads to {0}",workerThreads);
}
// Increase the number of IOCP threads available.
// Mono defaults to a tragically low number (24 on 6-core / 8GB Fedora 17)
if (iocpThreads < iocpThreadsMin)

View File

@ -372,7 +372,7 @@ namespace OpenSim
"Unload a module", HandleModules);
}
public override void ShutdownSpecific()
protected override void ShutdownSpecific()
{
if (m_shutdownCommandsFile != String.Empty)
{

View File

@ -231,10 +231,7 @@ namespace OpenSim
}
if (m_console != null)
{
StatsManager.RegisterConsoleCommands(m_console);
AddPluginCommands(m_console);
}
}
protected virtual void AddPluginCommands(ICommandConsole console)
@ -880,7 +877,7 @@ namespace OpenSim
/// <summary>
/// Performs any last-minute sanity checking and shuts down the region server
/// </summary>
public override void ShutdownSpecific()
protected override void ShutdownSpecific()
{
if (proxyUrl.Length > 0)
{
@ -900,6 +897,8 @@ namespace OpenSim
{
m_log.Error("[SHUTDOWN]: Ignoring failure during shutdown - ", e);
}
base.ShutdownSpecific();
}
/// <summary>

View File

@ -34,6 +34,7 @@ using log4net;
using Nini.Config;
using Mono.Addins;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
using OpenSim.Framework.Monitoring;
using OpenSim.Framework.Servers;
@ -44,8 +45,6 @@ using OpenSim.Framework.Capabilities;
using OpenSim.Services.Interfaces;
using Caps = OpenSim.Framework.Capabilities.Caps;
using OpenSim.Capabilities.Handlers;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
namespace OpenSim.Region.ClientStack.Linden
{
@ -64,7 +63,7 @@ namespace OpenSim.Region.ClientStack.Linden
public List<UUID> folders;
}
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private Scene m_scene;

View File

@ -33,6 +33,7 @@ using NUnit.Framework;
using OpenMetaverse;
using OpenMetaverse.Packets;
using OpenSim.Framework;
using OpenSim.Framework.Monitoring;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Tests.Common;
using OpenSim.Tests.Common.Mock;
@ -69,6 +70,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
{
base.SetUp();
m_scene = new SceneHelpers().SetupScene();
StatsManager.SimExtraStats = new SimExtraStatsCollector();
}
/// <summary>
@ -210,8 +212,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
ScenePresence spAfterAckTimeout = m_scene.GetScenePresence(sp.UUID);
Assert.That(spAfterAckTimeout, Is.Null);
// TestHelpers.DisableLogging();
}
// /// <summary>

View File

@ -182,7 +182,10 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
"POST", m_RestURL + "/RetrieveMessages/", client.AgentId);
if (msglist == null)
{
m_log.WarnFormat("[OFFLINE MESSAGING]: WARNING null message list.");
return;
}
foreach (GridInstantMessage im in msglist)
{

View File

@ -53,8 +53,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private int m_levelHGTeleport = 0;
private string m_ThisHomeURI;
private GatekeeperServiceConnector m_GatekeeperConnector;
private IUserAgentService m_UAS;
protected bool m_RestrictAppearanceAbroad;
protected string m_AccountName;
@ -143,6 +145,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name);
}
}
moduleConfig = source.Configs["Hypergrid"];
if (moduleConfig != null)
{
m_ThisHomeURI = moduleConfig.GetString("HomeURI", string.Empty);
if (m_ThisHomeURI != string.Empty && !m_ThisHomeURI.EndsWith("/"))
m_ThisHomeURI += '/';
}
}
public override void AddRegion(Scene scene)
@ -194,7 +204,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
base.RegionLoaded(scene);
if (m_Enabled)
{
m_GatekeeperConnector = new GatekeeperServiceConnector(scene.AssetService);
m_UAS = scene.RequestModuleInterface<IUserAgentService>();
}
}
public override void RemoveRegion(Scene scene)
@ -272,8 +285,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (agentCircuit.ServiceURLs.ContainsKey("HomeURI"))
{
string userAgentDriver = agentCircuit.ServiceURLs["HomeURI"].ToString();
IUserAgentService connector = new UserAgentServiceConnector(userAgentDriver);
bool success = connector.LoginAgentToGrid(agentCircuit, reg, finalDestination, out reason);
IUserAgentService connector;
if (userAgentDriver.Equals(m_ThisHomeURI) && m_UAS != null)
connector = m_UAS;
else
connector = new UserAgentServiceConnector(userAgentDriver);
bool success = connector.LoginAgentToGrid(agentCircuit, reg, finalDestination, false, out reason);
logout = success; // flag for later logout from this grid; this is an HG TP
if (success)

View File

@ -194,7 +194,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
return false;
// Try local first
if (m_localBackend.IsLocalRegion(destination.RegionHandle))
if (m_localBackend.IsLocalRegion(destination.RegionID))
return m_localBackend.UpdateAgent(destination, cAgentData);
return m_remoteConnector.UpdateAgent(destination, cAgentData);
@ -206,7 +206,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
return false;
// Try local first
if (m_localBackend.IsLocalRegion(destination.RegionHandle))
if (m_localBackend.IsLocalRegion(destination.RegionID))
return m_localBackend.UpdateAgent(destination, cAgentData);
return m_remoteConnector.UpdateAgent(destination, cAgentData);
@ -224,7 +224,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
return true;
// else do the remote thing
if (!m_localBackend.IsLocalRegion(destination.RegionHandle))
if (!m_localBackend.IsLocalRegion(destination.RegionID))
return m_remoteConnector.RetrieveAgent(destination, id, out agent);
return false;
@ -273,7 +273,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
return true;
// else do the remote thing
if (!m_localBackend.IsLocalRegion(destination.RegionHandle))
if (!m_localBackend.IsLocalRegion(destination.RegionID))
return m_remoteConnector.CloseAgent(destination, id);
return false;
@ -296,7 +296,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
}
// else do the remote thing
if (!m_localBackend.IsLocalRegion(destination.RegionHandle))
if (!m_localBackend.IsLocalRegion(destination.RegionID))
return m_remoteConnector.CreateObject(destination, newPosition, sog, isLocalCall);
return false;

View File

@ -81,14 +81,14 @@ namespace OpenSim.Region.CoreModules.World.Land
set { m_landData = value; }
}
public IPrimCounts PrimCounts { get; set; }
public UUID RegionUUID
{
get { return m_scene.RegionInfo.RegionID; }
}
public Vector3 StartPoint
{
get
@ -101,11 +101,11 @@ namespace OpenSim.Region.CoreModules.World.Land
return new Vector3(x * 4, y * 4, 0);
}
}
return new Vector3(-1, -1, -1);
}
}
}
public Vector3 EndPoint
{
get
@ -116,15 +116,15 @@ namespace OpenSim.Region.CoreModules.World.Land
{
if (LandBitmap[x, y])
{
return new Vector3(x * 4, y * 4, 0);
}
return new Vector3(x * 4 + 4, y * 4 + 4, 0);
}
}
}
}
return new Vector3(-1, -1, -1);
}
}
#region Constructors
public LandObject(UUID owner_id, bool is_group_owned, Scene scene)

View File

@ -326,7 +326,7 @@ namespace OpenSim.Region.Framework.Scenes
// Update item with new asset
item.AssetID = asset.FullID;
if (group.UpdateInventoryItem(item))
remoteClient.SendAgentAlertMessage("Script saved", false);
remoteClient.SendAlertMessage("Script saved");
part.SendPropertiesToClient(remoteClient);
@ -342,7 +342,7 @@ namespace OpenSim.Region.Framework.Scenes
}
else
{
remoteClient.SendAgentAlertMessage("Script saved", false);
remoteClient.SendAlertMessage("Script saved");
}
// Tell anyone managing scripts that a script has been reloaded/changed
@ -1616,11 +1616,11 @@ namespace OpenSim.Region.Framework.Scenes
remoteClient, part, transactionID, currentItem);
if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
remoteClient.SendAgentAlertMessage("Notecard saved", false);
remoteClient.SendAlertMessage("Notecard saved");
else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
remoteClient.SendAgentAlertMessage("Script saved", false);
remoteClient.SendAlertMessage("Script saved");
else
remoteClient.SendAgentAlertMessage("Item saved", false);
remoteClient.SendAlertMessage("Item saved");
}
// Base ALWAYS has move

View File

@ -1,339 +0,0 @@
/*
* 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.Diagnostics;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading;
using log4net;
using Mono.Addins;
using Nini.Config;
using OpenSim.Framework;
using OpenSim.Framework.Console;
using OpenSim.Framework.Monitoring;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenMetaverse.StructuredData;
namespace OpenSim.Region.OptionalModules.Framework.Monitoring
{
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ServerStatistics")]
public class ServerStats : ISharedRegionModule
{
private readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private readonly string LogHeader = "[SERVER STATS]";
public bool Enabled = false;
private static Dictionary<string, Stat> RegisteredStats = new Dictionary<string, Stat>();
public readonly string CategoryServer = "server";
public readonly string ContainerProcessor = "processor";
public readonly string ContainerMemory = "memory";
public readonly string ContainerNetwork = "network";
public readonly string ContainerProcess = "process";
public string NetworkInterfaceTypes = "Ethernet";
readonly int performanceCounterSampleInterval = 500;
int lastperformanceCounterSampleTime = 0;
private class PerfCounterControl
{
public PerformanceCounter perfCounter;
public int lastFetch;
public string name;
public PerfCounterControl(PerformanceCounter pPc)
: this(pPc, String.Empty)
{
}
public PerfCounterControl(PerformanceCounter pPc, string pName)
{
perfCounter = pPc;
lastFetch = 0;
name = pName;
}
}
PerfCounterControl processorPercentPerfCounter = null;
#region ISharedRegionModule
// IRegionModuleBase.Name
public string Name { get { return "Server Stats"; } }
// IRegionModuleBase.ReplaceableInterface
public Type ReplaceableInterface { get { return null; } }
// IRegionModuleBase.Initialize
public void Initialise(IConfigSource source)
{
IConfig cfg = source.Configs["Monitoring"];
if (cfg != null)
Enabled = cfg.GetBoolean("ServerStatsEnabled", true);
if (Enabled)
{
NetworkInterfaceTypes = cfg.GetString("NetworkInterfaceTypes", "Ethernet");
}
}
// IRegionModuleBase.Close
public void Close()
{
if (RegisteredStats.Count > 0)
{
foreach (Stat stat in RegisteredStats.Values)
{
StatsManager.DeregisterStat(stat);
stat.Dispose();
}
RegisteredStats.Clear();
}
}
// IRegionModuleBase.AddRegion
public void AddRegion(Scene scene)
{
}
// IRegionModuleBase.RemoveRegion
public void RemoveRegion(Scene scene)
{
}
// IRegionModuleBase.RegionLoaded
public void RegionLoaded(Scene scene)
{
}
// ISharedRegionModule.PostInitialize
public void PostInitialise()
{
if (RegisteredStats.Count == 0)
{
RegisterServerStats();
}
}
#endregion ISharedRegionModule
private void MakeStat(string pName, string pDesc, string pUnit, string pContainer, Action<Stat> act)
{
string desc = pDesc;
if (desc == null)
desc = pName;
Stat stat = new Stat(pName, pName, desc, pUnit, CategoryServer, pContainer, StatType.Pull, act, StatVerbosity.Info);
StatsManager.RegisterStat(stat);
RegisteredStats.Add(pName, stat);
}
public void RegisterServerStats()
{
lastperformanceCounterSampleTime = Util.EnvironmentTickCount();
PerformanceCounter tempPC;
Stat tempStat;
string tempName;
try
{
tempName = "CPUPercent";
tempPC = new PerformanceCounter("Processor", "% Processor Time", "_Total");
processorPercentPerfCounter = new PerfCounterControl(tempPC);
// A long time bug in mono is that CPU percent is reported as CPU percent idle. Windows reports CPU percent busy.
tempStat = new Stat(tempName, tempName, "", "percent", CategoryServer, ContainerProcessor,
StatType.Pull, (s) => { GetNextValue(s, processorPercentPerfCounter, Util.IsWindows() ? 1 : -1); },
StatVerbosity.Info);
StatsManager.RegisterStat(tempStat);
RegisteredStats.Add(tempName, tempStat);
MakeStat("TotalProcessorTime", null, "sec", ContainerProcessor,
(s) => { s.Value = Process.GetCurrentProcess().TotalProcessorTime.TotalSeconds; });
MakeStat("UserProcessorTime", null, "sec", ContainerProcessor,
(s) => { s.Value = Process.GetCurrentProcess().UserProcessorTime.TotalSeconds; });
MakeStat("PrivilegedProcessorTime", null, "sec", ContainerProcessor,
(s) => { s.Value = Process.GetCurrentProcess().PrivilegedProcessorTime.TotalSeconds; });
MakeStat("Threads", null, "threads", ContainerProcessor,
(s) => { s.Value = Process.GetCurrentProcess().Threads.Count; });
}
catch (Exception e)
{
m_log.ErrorFormat("{0} Exception creating 'Process': {1}", LogHeader, e);
}
try
{
List<string> okInterfaceTypes = new List<string>(NetworkInterfaceTypes.Split(','));
IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces();
foreach (NetworkInterface nic in nics)
{
if (nic.OperationalStatus != OperationalStatus.Up)
continue;
string nicInterfaceType = nic.NetworkInterfaceType.ToString();
if (!okInterfaceTypes.Contains(nicInterfaceType))
{
m_log.DebugFormat("{0} Not including stats for network interface '{1}' of type '{2}'.",
LogHeader, nic.Name, nicInterfaceType);
m_log.DebugFormat("{0} To include, add to comma separated list in [Monitoring]NetworkInterfaceTypes={1}",
LogHeader, NetworkInterfaceTypes);
continue;
}
if (nic.Supports(NetworkInterfaceComponent.IPv4))
{
IPv4InterfaceStatistics nicStats = nic.GetIPv4Statistics();
if (nicStats != null)
{
MakeStat("BytesRcvd/" + nic.Name, nic.Name, "KB", ContainerNetwork,
(s) => { LookupNic(s, (ns) => { return ns.BytesReceived; }, 1024.0); });
MakeStat("BytesSent/" + nic.Name, nic.Name, "KB", ContainerNetwork,
(s) => { LookupNic(s, (ns) => { return ns.BytesSent; }, 1024.0); });
MakeStat("TotalBytes/" + nic.Name, nic.Name, "KB", ContainerNetwork,
(s) => { LookupNic(s, (ns) => { return ns.BytesSent + ns.BytesReceived; }, 1024.0); });
}
}
// TODO: add IPv6 (it may actually happen someday)
}
}
catch (Exception e)
{
m_log.ErrorFormat("{0} Exception creating 'Network Interface': {1}", LogHeader, e);
}
MakeStat("ProcessMemory", null, "MB", ContainerMemory,
(s) => { s.Value = Process.GetCurrentProcess().WorkingSet64 / 1024d / 1024d; });
MakeStat("ObjectMemory", null, "MB", ContainerMemory,
(s) => { s.Value = GC.GetTotalMemory(false) / 1024d / 1024d; });
MakeStat("LastMemoryChurn", null, "MB/sec", ContainerMemory,
(s) => { s.Value = Math.Round(MemoryWatchdog.LastMemoryChurn * 1000d / 1024d / 1024d, 3); });
MakeStat("AverageMemoryChurn", null, "MB/sec", ContainerMemory,
(s) => { s.Value = Math.Round(MemoryWatchdog.AverageMemoryChurn * 1000d / 1024d / 1024d, 3); });
}
// Notes on performance counters:
// "How To Read Performance Counters": http://blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx
// "How to get the CPU Usage in C#": http://stackoverflow.com/questions/278071/how-to-get-the-cpu-usage-in-c
// "Mono Performance Counters": http://www.mono-project.com/Mono_Performance_Counters
private delegate double PerfCounterNextValue();
private void GetNextValue(Stat stat, PerfCounterControl perfControl)
{
GetNextValue(stat, perfControl, 1.0);
}
private void GetNextValue(Stat stat, PerfCounterControl perfControl, double factor)
{
if (Util.EnvironmentTickCountSubtract(perfControl.lastFetch) > performanceCounterSampleInterval)
{
if (perfControl != null && perfControl.perfCounter != null)
{
try
{
// Kludge for factor to run double duty. If -1, subtract the value from one
if (factor == -1)
stat.Value = 1 - perfControl.perfCounter.NextValue();
else
stat.Value = perfControl.perfCounter.NextValue() / factor;
}
catch (Exception e)
{
m_log.ErrorFormat("{0} Exception on NextValue fetching {1}: {2}", LogHeader, stat.Name, e);
}
perfControl.lastFetch = Util.EnvironmentTickCount();
}
}
}
// Lookup the nic that goes with this stat and set the value by using a fetch action.
// Not sure about closure with delegates inside delegates.
private delegate double GetIPv4StatValue(IPv4InterfaceStatistics interfaceStat);
private void LookupNic(Stat stat, GetIPv4StatValue getter, double factor)
{
// Get the one nic that has the name of this stat
IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces().Where(
(network) => network.Name == stat.Description);
try
{
foreach (NetworkInterface nic in nics)
{
IPv4InterfaceStatistics intrStats = nic.GetIPv4Statistics();
if (intrStats != null)
{
double newVal = Math.Round(getter(intrStats) / factor, 3);
stat.Value = newVal;
}
break;
}
}
catch
{
// There are times interfaces go away so we just won't update the stat for this
m_log.ErrorFormat("{0} Exception fetching stat on interface '{1}'", LogHeader, stat.Description);
}
}
}
public class ServerStatsAggregator : Stat
{
public ServerStatsAggregator(
string shortName,
string name,
string description,
string unitName,
string category,
string container
)
: base(
shortName,
name,
description,
unitName,
category,
container,
StatType.Push,
MeasuresOfInterest.None,
null,
StatVerbosity.Info)
{
}
public override string ToConsoleString()
{
StringBuilder sb = new StringBuilder();
return sb.ToString();
}
public override OSDMap ToOSDMap()
{
OSDMap ret = new OSDMap();
return ret;
}
}
}

View File

@ -43,8 +43,14 @@ public class BSActorAvatarMove : BSActor
// Set to true if we think we're going up stairs.
// This state is remembered because collisions will turn on and off as we go up stairs.
int m_walkingUpStairs;
// The amount the step up is applying. Used to smooth stair walking.
float m_lastStepUp;
// Jumping happens over several frames. If use applies up force while colliding, start the
// jump and allow the jump to continue for this number of frames.
int m_jumpFrames = 0;
float m_jumpVelocity = 0f;
public BSActorAvatarMove(BSScene physicsScene, BSPhysObject pObj, string actorName)
: base(physicsScene, pObj, actorName)
{
@ -206,17 +212,45 @@ public class BSActorAvatarMove : BSActor
if (m_controllingPrim.Friction != BSParam.AvatarFriction)
{
// Probably starting up walking. Set friction to moving friction.
// Probably starting to walk. Set friction to moving friction.
m_controllingPrim.Friction = BSParam.AvatarFriction;
m_physicsScene.PE.SetFriction(m_controllingPrim.PhysBody, m_controllingPrim.Friction);
}
// If falling, we keep the world's downward vector no matter what the other axis specify.
// The check for RawVelocity.Z < 0 makes jumping work (temporary upward force).
if (!m_controllingPrim.Flying && !m_controllingPrim.IsColliding)
{
if (m_controllingPrim.RawVelocity.Z < 0)
stepVelocity.Z = m_controllingPrim.RawVelocity.Z;
}
// Colliding and not flying with an upward force. The avatar must be trying to jump.
if (!m_controllingPrim.Flying && m_controllingPrim.IsColliding && stepVelocity.Z > 0)
{
// We allow the upward force to happen for this many frames.
m_jumpFrames = BSParam.AvatarJumpFrames;
m_jumpVelocity = stepVelocity.Z;
}
// The case where the avatar is not colliding and is not flying is special.
// The avatar is either falling or jumping and the user can be applying force to the avatar
// (force in some direction or force up or down).
// If the avatar has negative Z velocity and is not colliding, presume we're falling and keep the velocity.
// If the user is trying to apply upward force but we're not colliding, assume the avatar
// is trying to jump and don't apply the upward force if not touching the ground any more.
if (!m_controllingPrim.Flying && !m_controllingPrim.IsColliding)
{
// If upward velocity is being applied, this must be a jump and only allow that to go on so long
if (m_jumpFrames > 0)
{
// Since not touching the ground, only apply upward force for so long.
m_jumpFrames--;
stepVelocity.Z = m_jumpVelocity;
}
else
{
// Since we're not affected by anything, whatever vertical motion the avatar has, continue that.
stepVelocity.Z = m_controllingPrim.RawVelocity.Z;
}
// DetailLog("{0},BSCharacter.MoveMotor,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity);
}
@ -241,7 +275,7 @@ public class BSActorAvatarMove : BSActor
m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4},avHeight={5}",
m_controllingPrim.LocalID, m_controllingPrim.IsColliding, m_controllingPrim.Flying,
m_controllingPrim.TargetVelocitySpeed, m_controllingPrim.CollisionsLastTick.Count, m_controllingPrim.Size.Z);
// This test is done if moving forward, not flying and is colliding with something.
// Check for stairs climbing if colliding, not flying and moving forward
if ( m_controllingPrim.IsColliding
&& !m_controllingPrim.Flying

View File

@ -209,7 +209,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
m_VhoverTimescale = Math.Max(pValue, 0.01f);
break;
case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
m_linearDeflectionEfficiency = Math.Max(pValue, 0.01f);
m_linearDeflectionEfficiency = ClampInRange(0f, pValue, 1f);
break;
case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
m_linearDeflectionTimescale = Math.Max(pValue, 0.01f);
@ -707,7 +707,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
private Vector3 m_knownRotationalVelocity;
private Vector3 m_knownRotationalForce;
private Vector3 m_knownRotationalImpulse;
private Vector3 m_knownForwardVelocity; // vehicle relative forward speed
private const int m_knownChangedPosition = 1 << 0;
private const int m_knownChangedVelocity = 1 << 1;
@ -719,7 +718,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
private const int m_knownChangedRotationalImpulse = 1 << 7;
private const int m_knownChangedTerrainHeight = 1 << 8;
private const int m_knownChangedWaterLevel = 1 << 9;
private const int m_knownChangedForwardVelocity = 1 <<10;
public void ForgetKnownVehicleProperties()
{
@ -923,12 +921,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
{
get
{
if ((m_knownHas & m_knownChangedForwardVelocity) == 0)
{
m_knownForwardVelocity = VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation));
m_knownHas |= m_knownChangedForwardVelocity;
}
return m_knownForwardVelocity;
return VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation));
}
}
private float VehicleForwardSpeed
@ -981,6 +974,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
{
ComputeLinearVelocity(pTimestep);
ComputeLinearDeflection(pTimestep);
ComputeLinearTerrainHeightCorrection(pTimestep);
ComputeLinearHover(pTimestep);
@ -1026,12 +1021,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
{
// Step the motor from the current value. Get the correction needed this step.
Vector3 origVelW = VehicleVelocity; // DEBUG
Vector3 currentVelV = VehicleVelocity * Quaternion.Inverse(VehicleOrientation);
Vector3 currentVelV = VehicleForwardVelocity;
Vector3 linearMotorCorrectionV = m_linearMotor.Step(pTimestep, currentVelV);
// Friction reduces vehicle motion
Vector3 frictionFactorW = ComputeFrictionFactor(m_linearFrictionTimescale, pTimestep);
linearMotorCorrectionV -= (currentVelV * frictionFactorW);
// Friction reduces vehicle motion based on absolute speed. Slow vehicle down by friction.
Vector3 frictionFactorV = ComputeFrictionFactor(m_linearFrictionTimescale, pTimestep);
linearMotorCorrectionV -= (currentVelV * frictionFactorV);
// Motor is vehicle coordinates. Rotate it to world coordinates
Vector3 linearMotorVelocityW = linearMotorCorrectionV * VehicleOrientation;
@ -1046,11 +1041,38 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// Add this correction to the velocity to make it faster/slower.
VehicleVelocity += linearMotorVelocityW;
VDetailLog("{0}, MoveLinear,velocity,origVelW={1},velV={2},correctV={3},correctW={4},newVelW={5},fricFact={6}",
ControllingPrim.LocalID, origVelW, currentVelV, linearMotorCorrectionV,
linearMotorVelocityW, VehicleVelocity, frictionFactorW);
linearMotorVelocityW, VehicleVelocity, frictionFactorV);
}
//Given a Deflection Effiency and a Velocity, Returns a Velocity that is Partially Deflected onto the X Axis
//Clamped so that a DeflectionTimescale of less then 1 does not increase force over original velocity
private void ComputeLinearDeflection(float pTimestep)
{
Vector3 linearDeflectionV = Vector3.Zero;
Vector3 velocityV = VehicleForwardVelocity;
// Velocity in Y and Z dimensions is movement to the side or turning.
// Compute deflection factor from the to the side and rotational velocity
linearDeflectionV.Y = SortedClampInRange(0, (velocityV.Y * m_linearDeflectionEfficiency) / m_linearDeflectionTimescale, velocityV.Y);
linearDeflectionV.Z = SortedClampInRange(0, (velocityV.Z * m_linearDeflectionEfficiency) / m_linearDeflectionTimescale, velocityV.Z);
// Velocity to the side and around is corrected and moved into the forward direction
linearDeflectionV.X += Math.Abs(linearDeflectionV.Y);
linearDeflectionV.X += Math.Abs(linearDeflectionV.Z);
// Scale the deflection to the fractional simulation time
linearDeflectionV *= pTimestep;
// Subtract the sideways and rotational velocity deflection factors while adding the correction forward
linearDeflectionV *= new Vector3(1,-1,-1);
// Correciont is vehicle relative. Convert to world coordinates and add to the velocity
VehicleVelocity += linearDeflectionV * VehicleOrientation;
VDetailLog("{0}, MoveLinear,LinearDeflection,linDefEff={1},linDefTS={2},linDeflectionV={3}",
ControllingPrim.LocalID, m_linearDeflectionEfficiency, m_linearDeflectionTimescale, linearDeflectionV);
}
public void ComputeLinearTerrainHeightCorrection(float pTimestep)
@ -1652,6 +1674,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin
return frictionFactor;
}
private float SortedClampInRange(float clampa, float val, float clampb)
{
if (clampa > clampb)
{
float temp = clampa;
clampa = clampb;
clampb = temp;
}
return ClampInRange(clampa, val, clampb);
}
private float ClampInRange(float low, float val, float high)
{
return Math.Max(low, Math.Min(val, high));

View File

@ -134,6 +134,7 @@ public static class BSParam
public static float AvatarHeightMidFudge { get; private set; }
public static float AvatarHeightHighFudge { get; private set; }
public static float AvatarContactProcessingThreshold { get; private set; }
public static int AvatarJumpFrames { get; private set; }
public static float AvatarBelowGroundUpCorrectionMeters { get; private set; }
public static float AvatarStepHeight { get; private set; }
public static float AvatarStepApproachFactor { get; private set; }
@ -567,6 +568,8 @@ public static class BSParam
0.1f ),
new ParameterDefn<float>("AvatarBelowGroundUpCorrectionMeters", "Meters to move avatar up if it seems to be below ground",
1.0f ),
new ParameterDefn<int>("AvatarJumpFrames", "Number of frames to allow jump forces. Changes jump height.",
4 ),
new ParameterDefn<float>("AvatarStepHeight", "Height of a step obstacle to consider step correction",
0.6f ) ,
new ParameterDefn<float>("AvatarStepApproachFactor", "Factor to control angle of approach to step (0=straight on)",

View File

@ -34,6 +34,7 @@ using System.Text;
using System.Xml;
using OpenSim.Framework;
using OpenSim.Framework.Console;
using OpenSim.Framework.Monitoring;
using OpenSim.Framework.Servers;
using log4net;
using log4net.Config;
@ -190,16 +191,7 @@ namespace OpenSim.Server.Base
}
RegisterCommonCommands();
// Register the quit command
//
MainConsole.Instance.Commands.AddCommand("General", false, "quit",
"quit",
"Quit the application", HandleQuit);
MainConsole.Instance.Commands.AddCommand("General", false, "shutdown",
"shutdown",
"Quit the application", HandleQuit);
RegisterCommonComponents(Config);
// Allow derived classes to perform initialization that
// needs to be done after the console has opened
@ -214,6 +206,9 @@ namespace OpenSim.Server.Base
public virtual int Run()
{
Watchdog.Enabled = true;
MemoryWatchdog.Enabled = true;
while (m_Running)
{
try
@ -231,11 +226,12 @@ namespace OpenSim.Server.Base
return 0;
}
protected virtual void HandleQuit(string module, string[] args)
protected override void ShutdownSpecific()
{
m_Running = false;
m_log.Info("[CONSOLE] Quitting");
base.ShutdownSpecific();
}
protected virtual void ReadConfig()
@ -246,4 +242,4 @@ namespace OpenSim.Server.Base
{
}
}
}
}

View File

@ -61,7 +61,7 @@ namespace OpenSim.Server.Handlers.Hypergrid
m_Proxy = proxy;
}
protected override bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, out string reason)
protected override bool CreateAgent(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, out string reason)
{
return m_GatekeeperService.LoginAgent(aCircuit, destination, out reason);
}

View File

@ -49,191 +49,87 @@ using log4net;
namespace OpenSim.Server.Handlers.Hypergrid
{
public class HomeAgentHandler
public class HomeAgentHandler : AgentPostHandler
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private IUserAgentService m_UserAgentService;
private string m_LoginServerIP;
private bool m_Proxy = false;
public HomeAgentHandler(IUserAgentService userAgentService, string loginServerIP, bool proxy)
public HomeAgentHandler(IUserAgentService userAgentService, string loginServerIP, bool proxy) :
base("/homeagent")
{
m_UserAgentService = userAgentService;
m_LoginServerIP = loginServerIP;
m_Proxy = proxy;
}
public Hashtable Handler(Hashtable request)
protected override AgentDestinationData CreateAgentDestinationData()
{
// m_log.Debug("[CONNECTION DEBUGGING]: HomeAgentHandler Called");
//
// m_log.Debug("---------------------------");
// m_log.Debug(" >> uri=" + request["uri"]);
// m_log.Debug(" >> content-type=" + request["content-type"]);
// m_log.Debug(" >> http-method=" + request["http-method"]);
// m_log.Debug("---------------------------\n");
Hashtable responsedata = new Hashtable();
responsedata["content_type"] = "text/html";
responsedata["keepalive"] = false;
UUID agentID;
UUID regionID;
string action;
if (!Utils.GetParams((string)request["uri"], out agentID, out regionID, out action))
{
m_log.InfoFormat("[HOME AGENT HANDLER]: Invalid parameters for agent message {0}", request["uri"]);
responsedata["int_response_code"] = 404;
responsedata["str_response_string"] = "false";
return responsedata;
}
// Next, let's parse the verb
string method = (string)request["http-method"];
if (method.Equals("POST"))
{
DoAgentPost(request, responsedata, agentID);
return responsedata;
}
else
{
m_log.InfoFormat("[HOME AGENT HANDLER]: method {0} not supported in agent message", method);
responsedata["int_response_code"] = HttpStatusCode.MethodNotAllowed;
responsedata["str_response_string"] = "Method not allowed";
return responsedata;
}
return new ExtendedAgentDestinationData();
}
protected void DoAgentPost(Hashtable request, Hashtable responsedata, UUID id)
protected override void UnpackData(OSDMap args, AgentDestinationData d, Hashtable request)
{
OSDMap args = Utils.GetOSDMap((string)request["body"]);
if (args == null)
{
responsedata["int_response_code"] = HttpStatusCode.BadRequest;
responsedata["str_response_string"] = "Bad request";
return;
}
// retrieve the input arguments
int x = 0, y = 0;
UUID uuid = UUID.Zero;
string regionname = string.Empty;
string gatekeeper_host = string.Empty;
string gatekeeper_serveruri = string.Empty;
string destination_serveruri = string.Empty;
int gatekeeper_port = 0;
IPEndPoint client_ipaddress = null;
if (args.ContainsKey("gatekeeper_host") && args["gatekeeper_host"] != null)
gatekeeper_host = args["gatekeeper_host"].AsString();
if (args.ContainsKey("gatekeeper_port") && args["gatekeeper_port"] != null)
Int32.TryParse(args["gatekeeper_port"].AsString(), out gatekeeper_port);
if (args.ContainsKey("gatekeeper_serveruri") && args["gatekeeper_serveruri"] !=null)
gatekeeper_serveruri = args["gatekeeper_serveruri"];
if (args.ContainsKey("destination_serveruri") && args["destination_serveruri"] !=null)
destination_serveruri = args["destination_serveruri"];
GridRegion gatekeeper = new GridRegion();
gatekeeper.ServerURI = gatekeeper_serveruri;
gatekeeper.ExternalHostName = gatekeeper_host;
gatekeeper.HttpPort = (uint)gatekeeper_port;
gatekeeper.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 0);
if (args.ContainsKey("destination_x") && args["destination_x"] != null)
Int32.TryParse(args["destination_x"].AsString(), out x);
else
m_log.WarnFormat(" -- request didn't have destination_x");
if (args.ContainsKey("destination_y") && args["destination_y"] != null)
Int32.TryParse(args["destination_y"].AsString(), out y);
else
m_log.WarnFormat(" -- request didn't have destination_y");
if (args.ContainsKey("destination_uuid") && args["destination_uuid"] != null)
UUID.TryParse(args["destination_uuid"].AsString(), out uuid);
if (args.ContainsKey("destination_name") && args["destination_name"] != null)
regionname = args["destination_name"].ToString();
if (args.ContainsKey("client_ip") && args["client_ip"] != null)
{
string ip_str = args["client_ip"].ToString();
try
{
string callerIP = GetCallerIP(request);
// Verify if this caller has authority to send the client IP
if (callerIP == m_LoginServerIP)
client_ipaddress = new IPEndPoint(IPAddress.Parse(ip_str), 0);
else // leaving this for now, but this warning should be removed
m_log.WarnFormat("[HOME AGENT HANDLER]: Unauthorized machine {0} tried to set client ip to {1}", callerIP, ip_str);
}
catch
{
m_log.DebugFormat("[HOME AGENT HANDLER]: Exception parsing client ip address from {0}", ip_str);
}
}
GridRegion destination = new GridRegion();
destination.RegionID = uuid;
destination.RegionLocX = x;
destination.RegionLocY = y;
destination.RegionName = regionname;
destination.ServerURI = destination_serveruri;
AgentCircuitData aCircuit = new AgentCircuitData();
base.UnpackData(args, d, request);
ExtendedAgentDestinationData data = (ExtendedAgentDestinationData)d;
try
{
aCircuit.UnpackAgentCircuitData(args);
if (args.ContainsKey("gatekeeper_host") && args["gatekeeper_host"] != null)
data.host = args["gatekeeper_host"].AsString();
if (args.ContainsKey("gatekeeper_port") && args["gatekeeper_port"] != null)
Int32.TryParse(args["gatekeeper_port"].AsString(), out data.port);
if (args.ContainsKey("gatekeeper_serveruri") && args["gatekeeper_serveruri"] != null)
data.gatekeeperServerURI = args["gatekeeper_serveruri"];
if (args.ContainsKey("destination_serveruri") && args["destination_serveruri"] != null)
data.destinationServerURI = args["destination_serveruri"];
}
catch (Exception ex)
catch (InvalidCastException e)
{
m_log.InfoFormat("[HOME AGENT HANDLER]: exception on unpacking ChildCreate message {0}", ex.Message);
responsedata["int_response_code"] = HttpStatusCode.BadRequest;
responsedata["str_response_string"] = "Bad request";
return;
m_log.ErrorFormat("[HOME AGENT HANDLER]: Bad cast in UnpackData");
}
OSDMap resp = new OSDMap(2);
string reason = String.Empty;
string callerIP = GetCallerIP(request);
// Verify if this call came from the login server
if (callerIP == m_LoginServerIP)
data.fromLogin = true;
bool result = m_UserAgentService.LoginAgentToGrid(aCircuit, gatekeeper, destination, client_ipaddress, out reason);
resp["reason"] = OSD.FromString(reason);
resp["success"] = OSD.FromBoolean(result);
// TODO: add reason if not String.Empty?
responsedata["int_response_code"] = HttpStatusCode.OK;
responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp);
}
private string GetCallerIP(Hashtable request)
protected override GridRegion ExtractGatekeeper(AgentDestinationData d)
{
if (!m_Proxy)
return Util.GetCallerIP(request);
// We're behind a proxy
Hashtable headers = (Hashtable)request["headers"];
string xff = "X-Forwarded-For";
if (headers.ContainsKey(xff.ToLower()))
xff = xff.ToLower();
if (!headers.ContainsKey(xff) || headers[xff] == null)
if (d is ExtendedAgentDestinationData)
{
m_log.WarnFormat("[AGENT HANDLER]: No XFF header");
return Util.GetCallerIP(request);
ExtendedAgentDestinationData data = (ExtendedAgentDestinationData)d;
GridRegion gatekeeper = new GridRegion();
gatekeeper.ServerURI = data.gatekeeperServerURI;
gatekeeper.ExternalHostName = data.host;
gatekeeper.HttpPort = (uint)data.port;
gatekeeper.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 0);
return gatekeeper;
}
else
m_log.WarnFormat("[HOME AGENT HANDLER]: Wrong data type");
m_log.DebugFormat("[AGENT HANDLER]: XFF is {0}", headers[xff]);
IPEndPoint ep = Util.GetClientIPFromXFF((string)headers[xff]);
if (ep != null)
return ep.Address.ToString();
// Oops
return Util.GetCallerIP(request);
return null;
}
protected override bool CreateAgent(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, out string reason)
{
return m_UserAgentService.LoginAgentToGrid(aCircuit, gatekeeper, destination, fromLogin, out reason);
}
}
public class ExtendedAgentDestinationData : AgentDestinationData
{
public string host;
public int port;
public string gatekeeperServerURI;
public string destinationServerURI;
}
}

View File

@ -108,7 +108,7 @@ namespace OpenSim.Server.Handlers.Hypergrid
server.AddXmlRPCHandler("get_uui", GetUUI, false);
server.AddXmlRPCHandler("get_uuid", GetUUID, false);
server.AddHTTPHandler("/homeagent/", new HomeAgentHandler(m_HomeUsersService, loginServerIP, proxy).Handler);
server.AddStreamHandler(new HomeAgentHandler(m_HomeUsersService, loginServerIP, proxy));
}
public XmlRpcResponse GetHomeRegion(XmlRpcRequest request, IPEndPoint remoteClient)

View File

@ -328,31 +328,16 @@ namespace OpenSim.Server.Handlers.Simulation
return;
}
// retrieve the input arguments
int x = 0, y = 0;
UUID uuid = UUID.Zero;
string regionname = string.Empty;
uint teleportFlags = 0;
if (args.ContainsKey("destination_x") && args["destination_x"] != null)
Int32.TryParse(args["destination_x"].AsString(), out x);
else
m_log.WarnFormat(" -- request didn't have destination_x");
if (args.ContainsKey("destination_y") && args["destination_y"] != null)
Int32.TryParse(args["destination_y"].AsString(), out y);
else
m_log.WarnFormat(" -- request didn't have destination_y");
if (args.ContainsKey("destination_uuid") && args["destination_uuid"] != null)
UUID.TryParse(args["destination_uuid"].AsString(), out uuid);
if (args.ContainsKey("destination_name") && args["destination_name"] != null)
regionname = args["destination_name"].ToString();
if (args.ContainsKey("teleport_flags") && args["teleport_flags"] != null)
teleportFlags = args["teleport_flags"].AsUInteger();
AgentDestinationData data = CreateAgentDestinationData();
UnpackData(args, data, request);
GridRegion destination = new GridRegion();
destination.RegionID = uuid;
destination.RegionLocX = x;
destination.RegionLocY = y;
destination.RegionName = regionname;
destination.RegionID = data.uuid;
destination.RegionLocX = data.x;
destination.RegionLocY = data.y;
destination.RegionName = data.name;
GridRegion gatekeeper = ExtractGatekeeper(data);
AgentCircuitData aCircuit = new AgentCircuitData();
try
@ -373,7 +358,7 @@ namespace OpenSim.Server.Handlers.Simulation
// This is the meaning of POST agent
//m_regionClient.AdjustUserInformation(aCircuit);
//bool result = m_SimulationService.CreateAgent(destination, aCircuit, teleportFlags, out reason);
bool result = CreateAgent(destination, aCircuit, teleportFlags, out reason);
bool result = CreateAgent(gatekeeper, destination, aCircuit, data.flags, data.fromLogin, out reason);
resp["reason"] = OSD.FromString(reason);
resp["success"] = OSD.FromBoolean(result);
@ -385,7 +370,36 @@ namespace OpenSim.Server.Handlers.Simulation
responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp);
}
private string GetCallerIP(Hashtable request)
protected virtual AgentDestinationData CreateAgentDestinationData()
{
return new AgentDestinationData();
}
protected virtual void UnpackData(OSDMap args, AgentDestinationData data, Hashtable request)
{
// retrieve the input arguments
if (args.ContainsKey("destination_x") && args["destination_x"] != null)
Int32.TryParse(args["destination_x"].AsString(), out data.x);
else
m_log.WarnFormat(" -- request didn't have destination_x");
if (args.ContainsKey("destination_y") && args["destination_y"] != null)
Int32.TryParse(args["destination_y"].AsString(), out data.y);
else
m_log.WarnFormat(" -- request didn't have destination_y");
if (args.ContainsKey("destination_uuid") && args["destination_uuid"] != null)
UUID.TryParse(args["destination_uuid"].AsString(), out data.uuid);
if (args.ContainsKey("destination_name") && args["destination_name"] != null)
data.name = args["destination_name"].ToString();
if (args.ContainsKey("teleport_flags") && args["teleport_flags"] != null)
data.flags = args["teleport_flags"].AsUInteger();
}
protected virtual GridRegion ExtractGatekeeper(AgentDestinationData data)
{
return null;
}
protected string GetCallerIP(Hashtable request)
{
if (!m_Proxy)
return Util.GetCallerIP(request);
@ -418,7 +432,7 @@ namespace OpenSim.Server.Handlers.Simulation
}
// subclasses can override this
protected virtual bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, out string reason)
protected virtual bool CreateAgent(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, out string reason)
{
return m_SimulationService.CreateAgent(destination, aCircuit, teleportFlags, out reason);
}
@ -562,7 +576,6 @@ namespace OpenSim.Server.Handlers.Simulation
//agent.Dump();
// This is one of the meanings of PUT agent
result = UpdateAgent(destination, agent);
}
else if ("AgentPosition".Equals(messageType))
{
@ -593,4 +606,14 @@ namespace OpenSim.Server.Handlers.Simulation
return m_SimulationService.UpdateAgent(destination, agent);
}
}
public class AgentDestinationData
{
public int x;
public int y;
public string name;
public UUID uuid;
public uint flags;
public bool fromLogin;
}
}

View File

@ -53,7 +53,8 @@ namespace OpenSim.Services.Connectors.Hypergrid
private IAssetService m_AssetService;
public GatekeeperServiceConnector() : base()
public GatekeeperServiceConnector()
: base()
{
}
@ -123,11 +124,13 @@ namespace OpenSim.Services.Connectors.Hypergrid
realHandle = Convert.ToUInt64((string)hash["handle"]);
//m_log.Debug(">> HERE, realHandle: " + realHandle);
}
if (hash["region_image"] != null) {
if (hash["region_image"] != null)
{
imageURL = (string)hash["region_image"];
//m_log.Debug(">> HERE, imageURL: " + imageURL);
}
if (hash["external_name"] != null) {
if (hash["external_name"] != null)
{
externalName = (string)hash["external_name"];
//m_log.Debug(">> HERE, externalName: " + externalName);
}
@ -178,7 +181,7 @@ namespace OpenSim.Services.Connectors.Hypergrid
//m_log.Debug("Size: " + m.PhysicalDimension.Height + "-" + m.PhysicalDimension.Width);
imageData = OpenJPEG.EncodeFromImage(bitmap, true);
}
AssetBase ass = new AssetBase(UUID.Random(), "region " + name, (sbyte)AssetType.Texture, regionID.ToString());
// !!! for now
@ -257,7 +260,8 @@ namespace OpenSim.Services.Connectors.Hypergrid
region.RegionName = (string)hash["region_name"];
//m_log.Debug(">> HERE, region_name: " + region.RegionName);
}
if (hash["hostname"] != null) {
if (hash["hostname"] != null)
{
region.ExternalHostName = (string)hash["hostname"];
//m_log.Debug(">> HERE, hostname: " + region.ExternalHostName);
}
@ -275,10 +279,10 @@ namespace OpenSim.Services.Connectors.Hypergrid
region.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), p);
//m_log.Debug(">> HERE, internal_port: " + region.InternalEndPoint);
}
if (hash["server_uri"] != null)
{
region.ServerURI = (string) hash["server_uri"];
region.ServerURI = (string)hash["server_uri"];
//m_log.Debug(">> HERE, server_uri: " + region.ServerURI);
}
@ -295,55 +299,5 @@ namespace OpenSim.Services.Connectors.Hypergrid
return null;
}
public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string myipaddress, out string reason)
{
// m_log.DebugFormat("[GATEKEEPER SERVICE CONNECTOR]: CreateAgent start");
myipaddress = String.Empty;
reason = String.Empty;
if (destination == null)
{
m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: Given destination is null");
return false;
}
string uri = destination.ServerURI + AgentPath() + aCircuit.AgentID + "/";
try
{
OSDMap args = aCircuit.PackAgentCircuitData();
args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString());
args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString());
args["destination_name"] = OSD.FromString(destination.RegionName);
args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString());
args["teleport_flags"] = OSD.FromString(flags.ToString());
OSDMap result = WebUtil.PostToService(uri, args, 80000);
if (result["Success"].AsBoolean())
{
OSDMap unpacked = (OSDMap)result["_Result"];
if (unpacked != null)
{
reason = unpacked["reason"].AsString();
myipaddress = unpacked["your_ip"].AsString();
return unpacked["success"].AsBoolean();
}
}
reason = result["Message"] != null ? result["Message"].AsString() : "error";
return false;
}
catch (Exception e)
{
m_log.Warn("[REMOTE SIMULATION CONNECTOR]: CreateAgent failed with exception: " + e.ToString());
reason = e.Message;
}
return false;
}
}
}

View File

@ -44,13 +44,14 @@ using Nini.Config;
namespace OpenSim.Services.Connectors.Hypergrid
{
public class UserAgentServiceConnector : IUserAgentService
public class UserAgentServiceConnector : SimulationServiceConnector, IUserAgentService
{
private static readonly ILog m_log =
LogManager.GetLogger(
MethodBase.GetCurrentMethod().DeclaringType);
string m_ServerURL;
private string m_ServerURL;
private GridRegion m_Gatekeeper;
public UserAgentServiceConnector(string url) : this(url, true)
{
@ -104,9 +105,15 @@ namespace OpenSim.Services.Connectors.Hypergrid
m_log.DebugFormat("[USER AGENT CONNECTOR]: UserAgentServiceConnector started for {0}", m_ServerURL);
}
protected override string AgentPath()
{
return "homeagent/";
}
// The Login service calls this interface with a non-null [client] ipaddress
public bool LoginAgentToGrid(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, IPEndPoint ipaddress, out string reason)
// The Login service calls this interface with fromLogin=true
// Sims call it with fromLogin=false
// Either way, this is verified by the handler
public bool LoginAgentToGrid(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, bool fromLogin, out string reason)
{
reason = String.Empty;
@ -117,119 +124,34 @@ namespace OpenSim.Services.Connectors.Hypergrid
return false;
}
string uri = m_ServerURL + "homeagent/" + aCircuit.AgentID + "/";
GridRegion home = new GridRegion();
home.ServerURI = m_ServerURL;
home.RegionID = destination.RegionID;
home.RegionLocX = destination.RegionLocX;
home.RegionLocY = destination.RegionLocY;
Console.WriteLine(" >>> LoginAgentToGrid <<< " + uri);
m_Gatekeeper = gatekeeper;
HttpWebRequest AgentCreateRequest = (HttpWebRequest)WebRequest.Create(uri);
AgentCreateRequest.Method = "POST";
AgentCreateRequest.ContentType = "application/json";
AgentCreateRequest.Timeout = 10000;
//AgentCreateRequest.KeepAlive = false;
//AgentCreateRequest.Headers.Add("Authorization", authKey);
// Fill it in
OSDMap args = PackCreateAgentArguments(aCircuit, gatekeeper, destination, ipaddress);
string strBuffer = "";
byte[] buffer = new byte[1];
try
{
strBuffer = OSDParser.SerializeJsonString(args);
Encoding str = Util.UTF8;
buffer = str.GetBytes(strBuffer);
}
catch (Exception e)
{
m_log.WarnFormat("[USER AGENT CONNECTOR]: Exception thrown on serialization of ChildCreate: {0}", e.Message);
// ignore. buffer will be empty, caller should check.
}
Stream os = null;
try
{ // send the Post
AgentCreateRequest.ContentLength = buffer.Length; //Count bytes to send
os = AgentCreateRequest.GetRequestStream();
os.Write(buffer, 0, strBuffer.Length); //Send it
m_log.InfoFormat("[USER AGENT CONNECTOR]: Posted CreateAgent request to remote sim {0}, region {1}, x={2} y={3}",
uri, destination.RegionName, destination.RegionLocX, destination.RegionLocY);
}
//catch (WebException ex)
catch
{
//m_log.InfoFormat("[USER AGENT CONNECTOR]: Bad send on ChildAgentUpdate {0}", ex.Message);
reason = "cannot contact remote region";
return false;
}
finally
{
if (os != null)
os.Close();
}
// Let's wait for the response
//m_log.Info("[USER AGENT CONNECTOR]: Waiting for a reply after DoCreateChildAgentCall");
try
{
using (WebResponse webResponse = AgentCreateRequest.GetResponse())
{
if (webResponse == null)
{
m_log.Info("[USER AGENT CONNECTOR]: Null reply on DoCreateChildAgentCall post");
}
else
{
using (Stream s = webResponse.GetResponseStream())
{
using (StreamReader sr = new StreamReader(s))
{
string response = sr.ReadToEnd().Trim();
m_log.InfoFormat("[USER AGENT CONNECTOR]: DoCreateChildAgentCall reply was {0} ", response);
if (!String.IsNullOrEmpty(response))
{
try
{
// we assume we got an OSDMap back
OSDMap r = Util.GetOSDMap(response);
bool success = r["success"].AsBoolean();
reason = r["reason"].AsString();
return success;
}
catch (NullReferenceException e)
{
m_log.InfoFormat("[USER AGENT CONNECTOR]: exception on reply of DoCreateChildAgentCall {0}", e.Message);
// check for old style response
if (response.ToLower().StartsWith("true"))
return true;
return false;
}
}
}
}
}
}
}
catch (WebException ex)
{
m_log.InfoFormat("[USER AGENT CONNECTOR]: exception on reply of DoCreateChildAgentCall {0}", ex.Message);
reason = "Destination did not reply";
return false;
}
return true;
Console.WriteLine(" >>> LoginAgentToGrid <<< " + home.ServerURI);
uint flags = fromLogin ? (uint)TeleportFlags.ViaLogin : (uint)TeleportFlags.ViaHome;
return CreateAgent(home, aCircuit, flags, out reason);
}
// The simulators call this interface
public bool LoginAgentToGrid(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, out string reason)
{
return LoginAgentToGrid(aCircuit, gatekeeper, destination, null, out reason);
return LoginAgentToGrid(aCircuit, gatekeeper, destination, false, out reason);
}
protected override void PackData(OSDMap args, AgentCircuitData aCircuit, GridRegion destination, uint flags)
{
base.PackData(args, aCircuit, destination, flags);
args["gatekeeper_serveruri"] = OSD.FromString(m_Gatekeeper.ServerURI);
args["gatekeeper_host"] = OSD.FromString(m_Gatekeeper.ExternalHostName);
args["gatekeeper_port"] = OSD.FromString(m_Gatekeeper.HttpPort.ToString());
args["destination_serveruri"] = OSD.FromString(destination.ServerURI);
}
protected OSDMap PackCreateAgentArguments(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, IPEndPoint ipaddress)

View File

@ -79,11 +79,27 @@ namespace OpenSim.Services.Connectors.Simulation
return "agent/";
}
protected virtual void PackData(OSDMap args, AgentCircuitData aCircuit, GridRegion destination, uint flags)
{
args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString());
args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString());
args["destination_name"] = OSD.FromString(destination.RegionName);
args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString());
args["teleport_flags"] = OSD.FromString(flags.ToString());
}
public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string reason)
{
// m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: CreateAgent start");
string tmp = String.Empty;
return CreateAgent(destination, aCircuit, flags, out tmp, out reason);
}
public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string myipaddress, out string reason)
{
m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: Creating agent at {0}", destination.ServerURI);
reason = String.Empty;
myipaddress = String.Empty;
if (destination == null)
{
m_log.Debug("[REMOTE SIMULATION CONNECTOR]: Given destination is null");
@ -95,12 +111,7 @@ namespace OpenSim.Services.Connectors.Simulation
try
{
OSDMap args = aCircuit.PackAgentCircuitData();
args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString());
args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString());
args["destination_name"] = OSD.FromString(destination.RegionName);
args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString());
args["teleport_flags"] = OSD.FromString(flags.ToString());
PackData(args, aCircuit, destination, flags);
OSDMap result = WebUtil.PostToServiceCompressed(uri, args, 30000);
bool success = result["success"].AsBoolean();
@ -110,6 +121,7 @@ namespace OpenSim.Services.Connectors.Simulation
reason = data["reason"].AsString();
success = data["success"].AsBoolean();
myipaddress = data["your_ip"].AsString();
return success;
}
@ -124,6 +136,7 @@ namespace OpenSim.Services.Connectors.Simulation
reason = data["reason"].AsString();
success = data["success"].AsBoolean();
myipaddress = data["your_ip"].AsString();
m_log.WarnFormat(
"[REMOTE SIMULATION CONNECTOR]: Remote simulator {0} did not accept compressed transfer, suggest updating it.", destination.RegionName);
return success;
@ -228,7 +241,7 @@ namespace OpenSim.Services.Connectors.Simulation
/// </summary>
private bool UpdateAgent(GridRegion destination, IAgentData cAgentData, int timeout)
{
// m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: UpdateAgent start");
// m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: UpdateAgent in {0}", destination.ServerURI);
// Eventually, we want to use a caps url instead of the agentID
string uri = destination.ServerURI + AgentPath() + cAgentData.AgentID + "/";

View File

@ -210,10 +210,10 @@ namespace OpenSim.Services.HypergridService
return home;
}
public bool LoginAgentToGrid(AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, IPEndPoint clientIP, out string reason)
public bool LoginAgentToGrid(AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, bool fromLogin, out string reason)
{
m_log.DebugFormat("[USER AGENT SERVICE]: Request to login user {0} {1} (@{2}) to grid {3}",
agentCircuit.firstname, agentCircuit.lastname, ((clientIP == null) ? "stored IP" : clientIP.Address.ToString()), gatekeeper.ServerURI);
agentCircuit.firstname, agentCircuit.lastname, (fromLogin ? agentCircuit.IPAddress : "stored IP"), gatekeeper.ServerURI);
string gridName = gatekeeper.ServerURI;
@ -265,7 +265,7 @@ namespace OpenSim.Services.HypergridService
bool success = false;
string myExternalIP = string.Empty;
m_log.DebugFormat("[USER AGENT SERVICE]: this grid: {0}, desired grid: {1}", m_GridName, gridName);
m_log.DebugFormat("[USER AGENT SERVICE]: this grid: {0}, desired grid: {1}, desired region: {2}", m_GridName, gridName, region.RegionID);
if (m_GridName == gridName)
success = m_GatekeeperService.LoginAgent(agentCircuit, finalDestination, out reason);
@ -296,8 +296,8 @@ namespace OpenSim.Services.HypergridService
m_log.DebugFormat("[USER AGENT SERVICE]: Gatekeeper sees me as {0}", myExternalIP);
// else set the IP addresses associated with this client
if (clientIP != null)
m_TravelingAgents[agentCircuit.SessionID].ClientIPAddress = clientIP.Address.ToString();
if (fromLogin)
m_TravelingAgents[agentCircuit.SessionID].ClientIPAddress = agentCircuit.IPAddress;
m_TravelingAgents[agentCircuit.SessionID].MyIpAddress = myExternalIP;
return true;
@ -306,7 +306,7 @@ namespace OpenSim.Services.HypergridService
public bool LoginAgentToGrid(AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, out string reason)
{
reason = string.Empty;
return LoginAgentToGrid(agentCircuit, gatekeeper, finalDestination, null, out reason);
return LoginAgentToGrid(agentCircuit, gatekeeper, finalDestination, false, out reason);
}
private void SetClientIP(UUID sessionID, string ip)

View File

@ -48,10 +48,7 @@ namespace OpenSim.Services.Interfaces
/// </summary>
public interface IUserAgentService
{
// called by login service only
bool LoginAgentToGrid(AgentCircuitData agent, GridRegion gatekeeper, GridRegion finalDestination, IPEndPoint clientIP, out string reason);
// called by simulators
bool LoginAgentToGrid(AgentCircuitData agent, GridRegion gatekeeper, GridRegion finalDestination, out string reason);
bool LoginAgentToGrid(AgentCircuitData agent, GridRegion gatekeeper, GridRegion finalDestination, bool fromLogin, out string reason);
void LogoutAgent(UUID userID, UUID sessionID);
GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt);
Dictionary<string, object> GetServerURLs(UUID userID);

View File

@ -933,7 +933,7 @@ namespace OpenSim.Services.LLLoginService
private bool LaunchAgentIndirectly(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, IPEndPoint clientIP, out string reason)
{
m_log.Debug("[LLOGIN SERVICE] Launching agent at " + destination.RegionName);
if (m_UserAgentService.LoginAgentToGrid(aCircuit, gatekeeper, destination, clientIP, out reason))
if (m_UserAgentService.LoginAgentToGrid(aCircuit, gatekeeper, destination, true, out reason))
return true;
return false;
}

View File

@ -157,6 +157,7 @@
<Reference name="System"/>
<Reference name="System.Core"/>
<Reference name="log4net" path="../../../bin/"/>
<Reference name="Nini" path="../../../bin/"/>
<Reference name="OpenMetaverseTypes" path="../../../bin/"/>
<Reference name="OpenMetaverse" path="../../../bin/"/>
<Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/>
@ -744,6 +745,7 @@
<Reference name="Mono.Addins.Setup" path="../../../bin/"/>
<Reference name="OpenSim.Framework"/>
<Reference name="OpenSim.Framework.Console"/>
<Reference name="OpenSim.Framework.Monitoring"/>
<Reference name="OpenSim.Framework.Servers"/>
<Reference name="OpenSim.Framework.Servers.HttpServer"/>
<Reference name="Nini" path="../../../bin/"/>