Replace flattenTrie by callback
Signed-off-by: Anthony Fieroni <bvbfan@abv.bg> Use interruption point instead of boolean condition Signed-off-by: Anthony Fieroni <bvbfan@abv.bg> Add ability to earlier exit in rpc methods getclaimtrie and getclaimsintrie Signed-off-by: Anthony Fieroni <bvbfan@abv.bg> simplified early exit handling ran formatter
This commit is contained in:
parent
b5a0c962d0
commit
02986f766c
4 changed files with 181 additions and 90 deletions
|
@ -403,28 +403,6 @@ CAmount CClaimTrie::getTotalValueOfClaimsRecursive(const CClaimTrieNode* current
|
|||
return value_in_subtrie;
|
||||
}
|
||||
|
||||
bool CClaimTrie::recursiveFlattenTrie(const std::string& name, const CClaimTrieNode* current, std::vector<namedNodeType>& nodes) const
|
||||
{
|
||||
namedNodeType node(name, *current);
|
||||
nodes.push_back(node);
|
||||
for (nodeMapType::const_iterator it = current->children.begin(); it != current->children.end(); ++it)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << name << it->first;
|
||||
if (!recursiveFlattenTrie(ss.str(), it->second, nodes))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<namedNodeType> CClaimTrie::flattenTrie() const
|
||||
{
|
||||
std::vector<namedNodeType> nodes;
|
||||
if (!recursiveFlattenTrie("", &root, nodes))
|
||||
LogPrintf("%s: Something went wrong flattening the trie", __func__);
|
||||
return nodes;
|
||||
}
|
||||
|
||||
const CClaimTrieNode* CClaimTrie::getNodeForName(const std::string& name) const
|
||||
{
|
||||
const CClaimTrieNode* current = &root;
|
||||
|
@ -2548,25 +2526,32 @@ uint256 CClaimTrieCache::getLeafHashForProof(const std::string& currentPosition,
|
|||
}
|
||||
}
|
||||
|
||||
void CClaimTrieCache::recursiveFlattenTrie(const std::string& name, const CClaimTrieNode* current, std::vector<namedNodeType>& nodes) const
|
||||
void CClaimTrieCache::recursiveIterateTrie(std::string& name, const CClaimTrieNode* current, CNodeCallback& callback) const
|
||||
{
|
||||
nodes.push_back(std::make_pair(name, *current));
|
||||
callback.visit(name, current);
|
||||
|
||||
nodeCacheType::const_iterator cachedNode;
|
||||
for (nodeMapType::const_iterator it = current->children.begin(); it != current->children.end(); ++it) {
|
||||
const std::string str = name + char(it->first);
|
||||
cachedNode = cache.find(str);
|
||||
name.push_back(it->first);
|
||||
cachedNode = cache.find(name);
|
||||
if (cachedNode != cache.end())
|
||||
recursiveFlattenTrie(str, cachedNode->second, nodes);
|
||||
recursiveIterateTrie(name, cachedNode->second, callback);
|
||||
else
|
||||
recursiveFlattenTrie(str, it->second, nodes);
|
||||
recursiveIterateTrie(name, it->second, callback);
|
||||
name.erase(name.end() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<namedNodeType> CClaimTrieCache::flattenTrie() const
|
||||
bool CClaimTrieCache::iterateTrie(CNodeCallback& callback) const
|
||||
{
|
||||
std::vector<namedNodeType> nodes;
|
||||
recursiveFlattenTrie("", getRoot(), nodes);
|
||||
return nodes;
|
||||
try {
|
||||
std::string name;
|
||||
recursiveIterateTrie(name, getRoot(), callback);
|
||||
assert(name.empty());
|
||||
} catch (const CNodeCallback::CRecursionInterruptionException& ex) {
|
||||
return ex.success;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
claimsForNameType CClaimTrieCache::getClaimsForName(const std::string& name) const
|
||||
|
|
|
@ -132,8 +132,6 @@ typedef std::vector<CSupportValue> supportMapEntryType;
|
|||
|
||||
typedef std::map<unsigned char, CClaimTrieNode*> nodeMapType;
|
||||
|
||||
typedef std::pair<std::string, CClaimTrieNode> namedNodeType;
|
||||
|
||||
class CClaimTrieNode
|
||||
{
|
||||
public:
|
||||
|
@ -317,7 +315,6 @@ public:
|
|||
bool WriteToDisk();
|
||||
bool ReadFromDisk(bool check = false);
|
||||
|
||||
std::vector<namedNodeType> flattenTrie() const;
|
||||
bool getInfoForName(const std::string& name, CClaimValue& claim) const;
|
||||
bool getLastTakeoverForName(const std::string& name, int& lastTakeoverHeight) const;
|
||||
|
||||
|
@ -392,9 +389,6 @@ private:
|
|||
unsigned int getTotalClaimsRecursive(const CClaimTrieNode* current) const;
|
||||
CAmount getTotalValueOfClaimsRecursive(const CClaimTrieNode* current,
|
||||
bool fControllingOnly) const;
|
||||
bool recursiveFlattenTrie(const std::string& name,
|
||||
const CClaimTrieNode* current,
|
||||
std::vector<namedNodeType>& nodes) const;
|
||||
|
||||
void markNodeDirty(const std::string& name, CClaimTrieNode* node);
|
||||
void updateQueueRow(int nHeight, claimQueueRowType& row);
|
||||
|
@ -459,6 +453,27 @@ public:
|
|||
int nHeightOfLastTakeover;
|
||||
};
|
||||
|
||||
struct CNodeCallback {
|
||||
struct CRecursionInterruptionException : public std::exception {
|
||||
const bool success;
|
||||
explicit CRecursionInterruptionException(bool success) : success(success) {}
|
||||
};
|
||||
|
||||
virtual ~CNodeCallback()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to be called on every trie node
|
||||
* @param[in] name full name of the node
|
||||
* @param[in] node pointer to node itself
|
||||
*
|
||||
* To breakout early throw an exception.
|
||||
* Throwing CRecursionInterruptionException will allow you to set the return value of iterateTrie.
|
||||
*/
|
||||
virtual void visit(const std::string& name, const CClaimTrieNode* node) = 0;
|
||||
};
|
||||
|
||||
class CClaimTrieCache
|
||||
{
|
||||
public:
|
||||
|
@ -533,7 +548,7 @@ public:
|
|||
|
||||
bool forkForExpirationChange(bool increment) const;
|
||||
|
||||
std::vector<namedNodeType> flattenTrie() const;
|
||||
bool iterateTrie(CNodeCallback& callback) const;
|
||||
|
||||
claimsForNameType getClaimsForName(const std::string& name) const;
|
||||
|
||||
|
@ -635,7 +650,7 @@ protected:
|
|||
|
||||
int getNumBlocksOfContinuousOwnership(const std::string& name) const;
|
||||
|
||||
void recursiveFlattenTrie(const std::string& name, const CClaimTrieNode* current, std::vector<namedNodeType>& nodes) const;
|
||||
void recursiveIterateTrie(std::string& name, const CClaimTrieNode* current, CNodeCallback& callback) const;
|
||||
|
||||
const CClaimTrieNode* getNodeForName(const std::string& name) const;
|
||||
};
|
||||
|
|
|
@ -112,44 +112,65 @@ UniValue getclaimsintrie(const UniValue& params, bool fHelp)
|
|||
RollBackTo(blockIndex, coinsCache, trieCache);
|
||||
}
|
||||
|
||||
UniValue ret(UniValue::VARR);
|
||||
std::vector<namedNodeType> nodes = trieCache.flattenTrie();
|
||||
for (std::vector<namedNodeType>::iterator it = nodes.begin(); it != nodes.end(); ++it) {
|
||||
if (it->second.claims.empty()) continue;
|
||||
|
||||
UniValue claims(UniValue::VARR);
|
||||
for (std::vector<CClaimValue>::iterator itClaims = it->second.claims.begin(); itClaims != it->second.claims.end(); ++itClaims) {
|
||||
UniValue claim(UniValue::VOBJ);
|
||||
claim.push_back(Pair("claimId", itClaims->claimId.GetHex()));
|
||||
claim.push_back(Pair("txid", itClaims->outPoint.hash.GetHex()));
|
||||
claim.push_back(Pair("n", (int)itClaims->outPoint.n));
|
||||
claim.push_back(Pair("amount", ValueFromAmount(itClaims->nAmount)));
|
||||
claim.push_back(Pair("height", itClaims->nHeight));
|
||||
const CCoins* coin = coinsCache.AccessCoins(itClaims->outPoint.hash);
|
||||
if (!coin) {
|
||||
LogPrintf("%s: %s does not exist in the coins view, despite being associated with a name\n",
|
||||
__func__, itClaims->outPoint.hash.GetHex());
|
||||
claim.push_back(Pair("error", "No value found for claim"));
|
||||
} else if (!coin->IsAvailable(itClaims->outPoint.n)) {
|
||||
LogPrintf("%s: the specified txout of %s appears to have been spent\n", __func__, itClaims->outPoint.hash.GetHex());
|
||||
claim.push_back(Pair("error", "Txout spent"));
|
||||
} else {
|
||||
int op;
|
||||
std::vector<std::vector<unsigned char> > vvchParams;
|
||||
if (!DecodeClaimScript(coin->vout[itClaims->outPoint.n].scriptPubKey, op, vvchParams)) {
|
||||
LogPrintf("%s: the specified txout of %s does not have an claim command\n", __func__, itClaims->outPoint.hash.GetHex());
|
||||
}
|
||||
std::string sValue(vvchParams[1].begin(), vvchParams[1].end());
|
||||
claim.push_back(Pair("value", sValue));
|
||||
}
|
||||
claims.push_back(claim);
|
||||
class CClaimsCallback : public CNodeCallback
|
||||
{
|
||||
public:
|
||||
CClaimsCallback(UniValue& ret, const CCoinsViewCache& coinsCache) : nodes(ret), coinsCache(coinsCache)
|
||||
{
|
||||
}
|
||||
|
||||
UniValue node(UniValue::VOBJ);
|
||||
node.push_back(Pair("name", it->first));
|
||||
node.push_back(Pair("claims", claims));
|
||||
ret.push_back(node);
|
||||
}
|
||||
void visit(const std::string& name, const CClaimTrieNode* node)
|
||||
{
|
||||
if (ShutdownRequested())
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Shutdown requested");
|
||||
|
||||
boost::this_thread::interruption_point();
|
||||
|
||||
if (node->claims.empty())
|
||||
return;
|
||||
|
||||
UniValue claims(UniValue::VARR);
|
||||
for (std::vector<CClaimValue>::const_iterator itClaims = node->claims.begin(); itClaims != node->claims.end(); ++itClaims) {
|
||||
UniValue claim(UniValue::VOBJ);
|
||||
claim.push_back(Pair("claimId", itClaims->claimId.GetHex()));
|
||||
claim.push_back(Pair("txid", itClaims->outPoint.hash.GetHex()));
|
||||
claim.push_back(Pair("n", (int)itClaims->outPoint.n));
|
||||
claim.push_back(Pair("amount", ::ValueFromAmount(itClaims->nAmount)));
|
||||
claim.push_back(Pair("height", itClaims->nHeight));
|
||||
const CCoins* coin = coinsCache.AccessCoins(itClaims->outPoint.hash);
|
||||
if (!coin) {
|
||||
LogPrintf("%s: %s does not exist in the coins view, despite being associated with a name\n",
|
||||
__func__, itClaims->outPoint.hash.GetHex());
|
||||
claim.push_back(Pair("error", "No value found for claim"));
|
||||
} else if (!coin->IsAvailable(itClaims->outPoint.n)) {
|
||||
LogPrintf("%s: the specified txout of %s appears to have been spent\n", __func__, itClaims->outPoint.hash.GetHex());
|
||||
claim.push_back(Pair("error", "Txout spent"));
|
||||
} else {
|
||||
int op;
|
||||
std::vector<std::vector<unsigned char> > vvchParams;
|
||||
if (!DecodeClaimScript(coin->vout[itClaims->outPoint.n].scriptPubKey, op, vvchParams)) {
|
||||
LogPrintf("%s: the specified txout of %s does not have an claim command\n", __func__, itClaims->outPoint.hash.GetHex());
|
||||
}
|
||||
std::string sValue(vvchParams[1].begin(), vvchParams[1].end());
|
||||
claim.push_back(Pair("value", sValue));
|
||||
}
|
||||
claims.push_back(claim);
|
||||
}
|
||||
|
||||
UniValue nodeObj(UniValue::VOBJ);
|
||||
nodeObj.push_back(Pair("name", name));
|
||||
nodeObj.push_back(Pair("claims", claims));
|
||||
nodes.push_back(nodeObj);
|
||||
}
|
||||
|
||||
private:
|
||||
UniValue& nodes;
|
||||
const CCoinsViewCache& coinsCache;
|
||||
};
|
||||
|
||||
UniValue ret(UniValue::VARR);
|
||||
CClaimsCallback claimsCallback(ret, coinsCache);
|
||||
trieCache.iterateTrie(claimsCallback);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -188,23 +209,40 @@ UniValue getclaimtrie(const UniValue& params, bool fHelp)
|
|||
RollBackTo(blockIndex, coinsCache, trieCache);
|
||||
}
|
||||
|
||||
UniValue ret(UniValue::VARR);
|
||||
std::vector<namedNodeType> nodes = trieCache.flattenTrie();
|
||||
for (std::vector<namedNodeType>::iterator it = nodes.begin(); it != nodes.end(); ++it)
|
||||
class CClaimCallback : public CNodeCallback
|
||||
{
|
||||
UniValue node(UniValue::VOBJ);
|
||||
node.push_back(Pair("name", it->first));
|
||||
node.push_back(Pair("hash", it->second.hash.GetHex()));
|
||||
CClaimValue claim;
|
||||
if (it->second.getBestClaim(claim))
|
||||
public:
|
||||
CClaimCallback(UniValue& ret) : nodes(ret)
|
||||
{
|
||||
node.push_back(Pair("txid", claim.outPoint.hash.GetHex()));
|
||||
node.push_back(Pair("n", (int)claim.outPoint.n));
|
||||
node.push_back(Pair("value", ValueFromAmount(claim.nAmount)));
|
||||
node.push_back(Pair("height", claim.nHeight));
|
||||
}
|
||||
ret.push_back(node);
|
||||
}
|
||||
|
||||
void visit(const std::string& name, const CClaimTrieNode* node)
|
||||
{
|
||||
if (ShutdownRequested())
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Shutdown requested");
|
||||
|
||||
boost::this_thread::interruption_point();
|
||||
|
||||
UniValue nodeObj(UniValue::VOBJ);
|
||||
nodeObj.push_back(Pair("name", name));
|
||||
nodeObj.push_back(Pair("hash", node->hash.GetHex()));
|
||||
CClaimValue claim;
|
||||
if (node->getBestClaim(claim)) {
|
||||
nodeObj.push_back(Pair("txid", claim.outPoint.hash.GetHex()));
|
||||
nodeObj.push_back(Pair("n", (int)claim.outPoint.n));
|
||||
nodeObj.push_back(Pair("value", ::ValueFromAmount(claim.nAmount)));
|
||||
nodeObj.push_back(Pair("height", claim.nHeight));
|
||||
}
|
||||
nodes.push_back(nodeObj);
|
||||
}
|
||||
|
||||
private:
|
||||
UniValue& nodes;
|
||||
};
|
||||
|
||||
UniValue ret(UniValue::VARR);
|
||||
CClaimCallback claimCallback(ret);
|
||||
trieCache.iterateTrie(claimCallback);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -274,5 +274,58 @@ BOOST_AUTO_TEST_CASE(recursive_prune_test)
|
|||
BOOST_CHECK_EQUAL(0, it->second->children.size());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(iteratetrie_test)
|
||||
{
|
||||
BOOST_CHECK(pclaimTrie->empty());
|
||||
CClaimTrieCacheTest ctc(pclaimTrie);
|
||||
|
||||
uint256 hash0(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
|
||||
CMutableTransaction tx1 = BuildTransaction(hash0);
|
||||
|
||||
const uint256 txhash = tx1.GetHash();
|
||||
CClaimValue claimVal(COutPoint(txhash, 0), ClaimIdHash(txhash, 0), CAmount(10), 0, 0);
|
||||
ctc.insertClaimIntoTrie("test", claimVal);
|
||||
|
||||
|
||||
int count = 0;
|
||||
|
||||
struct TestCallBack : public CNodeCallback {
|
||||
TestCallBack(int& count) : count(count)
|
||||
{
|
||||
}
|
||||
|
||||
void visit(const std::string& name, const CClaimTrieNode* node)
|
||||
{
|
||||
count++;
|
||||
if (name == "test") {
|
||||
BOOST_CHECK(node->claims.size() == 1);
|
||||
}
|
||||
}
|
||||
|
||||
int& count;
|
||||
} testCallback(count);
|
||||
|
||||
BOOST_CHECK(ctc.iterateTrie(testCallback));
|
||||
BOOST_CHECK(count == 5);
|
||||
|
||||
count = 3;
|
||||
|
||||
struct TestCallBack2 : public CNodeCallback {
|
||||
TestCallBack2(int& count) : count(count)
|
||||
{
|
||||
}
|
||||
|
||||
void visit(const std::string& name, const CClaimTrieNode* node)
|
||||
{
|
||||
if (--count <= 0)
|
||||
throw CRecursionInterruptionException(false);
|
||||
}
|
||||
|
||||
int& count;
|
||||
} testCallback2(count);
|
||||
|
||||
BOOST_CHECK(!ctc.iterateTrie(testCallback2));
|
||||
BOOST_CHECK(count == 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
|
Loading…
Reference in a new issue