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    }