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