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
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
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):
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])
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()
+
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
# 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):
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
"""
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
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():
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.
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))
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
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()
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])
--- /dev/null
+
+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
+
+