void doLedgerData (Job&, LedgerHash hash) { InboundLedger::pointer ledger = find (hash); if (ledger) ledger->runData (); }
/** We received a TMLedgerData from a peer. */ bool gotLedgerData (LedgerHash const& hash, std::shared_ptr<Peer> peer, std::shared_ptr<protocol::TMLedgerData> packet_ptr) { protocol::TMLedgerData& packet = *packet_ptr; WriteLog (lsTRACE, InboundLedger) << "Got data (" << packet.nodes ().size () << ") for acquiring ledger: " << hash; InboundLedger::pointer ledger = find (hash); if (!ledger) { WriteLog (lsTRACE, InboundLedger) << "Got data for ledger we're no longer acquiring"; // If it's state node data, stash it because it still might be useful if (packet.type () == protocol::liAS_NODE) { getApp().getJobQueue().addJob(jtLEDGER_DATA, "gotStaleData", std::bind(&InboundLedgers::gotStaleData, this, packet_ptr)); } return false; } // Stash the data for later processing and see if we need to dispatch if (ledger->gotData(std::weak_ptr<Peer>(peer), packet_ptr)) getApp().getJobQueue().addJob (jtLEDGER_DATA, "processLedgerData", std::bind (&InboundLedgers::doLedgerData, this, std::placeholders::_1, hash)); return true; }
// VFALCO TODO Should this be called findOrAdd ? // InboundLedger::pointer findCreate (uint256 const& hash, std::uint32_t seq, InboundLedger::fcReason reason) { assert (hash.isNonZero ()); InboundLedger::pointer ret; // Ensure that any previous IL is destroyed outside the lock InboundLedger::pointer oldLedger; { ScopedLockType sl (mLock); if (! isStopping ()) { if (reason == InboundLedger::fcCONSENSUS) { if (mConsensusLedger.isNonZero() && (mValidationLedger != mConsensusLedger) && (hash != mConsensusLedger)) { hash_map<uint256, InboundLedger::pointer>::iterator it = mLedgers.find (mConsensusLedger); if (it != mLedgers.end ()) { oldLedger = it->second; mLedgers.erase (it); } } mConsensusLedger = hash; } else if (reason == InboundLedger::fcVALIDATION) { if (mValidationLedger.isNonZero() && (mValidationLedger != mConsensusLedger) && (hash != mValidationLedger)) { hash_map<uint256, InboundLedger::pointer>::iterator it = mLedgers.find (mValidationLedger); if (it != mLedgers.end ()) { oldLedger = it->second; mLedgers.erase (it); } } mValidationLedger = hash; } hash_map<uint256, InboundLedger::pointer>::iterator it = mLedgers.find (hash); if (it != mLedgers.end ()) { ret = it->second; // FIXME: Should set the sequence if it's not set } else { ret = std::make_shared <InboundLedger> (hash, seq, reason, std::ref (m_clock)); assert (ret); mLedgers.insert (std::make_pair (hash, ret)); ret->init (sl); ++mCounter; } } } return ret; }
bool InboundLedgers::awaitLedgerData (uint256 const& ledgerHash) { InboundLedger::pointer ledger = find (ledgerHash); if (!ledger) return false; ledger->awaitData (); return true; }
Ledger::pointer acquire (uint256 const& hash, std::uint32_t seq, InboundLedger::fcReason reason) { assert (hash.isNonZero ()); InboundLedger::pointer inbound; { ScopedLockType sl (mLock); if (! isStopping ()) { auto it = mLedgers.find (hash); if (it != mLedgers.end ()) { inbound = it->second; // If the acquisition failed, don't mark the item as // recently accessed so that it can expire. if (! inbound->isFailed ()) inbound->update (seq); } else { inbound = std::make_shared <InboundLedger> ( hash, seq, reason, std::ref (m_clock)); mLedgers.emplace (hash, inbound); inbound->init (sl); ++mCounter; } } } if (inbound && inbound->isComplete ()) return inbound->getLedger(); return {}; }
InboundLedger::pointer InboundLedgers::findCreate (uint256 const& hash, uint32 seq) { assert (hash.isNonZero ()); InboundLedger::pointer ret; { boost::mutex::scoped_lock sl (mLock); boost::unordered_map<uint256, InboundLedger::pointer>::iterator it = mLedgers.find (hash); if (it != mLedgers.end ()) { ret = it->second; // FIXME: Should set the sequence if it's not set } else { ret = boost::make_shared<InboundLedger> (hash, seq); assert (ret); mLedgers.insert (std::make_pair (hash, ret)); if (!ret->tryLocal()) { ret->addPeers (); ret->setTimer (); // Cannot call in constructor } else if (!ret->isFailed ()) { WriteLog (lsDEBUG, InboundLedger) << "Acquiring ledger we already have locally: " << hash; Ledger::pointer ledger = ret->getLedger (); ledger->setClosed (); ledger->setImmutable (); getApp().getLedgerMaster ().storeLedger (ledger); } } } return ret; }
// means "We got some data from an inbound ledger" void InboundLedgers::gotLedgerData (Job&, uint256 hash, boost::shared_ptr<protocol::TMLedgerData> packet_ptr, boost::weak_ptr<Peer> wPeer) { protocol::TMLedgerData& packet = *packet_ptr; Peer::pointer peer = wPeer.lock (); WriteLog (lsTRACE, InboundLedger) << "Got data (" << packet.nodes ().size () << ") for acquiring ledger: " << hash; InboundLedger::pointer ledger = find (hash); if (!ledger) { WriteLog (lsTRACE, InboundLedger) << "Got data for ledger we're not acquiring"; if (peer) peer->applyLoadCharge (LT_InvalidRequest); return; } ledger->noAwaitData (); if (!peer) return; if (packet.type () == protocol::liBASE) { if (packet.nodes_size () < 1) { WriteLog (lsWARNING, InboundLedger) << "Got empty base data"; peer->applyLoadCharge (LT_InvalidRequest); return; } if (!ledger->takeBase (packet.nodes (0).nodedata ())) { WriteLog (lsWARNING, InboundLedger) << "Got invalid base data"; peer->applyLoadCharge (LT_InvalidRequest); return; } SHAMapAddNode san = SHAMapAddNode::useful (); if ((packet.nodes ().size () > 1) && !ledger->takeAsRootNode (strCopy (packet.nodes (1).nodedata ()), san)) { WriteLog (lsWARNING, InboundLedger) << "Included ASbase invalid"; } if ((packet.nodes ().size () > 2) && !ledger->takeTxRootNode (strCopy (packet.nodes (2).nodedata ()), san)) { WriteLog (lsWARNING, InboundLedger) << "Included TXbase invalid"; } if (!san.isInvalid ()) { ledger->progress (); ledger->trigger (peer); } else WriteLog (lsDEBUG, InboundLedger) << "Peer sends invalid base data"; return; } if ((packet.type () == protocol::liTX_NODE) || (packet.type () == protocol::liAS_NODE)) { std::list<SHAMapNode> nodeIDs; std::list< Blob > nodeData; if (packet.nodes ().size () <= 0) { WriteLog (lsINFO, InboundLedger) << "Got response with no nodes"; peer->applyLoadCharge (LT_InvalidRequest); return; } for (int i = 0; i < packet.nodes ().size (); ++i) { const protocol::TMLedgerNode& node = packet.nodes (i); if (!node.has_nodeid () || !node.has_nodedata ()) { WriteLog (lsWARNING, InboundLedger) << "Got bad node"; peer->applyLoadCharge (LT_InvalidRequest); return; } nodeIDs.push_back (SHAMapNode (node.nodeid ().data (), node.nodeid ().size ())); nodeData.push_back (Blob (node.nodedata ().begin (), node.nodedata ().end ())); } SHAMapAddNode ret; if (packet.type () == protocol::liTX_NODE) ledger->takeTxNode (nodeIDs, nodeData, ret); else ledger->takeAsNode (nodeIDs, nodeData, ret); if (!ret.isInvalid ()) { ledger->progress (); ledger->trigger (peer); } else WriteLog (lsDEBUG, InboundLedger) << "Peer sends invalid node data"; return; } WriteLog (lsWARNING, InboundLedger) << "Not sure what ledger data we got"; peer->applyLoadCharge (LT_InvalidRequest); }