void BlockchainSynchronizer::workingProcedure() { while (!checkIfShouldStop()) { actualizeFutureState(); } actualizeFutureState(); }
bool BlockchainSynchronizer::removeConsumer(IBlockchainConsumer* consumer) { assert(consumer != nullptr); if (!(checkIfStopped() && checkIfShouldStop())) { throw std::runtime_error("Can't remove consumer, because BlockchainSynchronizer isn't stopped"); } return m_consumers.erase(consumer) > 0; }
void BlockchainSynchronizer::addConsumer(IBlockchainConsumer* consumer) { assert(consumer != nullptr); assert(m_consumers.count(consumer) == 0); if (!(checkIfStopped() && checkIfShouldStop())) { throw std::runtime_error("Can't add consumer, because BlockchainSynchronizer isn't stopped"); } m_consumers.insert(std::make_pair(consumer, std::make_shared<SynchronizationState>(m_genesisBlockHash))); }
///pre: m_consumersMutex is locked SynchronizationState* BlockchainSynchronizer::getConsumerSynchronizationState(IBlockchainConsumer* consumer) const { assert(consumer != nullptr); if (!(checkIfStopped() && checkIfShouldStop())) { throw std::runtime_error("Can't get consumer state, because BlockchainSynchronizer isn't stopped"); } auto it = m_consumers.find(consumer); if (it == m_consumers.end()) { return nullptr; } return it->second.get(); }
IStreamSerializable* BlockchainSynchronizer::getConsumerState(IBlockchainConsumer* consumer) { assert(consumer != nullptr); if (!(checkIfStopped() && checkIfShouldStop())) { throw std::runtime_error("Can't get consumer state, because BlockchainSynchronizer isn't stopped"); } std::unique_lock<std::mutex> lk(m_consumersMutex); auto it = m_consumers.find(consumer); if (it == m_consumers.end()) { return nullptr; } return it->second.get(); }
std::error_code BlockchainSynchronizer::processPoolTxs(GetPoolResponse& response) { std::error_code error; { std::unique_lock<std::mutex> lk(m_consumersMutex); for (auto& consumer : m_consumers) { if (checkIfShouldStop()) { //if stop, return immediately, without notification return std::make_error_code(std::errc::interrupted); } error = consumer.first->onPoolUpdated(response.newTxs, response.deletedTxIds); if (error) { break; } } } return error; }
void BlockchainSynchronizer::processBlocks(GetBlocksResponse& response) { uint32_t newHeight = response.startHeight + static_cast<uint32_t>(response.newBlocks.size()); BlockchainInterval interval; interval.startHeight = response.startHeight; std::vector<CompleteBlock> blocks; for (auto& block : response.newBlocks) { if (checkIfShouldStop()) { break; } CompleteBlock completeBlock; completeBlock.blockHash = block.blockHash; interval.blocks.push_back(completeBlock.blockHash); if (block.hasBlock) { completeBlock.block = std::move(block.block); completeBlock.transactions.push_back(createTransactionPrefix(completeBlock.block->baseTransaction)); try { for (const auto& txShortInfo : block.txsShortInfo) { completeBlock.transactions.push_back(createTransactionPrefix(txShortInfo.txPrefix, reinterpret_cast<const Hash&>(txShortInfo.txId))); } } catch (std::exception&) { setFutureStateIf(State::idle, std::bind( [](State futureState) -> bool { return futureState != State::stopped; }, std::ref(m_futureState))); m_observerManager.notify( &IBlockchainSynchronizerObserver::synchronizationCompleted, std::make_error_code(std::errc::invalid_argument)); return; } } blocks.push_back(std::move(completeBlock)); } if (!checkIfShouldStop()) { response.newBlocks.clear(); std::unique_lock<std::mutex> lk(m_consumersMutex); auto result = updateConsumers(interval, blocks); lk.unlock(); switch (result) { case UpdateConsumersResult::errorOccured: if (setFutureStateIf(State::idle, std::bind( [](State futureState) -> bool { return futureState != State::stopped; }, std::ref(m_futureState)))) { m_observerManager.notify( &IBlockchainSynchronizerObserver::synchronizationCompleted, std::make_error_code(std::errc::invalid_argument)); } break; case UpdateConsumersResult::nothingChanged: if (m_node.getLastKnownBlockHeight() != m_node.getLastLocalBlockHeight()) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); } else { break; } case UpdateConsumersResult::addedNewBlocks: setFutureState(State::blockchainSync); m_observerManager.notify( &IBlockchainSynchronizerObserver::synchronizationProgressUpdated, newHeight, std::max(m_node.getKnownBlockCount(), m_node.getLocalBlockCount())); break; } if (!blocks.empty()) { lastBlockId = blocks.back().blockHash; } } if (checkIfShouldStop()) { //Sic! m_observerManager.notify( &IBlockchainSynchronizerObserver::synchronizationCompleted, std::make_error_code(std::errc::interrupted)); } }