class NotWriteableError(Exception):
pass
-class NeedMoreDataError(Exception):
+class BadShareError(Exception):
+ """This represents an error discovered in a particular share, during
+ retrieve, from which we can recover by using some other share. This does
+ *not* include local coding errors.
+ """
+
+class NeedMoreDataError(BadShareError):
def __init__(self, needed_bytes, encprivkey_offset, encprivkey_length):
Exception.__init__(self)
self.needed_bytes = needed_bytes # up through EOF
Exception.__init__(self, why, first_error)
self.first_error = first_error
-class CorruptShareError(Exception):
+class CorruptShareError(BadShareError):
def __init__(self, server, shnum, reason):
self.args = (server, shnum, reason)
self.server = server
return "<CorruptShareError server=%s shnum[%d]: %s" % \
(self.server.get_name(), self.shnum, self.reason)
-class UnknownVersionError(Exception):
+class UnknownVersionError(BadShareError):
"""The share we received was of a version we don't recognize."""
class ResponseCache:
import struct
-from allmydata.mutable.common import NeedMoreDataError, UnknownVersionError
+from allmydata.mutable.common import NeedMoreDataError, UnknownVersionError, \
+ BadShareError
from allmydata.interfaces import HASH_SIZE, SALT_SIZE, SDMF_VERSION, \
MDMF_VERSION, IMutableSlotWriter
from allmydata.util import mathutil
share_hash_chain_s = data[o['share_hash_chain']:o['block_hash_tree']]
share_hash_format = ">H32s"
hsize = struct.calcsize(share_hash_format)
- assert len(share_hash_chain_s) % hsize == 0, len(share_hash_chain_s)
+ if len(share_hash_chain_s) % hsize != 0:
+ raise BadShareError("hash chain is %d bytes, not multiple of %d"
+ % (len(share_hash_chain_s), hsize))
share_hash_chain = []
for i in range(0, len(share_hash_chain_s), hsize):
chunk = share_hash_chain_s[i:i+hsize]
share_hash_chain.append( (hid, h) )
share_hash_chain = dict(share_hash_chain)
block_hash_tree_s = data[o['block_hash_tree']:o['share_data']]
- assert len(block_hash_tree_s) % 32 == 0, len(block_hash_tree_s)
+ if len(block_hash_tree_s) % 32 != 0:
+ raise BadShareError("block_hash_tree is %d bytes, not multiple of %d"
+ % (len(block_hash_tree_s), 32))
block_hash_tree = []
for i in range(0, len(block_hash_tree_s), 32):
block_hash_tree.append(block_hash_tree_s[i:i+32])
d.addCallback(_result)
return d
+def _handle_bad_struct(f):
+ # struct.unpack errors mean the server didn't give us enough data, so
+ # this share is bad
+ f.trap(struct.error)
+ raise BadShareError(f.value.args[0])
class MDMFSlotReadProxy:
"""
d = self._read(readvs, force_remote)
d.addCallback(self._process_encoding_parameters)
d.addCallback(self._process_offsets)
+ d.addErrback(_handle_bad_struct)
return d
def _process_encoding_parameters(self, encoding_parameters):
- assert self.shnum in encoding_parameters
+ if self.shnum not in encoding_parameters:
+ raise BadShareError("no data for shnum %d" % self.shnum)
encoding_parameters = encoding_parameters[self.shnum][0]
# The first byte is the version number. It will tell us what
# to do next.
d.addCallback(_then)
d.addCallback(lambda readvs: self._read(readvs))
def _process_results(results):
- assert self.shnum in results
+ if self.shnum not in results:
+ raise BadShareError("no data for shnum %d" % self.shnum)
if self._version_number == 0:
# We only read the share data, but we know the salt from
# when we fetched the header
if not data:
data = ""
else:
- assert len(data) == 1
+ if len(data) != 1:
+ raise BadShareError("got %d vectors, not 1" % len(data))
data = data[0]
salt = self._salt
else:
d.addCallback(lambda readvs:
self._read(readvs, force_remote=force_remote))
def _build_block_hash_tree(results):
- assert self.shnum in results
+ if self.shnum not in results:
+ raise BadShareError("no data for shnum %d" % self.shnum)
rawhashes = results[self.shnum][0]
results = [rawhashes[i:i+HASH_SIZE]
d.addCallback(lambda readvs:
self._read(readvs, force_remote=force_remote))
def _build_share_hash_chain(results):
- assert self.shnum in results
+ if self.shnum not in results:
+ raise BadShareError("no data for shnum %d" % self.shnum)
sharehashes = results[self.shnum][0]
results = [sharehashes[i:i+(HASH_SIZE + 2)]
for data in results])
return results
d.addCallback(_build_share_hash_chain)
+ d.addErrback(_handle_bad_struct)
return d
d.addCallback(_make_readvs)
d.addCallback(lambda readvs: self._read(readvs))
def _process_results(results):
- assert self.shnum in results
+ if self.shnum not in results:
+ raise BadShareError("no data for shnum %d" % self.shnum)
privkey = results[self.shnum][0]
return privkey
d.addCallback(_process_results)
d.addCallback(_make_readvs)
d.addCallback(lambda readvs: self._read(readvs))
def _process_results(results):
- assert self.shnum in results
+ if self.shnum not in results:
+ raise BadShareError("no data for shnum %d" % self.shnum)
signature = results[self.shnum][0]
return signature
d.addCallback(_process_results)
d.addCallback(_make_readvs)
d.addCallback(lambda readvs: self._read(readvs))
def _process_results(results):
- assert self.shnum in results
+ if self.shnum not in results:
+ raise BadShareError("no data for shnum %d" % self.shnum)
verification_key = results[self.shnum][0]
return verification_key
d.addCallback(_process_results)
return d
-class LayoutInvalid(Exception):
+class LayoutInvalid(BadShareError):
"""
This isn't a valid MDMF mutable file
"""