Merge branch 'master' into presence-refactor

This was a large, heavily conflicted merge and things MAY have got broken.
Please check!
slimupdates
Melanie 2010-02-08 15:53:20 +00:00
commit baaf660511
63 changed files with 5627 additions and 3494 deletions

View File

@ -56,7 +56,7 @@ namespace OpenSim.Client.MXP.PacketHandler
private readonly Dictionary<UUID, Scene> m_scenes; private readonly Dictionary<UUID, Scene> m_scenes;
private readonly Transmitter m_transmitter; private readonly Transmitter m_transmitter;
private readonly Thread m_clientThread; // private readonly Thread m_clientThread;
private readonly IList<Session> m_sessions = new List<Session>(); private readonly IList<Session> m_sessions = new List<Session>();
private readonly IList<Session> m_sessionsToClient = new List<Session>(); private readonly IList<Session> m_sessionsToClient = new List<Session>();

View File

@ -82,9 +82,11 @@ namespace OpenSim.ConsoleClient
private static void SendCommand(string module, string[] cmd) private static void SendCommand(string module, string[] cmd)
{ {
string sendCmd = cmd[0]; string sendCmd = "";
if (cmd.Length > 1) if (cmd.Length > 1)
{ {
sendCmd = cmd[0];
Array.Copy(cmd, 1, cmd, 0, cmd.Length-1); Array.Copy(cmd, 1, cmd, 0, cmd.Length-1);
Array.Resize(ref cmd, cmd.Length-1); Array.Resize(ref cmd, cmd.Length-1);
sendCmd += "\"" + String.Join("\" \"", cmd) + "\""; sendCmd += "\"" + String.Join("\" \"", cmd) + "\"";

View File

@ -43,10 +43,13 @@ namespace OpenSim.Data.MySQL
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private MySQLManager _dbConnection; private string m_connectionString;
private object m_dbLock = new object();
#region IPlugin Members #region IPlugin Members
public override string Version { get { return "1.0.0.0"; } }
/// <summary> /// <summary>
/// <para>Initialises Asset interface</para> /// <para>Initialises Asset interface</para>
/// <para> /// <para>
@ -58,62 +61,28 @@ namespace OpenSim.Data.MySQL
/// </para> /// </para>
/// </summary> /// </summary>
/// <param name="connect">connect string</param> /// <param name="connect">connect string</param>
override public void Initialise(string connect) public override void Initialise(string connect)
{ {
// TODO: This will let you pass in the connect string in m_connectionString = connect;
// the config, though someone will need to write that.
if (connect == String.Empty)
{
// This is old seperate config file
m_log.Warn("no connect string, using old mysql_connection.ini instead");
Initialise();
}
else
{
_dbConnection = new MySQLManager(connect);
}
// This actually does the roll forward assembly stuff // This actually does the roll forward assembly stuff
Assembly assem = GetType().Assembly; Assembly assem = GetType().Assembly;
Migration m = new Migration(_dbConnection.Connection, assem, "AssetStore");
m.Update(); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
Migration m = new Migration(dbcon, assem, "AssetStore");
m.Update();
}
} }
/// <summary>
/// <para>Initialises Asset interface</para>
/// <para>
/// <list type="bullet">
/// <item>Loads and initialises the MySQL storage plugin</item>
/// <item>uses the obsolete mysql_connection.ini</item>
/// </list>
/// </para>
/// </summary>
/// <remarks>DEPRECATED and shouldn't be used</remarks>
public override void Initialise() public override void Initialise()
{ {
IniFile GridDataMySqlFile = new IniFile("mysql_connection.ini"); throw new NotImplementedException();
string hostname = GridDataMySqlFile.ParseFileReadValue("hostname");
string database = GridDataMySqlFile.ParseFileReadValue("database");
string username = GridDataMySqlFile.ParseFileReadValue("username");
string password = GridDataMySqlFile.ParseFileReadValue("password");
string pooling = GridDataMySqlFile.ParseFileReadValue("pooling");
string port = GridDataMySqlFile.ParseFileReadValue("port");
_dbConnection = new MySQLManager(hostname, database, username, password, pooling, port);
} }
public override void Dispose() { } public override void Dispose() { }
/// <summary>
/// Database provider version
/// </summary>
override public string Version
{
get { return _dbConnection.getVersion(); }
}
/// <summary> /// <summary>
/// The name of this DB provider /// The name of this DB provider
/// </summary> /// </summary>
@ -135,46 +104,43 @@ namespace OpenSim.Data.MySQL
override public AssetBase GetAsset(UUID assetID) override public AssetBase GetAsset(UUID assetID)
{ {
AssetBase asset = null; AssetBase asset = null;
lock (_dbConnection) lock (m_dbLock)
{ {
_dbConnection.CheckConnection(); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
MySqlCommand cmd = using (MySqlCommand cmd = new MySqlCommand(
new MySqlCommand(
"SELECT name, description, assetType, local, temporary, data FROM assets WHERE id=?id", "SELECT name, description, assetType, local, temporary, data FROM assets WHERE id=?id",
_dbConnection.Connection); dbcon))
cmd.Parameters.AddWithValue("?id", assetID.ToString());
try
{
using (MySqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow))
{ {
if (dbReader.Read()) cmd.Parameters.AddWithValue("?id", assetID.ToString());
try
{ {
asset = new AssetBase(assetID, (string)dbReader["name"], (sbyte)dbReader["assetType"]); using (MySqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow))
asset.Data = (byte[]) dbReader["data"]; {
asset.Description = (string) dbReader["description"]; if (dbReader.Read())
{
asset = new AssetBase(assetID, (string)dbReader["name"], (sbyte)dbReader["assetType"]);
asset.Data = (byte[])dbReader["data"];
asset.Description = (string)dbReader["description"];
string local = dbReader["local"].ToString(); string local = dbReader["local"].ToString();
if (local.Equals("1") || local.Equals("true", StringComparison.InvariantCultureIgnoreCase)) if (local.Equals("1") || local.Equals("true", StringComparison.InvariantCultureIgnoreCase))
asset.Local = true; asset.Local = true;
else else
asset.Local = false; asset.Local = false;
asset.Temporary = Convert.ToBoolean(dbReader["temporary"]); asset.Temporary = Convert.ToBoolean(dbReader["temporary"]);
}
}
}
catch (Exception e)
{
m_log.Error("[ASSETS DB]: MySql failure fetching asset " + assetID + ": " + e.Message);
} }
dbReader.Close();
cmd.Dispose();
} }
if (asset != null)
UpdateAccessTime(asset);
}
catch (Exception e)
{
m_log.ErrorFormat(
"[ASSETS DB]: MySql failure fetching asset {0}" + Environment.NewLine + e.ToString()
+ Environment.NewLine + "Reconnecting", assetID);
_dbConnection.Reconnect();
} }
} }
return asset; return asset;
@ -187,55 +153,57 @@ namespace OpenSim.Data.MySQL
/// <remarks>On failure : Throw an exception and attempt to reconnect to database</remarks> /// <remarks>On failure : Throw an exception and attempt to reconnect to database</remarks>
override public void StoreAsset(AssetBase asset) override public void StoreAsset(AssetBase asset)
{ {
lock (_dbConnection) lock (m_dbLock)
{ {
_dbConnection.CheckConnection(); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
MySqlCommand cmd = MySqlCommand cmd =
new MySqlCommand( new MySqlCommand(
"replace INTO assets(id, name, description, assetType, local, temporary, create_time, access_time, data)" + "replace INTO assets(id, name, description, assetType, local, temporary, create_time, access_time, data)" +
"VALUES(?id, ?name, ?description, ?assetType, ?local, ?temporary, ?create_time, ?access_time, ?data)", "VALUES(?id, ?name, ?description, ?assetType, ?local, ?temporary, ?create_time, ?access_time, ?data)",
_dbConnection.Connection); dbcon);
string assetName = asset.Name; string assetName = asset.Name;
if (asset.Name.Length > 64) if (asset.Name.Length > 64)
{
assetName = asset.Name.Substring(0, 64);
m_log.Warn("[ASSET DB]: Name field truncated from " + asset.Name.Length + " to " + assetName.Length + " characters on add");
}
string assetDescription = asset.Description;
if (asset.Description.Length > 64)
{
assetDescription = asset.Description.Substring(0, 64);
m_log.Warn("[ASSET DB]: Description field truncated from " + asset.Description.Length + " to " + assetDescription.Length + " characters on add");
}
// need to ensure we dispose
try
{
using (cmd)
{ {
// create unix epoch time assetName = asset.Name.Substring(0, 64);
int now = (int)Utils.DateTimeToUnixTime(DateTime.UtcNow); m_log.Warn("[ASSET DB]: Name field truncated from " + asset.Name.Length + " to " + assetName.Length + " characters on add");
cmd.Parameters.AddWithValue("?id", asset.ID); }
cmd.Parameters.AddWithValue("?name", assetName);
cmd.Parameters.AddWithValue("?description", assetDescription); string assetDescription = asset.Description;
cmd.Parameters.AddWithValue("?assetType", asset.Type); if (asset.Description.Length > 64)
cmd.Parameters.AddWithValue("?local", asset.Local); {
cmd.Parameters.AddWithValue("?temporary", asset.Temporary); assetDescription = asset.Description.Substring(0, 64);
cmd.Parameters.AddWithValue("?create_time", now); m_log.Warn("[ASSET DB]: Description field truncated from " + asset.Description.Length + " to " + assetDescription.Length + " characters on add");
cmd.Parameters.AddWithValue("?access_time", now); }
cmd.Parameters.AddWithValue("?data", asset.Data);
cmd.ExecuteNonQuery(); // need to ensure we dispose
cmd.Dispose(); try
{
using (cmd)
{
// create unix epoch time
int now = (int)Utils.DateTimeToUnixTime(DateTime.UtcNow);
cmd.Parameters.AddWithValue("?id", asset.ID);
cmd.Parameters.AddWithValue("?name", assetName);
cmd.Parameters.AddWithValue("?description", assetDescription);
cmd.Parameters.AddWithValue("?assetType", asset.Type);
cmd.Parameters.AddWithValue("?local", asset.Local);
cmd.Parameters.AddWithValue("?temporary", asset.Temporary);
cmd.Parameters.AddWithValue("?create_time", now);
cmd.Parameters.AddWithValue("?access_time", now);
cmd.Parameters.AddWithValue("?data", asset.Data);
cmd.ExecuteNonQuery();
cmd.Dispose();
}
}
catch (Exception e)
{
m_log.ErrorFormat("[ASSET DB]: MySQL failure creating asset {0} with name \"{1}\". Error: {2}",
asset.FullID, asset.Name, e.Message);
} }
}
catch (Exception e)
{
m_log.ErrorFormat("[ASSET DB]: MySQL failure creating asset {0} with name \"{1}\". Attempting reconnect. Error: {2}",
asset.FullID, asset.Name, e.Message);
_dbConnection.Reconnect();
} }
} }
} }
@ -245,34 +213,35 @@ namespace OpenSim.Data.MySQL
// Writing to the database every time Get() is called on an asset is killing us. Seriously. -jph // Writing to the database every time Get() is called on an asset is killing us. Seriously. -jph
return; return;
lock (_dbConnection) lock (m_dbLock)
{ {
_dbConnection.CheckConnection(); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
MySqlCommand cmd =
new MySqlCommand("update assets set access_time=?access_time where id=?id",
_dbConnection.Connection);
// need to ensure we dispose
try
{ {
using (cmd) dbcon.Open();
MySqlCommand cmd =
new MySqlCommand("update assets set access_time=?access_time where id=?id",
dbcon);
// need to ensure we dispose
try
{ {
// create unix epoch time using (cmd)
int now = (int)Utils.DateTimeToUnixTime(DateTime.UtcNow); {
cmd.Parameters.AddWithValue("?id", asset.ID); // create unix epoch time
cmd.Parameters.AddWithValue("?access_time", now); int now = (int)Utils.DateTimeToUnixTime(DateTime.UtcNow);
cmd.ExecuteNonQuery(); cmd.Parameters.AddWithValue("?id", asset.ID);
cmd.Dispose(); cmd.Parameters.AddWithValue("?access_time", now);
cmd.ExecuteNonQuery();
cmd.Dispose();
}
}
catch (Exception e)
{
m_log.ErrorFormat(
"[ASSETS DB]: " +
"MySql failure updating access_time for asset {0} with name {1}" + Environment.NewLine + e.ToString()
+ Environment.NewLine + "Attempting reconnection", asset.FullID, asset.Name);
} }
}
catch (Exception e)
{
m_log.ErrorFormat(
"[ASSETS DB]: " +
"MySql failure updating access_time for asset {0} with name {1}" + Environment.NewLine + e.ToString()
+ Environment.NewLine + "Attempting reconnection", asset.FullID, asset.Name);
_dbConnection.Reconnect();
} }
} }
@ -287,37 +256,30 @@ namespace OpenSim.Data.MySQL
{ {
bool assetExists = false; bool assetExists = false;
lock (_dbConnection) lock (m_dbLock)
{ {
_dbConnection.CheckConnection(); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
MySqlCommand cmd =
new MySqlCommand(
"SELECT id FROM assets WHERE id=?id",
_dbConnection.Connection);
cmd.Parameters.AddWithValue("?id", uuid.ToString());
try
{ {
using (MySqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow)) dbcon.Open();
using (MySqlCommand cmd = new MySqlCommand("SELECT id FROM assets WHERE id=?id", dbcon))
{ {
if (dbReader.Read()) cmd.Parameters.AddWithValue("?id", uuid.ToString());
{
assetExists = true;
}
dbReader.Close(); try
cmd.Dispose(); {
using (MySqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow))
{
if (dbReader.Read())
assetExists = true;
}
}
catch (Exception e)
{
m_log.ErrorFormat(
"[ASSETS DB]: MySql failure fetching asset {0}" + Environment.NewLine + e.ToString(), uuid);
}
} }
} }
catch (Exception e)
{
m_log.ErrorFormat(
"[ASSETS DB]: MySql failure fetching asset {0}" + Environment.NewLine + e.ToString()
+ Environment.NewLine + "Attempting reconnection", uuid);
_dbConnection.Reconnect();
}
} }
return assetExists; return assetExists;
@ -335,38 +297,39 @@ namespace OpenSim.Data.MySQL
{ {
List<AssetMetadata> retList = new List<AssetMetadata>(count); List<AssetMetadata> retList = new List<AssetMetadata>(count);
lock (_dbConnection) lock (m_dbLock)
{ {
_dbConnection.CheckConnection(); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
MySqlCommand cmd = new MySqlCommand("SELECT name,description,assetType,temporary,id FROM assets LIMIT ?start, ?count", _dbConnection.Connection);
cmd.Parameters.AddWithValue("?start", start);
cmd.Parameters.AddWithValue("?count", count);
try
{ {
using (MySqlDataReader dbReader = cmd.ExecuteReader()) dbcon.Open();
MySqlCommand cmd = new MySqlCommand("SELECT name,description,assetType,temporary,id FROM assets LIMIT ?start, ?count", dbcon);
cmd.Parameters.AddWithValue("?start", start);
cmd.Parameters.AddWithValue("?count", count);
try
{ {
while (dbReader.Read()) using (MySqlDataReader dbReader = cmd.ExecuteReader())
{ {
AssetMetadata metadata = new AssetMetadata(); while (dbReader.Read())
metadata.Name = (string) dbReader["name"]; {
metadata.Description = (string) dbReader["description"]; AssetMetadata metadata = new AssetMetadata();
metadata.Type = (sbyte) dbReader["assetType"]; metadata.Name = (string)dbReader["name"];
metadata.Temporary = Convert.ToBoolean(dbReader["temporary"]); // Not sure if this is correct. metadata.Description = (string)dbReader["description"];
metadata.FullID = new UUID((string) dbReader["id"]); metadata.Type = (sbyte)dbReader["assetType"];
metadata.Temporary = Convert.ToBoolean(dbReader["temporary"]); // Not sure if this is correct.
metadata.FullID = new UUID((string)dbReader["id"]);
// Current SHA1s are not stored/computed. // Current SHA1s are not stored/computed.
metadata.SHA1 = new byte[] {}; metadata.SHA1 = new byte[] { };
retList.Add(metadata); retList.Add(metadata);
}
} }
} }
} catch (Exception e)
catch (Exception e) {
{ m_log.Error("[ASSETS DB]: MySql failure fetching asset set" + Environment.NewLine + e.ToString());
m_log.Error("[ASSETS DB]: MySql failure fetching asset set" + Environment.NewLine + e.ToString() + Environment.NewLine + "Attempting reconnection"); }
_dbConnection.Reconnect();
} }
} }
@ -374,7 +337,5 @@ namespace OpenSim.Data.MySQL
} }
#endregion #endregion
} }
} }

View File

@ -38,16 +38,22 @@ namespace OpenSim.Data.MySQL
public class MySqlAuthenticationData : MySqlFramework, IAuthenticationData public class MySqlAuthenticationData : MySqlFramework, IAuthenticationData
{ {
private string m_Realm; private string m_Realm;
private List<string> m_ColumnNames = null; private List<string> m_ColumnNames;
private int m_LastExpire = 0; private int m_LastExpire;
// private string m_connectionString;
public MySqlAuthenticationData(string connectionString, string realm) public MySqlAuthenticationData(string connectionString, string realm)
: base(connectionString) : base(connectionString)
{ {
m_Realm = realm; m_Realm = realm;
m_connectionString = connectionString;
Migration m = new Migration(m_Connection, GetType().Assembly, "AuthStore"); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
m.Update(); {
dbcon.Open();
Migration m = new Migration(dbcon, GetType().Assembly, "AuthStore");
m.Update();
}
} }
public AuthenticationData Get(UUID principalID) public AuthenticationData Get(UUID principalID)
@ -55,45 +61,42 @@ namespace OpenSim.Data.MySQL
AuthenticationData ret = new AuthenticationData(); AuthenticationData ret = new AuthenticationData();
ret.Data = new Dictionary<string, object>(); ret.Data = new Dictionary<string, object>();
MySqlCommand cmd = new MySqlCommand( using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
"select * from `"+m_Realm+"` where UUID = ?principalID"
);
cmd.Parameters.AddWithValue("?principalID", principalID.ToString());
IDataReader result = ExecuteReader(cmd);
if (result.Read())
{ {
ret.PrincipalID = principalID; dbcon.Open();
MySqlCommand cmd = new MySqlCommand("select * from `" + m_Realm + "` where UUID = ?principalID", dbcon);
cmd.Parameters.AddWithValue("?principalID", principalID.ToString());
if (m_ColumnNames == null) IDataReader result = cmd.ExecuteReader();
if (result.Read())
{ {
m_ColumnNames = new List<string>(); ret.PrincipalID = principalID;
DataTable schemaTable = result.GetSchemaTable(); if (m_ColumnNames == null)
foreach (DataRow row in schemaTable.Rows) {
m_ColumnNames.Add(row["ColumnName"].ToString()); m_ColumnNames = new List<string>();
DataTable schemaTable = result.GetSchemaTable();
foreach (DataRow row in schemaTable.Rows)
m_ColumnNames.Add(row["ColumnName"].ToString());
}
foreach (string s in m_ColumnNames)
{
if (s == "UUID")
continue;
ret.Data[s] = result[s].ToString();
}
return ret;
} }
else
foreach (string s in m_ColumnNames)
{ {
if (s == "UUID") return null;
continue;
ret.Data[s] = result[s].ToString();
} }
result.Close();
CloseReaderCommand(cmd);
return ret;
} }
result.Close();
CloseReaderCommand(cmd);
return null;
} }
public bool Store(AuthenticationData data) public bool Store(AuthenticationData data)

View File

@ -44,7 +44,6 @@ namespace OpenSim.Data.MySQL
private const string m_waitTimeoutSelect = "select @@wait_timeout"; private const string m_waitTimeoutSelect = "select @@wait_timeout";
private MySqlConnection m_connection;
private string m_connectionString; private string m_connectionString;
private long m_waitTimeout; private long m_waitTimeout;
private long m_waitTimeoutLeeway = 60 * TimeSpan.TicksPerSecond; private long m_waitTimeoutLeeway = 60 * TimeSpan.TicksPerSecond;
@ -67,24 +66,26 @@ namespace OpenSim.Data.MySQL
m_log.Debug("Exception: password not found in connection string\n" + e.ToString()); m_log.Debug("Exception: password not found in connection string\n" + e.ToString());
} }
m_connection = new MySqlConnection(m_connectionString);
m_connection.Open();
GetWaitTimeout(); GetWaitTimeout();
Assembly assem = GetType().Assembly; using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
Migration m = new Migration(m_connection, assem, "EstateStore");
m.Update();
Type t = typeof(EstateSettings);
m_Fields = t.GetFields(BindingFlags.NonPublic |
BindingFlags.Instance |
BindingFlags.DeclaredOnly);
foreach (FieldInfo f in m_Fields)
{ {
if (f.Name.Substring(0, 2) == "m_") dbcon.Open();
m_FieldMap[f.Name.Substring(2)] = f;
Assembly assem = GetType().Assembly;
Migration m = new Migration(dbcon, assem, "EstateStore");
m.Update();
Type t = typeof(EstateSettings);
m_Fields = t.GetFields(BindingFlags.NonPublic |
BindingFlags.Instance |
BindingFlags.DeclaredOnly);
foreach (FieldInfo f in m_Fields)
{
if (f.Name.Substring(0, 2) == "m_")
m_FieldMap[f.Name.Substring(2)] = f;
}
} }
} }
@ -95,47 +96,29 @@ namespace OpenSim.Data.MySQL
protected void GetWaitTimeout() protected void GetWaitTimeout()
{ {
MySqlCommand cmd = new MySqlCommand(m_waitTimeoutSelect, using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
m_connection);
using (MySqlDataReader dbReader =
cmd.ExecuteReader(CommandBehavior.SingleRow))
{ {
if (dbReader.Read()) dbcon.Open();
using (MySqlCommand cmd = new MySqlCommand(m_waitTimeoutSelect, dbcon))
{ {
m_waitTimeout using (MySqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow))
= Convert.ToInt32(dbReader["@@wait_timeout"]) * {
TimeSpan.TicksPerSecond + m_waitTimeoutLeeway; if (dbReader.Read())
{
m_waitTimeout
= Convert.ToInt32(dbReader["@@wait_timeout"]) *
TimeSpan.TicksPerSecond + m_waitTimeoutLeeway;
}
}
} }
dbReader.Close(); m_lastConnectionUse = DateTime.Now.Ticks;
cmd.Dispose();
m_log.DebugFormat(
"[REGION DB]: Connection wait timeout {0} seconds",
m_waitTimeout / TimeSpan.TicksPerSecond);
} }
m_lastConnectionUse = DateTime.Now.Ticks;
m_log.DebugFormat(
"[REGION DB]: Connection wait timeout {0} seconds",
m_waitTimeout / TimeSpan.TicksPerSecond);
}
protected void CheckConnection()
{
long timeNow = DateTime.Now.Ticks;
if (timeNow - m_lastConnectionUse > m_waitTimeout ||
m_connection.State != ConnectionState.Open)
{
m_log.DebugFormat("[REGION DB]: Database connection has gone away - reconnecting");
lock (m_connection)
{
m_connection.Close();
m_connection = new MySqlConnection(m_connectionString);
m_connection.Open();
}
}
m_lastConnectionUse = timeNow;
} }
public EstateSettings LoadEstateSettings(UUID regionID) public EstateSettings LoadEstateSettings(UUID regionID)
@ -143,114 +126,111 @@ namespace OpenSim.Data.MySQL
EstateSettings es = new EstateSettings(); EstateSettings es = new EstateSettings();
es.OnSave += StoreEstateSettings; es.OnSave += StoreEstateSettings;
string sql = "select estate_settings." + String.Join(",estate_settings.", FieldList) + " from estate_map left join estate_settings on estate_map.EstateID = estate_settings.EstateID where estate_settings.EstateID is not null and RegionID = ?RegionID"; string sql = "select estate_settings." + String.Join(",estate_settings.", FieldList) +
" from estate_map left join estate_settings on estate_map.EstateID = estate_settings.EstateID where estate_settings.EstateID is not null and RegionID = ?RegionID";
CheckConnection(); bool migration = true;
MySqlCommand cmd = m_connection.CreateCommand(); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
cmd.CommandText = sql;
cmd.Parameters.AddWithValue("?RegionID", regionID.ToString());
IDataReader r = cmd.ExecuteReader();
if (r.Read())
{ {
foreach (string name in FieldList) dbcon.Open();
using (MySqlCommand cmd = dbcon.CreateCommand())
{ {
if (m_FieldMap[name].GetValue(es) is bool) cmd.CommandText = sql;
cmd.Parameters.AddWithValue("?RegionID", regionID.ToString());
using (IDataReader r = cmd.ExecuteReader())
{ {
int v = Convert.ToInt32(r[name]); if (r.Read())
if (v != 0) {
m_FieldMap[name].SetValue(es, true); migration = false;
else
m_FieldMap[name].SetValue(es, false);
}
else if (m_FieldMap[name].GetValue(es) is UUID)
{
UUID uuid = UUID.Zero;
UUID.TryParse(r[name].ToString(), out uuid); foreach (string name in FieldList)
m_FieldMap[name].SetValue(es, uuid); {
} if (m_FieldMap[name].GetValue(es) is bool)
else {
{ int v = Convert.ToInt32(r[name]);
m_FieldMap[name].SetValue(es, r[name]); if (v != 0)
} m_FieldMap[name].SetValue(es, true);
} else
r.Close(); m_FieldMap[name].SetValue(es, false);
} }
else else if (m_FieldMap[name].GetValue(es) is UUID)
{ {
// Migration case UUID uuid = UUID.Zero;
//
r.Close();
List<string> names = new List<string>(FieldList); UUID.TryParse(r[name].ToString(), out uuid);
m_FieldMap[name].SetValue(es, uuid);
names.Remove("EstateID"); }
else
sql = "insert into estate_settings (" + String.Join(",", names.ToArray()) + ") values ( ?" + String.Join(", ?", names.ToArray()) + ")"; {
m_FieldMap[name].SetValue(es, r[name]);
cmd.CommandText = sql; }
cmd.Parameters.Clear(); }
}
foreach (string name in FieldList)
{
if (m_FieldMap[name].GetValue(es) is bool)
{
if ((bool)m_FieldMap[name].GetValue(es))
cmd.Parameters.AddWithValue("?" + name, "1");
else
cmd.Parameters.AddWithValue("?" + name, "0");
}
else
{
cmd.Parameters.AddWithValue("?" + name, m_FieldMap[name].GetValue(es).ToString());
} }
} }
cmd.ExecuteNonQuery(); if (migration)
cmd.CommandText = "select LAST_INSERT_ID() as id";
cmd.Parameters.Clear();
r = cmd.ExecuteReader();
r.Read();
es.EstateID = Convert.ToUInt32(r["id"]);
r.Close();
cmd.CommandText = "insert into estate_map values (?RegionID, ?EstateID)";
cmd.Parameters.AddWithValue("?RegionID", regionID.ToString());
cmd.Parameters.AddWithValue("?EstateID", es.EstateID.ToString());
// This will throw on dupe key
try
{ {
cmd.ExecuteNonQuery(); // Migration case
} List<string> names = new List<string>(FieldList);
catch (Exception)
{
}
// Munge and transfer the ban list names.Remove("EstateID");
//
cmd.Parameters.Clear();
cmd.CommandText = "insert into estateban select " + es.EstateID.ToString() + ", bannedUUID, bannedIp, bannedIpHostMask, '' from regionban where regionban.regionUUID = ?UUID";
cmd.Parameters.AddWithValue("?UUID", regionID.ToString());
try sql = "insert into estate_settings (" + String.Join(",", names.ToArray()) + ") values ( ?" + String.Join(", ?", names.ToArray()) + ")";
{
cmd.ExecuteNonQuery();
}
catch (Exception)
{
}
es.Save(); using (MySqlCommand cmd = dbcon.CreateCommand())
{
cmd.CommandText = sql;
cmd.Parameters.Clear();
foreach (string name in FieldList)
{
if (m_FieldMap[name].GetValue(es) is bool)
{
if ((bool)m_FieldMap[name].GetValue(es))
cmd.Parameters.AddWithValue("?" + name, "1");
else
cmd.Parameters.AddWithValue("?" + name, "0");
}
else
{
cmd.Parameters.AddWithValue("?" + name, m_FieldMap[name].GetValue(es).ToString());
}
}
cmd.ExecuteNonQuery();
cmd.CommandText = "select LAST_INSERT_ID() as id";
cmd.Parameters.Clear();
using (IDataReader r = cmd.ExecuteReader())
{
r.Read();
es.EstateID = Convert.ToUInt32(r["id"]);
}
cmd.CommandText = "insert into estate_map values (?RegionID, ?EstateID)";
cmd.Parameters.AddWithValue("?RegionID", regionID.ToString());
cmd.Parameters.AddWithValue("?EstateID", es.EstateID.ToString());
// This will throw on dupe key
try { cmd.ExecuteNonQuery(); }
catch (Exception) { }
// Munge and transfer the ban list
cmd.Parameters.Clear();
cmd.CommandText = "insert into estateban select " + es.EstateID.ToString() + ", bannedUUID, bannedIp, bannedIpHostMask, '' from regionban where regionban.regionUUID = ?UUID";
cmd.Parameters.AddWithValue("?UUID", regionID.ToString());
try { cmd.ExecuteNonQuery(); }
catch (Exception) { }
es.Save();
}
}
} }
LoadBanList(es); LoadBanList(es);
@ -265,29 +245,33 @@ namespace OpenSim.Data.MySQL
{ {
string sql = "replace into estate_settings (" + String.Join(",", FieldList) + ") values ( ?" + String.Join(", ?", FieldList) + ")"; string sql = "replace into estate_settings (" + String.Join(",", FieldList) + ") values ( ?" + String.Join(", ?", FieldList) + ")";
CheckConnection(); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
MySqlCommand cmd = m_connection.CreateCommand();
cmd.CommandText = sql;
foreach (string name in FieldList)
{ {
if (m_FieldMap[name].GetValue(es) is bool) dbcon.Open();
using (MySqlCommand cmd = dbcon.CreateCommand())
{ {
if ((bool)m_FieldMap[name].GetValue(es)) cmd.CommandText = sql;
cmd.Parameters.AddWithValue("?" + name, "1");
else foreach (string name in FieldList)
cmd.Parameters.AddWithValue("?" + name, "0"); {
} if (m_FieldMap[name].GetValue(es) is bool)
else {
{ if ((bool)m_FieldMap[name].GetValue(es))
cmd.Parameters.AddWithValue("?" + name, m_FieldMap[name].GetValue(es).ToString()); cmd.Parameters.AddWithValue("?" + name, "1");
else
cmd.Parameters.AddWithValue("?" + name, "0");
}
else
{
cmd.Parameters.AddWithValue("?" + name, m_FieldMap[name].GetValue(es).ToString());
}
}
cmd.ExecuteNonQuery();
} }
} }
cmd.ExecuteNonQuery();
SaveBanList(es); SaveBanList(es);
SaveUUIDList(es.EstateID, "estate_managers", es.EstateManagers); SaveUUIDList(es.EstateID, "estate_managers", es.EstateManagers);
SaveUUIDList(es.EstateID, "estate_users", es.EstateAccess); SaveUUIDList(es.EstateID, "estate_users", es.EstateAccess);
@ -298,77 +282,89 @@ namespace OpenSim.Data.MySQL
{ {
es.ClearBans(); es.ClearBans();
CheckConnection(); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
MySqlCommand cmd = m_connection.CreateCommand();
cmd.CommandText = "select bannedUUID from estateban where EstateID = ?EstateID";
cmd.Parameters.AddWithValue("?EstateID", es.EstateID);
IDataReader r = cmd.ExecuteReader();
while (r.Read())
{ {
EstateBan eb = new EstateBan(); dbcon.Open();
UUID uuid = new UUID(); using (MySqlCommand cmd = dbcon.CreateCommand())
UUID.TryParse(r["bannedUUID"].ToString(), out uuid); {
cmd.CommandText = "select bannedUUID from estateban where EstateID = ?EstateID";
cmd.Parameters.AddWithValue("?EstateID", es.EstateID);
eb.BannedUserID = uuid; using (IDataReader r = cmd.ExecuteReader())
eb.BannedHostAddress = "0.0.0.0"; {
eb.BannedHostIPMask = "0.0.0.0"; while (r.Read())
es.AddBan(eb); {
EstateBan eb = new EstateBan();
UUID uuid = new UUID();
UUID.TryParse(r["bannedUUID"].ToString(), out uuid);
eb.BannedUserID = uuid;
eb.BannedHostAddress = "0.0.0.0";
eb.BannedHostIPMask = "0.0.0.0";
es.AddBan(eb);
}
}
}
} }
r.Close();
} }
private void SaveBanList(EstateSettings es) private void SaveBanList(EstateSettings es)
{ {
CheckConnection(); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
MySqlCommand cmd = m_connection.CreateCommand();
cmd.CommandText = "delete from estateban where EstateID = ?EstateID";
cmd.Parameters.AddWithValue("?EstateID", es.EstateID.ToString());
cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
cmd.CommandText = "insert into estateban (EstateID, bannedUUID, bannedIp, bannedIpHostMask, bannedNameMask) values ( ?EstateID, ?bannedUUID, '', '', '' )";
foreach (EstateBan b in es.EstateBans)
{ {
cmd.Parameters.AddWithValue("?EstateID", es.EstateID.ToString()); dbcon.Open();
cmd.Parameters.AddWithValue("?bannedUUID", b.BannedUserID.ToString());
cmd.ExecuteNonQuery(); using (MySqlCommand cmd = dbcon.CreateCommand())
cmd.Parameters.Clear(); {
cmd.CommandText = "delete from estateban where EstateID = ?EstateID";
cmd.Parameters.AddWithValue("?EstateID", es.EstateID.ToString());
cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
cmd.CommandText = "insert into estateban (EstateID, bannedUUID, bannedIp, bannedIpHostMask, bannedNameMask) values ( ?EstateID, ?bannedUUID, '', '', '' )";
foreach (EstateBan b in es.EstateBans)
{
cmd.Parameters.AddWithValue("?EstateID", es.EstateID.ToString());
cmd.Parameters.AddWithValue("?bannedUUID", b.BannedUserID.ToString());
cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
}
}
} }
} }
void SaveUUIDList(uint EstateID, string table, UUID[] data) void SaveUUIDList(uint EstateID, string table, UUID[] data)
{ {
CheckConnection(); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
MySqlCommand cmd = m_connection.CreateCommand();
cmd.CommandText = "delete from " + table + " where EstateID = ?EstateID";
cmd.Parameters.AddWithValue("?EstateID", EstateID.ToString());
cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
cmd.CommandText = "insert into " + table + " (EstateID, uuid) values ( ?EstateID, ?uuid )";
foreach (UUID uuid in data)
{ {
cmd.Parameters.AddWithValue("?EstateID", EstateID.ToString()); dbcon.Open();
cmd.Parameters.AddWithValue("?uuid", uuid.ToString());
cmd.ExecuteNonQuery(); using (MySqlCommand cmd = dbcon.CreateCommand())
cmd.Parameters.Clear(); {
cmd.CommandText = "delete from " + table + " where EstateID = ?EstateID";
cmd.Parameters.AddWithValue("?EstateID", EstateID.ToString());
cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
cmd.CommandText = "insert into " + table + " (EstateID, uuid) values ( ?EstateID, ?uuid )";
foreach (UUID uuid in data)
{
cmd.Parameters.AddWithValue("?EstateID", EstateID.ToString());
cmd.Parameters.AddWithValue("?uuid", uuid.ToString());
cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
}
}
} }
} }
@ -376,25 +372,29 @@ namespace OpenSim.Data.MySQL
{ {
List<UUID> uuids = new List<UUID>(); List<UUID> uuids = new List<UUID>();
CheckConnection(); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
MySqlCommand cmd = m_connection.CreateCommand();
cmd.CommandText = "select uuid from " + table + " where EstateID = ?EstateID";
cmd.Parameters.AddWithValue("?EstateID", EstateID);
IDataReader r = cmd.ExecuteReader();
while (r.Read())
{ {
// EstateBan eb = new EstateBan(); dbcon.Open();
UUID uuid = new UUID(); using (MySqlCommand cmd = dbcon.CreateCommand())
UUID.TryParse(r["uuid"].ToString(), out uuid); {
cmd.CommandText = "select uuid from " + table + " where EstateID = ?EstateID";
cmd.Parameters.AddWithValue("?EstateID", EstateID);
uuids.Add(uuid); using (IDataReader r = cmd.ExecuteReader())
{
while (r.Read())
{
// EstateBan eb = new EstateBan();
UUID uuid = new UUID();
UUID.TryParse(r["uuid"].ToString(), out uuid);
uuids.Add(uuid);
}
}
}
} }
r.Close();
return uuids.ToArray(); return uuids.ToArray();
} }

View File

@ -40,12 +40,16 @@ namespace OpenSim.Data.MySQL
/// </summary> /// </summary>
public class MySqlFramework public class MySqlFramework
{ {
protected MySqlConnection m_Connection; private static readonly log4net.ILog m_log =
log4net.LogManager.GetLogger(
System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
protected string m_connectionString;
protected object m_dbLock = new object();
protected MySqlFramework(string connectionString) protected MySqlFramework(string connectionString)
{ {
m_Connection = new MySqlConnection(connectionString); m_connectionString = connectionString;
m_Connection.Open();
} }
////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////
@ -55,64 +59,24 @@ namespace OpenSim.Data.MySQL
// //
protected int ExecuteNonQuery(MySqlCommand cmd) protected int ExecuteNonQuery(MySqlCommand cmd)
{ {
lock (m_Connection) lock (m_dbLock)
{ {
cmd.Connection = m_Connection; using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
bool errorSeen = false;
while (true)
{ {
dbcon.Open();
cmd.Connection = dbcon;
try try
{ {
return cmd.ExecuteNonQuery(); return cmd.ExecuteNonQuery();
} }
catch (MySqlException e)
{
if (errorSeen)
throw;
// This is "Server has gone away" and "Server lost"
//
if (e.Number == 2006 || e.Number == 2013)
{
errorSeen = true;
m_Connection.Close();
MySqlConnection newConnection =
(MySqlConnection)((ICloneable)m_Connection).Clone();
m_Connection.Dispose();
m_Connection = newConnection;
m_Connection.Open();
cmd.Connection = m_Connection;
}
else
throw;
}
catch (Exception e) catch (Exception e)
{ {
m_log.Error(e.Message, e);
return 0; return 0;
} }
} }
} }
} }
protected IDataReader ExecuteReader(MySqlCommand cmd)
{
MySqlConnection newConnection =
(MySqlConnection)((ICloneable)m_Connection).Clone();
newConnection.Open();
cmd.Connection = newConnection;
return cmd.ExecuteReader();
}
protected void CloseReaderCommand(MySqlCommand cmd)
{
cmd.Connection.Close();
cmd.Connection.Dispose();
cmd.Dispose();
}
} }
} }

View File

@ -54,12 +54,16 @@ namespace OpenSim.Data.MySQL
string realm, string storeName) : base(connectionString) string realm, string storeName) : base(connectionString)
{ {
m_Realm = realm; m_Realm = realm;
m_connectionString = connectionString;
if (storeName != String.Empty) if (storeName != String.Empty)
{ {
Assembly assem = GetType().Assembly; using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
Migration m = new Migration(m_Connection, assem, storeName); dbcon.Open();
m.Update(); Migration m = new Migration(dbcon, GetType().Assembly, storeName);
m.Update();
}
} }
Type t = typeof(T); Type t = typeof(T);
@ -107,149 +111,160 @@ namespace OpenSim.Data.MySQL
List<string> terms = new List<string>(); List<string> terms = new List<string>();
MySqlCommand cmd = new MySqlCommand(); using (MySqlCommand cmd = new MySqlCommand())
for (int i = 0 ; i < fields.Length ; i++)
{ {
cmd.Parameters.AddWithValue(fields[i], keys[i]); for (int i = 0 ; i < fields.Length ; i++)
terms.Add("`" + fields[i] + "` = ?" + fields[i]); {
cmd.Parameters.AddWithValue(fields[i], keys[i]);
terms.Add("`" + fields[i] + "` = ?" + fields[i]);
}
string where = String.Join(" and ", terms.ToArray());
string query = String.Format("select * from {0} where {1}",
m_Realm, where);
cmd.CommandText = query;
return DoQuery(cmd);
} }
string where = String.Join(" and ", terms.ToArray());
string query = String.Format("select * from {0} where {1}",
m_Realm, where);
cmd.CommandText = query;
return DoQuery(cmd);
} }
protected T[] DoQuery(MySqlCommand cmd) protected T[] DoQuery(MySqlCommand cmd)
{ {
IDataReader reader = ExecuteReader(cmd);
if (reader == null)
return new T[0];
CheckColumnNames(reader);
List<T> result = new List<T>(); List<T> result = new List<T>();
while (reader.Read()) using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{ {
T row = new T(); dbcon.Open();
cmd.Connection = dbcon;
foreach (string name in m_Fields.Keys) using (IDataReader reader = cmd.ExecuteReader())
{ {
if (m_Fields[name].GetValue(row) is bool) if (reader == null)
{ return new T[0];
int v = Convert.ToInt32(reader[name]);
m_Fields[name].SetValue(row, v != 0 ? true : false);
}
else if (m_Fields[name].GetValue(row) is UUID)
{
UUID uuid = UUID.Zero;
UUID.TryParse(reader[name].ToString(), out uuid); CheckColumnNames(reader);
m_Fields[name].SetValue(row, uuid);
} while (reader.Read())
else if (m_Fields[name].GetValue(row) is int)
{ {
int v = Convert.ToInt32(reader[name]); T row = new T();
m_Fields[name].SetValue(row, v);
} foreach (string name in m_Fields.Keys)
else {
{ if (m_Fields[name].GetValue(row) is bool)
m_Fields[name].SetValue(row, reader[name]); {
} int v = Convert.ToInt32(reader[name]);
} m_Fields[name].SetValue(row, v != 0 ? true : false);
}
else if (m_Fields[name].GetValue(row) is UUID)
{
UUID uuid = UUID.Zero;
UUID.TryParse(reader[name].ToString(), out uuid);
m_Fields[name].SetValue(row, uuid);
}
else if (m_Fields[name].GetValue(row) is int)
{
int v = Convert.ToInt32(reader[name]);
m_Fields[name].SetValue(row, v);
}
else
{
m_Fields[name].SetValue(row, reader[name]);
}
}
if (m_DataField != null) if (m_DataField != null)
{ {
Dictionary<string, string> data = Dictionary<string, string> data =
new Dictionary<string, string>(); new Dictionary<string, string>();
foreach (string col in m_ColumnNames) foreach (string col in m_ColumnNames)
{ {
data[col] = reader[col].ToString(); data[col] = reader[col].ToString();
if (data[col] == null) if (data[col] == null)
data[col] = String.Empty; data[col] = String.Empty;
}
m_DataField.SetValue(row, data);
}
result.Add(row);
} }
m_DataField.SetValue(row, data);
} }
result.Add(row);
} }
reader.Close();
CloseReaderCommand(cmd);
return result.ToArray(); return result.ToArray();
} }
public virtual T[] Get(string where) public virtual T[] Get(string where)
{ {
MySqlCommand cmd = new MySqlCommand(); using (MySqlCommand cmd = new MySqlCommand())
{
string query = String.Format("select * from {0} where {1}",
m_Realm, where); string query = String.Format("select * from {0} where {1}",
m_Realm, where);
cmd.CommandText = query;
cmd.CommandText = query;
return DoQuery(cmd);
return DoQuery(cmd);
}
} }
public virtual bool Store(T row) public virtual bool Store(T row)
{ {
MySqlCommand cmd = new MySqlCommand(); using (MySqlCommand cmd = new MySqlCommand())
string query = "";
List<String> names = new List<String>();
List<String> values = new List<String>();
foreach (FieldInfo fi in m_Fields.Values)
{ {
names.Add(fi.Name);
values.Add("?" + fi.Name);
cmd.Parameters.AddWithValue(fi.Name, fi.GetValue(row).ToString());
}
if (m_DataField != null) string query = "";
{ List<String> names = new List<String>();
Dictionary<string, string> data = List<String> values = new List<String>();
foreach (FieldInfo fi in m_Fields.Values)
{
names.Add(fi.Name);
values.Add("?" + fi.Name);
cmd.Parameters.AddWithValue(fi.Name, fi.GetValue(row).ToString());
}
if (m_DataField != null)
{
Dictionary<string, string> data =
(Dictionary<string, string>)m_DataField.GetValue(row); (Dictionary<string, string>)m_DataField.GetValue(row);
foreach (KeyValuePair<string, string> kvp in data) foreach (KeyValuePair<string, string> kvp in data)
{ {
names.Add(kvp.Key); names.Add(kvp.Key);
values.Add("?" + kvp.Key); values.Add("?" + kvp.Key);
cmd.Parameters.AddWithValue("?" + kvp.Key, kvp.Value); cmd.Parameters.AddWithValue("?" + kvp.Key, kvp.Value);
}
} }
query = String.Format("replace into {0} (`", m_Realm) + String.Join("`,`", names.ToArray()) + "`) values (" + String.Join(",", values.ToArray()) + ")";
cmd.CommandText = query;
if (ExecuteNonQuery(cmd) > 0)
return true;
return false;
} }
query = String.Format("replace into {0} (`", m_Realm) + String.Join("`,`", names.ToArray()) + "`) values (" + String.Join(",", values.ToArray()) + ")";
cmd.CommandText = query;
if (ExecuteNonQuery(cmd) > 0)
return true;
return false;
} }
public virtual bool Delete(string field, string val) public virtual bool Delete(string field, string val)
{ {
MySqlCommand cmd = new MySqlCommand(); using (MySqlCommand cmd = new MySqlCommand())
{
cmd.CommandText = String.Format("delete from {0} where `{1}` = ?{1}", m_Realm, field); cmd.CommandText = String.Format("delete from {0} where `{1}` = ?{1}", m_Realm, field);
cmd.Parameters.AddWithValue(field, val); cmd.Parameters.AddWithValue(field, val);
if (ExecuteNonQuery(cmd) > 0) if (ExecuteNonQuery(cmd) > 0)
return true; return true;
return false; return false;
}
} }
} }
} }

