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.cs192
1 files changed, 110 insertions, 82 deletions
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index 557f38e..1775fef 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -89,9 +89,30 @@ namespace OpenSim.Framework
89 } 89 }
90 90
91 /// <summary> 91 /// <summary>
92 /// Class for delivering SmartThreadPool statistical information
93 /// </summary>
94 /// <remarks>
95 /// We do it this way so that we do not directly expose STP.
96 /// </remarks>
97 public class STPInfo
98 {
99 public string Name { get; set; }
100 public STPStartInfo STPStartInfo { get; set; }
101 public WIGStartInfo WIGStartInfo { get; set; }
102 public bool IsIdle { get; set; }
103 public bool IsShuttingDown { get; set; }
104 public int MaxThreads { get; set; }
105 public int MinThreads { get; set; }
106 public int InUseThreads { get; set; }
107 public int ActiveThreads { get; set; }
108 public int WaitingCallbacks { get; set; }
109 public int MaxConcurrentWorkItems { get; set; }
110 }
111
112 /// <summary>
92 /// Miscellaneous utility functions 113 /// Miscellaneous utility functions
93 /// </summary> 114 /// </summary>
94 public class Util 115 public static class Util
95 { 116 {
96 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 117 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
97 118
@@ -109,7 +130,7 @@ namespace OpenSim.Framework
109 private static SmartThreadPool m_ThreadPool; 130 private static SmartThreadPool m_ThreadPool;
110 131
111 // Unix-epoch starts at January 1st 1970, 00:00:00 UTC. And all our times in the server are (or at least should be) in UTC. 132 // Unix-epoch starts at January 1st 1970, 00:00:00 UTC. And all our times in the server are (or at least should be) in UTC.
112 private static readonly DateTime unixEpoch = 133 public static readonly DateTime UnixEpoch =
113 DateTime.ParseExact("1970-01-01 00:00:00 +0", "yyyy-MM-dd hh:mm:ss z", DateTimeFormatInfo.InvariantInfo).ToUniversalTime(); 134 DateTime.ParseExact("1970-01-01 00:00:00 +0", "yyyy-MM-dd hh:mm:ss z", DateTimeFormatInfo.InvariantInfo).ToUniversalTime();
114 135
115 private static readonly string rawUUIDPattern 136 private static readonly string rawUUIDPattern
@@ -120,6 +141,11 @@ namespace OpenSim.Framework
120 public static FireAndForgetMethod DefaultFireAndForgetMethod = FireAndForgetMethod.SmartThreadPool; 141 public static FireAndForgetMethod DefaultFireAndForgetMethod = FireAndForgetMethod.SmartThreadPool;
121 public static FireAndForgetMethod FireAndForgetMethod = DefaultFireAndForgetMethod; 142 public static FireAndForgetMethod FireAndForgetMethod = DefaultFireAndForgetMethod;
122 143
144 public static bool IsPlatformMono
145 {
146 get { return Type.GetType("Mono.Runtime") != null; }
147 }
148
123 /// <summary> 149 /// <summary>
124 /// Gets the name of the directory where the current running executable 150 /// Gets the name of the directory where the current running executable
125 /// is located 151 /// is located
@@ -307,6 +333,49 @@ namespace OpenSim.Framework
307 return Utils.UIntsToLong(X, Y); 333 return Utils.UIntsToLong(X, Y);
308 } 334 }
309 335
336 // Regions are identified with a 'handle' made up of its region coordinates packed into a ulong.
337 // Several places rely on the ability to extract a region's location from its handle.
338 // Note the location is in 'world coordinates' (see below).
339 // Region handles are based on the lowest coordinate of the region so trim the passed x,y to be the regions 0,0.
340 public static ulong RegionWorldLocToHandle(uint X, uint Y)
341 {
342 return Utils.UIntsToLong(X, Y);
343 }
344
345 public static ulong RegionLocToHandle(uint X, uint Y)
346 {
347 return Utils.UIntsToLong(Util.RegionToWorldLoc(X), Util.RegionToWorldLoc(Y));
348 }
349
350 public static void RegionHandleToWorldLoc(ulong handle, out uint X, out uint Y)
351 {
352 X = (uint)(handle >> 32);
353 Y = (uint)(handle & (ulong)uint.MaxValue);
354 }
355
356 public static void RegionHandleToRegionLoc(ulong handle, out uint X, out uint Y)
357 {
358 uint worldX, worldY;
359 RegionHandleToWorldLoc(handle, out worldX, out worldY);
360 X = WorldToRegionLoc(worldX);
361 Y = WorldToRegionLoc(worldY);
362 }
363
364 // A region location can be 'world coordinates' (meters from zero) or 'region coordinates'
365 // (number of regions from zero). This measurement of regions relies on the legacy 256 region size.
366 // These routines exist to make what is being converted explicit so the next person knows what was meant.
367 // Convert a region's 'world coordinate' to its 'region coordinate'.
368 public static uint WorldToRegionLoc(uint worldCoord)
369 {
370 return worldCoord / Constants.RegionSize;
371 }
372
373 // Convert a region's 'region coordinate' to its 'world coordinate'.
374 public static uint RegionToWorldLoc(uint regionCoord)
375 {
376 return regionCoord * Constants.RegionSize;
377 }
378
310 public static T Clamp<T>(T x, T min, T max) 379 public static T Clamp<T>(T x, T min, T max)
311 where T : IComparable<T> 380 where T : IComparable<T>
312 { 381 {
@@ -495,20 +564,18 @@ namespace OpenSim.Framework
495 564
496 public static int ToUnixTime(DateTime stamp) 565 public static int ToUnixTime(DateTime stamp)
497 { 566 {
498 TimeSpan t = stamp.ToUniversalTime() - unixEpoch; 567 TimeSpan t = stamp.ToUniversalTime() - UnixEpoch;
499 return (int) t.TotalSeconds; 568 return (int)t.TotalSeconds;
500 } 569 }
501 570
502 public static DateTime ToDateTime(ulong seconds) 571 public static DateTime ToDateTime(ulong seconds)
503 { 572 {
504 DateTime epoch = unixEpoch; 573 return UnixEpoch.AddSeconds(seconds);
505 return epoch.AddSeconds(seconds);
506 } 574 }
507 575
508 public static DateTime ToDateTime(int seconds) 576 public static DateTime ToDateTime(int seconds)
509 { 577 {
510 DateTime epoch = unixEpoch; 578 return UnixEpoch.AddSeconds(seconds);
511 return epoch.AddSeconds(seconds);
512 } 579 }
513 580
514 /// <summary> 581 /// <summary>
@@ -976,7 +1043,7 @@ namespace OpenSim.Framework
976 else if (typeof(T) == typeof(Int32)) 1043 else if (typeof(T) == typeof(Int32))
977 val = cnf.GetInt(varname, (int)val); 1044 val = cnf.GetInt(varname, (int)val);
978 else if (typeof(T) == typeof(float)) 1045 else if (typeof(T) == typeof(float))
979 val = cnf.GetFloat(varname, (int)val); 1046 val = cnf.GetFloat(varname, (float)val);
980 else 1047 else
981 m_log.ErrorFormat("[UTIL]: Unhandled type {0}", typeof(T)); 1048 m_log.ErrorFormat("[UTIL]: Unhandled type {0}", typeof(T));
982 } 1049 }
@@ -1233,7 +1300,7 @@ namespace OpenSim.Framework
1233 byte[] bytes = 1300 byte[] bytes =
1234 { 1301 {
1235 (byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24), 1302 (byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24),
1236 (byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle << 56), 1303 (byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle >> 56),
1237 (byte)x, (byte)(x >> 8), 0, 0, 1304 (byte)x, (byte)(x >> 8), 0, 0,
1238 (byte)y, (byte)(y >> 8), 0, 0 }; 1305 (byte)y, (byte)(y >> 8), 0, 0 };
1239 return new UUID(bytes, 0); 1306 return new UUID(bytes, 0);
@@ -1244,7 +1311,7 @@ namespace OpenSim.Framework
1244 byte[] bytes = 1311 byte[] bytes =
1245 { 1312 {
1246 (byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24), 1313 (byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24),
1247 (byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle << 56), 1314 (byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle >> 56),
1248 (byte)x, (byte)(x >> 8), (byte)z, (byte)(z >> 8), 1315 (byte)x, (byte)(x >> 8), (byte)z, (byte)(z >> 8),
1249 (byte)y, (byte)(y >> 8), 0, 0 }; 1316 (byte)y, (byte)(y >> 8), 0, 0 };
1250 return new UUID(bytes, 0); 1317 return new UUID(bytes, 0);
@@ -1317,7 +1384,7 @@ namespace OpenSim.Framework
1317 ru = "OSX/Mono"; 1384 ru = "OSX/Mono";
1318 else 1385 else
1319 { 1386 {
1320 if (Type.GetType("Mono.Runtime") != null) 1387 if (IsPlatformMono)
1321 ru = "Win/Mono"; 1388 ru = "Win/Mono";
1322 else 1389 else
1323 ru = "Win/.NET"; 1390 ru = "Win/.NET";
@@ -1765,10 +1832,12 @@ namespace OpenSim.Framework
1765 FireAndForget(callback, null); 1832 FireAndForget(callback, null);
1766 } 1833 }
1767 1834
1768 public static void InitThreadPool(int maxThreads) 1835 public static void InitThreadPool(int minThreads, int maxThreads)
1769 { 1836 {
1770 if (maxThreads < 2) 1837 if (maxThreads < 2)
1771 throw new ArgumentOutOfRangeException("maxThreads", "maxThreads must be greater than 2"); 1838 throw new ArgumentOutOfRangeException("maxThreads", "maxThreads must be greater than 2");
1839 if (minThreads > maxThreads || minThreads < 2)
1840 throw new ArgumentOutOfRangeException("minThreads", "minThreads must be greater than 2 and less than or equal to maxThreads");
1772 if (m_ThreadPool != null) 1841 if (m_ThreadPool != null)
1773 throw new InvalidOperationException("SmartThreadPool is already initialized"); 1842 throw new InvalidOperationException("SmartThreadPool is already initialized");
1774 1843
@@ -1776,7 +1845,7 @@ namespace OpenSim.Framework
1776 startInfo.ThreadPoolName = "Util"; 1845 startInfo.ThreadPoolName = "Util";
1777 startInfo.IdleTimeout = 2000; 1846 startInfo.IdleTimeout = 2000;
1778 startInfo.MaxWorkerThreads = maxThreads; 1847 startInfo.MaxWorkerThreads = maxThreads;
1779 startInfo.MinWorkerThreads = 2; 1848 startInfo.MinWorkerThreads = minThreads;
1780 1849
1781 m_ThreadPool = new SmartThreadPool(startInfo); 1850 m_ThreadPool = new SmartThreadPool(startInfo);
1782 } 1851 }
@@ -1851,8 +1920,8 @@ namespace OpenSim.Framework
1851 break; 1920 break;
1852 case FireAndForgetMethod.SmartThreadPool: 1921 case FireAndForgetMethod.SmartThreadPool:
1853 if (m_ThreadPool == null) 1922 if (m_ThreadPool == null)
1854 InitThreadPool(15); 1923 InitThreadPool(2, 15);
1855 m_ThreadPool.QueueWorkItem(SmartThreadPoolCallback, new object[] { realCallback, obj }); 1924 m_ThreadPool.QueueWorkItem((cb, o) => cb(o), realCallback, obj);
1856 break; 1925 break;
1857 case FireAndForgetMethod.Thread: 1926 case FireAndForgetMethod.Thread:
1858 Thread thread = new Thread(delegate(object o) { realCallback(o); }); 1927 Thread thread = new Thread(delegate(object o) { realCallback(o); });
@@ -1864,72 +1933,29 @@ namespace OpenSim.Framework
1864 } 1933 }
1865 1934
1866 /// <summary> 1935 /// <summary>
1867 /// Get a thread pool report. 1936 /// Get information about the current state of the smart thread pool.
1868 /// </summary> 1937 /// </summary>
1869 /// <returns></returns> 1938 /// <returns>
1870 public static string GetThreadPoolReport() 1939 /// null if this isn't the pool being used for non-scriptengine threads.
1940 /// </returns>
1941 public static STPInfo GetSmartThreadPoolInfo()
1871 { 1942 {
1872 string threadPoolUsed = null; 1943 if (m_ThreadPool == null)
1873 int maxThreads = 0; 1944 return null;
1874 int minThreads = 0;
1875 int allocatedThreads = 0;
1876 int inUseThreads = 0;
1877 int waitingCallbacks = 0;
1878 int completionPortThreads = 0;
1879
1880 StringBuilder sb = new StringBuilder();
1881 if (FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
1882 {
1883 // ROBUST currently leaves this the FireAndForgetMethod but never actually initializes the threadpool.
1884 if (m_ThreadPool != null)
1885 {
1886 threadPoolUsed = "SmartThreadPool";
1887 maxThreads = m_ThreadPool.MaxThreads;
1888 minThreads = m_ThreadPool.MinThreads;
1889 inUseThreads = m_ThreadPool.InUseThreads;
1890 allocatedThreads = m_ThreadPool.ActiveThreads;
1891 waitingCallbacks = m_ThreadPool.WaitingCallbacks;
1892 }
1893 }
1894 else if (
1895 FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem
1896 || FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem)
1897 {
1898 threadPoolUsed = "BuiltInThreadPool";
1899 ThreadPool.GetMaxThreads(out maxThreads, out completionPortThreads);
1900 ThreadPool.GetMinThreads(out minThreads, out completionPortThreads);
1901 int availableThreads;
1902 ThreadPool.GetAvailableThreads(out availableThreads, out completionPortThreads);
1903 inUseThreads = maxThreads - availableThreads;
1904 allocatedThreads = -1;
1905 waitingCallbacks = -1;
1906 }
1907
1908 if (threadPoolUsed != null)
1909 {
1910 sb.AppendFormat("Thread pool used : {0}\n", threadPoolUsed);
1911 sb.AppendFormat("Max threads : {0}\n", maxThreads);
1912 sb.AppendFormat("Min threads : {0}\n", minThreads);
1913 sb.AppendFormat("Allocated threads : {0}\n", allocatedThreads < 0 ? "not applicable" : allocatedThreads.ToString());
1914 sb.AppendFormat("In use threads : {0}\n", inUseThreads);
1915 sb.AppendFormat("Work items waiting : {0}\n", waitingCallbacks < 0 ? "not available" : waitingCallbacks.ToString());
1916 }
1917 else
1918 {
1919 sb.AppendFormat("Thread pool not used\n");
1920 }
1921
1922 return sb.ToString();
1923 }
1924 1945
1925 private static object SmartThreadPoolCallback(object o) 1946 STPInfo stpi = new STPInfo();
1926 { 1947 stpi.Name = m_ThreadPool.Name;
1927 object[] array = (object[])o; 1948 stpi.STPStartInfo = m_ThreadPool.STPStartInfo;
1928 WaitCallback callback = (WaitCallback)array[0]; 1949 stpi.IsIdle = m_ThreadPool.IsIdle;
1929 object obj = array[1]; 1950 stpi.IsShuttingDown = m_ThreadPool.IsShuttingdown;
1951 stpi.MaxThreads = m_ThreadPool.MaxThreads;
1952 stpi.MinThreads = m_ThreadPool.MinThreads;
1953 stpi.InUseThreads = m_ThreadPool.InUseThreads;
1954 stpi.ActiveThreads = m_ThreadPool.ActiveThreads;
1955 stpi.WaitingCallbacks = m_ThreadPool.WaitingCallbacks;
1956 stpi.MaxConcurrentWorkItems = m_ThreadPool.Concurrency;
1930 1957
1931 callback(obj); 1958 return stpi;
1932 return null;
1933 } 1959 }
1934 1960
1935 #endregion FireAndForget Threading Pattern 1961 #endregion FireAndForget Threading Pattern
@@ -2058,8 +2084,10 @@ namespace OpenSim.Framework
2058 #region Xml Serialization Utilities 2084 #region Xml Serialization Utilities
2059 public static bool ReadBoolean(XmlTextReader reader) 2085 public static bool ReadBoolean(XmlTextReader reader)
2060 { 2086 {
2087 // AuroraSim uses "int" for some fields that are boolean in OpenSim, e.g. "PassCollisions". Don't fail because of this.
2061 reader.ReadStartElement(); 2088 reader.ReadStartElement();
2062 bool result = Boolean.Parse(reader.ReadContentAsString().ToLower()); 2089 string val = reader.ReadContentAsString().ToLower();
2090 bool result = val.Equals("true") || val.Equals("1");
2063 reader.ReadEndElement(); 2091 reader.ReadEndElement();
2064 2092
2065 return result; 2093 return result;
@@ -2148,7 +2176,7 @@ namespace OpenSim.Framework
2148 /// <param name="secret">the secret part</param> 2176 /// <param name="secret">the secret part</param>
2149 public static bool ParseUniversalUserIdentifier(string value, out UUID uuid, out string url, out string firstname, out string lastname, out string secret) 2177 public static bool ParseUniversalUserIdentifier(string value, out UUID uuid, out string url, out string firstname, out string lastname, out string secret)
2150 { 2178 {
2151 uuid = UUID.Zero; url = string.Empty; firstname = "Unknown"; lastname = "User"; secret = string.Empty; 2179 uuid = UUID.Zero; url = string.Empty; firstname = "Unknown"; lastname = "UserUPUUI"; secret = string.Empty;
2152 2180
2153 string[] parts = value.Split(';'); 2181 string[] parts = value.Split(';');
2154 if (parts.Length >= 1) 2182 if (parts.Length >= 1)
@@ -2282,7 +2310,7 @@ namespace OpenSim.Framework
2282 { 2310 {
2283 lock (m_syncRoot) 2311 lock (m_syncRoot)
2284 { 2312 {
2285 m_lowQueue.Enqueue(data); 2313 q.Enqueue(data);
2286 m_s.WaitOne(0); 2314 m_s.WaitOne(0);
2287 m_s.Release(); 2315 m_s.Release();
2288 } 2316 }
@@ -2322,7 +2350,7 @@ namespace OpenSim.Framework
2322 { 2350 {
2323 if (m_highQueue.Count > 0) 2351 if (m_highQueue.Count > 0)
2324 res = m_highQueue.Dequeue(); 2352 res = m_highQueue.Dequeue();
2325 else 2353 else if (m_lowQueue.Count > 0)
2326 res = m_lowQueue.Dequeue(); 2354 res = m_lowQueue.Dequeue();
2327 2355
2328 if (m_highQueue.Count == 0 && m_lowQueue.Count == 0) 2356 if (m_highQueue.Count == 0 && m_lowQueue.Count == 0)