|
@@ -1,4 +1,4 @@
|
|
|
-/**
|
|
|
+ /**
|
|
|
* 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
|
|
@@ -27,6 +27,7 @@ import java.io.IOException;
|
|
|
import java.io.InputStream;
|
|
|
import java.io.OutputStream;
|
|
|
import java.util.ArrayList;
|
|
|
+import java.util.Arrays;
|
|
|
import java.util.Collections;
|
|
|
import java.util.Comparator;
|
|
|
import java.util.HashMap;
|
|
@@ -49,6 +50,7 @@ import org.apache.hadoop.hdfs.server.blockmanagement.BlockManager;
|
|
|
import org.apache.hadoop.hdfs.server.namenode.AclEntryStatusFormat;
|
|
|
import org.apache.hadoop.hdfs.server.namenode.AclFeature;
|
|
|
import org.apache.hadoop.hdfs.server.namenode.FSDirectory;
|
|
|
+import org.apache.hadoop.hdfs.server.namenode.FSImage;
|
|
|
import org.apache.hadoop.hdfs.server.namenode.FSImageFormatPBINode;
|
|
|
import org.apache.hadoop.hdfs.server.namenode.FSImageFormatProtobuf;
|
|
|
import org.apache.hadoop.hdfs.server.namenode.FSImageFormatProtobuf.LoaderContext;
|
|
@@ -415,6 +417,7 @@ public class FSImageFormatPBSnapshot {
|
|
|
private final FileSummary.Builder headers;
|
|
|
private final FSImageFormatProtobuf.Saver parent;
|
|
|
private final SaveNamespaceContext context;
|
|
|
+ private long numImageErrors;
|
|
|
|
|
|
public Saver(FSImageFormatProtobuf.Saver parent,
|
|
|
FileSummary.Builder headers, SaveNamespaceContext context,
|
|
@@ -423,6 +426,7 @@ public class FSImageFormatPBSnapshot {
|
|
|
this.headers = headers;
|
|
|
this.context = context;
|
|
|
this.fsn = fsn;
|
|
|
+ this.numImageErrors = 0;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -471,15 +475,17 @@ public class FSImageFormatPBSnapshot {
|
|
|
throws IOException {
|
|
|
final List<INodeReference> refList = parent.getSaverContext()
|
|
|
.getRefList();
|
|
|
+ long i = 0;
|
|
|
for (INodeReference ref : refList) {
|
|
|
- INodeReferenceSection.INodeReference.Builder rb = buildINodeReference(ref);
|
|
|
+ INodeReferenceSection.INodeReference.Builder rb =
|
|
|
+ buildINodeReference(ref, i++);
|
|
|
rb.build().writeDelimitedTo(out);
|
|
|
}
|
|
|
parent.commitSection(headers, SectionName.INODE_REFERENCE);
|
|
|
}
|
|
|
|
|
|
private INodeReferenceSection.INodeReference.Builder buildINodeReference(
|
|
|
- INodeReference ref) throws IOException {
|
|
|
+ final INodeReference ref, final long refIndex) throws IOException {
|
|
|
INodeReferenceSection.INodeReference.Builder rb =
|
|
|
INodeReferenceSection.INodeReference.newBuilder().
|
|
|
setReferredId(ref.getId());
|
|
@@ -489,6 +495,16 @@ public class FSImageFormatPBSnapshot {
|
|
|
} else if (ref instanceof DstReference) {
|
|
|
rb.setDstSnapshotId(ref.getDstSnapshotId());
|
|
|
}
|
|
|
+
|
|
|
+ if (fsn.getFSDirectory().getInode(ref.getId()) == null) {
|
|
|
+ FSImage.LOG.error(
|
|
|
+ "FSImageFormatPBSnapshot: Missing referred INodeId " +
|
|
|
+ ref.getId() + " for INodeReference index " + refIndex +
|
|
|
+ "; path=" + ref.getFullPathName() +
|
|
|
+ "; parent=" + (ref.getParent() == null ? "null" :
|
|
|
+ ref.getParent().getFullPathName()));
|
|
|
+ ++numImageErrors;
|
|
|
+ }
|
|
|
return rb;
|
|
|
}
|
|
|
|
|
@@ -583,7 +599,23 @@ public class FSImageFormatPBSnapshot {
|
|
|
List<INode> created = diff.getChildrenDiff().getCreatedUnmodifiable();
|
|
|
db.setCreatedListSize(created.size());
|
|
|
List<INode> deleted = diff.getChildrenDiff().getDeletedUnmodifiable();
|
|
|
+ INode previousNode = null;
|
|
|
+ boolean misordered = false;
|
|
|
for (INode d : deleted) {
|
|
|
+ // getBytes() may return null below, and that is okay.
|
|
|
+ final int result = previousNode == null ? -1 :
|
|
|
+ previousNode.compareTo(d.getLocalNameBytes());
|
|
|
+ if (result == 0) {
|
|
|
+ FSImage.LOG.error(
|
|
|
+ "Name '" + d.getLocalName() + "' is repeated in the " +
|
|
|
+ "'deleted' difflist of directory " +
|
|
|
+ dir.getFullPathName() + ", INodeId=" + dir.getId());
|
|
|
+ ++numImageErrors;
|
|
|
+ } else if (result > 0 && !misordered) {
|
|
|
+ misordered = true;
|
|
|
+ ++numImageErrors;
|
|
|
+ }
|
|
|
+ previousNode = d;
|
|
|
if (d.isReference()) {
|
|
|
refList.add(d.asReference());
|
|
|
db.addDeletedINodeRef(refList.size() - 1);
|
|
@@ -591,11 +623,28 @@ public class FSImageFormatPBSnapshot {
|
|
|
db.addDeletedINode(d.getId());
|
|
|
}
|
|
|
}
|
|
|
+ if (misordered) {
|
|
|
+ FSImage.LOG.error(
|
|
|
+ "Misordered entries in the 'deleted' difflist of directory " +
|
|
|
+ dir.getFullPathName() + ", INodeId=" + dir.getId() +
|
|
|
+ ". The full list is " +
|
|
|
+ Arrays.toString(deleted.toArray()));
|
|
|
+ }
|
|
|
db.build().writeDelimitedTo(out);
|
|
|
saveCreatedList(created, out);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Number of non-fatal errors detected while writing the
|
|
|
+ * SnapshotDiff and INodeReference sections.
|
|
|
+ * @return the number of non-fatal errors detected.
|
|
|
+ */
|
|
|
+ public long getNumImageErrors() {
|
|
|
+ return numImageErrors;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
private FSImageFormatPBSnapshot(){}
|