/*******************************************************************************
* Copyright (c) 2013 Imperial College London.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Raul Castro Fernandez - initial design and implementation
* Martin Rouaux - Added methods to collapse replicas
******************************************************************************/
package uk.ac.imperial.lsds.seep.comm.routing;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class StatelessRoutingImpl implements RoutingStrategyI, Serializable{
private static final Logger LOG = LoggerFactory.getLogger(StatelessRoutingImpl.class);
private static final long serialVersionUID = 1L;
private int splitWindow = 0;
private int target = 0;
private int downstreamIndex = 0;
private int remainingWindow = 0;
private int numberOfDownstreams = 0;
//This structure maps the real indexes (where is a given downstream) with the virtual index (where is a downstream within the set of downstream of same type
// so map virtual integer with real integer
/// \todo{consider change this structure to arraylist}
private HashMap<Integer, Integer> virtualIndexToRealIndex = new HashMap<Integer, Integer>();
private int virtualIndex = 0;
// public void setNumberOfDownstreams(int numberOfDownstreams){
// this.numberOfDownstreams = numberOfDownstreams;
// }
public StatelessRoutingImpl(int splitWindow, int index, int numOfDownstreams){
//this.splitWindow = splitWindow-1;
this.splitWindow = splitWindow;
//Map the virtual index with the real index
virtualIndexToRealIndex.put(virtualIndex, index);
virtualIndex++;
this.numberOfDownstreams = numOfDownstreams;
}
@Override
public synchronized ArrayList<Integer> route(ArrayList<Integer> targets, int value){
int targetRealIndex = -1;
if(remainingWindow == 0){
//Reinitialize the window size
remainingWindow = splitWindow;
// update target and reinitialize filterValue
target = downstreamIndex++%numberOfDownstreams;
//System.out.println("NUM DOWNSTR: "+numberOfDownstreams);
//System.out.println("Down INDEX: "+downstreamIndex);
//System.out.println("Target: "+target);
// System.out.println("Real routing info is: ");
// for(Entry<Integer, Integer> entry : virtualIndexToRealIndex.entrySet()){
// System.out.println("VirtualIdx: "+entry.getKey()+" RealIdx: "+entry.getValue());
// }
// System.out.println("And we are asking for: "+target);
targetRealIndex = virtualIndexToRealIndex.get(target);
//System.out.println("NW routeStrem add realIndex: "+targetRealIndex );
//If the index was not present in the targets list, add it.
if(!targets.contains(targetRealIndex)){
targets.add(targetRealIndex);
}
//System.out.println("NoWindow: targets-size: "+targets.size());
return targets;
}
remainingWindow--;
/// \todo Return the real Index, got from the virtual one. Optimize this
// for(Entry<Integer, Integer> entry : virtualIndexToRealIndex.entrySet()){
// System.out.println("vidx: "+entry.getKey()+" ridx: "+entry.getValue());
// }
targetRealIndex = virtualIndexToRealIndex.get(target);
//System.out.println("W routeStrem add realIndex: "+virtualIndexToRealIndex.get(target));
if(!targets.contains(targetRealIndex)){
targets.add(targetRealIndex);
}
//System.out.println("Window: targets-size: "+targets.size());
return targets;
}
//overriden to make ANY faster...
@Override
public synchronized ArrayList<Integer> route(int value){
//System.out.println("Rem window: "+remainingWindow);
//System.out.println("splitWindow: "+splitWindow);
ArrayList<Integer> targets = new ArrayList<Integer>();
if(remainingWindow == 0){
//Reinitialize the window size
remainingWindow = splitWindow;
// update target and reinitialize filterValue
target = downstreamIndex++%numberOfDownstreams;
// get the real index from the virtual one.
//target = virtualIndexToRealIndex.get(target);
//System.out.println("target: "+target);
//System.out.println("numberOfDownstreams: "+numberOfDownstreams);
targets.add(target);
return targets;
}
remainingWindow--;
/// \todo Return the real Index, got from the virtual one. Optimize this
//target = virtualIndexToRealIndex.get(target);
//System.out.println("Target: "+target);
targets.add(target);
return targets;
}
@Override
public synchronized int[] newReplica(int oldOpIndex, int newOpIndex) {
//In this case oldOpIndex does not do anything
//System.out.println("#### There is a NEW SPLIT here, newOpIndex: "+newOpIndex);
//First of all, we map the real index to virtual index
//System.out.println("MAPPING virtualIndex: "+virtualIndex+" to realIndex: "+newOpIndex);
virtualIndexToRealIndex.put(virtualIndex, newOpIndex);
virtualIndex++;
//Update the number of downstreams
//System.out.println("PREV: "+numberOfDownstreams);
numberOfDownstreams++;
//System.out.println("POST: "+numberOfDownstreams);
//return something cause interface implementation...
//return -1;
int[] fakeKeys = {-1, -1};
return fakeKeys;
}
/**
* Collapses an existing replica and ensures that no more tuples are routed
* @param opIndex
* @return
*/
@Override
public synchronized int[] collapseReplica(int opIndex) {
numberOfDownstreams--;
virtualIndex--;
HashMap<Integer, Integer> copyVirtualIndexToRealIndex = new HashMap<Integer, Integer>();
// Just copy every virtual to real index mapping, except for the
// one corresponding to the replica being collapsed.
int newVirtualIndex = 0;
for(Integer virtualIndex : virtualIndexToRealIndex.keySet()) {
Integer realIndex = virtualIndexToRealIndex.get(virtualIndex);
if (!realIndex.equals(opIndex)) {
copyVirtualIndexToRealIndex.put(newVirtualIndex, realIndex);
newVirtualIndex++;
}
}
// Now we replace the map with the new one, excluding the collapsed replica
virtualIndexToRealIndex = copyVirtualIndexToRealIndex;
// Close window to force the router to calculate the target operator for tuples
remainingWindow = 0;
int[] fakeKeys = {-1, -1};
return fakeKeys;
}
@Override
public synchronized int[] newStaticReplica(int oldOpIndex, int newOpIndex){
//In this case oldOpIndex does not do anything
//First of all, we map the real index to virtual index
virtualIndexToRealIndex.put(virtualIndex, newOpIndex);
virtualIndex++;
numberOfDownstreams++;
///\fixme{return something meaningful}
int[] fakeKeys = {-1, -1};
return fakeKeys;
}
@Override
public synchronized int[] collapseStaticReplica(int opIndex) {
return collapseReplica(opIndex);
}
@Override
public synchronized ArrayList<Integer> routeToAll(ArrayList<Integer> targets) {
return new ArrayList<Integer>(virtualIndexToRealIndex.values());
}
@Override
public synchronized ArrayList<Integer> routeToAll() {
ArrayList<Integer> targets = new ArrayList<Integer>();
return routeToAll(targets);
}
}