private void serializeFileDiffList(INodeFile file, OutputStream out) throws IOException {
   FileWithSnapshotFeature sf = file.getFileWithSnapshotFeature();
   if (sf != null) {
     List<FileDiff> diffList = sf.getDiffs().asList();
     SnapshotDiffSection.DiffEntry entry =
         SnapshotDiffSection.DiffEntry.newBuilder()
             .setInodeId(file.getId())
             .setType(Type.FILEDIFF)
             .setNumOfDiff(diffList.size())
             .build();
     entry.writeDelimitedTo(out);
     for (int i = diffList.size() - 1; i >= 0; i--) {
       FileDiff diff = diffList.get(i);
       SnapshotDiffSection.FileDiff.Builder fb =
           SnapshotDiffSection.FileDiff.newBuilder()
               .setSnapshotId(diff.getSnapshotId())
               .setFileSize(diff.getFileSize());
       INodeFileAttributes copy = diff.snapshotINode;
       if (copy != null) {
         fb.setName(ByteString.copyFrom(copy.getLocalNameBytes()))
             .setSnapshotCopy(buildINodeFile(copy, parent.getSaverContext()));
       }
       fb.build().writeDelimitedTo(out);
     }
   }
 }
 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;
     }
   }
 }