Merge branch 'master' into careminster

avinationmerge
Melanie 2010-02-08 22:11:38 +00:00
commit c8f3bb56ff
32 changed files with 2899 additions and 2727 deletions

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");
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
Migration m = new Migration(dbcon, assem, "AssetStore");
m.Update(); 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,14 +104,16 @@ 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()); cmd.Parameters.AddWithValue("?id", assetID.ToString());
try try
@ -152,8 +123,8 @@ namespace OpenSim.Data.MySQL
if (dbReader.Read()) if (dbReader.Read())
{ {
asset = new AssetBase(assetID, (string)dbReader["name"], (sbyte)dbReader["assetType"]); asset = new AssetBase(assetID, (string)dbReader["name"], (sbyte)dbReader["assetType"]);
asset.Data = (byte[]) dbReader["data"]; asset.Data = (byte[])dbReader["data"];
asset.Description = (string) dbReader["description"]; 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))
@ -163,18 +134,13 @@ namespace OpenSim.Data.MySQL
asset.Temporary = Convert.ToBoolean(dbReader["temporary"]); asset.Temporary = Convert.ToBoolean(dbReader["temporary"]);
} }
dbReader.Close();
cmd.Dispose();
} }
if (asset != null)
UpdateAccessTime(asset);
} }
catch (Exception e) catch (Exception e)
{ {
m_log.ErrorFormat( m_log.Error("[ASSETS DB]: MySql failure fetching asset " + assetID + ": " + e.Message);
"[ASSETS DB]: MySql failure fetching asset {0}" + Environment.NewLine + e.ToString() }
+ Environment.NewLine + "Reconnecting", assetID); }
_dbConnection.Reconnect();
} }
} }
return asset; return asset;
@ -187,15 +153,17 @@ 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)
@ -233,9 +201,9 @@ namespace OpenSim.Data.MySQL
} }
catch (Exception e) catch (Exception e)
{ {
m_log.ErrorFormat("[ASSET DB]: MySQL failure creating asset {0} with name \"{1}\". Attempting reconnect. Error: {2}", m_log.ErrorFormat("[ASSET DB]: MySQL failure creating asset {0} with name \"{1}\". Error: {2}",
asset.FullID, asset.Name, e.Message); asset.FullID, asset.Name, e.Message);
_dbConnection.Reconnect(); }
} }
} }
} }
@ -245,13 +213,14 @@ 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))
{
dbcon.Open();
MySqlCommand cmd = MySqlCommand cmd =
new MySqlCommand("update assets set access_time=?access_time where id=?id", new MySqlCommand("update assets set access_time=?access_time where id=?id",
_dbConnection.Connection); dbcon);
// need to ensure we dispose // need to ensure we dispose
try try
@ -272,7 +241,7 @@ namespace OpenSim.Data.MySQL
"[ASSETS DB]: " + "[ASSETS DB]: " +
"MySql failure updating access_time for asset {0} with name {1}" + Environment.NewLine + e.ToString() "MySql failure updating access_time for asset {0} with name {1}" + Environment.NewLine + e.ToString()
+ Environment.NewLine + "Attempting reconnection", asset.FullID, asset.Name); + Environment.NewLine + "Attempting reconnection", asset.FullID, asset.Name);
_dbConnection.Reconnect(); }
} }
} }
@ -287,15 +256,13 @@ namespace OpenSim.Data.MySQL
{ {
bool assetExists = false; bool assetExists = false;
lock (_dbConnection) lock (m_dbLock)
{
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = new MySqlCommand("SELECT id FROM assets WHERE id=?id", dbcon))
{ {
_dbConnection.CheckConnection();
MySqlCommand cmd =
new MySqlCommand(
"SELECT id FROM assets WHERE id=?id",
_dbConnection.Connection);
cmd.Parameters.AddWithValue("?id", uuid.ToString()); cmd.Parameters.AddWithValue("?id", uuid.ToString());
try try
@ -303,20 +270,15 @@ namespace OpenSim.Data.MySQL
using (MySqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow)) using (MySqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow))
{ {
if (dbReader.Read()) if (dbReader.Read())
{
assetExists = true; assetExists = true;
} }
dbReader.Close();
cmd.Dispose();
}
} }
catch (Exception e) catch (Exception e)
{ {
m_log.ErrorFormat( m_log.ErrorFormat(
"[ASSETS DB]: MySql failure fetching asset {0}" + Environment.NewLine + e.ToString() "[ASSETS DB]: MySql failure fetching asset {0}" + Environment.NewLine + e.ToString(), uuid);
+ Environment.NewLine + "Attempting reconnection", uuid); }
_dbConnection.Reconnect(); }
} }
} }
@ -335,11 +297,12 @@ 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); 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("?start", start);
cmd.Parameters.AddWithValue("?count", count); cmd.Parameters.AddWithValue("?count", count);
@ -350,14 +313,14 @@ namespace OpenSim.Data.MySQL
while (dbReader.Read()) while (dbReader.Read())
{ {
AssetMetadata metadata = new AssetMetadata(); AssetMetadata metadata = new AssetMetadata();
metadata.Name = (string) dbReader["name"]; metadata.Name = (string)dbReader["name"];
metadata.Description = (string) dbReader["description"]; metadata.Description = (string)dbReader["description"];
metadata.Type = (sbyte) dbReader["assetType"]; metadata.Type = (sbyte)dbReader["assetType"];
metadata.Temporary = Convert.ToBoolean(dbReader["temporary"]); // Not sure if this is correct. metadata.Temporary = Convert.ToBoolean(dbReader["temporary"]); // Not sure if this is correct.
metadata.FullID = new UUID((string) dbReader["id"]); 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);
} }
@ -365,8 +328,8 @@ namespace OpenSim.Data.MySQL
} }
catch (Exception e) catch (Exception e)
{ {
m_log.Error("[ASSETS DB]: MySql failure fetching asset set" + Environment.NewLine + e.ToString() + Environment.NewLine + "Attempting reconnection"); m_log.Error("[ASSETS DB]: MySql failure fetching asset set" + Environment.NewLine + e.ToString());
_dbConnection.Reconnect(); }
} }
} }
@ -374,7 +337,5 @@ namespace OpenSim.Data.MySQL
} }
#endregion #endregion
} }
} }

View File

