diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Framework/Data.MySQL/MySQLDataStore.cs | 129 |
1 files changed, 64 insertions, 65 deletions
diff --git a/OpenSim/Framework/Data.MySQL/MySQLDataStore.cs b/OpenSim/Framework/Data.MySQL/MySQLDataStore.cs index 6523105..7ac4bde 100644 --- a/OpenSim/Framework/Data.MySQL/MySQLDataStore.cs +++ b/OpenSim/Framework/Data.MySQL/MySQLDataStore.cs | |||
@@ -50,6 +50,7 @@ namespace OpenSim.Framework.Data.MySQL | |||
50 | private const string m_landAccessListSelect = "select * from landaccesslist"; | 50 | private const string m_landAccessListSelect = "select * from landaccesslist"; |
51 | 51 | ||
52 | private DataSet m_dataSet; | 52 | private DataSet m_dataSet; |
53 | private static object DBAccessLock = new object(); // Trying to use a static object because there might be other regions that keep modifying table | ||
53 | private MySqlDataAdapter m_primDataAdapter; | 54 | private MySqlDataAdapter m_primDataAdapter; |
54 | private MySqlDataAdapter m_shapeDataAdapter; | 55 | private MySqlDataAdapter m_shapeDataAdapter; |
55 | private MySqlDataAdapter m_itemsDataAdapter; | 56 | private MySqlDataAdapter m_itemsDataAdapter; |
@@ -103,7 +104,7 @@ namespace OpenSim.Framework.Data.MySQL | |||
103 | 104 | ||
104 | TestTables(m_connection); | 105 | TestTables(m_connection); |
105 | 106 | ||
106 | lock (m_dataSet) | 107 | lock (DBAccessLock) |
107 | { | 108 | { |
108 | m_primTable = createPrimTable(); | 109 | m_primTable = createPrimTable(); |
109 | m_dataSet.Tables.Add(m_primTable); | 110 | m_dataSet.Tables.Add(m_primTable); |
@@ -142,7 +143,7 @@ namespace OpenSim.Framework.Data.MySQL | |||
142 | 143 | ||
143 | public void StoreObject(SceneObjectGroup obj, LLUUID regionUUID) | 144 | public void StoreObject(SceneObjectGroup obj, LLUUID regionUUID) |
144 | { | 145 | { |
145 | lock (m_dataSet) | 146 | lock (DBAccessLock) |
146 | { | 147 | { |
147 | foreach (SceneObjectPart prim in obj.Children.Values) | 148 | foreach (SceneObjectPart prim in obj.Children.Values) |
148 | { | 149 | { |
@@ -169,7 +170,7 @@ namespace OpenSim.Framework.Data.MySQL | |||
169 | DataTable shapes = m_shapeTable; | 170 | DataTable shapes = m_shapeTable; |
170 | 171 | ||
171 | string selectExp = "SceneGroupID = '" + Util.ToRawUuidString(obj) + "'"; | 172 | string selectExp = "SceneGroupID = '" + Util.ToRawUuidString(obj) + "'"; |
172 | lock (m_dataSet) | 173 | lock (DBAccessLock) |
173 | { | 174 | { |
174 | DataRow[] primRows = prims.Select(selectExp); | 175 | DataRow[] primRows = prims.Select(selectExp); |
175 | foreach (DataRow row in primRows) | 176 | foreach (DataRow row in primRows) |
@@ -225,7 +226,7 @@ namespace OpenSim.Framework.Data.MySQL | |||
225 | string byRegion = "RegionUUID = '" + Util.ToRawUuidString(regionUUID) + "'"; | 226 | string byRegion = "RegionUUID = '" + Util.ToRawUuidString(regionUUID) + "'"; |
226 | string orderByParent = "ParentID ASC"; | 227 | string orderByParent = "ParentID ASC"; |
227 | 228 | ||
228 | lock (m_dataSet) | 229 | lock (DBAccessLock) |
229 | { | 230 | { |
230 | DataRow[] primsForRegion = prims.Select(byRegion, orderByParent); | 231 | DataRow[] primsForRegion = prims.Select(byRegion, orderByParent); |
231 | MainLog.Instance.Verbose("DATASTORE", | 232 | MainLog.Instance.Verbose("DATASTORE", |
@@ -335,7 +336,7 @@ namespace OpenSim.Framework.Data.MySQL | |||
335 | MainLog.Instance.Verbose("DATASTORE", "Storing terrain revision r" + revision.ToString()); | 336 | MainLog.Instance.Verbose("DATASTORE", "Storing terrain revision r" + revision.ToString()); |
336 | 337 | ||
337 | DataTable terrain = m_dataSet.Tables["terrain"]; | 338 | DataTable terrain = m_dataSet.Tables["terrain"]; |
338 | lock (m_dataSet) | 339 | lock (DBAccessLock) |
339 | { | 340 | { |
340 | MySqlCommand cmd = new MySqlCommand("insert into terrain(RegionUUID, Revision, Heightfield)" + | 341 | MySqlCommand cmd = new MySqlCommand("insert into terrain(RegionUUID, Revision, Heightfield)" + |
341 | " values(?RegionUUID, ?Revision, ?Heightfield)", m_connection); | 342 | " values(?RegionUUID, ?Revision, ?Heightfield)", m_connection); |
@@ -396,7 +397,7 @@ namespace OpenSim.Framework.Data.MySQL | |||
396 | 397 | ||
397 | public void RemoveLandObject(LLUUID globalID) | 398 | public void RemoveLandObject(LLUUID globalID) |
398 | { | 399 | { |
399 | lock (m_dataSet) | 400 | lock (DBAccessLock) |
400 | { | 401 | { |
401 | using (MySqlCommand cmd = new MySqlCommand("delete from land where UUID=?UUID", m_connection)) | 402 | using (MySqlCommand cmd = new MySqlCommand("delete from land where UUID=?UUID", m_connection)) |
402 | { | 403 | { |
@@ -418,62 +419,47 @@ namespace OpenSim.Framework.Data.MySQL | |||
418 | { | 419 | { |
419 | MainLog.Instance.Verbose("DATASTORE", "Tedds temp fix: Waiting 3 seconds for stuff to catch up. (Someone please fix! :))"); | 420 | MainLog.Instance.Verbose("DATASTORE", "Tedds temp fix: Waiting 3 seconds for stuff to catch up. (Someone please fix! :))"); |
420 | System.Threading.Thread.Sleep(3000); | 421 | System.Threading.Thread.Sleep(3000); |
421 | 422 | ||
422 | int loopCount = 0; | 423 | lock (DBAccessLock) |
423 | while (true) | ||
424 | { | 424 | { |
425 | loopCount++; | 425 | DataTable land = m_landTable; |
426 | try | 426 | DataTable landaccesslist = m_landAccessListTable; |
427 | { | ||
428 | lock (m_dataSet) | ||
429 | { | ||
430 | DataTable land = m_landTable; | ||
431 | DataTable landaccesslist = m_landAccessListTable; | ||
432 | |||
433 | DataRow landRow = land.Rows.Find(Util.ToRawUuidString(parcel.landData.globalID)); | ||
434 | if (landRow == null) | ||
435 | { | ||
436 | landRow = land.NewRow(); | ||
437 | fillLandRow(landRow, parcel.landData, regionUUID); | ||
438 | land.Rows.Add(landRow); | ||
439 | } | ||
440 | else | ||
441 | { | ||
442 | fillLandRow(landRow, parcel.landData, regionUUID); | ||
443 | } | ||
444 | 427 | ||
445 | using ( | 428 | DataRow landRow = land.Rows.Find(Util.ToRawUuidString(parcel.landData.globalID)); |
446 | MySqlCommand cmd = | 429 | if (landRow == null) |
447 | new MySqlCommand("delete from landaccesslist where LandUUID=?LandUUID", m_connection)) | 430 | { |
448 | { | 431 | landRow = land.NewRow(); |
449 | cmd.Parameters.Add( | 432 | fillLandRow(landRow, parcel.landData, regionUUID); |
450 | new MySqlParameter("?LandUUID", Util.ToRawUuidString(parcel.landData.globalID))); | 433 | land.Rows.Add(landRow); |
451 | cmd.ExecuteNonQuery(); | 434 | } |
452 | } | 435 | else |
436 | { | ||
437 | fillLandRow(landRow, parcel.landData, regionUUID); | ||
438 | } | ||
453 | 439 | ||
454 | foreach (ParcelManager.ParcelAccessEntry entry in parcel.landData.parcelAccessList) | 440 | using ( |
455 | { | 441 | MySqlCommand cmd = |
456 | DataRow newAccessRow = landaccesslist.NewRow(); | 442 | new MySqlCommand("delete from landaccesslist where LandUUID=?LandUUID", m_connection)) |
457 | fillLandAccessRow(newAccessRow, entry, parcel.landData.globalID); | 443 | { |
458 | landaccesslist.Rows.Add(newAccessRow); | 444 | cmd.Parameters.Add(new MySqlParameter("?LandUUID", Util.ToRawUuidString(parcel.landData.globalID))); |
459 | } | 445 | cmd.ExecuteNonQuery(); |
460 | } | ||
461 | Commit(); | ||
462 | break; | ||
463 | } | 446 | } |
464 | catch (Exception ex) | 447 | |
448 | foreach (ParcelManager.ParcelAccessEntry entry in parcel.landData.parcelAccessList) | ||
465 | { | 449 | { |
466 | System.Console.WriteLine("Tedds temp fix exception, will repeat taks: " + ex.ToString()); | 450 | DataRow newAccessRow = landaccesslist.NewRow(); |
467 | if (loopCount > 3) | 451 | fillLandAccessRow(newAccessRow, entry, parcel.landData.globalID); |
468 | throw (ex); | 452 | landaccesslist.Rows.Add(newAccessRow); |
469 | } | 453 | } |
454 | |||
455 | Commit_NoLock(); | ||
470 | } | 456 | } |
471 | } | 457 | } |
472 | 458 | ||
473 | public List<LandData> LoadLandObjects(LLUUID regionUUID) | 459 | public List<LandData> LoadLandObjects(LLUUID regionUUID) |
474 | { | 460 | { |
475 | List<LandData> landDataForRegion = new List<LandData>(); | 461 | List<LandData> landDataForRegion = new List<LandData>(); |
476 | lock (m_dataSet) | 462 | lock (DBAccessLock) |
477 | { | 463 | { |
478 | DataTable land = m_landTable; | 464 | DataTable land = m_landTable; |
479 | DataTable landaccesslist = m_landAccessListTable; | 465 | DataTable landaccesslist = m_landAccessListTable; |
@@ -535,24 +521,37 @@ namespace OpenSim.Framework.Data.MySQL | |||
535 | m_connection.Open(); | 521 | m_connection.Open(); |
536 | } | 522 | } |
537 | 523 | ||
538 | lock (m_dataSet) | 524 | lock (DBAccessLock) |
539 | { | 525 | { |
540 | // DisplayDataSet(m_dataSet, "Region DataSet"); | 526 | // Moved code to own sub that can be called directly by "StoreLandObject". |
527 | // Problem is that: | ||
528 | // - StoreLandObject locks | ||
529 | // - Some other function waits for lock | ||
530 | // - StoreLandObject releases lock | ||
531 | // - Other function obtains lock | ||
532 | // - StoreLandObject calls Commit that tries to take lock back | ||
533 | // - When StoreLandObject's Commit finally gets lock the table has been changed and we crash | ||
534 | Commit_NoLock(); | ||
535 | } | ||
536 | } | ||
541 | 537 | ||
542 | m_primDataAdapter.Update(m_primTable); | 538 | private void Commit_NoLock() |
543 | m_shapeDataAdapter.Update(m_shapeTable); | 539 | { |
544 | 540 | // DisplayDataSet(m_dataSet, "Region DataSet"); | |
545 | if (persistPrimInventories) | ||
546 | { | ||
547 | m_itemsDataAdapter.Update(m_itemsTable); | ||
548 | } | ||
549 | |||
550 | m_terrainDataAdapter.Update(m_terrainTable); | ||
551 | m_landDataAdapter.Update(m_landTable); | ||
552 | m_landAccessListDataAdapter.Update(m_landAccessListTable); | ||
553 | 541 | ||
554 | m_dataSet.AcceptChanges(); | 542 | m_primDataAdapter.Update(m_primTable); |
543 | m_shapeDataAdapter.Update(m_shapeTable); | ||
544 | |||
545 | if (persistPrimInventories) | ||
546 | { | ||
547 | m_itemsDataAdapter.Update(m_itemsTable); | ||
555 | } | 548 | } |
549 | |||
550 | m_terrainDataAdapter.Update(m_terrainTable); | ||
551 | m_landDataAdapter.Update(m_landTable); | ||
552 | m_landAccessListDataAdapter.Update(m_landAccessListTable); | ||
553 | |||
554 | m_dataSet.AcceptChanges(); | ||
556 | } | 555 | } |
557 | 556 | ||
558 | public void Shutdown() | 557 | public void Shutdown() |
@@ -1230,7 +1229,7 @@ namespace OpenSim.Framework.Data.MySQL | |||
1230 | 1229 | ||
1231 | // For now, we're just going to crudely remove all the previous inventory items | 1230 | // For now, we're just going to crudely remove all the previous inventory items |
1232 | // no matter whether they have changed or not, and replace them with the current set. | 1231 | // no matter whether they have changed or not, and replace them with the current set. |
1233 | lock (m_dataSet) | 1232 | lock (DBAccessLock) |
1234 | { | 1233 | { |
1235 | RemoveItems(primID); | 1234 | RemoveItems(primID); |
1236 | 1235 | ||