Browse Source

make blockchain.size() threadsafe

2.9.x
ThomasV 8 years ago
parent
commit
d71c9d5be3
  1. 56
      lib/blockchain.py
  2. 3
      lib/network.py

56
lib/blockchain.py

@ -27,6 +27,8 @@
import os
import util
import threading
import bitcoin
from bitcoin import *
@ -101,6 +103,9 @@ class Blockchain(util.PrintError):
self.catch_up = None # interface catching up
self.checkpoint = checkpoint
self.parent_id = parent_id
self.lock = threading.Lock()
with self.lock:
self.update_size()
def parent(self):
return blockchains[self.parent_id]
@ -124,18 +129,23 @@ class Blockchain(util.PrintError):
height = header.get('block_height')
return header_hash == self.get_hash(height)
def fork(parent, checkpoint):
def fork(parent, header):
checkpoint = header.get('block_height')
self = Blockchain(parent.config, checkpoint, parent.checkpoint)
# create file
open(self.path(), 'w+').close()
self.save_header(header)
return self
def height(self):
return self.checkpoint + self.size() - 1
def size(self):
with self.lock:
return self._size
def update_size(self):
p = self.path()
return os.path.getsize(p)/80 if os.path.exists(p) else 0
self._size = os.path.getsize(p)/80 if os.path.exists(p) else 0
def verify_header(self, header, prev_header, bits, target):
prev_hash = hash_header(prev_header)
@ -181,9 +191,11 @@ class Blockchain(util.PrintError):
if d < 0:
chunk = chunk[-d:]
d = 0
with open(filename, 'rb+') as f:
f.seek(d)
f.write(chunk)
with self.lock:
with open(filename, 'rb+') as f:
f.seek(d)
f.write(chunk)
self.update_size()
self.swap_with_parent()
def swap_with_parent(self):
@ -199,16 +211,20 @@ class Blockchain(util.PrintError):
with open(parent.path(), 'rb+') as f:
f.seek((checkpoint - parent.checkpoint)*80)
parent_data = f.read(parent_branch_size*80)
f.seek((checkpoint - parent.checkpoint)*80)
f.truncate()
with open(self.path(), 'rb+') as f:
my_data = f.read()
f.seek(0)
f.truncate()
f.write(parent_data)
with open(parent.path(), 'rb+') as f:
f.seek((checkpoint - parent.checkpoint)*80)
f.write(my_data)
with self.lock:
with open(self.path(), 'rb+') as f:
my_data = f.read()
f.seek(0)
f.truncate()
f.write(parent_data)
self.update_size()
with parent.lock:
with open(parent.path(), 'rb+') as f:
f.seek((checkpoint - parent.checkpoint)*80)
f.truncate()
f.seek((checkpoint - parent.checkpoint)*80)
f.write(my_data)
parent.update_size()
# store file path
for b in blockchains.values():
b.old_path = b.path()
@ -231,9 +247,11 @@ class Blockchain(util.PrintError):
data = serialize_header(header).decode('hex')
assert delta == self.size()
assert len(data) == 80
with open(filename, 'rb+') as f:
f.seek(delta * 80)
f.write(data)
with self.lock:
with open(filename, 'rb+') as f:
f.seek(delta * 80)
f.write(data)
self.update_size()
# order files
self.swap_with_parent()

3
lib/network.py

@ -854,8 +854,7 @@ class Network(util.DaemonThread):
if bh > interface.good:
if not interface.blockchain.check_header(interface.bad_header):
if interface.blockchain.can_connect(interface.bad_header, check_height=False):
b = interface.blockchain.fork(interface.bad)
b.save_header(interface.bad_header)
b = interface.blockchain.fork(interface.bad_header)
self.blockchains[interface.bad] = b
interface.blockchain = b
interface.print_error("new chain", b.checkpoint)

Loading…
Cancel
Save