mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-20 06:39:54 +01:00
Allow the code and the DB to have different but compatible schemas.
We check for compatibility by specifying a schema version and minimum schema version in the code, storing them in the DB, and checking whether the DB is too old for the code or vice versa.
This commit is contained in:
@@ -15,7 +15,7 @@
|
|||||||
<string name="passwords_do_not_match">Passwords do not match</string>
|
<string name="passwords_do_not_match">Passwords do not match</string>
|
||||||
<string name="enter_password">Enter your password:</string>
|
<string name="enter_password">Enter your password:</string>
|
||||||
<string name="try_again">Wrong password, try again:</string>
|
<string name="try_again">Wrong password, try again:</string>
|
||||||
<string name="startup_failed_notification_title">Briar could not start up</string>
|
<string name="startup_failed_notification_title">Briar could not start</string>
|
||||||
<string name="startup_failed_notification_text">You may need to reinstall Briar.</string>
|
<string name="startup_failed_notification_text">You may need to reinstall Briar.</string>
|
||||||
<string name="expiry_warning">This software has expired.\nPlease install a newer version.</string>
|
<string name="expiry_warning">This software has expired.\nPlease install a newer version.</string>
|
||||||
<string name="contact_list_button">Contacts</string>
|
<string name="contact_list_button">Contacts</string>
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
package org.briarproject.api.db;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Thrown when the schema of the database differs from the schema expected by
|
|
||||||
* the code.
|
|
||||||
*/
|
|
||||||
public class DbSchemaException extends DbException {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = -4444069279533651710L;
|
|
||||||
}
|
|
||||||
@@ -38,7 +38,6 @@ import org.briarproject.api.TransportId;
|
|||||||
import org.briarproject.api.TransportProperties;
|
import org.briarproject.api.TransportProperties;
|
||||||
import org.briarproject.api.db.DbClosedException;
|
import org.briarproject.api.db.DbClosedException;
|
||||||
import org.briarproject.api.db.DbException;
|
import org.briarproject.api.db.DbException;
|
||||||
import org.briarproject.api.db.DbSchemaException;
|
|
||||||
import org.briarproject.api.db.MessageHeader;
|
import org.briarproject.api.db.MessageHeader;
|
||||||
import org.briarproject.api.messaging.Group;
|
import org.briarproject.api.messaging.Group;
|
||||||
import org.briarproject.api.messaging.GroupId;
|
import org.briarproject.api.messaging.GroupId;
|
||||||
@@ -61,7 +60,8 @@ import org.briarproject.api.transport.TemporarySecret;
|
|||||||
*/
|
*/
|
||||||
abstract class JdbcDatabase implements Database<Connection> {
|
abstract class JdbcDatabase implements Database<Connection> {
|
||||||
|
|
||||||
private static final int SCHEMA_VERSION = 2;
|
private static final int SCHEMA_VERSION = 3;
|
||||||
|
private static final int MIN_SCHEMA_VERSION = 3;
|
||||||
|
|
||||||
private static final String CREATE_SETTINGS =
|
private static final String CREATE_SETTINGS =
|
||||||
"CREATE TABLE settings"
|
"CREATE TABLE settings"
|
||||||
@@ -372,11 +372,13 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
Connection txn = startTransaction();
|
Connection txn = startTransaction();
|
||||||
try {
|
try {
|
||||||
if(reopen) {
|
if(reopen) {
|
||||||
if(!checkSchemaVersion(txn))
|
if(!checkSchemaVersion(txn)) throw new DbException();
|
||||||
throw new DbSchemaException();
|
|
||||||
} else {
|
} else {
|
||||||
createTables(txn);
|
createTables(txn);
|
||||||
setSchemaVersion(txn);
|
String schemaVersion = String.valueOf(SCHEMA_VERSION);
|
||||||
|
setSetting(txn, "schemaVersion", schemaVersion);
|
||||||
|
String minSchemaVersion = String.valueOf(MIN_SCHEMA_VERSION);
|
||||||
|
setSetting(txn, "minSchemaVersion", minSchemaVersion);
|
||||||
}
|
}
|
||||||
commitTransaction(txn);
|
commitTransaction(txn);
|
||||||
} catch(DbException e) {
|
} catch(DbException e) {
|
||||||
@@ -386,27 +388,53 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkSchemaVersion(Connection txn) throws DbException {
|
private boolean checkSchemaVersion(Connection txn) throws DbException {
|
||||||
|
try {
|
||||||
|
String value = getSetting(txn, "schemaVersion");
|
||||||
|
int schemaVersion = Integer.valueOf(value);
|
||||||
|
if(schemaVersion == SCHEMA_VERSION) return true;
|
||||||
|
if(schemaVersion < MIN_SCHEMA_VERSION) return false;
|
||||||
|
value = getSetting(txn, "minSchemaVersion");
|
||||||
|
int minSchemaVersion = Integer.valueOf(value);
|
||||||
|
return SCHEMA_VERSION >= minSchemaVersion;
|
||||||
|
} catch(NumberFormatException e) {
|
||||||
|
throw new DbException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getSetting(Connection txn, String key) throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
String value;
|
|
||||||
try {
|
try {
|
||||||
String sql = "SELECT value FROM settings WHERE key = ?";
|
String sql = "SELECT value FROM settings WHERE key = ?";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setString(1, "schemaVersion");
|
ps.setString(1, key);
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
if(!rs.next()) throw new DbStateException();
|
if(!rs.next()) throw new DbStateException();
|
||||||
value = rs.getString(1);
|
String value = rs.getString(1);
|
||||||
if(rs.next()) throw new DbStateException();
|
if(rs.next()) throw new DbStateException();
|
||||||
rs.close();
|
rs.close();
|
||||||
ps.close();
|
ps.close();
|
||||||
|
return value;
|
||||||
} catch(SQLException e) {
|
} catch(SQLException e) {
|
||||||
tryToClose(rs);
|
tryToClose(rs);
|
||||||
tryToClose(ps);
|
tryToClose(ps);
|
||||||
throw new DbException(e);
|
throw new DbException(e);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setSetting(Connection txn, String key, String value)
|
||||||
|
throws DbException {
|
||||||
|
PreparedStatement ps = null;
|
||||||
try {
|
try {
|
||||||
return Integer.valueOf(value) == SCHEMA_VERSION;
|
String sql = "INSERT INTO settings (key, value) VALUES (?, ?)";
|
||||||
} catch(NumberFormatException e) {
|
ps = txn.prepareStatement(sql);
|
||||||
|
ps.setString(1, key);
|
||||||
|
ps.setString(2, value);
|
||||||
|
int affected = ps.executeUpdate();
|
||||||
|
if(affected < 1) throw new DbStateException();
|
||||||
|
ps.close();
|
||||||
|
} catch(SQLException e) {
|
||||||
|
tryToClose(ps);
|
||||||
throw new DbException(e);
|
throw new DbException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -469,22 +497,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setSchemaVersion(Connection txn) throws DbException {
|
|
||||||
PreparedStatement ps = null;
|
|
||||||
try {
|
|
||||||
String sql = "INSERT INTO settings (key, value) VALUES (?, ?)";
|
|
||||||
ps = txn.prepareStatement(sql);
|
|
||||||
ps.setString(1, "schemaVersion");
|
|
||||||
ps.setString(2, String.valueOf(SCHEMA_VERSION));
|
|
||||||
int affected = ps.executeUpdate();
|
|
||||||
if(affected != 1) throw new DbStateException();
|
|
||||||
ps.close();
|
|
||||||
} catch(SQLException e) {
|
|
||||||
tryToClose(ps);
|
|
||||||
throw new DbException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Connection startTransaction() throws DbException {
|
public Connection startTransaction() throws DbException {
|
||||||
Connection txn = null;
|
Connection txn = null;
|
||||||
synchronized(connections) {
|
synchronized(connections) {
|
||||||
|
|||||||
Reference in New Issue
Block a user