# -*- coding: utf-8 -*- import cherrypy from random import randint from fcntl import flock, LOCK_EX, LOCK_UN __all__ = ["LockTool"] class LockTool(cherrypy.Tool): def __init__(self): cherrypy.Tool.__init__(self, 'before_handler', self.acquire, priority=9) def _setup(self): cherrypy.Tool._setup(self) cherrypy.request.hooks.attach('before_finalize', self.release, priority=90) cherrypy.request.hooks.attach('after_error_response', self.release, priority=90) def acquire(self, key=None, methods=["POST", "PUT", "DELETE"]): if cherrypy.request.method in methods: parameter = key + cherrypy.request.params[key] if key else 'global' lock = ExclusiveLock(parameter) lock.lock() cherrypy.request.lock = lock def release(self): if hasattr(cherrypy.request, 'lock'): lock = cherrypy.request.lock lock.unlock() class ExclusiveLock(): key = None #user given value file = None #resource to lock own = False #have we locked resource def __init__(self, key): self.id = randint(0, 1000) self.key = key #create a new resource or get exisitng with same key self.file = open("/tmp/%s.lockfile" % key, 'w+') def __del__(self): if self.own == True: self.unlock() def lock(self): flock(self.file, LOCK_EX) self.file.truncate(0) # truncate file #write something to just help debugging self.file.write("Locked\n"); self.file.flush() self.own = True cherrypy.engine.log('Lock<%d> %s ACQUIRED' % (self.id, self.key)) return self.own def unlock(self): if self.own == True: flock(self.file, LOCK_UN) self.file.truncate(0) # truncate file #write something to just help debugging self.file.write("Unlocked\n") self.file.flush() cherrypy.engine.log('Lock<%d> %s RELEASED' % (self.id, self.key)) else: pass self.own = False return self.own