[Checkins] SVN: gocept.zeoraid/trunk/ - Fix another recovery issue by using the correct previous Tid of a data
Christian Theune
ct at gocept.com
Thu Jul 2 13:08:31 EDT 2009
Log message for revision 101400:
- Fix another recovery issue by using the correct previous Tid of a data
record.
Improve logging during recovery.
- Show current recovery process in the management `details` command.
- Fix recipe test to not mention the removed ZODB external anymore.
- Don't require the ZEO configuration file to be named again, determine
automatically.
Changed:
U gocept.zeoraid/trunk/CHANGES.txt
U gocept.zeoraid/trunk/setup.py
U gocept.zeoraid/trunk/src/gocept/zeoraid/recovery.py
U gocept.zeoraid/trunk/src/gocept/zeoraid/scripts/controller.py
U gocept.zeoraid/trunk/src/gocept/zeoraid/scripts/recipe.txt
U gocept.zeoraid/trunk/src/gocept/zeoraid/scripts/stresstest.py
U gocept.zeoraid/trunk/src/gocept/zeoraid/storage.py
U gocept.zeoraid/trunk/src/gocept/zeoraid/tests/test_recovery.py
-=-
Modified: gocept.zeoraid/trunk/CHANGES.txt
===================================================================
--- gocept.zeoraid/trunk/CHANGES.txt 2009-07-02 15:59:34 UTC (rev 101399)
+++ gocept.zeoraid/trunk/CHANGES.txt 2009-07-02 17:08:31 UTC (rev 101400)
@@ -2,6 +2,21 @@
Change History
==============
+1.0b3 (unreleased)
+------------------
+
+- Fix another recovery issue by using the correct previous Tid of a data
+ record.
+
+ Improve logging during recovery.
+
+- Show current recovery process in the management `details` command.
+
+- Fix recipe test to not mention the removed ZODB external anymore.
+
+- Don't require the ZEO configuration file to be named again, determine
+ automatically.
+
1.0b2 (2009-07-02)
------------------
Modified: gocept.zeoraid/trunk/setup.py
===================================================================
--- gocept.zeoraid/trunk/setup.py 2009-07-02 15:59:34 UTC (rev 101399)
+++ gocept.zeoraid/trunk/setup.py 2009-07-02 17:08:31 UTC (rev 101400)
@@ -19,7 +19,7 @@
name = "gocept.zeoraid"
setup(
name = name,
- version = "1.0b2dev",
+ version = "1.0b3dev",
author = "Christian Theune",
author_email = "ct at gocept.com",
description = "A ZODB storage for replication using RAID techniques.",
Modified: gocept.zeoraid/trunk/src/gocept/zeoraid/recovery.py
===================================================================
--- gocept.zeoraid/trunk/src/gocept/zeoraid/recovery.py 2009-07-02 15:59:34 UTC (rev 101399)
+++ gocept.zeoraid/trunk/src/gocept/zeoraid/recovery.py 2009-07-02 17:08:31 UTC (rev 101400)
@@ -13,6 +13,7 @@
##############################################################################
"""Online storage recovery."""
+import logging
import tempfile
import transaction
@@ -21,7 +22,9 @@
import gocept.zeoraid.storage
+logger = logging.getLogger('gocept.zeoraid.recovery')
+
def continuous_storage_iterator(storage):
seen = ZODB.utils.z64
while seen < storage.lastTransaction():
@@ -94,7 +97,7 @@
'in source transaction %r.' % (
name, source_value, target_value, source_txn.tid))
- yield ('verify', source_txn.tid)
+ yield ('verify', ZODB.utils.tid_repr(source_txn.tid))
yield ('verified',)
@@ -115,9 +118,17 @@
finally:
self.source.tpc_abort(t)
+ logger.debug('Recovering transaction %s' %
+ ZODB.utils.tid_repr(txn_info.tid))
self.target.tpc_begin(txn_info, txn_info.tid, txn_info.status)
for r in txn_info:
+ before = self.source.loadBefore(r.oid, txn_info.tid)
+ if before is not None:
+ _, prev_tid, _ = before
+ else:
+ prev_tid = None
+
if self.recover_blobs:
try:
blob_file_name = self.source.loadBlob(
@@ -130,11 +141,14 @@
gocept.zeoraid.storage.optimistic_copy(blob_file_name,
temp_file_name)
self.target.storeBlob(
- r.oid, r.tid, r.data, temp_file_name, r.version,
+ r.oid, prev_tid, r.data, temp_file_name, r.version,
txn_info)
continue
- self.target.store(r.oid, r.tid, r.data, r.version, txn_info)
+ # XXX Charlie Clark has a database that conflicts so we need
+ # to reconsider using store here.
+ self.target.store(r.oid, prev_tid, r.data, r.version, txn_info)
+
self.target.tpc_vote(txn_info)
self.target.tpc_finish(txn_info)
Modified: gocept.zeoraid/trunk/src/gocept/zeoraid/scripts/controller.py
===================================================================
--- gocept.zeoraid/trunk/src/gocept/zeoraid/scripts/controller.py 2009-07-02 15:59:34 UTC (rev 101399)
+++ gocept.zeoraid/trunk/src/gocept/zeoraid/scripts/controller.py 2009-07-02 17:08:31 UTC (rev 101400)
@@ -33,7 +33,7 @@
disable <storage> -- Disable a storage
- reload </path/to/zeo.conf> -- Reload a specified zeo.conf file
+ reload -- Reload this raid storage's configuration from the zeo.conf
"""
@@ -59,12 +59,12 @@
print self.raid.raid_status()
def cmd_details(self):
- ok, recovering, failed = self.raid.raid_details()
+ ok, recovering, failed, recovery_status = self.raid.raid_details()
print "RAID status:"
print "\t", self.raid.raid_status()
print "Storage status:"
print "\toptimal\t\t", ok
- print "\trecovering\t", recovering
+ print "\trecovering\t", recovering, recovery_status
print "\tfailed\t\t", failed
def cmd_recover(self, storage):
@@ -73,8 +73,8 @@
def cmd_disable(self, storage):
print self.raid.raid_disable(storage)
- def cmd_reload(self, path):
- print self.raid.raid_reload(path)
+ def cmd_reload(self):
+ self.raid.raid_reload()
def main(host="127.0.0.1", port=8100, storage="1"):
usage = "usage: %prog [options] command [command-options]"
Modified: gocept.zeoraid/trunk/src/gocept/zeoraid/scripts/recipe.txt
===================================================================
--- gocept.zeoraid/trunk/src/gocept/zeoraid/scripts/recipe.txt 2009-07-02 15:59:34 UTC (rev 101399)
+++ gocept.zeoraid/trunk/src/gocept/zeoraid/scripts/recipe.txt 2009-07-02 17:08:31 UTC (rev 101400)
@@ -112,7 +112,6 @@
import sys
sys.path[0:0] = [
'.../src',
- '.../externals/ZODB/src',
'/sample-pyN.N.egg',
'/sample-pyN.N.egg',
'/sample-pyN.N.egg',
@@ -125,6 +124,7 @@
'/sample-pyN.N.egg',
'/sample-pyN.N.egg',
'/sample-pyN.N.egg',
+ '/sample-pyN.N.egg',
]
<BLANKLINE>
import gocept.zeoraid.scripts.controller
@@ -210,7 +210,6 @@
import sys
sys.path[0:0] = [
'.../src',
- '.../externals/ZODB/src',
'/sample-pyN.N.egg',
'/sample-pyN.N.egg',
'/sample-pyN.N.egg',
@@ -223,6 +222,7 @@
'/sample-pyN.N.egg',
'/sample-pyN.N.egg',
'/sample-pyN.N.egg',
+ '/sample-pyN.N.egg',
]
<BLANKLINE>
import gocept.zeoraid.scripts.controller
Modified: gocept.zeoraid/trunk/src/gocept/zeoraid/scripts/stresstest.py
===================================================================
--- gocept.zeoraid/trunk/src/gocept/zeoraid/scripts/stresstest.py 2009-07-02 15:59:34 UTC (rev 101399)
+++ gocept.zeoraid/trunk/src/gocept/zeoraid/scripts/stresstest.py 2009-07-02 17:08:31 UTC (rev 101400)
@@ -6,10 +6,13 @@
import ZEO.zrpc.error
import ZEO.Exceptions
import ZODB.utils
+import logging
+logging.getLogger().addHandler(logging.StreamHandler())
+logging.getLogger().setLevel(0)
-storage = ClientStorage([('127.0.0.1', 8100)],#, ('127.0.0.1', 8201)],
- storage='1')
+storage = ClientStorage([('127.0.0.1', 8200), ('127.0.0.1', 8201)],
+ storage='main')
db = DB(storage)
conn = db.open()
root = conn.root()
@@ -26,5 +29,4 @@
transaction.abort()
continue
print root['x']
- print ZODB.utils.oid_repr(storage.lastTransaction())
time.sleep(1)
Modified: gocept.zeoraid/trunk/src/gocept/zeoraid/storage.py
===================================================================
--- gocept.zeoraid/trunk/src/gocept/zeoraid/storage.py 2009-07-02 15:59:34 UTC (rev 101399)
+++ gocept.zeoraid/trunk/src/gocept/zeoraid/storage.py 2009-07-02 17:08:31 UTC (rev 101400)
@@ -173,6 +173,7 @@
# No storage is recovering initially
self.storage_recovering = None
+ self.recovery_status = ''
# IStorage
@@ -570,7 +571,8 @@
@ensure_open_storage
def raid_details(self):
- return [self.storages_optimal, self.storage_recovering, self.storages_degraded]
+ return [self.storages_optimal, self.storage_recovering,
+ self.storages_degraded, self.recovery_status]
@ensure_open_storage
def raid_disable(self, name):
@@ -788,6 +790,7 @@
self, storage, self._finalize_recovery,
recover_blobs=(self.blob_fshelper and not self.shared_blob_dir))
for msg in recovery():
+ self.recovery_status = msg
logger.debug(str(msg))
def _finalize_recovery(self, storage):
Modified: gocept.zeoraid/trunk/src/gocept/zeoraid/tests/test_recovery.py
===================================================================
--- gocept.zeoraid/trunk/src/gocept/zeoraid/tests/test_recovery.py 2009-07-02 15:59:34 UTC (rev 101399)
+++ gocept.zeoraid/trunk/src/gocept/zeoraid/tests/test_recovery.py 2009-07-02 17:08:31 UTC (rev 101400)
@@ -50,6 +50,11 @@
test.assertEquals(getattr(source_record, name),
getattr(target_record, name))
+ # Check that the loadBefores return the same information
+ test.assertEquals(
+ source.loadBefore(source_record.oid, source_record.tid),
+ target.loadBefore(target_record.oid, target_record.tid))
+
if not hasattr(source, 'loadBlob'):
continue
try:
@@ -117,8 +122,15 @@
shared = False
def store(self, storages, tid=None, status=' ', user=None,
- description=None, extension={}):
- oid = storages[0].new_oid()
+ description=None, extension={}, oid=None):
+ if oid is None:
+ oid = storages[0].new_oid()
+
+ try:
+ data, base_tid = storages[0].load(oid, '')
+ except ZODB.POSException.POSKeyError:
+ base_tid = ZODB.utils.z64
+
data = ZODB.tests.MinPO.MinPO(7)
data = ZODB.tests.StorageTestBase.zodb_pickle(data)
# Begin the transaction
@@ -139,9 +151,9 @@
blob_file.write('I am a happy blob.')
blob_file.close()
r1 = storage.storeBlob(
- oid, ZODB.utils.z64, data, blob_file_name, '', t)
+ oid, base_tid, data, blob_file_name, '', t)
else:
- r1 = storage.store(oid, ZODB.utils.z64, data, '', t)
+ r1 = storage.store(oid, base_tid, data, '', t)
# Finish the transaction
r2 = storage.tpc_vote(t)
tid = ZODB.tests.StorageTestBase.handle_serials(oid, r1, r2)
@@ -151,7 +163,7 @@
for storage in storages:
storage.tpc_abort(t)
raise
- return tid
+ return tid, oid
def compare(self, source, target):
compare(self, source, target)
@@ -172,7 +184,6 @@
shutil.rmtree(path)
def setup_raid(self):
-
if self.use_blobs:
blob_dir = tempfile.mkdtemp()
self.temp_paths.append(blob_dir)
@@ -228,25 +239,25 @@
self.assertRaises(ValueError, recovery.next)
def test_verify_status_mismatch(self):
- tid = self.store([self.source])
+ tid, _ = self.store([self.source])
self.store([self.target], tid=tid, status='p')
recovery = self.recovery()
self.assertRaises(ValueError, recovery.next)
def test_verify_user_mismatch(self):
- tid = self.store([self.source])
+ tid, _ = self.store([self.source])
self.store([self.target], tid=tid, user='Hans')
recovery = self.recovery()
self.assertRaises(ValueError, recovery.next)
def test_verify_description_mismatch(self):
- tid = self.store([self.source])
+ tid, _ = self.store([self.source])
self.store([self.target], tid=tid, description='foo bar')
recovery = self.recovery()
self.assertRaises(ValueError, recovery.next)
def test_verify_extension_mismatch(self):
- tid = self.store([self.source])
+ tid, _ = self.store([self.source])
self.store([self.target], tid=tid, extension=dict(foo=3))
recovery = self.recovery()
self.assertRaises(ValueError, recovery.next)
@@ -260,11 +271,13 @@
def test_recover_simple(self):
self.store([self.source, self.target])
- self.store([self.source])
+ _, oid = self.store([self.source])
+ self.store([self.source], oid=oid)
recovery = self.recovery()
self.assertEquals('verify', recovery.next()[0])
self.assertEquals('verified', recovery.next()[0])
self.assertEquals('recover', recovery.next()[0])
+ self.assertEquals('recover', recovery.next()[0])
self.assertEquals('recovered', recovery.next()[0])
self.compare(self.source, self.target)
More information about the Checkins
mailing list