@@ -69,23 +69,51 @@ class InboundLedgersImp : public InboundLedgers
69
69
std::uint32_t seq,
70
70
InboundLedger::Reason reason) override
71
71
{
72
+ std::stringstream ss;
73
+ ss << " InboundLedger::acquire: "
74
+ << " Request: " << to_string (hash) << " , " << seq
75
+ << " NeedNetworkLedger: "
76
+ << (app_.getOPs ().isNeedNetworkLedger () ? " yes" : " no" )
77
+ << " Reason: " << to_string (reason) << " Old rule: " ;
78
+ if (app_.getOPs ().isNeedNetworkLedger () &&
79
+ (reason != InboundLedger::Reason::GENERIC) &&
80
+ (reason != InboundLedger::Reason::CONSENSUS))
81
+ ss << " false" ;
82
+ else
83
+ ss << " true" ;
84
+
72
85
assert (hash.isNonZero ());
73
86
assert (
74
87
reason != InboundLedger::Reason::SHARD ||
75
88
(seq != 0 && app_.getShardStore ()));
76
89
77
- // probably not the right rule
78
- if (app_.getOPs ().isNeedNetworkLedger () &&
79
- (reason != InboundLedger::Reason::GENERIC) &&
80
- (reason != InboundLedger::Reason::CONSENSUS))
81
- return {};
90
+ bool const isFull = app_.getOPs ().isFull ();
91
+ bool const fallingBehind = app_.getOPs ().isFallingBehind ();
92
+ LedgerIndex const validSeq =
93
+ app_.getLedgerMaster ().getValidLedgerIndex ();
94
+ constexpr std::size_t lagLeeway = 20 ;
95
+ bool const nearFuture =
96
+ (seq > validSeq) && (seq < validSeq + lagLeeway);
97
+ bool const consensus = reason == InboundLedger::Reason::CONSENSUS;
98
+ bool const shouldAcquire =
99
+ !(isFull && !fallingBehind && (nearFuture || consensus));
100
+ ss << " Evaluating whether to acquire ledger " << hash
101
+ << " . full: " << (isFull ? " true" : " false" )
102
+ << " . falling behind: " << (fallingBehind ? " true" : " false" )
103
+ << " . ledger sequence " << seq << " . Valid sequence: " << validSeq
104
+ << " . Lag leeway: " << lagLeeway
105
+ << " . request for near future ledger: "
106
+ << (nearFuture ? " true" : " false" )
107
+ << " . Consensus: " << (consensus ? " true" : " false" )
108
+ << " . Acquiring ledger? " << (shouldAcquire ? " true" : " false" );
82
109
83
110
bool isNew = true ;
84
111
std::shared_ptr<InboundLedger> inbound;
85
112
{
86
113
ScopedLockType sl (mLock );
87
114
if (stopping_)
88
115
{
116
+ JLOG (j_.debug ()) << " Abort (stopping): " << ss.str ();
89
117
return {};
90
118
}
91
119
@@ -111,13 +139,19 @@ class InboundLedgersImp : public InboundLedgers
111
139
}
112
140
113
141
if (inbound->isFailed ())
142
+ {
143
+ JLOG (j_.debug ()) << " Abort (failed): " << ss.str ();
114
144
return {};
145
+ }
115
146
116
147
if (!isNew)
117
148
inbound->update (seq);
118
149
119
150
if (!inbound->isComplete ())
151
+ {
152
+ JLOG (j_.debug ()) << " Abort (incomplete): " << ss.str ();
120
153
return {};
154
+ }
121
155
122
156
if (reason == InboundLedger::Reason::HISTORY)
123
157
{
@@ -130,14 +164,45 @@ class InboundLedgersImp : public InboundLedgers
130
164
if (!shardStore)
131
165
{
132
166
JLOG (j_.error ())
133
- << " Acquiring shard with no shard store available" ;
167
+ << " Acquiring shard with no shard store available"
168
+ << ss.str ();
134
169
return {};
135
170
}
136
171
if (inbound->getLedger ()->stateMap ().family ().isShardBacked ())
137
172
shardStore->setStored (inbound->getLedger ());
138
173
else
139
174
shardStore->storeLedger (inbound->getLedger ());
140
175
}
176
+
177
+ /* Acquiring ledgers is somewhat expensive. It requires lots of
178
+ * computation and network communication. Avoid it when it's not
179
+ * appropriate. Every validation from a peer for a ledger that
180
+ * we do not have locally results in a call to this function: even
181
+ * if we are moments away from validating the same ledger.
182
+ *
183
+ * When the following are all true, it is very likely that we will
184
+ * soon validate the ledger ourselves. Therefore, avoid acquiring
185
+ * ledgers from the network if:
186
+ * + Our mode is "full". It is very likely that we will build
187
+ * the ledger through the normal consensus process, and
188
+ * + Our latest ledger is close to the most recently validated ledger.
189
+ * Otherwise, we are likely falling behind the network because
190
+ * we have been closing ledgers that have not been validated, and
191
+ * + The requested ledger sequence is greater than our validated
192
+ * ledger, but not far into the future. Otherwise, it is either a
193
+ * request for an historical ledger or, if far into the future,
194
+ * likely we're quite behind and will benefit from acquiring it
195
+ * from the network.
196
+ */
197
+ if (!shouldAcquire)
198
+ {
199
+ // This check should be before the others because it's cheaper, but
200
+ // it's at the end for now to test the effectiveness of the change
201
+ JLOG (j_.debug ()) << " Abort (rule): " << ss.str ();
202
+ return {};
203
+ }
204
+
205
+ JLOG (j_.debug ()) << " Requesting: " << ss.str ();
141
206
return inbound->getLedger ();
142
207
}
143
208
0 commit comments