View File

@ -31,6 +31,7 @@ using System.Data;
using System.Reflection; using System.Reflection;
using System.Threading; using System.Threading;
using log4net; using log4net;
using MySql.Data.MySqlClient;
using OpenMetaverse; using OpenMetaverse;
using OpenSim.Framework; using OpenSim.Framework;
@ -43,49 +44,9 @@ namespace OpenSim.Data.MySQL
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
/// <summary> private MySQLManager m_database;
/// MySQL Database Manager private object m_dbLock = new object();
/// </summary> private string m_connectionString;
private MySQLManager database;
/// <summary>
/// Better DB manager. Swap-in replacement too.
/// </summary>
public Dictionary<int, MySQLSuperManager> m_dbconnections = new Dictionary<int, MySQLSuperManager>();
public int m_maxConnections = 10;
public int m_lastConnect;
public MySQLSuperManager GetLockedConnection()
{
int lockedCons = 0;
while (true)
{
m_lastConnect++;
// Overflow protection
if (m_lastConnect == int.MaxValue)
m_lastConnect = 0;
MySQLSuperManager x = m_dbconnections[m_lastConnect % m_maxConnections];
if (!x.Locked)
{
x.GetLock();
return x;
}
lockedCons++;
if (lockedCons > m_maxConnections)
{
lockedCons = 0;
Thread.Sleep(1000); // Wait some time before searching them again.
m_log.Debug(
"WARNING: All threads are in use. Probable cause: Something didnt release a mutex properly, or high volume of requests inbound.");
}
}
}
override public void Initialise() override public void Initialise()
{ {
@ -106,49 +67,17 @@ namespace OpenSim.Data.MySQL
/// <param name="connect">connect string.</param> /// <param name="connect">connect string.</param>
override public void Initialise(string connect) override public void Initialise(string connect)
{ {
if (connect != String.Empty) m_connectionString = connect;
{ m_database = new MySQLManager(connect);
database = new MySQLManager(connect);
m_log.Info("Creating " + m_maxConnections + " DB connections...");
for (int i = 0; i < m_maxConnections; i++)
{
m_log.Info("Connecting to DB... [" + i + "]");
MySQLSuperManager msm = new MySQLSuperManager();
msm.Manager = new MySQLManager(connect);
m_dbconnections.Add(i, msm);
}
}
else
{
m_log.Warn("Using deprecated mysql_connection.ini. Please update database_connect in GridServer_Config.xml and we'll use that instead");
IniFile GridDataMySqlFile = new IniFile("mysql_connection.ini");
string settingHostname = GridDataMySqlFile.ParseFileReadValue("hostname");
string settingDatabase = GridDataMySqlFile.ParseFileReadValue("database");
string settingUsername = GridDataMySqlFile.ParseFileReadValue("username");
string settingPassword = GridDataMySqlFile.ParseFileReadValue("password");
string settingPooling = GridDataMySqlFile.ParseFileReadValue("pooling");
string settingPort = GridDataMySqlFile.ParseFileReadValue("port");
database = new MySQLManager(settingHostname, settingDatabase, settingUsername, settingPassword,
settingPooling, settingPort);
m_log.Info("Creating " + m_maxConnections + " DB connections...");
for (int i = 0; i < m_maxConnections; i++)
{
m_log.Info("Connecting to DB... [" + i + "]");
MySQLSuperManager msm = new MySQLSuperManager();
msm.Manager = new MySQLManager(settingHostname, settingDatabase, settingUsername, settingPassword,
settingPooling, settingPort);
m_dbconnections.Add(i, msm);
}
}
// This actually does the roll forward assembly stuff // This actually does the roll forward assembly stuff
Assembly assem = GetType().Assembly; Assembly assem = GetType().Assembly;
Migration m = new Migration(database.Connection, assem, "GridStore");
m.Update(); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
Migration m = new Migration(dbcon, assem, "GridStore");
m.Update();
}
} }
/// <summary> /// <summary>
@ -156,7 +85,6 @@ namespace OpenSim.Data.MySQL
/// </summary> /// </summary>
override public void Dispose() override public void Dispose()
{ {
database.Close();
} }
/// <summary> /// <summary>
@ -187,8 +115,6 @@ namespace OpenSim.Data.MySQL
/// <returns>Array of sim profiles</returns> /// <returns>Array of sim profiles</returns>
override public RegionProfileData[] GetProfilesInRange(uint xmin, uint ymin, uint xmax, uint ymax) override public RegionProfileData[] GetProfilesInRange(uint xmin, uint ymin, uint xmax, uint ymax)
{ {
MySQLSuperManager dbm = GetLockedConnection();
try try
{ {
Dictionary<string, object> param = new Dictionary<string, object>(); Dictionary<string, object> param = new Dictionary<string, object>();
@ -197,35 +123,33 @@ namespace OpenSim.Data.MySQL
param["?xmax"] = xmax.ToString(); param["?xmax"] = xmax.ToString();
param["?ymax"] = ymax.ToString(); param["?ymax"] = ymax.ToString();
IDbCommand result = using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
dbm.Manager.Query(
"SELECT * FROM regions WHERE locX >= ?xmin AND locX <= ?xmax AND locY >= ?ymin AND locY <= ?ymax",
param);
IDataReader reader = result.ExecuteReader();
RegionProfileData row;
List<RegionProfileData> rows = new List<RegionProfileData>();
while ((row = dbm.Manager.readSimRow(reader)) != null)
{ {
rows.Add(row); dbcon.Open();
}
reader.Close();
result.Dispose();
return rows.ToArray(); using (IDbCommand result = m_database.Query(dbcon,
"SELECT * FROM regions WHERE locX >= ?xmin AND locX <= ?xmax AND locY >= ?ymin AND locY <= ?ymax",
param))
{
using (IDataReader reader = result.ExecuteReader())
{
RegionProfileData row;
List<RegionProfileData> rows = new List<RegionProfileData>();
while ((row = m_database.readSimRow(reader)) != null)
rows.Add(row);
return rows.ToArray();
}
}
}
} }
catch (Exception e) catch (Exception e)
{ {
dbm.Manager.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString());
return null; return null;
} }
finally
{
dbm.Release();
}
} }
/// <summary> /// <summary>
@ -236,42 +160,38 @@ namespace OpenSim.Data.MySQL
/// <returns>A list of sim profiles</returns> /// <returns>A list of sim profiles</returns>
override public List<RegionProfileData> GetRegionsByName(string namePrefix, uint maxNum) override public List<RegionProfileData> GetRegionsByName(string namePrefix, uint maxNum)
{ {
MySQLSuperManager dbm = GetLockedConnection();
try try
{ {
Dictionary<string, object> param = new Dictionary<string, object>(); Dictionary<string, object> param = new Dictionary<string, object>();
param["?name"] = namePrefix + "%"; param["?name"] = namePrefix + "%";
IDbCommand result = using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
dbm.Manager.Query(
"SELECT * FROM regions WHERE regionName LIKE ?name",
param);
IDataReader reader = result.ExecuteReader();
RegionProfileData row;
List<RegionProfileData> rows = new List<RegionProfileData>();
while (rows.Count < maxNum && (row = dbm.Manager.readSimRow(reader)) != null)
{ {
rows.Add(row); dbcon.Open();
}
reader.Close();
result.Dispose();
return rows; using (IDbCommand result = m_database.Query(dbcon,
"SELECT * FROM regions WHERE regionName LIKE ?name",
param))
{
using (IDataReader reader = result.ExecuteReader())
{
RegionProfileData row;
List<RegionProfileData> rows = new List<RegionProfileData>();
while (rows.Count < maxNum && (row = m_database.readSimRow(reader)) != null)
rows.Add(row);
return rows;
}
}
}
} }
catch (Exception e) catch (Exception e)
{ {
dbm.Manager.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString());
return null; return null;
} }
finally
{
dbm.Release();
}
} }
/// <summary> /// <summary>
@ -281,32 +201,30 @@ namespace OpenSim.Data.MySQL
/// <returns>Sim profile</returns> /// <returns>Sim profile</returns>
override public RegionProfileData GetProfileByHandle(ulong handle) override public RegionProfileData GetProfileByHandle(ulong handle)
{ {
MySQLSuperManager dbm = GetLockedConnection();
try try
{ {
Dictionary<string, object> param = new Dictionary<string, object>(); Dictionary<string, object> param = new Dictionary<string, object>();
param["?handle"] = handle.ToString(); param["?handle"] = handle.ToString();
IDbCommand result = dbm.Manager.Query("SELECT * FROM regions WHERE regionHandle = ?handle", param); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
IDataReader reader = result.ExecuteReader(); {
dbcon.Open();
RegionProfileData row = dbm.Manager.readSimRow(reader); using (IDbCommand result = m_database.Query(dbcon, "SELECT * FROM regions WHERE regionHandle = ?handle", param))
reader.Close(); {
result.Dispose(); using (IDataReader reader = result.ExecuteReader())
{
return row; RegionProfileData row = m_database.readSimRow(reader);
return row;
}
}
} }
}
catch (Exception e) catch (Exception e)
{ {
dbm.Manager.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString());
return null; return null;
} }
finally
{
dbm.Release();
}
} }
/// <summary> /// <summary>
@ -316,30 +234,29 @@ namespace OpenSim.Data.MySQL
/// <returns>The sim profile</returns> /// <returns>The sim profile</returns>
override public RegionProfileData GetProfileByUUID(UUID uuid) override public RegionProfileData GetProfileByUUID(UUID uuid)
{ {
MySQLSuperManager dbm = GetLockedConnection();
try try
{ {
Dictionary<string, object> param = new Dictionary<string, object>(); Dictionary<string, object> param = new Dictionary<string, object>();
param["?uuid"] = uuid.ToString(); param["?uuid"] = uuid.ToString();
IDbCommand result = dbm.Manager.Query("SELECT * FROM regions WHERE uuid = ?uuid", param); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
IDataReader reader = result.ExecuteReader(); {
dbcon.Open();
RegionProfileData row = dbm.Manager.readSimRow(reader); using (IDbCommand result = m_database.Query(dbcon, "SELECT * FROM regions WHERE uuid = ?uuid", param))
reader.Close(); {
result.Dispose(); using (IDataReader reader = result.ExecuteReader())
{
return row; RegionProfileData row = m_database.readSimRow(reader);
return row;
}
}
} }
}
catch (Exception e) catch (Exception e)
{ {
dbm.Manager.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString());
return null; return null;
} finally
{
dbm.Release();
} }
} }
@ -351,37 +268,36 @@ namespace OpenSim.Data.MySQL
{ {
if (regionName.Length > 2) if (regionName.Length > 2)
{ {
MySQLSuperManager dbm = GetLockedConnection();
try try
{ {
Dictionary<string, object> param = new Dictionary<string, object>(); Dictionary<string, object> param = new Dictionary<string, object>();
// Add % because this is a like query. // Add % because this is a like query.
param["?regionName"] = regionName + "%"; param["?regionName"] = regionName + "%";
// Order by statement will return shorter matches first. Only returns one record or no record.
IDbCommand result = using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
dbm.Manager.Query( {
dbcon.Open();
// Order by statement will return shorter matches first. Only returns one record or no record.
using (IDbCommand result = m_database.Query(dbcon,
"SELECT * FROM regions WHERE regionName like ?regionName order by LENGTH(regionName) asc LIMIT 1", "SELECT * FROM regions WHERE regionName like ?regionName order by LENGTH(regionName) asc LIMIT 1",
param); param))
IDataReader reader = result.ExecuteReader(); {
using (IDataReader reader = result.ExecuteReader())
RegionProfileData row = dbm.Manager.readSimRow(reader); {
reader.Close(); RegionProfileData row = m_database.readSimRow(reader);
result.Dispose(); return row;
}
return row; }
}
} }
catch (Exception e) catch (Exception e)
{ {
dbm.Manager.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString());
return null; return null;
} }
finally
{
dbm.Release();
}
} }
m_log.Error("[GRID DB]: Searched for a Region Name shorter then 3 characters"); m_log.Error("[GRID DB]: Searched for a Region Name shorter then 3 characters");
return null; return null;
} }
@ -393,17 +309,16 @@ namespace OpenSim.Data.MySQL
/// <returns>Successful?</returns> /// <returns>Successful?</returns>
override public DataResponse StoreProfile(RegionProfileData profile) override public DataResponse StoreProfile(RegionProfileData profile)
{ {
MySQLSuperManager dbm = GetLockedConnection(); try
try {
if (dbm.Manager.insertRegion(profile))
{
return DataResponse.RESPONSE_OK;
}
return DataResponse.RESPONSE_ERROR;
}
finally
{ {
dbm.Release(); if (m_database.insertRegion(profile))
return DataResponse.RESPONSE_OK;
else
return DataResponse.RESPONSE_ERROR;
}
catch
{
return DataResponse.RESPONSE_ERROR;
} }
} }
@ -415,18 +330,16 @@ namespace OpenSim.Data.MySQL
//public DataResponse DeleteProfile(RegionProfileData profile) //public DataResponse DeleteProfile(RegionProfileData profile)
override public DataResponse DeleteProfile(string uuid) override public DataResponse DeleteProfile(string uuid)
{ {
MySQLSuperManager dbm = GetLockedConnection(); try
try {
if (dbm.Manager.deleteRegion(uuid))
{
return DataResponse.RESPONSE_OK;
}
return DataResponse.RESPONSE_ERROR;
} finally
{ {
dbm.Release(); if (m_database.deleteRegion(uuid))
return DataResponse.RESPONSE_OK;
else
return DataResponse.RESPONSE_ERROR;
}
catch
{
return DataResponse.RESPONSE_ERROR;
} }
} }
@ -477,33 +390,32 @@ namespace OpenSim.Data.MySQL
/// <returns></returns> /// <returns></returns>
override public ReservationData GetReservationAtPoint(uint x, uint y) override public ReservationData GetReservationAtPoint(uint x, uint y)
{ {
MySQLSuperManager dbm = GetLockedConnection();
try try
{ {
Dictionary<string, object> param = new Dictionary<string, object>(); Dictionary<string, object> param = new Dictionary<string, object>();
param["?x"] = x.ToString(); param["?x"] = x.ToString();
param["?y"] = y.ToString(); param["?y"] = y.ToString();
IDbCommand result =
dbm.Manager.Query(
"SELECT * FROM reservations WHERE resXMin <= ?x AND resXMax >= ?x AND resYMin <= ?y AND resYMax >= ?y",
param);
IDataReader reader = result.ExecuteReader();
ReservationData row = dbm.Manager.readReservationRow(reader); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
reader.Close(); {
result.Dispose(); dbcon.Open();
return row; using (IDbCommand result = m_database.Query(dbcon,
"SELECT * FROM reservations WHERE resXMin <= ?x AND resXMax >= ?x AND resYMin <= ?y AND resYMax >= ?y",
param))
{
using (IDataReader reader = result.ExecuteReader())
{
ReservationData row = m_database.readReservationRow(reader);
return row;
}
}
}
} }
catch (Exception e) catch (Exception e)
{ {
dbm.Manager.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString());
return null; return null;
} finally
{
dbm.Release();
} }
} }
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -79,14 +79,19 @@ namespace OpenSim.Data.MySQL
// This actually does the roll forward assembly stuff // This actually does the roll forward assembly stuff
Assembly assem = GetType().Assembly; Assembly assem = GetType().Assembly;
Migration m = new Migration(database.Connection, assem, "LogStore");
// TODO: After rev 6000, remove this. People should have using (MySql.Data.MySqlClient.MySqlConnection dbcon = new MySql.Data.MySqlClient.MySqlConnection(connect))
// been rolled onto the new migration code by then. {
TestTables(m); dbcon.Open();
m.Update(); Migration m = new Migration(dbcon, assem, "LogStore");
// TODO: After rev 6000, remove this. People should have
// been rolled onto the new migration code by then.
TestTables(m);
m.Update();
}
} }
/// <summary></summary> /// <summary></summary>
@ -128,7 +133,6 @@ namespace OpenSim.Data.MySQL
} }
catch catch
{ {
database.Reconnect();
} }
} }

View File

