# HG changeset patch # User Tero Marttila # Date 1358700711 -7200 # Node ID 11df86fd2d6733778b3a073d3e4b2def563fc0d7 # Parent 8930f54b59b4a2f5d3c254938b11f1a9e631fbbd pvl.web.rrd: --cache diff -r 8930f54b59b4 -r 11df86fd2d67 bin/pvl.verkko-rrd --- a/bin/pvl.verkko-rrd Sun Jan 20 18:31:21 2013 +0200 +++ b/bin/pvl.verkko-rrd Sun Jan 20 18:51:51 2013 +0200 @@ -33,7 +33,10 @@ parser.add_option_group(pvl.args.parser(parser)) parser.add_option('--rrd', metavar='PATH', - help="Path to RRD files") + help="Find RRD files") + + parser.add_option('--cache', metavar='PATH', + help="Cache RRD graphs") # parse options, args = parser.parse_args(args) @@ -56,7 +59,7 @@ log.error("no --rrd given") return 2 - rrd = pvl.verkko.rrd.RRDDatabase(options.rrd) + rrd = pvl.verkko.rrd.RRDDatabase(options.rrd, options.cache) # app application = pvl.verkko.rrd.Application(rrd) diff -r 8930f54b59b4 -r 11df86fd2d67 pvl/verkko/rrd.py --- a/pvl/verkko/rrd.py Sun Jan 20 18:31:21 2013 +0200 +++ b/pvl/verkko/rrd.py Sun Jan 20 18:51:51 2013 +0200 @@ -12,20 +12,21 @@ import logging; log = logging.getLogger('pvl.verkko.rrd') # Model -import os, os.path +import os, os.path, errno class RRDDatabase (object) : """ A filesystem directory containing .rrd files. """ - def __init__ (self, path) : + def __init__ (self, path, cache=None) : if not path : raise ValueError("RRDDatabase: no path given") - log.info("%s", path) + log.info("%s: cache=%s", path, cache) self._path = path + self._cache = cache def path (self, node=None, *subnodes) : """ @@ -73,10 +74,8 @@ if tree : node = os.path.join(tree, node) - - node += '.rrd' - path = self.path(node) + path = self.path(node) + '.rrd' if not os.path.isfile(path) : raise ValueError("%: Invalid rrd: %s: %s" % (self, node, path)) @@ -110,21 +109,77 @@ # return sorted lists return sorted(dirs), sorted(rrds) + def _stat (self, path) : + """ + os.stat or None. + """ + + try : + return os.stat(path) + + except OSError as ex : + if ex.errno == errno.ENOENT : + return None + else : + raise + + def cache (self, source, *key) : + """ + Lookup given key from cache, returning (hit, file). + """ + + # output + if not self._cache : + return None, None + + # cache path + path = os.path.join(self._cache, *key) + + # create + dir = os.path.dirname(path) + if not os.path.isdir(dir) : + log.warn("makedirs %s", dir) + os.makedirs(dir) + + # stats's + src = self._stat(source) + dst = self._stat(path) + + if not dst: + log.debug("%s: %s: %s: miss", self._cache, source, path) + return None, path + + elif dst and src.st_mtime < dst.st_mtime : + log.debug("%s: %s: %s: hit", self._cache, source, path) + + return True, path + + else : + log.debug("%s: %s: %s: update", self._cache, source, path) + return False, path + def graph (self, rrd, style, interval) : """ Graph given rrd using given style/interval, returning the opened png data file. """ - title = " / ".join(rrd.split('/')) - - log.debug("%s: %s: %s/%s", self, rrd, style, interval) + title = str(rrd) # " / ".join(rrd.split('/')) - # XXX: lookup graph style.. - # XXX: collectd - # XXX: out=None -> tempfile - dimensions, lines, outfile = pvl.rrd.graph.collectd_ifoctets(style, interval, title, self.path(rrd), None) + path = self.path(rrd) + '.rrd' - log.debug("%s: %s: %s", self, rrd, outfile) + cached, out = self.cache(path, style, interval, rrd + '.png') + + log.debug("%s: %s: %s", self, rrd, out) + + if cached : + # from cache + outfile = open(out) + + else : + # to cache + # XXX: lookup graph style.. + # XXX: collectd + dimensions, lines, outfile = pvl.rrd.graph.collectd_ifoctets(style, interval, title, path, out) return outfile