diff options
Diffstat (limited to 'OpenSim/Framework')
-rw-r--r-- | OpenSim/Framework/Parallel.cs | 207 | ||||
-rw-r--r-- | OpenSim/Framework/Servers/BaseOpenSimServer.cs | 27 | ||||
-rw-r--r-- | OpenSim/Framework/Tests/ThreadTrackerTests.cs | 140 | ||||
-rw-r--r-- | OpenSim/Framework/ThreadTracker.cs | 127 | ||||
-rw-r--r-- | OpenSim/Framework/ThrottleOutPacketType.cs | 8 | ||||
-rw-r--r-- | OpenSim/Framework/Util.cs | 40 |
6 files changed, 260 insertions, 289 deletions
diff --git a/OpenSim/Framework/Parallel.cs b/OpenSim/Framework/Parallel.cs new file mode 100644 index 0000000..74537ba --- /dev/null +++ b/OpenSim/Framework/Parallel.cs | |||
@@ -0,0 +1,207 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSimulator Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.Threading; | ||
31 | |||
32 | namespace OpenSim.Framework | ||
33 | { | ||
34 | /// <summary> | ||
35 | /// Provides helper methods for parallelizing loops | ||
36 | /// </summary> | ||
37 | public static class Parallel | ||
38 | { | ||
39 | private static readonly int processorCount = System.Environment.ProcessorCount; | ||
40 | |||
41 | /// <summary> | ||
42 | /// Executes a for loop in which iterations may run in parallel | ||
43 | /// </summary> | ||
44 | /// <param name="fromInclusive">The loop will be started at this index</param> | ||
45 | /// <param name="toExclusive">The loop will be terminated before this index is reached</param> | ||
46 | /// <param name="body">Method body to run for each iteration of the loop</param> | ||
47 | public static void For(int fromInclusive, int toExclusive, Action<int> body) | ||
48 | { | ||
49 | For(processorCount, fromInclusive, toExclusive, body); | ||
50 | } | ||
51 | |||
52 | /// <summary> | ||
53 | /// Executes a for loop in which iterations may run in parallel | ||
54 | /// </summary> | ||
55 | /// <param name="threadCount">The number of concurrent execution threads to run</param> | ||
56 | /// <param name="fromInclusive">The loop will be started at this index</param> | ||
57 | /// <param name="toExclusive">The loop will be terminated before this index is reached</param> | ||
58 | /// <param name="body">Method body to run for each iteration of the loop</param> | ||
59 | public static void For(int threadCount, int fromInclusive, int toExclusive, Action<int> body) | ||
60 | { | ||
61 | int counter = threadCount; | ||
62 | AutoResetEvent threadFinishEvent = new AutoResetEvent(false); | ||
63 | Exception exception = null; | ||
64 | |||
65 | --fromInclusive; | ||
66 | |||
67 | for (int i = 0; i < threadCount; i++) | ||
68 | { | ||
69 | ThreadPool.QueueUserWorkItem( | ||
70 | delegate(object o) | ||
71 | { | ||
72 | int threadIndex = (int)o; | ||
73 | |||
74 | while (exception == null) | ||
75 | { | ||
76 | int currentIndex = Interlocked.Increment(ref fromInclusive); | ||
77 | |||
78 | if (currentIndex >= toExclusive) | ||
79 | break; | ||
80 | |||
81 | try { body(currentIndex); } | ||
82 | catch (Exception ex) { exception = ex; break; } | ||
83 | } | ||
84 | |||
85 | if (Interlocked.Decrement(ref counter) == 0) | ||
86 | threadFinishEvent.Set(); | ||
87 | }, i | ||
88 | ); | ||
89 | } | ||
90 | |||
91 | threadFinishEvent.WaitOne(); | ||
92 | |||
93 | if (exception != null) | ||
94 | throw new Exception(exception.Message, exception); | ||
95 | } | ||
96 | |||
97 | /// <summary> | ||
98 | /// Executes a foreach loop in which iterations may run in parallel | ||
99 | /// </summary> | ||
100 | /// <typeparam name="T">Object type that the collection wraps</typeparam> | ||
101 | /// <param name="enumerable">An enumerable collection to iterate over</param> | ||
102 | /// <param name="body">Method body to run for each object in the collection</param> | ||
103 | public static void ForEach<T>(IEnumerable<T> enumerable, Action<T> body) | ||
104 | { | ||
105 | ForEach<T>(processorCount, enumerable, body); | ||
106 | } | ||
107 | |||
108 | /// <summary> | ||
109 | /// Executes a foreach loop in which iterations may run in parallel | ||
110 | /// </summary> | ||
111 | /// <typeparam name="T">Object type that the collection wraps</typeparam> | ||
112 | /// <param name="threadCount">The number of concurrent execution threads to run</param> | ||
113 | /// <param name="enumerable">An enumerable collection to iterate over</param> | ||
114 | /// <param name="body">Method body to run for each object in the collection</param> | ||
115 | public static void ForEach<T>(int threadCount, IEnumerable<T> enumerable, Action<T> body) | ||
116 | { | ||
117 | int counter = threadCount; | ||
118 | AutoResetEvent threadFinishEvent = new AutoResetEvent(false); | ||
119 | IEnumerator<T> enumerator = enumerable.GetEnumerator(); | ||
120 | Exception exception = null; | ||
121 | |||
122 | for (int i = 0; i < threadCount; i++) | ||
123 | { | ||
124 | ThreadPool.QueueUserWorkItem( | ||
125 | delegate(object o) | ||
126 | { | ||
127 | int threadIndex = (int)o; | ||
128 | |||
129 | while (exception == null) | ||
130 | { | ||
131 | T entry; | ||
132 | |||
133 | lock (enumerator) | ||
134 | { | ||
135 | if (!enumerator.MoveNext()) | ||
136 | break; | ||
137 | entry = (T)enumerator.Current; // Explicit typecast for Mono's sake | ||
138 | } | ||
139 | |||
140 | try { body(entry); } | ||
141 | catch (Exception ex) { exception = ex; break; } | ||
142 | } | ||
143 | |||
144 | if (Interlocked.Decrement(ref counter) == 0) | ||
145 | threadFinishEvent.Set(); | ||
146 | }, i | ||
147 | ); | ||
148 | } | ||
149 | |||
150 | threadFinishEvent.WaitOne(); | ||
151 | |||
152 | if (exception != null) | ||
153 | throw new Exception(exception.Message, exception); | ||
154 | } | ||
155 | |||
156 | /// <summary> | ||
157 | /// Executes a series of tasks in parallel | ||
158 | /// </summary> | ||
159 | /// <param name="actions">A series of method bodies to execute</param> | ||
160 | public static void Invoke(params Action[] actions) | ||
161 | { | ||
162 | Invoke(processorCount, actions); | ||
163 | } | ||
164 | |||
165 | /// <summary> | ||
166 | /// Executes a series of tasks in parallel | ||
167 | /// </summary> | ||
168 | /// <param name="threadCount">The number of concurrent execution threads to run</param> | ||
169 | /// <param name="actions">A series of method bodies to execute</param> | ||
170 | public static void Invoke(int threadCount, params Action[] actions) | ||
171 | { | ||
172 | int counter = threadCount; | ||
173 | AutoResetEvent threadFinishEvent = new AutoResetEvent(false); | ||
174 | int index = -1; | ||
175 | Exception exception = null; | ||
176 | |||
177 | for (int i = 0; i < threadCount; i++) | ||
178 | { | ||
179 | ThreadPool.QueueUserWorkItem( | ||
180 | delegate(object o) | ||
181 | { | ||
182 | int threadIndex = (int)o; | ||
183 | |||
184 | while (exception == null) | ||
185 | { | ||
186 | int currentIndex = Interlocked.Increment(ref index); | ||
187 | |||
188 | if (currentIndex >= actions.Length) | ||
189 | break; | ||
190 | |||
191 | try { actions[currentIndex](); } | ||
192 | catch (Exception ex) { exception = ex; break; } | ||
193 | } | ||
194 | |||
195 | if (Interlocked.Decrement(ref counter) == 0) | ||
196 | threadFinishEvent.Set(); | ||
197 | }, i | ||
198 | ); | ||
199 | } | ||
200 | |||
201 | threadFinishEvent.WaitOne(); | ||
202 | |||
203 | if (exception != null) | ||
204 | throw new Exception(exception.Message, exception); | ||
205 | } | ||
206 | } | ||
207 | } | ||
diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs index 56155dd..8e58980 100644 --- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs +++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs | |||
@@ -27,6 +27,7 @@ | |||
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Diagnostics; | ||
30 | using System.IO; | 31 | using System.IO; |
31 | using System.Reflection; | 32 | using System.Reflection; |
32 | using System.Text; | 33 | using System.Text; |
@@ -109,9 +110,8 @@ namespace OpenSim.Framework.Servers | |||
109 | m_periodicDiagnosticsTimer.Elapsed += new ElapsedEventHandler(LogDiagnostics); | 110 | m_periodicDiagnosticsTimer.Elapsed += new ElapsedEventHandler(LogDiagnostics); |
110 | m_periodicDiagnosticsTimer.Enabled = true; | 111 | m_periodicDiagnosticsTimer.Enabled = true; |
111 | 112 | ||
112 | // Add ourselves to thread monitoring. This thread will go on to become the console listening thread | 113 | // This thread will go on to become the console listening thread |
113 | Thread.CurrentThread.Name = "ConsoleThread"; | 114 | Thread.CurrentThread.Name = "ConsoleThread"; |
114 | ThreadTracker.Add(Thread.CurrentThread); | ||
115 | 115 | ||
116 | ILoggerRepository repository = LogManager.GetRepository(); | 116 | ILoggerRepository repository = LogManager.GetRepository(); |
117 | IAppender[] appenders = repository.GetAppenders(); | 117 | IAppender[] appenders = repository.GetAppenders(); |
@@ -235,7 +235,7 @@ namespace OpenSim.Framework.Servers | |||
235 | { | 235 | { |
236 | StringBuilder sb = new StringBuilder(); | 236 | StringBuilder sb = new StringBuilder(); |
237 | 237 | ||
238 | List<Thread> threads = ThreadTracker.GetThreads(); | 238 | ProcessThreadCollection threads = ThreadTracker.GetThreads(); |
239 | if (threads == null) | 239 | if (threads == null) |
240 | { | 240 | { |
241 | sb.Append("OpenSim thread tracking is only enabled in DEBUG mode."); | 241 | sb.Append("OpenSim thread tracking is only enabled in DEBUG mode."); |
@@ -243,25 +243,10 @@ namespace OpenSim.Framework.Servers | |||
243 | else | 243 | else |
244 | { | 244 | { |
245 | sb.Append(threads.Count + " threads are being tracked:" + Environment.NewLine); | 245 | sb.Append(threads.Count + " threads are being tracked:" + Environment.NewLine); |
246 | foreach (Thread t in threads) | 246 | foreach (ProcessThread t in threads) |
247 | { | 247 | { |
248 | if (t.IsAlive) | 248 | sb.Append("ID: " + t.Id + ", TotalProcessorTime: " + t.TotalProcessorTime + ", TimeRunning: " + |
249 | { | 249 | (DateTime.Now - t.StartTime) + ", Pri: " + t.CurrentPriority + ", State: " + t.ThreadState + Environment.NewLine); |
250 | sb.Append( | ||
251 | "ID: " + t.ManagedThreadId + ", Name: " + t.Name + ", Alive: " + t.IsAlive | ||
252 | + ", Pri: " + t.Priority + ", State: " + t.ThreadState + Environment.NewLine); | ||
253 | } | ||
254 | else | ||
255 | { | ||
256 | try | ||
257 | { | ||
258 | sb.Append("ID: " + t.ManagedThreadId + ", Name: " + t.Name + ", DEAD" + Environment.NewLine); | ||
259 | } | ||
260 | catch | ||
261 | { | ||
262 | sb.Append("THREAD ERROR" + Environment.NewLine); | ||
263 | } | ||
264 | } | ||
265 | } | 250 | } |
266 | } | 251 | } |
267 | int workers = 0, ports = 0, maxWorkers = 0, maxPorts = 0; | 252 | int workers = 0, ports = 0, maxWorkers = 0, maxPorts = 0; |
diff --git a/OpenSim/Framework/Tests/ThreadTrackerTests.cs b/OpenSim/Framework/Tests/ThreadTrackerTests.cs index 15d5b73..7eb83e6 100644 --- a/OpenSim/Framework/Tests/ThreadTrackerTests.cs +++ b/OpenSim/Framework/Tests/ThreadTrackerTests.cs | |||
@@ -41,7 +41,7 @@ namespace OpenSim.Framework.Tests | |||
41 | [Test] | 41 | [Test] |
42 | public void DefaultThreadTrackerTest() | 42 | public void DefaultThreadTrackerTest() |
43 | { | 43 | { |
44 | List<Thread> lThread = ThreadTracker.GetThreads(); | 44 | System.Diagnostics.ProcessThreadCollection lThread = ThreadTracker.GetThreads(); |
45 | 45 | ||
46 | /* | 46 | /* |
47 | foreach (Thread t in lThread) | 47 | foreach (Thread t in lThread) |
@@ -50,143 +50,7 @@ namespace OpenSim.Framework.Tests | |||
50 | } | 50 | } |
51 | */ | 51 | */ |
52 | 52 | ||
53 | Assert.That(lThread.Count == 1); | 53 | Assert.That(lThread.Count > 0); |
54 | Assert.That(lThread[0].Name == "ThreadTrackerThread"); | ||
55 | } | 54 | } |
56 | |||
57 | /// <summary> | ||
58 | /// Validate that adding a thread to the thread tracker works | ||
59 | /// Validate that removing a thread from the thread tracker also works. | ||
60 | /// </summary> | ||
61 | [Test] | ||
62 | public void AddThreadToThreadTrackerTestAndRemoveTest() | ||
63 | { | ||
64 | Thread t = new Thread(run); | ||
65 | t.Name = "TestThread"; | ||
66 | t.Priority = ThreadPriority.BelowNormal; | ||
67 | t.IsBackground = true; | ||
68 | t.SetApartmentState(ApartmentState.MTA); | ||
69 | t.Start(); | ||
70 | ThreadTracker.Add(t); | ||
71 | |||
72 | List<Thread> lThread = ThreadTracker.GetThreads(); | ||
73 | |||
74 | Assert.That(lThread.Count == 2); | ||
75 | |||
76 | foreach (Thread tr in lThread) | ||
77 | { | ||
78 | Assert.That((tr.Name == "ThreadTrackerThread" || tr.Name == "TestThread")); | ||
79 | } | ||
80 | running = false; | ||
81 | ThreadTracker.Remove(t); | ||
82 | |||
83 | lThread = ThreadTracker.GetThreads(); | ||
84 | |||
85 | Assert.That(lThread.Count == 1); | ||
86 | |||
87 | foreach (Thread tr in lThread) | ||
88 | { | ||
89 | Assert.That((tr.Name == "ThreadTrackerThread")); | ||
90 | } | ||
91 | |||
92 | |||
93 | } | ||
94 | |||
95 | /// <summary> | ||
96 | /// Test a dead thread removal by aborting it and setting it's last seen active date to 50 seconds | ||
97 | /// </summary> | ||
98 | [Test] | ||
99 | public void DeadThreadTest() | ||
100 | { | ||
101 | Thread t = new Thread(run2); | ||
102 | t.Name = "TestThread"; | ||
103 | t.Priority = ThreadPriority.BelowNormal; | ||
104 | t.IsBackground = true; | ||
105 | t.SetApartmentState(ApartmentState.MTA); | ||
106 | t.Start(); | ||
107 | ThreadTracker.Add(t); | ||
108 | t.Abort(); | ||
109 | Thread.Sleep(5000); | ||
110 | ThreadTracker.m_Threads[1].LastSeenActive = DateTime.Now.Ticks - (50*10000000); | ||
111 | ThreadTracker.CleanUp(); | ||
112 | List<Thread> lThread = ThreadTracker.GetThreads(); | ||
113 | |||
114 | Assert.That(lThread.Count == 1); | ||
115 | |||
116 | foreach (Thread tr in lThread) | ||
117 | { | ||
118 | Assert.That((tr.Name == "ThreadTrackerThread")); | ||
119 | } | ||
120 | } | ||
121 | |||
122 | [Test] | ||
123 | public void UnstartedThreadTest() | ||
124 | { | ||
125 | Thread t = new Thread(run2); | ||
126 | t.Name = "TestThread"; | ||
127 | t.Priority = ThreadPriority.BelowNormal; | ||
128 | t.IsBackground = true; | ||
129 | t.SetApartmentState(ApartmentState.MTA); | ||
130 | ThreadTracker.Add(t); | ||
131 | ThreadTracker.m_Threads[1].LastSeenActive = DateTime.Now.Ticks - (50 * 10000000); | ||
132 | ThreadTracker.CleanUp(); | ||
133 | List<Thread> lThread = ThreadTracker.GetThreads(); | ||
134 | |||
135 | Assert.That(lThread.Count == 1); | ||
136 | |||
137 | foreach (Thread tr in lThread) | ||
138 | { | ||
139 | Assert.That((tr.Name == "ThreadTrackerThread")); | ||
140 | } | ||
141 | } | ||
142 | |||
143 | [Test] | ||
144 | public void NullThreadTest() | ||
145 | { | ||
146 | Thread t = null; | ||
147 | ThreadTracker.Add(t); | ||
148 | |||
149 | List<Thread> lThread = ThreadTracker.GetThreads(); | ||
150 | |||
151 | Assert.That(lThread.Count == 1); | ||
152 | |||
153 | foreach (Thread tr in lThread) | ||
154 | { | ||
155 | Assert.That((tr.Name == "ThreadTrackerThread")); | ||
156 | } | ||
157 | } | ||
158 | |||
159 | |||
160 | /// <summary> | ||
161 | /// Worker thread 0 | ||
162 | /// </summary> | ||
163 | /// <param name="o"></param> | ||
164 | public void run(object o) | ||
165 | { | ||
166 | while (running) | ||
167 | { | ||
168 | Thread.Sleep(5000); | ||
169 | } | ||
170 | } | ||
171 | |||
172 | /// <summary> | ||
173 | /// Worker thread 1 | ||
174 | /// </summary> | ||
175 | /// <param name="o"></param> | ||
176 | public void run2(object o) | ||
177 | { | ||
178 | try | ||
179 | { | ||
180 | while (running2) | ||
181 | { | ||
182 | Thread.Sleep(5000); | ||
183 | } | ||
184 | |||
185 | } | ||
186 | catch (ThreadAbortException) | ||
187 | { | ||
188 | } | ||
189 | } | ||
190 | |||
191 | } | 55 | } |
192 | } | 56 | } |
diff --git a/OpenSim/Framework/ThreadTracker.cs b/OpenSim/Framework/ThreadTracker.cs index d3a239d..b68d9b3 100644 --- a/OpenSim/Framework/ThreadTracker.cs +++ b/OpenSim/Framework/ThreadTracker.cs | |||
@@ -26,138 +26,21 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections; | ||
30 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
31 | using System.Reflection; | 30 | using System.Reflection; |
32 | using System.Threading; | 31 | using System.Diagnostics; |
33 | using log4net; | 32 | using log4net; |
34 | 33 | ||
35 | namespace OpenSim.Framework | 34 | namespace OpenSim.Framework |
36 | { | 35 | { |
37 | public static class ThreadTracker | 36 | public static class ThreadTracker |
38 | { | 37 | { |
39 | private static readonly ILog m_log | 38 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
40 | = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
41 | |||
42 | private static readonly long ThreadTimeout = 30 * 10000000; | ||
43 | public static List<ThreadTrackerItem> m_Threads; | ||
44 | public static Thread ThreadTrackerThread; | ||
45 | 39 | ||
46 | static ThreadTracker() | 40 | public static ProcessThreadCollection GetThreads() |
47 | { | 41 | { |
48 | #if DEBUG | 42 | Process thisProc = Process.GetCurrentProcess(); |
49 | m_Threads = new List<ThreadTrackerItem>(); | 43 | return thisProc.Threads; |
50 | ThreadTrackerThread = new Thread(ThreadTrackerThreadLoop); | ||
51 | ThreadTrackerThread.Name = "ThreadTrackerThread"; | ||
52 | ThreadTrackerThread.IsBackground = true; | ||
53 | ThreadTrackerThread.Priority = ThreadPriority.BelowNormal; | ||
54 | ThreadTrackerThread.Start(); | ||
55 | Add(ThreadTrackerThread); | ||
56 | #endif | ||
57 | } | 44 | } |
58 | |||
59 | private static void ThreadTrackerThreadLoop() | ||
60 | { | ||
61 | try | ||
62 | { | ||
63 | while (true) | ||
64 | { | ||
65 | Thread.Sleep(5000); | ||
66 | CleanUp(); | ||
67 | } | ||
68 | } | ||
69 | catch (Exception e) | ||
70 | { | ||
71 | m_log.ErrorFormat( | ||
72 | "[THREAD TRACKER]: Thread tracker cleanup thread terminating with exception. Please report this error. Exception is {0}", | ||
73 | e); | ||
74 | } | ||
75 | } | ||
76 | |||
77 | public static void Add(Thread thread) | ||
78 | { | ||
79 | #if DEBUG | ||
80 | if (thread != null) | ||
81 | { | ||
82 | lock (m_Threads) | ||
83 | { | ||
84 | ThreadTrackerItem tti = new ThreadTrackerItem(); | ||
85 | tti.Thread = thread; | ||
86 | tti.LastSeenActive = DateTime.Now.Ticks; | ||
87 | m_Threads.Add(tti); | ||
88 | } | ||
89 | } | ||
90 | #endif | ||
91 | } | ||
92 | |||
93 | public static void Remove(Thread thread) | ||
94 | { | ||
95 | #if DEBUG | ||
96 | lock (m_Threads) | ||
97 | { | ||
98 | foreach (ThreadTrackerItem tti in new ArrayList(m_Threads)) | ||
99 | { | ||
100 | if (tti.Thread == thread) | ||
101 | m_Threads.Remove(tti); | ||
102 | } | ||
103 | } | ||
104 | #endif | ||
105 | } | ||
106 | |||
107 | public static void CleanUp() | ||
108 | { | ||
109 | lock (m_Threads) | ||
110 | { | ||
111 | foreach (ThreadTrackerItem tti in new ArrayList(m_Threads)) | ||
112 | { | ||
113 | try | ||
114 | { | ||
115 | |||
116 | |||
117 | if (tti.Thread.IsAlive) | ||
118 | { | ||
119 | // Its active | ||
120 | tti.LastSeenActive = DateTime.Now.Ticks; | ||
121 | } | ||
122 | else | ||
123 | { | ||
124 | // Its not active -- if its expired then remove it | ||
125 | if (tti.LastSeenActive + ThreadTimeout < DateTime.Now.Ticks) | ||
126 | m_Threads.Remove(tti); | ||
127 | } | ||
128 | } | ||
129 | catch (NullReferenceException) | ||
130 | { | ||
131 | m_Threads.Remove(tti); | ||
132 | } | ||
133 | } | ||
134 | } | ||
135 | } | ||
136 | |||
137 | public static List<Thread> GetThreads() | ||
138 | { | ||
139 | if (m_Threads == null) | ||
140 | return null; | ||
141 | |||
142 | List<Thread> threads = new List<Thread>(); | ||
143 | lock (m_Threads) | ||
144 | { | ||
145 | foreach (ThreadTrackerItem tti in new ArrayList(m_Threads)) | ||
146 | { | ||
147 | threads.Add(tti.Thread); | ||
148 | } | ||
149 | } | ||
150 | return threads; | ||
151 | } | ||
152 | |||
153 | #region Nested type: ThreadTrackerItem | ||
154 | |||
155 | public class ThreadTrackerItem | ||
156 | { | ||
157 | public long LastSeenActive; | ||
158 | public Thread Thread; | ||
159 | } | ||
160 | |||
161 | #endregion | ||
162 | } | 45 | } |
163 | } | 46 | } |
diff --git a/OpenSim/Framework/ThrottleOutPacketType.cs b/OpenSim/Framework/ThrottleOutPacketType.cs index 0843757..fd490a5 100644 --- a/OpenSim/Framework/ThrottleOutPacketType.cs +++ b/OpenSim/Framework/ThrottleOutPacketType.cs | |||
@@ -29,9 +29,9 @@ using System; | |||
29 | 29 | ||
30 | namespace OpenSim.Framework | 30 | namespace OpenSim.Framework |
31 | { | 31 | { |
32 | [Flags] | ||
33 | public enum ThrottleOutPacketType : int | 32 | public enum ThrottleOutPacketType : int |
34 | { | 33 | { |
34 | Unknown = -1, // Also doubles as 'do not throttle' | ||
35 | Resend = 0, | 35 | Resend = 0, |
36 | Land = 1, | 36 | Land = 1, |
37 | Wind = 2, | 37 | Wind = 2, |
@@ -39,11 +39,5 @@ namespace OpenSim.Framework | |||
39 | Task = 4, | 39 | Task = 4, |
40 | Texture = 5, | 40 | Texture = 5, |
41 | Asset = 6, | 41 | Asset = 6, |
42 | Unknown = 7, // Also doubles as 'do not throttle' | ||
43 | Back = 8, | ||
44 | |||
45 | TypeMask = 15, // The mask to mask off the flags | ||
46 | |||
47 | LowPriority = 128 // Additional flags | ||
48 | } | 42 | } |
49 | } | 43 | } |
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index 0851d26..38729c6 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs | |||
@@ -1231,6 +1231,42 @@ namespace OpenSim.Framework | |||
1231 | return (ipaddr1 != null) ? "http://" + ipaddr1.ToString() + ":" + port1 : uri; | 1231 | return (ipaddr1 != null) ? "http://" + ipaddr1.ToString() + ":" + port1 : uri; |
1232 | } | 1232 | } |
1233 | 1233 | ||
1234 | public static byte[] StringToBytes256(string str) | ||
1235 | { | ||
1236 | if (String.IsNullOrEmpty(str)) { return Utils.EmptyBytes; } | ||
1237 | if (str.Length > 254) str = str.Remove(254); | ||
1238 | if (!str.EndsWith("\0")) { str += "\0"; } | ||
1239 | |||
1240 | // Because this is UTF-8 encoding and not ASCII, it's possible we | ||
1241 | // might have gotten an oversized array even after the string trim | ||
1242 | byte[] data = UTF8.GetBytes(str); | ||
1243 | if (data.Length > 256) | ||
1244 | { | ||
1245 | Array.Resize<byte>(ref data, 256); | ||
1246 | data[255] = 0; | ||
1247 | } | ||
1248 | |||
1249 | return data; | ||
1250 | } | ||
1251 | |||
1252 | public static byte[] StringToBytes1024(string str) | ||
1253 | { | ||
1254 | if (String.IsNullOrEmpty(str)) { return Utils.EmptyBytes; } | ||
1255 | if (str.Length > 1023) str = str.Remove(1023); | ||
1256 | if (!str.EndsWith("\0")) { str += "\0"; } | ||
1257 | |||
1258 | // Because this is UTF-8 encoding and not ASCII, it's possible we | ||
1259 | // might have gotten an oversized array even after the string trim | ||
1260 | byte[] data = UTF8.GetBytes(str); | ||
1261 | if (data.Length > 1024) | ||
1262 | { | ||
1263 | Array.Resize<byte>(ref data, 1024); | ||
1264 | data[1023] = 0; | ||
1265 | } | ||
1266 | |||
1267 | return data; | ||
1268 | } | ||
1269 | |||
1234 | #region FireAndForget Threading Pattern | 1270 | #region FireAndForget Threading Pattern |
1235 | 1271 | ||
1236 | public static void FireAndForget(System.Threading.WaitCallback callback) | 1272 | public static void FireAndForget(System.Threading.WaitCallback callback) |
@@ -1247,7 +1283,9 @@ namespace OpenSim.Framework | |||
1247 | { | 1283 | { |
1248 | System.Threading.WaitCallback callback = (System.Threading.WaitCallback)ar.AsyncState; | 1284 | System.Threading.WaitCallback callback = (System.Threading.WaitCallback)ar.AsyncState; |
1249 | 1285 | ||
1250 | callback.EndInvoke(ar); | 1286 | try { callback.EndInvoke(ar); } |
1287 | catch (Exception ex) { m_log.Error("[UTIL]: Asynchronous method threw an exception: " + ex.Message, ex); } | ||
1288 | |||
1251 | ar.AsyncWaitHandle.Close(); | 1289 | ar.AsyncWaitHandle.Close(); |
1252 | } | 1290 | } |
1253 | 1291 | ||