/** * 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 */ 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 (meta == null) { throw new IOException("Meta file not found for block " + this); } 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; }
/** * Returns true if this block was copied, otherwise returns false. */ boolean detachBlock(Block block, int numLinks) throws IOException { if (isDetached()) { return false; } if (file == null || volume == null) { throw new IOException("detachBlock:Block not found. " + block); } File meta = FSDataset.getMetaFile(file, block); if (meta == null) { throw new IOException("Meta file not found for block " + block); } if (HardLink.getLinkCount(file) > numLinks) { DataNode.LOG.info("CopyOnWrite for block " + block); detachFile(file, block); } if (HardLink.getLinkCount(meta) > numLinks) { detachFile(meta, block); } setDetached(); return true; }
static void linkBlocks(File from, File to, int oldLV) throws IOException { if (!from.isDirectory()) { if (from.getName().startsWith(COPY_FILE_PREFIX)) { IOUtils.copyBytes(new FileInputStream(from), new FileOutputStream(to), 16*1024, true); } else { //check if we are upgrading from pre-generation stamp version. if (oldLV >= PRE_GENERATIONSTAMP_LAYOUT_VERSION) { // Link to the new file name. to = new File(convertMetatadataFileName(to.getAbsolutePath())); } HardLink.createHardLink(from, to); } return; } // from is a directory if (!to.mkdir()) throw new IOException("Cannot create directory " + to); String[] blockNames = from.list(new java.io.FilenameFilter() { public boolean accept(File dir, String name) { return name.startsWith(BLOCK_SUBDIR_PREFIX) || name.startsWith(BLOCK_FILE_PREFIX) || name.startsWith(COPY_FILE_PREFIX); } }); for(int i = 0; i < blockNames.length; i++) linkBlocks(new File(from, blockNames[i]), new File(to, blockNames[i]), oldLV); }
static void linkBlocks(File from, File to, int oldLV) throws IOException { if (!from.exists()) { return; } if (!from.isDirectory()) { if (from.getName().startsWith(COPY_FILE_PREFIX)) { FileInputStream in = new FileInputStream(from); try { FileOutputStream out = new FileOutputStream(to); try { IOUtils.copyBytes(in, out, 16*1024); } finally { out.close(); } } finally { in.close(); } } else { //check if we are upgrading from pre-generation stamp version. if (oldLV >= PRE_GENERATIONSTAMP_LAYOUT_VERSION) { // Link to the new file name. to = new File(convertMetatadataFileName(to.getAbsolutePath())); } HardLink.createHardLink(from, to); } return; } // from is a directory if (!to.mkdirs()) throw new IOException("Cannot create directory " + to); String[] blockNames = from.list(new java.io.FilenameFilter() { public boolean accept(File dir, String name) { return name.startsWith(BLOCK_SUBDIR_PREFIX) || name.startsWith(BLOCK_FILE_PREFIX) || name.startsWith(COPY_FILE_PREFIX); } }); for(int i = 0; i < blockNames.length; i++) linkBlocks(new File(from, blockNames[i]), new File(to, blockNames[i]), oldLV); }