@ -45,16 +45,13 @@ namespace OpenSim.Data.MySQL
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
/// <summary>
/// The database connection object
/// </summary>
private MySqlConnection dbcon;
/// <summary> /// <summary>
/// Connection string for ADO.net /// Connection string for ADO.net
/// </summary> /// </summary>
private string connectionString; private string connectionString;
private object m_dbLock = new object();
private const string m_waitTimeoutSelect = "select @@wait_timeout"; private const string m_waitTimeoutSelect = "select @@wait_timeout";
/// <summary> /// <summary>
@ -109,11 +106,11 @@ namespace OpenSim.Data.MySQL
try try
{ {
connectionString = connect; connectionString = connect;
dbcon = new MySqlConnection(connectionString); //dbcon = new MySqlConnection(connectionString);
try try
{ {
dbcon.Open(); //dbcon.Open();
} }
catch(Exception e) catch(Exception e)
{ {
@ -134,18 +131,21 @@ namespace OpenSim.Data.MySQL
/// </summary> /// </summary>
protected void GetWaitTimeout() protected void GetWaitTimeout()
{ {
MySqlCommand cmd = new MySqlCommand(m_waitTimeoutSelect, dbcon); using (MySqlConnection dbcon = new MySqlConnection(connectionString))
using (MySqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow))
{ {
if (dbReader.Read()) dbcon.Open();
{
m_waitTimeout
= Convert.ToInt32(dbReader["@@wait_timeout"]) * TimeSpan.TicksPerSecond + m_waitTimeoutLeeway;
}
dbReader.Close(); using (MySqlCommand cmd = new MySqlCommand(m_waitTimeoutSelect, dbcon))
cmd.Dispose(); {
using (MySqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow))
{
if (dbReader.Read())
{
m_waitTimeout
= Convert.ToInt32(dbReader["@@wait_timeout"]) * TimeSpan.TicksPerSecond + m_waitTimeoutLeeway;
}
}
}
} }
m_lastConnectionUse = DateTime.Now.Ticks; m_lastConnectionUse = DateTime.Now.Ticks;
@ -154,66 +154,9 @@ namespace OpenSim.Data.MySQL
"[REGION DB]: Connection wait timeout {0} seconds", m_waitTimeout / TimeSpan.TicksPerSecond); "[REGION DB]: Connection wait timeout {0} seconds", m_waitTimeout / TimeSpan.TicksPerSecond);
} }
/// <summary> public string ConnectionString
/// Should be called before any db operation. This checks to see if the connection has not timed out
/// </summary>
public void CheckConnection()
{ {
//m_log.Debug("[REGION DB]: Checking connection"); get { return connectionString; }
long timeNow = DateTime.Now.Ticks;
if (timeNow - m_lastConnectionUse > m_waitTimeout || dbcon.State != ConnectionState.Open)
{
m_log.DebugFormat("[REGION DB]: Database connection has gone away - reconnecting");
Reconnect();
}
// Strictly, we should set this after the actual db operation. But it's more convenient to set here rather
// than require the code to call another method - the timeout leeway should be large enough to cover the
// inaccuracy.
m_lastConnectionUse = timeNow;
}
/// <summary>
/// Get the connection being used
/// </summary>
/// <returns>MySqlConnection Object</returns>
public MySqlConnection Connection
{
get { return dbcon; }
}
/// <summary>
/// Shuts down the database connection
/// </summary>
public void Close()
{
dbcon.Close();
dbcon = null;
}
/// <summary>
/// Reconnects to the database
/// </summary>
public void Reconnect()
{
m_log.Info("[REGION DB] Reconnecting database");
lock (dbcon)
{
try
{
// Close the DB connection
dbcon.Close();
// Try reopen it
dbcon = new MySqlConnection(connectionString);
dbcon.Open();
}
catch (Exception e)
{
m_log.Error("Unable to reconnect to database " + e.ToString());
}
}
} }
/// <summary> /// <summary>
@ -264,9 +207,13 @@ namespace OpenSim.Data.MySQL
/// <param name="name">name of embedded resource</param> /// <param name="name">name of embedded resource</param>
public void ExecuteResourceSql(string name) public void ExecuteResourceSql(string name)
{ {
CheckConnection(); using (MySqlConnection dbcon = new MySqlConnection(connectionString))
MySqlCommand cmd = new MySqlCommand(getResourceString(name), dbcon); {
cmd.ExecuteNonQuery(); dbcon.Open();
MySqlCommand cmd = new MySqlCommand(getResourceString(name), dbcon);
cmd.ExecuteNonQuery();
}
} }
/// <summary> /// <summary>
@ -275,22 +222,29 @@ namespace OpenSim.Data.MySQL
/// <param name="sql">sql string to execute</param> /// <param name="sql">sql string to execute</param>
public void ExecuteSql(string sql) public void ExecuteSql(string sql)
{ {
CheckConnection(); using (MySqlConnection dbcon = new MySqlConnection(connectionString))
MySqlCommand cmd = new MySqlCommand(sql, dbcon); {
cmd.ExecuteNonQuery(); dbcon.Open();
MySqlCommand cmd = new MySqlCommand(sql, dbcon);
cmd.ExecuteNonQuery();
}
} }
public void ExecuteParameterizedSql(string sql, Dictionary<string, string> parameters) public void ExecuteParameterizedSql(string sql, Dictionary<string, string> parameters)
{ {
CheckConnection(); using (MySqlConnection dbcon = new MySqlConnection(connectionString))
MySqlCommand cmd = (MySqlCommand)dbcon.CreateCommand();
cmd.CommandText = sql;
foreach (KeyValuePair<string, string> param in parameters)
{ {
cmd.Parameters.AddWithValue(param.Key, param.Value); dbcon.Open();
MySqlCommand cmd = (MySqlCommand)dbcon.CreateCommand();
cmd.CommandText = sql;
foreach (KeyValuePair<string, string> param in parameters)
{
cmd.Parameters.AddWithValue(param.Key, param.Value);
}
cmd.ExecuteNonQuery();
} }
cmd.ExecuteNonQuery();
} }
/// <summary> /// <summary>
@ -299,35 +253,37 @@ namespace OpenSim.Data.MySQL
/// <param name="tableList"></param> /// <param name="tableList"></param>
public void GetTableVersion(Dictionary<string, string> tableList) public void GetTableVersion(Dictionary<string, string> tableList)
{ {
lock (dbcon) lock (m_dbLock)
{ {
CheckConnection(); using (MySqlConnection dbcon = new MySqlConnection(connectionString))
MySqlCommand tablesCmd =
new MySqlCommand(
"SELECT TABLE_NAME, TABLE_COMMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=?dbname",
dbcon);
tablesCmd.Parameters.AddWithValue("?dbname", dbcon.Database);
using (MySqlDataReader tables = tablesCmd.ExecuteReader())
{ {
while (tables.Read()) dbcon.Open();
using (MySqlCommand tablesCmd = new MySqlCommand(
"SELECT TABLE_NAME, TABLE_COMMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=?dbname", dbcon))
{ {
try tablesCmd.Parameters.AddWithValue("?dbname", dbcon.Database);
using (MySqlDataReader tables = tablesCmd.ExecuteReader())
{ {
string tableName = (string) tables["TABLE_NAME"]; while (tables.Read())
string comment = (string) tables["TABLE_COMMENT"];
if (tableList.ContainsKey(tableName))
{ {
tableList[tableName] = comment; try
{
string tableName = (string)tables["TABLE_NAME"];
string comment = (string)tables["TABLE_COMMENT"];
if (tableList.ContainsKey(tableName))
{
tableList[tableName] = comment;
}
}
catch (Exception e)
{
m_log.Error(e.Message, e);
}
} }
} }
catch (Exception e)
{
m_log.Error(e.ToString());
}
} }
tables.Close();
} }
} }
} }
@ -337,28 +293,27 @@ namespace OpenSim.Data.MySQL
/// <summary> /// <summary>
/// Runs a query with protection against SQL Injection by using parameterised input. /// Runs a query with protection against SQL Injection by using parameterised input.
/// </summary> /// </summary>
/// <param name="dbcon">Database connection</param>
/// <param name="sql">The SQL string - replace any variables such as WHERE x = "y" with WHERE x = @y</param> /// <param name="sql">The SQL string - replace any variables such as WHERE x = "y" with WHERE x = @y</param>
/// <param name="parameters">The parameters - index so that @y is indexed as 'y'</param> /// <param name="parameters">The parameters - index so that @y is indexed as 'y'</param>
/// <returns>A MySQL DB Command</returns> /// <returns>A MySQL DB Command</returns>
public IDbCommand Query(string sql, Dictionary<string, object> parameters) public IDbCommand Query(MySqlConnection dbcon, string sql, Dictionary<string, object> parameters)
{ {
try try
{ {
CheckConnection(); // Not sure if this one is necessary MySqlCommand dbcommand = (MySqlCommand)dbcon.CreateCommand();
MySqlCommand dbcommand = (MySqlCommand) dbcon.CreateCommand();
dbcommand.CommandText = sql; dbcommand.CommandText = sql;
foreach (KeyValuePair<string, object> param in parameters) foreach (KeyValuePair<string, object> param in parameters)
{ {
dbcommand.Parameters.AddWithValue(param.Key, param.Value); dbcommand.Parameters.AddWithValue(param.Key, param.Value);
} }
return (IDbCommand) dbcommand; return (IDbCommand)dbcommand;
} }
catch (Exception e) catch (Exception e)
{ {
// Return null if it fails. // Return null if it fails.
m_log.Error("Failed during Query generation: " + e.ToString()); m_log.Error("Failed during Query generation: " + e.Message, e);
return null; return null;
} }
} }
@ -694,8 +649,6 @@ namespace OpenSim.Data.MySQL
ret.Add(attachpoint, item); ret.Add(attachpoint, item);
} }
r.Close();
return ret; return ret;
} }
@ -727,12 +680,17 @@ namespace OpenSim.Data.MySQL
try try
{ {
IDbCommand result = Query(sql, parameters); using (MySqlConnection dbcon = new MySqlConnection(connectionString))
{
dbcon.Open();
if (result.ExecuteNonQuery() == 1) IDbCommand result = Query(dbcon, sql, parameters);
returnval = true;
result.Dispose(); if (result.ExecuteNonQuery() == 1)
returnval = true;
result.Dispose();
}
} }
catch (Exception e) catch (Exception e)
{ {
@ -828,12 +786,17 @@ namespace OpenSim.Data.MySQL
try try
{ {
IDbCommand result = Query(sql, parameters); using (MySqlConnection dbcon = new MySqlConnection(connectionString))
{
dbcon.Open();
if (result.ExecuteNonQuery() == 1) IDbCommand result = Query(dbcon, sql, parameters);
returnval = true;
result.Dispose(); if (result.ExecuteNonQuery() == 1)
returnval = true;
result.Dispose();
}
} }
catch (Exception e) catch (Exception e)
{ {
@ -927,12 +890,17 @@ namespace OpenSim.Data.MySQL
bool returnval = false; bool returnval = false;
try try
{ {
IDbCommand result = Query(sql, parameters); using (MySqlConnection dbcon = new MySqlConnection(connectionString))
{
dbcon.Open();
if (result.ExecuteNonQuery() == 1) IDbCommand result = Query(dbcon, sql, parameters);
returnval = true;
result.Dispose(); if (result.ExecuteNonQuery() == 1)
returnval = true;
result.Dispose();
}
} }
catch (Exception e) catch (Exception e)
{ {
@ -1030,18 +998,23 @@ namespace OpenSim.Data.MySQL
try try
{ {
IDbCommand result = Query(sql, parameters); using (MySqlConnection dbcon = new MySqlConnection(connectionString))
// int x;
// if ((x = result.ExecuteNonQuery()) > 0)
// {
// returnval = true;
// }
if (result.ExecuteNonQuery() > 0)
{ {
returnval = true; dbcon.Open();
IDbCommand result = Query(dbcon, sql, parameters);
// int x;
// if ((x = result.ExecuteNonQuery()) > 0)
// {
// returnval = true;
// }
if (result.ExecuteNonQuery() > 0)
{
returnval = true;
}
result.Dispose();
} }
result.Dispose();
} }
catch (Exception e) catch (Exception e)
{ {
@ -1070,18 +1043,23 @@ namespace OpenSim.Data.MySQL
{ {
parameters["?uuid"] = uuid; parameters["?uuid"] = uuid;
IDbCommand result = Query(sql, parameters); using (MySqlConnection dbcon = new MySqlConnection(connectionString))
// int x;
// if ((x = result.ExecuteNonQuery()) > 0)
// {
// returnval = true;
// }
if (result.ExecuteNonQuery() > 0)
{ {
returnval = true; dbcon.Open();
IDbCommand result = Query(dbcon, sql, parameters);
// int x;
// if ((x = result.ExecuteNonQuery()) > 0)
// {
// returnval = true;
// }
if (result.ExecuteNonQuery() > 0)
{
returnval = true;
}
result.Dispose();
} }
result.Dispose();
} }
catch (Exception e) catch (Exception e)
{ {
@ -1122,18 +1100,23 @@ namespace OpenSim.Data.MySQL
try try
{ {
IDbCommand result = Query(sql, parameters); using (MySqlConnection dbcon = new MySqlConnection(connectionString))
// int x;
// if ((x = result.ExecuteNonQuery()) > 0)
// {
// returnval = true;
// }
if (result.ExecuteNonQuery() > 0)
{ {
returnval = true; dbcon.Open();
IDbCommand result = Query(dbcon, sql, parameters);
// int x;
// if ((x = result.ExecuteNonQuery()) > 0)
// {
// returnval = true;
// }
if (result.ExecuteNonQuery() > 0)
{
returnval = true;
}
result.Dispose();
} }
result.Dispose();
} }
catch (Exception e) catch (Exception e)
{ {
@ -1167,45 +1150,51 @@ namespace OpenSim.Data.MySQL
bool returnval = false; bool returnval = false;
// we want to send in byte data, which means we can't just pass down strings // we want to send in byte data, which means we can't just pass down strings
try { try
MySqlCommand cmd = (MySqlCommand) dbcon.CreateCommand(); {
cmd.CommandText = sql; using (MySqlConnection dbcon = new MySqlConnection(connectionString))
cmd.Parameters.AddWithValue("?owner", appearance.Owner.ToString()); {
cmd.Parameters.AddWithValue("?serial", appearance.Serial); dbcon.Open();
cmd.Parameters.AddWithValue("?visual_params", appearance.VisualParams);
cmd.Parameters.AddWithValue("?texture", appearance.Texture.GetBytes());
cmd.Parameters.AddWithValue("?avatar_height", appearance.AvatarHeight);
cmd.Parameters.AddWithValue("?body_item", appearance.BodyItem.ToString());
cmd.Parameters.AddWithValue("?body_asset", appearance.BodyAsset.ToString());
cmd.Parameters.AddWithValue("?skin_item", appearance.SkinItem.ToString());
cmd.Parameters.AddWithValue("?skin_asset", appearance.SkinAsset.ToString());
cmd.Parameters.AddWithValue("?hair_item", appearance.HairItem.ToString());
cmd.Parameters.AddWithValue("?hair_asset", appearance.HairAsset.ToString());
cmd.Parameters.AddWithValue("?eyes_item", appearance.EyesItem.ToString());
cmd.Parameters.AddWithValue("?eyes_asset", appearance.EyesAsset.ToString());
cmd.Parameters.AddWithValue("?shirt_item", appearance.ShirtItem.ToString());
cmd.Parameters.AddWithValue("?shirt_asset", appearance.ShirtAsset.ToString());
cmd.Parameters.AddWithValue("?pants_item", appearance.PantsItem.ToString());
cmd.Parameters.AddWithValue("?pants_asset", appearance.PantsAsset.ToString());
cmd.Parameters.AddWithValue("?shoes_item", appearance.ShoesItem.ToString());
cmd.Parameters.AddWithValue("?shoes_asset", appearance.ShoesAsset.ToString());
cmd.Parameters.AddWithValue("?socks_item", appearance.SocksItem.ToString());
cmd.Parameters.AddWithValue("?socks_asset", appearance.SocksAsset.ToString());
cmd.Parameters.AddWithValue("?jacket_item", appearance.JacketItem.ToString());
cmd.Parameters.AddWithValue("?jacket_asset", appearance.JacketAsset.ToString());
cmd.Parameters.AddWithValue("?gloves_item", appearance.GlovesItem.ToString());
cmd.Parameters.AddWithValue("?gloves_asset", appearance.GlovesAsset.ToString());
cmd.Parameters.AddWithValue("?undershirt_item", appearance.UnderShirtItem.ToString());
cmd.Parameters.AddWithValue("?undershirt_asset", appearance.UnderShirtAsset.ToString());
cmd.Parameters.AddWithValue("?underpants_item", appearance.UnderPantsItem.ToString());
cmd.Parameters.AddWithValue("?underpants_asset", appearance.UnderPantsAsset.ToString());
cmd.Parameters.AddWithValue("?skirt_item", appearance.SkirtItem.ToString());
cmd.Parameters.AddWithValue("?skirt_asset", appearance.SkirtAsset.ToString());
if (cmd.ExecuteNonQuery() > 0) using (MySqlCommand cmd = (MySqlCommand)dbcon.CreateCommand())
returnval = true; {
cmd.CommandText = sql;
cmd.Parameters.AddWithValue("?owner", appearance.Owner.ToString());
cmd.Parameters.AddWithValue("?serial", appearance.Serial);
cmd.Parameters.AddWithValue("?visual_params", appearance.VisualParams);
cmd.Parameters.AddWithValue("?texture", appearance.Texture.GetBytes());
cmd.Parameters.AddWithValue("?avatar_height", appearance.AvatarHeight);
cmd.Parameters.AddWithValue("?body_item", appearance.BodyItem.ToString());
cmd.Parameters.AddWithValue("?body_asset", appearance.BodyAsset.ToString());
cmd.Parameters.AddWithValue("?skin_item", appearance.SkinItem.ToString());
cmd.Parameters.AddWithValue("?skin_asset", appearance.SkinAsset.ToString());
cmd.Parameters.AddWithValue("?hair_item", appearance.HairItem.ToString());
cmd.Parameters.AddWithValue("?hair_asset", appearance.HairAsset.ToString());
cmd.Parameters.AddWithValue("?eyes_item", appearance.EyesItem.ToString());
cmd.Parameters.AddWithValue("?eyes_asset", appearance.EyesAsset.ToString());
cmd.Parameters.AddWithValue("?shirt_item", appearance.ShirtItem.ToString());
cmd.Parameters.AddWithValue("?shirt_asset", appearance.ShirtAsset.ToString());
cmd.Parameters.AddWithValue("?pants_item", appearance.PantsItem.ToString());
cmd.Parameters.AddWithValue("?pants_asset", appearance.PantsAsset.ToString());
cmd.Parameters.AddWithValue("?shoes_item", appearance.ShoesItem.ToString());
cmd.Parameters.AddWithValue("?shoes_asset", appearance.ShoesAsset.ToString());
cmd.Parameters.AddWithValue("?socks_item", appearance.SocksItem.ToString());
cmd.Parameters.AddWithValue("?socks_asset", appearance.SocksAsset.ToString());
cmd.Parameters.AddWithValue("?jacket_item", appearance.JacketItem.ToString());
cmd.Parameters.AddWithValue("?jacket_asset", appearance.JacketAsset.ToString());
cmd.Parameters.AddWithValue("?gloves_item", appearance.GlovesItem.ToString());
cmd.Parameters.AddWithValue("?gloves_asset", appearance.GlovesAsset.ToString());
cmd.Parameters.AddWithValue("?undershirt_item", appearance.UnderShirtItem.ToString());
cmd.Parameters.AddWithValue("?undershirt_asset", appearance.UnderShirtAsset.ToString());
cmd.Parameters.AddWithValue("?underpants_item", appearance.UnderPantsItem.ToString());
cmd.Parameters.AddWithValue("?underpants_asset", appearance.UnderPantsAsset.ToString());
cmd.Parameters.AddWithValue("?skirt_item", appearance.SkirtItem.ToString());
cmd.Parameters.AddWithValue("?skirt_asset", appearance.SkirtAsset.ToString());
cmd.Dispose(); if (cmd.ExecuteNonQuery() > 0)
returnval = true;
}
}
} }
catch (Exception e) catch (Exception e)
{ {
@ -1221,33 +1210,38 @@ namespace OpenSim.Data.MySQL
{ {
string sql = "delete from avatarattachments where UUID = ?uuid"; string sql = "delete from avatarattachments where UUID = ?uuid";
MySqlCommand cmd = (MySqlCommand) dbcon.CreateCommand(); using (MySqlConnection dbcon = new MySqlConnection(connectionString))
cmd.CommandText = sql;
cmd.Parameters.AddWithValue("?uuid", agentID.ToString());
cmd.ExecuteNonQuery();
if (data == null)
return;
sql = "insert into avatarattachments (UUID, attachpoint, item, asset) values (?uuid, ?attachpoint, ?item, ?asset)";
cmd = (MySqlCommand) dbcon.CreateCommand();
cmd.CommandText = sql;
foreach (DictionaryEntry e in data)
{ {
int attachpoint = Convert.ToInt32(e.Key); dbcon.Open();
Hashtable item = (Hashtable)e.Value; MySqlCommand cmd = (MySqlCommand)dbcon.CreateCommand();
cmd.CommandText = sql;
cmd.Parameters.Clear();
cmd.Parameters.AddWithValue("?uuid", agentID.ToString()); cmd.Parameters.AddWithValue("?uuid", agentID.ToString());
cmd.Parameters.AddWithValue("?attachpoint", attachpoint);
cmd.Parameters.AddWithValue("?item", item["item"]);
cmd.Parameters.AddWithValue("?asset", item["asset"]);
cmd.ExecuteNonQuery(); cmd.ExecuteNonQuery();
if (data == null)
return;
sql = "insert into avatarattachments (UUID, attachpoint, item, asset) values (?uuid, ?attachpoint, ?item, ?asset)";
cmd = (MySqlCommand)dbcon.CreateCommand();
cmd.CommandText = sql;
foreach (DictionaryEntry e in data)
{
int attachpoint = Convert.ToInt32(e.Key);
Hashtable item = (Hashtable)e.Value;
cmd.Parameters.Clear();
cmd.Parameters.AddWithValue("?uuid", agentID.ToString());
cmd.Parameters.AddWithValue("?attachpoint", attachpoint);
cmd.Parameters.AddWithValue("?item", item["item"]);
cmd.Parameters.AddWithValue("?asset", item["asset"]);
cmd.ExecuteNonQuery();
}
} }
} }
} }

View File

@ -123,27 +123,26 @@ namespace OpenSim.Data.MySQL
cmd.Parameters.AddWithValue("?UserID", userID); cmd.Parameters.AddWithValue("?UserID", userID);
IDataReader reader = ExecuteReader(cmd); using (IDataReader reader = cmd.ExecuteReader())
List<UUID> deleteSessions = new List<UUID>();
int online = 0;
while(reader.Read())
{ {
if (bool.Parse(reader["Online"].ToString()))
online++; List<UUID> deleteSessions = new List<UUID>();
else int online = 0;
deleteSessions.Add(new UUID(reader["SessionID"].ToString()));
while(reader.Read())
{
if (bool.Parse(reader["Online"].ToString()))
online++;
else
deleteSessions.Add(new UUID(reader["SessionID"].ToString()));
}
if (online == 0 && deleteSessions.Count > 0)
deleteSessions.RemoveAt(0);
foreach (UUID s in deleteSessions)
Delete("SessionID", s.ToString());
} }
if (online == 0 && deleteSessions.Count > 0)
deleteSessions.RemoveAt(0);
reader.Close();
CloseReaderCommand(cmd);
foreach (UUID s in deleteSessions)
Delete("SessionID", s.ToString());
} }
} }
} }

View File

@ -38,16 +38,21 @@ namespace OpenSim.Data.MySQL
public class MySqlRegionData : MySqlFramework, IRegionData public class MySqlRegionData : MySqlFramework, IRegionData
{ {
private string m_Realm; private string m_Realm;
private List<string> m_ColumnNames = null; private List<string> m_ColumnNames;
// private int m_LastExpire = 0; //private string m_connectionString;
public MySqlRegionData(string connectionString, string realm) public MySqlRegionData(string connectionString, string realm)
: base(connectionString) : base(connectionString)
{ {
m_Realm = realm; m_Realm = realm;
m_connectionString = connectionString;
Migration m = new Migration(m_Connection, GetType().Assembly, "GridStore"); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
m.Update(); {
dbcon.Open();
Migration m = new Migration(dbcon, GetType().Assembly, "GridStore");
m.Update();
}
} }
public List<RegionData> Get(string regionName, UUID scopeID) public List<RegionData> Get(string regionName, UUID scopeID)
@ -56,12 +61,13 @@ namespace OpenSim.Data.MySQL
if (scopeID != UUID.Zero) if (scopeID != UUID.Zero)
command += " and ScopeID = ?scopeID"; command += " and ScopeID = ?scopeID";
MySqlCommand cmd = new MySqlCommand(command); using (MySqlCommand cmd = new MySqlCommand(command))
{
cmd.Parameters.AddWithValue("?regionName", regionName);
cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString());
cmd.Parameters.AddWithValue("?regionName", regionName); return RunCommand(cmd);
cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString()); }
return RunCommand(cmd);
} }
public RegionData Get(int posX, int posY, UUID scopeID) public RegionData Get(int posX, int posY, UUID scopeID)
@ -70,17 +76,18 @@ namespace OpenSim.Data.MySQL
if (scopeID != UUID.Zero) if (scopeID != UUID.Zero)
command += " and ScopeID = ?scopeID"; command += " and ScopeID = ?scopeID";
MySqlCommand cmd = new MySqlCommand(command); using (MySqlCommand cmd = new MySqlCommand(command))
{
cmd.Parameters.AddWithValue("?posX", posX.ToString());
cmd.Parameters.AddWithValue("?posY", posY.ToString());
cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString());
cmd.Parameters.AddWithValue("?posX", posX.ToString()); List<RegionData> ret = RunCommand(cmd);
cmd.Parameters.AddWithValue("?posY", posY.ToString()); if (ret.Count == 0)
cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString()); return null;
List<RegionData> ret = RunCommand(cmd); return ret[0];
if (ret.Count == 0) }
return null;
return ret[0];
} }
public RegionData Get(UUID regionID, UUID scopeID) public RegionData Get(UUID regionID, UUID scopeID)
@ -89,16 +96,17 @@ namespace OpenSim.Data.MySQL
if (scopeID != UUID.Zero) if (scopeID != UUID.Zero)
command += " and ScopeID = ?scopeID"; command += " and ScopeID = ?scopeID";
MySqlCommand cmd = new MySqlCommand(command); using (MySqlCommand cmd = new MySqlCommand(command))
{
cmd.Parameters.AddWithValue("?regionID", regionID.ToString());
cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString());
cmd.Parameters.AddWithValue("?regionID", regionID.ToString()); List<RegionData> ret = RunCommand(cmd);
cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString()); if (ret.Count == 0)
return null;
List<RegionData> ret = RunCommand(cmd); return ret[0];
if (ret.Count == 0) }
return null;
return ret[0];
} }
public List<RegionData> Get(int startX, int startY, int endX, int endY, UUID scopeID) public List<RegionData> Get(int startX, int startY, int endX, int endY, UUID scopeID)
@ -107,74 +115,79 @@ namespace OpenSim.Data.MySQL
if (scopeID != UUID.Zero) if (scopeID != UUID.Zero)
command += " and ScopeID = ?scopeID"; command += " and ScopeID = ?scopeID";
MySqlCommand cmd = new MySqlCommand(command); using (MySqlCommand cmd = new MySqlCommand(command))
{
cmd.Parameters.AddWithValue("?startX", startX.ToString());
cmd.Parameters.AddWithValue("?startY", startY.ToString());
cmd.Parameters.AddWithValue("?endX", endX.ToString());
cmd.Parameters.AddWithValue("?endY", endY.ToString());
cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString());
cmd.Parameters.AddWithValue("?startX", startX.ToString()); return RunCommand(cmd);
cmd.Parameters.AddWithValue("?startY", startY.ToString()); }
cmd.Parameters.AddWithValue("?endX", endX.ToString());
cmd.Parameters.AddWithValue("?endY", endY.ToString());
cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString());
return RunCommand(cmd);
} }
public List<RegionData> RunCommand(MySqlCommand cmd) public List<RegionData> RunCommand(MySqlCommand cmd)
{ {
List<RegionData> retList = new List<RegionData>(); List<RegionData> retList = new List<RegionData>();
IDataReader result = ExecuteReader(cmd); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
while (result.Read())
{ {
RegionData ret = new RegionData(); dbcon.Open();
ret.Data = new Dictionary<string, object>(); cmd.Connection = dbcon;
UUID regionID; using (IDataReader result = cmd.ExecuteReader())
UUID.TryParse(result["uuid"].ToString(), out regionID);
ret.RegionID = regionID;
UUID scope;
UUID.TryParse(result["ScopeID"].ToString(), out scope);
ret.ScopeID = scope;
ret.RegionName = result["regionName"].ToString();
ret.posX = Convert.ToInt32(result["locX"]);
ret.posY = Convert.ToInt32(result["locY"]);
ret.sizeX = Convert.ToInt32(result["sizeX"]);
ret.sizeY = Convert.ToInt32(result["sizeY"]);
if (m_ColumnNames == null)
{ {
m_ColumnNames = new List<string>(); while (result.Read())
{
RegionData ret = new RegionData();
ret.Data = new Dictionary<string, object>();
DataTable schemaTable = result.GetSchemaTable(); UUID regionID;
foreach (DataRow row in schemaTable.Rows) UUID.TryParse(result["uuid"].ToString(), out regionID);
ret.RegionID = regionID;
UUID scope;
UUID.TryParse(result["ScopeID"].ToString(), out scope);
ret.ScopeID = scope;
ret.RegionName = result["regionName"].ToString();
ret.posX = Convert.ToInt32(result["locX"]);
ret.posY = Convert.ToInt32(result["locY"]);
ret.sizeX = Convert.ToInt32(result["sizeX"]);
ret.sizeY = Convert.ToInt32(result["sizeY"]);
if (m_ColumnNames == null)
{ {
if (row["ColumnName"] != null) m_ColumnNames = new List<string>();
m_ColumnNames.Add(row["ColumnName"].ToString());
DataTable schemaTable = result.GetSchemaTable();
foreach (DataRow row in schemaTable.Rows)
{
if (row["ColumnName"] != null)
m_ColumnNames.Add(row["ColumnName"].ToString());
}
} }
foreach (string s in m_ColumnNames)
{
if (s == "uuid")
continue;
if (s == "ScopeID")
continue;
if (s == "regionName")
continue;
if (s == "locX")
continue;
if (s == "locY")
continue;
ret.Data[s] = result[s].ToString();
}
retList.Add(ret);
} }
foreach (string s in m_ColumnNames)
{
if (s == "uuid")
continue;
if (s == "ScopeID")
continue;
if (s == "regionName")
continue;
if (s == "locX")
continue;
if (s == "locY")
continue;
ret.Data[s] = result[s].ToString();
} }
retList.Add(ret);
} }
result.Close();
CloseReaderCommand(cmd);
return retList; return retList;
} }
@ -201,76 +214,72 @@ namespace OpenSim.Data.MySQL
string[] fields = new List<string>(data.Data.Keys).ToArray(); string[] fields = new List<string>(data.Data.Keys).ToArray();
MySqlCommand cmd = new MySqlCommand(); using (MySqlCommand cmd = new MySqlCommand())
string update = "update `"+m_Realm+"` set locX=?posX, locY=?posY, sizeX=?sizeX, sizeY=?sizeY";
foreach (string field in fields)
{ {
update += ", "; string update = "update `" + m_Realm + "` set locX=?posX, locY=?posY, sizeX=?sizeX, sizeY=?sizeY";
update += "`" + field + "` = ?"+field; foreach (string field in fields)
{
update += ", ";
update += "`" + field + "` = ?" + field;
cmd.Parameters.AddWithValue("?"+field, data.Data[field]); cmd.Parameters.AddWithValue("?" + field, data.Data[field]);
} }
update += " where uuid = ?regionID"; update += " where uuid = ?regionID";
if (data.ScopeID != UUID.Zero) if (data.ScopeID != UUID.Zero)
update += " and ScopeID = ?scopeID"; update += " and ScopeID = ?scopeID";
cmd.CommandText = update; cmd.CommandText = update;
cmd.Parameters.AddWithValue("?regionID", data.RegionID.ToString()); cmd.Parameters.AddWithValue("?regionID", data.RegionID.ToString());
cmd.Parameters.AddWithValue("?regionName", data.RegionName); cmd.Parameters.AddWithValue("?regionName", data.RegionName);
cmd.Parameters.AddWithValue("?scopeID", data.ScopeID.ToString()); cmd.Parameters.AddWithValue("?scopeID", data.ScopeID.ToString());
cmd.Parameters.AddWithValue("?posX", data.posX.ToString()); cmd.Parameters.AddWithValue("?posX", data.posX.ToString());
cmd.Parameters.AddWithValue("?posY", data.posY.ToString()); cmd.Parameters.AddWithValue("?posY", data.posY.ToString());
cmd.Parameters.AddWithValue("?sizeX", data.sizeX.ToString()); cmd.Parameters.AddWithValue("?sizeX", data.sizeX.ToString());
cmd.Parameters.AddWithValue("?sizeY", data.sizeY.ToString()); cmd.Parameters.AddWithValue("?sizeY", data.sizeY.ToString());
if (ExecuteNonQuery(cmd) < 1)
{
string insert = "insert into `" + m_Realm + "` (`uuid`, `ScopeID`, `locX`, `locY`, `sizeX`, `sizeY`, `regionName`, `" +
String.Join("`, `", fields) +
"`) values ( ?regionID, ?scopeID, ?posX, ?posY, ?sizeX, ?sizeY, ?regionName, ?" + String.Join(", ?", fields) + ")";
cmd.CommandText = insert;
if (ExecuteNonQuery(cmd) < 1) if (ExecuteNonQuery(cmd) < 1)
{ {
cmd.Dispose(); string insert = "insert into `" + m_Realm + "` (`uuid`, `ScopeID`, `locX`, `locY`, `sizeX`, `sizeY`, `regionName`, `" +
return false; String.Join("`, `", fields) +
"`) values ( ?regionID, ?scopeID, ?posX, ?posY, ?sizeX, ?sizeY, ?regionName, ?" + String.Join(", ?", fields) + ")";
cmd.CommandText = insert;
if (ExecuteNonQuery(cmd) < 1)
{
return false;
}
} }
} }
cmd.Dispose();
return true; return true;
} }
public bool SetDataItem(UUID regionID, string item, string value) public bool SetDataItem(UUID regionID, string item, string value)
{ {
MySqlCommand cmd = new MySqlCommand("update `" + m_Realm + using (MySqlCommand cmd = new MySqlCommand("update `" + m_Realm + "` set `" + item + "` = ?" + item + " where uuid = ?UUID"))
"` set `" + item + "` = ?" + item + " where uuid = ?UUID"); {
cmd.Parameters.AddWithValue("?" + item, value);
cmd.Parameters.AddWithValue("?UUID", regionID.ToString());
if (ExecuteNonQuery(cmd) > 0)
cmd.Parameters.AddWithValue("?"+item, value); return true;
cmd.Parameters.AddWithValue("?UUID", regionID.ToString()); }
if (ExecuteNonQuery(cmd) > 0)
return true;
return false; return false;
} }
public bool Delete(UUID regionID) public bool Delete(UUID regionID)
{ {
MySqlCommand cmd = new MySqlCommand("delete from `" + m_Realm + using (MySqlCommand cmd = new MySqlCommand("delete from `" + m_Realm + "` where uuid = ?UUID"))
"` where uuid = ?UUID"); {
cmd.Parameters.AddWithValue("?UUID", regionID.ToString());
if (ExecuteNonQuery(cmd) > 0)
cmd.Parameters.AddWithValue("?UUID", regionID.ToString()); return true;
}
if (ExecuteNonQuery(cmd) > 0)
return true;
return false; return false;
} }

View File

