/* * 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; /** * Abstract class to represent an Action. This could be either a migration or a * split (or any other action we choose to add later). This will include all * actions required from a node including exchanges, discards and renaming. */ public abstract class Action implements Serializable { /** * @param string * String representation of Action as produced by * {@link toString} * @return Action object. */ public static Action fromString(String string) { final String[] parts = string.split(" "); if (new String(parts[0]).equals(MIGRATION)) return new Migration(Integer.parseInt(new String(parts[1])), Integer.parseInt(new String(parts[2])), Integer.parseInt(new String(parts[3])), Integer.parseInt(new String(parts[4])), Integer.parseInt(new String(parts[5]))); else return null; } /** * */ private static final long serialVersionUID = 1L; protected static final String MIGRATION = "Migration"; protected static final String SPLIT = "Split"; // Total number of reducers protected int reducerCount; // Old and new reducer split dimensions. protected int previousRows, previousColumns; protected int newRows, newColumns; public Action(int reducerCount, int previousRows, int previousColumns, int newRows, int newColumns) { this.reducerCount = reducerCount; this.previousRows = previousRows; this.previousColumns = previousColumns; this.newRows = newRows; this.newColumns = newColumns; // Precompute all actions for all reducers. process(); } /* * (non-Javadoc) * * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object o) { if (o == null) return false; final Action action = (Action) o; return reducerCount == action.reducerCount && previousRows == action.previousRows && previousColumns == action.previousColumns && newRows == action.newRows && newColumns == action.newColumns; } /** * @param oldId * The current id given to the reducer before the action is * performed. * @return An array of the reducers that the input reducer should exchange * tuples (from the relation along the columns) with. If no * exchanges should happen, the array will be empty. */ protected abstract int[] getColumnExchangeReducers(int oldId); public int[] getColumnExchangeReducersByNewId(int newId) { final int[] result = getColumnExchangeReducers(getOldReducerName(newId)); final int[] modifiedResult = new int[result.length]; for (int i = 0; i < result.length; ++i) modifiedResult[i] = getNewReducerName(result[i]); return modifiedResult; } /** * @param oldId * The current id given to the reducer before the action is * performed. * @return Returns the index of the piece of the relation along the columns * that should be kept and not discarded. All other pieces should be * discarded. This is used with {@link getDiscardColumnSplits}. If * the relation is to be entirely kept, this will always return 0. */ protected abstract int getColumnKeptPieceIndex(int oldId); public int getColumnKeptPieceIndexByNewId(int newId) { return getColumnKeptPieceIndex(getOldReducerName(newId)); } /** * @return Returns the number of pieces that the reducer should split the * tuples from the relation along the columns into. This is used * with {@link getColumnKeptPieceIndex}. If the relation is to be * entirely kept, this will always return 1. */ public abstract int getDiscardColumnSplits(); /** * @return Returns the number of pieces that the reducer should split the * tuples from the relation along the rows into. This is used with * {@link getRowKeptPieceIndex}. If the relation is to be entirely * kept, this will always return 1. */ public abstract int getDiscardRowSplits(); /** * @return The number of column splits. */ public int getNewColumns() { return newColumns; } /** * @param oldId * The current id given to the reducer before the action is * performed. * @return The new id after the action is performed. This should be called * last after all other actions have been performed. */ public abstract int getNewReducerName(int oldId); /** * @return The number of row splits. */ public int getNewRows() { return newRows; } public abstract int getOldReducerName(int newId); /** * @return The number of column splits before performing the action. */ public int getPreviousColumns() { return previousColumns; } /** * @return The number of row splits before performing the action. */ public int getPreviousRows() { return previousRows; } /** * @param oldId * The current id given to the reducer before the action is * performed. * @return An array of the reducers that the input reducer should exchange * tuples (from the relation along the rows) with. If no exchanges * should happen, the array will be empty. */ protected abstract int[] getRowExchangeReducers(int oldId); public int[] getRowExchangeReducersByNewId(int newId) { final int[] result = getRowExchangeReducers(getOldReducerName(newId)); final int[] modifiedResult = new int[result.length]; for (int i = 0; i < result.length; ++i) modifiedResult[i] = getNewReducerName(result[i]); return modifiedResult; } /** * @param oldId * The current id given to the reducer before the action is * performed. * @return Returns the index of the piece of the relation along the rows * that should be kept and not discarded. All other pieces should be * discarded. This is used with {@link getDiscardRowSplits}. If the * relation is to be entirely kept, this will always return 0. */ protected abstract int getRowKeptPieceIndex(int oldId); public int getRowKeptPieceIndexByNewId(int newId) { return getRowKeptPieceIndex(getOldReducerName(newId)); } /** * This is where all the precomputation of actions goes. */ protected abstract void process(); /* * (non-Javadoc) * * @see java.lang.Object#toString() */ @Override public String toString() { return getNewRows() + "," + getNewColumns(); } }