diff -r 74f6a0b01ddf -r 48fca00689e3 log_source.py --- a/log_source.py Wed Feb 11 01:21:22 2009 +0200 +++ b/log_source.py Wed Feb 11 02:07:07 2009 +0200 @@ -3,10 +3,10 @@ """ import datetime, calendar, itertools, functools, math -import os, errno +import os, os.path, errno import pytz -import config +import config, utils class LogSourceDecoder (object) : """ @@ -161,6 +161,17 @@ """ abstract + + def get_modified (self, dt=None) : + """ + Returns a sequence of LogLines that may have been *modified* from their old values since the given datetime. + + If the datetime is not given, *all* lines are returned + + The LogLines should be in time order. + """ + + abstract class LogFile (object) : """ @@ -364,12 +375,14 @@ # convert to date and use that return self._get_logfile_date(dtz.date()) - def _get_logfile_date (self, d, load=True) : + def _get_logfile_date (self, d, load=True, stat=True, ignore_missing=True) : """ - Get the logfile corresponding to the given naive date in our timezone. If load is False, only test for the - presence of the logfile, do not actually open it. + Get the logfile corresponding to the given naive date in our timezone. + + If load is False, only test for the presence of the logfile, do not actually open it. If stat is given, + then this returns the stat() result - Returns None if the logfile does not exist. + Returns None if the logfile does not exist, unless ignore_missing is given as False. """ # format filename @@ -383,6 +396,10 @@ # open+return the LogFile return LogFile(path, self.parser, self.decoder, start_date=d, channel=self.channel) + elif stat : + # stat + return os.stat(path) + else : # test return os.path.exists(path) @@ -390,12 +407,33 @@ # XXX: move to LogFile except IOError, e : # return None for missing files - if e.errno == errno.ENOENT : + if e.errno == errno.ENOENT and ignore_missing : return None else : raise + def _iter_logfile_dates (self) : + """ + Yields a series of naive datetime objects representing the logfiles that are available, in time order + """ + + # listdir + filenames = os.listdir(self.path) + + # sort + filenames.sort() + + # iter files + for filename in filenames : + try : + # parse date + yield + yield datetime.datetime.strptime(filename, self.filename_fmt).replace(tzinfo=self.tz) + + except : + # ignore + continue + def _iter_date_reverse (self, dt=None) : """ Yields an infinite series of naive date objects in our timezone, iterating backwards in time starting at the @@ -566,3 +604,27 @@ # valid yield dt.date() + def get_modified (self, dt=None) : + """ + Returns the contents off all logfiles with mtimes past the given date + """ + + # iterate through all available logfiles in date order, as datetimes + for log_date in self._iter_logfile_dates() : + # compare against dt? + if dt : + # stat + st = self._get_logfile_date(log_date, load=False, stat=True) + + # not modified? + if utils.from_utc_timestamp(st.st_mtime) < dt : + # skip + continue + + # open + logfile = self._get_logfile_date(log_date, ignore_missing=False) + + # yield all lines + for line in logfile.read_full() : + yield line +