/** * Load {@link DirectoryDiff} from fsimage. * @param parent The directory that the SnapshotDiff belongs to. * @param in The {@link DataInput} instance to read. * @param loader The {@link Loader} instance that this loading procedure is * using. * @return A {@link DirectoryDiff}. */ private static DirectoryDiff loadDirectoryDiff(INodeDirectory parent, DataInput in, FSImageFormat.Loader loader) throws IOException { // 1. Read the full path of the Snapshot root to identify the Snapshot final Snapshot snapshot = loader.getSnapshot(in); // 2. Load DirectoryDiff#childrenSize int childrenSize = in.readInt(); // 3. Load DirectoryDiff#snapshotINode INodeDirectoryAttributes snapshotINode = loadSnapshotINodeInDirectoryDiff( snapshot, in, loader); // 4. Load the created list in SnapshotDiff#Diff List<INode> createdList = loadCreatedList(parent, in); // 5. Load the deleted list in SnapshotDiff#Diff List<INode> deletedList = loadDeletedList(parent, createdList, in, loader); // 6. Compose the SnapshotDiff List<DirectoryDiff> diffs = parent.getDiffs().asList(); DirectoryDiff sdiff = new DirectoryDiff(snapshot.getId(), snapshotINode, diffs.isEmpty() ? null : diffs.get(0), childrenSize, createdList, deletedList, snapshotINode == snapshot.getRoot()); return sdiff; }
/** * Load the snapshotINode field of {@link AbstractINodeDiff}. * @param snapshot The Snapshot associated with the {@link AbstractINodeDiff}. * @param in The {@link DataInput} to read. * @param loader The {@link Loader} instance that this loading procedure is * using. * @return The snapshotINode. */ private static INodeDirectoryAttributes loadSnapshotINodeInDirectoryDiff( Snapshot snapshot, DataInput in, FSImageFormat.Loader loader) throws IOException { // read the boolean indicating whether snapshotINode == Snapshot.Root boolean useRoot = in.readBoolean(); if (useRoot) { return snapshot.getRoot(); } else { // another boolean is used to indicate whether snapshotINode is non-null return in.readBoolean()? loader.loadINodeDirectoryAttributes(in): null; } }
/** Constructor used by FSImage loading */ DirectoryDiff(int snapshotId, INodeDirectoryAttributes snapshotINode, DirectoryDiff posteriorDiff, int childrenSize, List<INode> createdList, List<INode> deletedList, boolean isSnapshotRoot) { super(snapshotId, snapshotINode, posteriorDiff); this.childrenSize = childrenSize; this.diff = new ChildrenDiff(createdList, deletedList); this.isSnapshotRoot = isSnapshotRoot; }
@Override QuotaCounts destroyDiffAndCollectBlocks( BlockStoragePolicySuite bsps, INodeDirectory currentINode, BlocksMapUpdateInfo collectedBlocks, final List<INode> removedINodes) { // this diff has been deleted QuotaCounts counts = new QuotaCounts.Builder().build(); counts.add(diff.destroyDeletedList(bsps, collectedBlocks, removedINodes)); INodeDirectoryAttributes snapshotINode = getSnapshotINode(); if (snapshotINode != null && snapshotINode.getAclFeature() != null) { AclStorage.removeAclFeature(snapshotINode.getAclFeature()); } return counts; }
/** * Compute the difference between Snapshots. * * @param fromSnapshot Start point of the diff computation. Null indicates * current tree. * @param toSnapshot End point of the diff computation. Null indicates current * tree. * @param diff Used to capture the changes happening to the children. Note * that the diff still represents (later_snapshot - earlier_snapshot) * although toSnapshot can be before fromSnapshot. * @param currentINode The {@link INodeDirectory} this feature belongs to. * @return Whether changes happened between the startSnapshot and endSnaphsot. */ boolean computeDiffBetweenSnapshots(Snapshot fromSnapshot, Snapshot toSnapshot, ChildrenDiff diff, INodeDirectory currentINode) { int[] diffIndexPair = diffs.changedBetweenSnapshots(fromSnapshot, toSnapshot); if (diffIndexPair == null) { return false; } int earlierDiffIndex = diffIndexPair[0]; int laterDiffIndex = diffIndexPair[1]; boolean dirMetadataChanged = false; INodeDirectoryAttributes dirCopy = null; List<DirectoryDiff> difflist = diffs.asList(); for (int i = earlierDiffIndex; i < laterDiffIndex; i++) { DirectoryDiff sdiff = difflist.get(i); diff.combinePosterior(sdiff.diff, null); if (!dirMetadataChanged && sdiff.snapshotINode != null) { if (dirCopy == null) { dirCopy = sdiff.snapshotINode; } else if (!dirCopy.metadataEquals(sdiff.snapshotINode)) { dirMetadataChanged = true; } } } if (!diff.isEmpty() || dirMetadataChanged) { return true; } else if (dirCopy != null) { for (int i = laterDiffIndex; i < difflist.size(); i++) { if (!dirCopy.metadataEquals(difflist.get(i).snapshotINode)) { return true; } } return !dirCopy.metadataEquals(currentINode); } else { return false; } }
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); } } }
@Override void destroyDiffAndCollectBlocks( INode.ReclaimContext reclaimContext, INodeDirectory currentINode) { // this diff has been deleted diff.destroyDeletedList(reclaimContext); INodeDirectoryAttributes snapshotINode = getSnapshotINode(); if (snapshotINode != null && snapshotINode.getAclFeature() != null) { AclStorage.removeAclFeature(snapshotINode.getAclFeature()); } }
/** Constructor used by FSImage loading */ DirectoryDiff(Snapshot snapshot, INodeDirectoryAttributes snapshotINode, DirectoryDiff posteriorDiff, int childrenSize, List<INode> createdList, List<INode> deletedList) { super(snapshot, snapshotINode, posteriorDiff); this.childrenSize = childrenSize; this.diff = new ChildrenDiff(createdList, deletedList); }
/** * Load {@link DirectoryDiff} from fsimage. * @param parent The directory that the SnapshotDiff belongs to. * @param in The {@link DataInput} instance to read. * @param loader The {@link Loader} instance that this loading procedure is * using. * @return A {@link DirectoryDiff}. */ private static DirectoryDiff loadDirectoryDiff( INodeDirectoryWithSnapshot parent, DataInput in, FSImageFormat.Loader loader) throws IOException { // 1. Read the full path of the Snapshot root to identify the Snapshot final Snapshot snapshot = loader.getSnapshot(in); // 2. Load DirectoryDiff#childrenSize int childrenSize = in.readInt(); // 3. Load DirectoryDiff#snapshotINode INodeDirectoryAttributes snapshotINode = loadSnapshotINodeInDirectoryDiff( snapshot, in, loader); // 4. Load the created list in SnapshotDiff#Diff List<INode> createdList = loadCreatedList(parent, in); // 5. Load the deleted list in SnapshotDiff#Diff List<INode> deletedList = loadDeletedList(parent, createdList, in, loader); // 6. Compose the SnapshotDiff List<DirectoryDiff> diffs = parent.getDiffs().asList(); DirectoryDiff sdiff = new DirectoryDiff(snapshot, snapshotINode, diffs.isEmpty() ? null : diffs.get(0), childrenSize, createdList, deletedList); return sdiff; }