Refactor Ledger and support classes:

This performs a deep refactor on the Ledger class and its supporting
classes, in preparation for the move to shared_ptr<SLE const> in
places where the SLE is immutable and we are currently using
shared_ptr<SLE>.

Member functions are converted to free functions, the SLECache is an
explicit parameter, one line convenience functions are removed to
streamline the interface. Some callers are changed to use <SLE const>
instead of <SLE>

SLECache:
* Moved to its own header file

RippleState:
* Remove unused functions
* Store the SLE as const
* Simplify callers

AccountState:
* Remove unused members
* Simplify existing members

Ledger:
* Replace writeBack with insert and update
* Remove unused functions
* Remove LedgerStateParams
* Move getLastFullLedger to Application
* add entryCacheI, exists, fetch, erase
* Use boost::optional where it makes sense
* Make member functions free functions

Free functions:
* fetch: cache-aware SLE retrieval
* forEachItem, forEachItemAfter
* (various)
This commit is contained in:
Vinnie Falco
2015-06-05 07:25:45 -07:00
parent 454d2f8c45
commit babaac9305
45 changed files with 1224 additions and 1129 deletions

View File

@@ -18,6 +18,7 @@
//==============================================================================
#include <BeastConfig.h>
#include <ripple/app/main/Application.h>
#include <ripple/protocol/Indexes.h>
namespace ripple {
@@ -62,7 +63,8 @@ Json::Value doAccountInfo (RPC::Context& context)
return jvAccepted;
AccountState::pointer asAccepted =
context.netOps.getAccountState (ledger, naAccount);
getAccountState(*ledger, naAccount,
getApp().getSLECache());
if (asAccepted)
{
@@ -71,7 +73,8 @@ Json::Value doAccountInfo (RPC::Context& context)
// See if there's a SignerEntries for this account.
Account const account = naAccount.getAccountID ();
uint256 const signerListIndex = getSignerListIndex (account);
SLE::pointer signerList = ledger->getSLEi (signerListIndex);
auto const signerList = fetch(*ledger, signerListIndex,
getApp().getSLECache());
if (signerList)
{

View File

@@ -18,6 +18,7 @@
//==============================================================================
#include <BeastConfig.h>
#include <ripple/app/main/Application.h>
#include <ripple/rpc/impl/Tuning.h>
#include <ripple/app/paths/RippleState.h>
@@ -100,7 +101,8 @@ Json::Value doAccountLines (RPC::Context& context)
return result;
}
if (! ledger->hasAccount (rippleAddress))
if (! ledger->exists(getAccountRootIndex(
rippleAddress.getAccountID())))
return rpcError (rpcACT_NOT_FOUND);
std::string strPeer (params.isMember (jss::peer)
@@ -166,7 +168,8 @@ Json::Value doAccountLines (RPC::Context& context)
return RPC::expected_field_error (jss::marker, "string");
startAfter.SetHex (marker.asString ());
SLE::pointer sleLine (ledger->getSLEi (startAfter));
auto const sleLine = fetch(*ledger, startAfter,
getApp().getSLECache());
if (sleLine == nullptr || sleLine->getType () != ltRIPPLE_STATE)
return rpcError (rpcINVALID_PARAMS);
@@ -179,7 +182,7 @@ Json::Value doAccountLines (RPC::Context& context)
return rpcError (rpcINVALID_PARAMS);
// Caller provided the first line (startAfter), add it as first result
auto const line (RippleState::makeItem (raAccount, sleLine));
auto const line = RippleState::makeItem (raAccount, sleLine);
if (line == nullptr)
return rpcError (rpcINVALID_PARAMS);
@@ -193,10 +196,12 @@ Json::Value doAccountLines (RPC::Context& context)
visitData.items.reserve (++reserve);
}
if (! ledger->visitAccountItems (raAccount, startAfter, startHint, reserve,
[&visitData](SLE::ref sleCur)
if (! forEachItemAfter(*ledger, raAccount, getApp().getSLECache(),
startAfter, startHint, reserve,
[&visitData](std::shared_ptr<SLE const> const& sleCur)
{
auto const line (RippleState::makeItem (visitData.accountID, sleCur));
auto const line =
RippleState::makeItem (visitData.accountID, sleCur);
if (line != nullptr &&
(! visitData.rippleAddressPeer.isValid () ||
visitData.raPeerAccount == line->getAccountIDPeer ()))
@@ -216,7 +221,7 @@ Json::Value doAccountLines (RPC::Context& context)
result[jss::limit] = limit;
RippleState::pointer line (visitData.items.back ());
result[jss::marker] = to_string (line->peekSLE ().getIndex ());
result[jss::marker] = to_string (line->key());
visitData.items.pop_back ();
}

View File

@@ -68,7 +68,8 @@ Json::Value doAccountObjects (RPC::Context& context)
}
}
if (! ledger->hasAccount (raAccount))
if (! ledger->exists(getAccountRootIndex(
raAccount.getAccountID())))
return rpcError (rpcACT_NOT_FOUND);
auto type = ltINVALID;

View File

@@ -18,6 +18,7 @@
//==============================================================================
#include <BeastConfig.h>
#include <ripple/app/main/Application.h>
#include <ripple/rpc/impl/Tuning.h>
namespace ripple {
@@ -62,7 +63,8 @@ Json::Value doAccountOffers (RPC::Context& context)
if (bIndex)
result[jss::account_index] = iIndex;
if (! ledger->hasAccount (rippleAddress))
if (! ledger->exists(getAccountRootIndex(
rippleAddress.getAccountID())))
return rpcError (rpcACT_NOT_FOUND);
unsigned int limit;
@@ -88,7 +90,7 @@ Json::Value doAccountOffers (RPC::Context& context)
Account const& raAccount (rippleAddress.getAccountID ());
Json::Value& jsonOffers (result[jss::offers] = Json::arrayValue);
std::vector <SLE::pointer> offers;
std::vector <std::shared_ptr<SLE const>> offers;
unsigned int reserve (limit);
uint256 startAfter;
std::uint64_t startHint;
@@ -103,7 +105,8 @@ Json::Value doAccountOffers (RPC::Context& context)
return RPC::expected_field_error (jss::marker, "string");
startAfter.SetHex (marker.asString ());
SLE::pointer sleOffer (ledger->getSLEi (startAfter));
auto const sleOffer = fetch (*ledger, startAfter,
getApp().getSLECache());
if (sleOffer == nullptr ||
sleOffer->getType () != ltOFFER ||
@@ -130,8 +133,9 @@ Json::Value doAccountOffers (RPC::Context& context)
offers.reserve (++reserve);
}
if (! ledger->visitAccountItems (raAccount, startAfter, startHint, reserve,
[&offers](SLE::ref offer)
if (! forEachItemAfter(*ledger, raAccount, getApp().getSLECache(),
startAfter, startHint, reserve,
[&offers](std::shared_ptr<SLE const> const& offer)
{
if (offer->getType () == ltOFFER)
{

View File

@@ -18,6 +18,7 @@
//==============================================================================
#include <BeastConfig.h>
#include <ripple/app/main/Application.h>
#include <ripple/protocol/Indexes.h>
namespace ripple {
@@ -207,7 +208,8 @@ Json::Value doLedgerEntry (RPC::Context& context)
if (uNodeIndex.isNonZero ())
{
auto sleNode = lpLedger->getSLEi(uNodeIndex);
auto const sleNode = fetch(*lpLedger, uNodeIndex,
getApp().getSLECache());
if (context.params.isMember(jss::binary))
bNodeBinary = context.params[jss::binary].asBool();

View File

@@ -63,27 +63,30 @@ Json::Value doLedgerRequest (RPC::Context& context)
if (ledgerIndex >= ledger->getLedgerSeq())
return RPC::make_param_error("Ledger index too large");
auto const j =
deprecatedLogs().journal("RPCHandler");
// Try to get the hash of the desired ledger from the validated ledger
ledgerHash = ledger->getLedgerHash (ledgerIndex);
if (ledgerHash == zero)
auto ledgerHash = hashOfSeq(*ledger, ledgerIndex,
getApp().getSLECache(), j);
if (! ledgerHash)
{
// Find a ledger more likely to have the hash of the desired ledger
auto refIndex = (ledgerIndex + 255) & (~255);
auto refHash = ledger->getLedgerHash (refIndex);
assert (refHash.isNonZero ());
auto refHash = hashOfSeq(*ledger, refIndex,
getApp().getSLECache(), j);
assert(refHash);
ledger = ledgerMaster.getLedgerByHash (refHash);
if (!ledger)
ledger = ledgerMaster.getLedgerByHash (*refHash);
if (! ledger)
{
// We don't have the ledger we need to figure out which ledger
// they want. Try to get it.
if (auto il = getApp().getInboundLedgers().acquire (
refHash, refIndex, InboundLedger::fcGENERIC))
*refHash, refIndex, InboundLedger::fcGENERIC))
return getJson (LedgerFill (*il));
if (auto il = getApp().getInboundLedgers().find (refHash))
if (auto il = getApp().getInboundLedgers().find (*refHash))
{
Json::Value jvResult = il->getJson (0);
@@ -95,8 +98,11 @@ Json::Value doLedgerRequest (RPC::Context& context)
return Json::Value();
}
ledgerHash = ledger->getLedgerHash (ledgerIndex);
assert (ledgerHash.isNonZero ());
ledgerHash = hashOfSeq(*ledger, ledgerIndex,
getApp().getSLECache(), j);
assert (ledgerHash);
if (! ledgerHash)
ledgerHash = zero; // kludge
}
}

View File

@@ -106,15 +106,17 @@ Json::Value doNoRippleCheck (RPC::Context& context)
return result;
}
AccountState::pointer accountState = ledger->getAccountState (rippleAddress);
AccountState::pointer accountState =
getAccountState(*ledger, rippleAddress,
getApp().getSLECache());
if (! accountState)
return rpcError (rpcACT_NOT_FOUND);
std::uint32_t seq = accountState->peekSLE().getFieldU32 (sfSequence);
std::uint32_t seq = accountState->sle().getFieldU32 (sfSequence);
Json::Value& problems = (result["problems"] = Json::arrayValue);
bool bDefaultRipple = accountState->peekSLE().getFieldU32 (sfFlags) & lsfDefaultRipple;
bool bDefaultRipple = accountState->sle().getFieldU32 (sfFlags) & lsfDefaultRipple;
if (bDefaultRipple & ! roleGateway)
{
@@ -135,8 +137,9 @@ Json::Value doNoRippleCheck (RPC::Context& context)
auto const accountID = rippleAddress.getAccountID ();
ledger->visitAccountItems (accountID, uint256(), 0, limit,
[&](SLE::ref ownedItem)
forEachItemAfter (*ledger, accountID, getApp().getSLECache(),
uint256(), 0, limit,
[&](std::shared_ptr<SLE const> const& ownedItem)
{
if (ownedItem->getType() == ltRIPPLE_STATE)
{

View File

@@ -19,6 +19,7 @@
#include <BeastConfig.h>
#include <ripple/rpc/impl/Accounts.h>
#include <ripple/app/main/Application.h>
namespace ripple {
namespace RPC {
@@ -40,7 +41,8 @@ Json::Value accounts (
naAccount.setAccountPublic (naMasterGenerator, uIndex++);
AccountState::pointer as = netOps.getAccountState (lrLedger, naAccount);
AccountState::pointer as =
getAccountState (*lrLedger, naAccount, getApp().getSLECache());
if (as)
{

View File

@@ -18,6 +18,7 @@
//==============================================================================
#include <ripple/rpc/impl/GetAccountObjects.h>
#include <ripple/app/main/Application.h>
#include <ripple/protocol/Indexes.h>
#include <ripple/protocol/JsonFields.h>
@@ -38,8 +39,9 @@ getAccountObjects (Ledger const& ledger, Account const& account,
found = true;
}
auto dir = ledger.getDirNode (dirIndex);
if (dir == nullptr)
auto dir = fetch(ledger, dirIndex,
getApp().getSLECache(), ltDIR_NODE);
if (! dir)
return false;
std::uint32_t i = 0;
@@ -60,7 +62,8 @@ getAccountObjects (Ledger const& ledger, Account const& account,
for (; iter != entries.end (); ++iter)
{
auto const sleNode = ledger.getSLEi (*iter);
auto const sleNode = fetch(ledger, *iter,
getApp().getSLECache());
if (type == ltINVALID || sleNode->getType () == type)
{
jvObjects.append (sleNode->getJson (0));
@@ -84,9 +87,10 @@ getAccountObjects (Ledger const& ledger, Account const& account,
if (nodeIndex == 0)
return true;
dirIndex = getDirNodeIndex (rootDirIndex, nodeIndex);
dir = ledger.getDirNode (dirIndex);
if (dir == nullptr)
dirIndex = getDirNodeIndex (rootDirIndex, nodeIndex);
dir = fetch(ledger, dirIndex,
getApp().getSLECache(), ltDIR_NODE);
if (! dir)
return true;
if (i == limit)

View File

@@ -19,6 +19,7 @@
#include <BeastConfig.h>
#include <ripple/app/ledger/LedgerFees.h>
#include <ripple/app/main/Application.h>
#include <ripple/rpc/impl/TransactionSign.h>
#include <ripple/rpc/impl/KeypairForSignature.h>
#include <ripple/app/paths/FindPaths.h>
@@ -111,7 +112,8 @@ void TxnSignApiFacade::snapshotAccountState (RippleAddress const& accountID)
ledger_ = netOPs_->getCurrentLedger ();
accountID_ = accountID;
accountState_ = netOPs_->getAccountState (ledger_, accountID_);
accountState_ = getAccountState (
*ledger_, accountID_, getApp().getSLECache());
}
bool TxnSignApiFacade::isValidAccount () const
@@ -127,7 +129,7 @@ std::uint32_t TxnSignApiFacade::getSeq () const
if (!ledger_) // Unit testing.
return 0;
return accountState_->getSeq ();
return accountState_->sle().getFieldU32(sfSequence);
}
Transaction::pointer TxnSignApiFacade::processTransaction (
@@ -192,11 +194,8 @@ bool TxnSignApiFacade::hasAccountRoot () const
{
if (!netOPs_) // Unit testing.
return true;
SLE::pointer const sleAccountRoot =
ledger_->getSLEi(getAccountRootIndex(accountID_));
return static_cast <bool> (sleAccountRoot);
return ledger_->exists(
getAccountRootIndex(accountID_));
}
error_code_i acctMatchesPubKey (
@@ -217,7 +216,7 @@ error_code_i acctMatchesPubKey (
}
// If we *can* get to the accountRoot, check for MASTER_DISABLED
STLedgerEntry const& sle = accountState->peekSLE ();
auto const& sle = accountState->sle();
if (isMasterKey)
{
if (sle.isFlag(lsfDisableMaster))
@@ -248,11 +247,13 @@ error_code_i TxnSignApiFacade::multiAcctMatchesPubKey (
RippleAddress const& publicKey) const
{
AccountState::pointer accountState;
// VFALCO Do we need to check netOPs_?
if (netOPs_ && ledger_)
// If it's available, get the AccountState for the multi-signer's
// accountID. It's okay if the AccountState is not available,
// since they might be signing with a phantom (unfunded) account.
accountState = netOPs_->getAccountState (ledger_, accountID);
accountState = getAccountState (
*ledger_, accountID, getApp().getSLECache());
return acctMatchesPubKey (accountState, accountID, publicKey);
}