Fix bug in archiving and simplify code

This commit is contained in:
Richard Frith-Macdonald 2017-06-23 11:26:17 +01:00
parent b4c1c3c320
commit 291b295089
5 changed files with 173 additions and 186 deletions

View file

@ -1,3 +1,14 @@
2017-06-23 Richard Frith-Macdonald <rfm@gnu.org>
* EcCommand.m:
* EcControl.m:
* EcProcess.h:
* EcProcess.m:
Replace cmdArchive: with ecArchive: changing trhe log file archiving
model to archive files primarily based on their last modification
date. Fixes the bug where files were archived to a folder with the
wrong datre on startup, and simplifies archiving code generally.
2017-03-06 Richard Frith-Macdonald <rfm@gnu.org> 2017-03-06 Richard Frith-Macdonald <rfm@gnu.org>
* EcAlarmDestination.h: * EcAlarmDestination.h:

View file

@ -752,16 +752,7 @@ static NSString* cmdWord(NSArray* a, unsigned int pos)
} }
else if (comp(wd, @"archive") >= 0) else if (comp(wd, @"archive") >= 0)
{ {
NSCalendarDate *when = [NSCalendarDate date]; m = [NSString stringWithFormat: @"\n%@\n\n", [self ecArchive: nil]];
NSString *sub;
int yy, mm, dd;
yy = [when yearOfCommonEra];
mm = [when monthOfYear];
dd = [when dayOfMonth];
sub = [NSString stringWithFormat: @"%04d-%02d-%02d", yy, mm, dd];
m = [NSString stringWithFormat: @"\n%@\n\n", [self cmdArchive: sub]];
} }
else if (comp(wd, @"help") >= 0) else if (comp(wd, @"help") >= 0)
{ {

View file

@ -798,16 +798,7 @@ static NSString* cmdWord(NSArray* a, unsigned int pos)
} }
else if (comp(wd, @"archive") >= 0) else if (comp(wd, @"archive") >= 0)
{ {
NSCalendarDate *when = [NSCalendarDate date]; m = [NSString stringWithFormat: @"\n%@\n\n", [self ecArchive: nil]];
NSString *sub;
int yy, mm, dd;
yy = [when yearOfCommonEra];
mm = [when monthOfYear];
dd = [when dayOfMonth];
sub = [NSString stringWithFormat: @"%04d-%02d-%02d", yy, mm, dd];
m = [NSString stringWithFormat: @"\n%@\n\n", [self cmdArchive: sub]];
} }
else if (comp(wd, @"clear") >= 0) else if (comp(wd, @"clear") >= 0)
{ {

View file

@ -570,12 +570,12 @@ extern NSString* cmdVersion(NSString *ver);
*/ */
- (void) cmdAlert: (NSString*)fmt, ... NS_FORMAT_FUNCTION(1,2); - (void) cmdAlert: (NSString*)fmt, ... NS_FORMAT_FUNCTION(1,2);
/** Archives debug log files into the specified subdirectory of the debug /** Archives debug log files into the appropriate subdirectory for the
* logging directory. If subdir is nil then a subdirectory name corresponding * supplied date (or the files last modification date if when is nil).<br />
* to the current date is generated and that subdirectory is created if * Returns a text description of any archiving actually done.<br />
* necessary. * The subdirectory is created if necessary.
*/ */
- (NSString*) cmdArchive: (NSString*)subdir; - (NSString*) ecArchive: (NSDate*)when;
/** Send a log message to the server. /** Send a log message to the server.
*/ */
@ -662,10 +662,12 @@ extern NSString* cmdVersion(NSString *ver);
*/ */
- (BOOL) cmdIsTesting; - (BOOL) cmdIsTesting;
/** Closes a file handle previously obtained using the -cmdLogFile: method. /** Closes a file previously obtained using the -cmdLogFile: method.<br />
* Returns a description of any file archiving done, or nil if the file
* dis not exist.<br />
* You should not close a logging handle directly, use this method. * You should not close a logging handle directly, use this method.
*/ */
- (void) cmdLogEnd: (NSString*)name; - (NSString*) cmdLogEnd: (NSString*)name;
/** Obtain a file handle for logging purposes. The file will have the /** Obtain a file handle for logging purposes. The file will have the
* specified name and will be created (if necessary) in the processes * specified name and will be created (if necessary) in the processes
@ -920,8 +922,10 @@ extern NSString* cmdVersion(NSString *ver);
* It's therefore recommended that you use 'lazy' initialisation of subclass * It's therefore recommended that you use 'lazy' initialisation of subclass
* instance variables as/when they are needed, rather than initialising * instance variables as/when they are needed, rather than initialising
* them in the -initWithDefaults: method.<br /> * them in the -initWithDefaults: method.<br />
* An alternative strategy is to perform subclass initialisaton before * For a normal process, the recommended place to perform initialisation is
* calling the superclass implementation. * immediately after initialisation (when configuration information has been
* retrieved from the Command server), typically by overriding the
* -ecRun method.
*/ */
- (id) initWithDefaults: (NSDictionary*)defs; - (id) initWithDefaults: (NSDictionary*)defs;
@ -1031,7 +1035,11 @@ extern NSString* cmdVersion(NSString *ver);
/** Establishes the receiver as a DO server and runs the runloop.<br /> /** Establishes the receiver as a DO server and runs the runloop.<br />
* Returns zero when the run loop completes.<br /> * Returns zero when the run loop completes.<br />
* Returns one (immediately) if the receiver is transent.<br /> * Returns one (immediately) if the receiver is transent.<br />
* Returns two if unable to register as a DO server. * Returns two if unable to register as a DO server.<br />
* This is the recommended location to perform any initialisation of your
* subclass which needs configuration information from the Command server;
* override this method, perform your initialisation, and then call the
* superclass implementation of the method to enter the run loop.
*/ */
- (int) ecRun; - (int) ecRun;

View file

@ -1038,7 +1038,7 @@ findMode(NSDictionary* d, NSString* s)
- (void) cmdMesgrelease: (NSArray*)msg; - (void) cmdMesgrelease: (NSArray*)msg;
- (void) cmdMesgtesting: (NSArray*)msg; - (void) cmdMesgtesting: (NSArray*)msg;
- (void) _memCheck; - (void) _memCheck;
- (NSString*) _moveLog: (NSString*)name to: (NSString*)sub; - (NSString*) _moveLog: (NSString*)name to: (NSDate*)when;
- (void) _timedOut: (NSTimer*)timer; - (void) _timedOut: (NSTimer*)timer;
- (void) _update: (NSMutableDictionary*)info; - (void) _update: (NSMutableDictionary*)info;
@end @end
@ -1496,24 +1496,27 @@ static NSString *noFiles = @"No log files to archive";
return [dateClass dateWithTimeIntervalSinceReferenceDate: lastOP]; return [dateClass dateWithTimeIntervalSinceReferenceDate: lastOP];
} }
- (void) cmdLogEnd: (NSString*)name - (NSString*) cmdLogEnd: (NSString*)name
{ {
NSFileHandle *hdl; NSString *status = nil;
if ([name length] == 0) if ([name length] == 0)
{ {
NSLog(@"Attempt to end log with empty filename"); NSLog(@"Attempt to end log with empty filename");
return;
} }
else
{
NSFileHandle *hdl;
name = [name lastPathComponent]; name = [name lastPathComponent];
[self ecDoLock]; [self ecDoLock];
hdl = [cmdLogMap objectForKey: name]; hdl = [cmdLogMap objectForKey: name];
if (hdl != nil) if (hdl != nil)
{ {
NSString *path; /* If the file is empty, remove it, otherwise archive it.
NSDictionary *attr; */
NSFileManager *mgr; status = [self _moveLog: name to: nil];
/* Ensure that all data is written to file, then close it unless it's /* Ensure that all data is written to file, then close it unless it's
* stderr (which we must keep open for logging at all times). * stderr (which we must keep open for logging at all times).
@ -1527,36 +1530,14 @@ static NSString *noFiles = @"No log files to archive";
NS_ENDHANDLER NS_ENDHANDLER
} }
/*
* If the file is empty, remove it, otherwise move to archive directory.
*/
path = [cmdLogsDir(nil) stringByAppendingPathComponent: name];
mgr = [NSFileManager defaultManager];
attr = [mgr fileAttributesAtPath: path traverseLink: NO];
if ([[attr objectForKey: NSFileSize] intValue] == 0)
{
[mgr removeFileAtPath: path handler: nil];
}
else
{
NSDate *when;
NSString *where;
when = [NSDate date];
where = [when descriptionWithCalendarFormat: @"%Y-%m-%d"
timeZone: nil locale: nil];
if (where != nil)
{
[self _moveLog: name to: where];
}
}
/* /*
* Unregister filename. * Unregister filename.
*/ */
[cmdLogMap removeObjectForKey: name]; [cmdLogMap removeObjectForKey: name];
} }
[self ecUnLock]; [self ecUnLock];
}
return status;
} }
- (NSFileHandle*) cmdLogFile: (NSString*)name - (NSFileHandle*) cmdLogFile: (NSString*)name
@ -1572,28 +1553,16 @@ static NSString *noFiles = @"No log files to archive";
name = [name lastPathComponent]; name = [name lastPathComponent];
[self ecDoLock]; [self ecDoLock];
hdl = [cmdLogMap objectForKey: name]; hdl = [cmdLogMap objectForKey: name];
if (hdl == nil) if (nil == hdl)
{ {
NSFileManager *mgr = [NSFileManager defaultManager]; NSFileManager *mgr = [NSFileManager defaultManager];
NSString *path; NSString *path;
path = [cmdLogsDir(nil) stringByAppendingPathComponent: name]; path = [cmdLogsDir(nil) stringByAppendingPathComponent: name];
if ([mgr fileExistsAtPath: path] == YES) /* Archive any old left-over file.
{ */
NSDictionary *attr; [self _moveLog: name to: nil];
NSDate *when;
NSString *where;
attr = [mgr fileAttributesAtPath: path traverseLink: NO];
when = [attr objectForKey: NSFileModificationDate];
where = [when descriptionWithCalendarFormat: @"%Y-%m-%d"
timeZone: nil locale: nil];
if (where != nil)
{
status = [self _moveLog: name to: where];
}
}
/* /*
* Create the file if necessary, and open it for updating. * Create the file if necessary, and open it for updating.
@ -1941,7 +1910,7 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
va_end (ap); va_end (ap);
} }
- (NSString*) cmdArchive: (NSString*)subdir - (NSString*) ecArchive: (NSDate*)when
{ {
NSString *status = @""; NSString *status = @"";
@ -1957,27 +1926,18 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
[self ecDoLock]; [self ecDoLock];
enumerator = [[cmdLogMap allKeys] objectEnumerator]; enumerator = [[cmdLogMap allKeys] objectEnumerator];
[self ecUnLock]; [self ecUnLock];
if (subdir == nil)
{
NSCalendarDate *when = [NSCalendarDate date];
int y, m, d;
y = [when yearOfCommonEra];
m = [when monthOfYear];
d = [when dayOfMonth];
subdir = [stringClass stringWithFormat: @"%04d-%02d-%02d", y, m, d];
}
while ((name = [enumerator nextObject]) != nil) while ((name = [enumerator nextObject]) != nil)
{ {
NSString *s; NSString *s;
s = [self _moveLog: name to: subdir]; s = [self cmdLogEnd: name];
if (nil != s)
{
if ([status length] > 0) if ([status length] > 0)
status = [status stringByAppendingString: @"\n"]; status = [status stringByAppendingString: @"\n"];
status = [status stringByAppendingString: s]; status = [status stringByAppendingString: s];
[self cmdLogEnd: name]; }
if (cmdIsQuitting == NO) if (cmdIsQuitting == NO)
{ {
[self cmdLogFile: name]; [self cmdLogFile: name];
@ -2320,21 +2280,21 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
- (void) ecNewDay: (NSCalendarDate*)when - (void) ecNewDay: (NSCalendarDate*)when
{ {
static NSDictionary *defs = nil; static NSDictionary *defs = nil;
NSString *sub; NSDictionary *d = [cmdDefs volatileDomainForName: @"EcCommand"];
NSDictionary *d;
if (nil != defs)
{
NSEnumerator *e; NSEnumerator *e;
NSString *k; NSString *k;
/* New day ... archive debug/log files into a subdirectory based on /* Archive previous day's logs. Force logs to be archived for the
* the current date. This is yesterday's debug, so we use yesterday. * specified date even if they have been modified today (on the basis
* that only the very latest info in them should be from today).
*/ */
sub = [[when dateByAddingYears: 0 months: 0 days: -1 hours: 0 minutes: 0 NSLog(@"%@", [self ecArchive: when]);
seconds: 0] descriptionWithCalendarFormat: @"%Y-%m-%d"];
NSLog(@"%@", [self cmdArchive: sub]);
/* Check information left in the EcCommand domain. /* Check information left in the EcCommand domain.
*/ */
d = [cmdDefs volatileDomainForName: @"EcCommand"];
e = [[d allKeys] objectEnumerator]; e = [[d allKeys] objectEnumerator];
while (nil != (k = [e nextObject])) while (nil != (k = [e nextObject]))
{ {
@ -2344,8 +2304,10 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
{ {
[self cmdError: @"The Console defaults override for '%@'" [self cmdError: @"The Console defaults override for '%@'"
@" has been left at '%@' for more than a day." @" has been left at '%@' for more than a day."
@" Please reset it ('tell %@ defaults delete %@') after updating" @" Please reset it ('tell %@ defaults delete %@') after"
@" Control.plist as required.", k, v, [self cmdName], k]; @" updating Control.plist as required.",
k, v, [self cmdName], k];
}
} }
} }
ASSIGNCOPY(defs, d); ASSIGNCOPY(defs, d);
@ -2855,7 +2817,7 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
} }
else else
{ {
[self cmdPrintf: @"\n%@\n", [self cmdArchive: nil]]; [self cmdPrintf: @"\n%@\n", [self ecArchive: nil]];
} }
} }
} }
@ -4309,7 +4271,7 @@ With two parameters ('maximum' and a number),\n\
/* /*
* Force archiving of old logfile. * Force archiving of old logfile.
*/ */
[self cmdArchive: nil]; [self ecArchive: nil];
ASSIGNCOPY(cmdDebugName, str); ASSIGNCOPY(cmdDebugName, str);
hdl = [self cmdLogFile: cmdDebugName]; hdl = [self cmdLogFile: cmdDebugName];
@ -4592,7 +4554,7 @@ With two parameters ('maximum' and a number),\n\
} }
} }
- (void)_ensureMemLogger - (void) _ensureMemLogger
{ {
NSString *bundle = [cmdDefs stringForKey: @"MemoryLoggerBundle"]; NSString *bundle = [cmdDefs stringForKey: @"MemoryLoggerBundle"];
Class cls = Nil; Class cls = Nil;
@ -4843,25 +4805,47 @@ With two parameters ('maximum' and a number),\n\
} }
} }
- (NSString*) _moveLog: (NSString*)name to: (NSString*)sub - (NSString*) _moveLog: (NSString*)name to: (NSDate*)when
{ {
NSString *status; NSString *status = nil;
NSString *where;
NS_DURING NS_DURING
{ {
NSFileManager *mgr = [NSFileManager defaultManager];
NSString *from;
NSDictionary *attr;
from = [cmdLogsDir(nil) stringByAppendingPathComponent: name];
attr = [mgr fileAttributesAtPath: from traverseLink: NO];
if (nil != attr)
{
if ([[attr objectForKey: NSFileSize] intValue] == 0)
{
[mgr removeFileAtPath: from handler: nil];
status = [NSString stringWithFormat:
@"Removed empty log %@", from];
}
else
{
NSString *where;
NSString *sub;
if (nil == when)
{
when = [attr fileModificationDate];
}
sub = [when descriptionWithCalendarFormat: @"%Y-%m-%d"
timeZone: nil
locale: nil];
where = cmdLogsDir(sub); where = cmdLogsDir(sub);
if (where != nil) if (where != nil)
{ {
NSFileManager *mgr = [NSFileManager defaultManager];
NSString *from;
NSString *path; NSString *path;
NSString *base; NSString *base;
NSString *gzpath; NSString *gzpath;
unsigned count = 0; unsigned count = 0;
path = [where stringByAppendingPathComponent: name]; path = [where stringByAppendingPathComponent: name];
from = [cmdLogsDir(nil) stringByAppendingPathComponent: name];
/* /*
* Check for pre-existing file - if found, try another. * Check for pre-existing file - if found, try another.
@ -4898,10 +4882,12 @@ With two parameters ('maximum' and a number),\n\
@"Unable to archive log %@ into %@", name, sub]; @"Unable to archive log %@ into %@", name, sub];
} }
} }
}
}
NS_HANDLER NS_HANDLER
{ {
status = [NSString stringWithFormat: @"Problem in %@ with %@ to %@ - %@", status = [NSString stringWithFormat: @"Problem in %@ with %@ to %@ - %@",
NSStringFromSelector(_cmd), name, sub, localException]; NSStringFromSelector(_cmd), name, when, localException];
} }
NS_ENDHANDLER NS_ENDHANDLER
return status; return status;