aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Data/MySQL
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Data/MySQL')
-rw-r--r--OpenSim/Data/MySQL/MySQLLegacyRegionData.cs288
1 files changed, 153 insertions, 135 deletions
diff --git a/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs b/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs
index fe0914b..801d6b9 100644
--- a/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs
+++ b/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs
@@ -68,12 +68,20 @@ namespace OpenSim.Data.MySQL
68 68
69 // Clean dropped attachments 69 // Clean dropped attachments
70 // 70 //
71 MySqlCommand cmd = m_Connection.CreateCommand(); 71 try
72 cmd.CommandText = "delete from prims, primshapes using prims " + 72 {
73 "left join primshapes on prims.uuid = primshapes.uuid " + 73 using (MySqlCommand cmd = m_Connection.CreateCommand())
74 "where PCode = 9 and State <> 0"; 74 {
75 ExecuteNonQuery(cmd); 75 cmd.CommandText = "delete from prims, primshapes using prims " +
76 cmd.Dispose(); 76 "left join primshapes on prims.uuid = primshapes.uuid " +
77 "where PCode = 9 and State <> 0";
78 ExecuteNonQuery(cmd);
79 }
80 }
81 catch (MySqlException ex)
82 {
83 m_log.Error("[REGION DB]: Error cleaning up dropped attachments: " + ex.Message);
84 }
77 } 85 }
78 86
79 private IDataReader ExecuteReader(MySqlCommand c) 87 private IDataReader ExecuteReader(MySqlCommand c)
@@ -395,25 +403,23 @@ namespace OpenSim.Data.MySQL
395 } 403 }
396 } 404 }
397 405
398 public List<SceneObjectGroup> LoadObjects(UUID regionUUID) 406 public List<SceneObjectGroup> LoadObjects(UUID regionID)
399 { 407 {
400 UUID lastGroupID = UUID.Zero; 408 const int ROWS_PER_QUERY = 5000;
409
410 Dictionary<UUID, SceneObjectPart> prims = new Dictionary<UUID, SceneObjectPart>(ROWS_PER_QUERY);
401 Dictionary<UUID, SceneObjectGroup> objects = new Dictionary<UUID, SceneObjectGroup>(); 411 Dictionary<UUID, SceneObjectGroup> objects = new Dictionary<UUID, SceneObjectGroup>();
402 Dictionary<UUID, SceneObjectPart> prims = new Dictionary<UUID, SceneObjectPart>(); 412 int count = 0;
403 SceneObjectGroup grp = null; 413
414 #region Prim Loading
404 415
405 lock (m_Connection) 416 lock (m_Connection)
406 { 417 {
407 using (MySqlCommand cmd = m_Connection.CreateCommand()) 418 using (MySqlCommand cmd = m_Connection.CreateCommand())
408 { 419 {
409 cmd.CommandText = "select *, " + 420 cmd.CommandText =
410 "case when prims.UUID = SceneGroupID " + 421 "SELECT * FROM prims LEFT JOIN primshapes ON prims.UUID = primshapes.UUID WHERE RegionUUID = ?RegionUUID";
411 "then 0 else 1 end as sort from prims " + 422 cmd.Parameters.AddWithValue("RegionUUID", regionID.ToString());
412 "left join primshapes on prims.UUID = primshapes.UUID " +
413 "where RegionUUID = ?RegionUUID " +
414 "order by SceneGroupID asc, sort asc, LinkNumber asc";
415
416 cmd.Parameters.AddWithValue("RegionUUID", regionUUID.ToString());
417 423
418 using (IDataReader reader = ExecuteReader(cmd)) 424 using (IDataReader reader = ExecuteReader(cmd))
419 { 425 {
@@ -425,52 +431,61 @@ namespace OpenSim.Data.MySQL
425 else 431 else
426 prim.Shape = BuildShape(reader); 432 prim.Shape = BuildShape(reader);
427 433
428 prims[prim.UUID] = prim; 434 UUID parentID = new UUID(reader["SceneGroupID"].ToString());
435 if (parentID != prim.UUID)
436 prim.ParentUUID = parentID;
429 437
430 UUID groupID = new UUID(reader["SceneGroupID"].ToString()); 438 prims[prim.UUID] = prim;
431 439
432 if (groupID != lastGroupID) // New SOG 440 ++count;
433 { 441 if (count % ROWS_PER_QUERY == 0)
434 if (grp != null) 442 m_log.Debug("[REGION DB]: Loaded " + count + " prims...");
435 objects[grp.UUID] = grp; 443 }
444 }
445 }
446 }
436 447
437 lastGroupID = groupID; 448 #endregion Prim Loading
438 449
439 // There sometimes exist OpenSim bugs that 'orphan groups' so that none of the prims are 450 #region SceneObjectGroup Creation
440 // recorded as the root prim (for which the UUID must equal the persisted group UUID). In
441 // this case, force the UUID to be the same as the group UUID so that at least these can be
442 // deleted (we need to change the UUID so that any other prims in the linkset can also be
443 // deleted).
444 if (prim.UUID != groupID && groupID != UUID.Zero)
445 {
446 m_log.WarnFormat(
447 "[REGION DB]: Found root prim {0} {1} at {2} where group was actually {3}. Forcing UUID to group UUID",
448 prim.Name, prim.UUID, prim.GroupPosition, groupID);
449 451
450 prim.UUID = groupID; 452 // Create all of the SOGs from the root prims first
451 } 453 foreach (SceneObjectPart prim in prims.Values)
454 {
455 if (prim.ParentUUID == UUID.Zero)
456 objects[prim.UUID] = new SceneObjectGroup(prim);
457 }
452 458
453 grp = new SceneObjectGroup(prim); 459 // Add all of the children objects to the SOGs
454 } 460 foreach (SceneObjectPart prim in prims.Values)
455 else 461 {
456 { 462 SceneObjectGroup sog;
457 // Black magic to preserve link numbers 463 if (prim.UUID != prim.ParentUUID)
458 // 464 {
459 int link = prim.LinkNum; 465 if (objects.TryGetValue(prim.ParentUUID, out sog))
466 {
467 int originalLinkNum = prim.LinkNum;
460 468
461 grp.AddPart(prim); 469 sog.AddPart(prim);
462 470
463 if (link != 0) 471 // SceneObjectGroup.AddPart() tries to be smart and automatically set the LinkNum.
464 prim.LinkNum = link; 472 // We override that here
465 } 473 if (originalLinkNum != 0)
466 } 474 prim.LinkNum = originalLinkNum;
475 }
476 else
477 {
478 m_log.Warn("[REGION DB]: Database contains an orphan child prim " + prim.UUID + " pointing to missing parent " + prim.ParentUUID);
467 } 479 }
468
469 if (grp != null)
470 objects[grp.UUID] = grp;
471 } 480 }
472 } 481 }
473 482
483 #endregion SceneObjectGroup Creation
484
485 m_log.DebugFormat("[REGION DB]: Loaded {0} objects using {1} prims", objects.Count, prims.Count);
486
487 #region Prim Inventory Loading
488
474 // Instead of attempting to LoadItems on every prim, 489 // Instead of attempting to LoadItems on every prim,
475 // most of which probably have no items... get a 490 // most of which probably have no items... get a
476 // list from DB of all prims which have items and 491 // list from DB of all prims which have items and
@@ -480,7 +495,7 @@ namespace OpenSim.Data.MySQL
480 { 495 {
481 using (MySqlCommand itemCmd = m_Connection.CreateCommand()) 496 using (MySqlCommand itemCmd = m_Connection.CreateCommand())
482 { 497 {
483 itemCmd.CommandText = "select distinct primID from primitems"; 498 itemCmd.CommandText = "SELECT DISTINCT primID FROM primitems";
484 using (IDataReader itemReader = ExecuteReader(itemCmd)) 499 using (IDataReader itemReader = ExecuteReader(itemCmd))
485 { 500 {
486 while (itemReader.Read()) 501 while (itemReader.Read())
@@ -489,9 +504,7 @@ namespace OpenSim.Data.MySQL
489 { 504 {
490 UUID primID = new UUID(itemReader["primID"].ToString()); 505 UUID primID = new UUID(itemReader["primID"].ToString());
491 if (prims.ContainsKey(primID)) 506 if (prims.ContainsKey(primID))
492 {
493 primsWithInventory.Add(prims[primID]); 507 primsWithInventory.Add(prims[primID]);
494 }
495 } 508 }
496 } 509 }
497 } 510 }
@@ -499,9 +512,14 @@ namespace OpenSim.Data.MySQL
499 } 512 }
500 513
501 foreach (SceneObjectPart prim in primsWithInventory) 514 foreach (SceneObjectPart prim in primsWithInventory)
515 {
502 LoadItems(prim); 516 LoadItems(prim);
517 }
518
519 #endregion Prim Inventory Loading
520
521 m_log.DebugFormat("[REGION DB]: Loaded inventory from {0} objects", primsWithInventory.Count);
503 522
504 m_log.DebugFormat("[REGION DB]: Loaded {0} objects using {1} prims", objects.Count, prims.Count);
505 return new List<SceneObjectGroup>(objects.Values); 523 return new List<SceneObjectGroup>(objects.Values);
506 } 524 }
507 525
@@ -798,137 +816,137 @@ namespace OpenSim.Data.MySQL
798 private SceneObjectPart BuildPrim(IDataReader row) 816 private SceneObjectPart BuildPrim(IDataReader row)
799 { 817 {
800 SceneObjectPart prim = new SceneObjectPart(); 818 SceneObjectPart prim = new SceneObjectPart();
801 prim.UUID = new UUID((String) row["UUID"]); 819 prim.UUID = new UUID((string)row["UUID"]);
802 // explicit conversion of integers is required, which sort 820 // explicit conversion of integers is required, which sort
803 // of sucks. No idea if there is a shortcut here or not. 821 // of sucks. No idea if there is a shortcut here or not.
804 prim.CreationDate = Convert.ToInt32(row["CreationDate"]); 822 prim.CreationDate = (int)row["CreationDate"];
805 if (row["Name"] != DBNull.Value) 823 if (row["Name"] != DBNull.Value)
806 prim.Name = (String)row["Name"]; 824 prim.Name = (string)row["Name"];
807 else 825 else
808 prim.Name = string.Empty; 826 prim.Name = String.Empty;
809 // various text fields 827 // Various text fields
810 prim.Text = (String) row["Text"]; 828 prim.Text = (string)row["Text"];
811 prim.Color = Color.FromArgb(Convert.ToInt32(row["ColorA"]), 829 prim.Color = Color.FromArgb((int)row["ColorA"],
812 Convert.ToInt32(row["ColorR"]), 830 (int)row["ColorR"],
813 Convert.ToInt32(row["ColorG"]), 831 (int)row["ColorG"],
814 Convert.ToInt32(row["ColorB"])); 832 (int)row["ColorB"]);
815 prim.Description = (String) row["Description"]; 833 prim.Description = (string)row["Description"];
816 prim.SitName = (String) row["SitName"]; 834 prim.SitName = (string)row["SitName"];
817 prim.TouchName = (String) row["TouchName"]; 835 prim.TouchName = (string)row["TouchName"];
818 // permissions 836 // Permissions
819 prim.ObjectFlags = Convert.ToUInt32(row["ObjectFlags"]); 837 prim.ObjectFlags = (uint)(int)row["ObjectFlags"];
820 prim.CreatorID = new UUID((String) row["CreatorID"]); 838 prim.CreatorID = new UUID((string)row["CreatorID"]);
821 prim.OwnerID = new UUID((String) row["OwnerID"]); 839 prim.OwnerID = new UUID((string)row["OwnerID"]);
822 prim.GroupID = new UUID((String) row["GroupID"]); 840 prim.GroupID = new UUID((string)row["GroupID"]);
823 prim.LastOwnerID = new UUID((String) row["LastOwnerID"]); 841 prim.LastOwnerID = new UUID((string)row["LastOwnerID"]);
824 prim.OwnerMask = Convert.ToUInt32(row["OwnerMask"]); 842 prim.OwnerMask = (uint)(int)row["OwnerMask"];
825 prim.NextOwnerMask = Convert.ToUInt32(row["NextOwnerMask"]); 843 prim.NextOwnerMask = (uint)(int)row["NextOwnerMask"];
826 prim.GroupMask = Convert.ToUInt32(row["GroupMask"]); 844 prim.GroupMask = (uint)(int)row["GroupMask"];
827 prim.EveryoneMask = Convert.ToUInt32(row["EveryoneMask"]); 845 prim.EveryoneMask = (uint)(int)row["EveryoneMask"];
828 prim.BaseMask = Convert.ToUInt32(row["BaseMask"]); 846 prim.BaseMask = (uint)(int)row["BaseMask"];
829 // vectors 847 // Vectors
830 prim.OffsetPosition = new Vector3( 848 prim.OffsetPosition = new Vector3(
831 Convert.ToSingle(row["PositionX"]), 849 (float)(double)row["PositionX"],
832 Convert.ToSingle(row["PositionY"]), 850 (float)(double)row["PositionY"],
833 Convert.ToSingle(row["PositionZ"]) 851 (float)(double)row["PositionZ"]
834 ); 852 );
835 prim.GroupPosition = new Vector3( 853 prim.GroupPosition = new Vector3(
836 Convert.ToSingle(row["GroupPositionX"]), 854 (float)(double)row["GroupPositionX"],
837 Convert.ToSingle(row["GroupPositionY"]), 855 (float)(double)row["GroupPositionY"],
838 Convert.ToSingle(row["GroupPositionZ"]) 856 (float)(double)row["GroupPositionZ"]
839 ); 857 );
840 prim.Velocity = new Vector3( 858 prim.Velocity = new Vector3(
841 Convert.ToSingle(row["VelocityX"]), 859 (float)(double)row["VelocityX"],
842 Convert.ToSingle(row["VelocityY"]), 860 (float)(double)row["VelocityY"],
843 Convert.ToSingle(row["VelocityZ"]) 861 (float)(double)row["VelocityZ"]
844 ); 862 );
845 prim.AngularVelocity = new Vector3( 863 prim.AngularVelocity = new Vector3(
846 Convert.ToSingle(row["AngularVelocityX"]), 864 (float)(double)row["AngularVelocityX"],
847 Convert.ToSingle(row["AngularVelocityY"]), 865 (float)(double)row["AngularVelocityY"],
848 Convert.ToSingle(row["AngularVelocityZ"]) 866 (float)(double)row["AngularVelocityZ"]
849 ); 867 );
850 prim.Acceleration = new Vector3( 868 prim.Acceleration = new Vector3(
851 Convert.ToSingle(row["AccelerationX"]), 869 (float)(double)row["AccelerationX"],
852 Convert.ToSingle(row["AccelerationY"]), 870 (float)(double)row["AccelerationY"],
853 Convert.ToSingle(row["AccelerationZ"]) 871 (float)(double)row["AccelerationZ"]
854 ); 872 );
855 // quaternions 873 // quaternions
856 prim.RotationOffset = new Quaternion( 874 prim.RotationOffset = new Quaternion(
857 Convert.ToSingle(row["RotationX"]), 875 (float)(double)row["RotationX"],
858 Convert.ToSingle(row["RotationY"]), 876 (float)(double)row["RotationY"],
859 Convert.ToSingle(row["RotationZ"]), 877 (float)(double)row["RotationZ"],
860 Convert.ToSingle(row["RotationW"]) 878 (float)(double)row["RotationW"]
861 ); 879 );
862 prim.SitTargetPositionLL = new Vector3( 880 prim.SitTargetPositionLL = new Vector3(
863 Convert.ToSingle(row["SitTargetOffsetX"]), 881 (float)(double)row["SitTargetOffsetX"],
864 Convert.ToSingle(row["SitTargetOffsetY"]), 882 (float)(double)row["SitTargetOffsetY"],
865 Convert.ToSingle(row["SitTargetOffsetZ"]) 883 (float)(double)row["SitTargetOffsetZ"]
866 ); 884 );
867 prim.SitTargetOrientationLL = new Quaternion( 885 prim.SitTargetOrientationLL = new Quaternion(
868 Convert.ToSingle(row["SitTargetOrientX"]), 886 (float)(double)row["SitTargetOrientX"],
869 Convert.ToSingle(row["SitTargetOrientY"]), 887 (float)(double)row["SitTargetOrientY"],
870 Convert.ToSingle(row["SitTargetOrientZ"]), 888 (float)(double)row["SitTargetOrientZ"],
871 Convert.ToSingle(row["SitTargetOrientW"]) 889 (float)(double)row["SitTargetOrientW"]
872 ); 890 );
873 891
874 prim.PayPrice[0] = Convert.ToInt32(row["PayPrice"]); 892 prim.PayPrice[0] = (int)row["PayPrice"];
875 prim.PayPrice[1] = Convert.ToInt32(row["PayButton1"]); 893 prim.PayPrice[1] = (int)row["PayButton1"];
876 prim.PayPrice[2] = Convert.ToInt32(row["PayButton2"]); 894 prim.PayPrice[2] = (int)row["PayButton2"];
877 prim.PayPrice[3] = Convert.ToInt32(row["PayButton3"]); 895 prim.PayPrice[3] = (int)row["PayButton3"];
878 prim.PayPrice[4] = Convert.ToInt32(row["PayButton4"]); 896 prim.PayPrice[4] = (int)row["PayButton4"];
879 897
880 prim.Sound = new UUID(row["LoopedSound"].ToString()); 898 prim.Sound = new UUID(row["LoopedSound"].ToString());
881 prim.SoundGain = Convert.ToSingle(row["LoopedSoundGain"]); 899 prim.SoundGain = (float)(double)row["LoopedSoundGain"];
882 prim.SoundFlags = 1; // If it's persisted at all, it's looped 900 prim.SoundFlags = 1; // If it's persisted at all, it's looped
883 901
884 if (!(row["TextureAnimation"] is DBNull)) 902 if (!(row["TextureAnimation"] is DBNull))
885 prim.TextureAnimation = (Byte[])row["TextureAnimation"]; 903 prim.TextureAnimation = (byte[])row["TextureAnimation"];
886 if (!(row["ParticleSystem"] is DBNull)) 904 if (!(row["ParticleSystem"] is DBNull))
887 prim.ParticleSystem = (Byte[])row["ParticleSystem"]; 905 prim.ParticleSystem = (byte[])row["ParticleSystem"];
888 906
889 prim.RotationalVelocity = new Vector3( 907 prim.RotationalVelocity = new Vector3(
890 Convert.ToSingle(row["OmegaX"]), 908 (float)(double)row["OmegaX"],
891 Convert.ToSingle(row["OmegaY"]), 909 (float)(double)row["OmegaY"],
892 Convert.ToSingle(row["OmegaZ"]) 910 (float)(double)row["OmegaZ"]
893 ); 911 );
894 912
895 prim.SetCameraEyeOffset(new Vector3( 913 prim.SetCameraEyeOffset(new Vector3(
896 Convert.ToSingle(row["CameraEyeOffsetX"]), 914 (float)(double)row["CameraEyeOffsetX"],
897 Convert.ToSingle(row["CameraEyeOffsetY"]), 915 (float)(double)row["CameraEyeOffsetY"],
898 Convert.ToSingle(row["CameraEyeOffsetZ"]) 916 (float)(double)row["CameraEyeOffsetZ"]
899 )); 917 ));
900 918
901 prim.SetCameraAtOffset(new Vector3( 919 prim.SetCameraAtOffset(new Vector3(
902 Convert.ToSingle(row["CameraAtOffsetX"]), 920 (float)(double)row["CameraAtOffsetX"],
903 Convert.ToSingle(row["CameraAtOffsetY"]), 921 (float)(double)row["CameraAtOffsetY"],
904 Convert.ToSingle(row["CameraAtOffsetZ"]) 922 (float)(double)row["CameraAtOffsetZ"]
905 )); 923 ));
906 924
907 if (Convert.ToInt16(row["ForceMouselook"]) != 0) 925 if ((sbyte)row["ForceMouselook"] != 0)
908 prim.SetForceMouselook(true); 926 prim.SetForceMouselook(true);
909 927
910 prim.ScriptAccessPin = Convert.ToInt32(row["ScriptAccessPin"]); 928 prim.ScriptAccessPin = (int)row["ScriptAccessPin"];
911 929
912 if (Convert.ToInt16(row["AllowedDrop"]) != 0) 930 if ((sbyte)row["AllowedDrop"] != 0)
913 prim.AllowedDrop = true; 931 prim.AllowedDrop = true;
914 932
915 if (Convert.ToInt16(row["DieAtEdge"]) != 0) 933 if ((sbyte)row["DieAtEdge"] != 0)
916 prim.DIE_AT_EDGE = true; 934 prim.DIE_AT_EDGE = true;
917 935
918 prim.SalePrice = Convert.ToInt32(row["SalePrice"]); 936 prim.SalePrice = (int)row["SalePrice"];
919 prim.ObjectSaleType = unchecked((byte)Convert.ToSByte(row["SaleType"])); 937 prim.ObjectSaleType = unchecked((byte)(sbyte)row["SaleType"]);
920 938
921 prim.Material = unchecked((byte)Convert.ToSByte(row["Material"])); 939 prim.Material = unchecked((byte)(sbyte)row["Material"]);
922 940
923 if (!(row["ClickAction"] is DBNull)) 941 if (!(row["ClickAction"] is DBNull))
924 prim.ClickAction = unchecked((byte)Convert.ToSByte(row["ClickAction"])); 942 prim.ClickAction = unchecked((byte)(sbyte)row["ClickAction"]);
925 943
926 prim.CollisionSound = new UUID(row["CollisionSound"].ToString()); 944 prim.CollisionSound = new UUID(row["CollisionSound"].ToString());
927 prim.CollisionSoundVolume = Convert.ToSingle(row["CollisionSoundVolume"]); 945 prim.CollisionSoundVolume = (float)(double)row["CollisionSoundVolume"];
928 946
929 if (Convert.ToInt16(row["PassTouches"]) != 0) 947 if ((sbyte)row["PassTouches"] != 0)
930 prim.PassTouches = true; 948 prim.PassTouches = true;
931 prim.LinkNum = Convert.ToInt32(row["LinkNumber"]); 949 prim.LinkNum = (int)row["LinkNumber"];
932 950
933 return prim; 951 return prim;
934 } 952 }