mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-26 05:55:51 +00:00
Allow a ledger close to be replayed for debug. Syntax: rippled -a --load --ledger=<seq> --replay
This commit is contained in:
@@ -14,7 +14,8 @@ DatabaseCon::DatabaseCon (const std::string& strName, const char* initStrings[],
|
|||||||
// responsibility to pass in the path. Add a member function to Application
|
// responsibility to pass in the path. Add a member function to Application
|
||||||
// or Config to compute this path.
|
// or Config to compute this path.
|
||||||
//
|
//
|
||||||
boost::filesystem::path pPath = (theConfig.RUN_STANDALONE && (theConfig.START_UP != Config::LOAD))
|
boost::filesystem::path pPath = (theConfig.RUN_STANDALONE &&
|
||||||
|
((theConfig.START_UP != Config::LOAD) && (theConfig.START_UP != Config::REPLAY)))
|
||||||
? "" // Use temporary files.
|
? "" // Use temporary files.
|
||||||
: (theConfig.DATA_DIR / strName); // Use regular db files.
|
: (theConfig.DATA_DIR / strName); // Use regular db files.
|
||||||
|
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ public:
|
|||||||
FRESH,
|
FRESH,
|
||||||
NORMAL,
|
NORMAL,
|
||||||
LOAD,
|
LOAD,
|
||||||
|
REPLAY,
|
||||||
NETWORK
|
NETWORK
|
||||||
};
|
};
|
||||||
StartUpType START_UP;
|
StartUpType START_UP;
|
||||||
|
|||||||
@@ -1132,6 +1132,10 @@ Json::Value RPCHandler::doAccountLines (Json::Value params, LoadType* loadType,
|
|||||||
jPeer["limit_peer"] = saLimitPeer.getText ();
|
jPeer["limit_peer"] = saLimitPeer.getText ();
|
||||||
jPeer["quality_in"] = static_cast<Json::UInt> (line->getQualityIn ());
|
jPeer["quality_in"] = static_cast<Json::UInt> (line->getQualityIn ());
|
||||||
jPeer["quality_out"] = static_cast<Json::UInt> (line->getQualityOut ());
|
jPeer["quality_out"] = static_cast<Json::UInt> (line->getQualityOut ());
|
||||||
|
if (line->getAuth())
|
||||||
|
jPeer["authorized"] = true;
|
||||||
|
if (line->getAuthPeer())
|
||||||
|
jPeer["peer_authorized"] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3681,7 +3685,7 @@ Json::Value RPCHandler::doCommand (const Json::Value& params, int iRole, LoadTyp
|
|||||||
return rpcError (rpcNO_NETWORK);
|
return rpcError (rpcNO_NETWORK);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((commandsA[i].iOptions & optCurrent) && (getApp().getLedgerMaster().getValidatedLedgerAge() > 120))
|
if (!theConfig.RUN_STANDALONE && (commandsA[i].iOptions & optCurrent) && (getApp().getLedgerMaster().getValidatedLedgerAge() > 120))
|
||||||
{
|
{
|
||||||
return rpcError (rpcNO_CURRENT);
|
return rpcError (rpcNO_CURRENT);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -281,7 +281,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
void updateTables ();
|
void updateTables ();
|
||||||
void startNewLedger ();
|
void startNewLedger ();
|
||||||
bool loadOldLedger (const std::string&);
|
bool loadOldLedger (const std::string&, bool);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
boost::asio::io_service mIOService;
|
boost::asio::io_service mIOService;
|
||||||
@@ -478,11 +478,11 @@ void ApplicationImp::setup ()
|
|||||||
|
|
||||||
startNewLedger ();
|
startNewLedger ();
|
||||||
}
|
}
|
||||||
else if (theConfig.START_UP == Config::LOAD)
|
else if ((theConfig.START_UP == Config::LOAD) || (theConfig.START_UP == Config::REPLAY))
|
||||||
{
|
{
|
||||||
WriteLog (lsINFO, Application) << "Loading specified Ledger";
|
WriteLog (lsINFO, Application) << "Loading specified Ledger";
|
||||||
|
|
||||||
if (!loadOldLedger (theConfig.START_LEDGER))
|
if (!loadOldLedger (theConfig.START_LEDGER, theConfig.START_UP == Config::REPLAY))
|
||||||
{
|
{
|
||||||
getApp().stop ();
|
getApp().stop ();
|
||||||
exit (-1);
|
exit (-1);
|
||||||
@@ -733,11 +733,11 @@ void ApplicationImp::startNewLedger ()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ApplicationImp::loadOldLedger (const std::string& l)
|
bool ApplicationImp::loadOldLedger (const std::string& l, bool bReplay)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Ledger::pointer loadLedger;
|
Ledger::pointer loadLedger, replayLedger;
|
||||||
|
|
||||||
if (l.empty () || (l == "latest"))
|
if (l.empty () || (l == "latest"))
|
||||||
loadLedger = Ledger::getLastFullLedger ();
|
loadLedger = Ledger::getLastFullLedger ();
|
||||||
@@ -757,6 +757,18 @@ bool ApplicationImp::loadOldLedger (const std::string& l)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bReplay)
|
||||||
|
{ // Replay a ledger close with same prior ledger and transactions
|
||||||
|
replayLedger = loadLedger; // this ledger holds the transactions we want to replay
|
||||||
|
loadLedger = Ledger::loadByIndex (replayLedger->getLedgerSeq() - 1); // this is the prior ledger
|
||||||
|
if (!loadLedger || (replayLedger->getParentHash() != loadLedger->getHash()))
|
||||||
|
{
|
||||||
|
WriteLog (lsFATAL, Application) << "Replay ledger missing/damaged";
|
||||||
|
assert (false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
loadLedger->setClosed ();
|
loadLedger->setClosed ();
|
||||||
|
|
||||||
WriteLog (lsINFO, Application) << "Loading ledger " << loadLedger->getHash () << " seq:" << loadLedger->getLedgerSeq ();
|
WriteLog (lsINFO, Application) << "Loading ledger " << loadLedger->getHash () << " seq:" << loadLedger->getLedgerSeq ();
|
||||||
@@ -785,6 +797,24 @@ bool ApplicationImp::loadOldLedger (const std::string& l)
|
|||||||
Ledger::pointer openLedger = boost::make_shared<Ledger> (false, boost::ref (*loadLedger));
|
Ledger::pointer openLedger = boost::make_shared<Ledger> (false, boost::ref (*loadLedger));
|
||||||
mLedgerMaster.switchLedgers (loadLedger, openLedger);
|
mLedgerMaster.switchLedgers (loadLedger, openLedger);
|
||||||
mNetOps.setLastCloseTime (loadLedger->getCloseTimeNC ());
|
mNetOps.setLastCloseTime (loadLedger->getCloseTimeNC ());
|
||||||
|
|
||||||
|
if (bReplay)
|
||||||
|
{ // inject transaction from replayLedger into consensus set
|
||||||
|
SHAMap::ref txns = replayLedger->peekTransactionMap();
|
||||||
|
Ledger::ref cur = getLedgerMaster().getCurrentLedger();
|
||||||
|
|
||||||
|
for (SHAMapItem::pointer it = txns->peekFirstItem(); it != nullptr; it = txns->peekNextItem(it->getTag()))
|
||||||
|
{
|
||||||
|
Transaction::pointer txn = replayLedger->getTransaction(it->getTag());
|
||||||
|
WriteLog (lsINFO, Application) << txn->getJson(0);
|
||||||
|
Serializer s;
|
||||||
|
txn->getSTransaction()->add(s);
|
||||||
|
if (!cur->addTransaction(it->getTag(), s))
|
||||||
|
{
|
||||||
|
WriteLog (lsWARNING, Application) << "Unable to add transaction " << it->getTag();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (SHAMapMissingNode&)
|
catch (SHAMapMissingNode&)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -237,6 +237,7 @@ int rippleMain (int argc, char** argv)
|
|||||||
("quiet,q", "Reduce diagnotics.")
|
("quiet,q", "Reduce diagnotics.")
|
||||||
("verbose,v", "Verbose logging.")
|
("verbose,v", "Verbose logging.")
|
||||||
("load", "Load the current ledger from the local DB.")
|
("load", "Load the current ledger from the local DB.")
|
||||||
|
("replay","Replay a ledger close.")
|
||||||
("ledger", po::value<std::string> (), "Load the specified ledger and start from .")
|
("ledger", po::value<std::string> (), "Load the specified ledger and start from .")
|
||||||
("start", "Start from a fresh Ledger.")
|
("start", "Start from a fresh Ledger.")
|
||||||
("net", "Get the initial ledger from the network.")
|
("net", "Get the initial ledger from the network.")
|
||||||
@@ -356,6 +357,9 @@ int rippleMain (int argc, char** argv)
|
|||||||
if (vm.count ("ledger"))
|
if (vm.count ("ledger"))
|
||||||
{
|
{
|
||||||
theConfig.START_LEDGER = vm["ledger"].as<std::string> ();
|
theConfig.START_LEDGER = vm["ledger"].as<std::string> ();
|
||||||
|
if (vm.count("replay"))
|
||||||
|
theConfig.START_UP = Config::REPLAY;
|
||||||
|
else
|
||||||
theConfig.START_UP = Config::LOAD;
|
theConfig.START_UP = Config::LOAD;
|
||||||
}
|
}
|
||||||
else if (vm.count ("load"))
|
else if (vm.count ("load"))
|
||||||
|
|||||||
Reference in New Issue
Block a user