/*
* Copyright (c) 2011-2015 EPFL DATA Laboratory
* Copyright (c) 2014-2015 The Squall Collaboration (see NOTICE)
*
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.epfl.data.squall.thetajoin.adaptive.advisor;
import java.io.Serializable;
import java.util.Random;
/**
* Advisor class that provides decision s on reducer assignment.
*/
public abstract class Advisor implements Serializable {
public static int[] getAssignedReducers(boolean isRow, int reducerCount,
int currentRows, int currentColumns) {
int[] result;
int k = 0;
final int reducersPerGroup = reducerCount / currentRows
/ currentColumns;
if (isRow) {
final int row = gen.nextInt(currentRows);
result = new int[currentColumns * reducersPerGroup];
for (int g = row * currentColumns; g < (row + 1) * currentColumns; ++g)
for (int i = 0; i < reducersPerGroup; ++i)
result[k++] = g * reducersPerGroup + i;
} else {
final int column = gen.nextInt(currentColumns);
result = new int[currentRows * reducersPerGroup];
for (int g = column; g < currentRows * currentColumns; g += currentColumns)
for (int i = 0; i < reducersPerGroup; ++i)
result[k++] = g * reducersPerGroup + i;
}
return result;
}
public static boolean isLeader(int reducerCount, int currentRows,
int currentColumns, int id) {
final int machinesPerGroup = reducerCount / currentColumns
/ currentRows;
return id % machinesPerGroup == 0;
}
/**
*
*/
private static final long serialVersionUID = 1L;
/* Counters */
// Total number of reducers.
protected int reducerCount;
// Current dimensions of the reducer assignment matrix.
protected int currentRows, currentColumns;
// Total number of tuples along the row and the column.
public long totalRowTuples, totalColumnTuples;
protected long deltaR, deltaS;
/**
* Randomized function that returns the ids of the reducers that should
* receive and input tuple.
*
* @param isRow
* True if the input tuple is from the relation along the rows,
* false otherwise.
* @param reducerCount
* Total number of reducers.
* @param currentRows
* Number of rows in the matrix.
* @param currentColumns
* Number of columns in the matrix.
* @return Ids of the reducers that should receive the tuples.
*/
private static Random gen = new Random();
/**
* Use this constructor to start with the default initial assignment.
*
* @param reducerCount
* Total number of reducers.
*/
public Advisor(int reducerCount) {
this(reducerCount, 1, 1);
}
/**
* Use this constructor when you want to start with a specific input matrix.
*
* @param reducerCount
* Total number of reducers.
* @param initialRows
* Number of row splits.
* @param initialColumns
* Number of column splits.
*/
public Advisor(int reducerCount, int initialRows, int initialColumns) {
this.reducerCount = reducerCount;
currentRows = initialRows;
currentColumns = initialColumns;
}
/**
* This is the main method to call. This returns the action to be taken.
*
* @return The action to take.
*/
public Maybe<Action> advise() {
if (currentRows * currentColumns < reducerCount)
// In splitting phase
return doSplit();
else
// Splitting is done, consider migration.
return doMigration();
}
/**
* Same as {@link advise} but also updates the matrix assignment.
*
* @return The action to take.
*/
public Maybe<Action> adviseAndUpdateDimensions() {
final Maybe<Action> result = advise();
if (!result.isNone())
updateMapping(result.get());
return result;
}
protected abstract Maybe<Action> doMigration();
protected abstract Maybe<Action> doSplit();
/**
* @param action
* The action including the new dimensions.
*/
public void updateMapping(Action action) {
currentRows = action.getNewRows();
currentColumns = action.getNewColumns();
}
/**
* This updates the instance with the arrival of tuples.
*
* @param rowTuples
* Number of tuples from the relation along the rows.
* @param columnTuples
* Number of tuples from the relation along the columns.
*/
public void updateTuples(long rowTuples, long columnTuples) {
totalRowTuples += rowTuples;
deltaR += rowTuples;
totalColumnTuples += columnTuples;
deltaS += columnTuples;
}
}