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 019package org.apache.hadoop.yarn.api.records; 020 021import java.text.NumberFormat; 022import java.util.Iterator; 023import java.util.NoSuchElementException; 024 025import org.apache.hadoop.classification.InterfaceAudience.Private; 026import org.apache.hadoop.classification.InterfaceAudience.Public; 027import org.apache.hadoop.classification.InterfaceStability.Stable; 028import org.apache.hadoop.classification.InterfaceStability.Unstable; 029import org.apache.hadoop.yarn.util.Records; 030 031import com.google.common.base.Splitter; 032 033/** 034 * <p><code>ApplicationAttemptId</code> denotes the particular <em>attempt</em> 035 * of an <code>ApplicationMaster</code> for a given {@link ApplicationId}.</p> 036 * 037 * <p>Multiple attempts might be needed to run an application to completion due 038 * to temporal failures of the <code>ApplicationMaster</code> such as hardware 039 * failures, connectivity issues etc. on the node on which it was scheduled.</p> 040 */ 041@Public 042@Stable 043public abstract class ApplicationAttemptId implements 044 Comparable<ApplicationAttemptId> { 045 private static Splitter _spliter = Splitter.on('_').trimResults(); 046 047 @Private 048 @Unstable 049 public static final String appAttemptIdStrPrefix = "appattempt"; 050 051 @Public 052 @Unstable 053 public static ApplicationAttemptId newInstance(ApplicationId appId, 054 int attemptId) { 055 ApplicationAttemptId appAttemptId = 056 Records.newRecord(ApplicationAttemptId.class); 057 appAttemptId.setApplicationId(appId); 058 appAttemptId.setAttemptId(attemptId); 059 appAttemptId.build(); 060 return appAttemptId; 061 } 062 063 /** 064 * Get the <code>ApplicationId</code> of the <code>ApplicationAttempId</code>. 065 * @return <code>ApplicationId</code> of the <code>ApplicationAttempId</code> 066 */ 067 @Public 068 @Stable 069 public abstract ApplicationId getApplicationId(); 070 071 @Private 072 @Unstable 073 protected abstract void setApplicationId(ApplicationId appID); 074 075 /** 076 * Get the <code>attempt id</code> of the <code>Application</code>. 077 * @return <code>attempt id</code> of the <code>Application</code> 078 */ 079 @Public 080 @Stable 081 public abstract int getAttemptId(); 082 083 @Private 084 @Unstable 085 protected abstract void setAttemptId(int attemptId); 086 087 static final ThreadLocal<NumberFormat> attemptIdFormat = 088 new ThreadLocal<NumberFormat>() { 089 @Override 090 public NumberFormat initialValue() { 091 NumberFormat fmt = NumberFormat.getInstance(); 092 fmt.setGroupingUsed(false); 093 fmt.setMinimumIntegerDigits(6); 094 return fmt; 095 } 096 }; 097 098 @Override 099 public int hashCode() { 100 // Generated by eclipse. 101 final int prime = 347671; 102 int result = 5501; 103 ApplicationId appId = getApplicationId(); 104 result = prime * result + appId.hashCode(); 105 result = prime * result + getAttemptId(); 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 ApplicationAttemptId other = (ApplicationAttemptId) obj; 118 if (!this.getApplicationId().equals(other.getApplicationId())) 119 return false; 120 if (this.getAttemptId() != other.getAttemptId()) 121 return false; 122 return true; 123 } 124 125 @Override 126 public int compareTo(ApplicationAttemptId other) { 127 int compareAppIds = this.getApplicationId().compareTo( 128 other.getApplicationId()); 129 if (compareAppIds == 0) { 130 return this.getAttemptId() - other.getAttemptId(); 131 } else { 132 return compareAppIds; 133 } 134 } 135 136 @Override 137 public String toString() { 138 StringBuilder sb = new StringBuilder(appAttemptIdStrPrefix); 139 sb.append("_"); 140 sb.append(this.getApplicationId().getClusterTimestamp()).append("_"); 141 sb.append(ApplicationId.appIdFormat.get().format( 142 this.getApplicationId().getId())); 143 sb.append("_").append(attemptIdFormat.get().format(getAttemptId())); 144 return sb.toString(); 145 } 146 147 protected abstract void build(); 148 149 @Public 150 @Stable 151 public static ApplicationAttemptId fromString(String applicationAttemptIdStr) { 152 Iterator<String> it = _spliter.split(applicationAttemptIdStr).iterator(); 153 if (!it.next().equals(appAttemptIdStrPrefix)) { 154 throw new IllegalArgumentException("Invalid AppAttemptId prefix: " 155 + applicationAttemptIdStr); 156 } 157 try { 158 return toApplicationAttemptId(it); 159 } catch (NumberFormatException n) { 160 throw new IllegalArgumentException("Invalid AppAttemptId: " 161 + applicationAttemptIdStr, n); 162 } catch (NoSuchElementException e) { 163 throw new IllegalArgumentException("Invalid AppAttemptId: " 164 + applicationAttemptIdStr, e); 165 } 166 } 167 168 private static ApplicationAttemptId toApplicationAttemptId( 169 Iterator<String> it) throws NumberFormatException { 170 ApplicationId appId = ApplicationId.newInstance(Long.parseLong(it.next()), 171 Integer.parseInt(it.next())); 172 ApplicationAttemptId appAttemptId = 173 ApplicationAttemptId.newInstance(appId, Integer.parseInt(it.next())); 174 return appAttemptId; 175 } 176}