upload: return an UploadResults instance (with .uri) instead of just a URI

This commit is contained in:
Brian Warner 2008-02-05 21:01:38 -07:00
parent 2f09b03bcc
commit 66f33ee504
11 changed files with 75 additions and 17 deletions

View File

@ -46,6 +46,7 @@ class ControlServer(Referenceable, service.Service, testutil.PollMixin):
uploader = self.parent.getServiceNamed("uploader")
u = upload.FileName(filename)
d = uploader.upload(u)
d.addCallback(lambda results: results.uri)
return d
def remote_download_from_uri_to_file(self, uri, filename):
@ -162,6 +163,7 @@ class SpeedTest:
else:
up = upload.FileName(fn)
d1 = self.parent.upload(up)
d1.addCallback(lambda results: results.uri)
d1.addCallback(_record_uri, i)
d1.addCallback(_upload_one_file, i+1)
return d1

View File

@ -279,6 +279,7 @@ class NewDirectoryNode:
if self.is_readonly():
return defer.fail(NotMutableError())
d = self._client.upload(uploadable)
d.addCallback(lambda results: results.uri)
d.addCallback(self._client.create_node_from_uri)
d.addCallback(lambda node: self.set_node(name, node))
return d

View File

@ -1207,10 +1207,19 @@ class IUploadable(Interface):
"""The upload is finished, and whatever filehandle was in use may be
closed."""
class IUploadResults(Interface):
"""I am returned by upload() methods. I contain a number of public
attributes which can be read to determine the results of the upload::
.uri : the CHK read-cap for the file
"""
class IUploader(Interface):
def upload(uploadable):
"""Upload the file. 'uploadable' must impement IUploadable. This
returns a Deferred which fires with the URI of the file."""
returns a Deferred which fires with an UploadResults instance, from
which the URI of the file can be obtained as results.uri ."""
def upload_ssk(write_capability, new_version, uploadable):
"""TODO: how should this work?"""
@ -1278,9 +1287,10 @@ class IChecker(Interface):
class IClient(Interface):
def upload(uploadable):
"""Upload some data into a CHK, get back the URI string for it.
"""Upload some data into a CHK, get back the UploadResults for it.
@param uploadable: something that implements IUploadable
@return: a Deferred that fires with the (string) URI for this file.
@return: a Deferred that fires with the UploadResults instance.
To get the URI for this file, use results.uri .
"""
def create_mutable_file(contents=""):

View File

@ -392,6 +392,7 @@ this file are ignored.
u = self.nodes[0].getServiceNamed("uploader")
d = self.nodes[0].debug_wait_for_client_connections(self.numnodes+1)
d.addCallback(lambda res: u.upload(upload.FileName(files[name])))
d.addCallback(lambda results: results.uri)
else:
raise RuntimeError("unknown mode=%s" % self.mode)
def _complete(uri):

View File

@ -44,7 +44,9 @@ class FakeClient:
def _got_data(datav):
data = "".join(datav)
n = create_chk_filenode(self, data)
return n.get_uri()
results = upload.UploadResults()
results.uri = n.get_uri()
return results
d.addCallback(_got_data)
return d

View File

@ -98,7 +98,8 @@ class AssistedUpload(unittest.TestCase):
DATA = "I need help\n" * 1000
return upload_data(u, DATA)
d.addCallback(_ready)
def _uploaded(uri):
def _uploaded(results):
uri = results.uri
assert "CHK" in uri
d.addCallback(_uploaded)
@ -141,7 +142,8 @@ class AssistedUpload(unittest.TestCase):
assert u._helper
return upload_data(u, DATA)
d.addCallback(_ready)
def _uploaded(uri):
def _uploaded(results):
uri = results.uri
assert "CHK" in uri
d.addCallback(_uploaded)
@ -172,7 +174,8 @@ class AssistedUpload(unittest.TestCase):
DATA = "I need help\n" * 1000
return upload_data(u, DATA)
d.addCallback(_ready)
def _uploaded(uri):
def _uploaded(results):
uri = results.uri
assert "CHK" in uri
d.addCallback(_uploaded)

View File

