void updateScheduling()

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);
            }
        }
    }