Allow a ledger close to be replayed for debug. Syntax: rippled -a --load --ledger=<seq> --replay

This commit is contained in:
JoelKatz
2013-07-17 03:31:23 -07:00
parent 00b0663e50
commit 65d46752df
5 changed files with 48 additions and 8 deletions

View File

@@ -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.

View File

@@ -101,6 +101,7 @@ public:
FRESH, FRESH,
NORMAL, NORMAL,
LOAD, LOAD,
REPLAY,
NETWORK NETWORK
}; };
StartUpType START_UP; StartUpType START_UP;

View File

@@ -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);
} }

View File

@@ -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&)
{ {

View File

@@ -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"))