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}