Extra Database base class from AccountDatabase

This commit is contained in:
AsamK 2022-02-06 13:01:35 +01:00
parent b9f66248ac
commit 3040da99c4
3 changed files with 73 additions and 38 deletions

View file

@ -0,0 +1,33 @@
package org.asamk.signal.manager.storage;
import com.zaxxer.hikari.HikariDataSource;
import org.asamk.signal.manager.storage.sendLog.MessageSendLogStore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.sql.Connection;
import java.sql.SQLException;
public class AccountDatabase extends Database {
private final static Logger logger = LoggerFactory.getLogger(AccountDatabase.class);
private static final long DATABASE_VERSION = 1;
private AccountDatabase(final HikariDataSource dataSource) {
super(logger, DATABASE_VERSION, dataSource);
}
public static AccountDatabase init(File databaseFile) throws SQLException {
return initDatabase(databaseFile, AccountDatabase::new);
}
@Override
protected void upgradeDatabase(final Connection connection, final long oldVersion) throws SQLException {
if (oldVersion < 1) {
logger.debug("Updating database: Creating message send log tables");
MessageSendLogStore.createSql(connection);
}
}
}

View file

@ -3,53 +3,38 @@ package org.asamk.signal.manager.storage;
import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource; import com.zaxxer.hikari.HikariDataSource;
import org.asamk.signal.manager.storage.sendLog.MessageSendLogStore;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sqlite.SQLiteConfig; import org.sqlite.SQLiteConfig;
import java.io.File; import java.io.File;
import java.sql.Connection; import java.sql.Connection;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.function.Function;
public class Database implements AutoCloseable { public abstract class Database implements AutoCloseable {
private final static Logger logger = LoggerFactory.getLogger(SignalAccount.class);
private static final long DATABASE_VERSION = 1;
private final Logger logger;
private final long databaseVersion;
private final HikariDataSource dataSource; private final HikariDataSource dataSource;
private Database(final HikariDataSource dataSource) { protected Database(final Logger logger, final long databaseVersion, final HikariDataSource dataSource) {
this.logger = logger;
this.databaseVersion = databaseVersion;
this.dataSource = dataSource; this.dataSource = dataSource;
} }
public static Database init(File databaseFile) throws SQLException { public static <T extends Database> T initDatabase(
File databaseFile, Function<HikariDataSource, T> newDatabase
) throws SQLException {
HikariDataSource dataSource = null; HikariDataSource dataSource = null;
try { try {
dataSource = getHikariDataSource(databaseFile.getAbsolutePath()); dataSource = getHikariDataSource(databaseFile.getAbsolutePath());
try (final var connection = dataSource.getConnection()) { final var result = newDatabase.apply(dataSource);
final var userVersion = getUserVersion(connection); result.initDb();
logger.trace("Current database version: {} Program database version: {}",
userVersion,
DATABASE_VERSION);
if (userVersion > DATABASE_VERSION) {
logger.error("Database has been updated by a newer signal-cli version");
throw new SQLException("Database has been updated by a newer signal-cli version");
} else if (userVersion < DATABASE_VERSION) {
if (userVersion < 1) {
logger.debug("Updating database: Creating message send log tables");
MessageSendLogStore.createSql(connection);
}
setUserVersion(connection, DATABASE_VERSION);
}
final var result = new Database(dataSource);
dataSource = null; dataSource = null;
return result; return result;
}
} finally { } finally {
if (dataSource != null) { if (dataSource != null) {
dataSource.close(); dataSource.close();
@ -57,7 +42,7 @@ public class Database implements AutoCloseable {
} }
} }
public Connection getConnection() throws SQLException { public final Connection getConnection() throws SQLException {
return dataSource.getConnection(); return dataSource.getConnection();
} }
@ -66,6 +51,23 @@ public class Database implements AutoCloseable {
dataSource.close(); dataSource.close();
} }
protected final void initDb() throws SQLException {
try (final var connection = dataSource.getConnection()) {
final var userVersion = getUserVersion(connection);
logger.trace("Current database version: {} Program database version: {}", userVersion, databaseVersion);
if (userVersion > databaseVersion) {
logger.error("Database has been updated by a newer signal-cli version");
throw new SQLException("Database has been updated by a newer signal-cli version");
} else if (userVersion < databaseVersion) {
upgradeDatabase(connection, userVersion);
setUserVersion(connection, databaseVersion);
}
}
}
protected abstract void upgradeDatabase(final Connection connection, long oldVersion) throws SQLException;
private static long getUserVersion(final Connection connection) throws SQLException { private static long getUserVersion(final Connection connection) throws SQLException {
try (final var statement = connection.createStatement()) { try (final var statement = connection.createStatement()) {
final var resultSet = statement.executeQuery("PRAGMA user_version"); final var resultSet = statement.executeQuery("PRAGMA user_version");

View file

@ -124,7 +124,7 @@ public class SignalAccount implements Closeable {
private MessageCache messageCache; private MessageCache messageCache;
private MessageSendLogStore messageSendLogStore; private MessageSendLogStore messageSendLogStore;
private Database database; private AccountDatabase accountDatabase;
private SignalAccount(final FileChannel fileChannel, final FileLock lock) { private SignalAccount(final FileChannel fileChannel, final FileLock lock) {
this.fileChannel = fileChannel; this.fileChannel = fileChannel;
@ -233,7 +233,7 @@ public class SignalAccount implements Closeable {
} }
public void initDatabase() { public void initDatabase() {
getDatabase(); getAccountDatabase();
} }
private void clearAllPreKeys() { private void clearAllPreKeys() {
@ -882,10 +882,10 @@ public class SignalAccount implements Closeable {
() -> messageCache = new MessageCache(getMessageCachePath(dataPath, account))); () -> messageCache = new MessageCache(getMessageCachePath(dataPath, account)));
} }
public Database getDatabase() { public AccountDatabase getAccountDatabase() {
return getOrCreate(() -> database, () -> { return getOrCreate(() -> accountDatabase, () -> {
try { try {
database = Database.init(getDatabaseFile(dataPath, account)); accountDatabase = AccountDatabase.init(getDatabaseFile(dataPath, account));
} catch (SQLException e) { } catch (SQLException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@ -894,7 +894,7 @@ public class SignalAccount implements Closeable {
public MessageSendLogStore getMessageSendLogStore() { public MessageSendLogStore getMessageSendLogStore() {
return getOrCreate(() -> messageSendLogStore, return getOrCreate(() -> messageSendLogStore,
() -> messageSendLogStore = new MessageSendLogStore(getRecipientStore(), getDatabase())); () -> messageSendLogStore = new MessageSendLogStore(getRecipientStore(), getAccountDatabase()));
} }
public String getAccount() { public String getAccount() {
@ -1081,9 +1081,9 @@ public class SignalAccount implements Closeable {
@Override @Override
public void close() { public void close() {
synchronized (fileChannel) { synchronized (fileChannel) {
if (database != null) { if (accountDatabase != null) {
try { try {
database.close(); accountDatabase.close();
} catch (SQLException e) { } catch (SQLException e) {
logger.warn("Failed to close account database: {}", e.getMessage(), e); logger.warn("Failed to close account database: {}", e.getMessage(), e);
} }