|
@@ -0,0 +1,422 @@
|
|
|
+/**
|
|
|
+ * Licensed to the Apache Software Foundation (ASF) under one
|
|
|
+ * or more contributor license agreements. See the NOTICE file
|
|
|
+ * distributed with this work for additional information
|
|
|
+ * regarding copyright ownership. The ASF licenses this file
|
|
|
+ * to you under the Apache License, Version 2.0 (the
|
|
|
+ * "License"); you may not use this file except in compliance
|
|
|
+ * with the License. You may obtain a copy of the License at
|
|
|
+ *
|
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
|
+ *
|
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
+ * See the License for the specific language governing permissions and
|
|
|
+ * limitations under the License.
|
|
|
+ */
|
|
|
+package org.apache.hadoop.hdfs.server.namenode.snapshot;
|
|
|
+
|
|
|
+import static org.apache.hadoop.hdfs.server.namenode.FSImageFormatPBINode.Loader.loadINodeDirectory;
|
|
|
+import static org.apache.hadoop.hdfs.server.namenode.FSImageFormatPBINode.Loader.loadINodeReference;
|
|
|
+import static org.apache.hadoop.hdfs.server.namenode.FSImageFormatPBINode.Loader.loadPermission;
|
|
|
+import static org.apache.hadoop.hdfs.server.namenode.FSImageFormatPBINode.Loader.updateBlocksMap;
|
|
|
+import static org.apache.hadoop.hdfs.server.namenode.FSImageFormatPBINode.Saver.buildINodeDirectory;
|
|
|
+import static org.apache.hadoop.hdfs.server.namenode.FSImageFormatPBINode.Saver.buildINodeFile;
|
|
|
+import static org.apache.hadoop.hdfs.server.namenode.FSImageFormatPBINode.Saver.buildINodeReference;
|
|
|
+
|
|
|
+import java.io.IOException;
|
|
|
+import java.io.InputStream;
|
|
|
+import java.io.OutputStream;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Collections;
|
|
|
+import java.util.Comparator;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.Iterator;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+import org.apache.hadoop.classification.InterfaceAudience;
|
|
|
+import org.apache.hadoop.fs.permission.PermissionStatus;
|
|
|
+import org.apache.hadoop.hdfs.server.namenode.FSDirectory;
|
|
|
+import org.apache.hadoop.hdfs.server.namenode.FSImageFormatProtobuf;
|
|
|
+import org.apache.hadoop.hdfs.server.namenode.FSNamesystem;
|
|
|
+import org.apache.hadoop.hdfs.server.namenode.FsImageProto.FileSummary;
|
|
|
+import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeSection;
|
|
|
+import org.apache.hadoop.hdfs.server.namenode.FsImageProto.SnapshotDiffSection;
|
|
|
+import org.apache.hadoop.hdfs.server.namenode.FsImageProto.SnapshotDiffSection.CreatedListEntry;
|
|
|
+import org.apache.hadoop.hdfs.server.namenode.FsImageProto.SnapshotsSection;
|
|
|
+import org.apache.hadoop.hdfs.server.namenode.INode;
|
|
|
+import org.apache.hadoop.hdfs.server.namenode.INodeDirectory;
|
|
|
+import org.apache.hadoop.hdfs.server.namenode.INodeDirectoryAttributes;
|
|
|
+import org.apache.hadoop.hdfs.server.namenode.INodeFile;
|
|
|
+import org.apache.hadoop.hdfs.server.namenode.INodeFileAttributes;
|
|
|
+import org.apache.hadoop.hdfs.server.namenode.INodeMap;
|
|
|
+import org.apache.hadoop.hdfs.server.namenode.INodeReference;
|
|
|
+import org.apache.hadoop.hdfs.server.namenode.INodeWithAdditionalFields;
|
|
|
+import org.apache.hadoop.hdfs.server.namenode.snapshot.DirectoryWithSnapshotFeature.DirectoryDiff;
|
|
|
+import org.apache.hadoop.hdfs.server.namenode.snapshot.DirectoryWithSnapshotFeature.DirectoryDiffList;
|
|
|
+import org.apache.hadoop.hdfs.server.namenode.snapshot.Snapshot.Root;
|
|
|
+import org.apache.hadoop.hdfs.util.Diff.ListType;
|
|
|
+
|
|
|
+import com.google.common.base.Preconditions;
|
|
|
+import com.google.protobuf.ByteString;
|
|
|
+
|
|
|
+@InterfaceAudience.Private
|
|
|
+public class FSImageFormatPBSnapshot {
|
|
|
+ /**
|
|
|
+ * Loading snapshot related information from protobuf based FSImage
|
|
|
+ */
|
|
|
+ public final static class Loader {
|
|
|
+ private final FSNamesystem fsn;
|
|
|
+ private final FSDirectory fsDir;
|
|
|
+ private final FSImageFormatProtobuf.Loader parent;
|
|
|
+ private final Map<Integer, Snapshot> snapshotMap;
|
|
|
+
|
|
|
+
|
|
|
+ public Loader(FSNamesystem fsn, FSImageFormatProtobuf.Loader parent) {
|
|
|
+ this.fsn = fsn;
|
|
|
+ this.fsDir = fsn.getFSDirectory();
|
|
|
+ this.snapshotMap = new HashMap<Integer, Snapshot>();
|
|
|
+ this.parent = parent;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Load the snapshots section from fsimage. Also convert snapshottable
|
|
|
+ * directories into {@link INodeDirectorySnapshottable}.
|
|
|
+ *
|
|
|
+ * @return A map containing all the snapshots loaded from the fsimage.
|
|
|
+ */
|
|
|
+ public void loadSnapshotsSection(InputStream in) throws IOException {
|
|
|
+ SnapshotManager sm = fsn.getSnapshotManager();
|
|
|
+ SnapshotsSection section = SnapshotsSection.parseDelimitedFrom(in);
|
|
|
+ int snum = section.getNumSnapshots();
|
|
|
+ sm.setNumSnapshots(snum);
|
|
|
+ sm.setSnapshotCounter(section.getSnapshotCounter());
|
|
|
+ for (long sdirId : section.getSnapshottableDirList()) {
|
|
|
+ INodeDirectory dir = fsDir.getInode(sdirId).asDirectory();
|
|
|
+ final INodeDirectorySnapshottable sdir;
|
|
|
+ if (!dir.isSnapshottable()) {
|
|
|
+ sdir = new INodeDirectorySnapshottable(dir);
|
|
|
+ fsDir.addToInodeMap(sdir);
|
|
|
+ } else {
|
|
|
+ // dir is root, and admin set root to snapshottable before
|
|
|
+ sdir = (INodeDirectorySnapshottable) dir;
|
|
|
+ sdir.setSnapshotQuota(INodeDirectorySnapshottable.SNAPSHOT_LIMIT);
|
|
|
+ }
|
|
|
+ sm.addSnapshottable(sdir);
|
|
|
+ }
|
|
|
+ loadSnapshots(in, snum);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void loadSnapshots(InputStream in, int size) throws IOException {
|
|
|
+ for (int i = 0; i < size; i++) {
|
|
|
+ SnapshotsSection.Snapshot pbs = SnapshotsSection.Snapshot
|
|
|
+ .parseDelimitedFrom(in);
|
|
|
+ INodeDirectory root = loadINodeDirectory(pbs.getRoot(),
|
|
|
+ parent.getStringTable());
|
|
|
+ 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 {
|
|
|
+ while (true) {
|
|
|
+ SnapshotDiffSection.DiffEntry entry = SnapshotDiffSection.DiffEntry
|
|
|
+ .parseDelimitedFrom(in);
|
|
|
+ if (entry == null) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ long inodeId = entry.getInodeId();
|
|
|
+ INode inode = fsDir.getInode(inodeId);
|
|
|
+ if (inode.isFile()) {
|
|
|
+ loadFileDiffList(in, inode.asFile(), entry.getNumOfDiff());
|
|
|
+ } else if (inode.isDirectory()) {
|
|
|
+ loadDirectoryDiffList(in, inode.asDirectory(), entry.getNumOfDiff());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 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();
|
|
|
+ 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(), parent.getStringTable());
|
|
|
+ copy = new INodeFileAttributes.SnapshotCopy(pbf.getName()
|
|
|
+ .toByteArray(), permission, 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);
|
|
|
+ }
|
|
|
+
|
|
|
+ /** Load the created list in a DirectoryDiff */
|
|
|
+ private List<INode> loadCreatedList(InputStream in, INodeDirectory dir,
|
|
|
+ int size) throws IOException {
|
|
|
+ List<INode> clist = new ArrayList<INode>(size);
|
|
|
+ for (long c = 0; c < size; c++) {
|
|
|
+ CreatedListEntry entry = CreatedListEntry.parseDelimitedFrom(in);
|
|
|
+ INode created = SnapshotFSImageFormat.loadCreated(entry.getName()
|
|
|
+ .toByteArray(), dir);
|
|
|
+ clist.add(created);
|
|
|
+ }
|
|
|
+ return clist;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void addToDeletedList(INode dnode, INodeDirectory parent) {
|
|
|
+ dnode.setParent(parent);
|
|
|
+ if (dnode.isFile()) {
|
|
|
+ updateBlocksMap(dnode.asFile(), fsn.getBlockManager());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Load the deleted list in a DirectoryDiff
|
|
|
+ * @param totalSize the total size of the deleted list
|
|
|
+ * @param deletedNodes non-reference inodes in the deleted list. These
|
|
|
+ * inodes' ids are directly recorded in protobuf
|
|
|
+ */
|
|
|
+ private List<INode> loadDeletedList(InputStream in, INodeDirectory dir,
|
|
|
+ int totalSize, List<Long> deletedNodes) throws IOException {
|
|
|
+ List<INode> dlist = new ArrayList<INode>(totalSize);
|
|
|
+ // load non-reference inodes
|
|
|
+ for (long deletedId : deletedNodes) {
|
|
|
+ INode deleted = fsDir.getInode(deletedId);
|
|
|
+ dlist.add(deleted);
|
|
|
+ addToDeletedList(deleted, dir);
|
|
|
+ }
|
|
|
+ // load reference nodes in the deleted list
|
|
|
+ int refNum = totalSize - deletedNodes.size();
|
|
|
+ for (int r = 0; r < refNum; r++) {
|
|
|
+ INodeSection.INodeReference ref = INodeSection.INodeReference
|
|
|
+ .parseDelimitedFrom(in);
|
|
|
+ INodeReference refNode = loadINodeReference(ref, fsDir);
|
|
|
+ dlist.add(refNode);
|
|
|
+ addToDeletedList(refNode, dir);
|
|
|
+ }
|
|
|
+ Collections.sort(dlist, new Comparator<INode>() {
|
|
|
+ @Override
|
|
|
+ public int compare(INode n1, INode n2) {
|
|
|
+ return n1.compareTo(n2.getLocalNameBytes());
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return dlist;
|
|
|
+ }
|
|
|
+
|
|
|
+ /** Load DirectoryDiff list for a directory with snapshot feature */
|
|
|
+ private void loadDirectoryDiffList(InputStream in, INodeDirectory dir,
|
|
|
+ int size) throws IOException {
|
|
|
+ if (!dir.isWithSnapshot()) {
|
|
|
+ dir.addSnapshotFeature(null);
|
|
|
+ }
|
|
|
+ DirectoryDiffList diffs = dir.getDiffs();
|
|
|
+ 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(), parent.getStringTable());
|
|
|
+ long modTime = dirCopyInPb.getModificationTime();
|
|
|
+ boolean noQuota = dirCopyInPb.getNsQuota() == -1
|
|
|
+ && dirCopyInPb.getDsQuota() == -1;
|
|
|
+ copy = noQuota ? new INodeDirectoryAttributes.SnapshotCopy(name,
|
|
|
+ permission, modTime)
|
|
|
+ : new INodeDirectoryAttributes.CopyWithQuota(name, permission,
|
|
|
+ modTime, dirCopyInPb.getNsQuota(), dirCopyInPb.getDsQuota());
|
|
|
+ }
|
|
|
+ // load created list
|
|
|
+ List<INode> clist = loadCreatedList(in, dir, diffInPb.getClistSize());
|
|
|
+ // load deleted list
|
|
|
+ List<INode> dlist = loadDeletedList(in, dir, diffInPb.getDlistSize(),
|
|
|
+ diffInPb.getDeletedINodeList());
|
|
|
+ // create the directory diff
|
|
|
+ DirectoryDiff diff = new DirectoryDiff(snapshotId, copy, null,
|
|
|
+ childrenSize, clist, dlist, useRoot);
|
|
|
+ diffs.addFirst(diff);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Saving snapshot related information to protobuf based FSImage
|
|
|
+ */
|
|
|
+ public final static class Saver {
|
|
|
+ private final FSNamesystem fsn;
|
|
|
+ private final FileSummary.Builder headers;
|
|
|
+ private final FSImageFormatProtobuf.Saver parent;
|
|
|
+
|
|
|
+ public Saver(FSImageFormatProtobuf.Saver parent,
|
|
|
+ FileSummary.Builder headers, FSNamesystem fsn) {
|
|
|
+ this.parent = parent;
|
|
|
+ this.headers = headers;
|
|
|
+ this.fsn = fsn;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * save all the snapshottable directories and snapshots to fsimage
|
|
|
+ */
|
|
|
+ public void serializeSnapshotsSection(OutputStream out) throws IOException {
|
|
|
+ SnapshotManager sm = fsn.getSnapshotManager();
|
|
|
+ SnapshotsSection.Builder b = SnapshotsSection.newBuilder()
|
|
|
+ .setSnapshotCounter(sm.getSnapshotCounter())
|
|
|
+ .setNumSnapshots(sm.getNumSnapshots());
|
|
|
+
|
|
|
+ INodeDirectorySnapshottable[] snapshottables = sm.getSnapshottableDirs();
|
|
|
+ for (INodeDirectorySnapshottable sdir : snapshottables) {
|
|
|
+ b.addSnapshottableDir(sdir.getId());
|
|
|
+ }
|
|
|
+ b.build().writeDelimitedTo(out);
|
|
|
+ int i = 0;
|
|
|
+ for(INodeDirectorySnapshottable sdir : snapshottables) {
|
|
|
+ for(Snapshot s : sdir.getSnapshotsByNames()) {
|
|
|
+ Root sroot = s.getRoot();
|
|
|
+ SnapshotsSection.Snapshot.Builder sb = SnapshotsSection.Snapshot
|
|
|
+ .newBuilder().setSnapshotId(s.getId());
|
|
|
+ INodeSection.INodeDirectory.Builder db = buildINodeDirectory(sroot,
|
|
|
+ parent.getStringMap());
|
|
|
+ INodeSection.INode r = INodeSection.INode.newBuilder()
|
|
|
+ .setId(sroot.getId())
|
|
|
+ .setType(INodeSection.INode.Type.DIRECTORY)
|
|
|
+ .setName(ByteString.copyFrom(sroot.getLocalNameBytes()))
|
|
|
+ .setDirectory(db).build();
|
|
|
+ sb.setRoot(r).build().writeDelimitedTo(out);
|
|
|
+ i++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Preconditions.checkState(i == sm.getNumSnapshots());
|
|
|
+ parent.commitSection(headers, FSImageFormatProtobuf.SectionName.SNAPSHOT);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * save all the snapshot diff to fsimage
|
|
|
+ */
|
|
|
+ public void serializeSnapshotDiffSection(OutputStream out)
|
|
|
+ throws IOException {
|
|
|
+ INodeMap inodesMap = fsn.getFSDirectory().getINodeMap();
|
|
|
+ Iterator<INodeWithAdditionalFields> iter = inodesMap.getMapIterator();
|
|
|
+ while (iter.hasNext()) {
|
|
|
+ INodeWithAdditionalFields inode = iter.next();
|
|
|
+ if (inode.isFile()) {
|
|
|
+ serializeFileDiffList(inode.asFile(), out);
|
|
|
+ } else if (inode.isDirectory()) {
|
|
|
+ serializeDirDiffList(inode.asDirectory(), out);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ parent.commitSection(headers,
|
|
|
+ FSImageFormatProtobuf.SectionName.SNAPSHOT_DIFF);
|
|
|
+ }
|
|
|
+
|
|
|
+ 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())
|
|
|
+ .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.getStringMap()));
|
|
|
+ }
|
|
|
+ fb.build().writeDelimitedTo(out);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void saveCreatedDeletedList(List<INode> created,
|
|
|
+ List<INodeReference> deletedRefs, OutputStream out) throws IOException {
|
|
|
+ // local names of the created list member
|
|
|
+ for (INode c : created) {
|
|
|
+ SnapshotDiffSection.CreatedListEntry.newBuilder()
|
|
|
+ .setName(ByteString.copyFrom(c.getLocalNameBytes())).build()
|
|
|
+ .writeDelimitedTo(out);
|
|
|
+ }
|
|
|
+ // reference nodes in deleted list
|
|
|
+ for (INodeReference ref : deletedRefs) {
|
|
|
+ INodeSection.INodeReference.Builder rb = buildINodeReference(ref);
|
|
|
+ rb.build().writeDelimitedTo(out);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void serializeDirDiffList(INodeDirectory dir, 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())
|
|
|
+ .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.getStringMap()));
|
|
|
+ }
|
|
|
+ // process created list and deleted list
|
|
|
+ List<INode> created = diff.getChildrenDiff()
|
|
|
+ .getList(ListType.CREATED);
|
|
|
+ db.setClistSize(created.size());
|
|
|
+ List<INode> deleted = diff.getChildrenDiff().getList(ListType.DELETED);
|
|
|
+ db.setDlistSize(deleted.size());
|
|
|
+ List<INodeReference> refs = new ArrayList<INodeReference>();
|
|
|
+ for (INode d : deleted) {
|
|
|
+ if (d.isReference()) {
|
|
|
+ refs.add(d.asReference());
|
|
|
+ } else {
|
|
|
+ db.addDeletedINode(d.getId());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ db.build().writeDelimitedTo(out);
|
|
|
+ saveCreatedDeletedList(created, refs, out);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private FSImageFormatPBSnapshot(){}
|
|
|
+}
|