[Checkins] SVN: z3c.extfile/trunk/src/z3c/extfile/ the readfile
does not use thread local anymore,
we handle the closing of readfiles in extbytesproperty,
because this is the only place where the file is implicitly opened,
and should be impl. closed too
Bernd Dorn
bernd.dorn at fhv.at
Thu Sep 14 03:39:36 EDT 2006
Log message for revision 70164:
the readfile does not use thread local anymore, we handle the closing of readfiles in extbytesproperty, because this is the only place where the file is implicitly opened, and should be impl. closed too
Changed:
U z3c.extfile/trunk/src/z3c/extfile/hashdir.py
U z3c.extfile/trunk/src/z3c/extfile/property.py
-=-
Modified: z3c.extfile/trunk/src/z3c/extfile/hashdir.py
===================================================================
--- z3c.extfile/trunk/src/z3c/extfile/hashdir.py 2006-09-13 22:28:56 UTC (rev 70163)
+++ z3c.extfile/trunk/src/z3c/extfile/hashdir.py 2006-09-14 07:39:34 UTC (rev 70164)
@@ -7,8 +7,8 @@
import interfaces
from zope import interface
from persistent import Persistent
-from zope import thread
+
class HashDir(Persistent):
"""a directory holding files named after their sha1 hash"""
@@ -72,8 +72,8 @@
def open(self, digest):
return ReadFile(self.getPath(digest))
-openFiles = thread.local()
+
class ReadFile(object):
interface.implements(interfaces.IReadFile)
@@ -83,18 +83,15 @@
self.digest = os.path.split(self.name)[1]
self.bufsize=bufsize
self._v_len = None
+ self._v_file = None
@property
def _file(self):
- if hasattr(openFiles, self.digest):
- f = getattr(openFiles, self.digest)
- if f.closed:
- delattr(openFiles, self.digest)
- else:
- return f
- f = file(self.name, 'rb', self.bufsize)
- setattr(openFiles, self.digest, f)
- return f
+ if self._v_file is not None:
+ if not self._v_file.closed:
+ return self._v_file
+ self._v_file = file(self.name, 'rb', self.bufsize)
+ return self._v_file
def __len__(self):
if self._v_len is None:
@@ -121,11 +118,10 @@
def close(self):
"""see file.close"""
- if hasattr(openFiles, self.digest):
- f = getattr(openFiles, self.digest)
- if not f.closed:
- f.close()
- delattr(openFiles, self.digest)
+ if self._v_file is not None:
+ if not self._v_file.closed:
+ return self._v_file.close()
+ self._v_file = None
def fileno(self):
return self._file.fileno()
Modified: z3c.extfile/trunk/src/z3c/extfile/property.py
===================================================================
--- z3c.extfile/trunk/src/z3c/extfile/property.py 2006-09-13 22:28:56 UTC (rev 70163)
+++ z3c.extfile/trunk/src/z3c/extfile/property.py 2006-09-14 07:39:34 UTC (rev 70164)
@@ -1,29 +1,43 @@
from zope import component, interface
import interfaces
from cStringIO import StringIO
+from transaction.interfaces import IDataManager
+from zope import thread
+import transaction
_marker = object()
BLOCK_SIZE = 1024*128
+_storage = thread.local()
+
class ExtBytesProperty(object):
"""a property which's values are stored as external files"""
def __init__(self, name):
self.__name = name
+
@property
def hd(self):
return component.getUtility(interfaces.IHashDir)
def __get__(self, inst, klass):
+
if inst is None:
return self
digest = inst.__dict__.get(self.__name, _marker)
if digest is _marker:
return None
- return self.hd.open(digest)
+
+ if not hasattr(_storage, 'dataManager'):
+ _storage.dataManager = ReadFileDataManager()
+ txn = transaction.manager.get()
+ if txn is not None:
+ txn.join(_storage.dataManager)
+ return _storage.dataManager.getFile(digest)
+
def __set__(self, inst, value):
# ignore if value is None
if value is None:
@@ -44,3 +58,48 @@
f.write(chunk)
+class ReadFileDataManager(object):
+
+ """Takes care of closing open files"""
+
+ interface.implements(IDataManager)
+
+ def __init__(self):
+ self.files = {}
+
+ @property
+ def hd(self):
+ return component.getUtility(interfaces.IHashDir)
+
+ def getFile(self, digest):
+ if digest in self.files:
+ return self.files[digest]
+ self.files[digest] = self.hd.open(digest)
+ return self.files[digest]
+
+ def _close(self):
+ import logging
+ logging.info('RFD.colse %r' % self.files.keys())
+ for f in self.files.values():
+ f.close()
+
+ def abort(self, trans):
+ self._close()
+
+ def tpc_begin(self, trans):
+ pass
+
+ def commit(self, trans):
+ self._close()
+
+ def tpc_vote(self, trans):
+ pass
+
+ def tpc_finish(self, trans):
+ self._close()
+
+ def tpc_abort(self, trans):
+ self._close()
+
+ def sortKey(self):
+ return str(id(self))
More information about the Checkins
mailing list