/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 org.apache.hadoop.mapred; import java.io.IOException; import java.net.InetSocketAddress; import java.util.List; import java.util.concurrent.ConcurrentHashMap; import org.apache.hadoop.ipc.RPC; /** * Implements logic behind asking local JT for permission to commit tasks in * remote JT */ @SuppressWarnings("deprecation") public class CoronaCommitPermission { /** Empty array */ public static final CommitTaskAction[] EMPTY_COMMIT_ACTIONS = new CommitTaskAction[0]; /** Asks for permission to commit */ public static class CommitPermissionClient { /** RPC client to authority that gives permissions to commit */ private InterCoronaJobTrackerProtocol serverClient; /** Attempt id of this job tracker */ private TaskAttemptID attemptId; /** True if there was unrecoverable error in connecting to authority */ private boolean faultyClient = false; /** Creates client that automatically allows committing any tasks */ public CommitPermissionClient() { } /** * Creates client that asks provided authority for permissions to commit * @param attemptId attempt id of remote JT asking for permissions * @param serverAddress addres of authority * @param conf job configuration * @throws IOException */ public CommitPermissionClient(TaskAttemptID attemptId, InetSocketAddress serverAddress, JobConf conf) throws IOException { this.attemptId = attemptId; this.serverClient = RPC.waitForProxy(InterCoronaJobTrackerProtocol.class, InterCoronaJobTrackerProtocol.versionID, serverAddress, conf, RemoteJTProxy.getRemotJTTimeout(conf)); } /** * Given array of task attempts that caller wants to commit returns array of * task attempts matching tasks of provided attempts, that were last * committing * @param actions list of actions to commit * @return array with attempt id of proper tasks that was/are committing * @throws IOException */ public TaskAttemptID[] getAndSetCommitting(List<CommitTaskAction> actions) throws IOException { if (faultyClient) throw new IOException("Authority client is faulty"); TaskAttemptID[] commmitPermissions; if (serverClient == null) { // Allow any commits commmitPermissions = new TaskAttemptID[actions.size()]; for (int i = 0; i < commmitPermissions.length; ++i) commmitPermissions[i] = null; } else { try { TaskAttemptID[] toCommit = new TaskAttemptID[actions.size()]; for (int i = 0; i < toCommit.length; ++i) toCommit[i] = actions.get(i).getTaskID(); // Get=and-set commmitPermissions = serverClient.getAndSetCommitting(attemptId, toCommit); } catch (IOException e) { faultyClient = true; throw e; } } return commmitPermissions; } /** * Closes authority server client */ public void close() { RPC.stopProxy(serverClient); serverClient = null; } } /** Dispatcher commit permissions */ public static class CommitPermissionServer { /** This is actual map that implements get and set */ private ConcurrentHashMap<TaskID, TaskAttemptID> taskToAttempt = new ConcurrentHashMap<TaskID, TaskAttemptID>(); /** * Given array of task attempts that caller wants to commit returns array of * task attempts matching tasks of provided attempts, that were last * committing * @param attemptId of JT asking for permission * @param toCommit attempts that we want to commit * @return array with attempt id of proper tasks that was/are committing */ public TaskAttemptID[] getAndSetCommitting(TaskAttemptID[] toCommit) { TaskAttemptID[] wasCommitting = new TaskAttemptID[toCommit.length]; for (int i = 0; i < toCommit.length; ++i) { TaskAttemptID attempt = toCommit[i]; TaskID task = attempt.getTaskID(); wasCommitting[i] = taskToAttempt.put(task, attempt); } return wasCommitting; } } }