<commit_before>package org.drools.core.reteoo;

import org.drools.core.common.InternalWorkingMemory;
import org.drools.core.common.LeftTupleSets;
import org.drools.core.common.Memory;
import org.drools.core.common.MemoryFactory;
import org.drools.core.common.NetworkNode;
import org.drools.core.util.LinkedList;
import org.drools.core.util.LinkedListNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

public class SegmentMemory extends LinkedList<SegmentMemory>
        implements
        LinkedListNode<SegmentMemory> {

    protected static transient Logger log = LoggerFactory.getLogger(SegmentMemory.class);
    private NetworkNode        rootNode;
    private NetworkNode        tipNode;
    private LinkedList<Memory> nodeMemories;
    private long               linkedNodeMask;
    private long               allLinkedMaskTest;
    private List<PathMemory>   pathMemories;
    private long               segmentPosMaskBit;
    private int                pos;
    private volatile LeftTupleSets      stagedLeftTuples;
    private boolean            active;
    private SegmentMemory      previous;
    private SegmentMemory      next;

    public SegmentMemory(NetworkNode rootNode) {
        this.rootNode = rootNode;
        this.pathMemories = new ArrayList<PathMemory>(1);
        this.nodeMemories = new LinkedList<Memory>();

        this.stagedLeftTuples = new LeftTupleSets();
    }

    public NetworkNode getRootNode() {
        return rootNode;
    }

    public NetworkNode getTipNode() {
        return tipNode;
    }

    public void setTipNode(NetworkNode tipNode) {
        this.tipNode = tipNode;
    }

    public LeftTupleSink getSinkFactory() {
        return (LeftTupleSink) rootNode;
    }

    public void setSinkFactory(LeftTupleSink sink) {
    }

    public Memory createNodeMemory(MemoryFactory memoryFactory,
                                   InternalWorkingMemory wm) {
        Memory memory = wm.getNodeMemory(memoryFactory);
        nodeMemories.add(memory);
        return memory;
    }

    public LinkedList<Memory> getNodeMemories() {
        return nodeMemories;
    }

    public long getLinkedNodeMask() {
        return linkedNodeMask;
    }

    public void setLinkedNodeMask(long linkedNodeMask) {
        this.linkedNodeMask = linkedNodeMask;
    }

    public String getRuleNames() {
        StringBuilder sbuilder = new StringBuilder();
        for (int i = 0; i < pathMemories.size(); i++) {
            if (i > 0) {
                sbuilder.append(", ");
            }
            sbuilder.append(pathMemories.get(i));
        }

        return sbuilder.toString();
    }

    public void linkNode(long mask,
                         InternalWorkingMemory wm) {
        linkedNodeMask = linkedNodeMask | mask;
        if (log.isTraceEnabled()) {
            log.trace("LinkNode notify=true nmask={} smask={} spos={} rules={}", mask, linkedNodeMask, pos, getRuleNames());
        }

        notifyRuleLinkSegment(wm);
    }

    public void linkNodeWithoutRuleNotify(long mask) {
        linkedNodeMask = linkedNodeMask | mask;

        if (log.isTraceEnabled()) {
            log.trace("LinkNode notify=false nmask={} smask={} spos={} rules={}", mask, linkedNodeMask, pos, getRuleNames());
        }

        if (isSegmentLinked()) {
            for (int i = 0, length = pathMemories.size(); i < length; i++) {
                // do not use foreach, don't want Iterator object creation
                pathMemories.get(i).linkNodeWithoutRuleNotify(segmentPosMaskBit);
            }
        }
    }

    public void notifyRuleLinkSegment(InternalWorkingMemory wm) {
        if (isSegmentLinked()) {
            for (int i = 0, length = pathMemories.size(); i < length; i++) {
                // do not use foreach, don't want Iterator object creation
                pathMemories.get(i).linkSegment(segmentPosMaskBit,
                                                wm);
            }
        }
    }

    public void unlinkNode(long mask,
                           InternalWorkingMemory wm) {
        if (log.isTraceEnabled()) {
            log.trace("UnlinkNode notify=true nmask={} smask={} spos={} rules={}", mask, linkedNodeMask, pos, getRuleNames());
        }

        // some node unlinking does not unlink the segment, such as nodes after a Branch CE
        boolean linked = isSegmentLinked();
        linkedNodeMask = linkedNodeMask ^ mask;
        if (linked && !isSegmentLinked()) {
            for (int i = 0, length = pathMemories.size(); i < length; i++) {
                // do not use foreach, don't want Iterator object creation
                pathMemories.get(i).unlinkedSegment(segmentPosMaskBit,
                                                    wm);
            }
        }
    }
<commit_msg>[DROOLS-7] notify a rule regardless if it has been unlinked or not<commit_after>package org.drools.core.reteoo;

import org.drools.core.common.InternalWorkingMemory;
import org.drools.core.common.LeftTupleSets;
import org.drools.core.common.Memory;
import org.drools.core.common.MemoryFactory;
import org.drools.core.common.NetworkNode;
import org.drools.core.util.LinkedList;
import org.drools.core.util.LinkedListNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

public class SegmentMemory extends LinkedList<SegmentMemory>
        implements
        LinkedListNode<SegmentMemory> {

    protected static transient Logger log = LoggerFactory.getLogger(SegmentMemory.class);
    private NetworkNode        rootNode;
    private NetworkNode        tipNode;
    private LinkedList<Memory> nodeMemories;
    private long               linkedNodeMask;
    private long               allLinkedMaskTest;
    private List<PathMemory>   pathMemories;
    private long               segmentPosMaskBit;
    private int                pos;
    private volatile LeftTupleSets      stagedLeftTuples;
    private boolean            active;
    private SegmentMemory      previous;
    private SegmentMemory      next;

    public SegmentMemory(NetworkNode rootNode) {
        this.rootNode = rootNode;
        this.pathMemories = new ArrayList<PathMemory>(1);
        this.nodeMemories = new LinkedList<Memory>();

        this.stagedLeftTuples = new LeftTupleSets();
    }

    public NetworkNode getRootNode() {
        return rootNode;
    }

    public NetworkNode getTipNode() {
        return tipNode;
    }

    public void setTipNode(NetworkNode tipNode) {
        this.tipNode = tipNode;
    }

    public LeftTupleSink getSinkFactory() {
        return (LeftTupleSink) rootNode;
    }

    public void setSinkFactory(LeftTupleSink sink) {
    }

    public Memory createNodeMemory(MemoryFactory memoryFactory,
                                   InternalWorkingMemory wm) {
        Memory memory = wm.getNodeMemory(memoryFactory);
        nodeMemories.add(memory);
        return memory;
    }

    public LinkedList<Memory> getNodeMemories() {
        return nodeMemories;
    }

    public long getLinkedNodeMask() {
        return linkedNodeMask;
    }

    public void setLinkedNodeMask(long linkedNodeMask) {
        this.linkedNodeMask = linkedNodeMask;
    }

    public String getRuleNames() {
        StringBuilder sbuilder = new StringBuilder();
        for (int i = 0; i < pathMemories.size(); i++) {
            if (i > 0) {
                sbuilder.append(", ");
            }
            sbuilder.append(pathMemories.get(i));
        }

        return sbuilder.toString();
    }

    public void linkNode(long mask,
                         InternalWorkingMemory wm) {
        linkedNodeMask = linkedNodeMask | mask;
        if (log.isTraceEnabled()) {
            log.trace("LinkNode notify=true nmask={} smask={} spos={} rules={}", mask, linkedNodeMask, pos, getRuleNames());
        }

        notifyRuleLinkSegment(wm);
    }

    public void linkNodeWithoutRuleNotify(long mask) {
        linkedNodeMask = linkedNodeMask | mask;

        if (log.isTraceEnabled()) {
            log.trace("LinkNode notify=false nmask={} smask={} spos={} rules={}", mask, linkedNodeMask, pos, getRuleNames());
        }

        if (isSegmentLinked()) {
            for (int i = 0, length = pathMemories.size(); i < length; i++) {
                // do not use foreach, don't want Iterator object creation
                pathMemories.get(i).linkNodeWithoutRuleNotify(segmentPosMaskBit);
            }
        }
    }

    public void notifyRuleLinkSegment(InternalWorkingMemory wm) {
        if (isSegmentLinked()) {
            for (int i = 0, length = pathMemories.size(); i < length; i++) {
                // do not use foreach, don't want Iterator object creation
                pathMemories.get(i).linkSegment(segmentPosMaskBit,
                                                wm);
            }
        }
    }

    public void unlinkNode(long mask,
                           InternalWorkingMemory wm) {
        if (log.isTraceEnabled()) {
            log.trace("UnlinkNode notify=true nmask={} smask={} spos={} rules={}", mask, linkedNodeMask, pos, getRuleNames());
        }

        // some node unlinking does not unlink the segment, such as nodes after a Branch CE
        boolean linked = isSegmentLinked();
        linkedNodeMask = linkedNodeMask ^ mask;
        if (linked) {
            for (int i = 0, length = pathMemories.size(); i < length; i++) {
                // do not use foreach, don't want Iterator object creation
                pathMemories.get(i).unlinkedSegment(segmentPosMaskBit,
                                                    wm);
            }
        }
    }

{'fraction_non_alphanumeric': 0.09193033082551788, 'fraction_numerical': 0.001752035452952695, 'mean_word_length': 2.180596525729269, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6541479', 'n_tokens_mistral': 2643, 'n_tokens_neox': 2561, 'n_words': 636}