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.csavinationmerge
commit
005c69511d
|
@ -467,12 +467,12 @@ namespace OpenSim.Groups
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send notice out to everyone that wants notices
|
// 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))
|
foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetRequestingAgentIDStr(remoteClient), GroupID))
|
||||||
{
|
{
|
||||||
if (member.AcceptNotices)
|
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;
|
msg.toAgentID = member.AgentID.Guid;
|
||||||
OutgoingInstantMessage(msg, member.AgentID);
|
OutgoingInstantMessage(msg, member.AgentID);
|
||||||
}
|
}
|
||||||
|
|
|
@ -292,6 +292,12 @@ namespace OpenSim.Framework
|
||||||
public Vector3 AtAxis;
|
public Vector3 AtAxis;
|
||||||
public Vector3 LeftAxis;
|
public Vector3 LeftAxis;
|
||||||
public Vector3 UpAxis;
|
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 bool SenderWantsToWaitForRoot;
|
||||||
|
|
||||||
public float Far;
|
public float Far;
|
||||||
|
|
|
@ -156,7 +156,27 @@ namespace OpenSim.Framework.Console
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
/// <param name='console'>Can be null if no console is available.</param>
|
/// <param name='console'>Can be null if no console is available.</param>
|
||||||
/// <param name='rawConsoleVector'>/param>
|
/// <param name='rawConsoleVector'>/param>
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -35,9 +35,9 @@ using OpenMetaverse.StructuredData;
|
||||||
namespace OpenSim.Framework.Monitoring
|
namespace OpenSim.Framework.Monitoring
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Singleton used to provide access to statistics reporters
|
/// Static class used to register/deregister/fetch statistics
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class StatsManager
|
public static class StatsManager
|
||||||
{
|
{
|
||||||
// Subcommand used to list other stats.
|
// Subcommand used to list other stats.
|
||||||
public const string AllSubCommand = "all";
|
public const string AllSubCommand = "all";
|
||||||
|
@ -81,6 +81,8 @@ namespace OpenSim.Framework.Monitoring
|
||||||
+ "More than one name can be given separated by spaces.\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);
|
||||||
|
|
||||||
|
StatsLogger.RegisterConsoleCommands(console);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void HandleShowStatsCommand(string module, string[] cmd)
|
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)
|
private static void OutputAllStatsToConsole(ICommandConsole con)
|
||||||
{
|
{
|
||||||
foreach (var category in RegisteredStats.Values)
|
foreach (string report in GetAllStatsReports())
|
||||||
{
|
con.Output(report);
|
||||||
OutputCategoryStatsToConsole(con, category);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(
|
private static void OutputCategoryStatsToConsole(
|
||||||
ICommandConsole con, SortedDictionary<string, SortedDictionary<string, Stat>> category)
|
ICommandConsole con, SortedDictionary<string, SortedDictionary<string, Stat>> category)
|
||||||
{
|
{
|
||||||
foreach (var container in category.Values)
|
foreach (string report in GetCategoryStatsReports(category))
|
||||||
{
|
con.Output(report);
|
||||||
OutputContainerStatsToConsole(con, container);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
foreach (Stat stat in container.Values)
|
||||||
{
|
reports.Add(stat.ToConsoleString());
|
||||||
con.Output(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:
|
// Creates an OSDMap of the format:
|
||||||
|
@ -257,7 +285,7 @@ namespace OpenSim.Framework.Monitoring
|
||||||
// }
|
// }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Registers a statistic.
|
/// Register a statistic.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name='stat'></param>
|
/// <param name='stat'></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
|
|
@ -380,6 +380,7 @@ namespace OpenSim.Framework.Monitoring
|
||||||
if (MemoryWatchdog.Enabled)
|
if (MemoryWatchdog.Enabled)
|
||||||
MemoryWatchdog.Update();
|
MemoryWatchdog.Update();
|
||||||
|
|
||||||
|
ChecksManager.CheckChecks();
|
||||||
StatsManager.RecordStats();
|
StatsManager.RecordStats();
|
||||||
|
|
||||||
m_watchdogTimer.Start();
|
m_watchdogTimer.Start();
|
||||||
|
|
|
@ -246,7 +246,7 @@ namespace OpenSim.Framework.Servers
|
||||||
"Show thread status", HandleShow);
|
"Show thread status", HandleShow);
|
||||||
|
|
||||||
m_console.Commands.AddCommand(
|
m_console.Commands.AddCommand(
|
||||||
"General", false, "threads abort",
|
"Debug", false, "threads abort",
|
||||||
"threads abort <thread-id>",
|
"threads abort <thread-id>",
|
||||||
"Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort);
|
"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\"",
|
"Show thread status. Synonym for \"show threads\"",
|
||||||
(string module, string[] args) => Notice(GetThreadsReport()));
|
(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(
|
m_console.Commands.AddCommand(
|
||||||
"General", false, "force gc",
|
"Debug", false, "force gc",
|
||||||
"force gc",
|
"force gc",
|
||||||
"Manually invoke runtime garbage collection. For debugging purposes",
|
"Manually invoke runtime garbage collection. For debugging purposes",
|
||||||
HandleForceGc);
|
HandleForceGc);
|
||||||
|
@ -272,16 +296,142 @@ namespace OpenSim.Framework.Servers
|
||||||
"shutdown",
|
"shutdown",
|
||||||
"Quit the application", (mod, args) => Shutdown());
|
"Quit the application", (mod, args) => Shutdown());
|
||||||
|
|
||||||
|
ChecksManager.RegisterConsoleCommands(m_console);
|
||||||
StatsManager.RegisterConsoleCommands(m_console);
|
StatsManager.RegisterConsoleCommands(m_console);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RegisterCommonComponents(IConfigSource configSource)
|
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 = new ServerStatsCollector();
|
||||||
m_serverStatsCollector.Initialise(configSource);
|
m_serverStatsCollector.Initialise(configSource);
|
||||||
m_serverStatsCollector.Start();
|
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)
|
private void HandleForceGc(string module, string[] args)
|
||||||
{
|
{
|
||||||
Notice("Manually invoking runtime garbage collection");
|
Notice("Manually invoking runtime garbage collection");
|
||||||
|
|
|
@ -66,6 +66,11 @@ namespace OpenSim.Framework
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static int RequestNumber { get; internal set; }
|
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>
|
/// <summary>
|
||||||
/// this is the header field used to communicate the local request id
|
/// this is the header field used to communicate the local request id
|
||||||
/// used for performance and debugging
|
/// used for performance and debugging
|
||||||
|
@ -144,10 +149,17 @@ namespace OpenSim.Framework
|
||||||
}
|
}
|
||||||
|
|
||||||
public static OSDMap ServiceOSDRequest(string url, OSDMap data, string method, int timeout, bool compressed)
|
public static OSDMap ServiceOSDRequest(string url, OSDMap data, string method, int timeout, bool compressed)
|
||||||
|
{
|
||||||
|
if (SerializeOSDRequestsPerEndpoint)
|
||||||
{
|
{
|
||||||
lock (EndPointLock(url))
|
lock (EndPointLock(url))
|
||||||
{
|
{
|
||||||
return ServiceOSDRequestWorker(url,data,method,timeout,compressed);
|
return ServiceOSDRequestWorker(url, data, method, timeout, compressed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ServiceOSDRequestWorker(url, data, method, timeout, compressed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -103,26 +103,38 @@ namespace OpenSim
|
||||||
"[OPENSIM MAIN]: Environment variable MONO_THREADS_PER_CPU is {0}", monoThreadsPerCpu ?? "unset");
|
"[OPENSIM MAIN]: Environment variable MONO_THREADS_PER_CPU is {0}", monoThreadsPerCpu ?? "unset");
|
||||||
|
|
||||||
// Verify the Threadpool allocates or uses enough worker and IO completion threads
|
// Verify the Threadpool allocates or uses enough worker and IO completion threads
|
||||||
// .NET 2.0 workerthreads default to 50 * numcores
|
// .NET 2.0, workerthreads default to 50 * numcores
|
||||||
// .NET 3.0 workerthreads defaults to 250 * numcores
|
// .NET 3.0, workerthreads defaults to 250 * numcores
|
||||||
// .NET 4.0 workerthreads are dynamic based on bitness and OS resources
|
// .NET 4.0, workerthreads are dynamic based on bitness and OS resources
|
||||||
// Max IO Completion threads are 1000 on all 3 CLRs.
|
// 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 workerThreadsMin = 500;
|
||||||
int workerThreadsMax = 1000; // may need further adjustment to match other CLR
|
int workerThreadsMax = 1000; // may need further adjustment to match other CLR
|
||||||
int iocpThreadsMin = 1000;
|
int iocpThreadsMin = 1000;
|
||||||
int iocpThreadsMax = 2000; // may need further adjustment to match other CLR
|
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;
|
int workerThreads, iocpThreads;
|
||||||
System.Threading.ThreadPool.GetMaxThreads(out workerThreads, out 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)
|
if (workerThreads < workerThreadsMin)
|
||||||
{
|
{
|
||||||
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)
|
if (workerThreads > workerThreadsMax)
|
||||||
{
|
{
|
||||||
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.
|
// Increase the number of IOCP threads available.
|
||||||
|
@ -130,22 +142,24 @@ namespace OpenSim
|
||||||
if (iocpThreads < iocpThreadsMin)
|
if (iocpThreads < iocpThreadsMin)
|
||||||
{
|
{
|
||||||
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
|
// Make sure we don't overallocate IOCP threads and thrash system resources
|
||||||
if ( iocpThreads > iocpThreadsMax )
|
if ( iocpThreads > iocpThreadsMax )
|
||||||
{
|
{
|
||||||
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
|
// set the resulting worker and IO completion thread counts back to ThreadPool
|
||||||
if ( System.Threading.ThreadPool.SetMaxThreads(workerThreads, iocpThreads) )
|
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
|
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.
|
// Check if the system is compatible with OpenSimulator.
|
||||||
|
@ -153,17 +167,16 @@ namespace OpenSim
|
||||||
string supported = String.Empty;
|
string supported = String.Empty;
|
||||||
if (Util.IsEnvironmentSupported(ref supported))
|
if (Util.IsEnvironmentSupported(ref supported))
|
||||||
{
|
{
|
||||||
m_log.Info("Environment is compatible.\n");
|
m_log.Info("[OPENSIM MAIN]: Environment is supported by OpenSimulator.");
|
||||||
}
|
}
|
||||||
else
|
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
|
// Configure nIni aliases and localles
|
||||||
Culture.SetCurrentCulture();
|
Culture.SetCurrentCulture();
|
||||||
|
|
||||||
|
|
||||||
// Validate that the user has the most basic configuration done
|
// 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
|
// If not, offer to do the most basic configuration for them warning them along the way of the importance of
|
||||||
// reading these files.
|
// reading these files.
|
||||||
|
|
|
@ -337,7 +337,6 @@ namespace OpenSim
|
||||||
config.Set("physics", "OpenDynamicsEngine");
|
config.Set("physics", "OpenDynamicsEngine");
|
||||||
config.Set("meshing", "Meshmerizer");
|
config.Set("meshing", "Meshmerizer");
|
||||||
config.Set("physical_prim", true);
|
config.Set("physical_prim", true);
|
||||||
config.Set("see_into_this_sim_from_neighbor", true);
|
|
||||||
config.Set("serverside_object_permissions", true);
|
config.Set("serverside_object_permissions", true);
|
||||||
config.Set("storage_plugin", "OpenSim.Data.SQLite.dll");
|
config.Set("storage_plugin", "OpenSim.Data.SQLite.dll");
|
||||||
config.Set("storage_connection_string", "URI=file:OpenSim.db,version=3");
|
config.Set("storage_connection_string", "URI=file:OpenSim.db,version=3");
|
||||||
|
|
|
@ -29,6 +29,7 @@ using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Threading;
|
||||||
using log4net.Config;
|
using log4net.Config;
|
||||||
using Nini.Config;
|
using Nini.Config;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
@ -53,6 +54,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
|
||||||
[TestFixtureSetUp]
|
[TestFixtureSetUp]
|
||||||
public void FixtureInit()
|
public void FixtureInit()
|
||||||
{
|
{
|
||||||
|
// Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread.
|
||||||
|
Util.FireAndForgetMethod = FireAndForgetMethod.None;
|
||||||
|
|
||||||
using (
|
using (
|
||||||
Stream resource
|
Stream resource
|
||||||
= GetType().Assembly.GetManifestResourceStream(
|
= 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]
|
[SetUp]
|
||||||
public override void SetUp()
|
public override void SetUp()
|
||||||
{
|
{
|
||||||
|
|
|
@ -166,7 +166,7 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender
|
||||||
|
|
||||||
// Do Decode!
|
// Do Decode!
|
||||||
if (decode)
|
if (decode)
|
||||||
Decode(assetID, j2kData);
|
Util.FireAndForget(delegate { Decode(assetID, j2kData); });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,8 +54,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
public int DebugLevel { get; set; }
|
public int DebugLevel { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Period to sleep per 100 prims in order to avoid CPU spikes when an avatar with many attachments logs in
|
/// Period to sleep per 100 prims in order to avoid CPU spikes when an avatar with many attachments logs in/changes
|
||||||
/// or many avatars with a medium levels of attachments login simultaneously.
|
/// outfit or many avatars with a medium levels of attachments login/change outfit simultaneously.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// A value of 0 will apply no pause. The pause is specified in milliseconds.
|
/// A value of 0 will apply no pause. The pause is specified in milliseconds.
|
||||||
|
@ -1096,6 +1096,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
if (tainted)
|
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;
|
return objatt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -694,7 +694,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
TransferAgent_V2(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, version, out reason);
|
TransferAgent_V2(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, version, out reason);
|
||||||
else
|
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,
|
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;
|
ulong destinationHandle = finalDestination.RegionHandle;
|
||||||
AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
|
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.
|
// Let's create an agent there if one doesn't exist yet.
|
||||||
// NOTE: logout will always be false for a non-HG teleport.
|
// NOTE: logout will always be false for a non-HG teleport.
|
||||||
bool logout = false;
|
bool logout = false;
|
||||||
|
@ -961,6 +963,27 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
return;
|
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.
|
// Past this point we have to attempt clean up if the teleport fails, so update transfer state.
|
||||||
m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
|
m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
|
||||||
|
|
||||||
|
@ -1063,21 +1086,23 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
if (!sp.DoNotCloseAfterTeleport)
|
if (!sp.DoNotCloseAfterTeleport)
|
||||||
{
|
{
|
||||||
// OK, it got this agent. Let's close everything
|
// 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.CloseChildAgents(newRegionX, newRegionY);
|
||||||
sp.Scene.IncomingCloseAgent(sp.UUID, false);
|
sp.Scene.IncomingCloseAgent(sp.UUID, false);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
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;
|
sp.DoNotCloseAfterTeleport = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
// now we have a child agent in this region.
|
// now we have a child agent in this region.
|
||||||
sp.Reset();
|
sp.Reset();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Clean up an inter-region teleport that did not complete, either because of simulator failure or cancellation.
|
/// Clean up an inter-region teleport that did not complete, either because of simulator failure or cancellation.
|
||||||
|
|
|
@ -62,6 +62,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||||
private string m_ThisGatekeeper;
|
private string m_ThisGatekeeper;
|
||||||
private bool m_RestrictInventoryAccessAbroad;
|
private bool m_RestrictInventoryAccessAbroad;
|
||||||
|
|
||||||
|
private bool m_bypassPermissions = true;
|
||||||
|
|
||||||
// private bool m_Initialized = false;
|
// private bool m_Initialized = false;
|
||||||
|
|
||||||
#region INonSharedRegionModule
|
#region INonSharedRegionModule
|
||||||
|
@ -100,6 +102,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_log.Warn("[HG INVENTORY ACCESS MODULE]: HGInventoryAccessModule configs not found. ProfileServerURI not set!");
|
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.OnNewInventoryItemUploadComplete += UploadInventoryItem;
|
||||||
scene.EventManager.OnTeleportStart += TeleportStart;
|
scene.EventManager.OnTeleportStart += TeleportStart;
|
||||||
scene.EventManager.OnTeleportFail += TeleportFail;
|
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
|
#endregion
|
||||||
|
@ -416,6 +427,37 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||||
// No-op for now
|
// 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
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -809,7 +809,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
|
||||||
}
|
}
|
||||||
|
|
||||||
objlist.Add(g);
|
objlist.Add(g);
|
||||||
veclist.Add(new Vector3(0, 0, 0));
|
veclist.Add(Vector3.Zero);
|
||||||
|
|
||||||
float offsetHeight = 0;
|
float offsetHeight = 0;
|
||||||
pos = m_Scene.GetNewRezLocation(
|
pos = m_Scene.GetNewRezLocation(
|
||||||
|
|
|
@ -163,7 +163,7 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
|
||||||
|
|
||||||
public void RegisterScriptInvocation(object target, MethodInfo mi)
|
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;
|
Type delegateType;
|
||||||
List<Type> typeArgs = mi.GetParameters()
|
List<Type> typeArgs = mi.GetParameters()
|
||||||
|
@ -325,7 +325,7 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void RegisterConstant(string cname, object value)
|
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)
|
lock (m_constants)
|
||||||
{
|
{
|
||||||
m_constants.Add(cname,value);
|
m_constants.Add(cname,value);
|
||||||
|
|
|
@ -63,35 +63,41 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private bool m_ModuleEnabled = false;
|
private bool m_ModuleEnabled = false;
|
||||||
|
|
||||||
public LocalSimulationConnectorModule()
|
|
||||||
{
|
|
||||||
ServiceVersion = "SIMULATION/0.2";
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Region Module interface
|
#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)
|
if (moduleConfig != null)
|
||||||
{
|
{
|
||||||
string name = moduleConfig.GetString("SimulationServices", "");
|
string name = moduleConfig.GetString("SimulationServices", "");
|
||||||
if (name == Name)
|
if (name == Name)
|
||||||
{
|
{
|
||||||
//IConfig userConfig = config.Configs["SimulationService"];
|
InitialiseService(configSource);
|
||||||
//if (userConfig == null)
|
|
||||||
//{
|
|
||||||
// m_log.Error("[AVATAR CONNECTOR]: SimulationService missing from OpenSim.ini");
|
|
||||||
// return;
|
|
||||||
//}
|
|
||||||
|
|
||||||
m_ModuleEnabled = true;
|
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()
|
public void PostInitialise()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,9 +50,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
|
||||||
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RemoteSimulationConnectorModule")]
|
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RemoteSimulationConnectorModule")]
|
||||||
public class RemoteSimulationConnectorModule : ISharedRegionModule, ISimulationService
|
public class RemoteSimulationConnectorModule : ISharedRegionModule, ISimulationService
|
||||||
{
|
{
|
||||||
private bool initialized = false;
|
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
private bool initialized = false;
|
||||||
protected bool m_enabled = false;
|
protected bool m_enabled = false;
|
||||||
protected Scene m_aScene;
|
protected Scene m_aScene;
|
||||||
// RemoteSimulationConnector does not care about local regions; it delegates that to the Local module
|
// 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
|
#region Region Module interface
|
||||||
|
|
||||||
public virtual void Initialise(IConfigSource config)
|
public virtual void Initialise(IConfigSource configSource)
|
||||||
{
|
{
|
||||||
|
IConfig moduleConfig = configSource.Configs["Modules"];
|
||||||
IConfig moduleConfig = config.Configs["Modules"];
|
|
||||||
if (moduleConfig != null)
|
if (moduleConfig != null)
|
||||||
{
|
{
|
||||||
string name = moduleConfig.GetString("SimulationServices", "");
|
string name = moduleConfig.GetString("SimulationServices", "");
|
||||||
if (name == Name)
|
if (name == Name)
|
||||||
{
|
{
|
||||||
//IConfig userConfig = config.Configs["SimulationService"];
|
m_localBackend = new LocalSimulationConnectorModule();
|
||||||
//if (userConfig == null)
|
|
||||||
//{
|
m_localBackend.InitialiseService(configSource);
|
||||||
// m_log.Error("[AVATAR CONNECTOR]: SimulationService missing from OpenSim.ini");
|
|
||||||
// return;
|
|
||||||
//}
|
|
||||||
|
|
||||||
m_remoteConnector = new SimulationServiceConnector();
|
m_remoteConnector = new SimulationServiceConnector();
|
||||||
|
|
||||||
m_enabled = true;
|
m_enabled = true;
|
||||||
|
|
||||||
m_log.Info("[SIMULATION CONNECTOR]: Remote simulation enabled");
|
m_log.Info("[REMOTE SIMULATION CONNECTOR]: Remote simulation enabled.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,7 +139,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
|
||||||
|
|
||||||
protected virtual void InitOnce(Scene scene)
|
protected virtual void InitOnce(Scene scene)
|
||||||
{
|
{
|
||||||
m_localBackend = new LocalSimulationConnectorModule();
|
|
||||||
m_aScene = scene;
|
m_aScene = scene;
|
||||||
//m_regionClient = new RegionToRegionClient(m_aScene, m_hyperlinkService);
|
//m_regionClient = new RegionToRegionClient(m_aScene, m_hyperlinkService);
|
||||||
m_thisIP = Util.GetHostFromDNS(scene.RegionInfo.ExternalHostName);
|
m_thisIP = Util.GetHostFromDNS(scene.RegionInfo.ExternalHostName);
|
||||||
|
|
|
@ -551,6 +551,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
//Console.WriteLine("Scene.Inventory.cs: GiveInventoryItem");
|
//Console.WriteLine("Scene.Inventory.cs: GiveInventoryItem");
|
||||||
|
|
||||||
|
if (!Permissions.CanTransferUserInventory(itemId, senderId, recipient))
|
||||||
|
return null;
|
||||||
|
|
||||||
InventoryItemBase item = new InventoryItemBase(itemId, senderId);
|
InventoryItemBase item = new InventoryItemBase(itemId, senderId);
|
||||||
item = InventoryService.GetItem(item);
|
item = InventoryService.GetItem(item);
|
||||||
|
|
||||||
|
@ -2127,7 +2130,10 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
{
|
{
|
||||||
// If we don't have permission, stop right here
|
// If we don't have permission, stop right here
|
||||||
if (!permissionToTakeCopy)
|
if (!permissionToTakeCopy)
|
||||||
|
{
|
||||||
|
remoteClient.SendAlertMessage("You don't have permission to take the object");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
permissionToTake = true;
|
permissionToTake = true;
|
||||||
// Don't delete
|
// Don't delete
|
||||||
|
|
|
@ -4174,9 +4174,16 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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)
|
if (RegionInfo.EstateSettings != null)
|
||||||
{
|
{
|
||||||
if (RegionInfo.EstateSettings.IsBanned(agent.AgentID, 0))
|
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",
|
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);
|
agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
|
||||||
|
@ -4190,12 +4197,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
m_log.ErrorFormat("[CONNECTION BEGIN]: Estate Settings is null!");
|
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)
|
|
||||||
{
|
|
||||||
List<UUID> agentGroups = new List<UUID>();
|
List<UUID> agentGroups = new List<UUID>();
|
||||||
|
|
||||||
if (m_groupsModule != null)
|
if (m_groupsModule != null)
|
||||||
|
@ -4392,36 +4393,42 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have to wait until the viewer contacts this region
|
// 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.
|
// 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}",
|
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;
|
int ntimes = 20;
|
||||||
if (cAgentData.SenderWantsToWaitForRoot)
|
if (cAgentData.SenderWantsToWaitForRoot)
|
||||||
{
|
{
|
||||||
while (childAgentUpdate.IsChildAgent && ntimes-- > 0)
|
while (sp.IsChildAgent && ntimes-- > 0)
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
|
|
||||||
m_log.DebugFormat(
|
m_log.DebugFormat(
|
||||||
"[SCENE]: Found presence {0} {1} {2} in {3} after {4} waits",
|
"[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 false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -294,10 +294,24 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private Vector3 posLastSignificantMove;
|
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;
|
string m_callbackURI;
|
||||||
|
|
||||||
UUID m_originRegionID;
|
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>
|
/// <value>
|
||||||
/// Script engines present in the scene
|
/// Script engines present in the scene
|
||||||
/// </value>
|
/// </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;
|
private float m_speedModifier = 1.0f;
|
||||||
|
|
||||||
public float SpeedModifier
|
public float SpeedModifier
|
||||||
|
@ -1516,14 +1523,14 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
int count = 20;
|
int count = 20;
|
||||||
while (m_originRegionID.Equals(UUID.Zero) && count-- > 0)
|
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);
|
Thread.Sleep(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_originRegionID.Equals(UUID.Zero))
|
if (m_originRegionID.Equals(UUID.Zero))
|
||||||
{
|
{
|
||||||
// Movement into region will fail
|
// 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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1829,8 +1836,14 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
// Here's where you get them.
|
// Here's where you get them.
|
||||||
m_AgentControlFlags = flags;
|
m_AgentControlFlags = flags;
|
||||||
m_headrotation = agentData.HeadRotation;
|
m_headrotation = agentData.HeadRotation;
|
||||||
|
byte oldState = State;
|
||||||
State = agentData.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;
|
PhysicsActor actor = PhysicsActor;
|
||||||
if (actor == null)
|
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
|
// Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m
|
||||||
if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance ||
|
if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance)
|
||||||
Util.GetDistanceTo(CameraPosition, m_lastChildAgentUpdateCamPosition) >= Scene.ChildReprioritizationDistance)
|
|
||||||
{
|
{
|
||||||
m_lastChildAgentUpdatePosition = AbsolutePosition;
|
m_lastChildAgentUpdatePosition = AbsolutePosition;
|
||||||
m_lastChildAgentUpdateCamPosition = CameraPosition;
|
m_lastChildAgentUpdateCamPosition = CameraPosition;
|
||||||
|
|
|
@ -49,10 +49,20 @@ public class ExtendedPhysics : INonSharedRegionModule
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
private static string LogHeader = "[EXTENDED PHYSICS]";
|
private static string LogHeader = "[EXTENDED PHYSICS]";
|
||||||
|
|
||||||
|
// =============================================================
|
||||||
// Since BulletSim is a plugin, this these values aren't defined easily in one place.
|
// 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";
|
public const string PhysFunctSetLinksetType = "BulletSim.SetLinksetType";
|
||||||
|
|
||||||
|
// =============================================================
|
||||||
|
|
||||||
private IConfig Configuration { get; set; }
|
private IConfig Configuration { get; set; }
|
||||||
private bool Enabled { get; set; }
|
private bool Enabled { get; set; }
|
||||||
private Scene BaseScene { get; set; }
|
private Scene BaseScene { get; set; }
|
||||||
|
@ -123,6 +133,7 @@ public class ExtendedPhysics : INonSharedRegionModule
|
||||||
|
|
||||||
// Register as LSL functions all the [ScriptInvocation] marked methods.
|
// Register as LSL functions all the [ScriptInvocation] marked methods.
|
||||||
Comms.RegisterScriptInvocations(this);
|
Comms.RegisterScriptInvocations(this);
|
||||||
|
Comms.RegisterConstants(this);
|
||||||
|
|
||||||
// When an object is modified, we might need to update its extended physics parameters
|
// When an object is modified, we might need to update its extended physics parameters
|
||||||
BaseScene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene;
|
BaseScene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene;
|
||||||
|
@ -136,7 +147,6 @@ public class ExtendedPhysics : INonSharedRegionModule
|
||||||
|
|
||||||
private void EventManager_OnObjectAddedToScene(SceneObjectGroup obj)
|
private void EventManager_OnObjectAddedToScene(SceneObjectGroup obj)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Event generated when some property of a prim changes.
|
// 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;
|
public static int PHYS_LINKSET_TYPE_MANUAL = 2;
|
||||||
|
|
||||||
[ScriptInvocation]
|
[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.
|
// The part that is requesting the change.
|
||||||
SceneObjectPart requestingPart = BaseScene.GetSceneObjectPart(hostID);
|
SceneObjectPart requestingPart = BaseScene.GetSceneObjectPart(hostID);
|
||||||
|
@ -186,7 +198,7 @@ public class ExtendedPhysics : INonSharedRegionModule
|
||||||
Physics.Manager.PhysicsActor rootPhysActor = rootPart.PhysActor;
|
Physics.Manager.PhysicsActor rootPhysActor = rootPart.PhysActor;
|
||||||
if (rootPhysActor != null)
|
if (rootPhysActor != null)
|
||||||
{
|
{
|
||||||
rootPhysActor.Extension(PhysFunctSetLinksetType, linksetType);
|
ret = (int)rootPhysActor.Extension(PhysFunctSetLinksetType, linksetType);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -204,6 +216,49 @@ public class ExtendedPhysics : INonSharedRegionModule
|
||||||
{
|
{
|
||||||
m_log.WarnFormat("{0} physSetLinsetType: cannot find script object in scene. hostID={1}", LogHeader, hostID);
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,17 @@ public abstract class BSLinkset
|
||||||
return ret;
|
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; }
|
public BSPrimLinkable LinksetRoot { get; protected set; }
|
||||||
|
|
||||||
protected BSScene m_physicsScene { get; private set; }
|
protected BSScene m_physicsScene { get; private set; }
|
||||||
|
@ -78,7 +89,8 @@ public abstract class BSLinkset
|
||||||
public int LinksetID { get; private set; }
|
public int LinksetID { get; private set; }
|
||||||
|
|
||||||
// The children under the root in this linkset.
|
// 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.
|
// We lock the diddling of linkset classes to prevent any badness.
|
||||||
// This locks the modification of the instances of this class. Changes
|
// This locks the modification of the instances of this class. Changes
|
||||||
|
@ -109,7 +121,7 @@ public abstract class BSLinkset
|
||||||
m_nextLinksetID = 1;
|
m_nextLinksetID = 1;
|
||||||
m_physicsScene = scene;
|
m_physicsScene = scene;
|
||||||
LinksetRoot = parent;
|
LinksetRoot = parent;
|
||||||
m_children = new HashSet<BSPrimLinkable>();
|
m_children = new Dictionary<BSPrimLinkable, BSLinkInfo>();
|
||||||
LinksetMass = parent.RawMass;
|
LinksetMass = parent.RawMass;
|
||||||
Rebuilding = false;
|
Rebuilding = false;
|
||||||
|
|
||||||
|
@ -170,17 +182,7 @@ public abstract class BSLinkset
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
lock (m_linksetActivityLock)
|
lock (m_linksetActivityLock)
|
||||||
{
|
{
|
||||||
ret = m_children.Contains(child);
|
ret = m_children.ContainsKey(child);
|
||||||
/* Safer version but the above should work
|
|
||||||
foreach (BSPrimLinkable bp in m_children)
|
|
||||||
{
|
|
||||||
if (child.LocalID == bp.LocalID)
|
|
||||||
{
|
|
||||||
ret = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -194,7 +196,24 @@ public abstract class BSLinkset
|
||||||
lock (m_linksetActivityLock)
|
lock (m_linksetActivityLock)
|
||||||
{
|
{
|
||||||
action(LinksetRoot);
|
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))
|
if (action(po))
|
||||||
break;
|
break;
|
||||||
|
@ -364,7 +383,7 @@ public abstract class BSLinkset
|
||||||
{
|
{
|
||||||
lock (m_linksetActivityLock)
|
lock (m_linksetActivityLock)
|
||||||
{
|
{
|
||||||
foreach (BSPrimLinkable bp in m_children)
|
foreach (BSPrimLinkable bp in m_children.Keys)
|
||||||
{
|
{
|
||||||
mass += bp.RawMass;
|
mass += bp.RawMass;
|
||||||
}
|
}
|
||||||
|
@ -382,7 +401,7 @@ public abstract class BSLinkset
|
||||||
com = LinksetRoot.Position * LinksetRoot.RawMass;
|
com = LinksetRoot.Position * LinksetRoot.RawMass;
|
||||||
float totalMass = LinksetRoot.RawMass;
|
float totalMass = LinksetRoot.RawMass;
|
||||||
|
|
||||||
foreach (BSPrimLinkable bp in m_children)
|
foreach (BSPrimLinkable bp in m_children.Keys)
|
||||||
{
|
{
|
||||||
com += bp.Position * bp.RawMass;
|
com += bp.Position * bp.RawMass;
|
||||||
totalMass += bp.RawMass;
|
totalMass += bp.RawMass;
|
||||||
|
@ -401,7 +420,7 @@ public abstract class BSLinkset
|
||||||
{
|
{
|
||||||
com = LinksetRoot.Position;
|
com = LinksetRoot.Position;
|
||||||
|
|
||||||
foreach (BSPrimLinkable bp in m_children)
|
foreach (BSPrimLinkable bp in m_children.Keys)
|
||||||
{
|
{
|
||||||
com += bp.Position;
|
com += bp.Position;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
public BSLinksetCompound(BSScene scene, BSPrimLinkable parent)
|
public BSLinksetCompound(BSScene scene, BSPrimLinkable parent)
|
||||||
: base(scene, parent)
|
: base(scene, parent)
|
||||||
{
|
{
|
||||||
|
LinksetImpl = LinksetImplementation.Compound;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ================================================================
|
// ================================================================
|
||||||
|
@ -257,7 +258,7 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
{
|
{
|
||||||
if (!HasChild(child))
|
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);
|
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
|
// Add the shapes of all the components of the linkset
|
||||||
int memberIndex = 1;
|
int memberIndex = 1;
|
||||||
ForEachMember(delegate(BSPrimLinkable cPrim)
|
ForEachMember((cPrim) =>
|
||||||
{
|
{
|
||||||
if (IsRoot(cPrim))
|
if (IsRoot(cPrim))
|
||||||
{
|
{
|
||||||
|
|
|
@ -36,8 +36,78 @@ public sealed class BSLinksetConstraints : BSLinkset
|
||||||
{
|
{
|
||||||
// private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]";
|
// 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)
|
public BSLinksetConstraints(BSScene scene, BSPrimLinkable parent) : base(scene, parent)
|
||||||
{
|
{
|
||||||
|
LinksetImpl = LinksetImplementation.Constraint;
|
||||||
}
|
}
|
||||||
|
|
||||||
// When physical properties are changed the linkset needs to recalculate
|
// When physical properties are changed the linkset needs to recalculate
|
||||||
|
@ -142,7 +212,7 @@ public sealed class BSLinksetConstraints : BSLinkset
|
||||||
{
|
{
|
||||||
if (!HasChild(child))
|
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);
|
DetailLog("{0},BSLinksetConstraints.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID);
|
||||||
|
|
||||||
|
@ -190,14 +260,23 @@ public sealed class BSLinksetConstraints : BSLinkset
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a static constraint between the two passed objects
|
// Create a static constraint between the two passed objects
|
||||||
private BSConstraint BuildConstraint(BSPrimLinkable rootPrim, BSPrimLinkable childPrim)
|
private BSConstraint BuildConstraint(BSPrimLinkable rootPrim, BSLinkInfo li)
|
||||||
{
|
{
|
||||||
// Zero motion for children so they don't interpolate
|
BSLinkInfoConstraint liConstraint = li as BSLinkInfoConstraint;
|
||||||
childPrim.ZeroMotion(true);
|
if (liConstraint == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Zero motion for children so they don't interpolate
|
||||||
|
li.member.ZeroMotion(true);
|
||||||
|
|
||||||
|
BSConstraint constrain = null;
|
||||||
|
|
||||||
|
switch (liConstraint.constraintType)
|
||||||
|
{
|
||||||
|
case ConstraintType.D6_CONSTRAINT_TYPE:
|
||||||
// Relative position normalized to the root prim
|
// Relative position normalized to the root prim
|
||||||
// Essentually a vector pointing from center of rootPrim to center of childPrim
|
// Essentually a vector pointing from center of rootPrim to center of li.member
|
||||||
OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position;
|
OMV.Vector3 childRelativePosition = liConstraint.member.Position - rootPrim.Position;
|
||||||
|
|
||||||
// real world coordinate of midpoint between the two objects
|
// real world coordinate of midpoint between the two objects
|
||||||
OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
|
OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
|
||||||
|
@ -205,15 +284,14 @@ public sealed class BSLinksetConstraints : BSLinkset
|
||||||
DetailLog("{0},BSLinksetConstraint.BuildConstraint,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}",
|
DetailLog("{0},BSLinksetConstraint.BuildConstraint,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}",
|
||||||
rootPrim.LocalID,
|
rootPrim.LocalID,
|
||||||
rootPrim.LocalID, rootPrim.PhysBody.AddrString,
|
rootPrim.LocalID, rootPrim.PhysBody.AddrString,
|
||||||
childPrim.LocalID, childPrim.PhysBody.AddrString,
|
liConstraint.member.LocalID, liConstraint.member.PhysBody.AddrString,
|
||||||
rootPrim.Position, childPrim.Position, midPoint);
|
rootPrim.Position, liConstraint.member.Position, midPoint);
|
||||||
|
|
||||||
// create a constraint that allows no freedom of movement between the two objects
|
// create a constraint that allows no freedom of movement between the two objects
|
||||||
// http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
|
// http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
|
||||||
|
|
||||||
BSConstraint6Dof constrain = new BSConstraint6Dof(
|
constrain = new BSConstraint6Dof(
|
||||||
m_physicsScene.World, rootPrim.PhysBody, childPrim.PhysBody, midPoint, true, true );
|
m_physicsScene.World, rootPrim.PhysBody, liConstraint.member.PhysBody, midPoint, true, true );
|
||||||
// PhysicsScene.World, childPrim.BSBody, rootPrim.BSBody, midPoint, true, true );
|
|
||||||
|
|
||||||
/* NOTE: below is an attempt to build constraint with full frame computation, etc.
|
/* 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
|
* Using the midpoint is easier since it lets the Bullet code manipulate the transforms
|
||||||
|
@ -222,41 +300,34 @@ public sealed class BSLinksetConstraints : BSLinkset
|
||||||
// ==================================================================================
|
// ==================================================================================
|
||||||
// relative position normalized to the root prim
|
// relative position normalized to the root prim
|
||||||
OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation);
|
OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation);
|
||||||
OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation;
|
OMV.Vector3 childRelativePosition = (liConstraint.member.Position - rootPrim.Position) * invThisOrientation;
|
||||||
|
|
||||||
// relative rotation of the child to the parent
|
// relative rotation of the child to the parent
|
||||||
OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation;
|
OMV.Quaternion childRelativeRotation = invThisOrientation * liConstraint.member.Orientation;
|
||||||
OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation);
|
OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation);
|
||||||
|
|
||||||
DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
|
DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, liConstraint.member.LocalID);
|
||||||
BS6DofConstraint constrain = new BS6DofConstraint(
|
constrain = new BS6DofConstraint(
|
||||||
PhysicsScene.World, rootPrim.Body, childPrim.Body,
|
PhysicsScene.World, rootPrim.Body, liConstraint.member.Body,
|
||||||
OMV.Vector3.Zero,
|
OMV.Vector3.Zero,
|
||||||
OMV.Quaternion.Inverse(rootPrim.Orientation),
|
OMV.Quaternion.Inverse(rootPrim.Orientation),
|
||||||
OMV.Vector3.Zero,
|
OMV.Vector3.Zero,
|
||||||
OMV.Quaternion.Inverse(childPrim.Orientation),
|
OMV.Quaternion.Inverse(liConstraint.member.Orientation),
|
||||||
true,
|
true,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
// ==================================================================================
|
// ==================================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
liConstraint.SetConstraintParameters(constrain);
|
||||||
|
|
||||||
m_physicsScene.Constraints.AddConstraint(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;
|
return constrain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,23 +388,24 @@ public sealed class BSLinksetConstraints : BSLinkset
|
||||||
return; // Note the 'finally' clause at the botton which will get executed.
|
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.
|
// 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.
|
// 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.)
|
// (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;
|
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.
|
// If constraint doesn't exist yet, create it.
|
||||||
constrain = BuildConstraint(LinksetRoot, child);
|
constrain = BuildConstraint(LinksetRoot, li);
|
||||||
}
|
}
|
||||||
constrain.RecomputeConstraintVariables(linksetMass);
|
constrain.RecomputeConstraintVariables(linksetMass);
|
||||||
|
|
||||||
// PhysicsScene.PE.DumpConstraint(PhysicsScene.World, constrain.Constraint); // DEBUG DEBUG
|
// PhysicsScene.PE.DumpConstraint(PhysicsScene.World, constrain.Constraint); // DEBUG DEBUG
|
||||||
}
|
return false; // 'false' says to keep processing other members
|
||||||
|
});
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|
|
@ -1541,6 +1541,50 @@ public class BSPrim : BSPhysObject
|
||||||
PhysicalActors.RemoveDependencies();
|
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 physics engine says that properties have updated. Update same and inform
|
||||||
// the world that things have changed.
|
// the world that things have changed.
|
||||||
// NOTE: BSPrim.UpdateProperties is overloaded by BSPrimLinkable which modifies updates from root and children prims.
|
// NOTE: BSPrim.UpdateProperties is overloaded by BSPrimLinkable which modifies updates from root and children prims.
|
||||||
|
|
|
@ -233,5 +233,46 @@ public class BSPrimLinkable : BSPrimDisplaced
|
||||||
base.HasSomeCollision = value;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -862,6 +862,23 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||||
|
|
||||||
public override bool IsThreaded { get { return false; } }
|
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
|
#region Taints
|
||||||
// The simulation execution order is:
|
// The simulation execution order is:
|
||||||
// Simulate()
|
// Simulate()
|
||||||
|
|
|
@ -418,7 +418,8 @@ namespace OpenSim.Region.Physics.Manager
|
||||||
// Extendable interface for new, physics engine specific operations
|
// Extendable interface for new, physics engine specific operations
|
||||||
public virtual object Extension(string pFunct, params object[] pParams)
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -393,7 +393,8 @@ namespace OpenSim.Region.Physics.Manager
|
||||||
// Extendable interface for new, physics engine specific operations
|
// Extendable interface for new, physics engine specific operations
|
||||||
public virtual object Extension(string pFunct, params object[] pParams)
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -319,7 +319,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
|
|
||||||
object[] convertedParms = new object[parms.Length];
|
object[] convertedParms = new object[parms.Length];
|
||||||
for (int i = 0; i < parms.Length; i++)
|
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
|
// now call the function, the contract with the function is that it will always return
|
||||||
// non-null but don't trust it completely
|
// 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;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -937,7 +937,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
|
||||||
{
|
{
|
||||||
string retval = null;
|
string retval = null;
|
||||||
if (value is int)
|
if (value is int)
|
||||||
retval = ((int)value).ToString();
|
retval = String.Format("new LSL_Types.LSLInteger({0})",((int)value).ToString());
|
||||||
else if (value is float)
|
else if (value is float)
|
||||||
retval = String.Format("new LSL_Types.LSLFloat({0})",((float)value).ToString());
|
retval = String.Format("new LSL_Types.LSLFloat({0})",((float)value).ToString());
|
||||||
else if (value is string)
|
else if (value is string)
|
||||||
|
|
|
@ -79,7 +79,11 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
||||||
{
|
{
|
||||||
m_simianURL = m_config.GetString("SimianServiceURL");
|
m_simianURL = m_config.GetString("SimianServiceURL");
|
||||||
if (String.IsNullOrEmpty(m_simianURL))
|
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
|
else
|
||||||
|
|
|
@ -74,11 +74,15 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
||||||
{
|
{
|
||||||
m_simianURL = m_config.GetString("SimianServiceURL");
|
m_simianURL = m_config.GetString("SimianServiceURL");
|
||||||
if (String.IsNullOrEmpty(m_simianURL))
|
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();
|
InitialiseSimCap();
|
||||||
SimulatorCapability = SimulatorCapability.Trim();
|
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)
|
catch (Exception e)
|
||||||
|
|
|
@ -68,8 +68,18 @@ namespace OpenSim.Tests.Clients.AssetsClient
|
||||||
m_log.InfoFormat("[ASSET CLIENT]: Connecting to {0} max threads = {1} - {2}", serverURI, max1, max2);
|
m_log.InfoFormat("[ASSET CLIENT]: Connecting to {0} max threads = {1} - {2}", serverURI, max1, max2);
|
||||||
ThreadPool.GetMinThreads(out max1, out max2);
|
ThreadPool.GetMinThreads(out max1, out max2);
|
||||||
m_log.InfoFormat("[ASSET CLIENT]: Connecting to {0} min threads = {1} - {2}", serverURI, max1, 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;
|
ServicePointManager.DefaultConnectionLimit = 12;
|
||||||
|
|
||||||
AssetServicesConnector m_Connector = new AssetServicesConnector(serverURI);
|
AssetServicesConnector m_Connector = new AssetServicesConnector(serverURI);
|
||||||
|
|
|
@ -239,7 +239,6 @@ namespace OpenSim.Tools.Configger
|
||||||
config.Set("physics", "OpenDynamicsEngine");
|
config.Set("physics", "OpenDynamicsEngine");
|
||||||
config.Set("meshing", "Meshmerizer");
|
config.Set("meshing", "Meshmerizer");
|
||||||
config.Set("physical_prim", true);
|
config.Set("physical_prim", true);
|
||||||
config.Set("see_into_this_sim_from_neighbor", true);
|
|
||||||
config.Set("serverside_object_permissions", true);
|
config.Set("serverside_object_permissions", true);
|
||||||
config.Set("storage_plugin", "OpenSim.Data.SQLite.dll");
|
config.Set("storage_plugin", "OpenSim.Data.SQLite.dll");
|
||||||
config.Set("storage_connection_string", "URI=file:OpenSim.db,version=3");
|
config.Set("storage_connection_string", "URI=file:OpenSim.db,version=3");
|
||||||
|
|
|
@ -11,22 +11,56 @@
|
||||||
</appSettings>
|
</appSettings>
|
||||||
<log4net>
|
<log4net>
|
||||||
<appender name="Console" type="OpenSim.Framework.Console.OpenSimAppender, OpenSim.Framework.Console">
|
<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">
|
<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>
|
</layout>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
<appender name="LogFileAppender" type="log4net.Appender.FileAppender">
|
<appender name="LogFileAppender" type="log4net.Appender.FileAppender">
|
||||||
<file value="OpenSim.32BitLaunch.log" />
|
<file value="OpenSim.32BitLaunch.log" />
|
||||||
<appendToFile value="true" />
|
<appendToFile value="true" />
|
||||||
|
<filter type="log4net.Filter.LoggerMatchFilter">
|
||||||
|
<loggerToMatch value="special"/>
|
||||||
|
<acceptOnMatch value="false"/>
|
||||||
|
</filter>
|
||||||
<layout type="log4net.Layout.PatternLayout">
|
<layout type="log4net.Layout.PatternLayout">
|
||||||
<conversionPattern value="%date %-5level - %logger %message%newline" />
|
<conversionPattern value="%date %-5level - %logger %message%newline" />
|
||||||
</layout>
|
</layout>
|
||||||
</appender>
|
</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>
|
<root>
|
||||||
<level value="DEBUG" />
|
<level value="DEBUG" />
|
||||||
<appender-ref ref="Console" />
|
<appender-ref ref="Console" />
|
||||||
<appender-ref ref="LogFileAppender" />
|
<appender-ref ref="LogFileAppender" />
|
||||||
</root>
|
</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>
|
</log4net>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|
|
@ -11,6 +11,10 @@
|
||||||
</appSettings>
|
</appSettings>
|
||||||
<log4net>
|
<log4net>
|
||||||
<appender name="Console" type="OpenSim.Framework.Console.OpenSimAppender, OpenSim.Framework.Console">
|
<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">
|
<layout type="log4net.Layout.PatternLayout">
|
||||||
<conversionPattern value="%date{HH:mm:ss} - %message" />
|
<conversionPattern value="%date{HH:mm:ss} - %message" />
|
||||||
<!-- console log with milliseconds. Useful for debugging -->
|
<!-- console log with milliseconds. Useful for debugging -->
|
||||||
|
@ -21,11 +25,23 @@
|
||||||
<appender name="LogFileAppender" type="log4net.Appender.FileAppender">
|
<appender name="LogFileAppender" type="log4net.Appender.FileAppender">
|
||||||
<file value="OpenSim.log" />
|
<file value="OpenSim.log" />
|
||||||
<appendToFile value="true" />
|
<appendToFile value="true" />
|
||||||
|
<filter type="log4net.Filter.LoggerMatchFilter">
|
||||||
|
<loggerToMatch value="special"/>
|
||||||
|
<acceptOnMatch value="false"/>
|
||||||
|
</filter>
|
||||||
<layout type="log4net.Layout.PatternLayout">
|
<layout type="log4net.Layout.PatternLayout">
|
||||||
<conversionPattern value="%date %-5level - %logger %message%newline" />
|
<conversionPattern value="%date %-5level - %logger %message%newline" />
|
||||||
</layout>
|
</layout>
|
||||||
</appender>
|
</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>
|
<root>
|
||||||
<level value="DEBUG" />
|
<level value="DEBUG" />
|
||||||
<appender-ref ref="Console" />
|
<appender-ref ref="Console" />
|
||||||
|
@ -42,5 +58,10 @@
|
||||||
<level value="INFO"/>
|
<level value="INFO"/>
|
||||||
</logger>
|
</logger>
|
||||||
|
|
||||||
|
<!-- used for stats recording -->
|
||||||
|
<logger name="special.StatsLogger">
|
||||||
|
<appender-ref ref="StatsLogFileAppender"/>
|
||||||
|
</logger>
|
||||||
|
|
||||||
</log4net>
|
</log4net>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|
|
@ -180,10 +180,6 @@
|
||||||
;; if the first change occurred this number of seconds ago.
|
;; if the first change occurred this number of seconds ago.
|
||||||
; MaximumTimeBeforePersistenceConsidered = 600
|
; 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
|
;# {physical_prim} {} {Allow prims to be physical?} {true false} true
|
||||||
;; if you would like to allow prims to be physical and move by physics
|
;; 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.
|
;; with the physical checkbox in the client set this to true.
|
||||||
|
|
|
@ -710,8 +710,8 @@
|
||||||
Enabled = true
|
Enabled = true
|
||||||
|
|
||||||
; Controls the number of milliseconds that are slept per 100 prims rezzed in attachments
|
; 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
|
; Experimental setting to control CPU spiking when avatars with many attachments login/change outfit
|
||||||
; or when multiple avatars with medium level attachments login simultaneously.
|
; or when multiple avatars with medium level attachments login/change outfit simultaneously.
|
||||||
; If 0 then no throttling is performed.
|
; If 0 then no throttling is performed.
|
||||||
ThrottlePer100PrimsRezzed = 0;
|
ThrottlePer100PrimsRezzed = 0;
|
||||||
|
|
||||||
|
|
|
@ -11,22 +11,44 @@
|
||||||
</appSettings>
|
</appSettings>
|
||||||
<log4net>
|
<log4net>
|
||||||
<appender name="Console" type="OpenSim.Framework.Console.OpenSimAppender, OpenSim.Framework.Console">
|
<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">
|
<layout type="log4net.Layout.PatternLayout">
|
||||||
<conversionPattern value="%date{HH:mm:ss} - %message%newline" />
|
<conversionPattern value="%date{HH:mm:ss} - %message%newline" />
|
||||||
</layout>
|
</layout>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
<appender name="LogFileAppender" type="log4net.Appender.FileAppender">
|
<appender name="LogFileAppender" type="log4net.Appender.FileAppender">
|
||||||
<file value="Robust.32BitLaunch.log" />
|
<file value="Robust.32BitLaunch.log" />
|
||||||
<appendToFile value="true" />
|
<appendToFile value="true" />
|
||||||
|
<filter type="log4net.Filter.LoggerMatchFilter">
|
||||||
|
<loggerToMatch value="special"/>
|
||||||
|
<acceptOnMatch value="false"/>
|
||||||
|
</filter>
|
||||||
<layout type="log4net.Layout.PatternLayout">
|
<layout type="log4net.Layout.PatternLayout">
|
||||||
<conversionPattern value="%date %-5level - %logger %message%newline" />
|
<conversionPattern value="%date %-5level - %logger %message%newline" />
|
||||||
</layout>
|
</layout>
|
||||||
</appender>
|
</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>
|
<root>
|
||||||
<level value="DEBUG" />
|
<level value="DEBUG" />
|
||||||
<appender-ref ref="Console" />
|
<appender-ref ref="Console" />
|
||||||
<appender-ref ref="LogFileAppender" />
|
<appender-ref ref="LogFileAppender" />
|
||||||
</root>
|
</root>
|
||||||
|
|
||||||
|
<!-- used for stats recording -->
|
||||||
|
<logger name="special.StatsLogger">
|
||||||
|
<appender-ref ref="StatsLogFileAppender"/>
|
||||||
|
</logger>
|
||||||
</log4net>
|
</log4net>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|
|
@ -11,6 +11,10 @@
|
||||||
</appSettings>
|
</appSettings>
|
||||||
<log4net>
|
<log4net>
|
||||||
<appender name="Console" type="OpenSim.Framework.Console.OpenSimAppender, OpenSim.Framework.Console">
|
<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">
|
<layout type="log4net.Layout.PatternLayout">
|
||||||
<conversionPattern value="%date{HH:mm:ss} - %message%newline" />
|
<conversionPattern value="%date{HH:mm:ss} - %message%newline" />
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -19,15 +23,32 @@
|
||||||
<appender name="LogFileAppender" type="log4net.Appender.FileAppender">
|
<appender name="LogFileAppender" type="log4net.Appender.FileAppender">
|
||||||
<file value="Robust.log" />
|
<file value="Robust.log" />
|
||||||
<appendToFile value="true" />
|
<appendToFile value="true" />
|
||||||
|
<filter type="log4net.Filter.LoggerMatchFilter">
|
||||||
|
<loggerToMatch value="special"/>
|
||||||
|
<acceptOnMatch value="false"/>
|
||||||
|
</filter>
|
||||||
<layout type="log4net.Layout.PatternLayout">
|
<layout type="log4net.Layout.PatternLayout">
|
||||||
<conversionPattern value="%date %-5level - %logger %message%newline" />
|
<conversionPattern value="%date %-5level - %logger %message%newline" />
|
||||||
</layout>
|
</layout>
|
||||||
</appender>
|
</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>
|
<root>
|
||||||
<level value="DEBUG" />
|
<level value="DEBUG" />
|
||||||
<appender-ref ref="Console" />
|
<appender-ref ref="Console" />
|
||||||
<appender-ref ref="LogFileAppender" />
|
<appender-ref ref="LogFileAppender" />
|
||||||
</root>
|
</root>
|
||||||
|
|
||||||
|
<!-- used for stats recording -->
|
||||||
|
<logger name="special.StatsLogger">
|
||||||
|
<appender-ref ref="StatsLogFileAppender"/>
|
||||||
|
</logger>
|
||||||
</log4net>
|
</log4net>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|
|
@ -30,6 +30,17 @@
|
||||||
SimulationServiceInConnector = true
|
SimulationServiceInConnector = true
|
||||||
LibraryModule = 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]
|
[SimulationDataStore]
|
||||||
LocalServiceModule = "OpenSim.Services.Connectors.dll:SimulationDataService"
|
LocalServiceModule = "OpenSim.Services.Connectors.dll:SimulationDataService"
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,17 @@
|
||||||
GridInfoServiceInConnector = true
|
GridInfoServiceInConnector = true
|
||||||
MapImageServiceInConnector = 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]
|
[SimulationDataStore]
|
||||||
LocalServiceModule = "OpenSim.Services.Connectors.dll:SimulationDataService"
|
LocalServiceModule = "OpenSim.Services.Connectors.dll:SimulationDataService"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue