document: enhance API for iter() on node_descriptors

Starting from WebDAV, the node_descriptors will need to act as stream
objects, iterable. This way, we hope to minimize copies of the huge
chunks of data each descriptor may contain (still, pywebdav will use a
single large buffer).

bzr revid: p_christ@hol.gr-20101103112534-go57aeaw946utfc5
This commit is contained in:
P. Christeas 2010-11-03 13:25:34 +02:00
parent deffd9703d
commit 7f882e14cf
2 changed files with 35 additions and 3 deletions

View File

@ -48,7 +48,7 @@ DMS_ROOT_PATH = tools.config.get('document_path', os.path.join(tools.config.get(
We have to consider 3 cases of data /retrieval/:
Given (context,path) we need to access the file (aka. node).
given (directory, context), we need one of its children (for listings, views)
given (ir.attachment, context), we needs its data and metadata (node).
given (ir.attachment, context), we need its data and metadata (node).
For data /storage/ we have the cases:
Have (ir.attachment, context), we modify the file (save, update, rename etc).
@ -100,10 +100,17 @@ class nodefd_file(nodes.node_descriptor):
if mode.endswith('b'):
mode = mode[:-1]
self.mode = mode
self._size = os.stat(path).st_size
for attr in ('closed', 'read', 'write', 'seek', 'tell'):
for attr in ('closed', 'read', 'write', 'seek', 'tell', 'next'):
setattr(self,attr, getattr(self.__file, attr))
def size(self):
return self._size
def __iter__(self):
return self
def close(self):
# TODO: locking in init, close()
fname = self.__file.name
@ -165,6 +172,7 @@ class nodefd_db(StringIO, nodes.node_descriptor):
"""
def __init__(self, parent, ira_browse, mode):
nodes.node_descriptor.__init__(self, parent)
self._size = 0L
if mode.endswith('b'):
mode = mode[:-1]
@ -172,6 +180,7 @@ class nodefd_db(StringIO, nodes.node_descriptor):
cr = ira_browse._cr # reuse the cursor of the browse object, just now
cr.execute('SELECT db_datas FROM ir_attachment WHERE id = %s',(ira_browse.id,))
data = cr.fetchone()[0]
self._size = len(data)
StringIO.__init__(self, data)
elif mode in ('w', 'w+'):
StringIO.__init__(self, None)
@ -184,6 +193,9 @@ class nodefd_db(StringIO, nodes.node_descriptor):
raise IOError(errno.EINVAL, "Invalid file mode")
self.mode = mode
def size(self):
return self._size
def close(self):
# we now open a *separate* cursor, to update the data.
# FIXME: this may be improved, for concurrency handling
@ -241,11 +253,14 @@ class nodefd_db64(StringIO, nodes.node_descriptor):
"""
def __init__(self, parent, ira_browse, mode):
nodes.node_descriptor.__init__(self, parent)
self._size = 0L
if mode.endswith('b'):
mode = mode[:-1]
if mode in ('r', 'r+'):
StringIO.__init__(self, base64.decodestring(ira_browse.db_datas))
data = base64.decodestring(ira_browse.db_datas)
self._size = len(data)
StringIO.__init__(self, data)
elif mode in ('w', 'w+'):
StringIO.__init__(self, None)
# at write, we start at 0 (= overwrite), but have the original
@ -257,6 +272,9 @@ class nodefd_db64(StringIO, nodes.node_descriptor):
raise IOError(errno.EINVAL, "Invalid file mode")
self.mode = mode
def size(self):
return self._size
def close(self):
# we now open a *separate* cursor, to update the data.
# FIXME: this may be improved, for concurrency handling

View File

@ -175,6 +175,15 @@ class node_descriptor(object):
def write(self, str):
raise NotImplementedError
def size(self):
raise NotImplementedError
def __len__(self):
return self.size()
def next(self, str):
raise NotImplementedError
class node_class(object):
""" this is a superclass for our inodes
It is an API for all code that wants to access the document files.
@ -1403,11 +1412,13 @@ class nodefd_content(StringIO, node_descriptor):
def __init__(self, parent, cr, mode, ctx):
node_descriptor.__init__(self, parent)
self._context=ctx
self._size = 0L
if mode in ('r', 'r+'):
cntobj = parent.context._dirobj.pool.get('document.directory.content')
data = cntobj.process_read(cr, parent.context.uid, parent, ctx)
if data:
self._size = len(data)
parent.content_length = len(data)
StringIO.__init__(self, data)
elif mode in ('w', 'w+'):
@ -1421,6 +1432,9 @@ class nodefd_content(StringIO, node_descriptor):
raise IOError(errno.EINVAL, "Invalid file mode")
self.mode = mode
def size(self):
return self._size
def close(self):
# we now open a *separate* cursor, to update the data.
# FIXME: this may be improved, for concurrency handling