@ -38,30 +38,36 @@ 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))
{
dbcon.Open();
Migration m = new Migration(dbcon, GetType().Assembly, "AuthStore");
m.Update(); m.Update();
} }
}
public AuthenticationData Get(UUID principalID) public AuthenticationData Get(UUID principalID)
{ {
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" {
); dbcon.Open();
MySqlCommand cmd = new MySqlCommand("select * from `" + m_Realm + "` where UUID = ?principalID", dbcon);
cmd.Parameters.AddWithValue("?principalID", principalID.ToString()); cmd.Parameters.AddWithValue("?principalID", principalID.ToString());
IDataReader result = ExecuteReader(cmd); IDataReader result = cmd.ExecuteReader();
if (result.Read()) if (result.Read())
{ {
@ -84,17 +90,14 @@ namespace OpenSim.Data.MySQL
ret.Data[s] = result[s].ToString(); ret.Data[s] = result[s].ToString();
} }
result.Close();
CloseReaderCommand(cmd);
return ret; return ret;
} }
else
result.Close(); {
CloseReaderCommand(cmd);
return null; 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,13 +66,14 @@ 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();
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
Assembly assem = GetType().Assembly; Assembly assem = GetType().Assembly;
Migration m = new Migration(m_connection, assem, "EstateStore"); Migration m = new Migration(dbcon, assem, "EstateStore");
m.Update(); m.Update();
Type t = typeof(EstateSettings); Type t = typeof(EstateSettings);
@ -87,6 +87,7 @@ namespace OpenSim.Data.MySQL
m_FieldMap[f.Name.Substring(2)] = f; m_FieldMap[f.Name.Substring(2)] = f;
} }
} }
}
private string[] FieldList private string[] FieldList
{ {
@ -95,11 +96,13 @@ 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); {
dbcon.Open();
using (MySqlDataReader dbReader = using (MySqlCommand cmd = new MySqlCommand(m_waitTimeoutSelect, dbcon))
cmd.ExecuteReader(CommandBehavior.SingleRow)) {
using (MySqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow))
{ {
if (dbReader.Read()) if (dbReader.Read())
{ {
@ -107,9 +110,7 @@ namespace OpenSim.Data.MySQL
= Convert.ToInt32(dbReader["@@wait_timeout"]) * = Convert.ToInt32(dbReader["@@wait_timeout"]) *
TimeSpan.TicksPerSecond + m_waitTimeoutLeeway; TimeSpan.TicksPerSecond + m_waitTimeoutLeeway;
} }
}
dbReader.Close();
cmd.Dispose();
} }
m_lastConnectionUse = DateTime.Now.Ticks; m_lastConnectionUse = DateTime.Now.Ticks;
@ -118,24 +119,6 @@ namespace OpenSim.Data.MySQL
"[REGION DB]: Connection wait timeout {0} seconds", "[REGION DB]: Connection wait timeout {0} seconds",
m_waitTimeout / TimeSpan.TicksPerSecond); 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,19 +126,26 @@ 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))
{
dbcon.Open();
using (MySqlCommand cmd = dbcon.CreateCommand())
{
cmd.CommandText = sql; cmd.CommandText = sql;
cmd.Parameters.AddWithValue("?RegionID", regionID.ToString()); cmd.Parameters.AddWithValue("?RegionID", regionID.ToString());
IDataReader r = cmd.ExecuteReader(); using (IDataReader r = cmd.ExecuteReader())
{
if (r.Read()) if (r.Read())
{ {
migration = false;
foreach (string name in FieldList) foreach (string name in FieldList)
{ {
if (m_FieldMap[name].GetValue(es) is bool) if (m_FieldMap[name].GetValue(es) is bool)
@ -178,20 +168,21 @@ namespace OpenSim.Data.MySQL
m_FieldMap[name].SetValue(es, r[name]); m_FieldMap[name].SetValue(es, r[name]);
} }
} }
r.Close();
} }
else }
}
if (migration)
{ {
// Migration case // Migration case
//
r.Close();
List<string> names = new List<string>(FieldList); List<string> names = new List<string>(FieldList);
names.Remove("EstateID"); names.Remove("EstateID");
sql = "insert into estate_settings (" + String.Join(",", names.ToArray()) + ") values ( ?" + String.Join(", ?", names.ToArray()) + ")"; sql = "insert into estate_settings (" + String.Join(",", names.ToArray()) + ") values ( ?" + String.Join(", ?", names.ToArray()) + ")";
using (MySqlCommand cmd = dbcon.CreateCommand())
{
cmd.CommandText = sql; cmd.CommandText = sql;
cmd.Parameters.Clear(); cmd.Parameters.Clear();
@ -215,43 +206,32 @@ namespace OpenSim.Data.MySQL
cmd.CommandText = "select LAST_INSERT_ID() as id"; cmd.CommandText = "select LAST_INSERT_ID() as id";
cmd.Parameters.Clear(); cmd.Parameters.Clear();
r = cmd.ExecuteReader(); using (IDataReader r = cmd.ExecuteReader())
{
r.Read(); r.Read();
es.EstateID = Convert.ToUInt32(r["id"]); es.EstateID = Convert.ToUInt32(r["id"]);
}
r.Close();
cmd.CommandText = "insert into estate_map values (?RegionID, ?EstateID)"; cmd.CommandText = "insert into estate_map values (?RegionID, ?EstateID)";
cmd.Parameters.AddWithValue("?RegionID", regionID.ToString()); cmd.Parameters.AddWithValue("?RegionID", regionID.ToString());
cmd.Parameters.AddWithValue("?EstateID", es.EstateID.ToString()); cmd.Parameters.AddWithValue("?EstateID", es.EstateID.ToString());
// This will throw on dupe key // This will throw on dupe key
try try { cmd.ExecuteNonQuery(); }
{ catch (Exception) { }
cmd.ExecuteNonQuery();
}
catch (Exception)
{
}
// Munge and transfer the ban list // Munge and transfer the ban list
//
cmd.Parameters.Clear(); cmd.Parameters.Clear();
cmd.CommandText = "insert into estateban select " + es.EstateID.ToString() + ", bannedUUID, bannedIp, bannedIpHostMask, '' from regionban where regionban.regionUUID = ?UUID"; cmd.CommandText = "insert into estateban select " + es.EstateID.ToString() + ", bannedUUID, bannedIp, bannedIpHostMask, '' from regionban where regionban.regionUUID = ?UUID";
cmd.Parameters.AddWithValue("?UUID", regionID.ToString()); cmd.Parameters.AddWithValue("?UUID", regionID.ToString());
try try { cmd.ExecuteNonQuery(); }
{ catch (Exception) { }
cmd.ExecuteNonQuery();
}
catch (Exception)
{
}
es.Save(); es.Save();
} }
}
}
LoadBanList(es); LoadBanList(es);
@ -265,10 +245,12 @@ 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(); dbcon.Open();
using (MySqlCommand cmd = dbcon.CreateCommand())
{
cmd.CommandText = sql; cmd.CommandText = sql;
foreach (string name in FieldList) foreach (string name in FieldList)
@ -287,6 +269,8 @@ namespace OpenSim.Data.MySQL
} }
cmd.ExecuteNonQuery(); cmd.ExecuteNonQuery();
}
}
SaveBanList(es); SaveBanList(es);
SaveUUIDList(es.EstateID, "estate_managers", es.EstateManagers); SaveUUIDList(es.EstateID, "estate_managers", es.EstateManagers);
@ -298,15 +282,17 @@ namespace OpenSim.Data.MySQL
{ {
es.ClearBans(); es.ClearBans();
CheckConnection(); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
MySqlCommand cmd = m_connection.CreateCommand(); dbcon.Open();
using (MySqlCommand cmd = dbcon.CreateCommand())
{
cmd.CommandText = "select bannedUUID from estateban where EstateID = ?EstateID"; cmd.CommandText = "select bannedUUID from estateban where EstateID = ?EstateID";
cmd.Parameters.AddWithValue("?EstateID", es.EstateID); cmd.Parameters.AddWithValue("?EstateID", es.EstateID);
IDataReader r = cmd.ExecuteReader(); using (IDataReader r = cmd.ExecuteReader())
{
while (r.Read()) while (r.Read())
{ {
EstateBan eb = new EstateBan(); EstateBan eb = new EstateBan();
@ -319,15 +305,19 @@ namespace OpenSim.Data.MySQL
eb.BannedHostIPMask = "0.0.0.0"; eb.BannedHostIPMask = "0.0.0.0";
es.AddBan(eb); 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(); dbcon.Open();
using (MySqlCommand cmd = dbcon.CreateCommand())
{
cmd.CommandText = "delete from estateban where EstateID = ?EstateID"; cmd.CommandText = "delete from estateban where EstateID = ?EstateID";
cmd.Parameters.AddWithValue("?EstateID", es.EstateID.ToString()); cmd.Parameters.AddWithValue("?EstateID", es.EstateID.ToString());
@ -346,13 +336,17 @@ namespace OpenSim.Data.MySQL
cmd.Parameters.Clear(); 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(); dbcon.Open();
using (MySqlCommand cmd = dbcon.CreateCommand())
{
cmd.CommandText = "delete from " + table + " where EstateID = ?EstateID"; cmd.CommandText = "delete from " + table + " where EstateID = ?EstateID";
cmd.Parameters.AddWithValue("?EstateID", EstateID.ToString()); cmd.Parameters.AddWithValue("?EstateID", EstateID.ToString());
@ -371,20 +365,24 @@ namespace OpenSim.Data.MySQL
cmd.Parameters.Clear(); cmd.Parameters.Clear();
} }
} }
}
}
UUID[] LoadUUIDList(uint EstateID, string table) UUID[] LoadUUIDList(uint EstateID, string table)
{ {
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(); dbcon.Open();
using (MySqlCommand cmd = dbcon.CreateCommand())
{
cmd.CommandText = "select uuid from " + table + " where EstateID = ?EstateID"; cmd.CommandText = "select uuid from " + table + " where EstateID = ?EstateID";
cmd.Parameters.AddWithValue("?EstateID", EstateID); cmd.Parameters.AddWithValue("?EstateID", EstateID);
IDataReader r = cmd.ExecuteReader(); using (IDataReader r = cmd.ExecuteReader())
{
while (r.Read()) while (r.Read())
{ {
// EstateBan eb = new EstateBan(); // EstateBan eb = new EstateBan();
@ -394,7 +392,9 @@ namespace OpenSim.Data.MySQL
uuids.Add(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,13 +54,17 @@ 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();
Migration m = new Migration(dbcon, GetType().Assembly, storeName);
m.Update(); m.Update();
} }
}
Type t = typeof(T); Type t = typeof(T);
FieldInfo[] fields = t.GetFields(BindingFlags.Public | FieldInfo[] fields = t.GetFields(BindingFlags.Public |
@ -107,8 +111,8 @@ 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++) for (int i = 0 ; i < fields.Length ; i++)
{ {
cmd.Parameters.AddWithValue(fields[i], keys[i]); cmd.Parameters.AddWithValue(fields[i], keys[i]);
@ -124,17 +128,24 @@ namespace OpenSim.Data.MySQL
return DoQuery(cmd); return DoQuery(cmd);
} }
}
protected T[] DoQuery(MySqlCommand cmd) protected T[] DoQuery(MySqlCommand cmd)
{ {
IDataReader reader = ExecuteReader(cmd); List<T> result = new List<T>();
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
cmd.Connection = dbcon;
using (IDataReader reader = cmd.ExecuteReader())
{
if (reader == null) if (reader == null)
return new T[0]; return new T[0];
CheckColumnNames(reader); CheckColumnNames(reader);
List<T> result = new List<T>();
while (reader.Read()) while (reader.Read())
{ {
T row = new T(); T row = new T();
@ -181,15 +192,16 @@ namespace OpenSim.Data.MySQL
result.Add(row); result.Add(row);
} }
}
CloseReaderCommand(cmd); }
return result.ToArray(); return result.ToArray();
} }
public T[] Get(string where) public T[] Get(string where)
{ {
MySqlCommand cmd = new MySqlCommand(); using (MySqlCommand cmd = new MySqlCommand())
{
string query = String.Format("select * from {0} where {1}", string query = String.Format("select * from {0} where {1}",
m_Realm, where); m_Realm, where);
@ -198,10 +210,12 @@ namespace OpenSim.Data.MySQL
return DoQuery(cmd); return DoQuery(cmd);
} }
}
public bool Store(T row) public bool Store(T row)
{ {
MySqlCommand cmd = new MySqlCommand(); using (MySqlCommand cmd = new MySqlCommand())
{
string query = ""; string query = "";
List<String> names = new List<String>(); List<String> names = new List<String>();
@ -236,10 +250,12 @@ namespace OpenSim.Data.MySQL
return false; return false;
} }
}
public bool Delete(string field, string val) public 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);
@ -250,4 +266,5 @@ namespace OpenSim.Data.MySQL
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,57 +67,24 @@ 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");
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
Migration m = new Migration(dbcon, assem, "GridStore");
m.Update(); m.Update();
} }
}
/// <summary> /// <summary>
/// Shuts down the grid interface /// Shuts down the grid interface
/// </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", dbcon.Open();
param);
IDataReader reader = result.ExecuteReader();
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; RegionProfileData row;
List<RegionProfileData> rows = new List<RegionProfileData>(); List<RegionProfileData> rows = new List<RegionProfileData>();
while ((row = dbm.Manager.readSimRow(reader)) != null) while ((row = m_database.readSimRow(reader)) != null)
{
rows.Add(row); rows.Add(row);
}
reader.Close();
result.Dispose();
return rows.ToArray(); 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", dbcon.Open();
param);
IDataReader reader = result.ExecuteReader();
using (IDbCommand result = m_database.Query(dbcon,
"SELECT * FROM regions WHERE regionName LIKE ?name",
param))
{
using (IDataReader reader = result.ExecuteReader())
{
RegionProfileData row; RegionProfileData row;
List<RegionProfileData> rows = new List<RegionProfileData>(); List<RegionProfileData> rows = new List<RegionProfileData>();
while (rows.Count < maxNum && (row = dbm.Manager.readSimRow(reader)) != null) while (rows.Count < maxNum && (row = m_database.readSimRow(reader)) != null)
{
rows.Add(row); rows.Add(row);
}
reader.Close();
result.Dispose();
return rows; 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);
reader.Close();
result.Dispose();
using (IDbCommand result = m_database.Query(dbcon, "SELECT * FROM regions WHERE regionHandle = ?handle", param))
{
using (IDataReader reader = result.ExecuteReader())
{
RegionProfileData row = m_database.readSimRow(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>
@ -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);
reader.Close();
result.Dispose();
using (IDbCommand result = m_database.Query(dbcon, "SELECT * FROM regions WHERE uuid = ?uuid", param))
{
using (IDataReader reader = result.ExecuteReader())
{
RegionProfileData row = m_database.readSimRow(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();
} }
} }
@ -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 + "%";
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
// Order by statement will return shorter matches first. Only returns one record or no record. // Order by statement will return shorter matches first. Only returns one record or no record.
IDbCommand result = using (IDbCommand result = m_database.Query(dbcon,
dbm.Manager.Query(
"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))
{ {
if (m_database.insertRegion(profile))
return DataResponse.RESPONSE_OK; return DataResponse.RESPONSE_OK;
} else
return DataResponse.RESPONSE_ERROR; return DataResponse.RESPONSE_ERROR;
} }
finally catch
{ {
dbm.Release(); 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))
{ {
if (m_database.deleteRegion(uuid))
return DataResponse.RESPONSE_OK; return DataResponse.RESPONSE_OK;
} else
return DataResponse.RESPONSE_ERROR; return DataResponse.RESPONSE_ERROR;
} finally }
catch
{ {
dbm.Release(); 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( using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (IDbCommand result = m_database.Query(dbcon,
"SELECT * FROM reservations WHERE resXMin <= ?x AND resXMax >= ?x AND resYMin <= ?y AND resYMax >= ?y", "SELECT * FROM reservations WHERE resXMin <= ?x AND resXMax >= ?x AND resYMin <= ?y AND resYMax >= ?y",
param); param))
IDataReader reader = result.ExecuteReader(); {
using (IDataReader reader = result.ExecuteReader())
ReservationData row = dbm.Manager.readReservationRow(reader); {
reader.Close(); ReservationData row = m_database.readReservationRow(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();
} }
} }
} }

View File

@ -26,7 +26,6 @@
*/ */
using System; using System;
using System.IO;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using log4net; using log4net;
@ -44,14 +43,10 @@ namespace OpenSim.Data.MySQL
private static readonly ILog m_log private static readonly ILog m_log
= LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
/// <summary> private string m_connectionString;
/// The database manager private object m_dbLock = new object();
/// </summary>
private MySQLManager database;
private bool rollbackStore = false; public string Version { get { return "1.0.0.0"; } }
private bool opengridmode = false;
private string rollbackDir = "";
public void Initialise() public void Initialise()
{ {
@ -72,38 +67,18 @@ namespace OpenSim.Data.MySQL
/// <param name="connect">connect string</param> /// <param name="connect">connect string</param>
public void Initialise(string connect) public void Initialise(string connect)
{ {
if (connect != String.Empty) m_connectionString = connect;
{
database = new MySQLManager(connect);
}
else
{
m_log.Warn("Reverting to deprecated mysql_connection.ini file for connection info");
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");
rollbackDir = GridDataMySqlFile.ParseFileReadValue("rollbackdir");
rollbackStore = GridDataMySqlFile.ParseFileReadValue("rollback") == "true";
opengridmode = GridDataMySqlFile.ParseFileReadValue("opengridmode") == "true";
if (rollbackStore)
m_log.Warn("[MysqlInventory] Enabling rollback mode in: " + rollbackDir);
database =
new MySQLManager(settingHostname, settingDatabase, settingUsername, settingPassword, settingPooling,
settingPort);
}
// 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, "InventoryStore");
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
Migration m = new Migration(dbcon, assem, "InventoryStore");
m.Update(); m.Update();
} }
}
/// <summary> /// <summary>
/// The name of this DB provider /// The name of this DB provider
@ -123,15 +98,6 @@ namespace OpenSim.Data.MySQL
// Do nothing. // Do nothing.
} }
/// <summary>
/// Returns the version of this DB provider
/// </summary>
/// <returns>A string containing the DB provider version</returns>
public string Version
{
get { return database.getVersion(); }
}
/// <summary> /// <summary>
/// Returns a list of items in a specified folder /// Returns a list of items in a specified folder
/// </summary> /// </summary>
@ -141,18 +107,20 @@ namespace OpenSim.Data.MySQL
{ {
try try
{ {
lock (database) lock (m_dbLock)
{ {
List<InventoryItemBase> items = new List<InventoryItemBase>(); List<InventoryItemBase> items = new List<InventoryItemBase>();
database.CheckConnection(); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
MySqlCommand result = using (MySqlCommand result = new MySqlCommand("SELECT * FROM inventoryitems WHERE parentFolderID = ?uuid", dbcon))
new MySqlCommand("SELECT * FROM inventoryitems WHERE parentFolderID = ?uuid", {
database.Connection);
result.Parameters.AddWithValue("?uuid", folderID.ToString()); result.Parameters.AddWithValue("?uuid", folderID.ToString());
MySqlDataReader reader = result.ExecuteReader();
using (MySqlDataReader reader = result.ExecuteReader())
{
while (reader.Read()) while (reader.Read())
{ {
// A null item (because something went wrong) breaks everything in the folder // A null item (because something went wrong) breaks everything in the folder
@ -161,16 +129,15 @@ namespace OpenSim.Data.MySQL
items.Add(item); items.Add(item);
} }
reader.Close();
result.Dispose();
return items; return items;
} }
} }
}
}
}
catch (Exception e) catch (Exception e)
{ {
database.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString());
return null; return null;
} }
} }
@ -184,33 +151,33 @@ namespace OpenSim.Data.MySQL
{ {
try try
{ {
lock (database) lock (m_dbLock)
{ {
database.CheckConnection(); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
MySqlCommand result = using (MySqlCommand result = new MySqlCommand(
new MySqlCommand( "SELECT * FROM inventoryfolders WHERE parentFolderID = ?zero AND agentID = ?uuid", dbcon))
"SELECT * FROM inventoryfolders WHERE parentFolderID = ?zero AND agentID = ?uuid", {
database.Connection);
result.Parameters.AddWithValue("?uuid", user.ToString()); result.Parameters.AddWithValue("?uuid", user.ToString());
result.Parameters.AddWithValue("?zero", UUID.Zero.ToString()); result.Parameters.AddWithValue("?zero", UUID.Zero.ToString());
MySqlDataReader reader = result.ExecuteReader();
using (MySqlDataReader reader = result.ExecuteReader())
{
List<InventoryFolderBase> items = new List<InventoryFolderBase>(); List<InventoryFolderBase> items = new List<InventoryFolderBase>();
while (reader.Read()) while (reader.Read())
items.Add(readInventoryFolder(reader)); items.Add(readInventoryFolder(reader));
reader.Close();
result.Dispose();
return items; return items;
} }
} }
}
}
}
catch (Exception e) catch (Exception e)
{ {
database.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString());
return null; return null;
} }
} }
@ -225,19 +192,20 @@ namespace OpenSim.Data.MySQL
{ {
try try
{ {
lock (database) lock (m_dbLock)
{ {
database.CheckConnection(); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
MySqlCommand result = using (MySqlCommand result = new MySqlCommand(
new MySqlCommand( "SELECT * FROM inventoryfolders WHERE parentFolderID = ?zero AND agentID = ?uuid", dbcon))
"SELECT * FROM inventoryfolders WHERE parentFolderID = ?zero AND agentID = ?uuid", {
database.Connection);
result.Parameters.AddWithValue("?uuid", user.ToString()); result.Parameters.AddWithValue("?uuid", user.ToString());
result.Parameters.AddWithValue("?zero", UUID.Zero.ToString()); result.Parameters.AddWithValue("?zero", UUID.Zero.ToString());
MySqlDataReader reader = result.ExecuteReader(); using (MySqlDataReader reader = result.ExecuteReader())
{
List<InventoryFolderBase> items = new List<InventoryFolderBase>(); List<InventoryFolderBase> items = new List<InventoryFolderBase>();
while (reader.Read()) while (reader.Read())
items.Add(readInventoryFolder(reader)); items.Add(readInventoryFolder(reader));
@ -250,21 +218,18 @@ namespace OpenSim.Data.MySQL
// to put such a message out, and it's too minor right now to spare the time to // to put such a message out, and it's too minor right now to spare the time to
// suitably refactor. // suitably refactor.
if (items.Count > 0) if (items.Count > 0)
{
rootFolder = items[0]; rootFolder = items[0];
}
reader.Close();
result.Dispose();
return rootFolder; return rootFolder;
} }
} }
}
}
}
catch (Exception e) catch (Exception e)
{ {
database.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString()); return null;
throw;
} }
} }
@ -279,31 +244,31 @@ namespace OpenSim.Data.MySQL
{ {
try try
{ {
lock (database) lock (m_dbLock)
{ {
database.CheckConnection(); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
MySqlCommand result = using (MySqlCommand result = new MySqlCommand("SELECT * FROM inventoryfolders WHERE parentFolderID = ?uuid", dbcon))
new MySqlCommand("SELECT * FROM inventoryfolders WHERE parentFolderID = ?uuid", {
database.Connection);
result.Parameters.AddWithValue("?uuid", parentID.ToString()); result.Parameters.AddWithValue("?uuid", parentID.ToString());
MySqlDataReader reader = result.ExecuteReader(); using (MySqlDataReader reader = result.ExecuteReader())
{
List<InventoryFolderBase> items = new List<InventoryFolderBase>(); List<InventoryFolderBase> items = new List<InventoryFolderBase>();
while (reader.Read()) while (reader.Read())
items.Add(readInventoryFolder(reader)); items.Add(readInventoryFolder(reader));
reader.Close();
result.Dispose();
return items; return items;
} }
} }
}
}
}
catch (Exception e) catch (Exception e)
{ {
database.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString());
return null; return null;
} }
} }
@ -345,8 +310,8 @@ namespace OpenSim.Data.MySQL
item.AssetID = new UUID((string) reader["assetID"]); item.AssetID = new UUID((string) reader["assetID"]);
item.AssetType = (int) reader["assetType"]; item.AssetType = (int) reader["assetType"];
item.Folder = new UUID((string) reader["parentFolderID"]); item.Folder = new UUID((string) reader["parentFolderID"]);
item.Name = (string) reader["inventoryName"]; item.Name = (string)(reader["inventoryName"] ?? String.Empty);
item.Description = (string) reader["inventoryDescription"]; item.Description = (string)(reader["inventoryDescription"] ?? String.Empty);
item.NextPermissions = (uint) reader["inventoryNextPermissions"]; item.NextPermissions = (uint) reader["inventoryNextPermissions"];
item.CurrentPermissions = (uint) reader["inventoryCurrentPermissions"]; item.CurrentPermissions = (uint) reader["inventoryCurrentPermissions"];
item.InvType = (int) reader["invType"]; item.InvType = (int) reader["invType"];
@ -378,29 +343,31 @@ namespace OpenSim.Data.MySQL
{ {
try try
{ {
lock (database) lock (m_dbLock)
{ {
database.CheckConnection(); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
MySqlCommand result = using (MySqlCommand result = new MySqlCommand("SELECT * FROM inventoryitems WHERE inventoryID = ?uuid", dbcon))
new MySqlCommand("SELECT * FROM inventoryitems WHERE inventoryID = ?uuid", database.Connection); {
result.Parameters.AddWithValue("?uuid", itemID.ToString()); result.Parameters.AddWithValue("?uuid", itemID.ToString());
MySqlDataReader reader = result.ExecuteReader();
using (MySqlDataReader reader = result.ExecuteReader())
{
InventoryItemBase item = null; InventoryItemBase item = null;
if (reader.Read()) if (reader.Read())
item = readInventoryItem(reader); item = readInventoryItem(reader);
reader.Close();
result.Dispose();
return item; return item;
} }
} }
}
}
}
catch (Exception e) catch (Exception e)
{ {
database.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString());
} }
return null; return null;
} }
@ -425,7 +392,7 @@ namespace OpenSim.Data.MySQL
} }
catch (Exception e) catch (Exception e)
{ {
m_log.Error(e.ToString()); m_log.Error(e.Message, e);
} }
return null; return null;
@ -441,151 +408,35 @@ namespace OpenSim.Data.MySQL
{ {
try try
{ {
lock (database) lock (m_dbLock)
{ {
database.CheckConnection(); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
MySqlCommand result = using (MySqlCommand result = new MySqlCommand("SELECT * FROM inventoryfolders WHERE folderID = ?uuid", dbcon))
new MySqlCommand("SELECT * FROM inventoryfolders WHERE folderID = ?uuid", database.Connection); {
result.Parameters.AddWithValue("?uuid", folderID.ToString()); result.Parameters.AddWithValue("?uuid", folderID.ToString());
MySqlDataReader reader = result.ExecuteReader();
using (MySqlDataReader reader = result.ExecuteReader())
{
InventoryFolderBase folder = null; InventoryFolderBase folder = null;
if (reader.Read()) if (reader.Read())
folder = readInventoryFolder(reader); folder = readInventoryFolder(reader);
reader.Close();
result.Dispose();
return folder; return folder;
} }
} }
}
}
}
catch (Exception e) catch (Exception e)
{ {
database.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString());
return null; return null;
} }
} }
#region Inventory Rollback-via-.sql Support
/// <summary>
/// Not a good SQL escape function, but it'll do the job (if mutilate the data.)
/// Someone may want to write something better here.
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
private static string cheapSQLescape(string str)
{
str = str.Replace("\\", "");
str = str.Replace("'", "");
str = str.Replace("\"", "");
return "'" + str + "'";
}
private static string InventoryItemToSql(InventoryItemBase item)
{
string sql =
"REPLACE /*! INVITEM AT ***$SUBS$*** */ INTO inventoryitems (inventoryID, assetID, assetType, parentFolderID, avatarID, inventoryName"
+ ", inventoryDescription, inventoryNextPermissions, inventoryCurrentPermissions, invType"
+ ", creatorID, inventoryBasePermissions, inventoryEveryOnePermissions, inventoryGroupPermissions, salePrice, saleType"
+ ", creationDate, groupID, groupOwned, flags) VALUES ";
sql +=
"(?inventoryID, ?assetID, ?assetType, ?parentFolderID, ?avatarID, ?inventoryName, ?inventoryDescription"
+ ", ?inventoryNextPermissions, ?inventoryCurrentPermissions, ?invType, ?creatorID"
+ ", ?inventoryBasePermissions, ?inventoryEveryOnePermissions, ?inventoryGroupPermissions, ?salePrice, ?saleType, ?creationDate"
+ ", ?groupID, ?groupOwned, ?flags);\r\n";
string itemName = item.Name;
string itemDesc = item.Description;
sql = sql.Replace("$SUBS$", Util.UnixTimeSinceEpoch().ToString());
sql = sql.Replace("?inventoryID", cheapSQLescape(item.ID.ToString()));
sql = sql.Replace("?assetID", cheapSQLescape(item.AssetID.ToString()));
sql = sql.Replace("?assetType", cheapSQLescape(item.AssetType.ToString()));
sql = sql.Replace("?parentFolderID", cheapSQLescape(item.Folder.ToString()));
sql = sql.Replace("?avatarID", cheapSQLescape(item.Owner.ToString()));
sql = sql.Replace("?inventoryName", cheapSQLescape(itemName));
sql = sql.Replace("?inventoryDescription", cheapSQLescape(itemDesc));
sql = sql.Replace("?inventoryNextPermissions", cheapSQLescape(item.NextPermissions.ToString()));
sql = sql.Replace("?inventoryCurrentPermissions", cheapSQLescape(item.CurrentPermissions.ToString()));
sql = sql.Replace("?invType", cheapSQLescape(item.InvType.ToString()));
sql = sql.Replace("?creatorID", cheapSQLescape(item.CreatorId));
sql = sql.Replace("?inventoryBasePermissions", cheapSQLescape(item.BasePermissions.ToString()));
sql = sql.Replace("?inventoryEveryOnePermissions", cheapSQLescape(item.EveryOnePermissions.ToString()));
sql = sql.Replace("?inventoryGroupPermissions", cheapSQLescape(item.GroupPermissions.ToString()));
sql = sql.Replace("?salePrice", cheapSQLescape(item.SalePrice.ToString()));
sql = sql.Replace("?saleType", cheapSQLescape(unchecked((sbyte)item.SaleType).ToString()));
sql = sql.Replace("?creationDate", cheapSQLescape(item.CreationDate.ToString()));
sql = sql.Replace("?groupID", cheapSQLescape(item.GroupID.ToString()));
sql = sql.Replace("?groupOwned", cheapSQLescape(item.GroupOwned.ToString()));
sql = sql.Replace("?flags", cheapSQLescape(item.Flags.ToString()));
return sql;
}
private static string InventoryFolderToSql(InventoryFolderBase folder)
{
string sql =
"REPLACE /*! INVFOLDER AT ***$SUBS$*** */ INTO inventoryfolders (folderID, agentID, parentFolderID, folderName, type, version) VALUES ";
sql += "(?folderID, ?agentID, ?parentFolderID, ?folderName, ?type, ?version);\r\n";
string folderName = folder.Name;
sql = sql.Replace("$SUBS$", Util.UnixTimeSinceEpoch().ToString());
sql = sql.Replace("?folderID", cheapSQLescape(folder.ID.ToString()));
sql = sql.Replace("?agentID", cheapSQLescape(folder.Owner.ToString()));
sql = sql.Replace("?parentFolderID", cheapSQLescape(folder.ParentID.ToString()));
sql = sql.Replace("?folderName", cheapSQLescape(folderName));
sql = sql.Replace("?type", cheapSQLescape(folder.Type.ToString()));
sql = sql.Replace("?version", cheapSQLescape(folder.Version.ToString()));
return sql;
}
private static string getRollbackFolderDate()
{
return DateTime.UtcNow.Year.ToString() + "-" + DateTime.UtcNow.Month.ToString() + "-" +
DateTime.UtcNow.Day.ToString();
}
private void StoreRollbackItem(UUID ItemID)
{
if (rollbackStore == true)
{
string todaysPath = RollbackGetTodaysPath();
InventoryItemBase imb = getInventoryItem(ItemID);
string sql = InventoryItemToSql(imb);
File.AppendAllText(Path.Combine(todaysPath, imb.Owner.ToString()), sql);
}
}
private void StoreRollbackFolder(UUID FolderID)
{
if (rollbackStore == true)
{
string todaysPath = RollbackGetTodaysPath();
InventoryFolderBase ifb = getInventoryFolder(FolderID);
string sql = InventoryFolderToSql(ifb);
File.AppendAllText(Path.Combine(todaysPath, ifb.Owner.ToString()), sql);
}
}
private string RollbackGetTodaysPath()
{
if (!Directory.Exists(rollbackDir))
Directory.CreateDirectory(rollbackDir);
string todaysPath = Path.Combine(rollbackDir, getRollbackFolderDate());
if (!Directory.Exists(todaysPath))
Directory.CreateDirectory(todaysPath);
return todaysPath;
}
#endregion
/// <summary> /// <summary>
/// Adds a specified item to the database /// Adds a specified item to the database
/// </summary> /// </summary>
@ -619,9 +470,11 @@ namespace OpenSim.Data.MySQL
try try
{ {
database.CheckConnection(); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
MySqlCommand result = new MySqlCommand(sql, database.Connection); MySqlCommand result = new MySqlCommand(sql, dbcon);
result.Parameters.AddWithValue("?inventoryID", item.ID.ToString()); result.Parameters.AddWithValue("?inventoryID", item.ID.ToString());
result.Parameters.AddWithValue("?assetID", item.AssetID.ToString()); result.Parameters.AddWithValue("?assetID", item.AssetID.ToString());
result.Parameters.AddWithValue("?assetType", item.AssetType.ToString()); result.Parameters.AddWithValue("?assetType", item.AssetType.ToString());
@ -644,22 +497,22 @@ namespace OpenSim.Data.MySQL
result.Parameters.AddWithValue("?groupOwned", item.GroupOwned); result.Parameters.AddWithValue("?groupOwned", item.GroupOwned);
result.Parameters.AddWithValue("?flags", item.Flags); result.Parameters.AddWithValue("?flags", item.Flags);
lock (database) lock (m_dbLock)
{ {
result.ExecuteNonQuery(); result.ExecuteNonQuery();
} }
result.Dispose(); result.Dispose();
result = new MySqlCommand("update inventoryfolders set version=version+1 where folderID = ?folderID", database.Connection); result = new MySqlCommand("update inventoryfolders set version=version+1 where folderID = ?folderID", dbcon);
result.Parameters.AddWithValue("?folderID", item.Folder.ToString result.Parameters.AddWithValue("?folderID", item.Folder.ToString());
()); lock (m_dbLock)
lock (database)
{ {
result.ExecuteNonQuery(); result.ExecuteNonQuery();
} }
result.Dispose(); result.Dispose();
} }
}
catch (MySqlException e) catch (MySqlException e)
{ {
m_log.Error(e.ToString()); m_log.Error(e.ToString());
@ -672,8 +525,6 @@ namespace OpenSim.Data.MySQL
/// <param name="item">Inventory item to update</param> /// <param name="item">Inventory item to update</param>
public void updateInventoryItem(InventoryItemBase item) public void updateInventoryItem(InventoryItemBase item)
{ {
StoreRollbackItem(item.ID);
addInventoryItem(item); addInventoryItem(item);
} }
@ -683,25 +534,24 @@ namespace OpenSim.Data.MySQL
/// <param name="item">The inventory item UUID to delete</param> /// <param name="item">The inventory item UUID to delete</param>
public void deleteInventoryItem(UUID itemID) public void deleteInventoryItem(UUID itemID)
{ {
StoreRollbackItem(itemID);
try try
{ {
database.CheckConnection(); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
MySqlCommand cmd = MySqlCommand cmd = new MySqlCommand("DELETE FROM inventoryitems WHERE inventoryID=?uuid", dbcon);
new MySqlCommand("DELETE FROM inventoryitems WHERE inventoryID=?uuid", database.Connection);
cmd.Parameters.AddWithValue("?uuid", itemID.ToString()); cmd.Parameters.AddWithValue("?uuid", itemID.ToString());
lock (database) lock (m_dbLock)
{ {
cmd.ExecuteNonQuery(); cmd.ExecuteNonQuery();
} }
} }
}
catch (MySqlException e) catch (MySqlException e)
{ {
database.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString());
} }
} }
@ -732,9 +582,11 @@ namespace OpenSim.Data.MySQL
m_log.Warn("[INVENTORY DB]: Name field truncated from " + folder.Name.Length + " to " + folderName.Length + " characters on add folder"); m_log.Warn("[INVENTORY DB]: Name field truncated from " + folder.Name.Length + " to " + folderName.Length + " characters on add folder");
} }
database.CheckConnection(); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
MySqlCommand cmd = new MySqlCommand(sql, database.Connection); MySqlCommand cmd = new MySqlCommand(sql, dbcon);
cmd.Parameters.AddWithValue("?folderID", folder.ID.ToString()); cmd.Parameters.AddWithValue("?folderID", folder.ID.ToString());
cmd.Parameters.AddWithValue("?agentID", folder.Owner.ToString()); cmd.Parameters.AddWithValue("?agentID", folder.Owner.ToString());
cmd.Parameters.AddWithValue("?parentFolderID", folder.ParentID.ToString()); cmd.Parameters.AddWithValue("?parentFolderID", folder.ParentID.ToString());
@ -744,7 +596,7 @@ namespace OpenSim.Data.MySQL
try try
{ {
lock (database) lock (m_dbLock)
{ {
cmd.ExecuteNonQuery(); cmd.ExecuteNonQuery();
} }
@ -754,6 +606,7 @@ namespace OpenSim.Data.MySQL
m_log.Error(e.ToString()); m_log.Error(e.ToString());
} }
} }
}
/// <summary> /// <summary>
/// Updates an inventory folder /// Updates an inventory folder
@ -761,7 +614,6 @@ namespace OpenSim.Data.MySQL
/// <param name="folder">Folder to update</param> /// <param name="folder">Folder to update</param>
public void updateInventoryFolder(InventoryFolderBase folder) public void updateInventoryFolder(InventoryFolderBase folder)
{ {
StoreRollbackFolder(folder.ID);
addInventoryFolder(folder); addInventoryFolder(folder);
} }
@ -772,20 +624,20 @@ namespace OpenSim.Data.MySQL
/// <remarks>UPDATE inventoryfolders SET parentFolderID=?parentFolderID WHERE folderID=?folderID</remarks> /// <remarks>UPDATE inventoryfolders SET parentFolderID=?parentFolderID WHERE folderID=?folderID</remarks>
public void moveInventoryFolder(InventoryFolderBase folder) public void moveInventoryFolder(InventoryFolderBase folder)
{ {
StoreRollbackFolder(folder.ID);
string sql = string sql =
"UPDATE inventoryfolders SET parentFolderID=?parentFolderID WHERE folderID=?folderID"; "UPDATE inventoryfolders SET parentFolderID=?parentFolderID WHERE folderID=?folderID";
database.CheckConnection(); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
MySqlCommand cmd = new MySqlCommand(sql, database.Connection); MySqlCommand cmd = new MySqlCommand(sql, dbcon);
cmd.Parameters.AddWithValue("?folderID", folder.ID.ToString()); cmd.Parameters.AddWithValue("?folderID", folder.ID.ToString());
cmd.Parameters.AddWithValue("?parentFolderID", folder.ParentID.ToString()); cmd.Parameters.AddWithValue("?parentFolderID", folder.ParentID.ToString());
try try
{ {
lock (database) lock (m_dbLock)
{ {
cmd.ExecuteNonQuery(); cmd.ExecuteNonQuery();
} }
@ -795,6 +647,7 @@ namespace OpenSim.Data.MySQL
m_log.Error(e.ToString()); m_log.Error(e.ToString());
} }
} }
}
/// <summary> /// <summary>
/// Append a list of all the child folders of a parent folder /// Append a list of all the child folders of a parent folder
@ -836,54 +689,60 @@ namespace OpenSim.Data.MySQL
try try
{ {
List<InventoryFolderBase> folders = new List<InventoryFolderBase>(); List<InventoryFolderBase> folders = new List<InventoryFolderBase>();
Dictionary<UUID, List<InventoryFolderBase>> hashtable Dictionary<UUID, List<InventoryFolderBase>> hashtable = new Dictionary<UUID, List<InventoryFolderBase>>(); ;
= new Dictionary<UUID, List<InventoryFolderBase>>(); ;
List<InventoryFolderBase> parentFolder = new List<InventoryFolderBase>(); List<InventoryFolderBase> parentFolder = new List<InventoryFolderBase>();
lock (database)
{
MySqlCommand result;
MySqlDataReader reader;
bool buildResultsFromHashTable = false; bool buildResultsFromHashTable = false;
database.CheckConnection(); lock (m_dbLock)
{
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
/* Fetch the parent folder from the database to determine the agent ID, and if /* Fetch the parent folder from the database to determine the agent ID, and if
* we're querying the root of the inventory folder tree */ * we're querying the root of the inventory folder tree */
result = new MySqlCommand("SELECT * FROM inventoryfolders WHERE folderID = ?uuid", using (MySqlCommand result = new MySqlCommand("SELECT * FROM inventoryfolders WHERE folderID = ?uuid", dbcon))
database.Connection); {
result.Parameters.AddWithValue("?uuid", parentID.ToString()); result.Parameters.AddWithValue("?uuid", parentID.ToString());
reader = result.ExecuteReader();
while (reader.Read()) // Should be at most 1 result using (MySqlDataReader reader = result.ExecuteReader())
{
// Should be at most 1 result
while (reader.Read())
parentFolder.Add(readInventoryFolder(reader)); parentFolder.Add(readInventoryFolder(reader));
reader.Close(); }
result.Dispose(); }
if (parentFolder.Count >= 1) // No result means parent folder does not exist if (parentFolder.Count >= 1) // No result means parent folder does not exist
{ {
if (parentFolder[0].ParentID == UUID.Zero) // We are querying the root folder if (parentFolder[0].ParentID == UUID.Zero) // We are querying the root folder
{ {
/* Get all of the agent's folders from the database, put them in a list and return it */ /* Get all of the agent's folders from the database, put them in a list and return it */
result = new MySqlCommand("SELECT * FROM inventoryfolders WHERE agentID = ?uuid", using (MySqlCommand result = new MySqlCommand("SELECT * FROM inventoryfolders WHERE agentID = ?uuid", dbcon))
database.Connection); {
result.Parameters.AddWithValue("?uuid", parentFolder[0].Owner.ToString()); result.Parameters.AddWithValue("?uuid", parentFolder[0].Owner.ToString());
reader = result.ExecuteReader();
using (MySqlDataReader reader = result.ExecuteReader())
{
while (reader.Read()) while (reader.Read())
{ {
InventoryFolderBase curFolder = readInventoryFolder(reader); InventoryFolderBase curFolder = readInventoryFolder(reader);
if (curFolder.ID != parentID) // Do not need to add the root node of the tree to the list if (curFolder.ID != parentID) // Do not need to add the root node of the tree to the list
folders.Add(curFolder); folders.Add(curFolder);
} }
reader.Close(); }
result.Dispose(); }
} // if we are querying the root folder } // if we are querying the root folder
else // else we are querying a subtree of the inventory folder tree else // else we are querying a subtree of the inventory folder tree
{ {
/* Get all of the agent's folders from the database, put them all in a hash table /* Get all of the agent's folders from the database, put them all in a hash table
* indexed by their parent ID */ * indexed by their parent ID */
result = new MySqlCommand("SELECT * FROM inventoryfolders WHERE agentID = ?uuid", using (MySqlCommand result = new MySqlCommand("SELECT * FROM inventoryfolders WHERE agentID = ?uuid", dbcon))
database.Connection); {
result.Parameters.AddWithValue("?uuid", parentFolder[0].Owner.ToString()); result.Parameters.AddWithValue("?uuid", parentFolder[0].Owner.ToString());
reader = result.ExecuteReader();
using (MySqlDataReader reader = result.ExecuteReader())
{
while (reader.Read()) while (reader.Read())
{ {
InventoryFolderBase curFolder = readInventoryFolder(reader); InventoryFolderBase curFolder = readInventoryFolder(reader);
@ -897,8 +756,8 @@ namespace OpenSim.Data.MySQL
hashtable.Add(curFolder.ParentID, siblingList); hashtable.Add(curFolder.ParentID, siblingList);
} }
} // while more items to read from the database } // while more items to read from the database
reader.Close(); }
result.Dispose(); }
// Set flag so we know we need to build the results from the hash table after // Set flag so we know we need to build the results from the hash table after
// we unlock the database // we unlock the database
@ -918,13 +777,14 @@ namespace OpenSim.Data.MySQL
if (hashtable.ContainsKey(folders[i].ID)) if (hashtable.ContainsKey(folders[i].ID))
folders.AddRange(hashtable[folders[i].ID]); folders.AddRange(hashtable[folders[i].ID]);
} }
}
} // lock (database) } // lock (database)
return folders; return folders;
} }
catch (Exception e) catch (Exception e)
{ {
database.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString());
return null; return null;
} }
} }
@ -935,25 +795,24 @@ namespace OpenSim.Data.MySQL
/// <param name="folderID">the folder UUID</param> /// <param name="folderID">the folder UUID</param>
protected void deleteOneFolder(UUID folderID) protected void deleteOneFolder(UUID folderID)
{ {
StoreRollbackFolder(folderID);
try try
{ {
database.CheckConnection(); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
MySqlCommand cmd = using (MySqlCommand cmd = new MySqlCommand("DELETE FROM inventoryfolders WHERE folderID=?uuid", dbcon))
new MySqlCommand("DELETE FROM inventoryfolders WHERE folderID=?uuid", database.Connection); {
cmd.Parameters.AddWithValue("?uuid", folderID.ToString()); cmd.Parameters.AddWithValue("?uuid", folderID.ToString());
lock (database) lock (m_dbLock)
{
cmd.ExecuteNonQuery(); cmd.ExecuteNonQuery();
} }
} }
}
catch (MySqlException e) catch (MySqlException e)
{ {
database.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString());
} }
} }
@ -963,30 +822,23 @@ namespace OpenSim.Data.MySQL
/// <param name="folderID">the folder UUID</param> /// <param name="folderID">the folder UUID</param>
protected void deleteItemsInFolder(UUID folderID) protected void deleteItemsInFolder(UUID folderID)
{ {
if (rollbackStore)
{
foreach (InventoryItemBase itemBase in getInventoryInFolder(folderID))
{
StoreRollbackItem(itemBase.ID);
}
}
try try
{ {
database.CheckConnection(); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
MySqlCommand cmd = using (MySqlCommand cmd = new MySqlCommand("DELETE FROM inventoryitems WHERE parentFolderID=?uuid", dbcon))
new MySqlCommand("DELETE FROM inventoryitems WHERE parentFolderID=?uuid", database.Connection); {
cmd.Parameters.AddWithValue("?uuid", folderID.ToString()); cmd.Parameters.AddWithValue("?uuid", folderID.ToString());
lock (database) lock (m_dbLock)
{
cmd.ExecuteNonQuery(); cmd.ExecuteNonQuery();
} }
} }
}
catch (MySqlException e) catch (MySqlException e)
{ {
database.Reconnect();
m_log.Error(e.ToString()); m_log.Error(e.ToString());
} }
} }
@ -999,60 +851,36 @@ namespace OpenSim.Data.MySQL
{ {
List<InventoryFolderBase> subFolders = getFolderHierarchy(folderID); List<InventoryFolderBase> subFolders = getFolderHierarchy(folderID);
// Dont delete in OGM - makes for easier restores if someone sends a malcious command. (just restore the folder entry)
if (opengridmode == false)
{
//Delete all sub-folders //Delete all sub-folders
foreach (InventoryFolderBase f in subFolders) foreach (InventoryFolderBase f in subFolders)
{ {
StoreRollbackFolder(f.ID);
deleteOneFolder(f.ID); deleteOneFolder(f.ID);
if (rollbackStore)
{
foreach (InventoryItemBase itemBase in getInventoryInFolder(f.ID))
{
StoreRollbackItem(itemBase.ID);
}
}
deleteItemsInFolder(f.ID); deleteItemsInFolder(f.ID);
} }
}
StoreRollbackFolder(folderID);
//Delete the actual row //Delete the actual row
deleteOneFolder(folderID); deleteOneFolder(folderID);
// Just delete the folder context in OGM
if (opengridmode == false)
{
if (rollbackStore)
{
foreach (InventoryItemBase itemBase in getInventoryInFolder(folderID))
{
StoreRollbackItem(itemBase.ID);
}
}
deleteItemsInFolder(folderID); deleteItemsInFolder(folderID);
} }
}
public List<InventoryItemBase> fetchActiveGestures(UUID avatarID) public List<InventoryItemBase> fetchActiveGestures(UUID avatarID)
{ {
MySqlDataReader result = null; lock (m_dbLock)
MySqlCommand sqlCmd = null;
lock (database)
{ {
try try
{ {
database.CheckConnection(); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
sqlCmd = new MySqlCommand( {
"SELECT * FROM inventoryitems WHERE avatarId = ?uuid AND assetType = ?type and flags = 1", dbcon.Open();
database.Connection);
using (MySqlCommand sqlCmd = new MySqlCommand(
"SELECT * FROM inventoryitems WHERE avatarId = ?uuid AND assetType = ?type and flags = 1", dbcon))
{
sqlCmd.Parameters.AddWithValue("?uuid", avatarID.ToString()); sqlCmd.Parameters.AddWithValue("?uuid", avatarID.ToString());
sqlCmd.Parameters.AddWithValue("?type", (int)AssetType.Gesture); sqlCmd.Parameters.AddWithValue("?type", (int)AssetType.Gesture);
result = sqlCmd.ExecuteReader();
using (MySqlDataReader result = sqlCmd.ExecuteReader())
{
List<InventoryItemBase> list = new List<InventoryItemBase>(); List<InventoryItemBase> list = new List<InventoryItemBase>();
while (result.Read()) while (result.Read())
{ {
@ -1062,17 +890,14 @@ namespace OpenSim.Data.MySQL
} }
return list; return list;
} }
}
}
}
catch (Exception e) catch (Exception e)
{ {
database.Reconnect(); m_log.Error(e.Message, e);
m_log.Error(e.ToString());
return null; return null;
} }
finally
{
if (result != null) result.Close();
if (sqlCmd != null) sqlCmd.Dispose();
}
} }
} }
} }

