# -*- coding: iso-8859-1 -*- """ MoinMoin caching module @copyright: 2001-2004 by Jürgen Hermann @license: GNU GPL, see COPYING for details. """ import os import tempfile from MoinMoin import config from MoinMoin.util import filesys, lock class CacheEntry: def __init__(self, request, arena, key): """ init a cache entry @param request: the request object @param arena: either a string or a page object, when we want to use page local cache area @param key: under which key we access the cache content """ self.request = request self.key = key if isinstance(arena, str): self.arena_dir = os.path.join(request.cfg.cache_dir, arena) filesys.makeDirs(self.arena_dir) else: # arena is in fact a page object self.arena_dir = arena.getPagePath('cache', check_create=1) self.lock_dir = os.path.join(self.arena_dir, '__lock__') self.rlock = lock.LazyReadLock(self.lock_dir, 60.0) self.wlock = lock.LazyWriteLock(self.lock_dir, 60.0) def _filename(self): return os.path.join(self.arena_dir, self.key) def exists(self): return os.path.exists(self._filename()) def mtime(self): try: return os.path.getmtime(self._filename()) except (IOError, OSError): return 0 def needsUpdate(self, filename, attachdir=None): # following code is not necessary. will trigger exception and give same result #if not self.exists(): # return 1 try: ctime = os.path.getmtime(self._filename()) ftime = os.path.getmtime(filename) except os.error: return 1 needsupdate = ftime > ctime # if a page depends on the attachment dir, we check this, too: if not needsupdate and attachdir: try: ftime2 = os.path.getmtime(attachdir) except os.error: ftime2 = 0 needsupdate = ftime2 > ctime return needsupdate def update(self, content, encode=False): fname = self._filename() if encode: content = content.encode(config.charset) if self.wlock.acquire(1.0): try: # we do not write content to old inode, but to a new file # se we don't need to lock when we just want to read the file # (at least on POSIX, this works) tmp_handle, tmp_fname = tempfile.mkstemp('.tmp', self.key, self.arena_dir) os.write(tmp_handle, content) os.close(tmp_handle) # this is either atomic or happening with real locks set: filesys.rename(tmp_fname, fname) filesys.chmod(fname, 0666 & config.umask) # fix mode that mkstemp chose finally: self.wlock.release() else: self.request.log("Can't acquire write lock in %s" % self.lock_dir) def remove(self): if self.wlock.acquire(1.0): try: try: os.remove(self._filename()) except OSError: pass finally: self.wlock.release() else: self.request.log("Can't acquire write lock in %s" % self.lock_dir) def content(self, decode=False): if self.rlock.acquire(1.0): try: f = open(self._filename(), 'rb') data = f.read() f.close() finally: self.rlock.release() else: self.request.log("Can't acquire read lock in %s" % self.lock_dir) if decode: data = data.decode(config.charset) return data