From: Brian Warner <warner@lothar.com> Date: Sun, 8 Jan 2012 02:05:08 +0000 (-0800) Subject: mutable/layout.py: raise BadShareError instead of assert() X-Git-Url: https://git.rkrishnan.org/pf/content/en/seg/pb.xhtml?a=commitdiff_plain;h=c56839478ef395f6b2bcaedee1fe2aeae0d75903;p=tahoe-lafs%2Ftahoe-lafs.git mutable/layout.py: raise BadShareError instead of assert() --- diff --git a/src/allmydata/mutable/common.py b/src/allmydata/mutable/common.py index 4a04339f..9ce11c53 100644 --- a/src/allmydata/mutable/common.py +++ b/src/allmydata/mutable/common.py @@ -10,7 +10,13 @@ MODE_READ = "MODE_READ" 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 @@ -40,7 +46,7 @@ class NotEnoughServersError(Exception): 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 @@ -50,7 +56,7 @@ class CorruptShareError(Exception): 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: diff --git a/src/allmydata/mutable/layout.py b/src/allmydata/mutable/layout.py index 84894014..cb113c39 100644 --- a/src/allmydata/mutable/layout.py +++ b/src/allmydata/mutable/layout.py @@ -1,6 +1,7 @@ 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 @@ -116,7 +117,9 @@ def unpack_share(data): 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] @@ -124,7 +127,9 @@ def unpack_share(data): 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]) @@ -1168,6 +1173,11 @@ class MDMFSlotWriteProxy: 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: """ @@ -1238,11 +1248,13 @@ 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. @@ -1387,7 +1399,8 @@ class MDMFSlotReadProxy: 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 @@ -1395,7 +1408,8 @@ class MDMFSlotReadProxy: 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: @@ -1445,7 +1459,8 @@ class MDMFSlotReadProxy: 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] @@ -1484,7 +1499,8 @@ class MDMFSlotReadProxy: 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)] @@ -1493,6 +1509,7 @@ class MDMFSlotReadProxy: for data in results]) return results d.addCallback(_build_share_hash_chain) + d.addErrback(_handle_bad_struct) return d @@ -1513,7 +1530,8 @@ class MDMFSlotReadProxy: 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) @@ -1537,7 +1555,8 @@ class MDMFSlotReadProxy: 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) @@ -1562,7 +1581,8 @@ class MDMFSlotReadProxy: 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) @@ -1738,7 +1758,7 @@ class MDMFSlotReadProxy: return d -class LayoutInvalid(Exception): +class LayoutInvalid(BadShareError): """ This isn't a valid MDMF mutable file """