<commit_before>package graphcreation.collisionbased;

import graphcreation.GraphCreationListener;
import graphcreation.GraphCreator;
import graphcreation.GraphCreator.GraphType;
import graphcreation.collisionbased.collisiondetector.Collision;
import graphcreation.collisionbased.collisiondetector.CollisionDetector;
import graphcreation.collisionbased.connectionManager.Connection;
import graphcreation.collisionbased.connectionManager.ConnectionsManager;
import graphcreation.collisionbased.message.CollisionResponseMessage;
import graphcreation.collisionbased.message.ConnectServicesMessage;
import graphcreation.collisionbased.message.DisconnectServicesMessage;
import graphcreation.collisionbased.message.InhibeCollisionsMessage;
import graphcreation.collisionbased.message.Inhibition;
import graphcreation.collisionbased.message.RemovedServicesMessage;
import graphcreation.graph.extendedServiceGraph.ExtendedServiceGraph;
import graphcreation.graph.servicegraph.node.ServiceNode;
import graphcreation.services.Service;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import multicast.SearchedParameter;
import multicast.search.message.SearchMessage.SearchType;
import multicast.search.message.SearchResponseMessage;
import peer.Peer;
import peer.message.PayloadMessage;
import peer.peerid.PeerID;
import peer.peerid.PeerIDSet;
import taxonomy.parameter.Parameter;
import util.logger.Logger;
import dissemination.DistanceChange;
import dissemination.ParameterDisseminator;

class CollisionNode {
	
	private final Peer peer;
	
	private final GraphCreator gCreator;
	
	private final GraphCreationListener graphCreationListener;
	
	private final Logger logger = Logger.getLogger(CollisionNode.class);
	
	// the connections manager
	private final ConnectionsManager cManager;
	
	public CollisionNode(final Peer peer, final GraphCreator gCreator, final GraphCreationListener graphCreationListener, final GraphType graphType) {
		this.peer = peer;
		this.gCreator = gCreator;
		this.graphCreationListener = graphCreationListener;
		this.cManager = new ConnectionsManager(gCreator.getPSearch().getDisseminationLayer().getTaxonomy(), graphType);
	}

	public PayloadMessage parametersChanged(final PeerID sender, final Set<Parameter> addedParameters, final Set<Parameter> removedParameters, final Map<Parameter, DistanceChange> changedParameters, final List<PayloadMessage> payloadMessages) {
		logger.trace("Peer " + peer.getPeerID() + " parameters table changed");
		final Set<Inhibition> inhibitions = new HashSet<Inhibition>();
		final Set<Collision> collisions = new HashSet<Collision>();
		
		if (!removedParameters.isEmpty()) {	
			logger.trace("Peer " + peer.getPeerID() + " parameters removed " + removedParameters + ", checking for affected collisions");

			// obtain which previously detected collisions are affected by
			// parameter removal
			final Set<Connection> removedConnections = cManager.checkCollisions(removedParameters);
	
			if (!removedConnections.isEmpty()) {
				// obtain those parameters whose search must be canceled
				final Set<Parameter> canceledParameters = new HashSet<Parameter>();
				for (final Connection connection : removedConnections) {
					final Collision collision = connection.getCollision();
					canceledParameters.add(collision.getInput());
					canceledParameters.add(collision.getOutput());
				}
	
				// send cancel search message
				gCreator.getPSearch().sendCancelSearchMessage(canceledParameters);
			}	
		}
		
		if (!addedParameters.isEmpty()) {
			logger.trace("Peer " + peer.getPeerID() + " new parameters added " + addedParameters + ", checking for collisions");

			// obtain which collisions are caused by the new parameters addition
			collisions.addAll(checkParametersCollisions(addedParameters, sender));
			
			processCollisions(sender, inhibitions, collisions);
		}

		if (!changedParameters.isEmpty()) {
			logger.trace("Peer " + peer.getPeerID() + " parameters estimated distance changed");
			
			Set<Collision> detectedCollisions = checkParametersCollisions(changedParameters.keySet(), sender);
			
			//remove already detected collisions
			//TODO improve with taxonomy checking
			synchronized (cManager) {
				for (final Iterator<Collision> it = detectedCollisions.iterator(); it.hasNext(); ) {
					Collision detectedCollision = it.next();
					if (cManager.contains(detectedCollision))
						it.remove();
				}
			}
			
			processCollisions(sender, inhibitions, collisions);
		}

		// include those inhibitions received with the message which added the
		// new parameters
		for (final PayloadMessage payload : payloadMessages) {
			final InhibeCollisionsMessage inhibeCollisionsMessage = (InhibeCollisionsMessage) payload;
			logger.trace("Peer " + peer.getPeerID() + " received inhibitions for collisions " + inhibeCollisionsMessage.getInhibedCollisions());

			// remove collisions using received inhibitions (checking if collision is applied)
			for (Inhibition inhibedCollision : inhibeCollisionsMessage.getInhibedCollisions()) {
				if (!inhibedCollision.getNotAppliedTo().equals(peer.getPeerID()))
					collisions.remove(inhibedCollision.getCollision());
			}
			
			logger.trace("Peer " + peer.getPeerID() + " provisional collisions after inhibition " + collisions);
				
			inhibitions.addAll(inhibeCollisionsMessage.getInhibedCollisions());
		}

		// if collisions were detected, notify them
		if (!collisions.isEmpty()) {
			logger.trace("Peer " + peer.getPeerID() + " detected collisions " + collisions);

			// Update the collisions detected by the current node
			synchronized (cManager) {
				for (final Collision collision : collisions)
					cManager.addConnection(collision);
			}

			// send a message to search for the colliding parameters
			sendCollisionSearchMessage(collisions);
		}

		// if collisions were detected return them as payload for parameter
		// table update propagated message
		if (!inhibitions.isEmpty()) {
			logger.trace("Peer " + peer.getPeerID() + " sending inhibitions " + inhibitions + " as parameter table payload");
			return new InhibeCollisionsMessage(peer.getPeerID(), inhibitions);
		}

		return null;
	}
	
