static Object computeInfoAndAdditions()

in accord-core/src/main/java/accord/local/cfk/Updating.java [310:414]


    static Object computeInfoAndAdditions(TxnInfo[] byId, int insertPos, int updatePos, TxnId plainTxnId, InternalStatus newStatus, boolean mayExecute, Ballot ballot, Timestamp executeAt, TxnInfo prunedBefore, Timestamp depsKnownBefore, MergeCursor<TxnId, DepList> deps)
    {
        TxnId[] additions = NO_TXNIDS, missing = NO_TXNIDS;
        int additionCount = 0, missingCount = 0;

        // the position until which we should have witnessed transactions, i.e. for computing the missing collection
        // *NOT* to be used for terminating *inserts* from deps parameter, as this may see the future
        // (due to pruning sometimes including a later transaction where it cannot include all earlier ones)
        int depsKnownBeforePos = insertPos;
        if (depsKnownBefore != plainTxnId)
        {
            depsKnownBeforePos = Arrays.binarySearch(byId, insertPos, byId.length, depsKnownBefore);
            // depsKnownBeforePos can be positive if we have a uniqueHlc but agreed the TxnId as the executeAt
            if (depsKnownBeforePos < 0)
                depsKnownBeforePos = -1 - depsKnownBeforePos;
        }

        int txnIdsIndex = 0;
        while (txnIdsIndex < byId.length && deps.hasCur())
        {
            TxnInfo t = byId[txnIdsIndex];
            TxnId d = deps.cur();
            int c = t.compareTo(d);
            if (c == 0)
            {
                // TODO (expected): if plainTxnId implies TRANSITIVE_VISIBLE dependencies,
                //  we should ensure any existing TRANSITIVE entries are upgraded.
                // OR we should remove TRANSITIVE for simplicity,
                // OR document/enforce that TRANSITIVE_VISIBLE can only be applied to dependencies of unmanaged transactions
                if (d.is(UNSTABLE)  && txnIdsIndex < depsKnownBeforePos && t.compareTo(COMMITTED) < 0 && plainTxnId.witnesses(d))
                    missing = append(missing, missingCount++, d, cachedTxnIds());

                ++txnIdsIndex;
                deps.advance();
            }
            else if (c < 0)
            {
                // we expect to be missing ourselves
                // we also permit any transaction we have recorded as COMMITTED or later to be missing, as recovery will not need to consult our information
                if (txnIdsIndex != updatePos && txnIdsIndex < depsKnownBeforePos && t.compareTo(COMMITTED) < 0 && plainTxnId.witnesses(t))
                    missing = append(missing, missingCount++, t.plainTxnId(), cachedTxnIds());
                txnIdsIndex++;
            }
            else
            {
                if (plainTxnId.witnesses(d))
                {
                    if (d.is(UNSTABLE))
                    {
                        if (d.compareTo(depsKnownBefore) < 0 && (manages(d) || d.compareTo(prunedBefore) > 0))
                            missing = append(missing, missingCount++, d, cachedTxnIds());
                        d = d.withoutNonIdentityFlags();
                    }
                    additions = append(additions, additionCount++, d, cachedTxnIds());
                }
                else
                {
                    // we can take dependencies on ExclusiveSyncPoints to represent a GC point in the log
                    // if we don't ordinarily witness a transaction it is meaningless to include it as a dependency
                    // as we will not logically be able to work with it (the missing collection will not correctly represent it anyway)
                    Invariants.require(d.is(ExclusiveSyncPoint));
                }
                deps.advance();
            }
        }

        if (deps.hasCur())
        {
            do
            {
                TxnId d = deps.cur();
                if (plainTxnId.witnesses(d))
                {
                    if (d.is(UNSTABLE))
                    {
                        if (d.compareTo(depsKnownBefore) < 0 && (manages(d) || d.compareTo(prunedBefore) > 0))
                            missing = append(missing, missingCount++, d, cachedTxnIds());
                        d = d.withoutNonIdentityFlags();
                    }
                    additions = append(additions, additionCount++, d, cachedTxnIds());
                }
                deps.advance();
            }
            while (deps.hasCur());
        }
        else if (txnIdsIndex < byId.length)
        {
            while (txnIdsIndex < depsKnownBeforePos)
            {
                if (txnIdsIndex != updatePos && byId[txnIdsIndex].compareTo(COMMITTED) < 0)
                {
                    TxnInfo txn = byId[txnIdsIndex];
                    if (plainTxnId.witnesses(txn))
                        missing = append(missing, missingCount++, txn.plainTxnId(), cachedTxnIds());
                }
                txnIdsIndex++;
            }
        }

        TxnInfo info = TxnInfo.create(plainTxnId, newStatus, mayExecute, executeAt, cachedTxnIds().completeAndDiscard(missing, missingCount), ballot);
        if (additionCount == 0)
            return info;

        return new InfoWithAdditions(info, additions, additionCount);
    }