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.cs211
1 files changed, 123 insertions, 88 deletions
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index 557f38e..b8b78fa 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -58,6 +58,15 @@ namespace OpenSim.Framework
58 public enum PermissionMask : uint 58 public enum PermissionMask : uint
59 { 59 {
60 None = 0, 60 None = 0,
61
62 // folded perms
63 foldedTransfer = 1,
64 foldedModify = 1 << 1,
65 foldedCopy = 1 << 2,
66
67 foldedMask = 0x07,
68
69 //
61 Transfer = 1 << 13, 70 Transfer = 1 << 13,
62 Modify = 1 << 14, 71 Modify = 1 << 14,
63 Copy = 1 << 15, 72 Copy = 1 << 15,
@@ -89,9 +98,30 @@ namespace OpenSim.Framework
89 } 98 }
90 99
91 /// <summary> 100 /// <summary>
101 /// Class for delivering SmartThreadPool statistical information
102 /// </summary>
103 /// <remarks>
104 /// We do it this way so that we do not directly expose STP.
105 /// </remarks>
106 public class STPInfo
107 {
108 public string Name { get; set; }
109 public STPStartInfo STPStartInfo { get; set; }
110 public WIGStartInfo WIGStartInfo { get; set; }
111 public bool IsIdle { get; set; }
112 public bool IsShuttingDown { get; set; }
113 public int MaxThreads { get; set; }
114 public int MinThreads { get; set; }
115 public int InUseThreads { get; set; }
116 public int ActiveThreads { get; set; }
117 public int WaitingCallbacks { get; set; }
118 public int MaxConcurrentWorkItems { get; set; }
119 }
120
121 /// <summary>
92 /// Miscellaneous utility functions 122 /// Miscellaneous utility functions
93 /// </summary> 123 /// </summary>
94 public class Util 124 public static class Util
95 { 125 {
96 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 126 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
97 127
@@ -109,7 +139,7 @@ namespace OpenSim.Framework
109 private static SmartThreadPool m_ThreadPool; 139 private static SmartThreadPool m_ThreadPool;
110 140
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. 141 // 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 = 142 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(); 143 DateTime.ParseExact("1970-01-01 00:00:00 +0", "yyyy-MM-dd hh:mm:ss z", DateTimeFormatInfo.InvariantInfo).ToUniversalTime();
114 144
115 private static readonly string rawUUIDPattern 145 private static readonly string rawUUIDPattern
@@ -120,6 +150,11 @@ namespace OpenSim.Framework
120 public static FireAndForgetMethod DefaultFireAndForgetMethod = FireAndForgetMethod.SmartThreadPool; 150 public static FireAndForgetMethod DefaultFireAndForgetMethod = FireAndForgetMethod.SmartThreadPool;
121 public static FireAndForgetMethod FireAndForgetMethod = DefaultFireAndForgetMethod; 151 public static FireAndForgetMethod FireAndForgetMethod = DefaultFireAndForgetMethod;
122 152
153 public static bool IsPlatformMono
154 {
155 get { return Type.GetType("Mono.Runtime") != null; }
156 }
157
123 /// <summary> 158 /// <summary>
124 /// Gets the name of the directory where the current running executable 159 /// Gets the name of the directory where the current running executable
125 /// is located 160 /// is located
@@ -217,14 +252,12 @@ namespace OpenSim.Framework
217 /// </summary> 252 /// </summary>
218 /// <param name="a">A 3d vector</param> 253 /// <param name="a">A 3d vector</param>
219 /// <returns>A new vector which is normalized form of the vector</returns> 254 /// <returns>A new vector which is normalized form of the vector</returns>
220 /// <remarks>The vector paramater cannot be <0,0,0></remarks> 255
221 public static Vector3 GetNormalizedVector(Vector3 a) 256 public static Vector3 GetNormalizedVector(Vector3 a)
222 { 257 {
223 if (IsZeroVector(a)) 258 Vector3 v = new Vector3(a.X, a.Y, a.Z);
224 throw new ArgumentException("Vector paramater cannot be a zero vector."); 259 v.Normalize();
225 260 return v;
226 float Mag = (float) GetMagnitude(a);
227 return new Vector3(a.X / Mag, a.Y / Mag, a.Z / Mag);
228 } 261 }
229 262
230 /// <summary> 263 /// <summary>
@@ -307,6 +340,49 @@ namespace OpenSim.Framework
307 return Utils.UIntsToLong(X, Y); 340 return Utils.UIntsToLong(X, Y);
308 } 341 }
309 342
343 // Regions are identified with a 'handle' made up of its region coordinates packed into a ulong.
344 // Several places rely on the ability to extract a region's location from its handle.
345 // Note the location is in 'world coordinates' (see below).
346 // Region handles are based on the lowest coordinate of the region so trim the passed x,y to be the regions 0,0.
347 public static ulong RegionWorldLocToHandle(uint X, uint Y)
348 {
349 return Utils.UIntsToLong(X, Y);
350 }
351
352 public static ulong RegionLocToHandle(uint X, uint Y)
353 {
354 return Utils.UIntsToLong(Util.RegionToWorldLoc(X), Util.RegionToWorldLoc(Y));
355 }
356
357 public static void RegionHandleToWorldLoc(ulong handle, out uint X, out uint Y)
358 {
359 X = (uint)(handle >> 32);
360 Y = (uint)(handle & (ulong)uint.MaxValue);
361 }
362
363 public static void RegionHandleToRegionLoc(ulong handle, out uint X, out uint Y)
364 {
365 uint worldX, worldY;
366 RegionHandleToWorldLoc(handle, out worldX, out worldY);
367 X = WorldToRegionLoc(worldX);
368 Y = WorldToRegionLoc(worldY);
369 }
370
371 // A region location can be 'world coordinates' (meters from zero) or 'region coordinates'
372 // (number of regions from zero). This measurement of regions relies on the legacy 256 region size.
373 // These routines exist to make what is being converted explicit so the next person knows what was meant.
374 // Convert a region's 'world coordinate' to its 'region coordinate'.
375 public static uint WorldToRegionLoc(uint worldCoord)
376 {
377 return worldCoord / Constants.RegionSize;
378 }
379
380 // Convert a region's 'region coordinate' to its 'world coordinate'.
381 public static uint RegionToWorldLoc(uint regionCoord)
382 {
383 return regionCoord * Constants.RegionSize;
384 }
385
310 public static T Clamp<T>(T x, T min, T max) 386 public static T Clamp<T>(T x, T min, T max)
311 where T : IComparable<T> 387 where T : IComparable<T>
312 { 388 {
@@ -495,20 +571,18 @@ namespace OpenSim.Framework
495 571
496 public static int ToUnixTime(DateTime stamp) 572 public static int ToUnixTime(DateTime stamp)
497 { 573 {
498 TimeSpan t = stamp.ToUniversalTime() - unixEpoch; 574 TimeSpan t = stamp.ToUniversalTime() - UnixEpoch;
499 return (int) t.TotalSeconds; 575 return (int)t.TotalSeconds;
500 } 576 }
501 577
502 public static DateTime ToDateTime(ulong seconds) 578 public static DateTime ToDateTime(ulong seconds)
503 { 579 {
504 DateTime epoch = unixEpoch; 580 return UnixEpoch.AddSeconds(seconds);
505 return epoch.AddSeconds(seconds);
506 } 581 }
507 582
508 public static DateTime ToDateTime(int seconds) 583 public static DateTime ToDateTime(int seconds)
509 { 584 {
510 DateTime epoch = unixEpoch; 585 return UnixEpoch.AddSeconds(seconds);
511 return epoch.AddSeconds(seconds);
512 } 586 }
513 587
514 /// <summary> 588 /// <summary>
@@ -976,7 +1050,7 @@ namespace OpenSim.Framework
976 else if (typeof(T) == typeof(Int32)) 1050 else if (typeof(T) == typeof(Int32))
977 val = cnf.GetInt(varname, (int)val); 1051 val = cnf.GetInt(varname, (int)val);
978 else if (typeof(T) == typeof(float)) 1052 else if (typeof(T) == typeof(float))
979 val = cnf.GetFloat(varname, (int)val); 1053 val = cnf.GetFloat(varname, (float)val);
980 else 1054 else
981 m_log.ErrorFormat("[UTIL]: Unhandled type {0}", typeof(T)); 1055 m_log.ErrorFormat("[UTIL]: Unhandled type {0}", typeof(T));
982 } 1056 }
@@ -1233,7 +1307,7 @@ namespace OpenSim.Framework
1233 byte[] bytes = 1307 byte[] bytes =
1234 { 1308 {
1235 (byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24), 1309 (byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24),
1236 (byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle << 56), 1310 (byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle >> 56),
1237 (byte)x, (byte)(x >> 8), 0, 0, 1311 (byte)x, (byte)(x >> 8), 0, 0,
1238 (byte)y, (byte)(y >> 8), 0, 0 }; 1312 (byte)y, (byte)(y >> 8), 0, 0 };
1239 return new UUID(bytes, 0); 1313 return new UUID(bytes, 0);
@@ -1244,7 +1318,7 @@ namespace OpenSim.Framework
1244 byte[] bytes = 1318 byte[] bytes =
1245 { 1319 {
1246 (byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24), 1320 (byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24),
1247 (byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle << 56), 1321 (byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle >> 56),
1248 (byte)x, (byte)(x >> 8), (byte)z, (byte)(z >> 8), 1322 (byte)x, (byte)(x >> 8), (byte)z, (byte)(z >> 8),
1249 (byte)y, (byte)(y >> 8), 0, 0 }; 1323 (byte)y, (byte)(y >> 8), 0, 0 };
1250 return new UUID(bytes, 0); 1324 return new UUID(bytes, 0);
@@ -1317,7 +1391,7 @@ namespace OpenSim.Framework
1317 ru = "OSX/Mono"; 1391 ru = "OSX/Mono";
1318 else 1392 else
1319 { 1393 {
1320 if (Type.GetType("Mono.Runtime") != null) 1394 if (IsPlatformMono)
1321 ru = "Win/Mono"; 1395 ru = "Win/Mono";
1322 else 1396 else
1323 ru = "Win/.NET"; 1397 ru = "Win/.NET";
@@ -1765,10 +1839,12 @@ namespace OpenSim.Framework
1765 FireAndForget(callback, null); 1839 FireAndForget(callback, null);
1766 } 1840 }
1767 1841
1768 public static void InitThreadPool(int maxThreads) 1842 public static void InitThreadPool(int minThreads, int maxThreads)
1769 { 1843 {
1770 if (maxThreads < 2) 1844 if (maxThreads < 2)
1771 throw new ArgumentOutOfRangeException("maxThreads", "maxThreads must be greater than 2"); 1845 throw new ArgumentOutOfRangeException("maxThreads", "maxThreads must be greater than 2");
1846 if (minThreads > maxThreads || minThreads < 2)
1847 throw new ArgumentOutOfRangeException("minThreads", "minThreads must be greater than 2 and less than or equal to maxThreads");
1772 if (m_ThreadPool != null) 1848 if (m_ThreadPool != null)
1773 throw new InvalidOperationException("SmartThreadPool is already initialized"); 1849 throw new InvalidOperationException("SmartThreadPool is already initialized");
1774 1850
@@ -1776,7 +1852,7 @@ namespace OpenSim.Framework
1776 startInfo.ThreadPoolName = "Util"; 1852 startInfo.ThreadPoolName = "Util";
1777 startInfo.IdleTimeout = 2000; 1853 startInfo.IdleTimeout = 2000;
1778 startInfo.MaxWorkerThreads = maxThreads; 1854 startInfo.MaxWorkerThreads = maxThreads;
1779 startInfo.MinWorkerThreads = 2; 1855 startInfo.MinWorkerThreads = minThreads;
1780 1856
1781 m_ThreadPool = new SmartThreadPool(startInfo); 1857 m_ThreadPool = new SmartThreadPool(startInfo);
1782 } 1858 }
@@ -1851,8 +1927,8 @@ namespace OpenSim.Framework
1851 break; 1927 break;
1852 case FireAndForgetMethod.SmartThreadPool: 1928 case FireAndForgetMethod.SmartThreadPool:
1853 if (m_ThreadPool == null) 1929 if (m_ThreadPool == null)
1854 InitThreadPool(15); 1930 InitThreadPool(2, 15);
1855 m_ThreadPool.QueueWorkItem(SmartThreadPoolCallback, new object[] { realCallback, obj }); 1931 m_ThreadPool.QueueWorkItem((cb, o) => cb(o), realCallback, obj);
1856 break; 1932 break;
1857 case FireAndForgetMethod.Thread: 1933 case FireAndForgetMethod.Thread:
1858 Thread thread = new Thread(delegate(object o) { realCallback(o); }); 1934 Thread thread = new Thread(delegate(object o) { realCallback(o); });
@@ -1864,72 +1940,29 @@ namespace OpenSim.Framework
1864 } 1940 }
1865 1941
1866 /// <summary> 1942 /// <summary>
1867 /// Get a thread pool report. 1943 /// Get information about the current state of the smart thread pool.
1868 /// </summary> 1944 /// </summary>
1869 /// <returns></returns> 1945 /// <returns>
1870 public static string GetThreadPoolReport() 1946 /// null if this isn't the pool being used for non-scriptengine threads.
1947 /// </returns>
1948 public static STPInfo GetSmartThreadPoolInfo()
1871 { 1949 {
1872 string threadPoolUsed = null; 1950 if (m_ThreadPool == null)
1873 int maxThreads = 0; 1951 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 1952
1922 return sb.ToString(); 1953 STPInfo stpi = new STPInfo();
1923 } 1954 stpi.Name = m_ThreadPool.Name;
1955 stpi.STPStartInfo = m_ThreadPool.STPStartInfo;
1956 stpi.IsIdle = m_ThreadPool.IsIdle;
1957 stpi.IsShuttingDown = m_ThreadPool.IsShuttingdown;
1958 stpi.MaxThreads = m_ThreadPool.MaxThreads;
1959 stpi.MinThreads = m_ThreadPool.MinThreads;
1960 stpi.InUseThreads = m_ThreadPool.InUseThreads;
1961 stpi.ActiveThreads = m_ThreadPool.ActiveThreads;
1962 stpi.WaitingCallbacks = m_ThreadPool.WaitingCallbacks;
1963 stpi.MaxConcurrentWorkItems = m_ThreadPool.Concurrency;
1924 1964
1925 private static object SmartThreadPoolCallback(object o) 1965 return stpi;
1926 {
1927 object[] array = (object[])o;
1928 WaitCallback callback = (WaitCallback)array[0];
1929 object obj = array[1];
1930
1931 callback(obj);
1932 return null;
1933 } 1966 }
1934 1967
1935 #endregion FireAndForget Threading Pattern 1968 #endregion FireAndForget Threading Pattern
@@ -2058,8 +2091,10 @@ namespace OpenSim.Framework
2058 #region Xml Serialization Utilities 2091 #region Xml Serialization Utilities
2059 public static bool ReadBoolean(XmlTextReader reader) 2092 public static bool ReadBoolean(XmlTextReader reader)
2060 { 2093 {
2094 // AuroraSim uses "int" for some fields that are boolean in OpenSim, e.g. "PassCollisions". Don't fail because of this.
2061 reader.ReadStartElement(); 2095 reader.ReadStartElement();
2062 bool result = Boolean.Parse(reader.ReadContentAsString().ToLower()); 2096 string val = reader.ReadContentAsString().ToLower();
2097 bool result = val.Equals("true") || val.Equals("1");
2063 reader.ReadEndElement(); 2098 reader.ReadEndElement();
2064 2099
2065 return result; 2100 return result;
@@ -2148,7 +2183,7 @@ namespace OpenSim.Framework
2148 /// <param name="secret">the secret part</param> 2183 /// <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) 2184 public static bool ParseUniversalUserIdentifier(string value, out UUID uuid, out string url, out string firstname, out string lastname, out string secret)
2150 { 2185 {
2151 uuid = UUID.Zero; url = string.Empty; firstname = "Unknown"; lastname = "User"; secret = string.Empty; 2186 uuid = UUID.Zero; url = string.Empty; firstname = "Unknown"; lastname = "UserUPUUI"; secret = string.Empty;
2152 2187
2153 string[] parts = value.Split(';'); 2188 string[] parts = value.Split(';');
2154 if (parts.Length >= 1) 2189 if (parts.Length >= 1)
@@ -2282,7 +2317,7 @@ namespace OpenSim.Framework
2282 { 2317 {
2283 lock (m_syncRoot) 2318 lock (m_syncRoot)
2284 { 2319 {
2285 m_lowQueue.Enqueue(data); 2320 q.Enqueue(data);
2286 m_s.WaitOne(0); 2321 m_s.WaitOne(0);
2287 m_s.Release(); 2322 m_s.Release();
2288 } 2323 }
@@ -2322,7 +2357,7 @@ namespace OpenSim.Framework
2322 { 2357 {
2323 if (m_highQueue.Count > 0) 2358 if (m_highQueue.Count > 0)
2324 res = m_highQueue.Dequeue(); 2359 res = m_highQueue.Dequeue();
2325 else 2360 else if (m_lowQueue.Count > 0)
2326 res = m_lowQueue.Dequeue(); 2361 res = m_lowQueue.Dequeue();
2327 2362
2328 if (m_highQueue.Count == 0 && m_lowQueue.Count == 0) 2363 if (m_highQueue.Count == 0 && m_lowQueue.Count == 0)