[Zope-CVS] CVS: Products/FileCacheManager - FileCache.py:1.1
FileCacheManager.py:1.14
Jens Vagelpohl
jens at dataflake.org
Thu Aug 19 14:17:00 EDT 2004
Update of /cvs-repository/Products/FileCacheManager
In directory cvs.zope.org:/tmp/cvs-serv12493
Modified Files:
FileCacheManager.py
Added Files:
FileCache.py
Log Message:
- code reorganization to shorten modules
=== Added File Products/FileCacheManager/FileCache.py ===
##############################################################################
#
# Copyright (c) 2004 Chris McDonough, Paul Winkler, Jens Vagelpohl and
# Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
import os
import tempfile
import md5
import zLOG
from thread import allocate_lock
from AccessControl.SecurityManagement import getSecurityManager
from BTrees import OOBTree
from ZPublisher.Iterators import filestream_iterator
from Products.StandardCacheManagers.RAMCacheManager import RAMCache
from Products.PageTemplates.Expressions import getEngine, \
SecureModuleImporter
from Products.PageTemplates.TALES import CompilerError
class FileCache(RAMCache):
""" A cache that caches rendered content to the filesystem """
def __init__(self, path='/tmp'):
# self.cache maps physical ZODB paths to disk files.
self.cache=OOBTree.OOBTree()
self.writelock = allocate_lock()
self.next_cleanup = 0
self.setDir(path)
self._makeDirs()
self._naming_expr = None
def _fileName(self, ob):
""" Compute a filename based on an MD5 hash: doesn't preserve
human-readable path, but otherwise makes life much easier """
if self._naming_expr is not None:
expr_context = self.getExprContext(ob)
munged = self._naming_expr(expr_context)
fname = os.path.join(self._dir, munged)
else:
phys_path = '/'.join(ob.getPhysicalPath())[1:]
hashed = md5.new(phys_path).hexdigest()
fname = os.path.join(self._dir, hashed[:2], hashed)
return fname
def getExprContext(self, ob=None):
""" Create a context for evaluating the TAL naming expression """
data = { 'user' : getSecurityManager().getUser()
, 'request' : getattr(ob, 'REQUEST', None)
, 'modules' : SecureModuleImporter
, 'object' : ob
, 'object_url' : ob.absolute_url()
, 'nothing' : None
}
return getEngine().getContext(data)
def setNamingExpression(self, naming_expression=''):
""" Set a new file naming expression """
msg = ''
if naming_expression:
try:
self._naming_expr = getEngine().compile(naming_expression)
except CompilerError:
msg = 'Invalid TAL expression "%s"' % naming_expression
else:
self._naming_expr = None
return msg
def getDir(self):
""" Retrieve the filesystem directory used for caching """
return self._dir
def setDir(self, dir):
""" Set the filesystem diriectory to use for caching """
self._dir = dir
self._makeDirs()
def ZCache_invalidate(self, ob):
""" Invalidate cache entries that apply to ob """
fname = self._fileName(ob)
try:
try:
self.writelock.acquire()
if os.path.exists(fname): # XXX race?
os.remove(fname)
except IOError, msg:
zLOG.LOG( 'FileCacheManager'
, zLOG.ERROR
, 'IOError removing file'
, error=msg
)
finally:
self.writelock.release()
def ZCache_get(self, ob, view_name='', keywords=None,
mtime_func=None, default=None):
""" Gets a cache entry and return a filestream_iterator """
fname = self._fileName(ob)
try:
fiter = filestream_iterator(fname, 'rb')
except IOError:
# couldn't get the actual cache
zLOG.LOG('FileCacheManager', zLOG.INFO,
'Failed to retrieve cache for %s' % \
'/'.join(ob.getPhysicalPath())
)
return default
return fiter
def ZCache_set(self, ob, data=None, view_name='', keywords=None,
mtime_func=None):
""" Sets a cache entry. """
fname = self._fileName(ob)
if data is None:
# maybe it's a File or an Image, grab the data
data = ob.data
try:
if fname:
# use a temp. file for writing.
fd, tempname = tempfile.mkstemp()
# isinstance won't work on extension class
if type(data) == type(''):
os.write(fd, data)
else:
# Image pdata objects?
# there's no interface to check
# and I don't want to test meta_type, so
# assume that's what we have here.
while data is not None and hasattr(data, 'next'):
os.write(fd, data.data)
data = data.next
os.fsync(fd)
os.close(fd)
# rename that sucker.
# This may fail if they are not on the same filesystem.
try:
self.writelock.acquire()
try:
os.rename(tempname, fname)
except OSError:
# windows fails if fname exists.
# if this doesn't work, tough noogies
os.unlink(fname)
os.rename(tempname, fname)
finally:
self.writelock.release()
except IOError, msg:
LOG('FileCacheManager', ERROR, 'IOError writing file', error=msg)
def _makeDirs(self):
""" Make sure we have somewhere to put files. """
chars = '0123456789abcdef'
for char in chars:
for char2 in chars:
dirpath = os.path.join(self._dir, '%s%s' % (char, char2))
try:
os.makedirs(dirpath)
except OSError:
zLOG.LOG('FileCacheManager', zLOG.PROBLEM,
'unable to create directory %s' % dirpath)
=== Products/FileCacheManager/FileCacheManager.py 1.13 => 1.14 ===
--- Products/FileCacheManager/FileCacheManager.py:1.13 Mon Aug 16 04:11:44 2004
+++ Products/FileCacheManager/FileCacheManager.py Thu Aug 19 14:16:29 2004
@@ -14,185 +14,17 @@
import os
import time
-import tempfile
-import md5
-
-import zLOG
-
-from thread import allocate_lock
from AccessControl import ClassSecurityInfo
-from AccessControl.SecurityManagement import getSecurityManager
from AccessControl.Permissions import view_management_screens
from Globals import InitializeClass
-from BTrees import OOBTree
from Products.PageTemplates.PageTemplateFile import PageTemplateFile
-from ZPublisher.Iterators import filestream_iterator
-from Products.StandardCacheManagers.RAMCacheManager import RAMCache, \
- CacheEntry, RAMCacheManager
-from Acquisition import aq_base
-from Products.PageTemplates.Expressions import getEngine, \
- SecureModuleImporter
-from Products.PageTemplates.TALES import CompilerError
+from Products.StandardCacheManagers.RAMCacheManager import RAMCacheManager
+from FileCache import FileCache
from permissions import change_cache_managers
caches = {}
-
-class FileCache(RAMCache):
- """ A cache that caches rendered content to the filesystem """
-
- def __init__(self, path='/tmp'):
- # self.cache maps physical ZODB paths to disk files.
- self.cache=OOBTree.OOBTree()
- self.writelock = allocate_lock()
- self.next_cleanup = 0
- self.setDir(path)
- self._makeDirs()
- self._naming_expr = None
-
- def _fileName(self, ob):
- """ Compute a filename based on an MD5 hash: doesn't preserve
- human-readable path, but otherwise makes life much easier """
- if self._naming_expr is not None:
- expr_context = self.getExprContext(ob)
- munged = self._naming_expr(expr_context)
- fname = os.path.join(self._dir, munged)
- else:
- phys_path = '/'.join(ob.getPhysicalPath())[1:]
- hashed = md5.new(phys_path).hexdigest()
- fname = os.path.join(self._dir, hashed[:2], hashed)
-
- return fname
-
- def getExprContext(self, ob=None):
- """ Create a context for evaluating the TAL naming expression """
- data = { 'user' : getSecurityManager().getUser()
- , 'request' : getattr(ob, 'REQUEST', None)
- , 'modules' : SecureModuleImporter
- , 'object' : ob
- , 'object_url' : ob.absolute_url()
- , 'nothing' : None
- }
-
- return getEngine().getContext(data)
-
- def setNamingExpression(self, naming_expression=''):
- """ Set a new file naming expression """
- msg = ''
-
- if naming_expression:
- try:
- self._naming_expr = getEngine().compile(naming_expression)
- except CompilerError:
- msg = 'Invalid TAL expression "%s"' % naming_expression
- else:
- self._naming_expr = None
-
- return msg
-
- def getDir(self):
- """ Retrieve the filesystem directory used for caching """
- return self._dir
-
- def setDir(self, dir):
- """ Set the filesystem diriectory to use for caching """
- self._dir = dir
- self._makeDirs()
-
- def ZCache_invalidate(self, ob):
- """ Invalidate cache entries that apply to ob """
- fname = self._fileName(ob)
-
- try:
- try:
- self.writelock.acquire()
- if os.path.exists(fname): # XXX race?
- os.remove(fname)
- except IOError, msg:
- zLOG.LOG( 'FileCacheManager'
- , zLOG.ERROR
- , 'IOError removing file'
- , error=msg
- )
- finally:
- self.writelock.release()
-
- def ZCache_get(self, ob, view_name='', keywords=None,
- mtime_func=None, default=None):
- """ Gets a cache entry and return a filestream_iterator """
- fname = self._fileName(ob)
-
- try:
- fiter = filestream_iterator(fname, 'rb')
- except IOError:
- # couldn't get the actual cache
- zLOG.LOG('FileCacheManager', zLOG.INFO,
- 'Failed to retrieve cache for %s' % \
- '/'.join(ob.getPhysicalPath())
- )
- return default
-
- return fiter
-
- def ZCache_set(self, ob, data=None, view_name='', keywords=None,
- mtime_func=None):
- """ Sets a cache entry. """
- fname = self._fileName(ob)
-
- if data is None:
- # maybe it's a File or an Image, grab the data
- data = ob.data
-
- try:
- if fname:
- # use a temp. file for writing.
- fd, tempname = tempfile.mkstemp()
- # isinstance won't work on extension class
- if type(data) == type(''):
- os.write(fd, data)
- else:
- # Image pdata objects?
- # there's no interface to check
- # and I don't want to test meta_type, so
- # assume that's what we have here.
- while data is not None and hasattr(data, 'next'):
- os.write(fd, data.data)
- data = data.next
-
- os.fsync(fd)
- os.close(fd)
- # rename that sucker.
- # This may fail if they are not on the same filesystem.
- try:
- self.writelock.acquire()
- try:
- os.rename(tempname, fname)
- except OSError:
- # windows fails if fname exists.
- # if this doesn't work, tough noogies
- os.unlink(fname)
- os.rename(tempname, fname)
- finally:
- self.writelock.release()
-
- except IOError, msg:
- LOG('FileCacheManager', ERROR, 'IOError writing file', error=msg)
-
- def _makeDirs(self):
- """ Make sure we have somewhere to put files. """
- chars = '0123456789abcdef'
-
- for char in chars:
- for char2 in chars:
- dirpath = os.path.join(self._dir, '%s%s' % (char, char2))
- try:
- os.makedirs(dirpath)
- except OSError:
- zLOG.LOG('FileCacheManager', zLOG.PROBLEM,
- 'unable to create directory %s' % dirpath)
-
-
class FileCacheManager(RAMCacheManager):
""" A cache manager for caching data to filesystem """
More information about the Zope-CVS
mailing list