<commit_before>package at.irian.ankor.switching.routing;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Multimap;

import java.util.Collection;

/**
 * A thread-safe AND concurrent-modification-safe RoutingTable.
 * @author <NAME>
 */
public class ConcurrentRoutingTable implements RoutingTable {
    //private static final org.slf4j.Logger LOG = org.slf4j.LoggerFactory.getLogger(RoutingTable.class);

    private volatile ImmutableSetMultimap<ModelAddress, ModelAddress> connections = ImmutableSetMultimap.of();

    @Override
    public boolean connect(ModelAddress a, ModelAddress b) {
        if (a == null) {
            throw new NullPointerException("ModelAddress a");
        }
        if (b == null) {
            throw new NullPointerException("ModelAddress b");
        }

        if (!isConnected(a, b)) {
            connections = ImmutableSetMultimap.<ModelAddress, ModelAddress>builder()
                                              .putAll(connections)
                                              .put(a, b)
                                              .put(b, a)
                                              .build();
            return true;
        } else {
            return false;
        }
    }

    @Override
    public boolean disconnect(ModelAddress a, ModelAddress b) {
        if (a == null) {
            throw new NullPointerException("ModelAddress a");
        }
        if (b == null) {
            throw new NullPointerException("ModelAddress b");
        }

        if (isConnected(a, b)) {
            Multimap<ModelAddress, ModelAddress> mutable = HashMultimap.create(connections);
            mutable.remove(a, b);
            mutable.remove(b, a);
            connections = ImmutableSetMultimap.copyOf(mutable);
            return true;
        } else {
            return false;
        }
    }

    @Override
    public boolean isConnected(ModelAddress a, ModelAddress b) {
        if (a == null) {
            throw new NullPointerException("ModelAddress a");
        }
        if (b == null) {
            throw new NullPointerException("ModelAddress b");
        }

        return connections.containsEntry(a, b);
    }

    @Override
    public boolean disconnectAll(ModelAddress a) {
        if (a == null) {
            throw new NullPointerException("ModelAddress a");
        }

        Collection<ModelAddress> addresses = connections.get(a);
        if (!addresses.isEmpty()) {
            for (ModelAddress b : addresses) {
                disconnect(a, b);
            }
            return true;
        } else {
            return false;
        }
    }


    @Override
    public Collection<ModelAddress> getConnectedAddresses(ModelAddress modelAddress) {
        if (modelAddress == null) {
            throw new NullPointerException("modelAddress");
        }

        return connections.get(modelAddress);
    }

    @Override
    public boolean hasConnectedAddresses(ModelAddress modelAddress) {
        if (modelAddress == null) {
            throw new NullPointerException("modelAddress");
        }

        Collection<ModelAddress> addresses = connections.get(modelAddress);
        return !addresses.isEmpty();
    }

    @Override
    public Collection<ModelAddress> getAllConnectedAddresses() {
        return connections.keySet();
    }

    @Override
    public void clear() {
        connections = ImmutableSetMultimap.of();
    }
}<commit_msg>fixed concurrency issue in ConcurrentRoutingTable<commit_after>package at.irian.ankor.switching.routing;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Multimap;

import java.util.Collection;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * A thread-safe AND concurrent-modification-safe RoutingTable.
 * @author <NAME>
 */
public class ConcurrentRoutingTable implements RoutingTable {
    //private static final org.slf4j.Logger LOG = org.slf4j.LoggerFactory.getLogger(RoutingTable.class);

    private volatile ImmutableSetMultimap<ModelAddress, ModelAddress> connections = ImmutableSetMultimap.of();
    private Lock writeLock = new ReentrantLock();

    @Override
    public boolean connect(ModelAddress a, ModelAddress b) {
        if (a == null) {
            throw new NullPointerException("ModelAddress a");
        }
        if (b == null) {
            throw new NullPointerException("ModelAddress b");
        }

        if (!isConnected(a, b)) {
            writeLock.lock();
            try {
                connections = ImmutableSetMultimap.<ModelAddress, ModelAddress>builder()
                                                  .putAll(connections)
                                                  .put(a, b)
                                                  .put(b, a)
                                                  .build();
            } finally {
                writeLock.unlock();
            }
            return true;
        } else {
            return false;
        }
    }

    @Override
    public boolean disconnect(ModelAddress a, ModelAddress b) {
        if (a == null) {
            throw new NullPointerException("ModelAddress a");
        }
        if (b == null) {
            throw new NullPointerException("ModelAddress b");
        }

        if (isConnected(a, b)) {
            writeLock.lock();
            try {
                Multimap<ModelAddress, ModelAddress> mutable = HashMultimap.create(connections);
                mutable.remove(a, b);
                mutable.remove(b, a);
                connections = ImmutableSetMultimap.copyOf(mutable);
            } finally {
                writeLock.unlock();
            }
            return true;
        } else {
            return false;
        }
    }

    @Override
    public boolean isConnected(ModelAddress a, ModelAddress b) {
        if (a == null) {
            throw new NullPointerException("ModelAddress a");
        }
        if (b == null) {
            throw new NullPointerException("ModelAddress b");
        }

        return connections.containsEntry(a, b);
    }

    @Override
    public boolean disconnectAll(ModelAddress a) {
        if (a == null) {
            throw new NullPointerException("ModelAddress a");
        }

        Collection<ModelAddress> addresses = connections.get(a);
        if (!addresses.isEmpty()) {
            for (ModelAddress b : addresses) {
                disconnect(a, b);
            }
            return true;
        } else {
            return false;
        }
    }


    @Override
    public Collection<ModelAddress> getConnectedAddresses(ModelAddress modelAddress) {
        if (modelAddress == null) {
            throw new NullPointerException("modelAddress");
        }

        return connections.get(modelAddress);
    }

    @Override
    public boolean hasConnectedAddresses(ModelAddress modelAddress) {
        if (modelAddress == null) {
            throw new NullPointerException("modelAddress");
        }

        Collection<ModelAddress> addresses = connections.get(modelAddress);
        return !addresses.isEmpty();
    }

    @Override
    public Collection<ModelAddress> getAllConnectedAddresses() {
        return connections.keySet();
    }

    @Override
    public void clear() {
        writeLock.lock();
        try {
            connections = ImmutableSetMultimap.of();
        } finally {
            writeLock.unlock();
        }
    }
}
{'fraction_non_alphanumeric': 0.09476045928467731, 'fraction_numerical': 0.0005279134221987594, 'mean_word_length': 1.8671963677639047, 'pattern_counts': {'":': 0, '<': 19, '<?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': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7395659', 'n_tokens_mistral': 1934, 'n_tokens_neox': 1888, 'n_words': 433}