	private int[] getTTL(final Collision collision) {
		final int[] ttls = new int[2];
		final int iDistance = gCreator.getPSearch().getDisseminationLayer().getDistanceTo(collision.getInput());
		logger.trace("Peer " + peer.getPeerID() + " distance to " + collision.getInput() + ": " + iDistance);
		final int oDistance = gCreator.getPSearch().getDisseminationLayer().getDistanceTo(collision.getOutput());
		logger.trace("Peer " + peer.getPeerID() + " distance to " + collision.getOutput() + ": " + oDistance);
		final int maxTTL = 2 * gCreator.getPSearch().getDisseminationLayer().getMaxDistance() - 2;
		ttls[0] = maxTTL - oDistance;
		ttls[1] = maxTTL - iDistance;
		return ttls; 
	}

	private void sendCollisionSearchMessage(final Set<Collision> collisions) {<commit_msg> * Search TTL calculation changed.<commit_after>package graphcreation.collisionbased;

import graphcreation.GraphCreationListener;
import graphcreation.GraphCreator;
import graphcreation.GraphCreator.GraphType;
import graphcreation.collisionbased.collisiondetector.Collision;
import graphcreation.collisionbased.collisiondetector.CollisionDetector;
import graphcreation.collisionbased.connectionManager.Connection;
import graphcreation.collisionbased.connectionManager.ConnectionsManager;
import graphcreation.collisionbased.message.CollisionResponseMessage;
import graphcreation.collisionbased.message.ConnectServicesMessage;
import graphcreation.collisionbased.message.DisconnectServicesMessage;
import graphcreation.collisionbased.message.InhibeCollisionsMessage;
import graphcreation.collisionbased.message.Inhibition;
import graphcreation.collisionbased.message.RemovedServicesMessage;
import graphcreation.graph.extendedServiceGraph.ExtendedServiceGraph;
import graphcreation.graph.servicegraph.node.ServiceNode;
import graphcreation.services.Service;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import multicast.SearchedParameter;
import multicast.search.message.SearchMessage.SearchType;
import multicast.search.message.SearchResponseMessage;
import peer.Peer;
import peer.message.PayloadMessage;
import peer.peerid.PeerID;
import peer.peerid.PeerIDSet;
import taxonomy.parameter.Parameter;
import util.logger.Logger;
import dissemination.DistanceChange;
import dissemination.ParameterDisseminator;

class CollisionNode {
	
	private final Peer peer;
	
	private final GraphCreator gCreator;
	
	private final GraphCreationListener graphCreationListener;
	
	private final Logger logger = Logger.getLogger(CollisionNode.class);
	
	// the connections manager
	private final ConnectionsManager cManager;
	
	public CollisionNode(final Peer peer, final GraphCreator gCreator, final GraphCreationListener graphCreationListener, final GraphType graphType) {
		this.peer = peer;
		this.gCreator = gCreator;
		this.graphCreationListener = graphCreationListener;
		this.cManager = new ConnectionsManager(gCreator.getPSearch().getDisseminationLayer().getTaxonomy(), graphType);
	}

	public PayloadMessage parametersChanged(final PeerID sender, final Set<Parameter> addedParameters, final Set<Parameter> removedParameters, final Map<Parameter, DistanceChange> changedParameters, final List<PayloadMessage> payloadMessages) {
		logger.trace("Peer " + peer.getPeerID() + " parameters table changed");
		final Set<Inhibition> inhibitions = new HashSet<Inhibition>();
		final Set<Collision> collisions = new HashSet<Collision>();
		
		if (!removedParameters.isEmpty()) {	
			logger.trace("Peer " + peer.getPeerID() + " parameters removed " + removedParameters + ", checking for affected collisions");

			// obtain which previously detected collisions are affected by
			// parameter removal
			final Set<Connection> removedConnections = cManager.checkCollisions(removedParameters);
	
			if (!removedConnections.isEmpty()) {
				// obtain those parameters whose search must be canceled
				final Set<Parameter> canceledParameters = new HashSet<Parameter>();
				for (final Connection connection : removedConnections) {
					final Collision collision = connection.getCollision();
					canceledParameters.add(collision.getInput());
					canceledParameters.add(collision.getOutput());
				}
	
				// send cancel search message
				gCreator.getPSearch().sendCancelSearchMessage(canceledParameters);
			}	
		}
		
		if (!addedParameters.isEmpty()) {
			logger.trace("Peer " + peer.getPeerID() + " new parameters added " + addedParameters + ", checking for collisions");

			// obtain which collisions are caused by the new parameters addition
			collisions.addAll(checkParametersCollisions(addedParameters, sender));
			
			processCollisions(sender, inhibitions, collisions);
		}

		if (!changedParameters.isEmpty()) {
			logger.trace("Peer " + peer.getPeerID() + " parameters estimated distance changed");
			
			Set<Collision> detectedCollisions = checkParametersCollisions(changedParameters.keySet(), sender);
			
			//remove already detected collisions
			//TODO improve with taxonomy checking
			synchronized (cManager) {
				for (final Iterator<Collision> it = detectedCollisions.iterator(); it.hasNext(); ) {
					Collision detectedCollision = it.next();
					if (cManager.contains(detectedCollision))
						it.remove();
				}
			}
			
			processCollisions(sender, inhibitions, collisions);
		}

		// include those inhibitions received with the message which added the
		// new parameters
		for (final PayloadMessage payload : payloadMessages) {
			final InhibeCollisionsMessage inhibeCollisionsMessage = (InhibeCollisionsMessage) payload;
			logger.trace("Peer " + peer.getPeerID() + " received inhibitions for collisions " + inhibeCollisionsMessage.getInhibedCollisions());

			// remove collisions using received inhibitions (checking if collision is applied)
			for (Inhibition inhibedCollision : inhibeCollisionsMessage.getInhibedCollisions()) {
				if (!inhibedCollision.getNotAppliedTo().equals(peer.getPeerID()))
					collisions.remove(inhibedCollision.getCollision());
			}
			
			logger.trace("Peer " + peer.getPeerID() + " provisional collisions after inhibition " + collisions);
				
			inhibitions.addAll(inhibeCollisionsMessage.getInhibedCollisions());
		}

		// if collisions were detected, notify them
		if (!collisions.isEmpty()) {
			logger.trace("Peer " + peer.getPeerID() + " detected collisions " + collisions);

			// Update the collisions detected by the current node
			synchronized (cManager) {
				for (final Collision collision : collisions)
					cManager.addConnection(collision);
			}

			// send a message to search for the colliding parameters
			sendCollisionSearchMessage(collisions);
		}

		// if collisions were detected return them as payload for parameter
		// table update propagated message
		if (!inhibitions.isEmpty()) {
			logger.trace("Peer " + peer.getPeerID() + " sending inhibitions " + inhibitions + " as parameter table payload");
			return new InhibeCollisionsMessage(peer.getPeerID(), inhibitions);
		}

		return null;
	}
	
	private int[] getTTL(final Collision collision) {
		final int[] ttls = new int[2];
		final int iDistance = gCreator.getPSearch().getDisseminationLayer().getDistanceTo(collision.getInput());
		logger.trace("Peer " + peer.getPeerID() + " distance to " + collision.getInput() + ": " + iDistance);
		final int oDistance = gCreator.getPSearch().getDisseminationLayer().getDistanceTo(collision.getOutput());
		logger.trace("Peer " + peer.getPeerID() + " distance to " + collision.getOutput() + ": " + oDistance);
		ttls[0] = gCreator.getPSearch().getDisseminationLayer().getMaxDistance() - oDistance;
		ttls[1] = gCreator.getPSearch().getDisseminationLayer().getMaxDistance() - iDistance;
		return ttls; 
	}

	private void sendCollisionSearchMessage(final Set<Collision> collisions) {
{'fraction_non_alphanumeric': 0.09744861800141744, 'fraction_numerical': 0.0005669737774627923, 'mean_word_length': 5.396645512239347, 'pattern_counts': {'":': 4, '<': 31, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5319937', 'n_tokens_mistral': 4253, 'n_tokens_neox': 3688, 'n_words': 888}