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.File; 023 import java.io.FilterInputStream; 024 import java.io.IOException; 025 import java.io.InputStream; 026 import java.io.OutputStream; 027 import java.util.List; 028 import java.util.Map; 029 030 import org.apache.hadoop.classification.InterfaceAudience; 031 import org.apache.hadoop.conf.Configuration; 032 import org.apache.hadoop.hdfs.DFSConfigKeys; 033 import org.apache.hadoop.hdfs.protocol.Block; 034 import org.apache.hadoop.hdfs.protocol.BlockListAsLongs; 035 import org.apache.hadoop.hdfs.protocol.BlockLocalPathInfo; 036 import org.apache.hadoop.hdfs.protocol.ExtendedBlock; 037 import org.apache.hadoop.hdfs.server.datanode.metrics.FSDatasetMBean; 038 import org.apache.hadoop.hdfs.server.protocol.BlockRecoveryCommand.RecoveringBlock; 039 import org.apache.hadoop.hdfs.server.protocol.ReplicaRecoveryInfo; 040 import org.apache.hadoop.io.IOUtils; 041 import org.apache.hadoop.util.DataChecksum; 042 import org.apache.hadoop.util.ReflectionUtils; 043 import 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 053 public 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 }