diff options
Diffstat (limited to 'OpenSim/Framework')
-rw-r--r-- | OpenSim/Framework/Communications/Clients/RegionClient.cs | 79 | ||||
-rw-r--r-- | OpenSim/Framework/Parallel.cs | 207 | ||||
-rw-r--r-- | OpenSim/Framework/Servers/BaseOpenSimServer.cs | 30 | ||||
-rw-r--r-- | OpenSim/Framework/Tests/ThreadTrackerTests.cs | 192 | ||||
-rw-r--r-- | OpenSim/Framework/ThreadTracker.cs | 127 | ||||
-rw-r--r-- | OpenSim/Framework/ThrottleOutPacketType.cs | 8 | ||||
-rw-r--r-- | OpenSim/Framework/Util.cs | 40 |
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 | |||
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..845a9fe 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,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 | |||
28 | using System; | ||
29 | using NUnit.Framework; | ||
30 | using System.Threading; | ||
31 | using System.Collections.Generic; | ||
32 | |||
33 | namespace 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 | ||
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 | ||