diff --git a/tsstats/cache.py b/tsstats/cache.py new file mode 100644 index 0000000..290c6a6 --- /dev/null +++ b/tsstats/cache.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +import hashlib +import logging +import os +import pickle +from collections import MutableMapping, namedtuple + +logger = logging.getLogger('tsstats') +CachedLog = namedtuple('CachedLog', ['path', 'hash', 'events']) + + +def _calculate_hash(path): + with open(path, 'rb') as f: + return hashlib.sha256(f.read()).hexdigest() + + +class Cache(MutableMapping): + def __init__(self, path, data={}): + self.path = path + self.store = data + + @classmethod + def read(cls, path): + data = {} + if os.path.exists(path): + logger.debug('Reading cache from %s', path) + with open(path, 'rb') as f: + try: + data = pickle.load(f) + except EOFError: + logger.debug('Couldn\'t read cache') + return cls(path, data) + + def write(self, path=None): + if not path: + path = self.path + logger.debug('Writing cache to %s', path) + with open(path, 'wb') as f: + pickle.dump(self.store, f) + + def needs_parsing(self, path): + if path not in self.store: + return True + return _calculate_hash(path) != self.store[path].hash + + def __setitem__(self, path, events): + self.store[path] = CachedLog(path, _calculate_hash(path), list(events)) + + def __getitem__(self, path): + return self.store[path] + + def __delitem__(self, path): + del self.store[path] + + def __iter__(self): + return iter(self.store.keys()) + + def __len__(self): + return len(self.store)