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
019package org.apache.hadoop.hdfs.server.protocol;
020
021import java.io.IOException;
022
023import org.apache.hadoop.classification.InterfaceAudience;
024import org.apache.hadoop.classification.InterfaceStability;
025import org.apache.hadoop.ha.HAServiceProtocol.HAServiceState;
026import org.apache.hadoop.hdfs.server.common.HdfsServerConstants;
027import org.apache.hadoop.hdfs.server.common.Storage;
028import org.apache.hadoop.hdfs.server.common.StorageInfo;
029import org.apache.hadoop.hdfs.server.common.HdfsServerConstants.NodeType;
030import org.apache.hadoop.hdfs.server.namenode.NNStorage;
031import org.apache.hadoop.util.VersionInfo;
032
033import com.google.common.annotations.VisibleForTesting;
034import com.google.common.base.Preconditions;
035
036/**
037 * NamespaceInfo is returned by the name-node in reply 
038 * to a data-node handshake.
039 * 
040 */
041@InterfaceAudience.Private
042@InterfaceStability.Evolving
043public class NamespaceInfo extends StorageInfo {
044  final String  buildVersion;
045  String blockPoolID = "";    // id of the block pool
046  String softwareVersion;
047  long capabilities;
048  HAServiceState state;
049
050  // only authoritative on the server-side to determine advertisement to
051  // clients.  enum will update the supported values
052  private static final long CAPABILITIES_SUPPORTED = getSupportedCapabilities();
053
054  private static long getSupportedCapabilities() {
055    long mask = 0;
056    for (Capability c : Capability.values()) {
057      if (c.supported) {
058        mask |= c.mask;
059      }
060    }
061    return mask;
062  }
063
064  public enum Capability {
065    UNKNOWN(false),
066    STORAGE_BLOCK_REPORT_BUFFERS(true); // use optimized ByteString buffers
067    private final boolean supported;
068    private final long mask;
069    Capability(boolean isSupported) {
070      supported = isSupported;
071      int bits = ordinal() - 1;
072      mask = (bits < 0) ? 0 : (1L << bits);
073    }
074    public long getMask() {
075      return mask;
076    }
077  }
078
079  // defaults to enabled capabilites since this ctor is for server
080  public NamespaceInfo() {
081    super(NodeType.NAME_NODE);
082    buildVersion = null;
083    capabilities = CAPABILITIES_SUPPORTED;
084  }
085
086  // defaults to enabled capabilites since this ctor is for server
087  public NamespaceInfo(int nsID, String clusterID, String bpID,
088      long cT, String buildVersion, String softwareVersion) {
089    this(nsID, clusterID, bpID, cT, buildVersion, softwareVersion,
090        CAPABILITIES_SUPPORTED);
091  }
092
093  public NamespaceInfo(int nsID, String clusterID, String bpID,
094      long cT, String buildVersion, String softwareVersion,
095      long capabilities, HAServiceState st) {
096    this(nsID, clusterID, bpID, cT, buildVersion, softwareVersion,
097        capabilities);
098    this.state = st;
099  }
100
101  // for use by server and/or client
102  public NamespaceInfo(int nsID, String clusterID, String bpID,
103      long cT, String buildVersion, String softwareVersion,
104      long capabilities) {
105    super(HdfsServerConstants.NAMENODE_LAYOUT_VERSION, nsID, clusterID, cT,
106        NodeType.NAME_NODE);
107    blockPoolID = bpID;
108    this.buildVersion = buildVersion;
109    this.softwareVersion = softwareVersion;
110    this.capabilities = capabilities;
111  }
112
113  public NamespaceInfo(int nsID, String clusterID, String bpID, 
114      long cT) {
115    this(nsID, clusterID, bpID, cT, Storage.getBuildVersion(),
116        VersionInfo.getVersion());
117  }
118
119  public NamespaceInfo(int nsID, String clusterID, String bpID,
120      long cT, HAServiceState st) {
121    this(nsID, clusterID, bpID, cT, Storage.getBuildVersion(),
122        VersionInfo.getVersion());
123    this.state = st;
124  }
125  
126  public long getCapabilities() {
127    return capabilities;
128  }
129
130  @VisibleForTesting
131  public void setCapabilities(long capabilities) {
132    this.capabilities = capabilities;
133  }
134
135  @VisibleForTesting
136  public void setState(HAServiceState state) {
137    this.state = state;
138  }
139
140  public boolean isCapabilitySupported(Capability capability) {
141    Preconditions.checkArgument(capability != Capability.UNKNOWN,
142        "cannot test for unknown capability");
143    long mask = capability.getMask();
144    return (capabilities & mask) == mask;
145  }
146
147  public String getBuildVersion() {
148    return buildVersion;
149  }
150
151  public String getBlockPoolID() {
152    return blockPoolID;
153  }
154  
155  public String getSoftwareVersion() {
156    return softwareVersion;
157  }
158
159  public HAServiceState getState() {
160    return state;
161  }
162
163  @Override
164  public String toString(){
165    return super.toString() + ";bpid=" + blockPoolID;
166  }
167
168  public void validateStorage(NNStorage storage) throws IOException {
169    if (layoutVersion != storage.getLayoutVersion() ||
170        namespaceID != storage.getNamespaceID() ||
171        cTime != storage.cTime ||
172        !clusterID.equals(storage.getClusterID()) ||
173        !blockPoolID.equals(storage.getBlockPoolID())) {
174      throw new IOException("Inconsistent namespace information:\n" +
175          "NamespaceInfo has:\n" +
176          "LV=" + layoutVersion + ";" +
177          "NS=" + namespaceID + ";" +
178          "cTime=" + cTime + ";" +
179          "CID=" + clusterID + ";" +
180          "BPID=" + blockPoolID +
181          ".\nStorage has:\n" +
182          "LV=" + storage.getLayoutVersion() + ";" +
183          "NS=" + storage.getNamespaceID() + ";" +
184          "cTime=" + storage.getCTime() + ";" +
185          "CID=" + storage.getClusterID() + ";" +
186          "BPID=" + storage.getBlockPoolID() + ".");
187    }
188  }
189}