/** * Serialize a {@link INodeDirectory} * @param node The node to write * @param out The {@link DataOutput} where the fields are written */ public static void writeINodeDirectory(INodeDirectory node, DataOutput out) throws IOException { writeLocalName(node, out); out.writeLong(node.getId()); out.writeShort(0); // replication out.writeLong(node.getModificationTime()); out.writeLong(0); // access time out.writeLong(0); // preferred block size out.writeInt(-1); // # of blocks out.writeLong(node.getNsQuota()); out.writeLong(node.getDsQuota()); if (node instanceof INodeDirectorySnapshottable) { out.writeBoolean(true); } else { out.writeBoolean(false); out.writeBoolean(node instanceof INodeDirectoryWithSnapshot); } writePermissionStatus(node, out); }
/** * When destroying a reference node (WithName or DstReference), we call this * method to identify the snapshot which is the latest snapshot before the * reference node's creation. */ static Snapshot getPriorSnapshot(INodeReference ref) { WithCount wc = (WithCount) ref.getReferredINode(); WithName wn = null; if (ref instanceof DstReference) { wn = wc.getLastWithName(); } else if (ref instanceof WithName) { wn = wc.getPriorWithName((WithName) ref); } if (wn != null) { INode referred = wc.getReferredINode(); if (referred instanceof FileWithSnapshot) { return ((FileWithSnapshot) referred).getDiffs().getPrior( wn.lastSnapshotId); } else if (referred instanceof INodeDirectoryWithSnapshot) { return ((INodeDirectoryWithSnapshot) referred).getDiffs().getPrior( wn.lastSnapshotId); } } return null; }
private Snapshot getSelfSnapshot(final Snapshot prior) { WithCount wc = (WithCount) getReferredINode().asReference(); INode referred = wc.getReferredINode(); Snapshot lastSnapshot = null; if (referred instanceof FileWithSnapshot) { lastSnapshot = ((FileWithSnapshot) referred).getDiffs() .getLastSnapshot(); } else if (referred instanceof INodeDirectoryWithSnapshot) { lastSnapshot = ((INodeDirectoryWithSnapshot) referred) .getLastSnapshot(); } if (lastSnapshot != null && !lastSnapshot.equals(prior)) { return lastSnapshot; } else { return null; } }
/** * Replace itself with {@link INodeDirectoryWithQuota} or * {@link INodeDirectoryWithSnapshot} depending on the latest snapshot. */ INodeDirectoryWithQuota replaceSelf4Quota(final Snapshot latest, final long nsQuota, final long dsQuota, final INodeMap inodeMap) throws QuotaExceededException { Preconditions.checkState(!(this instanceof INodeDirectoryWithQuota), "this is already an INodeDirectoryWithQuota, this=%s", this); if (!this.isInLatestSnapshot(latest)) { final INodeDirectoryWithQuota q = new INodeDirectoryWithQuota( this, true, nsQuota, dsQuota); replaceSelf(q, inodeMap); return q; } else { final INodeDirectoryWithSnapshot s = new INodeDirectoryWithSnapshot(this); s.setQuota(nsQuota, dsQuota); return replaceSelf(s, inodeMap).saveSelf2Snapshot(latest, this); } }
/** * Add a child inode to the directory. * * @param node INode to insert * @param setModTime set modification time for the parent node * not needed when replaying the addition and * the parent already has the proper mod time * @param inodeMap update the inodeMap if the directory node gets replaced * @return false if the child with this name already exists; * otherwise, return true; */ public boolean addChild(INode node, final boolean setModTime, final Snapshot latest, final INodeMap inodeMap) throws QuotaExceededException { final int low = searchChildren(node.getLocalNameBytes()); if (low >= 0) { return false; } if (isInLatestSnapshot(latest)) { INodeDirectoryWithSnapshot sdir = replaceSelf4INodeDirectoryWithSnapshot(inodeMap); boolean added = sdir.addChild(node, setModTime, latest, inodeMap); return added; } addChild(node, low); if (setModTime) { // update modification time of the parent directory updateModificationTime(node.getModificationTime(), latest, inodeMap); } return true; }
private Snapshot getSelfSnapshot() { INode referred = getReferredINode().asReference().getReferredINode(); Snapshot snapshot = null; if (referred instanceof FileWithSnapshot) { snapshot = ((FileWithSnapshot) referred).getDiffs().getPrior( lastSnapshotId); } else if (referred instanceof INodeDirectoryWithSnapshot) { snapshot = ((INodeDirectoryWithSnapshot) referred).getDiffs().getPrior( lastSnapshotId); } return snapshot; }
/** Replace itself with an {@link INodeDirectoryWithSnapshot}. */ public INodeDirectoryWithSnapshot replaceSelf4INodeDirectoryWithSnapshot( final INodeMap inodeMap) { return replaceSelf(new INodeDirectoryWithSnapshot(this), inodeMap); }
/** * Test {@link INodeDirectory#getExistingPathINodes(byte[][], int, boolean)} * for snapshot file. */ @Test (timeout=15000) public void testSnapshotPathINodes() throws Exception { // Create a snapshot for the dir, and check the inodes for the path // pointing to a snapshot file hdfs.allowSnapshot(sub1); hdfs.createSnapshot(sub1, "s1"); // The path when accessing the snapshot file of file1 is // /TestSnapshot/sub1/.snapshot/s1/file1 String snapshotPath = sub1.toString() + "/.snapshot/s1/file1"; String[] names = INode.getPathNames(snapshotPath); byte[][] components = INode.getPathComponents(names); INodesInPath nodesInPath = INodesInPath.resolve(fsdir.rootDir, components); INode[] inodes = nodesInPath.getINodes(); // Length of inodes should be (components.length - 1), since we will ignore // ".snapshot" assertEquals(inodes.length, components.length - 1); // SnapshotRootIndex should be 3: {root, Testsnapshot, sub1, s1, file1} final Snapshot snapshot = getSnapshot(nodesInPath, "s1"); assertSnapshot(nodesInPath, true, snapshot, 3); // Check the INode for file1 (snapshot file) INode snapshotFileNode = inodes[inodes.length - 1]; assertINodeFile(snapshotFileNode, file1); assertTrue(snapshotFileNode.getParent() instanceof INodeDirectoryWithSnapshot); // Call getExistingPathINodes and request only one INode. nodesInPath = INodesInPath.resolve(fsdir.rootDir, components, 1, false); inodes = nodesInPath.getINodes(); assertEquals(inodes.length, 1); // The snapshotroot (s1) is not included in inodes. Thus the // snapshotRootIndex should be -1. assertSnapshot(nodesInPath, true, snapshot, -1); // Check the INode for file1 (snapshot file) assertINodeFile(nodesInPath.getLastINode(), file1); // Call getExistingPathINodes and request 2 INodes. nodesInPath = INodesInPath.resolve(fsdir.rootDir, components, 2, false); inodes = nodesInPath.getINodes(); assertEquals(inodes.length, 2); // There should be two INodes in inodes: s1 and snapshot of file1. Thus the // SnapshotRootIndex should be 0. assertSnapshot(nodesInPath, true, snapshot, 0); assertINodeFile(nodesInPath.getLastINode(), file1); // Resolve the path "/TestSnapshot/sub1/.snapshot" String dotSnapshotPath = sub1.toString() + "/.snapshot"; names = INode.getPathNames(dotSnapshotPath); components = INode.getPathComponents(names); nodesInPath = INodesInPath.resolve(fsdir.rootDir, components); inodes = nodesInPath.getINodes(); // The number of INodes returned should be components.length - 1 since we // will ignore ".snapshot" assertEquals(inodes.length, components.length - 1); // No SnapshotRoot dir is included in the resolved inodes assertSnapshot(nodesInPath, true, snapshot, -1); // The last INode should be the INode for sub1 final INode last = nodesInPath.getLastINode(); assertEquals(last.getFullPathName(), sub1.toString()); assertFalse(last instanceof INodeFileWithSnapshot); String[] invalidPathComponent = {"invalidDir", "foo", ".snapshot", "bar"}; Path invalidPath = new Path(invalidPathComponent[0]); for(int i = 1; i < invalidPathComponent.length; i++) { invalidPath = new Path(invalidPath, invalidPathComponent[i]); try { hdfs.getFileStatus(invalidPath); Assert.fail(); } catch(FileNotFoundException fnfe) { System.out.println("The exception is expected: " + fnfe); } } }