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 DirectoryDiff list for a directory with snapshot feature */ private void loadDirectoryDiffList( InputStream in, INodeDirectory dir, int size, final List<INodeReference> refList) throws IOException { if (!dir.isWithSnapshot()) { dir.addSnapshotFeature(null); } DirectoryDiffList diffs = dir.getDiffs(); final LoaderContext state = parent.getLoaderContext(); for (int i = 0; i < size; i++) { // load a directory diff SnapshotDiffSection.DirectoryDiff diffInPb = SnapshotDiffSection.DirectoryDiff.parseDelimitedFrom(in); final int snapshotId = diffInPb.getSnapshotId(); final Snapshot snapshot = snapshotMap.get(snapshotId); int childrenSize = diffInPb.getChildrenSize(); boolean useRoot = diffInPb.getIsSnapshotRoot(); INodeDirectoryAttributes copy = null; if (useRoot) { copy = snapshot.getRoot(); } else if (diffInPb.hasSnapshotCopy()) { INodeSection.INodeDirectory dirCopyInPb = diffInPb.getSnapshotCopy(); final byte[] name = diffInPb.getName().toByteArray(); PermissionStatus permission = loadPermission(dirCopyInPb.getPermission(), state.getStringTable()); AclFeature acl = null; if (dirCopyInPb.hasAcl()) { acl = new AclFeature( FSImageFormatPBINode.Loader.loadAclEntries( dirCopyInPb.getAcl(), state.getStringTable())); } long modTime = dirCopyInPb.getModificationTime(); boolean noQuota = dirCopyInPb.getNsQuota() == -1 && dirCopyInPb.getDsQuota() == -1; copy = noQuota ? new INodeDirectoryAttributes.SnapshotCopy(name, permission, acl, modTime) : new INodeDirectoryAttributes.CopyWithQuota( name, permission, acl, modTime, dirCopyInPb.getNsQuota(), dirCopyInPb.getDsQuota()); } // load created list List<INode> clist = loadCreatedList(in, dir, diffInPb.getCreatedListSize()); // load deleted list List<INode> dlist = loadDeletedList( refList, in, dir, diffInPb.getDeletedINodeList(), diffInPb.getDeletedINodeRefList()); // create the directory diff DirectoryDiff diff = new DirectoryDiff(snapshotId, copy, null, childrenSize, clist, dlist, useRoot); diffs.addFirst(diff); } }