diff options
Diffstat (limited to 'OpenSim/Framework/Util.cs')
-rw-r--r-- | OpenSim/Framework/Util.cs | 143 |
1 files changed, 63 insertions, 80 deletions
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index 557f38e..7db575b 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 |
@@ -495,20 +521,18 @@ namespace OpenSim.Framework | |||
495 | 521 | ||
496 | public static int ToUnixTime(DateTime stamp) | 522 | public static int ToUnixTime(DateTime stamp) |
497 | { | 523 | { |
498 | TimeSpan t = stamp.ToUniversalTime() - unixEpoch; | 524 | TimeSpan t = stamp.ToUniversalTime() - UnixEpoch; |
499 | return (int) t.TotalSeconds; | 525 | return (int)t.TotalSeconds; |
500 | } | 526 | } |
501 | 527 | ||
502 | public static DateTime ToDateTime(ulong seconds) | 528 | public static DateTime ToDateTime(ulong seconds) |
503 | { | 529 | { |
504 | DateTime epoch = unixEpoch; | 530 | return UnixEpoch.AddSeconds(seconds); |
505 | return epoch.AddSeconds(seconds); | ||
506 | } | 531 | } |
507 | 532 | ||
508 | public static DateTime ToDateTime(int seconds) | 533 | public static DateTime ToDateTime(int seconds) |
509 | { | 534 | { |
510 | DateTime epoch = unixEpoch; | 535 | return UnixEpoch.AddSeconds(seconds); |
511 | return epoch.AddSeconds(seconds); | ||
512 | } | 536 | } |
513 | 537 | ||
514 | /// <summary> | 538 | /// <summary> |
@@ -1233,7 +1257,7 @@ namespace OpenSim.Framework | |||
1233 | byte[] bytes = | 1257 | byte[] bytes = |
1234 | { | 1258 | { |
1235 | (byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24), | 1259 | (byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24), |
1236 | (byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle << 56), | 1260 | (byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle >> 56), |
1237 | (byte)x, (byte)(x >> 8), 0, 0, | 1261 | (byte)x, (byte)(x >> 8), 0, 0, |
1238 | (byte)y, (byte)(y >> 8), 0, 0 }; | 1262 | (byte)y, (byte)(y >> 8), 0, 0 }; |
1239 | return new UUID(bytes, 0); | 1263 | return new UUID(bytes, 0); |
@@ -1244,7 +1268,7 @@ namespace OpenSim.Framework | |||
1244 | byte[] bytes = | 1268 | byte[] bytes = |
1245 | { | 1269 | { |
1246 | (byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24), | 1270 | (byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24), |
1247 | (byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle << 56), | 1271 | (byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle >> 56), |
1248 | (byte)x, (byte)(x >> 8), (byte)z, (byte)(z >> 8), | 1272 | (byte)x, (byte)(x >> 8), (byte)z, (byte)(z >> 8), |
1249 | (byte)y, (byte)(y >> 8), 0, 0 }; | 1273 | (byte)y, (byte)(y >> 8), 0, 0 }; |
1250 | return new UUID(bytes, 0); | 1274 | return new UUID(bytes, 0); |
@@ -1317,7 +1341,7 @@ namespace OpenSim.Framework | |||
1317 | ru = "OSX/Mono"; | 1341 | ru = "OSX/Mono"; |
1318 | else | 1342 | else |
1319 | { | 1343 | { |
1320 | if (Type.GetType("Mono.Runtime") != null) | 1344 | if (IsPlatformMono) |
1321 | ru = "Win/Mono"; | 1345 | ru = "Win/Mono"; |
1322 | else | 1346 | else |
1323 | ru = "Win/.NET"; | 1347 | ru = "Win/.NET"; |
@@ -1765,10 +1789,12 @@ namespace OpenSim.Framework | |||
1765 | FireAndForget(callback, null); | 1789 | FireAndForget(callback, null); |
1766 | } | 1790 | } |
1767 | 1791 | ||
1768 | public static void InitThreadPool(int maxThreads) | 1792 | public static void InitThreadPool(int minThreads, int maxThreads) |
1769 | { | 1793 | { |
1770 | if (maxThreads < 2) | 1794 | if (maxThreads < 2) |
1771 | throw new ArgumentOutOfRangeException("maxThreads", "maxThreads must be greater than 2"); | 1795 | throw new ArgumentOutOfRangeException("maxThreads", "maxThreads must be greater than 2"); |
1796 | if (minThreads > maxThreads || minThreads < 2) | ||
1797 | throw new ArgumentOutOfRangeException("minThreads", "minThreads must be greater than 2 and less than or equal to maxThreads"); | ||
1772 | if (m_ThreadPool != null) | 1798 | if (m_ThreadPool != null) |
1773 | throw new InvalidOperationException("SmartThreadPool is already initialized"); | 1799 | throw new InvalidOperationException("SmartThreadPool is already initialized"); |
1774 | 1800 | ||
@@ -1776,7 +1802,7 @@ namespace OpenSim.Framework | |||
1776 | startInfo.ThreadPoolName = "Util"; | 1802 | startInfo.ThreadPoolName = "Util"; |
1777 | startInfo.IdleTimeout = 2000; | 1803 | startInfo.IdleTimeout = 2000; |
1778 | startInfo.MaxWorkerThreads = maxThreads; | 1804 | startInfo.MaxWorkerThreads = maxThreads; |
1779 | startInfo.MinWorkerThreads = 2; | 1805 | startInfo.MinWorkerThreads = minThreads; |
1780 | 1806 | ||
1781 | m_ThreadPool = new SmartThreadPool(startInfo); | 1807 | m_ThreadPool = new SmartThreadPool(startInfo); |
1782 | } | 1808 | } |
@@ -1851,8 +1877,8 @@ namespace OpenSim.Framework | |||
1851 | break; | 1877 | break; |
1852 | case FireAndForgetMethod.SmartThreadPool: | 1878 | case FireAndForgetMethod.SmartThreadPool: |
1853 | if (m_ThreadPool == null) | 1879 | if (m_ThreadPool == null) |
1854 | InitThreadPool(15); | 1880 | InitThreadPool(2, 15); |
1855 | m_ThreadPool.QueueWorkItem(SmartThreadPoolCallback, new object[] { realCallback, obj }); | 1881 | m_ThreadPool.QueueWorkItem((cb, o) => cb(o), realCallback, obj); |
1856 | break; | 1882 | break; |
1857 | case FireAndForgetMethod.Thread: | 1883 | case FireAndForgetMethod.Thread: |
1858 | Thread thread = new Thread(delegate(object o) { realCallback(o); }); | 1884 | Thread thread = new Thread(delegate(object o) { realCallback(o); }); |
@@ -1864,72 +1890,29 @@ namespace OpenSim.Framework | |||
1864 | } | 1890 | } |
1865 | 1891 | ||
1866 | /// <summary> | 1892 | /// <summary> |
1867 | /// Get a thread pool report. | 1893 | /// Get information about the current state of the smart thread pool. |
1868 | /// </summary> | 1894 | /// </summary> |
1869 | /// <returns></returns> | 1895 | /// <returns> |
1870 | public static string GetThreadPoolReport() | 1896 | /// null if this isn't the pool being used for non-scriptengine threads. |
1897 | /// </returns> | ||
1898 | public static STPInfo GetSmartThreadPoolInfo() | ||
1871 | { | 1899 | { |
1872 | string threadPoolUsed = null; | 1900 | if (m_ThreadPool == null) |
1873 | int maxThreads = 0; | 1901 | 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 | 1902 | ||
1925 | private static object SmartThreadPoolCallback(object o) | 1903 | STPInfo stpi = new STPInfo(); |
1926 | { | 1904 | stpi.Name = m_ThreadPool.Name; |
1927 | object[] array = (object[])o; | 1905 | stpi.STPStartInfo = m_ThreadPool.STPStartInfo; |
1928 | WaitCallback callback = (WaitCallback)array[0]; | 1906 | stpi.IsIdle = m_ThreadPool.IsIdle; |
1929 | object obj = array[1]; | 1907 | stpi.IsShuttingDown = m_ThreadPool.IsShuttingdown; |
1908 | stpi.MaxThreads = m_ThreadPool.MaxThreads; | ||
1909 | stpi.MinThreads = m_ThreadPool.MinThreads; | ||
1910 | stpi.InUseThreads = m_ThreadPool.InUseThreads; | ||
1911 | stpi.ActiveThreads = m_ThreadPool.ActiveThreads; | ||
1912 | stpi.WaitingCallbacks = m_ThreadPool.WaitingCallbacks; | ||
1913 | stpi.MaxConcurrentWorkItems = m_ThreadPool.Concurrency; | ||
1930 | 1914 | ||
1931 | callback(obj); | 1915 | return stpi; |
1932 | return null; | ||
1933 | } | 1916 | } |
1934 | 1917 | ||
1935 | #endregion FireAndForget Threading Pattern | 1918 | #endregion FireAndForget Threading Pattern |
@@ -2148,7 +2131,7 @@ namespace OpenSim.Framework | |||
2148 | /// <param name="secret">the secret part</param> | 2131 | /// <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) | 2132 | public static bool ParseUniversalUserIdentifier(string value, out UUID uuid, out string url, out string firstname, out string lastname, out string secret) |
2150 | { | 2133 | { |
2151 | uuid = UUID.Zero; url = string.Empty; firstname = "Unknown"; lastname = "User"; secret = string.Empty; | 2134 | uuid = UUID.Zero; url = string.Empty; firstname = "Unknown"; lastname = "UserUPUUI"; secret = string.Empty; |
2152 | 2135 | ||
2153 | string[] parts = value.Split(';'); | 2136 | string[] parts = value.Split(';'); |
2154 | if (parts.Length >= 1) | 2137 | if (parts.Length >= 1) |
@@ -2282,7 +2265,7 @@ namespace OpenSim.Framework | |||
2282 | { | 2265 | { |
2283 | lock (m_syncRoot) | 2266 | lock (m_syncRoot) |
2284 | { | 2267 | { |
2285 | m_lowQueue.Enqueue(data); | 2268 | q.Enqueue(data); |
2286 | m_s.WaitOne(0); | 2269 | m_s.WaitOne(0); |
2287 | m_s.Release(); | 2270 | m_s.Release(); |
2288 | } | 2271 | } |
@@ -2322,7 +2305,7 @@ namespace OpenSim.Framework | |||
2322 | { | 2305 | { |
2323 | if (m_highQueue.Count > 0) | 2306 | if (m_highQueue.Count > 0) |
2324 | res = m_highQueue.Dequeue(); | 2307 | res = m_highQueue.Dequeue(); |
2325 | else | 2308 | else if (m_lowQueue.Count > 0) |
2326 | res = m_lowQueue.Dequeue(); | 2309 | res = m_lowQueue.Dequeue(); |
2327 | 2310 | ||
2328 | if (m_highQueue.Count == 0 && m_lowQueue.Count == 0) | 2311 | if (m_highQueue.Count == 0 && m_lowQueue.Count == 0) |