diff options
-rw-r--r-- | patchtracker/CacheObject.py | 63 | ||||
-rwxr-xr-x | patchtracker/Conf.py | 12 | ||||
-rwxr-xr-x | patchtracker/ReqHandler.py | 28 |
3 files changed, 101 insertions, 2 deletions
diff --git a/patchtracker/CacheObject.py b/patchtracker/CacheObject.py new file mode 100644 index 0000000..c37c3b5 --- /dev/null +++ b/patchtracker/CacheObject.py @@ -0,0 +1,63 @@ +import errno +import gzip +import md5 +import os + +import Conf + +class CacheMissException (Exception): + pass + +class CacheObject: + """ A CacheObject is a compressed on-disk version of a serialized object. + """ + def __init__ (self, key=None, keys=None): + self.obj = None + #print "CacheObject: key=%s keys=%s"%(key, keys) + if not key and not keys: + raise "CacheObject needs at least one of key, keys" + checksum = md5.md5() + if key: + checksum.update(key) + if keys: + for k in keys: + checksum.update(str(k)) + self.path = os.path.sep.join([Conf.cachedir, checksum.hexdigest()]) + + def get(self): + if not self.obj: + try: + if Conf.cachecompress: + self.obj = gzip.GzipFile(self.path).read() + else: + self.obj = file(self.path).read() + except IOError, e: + if e.errno != errno.ENOENT: + raise e + else: + #print "CacheObject: cache miss" + raise CacheMissException("Object not present in cache") + #print "CacheObject: cache hit" + return self.obj + + def put(self, obj): + self.obj = obj + #print "CacheObject: cache put" + try: + if Conf.cachecompress: + gzip.GzipFile(self.path, "wb").write(str(self.obj)) + else: + file(self.path, "wb").write(str(self.obj)) + except Exception, e: + os.unlink(self.path) + raise e + +if __name__ == '__main__': + co = CacheObject( key="magic" ) + try: + print "going to try to read an object before it exists" + print "first line:", co.get().split()[0] + except CacheMissException: + print "file was missing as expected. now let's try to put it and fetch it" + co.put(file("/etc/passwd").read()) + print "first line:", co.get().split()[0] diff --git a/patchtracker/Conf.py b/patchtracker/Conf.py index 954001e..448f595 100755 --- a/patchtracker/Conf.py +++ b/patchtracker/Conf.py @@ -22,6 +22,18 @@ pts_index_file = "pts-index.json.gz" by the PTS system """ +caching = True +""" Should caching be enabled? """ + +cachedir = "cache" +""" The location of the output cache directory. This directory contains + cached output from system commands or other nontrivial calculations + for faster and less resource intensive re-use +""" + +cachecompress = False +""" Should compression of cache data be enabled? """ + try: from localconfig import * except ImportError: diff --git a/patchtracker/ReqHandler.py b/patchtracker/ReqHandler.py index a87fd68..59e0f53 100755 --- a/patchtracker/ReqHandler.py +++ b/patchtracker/ReqHandler.py @@ -7,6 +7,7 @@ import sys import patchtracker.Conf as Conf from patchtracker.Templates import ErrorTemplate, PatchTemplate, PackageVersTemplate, LetterTocTemplate, FrontPageTemplate, SearchResultsTemplate from patchtracker.DiffGzHandler import DiffGzHandler, DiffGzException +from patchtracker.CacheObject import CacheObject, CacheMissException import patchtracker.DB as DB from patchtracker.DB import PatchTrackerDB import pygments @@ -158,14 +159,19 @@ class FrontPageCmd(Cmd): class CmdHandler: def __init__(self, env): self.headers = [] - uri=Conf.root_url+env['PATH_INFO'] + uri = Conf.root_url+env['PATH_INFO'] + self.cacheobj = None + #print "Accept:",env['HTTP_ACCEPT'] args = uri[len(Conf.root_url)+1:].split("/") cmdarg = args[0] + cacheable = False if cmdarg == "patch": self.cmd = PatchCmd(args[1:]) + cacheable = True elif cmdarg == "package": self.cmd = PackageCmd(args[1:]) + cacheable = True elif cmdarg == "index": self.cmd = IndexCmd(args[1:]) elif cmdarg == "jump": @@ -178,11 +184,29 @@ class CmdHandler: else: self.cmd = ErrorCmd("invalid command/location '%s'"%(cmdarg), "404 Not found") + if Conf.caching and cacheable: + self.cacheobj = CacheObject(key=uri) + self.headers.append( ('Content-type', self.cmd.content_type) ) self.status = self.cmd.status def output(self): + result = None try: - return self.cmd.output() + if self.cacheobj: + result = self.cacheobj.get() + else: + result = self.cmd.output() + except CacheMissException: + result = self.cmd.output() + self.cacheobj.put(result) except DiffGzException, e: return ErrorCmd(str(e), "500 Oh Noez!!1!").output() + + return result + +if __name__ == '__main__': + fake_env = { 'PATH_INFO': sys.argv[1] } + cmdh = CmdHandler(fake_env) + print "Status: %s\nHeaders: %s"%(cmdh.status, cmdh.headers) + print cmdh.output() |