View File

@ -48,109 +48,70 @@ 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 string m_ConnectionString; private string m_connectionString;
private object m_dbLock = new object();
private MySqlConnection m_Connection = null;
public void Initialise(string connectionString) public void Initialise(string connectionString)
{ {
m_ConnectionString = connectionString; m_connectionString = connectionString;
m_Connection = new MySqlConnection(m_ConnectionString); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
m_Connection.Open(); dbcon.Open();
// Apply new Migrations // Apply new Migrations
// //
Assembly assem = GetType().Assembly; Assembly assem = GetType().Assembly;
Migration m = new Migration(m_Connection, assem, "RegionStore"); Migration m = new Migration(dbcon, assem, "RegionStore");
m.Update(); m.Update();
// NOTE: This is a very slow query that times out on regions with a lot of prims.
// I'm told that it is no longer relevant so it's commented out now, but if it
// is relevant it should be added as a console command instead of part of the
// startup phase
// Clean dropped attachments // Clean dropped attachments
// //
//try try
//{ {
// using (MySqlCommand cmd = m_Connection.CreateCommand()) using (MySqlCommand cmd = dbcon.CreateCommand())
// { {
// cmd.CommandText = "delete from prims, primshapes using prims " + cmd.CommandText = "delete from prims, primshapes using prims " +
// "left join primshapes on prims.uuid = primshapes.uuid " + "left join primshapes on prims.uuid = primshapes.uuid " +
// "where PCode = 9 and State <> 0"; "where PCode = 9 and State <> 0";
// ExecuteNonQuery(cmd); ExecuteNonQuery(cmd);
// } }
//} }
//catch (MySqlException ex) catch (MySqlException ex)
//{ {
// m_log.Error("[REGION DB]: Error cleaning up dropped attachments: " + ex.Message); m_log.Error("[REGION DB]: Error cleaning up dropped attachments: " + ex.Message);
//} }
}
} }
private IDataReader ExecuteReader(MySqlCommand c) private IDataReader ExecuteReader(MySqlCommand c)
{ {
IDataReader r = null; IDataReader r = null;
bool errorSeen = false;
while (true)
{
try try
{ {
r = c.ExecuteReader(); r = c.ExecuteReader();
} }
catch (Exception) catch (Exception e)
{ {
Thread.Sleep(500); m_log.Error("[REGION DB]: MySQL error in ExecuteReader: " + e.Message);
m_Connection.Close();
m_Connection = (MySqlConnection) ((ICloneable)m_Connection).Clone();
m_Connection.Open();
c.Connection = m_Connection;
if (!errorSeen)
{
errorSeen = true;
continue;
}
throw; throw;
} }
break;
}
return r; return r;
} }
private void ExecuteNonQuery(MySqlCommand c) private void ExecuteNonQuery(MySqlCommand c)
{
bool errorSeen = false;
while (true)
{ {
try try
{ {
c.ExecuteNonQuery(); c.ExecuteNonQuery();
} }
catch (Exception) catch (Exception e)
{ {
Thread.Sleep(500); m_log.Error("[REGION DB]: MySQL error in ExecuteNonQuery: " + e.Message);
m_Connection.Close();
m_Connection = (MySqlConnection) ((ICloneable)m_Connection).Clone();
m_Connection.Open();
c.Connection = m_Connection;
if (!errorSeen)
{
errorSeen = true;
continue;
}
throw; throw;
} }
break;
}
} }
public void Dispose() {} public void Dispose() {}
@ -166,80 +127,83 @@ namespace OpenSim.Data.MySQL
if ((flags & (uint)PrimFlags.TemporaryOnRez) != 0) if ((flags & (uint)PrimFlags.TemporaryOnRez) != 0)
return; return;
lock (m_Connection) lock (m_dbLock)
{ {
MySqlCommand cmd = m_Connection.CreateCommand(); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
MySqlCommand cmd = dbcon.CreateCommand();
foreach (SceneObjectPart prim in obj.Children.Values) foreach (SceneObjectPart prim in obj.Children.Values)
{ {
cmd.Parameters.Clear(); cmd.Parameters.Clear();
cmd.CommandText = "replace into prims ("+ cmd.CommandText = "replace into prims (" +
"UUID, CreationDate, "+ "UUID, CreationDate, " +
"Name, Text, Description, "+ "Name, Text, Description, " +
"SitName, TouchName, ObjectFlags, "+ "SitName, TouchName, ObjectFlags, " +
"OwnerMask, NextOwnerMask, GroupMask, "+ "OwnerMask, NextOwnerMask, GroupMask, " +
"EveryoneMask, BaseMask, PositionX, "+ "EveryoneMask, BaseMask, PositionX, " +
"PositionY, PositionZ, GroupPositionX, "+ "PositionY, PositionZ, GroupPositionX, " +
"GroupPositionY, GroupPositionZ, VelocityX, "+ "GroupPositionY, GroupPositionZ, VelocityX, " +
"VelocityY, VelocityZ, AngularVelocityX, "+ "VelocityY, VelocityZ, AngularVelocityX, " +
"AngularVelocityY, AngularVelocityZ, "+ "AngularVelocityY, AngularVelocityZ, " +
"AccelerationX, AccelerationY, "+ "AccelerationX, AccelerationY, " +
"AccelerationZ, RotationX, "+ "AccelerationZ, RotationX, " +
"RotationY, RotationZ, "+ "RotationY, RotationZ, " +
"RotationW, SitTargetOffsetX, "+ "RotationW, SitTargetOffsetX, " +
"SitTargetOffsetY, SitTargetOffsetZ, "+ "SitTargetOffsetY, SitTargetOffsetZ, " +
"SitTargetOrientW, SitTargetOrientX, "+ "SitTargetOrientW, SitTargetOrientX, " +
"SitTargetOrientY, SitTargetOrientZ, "+ "SitTargetOrientY, SitTargetOrientZ, " +
"RegionUUID, CreatorID, "+ "RegionUUID, CreatorID, " +
"OwnerID, GroupID, "+ "OwnerID, GroupID, " +
"LastOwnerID, SceneGroupID, "+ "LastOwnerID, SceneGroupID, " +
"PayPrice, PayButton1, "+ "PayPrice, PayButton1, " +
"PayButton2, PayButton3, "+ "PayButton2, PayButton3, " +
"PayButton4, LoopedSound, "+ "PayButton4, LoopedSound, " +
"LoopedSoundGain, TextureAnimation, "+ "LoopedSoundGain, TextureAnimation, " +
"OmegaX, OmegaY, OmegaZ, "+ "OmegaX, OmegaY, OmegaZ, " +
"CameraEyeOffsetX, CameraEyeOffsetY, "+ "CameraEyeOffsetX, CameraEyeOffsetY, " +
"CameraEyeOffsetZ, CameraAtOffsetX, "+ "CameraEyeOffsetZ, CameraAtOffsetX, " +
"CameraAtOffsetY, CameraAtOffsetZ, "+ "CameraAtOffsetY, CameraAtOffsetZ, " +
"ForceMouselook, ScriptAccessPin, "+ "ForceMouselook, ScriptAccessPin, " +
"AllowedDrop, DieAtEdge, "+ "AllowedDrop, DieAtEdge, " +
"SalePrice, SaleType, "+ "SalePrice, SaleType, " +
"ColorR, ColorG, ColorB, ColorA, "+ "ColorR, ColorG, ColorB, ColorA, " +
"ParticleSystem, ClickAction, Material, "+ "ParticleSystem, ClickAction, Material, " +
"CollisionSound, CollisionSoundVolume, "+ "CollisionSound, CollisionSoundVolume, " +
"PassTouches, "+ "PassTouches, " +
"LinkNumber) values (" + "?UUID, "+ "LinkNumber) values (" + "?UUID, " +
"?CreationDate, ?Name, ?Text, "+ "?CreationDate, ?Name, ?Text, " +
"?Description, ?SitName, ?TouchName, "+ "?Description, ?SitName, ?TouchName, " +
"?ObjectFlags, ?OwnerMask, ?NextOwnerMask, "+ "?ObjectFlags, ?OwnerMask, ?NextOwnerMask, " +
"?GroupMask, ?EveryoneMask, ?BaseMask, "+ "?GroupMask, ?EveryoneMask, ?BaseMask, " +
"?PositionX, ?PositionY, ?PositionZ, "+ "?PositionX, ?PositionY, ?PositionZ, " +
"?GroupPositionX, ?GroupPositionY, "+ "?GroupPositionX, ?GroupPositionY, " +
"?GroupPositionZ, ?VelocityX, "+ "?GroupPositionZ, ?VelocityX, " +
"?VelocityY, ?VelocityZ, ?AngularVelocityX, "+ "?VelocityY, ?VelocityZ, ?AngularVelocityX, " +
"?AngularVelocityY, ?AngularVelocityZ, "+ "?AngularVelocityY, ?AngularVelocityZ, " +
"?AccelerationX, ?AccelerationY, "+ "?AccelerationX, ?AccelerationY, " +
"?AccelerationZ, ?RotationX, "+ "?AccelerationZ, ?RotationX, " +
"?RotationY, ?RotationZ, "+ "?RotationY, ?RotationZ, " +
"?RotationW, ?SitTargetOffsetX, "+ "?RotationW, ?SitTargetOffsetX, " +
"?SitTargetOffsetY, ?SitTargetOffsetZ, "+ "?SitTargetOffsetY, ?SitTargetOffsetZ, " +
"?SitTargetOrientW, ?SitTargetOrientX, "+ "?SitTargetOrientW, ?SitTargetOrientX, " +
"?SitTargetOrientY, ?SitTargetOrientZ, "+ "?SitTargetOrientY, ?SitTargetOrientZ, " +
"?RegionUUID, ?CreatorID, ?OwnerID, "+ "?RegionUUID, ?CreatorID, ?OwnerID, " +
"?GroupID, ?LastOwnerID, ?SceneGroupID, "+ "?GroupID, ?LastOwnerID, ?SceneGroupID, " +
"?PayPrice, ?PayButton1, ?PayButton2, "+ "?PayPrice, ?PayButton1, ?PayButton2, " +
"?PayButton3, ?PayButton4, ?LoopedSound, "+ "?PayButton3, ?PayButton4, ?LoopedSound, " +
"?LoopedSoundGain, ?TextureAnimation, "+ "?LoopedSoundGain, ?TextureAnimation, " +
"?OmegaX, ?OmegaY, ?OmegaZ, "+ "?OmegaX, ?OmegaY, ?OmegaZ, " +
"?CameraEyeOffsetX, ?CameraEyeOffsetY, "+ "?CameraEyeOffsetX, ?CameraEyeOffsetY, " +
"?CameraEyeOffsetZ, ?CameraAtOffsetX, "+ "?CameraEyeOffsetZ, ?CameraAtOffsetX, " +
"?CameraAtOffsetY, ?CameraAtOffsetZ, "+ "?CameraAtOffsetY, ?CameraAtOffsetZ, " +
"?ForceMouselook, ?ScriptAccessPin, "+ "?ForceMouselook, ?ScriptAccessPin, " +
"?AllowedDrop, ?DieAtEdge, ?SalePrice, "+ "?AllowedDrop, ?DieAtEdge, ?SalePrice, " +
"?SaleType, ?ColorR, ?ColorG, "+ "?SaleType, ?ColorR, ?ColorG, " +
"?ColorB, ?ColorA, ?ParticleSystem, "+ "?ColorB, ?ColorA, ?ParticleSystem, " +
"?ClickAction, ?Material, ?CollisionSound, "+ "?ClickAction, ?Material, ?CollisionSound, " +
"?CollisionSoundVolume, ?PassTouches, ?LinkNumber)"; "?CollisionSoundVolume, ?PassTouches, ?LinkNumber)";
FillPrimCommand(cmd, prim, obj.UUID, regionUUID); FillPrimCommand(cmd, prim, obj.UUID, regionUUID);
@ -248,26 +212,26 @@ namespace OpenSim.Data.MySQL
cmd.Parameters.Clear(); cmd.Parameters.Clear();
cmd.CommandText = "replace into primshapes ("+ cmd.CommandText = "replace into primshapes (" +
"UUID, Shape, ScaleX, ScaleY, "+ "UUID, Shape, ScaleX, ScaleY, " +
"ScaleZ, PCode, PathBegin, PathEnd, "+ "ScaleZ, PCode, PathBegin, PathEnd, " +
"PathScaleX, PathScaleY, PathShearX, "+ "PathScaleX, PathScaleY, PathShearX, " +
"PathShearY, PathSkew, PathCurve, "+ "PathShearY, PathSkew, PathCurve, " +
"PathRadiusOffset, PathRevolutions, "+ "PathRadiusOffset, PathRevolutions, " +
"PathTaperX, PathTaperY, PathTwist, "+ "PathTaperX, PathTaperY, PathTwist, " +
"PathTwistBegin, ProfileBegin, ProfileEnd, "+ "PathTwistBegin, ProfileBegin, ProfileEnd, " +
"ProfileCurve, ProfileHollow, Texture, "+ "ProfileCurve, ProfileHollow, Texture, " +
"ExtraParams, State) values (?UUID, "+ "ExtraParams, State) values (?UUID, " +
"?Shape, ?ScaleX, ?ScaleY, ?ScaleZ, "+ "?Shape, ?ScaleX, ?ScaleY, ?ScaleZ, " +
"?PCode, ?PathBegin, ?PathEnd, "+ "?PCode, ?PathBegin, ?PathEnd, " +
"?PathScaleX, ?PathScaleY, "+ "?PathScaleX, ?PathScaleY, " +
"?PathShearX, ?PathShearY, "+ "?PathShearX, ?PathShearY, " +
"?PathSkew, ?PathCurve, ?PathRadiusOffset, "+ "?PathSkew, ?PathCurve, ?PathRadiusOffset, " +
"?PathRevolutions, ?PathTaperX, "+ "?PathRevolutions, ?PathTaperX, " +
"?PathTaperY, ?PathTwist, "+ "?PathTaperY, ?PathTwist, " +
"?PathTwistBegin, ?ProfileBegin, "+ "?PathTwistBegin, ?ProfileBegin, " +
"?ProfileEnd, ?ProfileCurve, "+ "?ProfileEnd, ?ProfileCurve, " +
"?ProfileHollow, ?Texture, ?ExtraParams, "+ "?ProfileHollow, ?Texture, ?ExtraParams, " +
"?State)"; "?State)";
FillShapeCommand(cmd, prim); FillShapeCommand(cmd, prim);
@ -277,6 +241,7 @@ namespace OpenSim.Data.MySQL
cmd.Dispose(); cmd.Dispose();
} }
} }
}
public void RemoveObject(UUID obj, UUID regionUUID) public void RemoveObject(UUID obj, UUID regionUUID)
{ {
@ -290,9 +255,13 @@ namespace OpenSim.Data.MySQL
// cause the loss of a prim, but is cleaner. // cause the loss of a prim, but is cleaner.
// It's also faster because it uses the primary key. // It's also faster because it uses the primary key.
// //
lock (m_Connection) lock (m_dbLock)
{ {
using (MySqlCommand cmd = m_Connection.CreateCommand()) using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = dbcon.CreateCommand())
{ {
cmd.CommandText = "select UUID from prims where SceneGroupID= ?UUID"; cmd.CommandText = "select UUID from prims where SceneGroupID= ?UUID";
cmd.Parameters.AddWithValue("UUID", obj.ToString()); cmd.Parameters.AddWithValue("UUID", obj.ToString());
@ -308,6 +277,7 @@ namespace OpenSim.Data.MySQL
ExecuteNonQuery(cmd); ExecuteNonQuery(cmd);
} }
} }
}
// there is no way this should be < 1 unless there is // there is no way this should be < 1 unless there is
// a very corrupt database, but in that case be extra // a very corrupt database, but in that case be extra
@ -326,9 +296,13 @@ namespace OpenSim.Data.MySQL
/// <param name="uuid">the Item UUID</param> /// <param name="uuid">the Item UUID</param>
private void RemoveItems(UUID uuid) private void RemoveItems(UUID uuid)
{ {
lock (m_Connection) lock (m_dbLock)
{ {
using (MySqlCommand cmd = m_Connection.CreateCommand()) using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = dbcon.CreateCommand())
{ {
cmd.CommandText = "delete from primitems where PrimID = ?PrimID"; cmd.CommandText = "delete from primitems where PrimID = ?PrimID";
cmd.Parameters.AddWithValue("PrimID", uuid.ToString()); cmd.Parameters.AddWithValue("PrimID", uuid.ToString());
@ -337,6 +311,7 @@ namespace OpenSim.Data.MySQL
} }
} }
} }
}
/// <summary> /// <summary>
/// Remove all persisted shapes for a list of prims /// Remove all persisted shapes for a list of prims
@ -345,11 +320,14 @@ namespace OpenSim.Data.MySQL
/// <param name="uuids">the list of UUIDs</param> /// <param name="uuids">the list of UUIDs</param>
private void RemoveShapes(List<UUID> uuids) private void RemoveShapes(List<UUID> uuids)
{ {
lock (m_Connection) lock (m_dbLock)
{ {
string sql = "delete from primshapes where "; string sql = "delete from primshapes where ";
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = m_Connection.CreateCommand()) using (MySqlCommand cmd = dbcon.CreateCommand())
{ {
for (int i = 0; i < uuids.Count; i++) for (int i = 0; i < uuids.Count; i++)
{ {
@ -371,6 +349,7 @@ namespace OpenSim.Data.MySQL
} }
} }
} }
}
/// <summary> /// <summary>
/// Remove all persisted items for a list of prims /// Remove all persisted items for a list of prims
@ -379,11 +358,14 @@ namespace OpenSim.Data.MySQL
/// <param name="uuids">the list of UUIDs</param> /// <param name="uuids">the list of UUIDs</param>
private void RemoveItems(List<UUID> uuids) private void RemoveItems(List<UUID> uuids)
{ {
lock (m_Connection) lock (m_dbLock)
{ {
string sql = "delete from primitems where "; string sql = "delete from primitems where ";
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = m_Connection.CreateCommand()) using (MySqlCommand cmd = dbcon.CreateCommand())
{ {
for (int i = 0; i < uuids.Count; i++) for (int i = 0; i < uuids.Count; i++)
{ {
@ -406,6 +388,7 @@ namespace OpenSim.Data.MySQL
} }
} }
} }
}
public List<SceneObjectGroup> LoadObjects(UUID regionID) public List<SceneObjectGroup> LoadObjects(UUID regionID)
{ {
@ -417,9 +400,13 @@ namespace OpenSim.Data.MySQL
#region Prim Loading #region Prim Loading
lock (m_Connection) lock (m_dbLock)
{ {
using (MySqlCommand cmd = m_Connection.CreateCommand()) using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = dbcon.CreateCommand())
{ {
cmd.CommandText = cmd.CommandText =
"SELECT * FROM prims LEFT JOIN primshapes ON prims.UUID = primshapes.UUID WHERE RegionUUID = ?RegionUUID"; "SELECT * FROM prims LEFT JOIN primshapes ON prims.UUID = primshapes.UUID WHERE RegionUUID = ?RegionUUID";
@ -448,6 +435,7 @@ namespace OpenSim.Data.MySQL
} }
} }
} }
}
#endregion Prim Loading #endregion Prim Loading
@ -497,9 +485,13 @@ namespace OpenSim.Data.MySQL
// list from DB of all prims which have items and // list from DB of all prims which have items and
// LoadItems only on those // LoadItems only on those
List<SceneObjectPart> primsWithInventory = new List<SceneObjectPart>(); List<SceneObjectPart> primsWithInventory = new List<SceneObjectPart>();
lock (m_Connection) lock (m_dbLock)
{ {
using (MySqlCommand itemCmd = m_Connection.CreateCommand()) using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand itemCmd = dbcon.CreateCommand())
{ {
itemCmd.CommandText = "SELECT DISTINCT primID FROM primitems"; itemCmd.CommandText = "SELECT DISTINCT primID FROM primitems";
using (IDataReader itemReader = ExecuteReader(itemCmd)) using (IDataReader itemReader = ExecuteReader(itemCmd))
@ -516,6 +508,7 @@ namespace OpenSim.Data.MySQL
} }
} }
} }
}
foreach (SceneObjectPart prim in primsWithInventory) foreach (SceneObjectPart prim in primsWithInventory)
{ {
@ -535,11 +528,15 @@ namespace OpenSim.Data.MySQL
/// <param name="prim">The prim</param> /// <param name="prim">The prim</param>
private void LoadItems(SceneObjectPart prim) private void LoadItems(SceneObjectPart prim)
{ {
lock (m_Connection) lock (m_dbLock)
{ {
List<TaskInventoryItem> inventory = new List<TaskInventoryItem>(); List<TaskInventoryItem> inventory = new List<TaskInventoryItem>();
using (MySqlCommand cmd = m_Connection.CreateCommand()) using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = dbcon.CreateCommand())
{ {
cmd.CommandText = "select * from primitems where PrimID = ?PrimID"; cmd.CommandText = "select * from primitems where PrimID = ?PrimID";
cmd.Parameters.AddWithValue("PrimID", prim.UUID.ToString()); cmd.Parameters.AddWithValue("PrimID", prim.UUID.ToString());
@ -555,6 +552,7 @@ namespace OpenSim.Data.MySQL
} }
} }
} }
}
prim.Inventory.RestoreInventoryItems(inventory); prim.Inventory.RestoreInventoryItems(inventory);
} }
@ -564,9 +562,13 @@ namespace OpenSim.Data.MySQL
{ {
m_log.Info("[REGION DB]: Storing terrain"); m_log.Info("[REGION DB]: Storing terrain");
lock (m_Connection) lock (m_dbLock)
{ {
using (MySqlCommand cmd = m_Connection.CreateCommand()) using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = dbcon.CreateCommand())
{ {
cmd.CommandText = "delete from terrain where RegionUUID = ?RegionUUID"; cmd.CommandText = "delete from terrain where RegionUUID = ?RegionUUID";
cmd.Parameters.AddWithValue("RegionUUID", regionID.ToString()); cmd.Parameters.AddWithValue("RegionUUID", regionID.ToString());
@ -583,14 +585,19 @@ namespace OpenSim.Data.MySQL
} }
} }
} }
}
public double[,] LoadTerrain(UUID regionID) public double[,] LoadTerrain(UUID regionID)
{ {
double[,] terrain = null; double[,] terrain = null;
lock (m_Connection) lock (m_dbLock)
{ {
using (MySqlCommand cmd = m_Connection.CreateCommand()) using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = dbcon.CreateCommand())
{ {
cmd.CommandText = "select RegionUUID, Revision, Heightfield " + cmd.CommandText = "select RegionUUID, Revision, Heightfield " +
"from terrain where RegionUUID = ?RegionUUID " + "from terrain where RegionUUID = ?RegionUUID " +
@ -625,15 +632,20 @@ namespace OpenSim.Data.MySQL
} }
} }
} }
}
return terrain; return terrain;
} }
public void RemoveLandObject(UUID globalID) public void RemoveLandObject(UUID globalID)
{ {
lock (m_Connection) lock (m_dbLock)
{ {
using (MySqlCommand cmd = m_Connection.CreateCommand()) using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = dbcon.CreateCommand())
{ {
cmd.CommandText = "delete from land where UUID = ?UUID"; cmd.CommandText = "delete from land where UUID = ?UUID";
cmd.Parameters.AddWithValue("UUID", globalID.ToString()); cmd.Parameters.AddWithValue("UUID", globalID.ToString());
@ -642,12 +654,17 @@ namespace OpenSim.Data.MySQL
} }
} }
} }
}
public void StoreLandObject(ILandObject parcel) public void StoreLandObject(ILandObject parcel)
{ {
lock (m_Connection) lock (m_dbLock)
{ {
using (MySqlCommand cmd = m_Connection.CreateCommand()) using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = dbcon.CreateCommand())
{ {
cmd.CommandText = "replace into land (UUID, RegionUUID, " + cmd.CommandText = "replace into land (UUID, RegionUUID, " +
"LocalLandID, Bitmap, Name, Description, " + "LocalLandID, Bitmap, Name, Description, " +
@ -692,6 +709,7 @@ namespace OpenSim.Data.MySQL
} }
} }
} }
}
public RegionMeta7WindlightData LoadRegionWindlightSettings(UUID regionUUID) public RegionMeta7WindlightData LoadRegionWindlightSettings(UUID regionUUID)
{ {
@ -788,9 +806,13 @@ namespace OpenSim.Data.MySQL
{ {
RegionSettings rs = null; RegionSettings rs = null;
lock (m_Connection) lock (m_dbLock)
{ {
using (MySqlCommand cmd = m_Connection.CreateCommand()) using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = dbcon.CreateCommand())
{ {
cmd.CommandText = "select * from regionsettings where regionUUID = ?RegionUUID"; cmd.CommandText = "select * from regionsettings where regionUUID = ?RegionUUID";
cmd.Parameters.AddWithValue("regionUUID", regionUUID); cmd.Parameters.AddWithValue("regionUUID", regionUUID);
@ -813,6 +835,7 @@ namespace OpenSim.Data.MySQL
} }
} }
} }
}
return rs; return rs;
} }
@ -920,9 +943,13 @@ namespace OpenSim.Data.MySQL
public void StoreRegionSettings(RegionSettings rs) public void StoreRegionSettings(RegionSettings rs)
{ {
lock (m_Connection) lock (m_dbLock)
{ {
using (MySqlCommand cmd = m_Connection.CreateCommand()) using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = dbcon.CreateCommand())
{ {
cmd.CommandText = "replace into regionsettings (regionUUID, " + cmd.CommandText = "replace into regionsettings (regionUUID, " +
"block_terraform, block_fly, allow_damage, " + "block_terraform, block_fly, allow_damage, " +
@ -963,14 +990,19 @@ namespace OpenSim.Data.MySQL
} }
} }
} }
}
public List<LandData> LoadLandObjects(UUID regionUUID) public List<LandData> LoadLandObjects(UUID regionUUID)
{ {
List<LandData> landData = new List<LandData>(); List<LandData> landData = new List<LandData>();
lock (m_Connection) lock (m_dbLock)
{ {
using (MySqlCommand cmd = m_Connection.CreateCommand()) using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = dbcon.CreateCommand())
{ {
cmd.CommandText = "select * from land where RegionUUID = ?RegionUUID"; cmd.CommandText = "select * from land where RegionUUID = ?RegionUUID";
cmd.Parameters.AddWithValue("RegionUUID", regionUUID.ToString()); cmd.Parameters.AddWithValue("RegionUUID", regionUUID.ToString());
@ -985,7 +1017,7 @@ namespace OpenSim.Data.MySQL
} }
} }
using (MySqlCommand cmd = m_Connection.CreateCommand()) using (MySqlCommand cmd = dbcon.CreateCommand())
{ {
foreach (LandData land in landData) foreach (LandData land in landData)
{ {
@ -1003,6 +1035,7 @@ namespace OpenSim.Data.MySQL
} }
} }
} }
}
return landData; return landData;
} }
@ -1705,29 +1738,33 @@ namespace OpenSim.Data.MySQL
public void StorePrimInventory(UUID primID, ICollection<TaskInventoryItem> items) public void StorePrimInventory(UUID primID, ICollection<TaskInventoryItem> items)
{ {
lock (m_Connection) lock (m_dbLock)
{ {
RemoveItems(primID); RemoveItems(primID);
MySqlCommand cmd = m_Connection.CreateCommand(); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
MySqlCommand cmd = dbcon.CreateCommand();
if (items.Count == 0) if (items.Count == 0)
return; return;
cmd.CommandText = "insert into primitems ("+ cmd.CommandText = "insert into primitems (" +
"invType, assetType, name, "+ "invType, assetType, name, " +
"description, creationDate, nextPermissions, "+ "description, creationDate, nextPermissions, " +
"currentPermissions, basePermissions, "+ "currentPermissions, basePermissions, " +
"everyonePermissions, groupPermissions, "+ "everyonePermissions, groupPermissions, " +
"flags, itemID, primID, assetID, "+ "flags, itemID, primID, assetID, " +
"parentFolderID, creatorID, ownerID, "+ "parentFolderID, creatorID, ownerID, " +
"groupID, lastOwnerID) values (?invType, "+ "groupID, lastOwnerID) values (?invType, " +
"?assetType, ?name, ?description, "+ "?assetType, ?name, ?description, " +
"?creationDate, ?nextPermissions, "+ "?creationDate, ?nextPermissions, " +
"?currentPermissions, ?basePermissions, "+ "?currentPermissions, ?basePermissions, " +
"?everyonePermissions, ?groupPermissions, "+ "?everyonePermissions, ?groupPermissions, " +
"?flags, ?itemID, ?primID, ?assetID, "+ "?flags, ?itemID, ?primID, ?assetID, " +
"?parentFolderID, ?creatorID, ?ownerID, "+ "?parentFolderID, ?creatorID, ?ownerID, " +
"?groupID, ?lastOwnerID)"; "?groupID, ?lastOwnerID)";
foreach (TaskInventoryItem item in items) foreach (TaskInventoryItem item in items)
@ -1743,4 +1780,5 @@ namespace OpenSim.Data.MySQL
} }
} }
} }
}
} }

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");
using (MySql.Data.MySqlClient.MySqlConnection dbcon = new MySql.Data.MySqlClient.MySqlConnection(connect))
{
dbcon.Open();
Migration m = new Migration(dbcon, assem, "LogStore");
// TODO: After rev 6000, remove this. People should have // TODO: After rev 6000, remove this. People should have
// been rolled onto the new migration code by then. // been rolled onto the new migration code by then.
TestTables(m); TestTables(m);
m.Update(); 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,8 +131,12 @@ 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))
{
dbcon.Open();
using (MySqlCommand cmd = new MySqlCommand(m_waitTimeoutSelect, dbcon))
{
using (MySqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow)) using (MySqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow))
{ {
if (dbReader.Read()) if (dbReader.Read())
@ -143,9 +144,8 @@ namespace OpenSim.Data.MySQL
m_waitTimeout m_waitTimeout
= Convert.ToInt32(dbReader["@@wait_timeout"]) * TimeSpan.TicksPerSecond + m_waitTimeoutLeeway; = Convert.ToInt32(dbReader["@@wait_timeout"]) * TimeSpan.TicksPerSecond + m_waitTimeoutLeeway;
} }
}
dbReader.Close(); }
cmd.Dispose();
} }
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,10 +207,14 @@ 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))
{
dbcon.Open();
MySqlCommand cmd = new MySqlCommand(getResourceString(name), dbcon); MySqlCommand cmd = new MySqlCommand(getResourceString(name), dbcon);
cmd.ExecuteNonQuery(); cmd.ExecuteNonQuery();
} }
}
/// <summary> /// <summary>
/// Execute a MySqlCommand /// Execute a MySqlCommand
@ -275,14 +222,20 @@ 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))
{
dbcon.Open();
MySqlCommand cmd = new MySqlCommand(sql, dbcon); MySqlCommand cmd = new MySqlCommand(sql, dbcon);
cmd.ExecuteNonQuery(); 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))
{
dbcon.Open();
MySqlCommand cmd = (MySqlCommand)dbcon.CreateCommand(); MySqlCommand cmd = (MySqlCommand)dbcon.CreateCommand();
cmd.CommandText = sql; cmd.CommandText = sql;
@ -292,6 +245,7 @@ namespace OpenSim.Data.MySQL
} }
cmd.ExecuteNonQuery(); cmd.ExecuteNonQuery();
} }
}
/// <summary> /// <summary>
/// Given a list of tables, return the version of the tables, as seen in the database /// Given a list of tables, return the version of the tables, as seen in the database
@ -299,14 +253,15 @@ 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))
{
dbcon.Open();
MySqlCommand tablesCmd = using (MySqlCommand tablesCmd = new MySqlCommand(
new MySqlCommand( "SELECT TABLE_NAME, TABLE_COMMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=?dbname", dbcon))
"SELECT TABLE_NAME, TABLE_COMMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=?dbname", {
dbcon);
tablesCmd.Parameters.AddWithValue("?dbname", dbcon.Database); tablesCmd.Parameters.AddWithValue("?dbname", dbcon.Database);
using (MySqlDataReader tables = tablesCmd.ExecuteReader()) using (MySqlDataReader tables = tablesCmd.ExecuteReader())
@ -315,8 +270,8 @@ namespace OpenSim.Data.MySQL
{ {
try try
{ {
string tableName = (string) tables["TABLE_NAME"]; string tableName = (string)tables["TABLE_NAME"];
string comment = (string) tables["TABLE_COMMENT"]; string comment = (string)tables["TABLE_COMMENT"];
if (tableList.ContainsKey(tableName)) if (tableList.ContainsKey(tableName))
{ {
tableList[tableName] = comment; tableList[tableName] = comment;
@ -324,10 +279,11 @@ namespace OpenSim.Data.MySQL
} }
catch (Exception e) catch (Exception e)
{ {
m_log.Error(e.ToString()); m_log.Error(e.Message, e);
}
}
} }
} }
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,13 +680,18 @@ namespace OpenSim.Data.MySQL
try try
{ {
IDbCommand result = Query(sql, parameters); using (MySqlConnection dbcon = new MySqlConnection(connectionString))
{
dbcon.Open();
IDbCommand result = Query(dbcon, sql, parameters);
if (result.ExecuteNonQuery() == 1) if (result.ExecuteNonQuery() == 1)
returnval = true; returnval = true;
result.Dispose(); result.Dispose();
} }
}
catch (Exception e) catch (Exception e)
{ {
m_log.Error(e.ToString()); m_log.Error(e.ToString());
@ -778,7 +736,7 @@ namespace OpenSim.Data.MySQL
string aboutText, string firstText, string aboutText, string firstText,
UUID profileImage, UUID firstImage, UUID webLoginKey, int userFlags, int godLevel, string customType, UUID partner) UUID profileImage, UUID firstImage, UUID webLoginKey, int userFlags, int godLevel, string customType, UUID partner)
{ {
m_log.Debug("[MySQLManager]: Fetching profile for " + uuid.ToString()); m_log.Debug("[MySQLManager]: Creating profile for \"" + username + " " + lastname + "\" (" + uuid + ")");
string sql = string sql =
"INSERT INTO users (`UUID`, `username`, `lastname`, `email`, `passwordHash`, `passwordSalt`, `homeRegion`, `homeRegionID`, "; "INSERT INTO users (`UUID`, `username`, `lastname`, `email`, `passwordHash`, `passwordSalt`, `homeRegion`, `homeRegionID`, ";
sql += sql +=
@ -828,13 +786,18 @@ namespace OpenSim.Data.MySQL
try try
{ {
IDbCommand result = Query(sql, parameters); using (MySqlConnection dbcon = new MySqlConnection(connectionString))
{
dbcon.Open();
IDbCommand result = Query(dbcon, sql, parameters);
if (result.ExecuteNonQuery() == 1) if (result.ExecuteNonQuery() == 1)
returnval = true; returnval = true;
result.Dispose(); result.Dispose();
} }
}
catch (Exception e) catch (Exception e)
{ {
m_log.Error(e.ToString()); m_log.Error(e.ToString());
@ -927,13 +890,18 @@ 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();
IDbCommand result = Query(dbcon, sql, parameters);
if (result.ExecuteNonQuery() == 1) if (result.ExecuteNonQuery() == 1)
returnval = true; returnval = true;
result.Dispose(); result.Dispose();
} }
}
catch (Exception e) catch (Exception e)
{ {
m_log.Error(e.ToString()); m_log.Error(e.ToString());
@ -1030,7 +998,11 @@ namespace OpenSim.Data.MySQL
try try
{ {
IDbCommand result = Query(sql, parameters); using (MySqlConnection dbcon = new MySqlConnection(connectionString))
{
dbcon.Open();
IDbCommand result = Query(dbcon, sql, parameters);
// int x; // int x;
// if ((x = result.ExecuteNonQuery()) > 0) // if ((x = result.ExecuteNonQuery()) > 0)
@ -1043,6 +1015,7 @@ namespace OpenSim.Data.MySQL
} }
result.Dispose(); result.Dispose();
} }
}
catch (Exception e) catch (Exception e)
{ {
m_log.Error(e.ToString()); m_log.Error(e.ToString());
@ -1070,7 +1043,11 @@ namespace OpenSim.Data.MySQL
{ {
parameters["?uuid"] = uuid; parameters["?uuid"] = uuid;
IDbCommand result = Query(sql, parameters); using (MySqlConnection dbcon = new MySqlConnection(connectionString))
{
dbcon.Open();
IDbCommand result = Query(dbcon, sql, parameters);
// int x; // int x;
// if ((x = result.ExecuteNonQuery()) > 0) // if ((x = result.ExecuteNonQuery()) > 0)
@ -1083,6 +1060,7 @@ namespace OpenSim.Data.MySQL
} }
result.Dispose(); result.Dispose();
} }
}
catch (Exception e) catch (Exception e)
{ {
m_log.Error(e.ToString()); m_log.Error(e.ToString());
@ -1122,7 +1100,11 @@ namespace OpenSim.Data.MySQL
try try
{ {
IDbCommand result = Query(sql, parameters); using (MySqlConnection dbcon = new MySqlConnection(connectionString))
{
dbcon.Open();
IDbCommand result = Query(dbcon, sql, parameters);
// int x; // int x;
// if ((x = result.ExecuteNonQuery()) > 0) // if ((x = result.ExecuteNonQuery()) > 0)
@ -1135,6 +1117,7 @@ namespace OpenSim.Data.MySQL
} }
result.Dispose(); result.Dispose();
} }
}
catch (Exception e) catch (Exception e)
{ {
m_log.Error(e.ToString()); m_log.Error(e.ToString());
@ -1167,8 +1150,14 @@ 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(); {
using (MySqlConnection dbcon = new MySqlConnection(connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = (MySqlCommand)dbcon.CreateCommand())
{
cmd.CommandText = sql; cmd.CommandText = sql;
cmd.Parameters.AddWithValue("?owner", appearance.Owner.ToString()); cmd.Parameters.AddWithValue("?owner", appearance.Owner.ToString());
cmd.Parameters.AddWithValue("?serial", appearance.Serial); cmd.Parameters.AddWithValue("?serial", appearance.Serial);
@ -1204,8 +1193,8 @@ namespace OpenSim.Data.MySQL
if (cmd.ExecuteNonQuery() > 0) if (cmd.ExecuteNonQuery() > 0)
returnval = true; returnval = true;
}
cmd.Dispose(); }
} }
catch (Exception e) catch (Exception e)
{ {
@ -1221,7 +1210,11 @@ 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))
{
dbcon.Open();
MySqlCommand cmd = (MySqlCommand)dbcon.CreateCommand();
cmd.CommandText = sql; cmd.CommandText = sql;
cmd.Parameters.AddWithValue("?uuid", agentID.ToString()); cmd.Parameters.AddWithValue("?uuid", agentID.ToString());
@ -1232,7 +1225,7 @@ namespace OpenSim.Data.MySQL
sql = "insert into avatarattachments (UUID, attachpoint, item, asset) values (?uuid, ?attachpoint, ?item, ?asset)"; sql = "insert into avatarattachments (UUID, attachpoint, item, asset) values (?uuid, ?attachpoint, ?item, ?asset)";
cmd = (MySqlCommand) dbcon.CreateCommand(); cmd = (MySqlCommand)dbcon.CreateCommand();
cmd.CommandText = sql; cmd.CommandText = sql;
foreach (DictionaryEntry e in data) foreach (DictionaryEntry e in data)
@ -1251,4 +1244,5 @@ namespace OpenSim.Data.MySQL
} }
} }
} }
}
} }

