mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2024-12-19 21:17:54 +00:00
dirnode: add set_uris() and set_nodes() (plural), to set multiple children at once. Use it to set up a new webapi test for issue #237.
This commit is contained in:
parent
2308420fc6
commit
9a8f68c41f
@ -6,7 +6,7 @@ from twisted.internet import defer
|
||||
import simplejson
|
||||
from allmydata.mutable import NotMutableError
|
||||
from allmydata.interfaces import IMutableFileNode, IDirectoryNode,\
|
||||
IURI, IFileNode, IMutableFileURI, IVerifierURI
|
||||
IURI, IFileNode, IMutableFileURI, IVerifierURI, IFilesystemNode
|
||||
from allmydata.util import hashutil
|
||||
from allmydata.util.hashutil import netstring
|
||||
from allmydata.uri import NewDirectoryURI
|
||||
@ -131,7 +131,7 @@ class NewDirectoryNode:
|
||||
child, metadata = children[name]
|
||||
assert (IFileNode.providedBy(child)
|
||||
or IMutableFileNode.providedBy(child)
|
||||
or IDirectoryNode.providedBy(child)), children
|
||||
or IDirectoryNode.providedBy(child)), (name,child)
|
||||
assert isinstance(metadata, dict)
|
||||
rwcap = child.get_uri() # might be RO if the child is not writeable
|
||||
rocap = child.get_readonly_uri()
|
||||
@ -224,7 +224,20 @@ class NewDirectoryNode:
|
||||
|
||||
If this directory node is read-only, the Deferred will errback with a
|
||||
NotMutableError."""
|
||||
return self.set_node(name, self._create_node(child_uri), metadata, wait_for_numpeers=wait_for_numpeers)
|
||||
return self.set_node(name, self._create_node(child_uri), metadata,
|
||||
wait_for_numpeers)
|
||||
|
||||
def set_uris(self, entries, wait_for_numpeers=None):
|
||||
node_entries = []
|
||||
for e in entries:
|
||||
if len(e) == 2:
|
||||
name, child_uri = e
|
||||
metadata = {}
|
||||
else:
|
||||
assert len(e) == 3
|
||||
name, child_uri, metadata = e
|
||||
node_entries.append( (name,self._create_node(child_uri),metadata) )
|
||||
return self.set_nodes(node_entries, wait_for_numpeers)
|
||||
|
||||
def set_node(self, name, child, metadata={}, wait_for_numpeers=None):
|
||||
"""I add a child at the specific name. I return a Deferred that fires
|
||||
@ -234,17 +247,31 @@ class NewDirectoryNode:
|
||||
|
||||
If this directory node is read-only, the Deferred will errback with a
|
||||
NotMutableError."""
|
||||
assert IFilesystemNode.providedBy(child), child
|
||||
d = self.set_nodes( [(name, child, metadata)], wait_for_numpeers)
|
||||
d.addCallback(lambda res: child)
|
||||
return d
|
||||
|
||||
def set_nodes(self, entries, wait_for_numpeers=None):
|
||||
if self.is_readonly():
|
||||
return defer.fail(NotMutableError())
|
||||
d = self._read()
|
||||
def _add(children):
|
||||
children[name] = (child, metadata)
|
||||
for e in entries:
|
||||
if len(e) == 2:
|
||||
name, child = e
|
||||
metadata = {}
|
||||
else:
|
||||
assert len(e) == 3
|
||||
name, child, metadata = e
|
||||
children[name] = (child, metadata)
|
||||
new_contents = self._pack_contents(children)
|
||||
return self._node.replace(new_contents, wait_for_numpeers=wait_for_numpeers)
|
||||
d.addCallback(_add)
|
||||
d.addCallback(lambda res: child)
|
||||
d.addCallback(lambda res: None)
|
||||
return d
|
||||
|
||||
|
||||
def add_file(self, name, uploadable, wait_for_numpeers=None):
|
||||
"""I upload a file (using the given IUploadable), then attach the
|
||||
resulting FileNode to the directory at the given name. I return a
|
||||
|
@ -530,6 +530,13 @@ class IDirectoryNode(IMutableFilesystemNode):
|
||||
If this directory node is read-only, the Deferred will errback with a
|
||||
NotMutableError."""
|
||||
|
||||
def set_uris(entries):
|
||||
"""Add multiple (name, child_uri) pairs to a directory node. Returns
|
||||
a Deferred that fires (with None) when the operation finishes. This
|
||||
is equivalent to calling set_uri() multiple times, but is much more
|
||||
efficient.
|
||||
"""
|
||||
|
||||
def set_node(name, child):
|
||||
"""I add a child at the specific name. I return a Deferred that fires
|
||||
when the operation finishes. This Deferred will fire with the child
|
||||
@ -539,6 +546,13 @@ class IDirectoryNode(IMutableFilesystemNode):
|
||||
If this directory node is read-only, the Deferred will errback with a
|
||||
NotMutableError."""
|
||||
|
||||
def set_nodes(entries):
|
||||
"""Add multiple (name, child_node) pairs to a directory node. Returns
|
||||
a Deferred that fires (with None) when the operation finishes. This
|
||||
is equivalent to calling set_node() multiple times, but is much more
|
||||
efficient."""
|
||||
|
||||
|
||||
def add_file(name, uploadable):
|
||||
"""I upload a file (using the given IUploadable), then attach the
|
||||
resulting FileNode to the directory at the given name. I return a
|
||||
|
@ -606,6 +606,35 @@ class Web(WebMixin, unittest.TestCase):
|
||||
|
||||
return d
|
||||
|
||||
def test_GET_DIRURL_large(self):
|
||||
# Nevow has a problem showing more than about 192 children of a
|
||||
# directory: it uses defer.success() and d.addCallback in a way that
|
||||
# can make the stack grow very quickly. See ticket #237 for details.
|
||||
# To work around this, I think we'll need to put a 'return
|
||||
# defer.fireEventually' in our render_ method. This test is intended
|
||||
# to trigger the bug (and eventually verify that our workaround
|
||||
# actually works), but it isn't yet failing for me.
|
||||
|
||||
d = self.s.create_empty_dirnode()
|
||||
COUNT = 400
|
||||
def _created(dirnode):
|
||||
entries = [ (str(i), self._foo_uri) for i in range(COUNT) ]
|
||||
d2 = dirnode.set_uris(entries)
|
||||
d2.addCallback(lambda res: dirnode)
|
||||
return d2
|
||||
d.addCallback(_created)
|
||||
|
||||
def _check(dirnode):
|
||||
large_url = "/uri/" + dirnode.get_uri() + "/"
|
||||
return self.GET(large_url)
|
||||
d.addCallback(_check)
|
||||
|
||||
def _done(res):
|
||||
self.failUnless('<a href="%d">%d</a>' % (COUNT-1, COUNT-1) in res)
|
||||
self.failIf("maximum recursion depth exceeded" in res)
|
||||
d.addCallback(_done)
|
||||
return d
|
||||
|
||||
def test_GET_DIRURL_json(self):
|
||||
d = self.GET(self.public_url + "/foo?t=json")
|
||||
d.addCallback(self.failUnlessIsFooJSON)
|
||||
|
Loading…
Reference in New Issue
Block a user