update URI format, include codec name

This commit is contained in:
Brian Warner 2007-01-16 21:29:59 -07:00
parent 9c6d190190
commit 4101bcf218
6 changed files with 52 additions and 22 deletions

View File

@ -12,7 +12,7 @@ def netstring(s):
class ReplicatingEncoder(object):
implements(ICodecEncoder)
ENCODER_TYPE = 0
ENCODER_TYPE = "rep"
def set_params(self, data_size, required_shares, max_shares):
self.data_size = data_size
@ -96,7 +96,7 @@ class Decoder(object):
class PyRSEncoder(object):
implements(ICodecEncoder)
ENCODER_TYPE = 1
ENCODER_TYPE = "pyrs"
# we will break the data into vectors in which each element is a single
# byte (i.e. a single number from 0 to 255), and the length of the vector
@ -138,7 +138,7 @@ class PyRSEncoder(object):
return self.ENCODER_TYPE
def get_serialized_params(self):
return "%d:%d:%d" % (self.data_size, self.required_shares,
return "%d-%d-%d" % (self.data_size, self.required_shares,
self.max_shares)
def get_share_size(self):
@ -179,7 +179,7 @@ class PyRSDecoder(object):
implements(ICodecDecoder)
def set_serialized_params(self, params):
pieces = params.split(":")
pieces = params.split("-")
self.data_size = int(pieces[0])
self.required_shares = int(pieces[1])
self.max_shares = int(pieces[2])
@ -234,3 +234,8 @@ all_encoders = {
ReplicatingEncoder.ENCODER_TYPE: (ReplicatingEncoder, ReplicatingDecoder),
PyRSEncoder.ENCODER_TYPE: (PyRSEncoder, PyRSDecoder),
}
def get_decoder_by_name(name):
decoder_class = all_encoders[name][1]
return decoder_class()

View File

@ -8,6 +8,7 @@ from twisted.application import service
from allmydata.util import idlib, bencode
from allmydata.util.deferredutil import DeferredListShouldSucceed
from allmydata import codec
from allmydata.uri import unpack_uri
class NotEnoughPeersError(Exception):
pass
@ -16,20 +17,17 @@ class HaveAllPeersError(Exception):
# we use this to jump out of the loop
pass
def unpack_uri(uri):
assert uri.startswith("URI:")
return bencode.bdecode(uri[4:])
class FileDownloader:
debug = False
def __init__(self, peer, verifierid, encoding_params):
def __init__(self, peer, uri):
self._peer = peer
(codec_name, codec_params, verifierid) = unpack_uri(uri)
assert isinstance(verifierid, str)
assert len(verifierid) == 20
self._verifierid = verifierid
self._decoder = codec.ReplicatingDecoder()
self._decoder.set_serialized_params(encoding_params)
self._decoder = codec.get_decoder_by_name(codec_name)
self._decoder.set_serialized_params(codec_params)
self.needed_shares = self._decoder.get_required_shares()
def set_download_target(self, target):
@ -236,14 +234,12 @@ class Downloader(service.MultiService):
debug = False
def download(self, uri, t):
(verifierid, params) = unpack_uri(uri)
assert self.parent
assert self.running
assert isinstance(verifierid, str)
t = IDownloadTarget(t)
assert t.write
assert t.close
dl = FileDownloader(self.parent, verifierid, params)
dl = FileDownloader(self.parent, uri)
dl.set_download_target(t)
if self.debug:
dl.debug = True

View File

@ -83,7 +83,7 @@ class ICodecEncoder(Interface):
"""
def get_encoder_type():
"""Return an integer that describes the type of this encoder.
"""Return a short string that describes the type of this encoder.
There must be a global table of encoder classes. This method returns
an index into this table; the value at this index is an encoder
@ -100,10 +100,11 @@ class ICodecEncoder(Interface):
This string is intended to be embedded in the URI, so there are
several restrictions on its contents. At the moment I'm thinking that
this means it may contain hex digits and colons, and nothing else.
The idea is that the URI contains '%d:%s.' %
(encoder.get_encoder_type(), encoder.get_serialized_params()), and
this is enough information to construct a compatible decoder.
this means it may contain hex digits and hyphens, and nothing else.
The idea is that the URI contains something like '%s:%s:%s' %
(encoder.get_encoder_name(), encoder.get_serialized_params(),
b2a(verifierid)), and this is enough information to construct a
compatible decoder.
"""
def get_share_size():

View File

@ -4,6 +4,7 @@ from twisted.internet import defer
from cStringIO import StringIO
from allmydata import upload, download
from allmydata.uri import unpack_uri
class StringBucketProxy:
# This is for unit tests: make a StringIO look like a RIBucketWriter.
@ -226,10 +227,10 @@ class Uploader(unittest.TestCase):
def _check(self, uri):
self.failUnless(isinstance(uri, str))
self.failUnless(uri.startswith("URI:"))
verifierid, params = download.unpack_uri(uri)
codec_name, codec_params, verifierid = unpack_uri(uri)
self.failUnless(isinstance(verifierid, str))
self.failUnlessEqual(len(verifierid), 20)
self.failUnless(isinstance(params, str))
self.failUnless(isinstance(codec_params, str))
peers = self.node.peers
self.failUnlessEqual(peers[0].allocated_size,
len(peers[0].data))

View File

@ -9,6 +9,7 @@ from allmydata.util import idlib, bencode
from allmydata.util.idlib import peerid_to_short_string as shortid
from allmydata.util.deferredutil import DeferredListShouldSucceed
from allmydata import codec
from allmydata.uri import pack_uri
from cStringIO import StringIO
import sha
@ -67,6 +68,7 @@ class FileUploader:
total_shares = self.max_shares
needed_shares = self.min_shares
self._encoder = codec.ReplicatingEncoder()
self._codec_name = self._encoder.get_encoder_type()
self._encoder.set_params(self._size, needed_shares, total_shares)
self._share_size = self._encoder.get_share_size()
@ -93,7 +95,7 @@ class FileUploader:
return d
def _compute_uri(self, params):
return "URI:%s" % bencode.bencode((self._verifierid, params))
return pack_uri(self._codec_name, params, self._verifierid)
def _build_not_enough_peers_error(self):
yes = ",".join([shortid(p) for p in self.peers_who_said_yes])

25
src/allmydata/uri.py Normal file
View File

@ -0,0 +1,25 @@
from allmydata.util import bencode, idlib
# the URI shall be an ascii representation of the file. It shall contain
# enough information to retrieve and validate the contents. It shall be
# expressed in a limited character set (namely [TODO]).
def pack_uri(codec_name, codec_params, verifierid):
assert isinstance(codec_name, str)
assert len(codec_name) < 10
assert ":" not in codec_name
assert isinstance(codec_params, str)
assert ":" not in codec_params
assert isinstance(verifierid, str)
assert len(verifierid) == 20 # sha1 hash
return "URI:%s:%s:%s" % (codec_name, codec_params, idlib.b2a(verifierid))
def unpack_uri(uri):
assert uri.startswith("URI:")
header, codec_name, codec_params, verifierid_s = uri.split(":")
verifierid = idlib.a2b(verifierid_s)
return codec_name, codec_params, verifierid