-
Notifications
You must be signed in to change notification settings - Fork 558
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
Ensure raft storage lock file is update atomically #10683
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,20 +16,14 @@ | |
*/ | ||
package io.atomix.raft.storage; | ||
|
||
import static org.junit.Assert.assertEquals; | ||
import static org.junit.Assert.assertFalse; | ||
import static org.junit.Assert.assertTrue; | ||
import static org.assertj.core.api.Assertions.assertThat; | ||
|
||
import io.camunda.zeebe.util.FileUtil; | ||
import java.io.File; | ||
import java.io.IOException; | ||
import java.nio.file.FileVisitResult; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.nio.file.Paths; | ||
import java.nio.file.SimpleFileVisitor; | ||
import java.nio.file.attribute.BasicFileAttributes; | ||
import org.junit.After; | ||
import org.junit.Before; | ||
import org.junit.Test; | ||
|
||
/** Raft storage test. */ | ||
|
@@ -38,14 +32,14 @@ public class RaftStorageTest { | |
private static final Path PATH = Paths.get("target/test-logs/"); | ||
|
||
@Test | ||
public void testDefaultConfiguration() throws Exception { | ||
public void testDefaultConfiguration() { | ||
final RaftStorage storage = RaftStorage.builder().build(); | ||
assertEquals("atomix", storage.prefix()); | ||
assertEquals(new File(System.getProperty("user.dir")), storage.directory()); | ||
assertThat(storage.prefix()).isEqualTo("atomix"); | ||
assertThat(storage.directory()).isEqualTo(new File(System.getProperty("user.dir"))); | ||
} | ||
|
||
@Test | ||
public void testCustomConfiguration() throws Exception { | ||
public void testCustomConfiguration() { | ||
final RaftStorage storage = | ||
RaftStorage.builder() | ||
.withPrefix("foo") | ||
|
@@ -54,49 +48,54 @@ public void testCustomConfiguration() throws Exception { | |
.withFreeDiskSpace(100) | ||
.withFlushExplicitly(false) | ||
.build(); | ||
assertEquals("foo", storage.prefix()); | ||
assertEquals(new File(PATH.toFile(), "foo"), storage.directory()); | ||
assertThat(storage.prefix()).isEqualTo("foo"); | ||
assertThat(storage.directory()).isEqualTo(new File(PATH.toFile(), "foo")); | ||
} | ||
|
||
@Test | ||
public void testStorageLock() throws Exception { | ||
public void canAcquireLockOnEmptyDirectory() { | ||
// given empty directory in PATH | ||
|
||
// when | ||
final RaftStorage storage1 = | ||
RaftStorage.builder().withDirectory(PATH.toFile()).withPrefix("test").build(); | ||
|
||
assertTrue(storage1.lock("a")); | ||
// then | ||
assertThat(storage1.lock("a")).isTrue(); | ||
} | ||
|
||
@Test | ||
public void cannotLockAlreadyLockedDirectory() { | ||
// given | ||
final RaftStorage storage1 = | ||
RaftStorage.builder().withDirectory(PATH.toFile()).withPrefix("test").build(); | ||
storage1.lock("a"); | ||
|
||
// when | ||
final RaftStorage storage2 = | ||
RaftStorage.builder().withDirectory(PATH.toFile()).withPrefix("test").build(); | ||
|
||
assertFalse(storage2.lock("b")); | ||
// then | ||
assertThat(storage2.lock("b")).isFalse(); | ||
} | ||
|
||
@Test | ||
public void canAcquireLockOnDirectoryLockedBySameNode() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💭 Just as an idea regarding another test. If we would make the writing to a file injectable (via dependency injection) we could also fail the writing and write a test whether failing write doesn't lock the storage anymore. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🤔 Ya. May be. I will pass it for now. It would be also good if we can inject a mock filesystem in which we can simulate all kinds of failure. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agree but then we shouldn't longer use Files class :) or at least some wrapper :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think @npepinpe had looked into to similar ideas for testing journal. |
||
// given | ||
final RaftStorage storage1 = | ||
RaftStorage.builder().withDirectory(PATH.toFile()).withPrefix("test").build(); | ||
storage1.lock("a"); | ||
|
||
// when | ||
final RaftStorage storage3 = | ||
RaftStorage.builder().withDirectory(PATH.toFile()).withPrefix("test").build(); | ||
|
||
assertTrue(storage3.lock("a")); | ||
// then | ||
assertThat(storage3.lock("a")).isTrue(); | ||
} | ||
|
||
@Before | ||
@After | ||
public void cleanupStorage() throws IOException { | ||
if (Files.exists(PATH)) { | ||
Files.walkFileTree( | ||
PATH, | ||
new SimpleFileVisitor<>() { | ||
@Override | ||
public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) | ||
throws IOException { | ||
Files.delete(file); | ||
return FileVisitResult.CONTINUE; | ||
} | ||
|
||
@Override | ||
public FileVisitResult postVisitDirectory(final Path dir, final IOException exc) | ||
throws IOException { | ||
Files.delete(dir); | ||
return FileVisitResult.CONTINUE; | ||
} | ||
}); | ||
} | ||
FileUtil.deleteFolderIfExists(PATH); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❓ I can remember a discussion that this was only supported on some environments wasn't that something? Like only linux or? Is this an issue?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you know what exactly was the problem?
Flushing the parent directory does not work in windows. But according to what is documented in
FileUtil
, this is ok.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are using
FileUtil#moveDurably
in other places as well. So far no problems are reported. So I guess it should be ok. So I will merge this PR. If we see/know any problems later, let's tackle it then.