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 */ 018package org.apache.hadoop.hdfs.server.common; 019 020import java.io.DataInput; 021import java.io.DataOutput; 022import java.io.IOException; 023import java.util.regex.Matcher; 024import java.util.regex.Pattern; 025 026import org.apache.hadoop.classification.InterfaceAudience; 027import org.apache.hadoop.hdfs.DFSUtil; 028import org.apache.hadoop.hdfs.client.HdfsClientConfigKeys; 029import org.apache.hadoop.hdfs.protocol.HdfsConstants; 030import org.apache.hadoop.hdfs.server.datanode.DataNodeLayoutVersion; 031import org.apache.hadoop.hdfs.server.namenode.FSDirectory; 032import org.apache.hadoop.hdfs.server.namenode.MetaRecoveryContext; 033 034import com.google.common.base.Preconditions; 035import org.apache.hadoop.hdfs.server.namenode.NameNodeLayoutVersion; 036import org.apache.hadoop.util.StringUtils; 037 038/************************************ 039 * Some handy internal HDFS constants 040 * 041 ************************************/ 042 043@InterfaceAudience.Private 044public interface HdfsServerConstants { 045 int MIN_BLOCKS_FOR_WRITE = 1; 046 047 /** 048 * Please see {@link HdfsConstants#LEASE_SOFTLIMIT_PERIOD} and 049 * {@link HdfsConstants#LEASE_HARDLIMIT_PERIOD} for more information. 050 */ 051 long LEASE_SOFTLIMIT_PERIOD = HdfsConstants.LEASE_SOFTLIMIT_PERIOD; 052 long LEASE_HARDLIMIT_PERIOD = HdfsConstants.LEASE_HARDLIMIT_PERIOD; 053 054 long LEASE_RECOVER_PERIOD = 10 * 1000; // in ms 055 // We need to limit the length and depth of a path in the filesystem. 056 // HADOOP-438 057 // Currently we set the maximum length to 8k characters and the maximum depth 058 // to 1k. 059 int MAX_PATH_LENGTH = 8000; 060 int MAX_PATH_DEPTH = 1000; 061 // An invalid transaction ID that will never be seen in a real namesystem. 062 long INVALID_TXID = -12345; 063 // Number of generation stamps reserved for legacy blocks. 064 long RESERVED_GENERATION_STAMPS_V1 = 065 1024L * 1024 * 1024 * 1024; 066 /** 067 * Current layout version for NameNode. 068 * Please see {@link NameNodeLayoutVersion.Feature} on adding new layout version. 069 */ 070 int NAMENODE_LAYOUT_VERSION 071 = NameNodeLayoutVersion.CURRENT_LAYOUT_VERSION; 072 /** 073 * Current layout version for DataNode. 074 * Please see {@link DataNodeLayoutVersion.Feature} on adding new layout version. 075 */ 076 int DATANODE_LAYOUT_VERSION 077 = DataNodeLayoutVersion.CURRENT_LAYOUT_VERSION; 078 /** 079 * Path components that are reserved in HDFS. 080 * <p> 081 * .reserved is only reserved under root ("/"). 082 */ 083 String[] RESERVED_PATH_COMPONENTS = new String[] { 084 HdfsConstants.DOT_SNAPSHOT_DIR, 085 FSDirectory.DOT_RESERVED_STRING 086 }; 087 byte[] DOT_SNAPSHOT_DIR_BYTES 088 = DFSUtil.string2Bytes(HdfsConstants.DOT_SNAPSHOT_DIR); 089 090 /** 091 * Type of the node 092 */ 093 enum NodeType { 094 NAME_NODE, 095 DATA_NODE, 096 JOURNAL_NODE 097 } 098 099 /** Startup options for rolling upgrade. */ 100 public static enum RollingUpgradeStartupOption{ 101 ROLLBACK, DOWNGRADE, STARTED; 102 103 public String getOptionString() { 104 return StartupOption.ROLLINGUPGRADE.getName() + " " 105 + StringUtils.toLowerCase(name()); 106 } 107 108 public boolean matches(StartupOption option) { 109 return option == StartupOption.ROLLINGUPGRADE 110 && option.getRollingUpgradeStartupOption() == this; 111 } 112 113 private static final RollingUpgradeStartupOption[] VALUES = values(); 114 115 static RollingUpgradeStartupOption fromString(String s) { 116 for(RollingUpgradeStartupOption opt : VALUES) { 117 if (opt.name().equalsIgnoreCase(s)) { 118 return opt; 119 } 120 } 121 throw new IllegalArgumentException("Failed to convert \"" + s 122 + "\" to " + RollingUpgradeStartupOption.class.getSimpleName()); 123 } 124 125 public static String getAllOptionString() { 126 final StringBuilder b = new StringBuilder("<"); 127 for(RollingUpgradeStartupOption opt : VALUES) { 128 b.append(StringUtils.toLowerCase(opt.name())).append("|"); 129 } 130 b.setCharAt(b.length() - 1, '>'); 131 return b.toString(); 132 } 133 } 134 135 /** Startup options */ 136 enum StartupOption{ 137 FORMAT ("-format"), 138 CLUSTERID ("-clusterid"), 139 GENCLUSTERID ("-genclusterid"), 140 REGULAR ("-regular"), 141 BACKUP ("-backup"), 142 CHECKPOINT("-checkpoint"), 143 UPGRADE ("-upgrade"), 144 ROLLBACK("-rollback"), 145 FINALIZE("-finalize"), 146 ROLLINGUPGRADE("-rollingUpgrade"), 147 IMPORT ("-importCheckpoint"), 148 BOOTSTRAPSTANDBY("-bootstrapStandby"), 149 INITIALIZESHAREDEDITS("-initializeSharedEdits"), 150 RECOVER ("-recover"), 151 FORCE("-force"), 152 NONINTERACTIVE("-nonInteractive"), 153 SKIPSHAREDEDITSCHECK("-skipSharedEditsCheck"), 154 RENAMERESERVED("-renameReserved"), 155 METADATAVERSION("-metadataVersion"), 156 UPGRADEONLY("-upgradeOnly"), 157 // The -hotswap constant should not be used as a startup option, it is 158 // only used for StorageDirectory.analyzeStorage() in hot swap drive scenario. 159 // TODO refactor StorageDirectory.analyzeStorage() so that we can do away with 160 // this in StartupOption. 161 HOTSWAP("-hotswap"); 162 163 private static final Pattern ENUM_WITH_ROLLING_UPGRADE_OPTION = Pattern.compile( 164 "(\\w+)\\((\\w+)\\)"); 165 166 private final String name; 167 168 // Used only with format and upgrade options 169 private String clusterId = null; 170 171 // Used only by rolling upgrade 172 private RollingUpgradeStartupOption rollingUpgradeStartupOption; 173 174 // Used only with format option 175 private boolean isForceFormat = false; 176 private boolean isInteractiveFormat = true; 177 178 // Used only with recovery option 179 private int force = 0; 180 181 StartupOption(String arg) {this.name = arg;} 182 public String getName() {return name;} 183 public NamenodeRole toNodeRole() { 184 switch(this) { 185 case BACKUP: 186 return NamenodeRole.BACKUP; 187 case CHECKPOINT: 188 return NamenodeRole.CHECKPOINT; 189 default: 190 return NamenodeRole.NAMENODE; 191 } 192 } 193 194 public void setClusterId(String cid) { 195 clusterId = cid; 196 } 197 198 public String getClusterId() { 199 return clusterId; 200 } 201 202 public void setRollingUpgradeStartupOption(String opt) { 203 Preconditions.checkState(this == ROLLINGUPGRADE); 204 rollingUpgradeStartupOption = RollingUpgradeStartupOption.fromString(opt); 205 } 206 207 public RollingUpgradeStartupOption getRollingUpgradeStartupOption() { 208 Preconditions.checkState(this == ROLLINGUPGRADE); 209 return rollingUpgradeStartupOption; 210 } 211 212 public MetaRecoveryContext createRecoveryContext() { 213 if (!name.equals(RECOVER.name)) 214 return null; 215 return new MetaRecoveryContext(force); 216 } 217 218 public void setForce(int force) { 219 this.force = force; 220 } 221 222 public int getForce() { 223 return this.force; 224 } 225 226 public boolean getForceFormat() { 227 return isForceFormat; 228 } 229 230 public void setForceFormat(boolean force) { 231 isForceFormat = force; 232 } 233 234 public boolean getInteractiveFormat() { 235 return isInteractiveFormat; 236 } 237 238 public void setInteractiveFormat(boolean interactive) { 239 isInteractiveFormat = interactive; 240 } 241 242 @Override 243 public String toString() { 244 if (this == ROLLINGUPGRADE) { 245 return new StringBuilder(super.toString()) 246 .append("(").append(getRollingUpgradeStartupOption()).append(")") 247 .toString(); 248 } 249 return super.toString(); 250 } 251 252 static public StartupOption getEnum(String value) { 253 Matcher matcher = ENUM_WITH_ROLLING_UPGRADE_OPTION.matcher(value); 254 if (matcher.matches()) { 255 StartupOption option = StartupOption.valueOf(matcher.group(1)); 256 option.setRollingUpgradeStartupOption(matcher.group(2)); 257 return option; 258 } else { 259 return StartupOption.valueOf(value); 260 } 261 } 262 } 263 264 /** 265 * Defines the NameNode role. 266 */ 267 enum NamenodeRole { 268 NAMENODE ("NameNode"), 269 BACKUP ("Backup Node"), 270 CHECKPOINT("Checkpoint Node"); 271 272 private String description = null; 273 NamenodeRole(String arg) {this.description = arg;} 274 275 @Override 276 public String toString() { 277 return description; 278 } 279 } 280 281 /** 282 * Block replica states, which it can go through while being constructed. 283 */ 284 enum ReplicaState { 285 /** Replica is finalized. The state when replica is not modified. */ 286 FINALIZED(0), 287 /** Replica is being written to. */ 288 RBW(1), 289 /** Replica is waiting to be recovered. */ 290 RWR(2), 291 /** Replica is under recovery. */ 292 RUR(3), 293 /** Temporary replica: created for replication and relocation only. */ 294 TEMPORARY(4); 295 296 private static final ReplicaState[] cachedValues = ReplicaState.values(); 297 298 private final int value; 299 300 ReplicaState(int v) { 301 value = v; 302 } 303 304 public int getValue() { 305 return value; 306 } 307 308 public static ReplicaState getState(int v) { 309 return cachedValues[v]; 310 } 311 312 /** Read from in */ 313 public static ReplicaState read(DataInput in) throws IOException { 314 return cachedValues[in.readByte()]; 315 } 316 317 /** Write to out */ 318 public void write(DataOutput out) throws IOException { 319 out.writeByte(ordinal()); 320 } 321 } 322 323 /** 324 * States, which a block can go through while it is under construction. 325 */ 326 enum BlockUCState { 327 /** 328 * Block construction completed.<br> 329 * The block has at least the configured minimal replication number 330 * of {@link ReplicaState#FINALIZED} replica(s), and is not going to be 331 * modified. 332 * NOTE, in some special cases, a block may be forced to COMPLETE state, 333 * even if it doesn't have required minimal replications. 334 */ 335 COMPLETE, 336 /** 337 * The block is under construction.<br> 338 * It has been recently allocated for write or append. 339 */ 340 UNDER_CONSTRUCTION, 341 /** 342 * The block is under recovery.<br> 343 * When a file lease expires its last block may not be {@link #COMPLETE} 344 * and needs to go through a recovery procedure, 345 * which synchronizes the existing replicas contents. 346 */ 347 UNDER_RECOVERY, 348 /** 349 * The block is committed.<br> 350 * The client reported that all bytes are written to data-nodes 351 * with the given generation stamp and block length, but no 352 * {@link ReplicaState#FINALIZED} 353 * replicas has yet been reported by data-nodes themselves. 354 */ 355 COMMITTED 356 } 357 358 String NAMENODE_LEASE_HOLDER = "HDFS_NameNode"; 359 360 String CRYPTO_XATTR_ENCRYPTION_ZONE = 361 "raw.hdfs.crypto.encryption.zone"; 362 String CRYPTO_XATTR_FILE_ENCRYPTION_INFO = 363 "raw.hdfs.crypto.file.encryption.info"; 364 String SECURITY_XATTR_UNREADABLE_BY_SUPERUSER = 365 "security.hdfs.unreadable.by.superuser"; 366}