| /** |
| * 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.yarn.api.records; |
| |
| import org.apache.hadoop.classification.InterfaceAudience.Private; |
| import org.apache.hadoop.classification.InterfaceAudience.Public; |
| import org.apache.hadoop.classification.InterfaceStability.Stable; |
| import org.apache.hadoop.classification.InterfaceStability.Unstable; |
| import org.apache.hadoop.util.FastNumberFormat; |
| import org.apache.hadoop.yarn.util.Records; |
| |
| /** |
| * <p><code>ContainerId</code> represents a globally unique identifier |
| * for a {@link Container} in the cluster.</p> |
| */ |
| @Public |
| @Stable |
| public abstract class ContainerId implements Comparable<ContainerId>{ |
| public static final long CONTAINER_ID_BITMASK = 0xffffffffffL; |
| private static final String CONTAINER_PREFIX = "container_"; |
| private static final String EPOCH_PREFIX = "e"; |
| |
| @Public |
| @Unstable |
| public static ContainerId newContainerId(ApplicationAttemptId appAttemptId, |
| long containerId) { |
| ContainerId id = Records.newRecord(ContainerId.class); |
| id.setContainerId(containerId); |
| id.setApplicationAttemptId(appAttemptId); |
| id.build(); |
| return id; |
| } |
| |
| @Private |
| @Deprecated |
| @Unstable |
| public static ContainerId newInstance(ApplicationAttemptId appAttemptId, |
| int containerId) { |
| ContainerId id = Records.newRecord(ContainerId.class); |
| id.setContainerId(containerId); |
| id.setApplicationAttemptId(appAttemptId); |
| id.build(); |
| return id; |
| } |
| |
| /** |
| * Get the <code>ApplicationAttemptId</code> of the application to which the |
| * <code>Container</code> was assigned. |
| * <p> |
| * Note: If containers are kept alive across application attempts via |
| * {@link ApplicationSubmissionContext#setKeepContainersAcrossApplicationAttempts(boolean)} |
| * the <code>ContainerId</code> does not necessarily contain the current |
| * running application attempt's <code>ApplicationAttemptId</code> This |
| * container can be allocated by previously exited application attempt and |
| * managed by the current running attempt thus have the previous application |
| * attempt's <code>ApplicationAttemptId</code>. |
| * </p> |
| * |
| * @return <code>ApplicationAttemptId</code> of the application to which the |
| * <code>Container</code> was assigned |
| */ |
| @Public |
| @Stable |
| public abstract ApplicationAttemptId getApplicationAttemptId(); |
| |
| @Private |
| @Unstable |
| protected abstract void setApplicationAttemptId(ApplicationAttemptId atId); |
| |
| /** |
| * Get the lower 32 bits of identifier of the <code>ContainerId</code>, |
| * which doesn't include epoch. Note that this method will be marked as |
| * deprecated, so please use <code>getContainerId</code> instead. |
| * @return lower 32 bits of identifier of the <code>ContainerId</code> |
| */ |
| @Public |
| @Deprecated |
| @Unstable |
| public abstract int getId(); |
| |
| /** |
| * Get the identifier of the <code>ContainerId</code>. Upper 24 bits are |
| * reserved as epoch of cluster, and lower 40 bits are reserved as |
| * sequential number of containers. |
| * @return identifier of the <code>ContainerId</code> |
| */ |
| @Public |
| @Unstable |
| public abstract long getContainerId(); |
| |
| @Private |
| @Unstable |
| protected abstract void setContainerId(long id); |
| |
| |
| private static final int APP_ID_MIN_DIGITS = 4; |
| |
| private static final int ATTEMPT_ID_MIN_DIGITS = 2; |
| |
| private static final int EPOCH_MIN_DIGITS = 2; |
| |
| private static final int CONTAINER_ID_MIN_DIGITS = 6; |
| |
| @Override |
| public int hashCode() { |
| // Generated by IntelliJ IDEA 13.1. |
| int result = (int) (getContainerId() ^ (getContainerId() >>> 32)); |
| result = 31 * result + getApplicationAttemptId().hashCode(); |
| return result; |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (this == obj) |
| return true; |
| if (obj == null) |
| return false; |
| if (getClass() != obj.getClass()) |
| return false; |
| ContainerId other = (ContainerId) obj; |
| if (!this.getApplicationAttemptId().equals(other.getApplicationAttemptId())) |
| return false; |
| if (this.getContainerId() != other.getContainerId()) |
| return false; |
| return true; |
| } |
| |
| @Override |
| public int compareTo(ContainerId other) { |
| int result = this.getApplicationAttemptId().compareTo( |
| other.getApplicationAttemptId()); |
| if (result == 0) { |
| return Long.compare(getContainerId(), other.getContainerId()); |
| } else { |
| return result; |
| } |
| } |
| |
| /** |
| * @return A string representation of containerId. The format is |
| * container_e*epoch*_*clusterTimestamp*_*appId*_*attemptId*_*containerId* |
| * when epoch is larger than 0 |
| * (e.g. container_e17_1410901177871_0001_01_000005). |
| * *epoch* is increased when RM restarts or fails over. |
| * When epoch is 0, epoch is omitted |
| * (e.g. container_1410901177871_0001_01_000005). |
| */ |
| @Override |
| public String toString() { |
| StringBuilder sb = new StringBuilder(64); |
| sb.append(CONTAINER_PREFIX); |
| long epoch = getContainerId() >> 40; |
| if (epoch > 0) { |
| sb.append(EPOCH_PREFIX); |
| FastNumberFormat.format(sb, epoch, EPOCH_MIN_DIGITS); |
| sb.append('_'); |
| } |
| ApplicationId appId = getApplicationAttemptId().getApplicationId(); |
| sb.append(appId.getClusterTimestamp()); |
| sb.append('_'); |
| FastNumberFormat.format(sb, appId.getId(), APP_ID_MIN_DIGITS); |
| sb.append('_'); |
| FastNumberFormat.format(sb, getApplicationAttemptId().getAttemptId(), |
| ATTEMPT_ID_MIN_DIGITS); |
| sb.append('_'); |
| FastNumberFormat.format(sb, CONTAINER_ID_BITMASK & getContainerId(), |
| CONTAINER_ID_MIN_DIGITS); |
| return sb.toString(); |
| } |
| |
| @Public |
| @Stable |
| public static ContainerId fromString(String containerIdStr) { |
| if (!containerIdStr.startsWith(CONTAINER_PREFIX)) { |
| throw new IllegalArgumentException("Invalid ContainerId prefix: " |
| + containerIdStr); |
| } |
| try { |
| int pos1 = CONTAINER_PREFIX.length() - 1; |
| |
| long epoch = 0; |
| if (containerIdStr.regionMatches(pos1 + 1, EPOCH_PREFIX, 0, |
| EPOCH_PREFIX.length())) { |
| int pos2 = containerIdStr.indexOf('_', pos1 + 1); |
| if (pos2 < 0) { |
| throw new IllegalArgumentException("Invalid ContainerId: " |
| + containerIdStr); |
| } |
| String epochStr = containerIdStr.substring( |
| pos1 + 1 + EPOCH_PREFIX.length(), pos2); |
| epoch = Integer.parseInt(epochStr); |
| // rewind the current position |
| pos1 = pos2; |
| } |
| int pos2 = containerIdStr.indexOf('_', pos1 + 1); |
| if (pos2 < 0) { |
| throw new IllegalArgumentException("Invalid ContainerId: " |
| + containerIdStr); |
| } |
| long clusterTimestamp = Long.parseLong( |
| containerIdStr.substring(pos1 + 1, pos2)); |
| |
| int pos3 = containerIdStr.indexOf('_', pos2 + 1); |
| if (pos3 < 0) { |
| throw new IllegalArgumentException("Invalid ContainerId: " |
| + containerIdStr); |
| } |
| int appId = Integer.parseInt(containerIdStr.substring(pos2 + 1, pos3)); |
| ApplicationId applicationId = ApplicationId.newInstance(clusterTimestamp, |
| appId); |
| int pos4 = containerIdStr.indexOf('_', pos3 + 1); |
| if (pos4 < 0) { |
| throw new IllegalArgumentException("Invalid ContainerId: " |
| + containerIdStr); |
| } |
| int attemptId = Integer.parseInt( |
| containerIdStr.substring(pos3 + 1, pos4)); |
| ApplicationAttemptId appAttemptId = |
| ApplicationAttemptId.newInstance(applicationId, attemptId); |
| long id = Long.parseLong(containerIdStr.substring(pos4 + 1)); |
| long cid = (epoch << 40) | id; |
| ContainerId containerId = ContainerId.newContainerId(appAttemptId, cid); |
| return containerId; |
| } catch (NumberFormatException n) { |
| throw new IllegalArgumentException("Invalid ContainerId: " |
| + containerIdStr, n); |
| } |
| } |
| |
| protected abstract void build(); |
| } |