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.hdfs.server.datanode;
019
020
021import java.io.Closeable;
022import java.io.File;
023import java.io.FilterInputStream;
024import java.io.IOException;
025import java.io.InputStream;
026import java.io.OutputStream;
027import java.util.List;
028import java.util.Map;
029
030import org.apache.hadoop.classification.InterfaceAudience;
031import org.apache.hadoop.conf.Configuration;
032import org.apache.hadoop.hdfs.DFSConfigKeys;
033import org.apache.hadoop.hdfs.protocol.Block;
034import org.apache.hadoop.hdfs.protocol.BlockListAsLongs;
035import org.apache.hadoop.hdfs.protocol.BlockLocalPathInfo;
036import org.apache.hadoop.hdfs.protocol.ExtendedBlock;
037import org.apache.hadoop.hdfs.server.datanode.metrics.FSDatasetMBean;
038import org.apache.hadoop.hdfs.server.protocol.BlockRecoveryCommand.RecoveringBlock;
039import org.apache.hadoop.hdfs.server.protocol.ReplicaRecoveryInfo;
040import org.apache.hadoop.io.IOUtils;
041import org.apache.hadoop.util.DataChecksum;
042import org.apache.hadoop.util.ReflectionUtils;
043import org.apache.hadoop.util.DiskChecker.DiskErrorException;
044
045/**
046 * This is an interface for the underlying storage that stores blocks for
047 * a data node. 
048 * Examples are the FSDataset (which stores blocks on dirs)  and 
049 * SimulatedFSDataset (which simulates data).
050 *
051 */
052@InterfaceAudience.Private
053public interface FSDatasetInterface extends FSDatasetMBean {
054  /**
055   * A factory for creating FSDatasetInterface objects.
056   */
057  public abstract class Factory {
058    /** @return the configured factory. */
059    public static Factory getFactory(Configuration conf) {
060      final Class<? extends Factory> clazz = conf.getClass(
061          DFSConfigKeys.DFS_DATANODE_FSDATASET_FACTORY_KEY,
062          FSDataset.Factory.class,
063          Factory.class);
064      return ReflectionUtils.newInstance(clazz, conf);
065    }
066
067    /** Create a FSDatasetInterface object. */
068    public abstract FSDatasetInterface createFSDatasetInterface(
069        DataNode datanode, DataStorage storage, Configuration conf
070        ) throws IOException;
071
072    /** Does the factory create simulated objects? */
073    public boolean isSimulated() {
074      return false;
075    }
076  }
077
078  /**
079   * This is an interface for the underlying volume.
080   * @see org.apache.hadoop.hdfs.server.datanode.FSDataset.FSVolume
081   */
082  interface FSVolumeInterface {
083    /** @return a list of block pools. */
084    public String[] getBlockPoolList();
085
086    /** @return the available storage space in bytes. */
087    public long getAvailable() throws IOException;
088
089    /** @return the base path to the volume */
090    public String getBasePath();
091
092    /** @return the directory for the block pool. */
093    public File getDirectory(String bpid) throws IOException;
094
095    /** @return the directory for the finalized blocks in the block pool. */
096    public File getFinalizedDir(String bpid) throws IOException;
097  }
098
099  /** @return a list of volumes. */
100  public List<FSVolumeInterface> getVolumes();
101
102  /** @return a volume information map (name => info). */
103  public Map<String, Object> getVolumeInfoMap();
104
105  /** @return a list of block pools. */
106  public String[] getBlockPoolList();
107
108  /** @return a list of finalized blocks for the given block pool. */
109  public List<Block> getFinalizedBlocks(String bpid);
110
111  /**
112   * Check whether the in-memory block record matches the block on the disk,
113   * and, in case that they are not matched, update the record or mark it
114   * as corrupted.
115   */
116  public void checkAndUpdate(String bpid, long blockId, File diskFile,
117      File diskMetaFile, FSVolumeInterface vol);
118
119  /**
120   * Returns the length of the metadata file of the specified block
121   * @param b - the block for which the metadata length is desired
122   * @return the length of the metadata file for the specified block.
123   * @throws IOException
124   */
125  public long getMetaDataLength(ExtendedBlock b) throws IOException;
126  
127  /**
128   * This class provides the input stream and length of the metadata
129   * of a block
130   *
131   */
132  static class MetaDataInputStream extends FilterInputStream {
133    MetaDataInputStream(InputStream stream, long len) {
134      super(stream);
135      length = len;
136    }
137    private long length;
138    
139    public long getLength() {
140      return length;
141    }
142  }
143  
144  /**
145   * Returns metaData of block b as an input stream (and its length)
146   * @param b - the block
147   * @return the metadata input stream; 
148   * @throws IOException
149   */
150  public MetaDataInputStream getMetaDataInputStream(ExtendedBlock b)
151        throws IOException;
152  
153  /**
154   * Does the meta file exist for this block?
155   * @param b - the block
156   * @return true of the metafile for specified block exits
157   * @throws IOException
158   */
159  public boolean metaFileExists(ExtendedBlock b) throws IOException;
160
161
162  /**
163   * Returns the specified block's on-disk length (excluding metadata)
164   * @param b
165   * @return   the specified block's on-disk length (excluding metadta)
166   * @throws IOException
167   */
168  public long getLength(ExtendedBlock b) throws IOException;
169
170  /**
171   * Get reference to the replica meta info in the replicasMap. 
172   * To be called from methods that are synchronized on {@link FSDataset}
173   * @param blockId
174   * @return replica from the replicas map
175   */
176  @Deprecated
177  public Replica getReplica(String bpid, long blockId);
178
179  /**
180   * @return replica meta information
181   */
182  public String getReplicaString(String bpid, long blockId);
183
184  /**
185   * @return the generation stamp stored with the block.
186   */
187  public Block getStoredBlock(String bpid, long blkid)
188      throws IOException;
189
190  /**
191   * Returns an input stream to read the contents of the specified block
192   * @param b
193   * @return an input stream to read the contents of the specified block
194   * @throws IOException
195   */
196  public InputStream getBlockInputStream(ExtendedBlock b) throws IOException;
197  
198  /**
199   * Returns an input stream at specified offset of the specified block
200   * @param b
201   * @param seekOffset
202   * @return an input stream to read the contents of the specified block,
203   *  starting at the offset
204   * @throws IOException
205   */
206  public InputStream getBlockInputStream(ExtendedBlock b, long seekOffset)
207            throws IOException;
208
209  /**
210   * Returns an input stream at specified offset of the specified block
211   * The block is still in the tmp directory and is not finalized
212   * @param b
213   * @param blkoff
214   * @param ckoff
215   * @return an input stream to read the contents of the specified block,
216   *  starting at the offset
217   * @throws IOException
218   */
219  public BlockInputStreams getTmpInputStreams(ExtendedBlock b, long blkoff,
220      long ckoff) throws IOException;
221
222     /**
223      * 
224      * This class contains the output streams for the data and checksum
225      * of a block
226      *
227      */
228     static class BlockWriteStreams {
229      OutputStream dataOut;
230      OutputStream checksumOut;
231      DataChecksum checksum;
232      
233      BlockWriteStreams(OutputStream dOut, OutputStream cOut,
234          DataChecksum checksum) {
235        dataOut = dOut;
236        checksumOut = cOut;
237        this.checksum = checksum;
238      }
239      
240      void close() throws IOException {
241        IOUtils.closeStream(dataOut);
242        IOUtils.closeStream(checksumOut);
243      }
244      
245      DataChecksum getChecksum() {
246        return checksum;
247      }
248    }
249
250  /**
251   * This class contains the input streams for the data and checksum
252   * of a block
253   */
254  static class BlockInputStreams implements Closeable {
255    final InputStream dataIn;
256    final InputStream checksumIn;
257
258    BlockInputStreams(InputStream dataIn, InputStream checksumIn) {
259      this.dataIn = dataIn;
260      this.checksumIn = checksumIn;
261    }
262
263    /** {@inheritDoc} */
264    public void close() {
265      IOUtils.closeStream(dataIn);
266      IOUtils.closeStream(checksumIn);
267    }
268  }
269    
270  /**
271   * Creates a temporary replica and returns the meta information of the replica
272   * 
273   * @param b block
274   * @return the meta info of the replica which is being written to
275   * @throws IOException if an error occurs
276   */
277  public ReplicaInPipelineInterface createTemporary(ExtendedBlock b)
278  throws IOException;
279
280  /**
281   * Creates a RBW replica and returns the meta info of the replica
282   * 
283   * @param b block
284   * @return the meta info of the replica which is being written to
285   * @throws IOException if an error occurs
286   */
287  public ReplicaInPipelineInterface createRbw(ExtendedBlock b) throws IOException;
288
289  /**
290   * Recovers a RBW replica and returns the meta info of the replica
291   * 
292   * @param b block
293   * @param newGS the new generation stamp for the replica
294   * @param minBytesRcvd the minimum number of bytes that the replica could have
295   * @param maxBytesRcvd the maximum number of bytes that the replica could have
296   * @return the meta info of the replica which is being written to
297   * @throws IOException if an error occurs
298   */
299  public ReplicaInPipelineInterface recoverRbw(ExtendedBlock b, 
300      long newGS, long minBytesRcvd, long maxBytesRcvd)
301  throws IOException;
302
303  /**
304   * Covert a temporary replica to a RBW.
305   * @param temporary the temporary replica being converted
306   * @return the result RBW
307   */
308  public ReplicaInPipelineInterface convertTemporaryToRbw(
309      ExtendedBlock temporary) throws IOException;
310
311  /**
312   * Append to a finalized replica and returns the meta info of the replica
313   * 
314   * @param b block
315   * @param newGS the new generation stamp for the replica
316   * @param expectedBlockLen the number of bytes the replica is expected to have
317   * @return the meata info of the replica which is being written to
318   * @throws IOException
319   */
320  public ReplicaInPipelineInterface append(ExtendedBlock b, 
321      long newGS, long expectedBlockLen) throws IOException;
322
323  /**
324   * Recover a failed append to a finalized replica
325   * and returns the meta info of the replica
326   * 
327   * @param b block
328   * @param newGS the new generation stamp for the replica
329   * @param expectedBlockLen the number of bytes the replica is expected to have
330   * @return the meta info of the replica which is being written to
331   * @throws IOException
332   */
333  public ReplicaInPipelineInterface recoverAppend(ExtendedBlock b,
334      long newGS, long expectedBlockLen) throws IOException;
335  
336  /**
337   * Recover a failed pipeline close
338   * It bumps the replica's generation stamp and finalize it if RBW replica
339   * 
340   * @param b block
341   * @param newGS the new generation stamp for the replica
342   * @param expectedBlockLen the number of bytes the replica is expected to have
343   * @throws IOException
344   */
345  public void recoverClose(ExtendedBlock b,
346      long newGS, long expectedBlockLen) throws IOException;
347  
348  /**
349   * Finalizes the block previously opened for writing using writeToBlock.
350   * The block size is what is in the parameter b and it must match the amount
351   *  of data written
352   * @param b
353   * @throws IOException
354   */
355  public void finalizeBlock(ExtendedBlock b) throws IOException;
356
357  /**
358   * Unfinalizes the block previously opened for writing using writeToBlock.
359   * The temporary file associated with this block is deleted.
360   * @param b
361   * @throws IOException
362   */
363  public void unfinalizeBlock(ExtendedBlock b) throws IOException;
364
365  /**
366   * Returns the block report - the full list of blocks stored under a 
367   * block pool
368   * @param bpid Block Pool Id
369   * @return - the block report - the full list of blocks stored
370   */
371  public BlockListAsLongs getBlockReport(String bpid);
372
373  /** Does the dataset contain the block? */
374  public boolean contains(ExtendedBlock block);
375
376  /**
377   * Is the block valid?
378   * @param b
379   * @return - true if the specified block is valid
380   */
381  public boolean isValidBlock(ExtendedBlock b);
382
383  /**
384   * Is the block a valid RBW?
385   * @param b
386   * @return - true if the specified block is a valid RBW
387   */
388  public boolean isValidRbw(ExtendedBlock b);
389
390  /**
391   * Invalidates the specified blocks
392   * @param bpid Block pool Id
393   * @param invalidBlks - the blocks to be invalidated
394   * @throws IOException
395   */
396  public void invalidate(String bpid, Block invalidBlks[]) throws IOException;
397
398    /**
399     * Check if all the data directories are healthy
400     * @throws DiskErrorException
401     */
402  public void checkDataDir() throws DiskErrorException;
403      
404    /**
405     * Stringifies the name of the storage
406     */
407  public String toString();
408  
409  /**
410   * Shutdown the FSDataset
411   */
412  public void shutdown();
413
414  /**
415   * Sets the file pointer of the checksum stream so that the last checksum
416   * will be overwritten
417   * @param b block
418   * @param stream The stream for the data file and checksum file
419   * @param checksumSize number of bytes each checksum has
420   * @throws IOException
421   */
422  public void adjustCrcChannelPosition(ExtendedBlock b, BlockWriteStreams stream, 
423      int checksumSize) throws IOException;
424
425  /**
426   * Checks how many valid storage volumes there are in the DataNode.
427   * @return true if more than the minimum number of valid volumes are left 
428   * in the FSDataSet.
429   */
430  public boolean hasEnoughResource();
431
432  /**
433   * Get visible length of the specified replica.
434   */
435  long getReplicaVisibleLength(final ExtendedBlock block) throws IOException;
436
437  /**
438   * Initialize a replica recovery.
439   * @return actual state of the replica on this data-node or 
440   * null if data-node does not have the replica.
441   */
442  public ReplicaRecoveryInfo initReplicaRecovery(RecoveringBlock rBlock)
443      throws IOException;
444
445  /**
446   * Update replica's generation stamp and length and finalize it.
447   */
448  public ReplicaInfo updateReplicaUnderRecovery(
449                                          ExtendedBlock oldBlock,
450                                          long recoveryId,
451                                          long newLength) throws IOException;
452  /**
453   * add new block pool ID
454   * @param bpid Block pool Id
455   * @param conf Configuration
456   */
457  public void addBlockPool(String bpid, Configuration conf) throws IOException;
458  
459  /**
460   * Shutdown and remove the block pool from underlying storage.
461   * @param bpid Block pool Id to be removed
462   */
463  public void shutdownBlockPool(String bpid) ;
464  
465  /**
466   * Deletes the block pool directories. If force is false, directories are 
467   * deleted only if no block files exist for the block pool. If force 
468   * is true entire directory for the blockpool is deleted along with its
469   * contents.
470   * @param bpid BlockPool Id to be deleted.
471   * @param force If force is false, directories are deleted only if no
472   *        block files exist for the block pool, otherwise entire 
473   *        directory for the blockpool is deleted along with its contents.
474   * @throws IOException
475   */
476  public void deleteBlockPool(String bpid, boolean force) throws IOException;
477  
478  /**
479   * Get {@link BlockLocalPathInfo} for the given block.
480   **/
481  public BlockLocalPathInfo getBlockLocalPathInfo(ExtendedBlock b) throws IOException;
482}