############################################################################## # # Zope Public License (ZPL) Version 1.0 # ------------------------------------- # # Copyright (c) Digital Creations. All rights reserved. # Copyright (c) 2000 Petru Paler (ppetru@coltronix.com) All rights reserved. # # This license has been certified as Open Source(tm). # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # 1. Redistributions in source code must retain the above copyright # notice, this list of conditions, and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions, and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # 3. Digital Creations requests that attribution be given to Zope # in any manner possible. Zope includes a "Powered by Zope" # button that is installed by default. While it is not a license # violation to remove this button, it is requested that the # attribution remain. A significant investment has been put # into Zope, and this effort will continue if the Zope community # continues to grow. This is one way to assure that growth. # # 4. All advertising materials and documentation mentioning # features derived from or use of this software must display # the following acknowledgement: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # In the event that the product being advertised includes an # intact Zope distribution (with copyright and license included) # then this clause is waived. # # 5. Names associated with Zope or Digital Creations must not be used to # endorse or promote products derived from this software without # prior written permission from Digital Creations. # # 6. Modified redistributions of any form whatsoever must retain # the following acknowledgment: # # "This product includes software developed by Digital Creations # for use in the Z Object Publishing Environment # (http://www.zope.org/)." # # Intact (re-)distributions of any official Zope release do not # require an external acknowledgement. # # 7. Modifications are encouraged but must be packaged separately as # patches to official Zope releases. Distributions that do not # clearly separate the patches from the original work must be clearly # labeled as unofficial distributions. Modifications which do not # carry the name Zope may be packaged in any form, as long as they # conform to all of the clauses above. # # # Disclaimer # # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY # EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL CREATIONS OR ITS # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # # This software consists of contributions made by Digital Creations and # many individuals on behalf of Digital Creations. Specific # attributions are listed in the accompanying credits file. # ############################################################################## # To-do list: # Critical: # - Most I/O operations are not atomic. This means that I/O errors (and, for # that matter, any exceptions occured in _finish) leave the storage in an # undefined state # # Not critical: # - Performance tuning -- add caches where apropiate # - make sure locking is ok # - provide directory splitting to enable use on non-reiser filesystems # # ... and probably many others """ReiserFS storage""" __version__ = "0.01" from BaseStorage import BaseStorage import POSException import os, struct, stat, operator from posix import fsync def oid2str(oid): return "%02X"*8 % struct.unpack("!8B", oid) class ReiserStorage(BaseStorage): def __init__(self, dirname): if dirname[-1] != '/': dirname = dirname + '/' BaseStorage.__init__(self, dirname) self._oid_dir = dirname + 'oid/' self._tindex = [] self._oid = '\0\0\0\0\0\0\0\0' try: f = open(dirname+'last_oid', 'rt') self._oid = f.read() f.close() except: pass self.lof = open(dirname+'last_oid', 'wt') def __len__(self): print '__len__' return len(os.listdir(self._oid_dir)) def getSize(self): print 'getSize' files = os.listdir(self._oid_dir) files = map(lambda x,d=self._oid_dir: d+x, files) sizes = map(lambda x: os.stat(x)[stat.ST_SIZE], files) return reduce(operator.add, sizes) def load(self, oid, version): self._lock_acquire() try: f = open(self._oid_dir+oid2str(oid), 'rb') p = f.read() f.close() return p[8:], p[:8] finally: self._lock_release() def store(self, oid, serial, data, version, transaction): if transaction is not self._transaction: raise POSException.StorageTransactionError(self, transaction) if version: raise POSException.Unsupported, "Versions aren't supported" self._lock_acquire() try: fname = self._oid_dir+oid2str(oid) if os.path.exists(fname): try: f = open(fname, 'rb') if serial != f.read(8): raise POSException.ConflictError f.close() except IOError: raise POSException.StorageSystemError, 'I/O error while checking for conflicts' serial = self._serial self._tindex.append((oid, serial+data)) finally: self._lock_release() return serial def _begin(self, tid, u, d, e): pass def _clear_temp(self): self._tindex = [] def _finish(self, tid, user, desc, ext): try: for oid, data in self._tindex: f = open(self._oid_dir+oid2str(oid), 'wb') f.write(data) fsync(f.fileno()) f.close() self.lof.seek(0) self.lof.write(self._oid) fsync(self.lof.fileno()) except: raise POSException.TransactionError, 'I/O error commiting transaction -- your storage is likely corrupt' def pack(self, t, referencesf): maxoid = oid2str(self._oid) rootl = ['\0\0\0\0\0\0\0\0'] pop = rootl.pop pindex = {} referenced = pindex.has_key while rootl: oid = pop() if referenced(oid): continue # scan pickle for references f = open(self._oid_dir+oid2str(oid)) r = f.read() f.close() pindex[oid2str(oid)] = r p = r[8:] referencesf(p, rootl) # now delete any unreferenced entries deleted = [] for oid in os.listdir(self._oid_dir): if not referenced(oid) and (oid <= maxoid): deleted.append(oid) try: for i in deleted: os.unlink(self._oid_dir+i) except: raise POSException.TransactionError, 'I/O error during pack -- your storage is probably screwed up'