package org.apache.hadoop.hdfs.server.namenode;
import org.mockito.internal.stubbing.answers.Returns;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import java.io.IOException;
import static org.mockito.Mockito.*;
public class FSNamesystemAdapter {
public static void forceNamenodeLeaseRecovery(
String src, FSNamesystem namesystem
) throws IOException {
LeaseManager.Lease lease = namesystem.leaseManager.getLeaseByPath(src);
if (lease != null) {
namesystem.internalReleaseLeaseOne(lease, src);
}
}
public static void assignLease(
String src, String newHolder, FSNamesystem namesystem
) {
LeaseManager.Lease lease = namesystem.leaseManager.getLeaseByPath(src);
if (lease != null) {
// not atomic, but probably ok for testing purposes
namesystem.leaseManager.removeLease(lease, newHolder);
namesystem.leaseManager.addLease(newHolder, src,
System.currentTimeMillis());
}
}
public static void expireLease(String src, FSNamesystem namesystem) {
// use Mockito to insert a return value of false
LeaseManager.Lease lease = spy(namesystem.leaseManager.getLeaseByPath(src));
Answer<Boolean> contextBasedValue = new Answer<Boolean>() {
@Override
public Boolean answer(InvocationOnMock invocationOnMock)
throws Throwable {
StackTraceElement[] stack = Thread.currentThread().getStackTrace();
// this will expire only when called during NamenodeFsck.fsck() :)
for (StackTraceElement element : stack) {
if (element.getMethodName().contains("checkForCorruptOpenFiles")) {
return true;
}
}
return (Boolean) invocationOnMock.callRealMethod();
}
};
doAnswer(contextBasedValue)
.when(lease)
.expiredHardLimit();
// this will remove the lease and add our mocked one
namesystem.leaseManager.replaceLease(lease);
}
public static void corruptFileForTesting(
String src, FSNamesystem namesystem
) throws IOException {
namesystem.corruptFileForTesting(src);
expireLease(src, namesystem);
}
}