compress/delete improvements.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/ec/trunk@36879 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2013-07-12 19:05:52 +00:00
parent 0479a99ef8
commit 8192603611
5 changed files with 245 additions and 3 deletions

View file

@ -1,3 +1,10 @@
2013-07-12 Richard Frith-Macdonald <rfm@gnu.org>
* EcProcess.h: New method to get EC user directory
* EcProcess.m: implement new method
* EcCommand.m: Add simple auto compress/delete of logs
CompressLogsAfter and DeleteLogsAfter control this.
2013-07-06 Richard Frith-Macdonald <rfm@gnu.org>
* EcConsole.m: Strip spaces from command line to avoid a space

View file

@ -85,7 +85,36 @@ static NSString* cmdWord(NSArray* a, unsigned int pos)
}
}
/* Special configuration options are:
*
* CompressLogsAfter
* A positive integer number of days after which logs should be compressed
* defaults to 14.
*
* DeleteLogsAfter
* A positive integer number of days after which logs should be deleted.
* Constrained to be at least as large as CompressLogsAfter.
* Defaults to 1000, but logs may still be deleted as if this were set
* to CompressLogsAfter if NodesFree or SpaceFree is reached.
*
* Environment
* A dictionary setting the default environment for launched processes.
*
* Launch
* A dictionary describing the processes which the server is responsible
* for launching.
*
* NodesFree
* A string giving a percentage of the total nodes on the disk below
* which an alert should be raised. Defaults to 10.
* Minimum 2, Maximum 90.
*
* SpaceFree
* A string giving a percentage of the total space on the disk below
* which an alert should be raised. Defaults to 10.
* Minimum 2, Maximum 90.
*
*/
@interface EcCommand : EcProcess <Command>
{
NSString *host;
@ -106,6 +135,9 @@ static NSString* cmdWord(NSArray* a, unsigned int pos)
unsigned revSequence;
float nodesFree;
float spaceFree;
NSTimeInterval uncompressed;
NSTimeInterval undeleted;
BOOL sweeping;
}
- (NSFileHandle*) openLog: (NSString*)lname;
- (void) cmdGnip: (id <CmdPing>)from
@ -275,7 +307,27 @@ static NSString* cmdWord(NSArray* a, unsigned int pos)
DESTROY(environment);
if ([d isKindOfClass: [NSDictionary class]] == YES)
{
NSString *k;
NSMutableDictionary *m;
NSString *k;
NSString *err;
m = [[d mutableCopy] autorelease];
d = m;
NS_DURING
[self cmdUpdate: m];
NS_HANDLER
[self cmdError: @"Problem before updating config: %@",
localException];
NS_ENDHANDLER
NS_DURING
err = [self cmdUpdated];
NS_HANDLER
err = [localException description];
NS_ENDHANDLER
if ([err length] > 0)
{
[self cmdError: @"Problem after updating config: %@", err];
}
launchInfo = [d objectForKey: @"Launch"];
if ([launchInfo isKindOfClass: [NSDictionary class]] == NO)
@ -1470,6 +1522,8 @@ static NSString* cmdWord(NSArray* a, unsigned int pos)
{
if (nil != (self = [super initWithDefaults: defs]))
{
uncompressed = 0.0;
undeleted = 0.0;
nodesFree = 0.1;
spaceFree = 0.1;
@ -1991,6 +2045,178 @@ static NSString* cmdWord(NSArray* a, unsigned int pos)
}
}
- (void) ecNewHour: (NSCalendarDate*)when
{
static const NSTimeInterval day = 24.0 * 60.0 * 60.0;
NSInteger compressAfter;
NSInteger deleteAfter;
NSTimeInterval latestCompressAt;
NSTimeInterval latestDeleteAt;
NSTimeInterval now;
NSTimeInterval ti;
NSFileManager *mgr;
NSString *logs;
NSString *file;
NSAutoreleasePool *arp;
if (sweeping == YES)
{
NSLog(@"Argh - nested sweep attempt");
return;
}
sweeping = YES;
arp = [NSAutoreleasePool new];
now = [when timeIntervalSinceReferenceDate];
logs = [[self ecUserDirectory] stringByAppendingPathComponent: @"Logs"];
/* get number of days after which to do log compression/deletion.
*/
compressAfter = [[self cmdDefaults] integerForKey: @"CompressLogsAfter"];
if (compressAfter < 1)
{
compressAfter = 14;
}
deleteAfter = [[self cmdDefaults] integerForKey: @"DeleteLogsAfter"];
if (deleteAfter < 1)
{
deleteAfter = 1000;
}
if (deleteAfter < compressAfter)
{
deleteAfter = compressAfter;
}
mgr = [NSFileManager defaultManager];
if (0.0 == undeleted)
{
undeleted = now - 365.0 * day;
}
ti = undeleted;
latestDeleteAt = now - day * deleteAfter;
while (ti < latestDeleteAt)
{
NSAutoreleasePool *pool = [NSAutoreleasePool new];
when = [NSCalendarDate dateWithTimeIntervalSinceReferenceDate: ti];
file = [[logs stringByAppendingPathComponent:
[when descriptionWithCalendarFormat: @"%Y-%m-%d"]]
stringByStandardizingPath];
if ([mgr fileExistsAtPath: file])
{
[mgr removeFileAtPath: file handler: nil];
}
ti += day;
[pool release];
}
undeleted = ti;
if (uncompressed < undeleted)
{
uncompressed = undeleted;
}
ti = uncompressed;
latestCompressAt = now - day * compressAfter;
while (ti < latestCompressAt)
{
NSAutoreleasePool *pool = [NSAutoreleasePool new];
NSDirectoryEnumerator *enumerator;
BOOL isDirectory;
NSString *base;
when = [NSCalendarDate dateWithTimeIntervalSinceReferenceDate: ti];
base = [[logs stringByAppendingPathComponent:
[when descriptionWithCalendarFormat: @"%Y-%m-%d"]]
stringByStandardizingPath];
if ([mgr fileExistsAtPath: base isDirectory: &isDirectory] == NO
|| NO == isDirectory)
{
continue; // No log directory for this date.
}
enumerator = [mgr enumeratorAtPath: base];
while ((file = [enumerator nextObject]) != nil)
{
NSString *src;
NSString *dst;
NSFileHandle *sh;
NSFileHandle *dh;
NSDictionary *a;
NSData *d;
if (YES == [[file pathExtension] isEqualToString: @"gz"])
{
continue; // Already compressed
}
a = [enumerator fileAttributes];
if (NSFileTypeRegular != [a fileType])
{
continue; // Not a regular file ... can't compress
}
src = [base stringByAppendingPathComponent: file];
if ([a fileSize] == 0)
{
[mgr removeFileAtPath: src handler: nil];
continue; // Nothing to compress
}
dst = [src stringByAppendingPathExtension: @"gz"];
if ([mgr fileExistsAtPath: dst isDirectory: &isDirectory] == YES)
{
[mgr removeFileAtPath: dst handler: nil];
}
[mgr createFileAtPath: dst contents: nil attributes: nil];
dh = [NSFileHandle fileHandleForWritingAtPath: dst];
if (NO == [dh useCompression])
{
[dh closeFile];
[mgr removeFileAtPath: dst handler: nil];
[self cmdError: @"Unable to compress %@ to %@", src, dst];
continue;
}
sh = nil;
NS_DURING
{
NSAutoreleasePool *inner;
sh = [NSFileHandle fileHandleForReadingAtPath: src];
inner = [NSAutoreleasePool new];
while ([(d = [sh readDataOfLength: 1000000]) length] > 0)
{
[dh writeData: d];
[inner release];
inner = [NSAutoreleasePool new];
}
[inner release];
[sh closeFile];
[dh closeFile];
[mgr removeFileAtPath: src handler: nil];
}
NS_HANDLER
{
[mgr removeFileAtPath: dst handler: nil];
[sh closeFile];
[dh closeFile];
}
NS_ENDHANDLER
}
ti += day;
[pool release];
}
uncompressed = ti;
DESTROY(arp);
sweeping = NO;
}
/*
* Tell all our clients to quit, and wait for them to do so.
* If called while already terminating ... force immediate shutdown.

View file

@ -887,6 +887,10 @@ extern NSString* cmdVersion(NSString *ver);
*/
- (void) ecTestLog: (NSString*)fmt, ...;
/** Returns the directory set as the root for files owned by the ECCL user
*/
- (NSString*) ecUserDirectory;
@end
@interface NSObject (RemoteServerDelegate)

View file

@ -2185,6 +2185,11 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
}
}
- (NSString*) ecUserDirectory
{
return cmdUserDir();
}
- (void) setCmdDebug: (NSString*)mode withDescription: (NSString*)desc
{
[cmdDebugKnown setObject: desc forKey: mode];

2
README
View file

@ -21,5 +21,5 @@ where 'xxx' is your username, to tell the system it should be running as you.
3. Configuration is in ~xxx/Data. Specifically, you need to configure
~xxx/Data/Command/Control.plist, ~xxx/Data/Command/Operators.plist, and
~xxx/Data/Command/AlertConfig.plist before the Control server will start.
There are examples in thee same directory as this README
There are examples in the same directory as this README