From 41516fa2c3942996e347597a967b30e5e8de1a3c Mon Sep 17 00:00:00 2001 From: Tedd Hansen Date: Sat, 2 Feb 2008 05:28:39 +0000 Subject: [PATCH] Last patch was a disaster... reset terrain whenever bug occurred. Trying again with some modifications on Mutex. --- .../Framework/Data.MySQL/MySQLDataStore.cs | 135 +++++++++--------- bin/OpenSim.32BitLaunch.exe | Bin 4608 -> 4608 bytes bin/OpenSim.32BitLaunch.pdb | Bin 11776 -> 11776 bytes 3 files changed, 67 insertions(+), 68 deletions(-) diff --git a/OpenSim/Framework/Data.MySQL/MySQLDataStore.cs b/OpenSim/Framework/Data.MySQL/MySQLDataStore.cs index 6523105d1b..7ac4bded22 100644 --- a/OpenSim/Framework/Data.MySQL/MySQLDataStore.cs +++ b/OpenSim/Framework/Data.MySQL/MySQLDataStore.cs @@ -50,6 +50,7 @@ namespace OpenSim.Framework.Data.MySQL private const string m_landAccessListSelect = "select * from landaccesslist"; private DataSet m_dataSet; + private static object DBAccessLock = new object(); // Trying to use a static object because there might be other regions that keep modifying table private MySqlDataAdapter m_primDataAdapter; private MySqlDataAdapter m_shapeDataAdapter; private MySqlDataAdapter m_itemsDataAdapter; @@ -103,7 +104,7 @@ namespace OpenSim.Framework.Data.MySQL TestTables(m_connection); - lock (m_dataSet) + lock (DBAccessLock) { m_primTable = createPrimTable(); m_dataSet.Tables.Add(m_primTable); @@ -142,7 +143,7 @@ namespace OpenSim.Framework.Data.MySQL public void StoreObject(SceneObjectGroup obj, LLUUID regionUUID) { - lock (m_dataSet) + lock (DBAccessLock) { foreach (SceneObjectPart prim in obj.Children.Values) { @@ -169,7 +170,7 @@ namespace OpenSim.Framework.Data.MySQL DataTable shapes = m_shapeTable; string selectExp = "SceneGroupID = '" + Util.ToRawUuidString(obj) + "'"; - lock (m_dataSet) + lock (DBAccessLock) { DataRow[] primRows = prims.Select(selectExp); foreach (DataRow row in primRows) @@ -225,7 +226,7 @@ namespace OpenSim.Framework.Data.MySQL string byRegion = "RegionUUID = '" + Util.ToRawUuidString(regionUUID) + "'"; string orderByParent = "ParentID ASC"; - lock (m_dataSet) + lock (DBAccessLock) { DataRow[] primsForRegion = prims.Select(byRegion, orderByParent); MainLog.Instance.Verbose("DATASTORE", @@ -335,7 +336,7 @@ namespace OpenSim.Framework.Data.MySQL MainLog.Instance.Verbose("DATASTORE", "Storing terrain revision r" + revision.ToString()); DataTable terrain = m_dataSet.Tables["terrain"]; - lock (m_dataSet) + lock (DBAccessLock) { MySqlCommand cmd = new MySqlCommand("insert into terrain(RegionUUID, Revision, Heightfield)" + " values(?RegionUUID, ?Revision, ?Heightfield)", m_connection); @@ -396,7 +397,7 @@ namespace OpenSim.Framework.Data.MySQL public void RemoveLandObject(LLUUID globalID) { - lock (m_dataSet) + lock (DBAccessLock) { using (MySqlCommand cmd = new MySqlCommand("delete from land where UUID=?UUID", m_connection)) { @@ -418,62 +419,47 @@ namespace OpenSim.Framework.Data.MySQL { MainLog.Instance.Verbose("DATASTORE", "Tedds temp fix: Waiting 3 seconds for stuff to catch up. (Someone please fix! :))"); System.Threading.Thread.Sleep(3000); - - int loopCount = 0; - while (true) + + lock (DBAccessLock) { - loopCount++; - try + DataTable land = m_landTable; + DataTable landaccesslist = m_landAccessListTable; + + DataRow landRow = land.Rows.Find(Util.ToRawUuidString(parcel.landData.globalID)); + if (landRow == null) { - lock (m_dataSet) - { - DataTable land = m_landTable; - DataTable landaccesslist = m_landAccessListTable; - - DataRow landRow = land.Rows.Find(Util.ToRawUuidString(parcel.landData.globalID)); - if (landRow == null) - { - landRow = land.NewRow(); - fillLandRow(landRow, parcel.landData, regionUUID); - land.Rows.Add(landRow); - } - else - { - fillLandRow(landRow, parcel.landData, regionUUID); - } - - using ( - MySqlCommand cmd = - new MySqlCommand("delete from landaccesslist where LandUUID=?LandUUID", m_connection)) - { - cmd.Parameters.Add( - new MySqlParameter("?LandUUID", Util.ToRawUuidString(parcel.landData.globalID))); - cmd.ExecuteNonQuery(); - } - - foreach (ParcelManager.ParcelAccessEntry entry in parcel.landData.parcelAccessList) - { - DataRow newAccessRow = landaccesslist.NewRow(); - fillLandAccessRow(newAccessRow, entry, parcel.landData.globalID); - landaccesslist.Rows.Add(newAccessRow); - } - } - Commit(); - break; + landRow = land.NewRow(); + fillLandRow(landRow, parcel.landData, regionUUID); + land.Rows.Add(landRow); } - catch (Exception ex) + else { - System.Console.WriteLine("Tedds temp fix exception, will repeat taks: " + ex.ToString()); - if (loopCount > 3) - throw (ex); + fillLandRow(landRow, parcel.landData, regionUUID); } + + using ( + MySqlCommand cmd = + new MySqlCommand("delete from landaccesslist where LandUUID=?LandUUID", m_connection)) + { + cmd.Parameters.Add(new MySqlParameter("?LandUUID", Util.ToRawUuidString(parcel.landData.globalID))); + cmd.ExecuteNonQuery(); + } + + foreach (ParcelManager.ParcelAccessEntry entry in parcel.landData.parcelAccessList) + { + DataRow newAccessRow = landaccesslist.NewRow(); + fillLandAccessRow(newAccessRow, entry, parcel.landData.globalID); + landaccesslist.Rows.Add(newAccessRow); + } + + Commit_NoLock(); } } public List LoadLandObjects(LLUUID regionUUID) { List landDataForRegion = new List(); - lock (m_dataSet) + lock (DBAccessLock) { DataTable land = m_landTable; DataTable landaccesslist = m_landAccessListTable; @@ -535,26 +521,39 @@ namespace OpenSim.Framework.Data.MySQL m_connection.Open(); } - lock (m_dataSet) + lock (DBAccessLock) { - // DisplayDataSet(m_dataSet, "Region DataSet"); - - m_primDataAdapter.Update(m_primTable); - m_shapeDataAdapter.Update(m_shapeTable); - - if (persistPrimInventories) - { - m_itemsDataAdapter.Update(m_itemsTable); - } - - m_terrainDataAdapter.Update(m_terrainTable); - m_landDataAdapter.Update(m_landTable); - m_landAccessListDataAdapter.Update(m_landAccessListTable); - - m_dataSet.AcceptChanges(); + // Moved code to own sub that can be called directly by "StoreLandObject". + // Problem is that: + // - StoreLandObject locks + // - Some other function waits for lock + // - StoreLandObject releases lock + // - Other function obtains lock + // - StoreLandObject calls Commit that tries to take lock back + // - When StoreLandObject's Commit finally gets lock the table has been changed and we crash + Commit_NoLock(); } } + private void Commit_NoLock() + { + // DisplayDataSet(m_dataSet, "Region DataSet"); + + m_primDataAdapter.Update(m_primTable); + m_shapeDataAdapter.Update(m_shapeTable); + + if (persistPrimInventories) + { + m_itemsDataAdapter.Update(m_itemsTable); + } + + m_terrainDataAdapter.Update(m_terrainTable); + m_landDataAdapter.Update(m_landTable); + m_landAccessListDataAdapter.Update(m_landAccessListTable); + + m_dataSet.AcceptChanges(); + } + public void Shutdown() { Commit(); @@ -1230,7 +1229,7 @@ namespace OpenSim.Framework.Data.MySQL // For now, we're just going to crudely remove all the previous inventory items // no matter whether they have changed or not, and replace them with the current set. - lock (m_dataSet) + lock (DBAccessLock) { RemoveItems(primID); diff --git a/bin/OpenSim.32BitLaunch.exe b/bin/OpenSim.32BitLaunch.exe index a3a00e877455dee1855b1a1dcfcba86f3f16aef0..5a2c71556a50082c69ac6173f6b643e193e2bcef 100644 GIT binary patch delta 84 zcmZorX;7Ka!PNb4W7j4&fp-pXV)PX^JGF>rZCLL4D|xaH`xBk+e~aB2fPe{z^MKex k4Tw1y7=nUbf^XLC^!lk_=(?dJ)Oy|9j+>ifIF@h%07y6v1}Ws diff --git a/bin/OpenSim.32BitLaunch.pdb b/bin/OpenSim.32BitLaunch.pdb index 069afee52fc7111ea8a8916f549e728f49e3472f..d9ca53720cf40e497dedfb377022953fc8554519 100644 GIT binary patch delta 87 zcmZpOX^7dt!X?rDZ?QWg0|Ud&x}9D>6%1WBbc9;3d)skyvkcc8PF58SkB8Blc}3Fs Tm<_HJZZ22qWyGUH