/* * Copyright 2013 LinkedIn, Inc * * 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 voldemort.client.rebalance.task; import java.util.concurrent.Semaphore; import org.apache.log4j.Logger; import voldemort.VoldemortException; import voldemort.client.protocol.admin.AdminClient; import voldemort.client.rebalance.RebalanceBatchPlanProgressBar; import voldemort.client.rebalance.RebalanceScheduler; import voldemort.client.rebalance.RebalanceTaskInfo; import voldemort.server.rebalance.AlreadyRebalancingException; import voldemort.store.UnreachableStoreException; import com.google.common.collect.Lists; /** * Immutable class that executes a {@link RebalanceTaskInfo} instance on * the rebalance client side. * * This is run from the stealer nodes perspective */ public class StealerBasedRebalanceTask extends RebalanceTask { private static final Logger logger = Logger.getLogger(StealerBasedRebalanceTask.class); private final int stealerNodeId; private final int donorNodeId; private final RebalanceScheduler scheduler; public StealerBasedRebalanceTask(final int batchId, final int taskId, final RebalanceTaskInfo stealInfo, final Semaphore donorPermit, final AdminClient adminClient, final RebalanceBatchPlanProgressBar progressBar, final RebalanceScheduler scheduler) { super(batchId, taskId, Lists.newArrayList(stealInfo), donorPermit, adminClient, progressBar, logger); this.stealerNodeId = stealInfo.getStealerId(); this.donorNodeId = stealInfo.getDonorId(); this.scheduler = scheduler; taskLog(toString()); } private int startNodeRebalancing() { try { taskLog("Trying to start async rebalance task on stealer node " + stealerNodeId); int asyncOperationId = adminClient.rebalanceOps.rebalanceNode(stealInfos.get(0)); taskLog("Started async rebalance task on stealer node " + stealerNodeId); return asyncOperationId; } catch(AlreadyRebalancingException e) { String errorMessage = "Node " + stealerNodeId + " is currently rebalancing. Should not have tried to start new task on stealer node!"; taskLog(errorMessage); throw new VoldemortException(errorMessage + " Failed to start rebalancing with plan: " + getStealInfos(), e); } } @Override public void run() { int rebalanceAsyncId = INVALID_REBALANCE_ID; String threadName = Thread.currentThread().getName(); try { Thread.currentThread().setName(threadName + "-Task-" + taskId + "-asyncid-" + rebalanceAsyncId); acquirePermit(stealInfos.get(0).getDonorId()); // Start rebalance task and then wait. rebalanceAsyncId = startNodeRebalancing(); taskStart(taskId, rebalanceAsyncId); adminClient.rpcOps.waitForCompletion(stealerNodeId, rebalanceAsyncId); taskDone(taskId, rebalanceAsyncId); } catch(UnreachableStoreException e) { exception = e; logger.error("Stealer node " + stealerNodeId + " is unreachable, please make sure it is up and running : " + e.getMessage(), e); } catch(Exception e) { exception = e; logger.error("Rebalance failed : " + e.getMessage(), e); } finally { Thread.currentThread().setName(threadName); donorPermit.release(); isComplete.set(true); scheduler.doneTask(stealerNodeId, donorNodeId); } } @Override public String toString() { return "Stealer based rebalance task on stealer node " + stealerNodeId + " from donor node " + donorNodeId + " : " + getStealInfos(); } }