aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Util.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Framework/Util.cs')
-rw-r--r--OpenSim/Framework/Util.cs735
1 files changed, 604 insertions, 131 deletions
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index b5c3e75..7093010 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -59,17 +59,41 @@ namespace OpenSim.Framework
59{ 59{
60 [Flags] 60 [Flags]
61 public enum PermissionMask : uint 61 public enum PermissionMask : uint
62 { 62 {
63 None = 0, 63 None = 0,
64 Transfer = 1 << 13, 64
65 Modify = 1 << 14, 65 // folded perms
66 Copy = 1 << 15, 66 FoldedTransfer = 1,
67 Export = 1 << 16, 67 FoldedModify = 1 << 1,
68 Move = 1 << 19, 68 FoldedCopy = 1 << 2,
69 Damage = 1 << 20, 69 FoldedExport = 1 << 3,
70
71 // DO NOT USE THIS FOR NEW WORK. IT IS DEPRECATED AND
72 // EXISTS ONLY TO REACT TO EXISTING OBJECTS HAVING IT.
73 // NEW CODE SHOULD NEVER SET THIS BIT!
74 // Use InventoryItemFlags.ObjectSlamPerm in the Flags field of
75 // this legacy slam bit. It comes from prior incomplete
76 // understanding of the code and the prohibition on
77 // reading viewer code that used to be in place.
78 Slam = (1 << 4),
79
80 FoldedMask = 0x0f,
81
82 FoldingShift = 13 , // number of bit shifts from normal perm to folded or back (same as Transfer shift below)
83 // when doing as a block
84
85 Transfer = 1 << 13, // 0x02000
86 Modify = 1 << 14, // 0x04000
87 Copy = 1 << 15, // 0x08000
88 Export = 1 << 16, // 0x10000
89 Move = 1 << 19, // 0x80000
90 Damage = 1 << 20, // 0x100000 does not seem to be in use
70 // All does not contain Export, which is special and must be 91 // All does not contain Export, which is special and must be
71 // explicitly given 92 // explicitly given
72 All = (1 << 13) | (1 << 14) | (1 << 15) | (1 << 19) 93 All = 0x8e000,
94 AllAndExport = 0x9e000,
95 AllEffective = 0x9e000,
96 UnfoldedMask = 0x1e000
73 } 97 }
74 98
75 /// <summary> 99 /// <summary>
@@ -103,7 +127,7 @@ namespace OpenSim.Framework
103 public STPStartInfo STPStartInfo { get; set; } 127 public STPStartInfo STPStartInfo { get; set; }
104 public WIGStartInfo WIGStartInfo { get; set; } 128 public WIGStartInfo WIGStartInfo { get; set; }
105 public bool IsIdle { get; set; } 129 public bool IsIdle { get; set; }
106 public bool IsShuttingDown { get; set; } 130 public bool IsShuttingDown { get; set; }
107 public int MaxThreads { get; set; } 131 public int MaxThreads { get; set; }
108 public int MinThreads { get; set; } 132 public int MinThreads { get; set; }
109 public int InUseThreads { get; set; } 133 public int InUseThreads { get; set; }
@@ -131,10 +155,16 @@ namespace OpenSim.Framework
131 155
132 public static readonly int MAX_THREADPOOL_LEVEL = 3; 156 public static readonly int MAX_THREADPOOL_LEVEL = 3;
133 157
158 public static double TimeStampClockPeriodMS;
159 public static double TimeStampClockPeriod;
160
134 static Util() 161 static Util()
135 { 162 {
136 LogThreadPool = 0; 163 LogThreadPool = 0;
137 LogOverloads = true; 164 LogOverloads = true;
165 TimeStampClockPeriod = 1.0D/ (double)Stopwatch.Frequency;
166 TimeStampClockPeriodMS = 1e3 * TimeStampClockPeriod;
167 m_log.InfoFormat("[UTIL] TimeStamp clock with period of {0}ms", Math.Round(TimeStampClockPeriodMS,6,MidpointRounding.AwayFromZero));
138 } 168 }
139 169
140 private static uint nextXferID = 5000; 170 private static uint nextXferID = 5000;
@@ -217,7 +247,7 @@ namespace OpenSim.Framework
217 public static Encoding UTF8NoBomEncoding = new UTF8Encoding(false); 247 public static Encoding UTF8NoBomEncoding = new UTF8Encoding(false);
218 248
219 /// <value> 249 /// <value>
220 /// Well known UUID for the blank texture used in the Linden SL viewer version 1.20 (and hopefully onwards) 250 /// Well known UUID for the blank texture used in the Linden SL viewer version 1.20 (and hopefully onwards)
221 /// </value> 251 /// </value>
222 public static UUID BLANK_TEXTURE_UUID = new UUID("5748decc-f629-461c-9a36-a35a221fe21f"); 252 public static UUID BLANK_TEXTURE_UUID = new UUID("5748decc-f629-461c-9a36-a35a221fe21f");
223 253
@@ -267,14 +297,12 @@ namespace OpenSim.Framework
267 /// </summary> 297 /// </summary>
268 /// <param name="a">A 3d vector</param> 298 /// <param name="a">A 3d vector</param>
269 /// <returns>A new vector which is normalized form of the vector</returns> 299 /// <returns>A new vector which is normalized form of the vector</returns>
270 /// <remarks>The vector paramater cannot be <0,0,0></remarks> 300
271 public static Vector3 GetNormalizedVector(Vector3 a) 301 public static Vector3 GetNormalizedVector(Vector3 a)
272 { 302 {
273 if (IsZeroVector(a)) 303 Vector3 v = new Vector3(a.X, a.Y, a.Z);
274 throw new ArgumentException("Vector paramater cannot be a zero vector."); 304 v.Normalize();
275 305 return v;
276 float Mag = (float) GetMagnitude(a);
277 return new Vector3(a.X / Mag, a.Y / Mag, a.Z / Mag);
278 } 306 }
279 307
280 /// <summary> 308 /// <summary>
@@ -357,47 +385,185 @@ namespace OpenSim.Framework
357 return Utils.UIntsToLong(X, Y); 385 return Utils.UIntsToLong(X, Y);
358 } 386 }
359 387
360 // Regions are identified with a 'handle' made up of its region coordinates packed into a ulong. 388 // Regions are identified with a 'handle' made up of its world coordinates packed into a ulong.
361 // Several places rely on the ability to extract a region's location from its handle. 389 // Region handles are based on the coordinate of the region corner with lower X and Y
362 // Note the location is in 'world coordinates' (see below). 390 // var regions need more work than this to get that right corner from a generic world position
363 // Region handles are based on the lowest coordinate of the region so trim the passed x,y to be the regions 0,0. 391 // this corner must be on a grid point
364 public static ulong RegionWorldLocToHandle(uint X, uint Y) 392 public static ulong RegionWorldLocToHandle(uint X, uint Y)
365 { 393 {
366 return Utils.UIntsToLong(X, Y); 394 ulong handle = X & 0xffffff00; // make sure it matchs grid coord points.
395 handle <<= 32; // to higher half
396 handle |= (Y & 0xffffff00);
397 return handle;
367 } 398 }
368 399
369 public static ulong RegionLocToHandle(uint X, uint Y) 400 public static ulong RegionGridLocToHandle(uint X, uint Y)
370 { 401 {
371 return Utils.UIntsToLong(Util.RegionToWorldLoc(X), Util.RegionToWorldLoc(Y)); 402 ulong handle = X;
403 handle <<= 40; // shift to higher half and mult by 256)
404 handle |= (Y << 8); // mult by 256)
405 return handle;
372 } 406 }
373 407
374 public static void RegionHandleToWorldLoc(ulong handle, out uint X, out uint Y) 408 public static void RegionHandleToWorldLoc(ulong handle, out uint X, out uint Y)
375 { 409 {
376 X = (uint)(handle >> 32); 410 X = (uint)(handle >> 32);
377 Y = (uint)(handle & (ulong)uint.MaxValue); 411 Y = (uint)(handle & 0xfffffffful);
378 } 412 }
379 413
380 public static void RegionHandleToRegionLoc(ulong handle, out uint X, out uint Y) 414 public static void RegionHandleToRegionLoc(ulong handle, out uint X, out uint Y)
381 { 415 {
382 uint worldX, worldY; 416 X = (uint)(handle >> 40) & 0x00ffffffu; // bring from higher half, divide by 256 and clean
383 RegionHandleToWorldLoc(handle, out worldX, out worldY); 417 Y = (uint)(handle >> 8) & 0x00ffffffu; // divide by 256 and clean
384 X = WorldToRegionLoc(worldX); 418 // if you trust the uint cast then the clean can be removed.
385 Y = WorldToRegionLoc(worldY);
386 } 419 }
387 420
388 // A region location can be 'world coordinates' (meters from zero) or 'region coordinates' 421 // A region location can be 'world coordinates' (meters) or 'region grid coordinates'
389 // (number of regions from zero). This measurement of regions relies on the legacy 256 region size. 422 // grid coordinates have a fixed step of 256m as defined by viewers
390 // These routines exist to make what is being converted explicit so the next person knows what was meant.
391 // Convert a region's 'world coordinate' to its 'region coordinate'.
392 public static uint WorldToRegionLoc(uint worldCoord) 423 public static uint WorldToRegionLoc(uint worldCoord)
393 { 424 {
394 return worldCoord / Constants.RegionSize; 425 return worldCoord >> 8;
395 } 426 }
396 427
397 // Convert a region's 'region coordinate' to its 'world coordinate'. 428 // Convert a region's 'region grid coordinate' to its 'world coordinate'.
398 public static uint RegionToWorldLoc(uint regionCoord) 429 public static uint RegionToWorldLoc(uint regionCoord)
399 { 430 {
400 return regionCoord * Constants.RegionSize; 431 return regionCoord << 8;
432 }
433
434
435 public static bool checkServiceURI(string uristr, out string serviceURI)
436 {
437 serviceURI = string.Empty;
438 try
439 {
440 Uri uri = new Uri(uristr);
441 serviceURI = uri.AbsoluteUri;
442 if(uri.Port == 80)
443 serviceURI = serviceURI.Trim(new char[] { '/', ' ' }) +":80/";
444 else if(uri.Port == 443)
445 serviceURI = serviceURI.Trim(new char[] { '/', ' ' }) +":443/";
446 return true;
447 }
448 catch
449 {
450 serviceURI = string.Empty;
451 }
452 return false;
453 }
454
455 public static bool buildHGRegionURI(string inputName, out string serverURI, out string regionName)
456 {
457 serverURI = string.Empty;
458 regionName = string.Empty;
459
460 inputName = inputName.Trim();
461
462 if (!inputName.StartsWith("http") && !inputName.StartsWith("https"))
463 {
464 // Formats: grid.example.com:8002:region name
465 // grid.example.com:region name
466 // grid.example.com:8002
467 // grid.example.com
468
469 string host;
470 uint port = 80;
471
472 string[] parts = inputName.Split(new char[] { ':' });
473 int indx;
474 if(parts.Length == 0)
475 return false;
476 if (parts.Length == 1)
477 {
478 indx = inputName.IndexOf('/');
479 if (indx < 0)
480 serverURI = "http://"+ inputName + "/";
481 else
482 {
483 serverURI = "http://"+ inputName.Substring(0,indx + 1);
484 if(indx + 2 < inputName.Length)
485 regionName = inputName.Substring(indx + 1);
486 }
487 }
488 else
489 {
490 host = parts[0];
491
492 if (parts.Length >= 2)
493 {
494 indx = parts[1].IndexOf('/');
495 if(indx < 0)
496 {
497 // If it's a number then assume it's a port. Otherwise, it's a region name.
498 if (!UInt32.TryParse(parts[1], out port))
499 {
500 port = 80;
501 regionName = parts[1];
502 }
503 }
504 else
505 {
506 string portstr = parts[1].Substring(0, indx);
507 if(indx + 2 < parts[1].Length)
508 regionName = parts[1].Substring(indx + 1);
509 if (!UInt32.TryParse(portstr, out port))
510 port = 80;
511 }
512 }
513 // always take the last one
514 if (parts.Length >= 3)
515 {
516 regionName = parts[2];
517 }
518
519 serverURI = "http://"+ host +":"+ port.ToString() + "/";
520 }
521 }
522 else
523 {
524 // Formats: http://grid.example.com region name
525 // http://grid.example.com "region name"
526 // http://grid.example.com
527
528 string[] parts = inputName.Split(new char[] { ' ' });
529
530 if (parts.Length == 0)
531 return false;
532
533 serverURI = parts[0];
534
535 int indx = serverURI.LastIndexOf('/');
536 if(indx > 10)
537 {
538 if(indx + 2 < inputName.Length)
539 regionName = inputName.Substring(indx + 1);
540 serverURI = inputName.Substring(0, indx + 1);
541 }
542 else if (parts.Length >= 2)
543 {
544 regionName = inputName.Substring(serverURI.Length);
545 }
546 }
547
548 // use better code for sanity check
549 Uri uri;
550 try
551 {
552 uri = new Uri(serverURI);
553 }
554 catch
555 {
556 return false;
557 }
558
559 if(!string.IsNullOrEmpty(regionName))
560 regionName = regionName.Trim(new char[] { '"', ' ' });
561 serverURI = uri.AbsoluteUri;
562 if(uri.Port == 80)
563 serverURI = serverURI.Trim(new char[] { '/', ' ' }) +":80/";
564 else if(uri.Port == 443)
565 serverURI = serverURI.Trim(new char[] { '/', ' ' }) +":443/";
566 return true;
401 } 567 }
402 568
403 public static T Clamp<T>(T x, T min, T max) 569 public static T Clamp<T>(T x, T min, T max)
@@ -505,6 +671,7 @@ namespace OpenSim.Framework
505 public static string GetFormattedXml(string rawXml) 671 public static string GetFormattedXml(string rawXml)
506 { 672 {
507 XmlDocument xd = new XmlDocument(); 673 XmlDocument xd = new XmlDocument();
674 xd.XmlResolver=null;
508 xd.LoadXml(rawXml); 675 xd.LoadXml(rawXml);
509 676
510 StringBuilder sb = new StringBuilder(); 677 StringBuilder sb = new StringBuilder();
@@ -641,19 +808,25 @@ namespace OpenSim.Framework
641 /// </summary> 808 /// </summary>
642 /// <param name="data"></param> 809 /// <param name="data"></param>
643 /// <returns></returns> 810 /// <returns></returns>
811
644 public static string Md5Hash(string data) 812 public static string Md5Hash(string data)
645 { 813 {
646 byte[] dataMd5 = ComputeMD5Hash(data); 814 return Md5Hash(data, Encoding.Default);
815 }
816
817 public static string Md5Hash(string data, Encoding encoding)
818 {
819 byte[] dataMd5 = ComputeMD5Hash(data, encoding);
647 StringBuilder sb = new StringBuilder(); 820 StringBuilder sb = new StringBuilder();
648 for (int i = 0; i < dataMd5.Length; i++) 821 for (int i = 0; i < dataMd5.Length; i++)
649 sb.AppendFormat("{0:x2}", dataMd5[i]); 822 sb.AppendFormat("{0:x2}", dataMd5[i]);
650 return sb.ToString(); 823 return sb.ToString();
651 } 824 }
652 825
653 private static byte[] ComputeMD5Hash(string data) 826 private static byte[] ComputeMD5Hash(string data, Encoding encoding)
654 { 827 {
655 MD5 md5 = MD5.Create(); 828 MD5 md5 = MD5.Create();
656 return md5.ComputeHash(Encoding.Default.GetBytes(data)); 829 return md5.ComputeHash(encoding.GetBytes(data));
657 } 830 }
658 831
659 /// <summary> 832 /// <summary>
@@ -661,6 +834,12 @@ namespace OpenSim.Framework
661 /// </summary> 834 /// </summary>
662 /// <param name="data"></param> 835 /// <param name="data"></param>
663 /// <returns></returns> 836 /// <returns></returns>
837
838 public static string SHA1Hash(string data, Encoding enc)
839 {
840 return SHA1Hash(enc.GetBytes(data));
841 }
842
664 public static string SHA1Hash(string data) 843 public static string SHA1Hash(string data)
665 { 844 {
666 return SHA1Hash(Encoding.Default.GetBytes(data)); 845 return SHA1Hash(Encoding.Default.GetBytes(data));
@@ -679,8 +858,10 @@ namespace OpenSim.Framework
679 858
680 private static byte[] ComputeSHA1Hash(byte[] src) 859 private static byte[] ComputeSHA1Hash(byte[] src)
681 { 860 {
682 SHA1CryptoServiceProvider SHA1 = new SHA1CryptoServiceProvider(); 861 byte[] ret;
683 return SHA1.ComputeHash(src); 862 using(SHA1CryptoServiceProvider SHA1 = new SHA1CryptoServiceProvider())
863 ret = SHA1.ComputeHash(src);
864 return ret;
684 } 865 }
685 866
686 public static int fast_distance2d(int x, int y) 867 public static int fast_distance2d(int x, int y)
@@ -713,18 +894,27 @@ namespace OpenSim.Framework
713 /// <param name="newx">New region x-coord</param> 894 /// <param name="newx">New region x-coord</param>
714 /// <param name="oldy">Old region y-coord</param> 895 /// <param name="oldy">Old region y-coord</param>
715 /// <param name="newy">New region y-coord</param> 896 /// <param name="newy">New region y-coord</param>
716 /// <returns></returns> 897 /// <returns></returns>
717 public static bool IsOutsideView(float drawdist, uint oldx, uint newx, uint oldy, uint newy) 898 public static bool IsOutsideView(float drawdist, uint oldx, uint newx, uint oldy, uint newy,
718 { 899 int oldsizex, int oldsizey, int newsizex, int newsizey)
719 int dd = (int)((drawdist + Constants.RegionSize - 1) / Constants.RegionSize); 900 {
720 901 // we still need to make sure we see new region 1stNeighbors
721 int startX = (int)oldx - dd; 902 drawdist--;
722 int startY = (int)oldy - dd; 903 oldx *= Constants.RegionSize;
904 newx *= Constants.RegionSize;
905 if (oldx + oldsizex + drawdist < newx)
906 return true;
907 if (newx + newsizex + drawdist < oldx)
908 return true;
723 909
724 int endX = (int)oldx + dd; 910 oldy *= Constants.RegionSize;
725 int endY = (int)oldy + dd; 911 newy *= Constants.RegionSize;
912 if (oldy + oldsizey + drawdist < newy)
913 return true;
914 if (newy + newsizey + drawdist < oldy)
915 return true;
726 916
727 return (newx < startX || endX < newx || newy < startY || endY < newy); 917 return false;
728 } 918 }
729 919
730 public static string FieldToString(byte[] bytes) 920 public static string FieldToString(byte[] bytes)
@@ -804,6 +994,18 @@ namespace OpenSim.Framework
804 return output.ToString(); 994 return output.ToString();
805 } 995 }
806 996
997 private static ExpiringCache<string,IPAddress> dnscache = new ExpiringCache<string, IPAddress>();
998
999 /// <summary>
1000 /// Converts a URL to a IPAddress
1001 /// </summary>
1002 /// <param name="url">URL Standard Format</param>
1003 /// <returns>A resolved IP Address</returns>
1004 public static IPAddress GetHostFromURL(string url)
1005 {
1006 return GetHostFromDNS(url.Split(new char[] {'/', ':'})[3]);
1007 }
1008
807 /// <summary> 1009 /// <summary>
808 /// Returns a IP address from a specified DNS, favouring IPv4 addresses. 1010 /// Returns a IP address from a specified DNS, favouring IPv4 addresses.
809 /// </summary> 1011 /// </summary>
@@ -811,38 +1013,128 @@ namespace OpenSim.Framework
811 /// <returns>An IP address, or null</returns> 1013 /// <returns>An IP address, or null</returns>
812 public static IPAddress GetHostFromDNS(string dnsAddress) 1014 public static IPAddress GetHostFromDNS(string dnsAddress)
813 { 1015 {
814 // Is it already a valid IP? No need to look it up. 1016 if(String.IsNullOrWhiteSpace(dnsAddress))
815 IPAddress ipa; 1017 return null;
816 if (IPAddress.TryParse(dnsAddress, out ipa))
817 return ipa;
818 1018
819 IPAddress[] hosts = null; 1019 IPAddress ia = null;
1020 if(dnscache.TryGetValue(dnsAddress, out ia) && ia != null)
1021 {
1022 dnscache.AddOrUpdate(dnsAddress, ia, 300);
1023 return ia;
1024 }
820 1025
821 // Not an IP, lookup required 1026 ia = null;
1027 // If it is already an IP, don't let GetHostEntry see it
1028 if (IPAddress.TryParse(dnsAddress, out ia) && ia != null)
1029 {
1030 if (ia.Equals(IPAddress.Any) || ia.Equals(IPAddress.IPv6Any))
1031 return null;
1032 dnscache.AddOrUpdate(dnsAddress, ia, 300);
1033 return ia;
1034 }
1035
1036 IPHostEntry IPH;
822 try 1037 try
823 { 1038 {
824 hosts = Dns.GetHostEntry(dnsAddress).AddressList; 1039 IPH = Dns.GetHostEntry(dnsAddress);
825 } 1040 }
826 catch (Exception e) 1041 catch // (SocketException e)
1042 {
1043 return null;
1044 }
1045
1046 if(IPH == null || IPH.AddressList.Length == 0)
1047 return null;
1048
1049 ia = null;
1050 foreach (IPAddress Adr in IPH.AddressList)
827 { 1051 {
828 m_log.WarnFormat("[UTIL]: An error occurred while resolving host name {0}, {1}", dnsAddress, e); 1052 if (ia == null)
1053 ia = Adr;
829 1054
830 // Still going to throw the exception on for now, since this was what was happening in the first place 1055 if (Adr.AddressFamily == AddressFamily.InterNetwork)
831 throw e; 1056 {
1057 ia = Adr;
1058 break;
1059 }
832 } 1060 }
1061 if(ia != null)
1062 dnscache.AddOrUpdate(dnsAddress, ia, 300);
1063 return ia;
1064 }
833 1065
834 foreach (IPAddress host in hosts) 1066 public static IPEndPoint getEndPoint(IPAddress ia, int port)
1067 {
1068 if(ia == null)
1069 return null;
1070
1071 IPEndPoint newEP = null;
1072 try
1073 {
1074 newEP = new IPEndPoint(ia, port);
1075 }
1076 catch
1077 {
1078 newEP = null;
1079 }
1080 return newEP;
1081 }
1082
1083 public static IPEndPoint getEndPoint(string hostname, int port)
1084 {
1085 if(String.IsNullOrWhiteSpace(hostname))
1086 return null;
1087
1088 IPAddress ia = null;
1089 if(dnscache.TryGetValue(hostname, out ia) && ia != null)
1090 {
1091 dnscache.AddOrUpdate(hostname, ia, 300);
1092 return getEndPoint(ia, port);
1093 }
1094
1095 ia = null;
1096
1097 // If it is already an IP, don't let GetHostEntry see it
1098 if (IPAddress.TryParse(hostname, out ia) && ia != null)
1099 {
1100 if (ia.Equals(IPAddress.Any) || ia.Equals(IPAddress.IPv6Any))
1101 return null;
1102
1103 dnscache.AddOrUpdate(hostname, ia, 300);
1104 return getEndPoint(ia, port);
1105 }
1106
1107
1108 IPHostEntry IPH;
1109 try
1110 {
1111 IPH = Dns.GetHostEntry(hostname);
1112 }
1113 catch // (SocketException e)
1114 {
1115 return null;
1116 }
1117
1118 if(IPH == null || IPH.AddressList.Length == 0)
1119 return null;
1120
1121 ia = null;
1122 foreach (IPAddress Adr in IPH.AddressList)
835 { 1123 {
836 if (host.AddressFamily == AddressFamily.InterNetwork) 1124 if (ia == null)
1125 ia = Adr;
1126
1127 if (Adr.AddressFamily == AddressFamily.InterNetwork)
837 { 1128 {
838 return host; 1129 ia = Adr;
1130 break;
839 } 1131 }
840 } 1132 }
841 1133
842 if (hosts.Length > 0) 1134 if(ia != null)
843 return hosts[0]; 1135 dnscache.AddOrUpdate(hostname, ia, 300);
844 1136
845 return null; 1137 return getEndPoint(ia,port);
846 } 1138 }
847 1139
848 public static Uri GetURI(string protocol, string hostname, int port, string path) 1140 public static Uri GetURI(string protocol, string hostname, int port, string path)
@@ -987,7 +1279,7 @@ namespace OpenSim.Framework
987 1279
988 public static string configDir() 1280 public static string configDir()
989 { 1281 {
990 return "../config"; 1282 return ".";
991 } 1283 }
992 1284
993 public static string dataDir() 1285 public static string dataDir()
@@ -999,13 +1291,26 @@ namespace OpenSim.Framework
999 { 1291 {
1000 foreach (IAppender appender in LogManager.GetRepository().GetAppenders()) 1292 foreach (IAppender appender in LogManager.GetRepository().GetAppenders())
1001 { 1293 {
1002 if (appender is FileAppender) 1294 if (appender is FileAppender && appender.Name == "LogFileAppender")
1003 { 1295 {
1004 return ((FileAppender)appender).File; 1296 return ((FileAppender)appender).File;
1005 } 1297 }
1006 } 1298 }
1007 1299
1008 return "../logs/OpenSim.log"; 1300 return "./OpenSim.log";
1301 }
1302
1303 public static string statsLogFile()
1304 {
1305 foreach (IAppender appender in LogManager.GetRepository().GetAppenders())
1306 {
1307 if (appender is FileAppender && appender.Name == "StatsLogFileAppender")
1308 {
1309 return ((FileAppender)appender).File;
1310 }
1311 }
1312
1313 return "./OpenSimStats.log";
1009 } 1314 }
1010 1315
1011 public static string logDir() 1316 public static string logDir()
@@ -1065,9 +1370,28 @@ namespace OpenSim.Framework
1065 } 1370 }
1066 } 1371 }
1067 1372
1373 public static string GetConfigVarWithDefaultSection(IConfigSource config, string varname, string section)
1374 {
1375 // First, check the Startup section, the default section
1376 IConfig cnf = config.Configs["Startup"];
1377 if (cnf == null)
1378 return string.Empty;
1379 string val = cnf.GetString(varname, string.Empty);
1380
1381 // Then check for an overwrite of the default in the given section
1382 if (!string.IsNullOrEmpty(section))
1383 {
1384 cnf = config.Configs[section];
1385 if (cnf != null)
1386 val = cnf.GetString(varname, val);
1387 }
1388
1389 return val;
1390 }
1391
1068 /// <summary> 1392 /// <summary>
1069 /// Gets the value of a configuration variable by looking into 1393 /// Gets the value of a configuration variable by looking into
1070 /// multiple sections in order. The latter sections overwrite 1394 /// multiple sections in order. The latter sections overwrite
1071 /// any values previously found. 1395 /// any values previously found.
1072 /// </summary> 1396 /// </summary>
1073 /// <typeparam name="T">Type of the variable</typeparam> 1397 /// <typeparam name="T">Type of the variable</typeparam>
@@ -1082,7 +1406,7 @@ namespace OpenSim.Framework
1082 1406
1083 /// <summary> 1407 /// <summary>
1084 /// Gets the value of a configuration variable by looking into 1408 /// Gets the value of a configuration variable by looking into
1085 /// multiple sections in order. The latter sections overwrite 1409 /// multiple sections in order. The latter sections overwrite
1086 /// any values previously found. 1410 /// any values previously found.
1087 /// </summary> 1411 /// </summary>
1088 /// <remarks> 1412 /// <remarks>
@@ -1138,7 +1462,7 @@ namespace OpenSim.Framework
1138 ConfigSource.ExpandKeyValues(); 1462 ConfigSource.ExpandKeyValues();
1139 } 1463 }
1140 } 1464 }
1141 1465
1142 public static T ReadSettingsFromIniFile<T>(IConfig config, T settingsClass) 1466 public static T ReadSettingsFromIniFile<T>(IConfig config, T settingsClass)
1143 { 1467 {
1144 Type settingsType = settingsClass.GetType(); 1468 Type settingsType = settingsClass.GetType();
@@ -1249,7 +1573,7 @@ namespace OpenSim.Framework
1249 1573
1250 if (File.Exists(configFile)) 1574 if (File.Exists(configFile))
1251 { 1575 {
1252 // Merge 1576 // Merge
1253 config.Merge(new IniConfigSource(configFile)); 1577 config.Merge(new IniConfigSource(configFile));
1254 config.ExpandKeyValues(); 1578 config.ExpandKeyValues();
1255 configFilePath = configFile; 1579 configFilePath = configFile;
@@ -1388,6 +1712,46 @@ namespace OpenSim.Framework
1388 return ret; 1712 return ret;
1389 } 1713 }
1390 1714
1715 public static string Compress(string text)
1716 {
1717 byte[] buffer = Util.UTF8.GetBytes(text);
1718 MemoryStream memory = new MemoryStream();
1719 using (GZipStream compressor = new GZipStream(memory, CompressionMode.Compress, true))
1720 {
1721 compressor.Write(buffer, 0, buffer.Length);
1722 }
1723
1724 memory.Position = 0;
1725
1726 byte[] compressed = new byte[memory.Length];
1727 memory.Read(compressed, 0, compressed.Length);
1728
1729 byte[] compressedBuffer = new byte[compressed.Length + 4];
1730 Buffer.BlockCopy(compressed, 0, compressedBuffer, 4, compressed.Length);
1731 Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, compressedBuffer, 0, 4);
1732 return Convert.ToBase64String(compressedBuffer);
1733 }
1734
1735 public static string Decompress(string compressedText)
1736 {
1737 byte[] compressedBuffer = Convert.FromBase64String(compressedText);
1738 using (MemoryStream memory = new MemoryStream())
1739 {
1740 int msgLength = BitConverter.ToInt32(compressedBuffer, 0);
1741 memory.Write(compressedBuffer, 4, compressedBuffer.Length - 4);
1742
1743 byte[] buffer = new byte[msgLength];
1744
1745 memory.Position = 0;
1746 using (GZipStream decompressor = new GZipStream(memory, CompressionMode.Decompress))
1747 {
1748 decompressor.Read(buffer, 0, buffer.Length);
1749 }
1750
1751 return Util.UTF8.GetString(buffer);
1752 }
1753 }
1754
1391 /// <summary> 1755 /// <summary>
1392 /// Copy data from one stream to another, leaving the read position of both streams at the beginning. 1756 /// Copy data from one stream to another, leaving the read position of both streams at the beginning.
1393 /// </summary> 1757 /// </summary>
@@ -1405,7 +1769,7 @@ namespace OpenSim.Framework
1405 const int readSize = 256; 1769 const int readSize = 256;
1406 byte[] buffer = new byte[readSize]; 1770 byte[] buffer = new byte[readSize];
1407 MemoryStream ms = new MemoryStream(); 1771 MemoryStream ms = new MemoryStream();
1408 1772
1409 int count = inputStream.Read(buffer, 0, readSize); 1773 int count = inputStream.Read(buffer, 0, readSize);
1410 1774
1411 while (count > 0) 1775 while (count > 0)
@@ -1485,12 +1849,16 @@ namespace OpenSim.Framework
1485 return new UUID(bytes, 0); 1849 return new UUID(bytes, 0);
1486 } 1850 }
1487 1851
1488 public static void ParseFakeParcelID(UUID parcelID, out ulong regionHandle, out uint x, out uint y) 1852 public static bool ParseFakeParcelID(UUID parcelID, out ulong regionHandle, out uint x, out uint y)
1489 { 1853 {
1490 byte[] bytes = parcelID.GetBytes(); 1854 byte[] bytes = parcelID.GetBytes();
1491 regionHandle = Utils.BytesToUInt64(bytes); 1855 regionHandle = Utils.BytesToUInt64(bytes);
1492 x = Utils.BytesToUInt(bytes, 8) & 0xffff; 1856 x = Utils.BytesToUInt(bytes, 8) & 0xffff;
1493 y = Utils.BytesToUInt(bytes, 12) & 0xffff; 1857 y = Utils.BytesToUInt(bytes, 12) & 0xffff;
1858 // validation may fail, just reducing the odds of using a real UUID as encoded parcel
1859 return ( bytes[0] == 0 && bytes[4] == 0 && // handler x,y multiples of 256
1860 bytes[9] < 64 && bytes[13] < 64 && // positions < 16km
1861 bytes[14] == 0 && bytes[15] == 0);
1494 } 1862 }
1495 1863
1496 public static void ParseFakeParcelID(UUID parcelID, out ulong regionHandle, out uint x, out uint y, out uint z) 1864 public static void ParseFakeParcelID(UUID parcelID, out ulong regionHandle, out uint x, out uint y, out uint z)
@@ -1513,7 +1881,7 @@ namespace OpenSim.Framework
1513 x += rx; 1881 x += rx;
1514 y += ry; 1882 y += ry;
1515 } 1883 }
1516 1884
1517 /// <summary> 1885 /// <summary>
1518 /// Get operating system information if available. Returns only the first 45 characters of information 1886 /// Get operating system information if available. Returns only the first 45 characters of information
1519 /// </summary> 1887 /// </summary>
@@ -1524,20 +1892,20 @@ namespace OpenSim.Framework
1524 { 1892 {
1525 string os = String.Empty; 1893 string os = String.Empty;
1526 1894
1527 if (Environment.OSVersion.Platform != PlatformID.Unix) 1895// if (Environment.OSVersion.Platform != PlatformID.Unix)
1528 { 1896// {
1529 os = Environment.OSVersion.ToString(); 1897// os = Environment.OSVersion.ToString();
1530 } 1898// }
1531 else 1899// else
1532 { 1900// {
1533 os = ReadEtcIssue(); 1901// os = ReadEtcIssue();
1534 } 1902// }
1535 1903//
1536 if (os.Length > 45) 1904// if (os.Length > 45)
1537 { 1905// {
1538 os = os.Substring(0, 45); 1906// os = os.Substring(0, 45);
1539 } 1907// }
1540 1908
1541 return os; 1909 return os;
1542 } 1910 }
1543 1911
@@ -1579,6 +1947,8 @@ namespace OpenSim.Framework
1579 1947
1580 // hide the password in the connection string 1948 // hide the password in the connection string
1581 passPosition = connectionString.IndexOf("password", StringComparison.OrdinalIgnoreCase); 1949 passPosition = connectionString.IndexOf("password", StringComparison.OrdinalIgnoreCase);
1950 if (passPosition == -1)
1951 return connectionString;
1582 passPosition = connectionString.IndexOf("=", passPosition); 1952 passPosition = connectionString.IndexOf("=", passPosition);
1583 if (passPosition < connectionString.Length) 1953 if (passPosition < connectionString.Length)
1584 passPosition += 1; 1954 passPosition += 1;
@@ -1645,7 +2015,7 @@ namespace OpenSim.Framework
1645 2015
1646 public static Guid GetHashGuid(string data, string salt) 2016 public static Guid GetHashGuid(string data, string salt)
1647 { 2017 {
1648 byte[] hash = ComputeMD5Hash(data + salt); 2018 byte[] hash = ComputeMD5Hash(data + salt, Encoding.Default);
1649 2019
1650 //string s = BitConverter.ToString(hash); 2020 //string s = BitConverter.ToString(hash);
1651 2021
@@ -1747,7 +2117,7 @@ namespace OpenSim.Framework
1747 vol = vcomps[0]; 2117 vol = vcomps[0];
1748 } 2118 }
1749 } 2119 }
1750 2120
1751 string[] comps = path.Split(new char[] {Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar}, StringSplitOptions.RemoveEmptyEntries); 2121 string[] comps = path.Split(new char[] {Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar}, StringSplitOptions.RemoveEmptyEntries);
1752 2122
1753 // Glob 2123 // Glob
@@ -1792,6 +2162,32 @@ namespace OpenSim.Framework
1792 return found.ToArray(); 2162 return found.ToArray();
1793 } 2163 }
1794 2164
2165 public static string ServerURI(string uri)
2166 {
2167 if (uri == string.Empty)
2168 return string.Empty;
2169
2170 // Get rid of eventual slashes at the end
2171 uri = uri.TrimEnd('/');
2172
2173 IPAddress ipaddr1 = null;
2174 string port1 = "";
2175 try
2176 {
2177 ipaddr1 = Util.GetHostFromURL(uri);
2178 }
2179 catch { }
2180
2181 try
2182 {
2183 port1 = uri.Split(new char[] { ':' })[2];
2184 }
2185 catch { }
2186
2187 // We tried our best to convert the domain names to IP addresses
2188 return (ipaddr1 != null) ? "http://" + ipaddr1.ToString() + ":" + port1 : uri;
2189 }
2190
1795 /// <summary> 2191 /// <summary>
1796 /// Convert a string to a byte format suitable for transport in an LLUDP packet. The output is truncated to 256 bytes if necessary. 2192 /// Convert a string to a byte format suitable for transport in an LLUDP packet. The output is truncated to 256 bytes if necessary.
1797 /// </summary> 2193 /// </summary>
@@ -1823,14 +2219,14 @@ namespace OpenSim.Framework
1823 2219
1824 if (!str.EndsWith("\0")) 2220 if (!str.EndsWith("\0"))
1825 str += "\0"; 2221 str += "\0";
1826 2222
1827 // Because this is UTF-8 encoding and not ASCII, it's possible we 2223 // Because this is UTF-8 encoding and not ASCII, it's possible we
1828 // might have gotten an oversized array even after the string trim 2224 // might have gotten an oversized array even after the string trim
1829 byte[] data = UTF8.GetBytes(str); 2225 byte[] data = UTF8.GetBytes(str);
1830 2226
1831 if (data.Length > 256) 2227 if (data.Length > 255) //play safe
1832 { 2228 {
1833 int cut = 255; 2229 int cut = 254;
1834 if((data[cut] & 0x80 ) != 0 ) 2230 if((data[cut] & 0x80 ) != 0 )
1835 { 2231 {
1836 while(cut > 0 && (data[cut] & 0xc0) != 0xc0) 2232 while(cut > 0 && (data[cut] & 0xc0) != 0xc0)
@@ -1895,6 +2291,56 @@ namespace OpenSim.Framework
1895 } 2291 }
1896 2292
1897 /// <summary> 2293 /// <summary>
2294 /// Convert a string to a byte format suitable for transport in an LLUDP packet. The output is truncated to MaxLength bytes if necessary.
2295 /// </summary>
2296 /// <param name="str">
2297 /// If null or empty, then an bytes[0] is returned.
2298 /// Using "\0" will return a conversion of the null character to a byte. This is not the same as bytes[0]
2299 /// </param>
2300 /// <param name="args">
2301 /// Arguments to substitute into the string via the {} mechanism.
2302 /// </param>
2303 /// <returns></returns>
2304 public static byte[] StringToBytes(string str, int MaxLength, params object[] args)
2305 {
2306 return StringToBytes1024(string.Format(str, args), MaxLength);
2307 }
2308
2309 /// <summary>
2310 /// Convert a string to a byte format suitable for transport in an LLUDP packet. The output is truncated to MaxLength bytes if necessary.
2311 /// </summary>
2312 /// <param name="str">
2313 /// If null or empty, then an bytes[0] is returned.
2314 /// Using "\0" will return a conversion of the null character to a byte. This is not the same as bytes[0]
2315 /// </param>
2316 /// <returns></returns>
2317 public static byte[] StringToBytes(string str, int MaxLength)
2318 {
2319 if (String.IsNullOrEmpty(str))
2320 return Utils.EmptyBytes;
2321
2322 if (!str.EndsWith("\0"))
2323 str += "\0";
2324
2325 // Because this is UTF-8 encoding and not ASCII, it's possible we
2326 // might have gotten an oversized array even after the string trim
2327 byte[] data = UTF8.GetBytes(str);
2328
2329 if (data.Length > MaxLength)
2330 {
2331 int cut = MaxLength - 1 ;
2332 if((data[cut] & 0x80 ) != 0 )
2333 {
2334 while(cut > 0 && (data[cut] & 0xc0) != 0xc0)
2335 cut--;
2336 }
2337 Array.Resize<byte>(ref data, cut + 1);
2338 data[cut] = 0;
2339 }
2340
2341 return data;
2342 }
2343 /// <summary>
1898 /// Pretty format the hashtable contents to a single line. 2344 /// Pretty format the hashtable contents to a single line.
1899 /// </summary> 2345 /// </summary>
1900 /// <remarks> 2346 /// <remarks>
@@ -2004,7 +2450,7 @@ namespace OpenSim.Framework
2004 2450
2005 STPStartInfo startInfo = new STPStartInfo(); 2451 STPStartInfo startInfo = new STPStartInfo();
2006 startInfo.ThreadPoolName = "Util"; 2452 startInfo.ThreadPoolName = "Util";
2007 startInfo.IdleTimeout = 2000; 2453 startInfo.IdleTimeout = 20000;
2008 startInfo.MaxWorkerThreads = maxThreads; 2454 startInfo.MaxWorkerThreads = maxThreads;
2009 startInfo.MinWorkerThreads = minThreads; 2455 startInfo.MinWorkerThreads = minThreads;
2010 2456
@@ -2032,7 +2478,7 @@ namespace OpenSim.Framework
2032 throw new NotImplementedException(); 2478 throw new NotImplementedException();
2033 } 2479 }
2034 } 2480 }
2035 2481
2036 /// <summary> 2482 /// <summary>
2037 /// Additional information about threads in the main thread pool. Used to time how long the 2483 /// Additional information about threads in the main thread pool. Used to time how long the
2038 /// thread has been running, and abort it if it has timed-out. 2484 /// thread has been running, and abort it if it has timed-out.
@@ -2043,14 +2489,15 @@ namespace OpenSim.Framework
2043 public string StackTrace { get; set; } 2489 public string StackTrace { get; set; }
2044 private string context; 2490 private string context;
2045 public bool LogThread { get; set; } 2491 public bool LogThread { get; set; }
2046 2492
2047 public IWorkItemResult WorkItem { get; set; } 2493 public IWorkItemResult WorkItem { get; set; }
2048 public Thread Thread { get; set; } 2494 public Thread Thread { get; set; }
2049 public bool Running { get; set; } 2495 public bool Running { get; set; }
2050 public bool Aborted { get; set; } 2496 public bool Aborted { get; set; }
2051 private int started; 2497 private int started;
2498 public bool DoTimeout;
2052 2499
2053 public ThreadInfo(long threadFuncNum, string context) 2500 public ThreadInfo(long threadFuncNum, string context, bool dotimeout = true)
2054 { 2501 {
2055 ThreadFuncNum = threadFuncNum; 2502 ThreadFuncNum = threadFuncNum;
2056 this.context = context; 2503 this.context = context;
@@ -2058,6 +2505,7 @@ namespace OpenSim.Framework
2058 Thread = null; 2505 Thread = null;
2059 Running = false; 2506 Running = false;
2060 Aborted = false; 2507 Aborted = false;
2508 DoTimeout = dotimeout;
2061 } 2509 }
2062 2510
2063 public void Started() 2511 public void Started()
@@ -2128,7 +2576,7 @@ namespace OpenSim.Framework
2128 foreach (KeyValuePair<long, ThreadInfo> entry in activeThreads) 2576 foreach (KeyValuePair<long, ThreadInfo> entry in activeThreads)
2129 { 2577 {
2130 ThreadInfo t = entry.Value; 2578 ThreadInfo t = entry.Value;
2131 if (t.Running && !t.Aborted && (t.Elapsed() >= THREAD_TIMEOUT)) 2579 if (t.DoTimeout && t.Running && !t.Aborted && (t.Elapsed() >= THREAD_TIMEOUT))
2132 { 2580 {
2133 m_log.WarnFormat("Timeout in threadfunc {0} ({1}) {2}", t.ThreadFuncNum, t.Thread.Name, t.GetStackTrace()); 2581 m_log.WarnFormat("Timeout in threadfunc {0} ({1}) {2}", t.ThreadFuncNum, t.Thread.Name, t.GetStackTrace());
2134 t.Abort(); 2582 t.Abort();
@@ -2138,7 +2586,7 @@ namespace OpenSim.Framework
2138 2586
2139 // It's possible that the thread won't abort. To make sure the thread pool isn't 2587 // It's possible that the thread won't abort. To make sure the thread pool isn't
2140 // depleted, increase the pool size. 2588 // depleted, increase the pool size.
2141 m_ThreadPool.MaxThreads++; 2589// m_ThreadPool.MaxThreads++;
2142 } 2590 }
2143 } 2591 }
2144 } 2592 }
@@ -2148,7 +2596,7 @@ namespace OpenSim.Framework
2148 public static Dictionary<string, int> GetFireAndForgetCallsMade() 2596 public static Dictionary<string, int> GetFireAndForgetCallsMade()
2149 { 2597 {
2150 return new Dictionary<string, int>(m_fireAndForgetCallsMade); 2598 return new Dictionary<string, int>(m_fireAndForgetCallsMade);
2151 } 2599 }
2152 2600
2153 private static Dictionary<string, int> m_fireAndForgetCallsMade = new Dictionary<string, int>(); 2601 private static Dictionary<string, int> m_fireAndForgetCallsMade = new Dictionary<string, int>();
2154 2602
@@ -2168,11 +2616,11 @@ namespace OpenSim.Framework
2168 { 2616 {
2169 FireAndForget(callback, obj, null); 2617 FireAndForget(callback, obj, null);
2170 } 2618 }
2171 2619
2172 public static void FireAndForget(System.Threading.WaitCallback callback, object obj, string context) 2620 public static void FireAndForget(System.Threading.WaitCallback callback, object obj, string context, bool dotimeout = true)
2173 { 2621 {
2174 Interlocked.Increment(ref numTotalThreadFuncsCalled); 2622 Interlocked.Increment(ref numTotalThreadFuncsCalled);
2175 2623/*
2176 if (context != null) 2624 if (context != null)
2177 { 2625 {
2178 if (!m_fireAndForgetCallsMade.ContainsKey(context)) 2626 if (!m_fireAndForgetCallsMade.ContainsKey(context))
@@ -2185,25 +2633,25 @@ namespace OpenSim.Framework
2185 else 2633 else
2186 m_fireAndForgetCallsInProgress[context]++; 2634 m_fireAndForgetCallsInProgress[context]++;
2187 } 2635 }
2188 2636*/
2189 WaitCallback realCallback; 2637 WaitCallback realCallback;
2190 2638
2191 bool loggingEnabled = LogThreadPool > 0; 2639 bool loggingEnabled = LogThreadPool > 0;
2192 2640
2193 long threadFuncNum = Interlocked.Increment(ref nextThreadFuncNum); 2641 long threadFuncNum = Interlocked.Increment(ref nextThreadFuncNum);
2194 ThreadInfo threadInfo = new ThreadInfo(threadFuncNum, context); 2642 ThreadInfo threadInfo = new ThreadInfo(threadFuncNum, context, dotimeout);
2195 2643
2196 if (FireAndForgetMethod == FireAndForgetMethod.RegressionTest) 2644 if (FireAndForgetMethod == FireAndForgetMethod.RegressionTest)
2197 { 2645 {
2198 // If we're running regression tests, then we want any exceptions to rise up to the test code. 2646 // If we're running regression tests, then we want any exceptions to rise up to the test code.
2199 realCallback = 2647 realCallback =
2200 o => 2648 o =>
2201 { 2649 {
2202 Culture.SetCurrentCulture(); 2650 Culture.SetCurrentCulture();
2203 callback(o); 2651 callback(o);
2204 2652
2205 if (context != null) 2653// if (context != null)
2206 m_fireAndForgetCallsInProgress[context]--; 2654// m_fireAndForgetCallsInProgress[context]--;
2207 }; 2655 };
2208 } 2656 }
2209 else 2657 else
@@ -2229,7 +2677,6 @@ namespace OpenSim.Framework
2229 } 2677 }
2230 catch (ThreadAbortException e) 2678 catch (ThreadAbortException e)
2231 { 2679 {
2232 m_log.Error(string.Format("Aborted threadfunc {0} ", threadFuncNum), e);
2233 } 2680 }
2234 catch (Exception e) 2681 catch (Exception e)
2235 { 2682 {
@@ -2244,8 +2691,8 @@ namespace OpenSim.Framework
2244 if ((loggingEnabled || (threadFuncOverloadMode == 1)) && threadInfo.LogThread) 2691 if ((loggingEnabled || (threadFuncOverloadMode == 1)) && threadInfo.LogThread)
2245 m_log.DebugFormat("Exit threadfunc {0} ({1})", threadFuncNum, FormatDuration(threadInfo.Elapsed())); 2692 m_log.DebugFormat("Exit threadfunc {0} ({1})", threadFuncNum, FormatDuration(threadInfo.Elapsed()));
2246 2693
2247 if (context != null) 2694// if (context != null)
2248 m_fireAndForgetCallsInProgress[context]--; 2695// m_fireAndForgetCallsInProgress[context]--;
2249 } 2696 }
2250 }; 2697 };
2251 } 2698 }
@@ -2253,6 +2700,7 @@ namespace OpenSim.Framework
2253 long numQueued = Interlocked.Increment(ref numQueuedThreadFuncs); 2700 long numQueued = Interlocked.Increment(ref numQueuedThreadFuncs);
2254 try 2701 try
2255 { 2702 {
2703/*
2256 long numRunning = numRunningThreadFuncs; 2704 long numRunning = numRunningThreadFuncs;
2257 2705
2258 if (m_ThreadPool != null && LogOverloads) 2706 if (m_ThreadPool != null && LogOverloads)
@@ -2285,6 +2733,7 @@ namespace OpenSim.Framework
2285 } 2733 }
2286 } 2734 }
2287 else 2735 else
2736*/
2288 { 2737 {
2289 // Since we didn't log "Queue threadfunc", don't log "Run threadfunc" or "End threadfunc" either. 2738 // Since we didn't log "Queue threadfunc", don't log "Run threadfunc" or "End threadfunc" either.
2290 // Those log lines aren't useful when we don't know which function is running in the thread. 2739 // Those log lines aren't useful when we don't know which function is running in the thread.
@@ -2342,7 +2791,7 @@ namespace OpenSim.Framework
2342 if (stackTrace.Contains("BeginFireQueueEmpty")) 2791 if (stackTrace.Contains("BeginFireQueueEmpty"))
2343 return false; 2792 return false;
2344 } 2793 }
2345 2794
2346 return true; 2795 return true;
2347 } 2796 }
2348 2797
@@ -2355,7 +2804,7 @@ namespace OpenSim.Framework
2355 { 2804 {
2356 string src = Environment.StackTrace; 2805 string src = Environment.StackTrace;
2357 string[] lines = src.Split(new string[] { Environment.NewLine }, StringSplitOptions.None); 2806 string[] lines = src.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
2358 2807
2359 StringBuilder dest = new StringBuilder(src.Length); 2808 StringBuilder dest = new StringBuilder(src.Length);
2360 2809
2361 bool started = false; 2810 bool started = false;
@@ -2400,11 +2849,11 @@ namespace OpenSim.Framework
2400 /// trace. And pausing another thread can cause a deadlock. This method attempts to 2849 /// trace. And pausing another thread can cause a deadlock. This method attempts to
2401 /// avoid deadlock by using a short timeout (200ms), after which it gives up and 2850 /// avoid deadlock by using a short timeout (200ms), after which it gives up and
2402 /// returns 'null' instead of the stack trace. 2851 /// returns 'null' instead of the stack trace.
2403 /// 2852 ///
2404 /// Take from: http://stackoverflow.com/a/14935378 2853 /// Take from: http://stackoverflow.com/a/14935378
2405 /// 2854 ///
2406 /// WARNING: this doesn't work in Mono. See https://bugzilla.novell.com/show_bug.cgi?id=571691 2855 /// WARNING: this doesn't work in Mono. See https://bugzilla.novell.com/show_bug.cgi?id=571691
2407 /// 2856 ///
2408 /// </remarks> 2857 /// </remarks>
2409 /// <returns>The stack trace, or null if failed to get it</returns> 2858 /// <returns>The stack trace, or null if failed to get it</returns>
2410 private static StackTrace GetStackTrace(Thread targetThread) 2859 private static StackTrace GetStackTrace(Thread targetThread)
@@ -2500,12 +2949,22 @@ namespace OpenSim.Framework
2500 return stpi; 2949 return stpi;
2501 } 2950 }
2502 2951
2952 public static void StopThreadPool()
2953 {
2954 if (m_ThreadPool == null)
2955 return;
2956 SmartThreadPool pool = m_ThreadPool;
2957 m_ThreadPool = null;
2958
2959 try { pool.Shutdown(); } catch {}
2960 }
2961
2503 #endregion FireAndForget Threading Pattern 2962 #endregion FireAndForget Threading Pattern
2504 2963
2505 /// <summary> 2964 /// <summary>
2506 /// Environment.TickCount is an int but it counts all 32 bits so it goes positive 2965 /// Environment.TickCount is an int but it counts all 32 bits so it goes positive
2507 /// and negative every 24.9 days. This trims down TickCount so it doesn't wrap 2966 /// and negative every 24.9 days. This trims down TickCount so it doesn't wrap
2508 /// for the callers. 2967 /// for the callers.
2509 /// This trims it to a 12 day interval so don't let your frame time get too long. 2968 /// This trims it to a 12 day interval so don't let your frame time get too long.
2510 /// </summary> 2969 /// </summary>
2511 /// <returns></returns> 2970 /// <returns></returns>
@@ -2513,6 +2972,7 @@ namespace OpenSim.Framework
2513 { 2972 {
2514 return Environment.TickCount & EnvironmentTickCountMask; 2973 return Environment.TickCount & EnvironmentTickCountMask;
2515 } 2974 }
2975
2516 const Int32 EnvironmentTickCountMask = 0x3fffffff; 2976 const Int32 EnvironmentTickCountMask = 0x3fffffff;
2517 2977
2518 /// <summary> 2978 /// <summary>
@@ -2557,6 +3017,18 @@ namespace OpenSim.Framework
2557 return tcA - tcB; 3017 return tcA - tcB;
2558 } 3018 }
2559 3019
3020 // returns a timestamp in ms as double
3021 // using the time resolution avaiable to StopWatch
3022 public static double GetTimeStamp()
3023 {
3024 return (double)Stopwatch.GetTimestamp() * TimeStampClockPeriod;
3025 }
3026
3027 public static double GetTimeStampMS()
3028 {
3029 return (double)Stopwatch.GetTimestamp() * TimeStampClockPeriodMS;
3030 }
3031
2560 /// <summary> 3032 /// <summary>
2561 /// Formats a duration (given in milliseconds). 3033 /// Formats a duration (given in milliseconds).
2562 /// </summary> 3034 /// </summary>
@@ -2855,7 +3327,7 @@ namespace OpenSim.Framework
2855 if (parts.Length == 2) 3327 if (parts.Length == 2)
2856 return CalcUniversalIdentifier(id, agentsURI, parts[0] + " " + parts[1]); 3328 return CalcUniversalIdentifier(id, agentsURI, parts[0] + " " + parts[1]);
2857 } 3329 }
2858 3330
2859 return CalcUniversalIdentifier(id, agentsURI, firstName + " " + lastName); 3331 return CalcUniversalIdentifier(id, agentsURI, firstName + " " + lastName);
2860 } 3332 }
2861 3333
@@ -2940,6 +3412,7 @@ namespace OpenSim.Framework
2940 3412
2941 } 3413 }
2942 3414
3415/* don't like this code
2943 public class DoubleQueue<T> where T:class 3416 public class DoubleQueue<T> where T:class
2944 { 3417 {
2945 private Queue<T> m_lowQueue = new Queue<T>(); 3418 private Queue<T> m_lowQueue = new Queue<T>();
@@ -2954,10 +3427,10 @@ namespace OpenSim.Framework
2954 3427
2955 public virtual int Count 3428 public virtual int Count
2956 { 3429 {
2957 get 3430 get
2958 { 3431 {
2959 lock (m_syncRoot) 3432 lock (m_syncRoot)
2960 return m_highQueue.Count + m_lowQueue.Count; 3433 return m_highQueue.Count + m_lowQueue.Count;
2961 } 3434 }
2962 } 3435 }
2963 3436
@@ -3051,7 +3524,7 @@ namespace OpenSim.Framework
3051 } 3524 }
3052 } 3525 }
3053 } 3526 }
3054 3527*/
3055 public class BetterRandom 3528 public class BetterRandom
3056 { 3529 {
3057 private const int BufferSize = 1024; // must be a multiple of 4 3530 private const int BufferSize = 1024; // must be a multiple of 4