@Override
  public void dumpTreeRecursively(PrintWriter out, StringBuilder prefix, Snapshot snapshot) {
    super.dumpTreeRecursively(out, prefix, snapshot);

    if (snapshot == null) {
      out.println();
      out.print(prefix);

      out.print("Snapshot of ");
      final String name = getLocalName();
      out.print(name.isEmpty() ? "/" : name);
      out.print(": quota=");
      out.print(getSnapshotQuota());

      int n = 0;
      for (DirectoryDiff diff : getDiffs()) {
        if (diff.isSnapshotRoot()) {
          n++;
        }
      }
      Preconditions.checkState(n == snapshotsByNames.size());
      out.print(", #snapshot=");
      out.println(n);

      dumpTreeRecursively(
          out,
          prefix,
          new Iterable<SnapshotAndINode>() {
            @Override
            public Iterator<SnapshotAndINode> iterator() {
              return new Iterator<SnapshotAndINode>() {
                final Iterator<DirectoryDiff> i = getDiffs().iterator();
                private DirectoryDiff next = findNext();

                private DirectoryDiff findNext() {
                  for (; i.hasNext(); ) {
                    final DirectoryDiff diff = i.next();
                    if (diff.isSnapshotRoot()) {
                      return diff;
                    }
                  }
                  return null;
                }

                @Override
                public boolean hasNext() {
                  return next != null;
                }

                @Override
                public SnapshotAndINode next() {
                  final Snapshot s = next.snapshot;
                  final SnapshotAndINode pair = new SnapshotAndINode(s);
                  next = findNext();
                  return pair;
                }

                @Override
                public void remove() {
                  throw new UnsupportedOperationException();
                }
              };
            }
          });
    }
  }