#ifndef __LEDGERACQUIRE__ #define __LEDGERACQUIRE__ #include #include #include #include #include #include #include #include #include #include #include "Ledger.h" #include "Peer.h" #include "TaggedCache.h" #include "InstanceCounter.h" #include "ripple.pb.h" // How long before we try again to acquire the same ledger #ifndef LEDGER_REACQUIRE_INTERVAL #define LEDGER_REACQUIRE_INTERVAL 600 #endif DEFINE_INSTANCE(LedgerAcquire); class PeerSet { protected: uint256 mHash; int mTimerInterval, mTimeouts; bool mComplete, mFailed, mProgress; time_t mLastAction; boost::recursive_mutex mLock; boost::asio::deadline_timer mTimer; boost::unordered_map mPeers; PeerSet(const uint256& hash, int interval); virtual ~PeerSet() { ; } void sendRequest(const ripple::TMGetLedger& message); void sendRequest(const ripple::TMGetLedger& message, Peer::ref peer); public: const uint256& getHash() const { return mHash; } bool isComplete() const { return mComplete; } bool isFailed() const { return mFailed; } int getTimeouts() const { return mTimeouts; } void progress() { mProgress = true; } bool isProgress() { return mProgress; } void touch() { mLastAction = time(NULL); } time_t getLastAction() { return mLastAction; } void peerHas(Peer::ref); void badPeer(Peer::ref); void setTimer(); int takePeerSetFrom(const PeerSet& s); int getPeerCount() const; virtual bool isDone() const { return mComplete || mFailed; } protected: virtual void newPeer(Peer::ref) = 0; virtual void onTimer(bool progress) = 0; virtual boost::weak_ptr pmDowncast() = 0; void setComplete() { mComplete = true; } void setFailed() { mFailed = true; } void invokeOnTimer(); private: static void TimerEntry(boost::weak_ptr, const boost::system::error_code& result); }; class LedgerAcquire : private IS_INSTANCE(LedgerAcquire), public PeerSet, public boost::enable_shared_from_this { // A ledger we are trying to acquire public: typedef boost::shared_ptr pointer; protected: Ledger::pointer mLedger; bool mHaveBase, mHaveState, mHaveTransactions, mAborted, mSignaled, mAccept, mByHash; std::set mRecentTXNodes; std::set mRecentASNodes; std::vector< boost::function > mOnComplete; void done(); void onTimer(bool progress); void newPeer(Peer::ref peer) { trigger(peer); } boost::weak_ptr pmDowncast(); public: LedgerAcquire(const uint256& hash); virtual ~LedgerAcquire() { ; } bool isBase() const { return mHaveBase; } bool isAcctStComplete() const { return mHaveState; } bool isTransComplete() const { return mHaveTransactions; } bool isDone() const { return mAborted || isComplete() || isFailed(); } Ledger::ref getLedger() { return mLedger; } void abort() { mAborted = true; } bool setAccept() { if (mAccept) return false; mAccept = true; return true; } void addOnComplete(boost::function); bool takeBase(const std::string& data); bool takeTxNode(const std::list& IDs, const std::list >& data, SMAddNode&); bool takeTxRootNode(const std::vector& data, SMAddNode&); bool takeAsNode(const std::list& IDs, const std::list >& data, SMAddNode&); bool takeAsRootNode(const std::vector& data, SMAddNode&); void trigger(Peer::ref); bool tryLocal(); void addPeers(); typedef std::pair neededHash_t; std::vector getNeededHashes(); static void filterNodes(std::vector& nodeIDs, std::vector& nodeHashes, std::set& recentNodes, int max); }; class LedgerAcquireMaster { protected: boost::mutex mLock; std::map mLedgers; KeyCache mRecentFailures; public: LedgerAcquireMaster() : mRecentFailures("LedgerAcquireRecentFailures", 0, LEDGER_REACQUIRE_INTERVAL) { ; } LedgerAcquire::pointer findCreate(const uint256& hash); LedgerAcquire::pointer find(const uint256& hash); bool hasLedger(const uint256& ledgerHash); void dropLedger(const uint256& ledgerHash); SMAddNode gotLedgerData(ripple::TMLedgerData& packet, Peer::ref); void logFailure(const uint256& h) { mRecentFailures.add(h); } bool isFailure(const uint256& h) { return mRecentFailures.isPresent(h, false); } void sweep(); }; #endif // vim:ts=4