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
077 /** Startup options */
078 static public enum StartupOption{
079 FORMAT ("-format"),
080 CLUSTERID ("-clusterid"),
081 GENCLUSTERID ("-genclusterid"),
082 REGULAR ("-regular"),
083 BACKUP ("-backup"),
084 CHECKPOINT("-checkpoint"),
085 UPGRADE ("-upgrade"),
086 ROLLBACK("-rollback"),
087 FINALIZE("-finalize"),
088 ROLLINGUPGRADE("-rollingUpgrade"),
089 IMPORT ("-importCheckpoint"),
090 BOOTSTRAPSTANDBY("-bootstrapStandby"),
091 INITIALIZESHAREDEDITS("-initializeSharedEdits"),
092 RECOVER ("-recover"),
093 FORCE("-force"),
094 NONINTERACTIVE("-nonInteractive"),
095 RENAMERESERVED("-renameReserved");
096
097 private static final Pattern ENUM_WITH_ROLLING_UPGRADE_OPTION = Pattern.compile(
098 "(\\w+)\\((\\w+)\\)");
099
100 private final String name;
101
102 // Used only with format and upgrade options
103 private String clusterId = null;
104
105 // Used only by rolling upgrade
106 private RollingUpgradeStartupOption rollingUpgradeStartupOption;
107
108 // Used only with format option
109 private boolean isForceFormat = false;
110 private boolean isInteractiveFormat = true;
111
112 // Used only with recovery option
113 private int force = 0;
114
115 private StartupOption(String arg) {this.name = arg;}
116 public String getName() {return name;}
117 public NamenodeRole toNodeRole() {
118 switch(this) {
119 case BACKUP:
120 return NamenodeRole.BACKUP;
121 case CHECKPOINT:
122 return NamenodeRole.CHECKPOINT;
123 default:
124 return NamenodeRole.NAMENODE;
125 }
126 }
127
128 public void setClusterId(String cid) {
129 clusterId = cid;
130 }
131
132 public String getClusterId() {
133 return clusterId;
134 }
135
136 public void setRollingUpgradeStartupOption(String opt) {
137 Preconditions.checkState(this == ROLLINGUPGRADE);
138 rollingUpgradeStartupOption = RollingUpgradeStartupOption.fromString(opt);
139 }
140
141 public RollingUpgradeStartupOption getRollingUpgradeStartupOption() {
142 Preconditions.checkState(this == ROLLINGUPGRADE);
143 return rollingUpgradeStartupOption;
144 }
145
146 public MetaRecoveryContext createRecoveryContext() {
147 if (!name.equals(RECOVER.name))
148 return null;
149 return new MetaRecoveryContext(force);
150 }
151
152 public void setForce(int force) {
153 this.force = force;
154 }
155
156 public int getForce() {
157 return this.force;
158 }
159
160 public boolean getForceFormat() {
161 return isForceFormat;
162 }
163
164 public void setForceFormat(boolean force) {
165 isForceFormat = force;
166 }
167
168 public boolean getInteractiveFormat() {
169 return isInteractiveFormat;
170 }
171
172 public void setInteractiveFormat(boolean interactive) {
173 isInteractiveFormat = interactive;
174 }
175
176 @Override
177 public String toString() {
178 if (this == ROLLINGUPGRADE) {
179 return new StringBuilder(super.toString())
180 .append("(").append(getRollingUpgradeStartupOption()).append(")")
181 .toString();
182 }
183 return super.toString();
184 }
185
186 static public StartupOption getEnum(String value) {
187 Matcher matcher = ENUM_WITH_ROLLING_UPGRADE_OPTION.matcher(value);
188 if (matcher.matches()) {
189 StartupOption option = StartupOption.valueOf(matcher.group(1));
190 option.setRollingUpgradeStartupOption(matcher.group(2));
191 return option;
192 } else {
193 return StartupOption.valueOf(value);
194 }
195 }
196 }
197
198 // Timeouts for communicating with DataNode for streaming writes/reads
199 public static final int READ_TIMEOUT = 60 * 1000;
200 public static final int READ_TIMEOUT_EXTENSION = 5 * 1000;
201 public static final int WRITE_TIMEOUT = 8 * 60 * 1000;
202 public static final int WRITE_TIMEOUT_EXTENSION = 5 * 1000; //for write pipeline
203
204 /**
205 * Defines the NameNode role.
206 */
207 static public enum NamenodeRole {
208 NAMENODE ("NameNode"),
209 BACKUP ("Backup Node"),
210 CHECKPOINT("Checkpoint Node");
211
212 private String description = null;
213 private NamenodeRole(String arg) {this.description = arg;}
214
215 @Override
216 public String toString() {
217 return description;
218 }
219 }
220
221 /**
222 * Block replica states, which it can go through while being constructed.
223 */
224 static public enum ReplicaState {
225 /** Replica is finalized. The state when replica is not modified. */
226 FINALIZED(0),
227 /** Replica is being written to. */
228 RBW(1),
229 /** Replica is waiting to be recovered. */
230 RWR(2),
231 /** Replica is under recovery. */
232 RUR(3),
233 /** Temporary replica: created for replication and relocation only. */
234 TEMPORARY(4);
235
236 private final int value;
237
238 private ReplicaState(int v) {
239 value = v;
240 }
241
242 public int getValue() {
243 return value;
244 }
245
246 public static ReplicaState getState(int v) {
247 return ReplicaState.values()[v];
248 }
249
250 /** Read from in */
251 public static ReplicaState read(DataInput in) throws IOException {
252 return values()[in.readByte()];
253 }
254
255 /** Write to out */
256 public void write(DataOutput out) throws IOException {
257 out.writeByte(ordinal());
258 }
259 }
260
261 /**
262 * States, which a block can go through while it is under construction.
263 */
264 static public enum BlockUCState {
265 /**
266 * Block construction completed.<br>
267 * The block has at least one {@link ReplicaState#FINALIZED} replica,
268 * and is not going to be modified.
269 */
270 COMPLETE,
271 /**
272 * The block is under construction.<br>
273 * It has been recently allocated for write or append.
274 */
275 UNDER_CONSTRUCTION,
276 /**
277 * The block is under recovery.<br>
278 * When a file lease expires its last block may not be {@link #COMPLETE}
279 * and needs to go through a recovery procedure,
280 * which synchronizes the existing replicas contents.
281 */
282 UNDER_RECOVERY,
283 /**
284 * The block is committed.<br>
285 * The client reported that all bytes are written to data-nodes
286 * with the given generation stamp and block length, but no
287 * {@link ReplicaState#FINALIZED}
288 * replicas has yet been reported by data-nodes themselves.
289 */
290 COMMITTED;
291 }
292
293 public static final String NAMENODE_LEASE_HOLDER = "HDFS_NameNode";
294 public static final long NAMENODE_LEASE_RECHECK_INTERVAL = 2000;
295 }
296