Merge branch 'master' into careminster

Conflicts:
	OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
	OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
	OpenSim/Region/Framework/Scenes/Scene.cs
avinationmerge
Melanie 2013-08-07 23:29:42 +01:00
commit 005c69511d
47 changed files with 1434 additions and 216 deletions

View File

@ -467,12 +467,12 @@ namespace OpenSim.Groups
}
// Send notice out to everyone that wants notices
// Build notice IIM
GridInstantMessage msg = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice);
foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetRequestingAgentIDStr(remoteClient), GroupID))
{
if (member.AcceptNotices)
{
// Build notice IIM, one of reach, because the sending may be async
GridInstantMessage msg = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice);
msg.toAgentID = member.AgentID.Guid;
OutgoingInstantMessage(msg, member.AgentID);
}

View File

@ -292,6 +292,12 @@ namespace OpenSim.Framework
public Vector3 AtAxis;
public Vector3 LeftAxis;
public Vector3 UpAxis;
/// <summary>
/// Signal on a V2 teleport that Scene.IncomingChildAgentDataUpdate(AgentData ad) should wait for the
/// scene presence to become root (triggered when the viewer sends a CompleteAgentMovement UDP packet after
/// establishing the connection triggered by it's receipt of a TeleportFinish EQ message).
/// </summary>
public bool SenderWantsToWaitForRoot;
public float Far;

View File

@ -156,7 +156,27 @@ namespace OpenSim.Framework.Console
}
/// <summary>
/// Convert a minimum vector input from the console to an OpenMetaverse.Vector3
/// Convert a console integer to an int, automatically complaining if a console is given.
/// </summary>
/// <param name='console'>Can be null if no console is available.</param>
/// <param name='rawConsoleVector'>/param>
/// <param name='vector'></param>
/// <returns></returns>
public static bool TryParseConsoleBool(ICommandConsole console, string rawConsoleString, out bool b)
{
if (!bool.TryParse(rawConsoleString, out b))
{
if (console != null)
console.OutputFormat("ERROR: {0} is not a true or false value", rawConsoleString);
return false;
}
return true;
}
/// <summary>
/// Convert a console integer to an int, automatically complaining if a console is given.
/// </summary>
/// <param name='console'>Can be null if no console is available.</param>
/// <param name='rawConsoleVector'>/param>

View File

