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 }