@ -33,6 +33,7 @@ using System.Reflection;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
using log4net; using log4net;
using MySql.Data.MySqlClient;
using OpenMetaverse; using OpenMetaverse;
using OpenSim.Framework; using OpenSim.Framework;
@ -45,15 +46,9 @@ namespace OpenSim.Data.MySQL
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
/// <summary> private MySQLManager m_database;
/// Database manager for MySQL private string m_connectionString;
/// </summary> private object m_dbLock = new object();
public MySQLManager database;
/// <summary>
/// Better DB manager. Swap-in replacement too.
/// </summary>
public Dictionary<int, MySQLSuperManager> m_dbconnections = new Dictionary<int, MySQLSuperManager>();
public int m_maxConnections = 10; public int m_maxConnections = 10;
public int m_lastConnect; public int m_lastConnect;
@ -63,7 +58,6 @@ namespace OpenSim.Data.MySQL
private string m_userFriendsTableName = "userfriends"; private string m_userFriendsTableName = "userfriends";
private string m_appearanceTableName = "avatarappearance"; private string m_appearanceTableName = "avatarappearance";
private string m_attachmentsTableName = "avatarattachments"; private string m_attachmentsTableName = "avatarattachments";
private string m_connectString;
public override void Initialise() public override void Initialise()
{ {
@ -71,41 +65,6 @@ namespace OpenSim.Data.MySQL
throw new PluginNotInitialisedException(Name); throw new PluginNotInitialisedException(Name);
} }
public MySQLSuperManager GetLockedConnection(string why)
{
int lockedCons = 0;
while (true)
{
m_lastConnect++;
// Overflow protection
if (m_lastConnect == int.MaxValue)
m_lastConnect = 0;
MySQLSuperManager x = m_dbconnections[m_lastConnect%m_maxConnections];
if (!x.Locked)
{
x.GetLock();
x.Running = why;
return x;
}
lockedCons++;
if (lockedCons > m_maxConnections)
{
lockedCons = 0;
Thread.Sleep(1000); // Wait some time before searching them again.
m_log.Debug(
"WARNING: All threads are in use. Probable cause: Something didnt release a mutex properly, or high volume of requests inbound.");
m_log.Debug("Current connections-in-use dump:");
foreach (KeyValuePair<int, MySQLSuperManager> kvp in m_dbconnections)
{
m_log.Debug(kvp.Value.Running);
}
}
}
}
/// <summary> /// <summary>
/// Initialise User Interface /// Initialise User Interface
/// Loads and initialises the MySQL storage plugin /// Loads and initialises the MySQL storage plugin
@ -115,55 +74,18 @@ namespace OpenSim.Data.MySQL
/// <param name="connect">connect string.</param> /// <param name="connect">connect string.</param>
public override void Initialise(string connect) public override void Initialise(string connect)
{ {
if (connect == String.Empty) m_connectionString = connect;
{ m_database = new MySQLManager(connect);
// TODO: actually do something with our connect string
// instead of loading the second config
m_log.Warn("Using obsoletely mysql_connection.ini, try using user_source connect string instead");
IniFile iniFile = new IniFile("mysql_connection.ini");
string settingHostname = iniFile.ParseFileReadValue("hostname");
string settingDatabase = iniFile.ParseFileReadValue("database");
string settingUsername = iniFile.ParseFileReadValue("username");
string settingPassword = iniFile.ParseFileReadValue("password");
string settingPooling = iniFile.ParseFileReadValue("pooling");
string settingPort = iniFile.ParseFileReadValue("port");
m_connectString = "Server=" + settingHostname + ";Port=" + settingPort + ";Database=" + settingDatabase +
";User ID=" +
settingUsername + ";Password=" + settingPassword + ";Pooling=" + settingPooling + ";";
m_log.Info("Creating " + m_maxConnections + " DB connections...");
for (int i = 0; i < m_maxConnections; i++)
{
m_log.Info("Connecting to DB... [" + i + "]");
MySQLSuperManager msm = new MySQLSuperManager();
msm.Manager = new MySQLManager(m_connectString);
m_dbconnections.Add(i, msm);
}
database = new MySQLManager(m_connectString);
}
else
{
m_connectString = connect;
database = new MySQLManager(m_connectString);
m_log.Info("Creating " + m_maxConnections + " DB connections...");
for (int i = 0; i < m_maxConnections; i++)
{
m_log.Info("Connecting to DB... [" + i + "]");
MySQLSuperManager msm = new MySQLSuperManager();
msm.Manager = new MySQLManager(m_connectString);
m_dbconnections.Add(i, msm);
}
}
// This actually does the roll forward assembly stuff // This actually does the roll forward assembly stuff
Assembly assem = GetType().Assembly; Assembly assem = GetType().Assembly;
Migration m = new Migration(database.Connection, assem, "UserStore");
m.Update(); using (MySql.Data.MySqlClient.MySqlConnection dbcon = new MySql.Data.MySqlClient.MySqlConnection(m_connectionString))
{
dbcon.Open();
Migration m = new Migration(dbcon, assem, "UserStore");
m.Update();
}
} }
public override void Dispose() public override void Dispose()
@ -173,35 +95,32 @@ namespace OpenSim.Data.MySQL
// see IUserDataPlugin // see IUserDataPlugin
public override UserProfileData GetUserByName(string user, string last) public override UserProfileData GetUserByName(string user, string last)
{ {
MySQLSuperManager dbm = GetLockedConnection("GetUserByName");
try try
{ {
Dictionary<string, object> param = new Dictionary<string, object>(); Dictionary<string, object> param = new Dictionary<string, object>();
param["?first"] = user; param["?first"] = user;
param["?second"] = last; param["?second"] = last;
IDbCommand result = using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
dbm.Manager.Query( {
"SELECT * FROM " + m_usersTableName + " WHERE username = ?first AND lastname = ?second", param); dbcon.Open();
IDataReader reader = result.ExecuteReader();
UserProfileData row = dbm.Manager.readUserRow(reader); using (IDbCommand result = m_database.Query(dbcon,
"SELECT * FROM " + m_usersTableName + " WHERE username = ?first AND lastname = ?second", param))
reader.Dispose(); {
result.Dispose(); using (IDataReader reader = result.ExecuteReader())
return row; {
UserProfileData row = m_database.readUserRow(reader);
return row;
}
}
}
} }
catch (Exception e) catch (Exception e)
{ {
dbm.Manager.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString());
return null; return null;
} }
finally
{
dbm.Release();
}
} }
#region User Friends List Data #region User Friends List Data
@ -216,38 +135,38 @@ namespace OpenSim.Data.MySQL
param["?friendPerms"] = perms.ToString(); param["?friendPerms"] = perms.ToString();
param["?datetimestamp"] = dtvalue.ToString(); param["?datetimestamp"] = dtvalue.ToString();
MySQLSuperManager dbm = GetLockedConnection("AddNewUserFriend");
try try
{ {
IDbCommand adder = using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
dbm.Manager.Query( {
dbcon.Open();
using (IDbCommand adder = m_database.Query(dbcon,
"INSERT INTO `" + m_userFriendsTableName + "` " + "INSERT INTO `" + m_userFriendsTableName + "` " +
"(`ownerID`,`friendID`,`friendPerms`,`datetimestamp`) " + "(`ownerID`,`friendID`,`friendPerms`,`datetimestamp`) " +
"VALUES " + "VALUES " +
"(?ownerID,?friendID,?friendPerms,?datetimestamp)", "(?ownerID,?friendID,?friendPerms,?datetimestamp)",
param); param))
adder.ExecuteNonQuery(); {
adder.ExecuteNonQuery();
}
adder = using (IDbCommand adder = m_database.Query(dbcon,
dbm.Manager.Query(
"INSERT INTO `" + m_userFriendsTableName + "` " + "INSERT INTO `" + m_userFriendsTableName + "` " +
"(`ownerID`,`friendID`,`friendPerms`,`datetimestamp`) " + "(`ownerID`,`friendID`,`friendPerms`,`datetimestamp`) " +
"VALUES " + "VALUES " +
"(?friendID,?ownerID,?friendPerms,?datetimestamp)", "(?friendID,?ownerID,?friendPerms,?datetimestamp)",
param); param))
adder.ExecuteNonQuery(); {
adder.ExecuteNonQuery();
}
}
} }
catch (Exception e) catch (Exception e)
{ {
dbm.Manager.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString());
return; return;
} }
finally
{
dbm.Release();
}
} }
public override void RemoveUserFriend(UUID friendlistowner, UUID friend) public override void RemoveUserFriend(UUID friendlistowner, UUID friend)
@ -256,32 +175,32 @@ namespace OpenSim.Data.MySQL
param["?ownerID"] = friendlistowner.ToString(); param["?ownerID"] = friendlistowner.ToString();
param["?friendID"] = friend.ToString(); param["?friendID"] = friend.ToString();
MySQLSuperManager dbm = GetLockedConnection("RemoveUserFriend");
try try
{ {
IDbCommand updater = using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
dbm.Manager.Query( {
"delete from " + m_userFriendsTableName + " where ownerID = ?ownerID and friendID = ?friendID", dbcon.Open();
param);
updater.ExecuteNonQuery();
updater = using (IDbCommand updater = m_database.Query(dbcon,
dbm.Manager.Query( "delete from " + m_userFriendsTableName + " where ownerID = ?ownerID and friendID = ?friendID",
"delete from " + m_userFriendsTableName + " where ownerID = ?friendID and friendID = ?ownerID", param))
param); {
updater.ExecuteNonQuery(); updater.ExecuteNonQuery();
}
using (IDbCommand updater = m_database.Query(dbcon,
"delete from " + m_userFriendsTableName + " where ownerID = ?friendID and friendID = ?ownerID",
param))
{
updater.ExecuteNonQuery();
}
}
} }
catch (Exception e) catch (Exception e)
{ {
dbm.Manager.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString());
return; return;
} }
finally
{
dbm.Release();
}
} }
public override void UpdateUserFriendPerms(UUID friendlistowner, UUID friend, uint perms) public override void UpdateUserFriendPerms(UUID friendlistowner, UUID friend, uint perms)
@ -291,28 +210,27 @@ namespace OpenSim.Data.MySQL
param["?friendID"] = friend.ToString(); param["?friendID"] = friend.ToString();
param["?friendPerms"] = perms.ToString(); param["?friendPerms"] = perms.ToString();
MySQLSuperManager dbm = GetLockedConnection("UpdateUserFriendPerms");
try try
{ {
IDbCommand updater = using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
dbm.Manager.Query( {
"update " + m_userFriendsTableName + dbcon.Open();
" SET friendPerms = ?friendPerms " +
"where ownerID = ?ownerID and friendID = ?friendID", using (IDbCommand updater = m_database.Query(dbcon,
param); "update " + m_userFriendsTableName +
updater.ExecuteNonQuery(); " SET friendPerms = ?friendPerms " +
"where ownerID = ?ownerID and friendID = ?friendID",
param))
{
updater.ExecuteNonQuery();
}
}
} }
catch (Exception e) catch (Exception e)
{ {
dbm.Manager.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString());
return; return;
} }
finally
{
dbm.Release();
}
} }
public override List<FriendListItem> GetUserFriendList(UUID friendlistowner) public override List<FriendListItem> GetUserFriendList(UUID friendlistowner)
@ -322,87 +240,83 @@ namespace OpenSim.Data.MySQL
Dictionary<string, object> param = new Dictionary<string, object>(); Dictionary<string, object> param = new Dictionary<string, object>();
param["?ownerID"] = friendlistowner.ToString(); param["?ownerID"] = friendlistowner.ToString();
MySQLSuperManager dbm = GetLockedConnection("GetUserFriendList");
try try
{ {
//Left Join userfriends to itself using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
IDbCommand result = {
dbm.Manager.Query( dbcon.Open();
//Left Join userfriends to itself
using (IDbCommand result = m_database.Query(dbcon,
"select a.ownerID,a.friendID,a.friendPerms,b.friendPerms as ownerperms from " + "select a.ownerID,a.friendID,a.friendPerms,b.friendPerms as ownerperms from " +
m_userFriendsTableName + " as a, " + m_userFriendsTableName + " as b" + m_userFriendsTableName + " as a, " + m_userFriendsTableName + " as b" +
" where a.ownerID = ?ownerID and b.ownerID = a.friendID and b.friendID = a.ownerID", " where a.ownerID = ?ownerID and b.ownerID = a.friendID and b.friendID = a.ownerID",
param); param))
IDataReader reader = result.ExecuteReader(); {
using (IDataReader reader = result.ExecuteReader())
{
while (reader.Read())
{
FriendListItem fli = new FriendListItem();
fli.FriendListOwner = new UUID((string)reader["ownerID"]);
fli.Friend = new UUID((string)reader["friendID"]);
fli.FriendPerms = (uint)Convert.ToInt32(reader["friendPerms"]);
while (reader.Read()) // This is not a real column in the database table, it's a joined column from the opposite record
{ fli.FriendListOwnerPerms = (uint)Convert.ToInt32(reader["ownerperms"]);
FriendListItem fli = new FriendListItem();
fli.FriendListOwner = new UUID((string) reader["ownerID"]);
fli.Friend = new UUID((string) reader["friendID"]);
fli.FriendPerms = (uint) Convert.ToInt32(reader["friendPerms"]);
// This is not a real column in the database table, it's a joined column from the opposite record Lfli.Add(fli);
fli.FriendListOwnerPerms = (uint) Convert.ToInt32(reader["ownerperms"]); }
}
Lfli.Add(fli); }
} }
reader.Dispose();
result.Dispose();
} }
catch (Exception e) catch (Exception e)
{ {
dbm.Manager.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString());
return Lfli; return Lfli;
} }
finally
{
dbm.Release();
}
return Lfli; return Lfli;
} }
override public Dictionary<UUID, FriendRegionInfo> GetFriendRegionInfos (List<UUID> uuids) override public Dictionary<UUID, FriendRegionInfo> GetFriendRegionInfos (List<UUID> uuids)
{ {
MySQLSuperManager dbm = GetLockedConnection("GetFriendRegionInfos");
Dictionary<UUID, FriendRegionInfo> infos = new Dictionary<UUID,FriendRegionInfo>(); Dictionary<UUID, FriendRegionInfo> infos = new Dictionary<UUID,FriendRegionInfo>();
try try
{ {
foreach (UUID uuid in uuids) using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{ {
Dictionary<string, object> param = new Dictionary<string, object>(); dbcon.Open();
param["?uuid"] = uuid.ToString();
IDbCommand result =
dbm.Manager.Query("select agentOnline,currentHandle from " + m_agentsTableName +
" where UUID = ?uuid", param);
IDataReader reader = result.ExecuteReader(); foreach (UUID uuid in uuids)
while (reader.Read())
{ {
FriendRegionInfo fri = new FriendRegionInfo(); Dictionary<string, object> param = new Dictionary<string, object>();
fri.isOnline = (sbyte)reader["agentOnline"] != 0; param["?uuid"] = uuid.ToString();
fri.regionHandle = (ulong)reader["currentHandle"];
infos[uuid] = fri; using (IDbCommand result = m_database.Query(dbcon, "select agentOnline,currentHandle from " + m_agentsTableName +
" where UUID = ?uuid", param))
{
using (IDataReader reader = result.ExecuteReader())
{
while (reader.Read())
{
FriendRegionInfo fri = new FriendRegionInfo();
fri.isOnline = (sbyte)reader["agentOnline"] != 0;
fri.regionHandle = (ulong)reader["currentHandle"];
infos[uuid] = fri;
}
}
}
} }
reader.Dispose();
result.Dispose();
} }
} }
catch (Exception e) catch (Exception e)
{ {
m_log.Warn("[MYSQL]: Got exception on trying to find friends regions:", e); m_log.Warn("[MYSQL]: Got exception on trying to find friends regions:", e);
dbm.Manager.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString());
}
finally
{
dbm.Release();
} }
return infos; return infos;
@ -423,76 +337,73 @@ namespace OpenSim.Data.MySQL
Dictionary<string, object> param = new Dictionary<string, object>(); Dictionary<string, object> param = new Dictionary<string, object>();
param["?first"] = objAlphaNumericPattern.Replace(querysplit[0], String.Empty) + "%"; param["?first"] = objAlphaNumericPattern.Replace(querysplit[0], String.Empty) + "%";
param["?second"] = objAlphaNumericPattern.Replace(querysplit[1], String.Empty) + "%"; param["?second"] = objAlphaNumericPattern.Replace(querysplit[1], String.Empty) + "%";
MySQLSuperManager dbm = GetLockedConnection("GeneratePickerResults");
try try
{ {
IDbCommand result = using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
dbm.Manager.Query( {
dbcon.Open();
using (IDbCommand result = m_database.Query(dbcon,
"SELECT UUID,username,lastname FROM " + m_usersTableName + "SELECT UUID,username,lastname FROM " + m_usersTableName +
" WHERE username like ?first AND lastname like ?second LIMIT 100", " WHERE username like ?first AND lastname like ?second LIMIT 100",
param); param))
IDataReader reader = result.ExecuteReader(); {
using (IDataReader reader = result.ExecuteReader())
while (reader.Read()) {
{ while (reader.Read())
AvatarPickerAvatar user = new AvatarPickerAvatar(); {
user.AvatarID = new UUID((string) reader["UUID"]); AvatarPickerAvatar user = new AvatarPickerAvatar();
user.firstName = (string) reader["username"]; user.AvatarID = new UUID((string)reader["UUID"]);
user.lastName = (string) reader["lastname"]; user.firstName = (string)reader["username"];
returnlist.Add(user); user.lastName = (string)reader["lastname"];
returnlist.Add(user);
}
}
}
} }
reader.Dispose();
result.Dispose();
} }
catch (Exception e) catch (Exception e)
{ {
dbm.Manager.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString());
return returnlist; return returnlist;
} }
finally
{
dbm.Release();
}
} }
else else
{ {
MySQLSuperManager dbm = GetLockedConnection("GeneratePickerResults");
try try
{ {
Dictionary<string, object> param = new Dictionary<string, object>(); Dictionary<string, object> param = new Dictionary<string, object>();
param["?first"] = objAlphaNumericPattern.Replace(querysplit[0], String.Empty) + "%"; param["?first"] = objAlphaNumericPattern.Replace(querysplit[0], String.Empty) + "%";
IDbCommand result = using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
dbm.Manager.Query( {
dbcon.Open();
using (IDbCommand result = m_database.Query(dbcon,
"SELECT UUID,username,lastname FROM " + m_usersTableName + "SELECT UUID,username,lastname FROM " + m_usersTableName +
" WHERE username like ?first OR lastname like ?first LIMIT 100", " WHERE username like ?first OR lastname like ?first LIMIT 100",
param); param))
IDataReader reader = result.ExecuteReader(); {
using (IDataReader reader = result.ExecuteReader())
while (reader.Read()) {
{ while (reader.Read())
AvatarPickerAvatar user = new AvatarPickerAvatar(); {
user.AvatarID = new UUID((string) reader["UUID"]); AvatarPickerAvatar user = new AvatarPickerAvatar();
user.firstName = (string) reader["username"]; user.AvatarID = new UUID((string)reader["UUID"]);
user.lastName = (string) reader["lastname"]; user.firstName = (string)reader["username"];
returnlist.Add(user); user.lastName = (string)reader["lastname"];
returnlist.Add(user);
}
}
}
} }
reader.Dispose();
result.Dispose();
} }
catch (Exception e) catch (Exception e)
{ {
dbm.Manager.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString());
return returnlist; return returnlist;
} }
finally
{
dbm.Release();
}
} }
return returnlist; return returnlist;
} }
@ -504,32 +415,30 @@ namespace OpenSim.Data.MySQL
/// <returns>User profile data</returns> /// <returns>User profile data</returns>
public override UserProfileData GetUserByUUID(UUID uuid) public override UserProfileData GetUserByUUID(UUID uuid)
{ {
MySQLSuperManager dbm = GetLockedConnection("GetUserByUUID");
try try
{ {
Dictionary<string, object> param = new Dictionary<string, object>(); Dictionary<string, object> param = new Dictionary<string, object>();
param["?uuid"] = uuid.ToString(); param["?uuid"] = uuid.ToString();
IDbCommand result = dbm.Manager.Query("SELECT * FROM " + m_usersTableName + " WHERE UUID = ?uuid", param); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
IDataReader reader = result.ExecuteReader(); {
dbcon.Open();
UserProfileData row = dbm.Manager.readUserRow(reader); using (IDbCommand result = m_database.Query(dbcon, "SELECT * FROM " + m_usersTableName + " WHERE UUID = ?uuid", param))
{
reader.Dispose(); using (IDataReader reader = result.ExecuteReader())
result.Dispose(); {
UserProfileData row = m_database.readUserRow(reader);
return row; return row;
}
}
}
} }
catch (Exception e) catch (Exception e)
{ {
dbm.Manager.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString());
return null; return null;
} }
finally
{
dbm.Release();
}
} }
/// <summary> /// <summary>
@ -565,25 +474,18 @@ namespace OpenSim.Data.MySQL
param["?UUID"] = AgentID.ToString(); param["?UUID"] = AgentID.ToString();
param["?webLoginKey"] = WebLoginKey.ToString(); param["?webLoginKey"] = WebLoginKey.ToString();
MySQLSuperManager dbm = GetLockedConnection("StoreWebLoginKey");
try try
{ {
dbm.Manager.ExecuteParameterizedSql( m_database.ExecuteParameterizedSql(
"update " + m_usersTableName + " SET webLoginKey = ?webLoginKey " + "update " + m_usersTableName + " SET webLoginKey = ?webLoginKey " +
"where UUID = ?UUID", "where UUID = ?UUID",
param); param);
} }
catch (Exception e) catch (Exception e)
{ {
dbm.Manager.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString());
return; return;
} }
finally
{
dbm.Release();
}
} }
/// <summary> /// <summary>
@ -593,34 +495,30 @@ namespace OpenSim.Data.MySQL
/// <returns>The users session</returns> /// <returns>The users session</returns>
public override UserAgentData GetAgentByUUID(UUID uuid) public override UserAgentData GetAgentByUUID(UUID uuid)
{ {
MySQLSuperManager dbm = GetLockedConnection("GetAgentByUUID");
try try
{ {
Dictionary<string, object> param = new Dictionary<string, object>(); Dictionary<string, object> param = new Dictionary<string, object>();
param["?uuid"] = uuid.ToString(); param["?uuid"] = uuid.ToString();
IDbCommand result = dbm.Manager.Query("SELECT * FROM " + m_agentsTableName + " WHERE UUID = ?uuid", using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
param); {
IDataReader reader = result.ExecuteReader(); dbcon.Open();
UserAgentData row = dbm.Manager.readAgentRow(reader); using (IDbCommand result = m_database.Query(dbcon, "SELECT * FROM " + m_agentsTableName + " WHERE UUID = ?uuid", param))
{
reader.Dispose(); using (IDataReader reader = result.ExecuteReader())
result.Dispose(); {
UserAgentData row = m_database.readAgentRow(reader);
return row; return row;
}
}
}
} }
catch (Exception e) catch (Exception e)
{ {
dbm.Manager.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString());
return null; return null;
} }
finally
{
dbm.Release();
}
} }
/// <summary> /// <summary>
@ -634,27 +532,22 @@ namespace OpenSim.Data.MySQL
{ {
return; return;
} }
MySQLSuperManager dbm = GetLockedConnection("AddNewUserProfile");
try try
{ {
dbm.Manager.insertUserRow(user.ID, user.FirstName, user.SurName, user.Email, user.PasswordHash, user.PasswordSalt, m_database.insertUserRow(
user.HomeRegion, user.HomeRegionID, user.HomeLocation.X, user.HomeLocation.Y, user.ID, user.FirstName, user.SurName, user.Email, user.PasswordHash, user.PasswordSalt,
user.HomeLocation.Z, user.HomeRegion, user.HomeRegionID, user.HomeLocation.X, user.HomeLocation.Y,
user.HomeLookAt.X, user.HomeLookAt.Y, user.HomeLookAt.Z, user.Created, user.HomeLocation.Z,
user.LastLogin, user.UserInventoryURI, user.UserAssetURI, user.HomeLookAt.X, user.HomeLookAt.Y, user.HomeLookAt.Z, user.Created,
user.CanDoMask, user.WantDoMask, user.LastLogin, user.UserInventoryURI, user.UserAssetURI,
user.AboutText, user.FirstLifeAboutText, user.Image, user.CanDoMask, user.WantDoMask,
user.FirstLifeImage, user.WebLoginKey, user.UserFlags, user.GodLevel, user.CustomType, user.Partner); user.AboutText, user.FirstLifeAboutText, user.Image,
user.FirstLifeImage, user.WebLoginKey, user.UserFlags, user.GodLevel, user.CustomType, user.Partner);
} }
catch (Exception e) catch (Exception e)
{ {
dbm.Manager.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString());
}
finally
{
dbm.Release();
} }
} }
@ -668,19 +561,13 @@ namespace OpenSim.Data.MySQL
if (agent.ProfileID == zero || agent.SessionID == zero) if (agent.ProfileID == zero || agent.SessionID == zero)
return; return;
MySQLSuperManager dbm = GetLockedConnection("AddNewUserAgent");
try try
{ {
dbm.Manager.insertAgentRow(agent); m_database.insertAgentRow(agent);
} }
catch (Exception e) catch (Exception e)
{ {
dbm.Manager.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString());
}
finally
{
dbm.Release();
} }
} }
@ -690,24 +577,24 @@ namespace OpenSim.Data.MySQL
/// <param name="user">The profile data to use to update the DB</param> /// <param name="user">The profile data to use to update the DB</param>
public override bool UpdateUserProfile(UserProfileData user) public override bool UpdateUserProfile(UserProfileData user)
{ {
MySQLSuperManager dbm = GetLockedConnection("UpdateUserProfile");
try try
{ {
dbm.Manager.updateUserRow(user.ID, user.FirstName, user.SurName, user.Email, user.PasswordHash, user.PasswordSalt, m_database.updateUserRow(
user.HomeRegion, user.HomeRegionID, user.HomeLocation.X, user.HomeLocation.Y, user.ID, user.FirstName, user.SurName, user.Email, user.PasswordHash, user.PasswordSalt,
user.HomeLocation.Z, user.HomeLookAt.X, user.HomeRegion, user.HomeRegionID, user.HomeLocation.X, user.HomeLocation.Y,
user.HomeLookAt.Y, user.HomeLookAt.Z, user.Created, user.LastLogin, user.HomeLocation.Z, user.HomeLookAt.X,
user.UserInventoryURI, user.HomeLookAt.Y, user.HomeLookAt.Z, user.Created, user.LastLogin,
user.UserAssetURI, user.CanDoMask, user.WantDoMask, user.AboutText, user.UserInventoryURI,
user.FirstLifeAboutText, user.Image, user.FirstLifeImage, user.WebLoginKey, user.UserAssetURI, user.CanDoMask, user.WantDoMask, user.AboutText,
user.UserFlags, user.GodLevel, user.CustomType, user.Partner); user.FirstLifeAboutText, user.Image, user.FirstLifeImage, user.WebLoginKey,
} user.UserFlags, user.GodLevel, user.CustomType, user.Partner);
finally
{
dbm.Release();
}
return true; return true;
}
catch
{
return false;
}
} }
/// <summary> /// <summary>
@ -742,41 +629,40 @@ namespace OpenSim.Data.MySQL
/// </summary> /// </summary>
public override AvatarAppearance GetUserAppearance(UUID user) public override AvatarAppearance GetUserAppearance(UUID user)
{ {
MySQLSuperManager dbm = GetLockedConnection("GetUserAppearance");
try try
{ {
Dictionary<string, object> param = new Dictionary<string, object>(); Dictionary<string, object> param = new Dictionary<string, object>();
param["?owner"] = user.ToString(); param["?owner"] = user.ToString();
IDbCommand result = dbm.Manager.Query( using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
"SELECT * FROM " + m_appearanceTableName + " WHERE owner = ?owner", param);
IDataReader reader = result.ExecuteReader();
AvatarAppearance appearance = dbm.Manager.readAppearanceRow(reader);
reader.Dispose();
result.Dispose();
if (null == appearance)
{ {
m_log.WarnFormat("[USER DB] No appearance found for user {0}", user.ToString()); dbcon.Open();
return null;
}
appearance.SetAttachments(GetUserAttachments(user));
return appearance; using (IDbCommand result = m_database.Query(dbcon, "SELECT * FROM " + m_appearanceTableName + " WHERE owner = ?owner", param))
{
using (IDataReader reader = result.ExecuteReader())
{
AvatarAppearance appearance = m_database.readAppearanceRow(reader);
if (appearance == null)
{
m_log.WarnFormat("[USER DB] No appearance found for user {0}", user.ToString());
return null;
}
else
{
appearance.SetAttachments(GetUserAttachments(user));
return appearance;
}
}
}
}
} }
catch (Exception e) catch (Exception e)
{ {
dbm.Manager.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString());
return null; return null;
} }
finally
{
dbm.Release();
}
} }
/// <summary> /// <summary>
@ -787,22 +673,16 @@ namespace OpenSim.Data.MySQL
// override // override
public override void UpdateUserAppearance(UUID user, AvatarAppearance appearance) public override void UpdateUserAppearance(UUID user, AvatarAppearance appearance)
{ {
MySQLSuperManager dbm = GetLockedConnection("UpdateUserAppearance");
try try
{ {
appearance.Owner = user; appearance.Owner = user;
dbm.Manager.insertAppearanceRow(appearance); m_database.insertAppearanceRow(appearance);
UpdateUserAttachments(user, appearance.GetAttachments()); UpdateUserAttachments(user, appearance.GetAttachments());
} }
catch (Exception e) catch (Exception e)
{ {
dbm.Manager.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString());
}
finally
{
dbm.Release();
} }
} }
@ -829,43 +709,33 @@ namespace OpenSim.Data.MySQL
Dictionary<string, object> param = new Dictionary<string, object>(); Dictionary<string, object> param = new Dictionary<string, object>();
param["?uuid"] = agentID.ToString(); param["?uuid"] = agentID.ToString();
MySQLSuperManager dbm = GetLockedConnection("GetUserAttachments");
try try
{ {
IDbCommand result = dbm.Manager.Query( using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
"SELECT attachpoint, item, asset from " + m_attachmentsTableName + " WHERE UUID = ?uuid", param); {
IDataReader reader = result.ExecuteReader(); dbcon.Open();
Hashtable ret = dbm.Manager.readAttachments(reader); using (IDbCommand result = m_database.Query(dbcon,
"SELECT attachpoint, item, asset from " + m_attachmentsTableName + " WHERE UUID = ?uuid", param))
reader.Dispose(); {
result.Dispose(); using (IDataReader reader = result.ExecuteReader())
return ret; {
Hashtable ret = m_database.readAttachments(reader);
return ret;
}
}
}
} }
catch (Exception e) catch (Exception e)
{ {
dbm.Manager.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString());
return null; return null;
} }
finally
{
dbm.Release();
}
} }
public void UpdateUserAttachments(UUID agentID, Hashtable data) public void UpdateUserAttachments(UUID agentID, Hashtable data)
{ {
MySQLSuperManager dbm = GetLockedConnection("UpdateUserAttachments"); m_database.writeAttachments(agentID, data);
try
{
dbm.Manager.writeAttachments(agentID, data);
}
finally
{
dbm.Release();
}
} }
public override void ResetAttachments(UUID userID) public override void ResetAttachments(UUID userID)
@ -873,19 +743,10 @@ namespace OpenSim.Data.MySQL
Dictionary<string, string> param = new Dictionary<string, string>(); Dictionary<string, string> param = new Dictionary<string, string>();
param["?uuid"] = userID.ToString(); param["?uuid"] = userID.ToString();
MySQLSuperManager dbm = GetLockedConnection("ResetAttachments"); m_database.ExecuteParameterizedSql(
"UPDATE " + m_attachmentsTableName +
try " SET asset = '00000000-0000-0000-0000-000000000000' WHERE UUID = ?uuid",
{ param);
dbm.Manager.ExecuteParameterizedSql(
"UPDATE " + m_attachmentsTableName +
" SET asset = '00000000-0000-0000-0000-000000000000' WHERE UUID = ?uuid",
param);
}
finally
{
dbm.Release();
}
} }
public override void LogoutUsers(UUID regionID) public override void LogoutUsers(UUID regionID)
@ -893,25 +754,18 @@ namespace OpenSim.Data.MySQL
Dictionary<string, string> param = new Dictionary<string, string>(); Dictionary<string, string> param = new Dictionary<string, string>();
param["?regionID"] = regionID.ToString(); param["?regionID"] = regionID.ToString();
MySQLSuperManager dbm = GetLockedConnection("LogoutUsers");
try try
{ {
dbm.Manager.ExecuteParameterizedSql( m_database.ExecuteParameterizedSql(
"update " + m_agentsTableName + " SET agentOnline = 0 " + "update " + m_agentsTableName + " SET agentOnline = 0 " +
"where currentRegion = ?regionID", "where currentRegion = ?regionID",
param); param);
} }
catch (Exception e) catch (Exception e)
{ {
dbm.Manager.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString());
return; return;
} }
finally
{
dbm.Release();
}
} }
} }
} }

View File

@ -110,47 +110,58 @@ namespace OpenSim.Data.MySQL
public bool MoveItem(string id, string newParent) public bool MoveItem(string id, string newParent)
{ {
MySqlCommand cmd = new MySqlCommand(); using (MySqlCommand cmd = new MySqlCommand())
{
cmd.CommandText = String.Format("update {0} set parentFolderID = ?ParentFolderID where inventoryID = ?InventoryID", m_Realm); cmd.CommandText = String.Format("update {0} set parentFolderID = ?ParentFolderID where inventoryID = ?InventoryID", m_Realm);
cmd.Parameters.AddWithValue("?ParentFolderID", newParent); cmd.Parameters.AddWithValue("?ParentFolderID", newParent);
cmd.Parameters.AddWithValue("?InventoryID", id); cmd.Parameters.AddWithValue("?InventoryID", id);
return ExecuteNonQuery(cmd) == 0 ? false : true; return ExecuteNonQuery(cmd) == 0 ? false : true;
}
} }
public XInventoryItem[] GetActiveGestures(UUID principalID) public XInventoryItem[] GetActiveGestures(UUID principalID)
{ {
MySqlCommand cmd = new MySqlCommand(); using (MySqlCommand cmd = new MySqlCommand())
cmd.CommandText = String.Format("select * from inventoryitems where avatarId = ?uuid and assetType = ?type and flags = 1", m_Realm); {
cmd.CommandText = String.Format("select * from inventoryitems where avatarId = ?uuid and assetType = ?type and flags = 1", m_Realm);
cmd.Parameters.AddWithValue("?uuid", principalID.ToString()); cmd.Parameters.AddWithValue("?uuid", principalID.ToString());
cmd.Parameters.AddWithValue("?type", (int)AssetType.Gesture); cmd.Parameters.AddWithValue("?type", (int)AssetType.Gesture);
return DoQuery(cmd); return DoQuery(cmd);
}
} }
public int GetAssetPermissions(UUID principalID, UUID assetID) public int GetAssetPermissions(UUID principalID, UUID assetID)
{ {
MySqlCommand cmd = new MySqlCommand(); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
cmd.CommandText = String.Format("select bit_or(inventoryCurrentPermissions) as inventoryCurrentPermissions from inventoryitems where avatarID = ?PrincipalID and assetID = ?AssetID group by assetID", m_Realm);
cmd.Parameters.AddWithValue("?PrincipalID", principalID.ToString());
cmd.Parameters.AddWithValue("?AssetID", assetID.ToString());
IDataReader reader = ExecuteReader(cmd);
int perms = 0;
if (reader.Read())
{ {
perms = Convert.ToInt32(reader["inventoryCurrentPermissions"]); dbcon.Open();
using (MySqlCommand cmd = new MySqlCommand())
{
cmd.Connection = dbcon;
cmd.CommandText = String.Format("select bit_or(inventoryCurrentPermissions) as inventoryCurrentPermissions from inventoryitems where avatarID = ?PrincipalID and assetID = ?AssetID group by assetID", m_Realm);
cmd.Parameters.AddWithValue("?PrincipalID", principalID.ToString());
cmd.Parameters.AddWithValue("?AssetID", assetID.ToString());
using (IDataReader reader = cmd.ExecuteReader())
{
int perms = 0;
if (reader.Read())
{
perms = Convert.ToInt32(reader["inventoryCurrentPermissions"]);
}
return perms;
}
}
} }
reader.Close();
CloseReaderCommand(cmd);
return perms;
} }
} }
} }

View File

@ -31,6 +31,7 @@ using OpenSim.Data.Tests;
using log4net; using log4net;
using System.Reflection; using System.Reflection;
using OpenSim.Tests.Common; using OpenSim.Tests.Common;
using MySql.Data.MySqlClient;
namespace OpenSim.Data.MySQL.Tests namespace OpenSim.Data.MySQL.Tests
{ {
@ -65,9 +66,13 @@ namespace OpenSim.Data.MySQL.Tests
// This actually does the roll forward assembly stuff // This actually does the roll forward assembly stuff
Assembly assem = GetType().Assembly; Assembly assem = GetType().Assembly;
Migration m = new Migration(database.Connection, assem, "GridStore");
m.Update(); using (MySqlConnection dbcon = new MySqlConnection(connect))
{
dbcon.Open();
Migration m = new Migration(dbcon, assem, "AssetStore");
m.Update();
}
} }
[TestFixtureTearDown] [TestFixtureTearDown]

View File

@ -41,7 +41,7 @@ namespace OpenSim.Data.SQLite
/// </summary> /// </summary>
public class SQLiteAssetData : AssetDataBase public class SQLiteAssetData : AssetDataBase
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private const string SelectAssetSQL = "select * from assets where UUID=:UUID"; private const string SelectAssetSQL = "select * from assets where UUID=:UUID";
private const string SelectAssetMetadataSQL = "select Name, Description, Type, Temporary, UUID from assets limit :start, :count"; private const string SelectAssetMetadataSQL = "select Name, Description, Type, Temporary, UUID from assets limit :start, :count";

View File