@ -214,7 +214,8 @@ class SystemTest(testutil.SignalMixin, testutil.PollMixin, unittest.TestCase):
d1 = u.upload(up)
return d1
d.addCallback(_do_upload)
def _upload_done(uri):
def _upload_done(results):
uri = results.uri
log.msg("upload finished: uri is %s" % (uri,))
self.uri = uri
dl = self.clients[1].getServiceNamed("downloader")
@ -295,7 +296,8 @@ class SystemTest(testutil.SignalMixin, testutil.PollMixin, unittest.TestCase):
def _upload_with_helper(res):
u = upload.Data(HELPER_DATA, contenthashkey=contenthashkey)
d = self.extra_node.upload(u)
def _uploaded(uri):
def _uploaded(results):
uri = results.uri
return self.downloader.download_to_data(uri)
d.addCallback(_uploaded)
def _check(newdata):
@ -308,7 +310,8 @@ class SystemTest(testutil.SignalMixin, testutil.PollMixin, unittest.TestCase):
u = upload.Data(HELPER_DATA, contenthashkey=contenthashkey)
u.debug_stash_RemoteEncryptedUploadable = True
d = self.extra_node.upload(u)
def _uploaded(uri):
def _uploaded(results):
uri = results.uri
return self.downloader.download_to_data(uri)
d.addCallback(_uploaded)
def _check(newdata):
@ -392,7 +395,8 @@ class SystemTest(testutil.SignalMixin, testutil.PollMixin, unittest.TestCase):
return self.extra_node.upload(u2)
d.addCallbacks(_upload_again)
def _uploaded(uri):
def _uploaded(results):
uri = results.uri
log.msg("Second upload complete", level=log.NOISY,
facility="tahoe.test.test_system")
reu = u2.debug_RemoteEncryptedUploadable

View File

@ -12,6 +12,9 @@ from foolscap import eventual
MiB = 1024*1024
def extract_uri(results):
return results.uri
class Uploadable(unittest.TestCase):
def shouldEqual(self, data, expected):
self.failUnless(isinstance(data, list))
@ -209,18 +212,21 @@ class GoodServer(unittest.TestCase):
def test_data_zero(self):
data = self.get_data(SIZE_ZERO)
d = upload_data(self.u, data)
d.addCallback(extract_uri)
d.addCallback(self._check_small, SIZE_ZERO)
return d
def test_data_small(self):
data = self.get_data(SIZE_SMALL)
d = upload_data(self.u, data)
d.addCallback(extract_uri)
d.addCallback(self._check_small, SIZE_SMALL)
return d
def test_data_large(self):
data = self.get_data(SIZE_LARGE)
d = upload_data(self.u, data)
d.addCallback(extract_uri)
d.addCallback(self._check_large, SIZE_LARGE)
return d
@ -230,24 +236,28 @@ class GoodServer(unittest.TestCase):
# we want 3 segments, since that's not a power of two
self.set_encoding_parameters(25, 75, 100, segsize)
d = upload_data(self.u, data)
d.addCallback(extract_uri)
d.addCallback(self._check_large, SIZE_LARGE)
return d
def test_filehandle_zero(self):
data = self.get_data(SIZE_ZERO)
d = upload_filehandle(self.u, StringIO(data))
d.addCallback(extract_uri)
d.addCallback(self._check_small, SIZE_ZERO)
return d
def test_filehandle_small(self):
data = self.get_data(SIZE_SMALL)
d = upload_filehandle(self.u, StringIO(data))
d.addCallback(extract_uri)
d.addCallback(self._check_small, SIZE_SMALL)
return d
def test_filehandle_large(self):
data = self.get_data(SIZE_LARGE)
d = upload_filehandle(self.u, StringIO(data))
d.addCallback(extract_uri)
d.addCallback(self._check_large, SIZE_LARGE)
return d
@ -258,6 +268,7 @@ class GoodServer(unittest.TestCase):
f.write(data)
f.close()
d = upload_filename(self.u, fn)
d.addCallback(extract_uri)
d.addCallback(self._check_small, SIZE_ZERO)
return d
@ -268,6 +279,7 @@ class GoodServer(unittest.TestCase):
f.write(data)
f.close()
d = upload_filename(self.u, fn)
d.addCallback(extract_uri)
d.addCallback(self._check_small, SIZE_SMALL)
return d
@ -278,6 +290,7 @@ class GoodServer(unittest.TestCase):
f.write(data)
f.close()
d = upload_filename(self.u, fn)
d.addCallback(extract_uri)
d.addCallback(self._check_large, SIZE_LARGE)
return d
@ -333,6 +346,7 @@ class PeerSelection(unittest.TestCase):
data = self.get_data(SIZE_LARGE)
self.set_encoding_parameters(25, 30, 50)
d = upload_data(self.u, data)
d.addCallback(extract_uri)
d.addCallback(self._check_large, SIZE_LARGE)
def _check(res):
for p in self.node.last_peers:
@ -350,6 +364,7 @@ class PeerSelection(unittest.TestCase):
data = self.get_data(SIZE_LARGE)
self.set_encoding_parameters(50, 75, 100)
d = upload_data(self.u, data)
d.addCallback(extract_uri)
d.addCallback(self._check_large, SIZE_LARGE)
def _check(res):
for p in self.node.last_peers:
@ -367,6 +382,7 @@ class PeerSelection(unittest.TestCase):
data = self.get_data(SIZE_LARGE)
self.set_encoding_parameters(24, 41, 51)
d = upload_data(self.u, data)
d.addCallback(extract_uri)
d.addCallback(self._check_large, SIZE_LARGE)
def _check(res):
got_one = []
@ -394,6 +410,7 @@ class PeerSelection(unittest.TestCase):
data = self.get_data(SIZE_LARGE)
self.set_encoding_parameters(100, 150, 200)
d = upload_data(self.u, data)
d.addCallback(extract_uri)
d.addCallback(self._check_large, SIZE_LARGE)
def _check(res):
for p in self.node.last_peers:
@ -411,6 +428,7 @@ class PeerSelection(unittest.TestCase):
data = self.get_data(SIZE_LARGE)
self.set_encoding_parameters(3, 5, 10)
d = upload_data(self.u, data)
d.addCallback(extract_uri)
d.addCallback(self._check_large, SIZE_LARGE)
def _check(res):
counts = {}

