make get_size/get_current_size consistent for all IFilesystemNode classes

* stop caching most_recent_size in dirnode, rely upon backing filenode for it
* start caching most_recent_size in MutableFileNode
* return None when you don't know, not "?"
* only render None as "?" in the web "more info" page
* add get_size/get_current_size to UnknownNode
This commit is contained in:
Brian Warner 2009-11-18 11:16:24 -08:00
parent 512fe3ad62
commit e046744f40
7 changed files with 61 additions and 31 deletions

View File

@ -195,7 +195,6 @@ class DirectoryNode:
self._uri = wrap_dirnode_cap(filenode_cap)
self._nodemaker = nodemaker
self._uploader = uploader
self._most_recent_size = None
def __repr__(self):
return "<%s %s-%s %s>" % (self.__class__.__name__,
@ -204,22 +203,19 @@ class DirectoryNode:
hasattr(self, '_uri') and self._uri.abbrev())
def get_size(self):
# return the size of our backing mutable file, in bytes, if we've
# fetched it.
if not self._node.is_mutable():
# TODO?: consider using IMutableFileNode.providedBy(self._node)
return self._node.get_size()
return self._most_recent_size
"""Return the size of our backing mutable file, in bytes, if we've
fetched it. Otherwise return None. This returns synchronously."""
return self._node.get_size()
def _set_size(self, data):
self._most_recent_size = len(data)
return data
def get_current_size(self):
"""Calculate the size of our backing mutable file, in bytes. Returns
a Deferred that fires with the result."""
return self._node.get_current_size()
def _read(self):
if self._node.is_mutable():
# use the IMutableFileNode API.
d = self._node.download_best_version()
d.addCallback(self._set_size)
else:
d = self._node.download_to_data()
d.addCallback(self._unpack_contents)
@ -706,9 +702,10 @@ class DeepStats:
def enter_directory(self, parent, children):
dirsize_bytes = parent.get_size()
if dirsize_bytes is not None:
self.add("size-directories", dirsize_bytes)
self.max("largest-directory", dirsize_bytes)
dirsize_children = len(children)
self.add("size-directories", dirsize_bytes)
self.max("largest-directory", dirsize_bytes)
self.max("largest-directory-children", dirsize_children)
def add(self, key, value=1):

View File

@ -196,6 +196,8 @@ class FileNode(_ImmutableFileNodeBase, log.PrefixingLogMixin):
def get_size(self):
return self.u.get_size()
def get_current_size(self):
return defer.succeed(self.get_size())
def get_cap(self):
return self.u
@ -323,6 +325,8 @@ class LiteralFileNode(_ImmutableFileNodeBase):
def get_size(self):
return len(self.u.data)
def get_current_size(self):
return defer.succeed(self.get_size())
def get_cap(self):
return self.u

View File

@ -550,6 +550,19 @@ class IFilesystemNode(Interface):
file.
"""
def get_size():
"""Return the length (in bytes) of the data this node represents. For
directory nodes, I return the size of the backing store. I return
synchronously and do not consult the network, so for mutable objects,
I will return the most recently observed size for the object, or None
if I don't remember a size. Use get_current_size, which returns a
Deferred, if you want more up-to-date information."""
def get_current_size():
"""I return a Deferred that fires with the length (in bytes) of the
data this node represents.
"""
class IMutableFilesystemNode(IFilesystemNode):
pass
@ -561,9 +574,6 @@ class IFileNode(IFilesystemNode):
"""Download the file's contents. Return a Deferred that fires
with those contents."""
def get_size():
"""Return the length (in bytes) of the data this node represents."""
def read(consumer, offset=0, size=None):
"""Download a portion (possibly all) of the file's contents, making
them available to the given IConsumer. Return a Deferred that fires

View File

@ -63,6 +63,7 @@ class MutableFileNode:
self._total_shares = default_encoding_parameters["n"]
self._sharemap = {} # known shares, shnum-to-[nodeids]
self._cache = ResponseCache()
self._most_recent_size = None
# all users of this MutableFileNode go through the serializer. This
# takes advantage of the fact that Deferreds discard the callbacks
@ -186,7 +187,14 @@ class MutableFileNode:
# IFilesystemNode
def get_size(self):
return "?" # TODO: this is likely to cause problems, not being an int
return self._most_recent_size
def get_current_size(self):
d = self.get_size_of_best_version()
d.addCallback(self._stash_size)
return d
def _stash_size(self, size):
self._most_recent_size = size
return size
def get_cap(self):
return self._uri
@ -427,7 +435,12 @@ class MutableFileNode:
r = Retrieve(self, servermap, version, fetch_privkey)
if self._history:
self._history.notify_retrieve(r.get_status())
return r.download()
d = r.download()
d.addCallback(self._downloaded_version)
return d
def _downloaded_version(self, data):
self._most_recent_size = len(data)
return data
def upload(self, new_contents, servermap):
return self._do_serialized(self._upload, new_contents, servermap)
@ -436,4 +449,9 @@ class MutableFileNode:
p = Publish(self, self._storage_broker, servermap)
if self._history:
self._history.notify_publish(p.get_status(), len(new_contents))
return p.publish(new_contents)
d = p.publish(new_contents)
d.addCallback(self._did_upload, len(new_contents))
return d
def _did_upload(self, res, size):
self._most_recent_size = size
return res

View File

@ -201,7 +201,9 @@ class FakeMutableFileNode:
def get_writekey(self):
return "\x00"*16
def get_size(self):
return "?" # TODO: see mutable.MutableFileNode.get_size
return len(self.all_contents[self.storage_index])
def get_current_size(self):
return self.get_size_of_best_version()
def get_size_of_best_version(self):
return defer.succeed(len(self.all_contents[self.storage_index]))

View File

@ -19,6 +19,10 @@ class UnknownNode:
return None
def get_repair_cap(self):
return None
def get_size(self):
return None
def get_current_size(self):
return defer.succeed(None)
def check(self, monitor, verify, add_lease):
return defer.succeed(None)
def check_and_repair(self, monitor, verify, add_lease):

View File

@ -55,17 +55,12 @@ class MoreInfo(rend.Page):
def render_size(self, ctx, data):
node = self.original
si = node.get_storage_index()
if IDirectoryNode.providedBy(node):
d = node._node.get_size_of_best_version()
elif IFileNode.providedBy(node):
if node.is_mutable():
d = node.get_size_of_best_version()
else:
# for immutable files and LIT files, we get the size from the
# URI
d = defer.succeed(node.get_size())
else:
d = defer.succeed("?")
d = node.get_current_size()
def _no_size(size):
if size is None:
return "?"
return size
d.addCallback(_no_size)
def _handle_unrecoverable(f):
f.trap(UnrecoverableFileError)
return "?"