in accord-core/src/main/java/accord/impl/progresslog/TxnState.java [40:135]
void updateScheduling(SafeCommandStore safeStore, DefaultProgressLog instance, TxnStateKind updated, @Nullable BlockedUntil blockedUntil, Progress newProgress)
{
long newDelay;
switch (newProgress)
{
default:
throw new UnhandledEnum(newProgress);
case NoneExpected:
case Querying:
newDelay = 0;
break;
case Queued:
switch (updated)
{
default: throw new UnhandledEnum(updated);
case Waiting:
newDelay = instance.commandStore.agent().slowReplicaDelay(instance.node, safeStore, txnId, 1 + waitingRetryCounter(), blockedUntil, MICROSECONDS);
break;
case Home:
newDelay = instance.commandStore.agent().slowCoordinatorDelay(instance.node, safeStore, txnId, MICROSECONDS, 1 + homeRetryCounter());
}
Invariants.require(newDelay > 0);
break;
case Awaiting:
int retries = updated == TxnStateKind.Home ? homeRetryCounter() : waitingRetryCounter();
newDelay = instance.commandStore.agent().slowAwaitDelay(instance.node, safeStore, txnId, 1 + retries, blockedUntil, MICROSECONDS);
Invariants.require(newDelay > 0);
break;
}
TxnStateKind scheduled = scheduledTimer();
if (scheduled == null)
{
Invariants.require(pendingTimer() == null);
}
// previousDeadline is the previous deadline of <updated>;
// otherDeadline is the active deadline (if any) of <updated.other()>
long previousDeadline, otherDeadline;
if (scheduled == updated)
{
previousDeadline = deadline();
otherDeadline = pendingTimerDeadline(previousDeadline);
}
else if (scheduled != null)
{
otherDeadline = deadline();
previousDeadline = pendingTimerDeadline(otherDeadline);
}
else
{
Invariants.require(pendingTimer() == null);
otherDeadline = previousDeadline = 0;
}
if (newDelay == 0)
{
if (otherDeadline > 0)
{
clearPendingTimerDelay();
setScheduledTimer(updated.other());
instance.update(otherDeadline, this);
}
else if (previousDeadline > 0)
{
instance.unschedule(this);
}
else
{
Invariants.require(!isScheduled());
}
}
else
{
long nowMicros = instance.node().elapsed(MICROSECONDS);
long newDeadline = nowMicros + newDelay;
if (otherDeadline == 0)
{
setScheduledTimer(updated);
if (previousDeadline > 0) instance.update(newDeadline, this);
else instance.add(newDeadline, this);
}
else if (newDeadline < otherDeadline)
{
setScheduledTimer(updated);
setPendingTimerDelay(Ints.saturatedCast(otherDeadline - newDeadline));
instance.update(newDeadline, this);
}
else
{
setScheduledTimer(updated.other());
setPendingTimerDelay(Ints.saturatedCast(Math.max(1, newDeadline - otherDeadline)));
instance.update(otherDeadline, this);
}
}
}