1 thilo.boehm 1.1 //%2006////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
4 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
5 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
6 // IBM Corp.; EMC Corporation, The Open Group.
7 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
9 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
11 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining a copy
15 // of this software and associated documentation files (the "Software"), to
16 // deal in the Software without restriction, including without limitation the
17 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
18 // sell copies of the Software, and to permit persons to whom the Software is
19 // furnished to do so, subject to the following conditions:
20 //
21 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
22 thilo.boehm 1.1 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
23 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
24 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
25 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
27 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30 //==============================================================================
31 //
32 //%/////////////////////////////////////////////////////////////////////////////
33
|
34 kumpf 1.4 // This _ISOC99_SOURCE definition and inclusion of stdio.h and stdarg.h
35 // must precede the other file contents on z/OS.
|
36 r.kieninger 1.10 #if defined(PEGASUS_OS_ZOS)
|
37 kumpf 1.4 # define _ISOC99_SOURCE
38 #endif
|
39 thilo.boehm 1.1 #include <stdio.h>
40 #include <stdarg.h>
41
42 #include <Pegasus/Common/TraceMemoryHandler.h>
43 #include <iostream>
44 #include <fstream>
45
|
46 venkat.puvvada 1.7 // ATTN: This is a workaround to allow HP-UX and Windows builds to succeed.
47 // It appears to work, but it may not be reliable. A better solution would be
48 // preferred.
49 #if defined(PEGASUS_OS_HPUX) || defined(PEGASUS_OS_TYPE_WINDOWS)
|
50 kumpf 1.4 # ifndef va_copy
51 # define va_copy(dest, src) (void)((dest) = (src))
52 # endif
53 #endif
54
|
55 thilo.boehm 1.1
56 PEGASUS_USING_STD;
57
58 PEGASUS_NAMESPACE_BEGIN
59
60 ////////////////////////////////////////////////////////////////////////////////
|
61 thilo.boehm 1.9 // Constructs TraceMemoryHandler with a custom buffer size
|
62 thilo.boehm 1.1 ////////////////////////////////////////////////////////////////////////////////
|
63 thilo.boehm 1.9 TraceMemoryHandler::TraceMemoryHandler():
64 _overflowBuffer(0),
65 _overflowBufferSize(0),
66 _traceArea(0),
67 _leftBytesInBuffer(0),
68 _inUseCounter(0),
69 _lockCounter(1),
70 _dying(false),
71 _contentionCount(0),
72 _numberOfLocksObtained(0),
73 _traceFileName(0)
|
74 thilo.boehm 1.1 {
75
|
76 kumpf 1.3
|
77 thilo.boehm 1.1 }
78
79 ////////////////////////////////////////////////////////////////////////////////
80 // Private method to (re-)initialize the memory buffer
81 ////////////////////////////////////////////////////////////////////////////////
|
82 thilo.boehm 1.9 void TraceMemoryHandler::_initializeTraceArea()
|
83 thilo.boehm 1.1 {
|
84 thilo.boehm 1.9 if (_traceArea)
85 {
86 delete _traceArea;
87 }
88
89 // get the memory buffer size from the tracer instance.
90 Uint32 traceAreaSize =
91 Tracer::_getInstance()->_traceMemoryBufferSize * 1024;
|
92 kumpf 1.3
|
93 thilo.boehm 1.1 _traceArea = (struct traceArea_t*) new char[traceAreaSize];
|
94 kumpf 1.3
|
95 thilo.boehm 1.1 // The final buffer size is the size of the allocated area, less the
96 // size of the header struct, less one byte reseved for a terminating 0
|
97 kumpf 1.2 _traceArea->bufferSize = traceAreaSize - sizeof(struct traceArea_t) - 1;
|
98 thilo.boehm 1.1 _traceArea->nextPos = 0;
|
99 kumpf 1.2 _traceArea->traceBuffer = (char*) (&(_traceArea->traceBuffer) + 1);
|
100 thilo.boehm 1.1 _leftBytesInBuffer = _traceArea->bufferSize-1;
|
101 kumpf 1.3
102 memcpy(_traceArea->eyeCatcher,
|
103 thilo.boehm 1.1 PEGASUS_TRC_BUFFER_EYE_CATCHER,
104 PEGASUS_TRC_BUFFER_EYE_CATCHER_LEN);
|
105 kumpf 1.3
106 _appendMarker();
|
107 thilo.boehm 1.1
108 // The end of the trace buffer is always null terminated
109 _traceArea->traceBuffer[_traceArea->bufferSize] = '\0';
110 }
111
112 ////////////////////////////////////////////////////////////////////////////////
113 // Destructs TraceMemoryHandler
114 ////////////////////////////////////////////////////////////////////////////////
115 TraceMemoryHandler::~TraceMemoryHandler()
116 {
117 // Signal to all callers and work in progress that this instance
|
118 kumpf 1.3 // will be destroyed soon.
|
119 thilo.boehm 1.1 // As from now, no other caller can get the the lock. They are blocked out.
120 die();
|
121 kumpf 1.3
|
122 thilo.boehm 1.1 // Debug code for the time being
123 // dumpTraceBuffer("cimserver.memorydump.trc");
|
124 kumpf 1.3
|
125 thilo.boehm 1.1 // Wait until all users have left the critical section
126 while ( _inUseCounter.get() > 0 )
127 {
128 // In any case, lock the buffer unconditional
|
129 kumpf 1.3 _lockCounter.set(0);
|
130 thilo.boehm 1.1 // Wait for 10ms, to give other therads to finish work.
131 Threads::sleep(10);
132 }
133
134 delete[] _overflowBuffer;
135 delete[] _traceArea;
|
136 kumpf 1.3
|
137 thilo.boehm 1.1 delete[] _traceFileName;
138 }
139
140 ////////////////////////////////////////////////////////////////////////////////
141 // Request to lock the memory buffer for writing a trace message.
142 //
143 // The locking of the memory buffer is implemented using a spinlock over
144 // an atomic int. The lock is obtained when the atomic lock counter increment
145 // results in a lock count of 1. Otherwise the lock count is decremented
146 // and incremented again until we end up at 1.
147 // To be able to replace in instance of the TraceMemoryHandler, two flags
148 // are kept around to control the lock processing:
|
149 kumpf 1.3 // _dying: This flag indicates that the traceMemoryHandler will soon be
|
150 thilo.boehm 1.1 // destroyed and cannot be used any more. Active attempts to obtain
151 // a lock are given up, leaving the spin loop.
152 // _inUseCounter: Keeps track of how many callers are trying to obtain a lock
153 // or currently hold the lock. This allows the destructor to
154 // wait for all callers to complete before destroying the
155 // instance.
156 ////////////////////////////////////////////////////////////////////////////////
157 inline Boolean TraceMemoryHandler::_lockBufferAccess()
158 {
159 if ( _dying )
160 {
|
161 kumpf 1.3 // The memory tracing is about to end.
|
162 thilo.boehm 1.1 // The caller will never get the lock.
163 return false;
164 }
165
166 // Keep track of work in progress
167 _inUseCounter.inc();
|
168 kumpf 1.3
|
169 thilo.boehm 1.1 // The lock is implemented as a spin loop, since the action to append
170 // a trace message to the memory buffer is very short.
171 while ( true )
172 {
173 if ( _dying )
174 {
|
175 kumpf 1.3 // The memory tracing is about to end.
|
176 thilo.boehm 1.1 // The caller will never get the lock.
177 _inUseCounter.dec();
|
178 kumpf 1.3 break;
|
179 thilo.boehm 1.1 }
180
181 // If the lock counter not 1,an other caller is in the critical section.
182 if ( _lockCounter.get() == 1 )
183 {
184 // Decrement the atomic lock counter and test if we do have lock:
|
185 kumpf 1.3 // _lockCounter == 0
|
186 thilo.boehm 1.1 if ( _lockCounter.decAndTestIfZero() )
187 {
|
188 kumpf 1.3 // We do have lock!
|
189 thilo.boehm 1.1 _numberOfLocksObtained++;
190 return true;
191 }
192 }
193 // I did not get the lock. So signal the scheduer to change the active
|
194 kumpf 1.3 // thread to allow other threads to proceed. This also prevents from
195 // looping in a tight loop that causes a dead look due to the
|
196 thilo.boehm 1.1 // lock optaining thread does not get any time ot finsh his work.
197 Threads::yield();
198 _contentionCount.inc();
|
199 kumpf 1.3 }
200
|
201 thilo.boehm 1.1 return false;
202 }
203
204 ////////////////////////////////////////////////////////////////////////////////
205 // Unlock the memory buffer when no longer used for writing.
206 ////////////////////////////////////////////////////////////////////////////////
207 inline void TraceMemoryHandler::_unlockBufferAccess()
208 {
|
209 kumpf 1.3 // set the lock counter to 1 to allow one next user to enter
|
210 thilo.boehm 1.1 // the critical section.
211 _lockCounter.set(1);
212 _inUseCounter.dec();
213 }
214
215
216 ////////////////////////////////////////////////////////////////////////////////
217 // Tells an instance of the traceMemoryHandler that it will be destructed
218 // soon and should accept no more requests for trace messages.
219 ////////////////////////////////////////////////////////////////////////////////
220 inline void TraceMemoryHandler::die()
221 {
222 _dying = true;
223 }
224
225 ////////////////////////////////////////////////////////////////////////////////
226 // Appends a marker after the last trace message in the buffer
|
227 kumpf 1.3 // The pointer for loction of the next message is not moved,
|
228 thilo.boehm 1.1 // because the marker must be overwritten by the next message it self.
229 ////////////////////////////////////////////////////////////////////////////////
230 void TraceMemoryHandler::_appendMarker()
231 {
232 if (_leftBytesInBuffer > PEGASUS_TRC_BUFFER_EOT_MARKER_LEN )
233 {
234 // Marker does fit inot the buffer, so ...
235 // ... append it the end of the last written message.
236 memcpy(&(_traceArea->traceBuffer[_traceArea->nextPos]),
237 PEGASUS_TRC_BUFFER_EOT_MARKER,
238 PEGASUS_TRC_BUFFER_EOT_MARKER_LEN );
239 }
240 else
241 {
242 // Marker does not fit into the buffer, so ...
243 // ... blank out the remainder of the buffer
244 memset(&(_traceArea->traceBuffer[_traceArea->nextPos]),
245 0,
246 _leftBytesInBuffer);
247
248 // ... and put marker to the front of the buffer
249 thilo.boehm 1.1 memcpy(&(_traceArea->traceBuffer[0]),
250 PEGASUS_TRC_BUFFER_EOT_MARKER,
251 PEGASUS_TRC_BUFFER_EOT_MARKER_LEN );
252 }
253 }
254
255 ////////////////////////////////////////////////////////////////////////////////
256 // Dumps the buffer to a given file.
257 // This function is not fully implemented yet, but used in tests.
258 // It will be revisited at implementing PEGAGAUS_ASSERT
259 ////////////////////////////////////////////////////////////////////////////////
260 void TraceMemoryHandler::dumpTraceBuffer(const char* filename)
261 {
|
262 thilo.boehm 1.9 if (!filename)
263 {
264 // if the file name is empty/NULL pointer do nothing
265 return;
266 }
267 #ifdef PEGASUS_DEBUG
|
268 thilo.boehm 1.1 cerr << "Number of lock contentions is <"<< _contentionCount.get()
269 << ">" << endl;
270 cerr << "Number of obtained locks is <"<< _numberOfLocksObtained
271 << ">" << endl;
|
272 thilo.boehm 1.9 #endif
|
273 thilo.boehm 1.1
274 ofstream ofile(filename,ios::app&ios::out);
275 if( ofile.good() )
276 {
277 Boolean locked = _lockBufferAccess();
278 ofile << _traceArea->traceBuffer << PEGASUS_STD(endl);
279 if (locked )
280 {
281 _unlockBufferAccess();
282 }
283
|
284 kumpf 1.3 ofile.close();
|
285 thilo.boehm 1.1 }
286 }
287
288
289 ////////////////////////////////////////////////////////////////////////////////
290 // Appends a simple fixed length message to the trace buffer
291 // WARNING: This is a private method that does not lock the trace buffer.
292 // Callers have to lock the buffer prior to calling this method.
293 ////////////////////////////////////////////////////////////////////////////////
294 inline void TraceMemoryHandler::_appendSimpleMessage(
|
295 kumpf 1.3 const char* message,
|
296 thilo.boehm 1.1 Uint32 msgLen )
297 {
298 if (_leftBytesInBuffer >= msgLen )
299 {
300 memcpy(&(_traceArea->traceBuffer[_traceArea->nextPos]),
301 message,
302 msgLen);
|
303 kumpf 1.3
|
304 thilo.boehm 1.1 _traceArea->nextPos += msgLen;
305 _leftBytesInBuffer -= msgLen;
306 }
307 else
308 {
309 // Message doesn't completely fit into buffer, so we need to wrap
310 // it around.
|
311 kumpf 1.3
|
312 thilo.boehm 1.1 // First fill the buffer till the end ...
313 memcpy(&(_traceArea->traceBuffer[_traceArea->nextPos]),
314 message,
315 _leftBytesInBuffer);
316
317 // ... and then add the rest at the beginning
318 msgLen = msgLen - _leftBytesInBuffer;
319 memcpy(&(_traceArea->traceBuffer[0]),
320 message + _leftBytesInBuffer,
321 msgLen );
|
322 kumpf 1.3
|
323 thilo.boehm 1.1 _traceArea->nextPos = msgLen;
324 _leftBytesInBuffer = _traceArea->bufferSize - msgLen;
325 }
326
327 return;
328 }
329
330
331 ////////////////////////////////////////////////////////////////////////////////
332 // Formats a trace message into the trace buffer
333 ////////////////////////////////////////////////////////////////////////////////
334 void TraceMemoryHandler::handleMessage(
335 const char *message,
336 Uint32 msgLen,
337 const char *fmt, va_list argList)
338 {
339 if(!_lockBufferAccess())
340 {
341 // Give up, buffer is going to be destroyed
342 return;
343 }
|
344 kumpf 1.3
|
345 thilo.boehm 1.9
346 // If the trace memory is not initialized.
347 if(!_traceArea)
348 {
349 _initializeTraceArea();
350 }
351
|
352 thilo.boehm 1.8 Uint32 msgStart = _traceArea->nextPos;
|
353 thilo.boehm 1.1 // Handle the static part of the message
354 _appendSimpleMessage(message, msgLen);
|
355 kumpf 1.3
|
356 thilo.boehm 1.1 if (_leftBytesInBuffer == 0)
357 {
358 // Wrap the buffer
359 _traceArea->nextPos = 0;
360 _leftBytesInBuffer = _traceArea->bufferSize;
361 }
362
363
|
364 kumpf 1.3 // In case the buffer is too short, we need to invoke vsnprintf twice and
|
365 thilo.boehm 1.1 // for this need a copy of the argList.
366 va_list argListCopy;
367 va_copy(argListCopy, argList);
368
|
369 kumpf 1.3
|
370 thilo.boehm 1.1 // We just use vsnprintf to format the variable right into the buffer,
371 // up to the amount of bytes left.
372 #ifdef PEGASUS_OS_TYPE_WINDOWS
373 // Windows until VC 8 does not support vsnprintf
374 // need to use Windows equivalent function with the underscore
|
375 kumpf 1.3 int ttlMsgLen =
376 _vsnprintf(&(_traceArea->traceBuffer[_traceArea->nextPos]),
377 _leftBytesInBuffer,
378 fmt,
|
379 thilo.boehm 1.1 argList);
380 #else
|
381 kumpf 1.3 int ttlMsgLen =
382 vsnprintf(&(_traceArea->traceBuffer[_traceArea->nextPos]),
383 _leftBytesInBuffer,
384 fmt,
|
385 thilo.boehm 1.1 argList);
|
386 kumpf 1.3 #endif
387
|
388 thilo.boehm 1.1 if (((Uint32)ttlMsgLen < _leftBytesInBuffer) &&
389 (ttlMsgLen != -1))
390 {
391 ttlMsgLen++; //Include the '/0'
|
392 kumpf 1.3
|
393 thilo.boehm 1.1 _traceArea->nextPos += ttlMsgLen;
394 _leftBytesInBuffer -= ttlMsgLen;
395 }
396 else
397 {
398 // Reached end of buffer and need to wrap.
399 // This is a bit ugly, since we can't just resume after what had
400 // already been written, but have to start all over.
401 //
402 // To do this we format the message to the overflow buffer, and copy
403 // the rest of the message from there to the beginning of the trace
|
404 kumpf 1.3 // buffer.
|
405 thilo.boehm 1.1 // To save memory allocations, the overflow buffer is kept around
406 // until it becomes to small and needs to be reallocated.
|
407 thilo.boehm 1.8 if (ttlMsgLen == -1 || (msgLen + ttlMsgLen) > _traceArea->bufferSize)
408 {
409 // The message does not fit in the remaining buffer and
410 // vsnprintf() did not return the bytes needed
411 // or the message is larger then the treace Buffer.
412
413 // The message does not fit in the remaining buffer,
414 // clean up the the message fragment.
415 _traceArea->traceBuffer[msgStart] = 0;
416
417 // Wrap the buffer
418 _traceArea->nextPos = 0;
419 _leftBytesInBuffer = _traceArea->bufferSize;
|
420 kumpf 1.5
|
421 thilo.boehm 1.8 // Rewrite the static part of the message
422 _appendSimpleMessage(message, msgLen);
423
424 // Rewrite the variable part of the message
425 #ifdef PEGASUS_OS_TYPE_WINDOWS
426 // Windows until VC 8 does not support vsnprintf
427 // need to use Windows equivalent function with the underscore
428 ttlMsgLen =
429 _vsnprintf(&(_traceArea->traceBuffer[_traceArea->nextPos]),
430 _leftBytesInBuffer,
431 fmt,
432 argListCopy);
433 #else
434 ttlMsgLen =
435 vsnprintf(&(_traceArea->traceBuffer[_traceArea->nextPos]),
436 _leftBytesInBuffer,
437 fmt,
438 argListCopy);
439 #endif
440 if (ttlMsgLen == -1 ||
441 (msgLen + ttlMsgLen) > _traceArea->bufferSize)
442 thilo.boehm 1.8 {
443 // The message still does not fit in the buffer, but know
444 // we know that the most part of the message is in the buffer.
445 // Truncate the message using the truncation marker and leave
446 // space for the EOT marker + '\n'.
447 _leftBytesInBuffer = PEGASUS_TRC_BUFFER_TRUNC_MARKER_LEN +
448 PEGASUS_TRC_BUFFER_EOT_MARKER_LEN + 1 ;
449
450 _traceArea->nextPos =
451 _traceArea->bufferSize - _leftBytesInBuffer ;
452
453 // copy the marker including the trailing '0' !
454 memcpy(&(_traceArea->traceBuffer[_traceArea->nextPos]),
455 PEGASUS_TRC_BUFFER_TRUNC_MARKER,
456 PEGASUS_TRC_BUFFER_TRUNC_MARKER_LEN + 1 );
457
458 _traceArea->nextPos += PEGASUS_TRC_BUFFER_TRUNC_MARKER_LEN + 1;
459 }
460 else
461 {
462 // Now the message fits into the buffer.
463 thilo.boehm 1.8 ttlMsgLen++; //Include the '/0'
|
464 kumpf 1.5
|
465 thilo.boehm 1.8 _traceArea->nextPos += ttlMsgLen;
466 _leftBytesInBuffer -= ttlMsgLen;
467 }
468 } // End of vsnprintf() == -1 or message > buffer size
469 else
470 {
471 // vsnprintf() retuns number of bytes of the variable message and
472 // the Message fits in the buffer.
|
473 thilo.boehm 1.9 if ((Uint32)ttlMsgLen >= _overflowBufferSize)
474 {
475 if (_overflowBuffer != NULL )
|
476 thilo.boehm 1.1 {
|
477 thilo.boehm 1.9 delete[] _overflowBuffer;
|
478 thilo.boehm 1.1 }
|
479 thilo.boehm 1.9 _overflowBufferSize = ttlMsgLen+1;
480 _overflowBuffer = new char[_overflowBufferSize];
481 }
|
482 kumpf 1.3
|
483 thilo.boehm 1.1 #ifdef PEGASUS_OS_TYPE_WINDOWS
|
484 thilo.boehm 1.9 // Windows until VC 8 does not support vsnprintf
485 // need to use Windows equivalent function with the underscore
486 ttlMsgLen = _vsnprintf(_overflowBuffer,
487 _overflowBufferSize,
488 fmt,
489 argListCopy);
|
490 thilo.boehm 1.1 #else
|
491 thilo.boehm 1.9 ttlMsgLen = vsnprintf(_overflowBuffer,
492 _overflowBufferSize,
493 fmt,
494 argListCopy);
|
495 kumpf 1.3 #endif
496
|
497 thilo.boehm 1.9 // The actual number of characters written to the buffer is the
498 // number of bytes left in the buffer minus the trailing '/0'.
499 Uint32 numCharsWritten = _leftBytesInBuffer-1;
500
501 // Now calculate how much data we have to copy from the overflow
502 // buffer back to the trace buffer.
503 ttlMsgLen -= numCharsWritten;
504
505 // Copy the remainder of the trace message to the trace buffer
506 memcpy(&(_traceArea->traceBuffer[0]),
507 &(_overflowBuffer[numCharsWritten]),
508 ttlMsgLen );
509
510 _traceArea->nextPos = ttlMsgLen+1;
511 _leftBytesInBuffer = _traceArea->bufferSize - _traceArea->nextPos;
512 }
|
513 thilo.boehm 1.8 } // End of reached end of buffer and need to wrap.
|
514 thilo.boehm 1.1
515 // replace null terminator with line break
516 _traceArea->traceBuffer[_traceArea->nextPos-1] = '\n';
517
518 _appendMarker();
|
519 kumpf 1.3
|
520 thilo.boehm 1.1 _unlockBufferAccess();
521 }
522
523 ////////////////////////////////////////////////////////////////////////////////
524 // Copies a simple trace message to trace buffer
525 ////////////////////////////////////////////////////////////////////////////////
526 void TraceMemoryHandler::handleMessage(const char *message, Uint32 msgLen)
527 {
528 if(!_lockBufferAccess())
529 {
530 // Give up, buffer is going to be destroyed
531 return;
532 }
|
533 kumpf 1.3
|
534 thilo.boehm 1.9 // If the trace memory is not initialized.
535 if(!_traceArea)
536 {
537 _initializeTraceArea();
538 }
539
|
540 thilo.boehm 1.1 // We include the terminating 0 in the message for easier handling
541 msgLen++;
542
543 _appendSimpleMessage(message, msgLen);
544
545
546 // replace null terminator with line break
547 _traceArea->traceBuffer[_traceArea->nextPos-1] = '\n';
548
549 _appendMarker();
550
551 _unlockBufferAccess();
552 }
553
554 ////////////////////////////////////////////////////////////////////////////////
555 // Flushes the trace
556 ////////////////////////////////////////////////////////////////////////////////
557 void TraceMemoryHandler::flushTrace()
558 {
|
559 thilo.boehm 1.9 dumpTraceBuffer((const char*)Tracer::_getInstance()
560 ->_traceFile.getCString());
|
561 thilo.boehm 1.1 }
562
563 PEGASUS_NAMESPACE_END
|