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.io.IOException; 022import java.text.NumberFormat; 023 024import org.apache.hadoop.classification.InterfaceAudience.Private; 025import org.apache.hadoop.classification.InterfaceAudience.Public; 026import org.apache.hadoop.classification.InterfaceStability.Unstable; 027import org.apache.hadoop.yarn.util.Records; 028 029/** 030 * <p> 031 * {@link ReservationId} represents the <em>globally unique</em> identifier for 032 * a reservation. 033 * </p> 034 * 035 * <p> 036 * The globally unique nature of the identifier is achieved by using the 037 * <em>cluster timestamp</em> i.e. start-time of the {@code ResourceManager} 038 * along with a monotonically increasing counter for the reservation. 039 * </p> 040 */ 041@Public 042@Unstable 043public abstract class ReservationId implements Comparable<ReservationId> { 044 045 @Private 046 @Unstable 047 public static final String reserveIdStrPrefix = "reservation_"; 048 protected long clusterTimestamp; 049 protected long id; 050 051 @Private 052 @Unstable 053 public static ReservationId newInstance(long clusterTimestamp, long id) { 054 ReservationId reservationId = Records.newRecord(ReservationId.class); 055 reservationId.setClusterTimestamp(clusterTimestamp); 056 reservationId.setId(id); 057 reservationId.build(); 058 return reservationId; 059 } 060 061 /** 062 * Get the long identifier of the {@link ReservationId} which is unique for 063 * all Reservations started by a particular instance of the 064 * {@code ResourceManager}. 065 * 066 * @return long identifier of the {@link ReservationId} 067 */ 068 @Public 069 @Unstable 070 public abstract long getId(); 071 072 @Private 073 @Unstable 074 protected abstract void setId(long id); 075 076 /** 077 * Get the <em>start time</em> of the {@code ResourceManager} which is used to 078 * generate globally unique {@link ReservationId}. 079 * 080 * @return <em>start time</em> of the {@code ResourceManager} 081 */ 082 @Public 083 @Unstable 084 public abstract long getClusterTimestamp(); 085 086 @Private 087 @Unstable 088 protected abstract void setClusterTimestamp(long clusterTimestamp); 089 090 protected abstract void build(); 091 092 static final ThreadLocal<NumberFormat> reservIdFormat = 093 new ThreadLocal<NumberFormat>() { 094 @Override 095 public NumberFormat initialValue() { 096 NumberFormat fmt = NumberFormat.getInstance(); 097 fmt.setGroupingUsed(false); 098 fmt.setMinimumIntegerDigits(4); 099 return fmt; 100 } 101 }; 102 103 @Override 104 public int compareTo(ReservationId other) { 105 if (this.getClusterTimestamp() - other.getClusterTimestamp() == 0) { 106 return getId() > getId() ? 1 : getId() < getId() ? -1 : 0; 107 } else { 108 return this.getClusterTimestamp() > other.getClusterTimestamp() ? 1 109 : this.getClusterTimestamp() < other.getClusterTimestamp() ? -1 : 0; 110 } 111 } 112 113 @Override 114 public String toString() { 115 return reserveIdStrPrefix + this.getClusterTimestamp() + "_" 116 + reservIdFormat.get().format(getId()); 117 } 118 119 /** 120 * Parse the string argument as a {@link ReservationId} 121 * 122 * @param reservationId the string representation of the {@link ReservationId} 123 * @return the {@link ReservationId} corresponding to the input string if 124 * valid, null if input is null 125 * @throws IOException if unable to parse the input string 126 */ 127 @Public 128 @Unstable 129 public static ReservationId parseReservationId(String reservationId) 130 throws IOException { 131 if (reservationId == null) { 132 return null; 133 } 134 if (!reservationId.startsWith(reserveIdStrPrefix)) { 135 throw new IOException("The specified reservation id is invalid: " 136 + reservationId); 137 } 138 String[] resFields = reservationId.split("_"); 139 if (resFields.length != 3) { 140 throw new IOException("The specified reservation id is not parseable: " 141 + reservationId); 142 } 143 return newInstance(Long.parseLong(resFields[1]), 144 Long.parseLong(resFields[2])); 145 } 146 147 @Override 148 public int hashCode() { 149 // generated by eclipse 150 final int prime = 31; 151 int result = 1; 152 result = 153 prime * result 154 + (int) (getClusterTimestamp() ^ (getClusterTimestamp() >>> 32)); 155 result = prime * result + (int) (getId() ^ (getId() >>> 32)); 156 return result; 157 } 158 159 @Override 160 public boolean equals(Object obj) { 161 // generated by eclipse 162 if (this == obj) 163 return true; 164 if (obj == null) 165 return false; 166 if (getClass() != obj.getClass()) 167 return false; 168 ReservationId other = (ReservationId) obj; 169 if (getClusterTimestamp() != other.getClusterTimestamp()) 170 return false; 171 if (getId() != other.getId()) 172 return false; 173 return true; 174 } 175 176}