def test_LogicalFile(tmpdir): prefix = os.path.join(tmpdir, 'log') L = util.LogicalFile(prefix, 2, 6) with pytest.raises(FileNotFoundError): L.open_file(0, create=False) # Check L.open creates a file with L.open_file(8, create=True) as f: pass with util.open_file(prefix + '01') as f: pass L.write(0, b'987') assert L.read(0, -1) == b'987' assert L.read(0, 4) == b'987' assert L.read(1, 1) == b'8' L.write(0, b'01234567890') assert L.read(0, -1) == b'01234567890' assert L.read(5, -1) == b'567890' with util.open_file(prefix + '01') as f: assert f.read(-1) == b'67890' # Test file boundary L.write(0, b'957' * 6) assert L.read(0, -1) == b'957' * 6
def test_open_fns(tmpdir): tmpfile = os.path.join(tmpdir, 'file1') with pytest.raises(FileNotFoundError): util.open_file(tmpfile) with util.open_file(tmpfile, create=True) as f: f.write(b'56') with util.open_file(tmpfile) as f: assert f.read(3) == b'56' # Test open_truncate truncates and creates with util.open_truncate(tmpfile) as f: assert f.read(3) == b'' tmpfile = os.path.join(tmpdir, 'file2') with util.open_truncate(tmpfile) as f: assert f.read(3) == b''
async def _open_dbs(self, for_sync: bool, compacting: bool): assert self.utxo_db is None # First UTXO DB self.utxo_db = self.db_class('utxo', for_sync) if self.utxo_db.is_new: self.logger.info('created new database') self.logger.info('creating metadata directory') os.mkdir('meta') with util.open_file('COIN', create=True) as f: f.write(f'ElectrumX databases and metadata for ' f'{self.coin.NAME} {self.coin.NET}'.encode()) if not self.coin.STATIC_BLOCK_HEADERS: self.headers_offsets_file.write(0, b'\0\0\0\0\0\0\0\0') else: self.logger.info(f'opened UTXO DB (for sync: {for_sync})') self.read_utxo_state() # Then history DB self.utxo_flush_count = self.history.open_db(self.db_class, for_sync, self.utxo_flush_count, compacting) self.clear_excess_undo_info() # Read TX counts (requires meta directory) await self._read_tx_counts()
def open_dbs(self): '''Open the databases. If already open they are closed and re-opened. When syncing we want to reserve a lot of open files for the synchronization. When serving clients we want the open files for serving network connections. ''' def log_reason(message, is_for_sync): reason = 'sync' if is_for_sync else 'serving' self.logger.info('{} for {}'.format(message, reason)) # Assume we're serving until we find out otherwise for for_sync in [False, True]: if self.utxo_db: if self.utxo_db.for_sync == for_sync: return log_reason('closing DB to re-open', for_sync) self.utxo_db.close() self.history.close_db() # Open DB and metadata files. Record some of its state. self.utxo_db = self.db_class('utxo', for_sync) if self.utxo_db.is_new: self.logger.info('created new database') self.logger.info('creating metadata directory') os.mkdir('meta') with util.open_file('COIN', create=True) as f: f.write( 'ElectrumX databases and metadata for {} {}'.format( self.coin.NAME, self.coin.NET).encode()) else: log_reason('opened DB', self.utxo_db.for_sync) self.read_utxo_state() if self.first_sync == self.utxo_db.for_sync: break # Open history DB, clear excess history self.utxo_flush_count = self.history.open_db(self.db_class, for_sync, self.utxo_flush_count) self.clear_excess_undo_info() self.logger.info('DB version: {:d}'.format(self.db_version)) self.logger.info('coin: {}'.format(self.coin.NAME)) self.logger.info('network: {}'.format(self.coin.NET)) self.logger.info('height: {:,d}'.format(self.db_height)) self.logger.info('tip: {}'.format(hash_to_str(self.db_tip))) self.logger.info('tx count: {:,d}'.format(self.db_tx_count)) if self.first_sync: self.logger.info('sync time so far: {}'.format( util.formatted_time(self.wall_time)))
def read_raw_block(self, height): '''Returns a raw block read from disk. Raises FileNotFoundError if the block isn't on-disk.''' with util.open_file(self.raw_block_path(height)) as f: return f.read(-1)
def __enter__(self): self.block_file = open_file(self.filename(self.hex_hash, self.height)) self.header = self._read(80) return self