More changes to the MySQL adapter. take advantage of pooling and run lock-free.

This should finally kill the "There is already an open data reader associated
with this connection, which must be closed first" error that makes people's
builds not save
0.6.1-post-fixes
Melanie Thielker 2008-11-30 05:20:19 +00:00
parent 07ee2c3504
commit 38380def17
1 changed files with 479 additions and 514 deletions

View File

@ -72,69 +72,10 @@ namespace OpenSim.Data.MySQL
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); cmd.ExecuteNonQuery();
cmd.Dispose(); cmd.Dispose();
}
private IDataReader ExecuteReader(MySqlCommand c)
{
IDataReader r = null;
bool errorSeen = false;
while (true)
{
try
{
r = c.ExecuteReader();
}
catch (MySqlException)
{
System.Threading.Thread.Sleep(500);
m_Connection.Close(); m_Connection.Close();
m_Connection.Open();
if (!errorSeen)
{
errorSeen = true;
continue;
}
throw;
}
break;
}
return r;
}
private void ExecuteNonQuery(MySqlCommand c)
{
bool errorSeen = false;
while (true)
{
try
{
c.ExecuteNonQuery();
}
catch (MySqlException)
{
System.Threading.Thread.Sleep(500);
m_Connection.Close();
m_Connection.Open();
if (!errorSeen)
{
errorSeen = true;
continue;
}
throw;
}
break;
}
} }
public void Dispose() {} public void Dispose() {}
@ -150,9 +91,10 @@ namespace OpenSim.Data.MySQL
if ((flags & (uint)PrimFlags.TemporaryOnRez) != 0) if ((flags & (uint)PrimFlags.TemporaryOnRez) != 0)
return; return;
lock (m_Connection) MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
{ c.Open();
MySqlCommand cmd = m_Connection.CreateCommand();
MySqlCommand cmd = c.CreateCommand();
foreach (SceneObjectPart prim in obj.Children.Values) foreach (SceneObjectPart prim in obj.Children.Values)
{ {
@ -227,7 +169,7 @@ namespace OpenSim.Data.MySQL
FillPrimCommand(cmd, prim, obj.UUID, regionUUID); FillPrimCommand(cmd, prim, obj.UUID, regionUUID);
ExecuteNonQuery(cmd); cmd.ExecuteNonQuery();
cmd.Parameters.Clear(); cmd.Parameters.Clear();
@ -255,10 +197,10 @@ namespace OpenSim.Data.MySQL
FillShapeCommand(cmd, prim); FillShapeCommand(cmd, prim);
ExecuteNonQuery(cmd); cmd.ExecuteNonQuery();
} }
cmd.Dispose(); cmd.Dispose();
} c.Close();
} }
public void RemoveObject(UUID obj, UUID regionUUID) public void RemoveObject(UUID obj, UUID regionUUID)
@ -271,9 +213,10 @@ 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) MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
{ c.Open();
MySqlCommand cmd = m_Connection.CreateCommand();
MySqlCommand cmd = c.CreateCommand();
cmd.CommandText = "select UUID from prims where "+ cmd.CommandText = "select UUID from prims where "+
"SceneGroupID= ?UUID"; "SceneGroupID= ?UUID";
@ -282,11 +225,11 @@ namespace OpenSim.Data.MySQL
List<UUID> uuids = new List<UUID>(); List<UUID> uuids = new List<UUID>();
IDataReader reader = ExecuteReader(cmd); IDataReader reader = cmd.ExecuteReader();
try try
{ {
while (reader.Read()) while(reader.Read())
{ {
uuids.Add(new UUID(reader["UUID"].ToString())); uuids.Add(new UUID(reader["UUID"].ToString()));
} }
@ -296,18 +239,25 @@ namespace OpenSim.Data.MySQL
reader.Close(); reader.Close();
} }
foreach (UUID uuid in uuids)
RemoveItems(uuid);
cmd.CommandText = "delete from prims where SceneGroupID= ?UUID"; cmd.CommandText = "delete from prims where SceneGroupID= ?UUID";
ExecuteNonQuery(cmd); cmd.ExecuteNonQuery();
cmd.CommandText = "delete from primshapes where UUID = ?UUID"; cmd.CommandText = "delete from primshapes where UUID = ?UUID";
ExecuteNonQuery(cmd); foreach (UUID uuid in uuids)
cmd.Dispose(); {
cmd.Parameters.Clear();
cmd.Parameters.AddWithValue("UUID", Util.ToRawUuidString(uuid));
cmd.ExecuteNonQuery();
} }
cmd.Dispose();
c.Close();
foreach (UUID uuid in uuids)
RemoveItems(uuid);
} }
/// <summary> /// <summary>
@ -317,18 +267,19 @@ 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) MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
{ c.Open();
MySqlCommand cmd = m_Connection.CreateCommand();
MySqlCommand cmd = c.CreateCommand();
cmd.CommandText = "delete from primitems where " + cmd.CommandText = "delete from primitems where " +
"PrimID = ?PrimID"; "PrimID = ?PrimID";
cmd.Parameters.AddWithValue("PrimID", uuid.ToString()); cmd.Parameters.AddWithValue("PrimID", uuid.ToString());
ExecuteNonQuery(cmd); cmd.ExecuteNonQuery();
cmd.Dispose(); cmd.Dispose();
} c.Close();
} }
public List<SceneObjectGroup> LoadObjects(UUID regionUUID) public List<SceneObjectGroup> LoadObjects(UUID regionUUID)
@ -338,9 +289,10 @@ namespace OpenSim.Data.MySQL
List<SceneObjectPart> prims = new List<SceneObjectPart>(); List<SceneObjectPart> prims = new List<SceneObjectPart>();
SceneObjectGroup grp = null; SceneObjectGroup grp = null;
lock (m_Connection) MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
{ c.Open();
MySqlCommand cmd = m_Connection.CreateCommand();
MySqlCommand cmd = c.CreateCommand();
cmd.CommandText = "select *, " + cmd.CommandText = "select *, " +
"case when prims.UUID = SceneGroupID " + "case when prims.UUID = SceneGroupID " +
@ -352,7 +304,7 @@ namespace OpenSim.Data.MySQL
cmd.Parameters.AddWithValue("RegionUUID", cmd.Parameters.AddWithValue("RegionUUID",
Util.ToRawUuidString(regionUUID)); Util.ToRawUuidString(regionUUID));
IDataReader reader = ExecuteReader(cmd); IDataReader reader = cmd.ExecuteReader();
try try
{ {
@ -402,7 +354,7 @@ namespace OpenSim.Data.MySQL
if (grp != null) if (grp != null)
objects.Add(grp); objects.Add(grp);
cmd.Dispose(); cmd.Dispose();
} c.Close();
foreach (SceneObjectPart part in prims) foreach (SceneObjectPart part in prims)
LoadItems(part); LoadItems(part);
@ -418,16 +370,17 @@ 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) MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
{ c.Open();
MySqlCommand cmd = m_Connection.CreateCommand();
MySqlCommand cmd = c.CreateCommand();
cmd.CommandText = "select * from primitems where "+ cmd.CommandText = "select * from primitems where "+
"PrimID = ?PrimID"; "PrimID = ?PrimID";
cmd.Parameters.AddWithValue("PrimID", prim.UUID.ToString()); cmd.Parameters.AddWithValue("PrimID", prim.UUID.ToString());
IDataReader reader = ExecuteReader(cmd); IDataReader reader = cmd.ExecuteReader();
List<TaskInventoryItem> inventory = List<TaskInventoryItem> inventory =
new List<TaskInventoryItem>(); new List<TaskInventoryItem>();
@ -448,24 +401,25 @@ namespace OpenSim.Data.MySQL
} }
cmd.Dispose(); cmd.Dispose();
c.Close();
prim.Inventory.RestoreInventoryItems(inventory); prim.Inventory.RestoreInventoryItems(inventory);
} }
}
public void StoreTerrain(double[,] ter, UUID regionID) public void StoreTerrain(double[,] ter, UUID regionID)
{ {
m_log.Info("[REGION DB]: Storing terrain"); m_log.Info("[REGION DB]: Storing terrain");
lock (m_Connection) MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
{ c.Open();
MySqlCommand cmd = m_Connection.CreateCommand();
MySqlCommand cmd = c.CreateCommand();
cmd.CommandText = "delete from terrain where " + cmd.CommandText = "delete from terrain where " +
"RegionUUID = ?RegionUUID"; "RegionUUID = ?RegionUUID";
cmd.Parameters.AddWithValue("RegionUUID", cmd.Parameters.AddWithValue("RegionUUID",
Util.ToRawUuidString(regionID)); Util.ToRawUuidString(regionID));
ExecuteNonQuery(cmd); cmd.ExecuteNonQuery();
cmd.CommandText = "insert into terrain (RegionUUID, " + cmd.CommandText = "insert into terrain (RegionUUID, " +
"Revision, Heightfield) values (?RegionUUID, " + "Revision, Heightfield) values (?RegionUUID, " +
@ -474,9 +428,9 @@ namespace OpenSim.Data.MySQL
cmd.Parameters.AddWithValue("Heightfield", cmd.Parameters.AddWithValue("Heightfield",
SerializeTerrain(ter)); SerializeTerrain(ter));
ExecuteNonQuery(cmd); cmd.ExecuteNonQuery();
cmd.Dispose(); cmd.Dispose();
} c.Close();
} }
public double[,] LoadTerrain(UUID regionID) public double[,] LoadTerrain(UUID regionID)
@ -484,15 +438,17 @@ namespace OpenSim.Data.MySQL
double[,] terrain = new double[256,256]; double[,] terrain = new double[256,256];
terrain.Initialize(); terrain.Initialize();
lock (m_Connection) MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
{ c.Open();
MySqlCommand cmd = m_Connection.CreateCommand();
MySqlCommand cmd = c.CreateCommand();
cmd.CommandText = "select RegionUUID, Revision, Heightfield " + cmd.CommandText = "select RegionUUID, Revision, Heightfield " +
"from terrain where RegionUUID = ?RegionUUID "+ "from terrain where RegionUUID = ?RegionUUID "+
"order by Revision desc limit 1"; "order by Revision desc limit 1";
cmd.Parameters.AddWithValue("RegionUUID", Util.ToRawUuidString(regionID)); cmd.Parameters.AddWithValue("RegionUUID", Util.ToRawUuidString(regionID));
IDataReader reader = ExecuteReader(cmd); IDataReader reader = cmd.ExecuteReader();
try try
{ {
@ -513,39 +469,44 @@ namespace OpenSim.Data.MySQL
m_log.InfoFormat("[REGION DB]: Loaded terrain " + m_log.InfoFormat("[REGION DB]: Loaded terrain " +
"revision r{0}", rev); "revision r{0}", rev);
reader.Close();
cmd.Dispose();
c.Close();
return terrain; return terrain;
} }
} }
finally catch (Exception)
{ {
}
reader.Close(); reader.Close();
}
cmd.Dispose(); cmd.Dispose();
} c.Close();
return null; return null;
} }
public void RemoveLandObject(UUID globalID) public void RemoveLandObject(UUID globalID)
{ {
lock (m_Connection) MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
{ c.Open();
MySqlCommand cmd = m_Connection.CreateCommand();
MySqlCommand cmd = c.CreateCommand();
cmd.CommandText = "delete from land where UUID = ?UUID"; cmd.CommandText = "delete from land where UUID = ?UUID";
cmd.Parameters.AddWithValue("UUID", Util.ToRawUuidString(globalID)); cmd.Parameters.AddWithValue("UUID", Util.ToRawUuidString(globalID));
ExecuteNonQuery(cmd); cmd.ExecuteNonQuery();
cmd.Dispose(); cmd.Dispose();
} c.Close();
} }
public void StoreLandObject(ILandObject parcel) public void StoreLandObject(ILandObject parcel)
{ {
lock (m_Connection) MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
{ c.Open();
MySqlCommand cmd = m_Connection.CreateCommand();
MySqlCommand cmd = c.CreateCommand();
cmd.CommandText = "replace into land (UUID, RegionUUID, " + cmd.CommandText = "replace into land (UUID, RegionUUID, " +
"LocalLandID, Bitmap, Name, Description, " + "LocalLandID, Bitmap, Name, Description, " +
@ -570,12 +531,12 @@ namespace OpenSim.Data.MySQL
FillLandCommand(cmd, parcel.landData, parcel.regionUUID); FillLandCommand(cmd, parcel.landData, parcel.regionUUID);
ExecuteNonQuery(cmd); cmd.ExecuteNonQuery();
cmd.CommandText = "delete from landaccesslist where " + cmd.CommandText = "delete from landaccesslist where " +
"LandUUID = ?UUID"; "LandUUID = ?UUID";
ExecuteNonQuery(cmd); cmd.ExecuteNonQuery();
cmd.Parameters.Clear(); cmd.Parameters.Clear();
cmd.CommandText = "insert into landaccesslist (LandUUID, " + cmd.CommandText = "insert into landaccesslist (LandUUID, " +
@ -586,26 +547,27 @@ namespace OpenSim.Data.MySQL
parcel.landData.ParcelAccessList) parcel.landData.ParcelAccessList)
{ {
FillLandAccessCommand(cmd, entry, parcel.landData.GlobalID); FillLandAccessCommand(cmd, entry, parcel.landData.GlobalID);
ExecuteNonQuery(cmd); cmd.ExecuteNonQuery();
cmd.Parameters.Clear(); cmd.Parameters.Clear();
} }
cmd.Dispose(); cmd.Dispose();
} c.Close();
} }
public RegionSettings LoadRegionSettings(UUID regionUUID) public RegionSettings LoadRegionSettings(UUID regionUUID)
{ {
RegionSettings rs = null; RegionSettings rs = null;
lock (m_Connection) MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
{ c.Open();
MySqlCommand cmd = m_Connection.CreateCommand();
MySqlCommand cmd = c.CreateCommand();
cmd.CommandText = "select * from regionsettings where " + cmd.CommandText = "select * from regionsettings where " +
"regionUUID = ?RegionUUID"; "regionUUID = ?RegionUUID";
cmd.Parameters.AddWithValue("regionUUID", regionUUID); cmd.Parameters.AddWithValue("regionUUID", regionUUID);
IDataReader reader = ExecuteReader(cmd); IDataReader reader = cmd.ExecuteReader();
try try
{ {
@ -628,16 +590,17 @@ namespace OpenSim.Data.MySQL
reader.Close(); reader.Close();
} }
cmd.Dispose(); cmd.Dispose();
} c.Close();
return rs; return rs;
} }
public void StoreRegionSettings(RegionSettings rs) public void StoreRegionSettings(RegionSettings rs)
{ {
lock (m_Connection) MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
{ c.Open();
MySqlCommand cmd = m_Connection.CreateCommand();
MySqlCommand cmd = c.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, " +
@ -672,18 +635,19 @@ namespace OpenSim.Data.MySQL
FillRegionSettingsCommand(cmd, rs); FillRegionSettingsCommand(cmd, rs);
ExecuteNonQuery(cmd); cmd.ExecuteNonQuery();
cmd.Dispose(); cmd.Dispose();
} c.Close();
} }
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) MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
{ c.Open();
MySqlCommand cmd = m_Connection.CreateCommand();
MySqlCommand cmd = c.CreateCommand();
cmd.CommandText = "select * from land where " + cmd.CommandText = "select * from land where " +
"RegionUUID = ?RegionUUID"; "RegionUUID = ?RegionUUID";
@ -691,7 +655,7 @@ namespace OpenSim.Data.MySQL
cmd.Parameters.AddWithValue("RegionUUID", cmd.Parameters.AddWithValue("RegionUUID",
Util.ToRawUuidString(regionUUID)); Util.ToRawUuidString(regionUUID));
IDataReader reader = ExecuteReader(cmd); IDataReader reader = cmd.ExecuteReader();
try try
{ {
@ -716,7 +680,7 @@ namespace OpenSim.Data.MySQL
cmd.Parameters.AddWithValue("LandUUID", cmd.Parameters.AddWithValue("LandUUID",
Util.ToRawUuidString(land.GlobalID)); Util.ToRawUuidString(land.GlobalID));
reader = ExecuteReader(cmd); reader = cmd.ExecuteReader();
try try
{ {
@ -731,7 +695,7 @@ namespace OpenSim.Data.MySQL
} }
} }
cmd.Dispose(); cmd.Dispose();
} c.Close();
return landData; return landData;
} }
@ -1414,12 +1378,13 @@ byte[] textureEntry = (byte[]) row["Texture"];
} }
public void StorePrimInventory(UUID primID, ICollection<TaskInventoryItem> items) public void StorePrimInventory(UUID primID, ICollection<TaskInventoryItem> items)
{
lock (m_Connection)
{ {
RemoveItems(primID); RemoveItems(primID);
MySqlCommand cmd = m_Connection.CreateCommand(); MySqlConnection c = (MySqlConnection) ((ICloneable)m_Connection).Clone();
c.Open();
MySqlCommand cmd = c.CreateCommand();
if (items.Count == 0) if (items.Count == 0)
return; return;
@ -1446,10 +1411,10 @@ byte[] textureEntry = (byte[]) row["Texture"];
FillItemCommand(cmd, item); FillItemCommand(cmd, item);
ExecuteNonQuery(cmd); cmd.ExecuteNonQuery();
} }
cmd.Dispose(); cmd.Dispose();
} c.Close();
} }
} }
} }