001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019 package org.apache.hadoop.yarn.api.records; 020 021 import java.text.NumberFormat; 022 023 import org.apache.hadoop.classification.InterfaceAudience.Private; 024 import org.apache.hadoop.classification.InterfaceAudience.Public; 025 import org.apache.hadoop.classification.InterfaceStability.Stable; 026 import org.apache.hadoop.classification.InterfaceStability.Unstable; 027 import org.apache.hadoop.yarn.util.Records; 028 029 /** 030 * <p><code>ContainerId</code> represents a globally unique identifier 031 * for a {@link Container} in the cluster.</p> 032 */ 033 @Public 034 @Stable 035 public abstract class ContainerId implements Comparable<ContainerId>{ 036 037 @Private 038 @Unstable 039 public static ContainerId newInstance(ApplicationAttemptId appAttemptId, 040 int containerId) { 041 ContainerId id = Records.newRecord(ContainerId.class); 042 id.setId(containerId); 043 id.setApplicationAttemptId(appAttemptId); 044 id.build(); 045 return id; 046 } 047 048 /** 049 * Get the <code>ApplicationAttemptId</code> of the application to which the 050 * <code>Container</code> was assigned. 051 * <p> 052 * Note: If containers are kept alive across application attempts via 053 * {@link ApplicationSubmissionContext#setKeepContainersAcrossApplicationAttempts(boolean)} 054 * the <code>ContainerId</code> does not necessarily contain the current 055 * running application attempt's <code>ApplicationAttemptId</code> This 056 * container can be allocated by previously exited application attempt and 057 * managed by the current running attempt thus have the previous application 058 * attempt's <code>ApplicationAttemptId</code>. 059 * </p> 060 * 061 * @return <code>ApplicationAttemptId</code> of the application to which the 062 * <code>Container</code> was assigned 063 */ 064 @Public 065 @Stable 066 public abstract ApplicationAttemptId getApplicationAttemptId(); 067 068 @Private 069 @Unstable 070 protected abstract void setApplicationAttemptId(ApplicationAttemptId atId); 071 072 /** 073 * Get the identifier of the <code>ContainerId</code>. 074 * @return identifier of the <code>ContainerId</code> 075 */ 076 @Public 077 @Stable 078 public abstract int getId(); 079 080 @Private 081 @Unstable 082 protected abstract void setId(int id); 083 084 085 // TODO: fail the app submission if attempts are more than 10 or something 086 private static final ThreadLocal<NumberFormat> appAttemptIdFormat = 087 new ThreadLocal<NumberFormat>() { 088 @Override 089 public NumberFormat initialValue() { 090 NumberFormat fmt = NumberFormat.getInstance(); 091 fmt.setGroupingUsed(false); 092 fmt.setMinimumIntegerDigits(2); 093 return fmt; 094 } 095 }; 096 // TODO: Why thread local? 097 // ^ NumberFormat instances are not threadsafe 098 private static final ThreadLocal<NumberFormat> containerIdFormat = 099 new ThreadLocal<NumberFormat>() { 100 @Override 101 public NumberFormat initialValue() { 102 NumberFormat fmt = NumberFormat.getInstance(); 103 fmt.setGroupingUsed(false); 104 fmt.setMinimumIntegerDigits(6); 105 return fmt; 106 } 107 }; 108 109 @Override 110 public int hashCode() { 111 // Generated by eclipse. 112 final int prime = 435569; 113 int result = 7507; 114 result = prime * result + getId(); 115 result = prime * result + getApplicationAttemptId().hashCode(); 116 return result; 117 } 118 119 @Override 120 public boolean equals(Object obj) { 121 if (this == obj) 122 return true; 123 if (obj == null) 124 return false; 125 if (getClass() != obj.getClass()) 126 return false; 127 ContainerId other = (ContainerId) obj; 128 if (!this.getApplicationAttemptId().equals(other.getApplicationAttemptId())) 129 return false; 130 if (this.getId() != other.getId()) 131 return false; 132 return true; 133 } 134 135 @Override 136 public int compareTo(ContainerId other) { 137 if (this.getApplicationAttemptId().compareTo( 138 other.getApplicationAttemptId()) == 0) { 139 return this.getId() - other.getId(); 140 } else { 141 return this.getApplicationAttemptId().compareTo( 142 other.getApplicationAttemptId()); 143 } 144 145 } 146 147 @Override 148 public String toString() { 149 StringBuilder sb = new StringBuilder(); 150 sb.append("container_"); 151 ApplicationId appId = getApplicationAttemptId().getApplicationId(); 152 sb.append(appId.getClusterTimestamp()).append("_"); 153 sb.append(ApplicationId.appIdFormat.get().format(appId.getId())) 154 .append("_"); 155 sb.append( 156 appAttemptIdFormat.get().format( 157 getApplicationAttemptId().getAttemptId())).append("_"); 158 sb.append(containerIdFormat.get().format(getId())); 159 return sb.toString(); 160 } 161 162 protected abstract void build(); 163 }