in accord-core/src/main/java/accord/local/cfk/CommandsForKey.java [1574:1638]
private CommandsForKeyUpdate update(InternalStatus newStatus, Command updated, @Nullable LoadingPruned loading)
{
TxnId txnId = updated.txnId();
Invariants.requireArgument(updated.participants().hasTouched(key) || !manages(txnId));
if (txnId.compareTo(redundantBefore()) < 0)
return this;
boolean mayExecute = mayExecute(txnId, newStatus, updated);
boolean isOutOfRange = !mayExecute && newStatus.compareTo(APPLIED) <= 0 && manages(txnId)
&& !updated.participants().stillTouches(key);
TxnId[] witnessedBy = loading != null ? loading.witnessedBy : NOT_LOADING_PRUNED;
if (loading == null && isOutOfRange && newStatus.compareTo(COMMITTED) < 0)
return this;
int pos = Arrays.binarySearch(byId, txnId);
CommandsForKeyUpdate result;
if (pos < 0)
{
if (isOutOfRange && loading == null)
return this; // if outOfRange we only need to maintain any existing records; if none, don't update
pos = -1 - pos;
if (isOutOfRange) result = insertOrUpdateOutOfRange(pos, txnId, null, newStatus, mayExecute, updated, witnessedBy);
else if (newStatus.hasDeps()) result = insert(pos, txnId, newStatus, mayExecute, updated, witnessedBy);
else result = insert(pos, txnId, TxnInfo.create(txnId, newStatus, mayExecute, updated), updated, witnessedBy);
}
else
{
// update
TxnInfo cur = byId[pos];
int c = cur.compareTo(newStatus);
if (c > 0)
{
// newStatus moves us backwards; we only permit this for (Pre)?(Not)?Accepted states
if (cur.compareTo(COMMITTED) >= 0 || newStatus.compareTo(PREACCEPTED) <= 0)
return this;
// and only when the new ballot is strictly greater
if (updated.acceptedOrCommitted().compareTo(cur.ballot()) <= 0)
return this;
}
else if (c == 0)
{
// we're updating to the same state; we only do this with a strictly greater ballot;
// even so, if we have no executeAt or deps there's nothing to record
if (updated.acceptedOrCommitted().compareTo(cur.ballot()) <= 0 || !newStatus.hasExecuteAtOrDeps())
return this;
}
else
{
// we're advancing to a higher status, but this is only permitted either if the new state is stable or the ballot is higher
if (cur.compareTo(STABLE) < 0 && updated.acceptedOrCommitted().compareTo(cur.ballot()) < 0)
return this;
}
if (isOutOfRange) result = insertOrUpdateOutOfRange(pos, txnId, cur, newStatus, mayExecute, updated, witnessedBy);
else if (cur.compareTo(STABLE) >= 0) result = update(pos, txnId, cur, cur.withEncodedStatus(TxnInfo.encode(txnId, newStatus, cur.mayExecute(), cur.statusOverrides())), updated, witnessedBy);
else if (newStatus.hasDeps()) result = update(pos, txnId, cur, newStatus, mayExecute, updated, witnessedBy);
else result = update(pos, txnId, cur, TxnInfo.create(txnId, newStatus, mayExecute, updated), updated, witnessedBy);
}
return result;
}