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