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