chainsyncer/chainsyncer/store/fs.py

125 lines
4.3 KiB
Python
Raw Normal View History

2022-03-17 15:54:34 +01:00
# standard imports
import uuid
import os
import logging
# external imports
from shep.store.file import SimpleFileStoreFactory
from shep.persist import PersistedState
2022-03-17 20:36:27 +01:00
# local imports
from chainsyncer.state import SyncState
2022-04-20 13:59:12 +02:00
from chainsyncer.store import (
SyncItem,
SyncStore,
2022-03-17 23:07:19 +01:00
)
2022-03-17 15:54:34 +01:00
2022-04-20 13:59:12 +02:00
logg = logging.getLogger(__name__)
2022-03-17 15:54:34 +01:00
2022-04-20 13:59:12 +02:00
class SyncFsStore(SyncStore):
2022-03-17 15:54:34 +01:00
def __init__(self, base_path, session_id=None, state_event_callback=None, filter_state_event_callback=None):
2022-04-20 13:59:12 +02:00
super(SyncFsStore, self).__init__(session_id=session_id)
2022-03-17 15:54:34 +01:00
default_path = os.path.join(base_path, 'default')
if session_id == None:
self.session_path = os.path.realpath(default_path)
self.is_default = True
else:
if session_id == 'default':
self.is_default = True
given_path = os.path.join(base_path, session_id)
self.session_path = os.path.realpath(given_path)
create_path = False
try:
os.stat(self.session_path)
except FileNotFoundError:
create_path = True
if create_path:
self.__create_path(base_path, default_path, session_id=session_id)
2022-03-19 01:52:47 +01:00
self.session_id = os.path.basename(self.session_path)
2022-03-17 15:54:34 +01:00
logg.info('session id {} resolved {} path {}'.format(session_id, self.session_id, self.session_path))
factory = SimpleFileStoreFactory(self.session_path, binary=True)
self.state = PersistedState(factory.add, 2, event_callback=state_event_callback)
2022-03-17 15:54:34 +01:00
self.state.add('SYNC')
self.state.add('DONE')
2022-03-17 20:36:27 +01:00
base_filter_path = os.path.join(self.session_path, 'filter')
factory = SimpleFileStoreFactory(base_filter_path, binary=True)
filter_state_backend = PersistedState(factory.add, 0, check_alias=False, event_callback=filter_state_event_callback)
self.filter_state = SyncState(filter_state_backend, scan_path=base_filter_path)
2022-03-19 02:24:08 +01:00
self.filters = [] # used by SyncSession
2022-03-17 23:07:19 +01:00
2022-03-17 15:54:34 +01:00
def __create_path(self, base_path, default_path, session_id=None):
logg.debug('fs store path {} does not exist, creating'.format(self.session_path))
if session_id == None:
session_id = str(uuid.uuid4())
self.session_path = os.path.join(base_path, session_id)
os.makedirs(self.session_path)
if self.is_default:
try:
os.symlink(self.session_path, default_path)
except FileExistsError:
pass
2022-04-20 13:59:12 +02:00
def load(self, target):
2022-03-17 15:54:34 +01:00
self.state.sync(self.state.NEW)
self.state.sync(self.state.SYNC)
2022-03-17 20:36:27 +01:00
thresholds_sync = []
2022-03-17 15:54:34 +01:00
for v in self.state.list(self.state.SYNC):
block_number = int(v)
2022-03-17 20:36:27 +01:00
thresholds_sync.append(block_number)
2022-03-17 15:54:34 +01:00
logg.debug('queue resume {}'.format(block_number))
2022-03-17 20:36:27 +01:00
thresholds_new = []
2022-03-17 15:54:34 +01:00
for v in self.state.list(self.state.NEW):
block_number = int(v)
2022-03-17 20:36:27 +01:00
thresholds_new.append(block_number)
2022-03-17 15:54:34 +01:00
logg.debug('queue new range {}'.format(block_number))
2022-03-17 20:36:27 +01:00
thresholds_sync.sort()
thresholds_new.sort()
thresholds = thresholds_sync + thresholds_new
2022-03-17 15:54:34 +01:00
lim = len(thresholds) - 1
2022-04-20 13:59:12 +02:00
logg.debug('thresholds {}'.format(thresholds))
2022-03-17 15:54:34 +01:00
for i in range(len(thresholds)):
item_target = target
if i < lim:
item_target = thresholds[i+1]
2022-04-20 13:59:12 +02:00
o = SyncItem(block_number, item_target, self.state, self.filter_state, started=True)
2022-03-17 15:54:34 +01:00
self.items[block_number] = o
2022-03-18 00:48:23 +01:00
self.item_keys.append(block_number)
2022-03-19 01:52:47 +01:00
logg.info('added existing {}'.format(o))
2022-03-17 15:54:34 +01:00
2022-03-19 02:13:37 +01:00
fp = os.path.join(self.session_path, 'target')
have_target = False
try:
f = open(fp, 'r')
v = f.read()
2022-03-17 15:54:34 +01:00
f.close()
self.target = int(v)
have_target = True
except FileNotFoundError as e:
pass
2022-03-17 15:54:34 +01:00
if len(thresholds) == 0:
if have_target:
logg.warning('sync "{}" is already done, nothing to do'.format(self.session_id))
else:
logg.info('syncer first run target {}'.format(target))
self.first = True
f = open(fp, 'w')
f.write(str(target))
f.close()
self.target = target