@@ -77,18 +77,114 @@ class InboundLedgersImp : public InboundLedgers
77
77
reason != InboundLedger::Reason::SHARD ||
78
78
(seq != 0 && app_.getShardStore ()));
79
79
80
- // probably not the right rule
81
- if (app_.getOPs ().isNeedNetworkLedger () &&
82
- (reason != InboundLedger::Reason::GENERIC) &&
83
- (reason != InboundLedger::Reason::CONSENSUS))
80
+ bool const shouldAcquire = [&]() {
81
+ if (!app_.getOPs ().isNeedNetworkLedger ())
82
+ return true ;
83
+ if (reason == InboundLedger::Reason::GENERIC)
84
+ return true ;
85
+ if (reason == InboundLedger::Reason::CONSENSUS)
86
+ return true ;
87
+ return false ;
88
+ }();
89
+ assert (
90
+ shouldAcquire ==
91
+ !(app_.getOPs ().isNeedNetworkLedger () &&
92
+ (reason != InboundLedger::Reason::GENERIC) &&
93
+ (reason != InboundLedger::Reason::CONSENSUS)));
94
+
95
+ std::stringstream ss;
96
+ ss << " InboundLedger::acquire: "
97
+ << " Request: " << to_string (hash) << " , " << seq
98
+ << " NeedNetworkLedger: "
99
+ << (app_.getOPs ().isNeedNetworkLedger () ? " yes" : " no" )
100
+ << " Reason: " << to_string (reason)
101
+ << " Should acquire: " << (shouldAcquire ? " true." : " false." );
102
+
103
+ /* Acquiring ledgers is somewhat expensive. It requires lots of
104
+ * computation and network communication. Avoid it when it's not
105
+ * appropriate. Every validation from a peer for a ledger that
106
+ * we do not have locally results in a call to this function: even
107
+ * if we are moments away from validating the same ledger.
108
+ */
109
+ bool const shouldBroadcast = [&]() {
110
+ // If the node is not in "full" state, it needs to sync to
111
+ // the network, and doesn't have the necessary tx's and
112
+ // ledger entries to build the ledger.
113
+ bool const isFull = app_.getOPs ().isFull ();
114
+ // fallingBehind means the last closed ledger is at least 2
115
+ // behind the validated ledger. If the node is falling
116
+ // behind the network, it probably needs information from
117
+ // the network to catch up.
118
+ //
119
+ // The reason this should not simply be only at least 1
120
+ // behind the validated ledger is that a slight lag is
121
+ // normal case because some nodes get there slightly later
122
+ // than others. A difference of 2 means that at least a full
123
+ // ledger interval has passed, so the node is beginning to
124
+ // fall behind.
125
+ bool const fallingBehind = app_.getOPs ().isFallingBehind ();
126
+ // If everything else is ok, don't try to acquire the ledger
127
+ // if the requested seq is in the near future relative to
128
+ // the validated ledger. If the requested ledger is between
129
+ // 1 and 19 inclusive ledgers ahead of the valid ledger this
130
+ // node has not built it yet, but it's possible/likely it
131
+ // has the tx's necessary to build it and get caught up.
132
+ // Plus it might not become validated. On the other hand, if
133
+ // it's more than 20 in the future, this node should request
134
+ // it so that it can jump ahead and get caught up.
135
+ LedgerIndex const validSeq =
136
+ app_.getLedgerMaster ().getValidLedgerIndex ();
137
+ constexpr std::size_t lagLeeway = 20 ;
138
+ bool const nearFuture =
139
+ (seq > validSeq) && (seq < validSeq + lagLeeway);
140
+ // If everything else is ok, don't try to acquire the ledger
141
+ // if the request is related to consensus. (Note that
142
+ // consensus calls usually pass a seq of 0, so nearFuture
143
+ // will be false other than on a brand new network.)
144
+ bool const consensus =
145
+ reason == InboundLedger::Reason::CONSENSUS;
146
+ ss << " Evaluating whether to broadcast requests to peers"
147
+ << " . full: " << (isFull ? " true" : " false" )
148
+ << " . falling behind: " << (fallingBehind ? " true" : " false" )
149
+ << " . ledger sequence " << seq
150
+ << " . Valid sequence: " << validSeq
151
+ << " . Lag leeway: " << lagLeeway
152
+ << " . request for near future ledger: "
153
+ << (nearFuture ? " true" : " false" )
154
+ << " . Consensus: " << (consensus ? " true" : " false" );
155
+
156
+ // If the node is not synced, send requests.
157
+ if (!isFull)
158
+ return true ;
159
+ // If the node is falling behind, send requests.
160
+ if (fallingBehind)
161
+ return true ;
162
+ // If the ledger is in the near future, do NOT send requests.
163
+ // This node is probably about to build it.
164
+ if (nearFuture)
165
+ return false ;
166
+ // If the request is because of consensus, do NOT send requests.
167
+ // This node is probably about to build it.
168
+ if (consensus)
169
+ return false ;
170
+ return true ;
171
+ }();
172
+ ss << " . Broadcast to peers? "
173
+ << (shouldBroadcast ? " true." : " false." );
174
+
175
+ if (!shouldAcquire)
176
+ {
177
+ JLOG (j_.debug ()) << " Abort(rule): " << ss.str ();
84
178
return {};
179
+ }
85
180
86
181
bool isNew = true ;
87
182
std::shared_ptr<InboundLedger> inbound;
88
183
{
89
184
ScopedLockType sl (mLock );
90
185
if (stopping_)
91
186
{
187
+ JLOG (j_.debug ()) << " Abort(stopping): " << ss.str ();
92
188
return {};
93
189
}
94
190
@@ -108,19 +204,26 @@ class InboundLedgersImp : public InboundLedgers
108
204
std::ref (m_clock),
109
205
mPeerSetBuilder ->build ());
110
206
mLedgers .emplace (hash, inbound);
111
- inbound->init (sl);
207
+ inbound->init (sl, shouldBroadcast );
112
208
++mCounter ;
113
209
}
114
210
}
211
+ ss << " IsNew: " << (isNew ? " true" : " false" );
115
212
116
213
if (inbound->isFailed ())
214
+ {
215
+ JLOG (j_.debug ()) << " Abort(failed): " << ss.str ();
117
216
return {};
217
+ }
118
218
119
219
if (!isNew)
120
- inbound->update (seq);
220
+ inbound->update (seq, shouldBroadcast );
121
221
122
222
if (!inbound->isComplete ())
223
+ {
224
+ JLOG (j_.debug ()) << " Incomplete: " << ss.str ();
123
225
return {};
226
+ }
124
227
125
228
if (reason == InboundLedger::Reason::HISTORY)
126
229
{
@@ -133,21 +236,22 @@ class InboundLedgersImp : public InboundLedgers
133
236
if (!shardStore)
134
237
{
135
238
JLOG (j_.error ())
136
- << " Acquiring shard with no shard store available" ;
239
+ << " Acquiring shard with no shard store available"
240
+ << ss.str ();
137
241
return {};
138
242
}
139
243
if (inbound->getLedger ()->stateMap ().family ().isShardBacked ())
140
244
shardStore->setStored (inbound->getLedger ());
141
245
else
142
246
shardStore->storeLedger (inbound->getLedger ());
143
247
}
248
+
249
+ JLOG (j_.debug ()) << " Complete: " << ss.str ();
144
250
return inbound->getLedger ();
145
251
};
146
252
using namespace std ::chrono_literals;
147
- std::shared_ptr<Ledger const > ledger = perf::measureDurationAndLog (
253
+ return perf::measureDurationAndLog (
148
254
doAcquire, " InboundLedgersImp::acquire" , 500ms, j_);
149
-
150
- return ledger;
151
255
}
152
256
153
257
void
0 commit comments