6890780312993d035f3523352751a6227bb17c4b
[mono.git] / mcs / class / referencesource / System / compmod / system / diagnostics / TraceInternal.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="TraceInternal.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>                                                                
5 //------------------------------------------------------------------------------
6
7 namespace System.Diagnostics {
8     using System.Threading;
9     using System.IO;
10     using System.Security.Permissions;
11     using System.Collections;
12
13     internal static class TraceInternal {
14         private static volatile string appName = null;
15         static volatile TraceListenerCollection listeners;
16         static volatile bool autoFlush;
17         static volatile bool useGlobalLock;
18         [ThreadStatic]
19         static int indentLevel;
20         static volatile int indentSize;
21         static volatile bool settingsInitialized;
22         static volatile bool defaultInitialized;
23
24
25         // this is internal so TraceSource can use it.  We want to lock on the same object because both TraceInternal and 
26         // TraceSource could be writing to the same listeners at the same time. 
27         internal static readonly object critSec = new object();
28
29         public static TraceListenerCollection Listeners { 
30             get {
31                 InitializeSettings();
32                 if (listeners == null) {
33                     lock (critSec) {
34                         if (listeners == null) {
35                             // We only need to check that the main section exists.  Everything else will get 
36                             // created for us if it doesn't exist already. 
37 #if CONFIGURATION_DEP
38                             SystemDiagnosticsSection configSectionSav = DiagnosticsConfiguration.SystemDiagnosticsSection;
39                             if (configSectionSav != null) {
40                                 listeners = configSectionSav.Trace.Listeners.GetRuntimeObject();
41                             }
42                             else {
43 #endif
44                                 // If machine.config was deleted the code will get to here
45                                 // supply at least something to prevent the world from coming to
46                                 // an abrupt end. 
47                                 listeners = new TraceListenerCollection();
48                                 TraceListener defaultListener = new DefaultTraceListener();
49                                 defaultListener.IndentLevel = indentLevel;
50                                 defaultListener.IndentSize = indentSize;
51                                 listeners.Add(defaultListener);
52 #if CONFIGURATION_DEP
53                             }
54 #endif
55                         }
56                     }
57                 }
58                 return listeners;
59             }
60         }
61
62         internal static string AppName {
63             get {
64                 if (appName == null) {
65                     new EnvironmentPermission(EnvironmentPermissionAccess.Read, "Path").Assert();
66                     appName = Path.GetFileName(Environment.GetCommandLineArgs()[0]);
67                 }
68                 return appName;
69             }
70         }
71         
72         public static bool AutoFlush { 
73             get { 
74                 InitializeSettings();
75                 return autoFlush; 
76             }
77
78             set {
79                 InitializeSettings();    
80                 autoFlush = value;
81             }
82         }
83
84         public static bool UseGlobalLock { 
85             get { 
86                 InitializeSettings();
87                 return useGlobalLock; 
88             }
89
90             set {
91                 InitializeSettings();    
92                 useGlobalLock = value;
93             }
94         }
95         
96         public static int IndentLevel {
97             get { return indentLevel; }
98
99             set {
100                 // Use global lock
101                 lock (critSec) {
102                     // We don't want to throw here -- it is very bad form to have debug or trace
103                     // code throw exceptions!
104                     if (value < 0) {
105                         value = 0;
106                     }
107                     indentLevel = value;
108                     
109                     if (listeners != null) {
110                         foreach (TraceListener listener in Listeners) {
111                             listener.IndentLevel = indentLevel;
112                         }
113                     }
114                 }
115             }
116         }
117
118         public static int IndentSize {
119             get { 
120                 InitializeSettings();
121                 return indentSize; 
122             }
123             
124             set {
125                 InitializeSettings();    
126                 SetIndentSize(value);
127             }
128         }
129
130         static void SetIndentSize(int value) {
131             // Use global lock
132             lock (critSec) {                
133                 // We don't want to throw here -- it is very bad form to have debug or trace
134                 // code throw exceptions!            
135                 if (value < 0) {
136                     value = 0;
137                 }
138
139                 indentSize = value;
140                 
141                 if (listeners != null) {
142                     foreach (TraceListener listener in Listeners) {
143                         listener.IndentSize = indentSize;
144                     }
145                 } 
146             }
147         }
148
149         public static void Indent() {
150             // Use global lock
151             lock (critSec) {
152                 InitializeSettings();
153                 if (indentLevel < Int32.MaxValue) {
154                     indentLevel++;
155                 }
156                 foreach (TraceListener listener in Listeners) {
157                     listener.IndentLevel = indentLevel;
158                 }
159             }
160         }
161
162         public static void Unindent() {
163             // Use global lock
164             lock (critSec) {
165                 InitializeSettings();
166                 if (indentLevel > 0) {
167                     indentLevel--;
168                 }
169                 foreach (TraceListener listener in Listeners) {
170                     listener.IndentLevel = indentLevel;
171                 }
172             }
173         }
174
175         public static void Flush() {
176             if (listeners != null) {
177                 if (UseGlobalLock) {
178                     lock (critSec) {
179                         foreach (TraceListener listener in Listeners) {
180                             listener.Flush();
181                         }            
182                     }
183                 }
184                 else {
185                     foreach (TraceListener listener in Listeners) {
186                         if (!listener.IsThreadSafe) {
187                             lock (listener) {
188                                 listener.Flush();
189                             }
190                         }
191                         else {
192                             listener.Flush();
193                         }
194                     }            
195                 }
196             }
197         }
198
199         public static void Close() {
200             if (listeners != null) {
201                 // Use global lock
202                 lock (critSec) {
203                     foreach (TraceListener listener in Listeners) {
204                         listener.Close();
205                     }            
206                 }
207             }
208         }
209
210         public static void Assert(bool condition) {
211             if (condition) return;
212             Fail(string.Empty);
213         }
214
215         public static void Assert(bool condition, string message) {
216             if (condition) return;
217             Fail(message);
218         }
219
220         public static void Assert(bool condition, string message, string detailMessage) {
221             if (condition) return;
222             Fail(message, detailMessage);
223         }
224
225         public static void Fail(string message) {
226             if (UseGlobalLock) {
227                 lock (critSec) {
228                     foreach (TraceListener listener in Listeners) {
229                         listener.Fail(message);
230                         if (AutoFlush) listener.Flush();
231                     }            
232                 }
233             }
234             else {
235                 foreach (TraceListener listener in Listeners) {
236                     if (!listener.IsThreadSafe) {
237                         lock (listener) {
238                             listener.Fail(message);
239                             if (AutoFlush) listener.Flush();
240                         }
241                     }
242                     else {
243                         listener.Fail(message);
244                         if (AutoFlush) listener.Flush();
245                     }
246                 }            
247             }
248         }        
249
250         public static void Fail(string message, string detailMessage) {
251             if (UseGlobalLock) {
252                 lock (critSec) {
253                     foreach (TraceListener listener in Listeners) {
254                         listener.Fail(message, detailMessage);
255                         if (AutoFlush) listener.Flush();
256                     }            
257                 }
258             }
259             else {
260                 foreach (TraceListener listener in Listeners) {
261                     if (!listener.IsThreadSafe) {
262                         lock (listener) {
263                             listener.Fail(message, detailMessage);
264                             if (AutoFlush) listener.Flush();
265                         }
266                     }
267                     else {
268                         listener.Fail(message, detailMessage);
269                         if (AutoFlush) listener.Flush();
270                     }
271                 }            
272             }
273         }        
274
275         private static void InitializeSettings() {
276 #if CONFIGURATION_DEP
277             // we want to redo this logic exactly once if the last time we entered the config
278             // system was still initializing.  (ASURT 111941, VSWhidbey 149552)
279             if (!settingsInitialized || (defaultInitialized && DiagnosticsConfiguration.IsInitialized())) {
280                 // we should avoid 2 threads altering the state concurrently for predictable behavior
281                 // though it may not be strictly necessary at present
282                 lock(critSec) {
283                     if (!settingsInitialized || (defaultInitialized && DiagnosticsConfiguration.IsInitialized())) {
284                         defaultInitialized = DiagnosticsConfiguration.IsInitializing();
285     
286                         // Getting IndentSize and AutoFlush will load config on demand.
287                         // If we load config and there are trace listeners added, we'll
288                         // end up recursing, but that recursion will be stopped in
289                         // DiagnosticsConfiguration.Initialize()           
290                         SetIndentSize(DiagnosticsConfiguration.IndentSize);
291                         autoFlush = DiagnosticsConfiguration.AutoFlush;
292                         useGlobalLock = DiagnosticsConfiguration.UseGlobalLock;
293                         settingsInitialized = true;
294                     }
295                 }
296             }
297 #endif
298         }
299
300         // This method refreshes all the data from the configuration file, so that updated to the configuration file are mirrored
301         // in the System.Diagnostics.Trace class
302         static internal void Refresh() {
303             lock (critSec) {
304                 settingsInitialized = false;
305                 listeners = null;
306             }
307             InitializeSettings();
308         }
309
310         public static void TraceEvent(TraceEventType eventType, int id, string format, params object[] args) {
311
312             TraceEventCache EventCache = new TraceEventCache();
313
314             if (UseGlobalLock) {
315                 lock (critSec) {
316                     if (args == null) {
317                         foreach (TraceListener listener in Listeners) {
318                             listener.TraceEvent(EventCache, AppName, eventType, id, format);
319                             if (AutoFlush) listener.Flush();
320                         }
321                     }
322                     else {
323                         foreach (TraceListener listener in Listeners) {
324                             listener.TraceEvent(EventCache, AppName, eventType, id, format, args);
325                             if (AutoFlush) listener.Flush();
326                         }
327                     }
328                 }
329             }
330             else {
331                 if (args == null) {
332                     foreach (TraceListener listener in Listeners) {
333                         if (!listener.IsThreadSafe) {
334                             lock (listener) {
335                                 listener.TraceEvent(EventCache, AppName, eventType, id, format);
336                                 if (AutoFlush) listener.Flush();
337                             }
338                         }
339                         else {
340                             listener.TraceEvent(EventCache, AppName, eventType, id, format);
341                             if (AutoFlush) listener.Flush();
342                         }
343                     }
344                 }
345                 else {
346                     foreach (TraceListener listener in Listeners) {
347                         if (!listener.IsThreadSafe) {
348                             lock (listener) {
349                                 listener.TraceEvent(EventCache, AppName, eventType, id, format, args);
350                                 if (AutoFlush) listener.Flush();
351                             }
352                         }
353                         else {
354                             listener.TraceEvent(EventCache, AppName, eventType, id, format, args);
355                             if (AutoFlush) listener.Flush();
356                         }
357                     }
358                 }
359             }
360         }
361         
362
363         public static void Write(string message) {
364             if (UseGlobalLock) {
365                 lock (critSec) {
366                     foreach (TraceListener listener in Listeners) {
367                         listener.Write(message);
368                         if (AutoFlush) listener.Flush();
369                     }                        
370                 }
371             }
372             else {
373                 foreach (TraceListener listener in Listeners) {
374                     if (!listener.IsThreadSafe) {
375                         lock (listener) {
376                             listener.Write(message);
377                             if (AutoFlush) listener.Flush();
378                         }
379                     }
380                     else {
381                         listener.Write(message);
382                         if (AutoFlush) listener.Flush();
383                     }
384                 }                        
385             }
386         }
387
388         public static void Write(object value) {
389             if (UseGlobalLock) {
390                 lock (critSec) {
391                     foreach (TraceListener listener in Listeners) {
392                         listener.Write(value);
393                         if (AutoFlush) listener.Flush();
394                     }                        
395                 }
396             }
397             else {
398                 foreach (TraceListener listener in Listeners) {
399                     if (!listener.IsThreadSafe) {
400                         lock (listener) {
401                             listener.Write(value);
402                             if (AutoFlush) listener.Flush();
403                         }
404                     }
405                     else {
406                         listener.Write(value);
407                         if (AutoFlush) listener.Flush();
408                     }
409                 }                        
410             }
411         }
412
413         public static void Write(string message, string category) {
414             if (UseGlobalLock) {
415                 lock (critSec) {
416                     foreach (TraceListener listener in Listeners) {
417                         listener.Write(message, category);
418                         if (AutoFlush) listener.Flush();
419                     }                        
420                 }
421             }
422             else {
423                 foreach (TraceListener listener in Listeners) {
424                     if (!listener.IsThreadSafe) {
425                         lock (listener) {
426                             listener.Write(message, category);
427                             if (AutoFlush) listener.Flush();
428                         }
429                     }
430                     else {
431                         listener.Write(message, category);
432                         if (AutoFlush) listener.Flush();
433                     }
434                 }                        
435             }
436         }
437
438         public static void Write(object value, string category) {
439             if (UseGlobalLock) {
440                 lock (critSec) {
441                     foreach (TraceListener listener in Listeners) {
442                         listener.Write(value, category);
443                         if (AutoFlush) listener.Flush();
444                     }                        
445                 }
446             }
447             else {
448                 foreach (TraceListener listener in Listeners) {
449                     if (!listener.IsThreadSafe) {
450                         lock (listener) {
451                             listener.Write(value, category);
452                             if (AutoFlush) listener.Flush();
453                         }
454                     }
455                     else {
456                         listener.Write(value, category);
457                         if (AutoFlush) listener.Flush();
458                     }
459                 }                        
460             }
461         }
462
463         public static void WriteLine(string message) {
464             if (UseGlobalLock) {
465                 lock (critSec) {
466                     foreach (TraceListener listener in Listeners) {
467                         listener.WriteLine(message);
468                         if (AutoFlush) listener.Flush();
469                     }                        
470                 }
471             }
472             else {
473                 foreach (TraceListener listener in Listeners) {
474                     if (!listener.IsThreadSafe) {
475                         lock (listener) {
476                             listener.WriteLine(message);
477                             if (AutoFlush) listener.Flush();
478                         }
479                     }
480                     else {
481                         listener.WriteLine(message);
482                         if (AutoFlush) listener.Flush();
483                     }
484                 }                        
485             }
486         }
487
488         public static void WriteLine(object value) {
489             if (UseGlobalLock) {
490                 lock (critSec) {
491                     foreach (TraceListener listener in Listeners) {
492                         listener.WriteLine(value);
493                         if (AutoFlush) listener.Flush();
494                     }                        
495                 }
496             }
497             else {
498                 foreach (TraceListener listener in Listeners) {
499                     if (!listener.IsThreadSafe) {
500                         lock (listener) {
501                             listener.WriteLine(value);
502                             if (AutoFlush) listener.Flush();
503                         }
504                     }
505                     else {
506                         listener.WriteLine(value);
507                         if (AutoFlush) listener.Flush();
508                     }
509                 }                        
510             }
511         }
512
513         public static void WriteLine(string message, string category) {
514             if (UseGlobalLock) {
515                 lock (critSec) {
516                     foreach (TraceListener listener in Listeners) {
517                         listener.WriteLine(message, category);
518                         if (AutoFlush) listener.Flush();
519                     }                        
520                 }
521             }
522             else {
523                 foreach (TraceListener listener in Listeners) {
524                     if (!listener.IsThreadSafe) {
525                         lock (listener) {
526                             listener.WriteLine(message, category);
527                             if (AutoFlush) listener.Flush();
528                         }
529                     }
530                     else {
531                         listener.WriteLine(message, category);
532                         if (AutoFlush) listener.Flush();
533                     }
534                 }                        
535             }
536         }
537
538         public static void WriteLine(object value, string category) {
539             if (UseGlobalLock) {
540                 lock (critSec) {
541                     foreach (TraceListener listener in Listeners) {
542                         listener.WriteLine(value, category);
543                         if (AutoFlush) listener.Flush();
544                     }                        
545                 }
546             }
547             else {
548                 foreach (TraceListener listener in Listeners) {
549                     if (!listener.IsThreadSafe) {
550                         lock (listener) {
551                             listener.WriteLine(value, category);
552                             if (AutoFlush) listener.Flush();
553                         }
554                     }
555                     else {
556                         listener.WriteLine(value, category);
557                         if (AutoFlush) listener.Flush();
558                     }
559                 }                        
560             }
561         }
562
563         public static void WriteIf(bool condition, string message) {
564             if (condition)
565                 Write(message);
566         }
567
568         public static void WriteIf(bool condition, object value) {
569             if (condition)
570                 Write(value);
571         }
572
573         public static void WriteIf(bool condition, string message, string category) {
574             if (condition)
575                 Write(message, category);
576         }
577
578         public static void WriteIf(bool condition, object value, string category) {
579             if (condition)
580                 Write(value, category);
581         }
582
583         public static void WriteLineIf(bool condition, string message) {
584             if (condition)
585                 WriteLine(message);
586         }
587
588         public static void WriteLineIf(bool condition, object value) {
589             if (condition)
590                 WriteLine(value);
591         }
592
593         public static void WriteLineIf(bool condition, string message, string category) {
594             if (condition)
595                 WriteLine(message, category);
596         }
597
598         public static void WriteLineIf(bool condition, object value, string category) {
599             if (condition)
600                 WriteLine(value, category);
601         }
602     }
603 }