View File

@ -5,7 +5,7 @@ from twisted.trial import unittest
from twisted.internet import defer
from twisted.web import client, error, http
from twisted.python import failure, log
from allmydata import interfaces, provisioning, uri, webish
from allmydata import interfaces, provisioning, uri, webish, upload
from allmydata.util import fileutil
from allmydata.test.common import NonGridDirectoryNode, FakeCHKFileNode, FakeMutableFileNode, create_chk_filenode
from allmydata.interfaces import IURI, INewDirectoryURI, IReadonlyNewDirectoryURI, IFileURI, IMutableFileURI, IMutableFileNode
@ -61,7 +61,9 @@ class FakeClient(service.MultiService):
def _got_data(datav):
data = "".join(datav)
n = create_chk_filenode(self, data)
return n.get_uri()
results = upload.UploadResults()
results.uri = n.get_uri()
return results
d.addCallback(_got_data)
return d

View File

@ -15,7 +15,7 @@ from allmydata.util.hashutil import file_renewal_secret_hash, \
from allmydata import encode, storage, hashtree, uri
from allmydata.util import idlib, mathutil
from allmydata.util.assertutil import precondition
from allmydata.interfaces import IUploadable, IUploader, \
from allmydata.interfaces import IUploadable, IUploader, IUploadResults, \
IEncryptedUploadable, RIEncryptedUploadable
from pycryptopp.cipher.aes import AES
@ -36,6 +36,9 @@ class HaveAllPeersError(Exception):
class TooFullError(Exception):
pass
class UploadResults:
implements(IUploadResults)
# our current uri_extension is 846 bytes for small files, a few bytes
# more for larger ones (since the filesize is encoded in decimal in a
# few places). Ask for a little bit more just in case we need it. If
@ -632,7 +635,9 @@ class CHKUploader:
total_shares=total_shares,
size=size,
)
return u.to_string()
results = UploadResults()
results.uri = u.to_string()
return results
def read_this_many_bytes(uploadable, size, prepend_data=[]):
@ -666,8 +671,14 @@ class LiteralUploader:
d.addCallback(lambda size: read_this_many_bytes(uploadable, size))
d.addCallback(lambda data: uri.LiteralFileURI("".join(data)))
d.addCallback(lambda u: u.to_string())
d.addCallback(self._build_results)
return d
def _build_results(self, uri):
results = UploadResults()
results.uri = uri
return results
def close(self):
pass
@ -838,7 +849,9 @@ class AssistedUploader:
total_shares=self._total_shares,
size=self._size,
)
return u.to_string()
results = UploadResults()
results.uri = u.to_string()
return results
class NoParameterPreferencesMixin:
max_segment_size = None

View File

@ -797,7 +797,7 @@ class POSTHandler(rend.Page):
# SDMF: files are small, and we can only upload data.
contents.file.seek(0)
data = contents.file.read()
uploadable = FileHandle(contents.file)
#uploadable = FileHandle(contents.file)
d = self._check_replacement(name)
d.addCallback(lambda res: self._node.has_child(name))
def _checked(present):
@ -1205,6 +1205,7 @@ class URIPUTHandler(rend.Page):
# without the associated set_uri.
uploadable = FileHandle(req.content)
d = IClient(ctx).upload(uploadable)
d.addCallback(lambda results: results.uri)
# that fires with the URI of the new file
return d
@ -1231,6 +1232,7 @@ class URIPOSTHandler(rend.Page):
fileobj = req.fields["file"].file
uploadable = FileHandle(fileobj)
d = IClient(ctx).upload(uploadable)
d.addCallback(lambda results: results.uri)
# that fires with the URI of the new file
return d