aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Tananaev <anton@traccar.org>2024-04-27 07:46:24 -0700
committerAnton Tananaev <anton@traccar.org>2024-04-27 07:46:24 -0700
commit8da81efe902ceb9a106dff15ce44638c6be1eecc (patch)
treecaf73fa775dda8ba7f6a1d8d68f41b4ae8ad7ffb
parent3b739942dafea3c9d2bb3f061fb6ee98a33c747a (diff)
downloadtrackermap-server-8da81efe902ceb9a106dff15ce44638c6be1eecc.tar.gz
trackermap-server-8da81efe902ceb9a106dff15ce44638c6be1eecc.tar.bz2
trackermap-server-8da81efe902ceb9a106dff15ce44638c6be1eecc.zip
Better DB lock error message
-rw-r--r--src/main/java/org/traccar/Main.java11
-rw-r--r--src/main/java/org/traccar/storage/DatabaseModule.java35
2 files changed, 35 insertions, 11 deletions
diff --git a/src/main/java/org/traccar/Main.java b/src/main/java/org/traccar/Main.java
index 33fcf654f..943b5bd7d 100644
--- a/src/main/java/org/traccar/Main.java
+++ b/src/main/java/org/traccar/Main.java
@@ -17,6 +17,7 @@ package org.traccar;
import com.google.inject.Guice;
import com.google.inject.Injector;
+import com.google.inject.ProvisionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.traccar.broadcast.BroadcastService;
@@ -142,8 +143,14 @@ public final class Main {
}
}));
} catch (Exception e) {
- LOGGER.error("Main method error", e);
- throw new RuntimeException(e);
+ Throwable unwrapped;
+ if (e instanceof ProvisionException) {
+ unwrapped = e.getCause();
+ } else {
+ unwrapped = e;
+ }
+ LOGGER.error("Main method error", unwrapped);
+ System.exit(1);
}
}
diff --git a/src/main/java/org/traccar/storage/DatabaseModule.java b/src/main/java/org/traccar/storage/DatabaseModule.java
index 9898a2fca..86e5267d4 100644
--- a/src/main/java/org/traccar/storage/DatabaseModule.java
+++ b/src/main/java/org/traccar/storage/DatabaseModule.java
@@ -20,10 +20,12 @@ import com.google.inject.Provides;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import liquibase.Contexts;
+import liquibase.GlobalConfiguration;
import liquibase.Liquibase;
import liquibase.database.Database;
import liquibase.database.DatabaseFactory;
import liquibase.exception.LiquibaseException;
+import liquibase.exception.LockException;
import liquibase.resource.DirectoryResourceAccessor;
import liquibase.resource.ResourceAccessor;
import org.traccar.config.Config;
@@ -83,16 +85,22 @@ public class DatabaseModule extends AbstractModule {
ResourceAccessor resourceAccessor = new DirectoryResourceAccessor(new File("."));
- Database database = DatabaseFactory.getInstance().openDatabase(
- config.getString(Keys.DATABASE_URL),
- config.getString(Keys.DATABASE_USER),
- config.getString(Keys.DATABASE_PASSWORD),
- config.getString(Keys.DATABASE_DRIVER),
- null, null, null, resourceAccessor);
+ System.setProperty("liquibase.changelogLockWaitTimeInMinutes", "1");
- try (Liquibase liquibase = new Liquibase(changelog, resourceAccessor, database)) {
- liquibase.clearCheckSums();
- liquibase.update(new Contexts());
+ try {
+ Database database = DatabaseFactory.getInstance().openDatabase(
+ config.getString(Keys.DATABASE_URL),
+ config.getString(Keys.DATABASE_USER),
+ config.getString(Keys.DATABASE_PASSWORD),
+ config.getString(Keys.DATABASE_DRIVER),
+ null, null, null, resourceAccessor);
+
+ try (Liquibase liquibase = new Liquibase(changelog, resourceAccessor, database)) {
+ liquibase.clearCheckSums();
+ liquibase.update(new Contexts());
+ }
+ } catch (LockException e) {
+ throw new DatabaseLockException();
}
}
@@ -100,3 +108,12 @@ public class DatabaseModule extends AbstractModule {
}
}
+
+class DatabaseLockException extends RuntimeException {
+ DatabaseLockException() {
+ super("Database is in a locked state. "
+ + "It could be due to early service termination on a previous launch. "
+ + "To unlock you can run this query: 'UPDATE DATABASECHANGELOGLOCK SET locked = 0'. "
+ + "Make sure the schema is up to date before unlocking the database.");
+ }
+}