static void insertOrUpdateWithAdditions()

in accord-core/src/main/java/accord/local/cfk/Updating.java [502:631]


    static void insertOrUpdateWithAdditions(TxnInfo[] byId, int sourceInsertPos, int sourceUpdatePos, TxnId plainTxnId, TxnInfo newInfo, TxnId[] additions, int additionCount, TxnInfo[] newById, TxnInfo[] newCommittedByExecuteAt, @Nonnull TxnId[] witnessedBy, QuickBounds bounds)
    {
        int additionInsertPos = Arrays.binarySearch(additions, 0, additionCount, plainTxnId);
        additionInsertPos = Invariants.requireArgument(-1 - additionInsertPos, additionInsertPos < 0);
        int targetInsertPos = sourceInsertPos + additionInsertPos;

        // we may need to insert or remove ourselves, depending on the new and prior status
        boolean insertSelfMissing = sourceUpdatePos < 0 && newInfo.compareTo(COMMITTED) < 0;
        boolean removeSelfMissing = newInfo.compareTo(COMMITTED) >= 0 && sourceUpdatePos >= 0 && byId[sourceUpdatePos].compareTo(COMMITTED) < 0;
        boolean removeWitnessedMissing = newInfo.compareTo(COMMITTED) >= 0 && witnessedBy.length > 0;
        // missingSource starts as additions, but if we insertSelfMissing at the relevant moment it becomes the merge of additions and plainTxnId
        TxnId[] missingSource = additions;

        // the most recently constructed pure insert missing array, so that it may be reused if possible
        int i = 0, j = 0, missingCount = 0, missingLimit = additionCount, count = 0;
        int minByExecuteAtSearchIndex = 0;
        while (i < byId.length)
        {
            if (count == targetInsertPos)
            {
                newById[count] = newInfo;
                if (i == sourceUpdatePos) ++i;
                else if (insertSelfMissing) ++missingCount;
                ++count;
                continue;
            }

            int c = j == additionCount ? -1 : byId[i].compareTo(additions[j]);
            if (c < 0)
            {
                TxnInfo txn = byId[i];
                if (i == sourceUpdatePos)
                {
                    txn = newInfo;
                }
                else if (txn.hasDeps())
                {
                    Timestamp depsKnownBefore = txn.depsKnownBefore();
                    if (insertSelfMissing && missingSource == additions && (missingCount != j || (depsKnownBefore != txn && depsKnownBefore.compareTo(plainTxnId) > 0)))
                    {
                        // add ourselves to the missing collection
                        missingSource = insertMissing(additions, additionCount, plainTxnId, additionInsertPos);
                        ++missingLimit;
                    }

                    int to = missingTo(txn, depsKnownBefore, missingSource, missingCount, missingLimit);
                    if (to > 0 || removeSelfMissing || removeWitnessedMissing)
                    {
                        int witnessedByIndex = -1;
                        if (witnessedBy != NOT_LOADING_PRUNED && (to > 0 || !removeSelfMissing))
                            witnessedByIndex = Arrays.binarySearch(witnessedBy, txn);

                        TxnId[] curMissing = txn.missing();
                        TxnId[] newMissing = curMissing;
                        if (to > 0)
                        {
                            TxnId skipInsertMissing = null;
                            if (insertSelfMissing && witnessedByIndex >= 0)
                                skipInsertMissing = plainTxnId;

                            newMissing = mergeAndFilterMissing(txn, curMissing, missingSource, to, skipInsertMissing);
                        }

                        if (removeSelfMissing || (removeWitnessedMissing && witnessedByIndex >= 0))
                            newMissing = removeOneMissing(newMissing, plainTxnId);

                        if (newMissing != curMissing)
                        {
                            TxnInfo newTxn = txn.withMissing(newMissing);

                            if (txn.isCommittedAndExecutes())
                            {
                                // update newCommittedByExecuteAt
                                int ci;
                                if (txn.executeAt == txn)
                                {
                                    ci = SortedArrays.exponentialSearch(newCommittedByExecuteAt, minByExecuteAtSearchIndex, newCommittedByExecuteAt.length, txn, TxnInfo::compareExecuteAt, FAST);
                                    minByExecuteAtSearchIndex = 1 + ci;
                                }
                                else
                                {
                                    ci = Arrays.binarySearch(newCommittedByExecuteAt, minByExecuteAtSearchIndex, newCommittedByExecuteAt.length, txn, TxnInfo::compareExecuteAt);
                                }
                                Invariants.require(newCommittedByExecuteAt[ci] == txn);
                                newCommittedByExecuteAt[ci] = newTxn;
                            }

                            txn = newTxn;
                        }
                    }
                }
                newById[count] = txn;
                i++;
            }
            else if (c > 0)
            {
                TxnId txnId = additions[j++];
                newById[count] = TxnInfo.createTransitive(txnId, bounds, plainTxnId);
                ++missingCount;
            }
            else
            {
                throw illegalState(byId[i] + " should be an insertion, but found match when merging with origin");
            }
            count++;
        }

        if (j < additionCount)
        {
            if (count <= targetInsertPos)
            {
                while (count < targetInsertPos)
                {
                    TxnId txnId = additions[j++];
                    newById[count++] = TxnInfo.createTransitive(txnId, bounds, plainTxnId);
                }
                newById[targetInsertPos] = newInfo;
                count = targetInsertPos + 1;
            }
            while (j < additionCount)
            {
                TxnId txnId = additions[j++];
                newById[count++] = TxnInfo.createTransitive(txnId, bounds, plainTxnId);
            }
        }
        else if (count == targetInsertPos)
        {
            newById[targetInsertPos] = newInfo;
        }
    }