Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle truncated translog gracefully #9797

Merged
merged 1 commit into from Mar 3, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -220,7 +220,7 @@ public void recover(boolean indexShouldExists, RecoveryState recoveryState) thro
in.readInt(); // ignored opSize
}
operation = stream.read(in);
} catch (EOFException e) {
} catch (TruncatedTranslogException|EOFException e) {
// ignore, not properly written the last op
logger.trace("ignoring translog EOF exception, the last operation was not properly written", e);
break;
Expand Down
Expand Up @@ -65,6 +65,8 @@ public Translog.Operation read(StreamInput inStream) throws IOException {
Translog.Operation.Type type = Translog.Operation.Type.fromId(in.readByte());
operation = TranslogStreams.newOperationFromType(type);
operation.readFrom(in);
} catch (EOFException e) {
throw new TruncatedTranslogException("reached premature end of file, translog is truncated", e);
} catch (AssertionError|Exception e) {
throw new TranslogCorruptedException("translog corruption while reading from stream", e);
}
Expand Down
Expand Up @@ -35,6 +35,7 @@
import org.junit.Before;
import org.junit.Test;

import java.io.EOFException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
Expand Down Expand Up @@ -528,6 +529,50 @@ public void testTranslogChecksums() throws Exception {
assertThat("at least one corruption was caused and caught", corruptionsCaught.get(), greaterThanOrEqualTo(1));
}

@Test
public void testTruncatedTranslogs() throws Exception {
List<Translog.Location> locations = newArrayList();

int translogOperations = randomIntBetween(10, 100);
for (int op = 0; op < translogOperations; op++) {
String ascii = randomAsciiOfLengthBetween(1, 50);
locations.add(translog.add(new Translog.Create("test", "" + op, ascii.getBytes("UTF-8"))));
}
translog.sync();

truncateTranslogs(translogFileDirectory());

AtomicInteger truncations = new AtomicInteger(0);
for (Translog.Location location : locations) {
try {
translog.read(location);
} catch (ElasticsearchException e) {
if (e.getCause() instanceof EOFException) {
truncations.incrementAndGet();
} else {
throw e;
}
}
}
assertThat("at least one truncation was caused and caught", truncations.get(), greaterThanOrEqualTo(1));
}

/**
* Randomly truncate some bytes in the translog files
*/
private void truncateTranslogs(Path directory) throws Exception {
Path[] files = FileSystemUtils.files(directory, "translog-*");
for (Path file : files) {
try (FileChannel f = FileChannel.open(file, StandardOpenOption.READ, StandardOpenOption.WRITE)) {
long prevSize = f.size();
long newSize = prevSize - randomIntBetween(1, (int) prevSize / 2);
logger.info("--> truncating {}, prev: {}, now: {}", file, prevSize, newSize);
f.truncate(newSize);
}
}
}


/**
* Randomly overwrite some bytes in the translog files
*/
Expand Down
Expand Up @@ -25,7 +25,6 @@
import org.junit.Test;

import java.io.EOFException;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;

Expand Down Expand Up @@ -146,4 +145,26 @@ public void testCorruptedTranslogs() throws Exception {
}

}

@Test
public void testTruncatedTranslog() throws Exception {
try {
Path translogFile = getResourcePath("/org/elasticsearch/index/translog/translog-v1-truncated.binary");
assertThat("test file should exist", Files.exists(translogFile), equalTo(true));
TranslogStream stream = TranslogStreams.translogStreamFor(translogFile);
try (StreamInput in = stream.openInput(translogFile)) {
while (true) {
try {
stream.read(in);
} catch (EOFException e) {
break;
}
}
}
fail("should have thrown an exception about the body being truncated");
} catch (TruncatedTranslogException e) {
assertThat("translog truncated: " + e.getMessage(),
e.getMessage().contains("reached premature end of file, translog is truncated"), equalTo(true));
}
}
}
Binary file not shown.