@ -39,9 +39,7 @@ namespace OpenSim.Data.SQLite
{ {
public class SQLiteGenericTableHandler<T> : SQLiteFramework where T: class, new() public class SQLiteGenericTableHandler<T> : SQLiteFramework where T: class, new()
{ {
private static readonly ILog m_log = // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
protected Dictionary<string, FieldInfo> m_Fields = protected Dictionary<string, FieldInfo> m_Fields =
new Dictionary<string, FieldInfo>(); new Dictionary<string, FieldInfo>();

View File

@ -41,8 +41,7 @@ namespace OpenSim.Data.SQLite
/// </summary> /// </summary>
public class SQLiteXInventoryData : IXInventoryData public class SQLiteXInventoryData : IXInventoryData
{ {
private static readonly ILog m_log = LogManager.GetLogger( // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
MethodBase.GetCurrentMethod().DeclaringType);
private SQLiteGenericTableHandler<XInventoryFolder> m_Folders; private SQLiteGenericTableHandler<XInventoryFolder> m_Folders;
private SqliteItemHandler m_Items; private SqliteItemHandler m_Items;

View File

@ -0,0 +1,755 @@
/*
* 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.IO;
using System.Net;
using System.Reflection;
using System.Text;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
using GridRegion = OpenSim.Services.Interfaces.GridRegion;
using log4net;
namespace OpenSim.Framework.Communications.Clients
{
public class RegionClient
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public bool DoCreateChildAgentCall(GridRegion region, AgentCircuitData aCircuit, string authKey, uint teleportFlags, out string reason)
{
reason = String.Empty;
// Eventually, we want to use a caps url instead of the agentID
string uri = string.Empty;
try
{
uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/agent/" + aCircuit.AgentID + "/";
}
catch (Exception e)
{
m_log.Debug("[REST COMMS]: Unable to resolve external endpoint on agent create. Reason: " + e.Message);
reason = e.Message;
return false;
}
//Console.WriteLine(" >>> DoCreateChildAgentCall <<< " + uri);
HttpWebRequest AgentCreateRequest = (HttpWebRequest)WebRequest.Create(uri);
AgentCreateRequest.Method = "POST";
AgentCreateRequest.ContentType = "application/json";
AgentCreateRequest.Timeout = 10000;
//AgentCreateRequest.KeepAlive = false;
AgentCreateRequest.Headers.Add("Authorization", authKey);
// Fill it in
OSDMap args = null;
try
{
args = aCircuit.PackAgentCircuitData();
}
catch (Exception e)
{
m_log.Debug("[REST COMMS]: PackAgentCircuitData failed with exception: " + e.Message);
}
// Add the regionhandle of the destination region
ulong regionHandle = GetRegionHandle(region.RegionHandle);
args["destination_handle"] = OSD.FromString(regionHandle.ToString());
args["teleport_flags"] = OSD.FromString(teleportFlags.ToString());
string strBuffer = "";
byte[] buffer = new byte[1];
try
{
strBuffer = OSDParser.SerializeJsonString(args);
Encoding str = Util.UTF8;
buffer = str.GetBytes(strBuffer);
}
catch (Exception e)
{
m_log.WarnFormat("[REST COMMS]: Exception thrown on serialization of ChildCreate: {0}", e.Message);
// ignore. buffer will be empty, caller should check.
}
Stream os = null;
try
{ // send the Post
AgentCreateRequest.ContentLength = buffer.Length; //Count bytes to send
os = AgentCreateRequest.GetRequestStream();
os.Write(buffer, 0, strBuffer.Length); //Send it
//m_log.InfoFormat("[REST COMMS]: Posted CreateChildAgent request to remote sim {0}", uri);
}
//catch (WebException ex)
catch
{
//m_log.InfoFormat("[REST COMMS]: Bad send on ChildAgentUpdate {0}", ex.Message);
reason = "cannot contact remote region";
return false;
}
finally
{
if (os != null)
os.Close();
}
// Let's wait for the response
//m_log.Info("[REST COMMS]: Waiting for a reply after DoCreateChildAgentCall");
WebResponse webResponse = null;
StreamReader sr = null;
try
{
webResponse = AgentCreateRequest.GetResponse();
if (webResponse == null)
{
m_log.Info("[REST COMMS]: Null reply on DoCreateChildAgentCall post");
}
else
{
sr = new StreamReader(webResponse.GetResponseStream());
string response = sr.ReadToEnd().Trim();
m_log.InfoFormat("[REST COMMS]: DoCreateChildAgentCall reply was {0} ", response);
if (!String.IsNullOrEmpty(response))
{
try
{
// we assume we got an OSDMap back
OSDMap r = GetOSDMap(response);
bool success = r["success"].AsBoolean();
reason = r["reason"].AsString();
return success;
}
catch (NullReferenceException e)
{
m_log.InfoFormat("[REST COMMS]: exception on reply of DoCreateChildAgentCall {0}", e.Message);
// check for old style response
if (response.ToLower().StartsWith("true"))
return true;
return false;
}
}
}
}
catch (WebException ex)
{
m_log.InfoFormat("[REST COMMS]: exception on reply of DoCreateChildAgentCall {0}", ex.Message);
// ignore, really
}
finally
{
if (sr != null)
sr.Close();
}
return true;
}
public bool DoChildAgentUpdateCall(GridRegion region, IAgentData cAgentData)
{
// Eventually, we want to use a caps url instead of the agentID
string uri = string.Empty;
try
{
uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/agent/" + cAgentData.AgentID + "/";
}
catch (Exception e)
{
m_log.Debug("[REST COMMS]: Unable to resolve external endpoint on agent update. Reason: " + e.Message);
return false;
}
//Console.WriteLine(" >>> DoChildAgentUpdateCall <<< " + uri);
HttpWebRequest ChildUpdateRequest = (HttpWebRequest)WebRequest.Create(uri);
ChildUpdateRequest.Method = "PUT";
ChildUpdateRequest.ContentType = "application/json";
ChildUpdateRequest.Timeout = 10000;
//ChildUpdateRequest.KeepAlive = false;
// Fill it in
OSDMap args = null;
try
{
args = cAgentData.Pack();
}
catch (Exception e)
{
m_log.Debug("[REST COMMS]: PackUpdateMessage failed with exception: " + e.Message);
}
// Add the regionhandle of the destination region
ulong regionHandle = GetRegionHandle(region.RegionHandle);
args["destination_handle"] = OSD.FromString(regionHandle.ToString());
string strBuffer = "";
byte[] buffer = new byte[1];
try
{
strBuffer = OSDParser.SerializeJsonString(args);
Encoding str = Util.UTF8;
buffer = str.GetBytes(strBuffer);
}
catch (Exception e)
{
m_log.WarnFormat("[REST COMMS]: Exception thrown on serialization of ChildUpdate: {0}", e.Message);
// ignore. buffer will be empty, caller should check.
}
Stream os = null;
try
{ // send the Post
ChildUpdateRequest.ContentLength = buffer.Length; //Count bytes to send
os = ChildUpdateRequest.GetRequestStream();
os.Write(buffer, 0, strBuffer.Length); //Send it
//m_log.InfoFormat("[REST COMMS]: Posted ChildAgentUpdate request to remote sim {0}", uri);
}
//catch (WebException ex)
catch
{
//m_log.InfoFormat("[REST COMMS]: Bad send on ChildAgentUpdate {0}", ex.Message);
return false;
}
finally
{
if (os != null)
os.Close();
}
// Let's wait for the response
//m_log.Info("[REST COMMS]: Waiting for a reply after ChildAgentUpdate");
WebResponse webResponse = null;
StreamReader sr = null;
try
{
webResponse = ChildUpdateRequest.GetResponse();
if (webResponse == null)
{
m_log.Info("[REST COMMS]: Null reply on ChilAgentUpdate post");
}
sr = new StreamReader(webResponse.GetResponseStream());
//reply = sr.ReadToEnd().Trim();
sr.ReadToEnd().Trim();
sr.Close();
//m_log.InfoFormat("[REST COMMS]: ChilAgentUpdate reply was {0} ", reply);
}
catch (WebException ex)
{
m_log.InfoFormat("[REST COMMS]: exception on reply of ChilAgentUpdate {0}", ex.Message);
// ignore, really
}
finally
{
if (sr != null)
sr.Close();
}
return true;
}
public bool DoRetrieveRootAgentCall(GridRegion region, UUID id, out IAgentData agent)
{
agent = null;
// Eventually, we want to use a caps url instead of the agentID
string uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/agent/" + id + "/" + region.RegionHandle.ToString() + "/";
//Console.WriteLine(" >>> DoRetrieveRootAgentCall <<< " + uri);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "GET";
request.Timeout = 10000;
//request.Headers.Add("authorization", ""); // coming soon
HttpWebResponse webResponse = null;
string reply = string.Empty;
StreamReader sr = null;
try
{
webResponse = (HttpWebResponse)request.GetResponse();
if (webResponse == null)
{
m_log.Info("[REST COMMS]: Null reply on agent get ");
}
sr = new StreamReader(webResponse.GetResponseStream());
reply = sr.ReadToEnd().Trim();
//Console.WriteLine("[REST COMMS]: ChilAgentUpdate reply was " + reply);
}
catch (WebException ex)
{
m_log.InfoFormat("[REST COMMS]: exception on reply of agent get {0}", ex.Message);
// ignore, really
return false;
}
finally
{
if (sr != null)
sr.Close();
}
if (webResponse.StatusCode == HttpStatusCode.OK)
{
// we know it's jason
OSDMap args = GetOSDMap(reply);
if (args == null)
{
//Console.WriteLine("[REST COMMS]: Error getting OSDMap from reply");
return false;
}
agent = new CompleteAgentData();
agent.Unpack(args);
return true;
}
//Console.WriteLine("[REST COMMS]: DoRetrieveRootAgentCall returned status " + webResponse.StatusCode);
return false;
}
public bool DoReleaseAgentCall(ulong regionHandle, UUID id, string uri)
{
//m_log.Debug(" >>> DoReleaseAgentCall <<< " + uri);
WebRequest request = WebRequest.Create(uri);
request.Method = "DELETE";
request.Timeout = 10000;
StreamReader sr = null;
try
{
WebResponse webResponse = request.GetResponse();
if (webResponse == null)
{
m_log.Info("[REST COMMS]: Null reply on agent delete ");
}
sr = new StreamReader(webResponse.GetResponseStream());
//reply = sr.ReadToEnd().Trim();
sr.ReadToEnd().Trim();
sr.Close();
//m_log.InfoFormat("[REST COMMS]: ChilAgentUpdate reply was {0} ", reply);
}
catch (WebException ex)
{
m_log.InfoFormat("[REST COMMS]: exception on reply of agent delete {0}", ex.Message);
// ignore, really
}
finally
{
if (sr != null)
sr.Close();
}
return true;
}
public bool DoCloseAgentCall(GridRegion region, UUID id)
{
string uri = string.Empty;
try
{
uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/agent/" + id + "/" + region.RegionHandle.ToString() + "/";
}
catch (Exception e)
{
m_log.Debug("[REST COMMS]: Unable to resolve external endpoint on agent close. Reason: " + e.Message);
return false;
}
//Console.WriteLine(" >>> DoCloseAgentCall <<< " + uri);
WebRequest request = WebRequest.Create(uri);
request.Method = "DELETE";
request.Timeout = 10000;
StreamReader sr = null;
try
{
WebResponse webResponse = request.GetResponse();
if (webResponse == null)
{
m_log.Info("[REST COMMS]: Null reply on agent delete ");
}
sr = new StreamReader(webResponse.GetResponseStream());
//reply = sr.ReadToEnd().Trim();
sr.ReadToEnd().Trim();
sr.Close();
//m_log.InfoFormat("[REST COMMS]: ChilAgentUpdate reply was {0} ", reply);
}
catch (WebException ex)
{
m_log.InfoFormat("[REST COMMS]: exception on reply of agent delete {0}", ex.Message);
// ignore, really
}
finally
{
if (sr != null)
sr.Close();
}
return true;
}
public bool DoCreateObjectCall(GridRegion region, ISceneObject sog, string sogXml2, bool allowScriptCrossing)
{
ulong regionHandle = GetRegionHandle(region.RegionHandle);
string uri
= "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort
+ "/object/" + sog.UUID + "/" + regionHandle.ToString() + "/";
//m_log.Debug(" >>> DoCreateChildAgentCall <<< " + uri);
WebRequest ObjectCreateRequest = WebRequest.Create(uri);
ObjectCreateRequest.Method = "POST";
ObjectCreateRequest.ContentType = "application/json";
ObjectCreateRequest.Timeout = 10000;
OSDMap args = new OSDMap(2);
args["sog"] = OSD.FromString(sogXml2);
args["extra"] = OSD.FromString(sog.ExtraToXmlString());
if (allowScriptCrossing)
{
string state = sog.GetStateSnapshot();
if (state.Length > 0)
args["state"] = OSD.FromString(state);
}
string strBuffer = "";
byte[] buffer = new byte[1];
try
{
strBuffer = OSDParser.SerializeJsonString(args);
Encoding str = Util.UTF8;
buffer = str.GetBytes(strBuffer);
}
catch (Exception e)
{
m_log.WarnFormat("[REST COMMS]: Exception thrown on serialization of CreateObject: {0}", e.Message);
// ignore. buffer will be empty, caller should check.
}
Stream os = null;
try
{ // send the Post
ObjectCreateRequest.ContentLength = buffer.Length; //Count bytes to send
os = ObjectCreateRequest.GetRequestStream();
os.Write(buffer, 0, strBuffer.Length); //Send it
m_log.InfoFormat("[REST COMMS]: Posted ChildAgentUpdate request to remote sim {0}", uri);
}
//catch (WebException ex)
catch
{
// m_log.InfoFormat("[REST COMMS]: Bad send on CreateObject {0}", ex.Message);
return false;
}
finally
{
if (os != null)
os.Close();
}
// Let's wait for the response
//m_log.Info("[REST COMMS]: Waiting for a reply after DoCreateChildAgentCall");
StreamReader sr = null;
try
{
WebResponse webResponse = ObjectCreateRequest.GetResponse();
if (webResponse == null)
{
m_log.Info("[REST COMMS]: Null reply on DoCreateObjectCall post");
}
sr = new StreamReader(webResponse.GetResponseStream());
//reply = sr.ReadToEnd().Trim();
sr.ReadToEnd().Trim();
//m_log.InfoFormat("[REST COMMS]: DoCreateChildAgentCall reply was {0} ", reply);
}
catch (WebException ex)
{
m_log.InfoFormat("[REST COMMS]: exception on reply of DoCreateObjectCall {0}", ex.Message);
// ignore, really
}
finally
{
if (sr != null)
sr.Close();
}
return true;
}
public bool DoCreateObjectCall(GridRegion region, UUID userID, UUID itemID)
{
ulong regionHandle = GetRegionHandle(region.RegionHandle);
string uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/object/" + UUID.Zero + "/" + regionHandle.ToString() + "/";
//m_log.Debug(" >>> DoCreateChildAgentCall <<< " + uri);
WebRequest ObjectCreateRequest = WebRequest.Create(uri);
ObjectCreateRequest.Method = "PUT";
ObjectCreateRequest.ContentType = "application/json";
ObjectCreateRequest.Timeout = 10000;
OSDMap args = new OSDMap(2);
args["userid"] = OSD.FromUUID(userID);
args["itemid"] = OSD.FromUUID(itemID);
string strBuffer = "";
byte[] buffer = new byte[1];
try
{
strBuffer = OSDParser.SerializeJsonString(args);
Encoding str = Util.UTF8;
buffer = str.GetBytes(strBuffer);
}
catch (Exception e)
{
m_log.WarnFormat("[REST COMMS]: Exception thrown on serialization of CreateObject: {0}", e.Message);
// ignore. buffer will be empty, caller should check.
}
Stream os = null;
try
{ // send the Post
ObjectCreateRequest.ContentLength = buffer.Length; //Count bytes to send
os = ObjectCreateRequest.GetRequestStream();
os.Write(buffer, 0, strBuffer.Length); //Send it
//m_log.InfoFormat("[REST COMMS]: Posted CreateObject request to remote sim {0}", uri);
}
//catch (WebException ex)
catch
{
// m_log.InfoFormat("[REST COMMS]: Bad send on CreateObject {0}", ex.Message);
return false;
}
finally
{
if (os != null)
os.Close();
}
// Let's wait for the response
//m_log.Info("[REST COMMS]: Waiting for a reply after DoCreateChildAgentCall");
StreamReader sr = null;
try
{
WebResponse webResponse = ObjectCreateRequest.GetResponse();
if (webResponse == null)
{
m_log.Info("[REST COMMS]: Null reply on DoCreateObjectCall post");
}
sr = new StreamReader(webResponse.GetResponseStream());
sr.ReadToEnd().Trim();
sr.ReadToEnd().Trim();
//m_log.InfoFormat("[REST COMMS]: DoCreateChildAgentCall reply was {0} ", reply);
}
catch (WebException ex)
{
m_log.InfoFormat("[REST COMMS]: exception on reply of DoCreateObjectCall {0}", ex.Message);
// ignore, really
}
finally
{
if (sr != null)
sr.Close();
}
return true;
}
public bool DoHelloNeighbourCall(RegionInfo region, RegionInfo thisRegion)
{
string uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/region/" + thisRegion.RegionID + "/";
//m_log.Debug(" >>> DoHelloNeighbourCall <<< " + uri);
WebRequest HelloNeighbourRequest = WebRequest.Create(uri);
HelloNeighbourRequest.Method = "POST";
HelloNeighbourRequest.ContentType = "application/json";
HelloNeighbourRequest.Timeout = 10000;
// Fill it in
OSDMap args = null;
try
{
args = thisRegion.PackRegionInfoData();
}
catch (Exception e)
{
m_log.Debug("[REST COMMS]: PackRegionInfoData failed with exception: " + e.Message);
}
// Add the regionhandle of the destination region
ulong regionHandle = GetRegionHandle(region.RegionHandle);
args["destination_handle"] = OSD.FromString(regionHandle.ToString());
string strBuffer = "";
byte[] buffer = new byte[1];
try
{
strBuffer = OSDParser.SerializeJsonString(args);
Encoding str = Util.UTF8;
buffer = str.GetBytes(strBuffer);
}
catch (Exception e)
{
m_log.WarnFormat("[REST COMMS]: Exception thrown on serialization of HelloNeighbour: {0}", e.Message);
// ignore. buffer will be empty, caller should check.
}
Stream os = null;
try
{ // send the Post
HelloNeighbourRequest.ContentLength = buffer.Length; //Count bytes to send
os = HelloNeighbourRequest.GetRequestStream();
os.Write(buffer, 0, strBuffer.Length); //Send it
//m_log.InfoFormat("[REST COMMS]: Posted HelloNeighbour request to remote sim {0}", uri);
}
//catch (WebException ex)
catch
{
//m_log.InfoFormat("[REST COMMS]: Bad send on HelloNeighbour {0}", ex.Message);
return false;
}
finally
{
if (os != null)
os.Close();
}
// Let's wait for the response
//m_log.Info("[REST COMMS]: Waiting for a reply after DoHelloNeighbourCall");
StreamReader sr = null;
try
{
WebResponse webResponse = HelloNeighbourRequest.GetResponse();
if (webResponse == null)
{
m_log.Info("[REST COMMS]: Null reply on DoHelloNeighbourCall post");
}
sr = new StreamReader(webResponse.GetResponseStream());
//reply = sr.ReadToEnd().Trim();
sr.ReadToEnd().Trim();
//m_log.InfoFormat("[REST COMMS]: DoHelloNeighbourCall reply was {0} ", reply);
}
catch (WebException ex)
{
m_log.InfoFormat("[REST COMMS]: exception on reply of DoHelloNeighbourCall {0}", ex.Message);
// ignore, really
}
finally
{
if (sr != null)
sr.Close();
}
return true;
}
#region Hyperlinks
public virtual ulong GetRegionHandle(ulong handle)
{
return handle;
}
public virtual bool IsHyperlink(ulong handle)
{
return false;
}
public virtual void SendUserInformation(GridRegion regInfo, AgentCircuitData aCircuit)
{
}
public virtual void AdjustUserInformation(AgentCircuitData aCircuit)
{
}
#endregion /* Hyperlinks */
public static OSDMap GetOSDMap(string data)
{
OSDMap args = null;
try
{
OSD buffer;
// We should pay attention to the content-type, but let's assume we know it's Json
buffer = OSDParser.DeserializeJson(data);
if (buffer.Type == OSDType.Map)
{
args = (OSDMap)buffer;
return args;
}
else
{
// uh?
System.Console.WriteLine("[REST COMMS]: Got OSD of type " + buffer.Type.ToString());
return null;
}
}
catch (Exception ex)
{
System.Console.WriteLine("[REST COMMS]: exception on parse of REST message " + ex.Message);
return null;
}
}
}
}

2
OpenSim/Framework/Console/ConsoleBase.cs Normal file → Executable file
View File

@ -73,7 +73,7 @@ namespace OpenSim.Framework.Console
public virtual void Output(string text) public virtual void Output(string text)
{ {
System.Console.Write(text); System.Console.WriteLine(text);
} }
public string CmdPrompt(string p) public string CmdPrompt(string p)

2
OpenSim/Framework/Console/ConsolePluginCommand.cs Normal file → Executable file
View File

@ -124,7 +124,7 @@ namespace OpenSim.Framework.Console
/// </summary> /// </summary>
public void ShowHelp(ConsoleBase console) public void ShowHelp(ConsoleBase console)
{ {
console.Output(String.Join(" ", m_cmdText) + " - " + m_helpText); console.Output(String.Join(" ", m_cmdText) + " - " + m_helpText + "\n");
} }
/// <summary> /// <summary>

View File

@ -302,6 +302,12 @@ namespace OpenSim.Framework.Console
if (!UUID.TryParse(post["ID"].ToString(), out id)) if (!UUID.TryParse(post["ID"].ToString(), out id))
return reply; return reply;
lock(m_Connections)
{
if(!m_Connections.ContainsKey(id))
return reply;
}
if (post["COMMAND"] == null || post["COMMAND"].ToString() == String.Empty) if (post["COMMAND"] == null || post["COMMAND"].ToString() == String.Empty)
return reply; return reply;

122
OpenSim/Region/Application/OpenSim.cs Normal file → Executable file
View File

@ -409,7 +409,7 @@ namespace OpenSim
if (presence.Firstname.ToLower().Contains(cmdparams[2].ToLower()) && if (presence.Firstname.ToLower().Contains(cmdparams[2].ToLower()) &&
presence.Lastname.ToLower().Contains(cmdparams[3].ToLower())) presence.Lastname.ToLower().Contains(cmdparams[3].ToLower()))
{ {
m_log.Info( MainConsole.Instance.Output(
String.Format( String.Format(
"Kicking user: {0,-16}{1,-16}{2,-37} in region: {3,-16}", "Kicking user: {0,-16}{1,-16}{2,-37} in region: {3,-16}",
presence.Firstname, presence.Lastname, presence.UUID, regionInfo.RegionName)); presence.Firstname, presence.Lastname, presence.UUID, regionInfo.RegionName));
@ -424,7 +424,7 @@ namespace OpenSim
presence.Scene.IncomingCloseAgent(presence.UUID); presence.Scene.IncomingCloseAgent(presence.UUID);
} }
} }
m_log.Info(""); MainConsole.Instance.Output("");
} }
/// <summary> /// <summary>
@ -471,7 +471,7 @@ namespace OpenSim
private void HandleClearAssets(string module, string[] args) private void HandleClearAssets(string module, string[] args)
{ {
m_log.Info("Not implemented."); MainConsole.Instance.Output("Not implemented.");
} }
/// <summary> /// <summary>
@ -481,7 +481,7 @@ namespace OpenSim
/// <param name="args"></param> /// <param name="args"></param>
private void HandleForceUpdate(string module, string[] args) private void HandleForceUpdate(string module, string[] args)
{ {
m_log.Info("Updating all clients"); MainConsole.Instance.Output("Updating all clients");
m_sceneManager.ForceCurrentSceneClientUpdate(); m_sceneManager.ForceCurrentSceneClientUpdate();
} }
@ -498,7 +498,7 @@ namespace OpenSim
} }
else else
{ {
m_log.Info("Argument error: edit scale <prim name> <x> <y> <z>"); MainConsole.Instance.Output("Argument error: edit scale <prim name> <x> <y> <z>");
} }
} }
@ -511,7 +511,7 @@ namespace OpenSim
{ {
if (cmd.Length < 4) if (cmd.Length < 4)
{ {
m_log.Error("Usage: create region <region name> <region_file.ini>"); MainConsole.Instance.Output("Usage: create region <region name> <region_file.ini>");
return; return;
} }
if (cmd[3].EndsWith(".xml")) if (cmd[3].EndsWith(".xml"))
@ -538,7 +538,7 @@ namespace OpenSim
} }
else else
{ {
m_log.Error("Usage: create region <region name> <region_file.ini>"); MainConsole.Instance.Output("Usage: create region <region name> <region_file.ini>");
return; return;
} }
} }
@ -562,8 +562,8 @@ namespace OpenSim
case "set": case "set":
if (cmdparams.Length < 4) if (cmdparams.Length < 4)
{ {
m_log.Error("SYNTAX: " + n + " SET SECTION KEY VALUE"); MainConsole.Instance.Output(String.Format("SYNTAX: {0} SET SECTION KEY VALUE",n));
m_log.Error("EXAMPLE: " + n + " SET ScriptEngine.DotNetEngine NumberOfScriptThreads 5"); MainConsole.Instance.Output(String.Format("EXAMPLE: {0} SET ScriptEngine.DotNetEngine NumberOfScriptThreads 5",n));
} }
else else
{ {
@ -576,8 +576,7 @@ namespace OpenSim
c.Set(cmdparams[2], _value); c.Set(cmdparams[2], _value);
m_config.Source.Merge(source); m_config.Source.Merge(source);
m_log.Error(n + " " + n + " " + cmdparams[1] + " " + cmdparams[2] + " " + MainConsole.Instance.Output(String.Format("{0} {0} {1} {2} {3}",n,cmdparams[1],cmdparams[2],_value));
_value);
} }
} }
break; break;
@ -585,21 +584,21 @@ namespace OpenSim
case "get": case "get":
if (cmdparams.Length < 3) if (cmdparams.Length < 3)
{ {
m_log.Error("SYNTAX: " + n + " GET SECTION KEY"); MainConsole.Instance.Output(String.Format("SYNTAX: {0} GET SECTION KEY",n));
m_log.Error("EXAMPLE: " + n + " GET ScriptEngine.DotNetEngine NumberOfScriptThreads"); MainConsole.Instance.Output(String.Format("EXAMPLE: {0} GET ScriptEngine.DotNetEngine NumberOfScriptThreads",n));
} }
else else
{ {
IConfig c = m_config.Source.Configs[cmdparams[1]]; IConfig c = m_config.Source.Configs[cmdparams[1]];
if (c == null) if (c == null)
{ {
m_log.Info("Section \"" + cmdparams[1] + "\" does not exist."); MainConsole.Instance.Output(String.Format("Section \"{0}\" does not exist.",cmdparams[1]));
break; break;
} }
else else
{ {
m_log.Info(n + " GET " + cmdparams[1] + " " + cmdparams[2] + ": " + MainConsole.Instance.Output(String.Format("{0} GET {1} {2} : {3}",n,cmdparams[1],cmdparams[2],
c.GetString(cmdparams[2])); c.GetString(cmdparams[2])));
} }
} }
@ -608,17 +607,17 @@ namespace OpenSim
case "save": case "save":
if (cmdparams.Length < 2) if (cmdparams.Length < 2)
{ {
m_log.Error("SYNTAX: " + n + " SAVE FILE"); MainConsole.Instance.Output("SYNTAX: " + n + " SAVE FILE");
return; return;
} }
if (Application.iniFilePath == cmdparams[1]) if (Application.iniFilePath == cmdparams[1])
{ {
m_log.Error("FILE can not be "+Application.iniFilePath); MainConsole.Instance.Output("FILE can not be " + Application.iniFilePath);
return; return;
} }
m_log.Info("Saving configuration file: " + cmdparams[1]); MainConsole.Instance.Output("Saving configuration file: " + cmdparams[1]);
m_config.Save(cmdparams[1]); m_config.Save(cmdparams[1]);
break; break;
} }
@ -644,7 +643,7 @@ namespace OpenSim
case "list": case "list":
foreach (IRegionModule irm in m_moduleLoader.GetLoadedSharedModules) foreach (IRegionModule irm in m_moduleLoader.GetLoadedSharedModules)
{ {
m_log.Info("Shared region module: " + irm.Name); MainConsole.Instance.Output(String.Format("Shared region module: {0}", irm.Name));
} }
break; break;
case "unload": case "unload":
@ -654,7 +653,7 @@ namespace OpenSim
{ {
if (rm.Name.ToLower() == cmdparams[1].ToLower()) if (rm.Name.ToLower() == cmdparams[1].ToLower())
{ {
m_log.Info("Unloading module: " + rm.Name); MainConsole.Instance.Output(String.Format("Unloading module: {0}", rm.Name));
m_moduleLoader.UnloadModule(rm); m_moduleLoader.UnloadModule(rm);
} }
} }
@ -665,7 +664,7 @@ namespace OpenSim
{ {
foreach (Scene s in new ArrayList(m_sceneManager.Scenes)) foreach (Scene s in new ArrayList(m_sceneManager.Scenes))
{ {
m_log.Info("Loading module: " + cmdparams[1]); MainConsole.Instance.Output(String.Format("Loading module: {0}", cmdparams[1]));
m_moduleLoader.LoadRegionModules(cmdparams[1], s); m_moduleLoader.LoadRegionModules(cmdparams[1], s);
} }
} }
@ -710,7 +709,7 @@ namespace OpenSim
if (m_sceneManager.TryGetScene(regRemoveName, out removeScene)) if (m_sceneManager.TryGetScene(regRemoveName, out removeScene))
RemoveRegion(removeScene, false); RemoveRegion(removeScene, false);
else else
m_log.Error("no region with that name"); MainConsole.Instance.Output("no region with that name");
break; break;
case "delete-region": case "delete-region":
@ -720,7 +719,7 @@ namespace OpenSim
if (m_sceneManager.TryGetScene(regDeleteName, out killScene)) if (m_sceneManager.TryGetScene(regDeleteName, out killScene))
RemoveRegion(killScene, true); RemoveRegion(killScene, true);
else else
m_log.Error("no region with that name"); MainConsole.Instance.Output("no region with that name");
break; break;
case "restart": case "restart":
@ -730,7 +729,7 @@ namespace OpenSim
case "Add-InventoryHost": case "Add-InventoryHost":
if (cmdparams.Length > 0) if (cmdparams.Length > 0)
{ {
m_log.Info("Not implemented."); MainConsole.Instance.Output("Not implemented.");
} }
break; break;
@ -748,20 +747,19 @@ namespace OpenSim
string newRegionName = CombineParams(cmdparams, 2); string newRegionName = CombineParams(cmdparams, 2);
if (!m_sceneManager.TrySetCurrentScene(newRegionName)) if (!m_sceneManager.TrySetCurrentScene(newRegionName))
m_log.Error("Couldn't select region " + newRegionName); MainConsole.Instance.Output(String.Format("Couldn't select region {0}", newRegionName));
} }
else else
{ {
m_log.Error("Usage: change region <region name>"); MainConsole.Instance.Output("Usage: change region <region name>");
} }
string regionName = (m_sceneManager.CurrentScene == null ? "root" : m_sceneManager.CurrentScene.RegionInfo.RegionName); string regionName = (m_sceneManager.CurrentScene == null ? "root" : m_sceneManager.CurrentScene.RegionInfo.RegionName);
m_log.Info(String.Format("Currently selected region is {0}", regionName)); MainConsole.Instance.Output(String.Format("Currently selected region is {0}", regionName));
m_console.DefaultPrompt = String.Format("Region ({0}) ", regionName); m_console.DefaultPrompt = String.Format("Region ({0}) ", regionName);
m_console.ConsoleScene = m_sceneManager.CurrentScene; m_console.ConsoleScene = m_sceneManager.CurrentScene;
} }
/// <summary> /// <summary>
/// Turn on some debugging values for OpenSim. /// Turn on some debugging values for OpenSim.
/// </summary> /// </summary>
@ -783,9 +781,9 @@ namespace OpenSim
} }
else else
{ {
m_log.Error("packet debug should be 0..255"); MainConsole.Instance.Output("packet debug should be 0..255");
} }
m_log.Info("New packet debug: " + newDebug.ToString()); MainConsole.Instance.Output(String.Format("New packet debug: {0}", newDebug));
} }
break; break;
@ -795,7 +793,7 @@ namespace OpenSim
{ {
if (m_sceneManager.CurrentScene == null) if (m_sceneManager.CurrentScene == null)
{ {
m_log.Info("Please use 'change region <regioname>' first"); MainConsole.Instance.Output("Please use 'change region <regioname>' first");
} }
else else
{ {
@ -804,7 +802,7 @@ namespace OpenSim
bool physicsOn = !Convert.ToBoolean(args[4]); bool physicsOn = !Convert.ToBoolean(args[4]);
m_sceneManager.CurrentScene.SetSceneCoreDebug(scriptingOn, collisionsOn, physicsOn); m_sceneManager.CurrentScene.SetSceneCoreDebug(scriptingOn, collisionsOn, physicsOn);
m_log.Info( MainConsole.Instance.Output(
String.Format( String.Format(
"Set debug scene scripting = {0}, collisions = {1}, physics = {2}", "Set debug scene scripting = {0}, collisions = {1}, physics = {2}",
!scriptingOn, !collisionsOn, !physicsOn)); !scriptingOn, !collisionsOn, !physicsOn));
@ -812,13 +810,13 @@ namespace OpenSim
} }
else else
{ {
m_log.Error("debug scene <scripting> <collisions> <physics> (where inside <> is true/false)"); MainConsole.Instance.Output("debug scene <scripting> <collisions> <physics> (where inside <> is true/false)");
} }
break; break;
default: default:
m_log.Error("Unknown debug"); MainConsole.Instance.Output("Unknown debug");
break; break;
} }
} }
@ -840,7 +838,7 @@ namespace OpenSim
switch (showParams[0]) switch (showParams[0])
{ {
case "assets": case "assets":
m_log.Info("Not implemented."); MainConsole.Instance.Output("Not implemented.");
break; break;
case "users": case "users":
@ -854,9 +852,9 @@ namespace OpenSim
agents = m_sceneManager.GetCurrentSceneAvatars(); agents = m_sceneManager.GetCurrentSceneAvatars();
} }
m_log.Info(String.Format("\nAgents connected: {0}\n", agents.Count)); MainConsole.Instance.Output(String.Format("\nAgents connected: {0}\n", agents.Count));
m_log.Info( MainConsole.Instance.Output(
String.Format("{0,-16}{1,-16}{2,-37}{3,-11}{4,-16}{5,-30}", "Firstname", "Lastname", String.Format("{0,-16}{1,-16}{2,-37}{3,-11}{4,-16}{5,-30}", "Firstname", "Lastname",
"Agent ID", "Root/Child", "Region", "Position")); "Agent ID", "Root/Child", "Region", "Position"));
@ -874,7 +872,7 @@ namespace OpenSim
regionName = regionInfo.RegionName; regionName = regionInfo.RegionName;
} }
m_log.Info( MainConsole.Instance.Output(
String.Format( String.Format(
"{0,-16}{1,-16}{2,-37}{3,-11}{4,-16}{5,-30}", "{0,-16}{1,-16}{2,-37}{3,-11}{4,-16}{5,-30}",
presence.Firstname, presence.Firstname,
@ -885,7 +883,7 @@ namespace OpenSim
presence.AbsolutePosition.ToString())); presence.AbsolutePosition.ToString()));
} }
m_log.Info(String.Empty); MainConsole.Instance.Output(String.Empty);
break; break;
case "connections": case "connections":
@ -903,25 +901,30 @@ namespace OpenSim
} }
); );
m_log.Info(connections.ToString()); MainConsole.Instance.Output(connections.ToString());
break; break;
case "modules": case "modules":
m_log.Info("The currently loaded shared modules are:"); MainConsole.Instance.Output("The currently loaded shared modules are:");
foreach (IRegionModule module in m_moduleLoader.GetLoadedSharedModules) foreach (IRegionModule module in m_moduleLoader.GetLoadedSharedModules)
{ {
m_log.Info("Shared Module: " + module.Name); MainConsole.Instance.Output("Shared Module: " + module.Name);
} }
MainConsole.Instance.Output("");
break; break;
case "regions": case "regions":
m_sceneManager.ForEachScene( m_sceneManager.ForEachScene(
delegate(Scene scene) delegate(Scene scene)
{ {
m_log.Info("Region Name: " + scene.RegionInfo.RegionName + " , Region XLoc: " + MainConsole.Instance.Output(String.Format(
scene.RegionInfo.RegionLocX + " , Region YLoc: " + "Region Name: {0}, Region XLoc: {1}, Region YLoc: {2}, Region Port: {3}",
scene.RegionInfo.RegionLocY + " , Region Port: " + scene.RegionInfo.RegionName,
scene.RegionInfo.InternalEndPoint.Port.ToString()); scene.RegionInfo.RegionLocX,
scene.RegionInfo.RegionLocY,
scene.RegionInfo.InternalEndPoint.Port));
}); });
break; break;
@ -946,8 +949,10 @@ namespace OpenSim
{ {
rating = "PG"; rating = "PG";
} }
m_log.Info("Region Name: " + scene.RegionInfo.RegionName + " , Region Rating: " + MainConsole.Instance.Output(String.Format(
rating); "Region Name: {0}, Region Rating {1}",
scene.RegionInfo.RegionName,
rating));
}); });
break; break;
} }
@ -968,7 +973,7 @@ namespace OpenSim
if (client is IStatsCollector) if (client is IStatsCollector)
{ {
report = report + client.FirstName + report = report + client.FirstName +
" " + client.LastName + "\n"; " " + client.LastName;
IStatsCollector stats = IStatsCollector stats =
(IStatsCollector) client; (IStatsCollector) client;
@ -985,7 +990,7 @@ namespace OpenSim
"Texture", "Texture",
"Asset"); "Asset");
report = report + stats.Report() + report = report + stats.Report() +
"\n\n"; "\n";
} }
}); });
}); });
@ -1017,7 +1022,7 @@ namespace OpenSim
/// <param name="cmdparams"></param> /// <param name="cmdparams"></param>
protected void SaveXml(string module, string[] cmdparams) protected void SaveXml(string module, string[] cmdparams)
{ {
m_log.Error("[CONSOLE]: PLEASE NOTE, save-xml is DEPRECATED and may be REMOVED soon. If you are using this and there is some reason you can't use save-xml2, please file a mantis detailing the reason."); MainConsole.Instance.Output("PLEASE NOTE, save-xml is DEPRECATED and may be REMOVED soon. If you are using this and there is some reason you can't use save-xml2, please file a mantis detailing the reason.");
if (cmdparams.Length > 0) if (cmdparams.Length > 0)
{ {
@ -1036,7 +1041,7 @@ namespace OpenSim
/// <param name="cmdparams"></param> /// <param name="cmdparams"></param>
protected void LoadXml(string module, string[] cmdparams) protected void LoadXml(string module, string[] cmdparams)
{ {
m_log.Error("[CONSOLE]: PLEASE NOTE, load-xml is DEPRECATED and may be REMOVED soon. If you are using this and there is some reason you can't use load-xml2, please file a mantis detailing the reason."); MainConsole.Instance.Output("PLEASE NOTE, load-xml is DEPRECATED and may be REMOVED soon. If you are using this and there is some reason you can't use load-xml2, please file a mantis detailing the reason.");
Vector3 loadOffset = new Vector3(0, 0, 0); Vector3 loadOffset = new Vector3(0, 0, 0);
if (cmdparams.Length > 2) if (cmdparams.Length > 2)
@ -1059,8 +1064,7 @@ namespace OpenSim
{ {
loadOffset.Z = (float) Convert.ToDecimal(cmdparams[6]); loadOffset.Z = (float) Convert.ToDecimal(cmdparams[6]);
} }
m_log.Error("loadOffsets <X,Y,Z> = <" + loadOffset.X + "," + loadOffset.Y + "," + MainConsole.Instance.Output(String.Format("loadOffsets <X,Y,Z> = <{0},{1},{2}>",loadOffset.X,loadOffset.Y,loadOffset.Z));
loadOffset.Z + ">");
} }
} }
m_sceneManager.LoadCurrentSceneFromXml(cmdparams[0], generateNewIDS, loadOffset); m_sceneManager.LoadCurrentSceneFromXml(cmdparams[0], generateNewIDS, loadOffset);
@ -1073,7 +1077,7 @@ namespace OpenSim
} }
catch (FileNotFoundException) catch (FileNotFoundException)
{ {
m_log.Error("Default xml not found. Usage: load-xml <filename>"); MainConsole.Instance.Output("Default xml not found. Usage: load-xml <filename>");
} }
} }
} }
@ -1109,7 +1113,7 @@ namespace OpenSim
} }
catch (FileNotFoundException) catch (FileNotFoundException)
{ {
m_log.Error("Specified xml not found. Usage: load xml2 <filename>"); MainConsole.Instance.Output("Specified xml not found. Usage: load xml2 <filename>");
} }
} }
else else
@ -1120,7 +1124,7 @@ namespace OpenSim
} }
catch (FileNotFoundException) catch (FileNotFoundException)
{ {
m_log.Error("Default xml not found. Usage: load xml2 <filename>"); MainConsole.Instance.Output("Default xml not found. Usage: load xml2 <filename>");
} }
} }
} }
@ -1137,7 +1141,7 @@ namespace OpenSim
} }
catch (Exception e) catch (Exception e)
{ {
m_log.Error(e.Message); MainConsole.Instance.Output(e.Message);
} }
} }

View File

@ -1471,6 +1471,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public void SendKillObject(ulong regionHandle, uint localID) public void SendKillObject(ulong regionHandle, uint localID)
{ {
// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle);
KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject); KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject);
// TODO: don't create new blocks if recycling an old packet // TODO: don't create new blocks if recycling an old packet
kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1]; kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1];
@ -3478,6 +3480,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public void SendPrimitiveToClient(SendPrimitiveData data) public void SendPrimitiveToClient(SendPrimitiveData data)
{ {
// string text = data.text;
// if (text.IndexOf("\n") >= 0)
// text = text.Remove(text.IndexOf("\n"));
// m_log.DebugFormat(
// "[CLIENT]: Placing request to send full info about prim {0} text {1} to client {2}",
// data.localID, text, Name);
if (data.priority == double.NaN) if (data.priority == double.NaN)
{ {
m_log.Error("[LLClientView] SendPrimitiveToClient received a NaN priority, dropping update"); m_log.Error("[LLClientView] SendPrimitiveToClient received a NaN priority, dropping update");
@ -3515,7 +3524,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
outPacket.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[count]; outPacket.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[count];
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{
outPacket.ObjectData[i] = m_primFullUpdates.Dequeue(); outPacket.ObjectData[i] = m_primFullUpdates.Dequeue();
// string text = Util.FieldToString(outPacket.ObjectData[i].Text);
// if (text.IndexOf("\n") >= 0)
// text = text.Remove(text.IndexOf("\n"));
// m_log.DebugFormat(
// "[CLIENT]: Sending full info about prim {0} text {1} to client {2}",
// outPacket.ObjectData[i].ID, text, Name);
}
} }
OutPacket(outPacket, ThrottleOutPacketType.State); OutPacket(outPacket, ThrottleOutPacketType.State);
@ -5173,6 +5191,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{ {
ScriptDialogReplyPacket rdialog = (ScriptDialogReplyPacket)Pack; ScriptDialogReplyPacket rdialog = (ScriptDialogReplyPacket)Pack;
//m_log.DebugFormat("[CLIENT]: Received ScriptDialogReply from {0}", rdialog.Data.ObjectID);
#region Packet Session and User Check #region Packet Session and User Check
if (m_checkPackets) if (m_checkPackets)
{ {
@ -5193,7 +5213,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
args.Type = ChatTypeEnum.Shout; args.Type = ChatTypeEnum.Shout;
args.Position = new Vector3(); args.Position = new Vector3();
args.Scene = Scene; args.Scene = Scene;
args.Sender = this; args.Sender = this;
ChatMessage handlerChatFromClient2 = OnChatFromClient; ChatMessage handlerChatFromClient2 = OnChatFromClient;
if (handlerChatFromClient2 != null) if (handlerChatFromClient2 != null)
handlerChatFromClient2(this, args); handlerChatFromClient2(this, args);
@ -9095,8 +9115,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private bool HandleSendPostcard(IClientAPI client, Packet packet) private bool HandleSendPostcard(IClientAPI client, Packet packet)
{ {
SendPostcardPacket SendPostcard = // SendPostcardPacket SendPostcard =
(SendPostcardPacket)packet; // (SendPostcardPacket)packet;
SendPostcard handlerSendPostcard = OnSendPostcard; SendPostcard handlerSendPostcard = OnSendPostcard;
if (handlerSendPostcard != null) if (handlerSendPostcard != null)
{ {

View File

@ -762,7 +762,7 @@ namespace Flotsam.RegionModules.AssetCache
case "expire": case "expire":
if (cmdparams.Length >= 3) if (cmdparams.Length < 3)
{ {
m_log.InfoFormat("[FLOTSAM ASSET CACHE] Invalid parameters for Expire, please specify a valid date & time", cmd); m_log.InfoFormat("[FLOTSAM ASSET CACHE] Invalid parameters for Expire, please specify a valid date & time", cmd);
break; break;

View File

@ -172,24 +172,27 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
private void RetrieveInstantMessages(IClientAPI client) private void RetrieveInstantMessages(IClientAPI client)
{ {
m_log.DebugFormat("[OFFLINE MESSAGING] Retrieving stored messages for {0}", client.AgentId); if (m_RestURL != "")
List<GridInstantMessage>msglist = SynchronousRestObjectPoster.BeginPostObject<UUID, List<GridInstantMessage>>(
"POST", m_RestURL+"/RetrieveMessages/", client.AgentId);
foreach (GridInstantMessage im in msglist)
{ {
// client.SendInstantMessage(im); m_log.DebugFormat("[OFFLINE MESSAGING] Retrieving stored messages for {0}", client.AgentId);
// Send through scene event manager so all modules get a chance List<GridInstantMessage> msglist = SynchronousRestObjectPoster.BeginPostObject<UUID, List<GridInstantMessage>>(
// to look at this message before it gets delivered. "POST", m_RestURL + "/RetrieveMessages/", client.AgentId);
//
// Needed for proper state management for stored group foreach (GridInstantMessage im in msglist)
// invitations {
// // client.SendInstantMessage(im);
Scene s = FindScene(client.AgentId);
if (s != null) // Send through scene event manager so all modules get a chance
s.EventManager.TriggerIncomingInstantMessage(im); // to look at this message before it gets delivered.
//
// Needed for proper state management for stored group
// invitations
//
Scene s = FindScene(client.AgentId);
if (s != null)
s.EventManager.TriggerIncomingInstantMessage(im);
}
} }
} }

View File

@ -191,7 +191,6 @@ namespace OpenSim.Region.CoreModules.Framework.Library
{ {
m_log.DebugFormat("[LIBRARY MODULE]: Exception when processing archive {0}: {1}", iarFileName, e.Message); m_log.DebugFormat("[LIBRARY MODULE]: Exception when processing archive {0}: {1}", iarFileName, e.Message);
} }
} }
} }
@ -203,6 +202,14 @@ namespace OpenSim.Region.CoreModules.Framework.Library
m_log.DebugFormat(" - folder {0}", lib.Name); m_log.DebugFormat(" - folder {0}", lib.Name);
DumpFolder(lib); DumpFolder(lib);
} }
//
// private void DumpLibrary()
// {
// InventoryFolderImpl lib = m_Scene.CommsManager.UserProfileCacheService.LibraryRoot;
//
// m_log.DebugFormat(" - folder {0}", lib.Name);
// DumpFolder(lib);
// }
private void DumpFolder(InventoryFolderImpl folder) private void DumpFolder(InventoryFolderImpl folder)
{ {

View File

@ -87,7 +87,10 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
foreach (IMonitor monitor in m_monitors) foreach (IMonitor monitor in m_monitors)
{ {
if (monitor.ToString() == monID) string elemName = monitor.ToString();
if (elemName.StartsWith(monitor.GetType().Namespace))
elemName = elemName.Substring(monitor.GetType().Namespace.Length + 1);
if (elemName == monID || monitor.ToString() == monID)
{ {
Hashtable ereply3 = new Hashtable(); Hashtable ereply3 = new Hashtable();

View File

@ -362,7 +362,14 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0)) if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0))
{ {
scene.AssetService.Delete(oldID.ToString()); if (oldAsset == null) oldAsset = scene.AssetService.Get(oldID.ToString());
if (oldAsset != null)
{
if (oldAsset.Temporary == true)
{
scene.AssetService.Delete(oldID.ToString());
}
}
} }
} }

View File

@ -342,6 +342,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
m_log.Error( m_log.Error(
"[VECTORRENDERMODULE]: OpenJpeg Encode Failed. Empty byte data returned!"); "[VECTORRENDERMODULE]: OpenJpeg Encode Failed. Empty byte data returned!");
} }
m_textureManager.ReturnData(id, imageJ2000); m_textureManager.ReturnData(id, imageJ2000);
} }

View File

@ -262,44 +262,34 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
{ {
case ChatTypeEnum.Whisper: case ChatTypeEnum.Whisper:
if (dis < m_whisperdistance) if (dis < m_whisperdistance)
{ QueueMessage(new ListenerInfo(li, name, id, msg));
lock (m_pending.SyncRoot)
{
m_pending.Enqueue(new ListenerInfo(li,name,id,msg));
}
}
break; break;
case ChatTypeEnum.Say: case ChatTypeEnum.Say:
if (dis < m_saydistance) if (dis < m_saydistance)
{ QueueMessage(new ListenerInfo(li, name, id, msg));
lock (m_pending.SyncRoot)
{
m_pending.Enqueue(new ListenerInfo(li,name,id,msg));
}
}
break; break;
case ChatTypeEnum.Shout: case ChatTypeEnum.Shout:
if (dis < m_shoutdistance) if (dis < m_shoutdistance)
{ QueueMessage(new ListenerInfo(li, name, id, msg));
lock (m_pending.SyncRoot)
{
m_pending.Enqueue(new ListenerInfo(li,name,id,msg));
}
}
break; break;
case ChatTypeEnum.Region: case ChatTypeEnum.Region:
lock (m_pending.SyncRoot) QueueMessage(new ListenerInfo(li, name, id, msg));
{
m_pending.Enqueue(new ListenerInfo(li,name,id,msg));
}
break; break;
} }
} }
} }
protected void QueueMessage(ListenerInfo li)
{
lock (m_pending.SyncRoot)
{
m_pending.Enqueue(li);
}
}
/// <summary> /// <summary>
/// Are there any listen events ready to be dispatched? /// Are there any listen events ready to be dispatched?
/// </summary> /// </summary>
@ -319,7 +309,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
lock (m_pending.SyncRoot) lock (m_pending.SyncRoot)
{ {
li = (ListenerInfo) m_pending.Dequeue(); li = (ListenerInfo)m_pending.Dequeue();
} }
return li; return li;

