if (replica.getState() != ReplicaState.RUR) { throw new IOException("replica.getState() != " + ReplicaState.RUR + ", replica=" + replica); if (replica.getBytesOnDisk() != oldBlock.getNumBytes()) { throw new IOException("THIS IS NOT SUPPOSED TO HAPPEN:" + " replica.getBytesOnDisk() != block.getNumBytes(), block=" assert finalized.getBlockId() == oldBlock.getBlockId() && finalized.getGenerationStamp() == recoveryId && finalized.getNumBytes() == newlength : "Replica information mismatched: oldBlock=" + oldBlock + ", recoveryId=" + recoveryId + ", newlength=" + newlength + ", newBlockId=" + newBlockId + ", finalized=" + finalized; } else { assert finalized.getBlockId() == oldBlock.getBlockId() && finalized.getGenerationStamp() == oldBlock.getGenerationStamp() && finalized.getNumBytes() == oldBlock.getNumBytes() : "Finalized and old information mismatched: oldBlock=" + oldBlock + ", genStamp=" + oldBlock.getGenerationStamp()
if (volumeMap.get(bpid, replicaInfo.getBlockId()).getGenerationStamp() > replicaInfo.getGenerationStamp()) { throw new IOException("Generation Stamp should be monotonically " + "increased."); if (replicaInfo.getState() == ReplicaState.RUR && replicaInfo.getOriginalReplica().getState() == ReplicaState.FINALIZED) { newReplicaInfo = replicaInfo.getOriginalReplica(); ((FinalizedReplica)newReplicaInfo).loadLastPartialChunkChecksum(); } else { FsVolumeImpl v = (FsVolumeImpl)replicaInfo.getVolume(); if (v == null) { throw new IOException("No volume for block " + replicaInfo); bpid, replicaInfo, replicaInfo, replicaInfo.getBytesReserved()); if (v.isTransientStorage()) { releaseLockedMemory( replicaInfo.getOriginalBytesReserved() - replicaInfo.getNumBytes(), false); ramDiskReplicaTracker.addReplica( bpid, replicaInfo.getBlockId(), v, replicaInfo.getNumBytes()); datanode.getMetrics().addRamDiskBytesWrite(replicaInfo.getNumBytes()); assert newReplicaInfo.getState() == ReplicaState.FINALIZED : "Replica should be finalized";
public ReplicaInPipeline append(String bpid, ReplicaInfo replicaInfo, long newGS, long estimateBlockLen) throws IOException { long bytesReserved = estimateBlockLen - replicaInfo.getNumBytes(); if (getAvailable() < bytesReserved) { throw new DiskOutOfSpaceException("Insufficient space for appending to " assert replicaInfo.getVolume() == this: "The volume of the replica should be the same as this volume"; File newBlkFile = new File(getRbwDir(bpid), replicaInfo.getBlockName()); LocalReplicaInPipeline newReplicaInfo = new ReplicaBuilder(ReplicaState.RBW) .setBlockId(replicaInfo.getBlockId()) .setLength(replicaInfo.getNumBytes()) .setGenerationStamp(newGS) .setFsVolume(this)
@Override //Object public String toString() { return getClass().getSimpleName() + ", " + super.toString() + ", " + getState() + "\n getNumBytes() = " + getNumBytes() + "\n getBytesOnDisk() = " + getBytesOnDisk() + "\n getVisibleLength()= " + getVisibleLength() + "\n getVolume() = " + getVolume() + "\n getBlockURI() = " + getBlockURI(); }
public ReplicaUnderRecovery(ReplicaInfo replica, long recoveryId) { super(replica, replica.getVolume(), ((LocalReplica)replica).getDir()); if ( replica.getState() != ReplicaState.FINALIZED && replica.getState() != ReplicaState.RBW && replica.getState() != ReplicaState.RWR ) { throw new IllegalArgumentException("Cannot recover replica: " + replica); } this.original = (LocalReplica) replica; this.recoveryId = recoveryId; }
/** * Cleanup the replicaInfo object passed. * * @param bpid - block pool id * @param replicaInfo - ReplicaInfo */ private void cleanupReplica(String bpid, ReplicaInfo replicaInfo) { if (replicaInfo.deleteBlockData() || !replicaInfo.blockDataExists()) { FsVolumeImpl volume = (FsVolumeImpl) replicaInfo.getVolume(); volume.onBlockFileDeletion(bpid, replicaInfo.getBytesOnDisk()); if (replicaInfo.deleteMetadata() || !replicaInfo.metadataExists()) { volume.onMetaFileDeletion(bpid, replicaInfo.getMetadataLength()); } } }
@Override //Object public String toString() { return getClass().getSimpleName() + ", " + super.toString() + ", " + getState() + "\n getNumBytes() = " + getNumBytes() + "\n getBytesOnDisk() = " + getBytesOnDisk() + "\n getVisibleLength()= " + getVisibleLength() + "\n getVolume() = " + getVolume() + "\n getBlockFile() = " + getBlockFile(); }
private synchronized FinalizedReplica finalizeReplica(String bpid, ReplicaInfo replicaInfo) throws IOException { FinalizedReplica newReplicaInfo = null; if (replicaInfo.getState() == ReplicaState.RUR && ((ReplicaUnderRecovery)replicaInfo).getOriginalReplica().getState() == ReplicaState.FINALIZED) { newReplicaInfo = (FinalizedReplica) ((ReplicaUnderRecovery)replicaInfo).getOriginalReplica(); } else { FsVolumeImpl v = (FsVolumeImpl)replicaInfo.getVolume(); File f = replicaInfo.getBlockFile(); if (v == null) { throw new IOException("No volume for temporary file " + f + " for block " + replicaInfo); } File dest = v.addFinalizedBlock( bpid, replicaInfo, f, replicaInfo.getBytesReserved()); newReplicaInfo = new FinalizedReplica(replicaInfo, v, dest.getParentFile()); if (v.isTransientStorage()) { ramDiskReplicaTracker.addReplica(bpid, replicaInfo.getBlockId(), v); datanode.getMetrics().addRamDiskBytesWrite(replicaInfo.getNumBytes()); } } volumeMap.add(bpid, newReplicaInfo); return newReplicaInfo; }
memBlockInfo = volumeMap.get(bpid, blockId); if (memBlockInfo != null && memBlockInfo.getState() != ReplicaState.FINALIZED) { if (!memBlockInfo.blockDataExists()) { if (vol.isTransientStorage()) { long lockedBytesReserved = cacheManager.reserve(diskBlockInfo.getNumBytes()) > 0 ? diskBlockInfo.getNumBytes() : 0; ramDiskReplicaTracker.addReplica( bpid, blockId, (FsVolumeImpl) vol, lockedBytesReserved); if (memBlockInfo.blockDataExists()) { if (memBlockInfo.getBlockURI().compareTo(diskFile.toURI()) != 0) { if (diskMetaFileExists) { if (memBlockInfo.metadataExists()) { + memBlockInfo.getBlockURI() + " does not exist. Updating it to the file found during scan " + diskFile.getAbsolutePath()); memBlockInfo.updateWithReplica( StorageLocation.parse(diskFile.toString())); + " from " + memBlockInfo.getGenerationStamp() + " to " + diskGS); memBlockInfo.setGenerationStamp(diskGS); if (memBlockInfo.getGenerationStamp() != diskGS) { File memMetaFile = FsDatasetUtil.getMetaFile(diskFile,
Preconditions.checkState(replicaInfo.getVolume().isTransientStorage()); blockFile = replicaInfo.getBlockFile(); metaFile = replicaInfo.getMetaFile(); blockFileUsed = blockFile.length(); metaFileUsed = metaFile.length(); new FinalizedReplica(replicaInfo.getBlockId(), replicaInfo.getBytesOnDisk(), replicaInfo.getGenerationStamp(), replicaState.getLazyPersistVolume(), newBlockFile.getParentFile());
/** * Remove a hard link by copying the block to a temporary place and * then moving it back * @param numLinks number of hard links * @return true if copy is successful; * false if it is already detached or no need to be detached * @throws IOException if there is any copy error */ public boolean unlinkBlock(int numLinks) throws IOException { if (isUnlinked()) { return false; } File file = getBlockFile(); if (file == null || getVolume() == null) { throw new IOException("detachBlock:Block not found. " + this); } File meta = getMetaFile(); if (HardLink.getLinkCount(file) > numLinks) { DataNode.LOG.info("CopyOnWrite for block " + this); unlinkFile(file, this); } if (HardLink.getLinkCount(meta) > numLinks) { unlinkFile(meta, this); } setUnlinked(); return true; }
/** Delete a block file */ private long deleteBlockFile() { synchronized(fds) { for (ReplicaInfo b : fds.volumeMap.replicas()) { File f = b.getBlockFile(); File mf = b.getMetaFile(); // Delete a block file that has corresponding metadata file if (f.exists() && mf.exists() && f.delete()) { LOG.info("Deleting block file " + f.getAbsolutePath()); return b.getBlockId(); } } } return 0; }
if (rur.getRecoveryID() != recoveryId) { throw new IOException("rur.getRecoveryID() != recoveryId = " + recoveryId + ", rur=" + rur); boolean copyOnTruncate = newBlockId > 0L && rur.getBlockId() != newBlockId; rur.bumpReplicaGS(recoveryId); if (rur.getNumBytes() < newlength) { throw new IOException("rur.getNumBytes() < newlength = " + newlength + ", rur=" + rur); if (rur.getNumBytes() > newlength) { if(!copyOnTruncate) { rur.breakHardLinksIfNeeded(); rur.truncateBlock(newlength); rur.setNumBytes(newlength); } else { FsVolumeImpl volume = (FsVolumeImpl) rur.getVolume(); ReplicaInPipeline newReplicaInfo = volume.updateRURCopyOnTruncate( rur, bpid, newBlockId, recoveryId, newlength); if (newReplicaInfo.getState() != ReplicaState.RBW) { throw new IOException("Append on block " + rur.getBlockId() + " returned a replica of state " + newReplicaInfo.getState() + "; expected RBW");
/** * Remove the temporary block file (if any) */ @Override // FsDatasetSpi public synchronized void unfinalizeBlock(ExtendedBlock b) throws IOException { ReplicaInfo replicaInfo = volumeMap.get(b.getBlockPoolId(), b.getLocalBlock()); if (replicaInfo != null && replicaInfo.getState() == ReplicaState.TEMPORARY) { // remove from volumeMap volumeMap.remove(b.getBlockPoolId(), b.getLocalBlock()); // delete the on-disk temp file if (delBlockFromDisk(replicaInfo.getBlockFile(), replicaInfo.getMetaFile(), b.getLocalBlock())) { LOG.warn("Block " + b + " unfinalized and removed. " ); } if (replicaInfo.getVolume().isTransientStorage()) { ramDiskReplicaTracker.discardReplica(b.getBlockPoolId(), b.getBlockId(), true); } } }
if (replica.getState() == ReplicaState.TEMPORARY || replica.getState() == ReplicaState.RBW) { final ReplicaInPipeline rip = (ReplicaInPipeline)replica; if (!rip.attemptToSetWriter(null, Thread.currentThread())) { if (replica.getBytesOnDisk() < replica.getVisibleLength()) { throw new IOException("getBytesOnDisk() < getVisibleLength(), rip=" + replica); if (replica.getGenerationStamp() < block.getGenerationStamp()) { throw new IOException( "replica.getGenerationStamp() < block.getGenerationStamp(), block=" if (replica.getGenerationStamp() >= recoveryId) { throw new IOException("THIS IS NOT SUPPOSED TO HAPPEN:" + " replica.getGenerationStamp() >= recoveryId = " + recoveryId if (replica.getState() == ReplicaState.RUR) { rur = replica; if (rur.getRecoveryID() >= recoveryId) { throw new RecoveryInProgressException( "rur.getRecoveryID() >= recoveryId = " + recoveryId + ", block=" + block + ", rur=" + rur); final long oldRecoveryID = rur.getRecoveryID(); rur.setRecoveryID(recoveryId); LOG.info("initReplicaRecovery: update recovery id for " + block + " from " + oldRecoveryID + " to " + recoveryId);
ReplicaInfo memBlock = bl.get(m); ScanInfo info = blockpoolReport[d]; if (info.getBlockId() < memBlock.getBlockId()) { if (!dataset.isDeletingBlock(bpid, info.getBlockId())) { continue; if (info.getBlockId() > memBlock.getBlockId()) { memBlock.getBlockId(), info.getVolume()); m++; continue; } else if (info.getGenStamp() != memBlock.getGenerationStamp() || info.getBlockLength() != memBlock.getNumBytes()) { } else if (memBlock.compareWith(info) != 0) { ReplicaInfo current = bl.get(m++); addDifference(diffRecord, statsRecord, current.getBlockId(), current.getVolume());
return; if (info.getState() != ReplicaState.FINALIZED) { LOG.warn("Failed to cache block with id " + blockId + ", pool " + bpid + ": replica is not finalized; it is in state " + info.getState()); return; volume = (FsVolumeImpl)info.getVolume(); if (volume == null) { LOG.warn("Failed to cache block with id " + blockId + ", pool " + blockFileName = info.getBlockURI().toString(); length = info.getVisibleLength(); genstamp = info.getGenerationStamp(); volumeExecutor = volume.getCacheExecutor();
if (r.getState() != ReplicaState.TEMPORARY) { throw new ReplicaAlreadyExistsException( "r.getState() != ReplicaState.TEMPORARY, r=" + r); if (temp.getGenerationStamp() != expectedGs) { throw new ReplicaAlreadyExistsException( "temp.getGenerationStamp() != expectedGs = " + expectedGs final long numBytes = temp.getNumBytes(); if (numBytes < visible) { throw new IOException(numBytes + " = numBytes < visible = " final FsVolumeImpl v = (FsVolumeImpl) temp.getVolume(); if (v == null) { throw new IOException("r.getVolume() = null, temp=" + temp);
@VisibleForTesting static ReplicaInfo selectReplicaToDelete(final ReplicaInfo replica1, final ReplicaInfo replica2) { ReplicaInfo replicaToKeep; ReplicaInfo replicaToDelete; // it's the same block so don't ever delete it, even if GS or size // differs. caller should keep the one it just discovered on disk if (replica1.getBlockURI().equals(replica2.getBlockURI())) { return null; } if (replica1.getGenerationStamp() != replica2.getGenerationStamp()) { replicaToKeep = replica1.getGenerationStamp() > replica2.getGenerationStamp() ? replica1 : replica2; } else if (replica1.getNumBytes() != replica2.getNumBytes()) { replicaToKeep = replica1.getNumBytes() > replica2.getNumBytes() ? replica1 : replica2; } else if (replica1.getVolume().isTransientStorage() && !replica2.getVolume().isTransientStorage()) { replicaToKeep = replica2; } else { replicaToKeep = replica1; } replicaToDelete = (replicaToKeep == replica1) ? replica2 : replica1; if (LOG.isDebugEnabled()) { LOG.debug("resolveDuplicateReplicas decide to keep " + replicaToKeep + ". Will try to delete " + replicaToDelete); } return replicaToDelete; }
throws IOException { ReplicaInfo replicaInfo = getReplicaInfo(block); if (replicaInfo.getState() != ReplicaState.FINALIZED) { throw new ReplicaNotFoundException( ReplicaNotFoundException.UNFINALIZED_REPLICA + block); if (replicaInfo.getNumBytes() != block.getNumBytes()) { throw new IOException("Corrupted replica " + replicaInfo + " with a length of " + replicaInfo.getNumBytes() + " expected length is " + block.getNumBytes()); if (replicaInfo.getVolume().getStorageType() == targetStorageType) { throw new ReplicaAlreadyExistsException("Replica " + replicaInfo + " already exists on storage " + targetStorageType); if (replicaInfo.isOnTransientStorage()) { + replicaInfo.getVolume().getStorageType());