1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 package org.apache.hadoop.hdfs.server.common;
19 
20 import java.io.DataInput;
21 import java.io.DataOutput;
22 import java.io.IOException;
23 import java.util.regex.Matcher;
24 import java.util.regex.Pattern;
25 
26 import org.apache.hadoop.classification.InterfaceAudience;
27 import org.apache.hadoop.hdfs.server.namenode.MetaRecoveryContext;
28 
29 import com.google.common.base.Preconditions;
30 import org.apache.hadoop.util.StringUtils;
31 
32 /************************************
33  * Some handy internal HDFS constants
34  *
35  ************************************/
36 
37 @InterfaceAudience.Private
38 public final class HdfsServerConstants {
39   /* Hidden constructor */
HdfsServerConstants()40   private HdfsServerConstants() { }
41 
42   /**
43    * Type of the node
44    */
45   static public enum NodeType {
46     NAME_NODE,
47     DATA_NODE,
48     JOURNAL_NODE;
49   }
50 
51   /** Startup options for rolling upgrade. */
52   public static enum RollingUpgradeStartupOption{
53     ROLLBACK, DOWNGRADE, STARTED;
54 
getOptionString()55     public String getOptionString() {
56       return StartupOption.ROLLINGUPGRADE.getName() + " "
57           + StringUtils.toLowerCase(name());
58     }
59 
matches(StartupOption option)60     public boolean matches(StartupOption option) {
61       return option == StartupOption.ROLLINGUPGRADE
62           && option.getRollingUpgradeStartupOption() == this;
63     }
64 
65     private static final RollingUpgradeStartupOption[] VALUES = values();
66 
fromString(String s)67     static RollingUpgradeStartupOption fromString(String s) {
68       for(RollingUpgradeStartupOption opt : VALUES) {
69         if (opt.name().equalsIgnoreCase(s)) {
70           return opt;
71         }
72       }
73       throw new IllegalArgumentException("Failed to convert \"" + s
74           + "\" to " + RollingUpgradeStartupOption.class.getSimpleName());
75     }
76 
getAllOptionString()77     public static String getAllOptionString() {
78       final StringBuilder b = new StringBuilder("<");
79       for(RollingUpgradeStartupOption opt : VALUES) {
80         b.append(StringUtils.toLowerCase(opt.name())).append("|");
81       }
82       b.setCharAt(b.length() - 1, '>');
83       return b.toString();
84     }
85   }
86 
87   /** Startup options */
88   static public enum StartupOption{
89     FORMAT  ("-format"),
90     CLUSTERID ("-clusterid"),
91     GENCLUSTERID ("-genclusterid"),
92     REGULAR ("-regular"),
93     BACKUP  ("-backup"),
94     CHECKPOINT("-checkpoint"),
95     UPGRADE ("-upgrade"),
96     ROLLBACK("-rollback"),
97     FINALIZE("-finalize"),
98     ROLLINGUPGRADE("-rollingUpgrade"),
99     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 
StartupOption(String arg)132     private StartupOption(String arg) {this.name = arg;}
getName()133     public String getName() {return name;}
toNodeRole()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 
setClusterId(String cid)145     public void setClusterId(String cid) {
146       clusterId = cid;
147     }
148 
getClusterId()149     public String getClusterId() {
150       return clusterId;
151     }
152 
setRollingUpgradeStartupOption(String opt)153     public void setRollingUpgradeStartupOption(String opt) {
154       Preconditions.checkState(this == ROLLINGUPGRADE);
155       rollingUpgradeStartupOption = RollingUpgradeStartupOption.fromString(opt);
156     }
157 
getRollingUpgradeStartupOption()158     public RollingUpgradeStartupOption getRollingUpgradeStartupOption() {
159       Preconditions.checkState(this == ROLLINGUPGRADE);
160       return rollingUpgradeStartupOption;
161     }
162 
createRecoveryContext()163     public MetaRecoveryContext createRecoveryContext() {
164       if (!name.equals(RECOVER.name))
165         return null;
166       return new MetaRecoveryContext(force);
167     }
168 
setForce(int force)169     public void setForce(int force) {
170       this.force = force;
171     }
172 
getForce()173     public int getForce() {
174       return this.force;
175     }
176 
getForceFormat()177     public boolean getForceFormat() {
178       return isForceFormat;
179     }
180 
setForceFormat(boolean force)181     public void setForceFormat(boolean force) {
182       isForceFormat = force;
183     }
184 
getInteractiveFormat()185     public boolean getInteractiveFormat() {
186       return isInteractiveFormat;
187     }
188 
setInteractiveFormat(boolean interactive)189     public void setInteractiveFormat(boolean interactive) {
190       isInteractiveFormat = interactive;
191     }
192 
193     @Override
toString()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 
getEnum(String value)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;
NamenodeRole(String arg)230     private NamenodeRole(String arg) {this.description = arg;}
231 
232     @Override
toString()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 static final ReplicaState[] cachedValues = ReplicaState.values();
254 
255     private final int value;
256 
ReplicaState(int v)257     private ReplicaState(int v) {
258       value = v;
259     }
260 
getValue()261     public int getValue() {
262       return value;
263     }
264 
getState(int v)265     public static ReplicaState getState(int v) {
266       return cachedValues[v];
267     }
268 
269     /** Read from in */
read(DataInput in)270     public static ReplicaState read(DataInput in) throws IOException {
271       return cachedValues[in.readByte()];
272     }
273 
274     /** Write to out */
write(DataOutput out)275     public void write(DataOutput out) throws IOException {
276       out.writeByte(ordinal());
277     }
278   }
279 
280   /**
281    * States, which a block can go through while it is under construction.
282    */
283   static public enum BlockUCState {
284     /**
285      * Block construction completed.<br>
286      * The block has at least the configured minimal replication number
287      * of {@link ReplicaState#FINALIZED} replica(s), and is not going to be
288      * modified.
289      * NOTE, in some special cases, a block may be forced to COMPLETE state,
290      * even if it doesn't have required minimal replications.
291      */
292     COMPLETE,
293     /**
294      * The block is under construction.<br>
295      * It has been recently allocated for write or append.
296      */
297     UNDER_CONSTRUCTION,
298     /**
299      * The block is under recovery.<br>
300      * When a file lease expires its last block may not be {@link #COMPLETE}
301      * and needs to go through a recovery procedure,
302      * which synchronizes the existing replicas contents.
303      */
304     UNDER_RECOVERY,
305     /**
306      * The block is committed.<br>
307      * The client reported that all bytes are written to data-nodes
308      * with the given generation stamp and block length, but no
309      * {@link ReplicaState#FINALIZED}
310      * replicas has yet been reported by data-nodes themselves.
311      */
312     COMMITTED;
313   }
314 
315   public static final String NAMENODE_LEASE_HOLDER = "HDFS_NameNode";
316   public static final long NAMENODE_LEASE_RECHECK_INTERVAL = 2000;
317 
318   public static final String CRYPTO_XATTR_ENCRYPTION_ZONE =
319       "raw.hdfs.crypto.encryption.zone";
320   public static final String CRYPTO_XATTR_FILE_ENCRYPTION_INFO =
321       "raw.hdfs.crypto.file.encryption.info";
322   public static final String SECURITY_XATTR_UNREADABLE_BY_SUPERUSER =
323       "security.hdfs.unreadable.by.superuser";
324 }
325