@ -0,0 +1,118 @@
/*
* 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.Text;
namespace OpenSim.Framework.Monitoring
{
public class Check
{
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public static readonly char[] DisallowedShortNameCharacters = { '.' };
/// <summary>
/// Category of this stat (e.g. cache, scene, etc).
/// </summary>
public string Category { get; private set; }
/// <summary>
/// Containing name for this stat.
/// FIXME: In the case of a scene, this is currently the scene name (though this leaves
/// us with a to-be-resolved problem of non-unique region names).
/// </summary>
/// <value>
/// The container.
/// </value>
public string Container { get; private set; }
/// <summary>
/// Action used to check whether alert should go off.
/// </summary>
/// <remarks>
/// Should return true if check passes. False otherwise.
/// </remarks>
public Func<Check, bool> CheckFunc { get; private set; }
/// <summary>
/// Message from the last failure, if any. If there is no message or no failure then will be null.
/// </summary>
/// <remarks>
/// Should be set by the CheckFunc when applicable.
/// </remarks>
public string LastFailureMessage { get; set; }
public StatVerbosity Verbosity { get; private set; }
public string ShortName { get; private set; }
public string Name { get; private set; }
public string Description { get; private set; }
public Check(
string shortName,
string name,
string description,
string category,
string container,
Func<Check, bool> checkFunc,
StatVerbosity verbosity)
{
if (ChecksManager.SubCommands.Contains(category))
throw new Exception(
string.Format("Alert 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("Alert name {0} cannot contain character {1}", shortName, c));
}
ShortName = shortName;
Name = name;
Description = description;
Category = category;
Container = container;
CheckFunc = checkFunc;
Verbosity = verbosity;
}
public bool CheckIt()
{
return CheckFunc(this);
}
public virtual string ToConsoleString()
{
return string.Format(
"{0}.{1}.{2} - {3}",
Category,
Container,
ShortName,
Description);
}
}
}

View File

@ -0,0 +1,262 @@
/*
* 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.Linq;
using System.Reflection;
using System.Text;
using log4net;
namespace OpenSim.Framework.Monitoring
{
/// <summary>
/// Static class used to register/deregister checks on runtime conditions.
/// </summary>
public static class ChecksManager
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
// Subcommand used to list other stats.
public const string ListSubCommand = "list";
// All subcommands
public static HashSet<string> SubCommands = new HashSet<string> { ListSubCommand };
/// <summary>
/// Checks categorized by category/container/shortname
/// </summary>
/// <remarks>
/// Do not add or remove directly from this dictionary.
/// </remarks>
public static SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Check>>> RegisteredChecks
= new SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Check>>>();
public static void RegisterConsoleCommands(ICommandConsole console)
{
console.Commands.AddCommand(
"General",
false,
"show checks",
"show checks",
"Show checks configured for this server",
"If no argument is specified then info on all checks will be shown.\n"
+ "'list' argument will show check categories.\n"
+ "THIS FACILITY IS EXPERIMENTAL",
HandleShowchecksCommand);
}
public static void HandleShowchecksCommand(string module, string[] cmd)
{
ICommandConsole con = MainConsole.Instance;
if (cmd.Length > 2)
{
foreach (string name in cmd.Skip(2))
{
string[] components = name.Split('.');
string categoryName = components[0];
// string containerName = components.Length > 1 ? components[1] : null;
if (categoryName == ListSubCommand)
{
con.Output("check categories available are:");
foreach (string category in RegisteredChecks.Keys)
con.OutputFormat(" {0}", category);
}
// else
// {
// SortedDictionary<string, SortedDictionary<string, Check>> category;
// if (!Registeredchecks.TryGetValue(categoryName, out category))
// {
// con.OutputFormat("No such category as {0}", categoryName);
// }
// else
// {
// if (String.IsNullOrEmpty(containerName))
// {
// OutputConfiguredToConsole(con, category);
// }
// else
// {
// SortedDictionary<string, Check> container;
// if (category.TryGetValue(containerName, out container))
// {
// OutputContainerChecksToConsole(con, container);
// }
// else
// {
// con.OutputFormat("No such container {0} in category {1}", containerName, categoryName);
// }
// }
// }
// }
}
}
else
{
OutputAllChecksToConsole(con);
}
}
/// <summary>
/// Registers a statistic.
/// </summary>
/// <param name='stat'></param>
/// <returns></returns>
public static bool RegisterCheck(Check check)
{
SortedDictionary<string, SortedDictionary<string, Check>> category = null, newCategory;
SortedDictionary<string, Check> container = null, newContainer;
lock (RegisteredChecks)
{
// Check name is not unique across category/container/shortname key.
// XXX: For now just return false. This is to avoid problems in regression tests where all tests
// in a class are run in the same instance of the VM.
if (TryGetCheckParents(check, out category, out container))
return false;
// We take a copy-on-write approach here of replacing dictionaries when keys are added or removed.
// This means that we don't need to lock or copy them on iteration, which will be a much more
// common operation after startup.
if (container != null)
newContainer = new SortedDictionary<string, Check>(container);
else
newContainer = new SortedDictionary<string, Check>();
if (category != null)
newCategory = new SortedDictionary<string, SortedDictionary<string, Check>>(category);
else
newCategory = new SortedDictionary<string, SortedDictionary<string, Check>>();
newContainer[check.ShortName] = check;
newCategory[check.Container] = newContainer;
RegisteredChecks[check.Category] = newCategory;
}
return true;
}
/// <summary>
/// Deregister an check
/// </summary>>
/// <param name='stat'></param>
/// <returns></returns>
public static bool DeregisterCheck(Check check)
{
SortedDictionary<string, SortedDictionary<string, Check>> category = null, newCategory;
SortedDictionary<string, Check> container = null, newContainer;
lock (RegisteredChecks)
{
if (!TryGetCheckParents(check, out category, out container))
return false;
newContainer = new SortedDictionary<string, Check>(container);
newContainer.Remove(check.ShortName);
newCategory = new SortedDictionary<string, SortedDictionary<string, Check>>(category);
newCategory.Remove(check.Container);
newCategory[check.Container] = newContainer;
RegisteredChecks[check.Category] = newCategory;
return true;
}
}
public static bool TryGetCheckParents(
Check check,
out SortedDictionary<string, SortedDictionary<string, Check>> category,
out SortedDictionary<string, Check> container)
{
category = null;
container = null;
lock (RegisteredChecks)
{
if (RegisteredChecks.TryGetValue(check.Category, out category))
{
if (category.TryGetValue(check.Container, out container))
{
if (container.ContainsKey(check.ShortName))
return true;
}
}
}
return false;
}
public static void CheckChecks()
{
lock (RegisteredChecks)
{
foreach (SortedDictionary<string, SortedDictionary<string, Check>> category in RegisteredChecks.Values)
{
foreach (SortedDictionary<string, Check> container in category.Values)
{
foreach (Check check in container.Values)
{
if (!check.CheckIt())
m_log.WarnFormat(
"[CHECKS MANAGER]: Check {0}.{1}.{2} failed with message {3}", check.Category, check.Container, check.ShortName, check.LastFailureMessage);
}
}
}
}
}
private static void OutputAllChecksToConsole(ICommandConsole con)
{
foreach (var category in RegisteredChecks.Values)
{
OutputCategoryChecksToConsole(con, category);
}
}
private static void OutputCategoryChecksToConsole(
ICommandConsole con, SortedDictionary<string, SortedDictionary<string, Check>> category)
{
foreach (var container in category.Values)
{
OutputContainerChecksToConsole(con, container);
}
}
private static void OutputContainerChecksToConsole(ICommandConsole con, SortedDictionary<string, Check> container)
{
foreach (Check check in container.Values)
{
con.Output(check.ToConsoleString());
}
}
}
}

View File

@ -0,0 +1,108 @@
/*
* 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.Reflection;
using System.Timers;
using log4net;
namespace OpenSim.Framework.Monitoring
{
/// <summary>
/// Provides a means to continuously log stats for debugging purposes.
/// </summary>
public static class StatsLogger
{
private static readonly ILog m_statsLog = LogManager.GetLogger("special.StatsLogger");
private static Timer m_loggingTimer;
private static int m_statsLogIntervalMs = 5000;
public static void RegisterConsoleCommands(ICommandConsole console)
{
console.Commands.AddCommand(
"Debug",
false,
"debug stats record",
"debug stats record start|stop",
"Control whether stats are being regularly recorded to a separate file.",
"For debug purposes. Experimental.",
HandleStatsRecordCommand);
}
public static void HandleStatsRecordCommand(string module, string[] cmd)
{
ICommandConsole con = MainConsole.Instance;
if (cmd.Length != 4)
{
con.Output("Usage: debug stats record start|stop");
return;
}
if (cmd[3] == "start")
{
Start();
con.OutputFormat("Now recording all stats very {0}ms to file", m_statsLogIntervalMs);
}
else if (cmd[3] == "stop")
{
Stop();
con.Output("Stopped recording stats to file.");
}
}
public static void Start()
{
if (m_loggingTimer != null)
Stop();
m_loggingTimer = new Timer(m_statsLogIntervalMs);
m_loggingTimer.AutoReset = false;
m_loggingTimer.Elapsed += Log;
m_loggingTimer.Start();
}
public static void Stop()
{
if (m_loggingTimer != null)
{
m_loggingTimer.Stop();
}
}
private static void Log(object sender, ElapsedEventArgs e)
{
m_statsLog.InfoFormat("*** STATS REPORT AT {0} ***", DateTime.Now);
foreach (string report in StatsManager.GetAllStatsReports())
m_statsLog.Info(report);
m_loggingTimer.Start();
}
}
}

View File

@ -35,9 +35,9 @@ using OpenMetaverse.StructuredData;
namespace OpenSim.Framework.Monitoring
{
/// <summary>
/// Singleton used to provide access to statistics reporters
/// Static class used to register/deregister/fetch statistics
/// </summary>
public class StatsManager
public static class StatsManager
{
// Subcommand used to list other stats.
public const string AllSubCommand = "all";
@ -81,6 +81,8 @@ namespace OpenSim.Framework.Monitoring
+ "More than one name can be given separated by spaces.\n"
+ "THIS STATS FACILITY IS EXPERIMENTAL AND DOES NOT YET CONTAIN ALL STATS",
HandleShowStatsCommand);
StatsLogger.RegisterConsoleCommands(console);
}
public static void HandleShowStatsCommand(string module, string[] cmd)
@ -145,29 +147,55 @@ namespace OpenSim.Framework.Monitoring
}
}
public static List<string> GetAllStatsReports()
{
List<string> reports = new List<string>();
foreach (var category in RegisteredStats.Values)
reports.AddRange(GetCategoryStatsReports(category));
return reports;
}
private static void OutputAllStatsToConsole(ICommandConsole con)
{
foreach (var category in RegisteredStats.Values)
{
OutputCategoryStatsToConsole(con, category);
}
foreach (string report in GetAllStatsReports())
con.Output(report);
}
private static List<string> GetCategoryStatsReports(
SortedDictionary<string, SortedDictionary<string, Stat>> category)
{
List<string> reports = new List<string>();
foreach (var container in category.Values)
reports.AddRange(GetContainerStatsReports(container));
return reports;
}
private static void OutputCategoryStatsToConsole(
ICommandConsole con, SortedDictionary<string, SortedDictionary<string, Stat>> category)
{
foreach (var container in category.Values)
{
OutputContainerStatsToConsole(con, container);
}
foreach (string report in GetCategoryStatsReports(category))
con.Output(report);
}
private static void OutputContainerStatsToConsole( ICommandConsole con, SortedDictionary<string, Stat> container)
private static List<string> GetContainerStatsReports(SortedDictionary<string, Stat> container)
{
List<string> reports = new List<string>();
foreach (Stat stat in container.Values)
{
con.Output(stat.ToConsoleString());
}
reports.Add(stat.ToConsoleString());
return reports;
}
private static void OutputContainerStatsToConsole(
ICommandConsole con, SortedDictionary<string, Stat> container)
{
foreach (string report in GetContainerStatsReports(container))
con.Output(report);
}
// Creates an OSDMap of the format:
@ -257,7 +285,7 @@ namespace OpenSim.Framework.Monitoring
// }
/// <summary>
/// Registers a statistic.
/// Register a statistic.
/// </summary>
/// <param name='stat'></param>
/// <returns></returns>

View File

@ -380,6 +380,7 @@ namespace OpenSim.Framework.Monitoring
if (MemoryWatchdog.Enabled)
MemoryWatchdog.Update();
ChecksManager.CheckChecks();
StatsManager.RecordStats();
m_watchdogTimer.Start();

View File

@ -246,7 +246,7 @@ namespace OpenSim.Framework.Servers
"Show thread status", HandleShow);
m_console.Commands.AddCommand(
"General", false, "threads abort",
"Debug", false, "threads abort",
"threads abort <thread-id>",
"Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort);
@ -256,8 +256,32 @@ namespace OpenSim.Framework.Servers
"Show thread status. Synonym for \"show threads\"",
(string module, string[] args) => Notice(GetThreadsReport()));
m_console.Commands.AddCommand (
"Debug", false, "debug comms set",
"debug comms set serialosdreq true|false",
"Set comms parameters. For debug purposes.",
HandleDebugCommsSet);
m_console.Commands.AddCommand (
"Debug", false, "debug comms status",
"debug comms status",
"Show current debug comms parameters.",
HandleDebugCommsStatus);
m_console.Commands.AddCommand (
"Debug", false, "debug threadpool set",
"debug threadpool set worker|iocp min|max <n>",
"Set threadpool parameters. For debug purposes.",
HandleDebugThreadpoolSet);
m_console.Commands.AddCommand (
"Debug", false, "debug threadpool status",
"debug threadpool status",
"Show current debug threadpool parameters.",
HandleDebugThreadpoolStatus);
m_console.Commands.AddCommand(
"General", false, "force gc",
"Debug", false, "force gc",
"force gc",
"Manually invoke runtime garbage collection. For debugging purposes",
HandleForceGc);
@ -272,16 +296,142 @@ namespace OpenSim.Framework.Servers
"shutdown",
"Quit the application", (mod, args) => Shutdown());
ChecksManager.RegisterConsoleCommands(m_console);
StatsManager.RegisterConsoleCommands(m_console);
}
public void RegisterCommonComponents(IConfigSource configSource)
{
IConfig networkConfig = configSource.Configs["Network"];
if (networkConfig != null)
{
WebUtil.SerializeOSDRequestsPerEndpoint = networkConfig.GetBoolean("SerializeOSDRequests", false);
}
m_serverStatsCollector = new ServerStatsCollector();
m_serverStatsCollector.Initialise(configSource);
m_serverStatsCollector.Start();
}
private void HandleDebugCommsStatus(string module, string[] args)
{
Notice("serialosdreq is {0}", WebUtil.SerializeOSDRequestsPerEndpoint);
}
private void HandleDebugCommsSet(string module, string[] args)
{
if (args.Length != 5)
{
Notice("Usage: debug comms set serialosdreq true|false");
return;
}
if (args[3] != "serialosdreq")
{
Notice("Usage: debug comms set serialosdreq true|false");
return;
}
bool setSerializeOsdRequests;
if (!ConsoleUtil.TryParseConsoleBool(m_console, args[4], out setSerializeOsdRequests))
return;
WebUtil.SerializeOSDRequestsPerEndpoint = setSerializeOsdRequests;
Notice("serialosdreq is now {0}", setSerializeOsdRequests);
}
private void HandleDebugThreadpoolStatus(string module, string[] args)
{
int workerThreads, iocpThreads;
ThreadPool.GetMinThreads(out workerThreads, out iocpThreads);
Notice("Min worker threads: {0}", workerThreads);
Notice("Min IOCP threads: {0}", iocpThreads);
ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads);
Notice("Max worker threads: {0}", workerThreads);
Notice("Max IOCP threads: {0}", iocpThreads);
ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads);
Notice("Available worker threads: {0}", workerThreads);
Notice("Available IOCP threads: {0}", iocpThreads);
}
private void HandleDebugThreadpoolSet(string module, string[] args)
{
if (args.Length != 6)
{
Notice("Usage: debug threadpool set worker|iocp min|max <n>");
return;
}
int newThreads;
if (!ConsoleUtil.TryParseConsoleInt(m_console, args[5], out newThreads))
return;
string poolType = args[3];
string bound = args[4];
bool fail = false;
int workerThreads, iocpThreads;
if (poolType == "worker")
{
if (bound == "min")
{
ThreadPool.GetMinThreads(out workerThreads, out iocpThreads);
if (!ThreadPool.SetMinThreads(newThreads, iocpThreads))
fail = true;
}
else
{
ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads);
if (!ThreadPool.SetMaxThreads(newThreads, iocpThreads))
fail = true;
}
}
else
{
if (bound == "min")
{
ThreadPool.GetMinThreads(out workerThreads, out iocpThreads);
if (!ThreadPool.SetMinThreads(workerThreads, newThreads))
fail = true;
}
else
{
ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads);
if (!ThreadPool.SetMaxThreads(workerThreads, newThreads))
fail = true;
}
}
if (fail)
{
Notice("ERROR: Could not set {0} {1} threads to {2}", poolType, bound, newThreads);
}
else
{
int minWorkerThreads, maxWorkerThreads, minIocpThreads, maxIocpThreads;
ThreadPool.GetMinThreads(out minWorkerThreads, out minIocpThreads);
ThreadPool.GetMaxThreads(out maxWorkerThreads, out maxIocpThreads);
Notice("Min worker threads now {0}", minWorkerThreads);
Notice("Min IOCP threads now {0}", minIocpThreads);
Notice("Max worker threads now {0}", maxWorkerThreads);
Notice("Max IOCP threads now {0}", maxIocpThreads);
}
}
private void HandleForceGc(string module, string[] args)
{
Notice("Manually invoking runtime garbage collection");

View File

@ -66,6 +66,11 @@ namespace OpenSim.Framework
/// </summary>
public static int RequestNumber { get; internal set; }
/// <summary>
/// Control where OSD requests should be serialized per endpoint.
/// </summary>
public static bool SerializeOSDRequestsPerEndpoint { get; set; }
/// <summary>
/// this is the header field used to communicate the local request id
/// used for performance and debugging
@ -145,9 +150,16 @@ namespace OpenSim.Framework
public static OSDMap ServiceOSDRequest(string url, OSDMap data, string method, int timeout, bool compressed)
{
lock (EndPointLock(url))
if (SerializeOSDRequestsPerEndpoint)
{
return ServiceOSDRequestWorker(url,data,method,timeout,compressed);
lock (EndPointLock(url))
{
return ServiceOSDRequestWorker(url, data, method, timeout, compressed);
}
}
else
{
return ServiceOSDRequestWorker(url, data, method, timeout, compressed);
}
}

View File

@ -103,26 +103,38 @@ namespace OpenSim
"[OPENSIM MAIN]: Environment variable MONO_THREADS_PER_CPU is {0}", monoThreadsPerCpu ?? "unset");
// Verify the Threadpool allocates or uses enough worker and IO completion threads
// .NET 2.0 workerthreads default to 50 * numcores
// .NET 3.0 workerthreads defaults to 250 * numcores
// .NET 4.0 workerthreads are dynamic based on bitness and OS resources
// Max IO Completion threads are 1000 on all 3 CLRs.
// .NET 2.0, workerthreads default to 50 * numcores
// .NET 3.0, workerthreads defaults to 250 * numcores
// .NET 4.0, workerthreads are dynamic based on bitness and OS resources
// Max IO Completion threads are 1000 on all 3 CLRs
//
// Mono 2.10.9 to at least Mono 3.1, workerthreads default to 100 * numcores, iocp threads to 4 * numcores
int workerThreadsMin = 500;
int workerThreadsMax = 1000; // may need further adjustment to match other CLR
int iocpThreadsMin = 1000;
int iocpThreadsMax = 2000; // may need further adjustment to match other CLR
{
int currentMinWorkerThreads, currentMinIocpThreads;
System.Threading.ThreadPool.GetMinThreads(out currentMinWorkerThreads, out currentMinIocpThreads);
m_log.InfoFormat(
"[OPENSIM MAIN]: Runtime gave us {0} min worker threads and {1} min IOCP threads",
currentMinWorkerThreads, currentMinIocpThreads);
}
int workerThreads, iocpThreads;
System.Threading.ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads);
m_log.InfoFormat("[OPENSIM MAIN]: Runtime gave us {0} worker threads and {1} IOCP threads", workerThreads, iocpThreads);
m_log.InfoFormat("[OPENSIM MAIN]: Runtime gave us {0} max worker threads and {1} max IOCP threads", workerThreads, iocpThreads);
if (workerThreads < workerThreadsMin)
{
workerThreads = workerThreadsMin;
m_log.InfoFormat("[OPENSIM MAIN]: Bumping up to worker threads to {0}",workerThreads);
m_log.InfoFormat("[OPENSIM MAIN]: Bumping up to max worker threads to {0}",workerThreads);
}
if (workerThreads > workerThreadsMax)
{
workerThreads = workerThreadsMax;
m_log.InfoFormat("[OPENSIM MAIN]: Limiting worker threads to {0}",workerThreads);
m_log.InfoFormat("[OPENSIM MAIN]: Limiting max worker threads to {0}",workerThreads);
}
// Increase the number of IOCP threads available.
@ -130,22 +142,24 @@ namespace OpenSim
if (iocpThreads < iocpThreadsMin)
{
iocpThreads = iocpThreadsMin;
m_log.InfoFormat("[OPENSIM MAIN]: Bumping up IO completion threads to {0}",iocpThreads);
m_log.InfoFormat("[OPENSIM MAIN]: Bumping up max IO completion threads to {0}",iocpThreads);
}
// Make sure we don't overallocate IOCP threads and thrash system resources
if ( iocpThreads > iocpThreadsMax )
{
iocpThreads = iocpThreadsMax;
m_log.InfoFormat("[OPENSIM MAIN]: Limiting IO completion threads to {0}",iocpThreads);
m_log.InfoFormat("[OPENSIM MAIN]: Limiting max IO completion threads to {0}",iocpThreads);
}
// set the resulting worker and IO completion thread counts back to ThreadPool
if ( System.Threading.ThreadPool.SetMaxThreads(workerThreads, iocpThreads) )
{
m_log.InfoFormat("[OPENSIM MAIN]: Threadpool set to {0} worker threads and {1} IO completion threads", workerThreads, iocpThreads);
m_log.InfoFormat(
"[OPENSIM MAIN]: Threadpool set to {0} max worker threads and {1} max IO completion threads",
workerThreads, iocpThreads);
}
else
{
m_log.Info("[OPENSIM MAIN]: Threadpool reconfiguration failed, runtime defaults still in effect.");
m_log.Warn("[OPENSIM MAIN]: Threadpool reconfiguration failed, runtime defaults still in effect.");
}
// Check if the system is compatible with OpenSimulator.
@ -153,17 +167,16 @@ namespace OpenSim
string supported = String.Empty;
if (Util.IsEnvironmentSupported(ref supported))
{
m_log.Info("Environment is compatible.\n");
m_log.Info("[OPENSIM MAIN]: Environment is supported by OpenSimulator.");
}
else
{
m_log.Warn("Environment is unsupported (" + supported + ")\n");
m_log.Warn("[OPENSIM MAIN]: Environment is not supported by OpenSimulator (" + supported + ")\n");
}
// Configure nIni aliases and localles
Culture.SetCurrentCulture();
// Validate that the user has the most basic configuration done
// If not, offer to do the most basic configuration for them warning them along the way of the importance of
// reading these files.

View File

@ -337,7 +337,6 @@ namespace OpenSim
config.Set("physics", "OpenDynamicsEngine");
config.Set("meshing", "Meshmerizer");
config.Set("physical_prim", true);
config.Set("see_into_this_sim_from_neighbor", true);
config.Set("serverside_object_permissions", true);
config.Set("storage_plugin", "OpenSim.Data.SQLite.dll");
config.Set("storage_connection_string", "URI=file:OpenSim.db,version=3");

View File

@ -29,6 +29,7 @@ using System;
using System.IO;
using System.Net;
using System.Reflection;
using System.Threading;
using log4net.Config;
using Nini.Config;
using NUnit.Framework;
@ -53,6 +54,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
[TestFixtureSetUp]
public void FixtureInit()
{
// Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread.
Util.FireAndForgetMethod = FireAndForgetMethod.None;
using (
Stream resource
= GetType().Assembly.GetManifestResourceStream(
@ -72,6 +76,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
}
}
[TestFixtureTearDown]
public void TearDown()
{
// We must set this back afterwards, otherwise later tests will fail since they're expecting multiple
// threads. Possibly, later tests should be rewritten not to worry about such things.
Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
}
[SetUp]
public override void SetUp()
{

View File

@ -166,7 +166,7 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender
// Do Decode!
if (decode)
Decode(assetID, j2kData);
Util.FireAndForget(delegate { Decode(assetID, j2kData); });
}
}

View File

@ -54,8 +54,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
public int DebugLevel { get; set; }
/// <summary>
/// Period to sleep per 100 prims in order to avoid CPU spikes when an avatar with many attachments logs in
/// or many avatars with a medium levels of attachments login simultaneously.
/// Period to sleep per 100 prims in order to avoid CPU spikes when an avatar with many attachments logs in/changes
/// outfit or many avatars with a medium levels of attachments login/change outfit simultaneously.
/// </summary>
/// <remarks>
/// A value of 0 will apply no pause. The pause is specified in milliseconds.
@ -1094,7 +1094,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
}
if (tainted)
objatt.HasGroupChanged = true;
objatt.HasGroupChanged = true;
if (ThrottlePer100PrimsRezzed > 0)
{
int throttleMs = (int)Math.Round((float)objatt.PrimCount / 100 * ThrottlePer100PrimsRezzed);
if (DebugLevel > 0)
m_log.DebugFormat(
"[ATTACHMENTS MODULE]: Throttling by {0}ms after rez of {1} with {2} prims for attachment to {3} on point {4} in {5}",
throttleMs, objatt.Name, objatt.PrimCount, sp.Name, attachmentPt, m_scene.Name);
Thread.Sleep(throttleMs);
}
return objatt;
}

View File

@ -693,8 +693,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (version.Equals("SIMULATION/0.2"))
TransferAgent_V2(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, version, out reason);
else
TransferAgent_V1(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, version, out reason);
TransferAgent_V1(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, version, out reason);
}
private void TransferAgent_V1(ScenePresence sp, AgentCircuitData agentCircuit, GridRegion reg, GridRegion finalDestination,
@ -703,7 +702,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
ulong destinationHandle = finalDestination.RegionHandle;
AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Using TP V1");
m_log.DebugFormat(
"[ENTITY TRANSFER MODULE]: Using TP V1 for {0} going from {1} to {2}",
sp.Name, Scene.Name, finalDestination.RegionName);
// Let's create an agent there if one doesn't exist yet.
// NOTE: logout will always be false for a non-HG teleport.
bool logout = false;
@ -961,6 +963,27 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
return;
}
if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Cancelling)
{
m_interRegionTeleportCancels.Value++;
m_log.DebugFormat(
"[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request",
sp.Name, finalDestination.RegionName, sp.Scene.Name);
return;
}
else if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
{
m_interRegionTeleportAborts.Value++;
m_log.DebugFormat(
"[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after CreateAgent due to previous client close.",
sp.Name, finalDestination.RegionName, sp.Scene.Name);
return;
}
// Past this point we have to attempt clean up if the teleport fails, so update transfer state.
m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
@ -1063,20 +1086,22 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (!sp.DoNotCloseAfterTeleport)
{
// OK, it got this agent. Let's close everything
m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Closing in agent {0} in region {1}", sp.Name, Scene.RegionInfo.RegionName);
m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Closing in agent {0} in region {1}", sp.Name, Scene.Name);
sp.CloseChildAgents(newRegionX, newRegionY);
sp.Scene.IncomingCloseAgent(sp.UUID, false);
}
else
{
m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Not closing agent {0}, user is back in {0}", sp.Name, Scene.RegionInfo.RegionName);
m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Not closing agent {0}, user is back in {0}", sp.Name, Scene.Name);
sp.DoNotCloseAfterTeleport = false;
}
}
else
{
// now we have a child agent in this region.
sp.Reset();
}
}
/// <summary>

View File

@ -62,6 +62,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
private string m_ThisGatekeeper;
private bool m_RestrictInventoryAccessAbroad;
private bool m_bypassPermissions = true;
// private bool m_Initialized = false;
#region INonSharedRegionModule
@ -100,6 +102,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
}
else
m_log.Warn("[HG INVENTORY ACCESS MODULE]: HGInventoryAccessModule configs not found. ProfileServerURI not set!");
m_bypassPermissions = !Util.GetConfigVarFromSections<bool>(source, "serverside_object_permissions",
new string[] { "Startup", "Permissions" }, true);
}
}
}
@ -114,6 +120,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
scene.EventManager.OnNewInventoryItemUploadComplete += UploadInventoryItem;
scene.EventManager.OnTeleportStart += TeleportStart;
scene.EventManager.OnTeleportFail += TeleportFail;
// We're fgoing to enforce some stricter permissions if Outbound is false
scene.Permissions.OnTakeObject += CanTakeObject;
scene.Permissions.OnTakeCopyObject += CanTakeObject;
scene.Permissions.OnTransferUserInventory += OnTransferUserInventory;
}
#endregion
@ -416,6 +427,37 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
// No-op for now
}
#endregion
#region Permissions
private bool CanTakeObject(UUID objectID, UUID stealer, Scene scene)
{
if (m_bypassPermissions) return true;
if (!m_OutboundPermission && !UserManagementModule.IsLocalGridUser(stealer))
{
SceneObjectGroup sog = null;
if (m_Scene.TryGetSceneObjectGroup(objectID, out sog) && sog.OwnerID == stealer)
return true;
return false;
}
return true;
}
private bool OnTransferUserInventory(UUID itemID, UUID userID, UUID recipientID)
{
if (m_bypassPermissions) return true;
if (!m_OutboundPermission && !UserManagementModule.IsLocalGridUser(recipientID))
return false;
return true;
}
#endregion
}
}

View File

@ -809,7 +809,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
}
objlist.Add(g);
veclist.Add(new Vector3(0, 0, 0));
veclist.Add(Vector3.Zero);
float offsetHeight = 0;
pos = m_Scene.GetNewRezLocation(

View File

@ -163,7 +163,7 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
public void RegisterScriptInvocation(object target, MethodInfo mi)
{
m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, (target is Type) ? ((Type)target).Name : target.GetType().Name);
// m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, (target is Type) ? ((Type)target).Name : target.GetType().Name);
Type delegateType;
List<Type> typeArgs = mi.GetParameters()
@ -325,7 +325,7 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
/// </summary>
public void RegisterConstant(string cname, object value)
{
m_log.DebugFormat("[MODULE COMMANDS] register constant <{0}> with value {1}",cname,value.ToString());
// m_log.DebugFormat("[MODULE COMMANDS] register constant <{0}> with value {1}",cname,value.ToString());
lock (m_constants)
{
m_constants.Add(cname,value);

View File

@ -63,35 +63,41 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
/// </summary>
private bool m_ModuleEnabled = false;
public LocalSimulationConnectorModule()
{
ServiceVersion = "SIMULATION/0.2";
}
#region Region Module interface
public void Initialise(IConfigSource config)
public void Initialise(IConfigSource configSource)
{
IConfig moduleConfig = config.Configs["Modules"];
IConfig moduleConfig = configSource.Configs["Modules"];
if (moduleConfig != null)
{
string name = moduleConfig.GetString("SimulationServices", "");
if (name == Name)
{
//IConfig userConfig = config.Configs["SimulationService"];
//if (userConfig == null)
//{
// m_log.Error("[AVATAR CONNECTOR]: SimulationService missing from OpenSim.ini");
// return;
//}
InitialiseService(configSource);
m_ModuleEnabled = true;
m_log.Info("[SIMULATION CONNECTOR]: Local simulation enabled");
m_log.Info("[LOCAL SIMULATION CONNECTOR]: Local simulation enabled.");
}
}
}
public void InitialiseService(IConfigSource configSource)
{
ServiceVersion = "SIMULATION/0.2";
IConfig config = configSource.Configs["SimulationService"];
if (config != null)
{
ServiceVersion = config.GetString("ConnectorProtocolVersion", ServiceVersion);
if (ServiceVersion != "SIMULATION/0.1" && ServiceVersion != "SIMULATION/0.2")
throw new Exception(string.Format("Invalid ConnectorProtocolVersion {0}", ServiceVersion));
m_log.InfoFormat(
"[LOCAL SIMULATION CONNECTOR]: Initialzied with connector protocol version {0}", ServiceVersion);
}
}
public void PostInitialise()
{
}

View File

@ -50,9 +50,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RemoteSimulationConnectorModule")]
public class RemoteSimulationConnectorModule : ISharedRegionModule, ISimulationService
{
private bool initialized = false;
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private bool initialized = false;
protected bool m_enabled = false;
protected Scene m_aScene;
// RemoteSimulationConnector does not care about local regions; it delegates that to the Local module
@ -64,27 +64,23 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
#region Region Module interface
public virtual void Initialise(IConfigSource config)
public virtual void Initialise(IConfigSource configSource)
{
IConfig moduleConfig = config.Configs["Modules"];
IConfig moduleConfig = configSource.Configs["Modules"];
if (moduleConfig != null)
{
string name = moduleConfig.GetString("SimulationServices", "");
if (name == Name)
{
//IConfig userConfig = config.Configs["SimulationService"];
//if (userConfig == null)
//{
// m_log.Error("[AVATAR CONNECTOR]: SimulationService missing from OpenSim.ini");
// return;
//}
m_localBackend = new LocalSimulationConnectorModule();
m_localBackend.InitialiseService(configSource);
m_remoteConnector = new SimulationServiceConnector();
m_enabled = true;
m_log.Info("[SIMULATION CONNECTOR]: Remote simulation enabled");
m_log.Info("[REMOTE SIMULATION CONNECTOR]: Remote simulation enabled.");
}
}
}
@ -142,8 +138,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
}
protected virtual void InitOnce(Scene scene)
{
m_localBackend = new LocalSimulationConnectorModule();
{
m_aScene = scene;
//m_regionClient = new RegionToRegionClient(m_aScene, m_hyperlinkService);
m_thisIP = Util.GetHostFromDNS(scene.RegionInfo.ExternalHostName);

View File

@ -551,6 +551,9 @@ namespace OpenSim.Region.Framework.Scenes
{
//Console.WriteLine("Scene.Inventory.cs: GiveInventoryItem");
if (!Permissions.CanTransferUserInventory(itemId, senderId, recipient))
return null;
InventoryItemBase item = new InventoryItemBase(itemId, senderId);
item = InventoryService.GetItem(item);
@ -2127,7 +2130,10 @@ namespace OpenSim.Region.Framework.Scenes
{
// If we don't have permission, stop right here
if (!permissionToTakeCopy)
{
remoteClient.SendAlertMessage("You don't have permission to take the object");
return;
}
permissionToTake = true;
// Don't delete

View File

@ -4174,28 +4174,29 @@ namespace OpenSim.Region.Framework.Scenes
}
}
if (RegionInfo.EstateSettings != null)
{
if (RegionInfo.EstateSettings.IsBanned(agent.AgentID, 0))
{
m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
reason = String.Format("Denied access to region {0}: You have been banned from that region.",
RegionInfo.RegionName);
return false;
}
}
else
{
m_log.ErrorFormat("[CONNECTION BEGIN]: Estate Settings is null!");
}
// We only test the things below when we want to cut off
// child agents from being present in the scene for which their root
// agent isn't allowed. Otherwise, we allow child agents. The test for
// the root is done elsewhere (QueryAccess)
if (!bypassAccessControl)
{
if (RegionInfo.EstateSettings != null)
{
int flags = GetUserFlags(agent.AgentID);
if (RegionInfo.EstateSettings.IsBanned(agent.AgentID, flags))
{
m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
reason = String.Format("Denied access to region {0}: You have been banned from that region.",
RegionInfo.RegionName);
return false;
}
}
else
{
m_log.ErrorFormat("[CONNECTION BEGIN]: Estate Settings is null!");
}
List<UUID> agentGroups = new List<UUID>();
if (m_groupsModule != null)
@ -4392,36 +4393,42 @@ namespace OpenSim.Region.Framework.Scenes
}
// We have to wait until the viewer contacts this region
// after receiving the EnableSimulator HTTP Event Queue message. This triggers the viewer to send
// after receiving the EnableSimulator HTTP Event Queue message (for the v1 teleport protocol)
// or TeleportFinish (for the v2 teleport protocol). This triggers the viewer to send
// a UseCircuitCode packet which in turn calls AddNewClient which finally creates the ScenePresence.
ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID);
ScenePresence sp = WaitGetScenePresence(cAgentData.AgentID);
if (childAgentUpdate != null)
if (sp != null)
{
if (cAgentData.SessionID != childAgentUpdate.ControllingClient.SessionId)
if (cAgentData.SessionID != sp.ControllingClient.SessionId)
{
m_log.WarnFormat("[SCENE]: Attempt to update agent {0} with invalid session id {1} (possibly from simulator in older version; tell them to update).", childAgentUpdate.UUID, cAgentData.SessionID);
m_log.WarnFormat(
"[SCENE]: Attempt to update agent {0} with invalid session id {1} (possibly from simulator in older version; tell them to update).",
sp.UUID, cAgentData.SessionID);
Console.WriteLine(String.Format("[SCENE]: Attempt to update agent {0} ({1}) with invalid session id {2}",
childAgentUpdate.UUID, childAgentUpdate.ControllingClient.SessionId, cAgentData.SessionID));
sp.UUID, sp.ControllingClient.SessionId, cAgentData.SessionID));
}
childAgentUpdate.ChildAgentDataUpdate(cAgentData);
sp.ChildAgentDataUpdate(cAgentData);
int ntimes = 20;
if (cAgentData.SenderWantsToWaitForRoot)
{
while (childAgentUpdate.IsChildAgent && ntimes-- > 0)
while (sp.IsChildAgent && ntimes-- > 0)
Thread.Sleep(1000);
m_log.DebugFormat(
"[SCENE]: Found presence {0} {1} {2} in {3} after {4} waits",
childAgentUpdate.Name, childAgentUpdate.UUID, childAgentUpdate.IsChildAgent ? "child" : "root", RegionInfo.RegionName, 20 - ntimes);
sp.Name, sp.UUID, sp.IsChildAgent ? "child" : "root", Name, 20 - ntimes);
if (childAgentUpdate.IsChildAgent)
if (sp.IsChildAgent)
return false;
}
return true;
}
return false;
}

View File

@ -294,10 +294,24 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary>
private Vector3 posLastSignificantMove;
// For teleports and crossings callbacks
#region For teleports and crossings callbacks
/// <summary>
/// In the V1 teleport protocol, the destination simulator sends ReleaseAgent to this address.
/// </summary>
string m_callbackURI;
UUID m_originRegionID;
/// <summary>
/// Used by the entity transfer module to signal when the presence should not be closed because a subsequent
/// teleport is reusing the connection.
/// </summary>
/// <remarks>May be refactored or move somewhere else soon.</remarks>
public bool DoNotCloseAfterTeleport { get; set; }
#endregion
/// <value>
/// Script engines present in the scene
/// </value>
@ -764,13 +778,6 @@ namespace OpenSim.Region.Framework.Scenes
}
}
/// <summary>
/// Used by the entity transfer module to signal when the presence should not be closed because a subsequent
/// teleport is reusing the connection.
/// </summary>
/// <remarks>May be refactored or move somewhere else soon.</remarks>
public bool DoNotCloseAfterTeleport { get; set; }
private float m_speedModifier = 1.0f;
public float SpeedModifier
@ -1516,14 +1523,14 @@ namespace OpenSim.Region.Framework.Scenes
int count = 20;
while (m_originRegionID.Equals(UUID.Zero) && count-- > 0)
{
m_log.DebugFormat("[SCENE PRESENCE]: Agent {0} waiting for update in {1}", client.Name, Scene.RegionInfo.RegionName);
m_log.DebugFormat("[SCENE PRESENCE]: Agent {0} waiting for update in {1}", client.Name, Scene.Name);
Thread.Sleep(200);
}
if (m_originRegionID.Equals(UUID.Zero))
{
// Movement into region will fail
m_log.WarnFormat("[SCENE PRESENCE]: Update agent {0} never arrived", client.Name);
m_log.WarnFormat("[SCENE PRESENCE]: Update agent {0} never arrived in {1}", client.Name, Scene.Name);
return false;
}
@ -1829,8 +1836,14 @@ namespace OpenSim.Region.Framework.Scenes
// Here's where you get them.
m_AgentControlFlags = flags;
m_headrotation = agentData.HeadRotation;
byte oldState = State;
State = agentData.State;
// We need to send this back to the client in order to stop the edit beams
if ((oldState & (uint)AgentState.Editing) != 0 && State == (uint)AgentState.None)
ControllingClient.SendAgentTerseUpdate(this);
PhysicsActor actor = PhysicsActor;
if (actor == null)
{
@ -3199,8 +3212,7 @@ namespace OpenSim.Region.Framework.Scenes
}
// Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m
if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance ||
Util.GetDistanceTo(CameraPosition, m_lastChildAgentUpdateCamPosition) >= Scene.ChildReprioritizationDistance)
if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance)
{
m_lastChildAgentUpdatePosition = AbsolutePosition;
m_lastChildAgentUpdateCamPosition = CameraPosition;

View File

@ -49,10 +49,20 @@ public class ExtendedPhysics : INonSharedRegionModule
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static string LogHeader = "[EXTENDED PHYSICS]";
// =============================================================
// Since BulletSim is a plugin, this these values aren't defined easily in one place.
// This table must coorespond to an identical table in BSScene.
// This table must correspond to an identical table in BSScene.
// Per scene functions. See BSScene.
// Per avatar functions. See BSCharacter.
// Per prim functions. See BSPrim.
public const string PhysFunctGetLinksetType = "BulletSim.GetLinksetType";
public const string PhysFunctSetLinksetType = "BulletSim.SetLinksetType";
// =============================================================
private IConfig Configuration { get; set; }
private bool Enabled { get; set; }
private Scene BaseScene { get; set; }
@ -123,6 +133,7 @@ public class ExtendedPhysics : INonSharedRegionModule
// Register as LSL functions all the [ScriptInvocation] marked methods.
Comms.RegisterScriptInvocations(this);
Comms.RegisterConstants(this);
// When an object is modified, we might need to update its extended physics parameters
BaseScene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene;
@ -136,7 +147,6 @@ public class ExtendedPhysics : INonSharedRegionModule
private void EventManager_OnObjectAddedToScene(SceneObjectGroup obj)
{
throw new NotImplementedException();
}
// Event generated when some property of a prim changes.
@ -168,9 +178,11 @@ public class ExtendedPhysics : INonSharedRegionModule
public static int PHYS_LINKSET_TYPE_MANUAL = 2;
[ScriptInvocation]
public void physSetLinksetType(UUID hostID, UUID scriptID, int linksetType)
public int physSetLinksetType(UUID hostID, UUID scriptID, int linksetType)
{
if (!Enabled) return;
int ret = -1;
if (!Enabled) return ret;
// The part that is requesting the change.
SceneObjectPart requestingPart = BaseScene.GetSceneObjectPart(hostID);
@ -186,7 +198,7 @@ public class ExtendedPhysics : INonSharedRegionModule
Physics.Manager.PhysicsActor rootPhysActor = rootPart.PhysActor;
if (rootPhysActor != null)
{
rootPhysActor.Extension(PhysFunctSetLinksetType, linksetType);
ret = (int)rootPhysActor.Extension(PhysFunctSetLinksetType, linksetType);
}
else
{
@ -204,6 +216,49 @@ public class ExtendedPhysics : INonSharedRegionModule
{
m_log.WarnFormat("{0} physSetLinsetType: cannot find script object in scene. hostID={1}", LogHeader, hostID);
}
return ret;
}
[ScriptInvocation]
public int physGetLinksetType(UUID hostID, UUID scriptID)
{
int ret = -1;
if (!Enabled) return ret;
// The part that is requesting the change.
SceneObjectPart requestingPart = BaseScene.GetSceneObjectPart(hostID);
if (requestingPart != null)
{
// The type is is always on the root of a linkset.
SceneObjectGroup containingGroup = requestingPart.ParentGroup;
SceneObjectPart rootPart = containingGroup.RootPart;
if (rootPart != null)
{
Physics.Manager.PhysicsActor rootPhysActor = rootPart.PhysActor;
if (rootPhysActor != null)
{
ret = (int)rootPhysActor.Extension(PhysFunctGetLinksetType);
}
else
{
m_log.WarnFormat("{0} physGetLinksetType: root part does not have a physics actor. rootName={1}, hostID={2}",
LogHeader, rootPart.Name, hostID);
}
}
else
{
m_log.WarnFormat("{0} physGetLinksetType: root part does not exist. RequestingPartName={1}, hostID={2}",
LogHeader, requestingPart.Name, hostID);
}
}
else
{
m_log.WarnFormat("{0} physGetLinsetType: cannot find script object in scene. hostID={1}", LogHeader, hostID);
}
return ret;
}
}
}

View File

@ -70,6 +70,17 @@ public abstract class BSLinkset
return ret;
}
public class BSLinkInfo
{
public BSPrimLinkable member;
public BSLinkInfo(BSPrimLinkable pMember)
{
member = pMember;
}
}
public LinksetImplementation LinksetImpl { get; protected set; }
public BSPrimLinkable LinksetRoot { get; protected set; }
protected BSScene m_physicsScene { get; private set; }
@ -78,7 +89,8 @@ public abstract class BSLinkset
public int LinksetID { get; private set; }
// The children under the root in this linkset.
protected HashSet<BSPrimLinkable> m_children;
// protected HashSet<BSPrimLinkable> m_children;
protected Dictionary<BSPrimLinkable, BSLinkInfo> m_children;
// We lock the diddling of linkset classes to prevent any badness.
// This locks the modification of the instances of this class. Changes
@ -109,7 +121,7 @@ public abstract class BSLinkset
m_nextLinksetID = 1;
m_physicsScene = scene;
LinksetRoot = parent;
m_children = new HashSet<BSPrimLinkable>();
m_children = new Dictionary<BSPrimLinkable, BSLinkInfo>();
LinksetMass = parent.RawMass;
Rebuilding = false;
@ -170,17 +182,7 @@ public abstract class BSLinkset
bool ret = false;
lock (m_linksetActivityLock)
{
ret = m_children.Contains(child);
/* Safer version but the above should work
foreach (BSPrimLinkable bp in m_children)
{
if (child.LocalID == bp.LocalID)
{
ret = true;
break;
}
}
*/
ret = m_children.ContainsKey(child);
}
return ret;
}
@ -194,7 +196,24 @@ public abstract class BSLinkset
lock (m_linksetActivityLock)
{
action(LinksetRoot);
foreach (BSPrimLinkable po in m_children)
foreach (BSPrimLinkable po in m_children.Keys)
{
if (action(po))
break;
}
}
return ret;
}
// Perform an action on each member of the linkset including root prim.
// Depends on the action on whether this should be done at taint time.
public delegate bool ForEachLinkInfoAction(BSLinkInfo obj);
public virtual bool ForEachLinkInfo(ForEachLinkInfoAction action)
{
bool ret = false;
lock (m_linksetActivityLock)
{
foreach (BSLinkInfo po in m_children.Values)
{
if (action(po))
break;
@ -364,7 +383,7 @@ public abstract class BSLinkset
{
lock (m_linksetActivityLock)
{
foreach (BSPrimLinkable bp in m_children)
foreach (BSPrimLinkable bp in m_children.Keys)
{
mass += bp.RawMass;
}
@ -382,7 +401,7 @@ public abstract class BSLinkset
com = LinksetRoot.Position * LinksetRoot.RawMass;
float totalMass = LinksetRoot.RawMass;
foreach (BSPrimLinkable bp in m_children)
foreach (BSPrimLinkable bp in m_children.Keys)
{
com += bp.Position * bp.RawMass;
totalMass += bp.RawMass;
@ -401,7 +420,7 @@ public abstract class BSLinkset
{
com = LinksetRoot.Position;
foreach (BSPrimLinkable bp in m_children)
foreach (BSPrimLinkable bp in m_children.Keys)
{
com += bp.Position;
}

View File

@ -42,6 +42,7 @@ public sealed class BSLinksetCompound : BSLinkset
public BSLinksetCompound(BSScene scene, BSPrimLinkable parent)
: base(scene, parent)
{
LinksetImpl = LinksetImplementation.Compound;
}
// ================================================================
@ -257,7 +258,7 @@ public sealed class BSLinksetCompound : BSLinkset
{
if (!HasChild(child))
{
m_children.Add(child);
m_children.Add(child, new BSLinkInfo(child));
DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID);
@ -353,7 +354,7 @@ public sealed class BSLinksetCompound : BSLinkset
// Add the shapes of all the components of the linkset
int memberIndex = 1;
ForEachMember(delegate(BSPrimLinkable cPrim)
ForEachMember((cPrim) =>
{
if (IsRoot(cPrim))
{

View File

@ -36,8 +36,78 @@ public sealed class BSLinksetConstraints : BSLinkset
{
// private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]";
public class BSLinkInfoConstraint : BSLinkInfo
{
public ConstraintType constraintType;
public BSConstraint constraint;
public OMV.Vector3 linearLimitLow;
public OMV.Vector3 linearLimitHigh;
public OMV.Vector3 angularLimitLow;
public OMV.Vector3 angularLimitHigh;
public bool useFrameOffset;
public bool enableTransMotor;
public float transMotorMaxVel;
public float transMotorMaxForce;
public float cfm;
public float erp;
public float solverIterations;
public BSLinkInfoConstraint(BSPrimLinkable pMember)
: base(pMember)
{
constraint = null;
ResetToFixedConstraint();
}
// Set all the parameters for this constraint to a fixed, non-movable constraint.
public void ResetToFixedConstraint()
{
constraintType = ConstraintType.D6_CONSTRAINT_TYPE;
linearLimitLow = OMV.Vector3.Zero;
linearLimitHigh = OMV.Vector3.Zero;
angularLimitLow = OMV.Vector3.Zero;
angularLimitHigh = OMV.Vector3.Zero;
useFrameOffset = BSParam.LinkConstraintUseFrameOffset;
enableTransMotor = BSParam.LinkConstraintEnableTransMotor;
transMotorMaxVel = BSParam.LinkConstraintTransMotorMaxVel;
transMotorMaxForce = BSParam.LinkConstraintTransMotorMaxForce;
cfm = BSParam.LinkConstraintCFM;
erp = BSParam.LinkConstraintERP;
solverIterations = BSParam.LinkConstraintSolverIterations;
}
// Given a constraint, apply the current constraint parameters to same.
public void SetConstraintParameters(BSConstraint constrain)
{
switch (constraintType)
{
case ConstraintType.D6_CONSTRAINT_TYPE:
BSConstraint6Dof constrain6dof = constrain as BSConstraint6Dof;
if (constrain6dof != null)
{
// zero linear and angular limits makes the objects unable to move in relation to each other
constrain6dof.SetLinearLimits(linearLimitLow, linearLimitHigh);
constrain6dof.SetAngularLimits(angularLimitLow, angularLimitHigh);
// tweek the constraint to increase stability
constrain6dof.UseFrameOffset(useFrameOffset);
constrain6dof.TranslationalLimitMotor(enableTransMotor, transMotorMaxVel, transMotorMaxForce);
constrain6dof.SetCFMAndERP(cfm, erp);
if (solverIterations != 0f)
{
constrain6dof.SetSolverIterations(solverIterations);
}
}
break;
default:
break;
}
}
}
public BSLinksetConstraints(BSScene scene, BSPrimLinkable parent) : base(scene, parent)
{
LinksetImpl = LinksetImplementation.Constraint;
}
// When physical properties are changed the linkset needs to recalculate
@ -142,7 +212,7 @@ public sealed class BSLinksetConstraints : BSLinkset
{
if (!HasChild(child))
{
m_children.Add(child);
m_children.Add(child, new BSLinkInfoConstraint(child));
DetailLog("{0},BSLinksetConstraints.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID);
@ -190,73 +260,74 @@ public sealed class BSLinksetConstraints : BSLinkset
}
// Create a static constraint between the two passed objects
private BSConstraint BuildConstraint(BSPrimLinkable rootPrim, BSPrimLinkable childPrim)
private BSConstraint BuildConstraint(BSPrimLinkable rootPrim, BSLinkInfo li)
{
BSLinkInfoConstraint liConstraint = li as BSLinkInfoConstraint;
if (liConstraint == null)
return null;
// Zero motion for children so they don't interpolate
childPrim.ZeroMotion(true);
li.member.ZeroMotion(true);
// Relative position normalized to the root prim
// Essentually a vector pointing from center of rootPrim to center of childPrim
OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position;
BSConstraint constrain = null;
// real world coordinate of midpoint between the two objects
OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
switch (liConstraint.constraintType)
{
case ConstraintType.D6_CONSTRAINT_TYPE:
// Relative position normalized to the root prim
// Essentually a vector pointing from center of rootPrim to center of li.member
OMV.Vector3 childRelativePosition = liConstraint.member.Position - rootPrim.Position;
DetailLog("{0},BSLinksetConstraint.BuildConstraint,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}",
rootPrim.LocalID,
rootPrim.LocalID, rootPrim.PhysBody.AddrString,
childPrim.LocalID, childPrim.PhysBody.AddrString,
rootPrim.Position, childPrim.Position, midPoint);
// real world coordinate of midpoint between the two objects
OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
// create a constraint that allows no freedom of movement between the two objects
// http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
DetailLog("{0},BSLinksetConstraint.BuildConstraint,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}",
rootPrim.LocalID,
rootPrim.LocalID, rootPrim.PhysBody.AddrString,
liConstraint.member.LocalID, liConstraint.member.PhysBody.AddrString,
rootPrim.Position, liConstraint.member.Position, midPoint);
BSConstraint6Dof constrain = new BSConstraint6Dof(
m_physicsScene.World, rootPrim.PhysBody, childPrim.PhysBody, midPoint, true, true );
// PhysicsScene.World, childPrim.BSBody, rootPrim.BSBody, midPoint, true, true );
// create a constraint that allows no freedom of movement between the two objects
// http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
/* NOTE: below is an attempt to build constraint with full frame computation, etc.
* Using the midpoint is easier since it lets the Bullet code manipulate the transforms
* of the objects.
* Code left for future programmers.
// ==================================================================================
// relative position normalized to the root prim
OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation);
OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation;
constrain = new BSConstraint6Dof(
m_physicsScene.World, rootPrim.PhysBody, liConstraint.member.PhysBody, midPoint, true, true );
// relative rotation of the child to the parent
OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation;
OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation);
/* NOTE: below is an attempt to build constraint with full frame computation, etc.
* Using the midpoint is easier since it lets the Bullet code manipulate the transforms
* of the objects.
* Code left for future programmers.
// ==================================================================================
// relative position normalized to the root prim
OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation);
OMV.Vector3 childRelativePosition = (liConstraint.member.Position - rootPrim.Position) * invThisOrientation;
DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
BS6DofConstraint constrain = new BS6DofConstraint(
PhysicsScene.World, rootPrim.Body, childPrim.Body,
OMV.Vector3.Zero,
OMV.Quaternion.Inverse(rootPrim.Orientation),
OMV.Vector3.Zero,
OMV.Quaternion.Inverse(childPrim.Orientation),
true,
true
);
// ==================================================================================
*/
// relative rotation of the child to the parent
OMV.Quaternion childRelativeRotation = invThisOrientation * liConstraint.member.Orientation;
OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation);
DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, liConstraint.member.LocalID);
constrain = new BS6DofConstraint(
PhysicsScene.World, rootPrim.Body, liConstraint.member.Body,
OMV.Vector3.Zero,
OMV.Quaternion.Inverse(rootPrim.Orientation),
OMV.Vector3.Zero,
OMV.Quaternion.Inverse(liConstraint.member.Orientation),
true,
true
);
// ==================================================================================
*/
break;
default:
break;
}
liConstraint.SetConstraintParameters(constrain);
m_physicsScene.Constraints.AddConstraint(constrain);
// zero linear and angular limits makes the objects unable to move in relation to each other
constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
// tweek the constraint to increase stability
constrain.UseFrameOffset(BSParam.LinkConstraintUseFrameOffset);
constrain.TranslationalLimitMotor(BSParam.LinkConstraintEnableTransMotor,
BSParam.LinkConstraintTransMotorMaxVel,
BSParam.LinkConstraintTransMotorMaxForce);
constrain.SetCFMAndERP(BSParam.LinkConstraintCFM, BSParam.LinkConstraintERP);
if (BSParam.LinkConstraintSolverIterations != 0f)
{
constrain.SetSolverIterations(BSParam.LinkConstraintSolverIterations);
}
return constrain;
}
@ -317,23 +388,24 @@ public sealed class BSLinksetConstraints : BSLinkset
return; // Note the 'finally' clause at the botton which will get executed.
}
foreach (BSPrimLinkable child in m_children)
ForEachLinkInfo((li) =>
{
// A child in the linkset physically shows the mass of the whole linkset.
// This allows Bullet to apply enough force on the child to move the whole linkset.
// (Also do the mass stuff before recomputing the constraint so mass is not zero.)
child.UpdatePhysicalMassProperties(linksetMass, true);
li.member.UpdatePhysicalMassProperties(linksetMass, true);
BSConstraint constrain;
if (!m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, child.PhysBody, out constrain))
if (!m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, li.member.PhysBody, out constrain))
{
// If constraint doesn't exist yet, create it.
constrain = BuildConstraint(LinksetRoot, child);
constrain = BuildConstraint(LinksetRoot, li);
}
constrain.RecomputeConstraintVariables(linksetMass);
// PhysicsScene.PE.DumpConstraint(PhysicsScene.World, constrain.Constraint); // DEBUG DEBUG
}
return false; // 'false' says to keep processing other members
});
}
finally
{

View File

@ -1541,6 +1541,50 @@ public class BSPrim : BSPhysObject
PhysicalActors.RemoveDependencies();
}
#region Extension
public override object Extension(string pFunct, params object[] pParams)
{
object ret = null;
switch (pFunct)
{
case BSScene.PhysFunctGetLinksetType:
{
BSPrimLinkable myHandle = this as BSPrimLinkable;
if (myHandle != null)
{
ret = (object)myHandle.LinksetType;
}
m_log.DebugFormat("{0} Extension.physGetLinksetType, type={1}", LogHeader, ret);
break;
}
case BSScene.PhysFunctSetLinksetType:
{
if (pParams.Length > 0)
{
BSLinkset.LinksetImplementation linksetType = (BSLinkset.LinksetImplementation)pParams[0];
BSPrimLinkable myHandle = this as BSPrimLinkable;
if (myHandle != null && myHandle.Linkset.IsRoot(myHandle))
{
PhysScene.TaintedObject("BSPrim.PhysFunctSetLinksetType", delegate()
{
// Cause the linkset type to change
m_log.DebugFormat("{0} Extension.physSetLinksetType, oldType={1}, newType={2}",
LogHeader, myHandle.Linkset.LinksetImpl, linksetType);
myHandle.ConvertLinkset(linksetType);
});
}
ret = (object)(int)linksetType;
}
break;
}
default:
ret = base.Extension(pFunct, pParams);
break;
}
return ret;
}
#endregion // Extension
// The physics engine says that properties have updated. Update same and inform
// the world that things have changed.
// NOTE: BSPrim.UpdateProperties is overloaded by BSPrimLinkable which modifies updates from root and children prims.

View File

@ -233,5 +233,46 @@ public class BSPrimLinkable : BSPrimDisplaced
base.HasSomeCollision = value;
}
}
// Convert the existing linkset of this prim into a new type.
public bool ConvertLinkset(BSLinkset.LinksetImplementation newType)
{
bool ret = false;
if (LinksetType != newType)
{
// Set the implementation type first so the call to BSLinkset.Factory gets the new type.
this.LinksetType = newType;
BSLinkset oldLinkset = this.Linkset;
BSLinkset newLinkset = BSLinkset.Factory(PhysScene, this);
this.Linkset = newLinkset;
// Pick up any physical dependencies this linkset might have in the physics engine.
oldLinkset.RemoveDependencies(this);
// Create a list of the children (mainly because can't interate through a list that's changing)
List<BSPrimLinkable> children = new List<BSPrimLinkable>();
oldLinkset.ForEachMember((child) =>
{
if (!oldLinkset.IsRoot(child))
children.Add(child);
return false; // 'false' says to continue to next member
});
// Remove the children from the old linkset and add to the new (will be a new instance from the factory)
foreach (BSPrimLinkable child in children)
{
oldLinkset.RemoveMeFromLinkset(child);
newLinkset.AddMeToLinkset(child);
child.Linkset = newLinkset;
}
// Force the shape and linkset to get reconstructed
newLinkset.Refresh(this);
this.ForceBodyShapeRebuild(true /* inTaintTime */);
}
return ret;
}
}
}

View File

@ -862,6 +862,23 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
public override bool IsThreaded { get { return false; } }
#region Extensions
// =============================================================
// Per scene functions. See below.
// Per avatar functions. See BSCharacter.
// Per prim functions. See BSPrim.
public const string PhysFunctGetLinksetType = "BulletSim.GetLinksetType";
public const string PhysFunctSetLinksetType = "BulletSim.SetLinksetType";
// =============================================================
public override object Extension(string pFunct, params object[] pParams)
{
return base.Extension(pFunct, pParams);
}
#endregion // Extensions
#region Taints
// The simulation execution order is:
// Simulate()

View File

@ -418,7 +418,8 @@ namespace OpenSim.Region.Physics.Manager
// Extendable interface for new, physics engine specific operations
public virtual object Extension(string pFunct, params object[] pParams)
{
throw new NotImplementedException();
// A NOP of the physics engine does not implement this feature
return null;
}
}

View File

@ -393,7 +393,8 @@ namespace OpenSim.Region.Physics.Manager
// Extendable interface for new, physics engine specific operations
public virtual object Extension(string pFunct, params object[] pParams)
{
throw new NotImplementedException();
// A NOP if the extension thing is not implemented by the physics engine
return null;
}
}
}

View File

@ -319,7 +319,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
object[] convertedParms = new object[parms.Length];
for (int i = 0; i < parms.Length; i++)
convertedParms[i] = ConvertFromLSL(parms[i],signature[i], fname);
convertedParms[i] = ConvertFromLSL(parms[i], signature[i], fname);
// now call the function, the contract with the function is that it will always return
// non-null but don't trust it completely
@ -448,7 +448,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
}
MODError(String.Format("{1}: parameter type mismatch; expecting {0}",type.Name, fname));
MODError(String.Format("{0}: parameter type mismatch; expecting {1}, type(parm)={2}", fname, type.Name, lslparm.GetType()));
return null;
}

