summaryrefslogtreecommitdiff
path: root/fsck-larch
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2011-06-06 16:19:21 +0100
committerLars Wirzenius <liw@liw.fi>2011-06-06 16:19:21 +0100
commitfc7a91769b6926e6aefd51d692aa274817c031a6 (patch)
tree94adaa8a186bf6e82d045f4014fba0ac2c093b0b /fsck-larch
parent42e0a0d47e4c922d39c25a54b3782820194ff9d2 (diff)
downloadlarch-fc7a91769b6926e6aefd51d692aa274817c031a6.tar.gz
Move fsck class into library so it can be easily reused.
Diffstat (limited to 'fsck-larch')
-rwxr-xr-xfsck-larch140
1 files changed, 2 insertions, 138 deletions
diff --git a/fsck-larch b/fsck-larch
index fc9d8b9..3faa0f5 100755
--- a/fsck-larch
+++ b/fsck-larch
@@ -20,143 +20,7 @@ import logging
import sys
import ttystatus
-import larch
-
-
-class BtreeFsck(object):
-
- '''Verify that a B-tree is logically correct.'''
-
- def __init__(self, status, forest):
- self.status = status
- self.forest = forest
- self.ns = self.forest.node_store
- self.minkey = '\x00' * self.ns.codec.key_bytes
- self.maxkey = '\xff' * self.ns.codec.key_bytes
-
- def error(self, msg):
- self.status.notify('ERROR: %s' % msg)
-
- def info(self, msg):
- self.status.notify(msg)
-
- def _assert(self, cond, msg1, msg2):
- if not cond:
- if msg1:
- self.error(msg1)
- self.error('not true: %s' % msg2)
-
- def assert_equal(self, a, b, msg=''):
- self._assert(a == b, msg, '%s == %s' % (repr(a), repr(b)))
-
- def assert_greater(self, a, b, msg=''):
- self._assert(a > b, msg, '%s > %s' % (repr(a), repr(b)))
-
- def assert_ge(self, a, b, msg=''):
- self._assert(a >= b, msg, '%s >= %s' % (repr(a), repr(b)))
-
- def assert_in_keyrange(self, a, lo, hi, msg=''):
- '''half-open range: lo <= a < hi'''
- self._assert(lo <= a < hi, msg,
- '%s <= %s < %s' % (repr(lo), repr(a), repr(hi)))
-
- def assert_in(self, value, collection, msg=''):
- self._assert(value in collection, msg,
- '%s in %s' % (repr(value), repr(collection)))
-
- def check_node(self, node, minkey, maxkey):
- keys = node.keys()
- self.assert_greater(self.ns.get_refcount(node.id), 0,
- 'node refcount must be > 0')
- self.assert_greater(len(keys), 0, 'node must have children')
- self.assert_equal(sorted(keys), keys, 'node keys must be sorted')
- self.assert_equal(sorted(set(keys)), keys, 'node keys must be unique')
- self.assert_in_keyrange(keys[0], minkey, maxkey,
- 'node keys must be within range')
- if len(keys) > 1:
- self.assert_in_keyrange(keys[-1], minkey, maxkey,
- 'keys must be within range')
-
- def check_leaf_node(self, node, minkey, maxkey):
- pass
-
- def check_index_node(self, node, minkey, maxkey):
- keys = node.keys()
- child0_id = node[keys[0]]
- try:
- child0 = self.ns.get_node(child0_id)
- except larch.NodeMissing:
- self.error('child missing: %d' % child0_id)
- self.error('index node not checked: %d' % node.id)
- return
- child_type = type(child0)
-
- for key in keys:
- child = self.ns.get_node(node[key])
-
- self.assert_in(type(child), [larch.IndexNode, larch.LeafNode],
- 'type must be index or leaf')
- self.assert_equal(type(child), child_type,
- 'all children must have same type')
-
- def check_root_node(self, root):
- self.assert_equal(self.ns.get_refcount(root.id), 1,
- 'root refcount should be 1')
- self.assert_equal(type(root), larch.IndexNode, 'root must be an index')
-
- def walk(self, node, minkey, maxkey):
- if node.id in self.checked:
- return
- self.checked.add(node.id)
- yield node, minkey, maxkey
- if type(node) is larch.IndexNode:
- keys = node.keys()
- next_keys = keys[1:] + [maxkey]
- for i in range(len(keys)):
- child_id = node[keys[i]]
- try:
- child = self.ns.get_node(child_id)
- except larch.NodeMissing:
- self.error('node missing: %d' % child_id)
- else:
- for t in self.walk(child, keys[i], next_keys[i]):
- yield t
-
- def check_tree(self, root_id):
- try:
- root = self.ns.get_node(root_id)
- except larch.NodeMissing:
- self.error('root node missing: %d' % root_id)
- else:
- self.check_root_node(root)
- for node, min2, max2 in self.walk(root, self.minkey, self.maxkey):
- self.status['node_id'] = str(node.id)
- self.status['nodes_done'] += 1
- self.check_node(node, min2, max2)
- if type(node) is larch.IndexNode:
- self.check_index_node(node, min2, max2)
- else:
- self.check_leaf_node(node, min2, max2)
-
- def forest_root_ids(self):
- string = self.ns.get_metadata('root_ids')
- return [int(x) for x in string.split(',')]
-
- def check_forest(self):
- self.info('larch fsck')
-
- nodes = self.ns.list_nodes()
- self.info('nodes: %d' % len(nodes))
-
- self.status['node_id'] = '---'
- self.status['nodes_done'] = 0
- self.status['nodes_total'] = len(nodes)
-
- self.checked = set()
- for root_id in self.forest_root_ids():
- self.check_tree(root_id)
-
- self.status.finish()
+import larch.fsck
class Fsck(cliapp.Application):
@@ -171,7 +35,7 @@ class Fsck(cliapp.Application):
for dirname in args:
forest = larch.open_forest(dirname=dirname)
- fsck = BtreeFsck(ts, forest)
+ fsck = larch.fsck.Fsck(ts, forest)
fsck.check_forest()