import os, sys import threading, Queue import pyinotify from bazjunk.path import makedirs from bazbase import db, conversion, cache, structure MAX_THREADS = 5 queue = Queue.PriorityQueue() started = False def error_path(ename, pn, format, rev): return os.path.join(cache.cache_dir(), ename, '__%s.%s.%s.error' % (pn, format, rev)) def render_from_queue(): while True: neg_priority, ename, propname, format = queue.get() with db.begin_transaction(): e = structure.get_element(ename) try: rendering = conversion.render(e, propname, format) except Exception, e: # !!!! This is the wrong place to do this? rev = db.get_revision() # This stuff is bazki-specific and should be there. if format.startswith('.'): propfmt = propname + format else: propfmt = "%s>%s" % (propname, format) with open(error_path(ename, propname, format, rev), 'w') as fil: fil.write('%s' % (ename, propfmt, type(e).__name__)) def start_render(ename, propnames, format, priority=0): global started if not started: # TODO(xavid): race started = True for x in xrange(MAX_THREADS): t = threading.Thread(target=render_from_queue) t.daemon = True t.start() for pn in propnames: currpn = pn currformat = format if '>' in pn: currpn, currformat = pn.split('>', 1) queue.put((-priority, ename, currpn, currformat)) def wait_for_render(ename, propnames, format): result_map = {} wm = pyinotify.WatchManager() dir = os.path.join(cache.cache_dir(), ename) makedirs(dir) wdd = wm.add_watch(dir, pyinotify.IN_CLOSE_WRITE | pyinotify.IN_MOVED_TO) notifier = pyinotify.Notifier(wm) # Is this the right place to get this??? rev = db.get_revision() try: while True: for pn in propnames: currpn = pn currformat = format if '>' in pn: currpn, currformat = pn.split('>', 1) rendering = conversion.cached(ename, currpn, currformat) if rendering is not None: result_map[pn] = rendering else: epath = error_path(ename, currpn, currformat, rev) try: with open(epath) as fil: result_map[pn] = fil.read() except IOError: pass if result_map: return result_map # If nothing, wait for an event. notifier.check_events() finally: notifier.stop()