private static int IndividualSelect(DistributionMatrix bMatrix) { for (int i = 0; i < bMatrix.MatrixDimension.Rows; i++) { long rowWeight = bMatrix.WeightPercentMatrix[i, 0]; if (rowWeight == bMatrix.PercentWeightToSacrifice) { return(i); //this row; } //Lets see if if required data is within +- of cushion factor if (rowWeight < bMatrix.PercentWeightToSacrifice) { rowWeight += bMatrix.CushionFactor; if (rowWeight >= bMatrix.PercentWeightToSacrifice) { return(i); //this row } } else { rowWeight -= bMatrix.CushionFactor; if (rowWeight <= bMatrix.PercentWeightToSacrifice) { return(i); //this row } } } return(-1); //We got no single row that can be selected under required criteria }
public DistributionData(ArrayList hashMap, Hashtable bucketStatistics, ArrayList members, ILogger NCacheLog, long cacheSizePerNode) { _members = members; int memberCount = _members.Count; _hashMapData = new ArrayList(memberCount); _cacheDataSum = 1; ArrayList _weightIdList = new ArrayList(); for (int i = 0; i < DistributionManager.TotalBuckets; i++) { HashMapBucket hmapBuck = (HashMapBucket)hashMap[i]; BucketStatistics buckStats = (BucketStatistics)bucketStatistics[i]; if (buckStats == null) { buckStats = new BucketStatistics(); } //Catering for situations when two nodes are balancing and a new node joins in OR // two nodes joins one after the other, first one started state transfer while second jumped in. if (hmapBuck.Status != BucketStatus.UnderStateTxfr) //include only those buckets that are Functional/NeedStateTr { //We are selecting buckets based on temp address; although it is possible that these buckets //might have not been transfered to TEMP owner but algorithm consider these are owned by TEMP owner. WeightIdPair listItem = new WeightIdPair(hmapBuck.BucketId, buckStats.DataSize, hmapBuck.TempAddress); _weightIdList.Add(listItem); } _cacheDataSum += buckStats.DataSize; //Lets get the TOTAL weight of the cluster. } if (NCacheLog.IsInfoEnabled) { NCacheLog.Info("DistributionData()", "cacheDataSum = " + _cacheDataSum.ToString()); } //Initialize the two very important data pieces. All distribution is based on this. _bucketsPerNode = DistributionManager.TotalBuckets / (memberCount + 1); _weightPerNode = _cacheDataSum / (memberCount + 1); _distMatrixForNodes = new ArrayList(memberCount); long maxCacheSize = cacheSizePerNode * memberCount; //in bytes..CacheSize/node is the one user has entered while creating the cluster foreach (Address mbr in _members) { DistributionMatrix distMatrix = new DistributionMatrix(_weightIdList, mbr, this, NCacheLog); distMatrix.MaxCacheSize = maxCacheSize; _distMatrixForNodes.Add(distMatrix); } }
//All 2-tuples of the given set. Set is array of %weights against each row. private static ArrayList CandidateTuples(DistributionMatrix bMatrix) { // here we'll have n choose r scenario. Where we need to choose all possible pairs from the given set // for n choose r int n = bMatrix.MatrixDimension.Rows; int r = 2; int tupleCount = (int)(Factorial(n) / (Factorial(r) * Factorial(n - r))); ArrayList listTuples = new ArrayList(tupleCount); for (int i = 0; i < bMatrix.MatrixDimension.Rows; i++) { for (int j = i + 1; j < bMatrix.MatrixDimension.Rows; j++) listTuples.Add(new Tuple(i, j)); } return listTuples; }
//Backbone to be written now.//Two arrays ....both need to give a right combination against required weight. private static RowsBalanceResult BalanceWeight(Tuple rowPair, DistributionMatrix bMatrix) { BalanceAction balAction = new BalanceAction(); long weightToMove = 0; long primaryRowWeight = bMatrix.WeightPercentMatrix[rowPair.First, 0]; long secondaryRowWeight = bMatrix.WeightPercentMatrix[rowPair.Second, 0]; if (primaryRowWeight < bMatrix.PercentWeightToSacrifice) // { weightToMove = bMatrix.PercentWeightToSacrifice - primaryRowWeight; weightToMove = (weightToMove * bMatrix.TotalWeight) / 100; balAction = BalanceAction.GainWeight; } else { weightToMove = primaryRowWeight - bMatrix.PercentWeightToSacrifice; weightToMove = (weightToMove * bMatrix.TotalWeight) / 100; balAction = BalanceAction.LoseWeight; } long[] primaryRowData = new long[bMatrix.MatrixDimension.Cols]; long[] secondaryRowData = new long[bMatrix.MatrixDimension.Cols]; //Fills the local copy of two rows to be manipulated for (int i = 0; i < bMatrix.MatrixDimension.Cols; i++) { primaryRowData[i] = bMatrix.Matrix[rowPair.First, i]; secondaryRowData[i] = bMatrix.Matrix[rowPair.Second, i]; } RowsBalanceResult rbResult = null; switch (balAction) { case BalanceAction.GainWeight: rbResult = RowBalanceGainWeight(rowPair, primaryRowData, secondaryRowData, weightToMove, bMatrix); break; case BalanceAction.LoseWeight: rbResult = RowBalanceLoseWeight(rowPair, weightToMove, bMatrix); break; default: break; } return(rbResult); }
public DistributionData(ArrayList hashMap, Hashtable bucketStatistics, ArrayList members, ILogger NCacheLog, long cacheSizePerNode) { _members = members; int memberCount = _members.Count; _hashMapData = new ArrayList(memberCount); _cacheDataSum = 1; ArrayList _weightIdList = new ArrayList(); for (int i = 0; i < DistributionManager.TotalBuckets; i++) { HashMapBucket hmapBuck = (HashMapBucket)hashMap[i]; BucketStatistics buckStats = (BucketStatistics)bucketStatistics[i]; //Catering for situations when two nodes are balancing and a new node joins in OR // two nodes joins one after the other, first one started state transfer while second jumped in. if (hmapBuck.Status != BucketStatus.UnderStateTxfr) //include only those buckets that are Functional/NeedStateTr { //We are selecting buckets based on temp address; although it is possible that these buckets //might have not been transfered to TEMP owner but algorithm consider these are owned by TEMP owner. WeightIdPair listItem = new WeightIdPair(hmapBuck.BucketId, buckStats.DataSize, hmapBuck.TempAddress); _weightIdList.Add(listItem); } _cacheDataSum += buckStats.DataSize; //Lets get the TOTAL weight of the cluster. } if (NCacheLog.IsInfoEnabled) NCacheLog.Info("DistributionData()", "cacheDataSum = " + _cacheDataSum.ToString()); //Initialize the two very important data pieces. All distribution is based on this. _bucketsPerNode = DistributionManager.TotalBuckets / (memberCount + 1); _weightPerNode = _cacheDataSum / (memberCount + 1); // _distMatrixForNodes = new ArrayList(memberCount); long maxCacheSize = cacheSizePerNode * memberCount; //in bytes..CacheSize/node is the one user has entered while creating the cluster foreach (Address mbr in _members) { DistributionMatrix distMatrix = new DistributionMatrix(_weightIdList, mbr,this,NCacheLog); distMatrix.MaxCacheSize = maxCacheSize; _distMatrixForNodes.Add(distMatrix); } }
//returns selected array of indicies that are the resultant set to be sacrificed public static RowsBalanceResult CompareAndSelect(DistributionMatrix bMatrix) { //First Pass:: Check if any individual row can fulfill the reqs . int rowNum = IndividualSelect(bMatrix); if (rowNum >= 0) { int[] selectedBuckets = new int[bMatrix.MatrixDimension.Cols]; for (int i = 0; i < bMatrix.MatrixDimension.Cols; i++) { selectedBuckets[i] = (rowNum * bMatrix.MatrixDimension.Cols) + i; } RowsBalanceResult rbResult = new RowsBalanceResult(); rbResult.ResultIndicies = selectedBuckets; rbResult.TargetDistance = Math.Abs(bMatrix.WeightPercentMatrix[rowNum, 1] - bMatrix.WeightToSacrifice); return(rbResult); } else //Second pass Compare all pairs. { ArrayList allTuples = CandidateTuples(bMatrix); RowsBalanceResult rbResultCurr, rbResultToKeep; rbResultCurr = null; rbResultToKeep = null; foreach (Tuple pair in allTuples) { rbResultCurr = BalanceWeight(pair, bMatrix); if (rbResultToKeep == null) { rbResultToKeep = rbResultCurr; } //If the current result is more optimized then previous then current is the candidate. if (rbResultCurr.TargetDistance < rbResultToKeep.TargetDistance) { rbResultToKeep = rbResultCurr; } } return(rbResultToKeep); } }
//We have the matrix. We need no weight balancing, but we need shuffled indexes to be selected. Here comes the routine and algo. // Shuffle works the way of moving diagonally within a matrix. If we reach end column, move to first row but extended column. public static RowsBalanceResult ShuffleSelect(DistributionMatrix bMatrix) { RowsBalanceResult rbResult = new RowsBalanceResult(); int[] selectedBuckets = new int[bMatrix.MatrixDimension.Cols]; for (int i = 0; i < bMatrix.MatrixDimension.Cols; ) { for (int j = 0; j < bMatrix.MatrixDimension.Rows && i < bMatrix.MatrixDimension.Cols; j++, i++) { if (bMatrix.Matrix[j, i] == -1) { break; } else { selectedBuckets[i] = (j * bMatrix.MatrixDimension.Cols) + i; } } } rbResult.ResultIndicies = selectedBuckets; rbResult.TargetDistance = 0; return rbResult; }
//Balances two rows in a way that primary need to lose some weight to get the resultant weight. //As secondary is always higher weight then primary, so primary cant lose weight. This makes it //straight forward. private static RowsBalanceResult RowBalanceLoseWeight(Tuple rowPair, long weightToLose, DistributionMatrix bMatrix) { int[] primaryIndicies = new int[bMatrix.MatrixDimension.Cols]; RowsBalanceResult rbResult = new RowsBalanceResult(); //lets first populated indicies list for each row.This would help in geting the final set of indicies. for (int i = 0; i < bMatrix.MatrixDimension.Cols; i++) primaryIndicies[i] = (rowPair.First * bMatrix.MatrixDimension.Cols) + i; rbResult.ResultIndicies = primaryIndicies; rbResult.TargetDistance = weightToLose; return rbResult; }
//Balances two rows in a way that primary need to add some more weight to get the resultant weight. private static RowsBalanceResult RowBalanceGainWeight(Tuple rowPair, long[] primaryRowData, long[] secondaryRowData, long weightToGain, DistributionMatrix bMatrix) { int[] primaryIndicies = new int[bMatrix.MatrixDimension.Cols]; int[] secondaryIndicies = new int[bMatrix.MatrixDimension.Cols]; int tmpIndex, primaryLockAt, secondaryLockAt; long primaryRowWeight = bMatrix.WeightPercentMatrix[rowPair.First, 1]; long secondaryRowWeight = bMatrix.WeightPercentMatrix[rowPair.Second, 1]; long weightToAchieve, primaryDistance, secondaryDistance, tmpWeightPri, tmpWeightSec, weightDifference; bool primarySelect = false; primaryLockAt = -1; secondaryLockAt = -1; primaryDistance = 0; secondaryDistance = 0; bool bSecondaryNeedsToLoose = true; //total weight to be made weightToAchieve = primaryRowWeight + weightToGain; RowsBalanceResult rbResult = new RowsBalanceResult(); // for example first-row weight = 1000, second-row weight = 2000, required weight = 3000, // in this case second row need not to lose weight, so no need to keep it as a candidate. if (secondaryRowWeight < weightToAchieve) bSecondaryNeedsToLoose = false; //lets first populated indicies list for each row.This would help in geting the final set of indicies. for (int i = 0; i < bMatrix.MatrixDimension.Cols; i++) { primaryIndicies[i] = (rowPair.First * bMatrix.MatrixDimension.Cols) + i; secondaryIndicies[i] = (rowPair.Second * bMatrix.MatrixDimension.Cols) + i; } //in this loop I am checking both ways. The one that needs to gain weight and the one that looses //weight in result. So any row can match the required weight. After each loop, each swap I check //for the criteria against both rows. In the end I get two indexes against both rows along with //possible extra/deficient count. //In Loose weight, primary is already high from the target,so no chance of secondary for (int i = 0; i < bMatrix.MatrixDimension.Cols; i++) { tmpWeightPri = primaryRowData[i]; tmpWeightSec = secondaryRowData[i]; weightDifference = tmpWeightSec - tmpWeightPri; primaryRowWeight += weightDifference; secondaryRowWeight -= weightDifference; if (primaryRowWeight > weightToAchieve && primaryLockAt == -1) { long diffAfterSwap = primaryRowWeight - weightToAchieve; long diffBeforeSwap = weightToAchieve - (primaryRowWeight - weightDifference); if (diffAfterSwap >= diffBeforeSwap) { primaryLockAt = i - 1; primaryDistance = diffBeforeSwap; } else { primaryLockAt = i; primaryDistance = diffAfterSwap; } } //Do secondary really needs to loose weight ?? Not all the time. if (secondaryRowWeight < weightToAchieve && secondaryLockAt == -1 && bSecondaryNeedsToLoose) { long diffAfterSwap = weightToAchieve - secondaryRowWeight; long diffBeforeSwap = (secondaryRowWeight + weightDifference) - weightToAchieve; if (diffAfterSwap >= diffBeforeSwap) { secondaryLockAt = i - 1; secondaryDistance = diffBeforeSwap; } else { secondaryLockAt = i; secondaryDistance = diffAfterSwap; } } } if (primaryLockAt != -1 && secondaryLockAt != -1) //if we found both rows be candidates then select one with less error { if (primaryDistance <= secondaryDistance) primarySelect = true; else primarySelect = false; } else { if (primaryLockAt != -1) primarySelect = true; if (secondaryLockAt != -1) primarySelect = false; } //unfortunately we found nothing ... So give the first row back with overhead value if (primaryLockAt == -1 && secondaryLockAt == -1) { primarySelect = true; primaryDistance = weightToAchieve - primaryRowWeight; } int swapCount = (primarySelect == true) ? primaryLockAt : secondaryLockAt; //do the items swapping according to swap count value for (int i = 0; i <= swapCount; i++) { tmpIndex = primaryIndicies[i]; primaryIndicies[i] = secondaryIndicies[i]; secondaryIndicies[i] = tmpIndex; } if (primarySelect == true) { rbResult.ResultIndicies = primaryIndicies; rbResult.TargetDistance = primaryDistance; } else { rbResult.ResultIndicies = secondaryIndicies; rbResult.TargetDistance = secondaryDistance; } return rbResult; }
/* public static RowsBalanceResult BucketSelectionFromTuples(ArrayList allTuples,DistributionMatrix bMatrix) { int primaryRow; //This row would be modified to acomodae required weight. int secondaryRow; //This row would be consulted to make primaryRow workable for (int i = 0; i < allTuples.Count; i++) { Tuple tempTuple = allTuples[i]; int firstWeight = bMatrix.WeightMatrix[tempTuple.First][0]; int secondWeight = bMatrix.WeightMatrix[tempTuple.second][0]; // Calculate which Move is cost-effective, Moving data from first to second or moving from second to first if (CalcMoveCost(firstWeight, bMatrix.PercentWeightToSacrifice) <= CalcMoveCost(secondWeight, bMatrix.PercentWeightToSacrifice)) { primaryRow = tempTuple.First; secondarayRow = tempTuple.Second; } else { primaryRow = tempTuple.Second; secondarayRow = tempTuple.First; } } } */ /*// Calculates cost to make sourceweight to be equal to desired weight. This can be in + and -. We take absolute value though. public static int CalcMoveCost(int sourceWeight,int toMoveWeight) { if (sourceWeight < toMoveWeight) // return (toMoveWeight - sourceWeight); if (sourceWeight > toMoveWeight) return (sourceWeight - toMoveWeight); if (sourceWeight == toMoveWeight) return 0; }*/ //Backbone to be written now.//Two arrays ....both need to give a right combination against required weight. private static RowsBalanceResult BalanceWeight(Tuple rowPair, DistributionMatrix bMatrix) { BalanceAction balAction = new BalanceAction(); long weightToMove = 0; long primaryRowWeight = bMatrix.WeightPercentMatrix[rowPair.First, 0]; long secondaryRowWeight = bMatrix.WeightPercentMatrix[rowPair.Second, 0]; if (primaryRowWeight < bMatrix.PercentWeightToSacrifice) // { weightToMove = bMatrix.PercentWeightToSacrifice - primaryRowWeight; weightToMove = (weightToMove * bMatrix.TotalWeight) / 100; balAction = BalanceAction.GainWeight; } else { weightToMove = primaryRowWeight - bMatrix.PercentWeightToSacrifice; weightToMove = (weightToMove * bMatrix.TotalWeight) / 100; balAction = BalanceAction.LoseWeight; } long[] primaryRowData = new long[bMatrix.MatrixDimension.Cols]; long[] secondaryRowData = new long[bMatrix.MatrixDimension.Cols]; //Fills the local copy of two rows to be manipulated for (int i = 0; i < bMatrix.MatrixDimension.Cols; i++) { primaryRowData[i] = bMatrix.Matrix[rowPair.First, i]; secondaryRowData[i] = bMatrix.Matrix[rowPair.Second, i]; } RowsBalanceResult rbResult= null; switch (balAction) { case BalanceAction.GainWeight: rbResult = RowBalanceGainWeight(rowPair, primaryRowData, secondaryRowData, weightToMove, bMatrix); break; case BalanceAction.LoseWeight: rbResult = RowBalanceLoseWeight(rowPair, weightToMove, bMatrix); break; default: break; } return rbResult; }
private static int IndividualSelect(DistributionMatrix bMatrix) { for (int i = 0; i < bMatrix.MatrixDimension.Rows; i++) { long rowWeight = bMatrix.WeightPercentMatrix[i, 0]; if (rowWeight == bMatrix.PercentWeightToSacrifice) return i; //this row; //Lets see if if required data is within +- of cushion factor if (rowWeight < bMatrix.PercentWeightToSacrifice) { rowWeight += bMatrix.CushionFactor; if (rowWeight >= bMatrix.PercentWeightToSacrifice) return i; //this row } else { rowWeight -= bMatrix.CushionFactor; if (rowWeight <= bMatrix.PercentWeightToSacrifice) return i; //this row } } return -1; //We got no single row that can be selected under required criteria }
//returns selected array of indicies that are the resultant set to be sacrificed public static RowsBalanceResult CompareAndSelect(DistributionMatrix bMatrix) { //First Pass:: Check if any individual row can fulfill the reqs . int rowNum = IndividualSelect(bMatrix); if (rowNum >= 0) { int[] selectedBuckets = new int[bMatrix.MatrixDimension.Cols]; for (int i = 0; i < bMatrix.MatrixDimension.Cols; i++) { selectedBuckets[i] = (rowNum * bMatrix.MatrixDimension.Cols) + i; } RowsBalanceResult rbResult = new RowsBalanceResult(); rbResult.ResultIndicies = selectedBuckets; rbResult.TargetDistance = Math.Abs(bMatrix.WeightPercentMatrix[rowNum, 1] - bMatrix.WeightToSacrifice); return rbResult; } else //Second pass Compare all pairs. { ArrayList allTuples = CandidateTuples(bMatrix); RowsBalanceResult rbResultCurr, rbResultToKeep; rbResultCurr = null; rbResultToKeep = null; foreach (Tuple pair in allTuples) { rbResultCurr = BalanceWeight(pair, bMatrix); if (rbResultToKeep == null) rbResultToKeep = rbResultCurr; //If the current result is more optimized then previous then current is the candidate. if (rbResultCurr.TargetDistance < rbResultToKeep.TargetDistance) rbResultToKeep = rbResultCurr; } return rbResultToKeep; } }
/* public static ArrayList CandidateSelection(ArrayList sortedBucketsForNode, int nodesToSacrifice, int weightToSacrifice) { int _matrixWidth = nodesToSacrifice; double _matrixHeightDbl = sortedBucketsForNode.Count / nodesToSacrifice; int _matrixHeight = Convert.ToInt32(Math.Ceiling(_matrixHeightDbl)); int _matrixItemsCount = _matrixHeight * _matrixWidth; int _ignoreItems = _matrixItemsCount - sortedBucketsForNode.Count; BucketMatrix _bMatrix = GetMatrix(_matrixHeight, _matrixWidth, sortedBucketsForNode, weightToSacrifice); CompareAndSelect(_bMatrix); return null; }*/ /* private static BucketMatrix GetMatrix(int matrixH, int matrixW, ArrayList sortedBucketsForNode, int weightToSacrifice) { int[,] bucketMatrix = new int[matrixH, matrixW]; int indexCount = 0; int itemsCount = sortedBucketsForNode.Count; //Fill up the Matrix with buckets for THIS node. for (int width = 0; width < matrixW; width++) { for (int height = 0; height < matrixH; height++) { if (indexCount < itemsCount) bucketMatrix[width, height] = Convert.ToInt32(sortedBucketsForNode[indexCount++]); else { bucketMatrix[width, height] = -1; indexCount++; } } } BucketMatrix bMatrix = new BucketMatrix(bucketMatrix, matrixH, matrixW, weightToSacrifice); return bMatrix; }*/ //We have the matrix. We need no weight balancing, but we need shuffled indexes to be selected. Here comes the routine and algo. // Shuffle works the way of moving diagonally within a matrix. If we reach end column, move to first row but extended column. public static RowsBalanceResult ShuffleSelect(DistributionMatrix bMatrix) { RowsBalanceResult rbResult = new RowsBalanceResult(); int[] selectedBuckets = new int[bMatrix.MatrixDimension.Cols]; for (int i = 0; i < bMatrix.MatrixDimension.Cols; ) { for (int j = 0; j < bMatrix.MatrixDimension.Rows && i < bMatrix.MatrixDimension.Cols; j++, i++) { if (bMatrix.Matrix[j, i] == -1) { break; } else { selectedBuckets[i] = (j * bMatrix.MatrixDimension.Cols) + i; } } } rbResult.ResultIndicies = selectedBuckets; rbResult.TargetDistance = 0; return rbResult; }