View File

@ -937,7 +937,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
{
string retval = null;
if (value is int)
retval = ((int)value).ToString();
retval = String.Format("new LSL_Types.LSLInteger({0})",((int)value).ToString());
else if (value is float)
retval = String.Format("new LSL_Types.LSLFloat({0})",((float)value).ToString());
else if (value is string)

View File

@ -79,7 +79,11 @@ namespace OpenSim.Services.Connectors.SimianGrid
{
m_simianURL = m_config.GetString("SimianServiceURL");
if (String.IsNullOrEmpty(m_simianURL))
m_log.ErrorFormat("[SimianGrid] service URL is not defined");
{
//m_log.DebugFormat("[SimianGrid] service URL is not defined");
m_enabled = false;
return;
}
}
}
else

View File

@ -74,11 +74,15 @@ namespace OpenSim.Services.Connectors.SimianGrid
{
m_simianURL = m_config.GetString("SimianServiceURL");
if (String.IsNullOrEmpty(m_simianURL))
m_log.ErrorFormat("[SimianGrid] service URL is not defined");
{
// m_log.DebugFormat("[SimianGrid] service URL is not defined");
m_enabled = false;
return;
}
InitialiseSimCap();
SimulatorCapability = SimulatorCapability.Trim();
m_log.WarnFormat("[SimianExternalCaps] using {0} as simulator capability",SimulatorCapability);
m_log.InfoFormat("[SimianExternalCaps] using {0} as simulator capability",SimulatorCapability);
}
}
catch (Exception e)

