Add support for incrementally updating owner count.

This commit is contained in:
Arthur Britto
2012-12-14 20:40:25 -08:00
parent 704b31e0f6
commit 12a4ce88ec
6 changed files with 111 additions and 16 deletions

View File

@@ -486,6 +486,35 @@ void LedgerEntrySet::calcRawMeta(Serializer& s, TER result, uint32 index)
cLog(lsTRACE) << "Metadata:" << mSet.getJson(0);
}
TER LedgerEntrySet::dirCount(const uint256& uRootIndex, uint32& uCount)
{
uint64 uNodeDir = 0;
uCount = 0;
do
{
SLE::pointer sleNode = entryCache(ltDIR_NODE, Ledger::getDirNodeIndex(uRootIndex, uNodeDir));
if (sleNode)
{
uCount += sleNode->getFieldV256(sfIndexes).peekValue().size();
uNodeDir = sleNode->getFieldU64(sfIndexNext); // Get next node.
}
else if (uNodeDir)
{
cLog(lsWARNING) << "dirCount: no such node";
assert(false);
return tefBAD_LEDGER;
}
} while (uNodeDir);
return tesSUCCESS;
}
// <-- uNodeDir: For deletion, present to make dirDelete efficient.
// --> uRootIndex: The index of the base of the directory. Nodes are based off of this.
// --> uLedgerIndex: Value to add to directory.
@@ -814,11 +843,53 @@ bool LedgerEntrySet::dirNext(
return true;
}
// If there is a count, adjust the owner count by iAmount. Otherwise, compute the owner count and store it.
TER LedgerEntrySet::ownerCountAdjust(const uint160& uOwnerID, int iAmount, SLE::ref sleAccountRoot)
{
SLE::pointer sleHold = sleAccountRoot
? SLE::pointer()
: entryCache(ltACCOUNT_ROOT, Ledger::getAccountRootIndex(uOwnerID));
SLE::ref sleRoot = sleAccountRoot
? sleAccountRoot
: sleHold;
const bool bHaveOwnerCount = sleRoot->isFieldPresent(sfOwnerCount);
TER terResult;
if (bHaveOwnerCount)
{
const uint32 uOwnerCount = sleRoot->getFieldU32(sfOwnerCount);
sleRoot->setFieldU32(sfOwnerCount, uOwnerCount+iAmount);
terResult = tesSUCCESS;
}
else
{
uint32 uActualCount;
terResult = dirCount(Ledger::getOwnerDirIndex(uOwnerID), uActualCount);
if (tesSUCCESS == terResult)
{
sleRoot->setFieldU32(sfOwnerCount, uActualCount);
}
}
return terResult;
}
TER LedgerEntrySet::offerDelete(const SLE::pointer& sleOffer, const uint256& uOfferIndex, const uint160& uOwnerID)
{
uint64 uOwnerNode = sleOffer->getFieldU64(sfOwnerNode);
TER terResult = dirDelete(false, uOwnerNode, Ledger::getOwnerDirIndex(uOwnerID), uOfferIndex, false);
if (tesSUCCESS == terResult)
{
terResult = ownerCountAdjust(uOwnerID, -1);
}
if (tesSUCCESS == terResult)
{
uint256 uDirectory = sleOffer->getFieldH256(sfBookDirectory);

View File

@@ -99,8 +99,11 @@ public:
const uint256& uLedgerIndex, // Item being deleted
const bool bStable);
bool dirFirst(const uint256& uRootIndex, SLE::pointer& sleNode, unsigned int& uDirEntry, uint256& uEntryIndex);
bool dirNext(const uint256& uRootIndex, SLE::pointer& sleNode, unsigned int& uDirEntry, uint256& uEntryIndex);
bool dirFirst(const uint256& uRootIndex, SLE::pointer& sleNode, unsigned int& uDirEntry, uint256& uEntryIndex);
bool dirNext(const uint256& uRootIndex, SLE::pointer& sleNode, unsigned int& uDirEntry, uint256& uEntryIndex);
TER dirCount(const uint256& uDirIndex, uint32& uCount);
TER ownerCountAdjust(const uint160& uOwnerID, int iAmount, SLE::ref sleAccountRoot=SLE::pointer());
// Offer functions.
TER offerDelete(const uint256& uOfferIndex);

View File

@@ -39,3 +39,5 @@ TER OfferCancelTransactor::doApply()
return terResult;
}
// vim:ts=4

View File

@@ -399,6 +399,12 @@ TER OfferCreateTransactor::doApply()
boost::bind(&Ledger::qualityDirDescriber, _1, saTakerPays.getCurrency(), uPaysIssuerID,
saTakerGets.getCurrency(), uGetsIssuerID, uRate));
// Update owner count.
if (tesSUCCESS == terResult)
{
terResult = mEngine->getNodes().ownerCountAdjust(mTxnAccountID, 1, mTxnAccount);
}
if (tesSUCCESS == terResult)
{
uint256 uBookBase = Ledger::getBookBase(uPaysCurrency, uPaysIssuerID, uGetsCurrency, uGetsIssuerID);

View File

@@ -9,21 +9,21 @@
class Transactor
{
protected:
const SerializedTransaction& mTxn;
TransactionEngine* mEngine;
TransactionEngineParams mParams;
uint160 mTxnAccountID;
STAmount mFeeDue;
STAmount mSourceBalance;
SLE::pointer mTxnAccount;
bool mHasAuthKey;
RippleAddress mSigningPubKey;
const SerializedTransaction& mTxn;
TransactionEngine* mEngine;
TransactionEngineParams mParams;
uint160 mTxnAccountID;
STAmount mFeeDue;
STAmount mSourceBalance;
SLE::pointer mTxnAccount;
bool mHasAuthKey;
RippleAddress mSigningPubKey;
TER preCheck();
TER checkSeq();
TER payFee();
virtual void calculateFee();
virtual TER checkSig();
virtual TER doApply()=0;
@@ -39,3 +39,5 @@ public:
};
#endif
// vim:ts=4

View File

@@ -53,7 +53,12 @@ TER TrustSetTransactor::doApply()
if (sleRippleState)
{
// A line exists in one or more directions.
#if 0
// We might delete a ripple state node if everything is set to defaults.
// However, this is problematic as it may make predicting reserve amounts harder for users.
// The code here is incomplete.
if (!saLimitAmount)
{
// Zeroing line.
@@ -135,7 +140,7 @@ TER TrustSetTransactor::doApply()
if (uQualityOut)
sleRippleState->setFieldU32(bFlipped ? sfHighQualityOut : sfLowQualityOut, uQualityOut);
uint64 uSrcRef; // Ignored, dirs never delete.
uint64 uSrcRef; // <-- Ignored, dirs never delete.
terResult = mEngine->getNodes().dirAdd(
uSrcRef,
@@ -143,12 +148,18 @@ TER TrustSetTransactor::doApply()
sleRippleState->getIndex(),
boost::bind(&Ledger::ownerDirDescriber, _1, mTxnAccountID));
if (tesSUCCESS == terResult)
terResult = mEngine->getNodes().ownerCountAdjust(mTxnAccountID, 1, mTxnAccount);
if (tesSUCCESS == terResult)
terResult = mEngine->getNodes().dirAdd(
uSrcRef,
Ledger::getOwnerDirIndex(uDstAccountID),
sleRippleState->getIndex(),
boost::bind(&Ledger::ownerDirDescriber, _1, uDstAccountID));
if (tesSUCCESS == terResult)
terResult = mEngine->getNodes().ownerCountAdjust(uDstAccountID, 1, sleDst);
}
Log(lsINFO) << "doTrustSet<";