aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Framework')
-rw-r--r--OpenSim/Framework/Communications/Clients/RegionClient.cs79
-rw-r--r--OpenSim/Framework/Parallel.cs207
-rw-r--r--OpenSim/Framework/Servers/BaseOpenSimServer.cs30
-rw-r--r--OpenSim/Framework/Tests/ThreadTrackerTests.cs192
-rw-r--r--OpenSim/Framework/ThreadTracker.cs127
-rw-r--r--OpenSim/Framework/ThrottleOutPacketType.cs8
-rw-r--r--OpenSim/Framework/Util.cs40
7 files changed, 324 insertions, 359 deletions
diff --git a/OpenSim/Framework/Communications/Clients/RegionClient.cs b/OpenSim/Framework/Communications/Clients/RegionClient.cs
index 10be069..220a9b6 100644
--- a/OpenSim/Framework/Communications/Clients/RegionClient.cs
+++ b/OpenSim/Framework/Communications/Clients/RegionClient.cs
@@ -124,9 +124,11 @@ namespace OpenSim.Framework.Communications.Clients
124 // Let's wait for the response 124 // Let's wait for the response
125 //m_log.Info("[REST COMMS]: Waiting for a reply after DoCreateChildAgentCall"); 125 //m_log.Info("[REST COMMS]: Waiting for a reply after DoCreateChildAgentCall");
126 126
127 WebResponse webResponse = null;
128 StreamReader sr = null;
127 try 129 try
128 { 130 {
129 WebResponse webResponse = AgentCreateRequest.GetResponse(); 131 webResponse = AgentCreateRequest.GetResponse();
130 if (webResponse == null) 132 if (webResponse == null)
131 { 133 {
132 m_log.Info("[REST COMMS]: Null reply on DoCreateChildAgentCall post"); 134 m_log.Info("[REST COMMS]: Null reply on DoCreateChildAgentCall post");
@@ -134,11 +136,10 @@ namespace OpenSim.Framework.Communications.Clients
134 else 136 else
135 { 137 {
136 138
137 StreamReader sr = new StreamReader(webResponse.GetResponseStream()); 139 sr = new StreamReader(webResponse.GetResponseStream());
138 string response = sr.ReadToEnd().Trim(); 140 string response = sr.ReadToEnd().Trim();
139 sr.Close();
140 m_log.InfoFormat("[REST COMMS]: DoCreateChildAgentCall reply was {0} ", response); 141 m_log.InfoFormat("[REST COMMS]: DoCreateChildAgentCall reply was {0} ", response);
141 142
142 if (!String.IsNullOrEmpty(response)) 143 if (!String.IsNullOrEmpty(response))
143 { 144 {
144 try 145 try
@@ -167,6 +168,11 @@ namespace OpenSim.Framework.Communications.Clients
167 m_log.InfoFormat("[REST COMMS]: exception on reply of DoCreateChildAgentCall {0}", ex.Message); 168 m_log.InfoFormat("[REST COMMS]: exception on reply of DoCreateChildAgentCall {0}", ex.Message);
168 // ignore, really 169 // ignore, really
169 } 170 }
171 finally
172 {
173 if (sr != null)
174 sr.Close();
175 }
170 176
171 return true; 177 return true;
172 178
@@ -246,15 +252,17 @@ namespace OpenSim.Framework.Communications.Clients
246 // Let's wait for the response 252 // Let's wait for the response
247 //m_log.Info("[REST COMMS]: Waiting for a reply after ChildAgentUpdate"); 253 //m_log.Info("[REST COMMS]: Waiting for a reply after ChildAgentUpdate");
248 254
255 WebResponse webResponse = null;
256 StreamReader sr = null;
249 try 257 try
250 { 258 {
251 WebResponse webResponse = ChildUpdateRequest.GetResponse(); 259 webResponse = ChildUpdateRequest.GetResponse();
252 if (webResponse == null) 260 if (webResponse == null)
253 { 261 {
254 m_log.Info("[REST COMMS]: Null reply on ChilAgentUpdate post"); 262 m_log.Info("[REST COMMS]: Null reply on ChilAgentUpdate post");
255 } 263 }
256 264
257 StreamReader sr = new StreamReader(webResponse.GetResponseStream()); 265 sr = new StreamReader(webResponse.GetResponseStream());
258 //reply = sr.ReadToEnd().Trim(); 266 //reply = sr.ReadToEnd().Trim();
259 sr.ReadToEnd().Trim(); 267 sr.ReadToEnd().Trim();
260 sr.Close(); 268 sr.Close();
@@ -266,6 +274,11 @@ namespace OpenSim.Framework.Communications.Clients
266 m_log.InfoFormat("[REST COMMS]: exception on reply of ChilAgentUpdate {0}", ex.Message); 274 m_log.InfoFormat("[REST COMMS]: exception on reply of ChilAgentUpdate {0}", ex.Message);
267 // ignore, really 275 // ignore, really
268 } 276 }
277 finally
278 {
279 if (sr != null)
280 sr.Close();
281 }
269 282
270 return true; 283 return true;
271 } 284 }
@@ -284,6 +297,7 @@ namespace OpenSim.Framework.Communications.Clients
284 297
285 HttpWebResponse webResponse = null; 298 HttpWebResponse webResponse = null;
286 string reply = string.Empty; 299 string reply = string.Empty;
300 StreamReader sr = null;
287 try 301 try
288 { 302 {
289 webResponse = (HttpWebResponse)request.GetResponse(); 303 webResponse = (HttpWebResponse)request.GetResponse();
@@ -292,9 +306,8 @@ namespace OpenSim.Framework.Communications.Clients
292 m_log.Info("[REST COMMS]: Null reply on agent get "); 306 m_log.Info("[REST COMMS]: Null reply on agent get ");
293 } 307 }
294 308
295 StreamReader sr = new StreamReader(webResponse.GetResponseStream()); 309 sr = new StreamReader(webResponse.GetResponseStream());
296 reply = sr.ReadToEnd().Trim(); 310 reply = sr.ReadToEnd().Trim();
297 sr.Close();
298 311
299 //Console.WriteLine("[REST COMMS]: ChilAgentUpdate reply was " + reply); 312 //Console.WriteLine("[REST COMMS]: ChilAgentUpdate reply was " + reply);
300 313
@@ -305,6 +318,11 @@ namespace OpenSim.Framework.Communications.Clients
305 // ignore, really 318 // ignore, really
306 return false; 319 return false;
307 } 320 }
321 finally
322 {
323 if (sr != null)
324 sr.Close();
325 }
308 326
309 if (webResponse.StatusCode == HttpStatusCode.OK) 327 if (webResponse.StatusCode == HttpStatusCode.OK)
310 { 328 {
@@ -333,6 +351,7 @@ namespace OpenSim.Framework.Communications.Clients
333 request.Method = "DELETE"; 351 request.Method = "DELETE";
334 request.Timeout = 10000; 352 request.Timeout = 10000;
335 353
354 StreamReader sr = null;
336 try 355 try
337 { 356 {
338 WebResponse webResponse = request.GetResponse(); 357 WebResponse webResponse = request.GetResponse();
@@ -341,7 +360,7 @@ namespace OpenSim.Framework.Communications.Clients
341 m_log.Info("[REST COMMS]: Null reply on agent delete "); 360 m_log.Info("[REST COMMS]: Null reply on agent delete ");
342 } 361 }
343 362
344 StreamReader sr = new StreamReader(webResponse.GetResponseStream()); 363 sr = new StreamReader(webResponse.GetResponseStream());
345 //reply = sr.ReadToEnd().Trim(); 364 //reply = sr.ReadToEnd().Trim();
346 sr.ReadToEnd().Trim(); 365 sr.ReadToEnd().Trim();
347 sr.Close(); 366 sr.Close();
@@ -353,6 +372,11 @@ namespace OpenSim.Framework.Communications.Clients
353 m_log.InfoFormat("[REST COMMS]: exception on reply of agent delete {0}", ex.Message); 372 m_log.InfoFormat("[REST COMMS]: exception on reply of agent delete {0}", ex.Message);
354 // ignore, really 373 // ignore, really
355 } 374 }
375 finally
376 {
377 if (sr != null)
378 sr.Close();
379 }
356 380
357 return true; 381 return true;
358 } 382 }
@@ -377,6 +401,7 @@ namespace OpenSim.Framework.Communications.Clients
377 request.Method = "DELETE"; 401 request.Method = "DELETE";
378 request.Timeout = 10000; 402 request.Timeout = 10000;
379 403
404 StreamReader sr = null;
380 try 405 try
381 { 406 {
382 WebResponse webResponse = request.GetResponse(); 407 WebResponse webResponse = request.GetResponse();
@@ -385,7 +410,7 @@ namespace OpenSim.Framework.Communications.Clients
385 m_log.Info("[REST COMMS]: Null reply on agent delete "); 410 m_log.Info("[REST COMMS]: Null reply on agent delete ");
386 } 411 }
387 412
388 StreamReader sr = new StreamReader(webResponse.GetResponseStream()); 413 sr = new StreamReader(webResponse.GetResponseStream());
389 //reply = sr.ReadToEnd().Trim(); 414 //reply = sr.ReadToEnd().Trim();
390 sr.ReadToEnd().Trim(); 415 sr.ReadToEnd().Trim();
391 sr.Close(); 416 sr.Close();
@@ -397,6 +422,11 @@ namespace OpenSim.Framework.Communications.Clients
397 m_log.InfoFormat("[REST COMMS]: exception on reply of agent delete {0}", ex.Message); 422 m_log.InfoFormat("[REST COMMS]: exception on reply of agent delete {0}", ex.Message);
398 // ignore, really 423 // ignore, really
399 } 424 }
425 finally
426 {
427 if (sr != null)
428 sr.Close();
429 }
400 430
401 return true; 431 return true;
402 } 432 }
@@ -463,6 +493,7 @@ namespace OpenSim.Framework.Communications.Clients
463 // Let's wait for the response 493 // Let's wait for the response
464 //m_log.Info("[REST COMMS]: Waiting for a reply after DoCreateChildAgentCall"); 494 //m_log.Info("[REST COMMS]: Waiting for a reply after DoCreateChildAgentCall");
465 495
496 StreamReader sr = null;
466 try 497 try
467 { 498 {
468 WebResponse webResponse = ObjectCreateRequest.GetResponse(); 499 WebResponse webResponse = ObjectCreateRequest.GetResponse();
@@ -471,10 +502,9 @@ namespace OpenSim.Framework.Communications.Clients
471 m_log.Info("[REST COMMS]: Null reply on DoCreateObjectCall post"); 502 m_log.Info("[REST COMMS]: Null reply on DoCreateObjectCall post");
472 } 503 }
473 504
474 StreamReader sr = new StreamReader(webResponse.GetResponseStream()); 505 sr = new StreamReader(webResponse.GetResponseStream());
475 //reply = sr.ReadToEnd().Trim(); 506 //reply = sr.ReadToEnd().Trim();
476 sr.ReadToEnd().Trim(); 507 sr.ReadToEnd().Trim();
477 sr.Close();
478 //m_log.InfoFormat("[REST COMMS]: DoCreateChildAgentCall reply was {0} ", reply); 508 //m_log.InfoFormat("[REST COMMS]: DoCreateChildAgentCall reply was {0} ", reply);
479 509
480 } 510 }
@@ -483,6 +513,11 @@ namespace OpenSim.Framework.Communications.Clients
483 m_log.InfoFormat("[REST COMMS]: exception on reply of DoCreateObjectCall {0}", ex.Message); 513 m_log.InfoFormat("[REST COMMS]: exception on reply of DoCreateObjectCall {0}", ex.Message);
484 // ignore, really 514 // ignore, really
485 } 515 }
516 finally
517 {
518 if (sr != null)
519 sr.Close();
520 }
486 521
487 return true; 522 return true;
488 523
@@ -542,6 +577,7 @@ namespace OpenSim.Framework.Communications.Clients
542 // Let's wait for the response 577 // Let's wait for the response
543 //m_log.Info("[REST COMMS]: Waiting for a reply after DoCreateChildAgentCall"); 578 //m_log.Info("[REST COMMS]: Waiting for a reply after DoCreateChildAgentCall");
544 579
580 StreamReader sr = null;
545 try 581 try
546 { 582 {
547 WebResponse webResponse = ObjectCreateRequest.GetResponse(); 583 WebResponse webResponse = ObjectCreateRequest.GetResponse();
@@ -550,11 +586,10 @@ namespace OpenSim.Framework.Communications.Clients
550 m_log.Info("[REST COMMS]: Null reply on DoCreateObjectCall post"); 586 m_log.Info("[REST COMMS]: Null reply on DoCreateObjectCall post");
551 } 587 }
552 588
553 StreamReader sr = new StreamReader(webResponse.GetResponseStream()); 589 sr = new StreamReader(webResponse.GetResponseStream());
554 sr.ReadToEnd().Trim(); 590 sr.ReadToEnd().Trim();
555 sr.ReadToEnd().Trim(); 591 sr.ReadToEnd().Trim();
556 sr.Close(); 592
557
558 //m_log.InfoFormat("[REST COMMS]: DoCreateChildAgentCall reply was {0} ", reply); 593 //m_log.InfoFormat("[REST COMMS]: DoCreateChildAgentCall reply was {0} ", reply);
559 594
560 } 595 }
@@ -563,6 +598,11 @@ namespace OpenSim.Framework.Communications.Clients
563 m_log.InfoFormat("[REST COMMS]: exception on reply of DoCreateObjectCall {0}", ex.Message); 598 m_log.InfoFormat("[REST COMMS]: exception on reply of DoCreateObjectCall {0}", ex.Message);
564 // ignore, really 599 // ignore, really
565 } 600 }
601 finally
602 {
603 if (sr != null)
604 sr.Close();
605 }
566 606
567 return true; 607 return true;
568 608
@@ -630,6 +670,7 @@ namespace OpenSim.Framework.Communications.Clients
630 // Let's wait for the response 670 // Let's wait for the response
631 //m_log.Info("[REST COMMS]: Waiting for a reply after DoHelloNeighbourCall"); 671 //m_log.Info("[REST COMMS]: Waiting for a reply after DoHelloNeighbourCall");
632 672
673 StreamReader sr = null;
633 try 674 try
634 { 675 {
635 WebResponse webResponse = HelloNeighbourRequest.GetResponse(); 676 WebResponse webResponse = HelloNeighbourRequest.GetResponse();
@@ -638,10 +679,9 @@ namespace OpenSim.Framework.Communications.Clients
638 m_log.Info("[REST COMMS]: Null reply on DoHelloNeighbourCall post"); 679 m_log.Info("[REST COMMS]: Null reply on DoHelloNeighbourCall post");
639 } 680 }
640 681
641 StreamReader sr = new StreamReader(webResponse.GetResponseStream()); 682 sr = new StreamReader(webResponse.GetResponseStream());
642 //reply = sr.ReadToEnd().Trim(); 683 //reply = sr.ReadToEnd().Trim();
643 sr.ReadToEnd().Trim(); 684 sr.ReadToEnd().Trim();
644 sr.Close();
645 //m_log.InfoFormat("[REST COMMS]: DoHelloNeighbourCall reply was {0} ", reply); 685 //m_log.InfoFormat("[REST COMMS]: DoHelloNeighbourCall reply was {0} ", reply);
646 686
647 } 687 }
@@ -650,6 +690,11 @@ namespace OpenSim.Framework.Communications.Clients
650 m_log.InfoFormat("[REST COMMS]: exception on reply of DoHelloNeighbourCall {0}", ex.Message); 690 m_log.InfoFormat("[REST COMMS]: exception on reply of DoHelloNeighbourCall {0}", ex.Message);
651 // ignore, really 691 // ignore, really
652 } 692 }
693 finally
694 {
695 if (sr != null)
696 sr.Close();
697 }
653 698
654 return true; 699 return true;
655 700
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
28using System;
29using System.Collections.Generic;
30using System.Threading;
31
32namespace 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..845a9fe 100644
--- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs
+++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Diagnostics;
30using System.IO; 31using System.IO;
31using System.Reflection; 32using System.Reflection;
32using System.Text; 33using 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,15 @@ 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 );
250 sb.Append( 250 if (t.ThreadState == System.Diagnostics.ThreadState.Wait)
251 "ID: " + t.ManagedThreadId + ", Name: " + t.Name + ", Alive: " + t.IsAlive 251 sb.Append(", Reason: " + t.WaitReason + Environment.NewLine);
252 + ", Pri: " + t.Priority + ", State: " + t.ThreadState + Environment.NewLine);
253 }
254 else 252 else
255 { 253 sb.Append(Environment.NewLine);
256 try 254
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 } 255 }
266 } 256 }
267 int workers = 0, ports = 0, maxWorkers = 0, maxPorts = 0; 257 int workers = 0, ports = 0, maxWorkers = 0, maxPorts = 0;
diff --git a/OpenSim/Framework/Tests/ThreadTrackerTests.cs b/OpenSim/Framework/Tests/ThreadTrackerTests.cs
deleted file mode 100644
index 15d5b73..0000000
--- a/OpenSim/Framework/Tests/ThreadTrackerTests.cs
+++ /dev/null
@@ -1,192 +0,0 @@
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
28using System;
29using NUnit.Framework;
30using System.Threading;
31using System.Collections.Generic;
32
33namespace OpenSim.Framework.Tests
34{
35 [TestFixture]
36 public class ThreadTrackerTests
37 {
38 private bool running = true;
39 private bool running2 = true;
40
41 [Test]
42 public void DefaultThreadTrackerTest()
43 {
44 List<Thread> lThread = ThreadTracker.GetThreads();
45
46 /*
47 foreach (Thread t in lThread)
48 {
49 System.Console.WriteLine(t.Name);
50 }
51 */
52
53 Assert.That(lThread.Count == 1);
54 Assert.That(lThread[0].Name == "ThreadTrackerThread");
55 }
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 }
192}
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
28using System; 28using System;
29using System.Collections;
30using System.Collections.Generic; 29using System.Collections.Generic;
31using System.Reflection; 30using System.Reflection;
32using System.Threading; 31using System.Diagnostics;
33using log4net; 32using log4net;
34 33
35namespace OpenSim.Framework 34namespace 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
30namespace OpenSim.Framework 30namespace 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