Add LocalDB Locking

FIxes #32
This commit is contained in:
Kai S. K. Engelbart 2020-09-19 15:28:04 +02:00
parent 1ccf4354aa
commit fd21c5789f
Signed by: kske
GPG Key ID: 8BEB13EC5DF7EF13
2 changed files with 33 additions and 4 deletions

View File

@ -1,11 +1,14 @@
package envoy.client.data; package envoy.client.data;
import java.io.*; import java.io.*;
import java.nio.channels.*;
import java.nio.file.StandardOpenOption;
import java.time.Instant; import java.time.Instant;
import java.util.*; import java.util.*;
import envoy.data.*; import envoy.data.*;
import envoy.event.*; import envoy.event.*;
import envoy.exception.EnvoyException;
import envoy.util.SerializationUtils; import envoy.util.SerializationUtils;
import dev.kske.eventbus.Event; import dev.kske.eventbus.Event;
@ -35,6 +38,7 @@ public final class LocalDB implements EventListener {
private Instant lastSync = Instant.EPOCH; private Instant lastSync = Instant.EPOCH;
private String authToken; private String authToken;
private File dbDir, userFile, idGeneratorFile, lastLoginFile, usersFile; private File dbDir, userFile, idGeneratorFile, lastLoginFile, usersFile;
private FileLock instanceLock;
/** /**
* Constructs an empty local database. To serialize any user-specific data to * Constructs an empty local database. To serialize any user-specific data to
@ -74,6 +78,28 @@ public final class LocalDB implements EventListener {
userFile = new File(dbDir, user.getID() + ".db"); userFile = new File(dbDir, user.getID() + ".db");
} }
FileChannel fc;
/**
* Ensured that only one Envoy instance is using this local database by creating
* a lock file.
* The lock file is deleted on application exit.
*
* @throws EnvoyException if the lock cannot by acquired
* @since Envoy Client v0.2-beta
*/
public void lock() throws EnvoyException {
File file = new File(dbDir, "instance.lock");
file.deleteOnExit();
try {
FileChannel fc = FileChannel.open(file.toPath(), StandardOpenOption.CREATE, StandardOpenOption.WRITE);
instanceLock = fc.tryLock();
if (instanceLock == null) throw new EnvoyException("Another Envoy instance is using this local database!");
} catch (IOException e) {
throw new EnvoyException("Could not create lock file!", e);
}
}
/** /**
* Stores all users. If the client user is specified, their chats will be stored * Stores all users. If the client user is specified, their chats will be stored
* as well. The message id generator will also be saved if present. * as well. The message id generator will also be saved if present.

View File

@ -67,10 +67,13 @@ public final class Startup extends Application {
// Initialize the local database // Initialize the local database
try { try {
localDB = new LocalDB(new File(config.getHomeDirectory(), config.getLocalDB().getPath())); File localDBDir = new File(config.getHomeDirectory(), config.getLocalDB().getPath());
} catch (final IOException e3) { logger.info("Initializing LocalDB at " + localDBDir);
logger.log(Level.SEVERE, "Could not initialize local database: ", e3); localDB = new LocalDB(localDBDir);
new Alert(AlertType.ERROR, "Could not initialize local database!\n" + e3).showAndWait(); localDB.lock();
} catch (IOException | EnvoyException e) {
logger.log(Level.SEVERE, "Could not initialize local database: ", e);
new Alert(AlertType.ERROR, "Could not initialize local database!\n" + e).showAndWait();
System.exit(1); System.exit(1);
return; return;
} }