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