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.fs;
019    
020    import java.io.DataInput;
021    import java.io.DataOutput;
022    import java.io.IOException;
023    
024    import org.apache.hadoop.classification.InterfaceAudience;
025    import org.apache.hadoop.classification.InterfaceStability;
026    import org.apache.hadoop.io.Text;
027    import org.apache.hadoop.io.Writable;
028    import org.apache.hadoop.io.WritableFactories;
029    import 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
038    public 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    }