View File

@ -38,17 +38,22 @@ 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))
{
dbcon.Open();
Migration m = new Migration(dbcon, GetType().Assembly, "GridStore");
m.Update(); m.Update();
} }
}
public List<RegionData> Get(string regionName, UUID scopeID) public List<RegionData> Get(string regionName, UUID scopeID)
{ {
@ -56,13 +61,14 @@ 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("?regionName", regionName);
cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString()); cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString());
return RunCommand(cmd); return RunCommand(cmd);
} }
}
public RegionData Get(int posX, int posY, UUID scopeID) public RegionData Get(int posX, int posY, UUID scopeID)
{ {
@ -70,8 +76,8 @@ 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("?posX", posX.ToString());
cmd.Parameters.AddWithValue("?posY", posY.ToString()); cmd.Parameters.AddWithValue("?posY", posY.ToString());
cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString()); cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString());
@ -82,6 +88,7 @@ namespace OpenSim.Data.MySQL
return ret[0]; return ret[0];
} }
}
public RegionData Get(UUID regionID, UUID scopeID) public RegionData Get(UUID regionID, UUID scopeID)
{ {
@ -89,8 +96,8 @@ 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("?regionID", regionID.ToString());
cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString()); cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString());
@ -100,6 +107,7 @@ namespace OpenSim.Data.MySQL
return ret[0]; 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,8 +115,8 @@ 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("?startX", startX.ToString());
cmd.Parameters.AddWithValue("?startY", startY.ToString()); cmd.Parameters.AddWithValue("?startY", startY.ToString());
cmd.Parameters.AddWithValue("?endX", endX.ToString()); cmd.Parameters.AddWithValue("?endX", endX.ToString());
@ -117,13 +125,19 @@ namespace OpenSim.Data.MySQL
return RunCommand(cmd); 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))
{
dbcon.Open();
cmd.Connection = dbcon;
using (IDataReader result = cmd.ExecuteReader())
{
while (result.Read()) while (result.Read())
{ {
RegionData ret = new RegionData(); RegionData ret = new RegionData();
@ -171,9 +185,8 @@ namespace OpenSim.Data.MySQL
retList.Add(ret); retList.Add(ret);
} }
}
result.Close(); }
CloseReaderCommand(cmd);
return retList; return retList;
} }
@ -201,15 +214,15 @@ 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"; string update = "update `" + m_Realm + "` set locX=?posX, locY=?posY, sizeX=?sizeX, sizeY=?sizeY";
foreach (string field in fields) foreach (string field in fields)
{ {
update += ", "; update += ", ";
update += "`" + field + "` = ?"+field; 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";
@ -236,41 +249,37 @@ namespace OpenSim.Data.MySQL
if (ExecuteNonQuery(cmd) < 1) if (ExecuteNonQuery(cmd) < 1)
{ {
cmd.Dispose();
return false; 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("?"+item, value);
cmd.Parameters.AddWithValue("?UUID", regionID.ToString()); cmd.Parameters.AddWithValue("?UUID", regionID.ToString());
if (ExecuteNonQuery(cmd) > 0) if (ExecuteNonQuery(cmd) > 0)
return true; 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()); cmd.Parameters.AddWithValue("?UUID", regionID.ToString());
if (ExecuteNonQuery(cmd) > 0) if (ExecuteNonQuery(cmd) > 0)
return true; return true;
}
return false; return false;
} }

