1
18 package net.bull.javamelody.internal.model;
19
20 import java.io.File;
21 import java.io.IOException;
22 import java.io.RandomAccessFile;
23 import java.nio.channels.FileChannel;
24 import java.nio.channels.FileLock;
25 import java.nio.channels.OverlappingFileLockException;
26
27 import net.bull.javamelody.internal.common.Parameters;
28
29
33 class StorageLock {
34 private static final String LOCK_FILENAME = "javamelody.lock";
35 private final File lockFile;
36 private RandomAccessFile input;
37 private FileChannel fileChannel;
38 private FileLock fileLock;
39
40 StorageLock(String application) {
41 this(new File(Parameters.getStorageDirectory(application), LOCK_FILENAME));
42 }
43
44 StorageLock(File lockFile) {
45 super();
46 this.lockFile = lockFile;
47
48 getFileLock();
49 }
50
51 void release() throws IOException {
52 try {
53 if (fileLock != null && fileLock.isValid()) {
54 fileLock.release();
55 }
56 } finally {
57 try {
58 if (fileChannel != null) {
59 fileChannel.close();
60 }
61 } finally {
62 if (input != null) {
63 input.close();
64 }
65 }
66 }
67 }
68
69 private FileLock getFileLock() {
70 if (fileLock == null) {
71 try {
72 final File storageDir = lockFile.getParentFile();
73 if (!storageDir.mkdirs() && !storageDir.exists()) {
74 return null;
75 }
76 if (input == null || fileChannel == null) {
77 input = new RandomAccessFile(lockFile, "rw");
78 fileChannel = input.getChannel();
79 }
80 fileLock = fileChannel.tryLock();
81 } catch (final IOException | OverlappingFileLockException e) {
82 return null;
83 }
84 }
85 return fileLock;
86 }
87
88 boolean isAcquired() {
89 return getFileLock() != null && getFileLock().isValid();
90 }
91 }
92