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); 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. // <-- uNodeDir: For deletion, present to make dirDelete efficient.
// --> uRootIndex: The index of the base of the directory. Nodes are based off of this. // --> uRootIndex: The index of the base of the directory. Nodes are based off of this.
// --> uLedgerIndex: Value to add to directory. // --> uLedgerIndex: Value to add to directory.
@@ -814,11 +843,53 @@ bool LedgerEntrySet::dirNext(
return true; 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) TER LedgerEntrySet::offerDelete(const SLE::pointer& sleOffer, const uint256& uOfferIndex, const uint160& uOwnerID)
{ {
uint64 uOwnerNode = sleOffer->getFieldU64(sfOwnerNode); uint64 uOwnerNode = sleOffer->getFieldU64(sfOwnerNode);
TER terResult = dirDelete(false, uOwnerNode, Ledger::getOwnerDirIndex(uOwnerID), uOfferIndex, false); TER terResult = dirDelete(false, uOwnerNode, Ledger::getOwnerDirIndex(uOwnerID), uOfferIndex, false);
if (tesSUCCESS == terResult)
{
terResult = ownerCountAdjust(uOwnerID, -1);
}
if (tesSUCCESS == terResult) if (tesSUCCESS == terResult)
{ {
uint256 uDirectory = sleOffer->getFieldH256(sfBookDirectory); uint256 uDirectory = sleOffer->getFieldH256(sfBookDirectory);

View File

@@ -99,8 +99,11 @@ public:
const uint256& uLedgerIndex, // Item being deleted const uint256& uLedgerIndex, // Item being deleted
const bool bStable); const bool bStable);
bool dirFirst(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); 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. // Offer functions.
TER offerDelete(const uint256& uOfferIndex); TER offerDelete(const uint256& uOfferIndex);

View File

@@ -38,4 +38,6 @@ TER OfferCancelTransactor::doApply()
} }
return terResult; return terResult;
} }
// vim:ts=4

View File

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

View File

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

View File

@@ -53,7 +53,12 @@ TER TrustSetTransactor::doApply()
if (sleRippleState) if (sleRippleState)
{ {
// A line exists in one or more directions. // A line exists in one or more directions.
#if 0 #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) if (!saLimitAmount)
{ {
// Zeroing line. // Zeroing line.
@@ -135,7 +140,7 @@ TER TrustSetTransactor::doApply()
if (uQualityOut) if (uQualityOut)
sleRippleState->setFieldU32(bFlipped ? sfHighQualityOut : sfLowQualityOut, uQualityOut); sleRippleState->setFieldU32(bFlipped ? sfHighQualityOut : sfLowQualityOut, uQualityOut);
uint64 uSrcRef; // Ignored, dirs never delete. uint64 uSrcRef; // <-- Ignored, dirs never delete.
terResult = mEngine->getNodes().dirAdd( terResult = mEngine->getNodes().dirAdd(
uSrcRef, uSrcRef,
@@ -143,12 +148,18 @@ TER TrustSetTransactor::doApply()
sleRippleState->getIndex(), sleRippleState->getIndex(),
boost::bind(&Ledger::ownerDirDescriber, _1, mTxnAccountID)); boost::bind(&Ledger::ownerDirDescriber, _1, mTxnAccountID));
if (tesSUCCESS == terResult)
terResult = mEngine->getNodes().ownerCountAdjust(mTxnAccountID, 1, mTxnAccount);
if (tesSUCCESS == terResult) if (tesSUCCESS == terResult)
terResult = mEngine->getNodes().dirAdd( terResult = mEngine->getNodes().dirAdd(
uSrcRef, uSrcRef,
Ledger::getOwnerDirIndex(uDstAccountID), Ledger::getOwnerDirIndex(uDstAccountID),
sleRippleState->getIndex(), sleRippleState->getIndex(),
boost::bind(&Ledger::ownerDirDescriber, _1, uDstAccountID)); boost::bind(&Ledger::ownerDirDescriber, _1, uDstAccountID));
if (tesSUCCESS == terResult)
terResult = mEngine->getNodes().ownerCountAdjust(uDstAccountID, 1, sleDst);
} }
Log(lsINFO) << "doTrustSet<"; Log(lsINFO) << "doTrustSet<";