HDFS-2173. saveNamespace should not throw IOE when only one storage directory fails to write VERSION file. Contributed by Andras Bokor.

This commit is contained in:
Andrew Wang 2016-05-18 14:13:41 -07:00
parent 992a49353f
commit 010e6ac328
2 changed files with 51 additions and 7 deletions

View File

@ -1116,4 +1116,27 @@ public void updateNameDirSize() {
nameDirSizeMap.clear(); nameDirSizeMap.clear();
nameDirSizeMap.putAll(nnDirSizeMap); nameDirSizeMap.putAll(nnDirSizeMap);
} }
}
/**
* Write all data storage files.
* @throws IOException When all the storage directory fails to write
* VERSION file
*/
@Override
public void writeAll() throws IOException {
this.layoutVersion = getServiceLayoutVersion();
for (StorageDirectory sd : storageDirs) {
try {
writeProperties(sd);
} catch (Exception e) {
LOG.warn("Error during write properties to the VERSION file to " +
sd.toString(), e);
reportErrorsOnDirectory(sd);
if (storageDirs.isEmpty()) {
throw new IOException("All the storage failed while writing " +
"properties to VERSION file");
}
}
}
}
}

View File

@ -111,6 +111,29 @@ public Void answer(InvocationOnMock invocation) throws Throwable {
} }
} }
private static class FaultyWriteProperties implements Answer<Void> {
private int count = 0;
private Fault faultType;
FaultyWriteProperties(Fault faultType) {
this.faultType = faultType;
}
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
StorageDirectory sd = (StorageDirectory)args[0];
if (faultType == Fault.WRITE_STORAGE_ALL ||
(faultType==Fault.WRITE_STORAGE_ONE && count++==1)) {
LOG.info("Injecting fault for sd: " + sd);
throw new IOException("Injected fault: writeProperties second time");
}
LOG.info("Not injecting fault for sd: " + sd);
return (Void)invocation.callRealMethod();
}
}
private enum Fault { private enum Fault {
SAVE_SECOND_FSIMAGE_RTE, SAVE_SECOND_FSIMAGE_RTE,
SAVE_SECOND_FSIMAGE_IOE, SAVE_SECOND_FSIMAGE_IOE,
@ -164,17 +187,15 @@ private void saveNamespaceWithInjectedFault(Fault fault) throws Exception {
break; break;
case WRITE_STORAGE_ALL: case WRITE_STORAGE_ALL:
// The spy throws an exception before writing any VERSION files // The spy throws an exception before writing any VERSION files
doThrow(new RuntimeException("Injected")) doAnswer(new FaultyWriteProperties(Fault.WRITE_STORAGE_ALL))
.when(spyStorage).writeAll(); .when(spyStorage).writeProperties((StorageDirectory)anyObject());
shouldFail = true; shouldFail = true;
break; break;
case WRITE_STORAGE_ONE: case WRITE_STORAGE_ONE:
// The spy throws on exception on one particular storage directory // The spy throws on exception on one particular storage directory
doAnswer(new FaultySaveImage(true)) doAnswer(new FaultyWriteProperties(Fault.WRITE_STORAGE_ONE))
.when(spyStorage).writeProperties((StorageDirectory)anyObject()); .when(spyStorage).writeProperties((StorageDirectory)anyObject());
// TODO: unfortunately this fails -- should be improved. shouldFail = false;
// See HDFS-2173.
shouldFail = true;
break; break;
} }