Changeset 6528


Ignore:
Timestamp:
23 Jul 2011, 02:22:13 (13 years ago)
Author:
uli
Message:

Fix imagestorage. It took ages to find out, that strange behaviour of
saved image files (content disappearing, etc.) was not due to the
imagestorage implementation, but most probably caused by some design
problem in ZODB Blob storage. Nevertheless the new implementation
seems to work properly.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.sirp/trunk/src/waeup/sirp/imagestorage.py

    r6519 r6528  
    2525import hashlib
    2626import os
     27import transaction
     28import warnings
    2729from StringIO import StringIO
    2830from ZODB.blob import Blob
    2931from persistent import Persistent
    3032from hurry.file.interfaces import IFileRetrieval
    31 from zope.container.contained import Contained
    3233from waeup.sirp.image import WAeUPImageFile
    3334from waeup.sirp.utils.helpers import cmp_files
     
    4546    """A basket holds a set of image files with same hash.
    4647    """
     48
    4749    def _del(self):
    4850        """Remove temporary files associated with local blobs.
     
    7173
    7274    def getInternalId(self, fd):
     75        """Get the basket-internal id for the file stored in `fd`.
     76
     77        `fd` must be a file open for reading. If an (byte-wise) equal
     78        file can be found in the basket, its internal id (basket id)
     79        is returned, ``None`` otherwise.
     80        """
     81        fd.seek(0)
    7382        for key, val in self.items():
    74             fd.seek(0)
    7583            fd_stored = val.open('r')
     84            file_len = os.stat(fd_stored.name)[6]
     85            if file_len == 0:
     86                # Nasty workaround. Blobs seem to suffer from being emptied
     87                # accidentally.
     88                site = grok.getSite()
     89                if site is not None:
     90                    site.logger.warn(
     91                        'Empty Blob detected: %s' % fd_stored.name)
     92                warnings.warn("EMPTY BLOB DETECTED: %s" % fd_stored.name)
     93                fd_stored.close()
     94                val.open('w').write(fd.read())
     95                return key
     96            fd_stored.seek(0)
    7697            if cmp_files(fd, fd_stored):
    7798                fd_stored.close()
     
    82103    @property
    83104    def curr_id(self):
     105        """The current basket id.
     106
     107        An integer number which is not yet in use. If there are
     108        already `maxint` entries in the basket, a :exc:`ValueError` is
     109        raised. The latter is _highly_ unlikely. It would mean to have
     110        more than 2**32 hash collisions, i.e. so many files with the
     111        same MD5 sum.
     112        """
    84113        num = 1
    85114        while True:
     
    92121
    93122    def storeFile(self, fd, filename):
    94         internal_id = self.getInternalId(fd)
     123        """Store the file in `fd` into the basket.
     124
     125        The file will be stored in a Blob.
     126        """
     127        fd.seek(0)
     128        internal_id = self.getInternalId(fd) # Moves file pointer!
    95129        if internal_id is None:
    96130            internal_id = self.curr_id
    97             self[internal_id] = Blob(fd.read())
     131            fd.seek(0)
     132            self[internal_id] = Blob()
     133            transaction.commit() # Urgently needed to make the Blob
     134                                 # persistent. Took me ages to find
     135                                 # out that solution, which makes some
     136                                 # design flaw in ZODB Blobs likely.
     137            self[internal_id].open('w').write(fd.read())
     138            fd.seek(0)
     139            self._p_changed = True
    98140        return internal_id
    99141
    100142    def retrieveFile(self, basket_id):
     143        """Retrieve a file open for reading with basket id `basket_id`.
     144
     145        If there is no such id, ``None`` is returned. It is the
     146        callers responsibility to close the open file.
     147        """
    101148        if basket_id in self.keys():
    102149            return self[basket_id].open('r')
     
    156203        if storage is None:
    157204            raise ValueError('Cannot find an image storage')
     205        result = storage.retrieveFile(data)
     206        if result is None:
     207            return StringIO(data)
    158208        return storage.retrieveFile(data)
    159209
Note: See TracChangeset for help on using the changeset viewer.