// Verify source
if (source == null || source.isEmpty()) {
throw new IOException("raidFile: source file name is empty");
}
// Verify codec
RaidCodec codec = RaidCodec.getCodec(codecId);
if (codec == null) {
throw new IOException("raidFile: codec " + codecId +
" doesn't exist");
}
// Verify expectedSourceRepl
if (codec.minSourceReplication > expectedSourceRepl) {
throw new IOException(
"raidFile: expectedSourceRepl is smaller than " +
codec.minSourceReplication);
}
INode[] sourceINodes = dir.getExistingPathINodes(source);
boolean status = false;
writeLock();
try {
if (isInSafeMode()) {
throw new SafeModeException("raidFile: Cannot raid file " + source, safeMode);
}
verifyReplication(source, expectedSourceRepl, null);
// write permissions for the source
if (isPermissionEnabled && isPermissionCheckingEnabled(sourceINodes)) {
checkPathAccess(source, sourceINodes, FsAction.WRITE);
}
INode sinode = sourceINodes[sourceINodes.length - 1];
if (sinode == null) {
throw new IOException("raidFile: source file doesn't exist");
}
if (sinode.isUnderConstruction()) {
throw new IOException(
"raidFile: source file is under-construction");
}
if (sinode.isDirectory()) {
throw new IOException("raidFile: source file is a directory");
}
INodeFile sourceINode = (INodeFile)sinode;
BlockInfo[] blocks = sourceINode.getBlocks();
if (blocks == null || blocks.length == 0) {
throw new IOException("raidFile: source file is empty");
}
if (sourceINode instanceof INodeHardLinkFile) {
throw new IOException("raidFile: cannot raid a hardlinked file");
}
if (sourceINode.getStorageType() == StorageType.RAID_STORAGE) {
INodeRaidStorage storage = (INodeRaidStorage)sourceINode.getStorage();
if (!storage.getCodec().id.equals(codec.id)) {
throw new IOException("raidFile: couldn't raid a raided file");
}
// check parity blocks and schedule raiding or set replication
if (codec.checkRaidProgress(sourceINode, raidEncodingTasks, this, false)) {
setReplicationInternal(source, expectedSourceRepl);
status = true;
}
} else if (sourceINode.getStorageType() == StorageType.REGULAR_STORAGE) {
// allocate parity blocks
checkFsObjectLimit();
// Verify all source blocks have checksums
boolean allHasChecksums = true;
for (int i = 0; i < blocks.length; i++) {
if (blocks[i].getChecksum() == BlockInfo.NO_BLOCK_CHECKSUM) {
allHasChecksums = false;
break;
}
}
if (!allHasChecksums) {
throw new IOException("raidFile: not all source blocks have checksums");
}
int numParityBlocks = codec.getNumParityBlocks(sourceINode.getBlocks().length);
Block[] parityBlocks = allocateParityBlocks(numParityBlocks);
// Convert to Raid format
dir.raidFile(sourceINodes, source, codec, expectedSourceRepl, parityBlocks);
// schedule raid tasks
codec.checkRaidProgress(sourceINode, raidEncodingTasks, this, true);
} else {
throw new IllegalArgumentException("raidFile: storage is not valid");
}
} finally {
writeUnlock();