View File

@ -38,17 +38,22 @@ namespace OpenSim.Data.MySQL
public class MySqlUserAccountData : MySqlFramework, IUserAccountData public class MySqlUserAccountData : MySqlFramework, IUserAccountData
{ {
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 MySqlUserAccountData(string connectionString, string realm) public MySqlUserAccountData(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, "UserStore"); using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
Migration m = new Migration(dbcon, GetType().Assembly, "UserStore");
m.Update(); m.Update();
} }
}
public List<UserAccountData> Query(UUID principalID, UUID scopeID, string query) public List<UserAccountData> Query(UUID principalID, UUID scopeID, string query)
{ {
@ -64,12 +69,15 @@ 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 (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
MySqlCommand cmd = new MySqlCommand(command, dbcon);
cmd.Parameters.AddWithValue("?principalID", principalID.ToString()); cmd.Parameters.AddWithValue("?principalID", principalID.ToString());
cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString()); cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString());
IDataReader result = ExecuteReader(cmd); IDataReader result = cmd.ExecuteReader();
if (result.Read()) if (result.Read())
{ {
@ -97,17 +105,14 @@ namespace OpenSim.Data.MySQL
ret.Data[s] = result[s].ToString(); ret.Data[s] = result[s].ToString();
} }
result.Close();
CloseReaderCommand(cmd);
return ret; return ret;
} }
else
result.Close(); {
CloseReaderCommand(cmd);
return null; return null;
} }
}
}
public bool Store(UserAccountData data) public bool Store(UserAccountData data)
{ {
@ -118,19 +123,19 @@ 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 "; string update = "update `" + m_Realm + "` set ";
bool first = true; bool first = true;
foreach (string field in fields) foreach (string field in fields)
{ {
if (!first) if (!first)
update += ", "; update += ", ";
update += "`" + field + "` = ?"+field; update += "`" + field + "` = ?" + field;
first = false; first = false;
cmd.Parameters.AddWithValue("?"+field, data.Data[field]); cmd.Parameters.AddWithValue("?" + field, data.Data[field]);
} }
update += " where UUID = ?principalID"; update += " where UUID = ?principalID";
@ -156,23 +161,22 @@ namespace OpenSim.Data.MySQL
return false; return false;
} }
} }
}
cmd.Dispose();
return true; return true;
} }
public bool SetDataItem(UUID principalID, string item, string value) public bool SetDataItem(UUID principalID, string item, string value)
{ {
MySqlCommand cmd = new MySqlCommand("update `" + m_Realm + using (MySqlCommand cmd = new MySqlCommand("update `" + m_Realm + "` set `" +
"` set `" + item + "` = ?" + item + " where UUID = ?UUID"); item + "` = ?" + item + " where UUID = ?UUID"))
{
cmd.Parameters.AddWithValue("?" + item, value);
cmd.Parameters.AddWithValue("?"+item, value);
cmd.Parameters.AddWithValue("?UUID", principalID.ToString()); cmd.Parameters.AddWithValue("?UUID", principalID.ToString());
if (ExecuteNonQuery(cmd) > 0) if (ExecuteNonQuery(cmd) > 0)
return true; 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,56 +74,19 @@ 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");
using (MySql.Data.MySqlClient.MySqlConnection dbcon = new MySql.Data.MySqlClient.MySqlConnection(m_connectionString))
{
dbcon.Open();
Migration m = new Migration(dbcon, assem, "UserStore");
m.Update(); 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())
{
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();
}
} }
#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( {
dbcon.Open();
using (IDbCommand updater = m_database.Query(dbcon,
"update " + m_userFriendsTableName + "update " + m_userFriendsTableName +
" SET friendPerms = ?friendPerms " + " SET friendPerms = ?friendPerms " +
"where ownerID = ?ownerID and friendID = ?friendID", "where ownerID = ?ownerID and friendID = ?friendID",
param); param))
{
updater.ExecuteNonQuery(); 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,65 +240,66 @@ 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
{ {
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
//Left Join userfriends to itself //Left Join userfriends to itself
IDbCommand result = using (IDbCommand result = m_database.Query(dbcon,
dbm.Manager.Query(
"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()) while (reader.Read())
{ {
FriendListItem fli = new FriendListItem(); FriendListItem fli = new FriendListItem();
fli.FriendListOwner = new UUID((string) reader["ownerID"]); fli.FriendListOwner = new UUID((string)reader["ownerID"]);
fli.Friend = new UUID((string) reader["friendID"]); fli.Friend = new UUID((string)reader["friendID"]);
fli.FriendPerms = (uint) Convert.ToInt32(reader["friendPerms"]); 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 // 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"]); fli.FriendListOwnerPerms = (uint)Convert.ToInt32(reader["ownerperms"]);
Lfli.Add(fli); 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
{ {
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
foreach (UUID uuid in uuids) foreach (UUID uuid in uuids)
{ {
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 agentOnline,currentHandle from " + m_agentsTableName +
" where UUID = ?uuid", param);
IDataReader reader = result.ExecuteReader(); 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()) while (reader.Read())
{ {
FriendRegionInfo fri = new FriendRegionInfo(); FriendRegionInfo fri = new FriendRegionInfo();
@ -389,20 +308,15 @@ namespace OpenSim.Data.MySQL
infos[uuid] = fri; 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(); AvatarPickerAvatar user = new AvatarPickerAvatar();
user.AvatarID = new UUID((string) reader["UUID"]); user.AvatarID = new UUID((string)reader["UUID"]);
user.firstName = (string) reader["username"]; user.firstName = (string)reader["username"];
user.lastName = (string) reader["lastname"]; user.lastName = (string)reader["lastname"];
returnlist.Add(user); 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(); AvatarPickerAvatar user = new AvatarPickerAvatar();
user.AvatarID = new UUID((string) reader["UUID"]); user.AvatarID = new UUID((string)reader["UUID"]);
user.firstName = (string) reader["username"]; user.firstName = (string)reader["username"];
user.lastName = (string) reader["lastname"]; user.lastName = (string)reader["lastname"];
returnlist.Add(user); 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);
reader.Dispose();
result.Dispose();
using (IDbCommand result = m_database.Query(dbcon, "SELECT * FROM " + m_usersTableName + " WHERE UUID = ?uuid", param))
{
using (IDataReader reader = result.ExecuteReader())
{
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);
reader.Dispose();
result.Dispose();
using (IDbCommand result = m_database.Query(dbcon, "SELECT * FROM " + m_agentsTableName + " WHERE UUID = ?uuid", param))
{
using (IDataReader reader = result.ExecuteReader())
{
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,11 +532,11 @@ 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.ID, user.FirstName, user.SurName, user.Email, user.PasswordHash, user.PasswordSalt,
user.HomeRegion, user.HomeRegionID, user.HomeLocation.X, user.HomeLocation.Y, user.HomeRegion, user.HomeRegionID, user.HomeLocation.X, user.HomeLocation.Y,
user.HomeLocation.Z, user.HomeLocation.Z,
user.HomeLookAt.X, user.HomeLookAt.Y, user.HomeLookAt.Z, user.Created, user.HomeLookAt.X, user.HomeLookAt.Y, user.HomeLookAt.Z, user.Created,
@ -649,12 +547,7 @@ namespace OpenSim.Data.MySQL
} }
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,10 +577,10 @@ 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.ID, user.FirstName, user.SurName, user.Email, user.PasswordHash, user.PasswordSalt,
user.HomeRegion, user.HomeRegionID, user.HomeLocation.X, user.HomeLocation.Y, user.HomeRegion, user.HomeRegionID, user.HomeLocation.X, user.HomeLocation.Y,
user.HomeLocation.Z, user.HomeLookAt.X, user.HomeLocation.Z, user.HomeLookAt.X,
user.HomeLookAt.Y, user.HomeLookAt.Z, user.Created, user.LastLogin, user.HomeLookAt.Y, user.HomeLookAt.Z, user.Created, user.LastLogin,
@ -701,14 +588,14 @@ namespace OpenSim.Data.MySQL
user.UserAssetURI, user.CanDoMask, user.WantDoMask, user.AboutText, user.UserAssetURI, user.CanDoMask, user.WantDoMask, user.AboutText,
user.FirstLifeAboutText, user.Image, user.FirstLifeImage, user.WebLoginKey, user.FirstLifeAboutText, user.Image, user.FirstLifeImage, user.WebLoginKey,
user.UserFlags, user.GodLevel, user.CustomType, user.Partner); user.UserFlags, user.GodLevel, user.CustomType, user.Partner);
}
finally
{
dbm.Release();
}
return true; return true;
} }
catch
{
return false;
}
}
/// <summary> /// <summary>
/// Performs a money transfer request between two accounts /// Performs a money transfer request between two accounts
@ -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(); dbcon.Open();
AvatarAppearance appearance = dbm.Manager.readAppearanceRow(reader); 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);
reader.Dispose(); if (appearance == null)
result.Dispose();
if (null == appearance)
{ {
m_log.WarnFormat("[USER DB] No appearance found for user {0}", user.ToString()); m_log.WarnFormat("[USER DB] No appearance found for user {0}", user.ToString());
return null; return null;
} }
else
{
appearance.SetAttachments(GetUserAttachments(user)); appearance.SetAttachments(GetUserAttachments(user));
return appearance; 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())
{
Hashtable ret = m_database.readAttachments(reader);
return ret; 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,45 +743,29 @@ 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(
try
{
dbm.Manager.ExecuteParameterizedSql(
"UPDATE " + m_attachmentsTableName + "UPDATE " + m_attachmentsTableName +
" SET asset = '00000000-0000-0000-0000-000000000000' WHERE UUID = ?uuid", " SET asset = '00000000-0000-0000-0000-000000000000' WHERE UUID = ?uuid",
param); param);
} }
finally
{
dbm.Release();
}
}
public override void LogoutUsers(UUID regionID) public override void LogoutUsers(UUID regionID)
{ {
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,7 +110,8 @@ 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);
@ -118,10 +119,12 @@ namespace OpenSim.Data.MySQL
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());
@ -129,16 +132,24 @@ namespace OpenSim.Data.MySQL
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))
{
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.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("?PrincipalID", principalID.ToString());
cmd.Parameters.AddWithValue("?AssetID", assetID.ToString()); cmd.Parameters.AddWithValue("?AssetID", assetID.ToString());
IDataReader reader = ExecuteReader(cmd); using (IDataReader reader = cmd.ExecuteReader())
{
int perms = 0; int perms = 0;
@ -147,10 +158,10 @@ namespace OpenSim.Data.MySQL
perms = Convert.ToInt32(reader["inventoryCurrentPermissions"]); perms = Convert.ToInt32(reader["inventoryCurrentPermissions"]);
} }
reader.Close();
CloseReaderCommand(cmd);
return perms; 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,10 +66,14 @@ 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");
using (MySqlConnection dbcon = new MySqlConnection(connect))
{
dbcon.Open();
Migration m = new Migration(dbcon, assem, "AssetStore");
m.Update(); m.Update();
} }
}
[TestFixtureTearDown] [TestFixtureTearDown]
public void Cleanup() public void Cleanup()

