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>ApplicationId</code> represents the <em>globally unique</em> 035 * identifier for an application.</p> 036 * 037 * <p>The globally unique nature of the identifier is achieved by using the 038 * <em>cluster timestamp</em> i.e. start-time of the 039 * <code>ResourceManager</code> along with a monotonically increasing counter 040 * for the application.</p> 041 */ 042@Public 043@Stable 044public abstract class ApplicationId implements Comparable<ApplicationId> { 045 private static Splitter _spliter = Splitter.on('_').trimResults(); 046 047 @Private 048 @Unstable 049 public static final String appIdStrPrefix = "application"; 050 051 @Public 052 @Unstable 053 public static ApplicationId newInstance(long clusterTimestamp, int id) { 054 ApplicationId appId = Records.newRecord(ApplicationId.class); 055 appId.setClusterTimestamp(clusterTimestamp); 056 appId.setId(id); 057 appId.build(); 058 return appId; 059 } 060 061 /** 062 * Get the short integer identifier of the <code>ApplicationId</code> 063 * which is unique for all applications started by a particular instance 064 * of the <code>ResourceManager</code>. 065 * @return short integer identifier of the <code>ApplicationId</code> 066 */ 067 @Public 068 @Stable 069 public abstract int getId(); 070 071 @Private 072 @Unstable 073 protected abstract void setId(int id); 074 075 /** 076 * Get the <em>start time</em> of the <code>ResourceManager</code> which is 077 * used to generate globally unique <code>ApplicationId</code>. 078 * @return <em>start time</em> of the <code>ResourceManager</code> 079 */ 080 @Public 081 @Stable 082 public abstract long getClusterTimestamp(); 083 084 @Private 085 @Unstable 086 protected abstract void setClusterTimestamp(long clusterTimestamp); 087 088 protected abstract void build(); 089 090 static final ThreadLocal<NumberFormat> appIdFormat = 091 new ThreadLocal<NumberFormat>() { 092 @Override 093 public NumberFormat initialValue() { 094 NumberFormat fmt = NumberFormat.getInstance(); 095 fmt.setGroupingUsed(false); 096 fmt.setMinimumIntegerDigits(4); 097 return fmt; 098 } 099 }; 100 101 @Override 102 public int compareTo(ApplicationId other) { 103 if (this.getClusterTimestamp() - other.getClusterTimestamp() == 0) { 104 return this.getId() - other.getId(); 105 } else { 106 return this.getClusterTimestamp() > other.getClusterTimestamp() ? 1 : 107 this.getClusterTimestamp() < other.getClusterTimestamp() ? -1 : 0; 108 } 109 } 110 111 @Override 112 public String toString() { 113 return appIdStrPrefix + "_" + this.getClusterTimestamp() + "_" + appIdFormat 114 .get().format(getId()); 115 } 116 117 private static ApplicationId toApplicationId( 118 Iterator<String> it) throws NumberFormatException { 119 ApplicationId appId = ApplicationId.newInstance(Long.parseLong(it.next()), 120 Integer.parseInt(it.next())); 121 return appId; 122 } 123 124 @Public 125 @Stable 126 public static ApplicationId fromString(String appIdStr) { 127 Iterator<String> it = _spliter.split((appIdStr)).iterator(); 128 if (!it.next().equals(appIdStrPrefix)) { 129 throw new IllegalArgumentException("Invalid ApplicationId prefix: " 130 + appIdStr + ". The valid ApplicationId should start with prefix " 131 + appIdStrPrefix); 132 } 133 try { 134 return toApplicationId(it); 135 } catch (NumberFormatException n) { 136 throw new IllegalArgumentException("Invalid ApplicationId: " 137 + appIdStr, n); 138 } catch (NoSuchElementException e) { 139 throw new IllegalArgumentException("Invalid ApplicationId: " 140 + appIdStr, e); 141 } 142 } 143 144 @Override 145 public int hashCode() { 146 // Generated by eclipse. 147 final int prime = 371237; 148 int result = 6521; 149 long clusterTimestamp = getClusterTimestamp(); 150 result = prime * result 151 + (int) (clusterTimestamp ^ (clusterTimestamp >>> 32)); 152 result = prime * result + getId(); 153 return result; 154 } 155 156 @Override 157 public boolean equals(Object obj) { 158 if (this == obj) 159 return true; 160 if (obj == null) 161 return false; 162 if (getClass() != obj.getClass()) 163 return false; 164 ApplicationId other = (ApplicationId) obj; 165 if (this.getClusterTimestamp() != other.getClusterTimestamp()) 166 return false; 167 if (this.getId() != other.getId()) 168 return false; 169 return true; 170 } 171}