[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