View File

@ -5177,6 +5177,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)
{ {

View File

@ -115,7 +115,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
// client.OnAvatarNowWearing -= AvatarIsWearing; // client.OnAvatarNowWearing -= AvatarIsWearing;
} }
public void SetAppearanceAssets(UUID userID, ref AvatarAppearance appearance) public void SetAppearanceAssets(UUID userID, ref AvatarAppearance appearance)
{ {
IInventoryService invService = m_scene.InventoryService; IInventoryService invService = m_scene.InventoryService;
@ -139,7 +138,10 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
} }
else else
{ {
m_log.ErrorFormat("[APPEARANCE]: Can't find inventory item {0}, setting to default", appearance.Wearables[i].ItemID); m_log.ErrorFormat(
"[APPEARANCE]: Can't find inventory item {0} for {1}, setting to default",
appearance.Wearables[i].ItemID, (WearableType)i);
appearance.Wearables[i].AssetID = def.Wearables[i].AssetID; appearance.Wearables[i].AssetID = def.Wearables[i].AssetID;
} }
} }

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

@ -43,10 +43,67 @@ namespace OpenSim.Region.Framework.Interfaces
int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face); int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face);
UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, string extraParams, UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, string extraParams,
int updateTimer); int updateTimer);
/// Apply a dynamically generated texture to all sides of the given prim. The texture is not persisted to the
/// asset service.
/// </summary>
/// <param name="simID">The simulator in which the texture is being generated</param>
/// <param name="primID">The prim to which to apply the texture.</param>
/// <param name="contentType">The content type to create. Current choices are "vector" to create a vector
/// based texture or "image" to create a texture from an image at a particular URL</param>
/// <param name="data">The data for the generator</param>
/// <param name="extraParams">Parameters for the generator that don't form part of the main data.</param>
/// <param name="updateTimer">If zero, the image is never updated after the first generation. If positive
/// the image is updated at the given interval. Not implemented for </param>
/// <param name="SetBlending">
/// If true, the newly generated texture is blended with the appropriate existing ones on the prim
/// </param>
/// <param name="AlphaValue">
/// The alpha value of the generated texture.
/// </param>
/// <returns>
/// The UUID of the texture updater, not the texture UUID. If you need the texture UUID then you will need
/// to obtain it directly from the SceneObjectPart. For instance, if ALL_SIDES is set then this texture
/// can be obtained as SceneObjectPart.Shape.Textures.DefaultTexture.TextureID
/// </returns>
UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, string extraParams, UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, string extraParams,
int updateTimer, bool SetBlending, byte AlphaValue); int updateTimer, bool SetBlending, byte AlphaValue);
UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, string extraParams,
/// <summary>
/// Apply a dynamically generated texture to the given prim.
/// </summary>
/// <param name="simID">The simulator in which the texture is being generated</param>
/// <param name="primID">The prim to which to apply the texture.</param>
/// <param name="contentType">The content type to create. Current choices are "vector" to create a vector
/// based texture or "image" to create a texture from an image at a particular URL</param>
/// <param name="data">The data for the generator</param>
/// <param name="extraParams">Parameters for the generator that don't form part of the main data.</param>
/// <param name="updateTimer">If zero, the image is never updated after the first generation. If positive
/// the image is updated at the given interval. Not implemented for </param>
/// <param name="SetBlending">
/// If true, the newly generated texture is blended with the appropriate existing ones on the prim
/// </param>
/// <param name="disp">
/// Display flags. If DISP_EXPIRE then the old texture is deleted if it is replaced by a
/// newer generated texture (may not currently be implemented). If DISP_TEMP then the asset is flagged as
/// temporary, which often means that it is not persisted to the database.
/// </param>
/// <param name="AlphaValue">
/// The alpha value of the generated texture.
/// </param>
/// <param name="face">
/// The face of the prim on which to put the generated texture. If ALL_SIDES then all sides of the prim are
/// set
/// </param>
/// <returns>
/// The UUID of the texture updater, not the texture UUID. If you need the texture UUID then you will need
/// to obtain it directly from the SceneObjectPart. For instance, if ALL_SIDES is set then this texture
/// can be obtained as SceneObjectPart.Shape.Textures.DefaultTexture.TextureID
/// </returns>
UUID AddDynamicTextureData(
UUID simID, UUID primID, string contentType, string data, string extraParams,
int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face); int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face);
void GetDrawStringSize(string contentType, string text, string fontName, int fontSize, void GetDrawStringSize(string contentType, string text, string fontName, int fontSize,
out double xSize, out double ySize); out double xSize, out double ySize);
} }

