/** Pairs up given nodes in balancing plan */ private void scheduleTask(Source source, long size, Target target) { NodeTask nodeTask = new NodeTask(target, size); source.addNodeTask(nodeTask); target.addNodeTask(nodeTask); sources.add(source); targets.add(target); LOG.info("scheduled " + size + " bytes : " + source.getName() + " -> " + target.getName()); }
/** Updates the plan with all pairs of nodes from this bucket which need to be connected */ public void updatePlan() { while (!this.sources.isEmpty() && !this.targets.isEmpty()) { Source source = this.sources.poll(); Target target = this.targets.poll(); if (!wasUrgent(source) && !wasUrgent(target)) { // Due to ordering of DataNodes we can skip the rest break; } long size = moveSize(source, target); if (size > 0) { scheduleTask(source, size, target); } if (source.getAvailableMoveSize() > 0) { this.sources.add(source); } if (target.getAvailableMoveSize() > 0) { this.targets.add(target); } // Loop termination: // In each step we either scheduleTask, therefore decreasing sum (over // all nodes) of availableMoveSize, or decrease number of nodes in // sources or targets queue, all of them are bounded by 0. } }
/** Determines how much data to move between given nodes */ private long moveSize(Source source, BalancerDatanode target) { // TODO balancing concurrency return Math.min(source.getAvailableMoveSize(), target.getAvailableMoveSize()); }