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.fs;
019
020import java.io.IOException;
021
022import org.apache.hadoop.classification.InterfaceAudience;
023import org.apache.hadoop.classification.InterfaceStability;
024import org.apache.hadoop.util.StringInterner;
025
026/**
027 * Represents the network location of a block, information about the hosts
028 * that contain block replicas, and other block metadata (E.g. the file
029 * offset associated with the block, length, whether it is corrupt, etc).
030 */
031@InterfaceAudience.Public
032@InterfaceStability.Stable
033public class BlockLocation {
034  private String[] hosts; // Datanode hostnames
035  private String[] cachedHosts; // Datanode hostnames with a cached replica
036  private String[] names; // Datanode IP:xferPort for accessing the block
037  private String[] topologyPaths; // Full path name in network topology
038  private String[] storageIds; // Storage ID of each replica
039  private long offset;  // Offset of the block in the file
040  private long length;
041  private boolean corrupt;
042
043  private static final String[] EMPTY_STR_ARRAY = new String[0];
044
045  /**
046   * Default Constructor
047   */
048  public BlockLocation() {
049    this(EMPTY_STR_ARRAY, EMPTY_STR_ARRAY, 0L, 0L);
050  }
051
052  /**
053   * Copy constructor
054   */
055  public BlockLocation(BlockLocation that) {
056    this.hosts = that.hosts;
057    this.cachedHosts = that.cachedHosts;
058    this.names = that.names;
059    this.topologyPaths = that.topologyPaths;
060    this.offset = that.offset;
061    this.length = that.length;
062    this.corrupt = that.corrupt;
063    this.storageIds = that.storageIds;
064  }
065
066  /**
067   * Constructor with host, name, offset and length
068   */
069  public BlockLocation(String[] names, String[] hosts, long offset, 
070                       long length) {
071    this(names, hosts, offset, length, false);
072  }
073
074  /**
075   * Constructor with host, name, offset, length and corrupt flag
076   */
077  public BlockLocation(String[] names, String[] hosts, long offset, 
078                       long length, boolean corrupt) {
079    this(names, hosts, null, offset, length, corrupt);
080  }
081
082  /**
083   * Constructor with host, name, network topology, offset and length
084   */
085  public BlockLocation(String[] names, String[] hosts, String[] topologyPaths,
086                       long offset, long length) {
087    this(names, hosts, topologyPaths, offset, length, false);
088  }
089
090  /**
091   * Constructor with host, name, network topology, offset, length 
092   * and corrupt flag
093   */
094  public BlockLocation(String[] names, String[] hosts, String[] topologyPaths,
095                       long offset, long length, boolean corrupt) {
096    this(names, hosts, null, topologyPaths, offset, length, corrupt);
097  }
098
099  public BlockLocation(String[] names, String[] hosts, String[] cachedHosts,
100      String[] topologyPaths, long offset, long length, boolean corrupt) {
101    this(names, hosts, cachedHosts, topologyPaths, null, offset, length,
102        corrupt);
103  }
104
105  public BlockLocation(String[] names, String[] hosts, String[] cachedHosts,
106      String[] topologyPaths, String[] storageIds,
107      long offset, long length, boolean corrupt) {
108    if (names == null) {
109      this.names = EMPTY_STR_ARRAY;
110    } else {
111      this.names = StringInterner.internStringsInArray(names);
112    }
113    if (hosts == null) {
114      this.hosts = EMPTY_STR_ARRAY;
115    } else {
116      this.hosts = StringInterner.internStringsInArray(hosts);
117    }
118    if (cachedHosts == null) {
119      this.cachedHosts = EMPTY_STR_ARRAY;
120    } else {
121      this.cachedHosts = StringInterner.internStringsInArray(cachedHosts);
122    }
123    if (topologyPaths == null) {
124      this.topologyPaths = EMPTY_STR_ARRAY;
125    } else {
126      this.topologyPaths = StringInterner.internStringsInArray(topologyPaths);
127    }
128    if (storageIds == null) {
129      this.storageIds = EMPTY_STR_ARRAY;
130    } else {
131      this.storageIds = StringInterner.internStringsInArray(storageIds);
132    }
133    this.offset = offset;
134    this.length = length;
135    this.corrupt = corrupt;
136  }
137
138  /**
139   * Get the list of hosts (hostname) hosting this block
140   */
141  public String[] getHosts() throws IOException {
142    return hosts;
143  }
144
145  /**
146   * Get the list of hosts (hostname) hosting a cached replica of the block
147   */
148  public String[] getCachedHosts() {
149   return cachedHosts;
150  }
151
152  /**
153   * Get the list of names (IP:xferPort) hosting this block
154   */
155  public String[] getNames() throws IOException {
156    return names;
157  }
158
159  /**
160   * Get the list of network topology paths for each of the hosts.
161   * The last component of the path is the "name" (IP:xferPort).
162   */
163  public String[] getTopologyPaths() throws IOException {
164    return topologyPaths;
165  }
166
167  /**
168   * Get the storageID of each replica of the block.
169   */
170  public String[] getStorageIds() {
171    return storageIds;
172  }
173
174  /**
175   * Get the start offset of file associated with this block
176   */
177  public long getOffset() {
178    return offset;
179  }
180  
181  /**
182   * Get the length of the block
183   */
184  public long getLength() {
185    return length;
186  }
187
188  /**
189   * Get the corrupt flag.
190   */
191  public boolean isCorrupt() {
192    return corrupt;
193  }
194
195  /**
196   * Set the start offset of file associated with this block
197   */
198  public void setOffset(long offset) {
199    this.offset = offset;
200  }
201
202  /**
203   * Set the length of block
204   */
205  public void setLength(long length) {
206    this.length = length;
207  }
208
209  /**
210   * Set the corrupt flag.
211   */
212  public void setCorrupt(boolean corrupt) {
213    this.corrupt = corrupt;
214  }
215
216  /**
217   * Set the hosts hosting this block
218   */
219  public void setHosts(String[] hosts) throws IOException {
220    if (hosts == null) {
221      this.hosts = EMPTY_STR_ARRAY;
222    } else {
223      this.hosts = StringInterner.internStringsInArray(hosts);
224    }
225  }
226
227  /**
228   * Set the hosts hosting a cached replica of this block
229   */
230  public void setCachedHosts(String[] cachedHosts) {
231    if (cachedHosts == null) {
232      this.cachedHosts = EMPTY_STR_ARRAY;
233    } else {
234      this.cachedHosts = StringInterner.internStringsInArray(cachedHosts);
235    }
236  }
237
238  /**
239   * Set the names (host:port) hosting this block
240   */
241  public void setNames(String[] names) throws IOException {
242    if (names == null) {
243      this.names = EMPTY_STR_ARRAY;
244    } else {
245      this.names = StringInterner.internStringsInArray(names);
246    }
247  }
248
249  /**
250   * Set the network topology paths of the hosts
251   */
252  public void setTopologyPaths(String[] topologyPaths) throws IOException {
253    if (topologyPaths == null) {
254      this.topologyPaths = EMPTY_STR_ARRAY;
255    } else {
256      this.topologyPaths = StringInterner.internStringsInArray(topologyPaths);
257    }
258  }
259
260  public void setStorageIds(String[] storageIds) {
261    if (storageIds == null) {
262      this.storageIds = EMPTY_STR_ARRAY;
263    } else {
264      this.storageIds = StringInterner.internStringsInArray(storageIds);
265    }
266  }
267
268  @Override
269  public String toString() {
270    StringBuilder result = new StringBuilder();
271    result.append(offset);
272    result.append(',');
273    result.append(length);
274    if (corrupt) {
275      result.append("(corrupt)");
276    }
277    for(String h: hosts) {
278      result.append(',');
279      result.append(h);
280    }
281    return result.toString();
282  }
283}