HDFS-5847. Consolidate INodeReference into a separate section. Contributed by Jing Zhao.

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1567812 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Jing Zhao 2014-02-13 00:00:42 +00:00
parent 256adb2106
commit 2624b20291
7 changed files with 198 additions and 119 deletions

View File

@ -338,6 +338,8 @@ Trunk (Unreleased)
HDFS-5915. Refactor FSImageFormatProtobuf to simplify cross section reads. HDFS-5915. Refactor FSImageFormatProtobuf to simplify cross section reads.
(Haohui Mai via cnauroth) (Haohui Mai via cnauroth)
HDFS-5847. Consolidate INodeReference into a separate section. (jing9)
Release 2.4.0 - UNRELEASED Release 2.4.0 - UNRELEASED
INCOMPATIBLE CHANGES INCOMPATIBLE CHANGES

View File

@ -43,9 +43,6 @@ import org.apache.hadoop.hdfs.server.namenode.FsImageProto.FileSummary;
import org.apache.hadoop.hdfs.server.namenode.FsImageProto.FilesUnderConstructionSection.FileUnderConstructionEntry; import org.apache.hadoop.hdfs.server.namenode.FsImageProto.FilesUnderConstructionSection.FileUnderConstructionEntry;
import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeDirectorySection; import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeDirectorySection;
import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeSection; import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeSection;
import org.apache.hadoop.hdfs.server.namenode.INodeReference.DstReference;
import org.apache.hadoop.hdfs.server.namenode.INodeReference.WithCount;
import org.apache.hadoop.hdfs.server.namenode.INodeReference.WithName;
import org.apache.hadoop.hdfs.server.namenode.snapshot.Snapshot; import org.apache.hadoop.hdfs.server.namenode.snapshot.Snapshot;
import org.apache.hadoop.hdfs.util.ReadOnlyList; import org.apache.hadoop.hdfs.util.ReadOnlyList;
@ -69,25 +66,6 @@ public final class FSImageFormatPBINode {
new FsPermission(perm)); new FsPermission(perm));
} }
public static INodeReference loadINodeReference(
INodeSection.INodeReference r, FSDirectory dir) throws IOException {
long referredId = r.getReferredId();
INode referred = dir.getInode(referredId);
WithCount withCount = (WithCount) referred.getParentReference();
if (withCount == null) {
withCount = new INodeReference.WithCount(null, referred);
}
final INodeReference ref;
if (r.hasDstSnapshotId()) { // DstReference
ref = new INodeReference.DstReference(null, withCount,
r.getDstSnapshotId());
} else {
ref = new INodeReference.WithName(null, withCount, r.getName()
.toByteArray(), r.getLastSnapshotId());
}
return ref;
}
public static INodeDirectory loadINodeDirectory(INodeSection.INode n, public static INodeDirectory loadINodeDirectory(INodeSection.INode n,
final String[] stringTable) { final String[] stringTable) {
assert n.getType() == INodeSection.INode.Type.DIRECTORY; assert n.getType() == INodeSection.INode.Type.DIRECTORY;
@ -126,6 +104,8 @@ public final class FSImageFormatPBINode {
} }
void loadINodeDirectorySection(InputStream in) throws IOException { void loadINodeDirectorySection(InputStream in) throws IOException {
final List<INodeReference> refList = parent.getLoaderContext()
.getRefList();
while (true) { while (true) {
INodeDirectorySection.DirEntry e = INodeDirectorySection.DirEntry INodeDirectorySection.DirEntry e = INodeDirectorySection.DirEntry
.parseDelimitedFrom(in); .parseDelimitedFrom(in);
@ -138,20 +118,13 @@ public final class FSImageFormatPBINode {
INode child = dir.getInode(id); INode child = dir.getInode(id);
addToParent(p, child); addToParent(p, child);
} }
for (int i = 0; i < e.getNumOfRef(); i++) { for (int refId : e.getRefChildrenList()) {
INodeReference ref = loadINodeReference(in); INodeReference ref = refList.get(refId);
addToParent(p, ref); addToParent(p, ref);
} }
} }
} }
private INodeReference loadINodeReference(InputStream in)
throws IOException {
INodeSection.INodeReference ref = INodeSection.INodeReference
.parseDelimitedFrom(in);
return loadINodeReference(ref, dir);
}
void loadINodeSection(InputStream in) throws IOException { void loadINodeSection(InputStream in) throws IOException {
INodeSection s = INodeSection.parseDelimitedFrom(in); INodeSection s = INodeSection.parseDelimitedFrom(in);
fsn.resetLastInodeId(s.getLastInodeId()); fsn.resetLastInodeId(s.getLastInodeId());
@ -306,19 +279,6 @@ public final class FSImageFormatPBINode {
return b; return b;
} }
public static INodeSection.INodeReference.Builder buildINodeReference(
INodeReference ref) throws IOException {
INodeSection.INodeReference.Builder rb = INodeSection.INodeReference
.newBuilder().setReferredId(ref.getId());
if (ref instanceof WithName) {
rb.setLastSnapshotId(((WithName) ref).getLastSnapshotId()).setName(
ByteString.copyFrom(ref.getLocalNameBytes()));
} else if (ref instanceof DstReference) {
rb.setDstSnapshotId(((DstReference) ref).getDstSnapshotId());
}
return rb;
}
private final FSNamesystem fsn; private final FSNamesystem fsn;
private final FileSummary.Builder summary; private final FileSummary.Builder summary;
private final SaveNamespaceContext context; private final SaveNamespaceContext context;
@ -334,6 +294,8 @@ public final class FSImageFormatPBINode {
void serializeINodeDirectorySection(OutputStream out) throws IOException { void serializeINodeDirectorySection(OutputStream out) throws IOException {
Iterator<INodeWithAdditionalFields> iter = fsn.getFSDirectory() Iterator<INodeWithAdditionalFields> iter = fsn.getFSDirectory()
.getINodeMap().getMapIterator(); .getINodeMap().getMapIterator();
final ArrayList<INodeReference> refList = parent.getSaverContext()
.getRefList();
int i = 0; int i = 0;
while (iter.hasNext()) { while (iter.hasNext()) {
INodeWithAdditionalFields n = iter.next(); INodeWithAdditionalFields n = iter.next();
@ -346,21 +308,16 @@ public final class FSImageFormatPBINode {
if (children.size() > 0) { if (children.size() > 0) {
INodeDirectorySection.DirEntry.Builder b = INodeDirectorySection. INodeDirectorySection.DirEntry.Builder b = INodeDirectorySection.
DirEntry.newBuilder().setParent(n.getId()); DirEntry.newBuilder().setParent(n.getId());
List<INodeReference> refs = new ArrayList<INodeReference>();
for (INode inode : children) { for (INode inode : children) {
if (!inode.isReference()) { if (!inode.isReference()) {
b.addChildren(inode.getId()); b.addChildren(inode.getId());
} else { } else {
refs.add(inode.asReference()); refList.add(inode.asReference());
b.addRefChildren(refList.size() - 1);
} }
} }
b.setNumOfRef(refs.size());
INodeDirectorySection.DirEntry e = b.build(); INodeDirectorySection.DirEntry e = b.build();
e.writeDelimitedTo(out); e.writeDelimitedTo(out);
for (INodeReference ref : refs) {
INodeSection.INodeReference.Builder rb = buildINodeReference(ref);
rb.build().writeDelimitedTo(out);
}
} }
++i; ++i;

View File

@ -75,10 +75,15 @@ public final class FSImageFormatProtobuf {
public static final class LoaderContext { public static final class LoaderContext {
private String[] stringTable; private String[] stringTable;
private final ArrayList<INodeReference> refList = Lists.newArrayList();
public String[] getStringTable() { public String[] getStringTable() {
return stringTable; return stringTable;
} }
public ArrayList<INodeReference> getRefList() {
return refList;
}
} }
public static final class SaverContext { public static final class SaverContext {
@ -112,10 +117,15 @@ public final class FSImageFormatProtobuf {
} }
} }
private final DeduplicationMap<String> stringMap = DeduplicationMap.newMap(); private final DeduplicationMap<String> stringMap = DeduplicationMap.newMap();
private final ArrayList<INodeReference> refList = Lists.newArrayList();
public DeduplicationMap<String> getStringMap() { public DeduplicationMap<String> getStringMap() {
return stringMap; return stringMap;
} }
public ArrayList<INodeReference> getRefList() {
return refList;
}
} }
public static final class Loader implements FSImageFormat.AbstractLoader { public static final class Loader implements FSImageFormat.AbstractLoader {
@ -123,7 +133,6 @@ public final class FSImageFormatProtobuf {
private final Configuration conf; private final Configuration conf;
private final FSNamesystem fsn; private final FSNamesystem fsn;
private final LoaderContext ctx; private final LoaderContext ctx;
/** The MD5 sum of the loaded file */ /** The MD5 sum of the loaded file */
private MD5Hash imgDigest; private MD5Hash imgDigest;
/** The transaction ID of the last edit represented by the loaded file */ /** The transaction ID of the last edit represented by the loaded file */
@ -226,6 +235,9 @@ public final class FSImageFormatProtobuf {
inodeLoader.loadINodeSection(in); inodeLoader.loadINodeSection(in);
} }
break; break;
case INODE_REFRENCE:
snapshotLoader.loadINodeReferenceSection(in);
break;
case INODE_DIR: case INODE_DIR:
inodeLoader.loadINodeDirectorySection(in); inodeLoader.loadINodeDirectorySection(in);
break; break;
@ -313,9 +325,10 @@ public final class FSImageFormatProtobuf {
} }
public static final class Saver { public static final class Saver {
public static final int CHECK_CANCEL_INTERVAL = 4096;
private final SaveNamespaceContext context; private final SaveNamespaceContext context;
private final SaverContext saverContext; private final SaverContext saverContext;
private long currentOffset = FSImageUtil.MAGIC_HEADER.length; private long currentOffset = FSImageUtil.MAGIC_HEADER.length;
private MD5Hash savedDigest; private MD5Hash savedDigest;
@ -324,7 +337,6 @@ public final class FSImageFormatProtobuf {
private OutputStream sectionOutputStream; private OutputStream sectionOutputStream;
private CompressionCodec codec; private CompressionCodec codec;
private OutputStream underlyingOutputStream; private OutputStream underlyingOutputStream;
public static final int CHECK_CANCEL_INTERVAL = 4096;
Saver(SaveNamespaceContext context) { Saver(SaveNamespaceContext context) {
this.context = context; this.context = context;
@ -400,6 +412,7 @@ public final class FSImageFormatProtobuf {
snapshotSaver.serializeSnapshotSection(sectionOutputStream); snapshotSaver.serializeSnapshotSection(sectionOutputStream);
snapshotSaver.serializeSnapshotDiffSection(sectionOutputStream); snapshotSaver.serializeSnapshotDiffSection(sectionOutputStream);
snapshotSaver.serializeINodeReferenceSection(sectionOutputStream);
} }
private void saveInternal(FileOutputStream fout, private void saveInternal(FileOutputStream fout,
@ -535,6 +548,7 @@ public final class FSImageFormatProtobuf {
NS_INFO("NS_INFO"), NS_INFO("NS_INFO"),
STRING_TABLE("STRING_TABLE"), STRING_TABLE("STRING_TABLE"),
INODE("INODE"), INODE("INODE"),
INODE_REFRENCE("INODE_REFRENCE"),
SNAPSHOT("SNAPSHOT"), SNAPSHOT("SNAPSHOT"),
INODE_DIR("INODE_DIR"), INODE_DIR("INODE_DIR"),
FILES_UNDERCONSTRUCTION("FILES_UNDERCONSTRUCTION"), FILES_UNDERCONSTRUCTION("FILES_UNDERCONSTRUCTION"),

View File

@ -18,12 +18,10 @@
package org.apache.hadoop.hdfs.server.namenode.snapshot; 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.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.loadPermission;
import static org.apache.hadoop.hdfs.server.namenode.FSImageFormatPBINode.Loader.updateBlocksMap; 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.buildINodeDirectory;
import static org.apache.hadoop.hdfs.server.namenode.FSImageFormatPBINode.Saver.buildINodeFile; 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.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -40,8 +38,10 @@ import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.fs.permission.PermissionStatus; import org.apache.hadoop.fs.permission.PermissionStatus;
import org.apache.hadoop.hdfs.server.namenode.FSDirectory; import org.apache.hadoop.hdfs.server.namenode.FSDirectory;
import org.apache.hadoop.hdfs.server.namenode.FSImageFormatProtobuf; import org.apache.hadoop.hdfs.server.namenode.FSImageFormatProtobuf;
import org.apache.hadoop.hdfs.server.namenode.FSImageFormatProtobuf.SectionName;
import org.apache.hadoop.hdfs.server.namenode.FSNamesystem; 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.FileSummary;
import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeReferenceSection;
import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeSection; 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;
import org.apache.hadoop.hdfs.server.namenode.FsImageProto.SnapshotDiffSection.CreatedListEntry; import org.apache.hadoop.hdfs.server.namenode.FsImageProto.SnapshotDiffSection.CreatedListEntry;
@ -54,6 +54,9 @@ import org.apache.hadoop.hdfs.server.namenode.INodeFile;
import org.apache.hadoop.hdfs.server.namenode.INodeFileAttributes; import org.apache.hadoop.hdfs.server.namenode.INodeFileAttributes;
import org.apache.hadoop.hdfs.server.namenode.INodeMap; import org.apache.hadoop.hdfs.server.namenode.INodeMap;
import org.apache.hadoop.hdfs.server.namenode.INodeReference; import org.apache.hadoop.hdfs.server.namenode.INodeReference;
import org.apache.hadoop.hdfs.server.namenode.INodeReference.DstReference;
import org.apache.hadoop.hdfs.server.namenode.INodeReference.WithCount;
import org.apache.hadoop.hdfs.server.namenode.INodeReference.WithName;
import org.apache.hadoop.hdfs.server.namenode.INodeWithAdditionalFields; import org.apache.hadoop.hdfs.server.namenode.INodeWithAdditionalFields;
import org.apache.hadoop.hdfs.server.namenode.SaveNamespaceContext; import org.apache.hadoop.hdfs.server.namenode.SaveNamespaceContext;
import org.apache.hadoop.hdfs.server.namenode.snapshot.DirectoryWithSnapshotFeature.DirectoryDiff; import org.apache.hadoop.hdfs.server.namenode.snapshot.DirectoryWithSnapshotFeature.DirectoryDiff;
@ -75,7 +78,6 @@ public class FSImageFormatPBSnapshot {
private final FSImageFormatProtobuf.Loader parent; private final FSImageFormatProtobuf.Loader parent;
private final Map<Integer, Snapshot> snapshotMap; private final Map<Integer, Snapshot> snapshotMap;
public Loader(FSNamesystem fsn, FSImageFormatProtobuf.Loader parent) { public Loader(FSNamesystem fsn, FSImageFormatProtobuf.Loader parent) {
this.fsn = fsn; this.fsn = fsn;
this.fsDir = fsn.getFSDirectory(); this.fsDir = fsn.getFSDirectory();
@ -83,6 +85,43 @@ public class FSImageFormatPBSnapshot {
this.parent = parent; this.parent = parent;
} }
/**
* 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 INodeReference loadINodeReference(
INodeReferenceSection.INodeReference r) throws IOException {
long referredId = r.getReferredId();
INode referred = fsDir.getInode(referredId);
WithCount withCount = (WithCount) referred.getParentReference();
if (withCount == null) {
withCount = new INodeReference.WithCount(null, referred);
}
final INodeReference ref;
if (r.hasDstSnapshotId()) { // DstReference
ref = new INodeReference.DstReference(null, withCount,
r.getDstSnapshotId());
} else {
ref = new INodeReference.WithName(null, withCount, r.getName()
.toByteArray(), r.getLastSnapshotId());
}
return ref;
}
/** /**
* Load the snapshots section from fsimage. Also convert snapshottable * Load the snapshots section from fsimage. Also convert snapshottable
* directories into {@link INodeDirectorySnapshottable}. * directories into {@link INodeDirectorySnapshottable}.
@ -131,6 +170,8 @@ public class FSImageFormatPBSnapshot {
* Load the snapshot diff section from fsimage. * Load the snapshot diff section from fsimage.
*/ */
public void loadSnapshotDiffSection(InputStream in) throws IOException { public void loadSnapshotDiffSection(InputStream in) throws IOException {
final List<INodeReference> refList = parent.getLoaderContext()
.getRefList();
while (true) { while (true) {
SnapshotDiffSection.DiffEntry entry = SnapshotDiffSection.DiffEntry SnapshotDiffSection.DiffEntry entry = SnapshotDiffSection.DiffEntry
.parseDelimitedFrom(in); .parseDelimitedFrom(in);
@ -145,7 +186,8 @@ public class FSImageFormatPBSnapshot {
loadFileDiffList(in, inode.asFile(), entry.getNumOfDiff()); loadFileDiffList(in, inode.asFile(), entry.getNumOfDiff());
break; break;
case DIRECTORYDIFF: case DIRECTORYDIFF:
loadDirectoryDiffList(in, inode.asDirectory(), entry.getNumOfDiff()); loadDirectoryDiffList(in, inode.asDirectory(), entry.getNumOfDiff(),
refList);
break; break;
} }
} }
@ -199,13 +241,13 @@ public class FSImageFormatPBSnapshot {
/** /**
* Load the deleted list in a DirectoryDiff * 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, private List<INode> loadDeletedList(final List<INodeReference> refList,
int refNum, List<Long> deletedNodes) throws IOException { InputStream in, INodeDirectory dir, List<Long> deletedNodes,
List<INode> dlist = new ArrayList<INode>(refNum + deletedNodes.size()); List<Integer> deletedRefNodes)
throws IOException {
List<INode> dlist = new ArrayList<INode>(deletedRefNodes.size()
+ deletedNodes.size());
// load non-reference inodes // load non-reference inodes
for (long deletedId : deletedNodes) { for (long deletedId : deletedNodes) {
INode deleted = fsDir.getInode(deletedId); INode deleted = fsDir.getInode(deletedId);
@ -213,13 +255,12 @@ public class FSImageFormatPBSnapshot {
addToDeletedList(deleted, dir); addToDeletedList(deleted, dir);
} }
// load reference nodes in the deleted list // load reference nodes in the deleted list
for (int r = 0; r < refNum; r++) { for (int refId : deletedRefNodes) {
INodeSection.INodeReference ref = INodeSection.INodeReference INodeReference deletedRef = refList.get(refId);
.parseDelimitedFrom(in); dlist.add(deletedRef);
INodeReference refNode = loadINodeReference(ref, fsDir); addToDeletedList(deletedRef, dir);
dlist.add(refNode);
addToDeletedList(refNode, dir);
} }
Collections.sort(dlist, new Comparator<INode>() { Collections.sort(dlist, new Comparator<INode>() {
@Override @Override
public int compare(INode n1, INode n2) { public int compare(INode n1, INode n2) {
@ -231,7 +272,7 @@ public class FSImageFormatPBSnapshot {
/** Load DirectoryDiff list for a directory with snapshot feature */ /** Load DirectoryDiff list for a directory with snapshot feature */
private void loadDirectoryDiffList(InputStream in, INodeDirectory dir, private void loadDirectoryDiffList(InputStream in, INodeDirectory dir,
int size) throws IOException { int size, final List<INodeReference> refList) throws IOException {
if (!dir.isWithSnapshot()) { if (!dir.isWithSnapshot()) {
dir.addSnapshotFeature(null); dir.addSnapshotFeature(null);
} }
@ -247,7 +288,7 @@ public class FSImageFormatPBSnapshot {
INodeDirectoryAttributes copy = null; INodeDirectoryAttributes copy = null;
if (useRoot) { if (useRoot) {
copy = snapshot.getRoot(); copy = snapshot.getRoot();
}else if (diffInPb.hasSnapshotCopy()) { } else if (diffInPb.hasSnapshotCopy()) {
INodeSection.INodeDirectory dirCopyInPb = diffInPb.getSnapshotCopy(); INodeSection.INodeDirectory dirCopyInPb = diffInPb.getSnapshotCopy();
final byte[] name = diffInPb.getName().toByteArray(); final byte[] name = diffInPb.getName().toByteArray();
PermissionStatus permission = loadPermission( PermissionStatus permission = loadPermission(
@ -265,8 +306,8 @@ public class FSImageFormatPBSnapshot {
List<INode> clist = loadCreatedList(in, dir, List<INode> clist = loadCreatedList(in, dir,
diffInPb.getCreatedListSize()); diffInPb.getCreatedListSize());
// load deleted list // load deleted list
List<INode> dlist = loadDeletedList(in, dir, List<INode> dlist = loadDeletedList(refList, in, dir,
diffInPb.getNumOfDeletedRef(), diffInPb.getDeletedINodeList()); diffInPb.getDeletedINodeList(), diffInPb.getDeletedINodeRefList());
// create the directory diff // create the directory diff
DirectoryDiff diff = new DirectoryDiff(snapshotId, copy, null, DirectoryDiff diff = new DirectoryDiff(snapshotId, copy, null,
childrenSize, clist, dlist, useRoot); childrenSize, clist, dlist, useRoot);
@ -285,7 +326,8 @@ public class FSImageFormatPBSnapshot {
private final SaveNamespaceContext context; private final SaveNamespaceContext context;
public Saver(FSImageFormatProtobuf.Saver parent, public Saver(FSImageFormatProtobuf.Saver parent,
FileSummary.Builder headers, SaveNamespaceContext context, FSNamesystem fsn) { FileSummary.Builder headers, SaveNamespaceContext context,
FSNamesystem fsn) {
this.parent = parent; this.parent = parent;
this.headers = headers; this.headers = headers;
this.context = context; this.context = context;
@ -330,12 +372,42 @@ public class FSImageFormatPBSnapshot {
parent.commitSection(headers, FSImageFormatProtobuf.SectionName.SNAPSHOT); parent.commitSection(headers, FSImageFormatProtobuf.SectionName.SNAPSHOT);
} }
/**
* This can only be called after serializing both INode_Dir and SnapshotDiff
*/
public void serializeINodeReferenceSection(OutputStream out)
throws IOException {
final List<INodeReference> refList = parent.getSaverContext()
.getRefList();
for (INodeReference ref : refList) {
INodeReferenceSection.INodeReference.Builder rb = buildINodeReference(ref);
rb.build().writeDelimitedTo(out);
}
parent.commitSection(headers, SectionName.INODE_REFRENCE);
}
private INodeReferenceSection.INodeReference.Builder buildINodeReference(
INodeReference ref) throws IOException {
INodeReferenceSection.INodeReference.Builder rb =
INodeReferenceSection.INodeReference.newBuilder().
setReferredId(ref.getId());
if (ref instanceof WithName) {
rb.setLastSnapshotId(((WithName) ref).getLastSnapshotId()).setName(
ByteString.copyFrom(ref.getLocalNameBytes()));
} else if (ref instanceof DstReference) {
rb.setDstSnapshotId(((DstReference) ref).getDstSnapshotId());
}
return rb;
}
/** /**
* save all the snapshot diff to fsimage * save all the snapshot diff to fsimage
*/ */
public void serializeSnapshotDiffSection(OutputStream out) public void serializeSnapshotDiffSection(OutputStream out)
throws IOException { throws IOException {
INodeMap inodesMap = fsn.getFSDirectory().getINodeMap(); INodeMap inodesMap = fsn.getFSDirectory().getINodeMap();
final List<INodeReference> refList = parent.getSaverContext()
.getRefList();
int i = 0; int i = 0;
Iterator<INodeWithAdditionalFields> iter = inodesMap.getMapIterator(); Iterator<INodeWithAdditionalFields> iter = inodesMap.getMapIterator();
while (iter.hasNext()) { while (iter.hasNext()) {
@ -343,7 +415,7 @@ public class FSImageFormatPBSnapshot {
if (inode.isFile()) { if (inode.isFile()) {
serializeFileDiffList(inode.asFile(), out); serializeFileDiffList(inode.asFile(), out);
} else if (inode.isDirectory()) { } else if (inode.isDirectory()) {
serializeDirDiffList(inode.asDirectory(), out); serializeDirDiffList(inode.asDirectory(), refList, out);
} }
++i; ++i;
if (i % FSImageFormatProtobuf.Saver.CHECK_CANCEL_INTERVAL == 0) { if (i % FSImageFormatProtobuf.Saver.CHECK_CANCEL_INTERVAL == 0) {
@ -378,22 +450,18 @@ public class FSImageFormatPBSnapshot {
} }
} }
private void saveCreatedDeletedList(List<INode> created, private void saveCreatedList(List<INode> created, OutputStream out)
List<INodeReference> deletedRefs, OutputStream out) throws IOException { throws IOException {
// local names of the created list member // local names of the created list member
for (INode c : created) { for (INode c : created) {
SnapshotDiffSection.CreatedListEntry.newBuilder() SnapshotDiffSection.CreatedListEntry.newBuilder()
.setName(ByteString.copyFrom(c.getLocalNameBytes())).build() .setName(ByteString.copyFrom(c.getLocalNameBytes())).build()
.writeDelimitedTo(out); .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) private void serializeDirDiffList(INodeDirectory dir,
final List<INodeReference> refList, OutputStream out)
throws IOException { throws IOException {
DirectoryWithSnapshotFeature sf = dir.getDirectoryWithSnapshotFeature(); DirectoryWithSnapshotFeature sf = dir.getDirectoryWithSnapshotFeature();
if (sf != null) { if (sf != null) {
@ -419,17 +487,16 @@ public class FSImageFormatPBSnapshot {
.getList(ListType.CREATED); .getList(ListType.CREATED);
db.setCreatedListSize(created.size()); db.setCreatedListSize(created.size());
List<INode> deleted = diff.getChildrenDiff().getList(ListType.DELETED); List<INode> deleted = diff.getChildrenDiff().getList(ListType.DELETED);
List<INodeReference> refs = new ArrayList<INodeReference>();
for (INode d : deleted) { for (INode d : deleted) {
if (d.isReference()) { if (d.isReference()) {
refs.add(d.asReference()); refList.add(d.asReference());
db.addDeletedINodeRef(refList.size() - 1);
} else { } else {
db.addDeletedINode(d.getId()); db.addDeletedINode(d.getId());
} }
} }
db.setNumOfDeletedRef(refs.size());
db.build().writeDelimitedTo(out); db.build().writeDelimitedTo(out);
saveCreatedDeletedList(created, refs, out); saveCreatedList(created, out);
} }
} }
} }

View File

@ -36,6 +36,7 @@ import org.apache.hadoop.hdfs.server.namenode.FSImageFormatProtobuf.SectionName;
import org.apache.hadoop.hdfs.server.namenode.FSImageUtil; import org.apache.hadoop.hdfs.server.namenode.FSImageUtil;
import org.apache.hadoop.hdfs.server.namenode.FsImageProto.FileSummary; import org.apache.hadoop.hdfs.server.namenode.FsImageProto.FileSummary;
import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeDirectorySection; import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeDirectorySection;
import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeReferenceSection;
import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeSection; import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeSection;
import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeSection.INode; import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeSection.INode;
import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeSection.INodeDirectory; import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeSection.INodeDirectory;
@ -79,6 +80,7 @@ final class LsrPBImage {
private String[] stringTable; private String[] stringTable;
private HashMap<Long, INodeSection.INode> inodes = Maps.newHashMap(); private HashMap<Long, INodeSection.INode> inodes = Maps.newHashMap();
private HashMap<Long, long[]> dirmap = Maps.newHashMap(); private HashMap<Long, long[]> dirmap = Maps.newHashMap();
private ArrayList<INodeReferenceSection.INodeReference> refList = Lists.newArrayList();
public LsrPBImage(Configuration conf, PrintWriter out) { public LsrPBImage(Configuration conf, PrintWriter out) {
this.conf = conf; this.conf = conf;
@ -125,6 +127,9 @@ final class LsrPBImage {
case INODE: case INODE:
loadINodeSection(is); loadINodeSection(is);
break; break;
case INODE_REFRENCE:
loadINodeReferenceSection(is);
break;
case INODE_DIR: case INODE_DIR:
loadINodeDirectorySection(is); loadINodeDirectorySection(is);
break; break;
@ -202,14 +207,26 @@ final class LsrPBImage {
if (e == null) { if (e == null) {
break; break;
} }
long[] l = new long[e.getChildrenCount()]; long[] l = new long[e.getChildrenCount() + e.getRefChildrenCount()];
for (int i = 0; i < l.length; ++i) { for (int i = 0; i < e.getChildrenCount(); ++i) {
l[i] = e.getChildren(i); l[i] = e.getChildren(i);
} }
dirmap.put(e.getParent(), l); for (int i = e.getChildrenCount(); i < l.length; i++) {
for (int i = 0; i < e.getNumOfRef(); i++) { int refId = e.getRefChildren(i - e.getChildrenCount());
INodeSection.INodeReference.parseDelimitedFrom(in); l[i] = refList.get(refId).getReferredId();
} }
dirmap.put(e.getParent(), l);
}
}
private void loadINodeReferenceSection(InputStream in) throws IOException {
while (true) {
INodeReferenceSection.INodeReference e = INodeReferenceSection
.INodeReference.parseDelimitedFrom(in);
if (e == null) {
break;
}
refList.add(e);
} }
} }

View File

@ -43,6 +43,7 @@ import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeDirectorySection
import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeSection; import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeSection;
import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeSection.INodeDirectory; import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeSection.INodeDirectory;
import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeSection.INodeSymlink; import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeSection.INodeSymlink;
import org.apache.hadoop.hdfs.server.namenode.FsImageProto.INodeReferenceSection;
import org.apache.hadoop.hdfs.server.namenode.FsImageProto.NameSystemSection; import org.apache.hadoop.hdfs.server.namenode.FsImageProto.NameSystemSection;
import org.apache.hadoop.hdfs.server.namenode.FsImageProto.SecretManagerSection; import org.apache.hadoop.hdfs.server.namenode.FsImageProto.SecretManagerSection;
import org.apache.hadoop.hdfs.server.namenode.FsImageProto.SnapshotDiffSection; import org.apache.hadoop.hdfs.server.namenode.FsImageProto.SnapshotDiffSection;
@ -132,6 +133,9 @@ public final class PBImageXmlWriter {
case INODE: case INODE:
dumpINodeSection(is); dumpINodeSection(is);
break; break;
case INODE_REFRENCE:
dumpINodeReferenceSection(is);
break;
case INODE_DIR: case INODE_DIR:
dumpINodeDirectorySection(is); dumpINodeDirectorySection(is);
break; break;
@ -227,18 +231,27 @@ public final class PBImageXmlWriter {
for (long id : e.getChildrenList()) { for (long id : e.getChildrenList()) {
o("inode", id); o("inode", id);
} }
for (int i = 0; i < e.getNumOfRef(); i++) { for (int refId : e.getRefChildrenList()) {
INodeSection.INodeReference r = INodeSection.INodeReference o("inodereference-index", refId);
.parseDelimitedFrom(in);
dumpINodeReference(r);
} }
out.print("</directory>\n"); out.print("</directory>\n");
} }
out.print("</INodeDirectorySection>\n"); out.print("</INodeDirectorySection>\n");
} }
private void dumpINodeReference(INodeSection.INodeReference r) { private void dumpINodeReferenceSection(InputStream in) throws IOException {
out.print("<INodeReferenceSection>");
while (true) {
INodeReferenceSection.INodeReference e = INodeReferenceSection
.INodeReference.parseDelimitedFrom(in);
if (e == null) {
break;
}
dumpINodeReference(e);
}
}
private void dumpINodeReference(INodeReferenceSection.INodeReference r) {
out.print("<ref>"); out.print("<ref>");
o("referredId", r.getReferredId()).o("name", r.getName().toStringUtf8()) o("referredId", r.getReferredId()).o("name", r.getName().toStringUtf8())
.o("dstSnapshotId", r.getDstSnapshotId()) .o("dstSnapshotId", r.getDstSnapshotId())
@ -362,10 +375,15 @@ public final class PBImageXmlWriter {
o("name", ce.getName().toStringUtf8()); o("name", ce.getName().toStringUtf8());
out.print("</created>\n"); out.print("</created>\n");
} }
for (int j = 0; j < d.getNumOfDeletedRef(); ++j) { for (long did : d.getDeletedINodeList()) {
INodeSection.INodeReference r = INodeSection.INodeReference out.print("<deleted>");
.parseDelimitedFrom(in); o("inode", did);
dumpINodeReference(r); out.print("</deleted>\n");
}
for (int dRefid : d.getDeletedINodeRefList()) {
out.print("<deleted>");
o("inodereference-index", dRefid);
out.print("</deleted>\n");
} }
out.print("</dirdiff>\n"); out.print("</dirdiff>\n");
} }

View File

@ -112,17 +112,6 @@ message INodeSection {
optional bytes target = 2; optional bytes target = 2;
} }
message INodeReference {
// id of the referred inode
optional uint64 referredId = 1;
// local name recorded in WithName
optional bytes name = 2;
// recorded in DstReference
optional uint32 dstSnapshotId = 3;
// recorded in WithName
optional uint32 lastSnapshotId = 4;
}
message INode { message INode {
enum Type { enum Type {
FILE = 1; FILE = 1;
@ -163,13 +152,28 @@ message FilesUnderConstructionSection {
message INodeDirectorySection { message INodeDirectorySection {
message DirEntry { message DirEntry {
optional uint64 parent = 1; optional uint64 parent = 1;
// children that are not reference nodes
repeated uint64 children = 2 [packed = true]; repeated uint64 children = 2 [packed = true];
optional uint64 numOfRef = 3; // children that are reference nodes, each element is a reference node id
// repeated INodeReference... repeated uint32 refChildren = 3 [packed = true];
} }
// repeated DirEntry, ended at the boundary of the section. // repeated DirEntry, ended at the boundary of the section.
} }
message INodeReferenceSection {
message INodeReference {
// id of the referred inode
optional uint64 referredId = 1;
// local name recorded in WithName
optional bytes name = 2;
// recorded in DstReference
optional uint32 dstSnapshotId = 3;
// recorded in WithName
optional uint32 lastSnapshotId = 4;
}
// repeated INodeReference...
}
/** /**
* This section records the information about snapshot * This section records the information about snapshot
* NAME: SNAPSHOT * NAME: SNAPSHOT
@ -204,10 +208,10 @@ message SnapshotDiffSection {
optional bytes name = 4; optional bytes name = 4;
optional INodeSection.INodeDirectory snapshotCopy = 5; optional INodeSection.INodeDirectory snapshotCopy = 5;
optional uint32 createdListSize = 6; optional uint32 createdListSize = 6;
optional uint32 numOfDeletedRef = 7; // number of reference nodes in deleted list repeated uint64 deletedINode = 7 [packed = true]; // id of deleted inodes
repeated uint64 deletedINode = 8 [packed = true]; // id of deleted inode // id of reference nodes in the deleted list
repeated uint32 deletedINodeRef = 8 [packed = true];
// repeated CreatedListEntry (size is specified by createdListSize) // repeated CreatedListEntry (size is specified by createdListSize)
// repeated INodeReference (reference inodes in deleted list)
} }
message FileDiff { message FileDiff {