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 package org.apache.hadoop.hdfs.protocol; 019 020 import java.util.EnumSet; 021 import java.util.HashMap; 022 import java.util.Map; 023 024 import org.apache.hadoop.classification.InterfaceAudience; 025 026 /** 027 * This class tracks changes in the layout version of HDFS. 028 * 029 * Layout version is changed for following reasons: 030 * <ol> 031 * <li>The layout of how namenode or datanode stores information 032 * on disk changes.</li> 033 * <li>A new operation code is added to the editlog.</li> 034 * <li>Modification such as format of a record, content of a record 035 * in editlog or fsimage.</li> 036 * </ol> 037 * <br> 038 * <b>How to update layout version:<br></b> 039 * When a change requires new layout version, please add an entry into 040 * {@link Feature} with a short enum name, new layout version and description 041 * of the change. Please see {@link Feature} for further details. 042 * <br> 043 */ 044 @InterfaceAudience.Private 045 public class LayoutVersion { 046 047 /** 048 * Version in which HDFS-2991 was fixed. This bug caused OP_ADD to 049 * sometimes be skipped for append() calls. If we see such a case when 050 * loading the edits, but the version is known to have that bug, we 051 * workaround the issue. Otherwise we should consider it a corruption 052 * and bail. 053 */ 054 public static final int BUGFIX_HDFS_2991_VERSION = -40; 055 056 /** 057 * Enums for features that change the layout version. 058 * <br><br> 059 * To add a new layout version: 060 * <ul> 061 * <li>Define a new enum constant with a short enum name, the new layout version 062 * and description of the added feature.</li> 063 * <li>When adding a layout version with an ancestor that is not same as 064 * its immediate predecessor, use the constructor where a spacific ancestor 065 * can be passed. 066 * </li> 067 * </ul> 068 */ 069 public static enum Feature { 070 NAMESPACE_QUOTA(-16, "Support for namespace quotas"), 071 FILE_ACCESS_TIME(-17, "Support for access time on files"), 072 DISKSPACE_QUOTA(-18, "Support for disk space quotas"), 073 STICKY_BIT(-19, "Support for sticky bits"), 074 APPEND_RBW_DIR(-20, "Datanode has \"rbw\" subdirectory for append"), 075 ATOMIC_RENAME(-21, "Support for atomic rename"), 076 CONCAT(-22, "Support for concat operation"), 077 SYMLINKS(-23, "Support for symbolic links"), 078 DELEGATION_TOKEN(-24, "Support for delegation tokens for security"), 079 FSIMAGE_COMPRESSION(-25, "Support for fsimage compression"), 080 FSIMAGE_CHECKSUM(-26, "Support checksum for fsimage"), 081 REMOVE_REL13_DISK_LAYOUT_SUPPORT(-27, "Remove support for 0.13 disk layout"), 082 EDITS_CHESKUM(-28, "Support checksum for editlog"), 083 UNUSED(-29, "Skipped version"), 084 FSIMAGE_NAME_OPTIMIZATION(-30, "Store only last part of path in fsimage"), 085 RESERVED_REL20_203(-31, -19, "Reserved for release 0.20.203"), 086 RESERVED_REL20_204(-32, "Reserved for release 0.20.204"), 087 RESERVED_REL22(-33, -27, "Reserved for release 0.22"), 088 RESERVED_REL23(-34, -30, "Reserved for release 0.23"), 089 FEDERATION(-35, "Support for namenode federation"), 090 LEASE_REASSIGNMENT(-36, "Support for persisting lease holder reassignment"), 091 STORED_TXIDS(-37, "Transaction IDs are stored in edits log and image files"), 092 TXID_BASED_LAYOUT(-38, "File names in NN Storage are based on transaction IDs"), 093 EDITLOG_OP_OPTIMIZATION(-39, 094 "Use LongWritable and ShortWritable directly instead of ArrayWritable of UTF8"), 095 OPTIMIZE_PERSIST_BLOCKS(-40, 096 "Serialize block lists with delta-encoded variable length ints, " + 097 "add OP_UPDATE_BLOCKS"); 098 099 final int lv; 100 final int ancestorLV; 101 final String description; 102 103 /** 104 * Feature that is added at {@code currentLV}. 105 * @param lv new layout version with the addition of this feature 106 * @param description description of the feature 107 */ 108 Feature(final int lv, final String description) { 109 this(lv, lv + 1, description); 110 } 111 112 /** 113 * Feature that is added at {@code currentLV}. 114 * @param lv new layout version with the addition of this feature 115 * @param ancestorLV layout version from which the new lv is derived 116 * from. 117 * @param description description of the feature 118 */ 119 Feature(final int lv, final int ancestorLV, 120 final String description) { 121 this.lv = lv; 122 this.ancestorLV = ancestorLV; 123 this.description = description; 124 } 125 126 /** 127 * Accessor method for feature layout version 128 * @return int lv value 129 */ 130 public int getLayoutVersion() { 131 return lv; 132 } 133 134 /** 135 * Accessor method for feature ancestor layout version 136 * @return int ancestor LV value 137 */ 138 public int getAncestorLayoutVersion() { 139 return ancestorLV; 140 } 141 142 /** 143 * Accessor method for feature description 144 * @return String feature description 145 */ 146 public String getDescription() { 147 return description; 148 } 149 } 150 151 // Build layout version and corresponding feature matrix 152 static final Map<Integer, EnumSet<Feature>>map = 153 new HashMap<Integer, EnumSet<Feature>>(); 154 155 // Static initialization 156 static { 157 initMap(); 158 } 159 160 /** 161 * Initialize the map of a layout version and EnumSet of {@link Feature}s 162 * supported. 163 */ 164 private static void initMap() { 165 // Go through all the enum constants and build a map of 166 // LayoutVersion <-> EnumSet of all supported features in that LayoutVersion 167 for (Feature f : Feature.values()) { 168 EnumSet<Feature> ancestorSet = map.get(f.ancestorLV); 169 if (ancestorSet == null) { 170 ancestorSet = EnumSet.noneOf(Feature.class); // Empty enum set 171 map.put(f.ancestorLV, ancestorSet); 172 } 173 EnumSet<Feature> featureSet = EnumSet.copyOf(ancestorSet); 174 featureSet.add(f); 175 map.put(f.lv, featureSet); 176 } 177 178 // Special initialization for 0.20.203 and 0.20.204 179 // to add Feature#DELEGATION_TOKEN 180 specialInit(Feature.RESERVED_REL20_203.lv, Feature.DELEGATION_TOKEN); 181 specialInit(Feature.RESERVED_REL20_204.lv, Feature.DELEGATION_TOKEN); 182 } 183 184 private static void specialInit(int lv, Feature f) { 185 EnumSet<Feature> set = map.get(lv); 186 set.add(f); 187 } 188 189 /** 190 * Gets formatted string that describes {@link LayoutVersion} information. 191 */ 192 public static String getString() { 193 final StringBuilder buf = new StringBuilder(); 194 buf.append("Feature List:\n"); 195 for (Feature f : Feature.values()) { 196 buf.append(f).append(" introduced in layout version ") 197 .append(f.lv).append(" ("). 198 append(f.description).append(")\n"); 199 } 200 201 buf.append("\n\nLayoutVersion and supported features:\n"); 202 for (Feature f : Feature.values()) { 203 buf.append(f.lv).append(": ").append(map.get(f.lv)) 204 .append("\n"); 205 } 206 return buf.toString(); 207 } 208 209 /** 210 * Returns true if a given feature is supported in the given layout version 211 * @param f Feature 212 * @param lv LayoutVersion 213 * @return true if {@code f} is supported in layout version {@code lv} 214 */ 215 public static boolean supports(final Feature f, final int lv) { 216 final EnumSet<Feature> set = map.get(lv); 217 return set != null && set.contains(f); 218 } 219 220 /** 221 * Get the current layout version 222 */ 223 public static int getCurrentLayoutVersion() { 224 Feature[] values = Feature.values(); 225 return values[values.length - 1].lv; 226 } 227 }