/** Load FileDiff list for a file with snapshot feature */
    private void loadFileDiffList(InputStream in, INodeFile file, int size) throws IOException {
      final FileDiffList diffs = new FileDiffList();
      final LoaderContext state = parent.getLoaderContext();
      for (int i = 0; i < size; i++) {
        SnapshotDiffSection.FileDiff pbf = SnapshotDiffSection.FileDiff.parseDelimitedFrom(in);
        INodeFileAttributes copy = null;
        if (pbf.hasSnapshotCopy()) {
          INodeSection.INodeFile fileInPb = pbf.getSnapshotCopy();
          PermissionStatus permission =
              loadPermission(fileInPb.getPermission(), state.getStringTable());

          AclFeature acl = null;
          if (fileInPb.hasAcl()) {
            acl =
                new AclFeature(
                    FSImageFormatPBINode.Loader.loadAclEntries(
                        fileInPb.getAcl(), state.getStringTable()));
          }

          copy =
              new INodeFileAttributes.SnapshotCopy(
                  pbf.getName().toByteArray(),
                  permission,
                  acl,
                  fileInPb.getModificationTime(),
                  fileInPb.getAccessTime(),
                  (short) fileInPb.getReplication(),
                  fileInPb.getPreferredBlockSize());
        }

        FileDiff diff = new FileDiff(pbf.getSnapshotId(), copy, null, pbf.getFileSize());
        diffs.addFirst(diff);
      }
      file.addSnapshotFeature(diffs);
    }
 /**
  * The sequence of the ref node in refList must be strictly the same with the sequence in
  * fsimage
  */
 public void loadINodeReferenceSection(InputStream in) throws IOException {
   final List<INodeReference> refList = parent.getLoaderContext().getRefList();
   while (true) {
     INodeReferenceSection.INodeReference e =
         INodeReferenceSection.INodeReference.parseDelimitedFrom(in);
     if (e == null) {
       break;
     }
     INodeReference ref = loadINodeReference(e);
     refList.add(ref);
   }
 }
 private void loadSnapshots(InputStream in, int size) throws IOException {
   for (int i = 0; i < size; i++) {
     SnapshotSection.Snapshot pbs = SnapshotSection.Snapshot.parseDelimitedFrom(in);
     INodeDirectory root = loadINodeDirectory(pbs.getRoot(), parent.getLoaderContext());
     int sid = pbs.getSnapshotId();
     INodeDirectorySnapshottable parent =
         (INodeDirectorySnapshottable) fsDir.getInode(root.getId()).asDirectory();
     Snapshot snapshot = new Snapshot(sid, root, parent);
     // add the snapshot to parent, since we follow the sequence of
     // snapshotsByNames when saving, we do not need to sort when loading
     parent.addSnapshot(snapshot);
     snapshotMap.put(sid, snapshot);
   }
 }
 /** 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;
     }
   }
 }
    /** 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);
      }
    }