Skip to content

Commit

Permalink
fix(raft): ensure lock files is created and updated atomically
Browse files Browse the repository at this point in the history
This is required to prevent an empty lock files during restart, if the system crashed before the lock content is written to the file.

(cherry picked from commit 8322db7)
  • Loading branch information
deepthidevaki authored and github-actions[bot] committed Oct 13, 2022
1 parent 31e08aa commit 3056a27
Showing 1 changed file with 23 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@
import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;

/**
Expand Down Expand Up @@ -110,17 +112,30 @@ public String prefix() {
* @return indicates whether the lock was successfully acquired
*/
public boolean lock(final String id) {
final File file = new File(directory, String.format(".%s.lock", prefix));
final File lockFile = new File(directory, String.format(".%s.lock", prefix));
final File tempLockFile = new File(directory, String.format(".%s.lock.tmp", id));
try {
if (file.createNewFile()) {
Files.writeString(file.toPath(), id, StandardOpenOption.WRITE);
return true;
} else {
final String lock = Files.readString(file.toPath());
return lock != null && lock.equals(id);
if (!lockFile.exists()) {
// Create and update the file atomically
Files.writeString(
tempLockFile.toPath(),
id,
StandardOpenOption.CREATE,
StandardOpenOption.TRUNCATE_EXISTING,
StandardOpenOption.WRITE,
StandardOpenOption.SYNC);

// If two nodes tries to acquire lock, move will fail with FileAlreadyExistsException
FileUtil.moveDurably(
tempLockFile.toPath(), lockFile.toPath(), StandardCopyOption.ATOMIC_MOVE);
}
// Read the lock file again to ensure that contents matches the local id
final String lock = Files.readString(lockFile.toPath());
return lock != null && lock.equals(id);
} catch (final FileAlreadyExistsException e) {
return false;
} catch (final IOException e) {
throw new StorageException("Failed to acquire storage lock");
throw new StorageException("Failed to acquire storage lock", e);
}
}

Expand Down

0 comments on commit 3056a27

Please sign in to comment.