@Override protected void acquire(TransactionLocks locks) throws IOException { INodeLock iNodeLock = (INodeLock) locks.getLock(Type.INode); INode iNode = iNodeLock.getTargetINode(target); BlockChecksumDataAccess.KeyTuple key = new BlockChecksumDataAccess.KeyTuple(iNode.getId(), blockIndex); acquireLock(DEFAULT_LOCK_TYPE, BlockChecksum.Finder.ByKeyTuple, key); }
private void saveCreatedList(List<INode> created, OutputStream out) throws IOException { // local names of the created list member for (INode c : created) { SnapshotDiffSection.CreatedListEntry.newBuilder() .setName(ByteString.copyFrom(c.getLocalNameBytes())) .build() .writeDelimitedTo(out); } }
/** * Find the latest snapshot that 1) covers the given inode (which means the snapshot was either * taken on the inode or taken on an ancestor of the inode), and 2) was taken before the given * snapshot (if the given snapshot is not null). * * @param inode the given inode that the returned snapshot needs to cover * @param anchor the returned snapshot should be taken before this given id. * @return id of the latest snapshot that covers the given inode and was taken before the the * given snapshot (if it is not null). */ public static int findLatestSnapshot(INode inode, final int anchor) { int latest = NO_SNAPSHOT_ID; for (; inode != null; inode = inode.getParent()) { if (inode.isDirectory()) { final INodeDirectory dir = inode.asDirectory(); if (dir.isWithSnapshot()) { latest = dir.getDiffs().updatePrior(anchor, latest); } } } return latest; }
@Override public int compare(INode left, INode right) { if (left == null) { return right == null ? 0 : -1; } else { if (right == null) { return 1; } else { int cmp = compare(left.getParent(), right.getParent()); return cmp == 0 ? SignedBytes.lexicographicalComparator() .compare(left.getLocalNameBytes(), right.getLocalNameBytes()) : cmp; } } }
/** * Recursively compute the difference between snapshots under a given directory/file. * * @param node The directory/file under which the diff is computed. * @param parentPath Relative path (corresponding to the snapshot root) of the node's parent. * @param diffReport data structure used to store the diff. */ private void computeDiffRecursively( INode node, List<byte[]> parentPath, SnapshotDiffInfo diffReport) { ChildrenDiff diff = new ChildrenDiff(); byte[][] relativePath = parentPath.toArray(new byte[parentPath.size()][]); if (node.isDirectory()) { INodeDirectory dir = node.asDirectory(); if (dir instanceof INodeDirectoryWithSnapshot) { INodeDirectoryWithSnapshot sdir = (INodeDirectoryWithSnapshot) dir; boolean change = sdir.computeDiffBetweenSnapshots(diffReport.from, diffReport.to, diff); if (change) { diffReport.addDirDiff(sdir, relativePath, diff); } } ReadOnlyList<INode> children = dir.getChildrenList(diffReport.isFromEarlier() ? diffReport.to : diffReport.from); for (INode child : children) { final byte[] name = child.getLocalNameBytes(); if (diff.searchIndex(ListType.CREATED, name) < 0 && diff.searchIndex(ListType.DELETED, name) < 0) { parentPath.add(name); computeDiffRecursively(child, parentPath, diffReport); parentPath.remove(parentPath.size() - 1); } } } else if (node.isFile() && node.asFile() instanceof FileWithSnapshot) { FileWithSnapshot file = (FileWithSnapshot) node.asFile(); Snapshot earlierSnapshot = diffReport.isFromEarlier() ? diffReport.from : diffReport.to; Snapshot laterSnapshot = diffReport.isFromEarlier() ? diffReport.to : diffReport.from; boolean change = file.getDiffs().changedBetweenSnapshots(earlierSnapshot, laterSnapshot); if (change) { diffReport.addFileDiff(file.asINodeFile(), relativePath); } } }
/** * Generate a {@link SnapshotDiffReport} based on detailed diff information. * * @return A {@link SnapshotDiffReport} describing the difference */ public SnapshotDiffReport generateReport() { List<DiffReportEntry> diffReportList = new ArrayList<DiffReportEntry>(); for (INode node : diffMap.keySet()) { diffReportList.add(new DiffReportEntry(DiffType.MODIFY, diffMap.get(node))); if (node.isDirectory()) { ChildrenDiff dirDiff = dirDiffMap.get(node); List<DiffReportEntry> subList = dirDiff.generateReport( diffMap.get(node), (INodeDirectoryWithSnapshot) node, isFromEarlier()); diffReportList.addAll(subList); } } return new SnapshotDiffReport( snapshotRoot.getFullPathName(), Snapshot.getSnapshotName(from), Snapshot.getSnapshotName(to), diffReportList); }
private INodeReference loadINodeReference(INodeReferenceSection.INodeReference r) throws IOException { long referredId = r.getReferredId(); INode referred = fsDir.getInode(referredId); WithCount withCount = (WithCount) referred.getParentReference(); if (withCount == null) { withCount = new INodeReference.WithCount(null, referred); } final INodeReference ref; if (r.hasDstSnapshotId()) { // DstReference ref = new INodeReference.DstReference(null, withCount, r.getDstSnapshotId()); } else { ref = new INodeReference.WithName( null, withCount, r.getName().toByteArray(), r.getLastSnapshotId()); } return ref; }
private void serializeDirDiffList( INodeDirectory dir, final List<INodeReference> refList, OutputStream out) throws IOException { DirectoryWithSnapshotFeature sf = dir.getDirectoryWithSnapshotFeature(); if (sf != null) { List<DirectoryDiff> diffList = sf.getDiffs().asList(); SnapshotDiffSection.DiffEntry entry = SnapshotDiffSection.DiffEntry.newBuilder() .setInodeId(dir.getId()) .setType(Type.DIRECTORYDIFF) .setNumOfDiff(diffList.size()) .build(); entry.writeDelimitedTo(out); for (int i = diffList.size() - 1; i >= 0; i--) { // reverse order! DirectoryDiff diff = diffList.get(i); SnapshotDiffSection.DirectoryDiff.Builder db = SnapshotDiffSection.DirectoryDiff.newBuilder() .setSnapshotId(diff.getSnapshotId()) .setChildrenSize(diff.getChildrenSize()) .setIsSnapshotRoot(diff.isSnapshotRoot()); INodeDirectoryAttributes copy = diff.snapshotINode; if (!diff.isSnapshotRoot() && copy != null) { db.setName(ByteString.copyFrom(copy.getLocalNameBytes())) .setSnapshotCopy(buildINodeDirectory(copy, parent.getSaverContext())); } // process created list and deleted list List<INode> created = diff.getChildrenDiff().getList(ListType.CREATED); db.setCreatedListSize(created.size()); List<INode> deleted = diff.getChildrenDiff().getList(ListType.DELETED); for (INode d : deleted) { if (d.isReference()) { refList.add(d.asReference()); db.addDeletedINodeRef(refList.size() - 1); } else { db.addDeletedINode(d.getId()); } } db.build().writeDelimitedTo(out); saveCreatedList(created, out); } } }
/** Load the snapshot diff section from fsimage. */ public void loadSnapshotDiffSection(InputStream in) throws IOException { final List<INodeReference> refList = parent.getLoaderContext().getRefList(); while (true) { SnapshotDiffSection.DiffEntry entry = SnapshotDiffSection.DiffEntry.parseDelimitedFrom(in); if (entry == null) { break; } long inodeId = entry.getInodeId(); INode inode = fsDir.getInode(inodeId); SnapshotDiffSection.DiffEntry.Type type = entry.getType(); switch (type) { case FILEDIFF: loadFileDiffList(in, inode.asFile(), entry.getNumOfDiff()); break; case DIRECTORYDIFF: loadDirectoryDiffList(in, inode.asDirectory(), entry.getNumOfDiff(), refList); break; } } }
static Snapshot read(DataInput in, FSImageFormat.Loader loader) throws IOException { final int snapshotId = in.readInt(); final INode root = loader.loadINodeWithLocalName(false, in, false); return new Snapshot(snapshotId, root.asDirectory(), null); }
private void addToDeletedList(INode dnode, INodeDirectory parent) { dnode.setParent(parent); if (dnode.isFile()) { updateBlocksMap(dnode.asFile(), fsn.getBlockManager()); } }