View File

@ -68,8 +68,18 @@ namespace OpenSim.Tests.Clients.AssetsClient
m_log.InfoFormat("[ASSET CLIENT]: Connecting to {0} max threads = {1} - {2}", serverURI, max1, max2);
ThreadPool.GetMinThreads(out max1, out max2);
m_log.InfoFormat("[ASSET CLIENT]: Connecting to {0} min threads = {1} - {2}", serverURI, max1, max2);
ThreadPool.SetMinThreads(1, 1);
ThreadPool.SetMaxThreads(10, 3);
if (!ThreadPool.SetMinThreads(1, 1))
m_log.WarnFormat("[ASSET CLIENT]: Failed to set min threads");
if (!ThreadPool.SetMaxThreads(10, 3))
m_log.WarnFormat("[ASSET CLIENT]: Failed to set max threads");
ThreadPool.GetMaxThreads(out max1, out max2);
m_log.InfoFormat("[ASSET CLIENT]: Post set max threads = {1} - {2}", serverURI, max1, max2);
ThreadPool.GetMinThreads(out max1, out max2);
m_log.InfoFormat("[ASSET CLIENT]: Post set min threads = {1} - {2}", serverURI, max1, max2);
ServicePointManager.DefaultConnectionLimit = 12;
AssetServicesConnector m_Connector = new AssetServicesConnector(serverURI);

