Updated MySQL connection management to use the MySQL connection pooling. This should accommodate various timeout problems that exist with the current connection pool code in a more general and standard way.

mysql-performance
Master ScienceSim 2010-02-04 13:19:30 -08:00 committed by John Hurliman
parent 5f1f5c29e9
commit e1b5c61247
15 changed files with 2261 additions and 2660 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;
} }
} }
@ -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,14 +709,19 @@ namespace OpenSim.Data.MySQL
} }
} }
} }
}
public RegionSettings LoadRegionSettings(UUID regionUUID) public RegionSettings LoadRegionSettings(UUID regionUUID)
{ {
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);
@ -722,15 +744,20 @@ namespace OpenSim.Data.MySQL
} }
} }
} }
}
return rs; return rs;
} }
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, " +
@ -771,14 +798,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());
@ -793,7 +825,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)
{ {
@ -811,6 +843,7 @@ namespace OpenSim.Data.MySQL
} }
} }
} }
}
return landData; return landData;
} }
@ -1513,29 +1546,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)
@ -1551,4 +1588,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());
@ -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()