View File

@ -41,9 +41,7 @@ namespace OpenSim.Region.CoreModules.World
{ {
public class AccessModule : ISharedRegionModule public class AccessModule : ISharedRegionModule
{ {
private static readonly ILog m_log = // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
LogManager.GetLogger(
MethodBase.GetCurrentMethod().DeclaringType);
private List<Scene> m_SceneList = new List<Scene>(); private List<Scene> m_SceneList = new List<Scene>();

View File

@ -420,9 +420,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver
currentRegionSettings.TerrainTexture4 = loadedRegionSettings.TerrainTexture4; currentRegionSettings.TerrainTexture4 = loadedRegionSettings.TerrainTexture4;
currentRegionSettings.UseEstateSun = loadedRegionSettings.UseEstateSun; currentRegionSettings.UseEstateSun = loadedRegionSettings.UseEstateSun;
currentRegionSettings.WaterHeight = loadedRegionSettings.WaterHeight; currentRegionSettings.WaterHeight = loadedRegionSettings.WaterHeight;
IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>(); IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>();
estateModule.sendRegionHandshakeToAll();
if (estateModule != null)
estateModule.sendRegionHandshakeToAll();
return true; return true;
} }

View File

@ -36,11 +36,13 @@ using OpenMetaverse;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Framework.Serialization; using OpenSim.Framework.Serialization;
using OpenSim.Framework.Serialization.External;
using OpenSim.Region.CoreModules.World.Serialiser; using OpenSim.Region.CoreModules.World.Serialiser;
using OpenSim.Region.CoreModules.World.Terrain; using OpenSim.Region.CoreModules.World.Terrain;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Scenes.Serialization; using OpenSim.Region.Framework.Scenes.Serialization;
using OpenSim.Tests.Common; using OpenSim.Tests.Common;
using OpenSim.Tests.Common.Mock;
using OpenSim.Tests.Common.Setup; using OpenSim.Tests.Common.Setup;
namespace OpenSim.Region.CoreModules.World.Archiver.Tests namespace OpenSim.Region.CoreModules.World.Archiver.Tests
@ -50,6 +52,20 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
{ {
private Guid m_lastRequestId; private Guid m_lastRequestId;
private string m_lastErrorMessage; private string m_lastErrorMessage;
protected TestScene m_scene;
protected ArchiverModule m_archiverModule;
[SetUp]
public void SetUp()
{
m_archiverModule = new ArchiverModule();
SerialiserModule serialiserModule = new SerialiserModule();
TerrainModule terrainModule = new TerrainModule();
m_scene = SceneSetupHelpers.SetupScene("scene1");
SceneSetupHelpers.SetupSceneModules(m_scene, m_archiverModule, serialiserModule, terrainModule);
}
private void LoadCompleted(Guid requestId, string errorMessage) private void LoadCompleted(Guid requestId, string errorMessage)
{ {
@ -74,6 +90,30 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
} }
} }
protected SceneObjectPart CreateSceneObjectPart1()
{
string partName = "My Little Pony";
UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000015");
PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere();
Vector3 groupPosition = new Vector3(10, 20, 30);
Quaternion rotationOffset = new Quaternion(20, 30, 40, 50);
Vector3 offsetPosition = new Vector3(5, 10, 15);
return new SceneObjectPart(ownerId, shape, groupPosition, rotationOffset, offsetPosition) { Name = partName };
}
protected SceneObjectPart CreateSceneObjectPart2()
{
string partName = "Action Man";
UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000016");
PrimitiveBaseShape shape = PrimitiveBaseShape.CreateCylinder();
Vector3 groupPosition = new Vector3(90, 80, 70);
Quaternion rotationOffset = new Quaternion(60, 70, 80, 90);
Vector3 offsetPosition = new Vector3(20, 25, 30);
return new SceneObjectPart(ownerId, shape, groupPosition, rotationOffset, offsetPosition) { Name = partName };
}
/// <summary> /// <summary>
/// Test saving a V0.2 OpenSim Region Archive. /// Test saving a V0.2 OpenSim Region Archive.
/// </summary> /// </summary>
@ -83,59 +123,20 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
TestHelper.InMethod(); TestHelper.InMethod();
//log4net.Config.XmlConfigurator.Configure(); //log4net.Config.XmlConfigurator.Configure();
ArchiverModule archiverModule = new ArchiverModule(); SceneObjectPart part1 = CreateSceneObjectPart1();
SerialiserModule serialiserModule = new SerialiserModule(); m_scene.AddNewSceneObject(new SceneObjectGroup(part1), false);
TerrainModule terrainModule = new TerrainModule();
Scene scene = SceneSetupHelpers.SetupScene("asset"); SceneObjectPart part2 = CreateSceneObjectPart2();
SceneSetupHelpers.SetupSceneModules(scene, archiverModule, serialiserModule, terrainModule); m_scene.AddNewSceneObject(new SceneObjectGroup(part2), false);
SceneObjectPart part1;
// Create and add prim 1
{
string partName = "My Little Pony";
UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000015");
PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere();
Vector3 groupPosition = new Vector3(10, 20, 30);
Quaternion rotationOffset = new Quaternion(20, 30, 40, 50);
Vector3 offsetPosition = new Vector3(5, 10, 15);
part1
= new SceneObjectPart(
ownerId, shape, groupPosition, rotationOffset, offsetPosition);
part1.Name = partName;
scene.AddNewSceneObject(new SceneObjectGroup(part1), false);
}
SceneObjectPart part2;
// Create and add prim 2
{
string partName = "Action Man";
UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000016");
PrimitiveBaseShape shape = PrimitiveBaseShape.CreateCylinder();
Vector3 groupPosition = new Vector3(90, 80, 70);
Quaternion rotationOffset = new Quaternion(60, 70, 80, 90);
Vector3 offsetPosition = new Vector3(20, 25, 30);
part2
= new SceneObjectPart(
ownerId, shape, groupPosition, rotationOffset, offsetPosition);
part2.Name = partName;
scene.AddNewSceneObject(new SceneObjectGroup(part2), false);
}
MemoryStream archiveWriteStream = new MemoryStream(); MemoryStream archiveWriteStream = new MemoryStream();
scene.EventManager.OnOarFileSaved += SaveCompleted; m_scene.EventManager.OnOarFileSaved += SaveCompleted;
Guid requestId = new Guid("00000000-0000-0000-0000-808080808080"); Guid requestId = new Guid("00000000-0000-0000-0000-808080808080");
lock (this) lock (this)
{ {
archiverModule.ArchiveRegion(archiveWriteStream, requestId); m_archiverModule.ArchiveRegion(archiveWriteStream, requestId);
//AssetServerBase assetServer = (AssetServerBase)scene.CommsManager.AssetCache.AssetServer; //AssetServerBase assetServer = (AssetServerBase)scene.CommsManager.AssetCache.AssetServer;
//while (assetServer.HasWaitingRequests()) //while (assetServer.HasWaitingRequests())
// assetServer.ProcessNextRequest(); // assetServer.ProcessNextRequest();
@ -214,32 +215,58 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
// Also check that direct entries which will also have a file entry containing that directory doesn't // Also check that direct entries which will also have a file entry containing that directory doesn't
// upset load // upset load
tar.WriteDir(ArchiveConstants.TERRAINS_PATH); tar.WriteDir(ArchiveConstants.TERRAINS_PATH);
tar.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, ArchiveWriteRequestExecution.Create0p2ControlFile()); tar.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, ArchiveWriteRequestExecution.Create0p2ControlFile());
string part1Name = "object1"; SceneObjectPart part1 = CreateSceneObjectPart1();
PrimitiveBaseShape shape = PrimitiveBaseShape.CreateCylinder();
Vector3 groupPosition = new Vector3(90, 80, 70);
Quaternion rotationOffset = new Quaternion(60, 70, 80, 90);
Vector3 offsetPosition = new Vector3(20, 25, 30);
SerialiserModule serialiserModule = new SerialiserModule();
ArchiverModule archiverModule = new ArchiverModule();
Scene scene = SceneSetupHelpers.SetupScene();
SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule);
SceneObjectPart part1
= new SceneObjectPart(
UUID.Zero, shape, groupPosition, rotationOffset, offsetPosition);
part1.Name = part1Name;
SceneObjectGroup object1 = new SceneObjectGroup(part1); SceneObjectGroup object1 = new SceneObjectGroup(part1);
scene.AddNewSceneObject(object1, false);
// Let's put some inventory items into our object
string soundItemName = "sound-item1";
UUID soundItemUuid = UUID.Parse("00000000-0000-0000-0000-000000000002");
Type type = GetType();
Assembly assembly = type.Assembly;
string soundDataResourceName = null;
string[] names = assembly.GetManifestResourceNames();
foreach (string name in names)
{
if (name.EndsWith(".Resources.test-sound.wav"))
soundDataResourceName = name;
}
Assert.That(soundDataResourceName, Is.Not.Null);
byte[] soundData;
Console.WriteLine("Loading " + soundDataResourceName);
using (Stream resource = assembly.GetManifestResourceStream(soundDataResourceName))
{
using (BinaryReader br = new BinaryReader(resource))
{
// FIXME: Use the inspector insteadthere are so many forums and lists already, though admittedly none of them are suitable for cross virtual-enivornemnt discussion
soundData = br.ReadBytes(99999999);
UUID soundUuid = UUID.Parse("00000000-0000-0000-0000-000000000001");
string soundAssetFileName
= ArchiveConstants.ASSETS_PATH + soundUuid
+ ArchiveConstants.ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV];
tar.WriteFile(soundAssetFileName, soundData);
/*
AssetBase soundAsset = AssetHelpers.CreateAsset(soundUuid, soundData);
scene.AssetService.Store(soundAsset);
asset1FileName = ArchiveConstants.ASSETS_PATH + soundUuid + ".wav";
*/
TaskInventoryItem item1
= new TaskInventoryItem { AssetID = soundUuid, ItemID = soundItemUuid, Name = soundItemName };
part1.Inventory.AddInventoryItem(item1, true);
}
}
m_scene.AddNewSceneObject(object1, false);
string object1FileName = string.Format( string object1FileName = string.Format(
"{0}_{1:000}-{2:000}-{3:000}__{4}.xml", "{0}_{1:000}-{2:000}-{3:000}__{4}.xml",
part1Name, part1.Name,
Math.Round(groupPosition.X), Math.Round(groupPosition.Y), Math.Round(groupPosition.Z), Math.Round(part1.GroupPosition.X), Math.Round(part1.GroupPosition.Y), Math.Round(part1.GroupPosition.Z),
part1.UUID); part1.UUID);
tar.WriteFile(ArchiveConstants.OBJECTS_PATH + object1FileName, SceneObjectSerializer.ToXml2Format(object1)); tar.WriteFile(ArchiveConstants.OBJECTS_PATH + object1FileName, SceneObjectSerializer.ToXml2Format(object1));
@ -249,26 +276,124 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
lock (this) lock (this)
{ {
scene.EventManager.OnOarFileLoaded += LoadCompleted; m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
archiverModule.DearchiveRegion(archiveReadStream); m_archiverModule.DearchiveRegion(archiveReadStream);
} }
Assert.That(m_lastErrorMessage, Is.Null); Assert.That(m_lastErrorMessage, Is.Null);
SceneObjectPart object1PartLoaded = scene.GetSceneObjectPart(part1Name); SceneObjectPart object1PartLoaded = m_scene.GetSceneObjectPart(part1.Name);
Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded"); Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded");
Assert.That(object1PartLoaded.Name, Is.EqualTo(part1Name), "object1 names not identical"); Assert.That(object1PartLoaded.Name, Is.EqualTo(part1.Name), "object1 names not identical");
Assert.That(object1PartLoaded.GroupPosition, Is.EqualTo(groupPosition), "object1 group position not equal"); Assert.That(object1PartLoaded.GroupPosition, Is.EqualTo(part1.GroupPosition), "object1 group position not equal");
Assert.That( Assert.That(
object1PartLoaded.RotationOffset, Is.EqualTo(rotationOffset), "object1 rotation offset not equal"); object1PartLoaded.RotationOffset, Is.EqualTo(part1.RotationOffset), "object1 rotation offset not equal");
Assert.That( Assert.That(
object1PartLoaded.OffsetPosition, Is.EqualTo(offsetPosition), "object1 offset position not equal"); object1PartLoaded.OffsetPosition, Is.EqualTo(part1.OffsetPosition), "object1 offset position not equal");
TaskInventoryItem loadedSoundItem = object1PartLoaded.Inventory.GetInventoryItems(soundItemName)[0];
Assert.That(loadedSoundItem, Is.Not.Null, "loaded sound item was null");
AssetBase loadedSoundAsset = m_scene.AssetService.Get(loadedSoundItem.AssetID.ToString());
Assert.That(loadedSoundAsset, Is.Not.Null, "loaded sound asset was null");
Assert.That(loadedSoundAsset.Data, Is.EqualTo(soundData), "saved and loaded sound data do not match");
// Temporary // Temporary
Console.WriteLine("Successfully completed {0}", MethodBase.GetCurrentMethod()); Console.WriteLine("Successfully completed {0}", MethodBase.GetCurrentMethod());
} }
/// <summary>
/// Test loading the region settings of a V0.2 OpenSim Region Archive.
/// </summary>
[Test]
public void TestLoadOarV0_2RegionSettings()
{
TestHelper.InMethod();
//log4net.Config.XmlConfigurator.Configure();
MemoryStream archiveWriteStream = new MemoryStream();
TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream);
tar.WriteDir(ArchiveConstants.TERRAINS_PATH);
tar.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, ArchiveWriteRequestExecution.Create0p2ControlFile());
RegionSettings rs = new RegionSettings();
rs.AgentLimit = 17;
rs.AllowDamage = true;
rs.AllowLandJoinDivide = true;
rs.AllowLandResell = true;
rs.BlockFly = true;
rs.BlockShowInSearch = true;
rs.BlockTerraform = true;
rs.DisableCollisions = true;
rs.DisablePhysics = true;
rs.DisableScripts = true;
rs.Elevation1NW = 15.9;
rs.Elevation1NE = 45.3;
rs.Elevation1SE = 49;
rs.Elevation1SW = 1.9;
rs.Elevation2NW = 4.5;
rs.Elevation2NE = 19.2;
rs.Elevation2SE = 9.2;
rs.Elevation2SW = 2.1;
rs.FixedSun = true;
rs.ObjectBonus = 1.4;
rs.RestrictPushing = true;
rs.TerrainLowerLimit = 0.4;
rs.TerrainRaiseLimit = 17.9;
rs.TerrainTexture1 = UUID.Parse("00000000-0000-0000-0000-000000000020");
rs.TerrainTexture2 = UUID.Parse("00000000-0000-0000-0000-000000000040");
rs.TerrainTexture3 = UUID.Parse("00000000-0000-0000-0000-000000000060");
rs.TerrainTexture4 = UUID.Parse("00000000-0000-0000-0000-000000000080");
rs.UseEstateSun = true;
rs.WaterHeight = 23;
tar.WriteFile(ArchiveConstants.SETTINGS_PATH + "region1.xml", RegionSettingsSerializer.Serialize(rs));
tar.Close();
MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray());
lock (this)
{
m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
m_archiverModule.DearchiveRegion(archiveReadStream);
}
Assert.That(m_lastErrorMessage, Is.Null);
RegionSettings loadedRs = m_scene.RegionInfo.RegionSettings;
Assert.That(loadedRs.AgentLimit, Is.EqualTo(17));
Assert.That(loadedRs.AllowDamage, Is.True);
Assert.That(loadedRs.AllowLandJoinDivide, Is.True);
Assert.That(loadedRs.AllowLandResell, Is.True);
Assert.That(loadedRs.BlockFly, Is.True);
Assert.That(loadedRs.BlockShowInSearch, Is.True);
Assert.That(loadedRs.BlockTerraform, Is.True);
Assert.That(loadedRs.DisableCollisions, Is.True);
Assert.That(loadedRs.DisablePhysics, Is.True);
Assert.That(loadedRs.DisableScripts, Is.True);
Assert.That(loadedRs.Elevation1NW, Is.EqualTo(15.9));
Assert.That(loadedRs.Elevation1NE, Is.EqualTo(45.3));
Assert.That(loadedRs.Elevation1SE, Is.EqualTo(49));
Assert.That(loadedRs.Elevation1SW, Is.EqualTo(1.9));
Assert.That(loadedRs.Elevation2NW, Is.EqualTo(4.5));
Assert.That(loadedRs.Elevation2NE, Is.EqualTo(19.2));
Assert.That(loadedRs.Elevation2SE, Is.EqualTo(9.2));
Assert.That(loadedRs.Elevation2SW, Is.EqualTo(2.1));
Assert.That(loadedRs.FixedSun, Is.True);
Assert.That(loadedRs.ObjectBonus, Is.EqualTo(1.4));
Assert.That(loadedRs.RestrictPushing, Is.True);
Assert.That(loadedRs.TerrainLowerLimit, Is.EqualTo(0.4));
Assert.That(loadedRs.TerrainRaiseLimit, Is.EqualTo(17.9));
Assert.That(loadedRs.TerrainTexture1, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000020")));
Assert.That(loadedRs.TerrainTexture2, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000040")));
Assert.That(loadedRs.TerrainTexture3, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000060")));
Assert.That(loadedRs.TerrainTexture4, Is.EqualTo(UUID.Parse("00000000-0000-0000-0000-000000000080")));
Assert.That(loadedRs.UseEstateSun, Is.True);
Assert.That(loadedRs.WaterHeight, Is.EqualTo(23));
}
/// <summary> /// <summary>
/// Test merging a V0.2 OpenSim Region Archive into an existing scene /// Test merging a V0.2 OpenSim Region Archive into an existing scene
/// </summary> /// </summary>
@ -280,11 +405,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
MemoryStream archiveWriteStream = new MemoryStream(); MemoryStream archiveWriteStream = new MemoryStream();
string part2Name = "objectMerge"; // string part2Name = "objectMerge";
PrimitiveBaseShape part2Shape = PrimitiveBaseShape.CreateCylinder(); // PrimitiveBaseShape part2Shape = PrimitiveBaseShape.CreateCylinder();
Vector3 part2GroupPosition = new Vector3(90, 80, 70); // Vector3 part2GroupPosition = new Vector3(90, 80, 70);
Quaternion part2RotationOffset = new Quaternion(60, 70, 80, 90); // Quaternion part2RotationOffset = new Quaternion(60, 70, 80, 90);
Vector3 part2OffsetPosition = new Vector3(20, 25, 30); // Vector3 part2OffsetPosition = new Vector3(20, 25, 30);
SceneObjectPart part2 = CreateSceneObjectPart2();
// Create an oar file that we can use for the merge // Create an oar file that we can use for the merge
{ {
@ -293,63 +420,39 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
TerrainModule terrainModule = new TerrainModule(); TerrainModule terrainModule = new TerrainModule();
Scene scene = SceneSetupHelpers.SetupScene(); Scene scene = SceneSetupHelpers.SetupScene();
SceneSetupHelpers.SetupSceneModules(scene, archiverModule, serialiserModule, terrainModule); SceneSetupHelpers.SetupSceneModules(scene, archiverModule, serialiserModule, terrainModule);
SceneObjectPart part2 m_scene.AddNewSceneObject(new SceneObjectGroup(part2), false);
= new SceneObjectPart(
UUID.Zero, part2Shape, part2GroupPosition, part2RotationOffset, part2OffsetPosition);
part2.Name = part2Name;
SceneObjectGroup object2 = new SceneObjectGroup(part2);
scene.AddNewSceneObject(object2, false);
// Write out this scene // Write out this scene
scene.EventManager.OnOarFileSaved += SaveCompleted; scene.EventManager.OnOarFileSaved += SaveCompleted;
lock (this) lock (this)
{ {
archiverModule.ArchiveRegion(archiveWriteStream); m_archiverModule.ArchiveRegion(archiveWriteStream);
Monitor.Wait(this, 60000); Monitor.Wait(this, 60000);
} }
} }
{ {
ArchiverModule archiverModule = new ArchiverModule(); SceneObjectPart part1 = CreateSceneObjectPart1();
SerialiserModule serialiserModule = new SerialiserModule(); m_scene.AddNewSceneObject(new SceneObjectGroup(part1), false);
TerrainModule terrainModule = new TerrainModule();
Scene scene = SceneSetupHelpers.SetupScene();
SceneSetupHelpers.SetupSceneModules(scene, archiverModule, serialiserModule, terrainModule);
string part1Name = "objectExisting";
PrimitiveBaseShape part1Shape = PrimitiveBaseShape.CreateCylinder();
Vector3 part1GroupPosition = new Vector3(80, 70, 60);
Quaternion part1RotationOffset = new Quaternion(50, 60, 70, 80);
Vector3 part1OffsetPosition = new Vector3(15, 20, 25);
SceneObjectPart part1
= new SceneObjectPart(
UUID.Zero, part1Shape, part1GroupPosition, part1RotationOffset, part1OffsetPosition);
part1.Name = part1Name;
SceneObjectGroup object1 = new SceneObjectGroup(part1);
scene.AddNewSceneObject(object1, false);
// Merge in the archive we created earlier // Merge in the archive we created earlier
byte[] archive = archiveWriteStream.ToArray(); byte[] archive = archiveWriteStream.ToArray();
MemoryStream archiveReadStream = new MemoryStream(archive); MemoryStream archiveReadStream = new MemoryStream(archive);
archiverModule.DearchiveRegion(archiveReadStream, true, Guid.Empty); m_archiverModule.DearchiveRegion(archiveReadStream, true, Guid.Empty);
SceneObjectPart object1Existing = scene.GetSceneObjectPart(part1Name); SceneObjectPart object1Existing = m_scene.GetSceneObjectPart(part1.Name);
Assert.That(object1Existing, Is.Not.Null, "object1 was not present after merge"); Assert.That(object1Existing, Is.Not.Null, "object1 was not present after merge");
Assert.That(object1Existing.Name, Is.EqualTo(part1Name), "object1 names not identical after merge"); Assert.That(object1Existing.Name, Is.EqualTo(part1.Name), "object1 names not identical after merge");
Assert.That(object1Existing.GroupPosition, Is.EqualTo(part1GroupPosition), "object1 group position not equal after merge"); Assert.That(object1Existing.GroupPosition, Is.EqualTo(part1.GroupPosition), "object1 group position not equal after merge");
SceneObjectPart object2PartMerged = scene.GetSceneObjectPart(part2Name); SceneObjectPart object2PartMerged = m_scene.GetSceneObjectPart(part2.Name);
Assert.That(object2PartMerged, Is.Not.Null, "object2 was not present after merge"); Assert.That(object2PartMerged, Is.Not.Null, "object2 was not present after merge");
Assert.That(object2PartMerged.Name, Is.EqualTo(part2Name), "object2 names not identical after merge"); Assert.That(object2PartMerged.Name, Is.EqualTo(part2.Name), "object2 names not identical after merge");
Assert.That(object2PartMerged.GroupPosition, Is.EqualTo(part2GroupPosition), "object2 group position not equal after merge"); Assert.That(object2PartMerged.GroupPosition, Is.EqualTo(part2.GroupPosition), "object2 group position not equal after merge");
} }
} }
} }

View File

@ -142,6 +142,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
private bool m_debugPermissions = false; private bool m_debugPermissions = false;
private bool m_allowGridGods = false; private bool m_allowGridGods = false;
private bool m_RegionOwnerIsGod = false; private bool m_RegionOwnerIsGod = false;
private bool m_RegionManagerIsGod = false;
private bool m_ParcelOwnerIsGod = false; private bool m_ParcelOwnerIsGod = false;
/// <value> /// <value>
@ -184,6 +185,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
m_bypassPermissions = !myConfig.GetBoolean("serverside_object_permissions", false); m_bypassPermissions = !myConfig.GetBoolean("serverside_object_permissions", false);
m_propagatePermissions = myConfig.GetBoolean("propagate_permissions", true); m_propagatePermissions = myConfig.GetBoolean("propagate_permissions", true);
m_RegionOwnerIsGod = myConfig.GetBoolean("region_owner_is_god", true); m_RegionOwnerIsGod = myConfig.GetBoolean("region_owner_is_god", true);
m_RegionManagerIsGod = myConfig.GetBoolean("region_manager_is_god", false);
m_ParcelOwnerIsGod = myConfig.GetBoolean("parcel_owner_is_god", true); m_ParcelOwnerIsGod = myConfig.GetBoolean("parcel_owner_is_god", true);
m_allowedScriptCreators m_allowedScriptCreators
@ -479,10 +481,13 @@ namespace OpenSim.Region.CoreModules.World.Permissions
if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero) if (m_scene.RegionInfo.EstateSettings.EstateOwner != UUID.Zero)
{ {
if (m_scene.RegionInfo.EstateSettings.EstateOwner == user) if (m_scene.RegionInfo.EstateSettings.EstateOwner == user && m_RegionOwnerIsGod)
return true; return true;
} }
if (IsEstateManager(user) && m_RegionManagerIsGod)
return true;
if (m_allowGridGods) if (m_allowGridGods)
{ {
UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, user); UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, user);
@ -495,6 +500,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
return false; return false;
} }
protected bool IsFriendWithPerms(UUID user,UUID objectOwner) protected bool IsFriendWithPerms(UUID user,UUID objectOwner)
{ {
@ -896,9 +902,6 @@ namespace OpenSim.Region.CoreModules.World.Permissions
DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
if (m_bypassPermissions) return m_bypassPermissionsValue; if (m_bypassPermissions) return m_bypassPermissionsValue;
if (IsEstateManager(user) && m_RegionOwnerIsGod)
return true;
return IsAdministrator(user); return IsAdministrator(user);
} }

View File

@ -71,13 +71,18 @@ namespace OpenSim.Region.Framework.Interfaces
/// <summary> /// <summary>
/// Start all the scripts contained in this entity's inventory /// Start all the scripts contained in this entity's inventory
/// </summary> /// </summary>
void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource); void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource);
ArrayList GetScriptErrors(UUID itemID); ArrayList GetScriptErrors(UUID itemID);
/// <summary> /// <summary>
/// Stop all the scripts in this entity. /// Stop all the scripts in this entity.
/// </summary> /// </summary>
void RemoveScriptInstances(); /// <param name="sceneObjectBeingDeleted">
/// Should be true if these scripts are being removed because the scene
/// object is being deleted. This will prevent spurious updates to the client.
/// </param>
void RemoveScriptInstances(bool sceneObjectBeingDeleted);
/// <summary> /// <summary>
/// Start a script which is in this entity's inventory. /// Start a script which is in this entity's inventory.
@ -103,7 +108,11 @@ namespace OpenSim.Region.Framework.Interfaces
/// Stop a script which is in this prim's inventory. /// Stop a script which is in this prim's inventory.
/// </summary> /// </summary>
/// <param name="itemId"></param> /// <param name="itemId"></param>
void RemoveScriptInstance(UUID itemId); /// <param name="sceneObjectBeingDeleted">
/// Should be true if these scripts are being removed because the scene
/// object is being deleted. This will prevent spurious updates to the client.
/// </param>
void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted);
/// <summary> /// <summary>
/// Add an item to this entity's inventory. If an item with the same name already exists, then an alternative /// Add an item to this entity's inventory. If an item with the same name already exists, then an alternative
@ -134,6 +143,16 @@ namespace OpenSim.Region.Framework.Interfaces
/// <returns>null if the item does not exist</returns> /// <returns>null if the item does not exist</returns>
TaskInventoryItem GetInventoryItem(UUID itemId); TaskInventoryItem GetInventoryItem(UUID itemId);
/// <summary>
/// Get inventory items by name.
/// </summary>
/// <param name="name"></param>
/// <returns>
/// A list of inventory items with that name.
/// If no inventory item has that name then an empty list is returned.
/// </returns>
IList<TaskInventoryItem> GetInventoryItems(string name);
/// <summary> /// <summary>
/// Update an existing inventory item. /// Update an existing inventory item.
/// </summary> /// </summary>

View File

@ -49,10 +49,49 @@ namespace OpenSim.Region.Framework.Interfaces
public interface IWorldComm public interface IWorldComm
{ {
/// <summary>
/// Create a listen event callback with the specified filters.
/// The parameters localID,itemID are needed to uniquely identify
/// the script during 'peek' time. Parameter hostID is needed to
/// determine the position of the script.
/// </summary>
/// <param name="localID">localID of the script engine</param>
/// <param name="itemID">UUID of the script engine</param>
/// <param name="hostID">UUID of the SceneObjectPart</param>
/// <param name="channel">channel to listen on</param>
/// <param name="name">name to filter on</param>
/// <param name="id">key to filter on (user given, could be totally faked)</param>
/// <param name="msg">msg to filter on</param>
/// <returns>number of the scripts handle</returns>
int Listen(uint LocalID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg); int Listen(uint LocalID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg);
/// <summary>
/// This method scans over the objects which registered an interest in listen callbacks.
/// For everyone it finds, it checks if it fits the given filter. If it does, then
/// enqueue the message for delivery to the objects listen event handler.
/// The enqueued ListenerInfo no longer has filter values, but the actually trigged values.
/// Objects that do an llSay have their messages delivered here and for nearby avatars,
/// the OnChatFromClient event is used.
/// </summary>
/// <param name="type">type of delvery (whisper,say,shout or regionwide)</param>
/// <param name="channel">channel to sent on</param>
/// <param name="name">name of sender (object or avatar)</param>
/// <param name="id">key of sender (object or avatar)</param>
/// <param name="msg">msg to sent</param>
void DeliverMessage(ChatTypeEnum type, int channel, string name, UUID id, string msg); void DeliverMessage(ChatTypeEnum type, int channel, string name, UUID id, string msg);
/// <summary>
/// Are there any listen events ready to be dispatched?
/// </summary>
/// <returns>boolean indication</returns>
bool HasMessages(); bool HasMessages();
/// <summary>
/// Pop the first availlable listen event from the queue
/// </summary>
/// <returns>ListenerInfo with filter filled in</returns>
IWorldCommListenerInfo GetNextMessage(); IWorldCommListenerInfo GetNextMessage();
void ListenControl(UUID itemID, int handle, int active); void ListenControl(UUID itemID, int handle, int active);
void ListenRemove(UUID itemID, int handle); void ListenRemove(UUID itemID, int handle);
void DeleteListener(UUID itemID); void DeleteListener(UUID itemID);

File diff suppressed because it is too large Load Diff

View File

@ -197,7 +197,7 @@ namespace OpenSim.Region.Framework.Scenes
if (isScriptRunning) if (isScriptRunning)
{ {
part.Inventory.RemoveScriptInstance(item.ItemID); part.Inventory.RemoveScriptInstance(item.ItemID, false);
} }
// Update item with new asset // Update item with new asset
@ -794,8 +794,10 @@ namespace OpenSim.Region.Framework.Scenes
if (item.Type == 10) if (item.Type == 10)
{ {
part.RemoveScriptEvents(itemID);
EventManager.TriggerRemoveScript(localID, itemID); EventManager.TriggerRemoveScript(localID, itemID);
} }
group.RemoveInventoryItem(localID, itemID); group.RemoveInventoryItem(localID, itemID);
part.GetProperties(remoteClient); part.GetProperties(remoteClient);
} }
@ -1879,9 +1881,19 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
public void AttachObject(IClientAPI controllingClient, uint localID, uint attachPoint, Quaternion rot, Vector3 pos, bool silent) /// <summary>
/// Attach an object.
/// </summary>
/// <param name="controllingClient"></param>
/// <param name="localID"></param>
/// <param name="attachPoint"></param>
/// <param name="rot"></param>
/// <param name="pos"></param>
/// <param name="silent"></param>
/// <returns>true if the object was successfully attached, false otherwise</returns>
public bool AttachObject(IClientAPI controllingClient, uint localID, uint attachPoint, Quaternion rot, Vector3 pos, bool silent)
{ {
m_sceneGraph.AttachObject(controllingClient, localID, attachPoint, rot, pos, silent); return m_sceneGraph.AttachObject(controllingClient, localID, attachPoint, rot, pos, silent);
} }
public void AttachObject(IClientAPI remoteClient, uint AttachmentPt, UUID itemID, SceneObjectGroup att) public void AttachObject(IClientAPI remoteClient, uint AttachmentPt, UUID itemID, SceneObjectGroup att)

View File

