Oolite 1.91.0.7745-260117-205bce7
Loading...
Searching...
No Matches
OOAsyncLogger Class Reference
Inheritance diagram for OOAsyncLogger:
Collaboration diagram for OOAsyncLogger:

Instance Methods

(void) - asyncLogMessage:
(void) - endLogging
(void) - changeFile
(BOOL) - startLogging
(void) - loggerThread
(void) - flushLog
(id) - init [implementation]
(void) - dealloc [implementation]

Private Attributes

OOAsyncQueuemessageQueue
NSConditionLock * threadStateMonitor
NSFileHandle * logFile
NSTimer * flushTimer

Detailed Description

Definition at line 90 of file OOLogOutputHandler.m.

Method Documentation

◆ asyncLogMessage:

- (void) asyncLogMessage: (NSString *) message

Definition at line 388 of file OOLogOutputHandler.m.

388 :(NSString *)message
389{
390 // Don't log of saturated flag is set.
391 if (sSaturated) return;
392
393 if (message != nil)
394 {
395 message = [message stringByAppendingString:@"\n"];
396
397#if OOLITE_WINDOWS
398 // Convert Unix line endings to Windows ones.
399 NSArray *messageComponents = [message componentsSeparatedByString:@"\n"];
400 message = [messageComponents componentsJoinedByString:@"\r\n"];
401#endif
402
403 [messageQueue enqueue:[message dataUsingEncoding:NSUTF8StringEncoding]];
404
405 if (flushTimer == nil)
406 {
407 // No pending flush
408 flushTimer = [NSTimer scheduledTimerWithTimeInterval:kFlushInterval target:self selector:@selector(flushLog) userInfo:nil repeats:NO];
409 }
410 }
411}
static BOOL sSaturated
return nil

References OOAsyncQueue::enqueue:, flushTimer, nil, and sSaturated.

Referenced by endLogging, and OOLogOutputHandlerPrint().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ changeFile

- (void) changeFile

Definition at line 381 of file OOLogOutputHandler.m.

382{
383 [self endLogging];
384 if (![self startLogging]) sWriteToStderr = YES;
385}
static BOOL sWriteToStderr

References changeFile, endLogging, startLogging, and sWriteToStderr.

Referenced by changeFile, and OOLogOutputHandlerChangeLogFile().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ dealloc

- (void) dealloc
implementation

Definition at line 285 of file OOLogOutputHandler.m.

286{
290 // We don't own a reference to flushTimer.
291
292 [super dealloc];
293}
#define DESTROY(x)
Definition OOCocoa.h:85
OOAsyncQueue * messageQueue
NSFileHandle * logFile
NSConditionLock * threadStateMonitor

References dealloc, DESTROY, logFile, messageQueue, and threadStateMonitor.

Referenced by dealloc.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ endLogging

- (void) endLogging

Definition at line 363 of file OOLogOutputHandler.m.

364{
365 NSString *postamble = nil;
366
368 {
369 // We're fully inited; write postamble, wait for worker thread to terminate cleanly, and close file.
370 postamble = [NSString stringWithFormat:@"\nClosing log at %@.", [NSDate date]];
371 [self asyncLogMessage:postamble];
372 [messageQueue enqueue:@"die"]; // Kill message
373 [threadStateMonitor lockWhenCondition:kConditionReadyToDealloc];
374 [threadStateMonitor unlock];
375
376 [logFile closeFile];
377 }
378}

References asyncLogMessage:, endLogging, OOAsyncQueue::enqueue:, messageQueue, nil, and threadStateMonitor.

Referenced by changeFile, endLogging, and OOLogOutputHandlerClose().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ flushLog

- (void) flushLog

Definition at line 414 of file OOLogOutputHandler.m.

415{
416 flushTimer = nil;
417 [messageQueue enqueue:@"flush"];
418}

References OOAsyncQueue::enqueue:, flushLog, flushTimer, and nil.

Referenced by flushLog.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ init

- (id) init
implementation

Definition at line 246 of file OOLogOutputHandler.m.

247{
248 BOOL OK = YES;
249 NSString *logPath = nil;
250 NSString *oldPath = nil;
251 NSFileManager *fmgr = nil;
252
253 self = [super init];
254 if (self == nil) OK = NO;
255
256 if (OK)
257 {
258 fmgr = [NSFileManager defaultManager];
259 logPath = OOLogHandlerGetLogPath();
260
261 // If there is an existing file, move it to Previous.log.
262 if ([fmgr fileExistsAtPath:logPath])
263 {
264 oldPath = [OOLogHandlerGetLogBasePath() stringByAppendingPathComponent:@"Previous.log"];
265 [fmgr oo_removeItemAtPath:oldPath];
266 if (![fmgr oo_moveItemAtPath:logPath toPath:oldPath])
267 {
268 if (![fmgr oo_removeItemAtPath:logPath])
269 {
270 NSLog(@"Log setup: could not move or delete existing log at %@, will log to stdout instead.", logPath);
271 OK = NO;
272 }
273 }
274 }
275 }
276
277 if (OK) OK = [self startLogging];
278
279 if (!OK) DESTROY(self);
280
281 return self;
282}
NSString * OOLogHandlerGetLogPath(void)
#define NSLog(format,...)
Definition OOLogging.h:137

References DESTROY, init, nil, NSLog, OOLogHandlerGetLogPath(), and startLogging.

Referenced by init.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ loggerThread

- (void) loggerThread

