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
050       * the <code>Container</code> was assigned.
051       * @return <code>ApplicationAttemptId</code> of the application to which
052       *         the <code>Container</code> was assigned
053       */
054      @Public
055      @Stable
056      public abstract ApplicationAttemptId getApplicationAttemptId();
057      
058      @Private
059      @Unstable
060      protected abstract void setApplicationAttemptId(ApplicationAttemptId atId);
061    
062      /**
063       * Get the identifier of the <code>ContainerId</code>.
064       * @return identifier of the <code>ContainerId</code>
065       */
066      @Public
067      @Stable
068      public abstract int getId();
069    
070      @Private
071      @Unstable
072      protected abstract void setId(int id);
073     
074      
075      // TODO: fail the app submission if attempts are more than 10 or something
076      private static final ThreadLocal<NumberFormat> appAttemptIdFormat =
077          new ThreadLocal<NumberFormat>() {
078            @Override
079            public NumberFormat initialValue() {
080              NumberFormat fmt = NumberFormat.getInstance();
081              fmt.setGroupingUsed(false);
082              fmt.setMinimumIntegerDigits(2);
083              return fmt;
084            }
085          };
086      // TODO: Why thread local?
087      // ^ NumberFormat instances are not threadsafe
088      private static final ThreadLocal<NumberFormat> containerIdFormat =
089          new ThreadLocal<NumberFormat>() {
090            @Override
091            public NumberFormat initialValue() {
092              NumberFormat fmt = NumberFormat.getInstance();
093              fmt.setGroupingUsed(false);
094              fmt.setMinimumIntegerDigits(6);
095              return fmt;
096            }
097          };
098      
099      @Override
100      public int hashCode() {
101        // Generated by eclipse.
102        final int prime = 435569;
103        int result = 7507;
104        result = prime * result + getId();
105        result = prime * result + getApplicationAttemptId().hashCode();
106        return result;
107      }
108    
109      @Override
110      public boolean equals(Object obj) {
111        if (this == obj)
112          return true;
113        if (obj == null)
114          return false;
115        if (getClass() != obj.getClass())
116          return false;
117        ContainerId other = (ContainerId) obj;
118        if (!this.getApplicationAttemptId().equals(other.getApplicationAttemptId()))
119          return false;
120        if (this.getId() != other.getId())
121          return false;
122        return true;
123      }
124    
125      @Override
126      public int compareTo(ContainerId other) {
127        if (this.getApplicationAttemptId().compareTo(
128            other.getApplicationAttemptId()) == 0) {
129          return this.getId() - other.getId();
130        } else {
131          return this.getApplicationAttemptId().compareTo(
132              other.getApplicationAttemptId());
133        }
134        
135      }
136    
137      @Override
138      public String toString() {
139        StringBuilder sb = new StringBuilder();
140        sb.append("container_");
141        ApplicationId appId = getApplicationAttemptId().getApplicationId();
142        sb.append(appId.getClusterTimestamp()).append("_");
143        sb.append(ApplicationId.appIdFormat.get().format(appId.getId()))
144            .append("_");
145        sb.append(
146            appAttemptIdFormat.get().format(
147                getApplicationAttemptId().getAttemptId())).append("_");
148        sb.append(containerIdFormat.get().format(getId()));
149        return sb.toString();
150      }
151    
152      protected abstract void build();
153    }