For reasons that I will not explain (because people will direct their responses at the other topic, instead of my problem at hand), I need to know how to determine whether or not my H2 database is locked. Using Java code, how do I determine whether or not the lock file exists on my database?
1 Answers
For others reading this question I need to explain why you you shouldn't do it yourself, and let the database detect itself whether it is locked or not. First of all, database file locking is an implementation detail that can and will change in future versions of the database. Then, there is a race condition: if you see the lock doesn't exist now, it may exist one second later. So the only reliable way is to try locking. So: try opening the database in read-write mode. Disadvantage: it is a bit slow, as it will initialize the database and also run the recovery code if needed. I understand this is not what you want, because it is slow (right?).
For lower level method, it depends which version of H2 you use.
Version 1.4 (currently beta)
Try locking the file itself using the following code:
static boolean isLocked(String fileName) {
try {
RandomAccessFile f = new RandomAccessFile(fileName, "r");
try {
FileLock lock = f.getChannel().tryLock(0, Long.MAX_VALUE, true);
if (lock != null) {
lock.release();
return false;
}
} finally {
f.close();
}
} catch (IOException e) {
// ignore
}
return true;
}
Or using H2 code (from the MVStore):
static boolean isLocked(String fileName) {
FileStore fs = new FileStore();
try {
fs.open(fileName, true, null);
return false;
} catch (IllegalStateException e) {
return true;
} finally {
fs.close();
}
}
Version 1.3 (stable) and 1.4 with the MVStore disabled
Simply checking if the file <databaseName>.lock.db
exists is not enough. It might exist even the database is not open, in case the process was killed. So some sample code (not tested) is:
// file name must be:
// path + databaseName + Constants.SUFFIX_LOCK_FILE
static boolean isLocked(String fileName) {
try {
FileLock lock = new FileLock(new TraceSystem(null), fileName, 1000);
lock.lock(FileLock.LOCK_FILE);
lock.unlock();
return false;
} catch (Exception e) {
return true;
}
}

- 48,905
- 14
- 116
- 132
-
Thomas, CORRECT code for "Version 1.3 (stable) and 1.4 with the MVStore disabled" is: FileLock lock=new FileLock(new TraceSystem(null), fileName, 1000); (the TRACE Object must exist or it will throw a NullPointer in public Properties load()). Using h2-1.3.176. – marcolopes Nov 22 '14 at 06:08
-
Sometimes after lock.unlock() the LOCK file still remains (it's not deleted). On fast machines i need to increase the "sleep" parameter value of the new FileLock method. Can you explain why?? I look at the code of the unlock and the file should NOT exist upon method exit! Something to do with the watchdog created over the file? I'm confused... i opted to keep the sleep at ZERO and created a loop to try to delete the file after the UNLOCK... – marcolopes Sep 20 '17 at 04:59
-
@marcolopes I think you refer to the the
.lock.db file. Even if the file exists after unlock, it shouldn't be a big problem, as the same happens on a process kill or power failure. The startup code can deal with that. – Thomas Mueller Sep 20 '17 at 07:41 -
Yes... but the problem is i have code that makes a manual backup of the database (i copy the local file and ZIP it... cannot use the H2 backup process because it FAILS on MAC - problem reported on forum). So, to avoid making a backup of an OPEN database, i check the existence of a LOCK using the code you provided here (H2 1.3). I use the LOCK_SOCKET method to check the lock (because it might be opened through the network) and if this lock file remains, i get an error opening the database with LOCK_FILE! What do you recommend? Should i check the lock with LOCK_FILE? – marcolopes Sep 20 '17 at 18:42