def start_workpool( self, bitcoind_opts ): """ Make a work pool for ourselves. Raise an exception if one already exists. NOT THREAD SAFE """ if self.pool is not None: raise Exception("Already indexing") self.pool = workpool.multiprocess_pool( bitcoind_opts, os.path.abspath( __file__ ) ) return True
def start_workpool(self, bitcoind_opts): """ Make a work pool for ourselves. Raise an exception if one already exists. NOT THREAD SAFE """ if self.pool is not None: raise Exception("Already indexing") self.pool = workpool.multiprocess_pool(bitcoind_opts, os.path.abspath(__file__)) return True
def build(self, bitcoind_opts, end_block_id): """ Top-level call to process all blocks in the blockchain. Goes and fetches all OP_RETURN nulldata in order, and feeds them into the state engine implementation using its 'db_parse', 'db_check', 'db_commit', and 'db_save' methods. Note that this method can take some time (hours, days) to complete when called from the first block. This method is *NOT* thread-safe. However, it can be interrupted with the "stop_build" method. Return True on success Return False on error Raise an exception on irrecoverable error--the caller should simply try again. """ first_block_id = self.lastblock + 1 num_workers, worker_batch_size = config.configure_multiprocessing( bitcoind_opts) rc = True # the state can be big. don't pass it to the slave processes free_memory = self.__delete_me self.pool = workpool.multiprocess_pool(bitcoind_opts, initializer=free_memory, initargs=[self.state]) try: log.debug("Process blocks %s to %s" % (first_block_id, end_block_id)) for block_id in xrange(first_block_id, end_block_id, worker_batch_size * num_workers): if not rc: break if self.pool is None: # interrupted log.debug("Build interrupted") rc = False break block_ids = range( block_id, min(block_id + worker_batch_size * num_workers, end_block_id)) # returns: [(block_id, txs)] block_ids_and_txs = transactions.get_nulldata_txs_in_blocks( self.pool, bitcoind_opts, block_ids) # process in order by block ID block_ids_and_txs.sort() for processed_block_id, txs in block_ids_and_txs: if self.get_consensus_at(processed_block_id) is not None: raise Exception( "Already processed block %s (%s)" % (processed_block_id, self.get_consensus_at(processed_block_id))) ops = self.parse_block(block_id, txs) consensus_hash = self.process_block( processed_block_id, ops) log.debug("CONSENSUS(%s): %s" % (processed_block_id, self.get_consensus_at(processed_block_id))) if consensus_hash is None: # fatal error rc = False log.error("Failed to process block %d" % processed_block_id) break log.debug("Last block is %s" % self.lastblock) except: self.pool.close() self.pool.terminate() self.pool.join() self.pool = None raise self.pool.close() self.pool.terminate() self.pool.join() self.pool = None return rc
def build( self, bitcoind_opts, end_block_id ): """ Top-level call to process all blocks in the blockchain. Goes and fetches all OP_RETURN nulldata in order, and feeds them into the state engine implementation using its 'db_parse', 'db_check', 'db_commit', and 'db_save' methods. Note that this method can take some time (hours, days) to complete when called from the first block. This method is *NOT* thread-safe. However, it can be interrupted with the "stop_build" method. Return True on success Return False on error Raise an exception on irrecoverable error--the caller should simply try again. """ first_block_id = self.lastblock + 1 num_workers, worker_batch_size = config.configure_multiprocessing( bitcoind_opts ) rc = True # the state can be big. don't pass it to the slave processes free_memory = self.__delete_me self.pool = workpool.multiprocess_pool( bitcoind_opts, initializer=free_memory, initargs=[self.state] ) try: log.debug("Process blocks %s to %s" % (first_block_id, end_block_id) ) for block_id in xrange( first_block_id, end_block_id, worker_batch_size * num_workers ): if not rc: break if self.pool is None: # interrupted log.debug("Build interrupted") rc = False break block_ids = range( block_id, min(block_id + worker_batch_size * num_workers, end_block_id) ) # returns: [(block_id, txs)] block_ids_and_txs = transactions.get_nulldata_txs_in_blocks( self.pool, bitcoind_opts, block_ids ) # process in order by block ID block_ids_and_txs.sort() for processed_block_id, txs in block_ids_and_txs: if self.get_consensus_at( processed_block_id ) is not None: raise Exception("Already processed block %s (%s)" % (processed_block_id, self.get_consensus_at( processed_block_id )) ) ops = self.parse_block( block_id, txs ) consensus_hash = self.process_block( processed_block_id, ops ) log.debug("CONSENSUS(%s): %s" % (processed_block_id, self.get_consensus_at( processed_block_id ))) if consensus_hash is None: # fatal error rc = False log.error("Failed to process block %d" % processed_block_id ) break log.debug("Last block is %s" % self.lastblock ) except: self.pool.close() self.pool.terminate() self.pool.join() self.pool = None raise self.pool.close() self.pool.terminate() self.pool.join() self.pool = None return rc