diff options
Diffstat (limited to 'OpenSim/Framework/Util.cs')
-rw-r--r-- | OpenSim/Framework/Util.cs | 278 |
1 files changed, 267 insertions, 11 deletions
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index e76a37b..557f38e 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs | |||
@@ -45,6 +45,7 @@ using System.Text.RegularExpressions; | |||
45 | using System.Xml; | 45 | using System.Xml; |
46 | using System.Threading; | 46 | using System.Threading; |
47 | using log4net; | 47 | using log4net; |
48 | using log4net.Appender; | ||
48 | using Nini.Config; | 49 | using Nini.Config; |
49 | using Nwc.XmlRpc; | 50 | using Nwc.XmlRpc; |
50 | using OpenMetaverse; | 51 | using OpenMetaverse; |
@@ -53,6 +54,21 @@ using Amib.Threading; | |||
53 | 54 | ||
54 | namespace OpenSim.Framework | 55 | namespace OpenSim.Framework |
55 | { | 56 | { |
57 | [Flags] | ||
58 | public enum PermissionMask : uint | ||
59 | { | ||
60 | None = 0, | ||
61 | Transfer = 1 << 13, | ||
62 | Modify = 1 << 14, | ||
63 | Copy = 1 << 15, | ||
64 | Export = 1 << 16, | ||
65 | Move = 1 << 19, | ||
66 | Damage = 1 << 20, | ||
67 | // All does not contain Export, which is special and must be | ||
68 | // explicitly given | ||
69 | All = (1 << 13) | (1 << 14) | (1 << 15) | (1 << 19) | ||
70 | } | ||
71 | |||
56 | /// <summary> | 72 | /// <summary> |
57 | /// The method used by Util.FireAndForget for asynchronously firing events | 73 | /// The method used by Util.FireAndForget for asynchronously firing events |
58 | /// </summary> | 74 | /// </summary> |
@@ -299,6 +315,25 @@ namespace OpenSim.Framework | |||
299 | x; | 315 | x; |
300 | } | 316 | } |
301 | 317 | ||
318 | // Clamp the maximum magnitude of a vector | ||
319 | public static Vector3 ClampV(Vector3 x, float max) | ||
320 | { | ||
321 | float lenSq = x.LengthSquared(); | ||
322 | if (lenSq > (max * max)) | ||
323 | { | ||
324 | x = x / x.Length() * max; | ||
325 | } | ||
326 | |||
327 | return x; | ||
328 | } | ||
329 | |||
330 | // Inclusive, within range test (true if equal to the endpoints) | ||
331 | public static bool InRange<T>(T x, T min, T max) | ||
332 | where T : IComparable<T> | ||
333 | { | ||
334 | return x.CompareTo(max) <= 0 && x.CompareTo(min) >= 0; | ||
335 | } | ||
336 | |||
302 | public static uint GetNextXferID() | 337 | public static uint GetNextXferID() |
303 | { | 338 | { |
304 | uint id = 0; | 339 | uint id = 0; |
@@ -809,9 +844,22 @@ namespace OpenSim.Framework | |||
809 | return "."; | 844 | return "."; |
810 | } | 845 | } |
811 | 846 | ||
847 | public static string logFile() | ||
848 | { | ||
849 | foreach (IAppender appender in LogManager.GetRepository().GetAppenders()) | ||
850 | { | ||
851 | if (appender is FileAppender) | ||
852 | { | ||
853 | return ((FileAppender)appender).File; | ||
854 | } | ||
855 | } | ||
856 | |||
857 | return "./OpenSim.log"; | ||
858 | } | ||
859 | |||
812 | public static string logDir() | 860 | public static string logDir() |
813 | { | 861 | { |
814 | return "."; | 862 | return Path.GetDirectoryName(logFile()); |
815 | } | 863 | } |
816 | 864 | ||
817 | // From: http://coercedcode.blogspot.com/2008/03/c-generate-unique-filenames-within.html | 865 | // From: http://coercedcode.blogspot.com/2008/03/c-generate-unique-filenames-within.html |
@@ -842,7 +890,7 @@ namespace OpenSim.Framework | |||
842 | return FileName; | 890 | return FileName; |
843 | } | 891 | } |
844 | 892 | ||
845 | // Nini (config) related Methods | 893 | #region Nini (config) related Methods |
846 | public static IConfigSource ConvertDataRowToXMLConfig(DataRow row, string fileName) | 894 | public static IConfigSource ConvertDataRowToXMLConfig(DataRow row, string fileName) |
847 | { | 895 | { |
848 | if (!File.Exists(fileName)) | 896 | if (!File.Exists(fileName)) |
@@ -865,6 +913,79 @@ namespace OpenSim.Framework | |||
865 | } | 913 | } |
866 | } | 914 | } |
867 | 915 | ||
916 | public static string GetConfigVarWithDefaultSection(IConfigSource config, string varname, string section) | ||
917 | { | ||
918 | // First, check the Startup section, the default section | ||
919 | IConfig cnf = config.Configs["Startup"]; | ||
920 | if (cnf == null) | ||
921 | return string.Empty; | ||
922 | string val = cnf.GetString(varname, string.Empty); | ||
923 | |||
924 | // Then check for an overwrite of the default in the given section | ||
925 | if (!string.IsNullOrEmpty(section)) | ||
926 | { | ||
927 | cnf = config.Configs[section]; | ||
928 | if (cnf != null) | ||
929 | val = cnf.GetString(varname, val); | ||
930 | } | ||
931 | |||
932 | return val; | ||
933 | } | ||
934 | |||
935 | /// <summary> | ||
936 | /// Gets the value of a configuration variable by looking into | ||
937 | /// multiple sections in order. The latter sections overwrite | ||
938 | /// any values previously found. | ||
939 | /// </summary> | ||
940 | /// <typeparam name="T">Type of the variable</typeparam> | ||
941 | /// <param name="config">The configuration object</param> | ||
942 | /// <param name="varname">The configuration variable</param> | ||
943 | /// <param name="sections">Ordered sequence of sections to look at</param> | ||
944 | /// <returns></returns> | ||
945 | public static T GetConfigVarFromSections<T>(IConfigSource config, string varname, string[] sections) | ||
946 | { | ||
947 | return GetConfigVarFromSections<T>(config, varname, sections, default(T)); | ||
948 | } | ||
949 | |||
950 | /// <summary> | ||
951 | /// Gets the value of a configuration variable by looking into | ||
952 | /// multiple sections in order. The latter sections overwrite | ||
953 | /// any values previously found. | ||
954 | /// </summary> | ||
955 | /// <remarks> | ||
956 | /// If no value is found then the given default value is returned | ||
957 | /// </remarks> | ||
958 | /// <typeparam name="T">Type of the variable</typeparam> | ||
959 | /// <param name="config">The configuration object</param> | ||
960 | /// <param name="varname">The configuration variable</param> | ||
961 | /// <param name="sections">Ordered sequence of sections to look at</param> | ||
962 | /// <param name="val">Default value</param> | ||
963 | /// <returns></returns> | ||
964 | public static T GetConfigVarFromSections<T>(IConfigSource config, string varname, string[] sections, object val) | ||
965 | { | ||
966 | foreach (string section in sections) | ||
967 | { | ||
968 | IConfig cnf = config.Configs[section]; | ||
969 | if (cnf == null) | ||
970 | continue; | ||
971 | |||
972 | if (typeof(T) == typeof(String)) | ||
973 | val = cnf.GetString(varname, (string)val); | ||
974 | else if (typeof(T) == typeof(Boolean)) | ||
975 | val = cnf.GetBoolean(varname, (bool)val); | ||
976 | else if (typeof(T) == typeof(Int32)) | ||
977 | val = cnf.GetInt(varname, (int)val); | ||
978 | else if (typeof(T) == typeof(float)) | ||
979 | val = cnf.GetFloat(varname, (int)val); | ||
980 | else | ||
981 | m_log.ErrorFormat("[UTIL]: Unhandled type {0}", typeof(T)); | ||
982 | } | ||
983 | |||
984 | return (T)val; | ||
985 | } | ||
986 | |||
987 | #endregion | ||
988 | |||
868 | public static float Clip(float x, float min, float max) | 989 | public static float Clip(float x, float min, float max) |
869 | { | 990 | { |
870 | return Math.Min(Math.Max(x, min), max); | 991 | return Math.Min(Math.Max(x, min), max); |
@@ -1651,7 +1772,13 @@ namespace OpenSim.Framework | |||
1651 | if (m_ThreadPool != null) | 1772 | if (m_ThreadPool != null) |
1652 | throw new InvalidOperationException("SmartThreadPool is already initialized"); | 1773 | throw new InvalidOperationException("SmartThreadPool is already initialized"); |
1653 | 1774 | ||
1654 | m_ThreadPool = new SmartThreadPool(2000, maxThreads, 2); | 1775 | STPStartInfo startInfo = new STPStartInfo(); |
1776 | startInfo.ThreadPoolName = "Util"; | ||
1777 | startInfo.IdleTimeout = 2000; | ||
1778 | startInfo.MaxWorkerThreads = maxThreads; | ||
1779 | startInfo.MinWorkerThreads = 2; | ||
1780 | |||
1781 | m_ThreadPool = new SmartThreadPool(startInfo); | ||
1655 | } | 1782 | } |
1656 | 1783 | ||
1657 | public static int FireAndForgetCount() | 1784 | public static int FireAndForgetCount() |
@@ -1724,7 +1851,7 @@ namespace OpenSim.Framework | |||
1724 | break; | 1851 | break; |
1725 | case FireAndForgetMethod.SmartThreadPool: | 1852 | case FireAndForgetMethod.SmartThreadPool: |
1726 | if (m_ThreadPool == null) | 1853 | if (m_ThreadPool == null) |
1727 | m_ThreadPool = new SmartThreadPool(2000, 15, 2); | 1854 | InitThreadPool(15); |
1728 | m_ThreadPool.QueueWorkItem(SmartThreadPoolCallback, new object[] { realCallback, obj }); | 1855 | m_ThreadPool.QueueWorkItem(SmartThreadPoolCallback, new object[] { realCallback, obj }); |
1729 | break; | 1856 | break; |
1730 | case FireAndForgetMethod.Thread: | 1857 | case FireAndForgetMethod.Thread: |
@@ -1753,12 +1880,16 @@ namespace OpenSim.Framework | |||
1753 | StringBuilder sb = new StringBuilder(); | 1880 | StringBuilder sb = new StringBuilder(); |
1754 | if (FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool) | 1881 | if (FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool) |
1755 | { | 1882 | { |
1756 | threadPoolUsed = "SmartThreadPool"; | 1883 | // ROBUST currently leaves this the FireAndForgetMethod but never actually initializes the threadpool. |
1757 | maxThreads = m_ThreadPool.MaxThreads; | 1884 | if (m_ThreadPool != null) |
1758 | minThreads = m_ThreadPool.MinThreads; | 1885 | { |
1759 | inUseThreads = m_ThreadPool.InUseThreads; | 1886 | threadPoolUsed = "SmartThreadPool"; |
1760 | allocatedThreads = m_ThreadPool.ActiveThreads; | 1887 | maxThreads = m_ThreadPool.MaxThreads; |
1761 | waitingCallbacks = m_ThreadPool.WaitingCallbacks; | 1888 | minThreads = m_ThreadPool.MinThreads; |
1889 | inUseThreads = m_ThreadPool.InUseThreads; | ||
1890 | allocatedThreads = m_ThreadPool.ActiveThreads; | ||
1891 | waitingCallbacks = m_ThreadPool.WaitingCallbacks; | ||
1892 | } | ||
1762 | } | 1893 | } |
1763 | else if ( | 1894 | else if ( |
1764 | FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem | 1895 | FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem |
@@ -1863,6 +1994,12 @@ namespace OpenSim.Framework | |||
1863 | /// </summary> | 1994 | /// </summary> |
1864 | public static void PrintCallStack() | 1995 | public static void PrintCallStack() |
1865 | { | 1996 | { |
1997 | PrintCallStack(m_log.DebugFormat); | ||
1998 | } | ||
1999 | |||
2000 | public delegate void DebugPrinter(string msg, params Object[] parm); | ||
2001 | public static void PrintCallStack(DebugPrinter printer) | ||
2002 | { | ||
1866 | StackTrace stackTrace = new StackTrace(true); // get call stack | 2003 | StackTrace stackTrace = new StackTrace(true); // get call stack |
1867 | StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames) | 2004 | StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames) |
1868 | 2005 | ||
@@ -1870,7 +2007,7 @@ namespace OpenSim.Framework | |||
1870 | foreach (StackFrame stackFrame in stackFrames) | 2007 | foreach (StackFrame stackFrame in stackFrames) |
1871 | { | 2008 | { |
1872 | MethodBase mb = stackFrame.GetMethod(); | 2009 | MethodBase mb = stackFrame.GetMethod(); |
1873 | m_log.DebugFormat("{0}.{1}:{2}", mb.DeclaringType, mb.Name, stackFrame.GetFileLineNumber()); // write method name | 2010 | printer("{0}.{1}:{2}", mb.DeclaringType, mb.Name, stackFrame.GetFileLineNumber()); // write method name |
1874 | } | 2011 | } |
1875 | } | 2012 | } |
1876 | 2013 | ||
@@ -2096,5 +2233,124 @@ namespace OpenSim.Framework | |||
2096 | return firstName + "." + lastName + " " + "@" + uri.Authority; | 2233 | return firstName + "." + lastName + " " + "@" + uri.Authority; |
2097 | } | 2234 | } |
2098 | #endregion | 2235 | #endregion |
2236 | |||
2237 | /// <summary> | ||
2238 | /// Escapes the special characters used in "LIKE". | ||
2239 | /// </summary> | ||
2240 | /// <remarks> | ||
2241 | /// For example: EscapeForLike("foo_bar%baz") = "foo\_bar\%baz" | ||
2242 | /// </remarks> | ||
2243 | public static string EscapeForLike(string str) | ||
2244 | { | ||
2245 | return str.Replace("_", "\\_").Replace("%", "\\%"); | ||
2246 | } | ||
2247 | } | ||
2248 | |||
2249 | public class DoubleQueue<T> where T:class | ||
2250 | { | ||
2251 | private Queue<T> m_lowQueue = new Queue<T>(); | ||
2252 | private Queue<T> m_highQueue = new Queue<T>(); | ||
2253 | |||
2254 | private object m_syncRoot = new object(); | ||
2255 | private Semaphore m_s = new Semaphore(0, 1); | ||
2256 | |||
2257 | public DoubleQueue() | ||
2258 | { | ||
2259 | } | ||
2260 | |||
2261 | public virtual int Count | ||
2262 | { | ||
2263 | get { return m_highQueue.Count + m_lowQueue.Count; } | ||
2264 | } | ||
2265 | |||
2266 | public virtual void Enqueue(T data) | ||
2267 | { | ||
2268 | Enqueue(m_lowQueue, data); | ||
2269 | } | ||
2270 | |||
2271 | public virtual void EnqueueLow(T data) | ||
2272 | { | ||
2273 | Enqueue(m_lowQueue, data); | ||
2274 | } | ||
2275 | |||
2276 | public virtual void EnqueueHigh(T data) | ||
2277 | { | ||
2278 | Enqueue(m_highQueue, data); | ||
2279 | } | ||
2280 | |||
2281 | private void Enqueue(Queue<T> q, T data) | ||
2282 | { | ||
2283 | lock (m_syncRoot) | ||
2284 | { | ||
2285 | m_lowQueue.Enqueue(data); | ||
2286 | m_s.WaitOne(0); | ||
2287 | m_s.Release(); | ||
2288 | } | ||
2289 | } | ||
2290 | |||
2291 | public virtual T Dequeue() | ||
2292 | { | ||
2293 | return Dequeue(Timeout.Infinite); | ||
2294 | } | ||
2295 | |||
2296 | public virtual T Dequeue(int tmo) | ||
2297 | { | ||
2298 | return Dequeue(TimeSpan.FromMilliseconds(tmo)); | ||
2299 | } | ||
2300 | |||
2301 | public virtual T Dequeue(TimeSpan wait) | ||
2302 | { | ||
2303 | T res = null; | ||
2304 | |||
2305 | if (!Dequeue(wait, ref res)) | ||
2306 | return null; | ||
2307 | |||
2308 | return res; | ||
2309 | } | ||
2310 | |||
2311 | public bool Dequeue(int timeout, ref T res) | ||
2312 | { | ||
2313 | return Dequeue(TimeSpan.FromMilliseconds(timeout), ref res); | ||
2314 | } | ||
2315 | |||
2316 | public bool Dequeue(TimeSpan wait, ref T res) | ||
2317 | { | ||
2318 | if (!m_s.WaitOne(wait)) | ||
2319 | return false; | ||
2320 | |||
2321 | lock (m_syncRoot) | ||
2322 | { | ||
2323 | if (m_highQueue.Count > 0) | ||
2324 | res = m_highQueue.Dequeue(); | ||
2325 | else | ||
2326 | res = m_lowQueue.Dequeue(); | ||
2327 | |||
2328 | if (m_highQueue.Count == 0 && m_lowQueue.Count == 0) | ||
2329 | return true; | ||
2330 | |||
2331 | try | ||
2332 | { | ||
2333 | m_s.Release(); | ||
2334 | } | ||
2335 | catch | ||
2336 | { | ||
2337 | } | ||
2338 | |||
2339 | return true; | ||
2340 | } | ||
2341 | } | ||
2342 | |||
2343 | public virtual void Clear() | ||
2344 | { | ||
2345 | |||
2346 | lock (m_syncRoot) | ||
2347 | { | ||
2348 | // Make sure sem count is 0 | ||
2349 | m_s.WaitOne(0); | ||
2350 | |||
2351 | m_lowQueue.Clear(); | ||
2352 | m_highQueue.Clear(); | ||
2353 | } | ||
2354 | } | ||
2099 | } | 2355 | } |
2100 | } | 2356 | } |