View File

@ -239,7 +239,6 @@ namespace OpenSim.Tools.Configger
config.Set("physics", "OpenDynamicsEngine");
config.Set("meshing", "Meshmerizer");
config.Set("physical_prim", true);
config.Set("see_into_this_sim_from_neighbor", true);
config.Set("serverside_object_permissions", true);
config.Set("storage_plugin", "OpenSim.Data.SQLite.dll");
config.Set("storage_connection_string", "URI=file:OpenSim.db,version=3");

View File

@ -11,22 +11,56 @@
</appSettings>
<log4net>
<appender name="Console" type="OpenSim.Framework.Console.OpenSimAppender, OpenSim.Framework.Console">
<filter type="log4net.Filter.LoggerMatchFilter">
<loggerToMatch value="special"/>
<acceptOnMatch value="false"/>
</filter>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date{HH:mm:ss} - %message%newline" />
<conversionPattern value="%date{HH:mm:ss} - %message" />
<!-- console log with milliseconds. Useful for debugging -->
<!-- <conversionPattern value="%date{HH:mm:ss.fff} - %message" /> -->
</layout>
</appender>
<appender name="LogFileAppender" type="log4net.Appender.FileAppender">
<file value="OpenSim.32BitLaunch.log" />
<appendToFile value="true" />
<filter type="log4net.Filter.LoggerMatchFilter">
<loggerToMatch value="special"/>
<acceptOnMatch value="false"/>
</filter>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %-5level - %logger %message%newline" />
</layout>
</appender>
<appender name="StatsLogFileAppender" type="log4net.Appender.FileAppender">
<file value="OpenSimStats.log"/>
<appendToFile value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date - %message%newline" />
</layout>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="Console" />
<appender-ref ref="LogFileAppender" />
</root>
<!-- Independently control logging level for XEngine -->
<logger name="OpenSim.Region.ScriptEngine.XEngine">
<level value="INFO"/>
</logger>
<!-- Independently control logging level for per region module loading -->
<logger name="OpenSim.ApplicationPlugins.RegionModulesController.RegionModulesControllerPlugin">
<level value="INFO"/>
</logger>
<!-- used for stats recording -->
<logger name="special.StatsLogger">
<appender-ref ref="StatsLogFileAppender"/>
</logger>
</log4net>
</configuration>

