|
9 | 9 | import java.nio.ByteBuffer; |
10 | 10 | import java.nio.channels.FileChannel; |
11 | 11 | import java.nio.channels.FileLock; |
| 12 | +import java.nio.channels.OverlappingFileLockException; |
12 | 13 | import java.nio.file.NoSuchFileException; |
13 | 14 | import java.nio.file.OpenOption; |
14 | 15 | import java.nio.file.attribute.FileAttribute; |
@@ -62,6 +63,14 @@ public synchronized boolean isLockFree(int id) { |
62 | 63 | // another process has an exclusive lock |
63 | 64 | return false; |
64 | 65 | } |
| 66 | + } catch (OverlappingFileLockException e) { |
| 67 | + // someone else (in the same JVM) has an exclusive lock |
| 68 | + /* |
| 69 | + * This shouldn't happen under normal circumstances, we have the singleton |
| 70 | + * {@link #locks} array to prevent overlapping locks from the same JVM, but |
| 71 | + * it can occur when there are multiple classloaders in the JVM |
| 72 | + */ |
| 73 | + return false; |
65 | 74 | } |
66 | 75 | } catch (NoSuchFileException e) { |
67 | 76 | // no lock file exists, nobody has the lock |
@@ -105,21 +114,32 @@ public synchronized boolean obtainLock(int id, String metaInfo) throws IOExcepti |
105 | 114 | private LockReference tryAcquireLockOnFile(int id, String metaInfo) throws IOException, ConcurrentLockFileDeletionException { |
106 | 115 | final File lockFile = toFile(id); |
107 | 116 | final FileChannel fileChannel = FileChannel.open(lockFile.toPath(), LOCK_FILE_OPEN_OPTIONS, LOCK_FILE_ATTRIBUTES); // NOSONAR |
108 | | - final FileLock fileLock = fileChannel.tryLock(0, Long.MAX_VALUE, false); |
109 | | - if (fileLock == null) { |
110 | | - // someone else has a lock (exclusive or shared), fail to acquire |
111 | | - closeQuietly(fileChannel); |
112 | | - return null; |
113 | | - } else { |
114 | | - if (!lockFile.exists()) { |
115 | | - // someone deleted the file between us opening it and acquiring the lock, signal to retry |
116 | | - closeQuietly(fileLock, fileChannel); |
117 | | - throw new ConcurrentLockFileDeletionException(); |
| 117 | + try { |
| 118 | + final FileLock fileLock = fileChannel.tryLock(0, Long.MAX_VALUE, false); |
| 119 | + if (fileLock == null) { |
| 120 | + // someone else has a lock (exclusive or shared), fail to acquire |
| 121 | + closeQuietly(fileChannel); |
| 122 | + return null; |
118 | 123 | } else { |
119 | | - // we have the lock, the file exists. That's success. |
120 | | - writeMetaInfoToFile(fileChannel, metaInfo); |
121 | | - return new LockReference(fileChannel, fileLock); |
| 124 | + if (!lockFile.exists()) { |
| 125 | + // someone deleted the file between us opening it and acquiring the lock, signal to retry |
| 126 | + closeQuietly(fileLock, fileChannel); |
| 127 | + throw new ConcurrentLockFileDeletionException(); |
| 128 | + } else { |
| 129 | + // we have the lock, the file exists. That's success. |
| 130 | + writeMetaInfoToFile(fileChannel, metaInfo); |
| 131 | + return new LockReference(fileChannel, fileLock); |
| 132 | + } |
122 | 133 | } |
| 134 | + } catch (OverlappingFileLockException e) { |
| 135 | + // someone else (in the same JVM) has a lock, fail to acquire |
| 136 | + /* |
| 137 | + * This shouldn't happen under normal circumstances, we have the singleton |
| 138 | + * {@link #locks} array to prevent overlapping locks from the same JVM, but |
| 139 | + * it can occur when there are multiple classloaders in the JVM |
| 140 | + */ |
| 141 | + closeQuietly(fileChannel); |
| 142 | + return null; |
123 | 143 | } |
124 | 144 | } |
125 | 145 |
|
|
0 commit comments