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