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