X-Git-Url: https://git.kaliko.me/?a=blobdiff_plain;f=sima%2Flib%2Fcache.py;fp=sima%2Flib%2Fcache.py;h=ebed3fcb3977bf12741163ff35c4a50f25e27f11;hb=71500abd7ef16784d027a8a20aa28b06e8a13a4f;hp=0000000000000000000000000000000000000000;hpb=bed2018b162e3493dd5a5a7fe5433af2005a7d0a;p=mpd-sima.git diff --git a/sima/lib/cache.py b/sima/lib/cache.py new file mode 100644 index 0000000..ebed3fc --- /dev/null +++ b/sima/lib/cache.py @@ -0,0 +1,95 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2014 Jack Kaliko +# Copyright (c) 2012, 2013 Eric Larson +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# +""" +The cache object API for implementing caches. The default is just a +dictionary, which in turns means it is not threadsafe for writing. +""" + +import os +import base64 +import codecs + +from hashlib import md5 +from pickle import load, dump +from threading import Lock + +from ..utils.filelock import FileLock + + +class BaseCache: + + def get(self, key): + raise NotImplemented() + + def set(self, key, value): + raise NotImplemented() + + def delete(self, key): + raise NotImplemented() + + +class DictCache(BaseCache): + + def __init__(self, init_dict=None): + self.lock = Lock() + self.data = init_dict or {} + + def get(self, key): + return self.data.get(key, None) + + def set(self, key, value): + with self.lock: + self.data.update({key: value}) + + def delete(self, key): + with self.lock: + if key in self.data: + self.data.pop(key) + + +class FileCache: + + def __init__(self, directory, forever=False): + self.directory = directory + self.forever = forever + + if not os.path.isdir(self.directory): + os.mkdir(self.directory) + + def encode(self, x): + return md5(x.encode('utf-8')).hexdigest() + + def _fn(self, name): + return os.path.join(self.directory, self.encode(name)) + + def get(self, key): + name = self._fn(key) + if os.path.exists(name): + return load(codecs.open(name, 'rb')) + + def set(self, key, value): + name = self._fn(key) + with FileLock(name): + with codecs.open(name, 'w+b') as fh: + dump(value, fh) + + def delete(self, key): + if not self.forever: + os.remove(self._fn(key))