Files
xahaud/modules/ripple_app/shamap/ripple_SHAMap.h
2013-08-22 18:10:02 -07:00

241 lines
8.4 KiB
C++

//------------------------------------------------------------------------------
/*
Copyright (c) 2011-2013, OpenCoin, Inc.
*/
//==============================================================================
#ifndef RIPPLE_SHAMAP_H
#define RIPPLE_SHAMAP_H
enum SHAMapState
{
smsModifying = 0, // Objects can be added and removed (like an open ledger)
smsImmutable = 1, // Map cannot be changed (like a closed ledger)
smsSynching = 2, // Map's hash is locked in, valid nodes can be added (like a peer's closing ledger)
smsFloating = 3, // Map is free to change hash (like a synching open ledger)
smsInvalid = 4, // Map is known not to be valid (usually synching a corrupt ledger)
};
class SHAMap
: public CountedObject <SHAMap>
{
public:
static char const* getCountedObjectName () { return "SHAMap"; }
typedef boost::shared_ptr<SHAMap> pointer;
typedef const boost::shared_ptr<SHAMap>& ref;
typedef std::pair<SHAMapItem::pointer, SHAMapItem::pointer> DeltaItem;
typedef std::map<uint256, DeltaItem> Delta;
typedef boost::unordered_map<SHAMapNode, SHAMapTreeNode::pointer> DirtyMap;
public:
// build new map
explicit SHAMap (SHAMapType t, uint32 seq = 1);
SHAMap (SHAMapType t, uint256 const & hash);
~SHAMap ();
std::size_t size () const noexcept
{
return mTNByID.size ();
}
// Returns a new map that's a snapshot of this one. Force CoW
SHAMap::pointer snapShot (bool isMutable);
// Remove nodes from memory
void dropCache ();
void setLedgerSeq (uint32 lseq)
{
mLedgerSeq = lseq;
}
// hold the map stable across operations
ScopedLock Lock () const
{
return ScopedLock (mLock);
}
bool hasNode (const SHAMapNode & id);
bool fetchRoot (uint256 const & hash, SHAMapSyncFilter * filter);
// normal hash access functions
bool hasItem (uint256 const & id);
bool delItem (uint256 const & id);
bool addItem (const SHAMapItem & i, bool isTransaction, bool hasMeta);
bool updateItem (const SHAMapItem & i, bool isTransaction, bool hasMeta);
SHAMapItem getItem (uint256 const & id);
uint256 getHash () const
{
return root->getNodeHash ();
}
uint256 getHash ()
{
return root->getNodeHash ();
}
// save a copy if you have a temporary anyway
bool updateGiveItem (SHAMapItem::ref, bool isTransaction, bool hasMeta);
bool addGiveItem (SHAMapItem::ref, bool isTransaction, bool hasMeta);
// save a copy if you only need a temporary
SHAMapItem::pointer peekItem (uint256 const & id);
SHAMapItem::pointer peekItem (uint256 const & id, uint256 & hash);
SHAMapItem::pointer peekItem (uint256 const & id, SHAMapTreeNode::TNType & type);
// traverse functions
SHAMapItem::pointer peekFirstItem ();
SHAMapItem::pointer peekFirstItem (SHAMapTreeNode::TNType & type);
SHAMapItem::pointer peekLastItem ();
SHAMapItem::pointer peekNextItem (uint256 const& );
SHAMapItem::pointer peekNextItem (uint256 const& , SHAMapTreeNode::TNType & type);
SHAMapItem::pointer peekPrevItem (uint256 const& );
// comparison/sync functions
void getMissingNodes (std::vector<SHAMapNode>& nodeIDs, std::vector<uint256>& hashes, int max,
SHAMapSyncFilter * filter);
bool getNodeFat (const SHAMapNode & node, std::vector<SHAMapNode>& nodeIDs,
std::list<Blob >& rawNode, bool fatRoot, bool fatLeaves);
bool getRootNode (Serializer & s, SHANodeFormat format);
std::vector<uint256> getNeededHashes (int max, SHAMapSyncFilter * filter);
SHAMapAddNode addRootNode (uint256 const & hash, Blob const & rootNode, SHANodeFormat format,
SHAMapSyncFilter * filter);
SHAMapAddNode addRootNode (Blob const & rootNode, SHANodeFormat format,
SHAMapSyncFilter * filter);
SHAMapAddNode addKnownNode (const SHAMapNode & nodeID, Blob const & rawNode,
SHAMapSyncFilter * filter);
// status functions
void setImmutable ()
{
assert (mState != smsInvalid);
mState = smsImmutable;
}
void clearImmutable ()
{
mState = smsModifying;
}
bool isSynching () const
{
return (mState == smsFloating) || (mState == smsSynching);
}
void setSynching ()
{
mState = smsSynching;
}
void setFloating ()
{
mState = smsFloating;
}
void clearSynching ()
{
mState = smsModifying;
}
bool isValid ()
{
return mState != smsInvalid;
}
// caution: otherMap must be accessed only by this function
// return value: true=successfully completed, false=too different
bool compare (SHAMap::ref otherMap, Delta & differences, int maxCount);
int armDirty ();
static int flushDirty (DirtyMap & dirtyMap, int maxNodes, NodeObjectType t, uint32 seq);
boost::shared_ptr<DirtyMap> disarmDirty ();
void setSeq (uint32 seq)
{
mSeq = seq;
}
uint32 getSeq ()
{
return mSeq;
}
// overloads for backed maps
boost::shared_ptr<SHAMapTreeNode> fetchNodeExternal (const SHAMapNode & id, uint256 const & hash); // throws
boost::shared_ptr<SHAMapTreeNode> fetchNodeExternalNT (const SHAMapNode & id, uint256 const & hash); // no throw
bool operator== (const SHAMap & s)
{
return getHash () == s.getHash ();
}
// trusted path operations - prove a particular node is in a particular ledger
std::list<Blob > getTrustedPath (uint256 const & index);
static Blob checkTrustedPath (uint256 const & ledgerHash, uint256 const & leafIndex,
const std::list<Blob >& path);
void walkMap (std::vector<SHAMapMissingNode>& missingNodes, int maxMissing);
bool getPath (uint256 const & index, std::vector< Blob >& nodes, SHANodeFormat format);
bool deepCompare (SHAMap & other);
virtual void dump (bool withHashes = false);
typedef std::pair <uint256, Blob> fetchPackEntry_t;
std::list<fetchPackEntry_t> getFetchPack (SHAMap * have, bool includeLeaves, int max);
void getFetchPack (SHAMap * have, bool includeLeaves, int max, FUNCTION_TYPE<void (const uint256&, const Blob&)>);
static int getFullBelowSize ()
{
return fullBelowCache.getSize ();
}
static void sweep ()
{
fullBelowCache.sweep ();
}
private:
static KeyCache <uint256, UptimeTimerAdapter> fullBelowCache;
void dirtyUp (std::stack<SHAMapTreeNode::pointer>& stack, uint256 const & target, uint256 prevHash);
std::stack<SHAMapTreeNode::pointer> getStack (uint256 const & id, bool include_nonmatching_leaf);
SHAMapTreeNode::pointer walkTo (uint256 const & id, bool modify);
SHAMapTreeNode* walkToPointer (uint256 const & id);
SHAMapTreeNode::pointer checkCacheNode (const SHAMapNode&);
void returnNode (SHAMapTreeNode::pointer&, bool modify);
void trackNewNode (SHAMapTreeNode::pointer&);
SHAMapTreeNode::pointer getNode (const SHAMapNode & id);
SHAMapTreeNode::pointer getNode (const SHAMapNode & id, uint256 const & hash, bool modify);
SHAMapTreeNode* getNodePointer (const SHAMapNode & id);
SHAMapTreeNode* getNodePointer (const SHAMapNode & id, uint256 const & hash);
SHAMapTreeNode* getNodePointerNT (const SHAMapNode & id, uint256 const & hash);
SHAMapTreeNode* getNodePointer (const SHAMapNode & id, uint256 const & hash, SHAMapSyncFilter * filter);
SHAMapTreeNode* getNodePointerNT (const SHAMapNode & id, uint256 const & hash, SHAMapSyncFilter * filter);
SHAMapTreeNode* firstBelow (SHAMapTreeNode*);
SHAMapTreeNode* lastBelow (SHAMapTreeNode*);
SHAMapItem::pointer onlyBelow (SHAMapTreeNode*);
void eraseChildren (SHAMapTreeNode::pointer);
void dropBelow (SHAMapTreeNode*);
bool hasInnerNode (const SHAMapNode & nodeID, uint256 const & hash);
bool hasLeafNode (uint256 const & tag, uint256 const & hash);
bool walkBranch (SHAMapTreeNode * node, SHAMapItem::ref otherMapItem, bool isFirstMap,
Delta & differences, int & maxCount);
private:
uint32 mSeq;
uint32 mLedgerSeq; // sequence number of ledger this is part of
mutable boost::recursive_mutex mLock;
boost::unordered_map<SHAMapNode, SHAMapTreeNode::pointer> mTNByID;
boost::shared_ptr<DirtyMap> mDirtyNodes;
SHAMapTreeNode::pointer root;
SHAMapState mState;
SHAMapType mType;
};
#endif
// vim:ts=4