@ -292,6 +292,46 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
public virtual void ProcessObjectGrabUpdate(UUID objectID, Vector3 offset, Vector3 pos, IClientAPI remoteClient, List<SurfaceTouchEventArgs> surfaceArgs)
{
List<EntityBase> EntityList = GetEntities();
SurfaceTouchEventArgs surfaceArg = null;
if (surfaceArgs != null && surfaceArgs.Count > 0)
surfaceArg = surfaceArgs[0];
foreach (EntityBase ent in EntityList)
{
if (ent is SceneObjectGroup)
{
SceneObjectGroup obj = ent as SceneObjectGroup;
if (obj != null)
{
// Is this prim part of the group
if (obj.HasChildPrim(objectID))
{
SceneObjectPart part = obj.GetChildPart(objectID);
// If the touched prim handles touches, deliver it
// If not, deliver to root prim
if ((part.ScriptEvents & scriptEvents.touch) != 0)
EventManager.TriggerObjectGrabbing(part.LocalId, 0, part.OffsetPosition, remoteClient, surfaceArg);
// Deliver to the root prim if the touched prim doesn't handle touches
// or if we're meant to pass on touches anyway. Don't send to root prim
// if prim touched is the root prim as we just did it
if (((part.ScriptEvents & scriptEvents.touch) == 0) ||
(part.PassTouches && (part.LocalId != obj.RootPart.LocalId)))
{
EventManager.TriggerObjectGrabbing(obj.RootPart.LocalId, part.LocalId, part.OffsetPosition, remoteClient, surfaceArg);
}
return;
}
}
}
}
}
public virtual void ProcessObjectDeGrab(uint localID, IClientAPI remoteClient, List<SurfaceTouchEventArgs> surfaceArgs) public virtual void ProcessObjectDeGrab(uint localID, IClientAPI remoteClient, List<SurfaceTouchEventArgs> surfaceArgs)
{ {
List<EntityBase> EntityList = GetEntities(); List<EntityBase> EntityList = GetEntities();

View File

@ -1102,7 +1102,7 @@ namespace OpenSim.Region.Framework.Scenes
{ {
if (ent is SceneObjectGroup) if (ent is SceneObjectGroup)
{ {
((SceneObjectGroup) ent).RemoveScriptInstances(); ((SceneObjectGroup) ent).RemoveScriptInstances(false);
} }
} }
} }
@ -1977,13 +1977,15 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="silent">Suppress broadcasting changes to other clients.</param> /// <param name="silent">Suppress broadcasting changes to other clients.</param>
public void DeleteSceneObject(SceneObjectGroup group, bool silent) public void DeleteSceneObject(SceneObjectGroup group, bool silent)
{ {
// m_log.DebugFormat("[SCENE]: Deleting scene object {0} {1}", group.Name, group.UUID);
//SceneObjectPart rootPart = group.GetChildPart(group.UUID); //SceneObjectPart rootPart = group.GetChildPart(group.UUID);
// Serialise calls to RemoveScriptInstances to avoid // Serialise calls to RemoveScriptInstances to avoid
// deadlocking on m_parts inside SceneObjectGroup // deadlocking on m_parts inside SceneObjectGroup
lock (m_deleting_scene_object) lock (m_deleting_scene_object)
{ {
group.RemoveScriptInstances(); group.RemoveScriptInstances(true);
} }
foreach (SceneObjectPart part in group.Children.Values) foreach (SceneObjectPart part in group.Children.Values)
@ -2011,6 +2013,8 @@ namespace OpenSim.Region.Framework.Scenes
} }
group.DeleteGroup(silent); group.DeleteGroup(silent);
// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
} }
/// <summary> /// <summary>
@ -2539,6 +2543,7 @@ namespace OpenSim.Region.Framework.Scenes
client.OnRequestObjectPropertiesFamily += m_sceneGraph.RequestObjectPropertiesFamily; client.OnRequestObjectPropertiesFamily += m_sceneGraph.RequestObjectPropertiesFamily;
client.OnObjectPermissions += HandleObjectPermissionsUpdate; client.OnObjectPermissions += HandleObjectPermissionsUpdate;
client.OnGrabObject += ProcessObjectGrab; client.OnGrabObject += ProcessObjectGrab;
client.OnGrabUpdate += ProcessObjectGrabUpdate;
client.OnDeGrabObject += ProcessObjectDeGrab; client.OnDeGrabObject += ProcessObjectDeGrab;
client.OnUndo += m_sceneGraph.HandleUndo; client.OnUndo += m_sceneGraph.HandleUndo;
client.OnObjectDescription += m_sceneGraph.PrimDescription; client.OnObjectDescription += m_sceneGraph.PrimDescription;

View File

@ -479,25 +479,35 @@ namespace OpenSim.Region.Framework.Scenes
if (part == null) if (part == null)
return; return;
if (!m_parentScene.Permissions.CanTakeObject( if (!m_parentScene.Permissions.CanTakeObject(part.UUID, remoteClient.AgentId))
part.UUID, remoteClient.AgentId))
return; return;
// Calls attach with a Zero position // Calls attach with a Zero position
AttachObject(remoteClient, objectLocalID, AttachmentPt, rot, Vector3.Zero, false); if (AttachObject(remoteClient, objectLocalID, AttachmentPt, rot, Vector3.Zero, false))
m_parentScene.SendAttachEvent(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId);
// Save avatar attachment information
ScenePresence presence;
if (m_parentScene.AvatarFactory != null && m_parentScene.TryGetAvatar(remoteClient.AgentId, out presence))
{ {
m_log.Info("[SCENE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId + ", AttachmentPoint: " + AttachmentPt); m_parentScene.SendAttachEvent(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId);
m_parentScene.AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance);
// Save avatar attachment information
ScenePresence presence;
if (m_parentScene.AvatarFactory != null && m_parentScene.TryGetAvatar(remoteClient.AgentId, out presence))
{
m_log.Info(
"[SCENE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId
+ ", AttachmentPoint: " + AttachmentPt);
m_parentScene.AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance);
}
} }
} }
public SceneObjectGroup RezSingleAttachment( /// <summary>
IClientAPI remoteClient, UUID itemID, uint AttachmentPt) /// Rez an attachment
/// </summary>
/// <param name="remoteClient"></param>
/// <param name="itemID"></param>
/// <param name="AttachmentPt"></param>
/// <returns>The scene object that was attached. Null if the scene object could not be found</returns>
public SceneObjectGroup RezSingleAttachment(IClientAPI remoteClient, UUID itemID, uint AttachmentPt)
{ {
IInventoryAccessModule invAccess = m_parentScene.RequestModuleInterface<IInventoryAccessModule>(); IInventoryAccessModule invAccess = m_parentScene.RequestModuleInterface<IInventoryAccessModule>();
if (invAccess != null) if (invAccess != null)
@ -560,7 +570,17 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
protected internal void AttachObject( /// <summary>
/// Attach a scene object to an avatar.
/// </summary>
/// <param name="remoteClient"></param>
/// <param name="objectLocalID"></param>
/// <param name="AttachmentPt"></param>
/// <param name="rot"></param>
/// <param name="attachPos"></param>
/// <param name="silent"></param>
/// <returns>true if the attachment was successful, false otherwise</returns>
protected internal bool AttachObject(
IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, Vector3 attachPos, bool silent) IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, Vector3 attachPos, bool silent)
{ {
SceneObjectGroup group = GetGroupByPrim(objectLocalID); SceneObjectGroup group = GetGroupByPrim(objectLocalID);
@ -589,10 +609,8 @@ namespace OpenSim.Region.Framework.Scenes
// Stick it on left hand with Zero Offset from the attachment point. // Stick it on left hand with Zero Offset from the attachment point.
AttachmentPt = (uint)AttachmentPoint.LeftHand; AttachmentPt = (uint)AttachmentPoint.LeftHand;
attachPos = Vector3.Zero; attachPos = Vector3.Zero;
} }
group.SetAttachmentPoint((byte)AttachmentPt); group.SetAttachmentPoint((byte)AttachmentPt);
group.AbsolutePosition = attachPos; group.AbsolutePosition = attachPos;
@ -615,15 +633,21 @@ namespace OpenSim.Region.Framework.Scenes
// it get cleaned up // it get cleaned up
// //
group.RootPart.RemFlag(PrimFlags.TemporaryOnRez); group.RootPart.RemFlag(PrimFlags.TemporaryOnRez);
group.HasGroupChanged = false; group.HasGroupChanged = false;
} }
else else
{ {
remoteClient.SendAgentAlertMessage("You don't have sufficient permissions to attach this object", false); remoteClient.SendAgentAlertMessage("You don't have sufficient permissions to attach this object", false);
return false;
} }
} }
else else
{
m_log.DebugFormat("[SCENE GRAPH]: AttachObject found no such scene object {0}", objectLocalID); m_log.DebugFormat("[SCENE GRAPH]: AttachObject found no such scene object {0}", objectLocalID);
return false;
}
return true;
} }
protected internal ScenePresence CreateAndAddChildScenePresence(IClientAPI client, AvatarAppearance appearance) protected internal ScenePresence CreateAndAddChildScenePresence(IClientAPI client, AvatarAppearance appearance)

View File

@ -74,13 +74,17 @@ namespace OpenSim.Region.Framework.Scenes
/// <summary> /// <summary>
/// Stop the scripts contained in all the prims in this group /// Stop the scripts contained in all the prims in this group
/// </summary> /// </summary>
public void RemoveScriptInstances() /// <param name="sceneObjectBeingDeleted">
/// Should be true if these scripts are being removed because the scene
/// object is being deleted. This will prevent spurious updates to the client.
/// </param>
public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
{ {
lock (m_parts) lock (m_parts)
{ {
foreach (SceneObjectPart part in m_parts.Values) foreach (SceneObjectPart part in m_parts.Values)
{ {
part.Inventory.RemoveScriptInstances(); part.Inventory.RemoveScriptInstances(sceneObjectBeingDeleted);
} }
} }
} }

View File

@ -235,6 +235,9 @@ namespace OpenSim.Region.Framework.Scenes
set { m_rootPart.GroupID = value; } set { m_rootPart.GroupID = value; }
} }
/// <value>
/// The parts of this scene object group. You must lock this property before using it.
/// </value>
public Dictionary<UUID, SceneObjectPart> Children public Dictionary<UUID, SceneObjectPart> Children
{ {
get { return m_parts; } get { return m_parts; }
@ -2097,7 +2100,7 @@ namespace OpenSim.Region.Framework.Scenes
} }
/// <summary> /// <summary>
/// Get a child part with a given UUID /// Get a part with a given UUID
/// </summary> /// </summary>
/// <param name="primID"></param> /// <param name="primID"></param>
/// <returns>null if a child part with the primID was not found</returns> /// <returns>null if a child part with the primID was not found</returns>
@ -2112,7 +2115,7 @@ namespace OpenSim.Region.Framework.Scenes
} }
/// <summary> /// <summary>
/// Get a child part with a given local ID /// Get a part with a given local ID
/// </summary> /// </summary>
/// <param name="localID"></param> /// <param name="localID"></param>
/// <returns>null if a child part with the local ID was not found</returns> /// <returns>null if a child part with the local ID was not found</returns>

View File

