Merge branch 'master' into careminster
Conflicts: OpenSim/Framework/Monitoring/BaseStatsCollector.cs OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs OpenSim/Region/Framework/Scenes/Scene.Inventory.csavinationmerge
commit
f70357eaa3
|
@ -46,7 +46,7 @@ namespace OpenSim.OfflineIM
|
||||||
{
|
{
|
||||||
public class OfflineIMService : OfflineIMServiceBase, IOfflineIMService
|
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 const int MAX_IM = 25;
|
||||||
|
|
||||||
private XmlSerializer m_serializer;
|
private XmlSerializer m_serializer;
|
||||||
|
|
|
@ -46,7 +46,7 @@ namespace OpenSim.Capabilities.Handlers
|
||||||
{
|
{
|
||||||
public class FetchInventory2Handler
|
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;
|
private IInventoryService m_inventoryService;
|
||||||
|
|
||||||
|
@ -121,4 +121,4 @@ namespace OpenSim.Capabilities.Handlers
|
||||||
return llsdItem;
|
return llsdItem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) Contributors, http://opensimulator.org/
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
*
|
*
|
||||||
|
@ -44,16 +44,16 @@ namespace OpenSim.Framework.Monitoring
|
||||||
sb.Append("MEMORY STATISTICS");
|
sb.Append("MEMORY STATISTICS");
|
||||||
sb.Append(Environment.NewLine);
|
sb.Append(Environment.NewLine);
|
||||||
sb.AppendFormat(
|
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));
|
Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0));
|
||||||
|
|
||||||
sb.AppendFormat(
|
sb.AppendFormat(
|
||||||
"OpenSim last object memory churn : {0} MB/s\n",
|
"Last heap allocation rate : {0} MB/s\n",
|
||||||
Math.Round((MemoryWatchdog.LastMemoryChurn * 1000) / 1024.0 / 1024, 3));
|
Math.Round((MemoryWatchdog.LastHeapAllocationRate * 1000) / 1024.0 / 1024, 3));
|
||||||
|
|
||||||
sb.AppendFormat(
|
sb.AppendFormat(
|
||||||
"OpenSim average object memory churn : {0} MB/s\n",
|
"Average heap allocation rate: {0} MB/s\n",
|
||||||
Math.Round((MemoryWatchdog.AverageMemoryChurn * 1000) / 1024.0 / 1024, 3));
|
Math.Round((MemoryWatchdog.AverageHeapAllocationRate * 1000) / 1024.0 / 1024, 3));
|
||||||
|
|
||||||
Process myprocess = Process.GetCurrentProcess();
|
Process myprocess = Process.GetCurrentProcess();
|
||||||
if (!myprocess.HasExited)
|
if (!myprocess.HasExited)
|
||||||
|
|
|
@ -60,17 +60,17 @@ namespace OpenSim.Framework.Monitoring
|
||||||
private static bool m_enabled;
|
private static bool m_enabled;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Last memory churn in bytes per millisecond.
|
/// Average heap allocation rate in bytes per millisecond.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static double AverageMemoryChurn
|
public static double AverageHeapAllocationRate
|
||||||
{
|
{
|
||||||
get { if (m_samples.Count > 0) return m_samples.Average(); else return 0; }
|
get { if (m_samples.Count > 0) return m_samples.Average(); else return 0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Average memory churn in bytes per millisecond.
|
/// Last heap allocation in bytes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static double LastMemoryChurn
|
public static double LastHeapAllocationRate
|
||||||
{
|
{
|
||||||
get { if (m_samples.Count > 0) return m_samples.Last(); else return 0; }
|
get { if (m_samples.Count > 0) return m_samples.Last(); else return 0; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,8 +27,10 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using log4net;
|
||||||
using OpenMetaverse.StructuredData;
|
using OpenMetaverse.StructuredData;
|
||||||
|
|
||||||
namespace OpenSim.Framework.Monitoring
|
namespace OpenSim.Framework.Monitoring
|
||||||
|
@ -38,6 +40,10 @@ namespace OpenSim.Framework.Monitoring
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Stat : IDisposable
|
public class Stat : IDisposable
|
||||||
{
|
{
|
||||||
|
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
public static readonly char[] DisallowedShortNameCharacters = { '.' };
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Category of this stat (e.g. cache, scene, etc).
|
/// Category of this stat (e.g. cache, scene, etc).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -95,7 +101,7 @@ namespace OpenSim.Framework.Monitoring
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Will be null if no measures of interest require samples.
|
/// Will be null if no measures of interest require samples.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
private static Queue<double> m_samples;
|
private Queue<double> m_samples;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Maximum number of statistical samples.
|
/// Maximum number of statistical samples.
|
||||||
|
@ -162,6 +168,12 @@ namespace OpenSim.Framework.Monitoring
|
||||||
throw new Exception(
|
throw new Exception(
|
||||||
string.Format("Stat cannot be in category '{0}' since this is reserved for a subcommand", category));
|
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;
|
ShortName = shortName;
|
||||||
Name = name;
|
Name = name;
|
||||||
Description = description;
|
Description = description;
|
||||||
|
@ -204,6 +216,8 @@ namespace OpenSim.Framework.Monitoring
|
||||||
if (m_samples.Count >= m_maxSamples)
|
if (m_samples.Count >= m_maxSamples)
|
||||||
m_samples.Dequeue();
|
m_samples.Dequeue();
|
||||||
|
|
||||||
|
// m_log.DebugFormat("[STAT]: Recording value {0} for {1}", newValue, Name);
|
||||||
|
|
||||||
m_samples.Enqueue(newValue);
|
m_samples.Enqueue(newValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -242,6 +256,10 @@ namespace OpenSim.Framework.Monitoring
|
||||||
|
|
||||||
lock (m_samples)
|
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)
|
foreach (double s in m_samples)
|
||||||
{
|
{
|
||||||
if (lastSample != null)
|
if (lastSample != null)
|
||||||
|
@ -253,7 +271,7 @@ namespace OpenSim.Framework.Monitoring
|
||||||
|
|
||||||
int divisor = m_samples.Count <= 1 ? 1 : m_samples.Count - 1;
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace OpenSim.Framework.Monitoring
|
namespace OpenSim.Framework.Monitoring
|
||||||
|
@ -54,13 +55,13 @@ namespace OpenSim.Framework.Monitoring
|
||||||
public static SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>> RegisteredStats
|
public static SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>> RegisteredStats
|
||||||
= new SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>>();
|
= new SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>>();
|
||||||
|
|
||||||
private static AssetStatsCollector assetStats;
|
// private static AssetStatsCollector assetStats;
|
||||||
private static UserStatsCollector userStats;
|
// private static UserStatsCollector userStats;
|
||||||
private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector();
|
// private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector();
|
||||||
|
|
||||||
public static AssetStatsCollector AssetStats { get { return assetStats; } }
|
// public static AssetStatsCollector AssetStats { get { return assetStats; } }
|
||||||
public static UserStatsCollector UserStats { get { return userStats; } }
|
// public static UserStatsCollector UserStats { get { return userStats; } }
|
||||||
public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } }
|
public static SimExtraStatsCollector SimExtraStats { get; set; }
|
||||||
|
|
||||||
public static void RegisterConsoleCommands(ICommandConsole console)
|
public static void RegisterConsoleCommands(ICommandConsole console)
|
||||||
{
|
{
|
||||||
|
@ -68,12 +69,14 @@ namespace OpenSim.Framework.Monitoring
|
||||||
"General",
|
"General",
|
||||||
false,
|
false,
|
||||||
"show stats",
|
"show stats",
|
||||||
"show stats [list|all|<category>]",
|
"show stats [list|all|(<category>[.<container>])+",
|
||||||
"Show statistical information for this server",
|
"Show statistical information for this server",
|
||||||
"If no final argument is specified then legacy statistics information is currently shown.\n"
|
"If no final argument is specified then legacy statistics information is currently shown.\n"
|
||||||
+ "If list is specified then statistic categories are shown.\n"
|
+ "'list' argument will show statistic categories.\n"
|
||||||
+ "If all is specified then all registered statistics are shown.\n"
|
+ "'all' will show all statistics.\n"
|
||||||
+ "If a category name is specified then only statistics from that category are shown.\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",
|
+ "THIS STATS FACILITY IS EXPERIMENTAL AND DOES NOT YET CONTAIN ALL STATS",
|
||||||
HandleShowStatsCommand);
|
HandleShowStatsCommand);
|
||||||
}
|
}
|
||||||
|
@ -84,43 +87,47 @@ namespace OpenSim.Framework.Monitoring
|
||||||
|
|
||||||
if (cmd.Length > 2)
|
if (cmd.Length > 2)
|
||||||
{
|
{
|
||||||
var categoryName = cmd[2];
|
foreach (string name in cmd.Skip(2))
|
||||||
var containerName = cmd.Length > 3 ? cmd[3] : String.Empty;
|
{
|
||||||
|
string[] components = name.Split('.');
|
||||||
|
|
||||||
if (categoryName == AllSubCommand)
|
string categoryName = components[0];
|
||||||
{
|
string containerName = components.Length > 1 ? components[1] : null;
|
||||||
foreach (var category in RegisteredStats.Values)
|
|
||||||
|
if (categoryName == AllSubCommand)
|
||||||
{
|
{
|
||||||
OutputCategoryStatsToConsole(con, category);
|
OutputAllStatsToConsole(con);
|
||||||
}
|
}
|
||||||
}
|
else if (categoryName == ListSubCommand)
|
||||||
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))
|
|
||||||
{
|
{
|
||||||
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
|
else
|
||||||
{
|
{
|
||||||
if (String.IsNullOrEmpty(containerName))
|
SortedDictionary<string, SortedDictionary<string, Stat>> category;
|
||||||
OutputCategoryStatsToConsole(con, category);
|
if (!RegisteredStats.TryGetValue(categoryName, out category))
|
||||||
|
{
|
||||||
|
con.OutputFormat("No such category as {0}", categoryName);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SortedDictionary<string, Stat> container;
|
if (String.IsNullOrEmpty(containerName))
|
||||||
if (category.TryGetValue(containerName, out container))
|
|
||||||
{
|
{
|
||||||
OutputContainerStatsToConsole(con, container);
|
OutputCategoryStatsToConsole(con, category);
|
||||||
}
|
}
|
||||||
else
|
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
|
else
|
||||||
{
|
{
|
||||||
// Legacy
|
// 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>
|
// /// <summary>
|
||||||
/// Start collecting statistics related to assets.
|
// /// Start collecting statistics related to assets.
|
||||||
/// Should only be called once.
|
// /// Should only be called once.
|
||||||
/// </summary>
|
// /// </summary>
|
||||||
public static AssetStatsCollector StartCollectingAssetStats()
|
// public static AssetStatsCollector StartCollectingAssetStats()
|
||||||
{
|
// {
|
||||||
assetStats = new AssetStatsCollector();
|
// assetStats = new AssetStatsCollector();
|
||||||
|
//
|
||||||
return assetStats;
|
// return assetStats;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
/// <summary>
|
// /// <summary>
|
||||||
/// Start collecting statistics related to users.
|
// /// Start collecting statistics related to users.
|
||||||
/// Should only be called once.
|
// /// Should only be called once.
|
||||||
/// </summary>
|
// /// </summary>
|
||||||
public static UserStatsCollector StartCollectingUserStats()
|
// public static UserStatsCollector StartCollectingUserStats()
|
||||||
{
|
// {
|
||||||
userStats = new UserStatsCollector();
|
// userStats = new UserStatsCollector();
|
||||||
|
//
|
||||||
return userStats;
|
// return userStats;
|
||||||
}
|
// }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Registers a statistic.
|
/// Registers a statistic.
|
||||||
|
|
|
@ -86,25 +86,22 @@ namespace OpenSim.Framework.Servers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual void StartupSpecific()
|
protected virtual void StartupSpecific()
|
||||||
{
|
{
|
||||||
if (m_console == null)
|
StatsManager.SimExtraStats = new SimExtraStatsCollector();
|
||||||
return;
|
|
||||||
|
|
||||||
RegisterCommonCommands();
|
RegisterCommonCommands();
|
||||||
|
RegisterCommonComponents(Config);
|
||||||
m_console.Commands.AddCommand("General", false, "quit",
|
}
|
||||||
"quit",
|
|
||||||
"Quit the application", HandleQuit);
|
|
||||||
|
|
||||||
m_console.Commands.AddCommand("General", false, "shutdown",
|
protected override void ShutdownSpecific()
|
||||||
"shutdown",
|
{
|
||||||
"Quit the application", HandleQuit);
|
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>
|
/// <summary>
|
||||||
/// Provides a list of help topics that are available. Overriding classes should append their topics to the
|
/// 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.
|
/// information returned when the base method is called.
|
||||||
|
@ -153,25 +150,8 @@ namespace OpenSim.Framework.Servers
|
||||||
timeTaken.Minutes, timeTaken.Seconds);
|
timeTaken.Minutes, timeTaken.Seconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public string osSecret
|
||||||
/// Should be overriden and referenced by descendents if they need to perform extra shutdown processing
|
|
||||||
/// </summary>
|
|
||||||
public virtual void Shutdown()
|
|
||||||
{
|
{
|
||||||
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
|
// Secret uuid for the simulator
|
||||||
get { return m_osSecret; }
|
get { return m_osSecret; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,6 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
private HttpServerLogWriter httpserverlog = new HttpServerLogWriter();
|
private HttpServerLogWriter httpserverlog = new HttpServerLogWriter();
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This is a pending websocket request before it got an sucessful upgrade response.
|
/// 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
|
/// The consumer must call handler.HandshakeAndUpgrade() to signal to the handler to
|
||||||
|
@ -81,6 +80,11 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public int RequestNumber { get; private set; }
|
public int RequestNumber { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Statistic for holding number of requests processed.
|
||||||
|
/// </summary>
|
||||||
|
private Stat m_requestsProcessedStat;
|
||||||
|
|
||||||
private volatile int NotSocketErrors = 0;
|
private volatile int NotSocketErrors = 0;
|
||||||
public volatile bool HTTPDRunning = false;
|
public volatile bool HTTPDRunning = false;
|
||||||
|
|
||||||
|
@ -437,9 +441,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);
|
OSHttpRequest req = new OSHttpRequest(context, request);
|
||||||
WebSocketRequestDelegate dWebSocketRequestDelegate = null;
|
WebSocketRequestDelegate dWebSocketRequestDelegate = null;
|
||||||
lock (m_WebSocketHandlers)
|
lock (m_WebSocketHandlers)
|
||||||
|
@ -455,8 +458,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||||
|
|
||||||
OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context);
|
OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context);
|
||||||
resp.ReuseContext = true;
|
resp.ReuseContext = true;
|
||||||
HandleRequest(req, resp);
|
HandleRequest(req, resp);
|
||||||
|
|
||||||
|
|
||||||
// !!!HACK ALERT!!!
|
// !!!HACK ALERT!!!
|
||||||
// There seems to be a bug in the underlying http code that makes subsequent requests
|
// There seems to be a bug in the underlying http code that makes subsequent requests
|
||||||
|
@ -1870,6 +1872,21 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||||
// useful without inbound HTTP.
|
// useful without inbound HTTP.
|
||||||
throw e;
|
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)
|
public void httpServerDisconnectMonitor(IHttpClientContext source, SocketError err)
|
||||||
|
@ -1902,6 +1919,9 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||||
public void Stop()
|
public void Stop()
|
||||||
{
|
{
|
||||||
HTTPDRunning = false;
|
HTTPDRunning = false;
|
||||||
|
|
||||||
|
StatsManager.DeregisterStat(m_requestsProcessedStat);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_PollServiceManager.Stop();
|
m_PollServiceManager.Stop();
|
||||||
|
|
|
@ -75,7 +75,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This is a regular HTTP Request... This may be removed in the future.
|
/// This is a regular HTTP Request... This may be removed in the future.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event RegularHttpRequestDelegate OnRegularHttpRequest;
|
// public event RegularHttpRequestDelegate OnRegularHttpRequest;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When the upgrade from a HTTP request to a Websocket is completed, this will be fired
|
/// 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)
|
if (d != null)
|
||||||
d(this, new UpgradeCompletedEventArgs());
|
d(this, new UpgradeCompletedEventArgs());
|
||||||
}
|
}
|
||||||
catch (IOException fail)
|
catch (IOException)
|
||||||
{
|
{
|
||||||
Close(string.Empty);
|
Close(string.Empty);
|
||||||
}
|
}
|
||||||
catch (ObjectDisposedException fail)
|
catch (ObjectDisposedException)
|
||||||
{
|
{
|
||||||
Close(string.Empty);
|
Close(string.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -414,8 +413,6 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||||
_socketState.Header = pheader;
|
_socketState.Header = pheader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (_socketState.FrameComplete)
|
if (_socketState.FrameComplete)
|
||||||
{
|
{
|
||||||
ProcessFrame(_socketState);
|
ProcessFrame(_socketState);
|
||||||
|
@ -424,7 +421,6 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||||
_socketState.ExpectedBytes = 0;
|
_socketState.ExpectedBytes = 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -457,8 +453,7 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||||
_socketState.ReceivedBytes.Clear();
|
_socketState.ReceivedBytes.Clear();
|
||||||
_socketState.ExpectedBytes = 0;
|
_socketState.ExpectedBytes = 0;
|
||||||
// do some processing
|
// do some processing
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (offset > 0)
|
if (offset > 0)
|
||||||
|
@ -477,13 +472,12 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||||
{
|
{
|
||||||
// We can't read the stream anymore...
|
// We can't read the stream anymore...
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (IOException fail)
|
catch (IOException)
|
||||||
{
|
{
|
||||||
Close(string.Empty);
|
Close(string.Empty);
|
||||||
}
|
}
|
||||||
catch (ObjectDisposedException fail)
|
catch (ObjectDisposedException)
|
||||||
{
|
{
|
||||||
Close(string.Empty);
|
Close(string.Empty);
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,8 @@ namespace OpenSim.Framework.Servers
|
||||||
|
|
||||||
protected string m_pidFile = String.Empty;
|
protected string m_pidFile = String.Empty;
|
||||||
|
|
||||||
|
protected ServerStatsCollector m_serverStatsCollector;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Server version information. Usually VersionInfo + information about git commit, operating system, etc.
|
/// Server version information. Usually VersionInfo + information about git commit, operating system, etc.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -259,6 +261,25 @@ namespace OpenSim.Framework.Servers
|
||||||
"force gc",
|
"force gc",
|
||||||
"Manually invoke runtime garbage collection. For debugging purposes",
|
"Manually invoke runtime garbage collection. For debugging purposes",
|
||||||
HandleForceGc);
|
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)
|
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.AppendFormat("Total threads active: {0}\n\n", totalThreads);
|
||||||
|
|
||||||
sb.Append("Main threadpool (excluding script engine pools)\n");
|
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();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
|
@ -698,5 +780,16 @@ namespace OpenSim.Framework.Servers
|
||||||
if (m_console != null)
|
if (m_console != null)
|
||||||
m_console.OutputFormat(format, components);
|
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() {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,10 +88,31 @@ namespace OpenSim.Framework
|
||||||
Thread,
|
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>
|
/// <summary>
|
||||||
/// Miscellaneous utility functions
|
/// Miscellaneous utility functions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Util
|
public static class Util
|
||||||
{
|
{
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
@ -1864,74 +1885,31 @@ namespace OpenSim.Framework
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a thread pool report.
|
/// Get information about the current state of the smart thread pool.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns>
|
||||||
public static string GetThreadPoolReport()
|
/// null if this isn't the pool being used for non-scriptengine threads.
|
||||||
|
/// </returns>
|
||||||
|
public static STPInfo GetSmartThreadPoolInfo()
|
||||||
{
|
{
|
||||||
string threadPoolUsed = null;
|
if (m_ThreadPool == null)
|
||||||
int maxThreads = 0;
|
return null;
|
||||||
int minThreads = 0;
|
|
||||||
int allocatedThreads = 0;
|
|
||||||
int inUseThreads = 0;
|
|
||||||
int waitingCallbacks = 0;
|
|
||||||
int completionPortThreads = 0;
|
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
STPInfo stpi = new STPInfo();
|
||||||
if (FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
|
stpi.Name = m_ThreadPool.Name;
|
||||||
{
|
stpi.STPStartInfo = m_ThreadPool.STPStartInfo;
|
||||||
// ROBUST currently leaves this the FireAndForgetMethod but never actually initializes the threadpool.
|
stpi.IsIdle = m_ThreadPool.IsIdle;
|
||||||
if (m_ThreadPool != null)
|
stpi.IsShuttingDown = m_ThreadPool.IsShuttingdown;
|
||||||
{
|
stpi.MaxThreads = m_ThreadPool.MaxThreads;
|
||||||
threadPoolUsed = "SmartThreadPool";
|
stpi.MinThreads = m_ThreadPool.MinThreads;
|
||||||
maxThreads = m_ThreadPool.MaxThreads;
|
stpi.InUseThreads = m_ThreadPool.InUseThreads;
|
||||||
minThreads = m_ThreadPool.MinThreads;
|
stpi.ActiveThreads = m_ThreadPool.ActiveThreads;
|
||||||
inUseThreads = m_ThreadPool.InUseThreads;
|
stpi.WaitingCallbacks = m_ThreadPool.WaitingCallbacks;
|
||||||
allocatedThreads = m_ThreadPool.ActiveThreads;
|
stpi.MaxConcurrentWorkItems = m_ThreadPool.Concurrency;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (threadPoolUsed != null)
|
return stpi;
|
||||||
{
|
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
#endregion FireAndForget Threading Pattern
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -124,6 +124,7 @@ namespace OpenSim
|
||||||
workerThreads = workerThreadsMax;
|
workerThreads = workerThreadsMax;
|
||||||
m_log.InfoFormat("[OPENSIM MAIN]: Limiting worker threads to {0}",workerThreads);
|
m_log.InfoFormat("[OPENSIM MAIN]: Limiting worker threads to {0}",workerThreads);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Increase the number of IOCP threads available.
|
// Increase the number of IOCP threads available.
|
||||||
// Mono defaults to a tragically low number (24 on 6-core / 8GB Fedora 17)
|
// Mono defaults to a tragically low number (24 on 6-core / 8GB Fedora 17)
|
||||||
if (iocpThreads < iocpThreadsMin)
|
if (iocpThreads < iocpThreadsMin)
|
||||||
|
|
|
@ -372,7 +372,7 @@ namespace OpenSim
|
||||||
"Unload a module", HandleModules);
|
"Unload a module", HandleModules);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ShutdownSpecific()
|
protected override void ShutdownSpecific()
|
||||||
{
|
{
|
||||||
if (m_shutdownCommandsFile != String.Empty)
|
if (m_shutdownCommandsFile != String.Empty)
|
||||||
{
|
{
|
||||||
|
|
|
@ -246,10 +246,7 @@ namespace OpenSim
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_console != null)
|
if (m_console != null)
|
||||||
{
|
|
||||||
StatsManager.RegisterConsoleCommands(m_console);
|
|
||||||
AddPluginCommands(m_console);
|
AddPluginCommands(m_console);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void AddPluginCommands(ICommandConsole console)
|
protected virtual void AddPluginCommands(ICommandConsole console)
|
||||||
|
@ -964,7 +961,7 @@ namespace OpenSim
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Performs any last-minute sanity checking and shuts down the region server
|
/// Performs any last-minute sanity checking and shuts down the region server
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public override void ShutdownSpecific()
|
protected override void ShutdownSpecific()
|
||||||
{
|
{
|
||||||
if (proxyUrl.Length > 0)
|
if (proxyUrl.Length > 0)
|
||||||
{
|
{
|
||||||
|
@ -984,6 +981,8 @@ namespace OpenSim
|
||||||
{
|
{
|
||||||
m_log.Error("[SHUTDOWN]: Ignoring failure during shutdown - ", e);
|
m_log.Error("[SHUTDOWN]: Ignoring failure during shutdown - ", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
base.ShutdownSpecific();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -33,6 +33,7 @@ using NUnit.Framework;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
using OpenMetaverse.Packets;
|
using OpenMetaverse.Packets;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Monitoring;
|
||||||
using OpenSim.Region.Framework.Scenes;
|
using OpenSim.Region.Framework.Scenes;
|
||||||
using OpenSim.Tests.Common;
|
using OpenSim.Tests.Common;
|
||||||
using OpenSim.Tests.Common.Mock;
|
using OpenSim.Tests.Common.Mock;
|
||||||
|
@ -69,6 +70,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
|
||||||
{
|
{
|
||||||
base.SetUp();
|
base.SetUp();
|
||||||
m_scene = new SceneHelpers().SetupScene();
|
m_scene = new SceneHelpers().SetupScene();
|
||||||
|
StatsManager.SimExtraStats = new SimExtraStatsCollector();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -210,8 +212,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
|
||||||
|
|
||||||
ScenePresence spAfterAckTimeout = m_scene.GetScenePresence(sp.UUID);
|
ScenePresence spAfterAckTimeout = m_scene.GetScenePresence(sp.UUID);
|
||||||
Assert.That(spAfterAckTimeout, Is.Null);
|
Assert.That(spAfterAckTimeout, Is.Null);
|
||||||
|
|
||||||
// TestHelpers.DisableLogging();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// /// <summary>
|
// /// <summary>
|
||||||
|
|
|
@ -53,8 +53,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
private int m_levelHGTeleport = 0;
|
private int m_levelHGTeleport = 0;
|
||||||
|
private string m_ThisHomeURI;
|
||||||
|
|
||||||
private GatekeeperServiceConnector m_GatekeeperConnector;
|
private GatekeeperServiceConnector m_GatekeeperConnector;
|
||||||
|
private IUserAgentService m_UAS;
|
||||||
|
|
||||||
protected bool m_RestrictAppearanceAbroad;
|
protected bool m_RestrictAppearanceAbroad;
|
||||||
protected string m_AccountName;
|
protected string m_AccountName;
|
||||||
|
@ -143,6 +145,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name);
|
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)
|
public override void AddRegion(Scene scene)
|
||||||
|
@ -194,7 +204,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
base.RegionLoaded(scene);
|
base.RegionLoaded(scene);
|
||||||
|
|
||||||
if (m_Enabled)
|
if (m_Enabled)
|
||||||
|
{
|
||||||
m_GatekeeperConnector = new GatekeeperServiceConnector(scene.AssetService);
|
m_GatekeeperConnector = new GatekeeperServiceConnector(scene.AssetService);
|
||||||
|
m_UAS = scene.RequestModuleInterface<IUserAgentService>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void RemoveRegion(Scene scene)
|
public override void RemoveRegion(Scene scene)
|
||||||
|
@ -272,8 +285,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
if (agentCircuit.ServiceURLs.ContainsKey("HomeURI"))
|
if (agentCircuit.ServiceURLs.ContainsKey("HomeURI"))
|
||||||
{
|
{
|
||||||
string userAgentDriver = agentCircuit.ServiceURLs["HomeURI"].ToString();
|
string userAgentDriver = agentCircuit.ServiceURLs["HomeURI"].ToString();
|
||||||
IUserAgentService connector = new UserAgentServiceConnector(userAgentDriver);
|
IUserAgentService connector;
|
||||||
bool success = connector.LoginAgentToGrid(agentCircuit, reg, finalDestination, out reason);
|
|
||||||
|
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
|
logout = success; // flag for later logout from this grid; this is an HG TP
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
|
|
|
@ -194,7 +194,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Try local first
|
// Try local first
|
||||||
if (m_localBackend.IsLocalRegion(destination.RegionHandle))
|
if (m_localBackend.IsLocalRegion(destination.RegionID))
|
||||||
return m_localBackend.UpdateAgent(destination, cAgentData);
|
return m_localBackend.UpdateAgent(destination, cAgentData);
|
||||||
|
|
||||||
return m_remoteConnector.UpdateAgent(destination, cAgentData);
|
return m_remoteConnector.UpdateAgent(destination, cAgentData);
|
||||||
|
@ -206,7 +206,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Try local first
|
// Try local first
|
||||||
if (m_localBackend.IsLocalRegion(destination.RegionHandle))
|
if (m_localBackend.IsLocalRegion(destination.RegionID))
|
||||||
return m_localBackend.UpdateAgent(destination, cAgentData);
|
return m_localBackend.UpdateAgent(destination, cAgentData);
|
||||||
|
|
||||||
return m_remoteConnector.UpdateAgent(destination, cAgentData);
|
return m_remoteConnector.UpdateAgent(destination, cAgentData);
|
||||||
|
@ -224,7 +224,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// else do the remote thing
|
// 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 m_remoteConnector.RetrieveAgent(destination, id, out agent);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -288,7 +288,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// else do the remote thing
|
// else do the remote thing
|
||||||
if (!m_localBackend.IsLocalRegion(destination.RegionHandle))
|
if (!m_localBackend.IsLocalRegion(destination.RegionID))
|
||||||
return m_remoteConnector.CloseAgent(destination, id);
|
return m_remoteConnector.CloseAgent(destination, id);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -311,7 +311,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
|
||||||
}
|
}
|
||||||
|
|
||||||
// else do the remote thing
|
// 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 m_remoteConnector.CreateObject(destination, newPosition, sog, isLocalCall);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -82,14 +82,14 @@ namespace OpenSim.Region.CoreModules.World.Land
|
||||||
|
|
||||||
set { m_landData = value; }
|
set { m_landData = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public IPrimCounts PrimCounts { get; set; }
|
public IPrimCounts PrimCounts { get; set; }
|
||||||
|
|
||||||
public UUID RegionUUID
|
public UUID RegionUUID
|
||||||
{
|
{
|
||||||
get { return m_scene.RegionInfo.RegionID; }
|
get { return m_scene.RegionInfo.RegionID; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector3 StartPoint
|
public Vector3 StartPoint
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -102,11 +102,11 @@ namespace OpenSim.Region.CoreModules.World.Land
|
||||||
return new Vector3(x * 4, y * 4, 0);
|
return new Vector3(x * 4, y * 4, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Vector3(-1, -1, -1);
|
return new Vector3(-1, -1, -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector3 EndPoint
|
public Vector3 EndPoint
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -117,15 +117,15 @@ namespace OpenSim.Region.CoreModules.World.Land
|
||||||
{
|
{
|
||||||
if (LandBitmap[x, y])
|
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);
|
return new Vector3(-1, -1, -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Constructors
|
#region Constructors
|
||||||
|
|
||||||
public LandObject(UUID owner_id, bool is_group_owned, Scene scene)
|
public LandObject(UUID owner_id, bool is_group_owned, Scene scene)
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -43,8 +43,14 @@ public class BSActorAvatarMove : BSActor
|
||||||
// Set to true if we think we're going up stairs.
|
// 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.
|
// This state is remembered because collisions will turn on and off as we go up stairs.
|
||||||
int m_walkingUpStairs;
|
int m_walkingUpStairs;
|
||||||
|
// The amount the step up is applying. Used to smooth stair walking.
|
||||||
float m_lastStepUp;
|
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)
|
public BSActorAvatarMove(BSScene physicsScene, BSPhysObject pObj, string actorName)
|
||||||
: base(physicsScene, pObj, actorName)
|
: base(physicsScene, pObj, actorName)
|
||||||
{
|
{
|
||||||
|
@ -206,17 +212,45 @@ public class BSActorAvatarMove : BSActor
|
||||||
|
|
||||||
if (m_controllingPrim.Friction != BSParam.AvatarFriction)
|
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_controllingPrim.Friction = BSParam.AvatarFriction;
|
||||||
m_physicsScene.PE.SetFriction(m_controllingPrim.PhysBody, m_controllingPrim.Friction);
|
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.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;
|
stepVelocity.Z = m_controllingPrim.RawVelocity.Z;
|
||||||
|
}
|
||||||
// DetailLog("{0},BSCharacter.MoveMotor,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity);
|
// 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_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.LocalID, m_controllingPrim.IsColliding, m_controllingPrim.Flying,
|
||||||
m_controllingPrim.TargetVelocitySpeed, m_controllingPrim.CollisionsLastTick.Count, m_controllingPrim.Size.Z);
|
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
|
// Check for stairs climbing if colliding, not flying and moving forward
|
||||||
if ( m_controllingPrim.IsColliding
|
if ( m_controllingPrim.IsColliding
|
||||||
&& !m_controllingPrim.Flying
|
&& !m_controllingPrim.Flying
|
||||||
|
|
|
@ -209,7 +209,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
m_VhoverTimescale = Math.Max(pValue, 0.01f);
|
m_VhoverTimescale = Math.Max(pValue, 0.01f);
|
||||||
break;
|
break;
|
||||||
case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
|
case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
|
||||||
m_linearDeflectionEfficiency = Math.Max(pValue, 0.01f);
|
m_linearDeflectionEfficiency = ClampInRange(0f, pValue, 1f);
|
||||||
break;
|
break;
|
||||||
case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
|
case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
|
||||||
m_linearDeflectionTimescale = Math.Max(pValue, 0.01f);
|
m_linearDeflectionTimescale = Math.Max(pValue, 0.01f);
|
||||||
|
@ -707,7 +707,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
private Vector3 m_knownRotationalVelocity;
|
private Vector3 m_knownRotationalVelocity;
|
||||||
private Vector3 m_knownRotationalForce;
|
private Vector3 m_knownRotationalForce;
|
||||||
private Vector3 m_knownRotationalImpulse;
|
private Vector3 m_knownRotationalImpulse;
|
||||||
private Vector3 m_knownForwardVelocity; // vehicle relative forward speed
|
|
||||||
|
|
||||||
private const int m_knownChangedPosition = 1 << 0;
|
private const int m_knownChangedPosition = 1 << 0;
|
||||||
private const int m_knownChangedVelocity = 1 << 1;
|
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_knownChangedRotationalImpulse = 1 << 7;
|
||||||
private const int m_knownChangedTerrainHeight = 1 << 8;
|
private const int m_knownChangedTerrainHeight = 1 << 8;
|
||||||
private const int m_knownChangedWaterLevel = 1 << 9;
|
private const int m_knownChangedWaterLevel = 1 << 9;
|
||||||
private const int m_knownChangedForwardVelocity = 1 <<10;
|
|
||||||
|
|
||||||
public void ForgetKnownVehicleProperties()
|
public void ForgetKnownVehicleProperties()
|
||||||
{
|
{
|
||||||
|
@ -923,12 +921,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if ((m_knownHas & m_knownChangedForwardVelocity) == 0)
|
return VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation));
|
||||||
{
|
|
||||||
m_knownForwardVelocity = VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation));
|
|
||||||
m_knownHas |= m_knownChangedForwardVelocity;
|
|
||||||
}
|
|
||||||
return m_knownForwardVelocity;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private float VehicleForwardSpeed
|
private float VehicleForwardSpeed
|
||||||
|
@ -981,6 +974,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
{
|
{
|
||||||
ComputeLinearVelocity(pTimestep);
|
ComputeLinearVelocity(pTimestep);
|
||||||
|
|
||||||
|
ComputeLinearDeflection(pTimestep);
|
||||||
|
|
||||||
ComputeLinearTerrainHeightCorrection(pTimestep);
|
ComputeLinearTerrainHeightCorrection(pTimestep);
|
||||||
|
|
||||||
ComputeLinearHover(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.
|
// Step the motor from the current value. Get the correction needed this step.
|
||||||
Vector3 origVelW = VehicleVelocity; // DEBUG
|
Vector3 origVelW = VehicleVelocity; // DEBUG
|
||||||
Vector3 currentVelV = VehicleVelocity * Quaternion.Inverse(VehicleOrientation);
|
Vector3 currentVelV = VehicleForwardVelocity;
|
||||||
Vector3 linearMotorCorrectionV = m_linearMotor.Step(pTimestep, currentVelV);
|
Vector3 linearMotorCorrectionV = m_linearMotor.Step(pTimestep, currentVelV);
|
||||||
|
|
||||||
// Friction reduces vehicle motion
|
// Friction reduces vehicle motion based on absolute speed. Slow vehicle down by friction.
|
||||||
Vector3 frictionFactorW = ComputeFrictionFactor(m_linearFrictionTimescale, pTimestep);
|
Vector3 frictionFactorV = ComputeFrictionFactor(m_linearFrictionTimescale, pTimestep);
|
||||||
linearMotorCorrectionV -= (currentVelV * frictionFactorW);
|
linearMotorCorrectionV -= (currentVelV * frictionFactorV);
|
||||||
|
|
||||||
// Motor is vehicle coordinates. Rotate it to world coordinates
|
// Motor is vehicle coordinates. Rotate it to world coordinates
|
||||||
Vector3 linearMotorVelocityW = linearMotorCorrectionV * VehicleOrientation;
|
Vector3 linearMotorVelocityW = linearMotorCorrectionV * VehicleOrientation;
|
||||||
|
@ -1046,11 +1041,38 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
// Add this correction to the velocity to make it faster/slower.
|
// Add this correction to the velocity to make it faster/slower.
|
||||||
VehicleVelocity += linearMotorVelocityW;
|
VehicleVelocity += linearMotorVelocityW;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
VDetailLog("{0}, MoveLinear,velocity,origVelW={1},velV={2},correctV={3},correctW={4},newVelW={5},fricFact={6}",
|
VDetailLog("{0}, MoveLinear,velocity,origVelW={1},velV={2},correctV={3},correctW={4},newVelW={5},fricFact={6}",
|
||||||
ControllingPrim.LocalID, origVelW, currentVelV, linearMotorCorrectionV,
|
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)
|
public void ComputeLinearTerrainHeightCorrection(float pTimestep)
|
||||||
|
@ -1652,6 +1674,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
return frictionFactor;
|
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)
|
private float ClampInRange(float low, float val, float high)
|
||||||
{
|
{
|
||||||
return Math.Max(low, Math.Min(val, high));
|
return Math.Max(low, Math.Min(val, high));
|
||||||
|
|
|
@ -134,6 +134,7 @@ public static class BSParam
|
||||||
public static float AvatarHeightMidFudge { get; private set; }
|
public static float AvatarHeightMidFudge { get; private set; }
|
||||||
public static float AvatarHeightHighFudge { get; private set; }
|
public static float AvatarHeightHighFudge { get; private set; }
|
||||||
public static float AvatarContactProcessingThreshold { 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 AvatarBelowGroundUpCorrectionMeters { get; private set; }
|
||||||
public static float AvatarStepHeight { get; private set; }
|
public static float AvatarStepHeight { get; private set; }
|
||||||
public static float AvatarStepApproachFactor { get; private set; }
|
public static float AvatarStepApproachFactor { get; private set; }
|
||||||
|
@ -567,6 +568,8 @@ public static class BSParam
|
||||||
0.1f ),
|
0.1f ),
|
||||||
new ParameterDefn<float>("AvatarBelowGroundUpCorrectionMeters", "Meters to move avatar up if it seems to be below ground",
|
new ParameterDefn<float>("AvatarBelowGroundUpCorrectionMeters", "Meters to move avatar up if it seems to be below ground",
|
||||||
1.0f ),
|
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",
|
new ParameterDefn<float>("AvatarStepHeight", "Height of a step obstacle to consider step correction",
|
||||||
0.6f ) ,
|
0.6f ) ,
|
||||||
new ParameterDefn<float>("AvatarStepApproachFactor", "Factor to control angle of approach to step (0=straight on)",
|
new ParameterDefn<float>("AvatarStepApproachFactor", "Factor to control angle of approach to step (0=straight on)",
|
||||||
|
|
|
@ -34,6 +34,7 @@ using System.Text;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using OpenSim.Framework.Console;
|
using OpenSim.Framework.Console;
|
||||||
|
using OpenSim.Framework.Monitoring;
|
||||||
using OpenSim.Framework.Servers;
|
using OpenSim.Framework.Servers;
|
||||||
using log4net;
|
using log4net;
|
||||||
using log4net.Config;
|
using log4net.Config;
|
||||||
|
@ -190,16 +191,7 @@ namespace OpenSim.Server.Base
|
||||||
}
|
}
|
||||||
|
|
||||||
RegisterCommonCommands();
|
RegisterCommonCommands();
|
||||||
|
RegisterCommonComponents(Config);
|
||||||
// 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);
|
|
||||||
|
|
||||||
// Allow derived classes to perform initialization that
|
// Allow derived classes to perform initialization that
|
||||||
// needs to be done after the console has opened
|
// needs to be done after the console has opened
|
||||||
|
@ -214,6 +206,9 @@ namespace OpenSim.Server.Base
|
||||||
|
|
||||||
public virtual int Run()
|
public virtual int Run()
|
||||||
{
|
{
|
||||||
|
Watchdog.Enabled = true;
|
||||||
|
MemoryWatchdog.Enabled = true;
|
||||||
|
|
||||||
while (m_Running)
|
while (m_Running)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -231,11 +226,12 @@ namespace OpenSim.Server.Base
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void HandleQuit(string module, string[] args)
|
protected override void ShutdownSpecific()
|
||||||
{
|
{
|
||||||
m_Running = false;
|
m_Running = false;
|
||||||
m_log.Info("[CONSOLE] Quitting");
|
m_log.Info("[CONSOLE] Quitting");
|
||||||
|
|
||||||
|
base.ShutdownSpecific();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void ReadConfig()
|
protected virtual void ReadConfig()
|
||||||
|
@ -246,4 +242,4 @@ namespace OpenSim.Server.Base
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -61,7 +61,7 @@ namespace OpenSim.Server.Handlers.Hypergrid
|
||||||
m_Proxy = proxy;
|
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);
|
return m_GatekeeperService.LoginAgent(aCircuit, destination, out reason);
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,191 +49,87 @@ using log4net;
|
||||||
|
|
||||||
namespace OpenSim.Server.Handlers.Hypergrid
|
namespace OpenSim.Server.Handlers.Hypergrid
|
||||||
{
|
{
|
||||||
public class HomeAgentHandler
|
public class HomeAgentHandler : AgentPostHandler
|
||||||
{
|
{
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
private IUserAgentService m_UserAgentService;
|
private IUserAgentService m_UserAgentService;
|
||||||
|
|
||||||
private string m_LoginServerIP;
|
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_UserAgentService = userAgentService;
|
||||||
m_LoginServerIP = loginServerIP;
|
m_LoginServerIP = loginServerIP;
|
||||||
m_Proxy = proxy;
|
m_Proxy = proxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Hashtable Handler(Hashtable request)
|
protected override AgentDestinationData CreateAgentDestinationData()
|
||||||
{
|
{
|
||||||
// m_log.Debug("[CONNECTION DEBUGGING]: HomeAgentHandler Called");
|
return new ExtendedAgentDestinationData();
|
||||||
//
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
protected override void UnpackData(OSDMap args, AgentDestinationData d, Hashtable request)
|
||||||
protected void DoAgentPost(Hashtable request, Hashtable responsedata, UUID id)
|
|
||||||
{
|
{
|
||||||
OSDMap args = Utils.GetOSDMap((string)request["body"]);
|
base.UnpackData(args, d, request);
|
||||||
if (args == null)
|
ExtendedAgentDestinationData data = (ExtendedAgentDestinationData)d;
|
||||||
{
|
|
||||||
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();
|
|
||||||
try
|
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);
|
m_log.ErrorFormat("[HOME AGENT HANDLER]: Bad cast in UnpackData");
|
||||||
responsedata["int_response_code"] = HttpStatusCode.BadRequest;
|
|
||||||
responsedata["str_response_string"] = "Bad request";
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OSDMap resp = new OSDMap(2);
|
string callerIP = GetCallerIP(request);
|
||||||
string reason = String.Empty;
|
// 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)
|
if (d is ExtendedAgentDestinationData)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
m_log.WarnFormat("[AGENT HANDLER]: No XFF header");
|
ExtendedAgentDestinationData data = (ExtendedAgentDestinationData)d;
|
||||||
return Util.GetCallerIP(request);
|
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]);
|
return null;
|
||||||
|
|
||||||
IPEndPoint ep = Util.GetClientIPFromXFF((string)headers[xff]);
|
|
||||||
if (ep != null)
|
|
||||||
return ep.Address.ToString();
|
|
||||||
|
|
||||||
// Oops
|
|
||||||
return Util.GetCallerIP(request);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,7 +108,7 @@ namespace OpenSim.Server.Handlers.Hypergrid
|
||||||
server.AddXmlRPCHandler("get_uui", GetUUI, false);
|
server.AddXmlRPCHandler("get_uui", GetUUI, false);
|
||||||
server.AddXmlRPCHandler("get_uuid", GetUUID, 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)
|
public XmlRpcResponse GetHomeRegion(XmlRpcRequest request, IPEndPoint remoteClient)
|
||||||
|
|
|
@ -351,31 +351,16 @@ namespace OpenSim.Server.Handlers.Simulation
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// retrieve the input arguments
|
AgentDestinationData data = CreateAgentDestinationData();
|
||||||
int x = 0, y = 0;
|
UnpackData(args, data, request);
|
||||||
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();
|
|
||||||
|
|
||||||
GridRegion destination = new GridRegion();
|
GridRegion destination = new GridRegion();
|
||||||
destination.RegionID = uuid;
|
destination.RegionID = data.uuid;
|
||||||
destination.RegionLocX = x;
|
destination.RegionLocX = data.x;
|
||||||
destination.RegionLocY = y;
|
destination.RegionLocY = data.y;
|
||||||
destination.RegionName = regionname;
|
destination.RegionName = data.name;
|
||||||
|
|
||||||
|
GridRegion gatekeeper = ExtractGatekeeper(data);
|
||||||
|
|
||||||
AgentCircuitData aCircuit = new AgentCircuitData();
|
AgentCircuitData aCircuit = new AgentCircuitData();
|
||||||
try
|
try
|
||||||
|
@ -396,7 +381,7 @@ namespace OpenSim.Server.Handlers.Simulation
|
||||||
// This is the meaning of POST agent
|
// This is the meaning of POST agent
|
||||||
//m_regionClient.AdjustUserInformation(aCircuit);
|
//m_regionClient.AdjustUserInformation(aCircuit);
|
||||||
//bool result = m_SimulationService.CreateAgent(destination, aCircuit, teleportFlags, out reason);
|
//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["reason"] = OSD.FromString(reason);
|
||||||
resp["success"] = OSD.FromBoolean(result);
|
resp["success"] = OSD.FromBoolean(result);
|
||||||
|
@ -408,7 +393,36 @@ namespace OpenSim.Server.Handlers.Simulation
|
||||||
responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp);
|
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)
|
if (!m_Proxy)
|
||||||
return Util.GetCallerIP(request);
|
return Util.GetCallerIP(request);
|
||||||
|
@ -441,7 +455,7 @@ namespace OpenSim.Server.Handlers.Simulation
|
||||||
}
|
}
|
||||||
|
|
||||||
// subclasses can override this
|
// 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)
|
||||||
{
|
{
|
||||||
reason = String.Empty;
|
reason = String.Empty;
|
||||||
|
|
||||||
|
@ -593,7 +607,6 @@ namespace OpenSim.Server.Handlers.Simulation
|
||||||
//agent.Dump();
|
//agent.Dump();
|
||||||
// This is one of the meanings of PUT agent
|
// This is one of the meanings of PUT agent
|
||||||
result = UpdateAgent(destination, agent);
|
result = UpdateAgent(destination, agent);
|
||||||
|
|
||||||
}
|
}
|
||||||
else if ("AgentPosition".Equals(messageType))
|
else if ("AgentPosition".Equals(messageType))
|
||||||
{
|
{
|
||||||
|
@ -624,4 +637,14 @@ namespace OpenSim.Server.Handlers.Simulation
|
||||||
return m_SimulationService.UpdateAgent(destination, agent);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,8 @@ namespace OpenSim.Services.Connectors.Hypergrid
|
||||||
|
|
||||||
private IAssetService m_AssetService;
|
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"]);
|
realHandle = Convert.ToUInt64((string)hash["handle"]);
|
||||||
//m_log.Debug(">> HERE, realHandle: " + realHandle);
|
//m_log.Debug(">> HERE, realHandle: " + realHandle);
|
||||||
}
|
}
|
||||||
if (hash["region_image"] != null) {
|
if (hash["region_image"] != null)
|
||||||
|
{
|
||||||
imageURL = (string)hash["region_image"];
|
imageURL = (string)hash["region_image"];
|
||||||
//m_log.Debug(">> HERE, imageURL: " + imageURL);
|
//m_log.Debug(">> HERE, imageURL: " + imageURL);
|
||||||
}
|
}
|
||||||
if (hash["external_name"] != null) {
|
if (hash["external_name"] != null)
|
||||||
|
{
|
||||||
externalName = (string)hash["external_name"];
|
externalName = (string)hash["external_name"];
|
||||||
//m_log.Debug(">> HERE, externalName: " + externalName);
|
//m_log.Debug(">> HERE, externalName: " + externalName);
|
||||||
}
|
}
|
||||||
|
@ -179,7 +182,7 @@ namespace OpenSim.Services.Connectors.Hypergrid
|
||||||
//m_log.Debug("Size: " + m.PhysicalDimension.Height + "-" + m.PhysicalDimension.Width);
|
//m_log.Debug("Size: " + m.PhysicalDimension.Height + "-" + m.PhysicalDimension.Width);
|
||||||
imageData = OpenJPEG.EncodeFromImage(bitmap, true);
|
imageData = OpenJPEG.EncodeFromImage(bitmap, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
AssetBase ass = new AssetBase(UUID.Random(), "region " + name, (sbyte)AssetType.Texture, regionID.ToString());
|
AssetBase ass = new AssetBase(UUID.Random(), "region " + name, (sbyte)AssetType.Texture, regionID.ToString());
|
||||||
|
|
||||||
// !!! for now
|
// !!! for now
|
||||||
|
@ -257,7 +260,8 @@ namespace OpenSim.Services.Connectors.Hypergrid
|
||||||
region.RegionName = (string)hash["region_name"];
|
region.RegionName = (string)hash["region_name"];
|
||||||
//m_log.Debug(">> HERE, region_name: " + region.RegionName);
|
//m_log.Debug(">> HERE, region_name: " + region.RegionName);
|
||||||
}
|
}
|
||||||
if (hash["hostname"] != null) {
|
if (hash["hostname"] != null)
|
||||||
|
{
|
||||||
region.ExternalHostName = (string)hash["hostname"];
|
region.ExternalHostName = (string)hash["hostname"];
|
||||||
//m_log.Debug(">> HERE, hostname: " + region.ExternalHostName);
|
//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);
|
region.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), p);
|
||||||
//m_log.Debug(">> HERE, internal_port: " + region.InternalEndPoint);
|
//m_log.Debug(">> HERE, internal_port: " + region.InternalEndPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hash["server_uri"] != null)
|
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);
|
//m_log.Debug(">> HERE, server_uri: " + region.ServerURI);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,55 +299,5 @@ namespace OpenSim.Services.Connectors.Hypergrid
|
||||||
|
|
||||||
return null;
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,13 +44,14 @@ using Nini.Config;
|
||||||
|
|
||||||
namespace OpenSim.Services.Connectors.Hypergrid
|
namespace OpenSim.Services.Connectors.Hypergrid
|
||||||
{
|
{
|
||||||
public class UserAgentServiceConnector : IUserAgentService
|
public class UserAgentServiceConnector : SimulationServiceConnector, IUserAgentService
|
||||||
{
|
{
|
||||||
private static readonly ILog m_log =
|
private static readonly ILog m_log =
|
||||||
LogManager.GetLogger(
|
LogManager.GetLogger(
|
||||||
MethodBase.GetCurrentMethod().DeclaringType);
|
MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
string m_ServerURL;
|
private string m_ServerURL;
|
||||||
|
private GridRegion m_Gatekeeper;
|
||||||
|
|
||||||
public UserAgentServiceConnector(string url) : this(url, true)
|
public UserAgentServiceConnector(string url) : this(url, true)
|
||||||
{
|
{
|
||||||
|
@ -102,9 +103,15 @@ namespace OpenSim.Services.Connectors.Hypergrid
|
||||||
m_log.DebugFormat("[USER AGENT CONNECTOR]: UserAgentServiceConnector started for {0}", m_ServerURL);
|
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
|
// The Login service calls this interface with fromLogin=true
|
||||||
public bool LoginAgentToGrid(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, IPEndPoint ipaddress, out string reason)
|
// 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;
|
reason = String.Empty;
|
||||||
|
|
||||||
|
@ -115,119 +122,34 @@ namespace OpenSim.Services.Connectors.Hypergrid
|
||||||
return false;
|
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);
|
Console.WriteLine(" >>> LoginAgentToGrid <<< " + home.ServerURI);
|
||||||
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;
|
|
||||||
|
|
||||||
|
uint flags = fromLogin ? (uint)TeleportFlags.ViaLogin : (uint)TeleportFlags.ViaHome;
|
||||||
|
return CreateAgent(home, aCircuit, flags, out reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// The simulators call this interface
|
// The simulators call this interface
|
||||||
public bool LoginAgentToGrid(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, out string reason)
|
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)
|
protected OSDMap PackCreateAgentArguments(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, IPEndPoint ipaddress)
|
||||||
|
|
|
@ -79,11 +79,27 @@ namespace OpenSim.Services.Connectors.Simulation
|
||||||
return "agent/";
|
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)
|
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;
|
reason = String.Empty;
|
||||||
|
myipaddress = String.Empty;
|
||||||
|
|
||||||
if (destination == null)
|
if (destination == null)
|
||||||
{
|
{
|
||||||
reason = "Destination not found";
|
reason = "Destination not found";
|
||||||
|
@ -96,12 +112,7 @@ namespace OpenSim.Services.Connectors.Simulation
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
OSDMap args = aCircuit.PackAgentCircuitData();
|
OSDMap args = aCircuit.PackAgentCircuitData();
|
||||||
|
PackData(args, aCircuit, destination, 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());
|
|
||||||
|
|
||||||
OSDMap result = WebUtil.PostToServiceCompressed(uri, args, 30000);
|
OSDMap result = WebUtil.PostToServiceCompressed(uri, args, 30000);
|
||||||
bool success = result["success"].AsBoolean();
|
bool success = result["success"].AsBoolean();
|
||||||
|
@ -111,6 +122,7 @@ namespace OpenSim.Services.Connectors.Simulation
|
||||||
|
|
||||||
reason = data["reason"].AsString();
|
reason = data["reason"].AsString();
|
||||||
success = data["success"].AsBoolean();
|
success = data["success"].AsBoolean();
|
||||||
|
myipaddress = data["your_ip"].AsString();
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,6 +137,7 @@ namespace OpenSim.Services.Connectors.Simulation
|
||||||
|
|
||||||
reason = data["reason"].AsString();
|
reason = data["reason"].AsString();
|
||||||
success = data["success"].AsBoolean();
|
success = data["success"].AsBoolean();
|
||||||
|
myipaddress = data["your_ip"].AsString();
|
||||||
m_log.WarnFormat(
|
m_log.WarnFormat(
|
||||||
"[REMOTE SIMULATION CONNECTOR]: Remote simulator {0} did not accept compressed transfer, suggest updating it.", destination.RegionName);
|
"[REMOTE SIMULATION CONNECTOR]: Remote simulator {0} did not accept compressed transfer, suggest updating it.", destination.RegionName);
|
||||||
return success;
|
return success;
|
||||||
|
@ -229,7 +242,7 @@ namespace OpenSim.Services.Connectors.Simulation
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private bool UpdateAgent(GridRegion destination, IAgentData cAgentData, int timeout)
|
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
|
// Eventually, we want to use a caps url instead of the agentID
|
||||||
string uri = destination.ServerURI + AgentPath() + cAgentData.AgentID + "/";
|
string uri = destination.ServerURI + AgentPath() + cAgentData.AgentID + "/";
|
||||||
|
|
|
@ -210,10 +210,10 @@ namespace OpenSim.Services.HypergridService
|
||||||
return home;
|
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}",
|
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;
|
string gridName = gatekeeper.ServerURI;
|
||||||
|
|
||||||
|
@ -265,7 +265,7 @@ namespace OpenSim.Services.HypergridService
|
||||||
bool success = false;
|
bool success = false;
|
||||||
string myExternalIP = string.Empty;
|
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)
|
if (m_GridName == gridName)
|
||||||
success = m_GatekeeperService.LoginAgent(agentCircuit, finalDestination, out reason);
|
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);
|
m_log.DebugFormat("[USER AGENT SERVICE]: Gatekeeper sees me as {0}", myExternalIP);
|
||||||
// else set the IP addresses associated with this client
|
// else set the IP addresses associated with this client
|
||||||
if (clientIP != null)
|
if (fromLogin)
|
||||||
m_TravelingAgents[agentCircuit.SessionID].ClientIPAddress = clientIP.Address.ToString();
|
m_TravelingAgents[agentCircuit.SessionID].ClientIPAddress = agentCircuit.IPAddress;
|
||||||
m_TravelingAgents[agentCircuit.SessionID].MyIpAddress = myExternalIP;
|
m_TravelingAgents[agentCircuit.SessionID].MyIpAddress = myExternalIP;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -306,7 +306,7 @@ namespace OpenSim.Services.HypergridService
|
||||||
public bool LoginAgentToGrid(AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, out string reason)
|
public bool LoginAgentToGrid(AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, out string reason)
|
||||||
{
|
{
|
||||||
reason = string.Empty;
|
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)
|
private void SetClientIP(UUID sessionID, string ip)
|
||||||
|
|
|
@ -48,10 +48,7 @@ namespace OpenSim.Services.Interfaces
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IUserAgentService
|
public interface IUserAgentService
|
||||||
{
|
{
|
||||||
// called by login service only
|
bool LoginAgentToGrid(AgentCircuitData agent, GridRegion gatekeeper, GridRegion finalDestination, bool fromLogin, out string reason);
|
||||||
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);
|
|
||||||
void LogoutAgent(UUID userID, UUID sessionID);
|
void LogoutAgent(UUID userID, UUID sessionID);
|
||||||
GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt);
|
GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt);
|
||||||
Dictionary<string, object> GetServerURLs(UUID userID);
|
Dictionary<string, object> GetServerURLs(UUID userID);
|
||||||
|
|
|
@ -941,7 +941,7 @@ namespace OpenSim.Services.LLLoginService
|
||||||
private bool LaunchAgentIndirectly(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, IPEndPoint clientIP, out string reason)
|
private bool LaunchAgentIndirectly(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, IPEndPoint clientIP, out string reason)
|
||||||
{
|
{
|
||||||
m_log.Debug("[LLOGIN SERVICE] Launching agent at " + destination.RegionName);
|
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 true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -157,6 +157,7 @@
|
||||||
<Reference name="System"/>
|
<Reference name="System"/>
|
||||||
<Reference name="System.Core"/>
|
<Reference name="System.Core"/>
|
||||||
<Reference name="log4net" path="../../../bin/"/>
|
<Reference name="log4net" path="../../../bin/"/>
|
||||||
|
<Reference name="Nini" path="../../../bin/"/>
|
||||||
<Reference name="OpenMetaverseTypes" path="../../../bin/"/>
|
<Reference name="OpenMetaverseTypes" path="../../../bin/"/>
|
||||||
<Reference name="OpenMetaverse" path="../../../bin/"/>
|
<Reference name="OpenMetaverse" path="../../../bin/"/>
|
||||||
<Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/>
|
<Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/>
|
||||||
|
@ -863,6 +864,7 @@
|
||||||
<Reference name="Mono.Addins.Setup" path="../../../bin/"/>
|
<Reference name="Mono.Addins.Setup" path="../../../bin/"/>
|
||||||
<Reference name="OpenSim.Framework"/>
|
<Reference name="OpenSim.Framework"/>
|
||||||
<Reference name="OpenSim.Framework.Console"/>
|
<Reference name="OpenSim.Framework.Console"/>
|
||||||
|
<Reference name="OpenSim.Framework.Monitoring"/>
|
||||||
<Reference name="OpenSim.Framework.Servers"/>
|
<Reference name="OpenSim.Framework.Servers"/>
|
||||||
<Reference name="OpenSim.Framework.Servers.HttpServer"/>
|
<Reference name="OpenSim.Framework.Servers.HttpServer"/>
|
||||||
<Reference name="Nini" path="../../../bin/"/>
|
<Reference name="Nini" path="../../../bin/"/>
|
||||||
|
|
Loading…
Reference in New Issue