View File

@ -11,6 +11,10 @@
</appSettings>
<log4net>
<appender name="Console" type="OpenSim.Framework.Console.OpenSimAppender, OpenSim.Framework.Console">
<filter type="log4net.Filter.LoggerMatchFilter">
<loggerToMatch value="special"/>
<acceptOnMatch value="false"/>
</filter>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date{HH:mm:ss} - %message" />
<!-- console log with milliseconds. Useful for debugging -->
@ -21,11 +25,23 @@
<appender name="LogFileAppender" type="log4net.Appender.FileAppender">
<file value="OpenSim.log" />
<appendToFile value="true" />
<filter type="log4net.Filter.LoggerMatchFilter">
<loggerToMatch value="special"/>
<acceptOnMatch value="false"/>
</filter>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %-5level - %logger %message%newline" />
</layout>
</appender>
<appender name="StatsLogFileAppender" type="log4net.Appender.FileAppender">
<file value="OpenSimStats.log"/>
<appendToFile value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date - %message%newline" />
</layout>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="Console" />
@ -42,5 +58,10 @@
<level value="INFO"/>
</logger>
<!-- used for stats recording -->
<logger name="special.StatsLogger">
<appender-ref ref="StatsLogFileAppender"/>
</logger>
</log4net>
</configuration>