@ -90,12 +90,38 @@ namespace OpenSim.Region.Framework.Scenes
SCALE = 0x40 SCALE = 0x40
} }
public enum PrimType : int
{
BOX = 0,
CYLINDER = 1,
PRISM = 2,
SPHERE = 3,
TORUS = 4,
TUBE = 5,
RING = 6,
SCULPT = 7
}
#endregion Enumerations #endregion Enumerations
public class SceneObjectPart : IScriptHost public class SceneObjectPart : IScriptHost
{ {
/// <value>
/// Denote all sides of the prim
/// </value>
public const int ALL_SIDES = -1;
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
/// <value>
/// Is this sop a root part?
/// </value>
[XmlIgnore]
public bool IsRoot
{
get { return ParentGroup.RootPart == this; }
}
// use only one serializer to give the runtime a chance to optimize it (it won't do that if you // use only one serializer to give the runtime a chance to optimize it (it won't do that if you
// use a new instance every time) // use a new instance every time)
private static XmlSerializer serializer = new XmlSerializer(typeof (SceneObjectPart)); private static XmlSerializer serializer = new XmlSerializer(typeof (SceneObjectPart));
@ -737,6 +763,9 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
/// <value>
/// Text color.
/// </value>
public Color Color public Color Color
{ {
get { return m_color; } get { return m_color; }
@ -1901,7 +1930,7 @@ namespace OpenSim.Region.Framework.Scenes
foreach (uint localId in startedColliders) foreach (uint localId in startedColliders)
{ {
if (localId == 0) if (localId == 0)
return; continue;
// always running this check because if the user deletes the object it would return a null reference. // always running this check because if the user deletes the object it would return a null reference.
if (m_parentGroup == null) if (m_parentGroup == null)
return; return;
@ -2037,7 +2066,7 @@ namespace OpenSim.Region.Framework.Scenes
{ {
// always running this check because if the user deletes the object it would return a null reference. // always running this check because if the user deletes the object it would return a null reference.
if (localId == 0) if (localId == 0)
return; continue;
if (m_parentGroup == null) if (m_parentGroup == null)
return; return;
@ -2169,7 +2198,7 @@ namespace OpenSim.Region.Framework.Scenes
foreach (uint localId in endedColliders) foreach (uint localId in endedColliders)
{ {
if (localId == 0) if (localId == 0)
return; continue;
// always running this check because if the user deletes the object it would return a null reference. // always running this check because if the user deletes the object it would return a null reference.
if (m_parentGroup == null) if (m_parentGroup == null)
@ -2479,7 +2508,7 @@ namespace OpenSim.Region.Framework.Scenes
//m_log.Debug("prev: " + prevflag.ToString() + " curr: " + Flags.ToString()); //m_log.Debug("prev: " + prevflag.ToString() + " curr: " + Flags.ToString());
//ScheduleFullUpdate(); //ScheduleFullUpdate();
} }
public void RemoveScriptEvents(UUID scriptid) public void RemoveScriptEvents(UUID scriptid)
{ {
lock (m_scriptEvents) lock (m_scriptEvents)
@ -2533,6 +2562,8 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary> /// </summary>
public void ScheduleFullUpdate() public void ScheduleFullUpdate()
{ {
// m_log.DebugFormat("[SCENE OBJECT PART]: Scheduling full update for {0} {1}", Name, LocalId);
if (m_parentGroup != null) if (m_parentGroup != null)
{ {
m_parentGroup.QueueForUpdateCheck(); m_parentGroup.QueueForUpdateCheck();
@ -2953,6 +2984,178 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
/// <summary>
/// Set the color of prim faces
/// </summary>
/// <param name="color"></param>
/// <param name="face"></param>
public void SetFaceColor(Vector3 color, int face)
{
Primitive.TextureEntry tex = Shape.Textures;
Color4 texcolor;
if (face >= 0 && face < GetNumberOfSides())
{
texcolor = tex.CreateFace((uint)face).RGBA;
texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f);
texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f);
texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f);
tex.FaceTextures[face].RGBA = texcolor;
UpdateTexture(tex);
return;
}
else if (face == ALL_SIDES)
{
for (uint i = 0; i < GetNumberOfSides(); i++)
{
if (tex.FaceTextures[i] != null)
{
texcolor = tex.FaceTextures[i].RGBA;
texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f);
texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f);
texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f);
tex.FaceTextures[i].RGBA = texcolor;
}
texcolor = tex.DefaultTexture.RGBA;
texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f);
texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f);
texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f);
tex.DefaultTexture.RGBA = texcolor;
}
UpdateTexture(tex);
return;
}
}
/// <summary>
/// Get the number of sides that this part has.
/// </summary>
/// <returns></returns>
public int GetNumberOfSides()
{
int ret = 0;
bool hasCut;
bool hasHollow;
bool hasDimple;
bool hasProfileCut;
PrimType primType = GetPrimType();
HasCutHollowDimpleProfileCut(primType, Shape, out hasCut, out hasHollow, out hasDimple, out hasProfileCut);
switch (primType)
{
case PrimType.BOX:
ret = 6;
if (hasCut) ret += 2;
if (hasHollow) ret += 1;
break;
case PrimType.CYLINDER:
ret = 3;
if (hasCut) ret += 2;
if (hasHollow) ret += 1;
break;
case PrimType.PRISM:
ret = 5;
if (hasCut) ret += 2;
if (hasHollow) ret += 1;
break;
case PrimType.SPHERE:
ret = 1;
if (hasCut) ret += 2;
if (hasDimple) ret += 2;
if (hasHollow) ret += 1;
break;
case PrimType.TORUS:
ret = 1;
if (hasCut) ret += 2;
if (hasProfileCut) ret += 2;
if (hasHollow) ret += 1;
break;
case PrimType.TUBE:
ret = 4;
if (hasCut) ret += 2;
if (hasProfileCut) ret += 2;
if (hasHollow) ret += 1;
break;
case PrimType.RING:
ret = 3;
if (hasCut) ret += 2;
if (hasProfileCut) ret += 2;
if (hasHollow) ret += 1;
break;
case PrimType.SCULPT:
ret = 1;
break;
}
return ret;
}
/// <summary>
/// Tell us what type this prim is
/// </summary>
/// <param name="primShape"></param>
/// <returns></returns>
public PrimType GetPrimType()
{
if (Shape.SculptEntry)
return PrimType.SCULPT;
if ((Shape.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
{
if (Shape.PathCurve == (byte)Extrusion.Straight)
return PrimType.BOX;
else if (Shape.PathCurve == (byte)Extrusion.Curve1)
return PrimType.TUBE;
}
else if ((Shape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
{
if (Shape.PathCurve == (byte)Extrusion.Straight)
return PrimType.CYLINDER;
// ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
else if (Shape.PathCurve == (byte)Extrusion.Curve1)
return PrimType.TORUS;
}
else if ((Shape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
{
if (Shape.PathCurve == (byte)Extrusion.Curve1 || Shape.PathCurve == (byte)Extrusion.Curve2)
return PrimType.SPHERE;
}
else if ((Shape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
{
if (Shape.PathCurve == (byte)Extrusion.Straight)
return PrimType.PRISM;
else if (Shape.PathCurve == (byte)Extrusion.Curve1)
return PrimType.RING;
}
return PrimType.BOX;
}
/// <summary>
/// Tell us if this object has cut, hollow, dimple, and other factors affecting the number of faces
/// </summary>
/// <param name="primType"></param>
/// <param name="shape"></param>
/// <param name="hasCut"></param>
/// <param name="hasHollow"></param>
/// <param name="hasDimple"></param>
/// <param name="hasProfileCut"></param>
protected static void HasCutHollowDimpleProfileCut(PrimType primType, PrimitiveBaseShape shape, out bool hasCut, out bool hasHollow,
out bool hasDimple, out bool hasProfileCut)
{
if (primType == PrimType.BOX
||
primType == PrimType.CYLINDER
||
primType == PrimType.PRISM)
hasCut = (shape.ProfileBegin > 0) || (shape.ProfileEnd > 0);
else
hasCut = (shape.PathBegin > 0) || (shape.PathEnd > 0);
hasHollow = shape.ProfileHollow > 0;
hasDimple = (shape.ProfileBegin > 0) || (shape.ProfileEnd > 0); // taken from llSetPrimitiveParms
hasProfileCut = hasDimple; // is it the same thing?
}
public void SetGroup(UUID groupID, IClientAPI client) public void SetGroup(UUID groupID, IClientAPI client)
{ {
_groupID = groupID; _groupID = groupID;
@ -2984,6 +3187,11 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
/// <summary>
/// Set the events that this part will pass on to listeners.
/// </summary>
/// <param name="scriptid"></param>
/// <param name="events"></param>
public void SetScriptEvents(UUID scriptid, int events) public void SetScriptEvents(UUID scriptid, int events)
{ {
// scriptEvents oldparts; // scriptEvents oldparts;
@ -3936,9 +4144,13 @@ namespace OpenSim.Region.Framework.Scenes
ScheduleFullUpdate(); ScheduleFullUpdate();
} }
// Added to handle bug in libsecondlife's TextureEntry.ToBytes() /// <summary>
// not handling RGBA properly. Cycles through, and "fixes" the color /// Update the textures on the part.
// info /// </summary>
/// Added to handle bug in libsecondlife's TextureEntry.ToBytes()
/// not handling RGBA properly. Cycles through, and "fixes" the color
/// info
/// <param name="tex"></param>
public void UpdateTexture(Primitive.TextureEntry tex) public void UpdateTexture(Primitive.TextureEntry tex)
{ {
//Color4 tmpcolor; //Color4 tmpcolor;
@ -4042,6 +4254,8 @@ namespace OpenSim.Region.Framework.Scenes
if (m_parentGroup == null) if (m_parentGroup == null)
{ {
// m_log.DebugFormat(
// "[SCENE OBJECT PART]: Scheduling part {0} {1} for full update in aggregateScriptEvents() since m_parentGroup == null", Name, LocalId);
ScheduleFullUpdate(); ScheduleFullUpdate();
return; return;
} }
@ -4058,9 +4272,15 @@ namespace OpenSim.Region.Framework.Scenes
LocalFlags=(PrimFlags)objectflagupdate; LocalFlags=(PrimFlags)objectflagupdate;
if (m_parentGroup != null && m_parentGroup.RootPart == this) if (m_parentGroup != null && m_parentGroup.RootPart == this)
{
m_parentGroup.aggregateScriptEvents(); m_parentGroup.aggregateScriptEvents();
}
else else
{
// m_log.DebugFormat(
// "[SCENE OBJECT PART]: Scheduling part {0} {1} for full update in aggregateScriptEvents()", Name, LocalId);
ScheduleFullUpdate(); ScheduleFullUpdate();
}
} }
public int registerTargetWaypoint(Vector3 target, float tolerance) public int registerTargetWaypoint(Vector3 target, float tolerance)

View File

@ -229,7 +229,11 @@ namespace OpenSim.Region.Framework.Scenes
/// <summary> /// <summary>
/// Stop all the scripts in this prim. /// Stop all the scripts in this prim.
/// </summary> /// </summary>
public void RemoveScriptInstances() /// <param name="sceneObjectBeingDeleted">
/// Should be true if these scripts are being removed because the scene
/// object is being deleted. This will prevent spurious updates to the client.
/// </param>
public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
{ {
lock (Items) lock (Items)
{ {
@ -237,8 +241,7 @@ namespace OpenSim.Region.Framework.Scenes
{ {
if ((int)InventoryType.LSL == item.InvType) if ((int)InventoryType.LSL == item.InvType)
{ {
RemoveScriptInstance(item.ItemID); RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
m_part.RemoveScriptEvents(item.ItemID);
} }
} }
} }
@ -266,8 +269,12 @@ namespace OpenSim.Region.Framework.Scenes
if (stateSource == 1 && // Prim crossing if (stateSource == 1 && // Prim crossing
m_part.ParentGroup.Scene.m_trustBinaries) m_part.ParentGroup.Scene.m_trustBinaries)
{ {
m_items[item.ItemID].PermsMask = 0; lock (m_items)
m_items[item.ItemID].PermsGranter = UUID.Zero; {
m_items[item.ItemID].PermsMask = 0;
m_items[item.ItemID].PermsGranter = UUID.Zero;
}
m_part.ParentGroup.Scene.EventManager.TriggerRezScript( m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
m_part.ParentGroup.AddActiveScriptCount(1); m_part.ParentGroup.AddActiveScriptCount(1);
@ -275,33 +282,38 @@ namespace OpenSim.Region.Framework.Scenes
return; return;
} }
m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString(), this, delegate(string id, object sender, AssetBase asset) m_part.ParentGroup.Scene.AssetService.Get(
{ item.AssetID.ToString(), this, delegate(string id, object sender, AssetBase asset)
if (null == asset) {
{ if (null == asset)
m_log.ErrorFormat( {
"[PRIM INVENTORY]: " + m_log.ErrorFormat(
"Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", "[PRIM INVENTORY]: " +
item.Name, item.ItemID, m_part.AbsolutePosition, "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
m_part.ParentGroup.Scene.RegionInfo.RegionName, item.AssetID); item.Name, item.ItemID, m_part.AbsolutePosition,
} m_part.ParentGroup.Scene.RegionInfo.RegionName, item.AssetID);
else }
{ else
if (m_part.ParentGroup.m_savedScriptState != null) {
RestoreSavedScriptState(item.OldItemID, item.ItemID); if (m_part.ParentGroup.m_savedScriptState != null)
m_items[item.ItemID].PermsMask = 0; RestoreSavedScriptState(item.OldItemID, item.ItemID);
m_items[item.ItemID].PermsGranter = UUID.Zero;
string script = Utils.BytesToString(asset.Data);
m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
m_part.ParentGroup.AddActiveScriptCount(1);
m_part.ScheduleFullUpdate();
}
});
}
}
static System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); lock (m_items)
{
m_items[item.ItemID].PermsMask = 0;
m_items[item.ItemID].PermsGranter = UUID.Zero;
}
string script = Utils.BytesToString(asset.Data);
m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
m_part.ParentGroup.AddActiveScriptCount(1);
m_part.ScheduleFullUpdate();
}
}
);
}
}
private void RestoreSavedScriptState(UUID oldID, UUID newID) private void RestoreSavedScriptState(UUID oldID, UUID newID)
{ {
@ -387,10 +399,25 @@ namespace OpenSim.Region.Framework.Scenes
/// Stop a script which is in this prim's inventory. /// Stop a script which is in this prim's inventory.
/// </summary> /// </summary>
/// <param name="itemId"></param> /// <param name="itemId"></param>
public void RemoveScriptInstance(UUID itemId) /// <param name="sceneObjectBeingDeleted">
/// Should be true if this script is being removed because the scene
/// object is being deleted. This will prevent spurious updates to the client.
/// </param>
public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted)
{ {
if (m_items.ContainsKey(itemId)) bool scriptPresent = false;
lock (m_items)
{ {
if (m_items.ContainsKey(itemId))
scriptPresent = true;
}
if (scriptPresent)
{
if (!sceneObjectBeingDeleted)
m_part.RemoveScriptEvents(itemId);
m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemId); m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemId);
m_part.ParentGroup.AddActiveScriptCount(-1); m_part.ParentGroup.AddActiveScriptCount(-1);
} }
@ -458,13 +485,19 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="item"></param> /// <param name="item"></param>
public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
{ {
List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values); List<TaskInventoryItem> il;
lock (m_items)
{
il = new List<TaskInventoryItem>(m_items.Values);
}
foreach (TaskInventoryItem i in il) foreach (TaskInventoryItem i in il)
{ {
if (i.Name == item.Name) if (i.Name == item.Name)
{ {
if (i.InvType == (int)InventoryType.LSL) if (i.InvType == (int)InventoryType.LSL)
RemoveScriptInstance(i.ItemID); RemoveScriptInstance(i.ItemID, false);
RemoveInventoryItem(i.ItemID); RemoveInventoryItem(i.ItemID);
break; break;
@ -540,11 +573,37 @@ namespace OpenSim.Region.Framework.Scenes
public TaskInventoryItem GetInventoryItem(UUID itemId) public TaskInventoryItem GetInventoryItem(UUID itemId)
{ {
TaskInventoryItem item; TaskInventoryItem item;
m_items.TryGetValue(itemId, out item);
lock (m_items)
m_items.TryGetValue(itemId, out item);
return item; return item;
} }
/// <summary>
/// Get inventory items by name.
/// </summary>
/// <param name="name"></param>
/// <returns>
/// A list of inventory items with that name.
/// If no inventory item has that name then an empty list is returned.
/// </returns>
public IList<TaskInventoryItem> GetInventoryItems(string name)
{
IList<TaskInventoryItem> items = new List<TaskInventoryItem>();
lock (m_items)
{
foreach (TaskInventoryItem item in m_items.Values)
{
if (item.Name == name)
items.Add(item);
}
}
return items;
}
/// <summary> /// <summary>
/// Update an existing inventory item. /// Update an existing inventory item.
/// </summary> /// </summary>
@ -612,6 +671,7 @@ namespace OpenSim.Region.Framework.Scenes
int type = m_items[itemID].InvType; int type = m_items[itemID].InvType;
if (type == 10) // Script if (type == 10) // Script
{ {
m_part.RemoveScriptEvents(itemID);
m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
} }
m_items.Remove(itemID); m_items.Remove(itemID);
@ -841,54 +901,61 @@ namespace OpenSim.Region.Framework.Scenes
{ {
uint mask=0x7fffffff; uint mask=0x7fffffff;
foreach (TaskInventoryItem item in m_items.Values) lock (m_items)
{ {
if (item.InvType != (int)InventoryType.Object) foreach (TaskInventoryItem item in m_items.Values)
{ {
if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) if (item.InvType != (int)InventoryType.Object)
mask &= ~((uint)PermissionMask.Copy >> 13); {
if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
mask &= ~((uint)PermissionMask.Transfer >> 13); mask &= ~((uint)PermissionMask.Copy >> 13);
if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
mask &= ~((uint)PermissionMask.Modify >> 13); mask &= ~((uint)PermissionMask.Transfer >> 13);
if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
mask &= ~((uint)PermissionMask.Modify >> 13);
}
else
{
if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
mask &= ~((uint)PermissionMask.Copy >> 13);
if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
mask &= ~((uint)PermissionMask.Transfer >> 13);
if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
mask &= ~((uint)PermissionMask.Modify >> 13);
}
if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
mask &= ~(uint)PermissionMask.Copy;
if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
mask &= ~(uint)PermissionMask.Transfer;
if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
mask &= ~(uint)PermissionMask.Modify;
} }
else
{
if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
mask &= ~((uint)PermissionMask.Copy >> 13);
if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
mask &= ~((uint)PermissionMask.Transfer >> 13);
if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
mask &= ~((uint)PermissionMask.Modify >> 13);
}
if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
mask &= ~(uint)PermissionMask.Copy;
if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
mask &= ~(uint)PermissionMask.Transfer;
if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
mask &= ~(uint)PermissionMask.Modify;
} }
return mask; return mask;
} }
public void ApplyNextOwnerPermissions() public void ApplyNextOwnerPermissions()
{ {
foreach (TaskInventoryItem item in m_items.Values) lock (m_items)
{ {
if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) foreach (TaskInventoryItem item in m_items.Values)
{ {
if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
item.CurrentPermissions &= ~(uint)PermissionMask.Copy; {
if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0) if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
item.CurrentPermissions &= ~(uint)PermissionMask.Modify; item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
item.CurrentPermissions |= 8; if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
item.CurrentPermissions |= 8;
}
item.CurrentPermissions &= item.NextPermissions;
item.BasePermissions &= item.NextPermissions;
item.EveryonePermissions &= item.NextPermissions;
} }
item.CurrentPermissions &= item.NextPermissions;
item.BasePermissions &= item.NextPermissions;
item.EveryonePermissions &= item.NextPermissions;
} }
m_part.TriggerScriptChangedEvent(Changed.OWNER); m_part.TriggerScriptChangedEvent(Changed.OWNER);
@ -896,22 +963,29 @@ namespace OpenSim.Region.Framework.Scenes
public void ApplyGodPermissions(uint perms) public void ApplyGodPermissions(uint perms)
{ {
foreach (TaskInventoryItem item in m_items.Values) lock (m_items)
{ {
item.CurrentPermissions = perms; foreach (TaskInventoryItem item in m_items.Values)
item.BasePermissions = perms; {
item.CurrentPermissions = perms;
item.BasePermissions = perms;
}
} }
} }
public bool ContainsScripts() public bool ContainsScripts()
{ {
foreach (TaskInventoryItem item in m_items.Values) lock (m_items)
{ {
if (item.InvType == (int)InventoryType.LSL) foreach (TaskInventoryItem item in m_items.Values)
{ {
return true; if (item.InvType == (int)InventoryType.LSL)
{
return true;
}
} }
} }
return false; return false;
} }
@ -919,8 +993,11 @@ namespace OpenSim.Region.Framework.Scenes
{ {
List<UUID> ret = new List<UUID>(); List<UUID> ret = new List<UUID>();
foreach (TaskInventoryItem item in m_items.Values) lock (m_items)
ret.Add(item.ItemID); {
foreach (TaskInventoryItem item in m_items.Values)
ret.Add(item.ItemID);
}
return ret; return ret;
} }
@ -933,26 +1010,30 @@ namespace OpenSim.Region.Framework.Scenes
if (engines == null) // No engine at all if (engines == null) // No engine at all
return ret; return ret;
foreach (TaskInventoryItem item in m_items.Values) lock (m_items)
{ {
if (item.InvType == (int)InventoryType.LSL) foreach (TaskInventoryItem item in m_items.Values)
{ {
foreach (IScriptModule e in engines) if (item.InvType == (int)InventoryType.LSL)
{ {
if (e != null) foreach (IScriptModule e in engines)
{ {
string n = e.GetXMLState(item.ItemID); if (e != null)
if (n != String.Empty)
{ {
if (!ret.ContainsKey(item.ItemID)) string n = e.GetXMLState(item.ItemID);
ret[item.ItemID] = n; if (n != String.Empty)
break; {
if (!ret.ContainsKey(item.ItemID))
ret[item.ItemID] = n;
break;
}
} }
} }
} }
} }
} }
return ret; return ret;
} }
} }
} }

View File

@ -104,6 +104,8 @@ namespace OpenSim.Region.Framework.Scenes
} }
protected ScenePresenceAnimator m_animator; protected ScenePresenceAnimator m_animator;
protected List<SceneObjectGroup> m_attachments = new List<SceneObjectGroup>();
private Dictionary<UUID, ScriptControllers> scriptedcontrols = new Dictionary<UUID, ScriptControllers>(); private Dictionary<UUID, ScriptControllers> scriptedcontrols = new Dictionary<UUID, ScriptControllers>();
private ScriptControlled IgnoredControls = ScriptControlled.CONTROL_ZERO; private ScriptControlled IgnoredControls = ScriptControlled.CONTROL_ZERO;
private ScriptControlled LastCommands = ScriptControlled.CONTROL_ZERO; private ScriptControlled LastCommands = ScriptControlled.CONTROL_ZERO;
@ -217,7 +219,6 @@ namespace OpenSim.Region.Framework.Scenes
protected AvatarAppearance m_appearance; protected AvatarAppearance m_appearance;
protected List<SceneObjectGroup> m_attachments = new List<SceneObjectGroup>();
public List<SceneObjectGroup> Attachments public List<SceneObjectGroup> Attachments
{ {
get { return m_attachments; } get { return m_attachments; }
@ -636,12 +637,16 @@ namespace OpenSim.Region.Framework.Scenes
#endregion #endregion
#region Constructor(s) #region Constructor(s)
private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) public ScenePresence()
{ {
m_animator = new ScenePresenceAnimator(this);
m_sendCourseLocationsMethod = SendCoarseLocationsDefault; m_sendCourseLocationsMethod = SendCoarseLocationsDefault;
CreateSceneViewer(); CreateSceneViewer();
m_animator = new ScenePresenceAnimator(this);
}
private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this()
{
m_rootRegionHandle = reginfo.RegionHandle; m_rootRegionHandle = reginfo.RegionHandle;
m_controllingClient = client; m_controllingClient = client;
m_firstname = m_controllingClient.FirstName; m_firstname = m_controllingClient.FirstName;
@ -665,7 +670,6 @@ namespace OpenSim.Region.Framework.Scenes
m_reprioritization_timer.Elapsed += new ElapsedEventHandler(Reprioritize); m_reprioritization_timer.Elapsed += new ElapsedEventHandler(Reprioritize);
m_reprioritization_timer.AutoReset = false; m_reprioritization_timer.AutoReset = false;
AdjustKnownSeeds(); AdjustKnownSeeds();
// TODO: I think, this won't send anything, as we are still a child here... // TODO: I think, this won't send anything, as we are still a child here...
@ -1294,6 +1298,12 @@ namespace OpenSim.Region.Framework.Scenes
if (m_allowMovement) if (m_allowMovement)
{ {
if (agentData.UseClientAgentPosition)
{
m_moveToPositionInProgress = (agentData.ClientAgentPosition - AbsolutePosition).Length() > 0.2f;
m_moveToPositionTarget = agentData.ClientAgentPosition;
}
int i = 0; int i = 0;
bool update_rotation = false; bool update_rotation = false;
@ -1400,7 +1410,7 @@ namespace OpenSim.Region.Framework.Scenes
if (bAllowUpdateMoveToPosition && (m_moveToPositionInProgress && !m_autopilotMoving)) if (bAllowUpdateMoveToPosition && (m_moveToPositionInProgress && !m_autopilotMoving))
{ {
//Check the error term of the current position in relation to the target position //Check the error term of the current position in relation to the target position
if (Util.GetDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 1.5f) if (Util.GetDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 0.5f)
{ {
// we are close enough to the target // we are close enough to the target
m_moveToPositionTarget = Vector3.Zero; m_moveToPositionTarget = Vector3.Zero;
@ -2795,7 +2805,14 @@ namespace OpenSim.Region.Framework.Scenes
protected void CrossToNewRegion() protected void CrossToNewRegion()
{ {
InTransit(); InTransit();
m_scene.CrossAgentToNewRegion(this, m_physicsActor.Flying); try
{
m_scene.CrossAgentToNewRegion(this, m_physicsActor.Flying);
}
catch
{
m_scene.CrossAgentToNewRegion(this, false);
}
} }
public void InTransit() public void InTransit()
@ -2873,7 +2890,6 @@ namespace OpenSim.Region.Framework.Scenes
{ {
RemoveNeighbourRegion(handle); RemoveNeighbourRegion(handle);
} }
} }
#endregion #endregion
@ -3037,7 +3053,7 @@ namespace OpenSim.Region.Framework.Scenes
List<int> attPoints = m_appearance.GetAttachedPoints(); List<int> attPoints = m_appearance.GetAttachedPoints();
if (attPoints != null) if (attPoints != null)
{ {
m_log.DebugFormat("[SCENE PRESENCE]: attachments {0}", attPoints.Count); //m_log.DebugFormat("[SCENE PRESENCE]: attachments {0}", attPoints.Count);
int i = 0; int i = 0;
AttachmentData[] attachs = new AttachmentData[attPoints.Count]; AttachmentData[] attachs = new AttachmentData[attPoints.Count];
foreach (int point in attPoints) foreach (int point in attPoints)
@ -3261,17 +3277,15 @@ namespace OpenSim.Region.Framework.Scenes
uint killerObj = 0; uint killerObj = 0;
foreach (uint localid in coldata.Keys) foreach (uint localid in coldata.Keys)
{ {
if (coldata[localid].PenetrationDepth <= 0.10f || m_invulnerable) SceneObjectPart part = Scene.GetSceneObjectPart(localid);
continue;
//if (localid == 0)
//continue;
SceneObjectPart part = m_scene.GetSceneObjectPart(localid);
if (part != null && part.ParentGroup.Damage != -1.0f) if (part != null && part.ParentGroup.Damage != -1.0f)
Health -= part.ParentGroup.Damage; Health -= part.ParentGroup.Damage;
else else
Health -= coldata[localid].PenetrationDepth * 5.0f; {
if (coldata[localid].PenetrationDepth >= 0.10f)
Health -= coldata[localid].PenetrationDepth * 5.0f;
}
if (Health <= 0.0f) if (Health <= 0.0f)
{ {
@ -3289,9 +3303,7 @@ namespace OpenSim.Region.Framework.Scenes
} }
if (m_health <= 0) if (m_health <= 0)
m_scene.EventManager.TriggerAvatarKill(killerObj, this); m_scene.EventManager.TriggerAvatarKill(killerObj, this);
} }
} }
public void setHealthWithUpdate(float health) public void setHealthWithUpdate(float health)
@ -3338,13 +3350,6 @@ namespace OpenSim.Region.Framework.Scenes
m_animator = null; m_animator = null;
} }
public ScenePresence()
{
m_sendCourseLocationsMethod = SendCoarseLocationsDefault;
CreateSceneViewer();
m_animator = new ScenePresenceAnimator(this);
}
public void AddAttachment(SceneObjectGroup gobj) public void AddAttachment(SceneObjectGroup gobj)
{ {
lock (m_attachments) lock (m_attachments)
@ -3843,4 +3848,4 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
} }
} }

View File

@ -116,7 +116,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
static string ConvertMRMKeywords(string script) static string ConvertMRMKeywords(string script)
{ {
script = script.Replace("microthreaded void ", "IEnumerable"); script = script.Replace("microthreaded void", "IEnumerable");
script = script.Replace("relax;", "yield return null;"); script = script.Replace("relax;", "yield return null;");
return script; return script;

View File

@ -1575,6 +1575,7 @@ Console.WriteLine(" JointCreateFixed");
{ {
//Console.WriteLine("Move " + m_primName); //Console.WriteLine("Move " + m_primName);
if (!d.BodyIsEnabled (Body)) d.BodyEnable (Body); // KF add 161009 if (!d.BodyIsEnabled (Body)) d.BodyEnable (Body); // KF add 161009
/*
// NON-'VEHICLES' are dealt with here // NON-'VEHICLES' are dealt with here
if (d.BodyIsEnabled(Body) && !m_angularlock.ApproxEquals(Vector3.Zero, 0.003f)) if (d.BodyIsEnabled(Body) && !m_angularlock.ApproxEquals(Vector3.Zero, 0.003f))
{ {
@ -1587,6 +1588,7 @@ Console.WriteLine(" JointCreateFixed");
avel2.Z = 0; avel2.Z = 0;
d.BodySetAngularVel(Body, avel2.X, avel2.Y, avel2.Z); d.BodySetAngularVel(Body, avel2.X, avel2.Y, avel2.Z);
} }
*/
//float PID_P = 900.0f; //float PID_P = 900.0f;
float m_mass = CalculateMass(); float m_mass = CalculateMass();

View File

@ -55,7 +55,7 @@ using OpenSim.Services.Interfaces;
using OpenSim.Services.Interfaces; using OpenSim.Services.Interfaces;
using GridRegion = OpenSim.Services.Interfaces.GridRegion; using GridRegion = OpenSim.Services.Interfaces.GridRegion;
using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
using PrimType = OpenSim.Region.Framework.Scenes.PrimType;
using AssetLandmark = OpenSim.Framework.AssetLandmark; using AssetLandmark = OpenSim.Framework.AssetLandmark;
using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
@ -1331,44 +1331,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
SetColor(m_host, color, face); if (face == ScriptBaseClass.ALL_SIDES)
} face = SceneObjectPart.ALL_SIDES;
protected void SetColor(SceneObjectPart part, LSL_Vector color, int face) m_host.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face);
{
Primitive.TextureEntry tex = part.Shape.Textures;
Color4 texcolor;
if (face >= 0 && face < GetNumberOfSides(part))
{
texcolor = tex.CreateFace((uint)face).RGBA;
texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
tex.FaceTextures[face].RGBA = texcolor;
part.UpdateTexture(tex);
return;
}
else if (face == ScriptBaseClass.ALL_SIDES)
{
for (uint i = 0; i < GetNumberOfSides(part); i++)
{
if (tex.FaceTextures[i] != null)
{
texcolor = tex.FaceTextures[i].RGBA;
texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
tex.FaceTextures[i].RGBA = texcolor;
}
texcolor = tex.DefaultTexture.RGBA;
texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f);
texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f);
texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f);
tex.DefaultTexture.RGBA = texcolor;
}
part.UpdateTexture(tex);
return;
}
} }
public void SetTexGen(SceneObjectPart part, int face,int style) public void SetTexGen(SceneObjectPart part, int face,int style)
@ -1515,7 +1481,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
int i; int i;
double sum = 0.0; double sum = 0.0;
for (i = 0 ; i < GetNumberOfSides(part) ; i++) for (i = 0 ; i < GetNumberOfSides(part); i++)
sum += (double)tex.GetFace((uint)i).RGBA.A; sum += (double)tex.GetFace((uint)i).RGBA.A;
return sum; return sum;
} }
@ -1662,7 +1628,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
int i; int i;
for (i = 0 ; i < GetNumberOfSides(part) ; i++) for (i = 0 ; i < GetNumberOfSides(part); i++)
{ {
texcolor = tex.GetFace((uint)i).RGBA; texcolor = tex.GetFace((uint)i).RGBA;
rgb.x += texcolor.R; rgb.x += texcolor.R;
@ -3415,7 +3381,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
List<SceneObjectPart> parts = GetLinkParts(linknumber); List<SceneObjectPart> parts = GetLinkParts(linknumber);
foreach (SceneObjectPart part in parts) foreach (SceneObjectPart part in parts)
SetColor(part, color, face); part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face);
} }
public void llCreateLink(string target, int parent) public void llCreateLink(string target, int parent)
@ -4262,7 +4228,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
if (item.Type == 10 && item.ItemID == m_itemID) if (item.Type == 10 && item.ItemID == m_itemID)
{ {
result = item.Name!=null?item.Name:String.Empty; result = item.Name != null ? item.Name : String.Empty;
break; break;
} }
} }
@ -4271,63 +4237,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return result; return result;
} }
// this function to understand which shape it is (taken from meshmerizer)
// quite useful can be used by meshmerizer to have a centralized point of understanding the shape
// except that it refers to scripting constants
public int getScriptPrimType(PrimitiveBaseShape primShape)
{
if (primShape.SculptEntry)
return ScriptBaseClass.PRIM_TYPE_SCULPT;
if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
{
if (primShape.PathCurve == (byte)Extrusion.Straight)
return ScriptBaseClass.PRIM_TYPE_BOX;
else if (primShape.PathCurve == (byte)Extrusion.Curve1)
return ScriptBaseClass.PRIM_TYPE_TUBE;
}
else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
{
if (primShape.PathCurve == (byte)Extrusion.Straight)
return ScriptBaseClass.PRIM_TYPE_CYLINDER;
// ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
else if (primShape.PathCurve == (byte)Extrusion.Curve1)
return ScriptBaseClass.PRIM_TYPE_TORUS;
}
else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
{
if (primShape.PathCurve == (byte)Extrusion.Curve1 || primShape.PathCurve == (byte)Extrusion.Curve2)
return ScriptBaseClass.PRIM_TYPE_SPHERE;
}
else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
{
if (primShape.PathCurve == (byte)Extrusion.Straight)
return ScriptBaseClass.PRIM_TYPE_PRISM;
else if (primShape.PathCurve == (byte)Extrusion.Curve1)
return ScriptBaseClass.PRIM_TYPE_RING;
}
return ScriptBaseClass.PRIM_TYPE_BOX;
}
// Helper functions to understand if object has cut, hollow, dimple, and other affecting number of faces
protected void hasCutHollowDimpleProfileCut(int primType, PrimitiveBaseShape shape, out bool hasCut, out bool hasHollow,
out bool hasDimple, out bool hasProfileCut)
{
if (primType == ScriptBaseClass.PRIM_TYPE_BOX
||
primType == ScriptBaseClass.PRIM_TYPE_CYLINDER
||
primType == ScriptBaseClass.PRIM_TYPE_PRISM)
hasCut = (shape.ProfileBegin > 0) || (shape.ProfileEnd > 0);
else
hasCut = (shape.PathBegin > 0) || (shape.PathEnd > 0);
hasHollow = shape.ProfileHollow > 0;
hasDimple = (shape.ProfileBegin > 0) || (shape.ProfileEnd > 0); // taken from llSetPrimitiveParms
hasProfileCut = hasDimple; // is it the same thing?
}
public LSL_Integer llGetNumberOfSides() public LSL_Integer llGetNumberOfSides()
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
@ -4337,63 +4246,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
protected int GetNumberOfSides(SceneObjectPart part) protected int GetNumberOfSides(SceneObjectPart part)
{ {
int ret = 0; int sides = part.GetNumberOfSides();
bool hasCut;
bool hasHollow;
bool hasDimple;
bool hasProfileCut;
int primType = getScriptPrimType(part.Shape); if (part.GetPrimType() == PrimType.SPHERE && part.Shape.ProfileHollow > 0)
hasCutHollowDimpleProfileCut(primType, part.Shape, out hasCut, out hasHollow, out hasDimple, out hasProfileCut);
switch (primType)
{ {
case ScriptBaseClass.PRIM_TYPE_BOX: // Make up for a bug where LSL shows 4 sides rather than 2
ret = 6; sides += 2;
if (hasCut) ret += 2;
if (hasHollow) ret += 1;
break;
case ScriptBaseClass.PRIM_TYPE_CYLINDER:
ret = 3;
if (hasCut) ret += 2;
if (hasHollow) ret += 1;
break;
case ScriptBaseClass.PRIM_TYPE_PRISM:
ret = 5;
if (hasCut) ret += 2;
if (hasHollow) ret += 1;
break;
case ScriptBaseClass.PRIM_TYPE_SPHERE:
ret = 1;
if (hasCut) ret += 2;
if (hasDimple) ret += 2;
if (hasHollow) ret += 3; // Emulate lsl on secondlife (according to documentation it should have added only +1)
break;
case ScriptBaseClass.PRIM_TYPE_TORUS:
ret = 1;
if (hasCut) ret += 2;
if (hasProfileCut) ret += 2;
if (hasHollow) ret += 1;
break;
case ScriptBaseClass.PRIM_TYPE_TUBE:
ret = 4;
if (hasCut) ret += 2;
if (hasProfileCut) ret += 2;
if (hasHollow) ret += 1;
break;
case ScriptBaseClass.PRIM_TYPE_RING:
ret = 3;
if (hasCut) ret += 2;
if (hasProfileCut) ret += 2;
if (hasHollow) ret += 1;
break;
case ScriptBaseClass.PRIM_TYPE_SCULPT:
ret = 1;
break;
} }
return ret;
}
return sides;
}
/* The new / changed functions were tested with the following LSL script: /* The new / changed functions were tested with the following LSL script:
@ -4418,8 +4281,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
} }
*/ */
// Xantor 29/apr/2008 // Xantor 29/apr/2008
// Returns rotation described by rotating angle radians about axis. // Returns rotation described by rotating angle radians about axis.
// q = cos(a/2) + i (x * sin(a/2)) + j (y * sin(a/2)) + k (z * sin(a/2)) // q = cos(a/2) + i (x * sin(a/2)) + j (y * sin(a/2)) + k (z * sin(a/2))
@ -7020,10 +6881,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
LSL_Vector color=rules.GetVector3Item(idx++); LSL_Vector color=rules.GetVector3Item(idx++);
double alpha=(double)rules.GetLSLFloatItem(idx++); double alpha=(double)rules.GetLSLFloatItem(idx++);
SetColor(part, color, face); part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face);
SetAlpha(part, alpha, face); SetAlpha(part, alpha, face);
break; break;
case (int)ScriptBaseClass.PRIM_FLEXIBLE: case (int)ScriptBaseClass.PRIM_FLEXIBLE:
if (remain < 7) if (remain < 7)
return; return;
@ -7039,6 +6901,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
SetFlexi(part, flexi, softness, gravity, friction, wind, tension, force); SetFlexi(part, flexi, softness, gravity, friction, wind, tension, force);
break; break;
case (int)ScriptBaseClass.PRIM_POINT_LIGHT: case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
if (remain < 5) if (remain < 5)
return; return;
@ -7051,6 +6914,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
SetPointLight(part, light, lightcolor, intensity, radius, falloff); SetPointLight(part, light, lightcolor, intensity, radius, falloff);
break; break;
case (int)ScriptBaseClass.PRIM_GLOW: case (int)ScriptBaseClass.PRIM_GLOW:
if (remain < 2) if (remain < 2)
return; return;
@ -7060,6 +6924,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
SetGlow(part, face, glow); SetGlow(part, face, glow);
break; break;
case (int)ScriptBaseClass.PRIM_BUMP_SHINY: case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
if (remain < 3) if (remain < 3)
return; return;
@ -7070,6 +6935,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
SetShiny(part, face, shiny, bump); SetShiny(part, face, shiny, bump);
break; break;
case (int)ScriptBaseClass.PRIM_FULLBRIGHT: case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
if (remain < 2) if (remain < 2)
return; return;
@ -7077,6 +6943,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
bool st = rules.GetLSLIntegerItem(idx++); bool st = rules.GetLSLIntegerItem(idx++);
SetFullBright(part, face , st); SetFullBright(part, face , st);
break; break;
case (int)ScriptBaseClass.PRIM_MATERIAL: case (int)ScriptBaseClass.PRIM_MATERIAL:
if (remain < 1) if (remain < 1)
return; return;
@ -7086,6 +6953,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
part.Material = Convert.ToByte(mat); part.Material = Convert.ToByte(mat);
break; break;
case (int)ScriptBaseClass.PRIM_PHANTOM: case (int)ScriptBaseClass.PRIM_PHANTOM:
if (remain < 1) if (remain < 1)
return; return;
@ -7100,6 +6968,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
part.ScriptSetPhantomStatus(phantom); part.ScriptSetPhantomStatus(phantom);
break; break;
case (int)ScriptBaseClass.PRIM_PHYSICS: case (int)ScriptBaseClass.PRIM_PHYSICS:
if (remain < 1) if (remain < 1)
return; return;
@ -7113,6 +6982,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
part.ScriptSetPhysicsStatus(physics); part.ScriptSetPhysicsStatus(physics);
break; break;
case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
if (remain < 1) if (remain < 1)
return; return;
@ -7380,7 +7250,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public LSL_List GetLinkPrimitiveParams(SceneObjectPart part, LSL_List rules) public LSL_List GetLinkPrimitiveParams(SceneObjectPart part, LSL_List rules)
{ {
LSL_List res = new LSL_List(); LSL_List res = new LSL_List();
int idx=0; int idx=0;
while (idx < rules.Length) while (idx < rules.Length)
@ -7442,7 +7311,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_TYPE: case (int)ScriptBaseClass.PRIM_TYPE:
// implementing box // implementing box
PrimitiveBaseShape Shape = part.Shape; PrimitiveBaseShape Shape = part.Shape;
int primType = getScriptPrimType(part.Shape); int primType = (int)part.GetPrimType();
res.Add(new LSL_Integer(primType)); res.Add(new LSL_Integer(primType));
double topshearx = (double)(sbyte)Shape.PathShearX / 100.0; // Fix negative values for PathShearX double topshearx = (double)(sbyte)Shape.PathShearX / 100.0; // Fix negative values for PathShearX
double topsheary = (double)(sbyte)Shape.PathShearY / 100.0; // and PathShearY. double topsheary = (double)(sbyte)Shape.PathShearY / 100.0; // and PathShearY.
@ -7522,7 +7391,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
Primitive.TextureEntry tex = part.Shape.Textures; Primitive.TextureEntry tex = part.Shape.Textures;
if (face == ScriptBaseClass.ALL_SIDES) if (face == ScriptBaseClass.ALL_SIDES)
{ {
for (face = 0 ; face < GetNumberOfSides(part) ; face++) for (face = 0 ; face < GetNumberOfSides(part); face++)
{ {
Primitive.TextureEntryFace texface = tex.GetFace((uint)face); Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
@ -7564,7 +7433,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
Color4 texcolor; Color4 texcolor;
if (face == ScriptBaseClass.ALL_SIDES) if (face == ScriptBaseClass.ALL_SIDES)
{ {
for (face = 0 ; face < GetNumberOfSides(part) ; face++) for (face = 0 ; face < GetNumberOfSides(part); face++)
{ {
texcolor = tex.GetFace((uint)face).RGBA; texcolor = tex.GetFace((uint)face).RGBA;
res.Add(new LSL_Vector(texcolor.R, res.Add(new LSL_Vector(texcolor.R,

View File

@ -55,6 +55,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
m_log.Info("[XEngine] Hooking up to server events"); m_log.Info("[XEngine] Hooking up to server events");
myScriptEngine.World.EventManager.OnAttach += attach; myScriptEngine.World.EventManager.OnAttach += attach;
myScriptEngine.World.EventManager.OnObjectGrab += touch_start; myScriptEngine.World.EventManager.OnObjectGrab += touch_start;
myScriptEngine.World.EventManager.OnObjectGrabbing += touch;
myScriptEngine.World.EventManager.OnObjectDeGrab += touch_end; myScriptEngine.World.EventManager.OnObjectDeGrab += touch_end;
myScriptEngine.World.EventManager.OnScriptChangedEvent += changed; myScriptEngine.World.EventManager.OnScriptChangedEvent += changed;
myScriptEngine.World.EventManager.OnScriptAtTargetEvent += at_target; myScriptEngine.World.EventManager.OnScriptAtTargetEvent += at_target;
@ -148,7 +149,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
} }
public void touch(uint localID, uint originalID, Vector3 offsetPos, public void touch(uint localID, uint originalID, Vector3 offsetPos,
IClientAPI remoteClient) IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs)
{ {
// Add to queue for all scripts in ObjectID object // Add to queue for all scripts in ObjectID object
DetectParams[] det = new DetectParams[1]; DetectParams[] det = new DetectParams[1];
@ -172,6 +173,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
SceneObjectPart originalPart = myScriptEngine.World.GetSceneObjectPart(originalID); SceneObjectPart originalPart = myScriptEngine.World.GetSceneObjectPart(originalID);
det[0].LinkNum = originalPart.LinkNum; det[0].LinkNum = originalPart.LinkNum;
} }
if (surfaceArgs != null)
{
det[0].SurfaceTouchArgs = surfaceArgs;
}
myScriptEngine.PostObjectEvent(localID, new EventParams( myScriptEngine.PostObjectEvent(localID, new EventParams(
"touch", new Object[] { new LSL_Types.LSLInteger(1) }, "touch", new Object[] { new LSL_Types.LSLInteger(1) },

View File

@ -806,12 +806,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine
instance.ClearQueue(); instance.ClearQueue();
instance.Stop(0); instance.Stop(0);
SceneObjectPart part =
m_Scene.GetSceneObjectPart(localID);
if (part != null)
part.RemoveScriptEvents(itemID);
// bool objectRemoved = false; // bool objectRemoved = false;
lock (m_PrimObjects) lock (m_PrimObjects)
@ -846,7 +840,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
ObjectRemoved handlerObjectRemoved = OnObjectRemoved; ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
if (handlerObjectRemoved != null) if (handlerObjectRemoved != null)
{
SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
handlerObjectRemoved(part.UUID); handlerObjectRemoved(part.UUID);
}
CleanAssemblies(); CleanAssemblies();
} }

View File

@ -63,7 +63,7 @@ namespace OpenSim.Server.Handlers.Asset
if (p.Length > 0) if (p.Length > 0)
{ {
result = m_AssetService.Delete(p[0]); // result = m_AssetService.Delete(p[0]);
} }
XmlSerializer xs = new XmlSerializer(typeof(bool)); XmlSerializer xs = new XmlSerializer(typeof(bool));

View File

@ -0,0 +1,251 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Xml;
using log4net;
using Nini.Config;
namespace Careminster
{
/// <summary>
/// Loads the Configuration files into nIni
/// </summary>
public class ConfigurationLoader
{
/// <summary>
/// A source of Configuration data
/// </summary>
protected IConfigSource m_config;
/// <summary>
/// Console logger
/// </summary>
private static readonly ILog m_log =
LogManager.GetLogger(
MethodBase.GetCurrentMethod().DeclaringType);
public ConfigurationLoader()
{
}
/// <summary>
/// Loads the region configuration
/// </summary>
/// <param name="argvSource">Parameters passed into the process when started</param>
/// <param name="configSettings"></param>
/// <param name="networkInfo"></param>
/// <returns>A configuration that gets passed to modules</returns>
public IConfigSource LoadConfigSettings()
{
bool iniFileExists = false;
List<string> sources = new List<string>();
string iniFileName = "OpenSim.ini";
string iniFilePath = Path.Combine(".", iniFileName);
if (IsUri(iniFileName))
{
if (!sources.Contains(iniFileName))
sources.Add(iniFileName);
}
else
{
if (File.Exists(iniFilePath))
{
if (!sources.Contains(iniFilePath))
sources.Add(iniFilePath);
}
}
m_config = new IniConfigSource();
m_config.Merge(DefaultConfig());
m_log.Info("[CONFIG] Reading configuration settings");
if (sources.Count == 0)
{
m_log.FatalFormat("[CONFIG] Could not load any configuration");
m_log.FatalFormat("[CONFIG] Did you copy the OpenSim.ini.example file to OpenSim.ini?");
Environment.Exit(1);
}
for (int i = 0 ; i < sources.Count ; i++)
{
if (ReadConfig(sources[i]))
iniFileExists = true;
AddIncludes(sources);
}
if (!iniFileExists)
{
m_log.FatalFormat("[CONFIG] Could not load any configuration");
m_log.FatalFormat("[CONFIG] Configuration exists, but there was an error loading it!");
Environment.Exit(1);
}
return m_config;
}
/// <summary>
/// Adds the included files as ini configuration files
/// </summary>
/// <param name="sources">List of URL strings or filename strings</param>
private void AddIncludes(List<string> sources)
{
//loop over config sources
foreach (IConfig config in m_config.Configs)
{
// Look for Include-* in the key name
string[] keys = config.GetKeys();
foreach (string k in keys)
{
if (k.StartsWith("Include-"))
{
// read the config file to be included.
string file = config.GetString(k);
if (IsUri(file))
{
if (!sources.Contains(file))
sources.Add(file);
}
else
{
string basepath = Path.GetFullPath(".");
string path = Path.Combine(basepath, file);
string[] paths = Util.Glob(path);
foreach (string p in paths)
{
if (!sources.Contains(p))
sources.Add(p);
}
}
}
}
}
}
/// <summary>
/// Check if we can convert the string to a URI
/// </summary>
/// <param name="file">String uri to the remote resource</param>
/// <returns>true if we can convert the string to a Uri object</returns>
bool IsUri(string file)
{
Uri configUri;
return Uri.TryCreate(file, UriKind.Absolute,
out configUri) && configUri.Scheme == Uri.UriSchemeHttp;
}
/// <summary>
/// Provide same ini loader functionality for standard ini and master ini - file system or XML over http
/// </summary>
/// <param name="iniPath">Full path to the ini</param>
/// <returns></returns>
private bool ReadConfig(string iniPath)
{
bool success = false;
if (!IsUri(iniPath))
{
m_log.InfoFormat("[CONFIG] Reading configuration file {0}",
Path.GetFullPath(iniPath));
m_config.Merge(new IniConfigSource(iniPath));
success = true;
}
else
{
m_log.InfoFormat("[CONFIG] {0} is a http:// URI, fetching ...",
iniPath);
// The ini file path is a http URI
// Try to read it
//
try
{
XmlReader r = XmlReader.Create(iniPath);
XmlConfigSource cs = new XmlConfigSource(r);
m_config.Merge(cs);
success = true;
}
catch (Exception e)
{
m_log.FatalFormat("[CONFIG] Exception reading config from URI {0}\n" + e.ToString(), iniPath);
Environment.Exit(1);
}
}
return success;
}
/// <summary>
/// Setup a default config values in case they aren't present in the ini file
/// </summary>
/// <returns>A Configuration source containing the default configuration</returns>
private static IConfigSource DefaultConfig()
{
IConfigSource defaultConfig = new IniConfigSource();
{
IConfig config = defaultConfig.Configs["Startup"];
if (null == config)
config = defaultConfig.AddConfig("Startup");
config.Set("region_info_source", "filesystem");
config.Set("gridmode", false);
config.Set("physics", "OpenDynamicsEngine");
config.Set("meshing", "Meshmerizer");
config.Set("physical_prim", true);
config.Set("see_into_this_sim_from_neighbor", true);
config.Set("serverside_object_permissions", false);
config.Set("storage_plugin", "OpenSim.Data.SQLite.dll");
config.Set("storage_connection_string", "URI=file:OpenSim.db,version=3");
config.Set("storage_prim_inventories", true);
config.Set("startup_console_commands_file", String.Empty);
config.Set("shutdown_console_commands_file", String.Empty);
config.Set("DefaultScriptEngine", "XEngine");
config.Set("clientstack_plugin", "OpenSim.Region.ClientStack.LindenUDP.dll");
// life doesn't really work without this
config.Set("EventQueue", true);
}
{
IConfig config = defaultConfig.Configs["StandAlone"];
if (null == config)
config = defaultConfig.AddConfig("StandAlone");
config.Set("accounts_authenticate", true);
config.Set("welcome_message", "Welcome to OpenSimulator");
config.Set("inventory_plugin", "OpenSim.Data.SQLite.dll");
config.Set("inventory_source", "");
config.Set("userDatabase_plugin", "OpenSim.Data.SQLite.dll");
config.Set("user_source", "");
config.Set("LibrariesXMLFile", string.Format(".{0}inventory{0}Libraries.xml", Path.DirectorySeparatorChar));
}
{
IConfig config = defaultConfig.Configs["Network"];
if (null == config)
config = defaultConfig.AddConfig("Network");
config.Set("default_location_x", 1000);
config.Set("default_location_y", 1000);
config.Set("grid_send_key", "null");
config.Set("grid_recv_key", "null");
config.Set("user_send_key", "null");
config.Set("user_recv_key", "null");
config.Set("secure_inventory_server", "true");
}
return defaultConfig;
}
}
}

View File

@ -0,0 +1,108 @@
using Nini.Config;
using System;
namespace Careminster
{
public class Configger
{
public static int Main(string[] args)
{
ArgvConfigSource argvConfig = new ArgvConfigSource(args);
argvConfig.AddSwitch("Startup", "format", "f");
IConfig startupConfig = argvConfig.Configs["Startup"];
string format = startupConfig.GetString("format", "ini");
ConfigurationLoader loader = new ConfigurationLoader();
IConfigSource s = loader.LoadConfigSettings();
if (format == "mysql")
{
foreach (IConfig c in s.Configs)
{
foreach (string k in c.GetKeys())
{
string v = c.GetString(k);
if (k.StartsWith("Include-"))
continue;
Console.WriteLine("insert ignore into config (section, name, value) values ('{0}', '{1}', '{2}');", c.Name, k, v);
}
}
}
else if (format == "xml")
{
Console.WriteLine("<Nini>");
foreach (IConfig c in s.Configs)
{
int count = 0;
foreach (string k in c.GetKeys())
{
if (k.StartsWith("Include-"))
continue;
count++;
}
if (count > 0)
{
Console.WriteLine("<Section Name=\"{0}\">", c.Name);
foreach (string k in c.GetKeys())
{
string v = c.GetString(k);
if (k.StartsWith("Include-"))
continue;
Console.WriteLine(" <Key Name=\"{0}\" Value=\"{1}\" />", k, v);
Console.WriteLine("</Section>");
}
}
}
Console.WriteLine("</Nini>");
}
else if (format == "ini")
{
foreach (IConfig c in s.Configs)
{
int count = 0;
foreach (string k in c.GetKeys())
{
if (k.StartsWith("Include-"))
continue;
count++;
}
if (count > 0)
{
Console.WriteLine("[{0}]", c.Name);
foreach (string k in c.GetKeys())
{
string v = c.GetString(k);
if (k.StartsWith("Include-"))
continue;
Console.WriteLine("{0} = \"{1}\"", k, v);
}
Console.WriteLine();
}
}
}
else
{
Console.WriteLine("Error: unknown format: {0}", format);
}
return 0;
}
}
}

View File

@ -0,0 +1,79 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using log4net;
using Nini.Config;
namespace Careminster
{
public static class Util
{
public static string[] Glob(string path)
{
string vol=String.Empty;
if (Path.VolumeSeparatorChar != Path.DirectorySeparatorChar)
{
string[] vcomps = path.Split(new char[] {Path.VolumeSeparatorChar}, 2, StringSplitOptions.RemoveEmptyEntries);
if (vcomps.Length > 1)
{
path = vcomps[1];
vol = vcomps[0];
}
}
string[] comps = path.Split(new char[] {Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar}, StringSplitOptions.RemoveEmptyEntries);
// Glob
path = vol;
if (vol != String.Empty)
path += new String(new char[] {Path.VolumeSeparatorChar, Path.DirectorySeparatorChar});
else
path = new String(new char[] {Path.DirectorySeparatorChar});
List<string> paths = new List<string>();
List<string> found = new List<string>();
paths.Add(path);
int compIndex = -1;
foreach (string c in comps)
{
compIndex++;
List<string> addpaths = new List<string>();
foreach (string p in paths)
{
string[] dirs = Directory.GetDirectories(p, c);
if (dirs.Length != 0)
{
foreach (string dir in dirs)
addpaths.Add(Path.Combine(path, dir));
}
// Only add files if that is the last path component
if (compIndex == comps.Length - 1)
{
string[] files = Directory.GetFiles(p, c);
foreach (string f in files)
found.Add(f);
}
}
paths = addpaths;
}
return found.ToArray();
}
}
}

View File

@ -123,3 +123,16 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003
WelcomeMessage = "Welcome, Avatar!" WelcomeMessage = "Welcome, Avatar!"
; * This is the new style grid service.
; * "Realm" is the table that is used for user lookup.
; * It defaults to "regions", which uses the legacy tables
; *
[GridService]
LocalServiceModule = "OpenSim.Services.GridService.dll:GridService"
StorageProvider = "OpenSim.Data.MySQL.dll:MySqlRegionData"
ConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=grid;"
Realm = "regions"
; If true, duplicate region names are allowed on the grid. If false, no duplicate names are allowed
; Default is false
; AllowDuplicateNames = "True"

2
bin/OpenSim.exe.config Normal file → Executable file
View File

@ -12,7 +12,7 @@
<log4net> <log4net>
<appender name="Console" type="OpenSim.Framework.Console.OpenSimAppender, OpenSim.Framework.Console"> <appender name="Console" type="OpenSim.Framework.Console.OpenSimAppender, OpenSim.Framework.Console">
<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" />
</layout> </layout>
</appender> </appender>

View File

@ -191,6 +191,7 @@
; This allows somne control over permissions ; This allows somne control over permissions
; please note that this still doesn't duplicate SL, and is not intended to ; please note that this still doesn't duplicate SL, and is not intended to
;region_owner_is_god = true ;region_owner_is_god = true
;region_manager_is_god = false
;parcel_owner_is_god = true ;parcel_owner_is_god = true
; Control user types that are allowed to create new scripts ; Control user types that are allowed to create new scripts

View File

@ -1915,6 +1915,7 @@
<Reference name="OpenMetaverseTypes.dll"/> <Reference name="OpenMetaverseTypes.dll"/>
<Reference name="OpenMetaverse.dll"/> <Reference name="OpenMetaverse.dll"/>
<Reference name="Nini.dll" /> <Reference name="Nini.dll" />
<Reference name="Mono.Addins" />
<Reference name="log4net.dll" /> <Reference name="log4net.dll" />
<Files> <Files>
<Match pattern="*.cs" recurse="true"/> <Match pattern="*.cs" recurse="true"/>
@ -1976,6 +1977,7 @@
<Reference name="log4net.dll"/> <Reference name="log4net.dll"/>
<Reference name="protobuf-net"/> <Reference name="protobuf-net"/>
<Reference name="MXP.dll"/> <Reference name="MXP.dll"/>
<Reference name="Mono.Addins"/>
<Files> <Files>
<Match pattern="*.cs" recurse="true"/> <Match pattern="*.cs" recurse="true"/>
</Files> </Files>
@ -2486,6 +2488,7 @@
<Reference name="OpenSim.Framework.Statistics"/> <Reference name="OpenSim.Framework.Statistics"/>
<Reference name="OpenSim.Region.Physics.Manager"/> <Reference name="OpenSim.Region.Physics.Manager"/>
<Reference name="Mono.Data.SqliteClient"/> <Reference name="Mono.Data.SqliteClient"/>
<Reference name="Mono.Addins"/>
<!-- For scripting in funny languages by default --> <!-- For scripting in funny languages by default -->
<Reference name="Microsoft.JScript"/> <Reference name="Microsoft.JScript"/>
@ -2557,6 +2560,28 @@
</Files> </Files>
</Project> </Project>
<Project frameworkVersion="v3_5" name="OpenSim.Tools.Configger" path="OpenSim/Tools/Configger" type="Exe">
<Configuration name="Debug">
<Options>
<OutputPath>../../../bin/</OutputPath>
</Options>
</Configuration>
<Configuration name="Release">
<Options>
<OutputPath>../../../bin/</OutputPath>
</Options>
</Configuration>
<ReferencePath>../../../bin/</ReferencePath>
<Reference name="System"/>
<Reference name="Nini.dll"/>
<Reference name="log4net.dll"/>
<Files>
<Match pattern="*.cs" recurse="true"/>
</Files>
</Project>
<!-- Test Suite --> <!-- Test Suite -->
<Project frameworkVersion="v3_5" name="OpenSim.TestSuite" path="OpenSim/TestSuite" type="Exe"> <Project frameworkVersion="v3_5" name="OpenSim.TestSuite" path="OpenSim/TestSuite" type="Exe">
<Configuration name="Debug"> <Configuration name="Debug">
@ -2963,6 +2988,7 @@
<Match path="Agent/TextureSender/Tests" pattern="*.cs" recurse="true" /> <Match path="Agent/TextureSender/Tests" pattern="*.cs" recurse="true" />
<Match path="Avatar/Inventory/Archiver/Tests" pattern="*.cs" recurse="true" /> <Match path="Avatar/Inventory/Archiver/Tests" pattern="*.cs" recurse="true" />
<Match path="World/Archiver/Tests" pattern="*.cs" recurse="true" /> <Match path="World/Archiver/Tests" pattern="*.cs" recurse="true" />
<Match path="World/Archiver/Tests/Resources" pattern="*" buildAction="EmbeddedResource"/>
<Match path="World/Serialiser/Tests" pattern="*.cs" recurse="true" /> <Match path="World/Serialiser/Tests" pattern="*.cs" recurse="true" />
<Match path="World/Terrain/Tests" pattern="*.cs" recurse="true" /> <Match path="World/Terrain/Tests" pattern="*.cs" recurse="true" />
<Match path="ServiceConnectorsOut/Grid/Tests" pattern="*.cs" recurse="true" /> <Match path="ServiceConnectorsOut/Grid/Tests" pattern="*.cs" recurse="true" />