View File

@ -209,6 +209,12 @@ namespace OpenSim.Region.Framework.Scenes
public event OnSendNewWindlightProfileTargetedDelegate OnSendNewWindlightProfileTargeted; public event OnSendNewWindlightProfileTargetedDelegate OnSendNewWindlightProfileTargeted;
public event OnSaveNewWindlightProfileDelegate OnSaveNewWindlightProfile; public event OnSaveNewWindlightProfileDelegate OnSaveNewWindlightProfile;
/// <summary>
/// Triggered when an object or attachment enters a scene
/// </summary>
public event OnIncomingSceneObjectDelegate OnIncomingSceneObject;
public delegate void OnIncomingSceneObjectDelegate(SceneObjectGroup so);
public delegate void NewInventoryItemUploadComplete(UUID avatarID, UUID assetID, string name, int userlevel); public delegate void NewInventoryItemUploadComplete(UUID avatarID, UUID assetID, string name, int userlevel);
public event NewInventoryItemUploadComplete OnNewInventoryItemUploadComplete; public event NewInventoryItemUploadComplete OnNewInventoryItemUploadComplete;
@ -1228,6 +1234,27 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
public void TriggerOnIncomingSceneObject(SceneObjectGroup so)
{
OnIncomingSceneObjectDelegate handlerIncomingSceneObject = OnIncomingSceneObject;
if (handlerIncomingSceneObject != null)
{
foreach (OnIncomingSceneObjectDelegate d in handlerIncomingSceneObject.GetInvocationList())
{
try
{
d(so);
}
catch (Exception e)
{
m_log.ErrorFormat(
"[EVENT MANAGER]: Delegate for TriggerOnIncomingSceneObject failed - continuing. {0} {1}",
e.Message, e.StackTrace);
}
}
}
}
public void TriggerOnRegisterCaps(UUID agentID, Caps caps) public void TriggerOnRegisterCaps(UUID agentID, Caps caps)
{ {
RegisterCapsEvent handlerRegisterCaps = OnRegisterCaps; RegisterCapsEvent handlerRegisterCaps = OnRegisterCaps;

View File

@ -2433,9 +2433,14 @@ namespace OpenSim.Region.Framework.Scenes
return successYN; return successYN;
} }
/// <summary>
/// Called when objects or attachments cross the border between regions.
/// </summary>
/// <param name="sog"></param>
/// <returns></returns>
public bool IncomingCreateObject(ISceneObject sog) public bool IncomingCreateObject(ISceneObject sog)
{ {
//m_log.Debug(" >>> IncomingCreateObject <<< " + ((SceneObjectGroup)sog).AbsolutePosition + " deleted? " + ((SceneObjectGroup)sog).IsDeleted); //m_log.Debug(" >>> IncomingCreateObject(sog) <<< " + ((SceneObjectGroup)sog).AbsolutePosition + " deleted? " + ((SceneObjectGroup)sog).IsDeleted);
SceneObjectGroup newObject; SceneObjectGroup newObject;
try try
{ {
@ -2452,7 +2457,12 @@ namespace OpenSim.Region.Framework.Scenes
m_log.DebugFormat("[SCENE]: Problem adding scene object {0} in {1} ", sog.UUID, RegionInfo.RegionName); m_log.DebugFormat("[SCENE]: Problem adding scene object {0} in {1} ", sog.UUID, RegionInfo.RegionName);
return false; return false;
} }
newObject.RootPart.ParentGroup.CreateScriptInstances(0, false, DefaultScriptEngine, 1); newObject.RootPart.ParentGroup.CreateScriptInstances(0, false, DefaultScriptEngine, 1);
// Do this as late as possible so that listeners have full access to the incoming object
EventManager.TriggerOnIncomingSceneObject(newObject);
return true; return true;
} }
@ -2464,6 +2474,8 @@ namespace OpenSim.Region.Framework.Scenes
/// <returns>False</returns> /// <returns>False</returns>
public virtual bool IncomingCreateObject(UUID userID, UUID itemID) public virtual bool IncomingCreateObject(UUID userID, UUID itemID)
{ {
//m_log.DebugFormat(" >>> IncomingCreateObject(userID, itemID) <<< {0} {1}", userID, itemID);
ScenePresence sp = GetScenePresence(userID); ScenePresence sp = GetScenePresence(userID);
if (sp != null) if (sp != null)
{ {
@ -2498,7 +2510,7 @@ namespace OpenSim.Region.Framework.Scenes
foreach (SceneObjectPart p in sceneObject.Children.Values) foreach (SceneObjectPart p in sceneObject.Children.Values)
p.LocalId = 0; p.LocalId = 0;
if ((sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim) && (sceneObject.RootPart.Shape.State != 0)) // Attachment if (sceneObject.IsAttachmentCheckFull()) // Attachment
{ {
sceneObject.RootPart.AddFlag(PrimFlags.TemporaryOnRez); sceneObject.RootPart.AddFlag(PrimFlags.TemporaryOnRez);
sceneObject.RootPart.AddFlag(PrimFlags.Phantom); sceneObject.RootPart.AddFlag(PrimFlags.Phantom);
@ -2523,20 +2535,15 @@ namespace OpenSim.Region.Framework.Scenes
//RootPrim.SetParentLocalId(parentLocalID); //RootPrim.SetParentLocalId(parentLocalID);
m_log.DebugFormat("[ATTACHMENT]: Received " + m_log.DebugFormat(
"attachment {0}, inworld asset id {1}", "[ATTACHMENT]: Received attachment {0}, inworld asset id {1}", grp.GetFromItemID(), grp.UUID);
//grp.RootPart.LastOwnerID.ToString(),
grp.GetFromItemID(),
grp.UUID.ToString());
//grp.SetFromAssetID(grp.RootPart.LastOwnerID); //grp.SetFromAssetID(grp.RootPart.LastOwnerID);
m_log.DebugFormat("[ATTACHMENT]: Attach " + m_log.DebugFormat(
"to avatar {0} at position {1}", "[ATTACHMENT]: Attach to avatar {0} at position {1}", sp.UUID, grp.AbsolutePosition);
sp.UUID.ToString(), grp.AbsolutePosition);
AttachObject(sp.ControllingClient, AttachObject(
grp.LocalId, (uint)0, sp.ControllingClient, grp.LocalId, (uint)0, grp.GroupRotation, grp.AbsolutePosition, false);
grp.GroupRotation,
grp.AbsolutePosition, false);
RootPrim.RemFlag(PrimFlags.TemporaryOnRez); RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
grp.SendGroupFullUpdate(); grp.SendGroupFullUpdate();
} }
@ -2545,7 +2552,6 @@ namespace OpenSim.Region.Framework.Scenes
RootPrim.RemFlag(PrimFlags.TemporaryOnRez); RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
RootPrim.AddFlag(PrimFlags.TemporaryOnRez); RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
} }
} }
else else
{ {

View File

@ -191,7 +191,6 @@ namespace OpenSim.Region.Framework.Scenes
if (handlerChildAgentUpdate != null) if (handlerChildAgentUpdate != null)
handlerChildAgentUpdate(cAgentData); handlerChildAgentUpdate(cAgentData);
return true; return true;
} }

