Source code: org/apache/derby/iapi/services/sanity/SanityManager.java
1 /*
2
3 Derby - Class org.apache.derby.iapi.services.sanity.SanityManager
4
5 Copyright 1997, 2004 The Apache Software Foundation or its licensors, as applicable.
6
7 Licensed under the Apache License, Version 2.0 (the "License");
8 you may not use this file except in compliance with the License.
9 You may obtain a copy of the License at
10
11 http://www.apache.org/licenses/LICENSE-2.0
12
13 Unless required by applicable law or agreed to in writing, software
14 distributed under the License is distributed on an "AS IS" BASIS,
15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 See the License for the specific language governing permissions and
17 limitations under the License.
18
19 */
20
21 package org.apache.derby.iapi.services.sanity;
22
23
24 import org.apache.derby.iapi.services.sanity.AssertFailure;
25
26 import java.util.Hashtable;
27 import java.util.Enumeration;
28
29 /**
30 * The SanityService provides assertion checking and debug
31 * control.
32 * <p>
33 * Assertions and debug checks
34 * can only be used for testing conditions that might occur
35 * in development code but not in production code.
36 * <b>They are compiled out of production code.</b>
37 * <p>
38 * Uses of assertions should not add AssertFailure catches or
39 * throws clauses; AssertFailure is under RuntimeException
40 * in the java exception hierarchy. Our outermost system block
41 * will bring the system down when it detects an assertion
42 * failure.
43 * <p>
44 * In addition to ASSERTs in code, classes can choose to implement
45 * an isConsistent method that would be used by ASSERTs, UnitTests,
46 * and any other code wanting to check the consistency of an object.
47 * <p>
48 * Assertions are meant to be used to verify the state of the system
49 * and bring the system down if the state is not correct. Debug checks
50 * are meant to display internal information about a running system.
51 * <p>
52 * @see org.apache.derby.iapi.services.sanity.AssertFailure
53 */
54 public class SanityManager {
55 /**
56 * The build tool may be configured to alter
57 * this source file to reset the static final variables
58 * so that assertion and debug checks can be compiled out
59 * of the code.
60 */
61
62 public static final boolean ASSERT = SanityState.ASSERT; // code should use DEBUG
63 public static final boolean DEBUG = SanityState.DEBUG;
64
65 public static final String DEBUGDEBUG = "DumpSanityDebug";
66
67 /**
68 * debugStream holds a pointer to the debug stream for writing out
69 * debug messages. It is cached at the first debug write request.
70 */
71 static private java.io.PrintWriter debugStream = new java.io.PrintWriter(System.err);
72 /**
73 * DebugFlags holds the values of all debug flags in
74 * the configuration file.
75 */
76 static private Hashtable DebugFlags = new Hashtable();
77 /**
78 * AllDebugOn and AllDebugOff override individual flags
79 */
80 static private boolean AllDebugOn = false;
81 static private boolean AllDebugOff = false;
82
83 //
84 // class interface
85 //
86
87 /**
88 * ASSERT checks the condition, and if it is
89 * false, throws AssertFailure.
90 * A message about the assertion failing is
91 * printed.
92 * <p>
93 * @see org.apache.derby.iapi.services.sanity.AssertFailure
94 */
95 public static final void ASSERT(boolean mustBeTrue) {
96 if (DEBUG)
97 if (! mustBeTrue) {
98 if (DEBUG) {
99 AssertFailure af = new AssertFailure("ASSERT FAILED");
100 if (DEBUG_ON("AssertFailureTrace")) {
101 showTrace(af);
102 }
103 throw af;
104 }
105 else
106 throw new AssertFailure("ASSERT FAILED");
107 }
108 }
109
110 /**
111 * ASSERT checks the condition, and if it is
112 * false, throws AssertFailure. The message will
113 * be printed and included in the assertion.
114 * <p>
115 * @see org.apache.derby.iapi.services.sanity.AssertFailure
116 */
117 public static final void ASSERT(boolean mustBeTrue, String msgIfFail) {
118 if (DEBUG)
119 if (! mustBeTrue) {
120 if (DEBUG) {
121 AssertFailure af = new AssertFailure("ASSERT FAILED " + msgIfFail);
122 if (DEBUG_ON("AssertFailureTrace")) {
123 showTrace(af);
124 }
125 throw af;
126 }
127 else
128 throw new AssertFailure("ASSERT FAILED " + msgIfFail);
129 }
130 }
131
132 /**
133 * THROWASSERT throws AssertFailure. This is used in cases where
134 * the caller has already detected the assertion failure (such as
135 * in the default case of a switch). This method should be used,
136 * rather than throwing AssertFailure directly, to allow us to
137 * centralize all sanity checking. The message argument will
138 * be printed and included in the assertion.
139 * <p>
140 * @param msgIfFail message to print with the assertion
141 *
142 * @see org.apache.derby.iapi.services.sanity.AssertFailure
143 */
144 public static final void THROWASSERT(String msgIfFail) {
145 // XXX (nat) Hmm, should we check ASSERT here? The caller is
146 // not expecting this function to return, whether assertions
147 // are compiled in or not.
148
149 if (DEBUG) {
150 AssertFailure af = new AssertFailure("ASSERT FAILED " + msgIfFail);
151 if (DEBUG_ON("AssertFailureTrace")) {
152 showTrace(af);
153 }
154 throw af;
155 }
156 else
157 throw new AssertFailure("ASSERT FAILED " + msgIfFail);
158 }
159
160 /**
161 * THROWASSERT throws AssertFailure.
162 * This flavor will print the stack associated with the exception.
163 * The message argument will
164 * be printed and included in the assertion.
165 * <p>
166 * @param msg message to print with the assertion
167 * @param t exception to print with the assertion
168 *
169 * @see org.apache.derby.iapi.services.sanity.AssertFailure
170 */
171 public static final void THROWASSERT(String msg, Throwable t) {
172
173 if (DEBUG) {
174 AssertFailure af = new AssertFailure("ASSERT FAILED " + t.toString(), t);
175 if (DEBUG_ON("AssertFailureTrace")) {
176 showTrace(af);
177 }
178 showTrace(t);
179 throw af;
180 }
181 else {
182 showTrace(t);
183 throw new AssertFailure("ASSERT FAILED " + t.toString(), t);
184 }
185 }
186
187 /**
188 * THROWASSERT throws AssertFailure.
189 * This flavor will print the stack associated with the exception.
190 * <p>
191 * @param t exception to print with the assertion
192 *
193 * @see org.apache.derby.iapi.services.sanity.AssertFailure
194 */
195 public static final void THROWASSERT(Throwable t) {
196
197 if (DEBUG) {
198 AssertFailure af = new AssertFailure("ASSERT FAILED " + t.toString(), t);
199 if (DEBUG_ON("AssertFailureTrace")) {
200 showTrace(af);
201 }
202 showTrace(t);
203 throw af;
204 }
205 else {
206 showTrace(t);
207 throw new AssertFailure("ASSERT FAILED " + t.toString(), t);
208 }
209 }
210
211 /**
212 * The DEBUG calls provide the ability to print information or
213 * perform actions based on whether a debug flag is set or not.
214 * debug flags are set in configurations and picked up by the
215 * sanity manager when the monitor finds them (see CONFIG below).
216 * <p>
217 * The message is output to the trace stream, so it ends up in
218 * db2j.LOG. It will include a header line of
219 * DEBUG <flagname> OUTPUT:
220 * before the message.
221 * <p>
222 * If the debugStream stream cannot be found, the message is printed to
223 * System.out.
224 */
225 public static final void DEBUG(String flag, String message) {
226 if (DEBUG) {
227 if (DEBUG_ON(flag)) {
228 DEBUG_PRINT(flag, message);
229 }
230 }
231 }
232
233 /**
234 * This can be called directly if you want to control
235 * what is done once the debug flag has been verified --
236 * for example, if you are calling a routine that prints to
237 * the trace stream directly rather than returning a string to
238 * be printed, or if you want to perform more (or fewer!)
239 *
240 * <p>
241 * Calls to this method should be surrounded with
242 * if (SanityManager.DEBUG) {
243 * }
244 * so that they can be compiled out completely.
245 *
246 * @return true if the flag has been set to "true"; false
247 * if the flag is not set, or is set to something other than "true".
248 */
249 public static final boolean DEBUG_ON(String flag) {
250 if (DEBUG) {
251 if (AllDebugOn) return true;
252 else if (AllDebugOff) return false;
253 else {
254 Boolean flagValue = (Boolean) DebugFlags.get(flag);
255 if (! DEBUGDEBUG.equals(flag)) {
256 if (DEBUG_ON(DEBUGDEBUG)) {
257 DEBUG_PRINT(DEBUGDEBUG, "DEBUG_ON: Debug flag "+flag+" = "+flagValue);
258 }
259 }
260 if (flagValue == null) return false;
261 else return flagValue.booleanValue();
262 }
263 }
264 else return false;
265 }
266
267 /**
268 * Set the named debug flag to true.
269 *
270 * <p>
271 * Calls to this method should be surrounded with
272 * if (SanityManager.DEBUG) {
273 * }
274 * so that they can be compiled out completely.
275 *
276 * @param flag The name of the debug flag to set to true
277 *
278 * @return Nothing
279 */
280 public static final void DEBUG_SET(String flag) {
281 if (DEBUG) {
282 if (! DEBUGDEBUG.equals(flag)) {
283 if (DEBUG_ON(DEBUGDEBUG))
284 DEBUG_PRINT(DEBUGDEBUG, "DEBUG_SET: Debug flag " + flag);
285 }
286
287 DebugFlags.put(flag, Boolean.TRUE);
288 }
289 }
290
291 /**
292 * Set the named debug flag to false.
293 *
294 * <p>
295 * Calls to this method should be surrounded with
296 * if (SanityManager.DEBUG) {
297 * }
298 * so that they can be compiled out completely.
299 *
300 * @param flag The name of the debug flag to set to false
301 *
302 * @return Nothing
303 */
304 public static final void DEBUG_CLEAR(String flag) {
305 if (DEBUG) {
306 if (! DEBUGDEBUG.equals(flag)) {
307 if (DEBUG_ON(DEBUGDEBUG))
308 DEBUG_PRINT(DEBUGDEBUG, "DEBUG_CLEAR: Debug flag " + flag);
309 }
310
311 DebugFlags.put(flag, Boolean.FALSE);
312 }
313 }
314
315 /**
316 * This can be used to have the SanityManager return TRUE
317 * for any DEBUG_ON check. DEBUG_CLEAR of an individual
318 * flag will appear to have no effect.
319 */
320 public static final void DEBUG_ALL_ON() {
321 if (DEBUG) {
322 AllDebugOn = true;
323 AllDebugOff = false;
324 }
325 }
326
327 /**
328 * This can be used to have the SanityManager return FALSE
329 * for any DEBUG_ON check. DEBUG_SET of an individual
330 * flag will appear to have no effect.
331 */
332 public static final void DEBUG_ALL_OFF() {
333 if (DEBUG) {
334 AllDebugOff = true;
335 AllDebugOn = false;
336 }
337 }
338
339 //
340 // class implementation
341 //
342
343 static public void SET_DEBUG_STREAM(java.io.PrintWriter pw) {
344 debugStream = pw;
345 }
346
347 static public java.io.PrintWriter GET_DEBUG_STREAM() {
348 return debugStream;
349 }
350
351 static private void showTrace(AssertFailure af) {
352 af.printStackTrace();
353 java.io.PrintWriter assertStream = GET_DEBUG_STREAM();
354
355 assertStream.println("Assertion trace:");
356 af.printStackTrace(assertStream);
357 assertStream.flush();
358 }
359
360 static public void showTrace(Throwable t) {
361 java.io.PrintWriter assertStream = GET_DEBUG_STREAM();
362
363 assertStream.println("Exception trace: ");
364 t.printStackTrace(assertStream);
365 }
366
367 /**
368 * The DEBUG_PRINT calls provides a convenient way to print debug
369 * information to the db2j.LOG file, The message includes a header
370 *<p>
371 * DEBUG <flag> OUTPUT:
372 * before the message
373 *<p>
374 * If the debugStream stream cannot be found, the message is printed to
375 * System.out.
376 *
377 */
378 static public void DEBUG_PRINT(String flag, String message) {
379 java.io.PrintWriter debugStream = GET_DEBUG_STREAM();
380
381 debugStream.println("DEBUG "+flag+" OUTPUT: " + message);
382 debugStream.flush();
383 }
384
385 public static void NOTREACHED() {
386 THROWASSERT("code should not be reached");
387 }
388 }
389