File locking example

This commit is contained in:
Philippe Soares 2020-01-03 00:43:57 -05:00
parent 65ee6e2207
commit af27178965
4 changed files with 144 additions and 1 deletions

View File

@ -11,5 +11,5 @@ This module contains articles about core Java input and output (IO)
- [List Files in a Directory in Java](https://www.baeldung.com/java-list-directory-files)
- [Java Append Data to a File](https://www.baeldung.com/java-append-to-file)
- [How to Copy a File with Java](https://www.baeldung.com/java-copy-file)
- [Create a Directory in Java](https://www.baeldung.com/java-create-directory)
- [Create a Directory in Java](https://www.baeldung.com/java-create-directory)
- [[<-- Prev]](/core-java-modules/core-java-io)

View File

@ -14,5 +14,22 @@
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../parent-java</relativePath>
</parent>
<dependencies>
<!-- https://mvnrepository.com/artifact/com.github.jnr/jnr-ffi -->
<dependency>
<groupId>com.github.jnr</groupId>
<artifactId>jnr-ffi</artifactId>
<version>2.1.11</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.github.jnr/jnr-constants -->
<dependency>
<groupId>com.github.jnr</groupId>
<artifactId>jnr-constants</artifactId>
<version>0.9.14</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,105 @@
package com.baeldung.lock;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import jnr.ffi.LibraryLoader;
import jnr.ffi.Memory;
import jnr.ffi.Pointer;
import jnr.ffi.types.pid_t;
public class FileLocks {
public static interface LibC {
public static final int O_NONBLOCK = jnr.constants.platform.OpenFlags.O_NONBLOCK.intValue();
public static final int O_RDWR = jnr.constants.platform.OpenFlags.O_RDWR.intValue();
public static final int O_EXLOCK = jnr.constants.platform.OpenFlags.O_EXLOCK.intValue();
public long write(int fd, Pointer data, long len);
@pid_t
long getpid();
int open(String filename, int flags);
int close(int fd);
}
public static void main(String[] args) throws IOException, InterruptedException {
Path path = Paths.get("/tmp/foo");
// Delete the file if it exists
Files.deleteIfExists(path);
// Start with a fresh empty file
Files.createFile(path);
// Prepare some external libc calls. Will only work on systems that have libc.
LibC libc = LibraryLoader.create(LibC.class).load("c");
byte[] bytes = "Hello from C\n".getBytes("UTF-8");
jnr.ffi.Runtime runtime = jnr.ffi.Runtime.getRuntime(libc);
Pointer buffer = Memory.allocateDirect(runtime, bytes.length);
buffer.put(0, bytes, 0, bytes.length);
// Open the file through a libc call. This returns a file descriptor.
int fd = libc.open(path.toString(), libc.O_RDWR + libc.O_EXLOCK + libc.O_NONBLOCK);
System.out.println("Opened the file through a libc call that locks it.");
// Our java method will see the lock. Itd will be well behaved and won't write to the file.
// Note that external processes on POSIX systems would still be able to write to this file ignoring any locks.
writeToRandomAccessFile(path, "I won't write this", 0L);
// Libc opened the file, it can write to its corresponding file handle.
libc.write(fd, buffer, bytes.length);
// Now let's close the file through a libc call, to release its lock.
libc.close(fd);
System.out.println("Invoked libc's close() method");
// This time our method won't see the lock and will write to the file.
writeToRandomAccessFile(path, "Hello from java", bytes.length);
System.out.println("Now that all the locks are gone, here are the file contents:");
System.out.println("------------------------------------------------------------");
Files.lines(path).forEach(System.out::println);
}
public static RandomAccessFile writeToRandomAccessFile(Path path, String data, long position) {
RandomAccessFile file = null;
try {
file = new RandomAccessFile(path.toFile(), "rws");
FileChannel channel = file.getChannel();
// Try to acquire a lock
try (FileLock lock = channel.tryLock()) {
if (lock == null) {
System.out.println("Tried to lock through the FileChannel's lock() method. This file is already locked! It's my responsibility to not write to it, even if the OS would let me!");
} else {
System.out.println("I don't see a lock on this file anymore. Now I can write to it.");
int i = 0;
channel.write(
ByteBuffer.wrap((data).getBytes(StandardCharsets.UTF_8)), position);
}
} catch (Exception e) {
System.out.println("Error while locking");
e.printStackTrace();
}
} catch (Exception e) {
System.out.println("Other Error.");
e.printStackTrace();
}
return file;
}
}

View File

@ -0,0 +1,21 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_baeldung_lock_FileLocks */
#ifndef _Included_com_baeldung_lock_FileLocks
#define _Included_com_baeldung_lock_FileLocks
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_baeldung_lock_FileLocks
* Method: getpid
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_com_baeldung_lock_FileLocks_getpid
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif