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