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