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