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.server.namenode.MetaRecoveryContext;
028
029import com.google.common.base.Preconditions;
030
031/************************************
032 * Some handy internal HDFS constants
033 *
034 ************************************/
035
036@InterfaceAudience.Private
037public 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