Definition at line 421 of file OOLogOutputHandler.m.

422{
423 id message = nil;
424 NSAutoreleasePool *rootPool = nil, *pool = nil;
425 NSUInteger size = 0;
426
427 rootPool = [[NSAutoreleasePool alloc] init];
428 [NSThread ooSetCurrentThreadName:@"OOLogOutputHandler logging thread"];
429
430 // Signal readiness
431 [messageQueue retain];
432 [threadStateMonitor lock];
433 [threadStateMonitor unlockWithCondition:kConditionWorking];
434
435 @try
436 {
437 for (;;)
438 {
439 pool = [[NSAutoreleasePool alloc] init];
440
441 message = [messageQueue dequeue];
442
443 if (!sSaturated && [message isKindOfClass:[NSData class]])
444 {
445 size += [message length];
446 if (size > 1 << 30) // 1 GiB
447 {
448 sSaturated = YES;
449#if OOLITE_WINDOWS
450 message = @"\r\n\r\n\r\n***** LOG TRUNCATED DUE TO EXCESSIVE LENGTH *****\r\n";
451#else
452 message = @"\n\n\n***** LOG TRUNCATED DUE TO EXCESSIVE LENGTH *****\n";
453#endif
454 message = [message dataUsingEncoding:NSUTF8StringEncoding];
455 }
456
457 [logFile writeData:message];
458 }
459 else if ([message isEqual:@"flush"])
460 {
461 [logFile synchronizeFile];
462 }
463 else if ([message isEqual:@"die"])
464 {
465 break;
466 }
467
468 [pool release];
469 }
470 }
471 @catch (NSException *exception) {}
472 [pool release];
473
474 // Clean up; after this, ivars are out of bounds.
475 [messageQueue release];
476 [threadStateMonitor lock];
477 [threadStateMonitor unlockWithCondition:kConditionReadyToDealloc];
478
479 [rootPool release];
480}
voidpf void uLong size
Definition ioapi.h:134

References OOAsyncQueue::dequeue, loggerThread, nil, and sSaturated.

Referenced by loggerThread.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ startLogging

- (BOOL) startLogging

Definition at line 296 of file OOLogOutputHandler.m.

297{
298 BOOL OK = YES;
299 NSString *logPath = nil;
300 NSFileManager *fmgr = nil;
301
302 fmgr = [NSFileManager defaultManager];
303
304 if (OK)
305 {
306 messageQueue = [[OOAsyncQueue alloc] init];
307 if (messageQueue == nil) OK = NO;
308 }
309
310 if (OK)
311 {
312 // set up threadStateMonitor -- used as a binary semaphore of sorts to check when the worker thread starts and stops.
313 threadStateMonitor = [[NSConditionLock alloc] initWithCondition:kConditionReadyToDealloc];
314 if (threadStateMonitor == nil) OK = NO;
315 [threadStateMonitor setName:@"OOLogOutputHandler thread state monitor"];
316 }
317
318 if (OK)
319 {
320 // Create work thread to actually handle messages.
321 // This needs to be done early to avoid messy state if something goes wrong.
322 [NSThread detachNewThreadSelector:@selector(loggerThread) toTarget:self withObject:nil];
323 // Wait for it to start.
324 if (![threadStateMonitor lockWhenCondition:kConditionWorking beforeDate:[NSDate dateWithTimeIntervalSinceNow:5.0]])
325 {
326 // If it doesn't signal a start within five seconds, assume something's wrong.
327 // Send kill signal, just in case it comes to life...
328 [messageQueue enqueue:@"die"];
329 // ...and stop -dealloc from waiting for thread death
330 [threadStateMonitor release];
332 OK = NO;
333 }
334 [threadStateMonitor unlockWithCondition:kConditionWorking];
335 }
336
337 if (OK)
338 {
339 logPath = OOLogHandlerGetLogPath();
340 OK = (logPath != nil);
341 }
342
343 if (OK)
344 {
345 // Create shiny new log file
346 OK = [fmgr createFileAtPath:logPath contents:nil attributes:nil];
347 if (OK)
348 {
349 logFile = [[NSFileHandle fileHandleForWritingAtPath:logPath] retain];
350 OK = (logFile != nil);
351 }
352 if (!OK)
353 {
354 NSLog(@"Log setup: could not open log at %@, will log to stdout instead.", logPath);
355 OK = NO;
356 }
357 }
358
359 return OK;
360}
@ kConditionWorking

References OOAsyncQueue::enqueue:, kConditionWorking, logFile, messageQueue, nil, NSLog, OOLogHandlerGetLogPath(), startLogging, and threadStateMonitor.

Referenced by changeFile, init, and startLogging.

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ flushTimer

- (NSTimer*) flushTimer
private

Definition at line 96 of file OOLogOutputHandler.m.

Referenced by asyncLogMessage:, and flushLog.

◆ logFile

- (NSFileHandle*) logFile
private

Definition at line 95 of file OOLogOutputHandler.m.

Referenced by dealloc, and startLogging.

◆ messageQueue

- (OOAsyncQueue*) messageQueue
private

Definition at line 93 of file OOLogOutputHandler.m.

Referenced by dealloc, endLogging, and startLogging.

◆ threadStateMonitor

- (NSConditionLock*) threadStateMonitor
private

Definition at line 94 of file OOLogOutputHandler.m.

Referenced by dealloc, endLogging, and startLogging.


The documentation for this class was generated from the following file: