diff --git a/Builds/VisualStudio2012/RippleD.vcxproj.filters b/Builds/VisualStudio2012/RippleD.vcxproj.filters
index fd67ab9a4..236c04c78 100644
--- a/Builds/VisualStudio2012/RippleD.vcxproj.filters
+++ b/Builds/VisualStudio2012/RippleD.vcxproj.filters
@@ -822,6 +822,18 @@
[1] Ripple\ripple_app
+
+ 1. Modules\ripple_app
+
+
+ 1. Modules\ripple_app
+
+
+ 1. Modules\ripple_app
+
+
+ 1. Modules\ripple_app
+
diff --git a/modules/ripple_data/protocol/ripple_SerializedObject.cpp b/modules/ripple_data/protocol/ripple_SerializedObject.cpp
index 587882ac0..7581afb12 100644
--- a/modules/ripple_data/protocol/ripple_SerializedObject.cpp
+++ b/modules/ripple_data/protocol/ripple_SerializedObject.cpp
@@ -379,7 +379,10 @@ bool STObject::isEquivalent (const SerializedType& t) const
const STObject* v = dynamic_cast (&t);
if (!v)
+ {
+ WriteLog (lsDEBUG, STObject) << "notEquiv " << getFullText() << " not object";
return false;
+ }
boost::ptr_vector::const_iterator it1 = mData.begin (), end1 = mData.end ();
boost::ptr_vector::const_iterator it2 = v->mData.begin (), end2 = v->mData.end ();
@@ -387,7 +390,19 @@ bool STObject::isEquivalent (const SerializedType& t) const
while ((it1 != end1) && (it2 != end2))
{
if ((it1->getSType () != it2->getSType ()) || !it1->isEquivalent (*it2))
+ {
+ if (it1->getSType () != it2->getSType ())
+ {
+ WriteLog (lsDEBUG, STObject) << "notEquiv type " << it1->getFullText() << " != "
+ << it2->getFullText();
+ }
+ else
+ {
+ WriteLog (lsDEBUG, STObject) << "notEquiv " << it1->getFullText() << " != "
+ << it2->getFullText();
+ }
return false;
+ }
++it1;
++it2;
@@ -1164,7 +1179,10 @@ bool STArray::isEquivalent (const SerializedType& t) const
const STArray* v = dynamic_cast (&t);
if (!v)
+ {
+ WriteLog (lsDEBUG, STObject) << "notEquiv " << getFullText() << " not array";
return false;
+ }
return value == v->value;
}
diff --git a/modules/ripple_data/protocol/ripple_SerializedTypes.cpp b/modules/ripple_data/protocol/ripple_SerializedTypes.cpp
index aa92e9bd6..b60ac1908 100644
--- a/modules/ripple_data/protocol/ripple_SerializedTypes.cpp
+++ b/modules/ripple_data/protocol/ripple_SerializedTypes.cpp
@@ -22,6 +22,14 @@ SerializedType& SerializedType::operator= (const SerializedType& t)
return *this;
}
+bool SerializedType::isEquivalent (const SerializedType& t) const
+{
+ assert (getSType () == STI_NOTPRESENT);
+ if (t.getSType () == STI_NOTPRESENT)
+ return true;
+ WriteLog (lsDEBUG, SerializedType) << "notEquiv " << getFullText() << " not STI_NOTPRESENT";
+ return false;
+}
void STPathSet::printDebug ()
{
diff --git a/modules/ripple_data/protocol/ripple_SerializedTypes.h b/modules/ripple_data/protocol/ripple_SerializedTypes.h
index 2ebcfdb43..2c01a4f47 100644
--- a/modules/ripple_data/protocol/ripple_SerializedTypes.h
+++ b/modules/ripple_data/protocol/ripple_SerializedTypes.h
@@ -113,11 +113,7 @@ public:
;
}
- virtual bool isEquivalent (const SerializedType& t) const
- {
- assert (getSType () == STI_NOTPRESENT);
- return t.getSType () == STI_NOTPRESENT;
- }
+ virtual bool isEquivalent (const SerializedType& t) const;
void addFieldID (Serializer& s) const
{
diff --git a/src/cpp/ripple/LedgerMaster.cpp b/src/cpp/ripple/LedgerMaster.cpp
index 9069dbd47..a26dfb458 100644
--- a/src/cpp/ripple/LedgerMaster.cpp
+++ b/src/cpp/ripple/LedgerMaster.cpp
@@ -25,6 +25,7 @@ Ledger::ref LedgerMaster::getCurrentSnapshot ()
int LedgerMaster::getValidatedLedgerAge ()
{
+ boost::recursive_mutex::scoped_lock ml (mLock);
if (!mValidLedger)
{
WriteLog (lsDEBUG, LedgerMaster) << "No validated ledger";
@@ -39,6 +40,27 @@ int LedgerMaster::getValidatedLedgerAge ()
return static_cast (ret);
}
+bool LedgerMaster::isCaughtUp(std::string& reason)
+{
+ if (getValidatedLedgerAge() > 180)
+ {
+ reason = "No recently-validated ledger";
+ return false;
+ }
+ boost::recursive_mutex::scoped_lock ml (mLock);
+ if (!mValidLedger || !mPubLedger)
+ {
+ reason = "No published ledger";
+ return false;
+ }
+ if (mValidLedger->getLedgerSeq() > (mPubLedger->getLedgerSeq() + 3))
+ {
+ reason = "Published ledger lags validated ledger";
+ return false;
+ }
+ return true;
+}
+
void LedgerMaster::addHeldTransaction (Transaction::ref transaction)
{
// returns true if transaction was added
diff --git a/src/cpp/ripple/LedgerMaster.h b/src/cpp/ripple/LedgerMaster.h
index ad4fc44d6..4df10d0eb 100644
--- a/src/cpp/ripple/LedgerMaster.h
+++ b/src/cpp/ripple/LedgerMaster.h
@@ -64,6 +64,7 @@ public:
return mPubLedger;
}
int getValidatedLedgerAge ();
+ bool isCaughtUp(std::string& reason);
TER doTransaction (SerializedTransaction::ref txn, TransactionEngineParams params, bool& didApply);
diff --git a/src/cpp/ripple/NetworkOPs.cpp b/src/cpp/ripple/NetworkOPs.cpp
index 351d98181..d48a971d3 100644
--- a/src/cpp/ripple/NetworkOPs.cpp
+++ b/src/cpp/ripple/NetworkOPs.cpp
@@ -246,14 +246,14 @@ void NetworkOPs::runTransactionQueue ()
if (isTemMalformed (r)) // malformed, cache bad
getApp().getHashRouter ().setFlag (txn->getID (), SF_BAD);
- else if (isTelLocal (r) || isTerRetry (r)) // can be retried
- getApp().getHashRouter ().setFlag (txn->getID (), SF_RETRY);
+// else if (isTelLocal (r) || isTerRetry (r)) // can be retried
+// getApp().getHashRouter ().setFlag (txn->getID (), SF_RETRY);
if (isTerRetry (r))
{
// transaction should be held
- WriteLog (lsDEBUG, NetworkOPs) << "Transaction should be held: " << r;
+ WriteLog (lsDEBUG, NetworkOPs) << "QTransaction should be held: " << r;
dbtx->setStatus (HELD);
getApp().getMasterTransaction ().canonicalize (dbtx, true);
mLedgerMaster->addHeldTransaction (dbtx);
@@ -261,27 +261,29 @@ void NetworkOPs::runTransactionQueue ()
else if (r == tefPAST_SEQ)
{
// duplicate or conflict
- WriteLog (lsINFO, NetworkOPs) << "Transaction is obsolete";
+ WriteLog (lsINFO, NetworkOPs) << "QTransaction is obsolete";
dbtx->setStatus (OBSOLETE);
}
else if (r == tesSUCCESS)
{
- WriteLog (lsINFO, NetworkOPs) << "Transaction is now included in open ledger";
+ WriteLog (lsINFO, NetworkOPs) << "QTransaction is now included in open ledger";
dbtx->setStatus (INCLUDED);
getApp().getMasterTransaction ().canonicalize (dbtx, true);
}
else
{
- WriteLog (lsDEBUG, NetworkOPs) << "Status other than success " << r;
+ WriteLog (lsDEBUG, NetworkOPs) << "QStatus other than success " << r;
dbtx->setStatus (INVALID);
}
- if (didApply || (mMode != omFULL))
+// if (didApply || (mMode != omFULL))
+ if (didApply)
{
std::set peers;
if (getApp().getHashRouter ().swapSet (txn->getID (), peers, SF_RELAYED))
{
+ WriteLog (lsDEBUG, NetworkOPs) << "relaying";
protocol::TMTransaction tx;
Serializer s;
dbtx->getSTransaction ()->add (s);
@@ -292,6 +294,8 @@ void NetworkOPs::runTransactionQueue ()
PackedMessage::pointer packet = boost::make_shared (tx, protocol::mtTRANSACTION);
getApp().getPeers ().relayMessageBut (peers, packet);
}
+ else
+ WriteLog(lsDEBUG, NetworkOPs) << "recently relayed";
}
txn->doCallbacks (r);
@@ -339,8 +343,8 @@ Transaction::pointer NetworkOPs::processTransaction (Transaction::pointer trans,
if (isTemMalformed (r)) // malformed, cache bad
getApp().getHashRouter ().setFlag (trans->getID (), SF_BAD);
- else if (isTelLocal (r) || isTerRetry (r)) // can be retried
- getApp().getHashRouter ().setFlag (trans->getID (), SF_RETRY);
+// else if (isTelLocal (r) || isTerRetry (r)) // can be retried
+// getApp().getHashRouter ().setFlag (trans->getID (), SF_RETRY);
#ifdef BEAST_DEBUG
diff --git a/src/cpp/ripple/RPCHandler.cpp b/src/cpp/ripple/RPCHandler.cpp
index 644e17b46..fd69eb4e1 100644
--- a/src/cpp/ripple/RPCHandler.cpp
+++ b/src/cpp/ripple/RPCHandler.cpp
@@ -3680,9 +3680,7 @@ Json::Value RPCHandler::doCommand (const Json::Value& params, int iRole, LoadTyp
return rpcError (rpcNO_NETWORK);
}
- // XXX Should verify we have a current ledger.
-
- if ((commandsA[i].iOptions & optCurrent) && false)
+ if ((commandsA[i].iOptions & optCurrent) && (getApp().getLedgerMaster().getValidatedLedgerAge() > 60))
{
return rpcError (rpcNO_CURRENT);
}
diff --git a/src/cpp/ripple/TransactionEngine.cpp b/src/cpp/ripple/TransactionEngine.cpp
index ab1b70db6..687c220a5 100644
--- a/src/cpp/ripple/TransactionEngine.cpp
+++ b/src/cpp/ripple/TransactionEngine.cpp
@@ -146,7 +146,7 @@ TER TransactionEngine::applyTransaction (const SerializedTransaction& txn, Trans
}
}
else
- WriteLog (lsDEBUG, TransactionEngine) << "Not applying transaction";
+ WriteLog (lsDEBUG, TransactionEngine) << "Not applying transaction " << txID;
if (didApply)
{
diff --git a/src/cpp/ripple/ripple_Application.cpp b/src/cpp/ripple/ripple_Application.cpp
index f6e099765..ee5c9b0e3 100644
--- a/src/cpp/ripple/ripple_Application.cpp
+++ b/src/cpp/ripple/ripple_Application.cpp
@@ -843,14 +843,6 @@ bool serverOkay (std::string& reason)
if (!theConfig.ELB_SUPPORT)
return true;
- /*
- if (!theApp)
- {
- reason = "Server has not started";
- return false;
- }
- */
-
if (getApp().isShutdown ())
{
reason = "Server is shutting down";
@@ -869,6 +861,9 @@ bool serverOkay (std::string& reason)
return false;
}
+ if (!getApp().getLedgerMaster().isCaughtUp(reason))
+ return false;
+
if (getApp().getFeeTrack ().isLoaded ())
{
reason = "Too much load";
diff --git a/src/cpp/ripple/ripple_IHashRouter.h b/src/cpp/ripple/ripple_IHashRouter.h
index 55b1cd8af..48f06cc9f 100644
--- a/src/cpp/ripple/ripple_IHashRouter.h
+++ b/src/cpp/ripple/ripple_IHashRouter.h
@@ -31,7 +31,7 @@ public:
//
static inline int getDefaultHoldTime ()
{
- return 120;
+ return 300;
}
// VFALCO TODO rename the parameter to entryHoldTimeInSeconds
diff --git a/src/cpp/ripple/ripple_LoadManager.cpp b/src/cpp/ripple/ripple_LoadManager.cpp
index e9aefaf02..df4ec6698 100644
--- a/src/cpp/ripple/ripple_LoadManager.cpp
+++ b/src/cpp/ripple/ripple_LoadManager.cpp
@@ -195,6 +195,8 @@ private:
// We do it this way in case we want to add exponential decay later
int now = UptimeTimer::getInstance ().getElapsedSeconds ();
+
+ boost::mutex::scoped_lock sl (mLock);
canonicalize (source, now);
source.mBalance += credits;
@@ -204,7 +206,8 @@ private:
if (source.isPrivileged ()) // privileged sources never warn/cutoff
return false;
- if ((source.mBalance >= mDebitLimit) && (source.mLastWarning == now)) // no need to warn
+ if ( (source.mBalance >= mDebitWarn) ||
+ ((source.mBalance >= mDebitLimit) && (source.mLastWarning == now)))
return false;
return true;
diff --git a/src/cpp/ripple/ripple_Peer.cpp b/src/cpp/ripple/ripple_Peer.cpp
index 401d496c7..bf8394c91 100644
--- a/src/cpp/ripple/ripple_Peer.cpp
+++ b/src/cpp/ripple/ripple_Peer.cpp
@@ -197,7 +197,7 @@ PeerImp::PeerImp (boost::asio::io_service& io_service, boost::asio::ssl::context
mCluster (false),
mPeerId (peerID),
mPrivate (false),
- mLoad (""),
+ mLoad (std::string()),
mMinLedger (0),
mMaxLedger (0),
mSocketSsl (io_service, ctx),
@@ -978,6 +978,8 @@ void PeerImp::recvHello (protocol::TMHello& packet)
{
mCluster = true;
mLoad.setPrivileged ();
+ if (!mNodeName.empty())
+ mLoad.rename (mNodeName);
WriteLog (lsINFO, Peer) << "Cluster connection to \"" << (mNodeName.empty () ? getIP () : mNodeName)
<< "\" established";
}
@@ -1104,10 +1106,11 @@ void PeerImp::recvTransaction (protocol::TMTransaction& packet, ScopedLock& Mast
Serializer s (packet.rawtransaction ());
SerializerIterator sit (s);
SerializedTransaction::pointer stx = boost::make_shared (boost::ref (sit));
+ uint256 txID = stx->getTransactionID();
int flags;
- if (! getApp().getHashRouter ().addSuppressionPeer (stx->getTransactionID (), mPeerId, flags))
+ if (! getApp().getHashRouter ().addSuppressionPeer (txID, mPeerId, flags))
{
// we have seen this transaction recently
if (isSetBit (flags, SF_BAD))
@@ -1120,12 +1123,24 @@ void PeerImp::recvTransaction (protocol::TMTransaction& packet, ScopedLock& Mast
return;
}
- WriteLog (lsDEBUG, Peer) << "Got new transaction from peer";
+ if (getApp().getMasterTransaction().fetch(txID, true))
+ {
+ WriteLog (lsDEBUG, Peer) << "Peer " << getDisplayName() << " send old TX " << txID;
+ applyLoadCharge (LT_InvalidRequest);
+ return;
+ }
+
+ WriteLog (lsDEBUG, Peer) << "Got new transaction from peer " << getDisplayName () << " : " << txID;
if (mCluster)
flags |= SF_TRUSTED | SF_SIGGOOD;
- getApp().getJobQueue ().addJob (jtTRANSACTION, "recvTransction->checkTransaction",
+ if (getApp().getJobQueue().getJobCount(jtTRANSACTION) > 100)
+ WriteLog(lsINFO, Peer) << "Transaction queue is full";
+ else if (getApp().getLedgerMaster().getValidatedLedgerAge() > 240)
+ WriteLog(lsINFO, Peer) << "No new transactions until synchronized";
+ else
+ getApp().getJobQueue ().addJob (jtTRANSACTION, "recvTransction->checkTransaction",
BIND_TYPE (&checkTransaction, P_1, flags, stx, boost::weak_ptr (shared_from_this ())));
#ifndef TRUST_NETWORK
@@ -2213,11 +2228,28 @@ void PeerImp::sendGetPeers ()
void PeerImp::applyLoadCharge (LoadType loadType)
{
+ // IMPLEMENTATION IS INCOMPLETE
+
+ // VFALCO TODO This needs to completed before open sourcing.
+
if (getApp().getLoadManager ().applyLoadCharge (mLoad, loadType))
{
- // UNIMPLEMENTED
-
- // VFALCO TODO This needs to implemented before open sourcing.
+ if (mCluster)
+ {
+ WriteLog (lsWARNING, Peer) << "aLC: " << getDisplayName() << " load from cluster";
+ }
+ else if (getApp().getLoadManager ().shouldCutoff(mLoad))
+ {
+ WriteLog (lsWARNING, Peer) << "aLC: " << getDisplayName() << " should cutoff";
+ }
+ else if (getApp().getLoadManager ().shouldWarn (mLoad))
+ {
+ WriteLog (lsWARNING, Peer) << "aLC: " << getDisplayName() << " load warning";
+ }
+ else
+ {
+ WriteLog (lsWARNING, Peer) << "aLC: " << getDisplayName() << " cannot figure out";
+ }
}
}
diff --git a/src/cpp/ripple/ripple_RippleCalc.cpp b/src/cpp/ripple/ripple_RippleCalc.cpp
index 3a54fc3c2..55fec68c5 100644
--- a/src/cpp/ripple/ripple_RippleCalc.cpp
+++ b/src/cpp/ripple/ripple_RippleCalc.cpp
@@ -49,7 +49,7 @@ TER RippleCalc::calcNodeAdvance (
TER terResult = tesSUCCESS;
- WriteLog (lsDEBUG, RippleCalc) << "calcNodeAdvance";
+ WriteLog (lsDEBUG, RippleCalc) << "calcNodeAdvance: TakerPays:" << saTakerPays << " TakerGets:" << saTakerGets;
int loopCount = 0;
@@ -478,6 +478,9 @@ TER RippleCalc::calcNodeDeliverRev (
% saOutPassAct
% saOutPlusFees);
+ if (saInPassReq > saTakerPays)
+ saInPassReq = saTakerPays;
+
if (!saInPassReq)
{
// After rounding did not want anything.
@@ -690,7 +693,7 @@ TER RippleCalc::calcNodeDeliverFwd (
STAmount saInFunded = STAmount::mulRound (saOutPassFunded, saOfrRate, saTakerPays, true); // Offer maximum in - Limited by by payout.
STAmount saInTotal = STAmount::mulRound (saInFunded, saInFeeRate, true); // Offer maximum in with fees.
STAmount saInSum = std::min (saInTotal, saInReq - saInAct - saInFees); // In limited by remaining.
- STAmount saInPassAct = STAmount::divRound (saInSum, saInFeeRate, true); // In without fees.
+ STAmount saInPassAct = std::min (saTakerPays, STAmount::divRound (saInSum, saInFeeRate, true)); // In without fees.
STAmount saOutPassMax = std::min (saOutPassFunded, STAmount::divRound (saInPassAct, saOfrRate, saTakerGets, true)); // Out limited by in remaining.
STAmount saInPassFeesMax = saInSum - saInPassAct;
@@ -789,7 +792,7 @@ TER RippleCalc::calcNodeDeliverFwd (
assert (saOutPassAct < saOutPassMax);
- saInPassAct = STAmount::mulRound (saOutPassAct, saOfrRate, saInReq, true);
+ saInPassAct = std::min (saTakerPays, STAmount::mulRound (saOutPassAct, saOfrRate, saInReq, true));
saInPassFees = std::min (saInPassFeesMax, STAmount::mulRound (saInPassAct, saInFeeRate, true));
}
@@ -2365,6 +2368,7 @@ void TransactionEngine::calcOfferBridgeNext (
{
// Offer is expired.
WriteLog (lsINFO, RippleCalc) << "calcOfferFirst: encountered expired offer";
+ musUnfundedFound.insert(uOfferIndex);
}
else
{
diff --git a/src/cpp/ripple/ripple_SHAMap.cpp b/src/cpp/ripple/ripple_SHAMap.cpp
index 29899e87b..415e37b25 100644
--- a/src/cpp/ripple/ripple_SHAMap.cpp
+++ b/src/cpp/ripple/ripple_SHAMap.cpp
@@ -889,7 +889,7 @@ bool SHAMap::fetchRoot (uint256 const& hash, SHAMapSyncFilter* filter)
SHAMapTreeNode::pointer newRoot = fetchNodeExternalNT(SHAMapNode(), hash);
if (newRoot)
root = newRoot;
- else
+ else
{
Blob nodeData;
diff --git a/src/cpp/ripple/ripple_SHAMapSync.cpp b/src/cpp/ripple/ripple_SHAMapSync.cpp
index b4ee5c33c..438b83d4b 100644
--- a/src/cpp/ripple/ripple_SHAMapSync.cpp
+++ b/src/cpp/ripple/ripple_SHAMapSync.cpp
@@ -56,7 +56,7 @@ void SHAMap::getMissingNodes (std::vector& nodeIDs, std::vector