View File

@ -180,10 +180,6 @@
;; if the first change occurred this number of seconds ago.
; MaximumTimeBeforePersistenceConsidered = 600
;# {see_into_this_sim_from_neighbor} {} {Should avatars in neighbor sims see objects in this sim?} {true false} true
;; Should avatars in neighbor sims see objects in this sim?
; see_into_this_sim_from_neighbor = true
;# {physical_prim} {} {Allow prims to be physical?} {true false} true
;; if you would like to allow prims to be physical and move by physics
;; with the physical checkbox in the client set this to true.

View File

@ -710,8 +710,8 @@
Enabled = true
; Controls the number of milliseconds that are slept per 100 prims rezzed in attachments
; Experimental setting to control CPU spiking when avatars with many attachments login
; or when multiple avatars with medium level attachments login simultaneously.
; Experimental setting to control CPU spiking when avatars with many attachments login/change outfit
; or when multiple avatars with medium level attachments login/change outfit simultaneously.
; If 0 then no throttling is performed.
ThrottlePer100PrimsRezzed = 0;

View File

@ -11,22 +11,44 @@
</appSettings>
<log4net>
<appender name="Console" type="OpenSim.Framework.Console.OpenSimAppender, OpenSim.Framework.Console">
<filter type="log4net.Filter.LoggerMatchFilter">
<loggerToMatch value="special"/>
<acceptOnMatch value="false"/>
</filter>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date{HH:mm:ss} - %message%newline" />
</layout>
</appender>
<appender name="LogFileAppender" type="log4net.Appender.FileAppender">
<file value="Robust.32BitLaunch.log" />
<appendToFile value="true" />
<filter type="log4net.Filter.LoggerMatchFilter">
<loggerToMatch value="special"/>
<acceptOnMatch value="false"/>
</filter>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %-5level - %logger %message%newline" />
</layout>
</appender>
<appender name="StatsLogFileAppender" type="log4net.Appender.FileAppender">
<file value="RobustStats.log"/>
<appendToFile value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date - %message%newline" />
</layout>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="Console" />
<appender-ref ref="LogFileAppender" />
</root>
<!-- used for stats recording -->
<logger name="special.StatsLogger">
<appender-ref ref="StatsLogFileAppender"/>
</logger>
</log4net>
</configuration>

