Skip to content

Commit

Permalink
HDFS-17380. FsImageValidation: remove inaccessible nodes. (#6549). Co…
Browse files Browse the repository at this point in the history
…ntributed by Tsz-wo Sze.

Signed-off-by: He Xiaoqiao <[email protected]>
  • Loading branch information
szetszwo authored Mar 18, 2024
1 parent 4d88f98 commit b25b28e
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
Expand Down Expand Up @@ -1213,6 +1214,14 @@ public void removeFromCheckpointing(long txid) {
currentlyCheckpointing.remove(txid);
}

void save(FSNamesystem src, File dst) throws IOException {
final SaveNamespaceContext context = new SaveNamespaceContext(src,
getCorrectLastAppliedOrWrittenTxId(), new Canceler());
final Storage.StorageDirectory storageDirectory = new Storage.StorageDirectory(dst);
Files.createDirectories(storageDirectory.getCurrentDir().toPath());
new FSImageSaver(context, storageDirectory, NameNodeFile.IMAGE).run();
}

private synchronized void saveFSImageInAllDirs(FSNamesystem source,
NameNodeFile nnf, long txid, Canceler canceler) throws IOException {
StartupProgress prog = NameNode.getStartupProgress();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
Expand Down Expand Up @@ -77,6 +79,35 @@ public class FsImageValidation {

static final String FS_IMAGE = "FS_IMAGE";

/**
* Use an environment variable "PRINT_ERROR" to enable/disable printing error messages.
* The default is true
*/
static final boolean PRINT_ERROR;

static {
PRINT_ERROR = getEnvBoolean("PRINT_ERROR", true);
}

/**
* @return the boolean value of an environment property.
* If the environment property is not set or cannot be parsed as a boolean,
* return the default value.
*/
static boolean getEnvBoolean(String property, boolean defaultValue) {
final String env = System.getenv().get(property);
final boolean setToNonDefault = ("" + !defaultValue).equalsIgnoreCase(env);
// default | setToNonDefault | value
// ---------------------------------
// true | true | false
// true | false | true
// false | true | true
// false | false | false
final boolean value = defaultValue != setToNonDefault;
LOG.info("ENV: {} = {} (\"{}\")", property, value, env);
return value;
}

static String getEnv(String property) {
final String value = System.getenv().get(property);
LOG.info("ENV: {} = {}", property, value);
Expand Down Expand Up @@ -186,13 +217,19 @@ int run(Configuration conf, AtomicInteger errorCount) throws Exception {
final FSNamesystem namesystem = checkINodeReference(conf, errorCount);

// check INodeMap
INodeMapValidation.run(namesystem.getFSDirectory(), errorCount);
final boolean changed = INodeMapValidation.run(namesystem.getFSDirectory(), errorCount);
LOG.info(Util.memoryInfo());

final int d = errorCount.get() - initCount;
if (d > 0) {
Cli.println("Found %d error(s) in %s", d, fsImageFile.getAbsolutePath());
}
if (changed) {
final File dir = fsImageFile.isDirectory()? fsImageFile: fsImageFile.getParentFile();
final Path temp = Files.createTempDirectory(dir.toPath(), "newFsImage");
Cli.println("INodeMap changed, save a new FSImage to %s", temp);
namesystem.getFSImage().save(namesystem, temp.toFile());
}
return d;
}

Expand Down Expand Up @@ -261,27 +298,26 @@ FSNamesystem checkINodeReference(Configuration conf,
}

static class INodeMapValidation {
static Iterable<INodeWithAdditionalFields> iterate(INodeMap map) {
return new Iterable<INodeWithAdditionalFields>() {
@Override
public Iterator<INodeWithAdditionalFields> iterator() {
return map.getMapIterator();
}
};
}

static void run(FSDirectory fsdir, AtomicInteger errorCount) {
static boolean run(FSDirectory fsdir, AtomicInteger errorCount) {
final String name = INodeMapValidation.class.getSimpleName();
final int initErrorCount = errorCount.get();
final Counts counts = INodeCountVisitor.countTree(fsdir.getRoot());
for (INodeWithAdditionalFields i : iterate(fsdir.getINodeMap())) {
final INodeMap map = fsdir.getINodeMap();
final int oldSize = map.size();
println("%s INodeMap old size: %d", name, oldSize);
for (final Iterator<INodeWithAdditionalFields> j = map.getMapIterator(); j.hasNext();) {
final INodeWithAdditionalFields i = j.next();
if (counts.getCount(i) == 0) {
j.remove();
Cli.printError(errorCount, "%s (%d) is inaccessible (%s)",
i, i.getId(), i.getFullPathName());
}
}
println("%s ended successfully: %d error(s) found.",
INodeMapValidation.class.getSimpleName(),
final int newSize = map.size();
println("%s INodeMap new size: %d", name, newSize);
println("%s ended successfully: %d error(s) found.", name,
errorCount.get() - initErrorCount);
return newSize != oldSize;
}
}

Expand Down Expand Up @@ -343,6 +379,10 @@ static synchronized void printError(String message, Throwable t) {
static synchronized void printError(AtomicInteger errorCount,
String format, Object... args) {
final int count = errorCount.incrementAndGet();
if (!PRINT_ERROR) {
return;
}

final String s = "FSIMAGE_ERROR " + count + ": "
+ String.format(format, args);
System.out.println(s);
Expand Down

0 comments on commit b25b28e

Please sign in to comment.