in accord-core/src/main/java/accord/local/RedundantBefore.java [1169:1249]
public final void removeRedundantDependencies(Unseekables<?> participants, Command.WaitingOn.Update builder)
{
// Note: we do not need to track the bootstraps we implicitly depend upon, because we will not serve any read requests until this has completed
// and since we are a timestamp store, and we write only this will sort itself out naturally
// TODO (required): make sure we have no races on HLC around SyncPoint else this resolution may not work (we need to know the micros equivalent timestamp of the snapshot)
/**
* If we have to handle bootstrapping ranges for range transactions, these may only partially cover the
* transaction, in which case we should not remove the transaction as a dependency. But if it is fully
* covered by bootstrapping ranges then we *must* remove it as a dependency.
*/
class RangeState
{
Range range;
int bootstrapIdx, appliedIdx;
Map<Integer, Ranges> partiallyBootstrapping;
/**
* Are the participating ranges for the txn fully covered by bootstrapping ranges for this command store
*/
boolean isFullyBootstrapping(int rangeTxnIdx)
{
// if all deps for the txnIdx are contained in the range, don't inflate any shared object state
if (builder.directRangeDeps.foldEachRange(rangeTxnIdx, range, true, (r1, r2, p) -> p && r1.contains(r2)))
return true;
if (partiallyBootstrapping == null)
partiallyBootstrapping = new HashMap<>();
Ranges prev = partiallyBootstrapping.get(rangeTxnIdx);
Ranges remaining = prev;
if (remaining == null) remaining = builder.directRangeDeps.ranges(rangeTxnIdx);
else Invariants.require(!remaining.isEmpty());
remaining = remaining.without(Ranges.of(range));
if (prev == null) Invariants.require(!remaining.isEmpty());
partiallyBootstrapping.put(rangeTxnIdx, remaining);
return remaining.isEmpty();
}
}
RangeDeps rangeDeps = builder.directRangeDeps;
foldl(participants, (e, s, d, b) -> {
int bootstrapIdx = d.txnIdsWithFlags().find(e.maxBootstrappedAt());
if (bootstrapIdx < 0) bootstrapIdx = -1 - bootstrapIdx;
s.bootstrapIdx = bootstrapIdx;
TxnId locallyAppliedBefore = e.maxLocallyAppliedBefore();
int appliedIdx = d.txnIdsWithFlags().find(locallyAppliedBefore);
if (appliedIdx < 0) appliedIdx = -1 - appliedIdx;
if (locallyAppliedBefore.epoch() >= e.endEpoch)
{
// for range transactions, we should not infer that a still-owned range is redundant because a not-owned range that overlaps is redundant
int altAppliedIdx = d.txnIdsWithFlags().find(TxnId.minForEpoch(e.endEpoch));
if (altAppliedIdx < 0) altAppliedIdx = -1 - altAppliedIdx;
if (altAppliedIdx < appliedIdx) appliedIdx = altAppliedIdx;
}
s.appliedIdx = appliedIdx;
// remove intersecting transactions with known redundant txnId
if (appliedIdx > bootstrapIdx)
{
// TODO (desired):
// TODO (desired): move the bounds check into forEach, matching structure used for keys
d.forEach(e.range, b, s, (b0, s0, txnIdx) -> {
if (txnIdx >= s0.bootstrapIdx && txnIdx < s0.appliedIdx)
b0.removeWaitingOnDirectRangeTxnId(txnIdx);
});
}
if (bootstrapIdx > 0)
{
// if we have any ranges where bootstrap is involved, we have to do a more complicated dance since
// this may imply only partial redundancy (we may still depend on the transaction for some other range)
s.range = e.range;
// TODO (desired): move the bounds check into forEach, matching structure used for keys
d.forEach(e.range, b, s, (b0, s0, txnIdx) -> {
if (txnIdx < s0.bootstrapIdx && b0.isWaitingOnDirectRangeTxnIdx(txnIdx) && s0.isFullyBootstrapping(txnIdx))
b0.removeWaitingOnDirectRangeTxnId(txnIdx);
});
}
return s;
}, new RangeState(), rangeDeps, builder);
}