View File

@ -11,6 +11,10 @@
</appSettings>
<log4net>
<appender name="Console" type="OpenSim.Framework.Console.OpenSimAppender, OpenSim.Framework.Console">
<filter type="log4net.Filter.LoggerMatchFilter">
<loggerToMatch value="special"/>
<acceptOnMatch value="false"/>
</filter>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date{HH:mm:ss} - %message%newline" />
</layout>
@ -19,15 +23,32 @@
<appender name="LogFileAppender" type="log4net.Appender.FileAppender">
<file value="Robust.log" />
<appendToFile value="true" />
<filter type="log4net.Filter.LoggerMatchFilter">
<loggerToMatch value="special"/>
<acceptOnMatch value="false"/>
</filter>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %-5level - %logger %message%newline" />
</layout>
</appender>
<appender name="StatsLogFileAppender" type="log4net.Appender.FileAppender">
<file value="RobustStats.log"/>
<appendToFile value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date - %message%newline" />
</layout>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="Console" />
<appender-ref ref="LogFileAppender" />
</root>
<!-- used for stats recording -->
<logger name="special.StatsLogger">
<appender-ref ref="StatsLogFileAppender"/>
</logger>
</log4net>
</configuration>

View File

@ -30,6 +30,17 @@
SimulationServiceInConnector = true
LibraryModule = true
[SimulationService]
; This is the protocol version which the simulator advertises to the source destination when acting as a target destination for a teleport
; It is used to control the teleport handoff process.
; Valid values are
; "SIMULATION/0.2"
; - this is the default. A source simulator which only implements "SIMULATION/0.1" can still teleport with that protocol
; - this protocol is more efficient than "SIMULATION/0.1"
; "SIMULATION/0.1"
; - this is an older teleport protocol used in OpenSimulator 0.7.5 and before.
ConnectorProtocolVersion = "SIMULATION/0.2"
[SimulationDataStore]
LocalServiceModule = "OpenSim.Services.Connectors.dll:SimulationDataService"

View File

@ -26,6 +26,17 @@
GridInfoServiceInConnector = true
MapImageServiceInConnector = true
[SimulationService]
; This is the protocol version which the simulator advertises to the source destination when acting as a target destination for a teleport
; It is used to control the teleport handoff process.
; Valid values are
; "SIMULATION/0.2"
; - this is the default. A source simulator which only implements "SIMULATION/0.1" can still teleport with that protocol
; - this protocol is more efficient than "SIMULATION/0.1"
; "SIMULATION/0.1"
; - this is an older teleport protocol used in OpenSimulator 0.7.5 and before.
ConnectorProtocolVersion = "SIMULATION/0.2"
[SimulationDataStore]
LocalServiceModule = "OpenSim.Services.Connectors.dll:SimulationDataService"