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