blockchain: swap a chain with its parent, if the parent branch is too short to be saved on disk

This commit is contained in:
ThomasV 2017-07-18 18:10:22 +02:00
parent 1316e4f70d
commit 50ad656c87
2 changed files with 38 additions and 5 deletions

View File

@ -65,8 +65,8 @@ blockchains = {}
def read_blockchains(config):
blockchains[0] = Blockchain(config, 'blockchain_headers')
# fixme: sort
l = sorted(filter(lambda x: x.startswith('fork_'), os.listdir(config.path)))
l = filter(lambda x: x.startswith('fork_'), os.listdir(config.path))
l = sorted(l, key = lambda x: int(x.split('_')[1]))
for x in l:
b = Blockchain(config, x)
blockchains[b.checkpoint] = b
@ -106,6 +106,15 @@ class Blockchain(util.PrintError):
else:
raise BaseException('')
def get_max_child(self):
children = filter(lambda y: y.parent==self, blockchains.values())
return max([x.checkpoint for x in children]) if children else None
def get_branch_size(self):
mc = self.get_max_child()
checkpoint = mc if mc is not None else self.checkpoint
return self.height() - checkpoint
def check_header(self, header):
header_hash = hash_header(header)
height = header.get('block_height')
@ -187,13 +196,38 @@ class Blockchain(util.PrintError):
self.is_saved = True
self.print_error("saved", self.filename)
def swap_with_parent(self):
self.print_error("swap")
parent = self.parent
checkpoint = self.checkpoint
# copy headers
parent.headers = [parent.read_header(h) for h in range(checkpoint, checkpoint + parent.get_branch_size())]
# truncate parent file
with open(parent.path(), 'rb+') as f:
f.seek(checkpoint*80)
f.truncate()
parent.is_saved = False
# swap chains
fn = self.filename; self.filename = parent.filename; parent.filename = fn
self.parent = parent.parent; parent.parent = parent
self.checkpoint = parent.checkpoint; parent.checkpoint = checkpoint
# write my headers
for h in self.headers:
self.write_header(h)
self.headers = []
self.is_saved = True
def save_header(self, header):
N = 10
height = header.get('block_height')
if not self.is_saved:
assert height == self.checkpoint + len(self.headers)
self.headers.append(header)
if len(self.headers) > 10 and self.parent.size() > 10:
self.save()
if len(self.headers) > N:
if self.parent.get_branch_size() <= N:
self.swap_with_parent()
else:
self.save()
return
self.write_header(header)

View File

@ -862,7 +862,6 @@ class Network(util.DaemonThread):
else:
interface.print_error('already catching up')
next_height = None
# todo: garbage collect blockchain objects
self.notify('updated')
elif interface.mode == 'catch_up':