View File

@ -337,7 +337,16 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
private bool IsAttachmentCheckFull() /// <summary>
/// Check both the attachment property and the relevant properties of the underlying root part.
/// </summary>
/// This is necessary in some cases, particularly when a scene object has just crossed into a region and doesn't
/// have the IsAttachment property yet checked.
///
/// FIXME: However, this should be fixed so that this property
/// propertly reflects the underlying status.
/// <returns></returns>
public bool IsAttachmentCheckFull()
{ {
return (IsAttachment || (m_rootPart.Shape.PCode == 9 && m_rootPart.Shape.State != 0)); return (IsAttachment || (m_rootPart.Shape.PCode == 9 && m_rootPart.Shape.State != 0));
} }

View File

@ -4171,9 +4171,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;

View File

@ -106,6 +106,16 @@ namespace OpenSim.Region.Framework.Scenes
} }
protected ScenePresenceAnimator m_animator; protected ScenePresenceAnimator m_animator;
/// <value>
/// The scene objects attached to this avatar. Do not change this list directly - use methods such as
/// AddAttachment() and RemoveAttachment(). Lock this list when performing any read operations upon it.
/// </value>
public List<SceneObjectGroup> Attachments
{
get { return m_attachments; }
}
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;
@ -225,8 +235,6 @@ namespace OpenSim.Region.Framework.Scenes
protected AvatarAppearance m_appearance; protected AvatarAppearance m_appearance;
protected List<SceneObjectGroup> m_attachments = new List<SceneObjectGroup>();
// neighbouring regions we have enabled a child agent in // neighbouring regions we have enabled a child agent in
// holds the seed cap for the child agent in that region // holds the seed cap for the child agent in that region
private Dictionary<ulong, string> m_knownChildRegions = new Dictionary<ulong, string>(); private Dictionary<ulong, string> m_knownChildRegions = new Dictionary<ulong, string>();
@ -641,11 +649,15 @@ namespace OpenSim.Region.Framework.Scenes
#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;
@ -669,7 +681,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();
Animator.TrySetMovementAnimation("STAND"); Animator.TrySetMovementAnimation("STAND");
// we created a new ScenePresence (a new child agent) in a fresh region. // we created a new ScenePresence (a new child agent) in a fresh region.
@ -1150,7 +1161,6 @@ namespace OpenSim.Region.Framework.Scenes
m_controllingClient.MoveAgentIntoRegion(m_regionInfo, AbsolutePosition, look); m_controllingClient.MoveAgentIntoRegion(m_regionInfo, AbsolutePosition, look);
SendInitialData(); SendInitialData();
} }
/// <summary> /// <summary>
@ -3389,7 +3399,6 @@ namespace OpenSim.Region.Framework.Scenes
m_physicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong m_physicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong
m_physicsActor.SubscribeEvents(500); m_physicsActor.SubscribeEvents(500);
m_physicsActor.LocalID = LocalId; m_physicsActor.LocalID = LocalId;
} }
private void OutOfBoundsCall(Vector3 pos) private void OutOfBoundsCall(Vector3 pos)
@ -3399,7 +3408,7 @@ namespace OpenSim.Region.Framework.Scenes
//AddToPhysicalScene(flying); //AddToPhysicalScene(flying);
if (ControllingClient != null) if (ControllingClient != null)
ControllingClient.SendAgentAlertMessage("Physics is having a problem with your avatar. You may not be able to move until you relog.",true); ControllingClient.SendAgentAlertMessage("Physics is having a problem with your avatar. You may not be able to move until you relog.", true);
} }
// Event called by the physics plugin to tell the avatar about a collision. // Event called by the physics plugin to tell the avatar about a collision.
@ -3539,13 +3548,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)

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

@ -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

@ -2916,6 +2916,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">