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