From 6d7319c5880acf7d439f161630fa5a7ae27be77d Mon Sep 17 00:00:00 2001
From: Brian Warner <warner@lothar.com>
Date: Sun, 8 Mar 2009 19:02:01 -0700
Subject: [PATCH] storage/mutable: raise a specific error upon seeing bad
 magic, instead of using assert

---
 src/allmydata/storage/common.py    |  2 ++
 src/allmydata/storage/mutable.py   |  8 ++++++--
 src/allmydata/test/test_storage.py | 17 ++++++++++++++++-
 3 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/src/allmydata/storage/common.py b/src/allmydata/storage/common.py
index a442dbf4..70f8fed0 100644
--- a/src/allmydata/storage/common.py
+++ b/src/allmydata/storage/common.py
@@ -4,6 +4,8 @@ from allmydata.util import base32
 
 class DataTooLargeError(Exception):
     pass
+class UnknownMutableContainerVersionError(Exception):
+    pass
 
 
 def si_b2a(storageindex):
diff --git a/src/allmydata/storage/mutable.py b/src/allmydata/storage/mutable.py
index 6520acde..c7619530 100644
--- a/src/allmydata/storage/mutable.py
+++ b/src/allmydata/storage/mutable.py
@@ -4,7 +4,8 @@ from allmydata.interfaces import BadWriteEnablerError
 from allmydata.util import idlib, log
 from allmydata.util.assertutil import precondition
 from allmydata.storage.lease import LeaseInfo
-from allmydata.storage.common import DataTooLargeError
+from allmydata.storage.common import UnknownMutableContainerVersionError, \
+     DataTooLargeError
 
 # the MutableShareFile is like the ShareFile, but used for mutable data. It
 # has a different layout. See docs/mutable.txt for more details.
@@ -56,7 +57,10 @@ class MutableShareFile:
              write_enabler_nodeid, write_enabler,
              data_length, extra_least_offset) = \
              struct.unpack(">32s20s32sQQ", data)
-            assert magic == self.MAGIC
+            if magic != self.MAGIC:
+                msg = "sharefile %s had magic '%r' but we wanted '%r'" % \
+                      (filename, magic, self.MAGIC)
+                raise UnknownMutableContainerVersionError(msg)
         self.parent = parent # for logging
 
     def log(self, *args, **kwargs):
diff --git a/src/allmydata/test/test_storage.py b/src/allmydata/test/test_storage.py
index 82dfa609..49734ea3 100644
--- a/src/allmydata/test/test_storage.py
+++ b/src/allmydata/test/test_storage.py
@@ -12,7 +12,8 @@ from allmydata.util import fileutil, hashutil, base32, pollmixin
 from allmydata.storage.server import StorageServer
 from allmydata.storage.mutable import MutableShareFile
 from allmydata.storage.immutable import BucketWriter, BucketReader
-from allmydata.storage.common import DataTooLargeError, storage_index_to_dir
+from allmydata.storage.common import DataTooLargeError, storage_index_to_dir, \
+     UnknownMutableContainerVersionError
 from allmydata.storage.lease import LeaseInfo
 from allmydata.storage.crawler import BucketCountingCrawler
 from allmydata.storage.expirer import LeaseCheckingCrawler
@@ -723,6 +724,20 @@ class MutableServer(unittest.TestCase):
         self.failUnless(isinstance(readv_data, dict))
         self.failUnlessEqual(len(readv_data), 0)
 
+    def test_bad_magic(self):
+        ss = self.create("test_bad_magic")
+        self.allocate(ss, "si1", "we1", self._lease_secret.next(), set([0]), 10)
+        fn = os.path.join(ss.sharedir, storage_index_to_dir("si1"), "0")
+        f = open(fn, "rb+")
+        f.seek(0)
+        f.write("BAD MAGIC")
+        f.close()
+        read = ss.remote_slot_readv
+        e = self.failUnlessRaises(UnknownMutableContainerVersionError,
+                                  read, "si1", [0], [(0,10)])
+        self.failUnless(" had magic " in str(e), e)
+        self.failUnless(" but we wanted " in str(e), e)
+
     def test_container_size(self):
         ss = self.create("test_container_size")
         self.allocate(ss, "si1", "we1", self._lease_secret.next(),
-- 
2.45.2