mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-19 14:19:53 +01:00
Basic connection window persistence.
This commit is contained in:
12
api/net/sf/briar/api/db/ConnectionWindow.java
Normal file
12
api/net/sf/briar/api/db/ConnectionWindow.java
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package net.sf.briar.api.db;
|
||||||
|
|
||||||
|
public interface ConnectionWindow {
|
||||||
|
|
||||||
|
long getCentre();
|
||||||
|
|
||||||
|
void setCentre(long centre);
|
||||||
|
|
||||||
|
int getBitmap();
|
||||||
|
|
||||||
|
void setBitmap(int bitmap);
|
||||||
|
}
|
||||||
30
components/net/sf/briar/db/ConnectionWindowImpl.java
Normal file
30
components/net/sf/briar/db/ConnectionWindowImpl.java
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package net.sf.briar.db;
|
||||||
|
|
||||||
|
import net.sf.briar.api.db.ConnectionWindow;
|
||||||
|
|
||||||
|
class ConnectionWindowImpl implements ConnectionWindow {
|
||||||
|
|
||||||
|
private long centre;
|
||||||
|
private int bitmap;
|
||||||
|
|
||||||
|
ConnectionWindowImpl(long centre, int bitmap) {
|
||||||
|
this.centre = centre;
|
||||||
|
this.bitmap = bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getCentre() {
|
||||||
|
return centre;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCentre(long centre) {
|
||||||
|
this.centre = centre;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBitmap() {
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBitmap(int bitmap) {
|
||||||
|
this.bitmap = bitmap;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
import net.sf.briar.api.ContactId;
|
import net.sf.briar.api.ContactId;
|
||||||
import net.sf.briar.api.Rating;
|
import net.sf.briar.api.Rating;
|
||||||
|
import net.sf.briar.api.db.ConnectionWindow;
|
||||||
import net.sf.briar.api.db.DbException;
|
import net.sf.briar.api.db.DbException;
|
||||||
import net.sf.briar.api.db.Status;
|
import net.sf.briar.api.db.Status;
|
||||||
import net.sf.briar.api.protocol.AuthorId;
|
import net.sf.briar.api.protocol.AuthorId;
|
||||||
@@ -155,6 +156,13 @@ interface Database<T> {
|
|||||||
*/
|
*/
|
||||||
Collection<BatchId> getBatchesToAck(T txn, ContactId c) throws DbException;
|
Collection<BatchId> getBatchesToAck(T txn, ContactId c) throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the connection reordering window for the given contact and
|
||||||
|
* transport.
|
||||||
|
*/
|
||||||
|
ConnectionWindow getConnectionWindow(T txn, ContactId c, int transport)
|
||||||
|
throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the IDs of all contacts.
|
* Returns the IDs of all contacts.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -371,6 +379,13 @@ interface Database<T> {
|
|||||||
*/
|
*/
|
||||||
void removeSubscription(T txn, GroupId g) throws DbException;
|
void removeSubscription(T txn, GroupId g) throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the connection reordering window for the given contact and
|
||||||
|
* transport.
|
||||||
|
*/
|
||||||
|
void setConnectionWindow(T txn, ContactId c, int transport,
|
||||||
|
ConnectionWindow w) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the user's rating for the given author.
|
* Sets the user's rating for the given author.
|
||||||
* <p>
|
* <p>
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class H2Database extends JdbcDatabase {
|
|||||||
@Inject
|
@Inject
|
||||||
H2Database(File dir, @DatabasePassword Password password, long maxSize,
|
H2Database(File dir, @DatabasePassword Password password, long maxSize,
|
||||||
GroupFactory groupFactory) {
|
GroupFactory groupFactory) {
|
||||||
super(groupFactory, "BINARY(32)", "BIGINT", "BINARY");
|
super(groupFactory, "BINARY(32)", "BINARY");
|
||||||
home = new File(dir, "db");
|
home = new File(dir, "db");
|
||||||
this.password = password;
|
this.password = password;
|
||||||
url = "jdbc:h2:split:" + home.getPath()
|
url = "jdbc:h2:split:" + home.getPath()
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
import net.sf.briar.api.ContactId;
|
import net.sf.briar.api.ContactId;
|
||||||
import net.sf.briar.api.Rating;
|
import net.sf.briar.api.Rating;
|
||||||
|
import net.sf.briar.api.db.ConnectionWindow;
|
||||||
import net.sf.briar.api.db.DatabaseComponent;
|
import net.sf.briar.api.db.DatabaseComponent;
|
||||||
import net.sf.briar.api.db.DbException;
|
import net.sf.briar.api.db.DbException;
|
||||||
import net.sf.briar.api.db.Status;
|
import net.sf.briar.api.db.Status;
|
||||||
@@ -43,7 +44,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
+ " (groupId HASH NOT NULL,"
|
+ " (groupId HASH NOT NULL,"
|
||||||
+ " groupName VARCHAR NOT NULL,"
|
+ " groupName VARCHAR NOT NULL,"
|
||||||
+ " groupKey BINARY,"
|
+ " groupKey BINARY,"
|
||||||
+ " start TIMESTAMP NOT NULL,"
|
+ " start BIGINT NOT NULL,"
|
||||||
+ " PRIMARY KEY (groupId))";
|
+ " PRIMARY KEY (groupId))";
|
||||||
|
|
||||||
private static final String CREATE_MESSAGES =
|
private static final String CREATE_MESSAGES =
|
||||||
@@ -52,7 +53,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
+ " parentId HASH NOT NULL,"
|
+ " parentId HASH NOT NULL,"
|
||||||
+ " groupId HASH NOT NULL,"
|
+ " groupId HASH NOT NULL,"
|
||||||
+ " authorId HASH NOT NULL,"
|
+ " authorId HASH NOT NULL,"
|
||||||
+ " timestamp TIMESTAMP NOT NULL,"
|
+ " timestamp BIGINT NOT NULL,"
|
||||||
+ " size INT NOT NULL,"
|
+ " size INT NOT NULL,"
|
||||||
+ " raw BLOB NOT NULL,"
|
+ " raw BLOB NOT NULL,"
|
||||||
+ " sendability INT NOT NULL,"
|
+ " sendability INT NOT NULL,"
|
||||||
@@ -66,7 +67,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
private static final String INDEX_MESSAGES_BY_AUTHOR =
|
private static final String INDEX_MESSAGES_BY_AUTHOR =
|
||||||
"CREATE INDEX messagesByAuthor ON messages (authorId)";
|
"CREATE INDEX messagesByAuthor ON messages (authorId)";
|
||||||
|
|
||||||
private static final String INDEX_MESSAGES_BY_TIMESTAMP =
|
private static final String INDEX_MESSAGES_BY_BIGINT =
|
||||||
"CREATE INDEX messagesByTimestamp ON messages (timestamp)";
|
"CREATE INDEX messagesByTimestamp ON messages (timestamp)";
|
||||||
|
|
||||||
private static final String INDEX_MESSAGES_BY_SENDABILITY =
|
private static final String INDEX_MESSAGES_BY_SENDABILITY =
|
||||||
@@ -75,8 +76,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
private static final String CREATE_CONTACTS =
|
private static final String CREATE_CONTACTS =
|
||||||
"CREATE TABLE contacts"
|
"CREATE TABLE contacts"
|
||||||
+ " (contactId INT NOT NULL,"
|
+ " (contactId INT NOT NULL,"
|
||||||
+ " subscriptionsTimestamp TIMESTAMP NOT NULL,"
|
+ " subscriptionsTimestamp BIGINT NOT NULL,"
|
||||||
+ " transportsTimestamp TIMESTAMP NOT NULL,"
|
+ " transportsTimestamp BIGINT NOT NULL,"
|
||||||
+ " PRIMARY KEY (contactId))";
|
+ " PRIMARY KEY (contactId))";
|
||||||
|
|
||||||
private static final String CREATE_VISIBILITIES =
|
private static final String CREATE_VISIBILITIES =
|
||||||
@@ -106,7 +107,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
+ " groupId HASH NOT NULL,"
|
+ " groupId HASH NOT NULL,"
|
||||||
+ " groupName VARCHAR NOT NULL,"
|
+ " groupName VARCHAR NOT NULL,"
|
||||||
+ " groupKey BINARY,"
|
+ " groupKey BINARY,"
|
||||||
+ " start TIMESTAMP NOT NULL,"
|
+ " start BIGINT NOT NULL,"
|
||||||
+ " PRIMARY KEY (contactId, groupId),"
|
+ " PRIMARY KEY (contactId, groupId),"
|
||||||
+ " FOREIGN KEY (contactId) REFERENCES contacts (contactId)"
|
+ " FOREIGN KEY (contactId) REFERENCES contacts (contactId)"
|
||||||
+ " ON DELETE CASCADE)";
|
+ " ON DELETE CASCADE)";
|
||||||
@@ -115,7 +116,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
"CREATE TABLE outstandingBatches"
|
"CREATE TABLE outstandingBatches"
|
||||||
+ " (batchId HASH NOT NULL,"
|
+ " (batchId HASH NOT NULL,"
|
||||||
+ " contactId INT NOT NULL,"
|
+ " contactId INT NOT NULL,"
|
||||||
+ " timestamp TIMESTAMP NOT NULL,"
|
+ " timestamp BIGINT NOT NULL,"
|
||||||
+ " passover INT NOT NULL,"
|
+ " passover INT NOT NULL,"
|
||||||
+ " PRIMARY KEY (batchId, contactId),"
|
+ " PRIMARY KEY (batchId, contactId),"
|
||||||
+ " FOREIGN KEY (contactId) REFERENCES contacts (contactId)"
|
+ " FOREIGN KEY (contactId) REFERENCES contacts (contactId)"
|
||||||
@@ -184,11 +185,21 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
+ " value VARCHAR NOT NULL,"
|
+ " value VARCHAR NOT NULL,"
|
||||||
+ " PRIMARY KEY (transportName, key))";
|
+ " PRIMARY KEY (transportName, key))";
|
||||||
|
|
||||||
|
private static final String CREATE_CONNECTION_WINDOWS =
|
||||||
|
"CREATE TABLE connectionWindows"
|
||||||
|
+ " (contactId INT NOT NULL,"
|
||||||
|
+ " transportId INT NOT NULL,"
|
||||||
|
+ " centre BIGINT NOT NULL,"
|
||||||
|
+ " bitmap INT NOT NULL,"
|
||||||
|
+ " PRIMARY KEY (contactId, transportId),"
|
||||||
|
+ " FOREIGN KEY (contactId) REFERENCES contacts (contactId)"
|
||||||
|
+ " ON DELETE CASCADE)";
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(JdbcDatabase.class.getName());
|
Logger.getLogger(JdbcDatabase.class.getName());
|
||||||
|
|
||||||
// Different database libraries use different names for certain types
|
// Different database libraries use different names for certain types
|
||||||
private final String hashType, timestampType, binaryType;
|
private final String hashType, binaryType;
|
||||||
private final GroupFactory groupFactory;
|
private final GroupFactory groupFactory;
|
||||||
private final LinkedList<Connection> connections =
|
private final LinkedList<Connection> connections =
|
||||||
new LinkedList<Connection>(); // Locking: self
|
new LinkedList<Connection>(); // Locking: self
|
||||||
@@ -199,10 +210,9 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
protected abstract Connection createConnection() throws SQLException;
|
protected abstract Connection createConnection() throws SQLException;
|
||||||
|
|
||||||
JdbcDatabase(GroupFactory groupFactory, String hashType,
|
JdbcDatabase(GroupFactory groupFactory, String hashType,
|
||||||
String timestampType, String binaryType) {
|
String binaryType) {
|
||||||
this.groupFactory = groupFactory;
|
this.groupFactory = groupFactory;
|
||||||
this.hashType = hashType;
|
this.hashType = hashType;
|
||||||
this.timestampType = timestampType;
|
|
||||||
this.binaryType = binaryType;
|
this.binaryType = binaryType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,7 +260,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
s.executeUpdate(insertTypeNames(CREATE_MESSAGES));
|
s.executeUpdate(insertTypeNames(CREATE_MESSAGES));
|
||||||
s.executeUpdate(INDEX_MESSAGES_BY_PARENT);
|
s.executeUpdate(INDEX_MESSAGES_BY_PARENT);
|
||||||
s.executeUpdate(INDEX_MESSAGES_BY_AUTHOR);
|
s.executeUpdate(INDEX_MESSAGES_BY_AUTHOR);
|
||||||
s.executeUpdate(INDEX_MESSAGES_BY_TIMESTAMP);
|
s.executeUpdate(INDEX_MESSAGES_BY_BIGINT);
|
||||||
s.executeUpdate(INDEX_MESSAGES_BY_SENDABILITY);
|
s.executeUpdate(INDEX_MESSAGES_BY_SENDABILITY);
|
||||||
s.executeUpdate(insertTypeNames(CREATE_CONTACTS));
|
s.executeUpdate(insertTypeNames(CREATE_CONTACTS));
|
||||||
s.executeUpdate(insertTypeNames(CREATE_VISIBILITIES));
|
s.executeUpdate(insertTypeNames(CREATE_VISIBILITIES));
|
||||||
@@ -267,6 +277,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
s.executeUpdate(insertTypeNames(CREATE_CONTACT_TRANSPORTS));
|
s.executeUpdate(insertTypeNames(CREATE_CONTACT_TRANSPORTS));
|
||||||
s.executeUpdate(insertTypeNames(CREATE_TRANSPORTS));
|
s.executeUpdate(insertTypeNames(CREATE_TRANSPORTS));
|
||||||
s.executeUpdate(insertTypeNames(CREATE_TRANSPORT_CONFIG));
|
s.executeUpdate(insertTypeNames(CREATE_TRANSPORT_CONFIG));
|
||||||
|
s.executeUpdate(insertTypeNames(CREATE_CONNECTION_WINDOWS));
|
||||||
s.close();
|
s.close();
|
||||||
} catch(SQLException e) {
|
} catch(SQLException e) {
|
||||||
tryToClose(s);
|
tryToClose(s);
|
||||||
@@ -276,7 +287,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
|
|
||||||
private String insertTypeNames(String s) {
|
private String insertTypeNames(String s) {
|
||||||
s = s.replaceAll("HASH", hashType);
|
s = s.replaceAll("HASH", hashType);
|
||||||
s = s.replaceAll("TIMESTAMP", timestampType);
|
|
||||||
s = s.replaceAll("BINARY", binaryType);
|
s = s.replaceAll("BINARY", binaryType);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@@ -392,19 +402,17 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try {
|
try {
|
||||||
String sql = "SELECT COUNT(batchId) FROM batchesToAck"
|
String sql = "SELECT NULL FROM batchesToAck"
|
||||||
+ " WHERE batchId = ? AND contactId = ?";
|
+ " WHERE batchId = ? AND contactId = ?";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setBytes(1, b.getBytes());
|
ps.setBytes(1, b.getBytes());
|
||||||
ps.setInt(2, c.getInt());
|
ps.setInt(2, c.getInt());
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
if(!rs.next()) throw new DbStateException();
|
boolean found = rs.next();
|
||||||
int count = rs.getInt(1);
|
|
||||||
if(count > 1) throw new DbStateException();
|
|
||||||
if(rs.next()) throw new DbStateException();
|
if(rs.next()) throw new DbStateException();
|
||||||
rs.close();
|
rs.close();
|
||||||
ps.close();
|
ps.close();
|
||||||
if(count == 1) return;
|
if(found) return;
|
||||||
sql = "INSERT INTO batchesToAck (batchId, contactId)"
|
sql = "INSERT INTO batchesToAck (batchId, contactId)"
|
||||||
+ " VALUES (?, ?)";
|
+ " VALUES (?, ?)";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
@@ -589,18 +597,15 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try {
|
try {
|
||||||
String sql = "SELECT COUNT(contactId) FROM contacts"
|
String sql = "SELECT NULL FROM contacts WHERE contactId = ?";
|
||||||
+ " WHERE contactId = ?";
|
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setInt(1, c.getInt());
|
ps.setInt(1, c.getInt());
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
if(!rs.next()) throw new DbStateException();
|
boolean found = rs.next();
|
||||||
int count = rs.getInt(1);
|
|
||||||
if(count > 1) throw new DbStateException();
|
|
||||||
if(rs.next()) throw new DbStateException();
|
if(rs.next()) throw new DbStateException();
|
||||||
rs.close();
|
rs.close();
|
||||||
ps.close();
|
ps.close();
|
||||||
return count > 0;
|
return found;
|
||||||
} catch(SQLException e) {
|
} catch(SQLException e) {
|
||||||
tryToClose(rs);
|
tryToClose(rs);
|
||||||
tryToClose(ps);
|
tryToClose(ps);
|
||||||
@@ -613,18 +618,15 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try {
|
try {
|
||||||
String sql = "SELECT COUNT(messageId) FROM messages"
|
String sql = "SELECT NULL FROM messages WHERE messageId = ?";
|
||||||
+ " WHERE messageId = ?";
|
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setBytes(1, m.getBytes());
|
ps.setBytes(1, m.getBytes());
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
if(!rs.next()) throw new DbStateException();
|
boolean found = rs.next();
|
||||||
int count = rs.getInt(1);
|
|
||||||
if(count > 1) throw new DbStateException();
|
|
||||||
if(rs.next()) throw new DbStateException();
|
if(rs.next()) throw new DbStateException();
|
||||||
rs.close();
|
rs.close();
|
||||||
ps.close();
|
ps.close();
|
||||||
return count > 0;
|
return found;
|
||||||
} catch(SQLException e) {
|
} catch(SQLException e) {
|
||||||
tryToClose(rs);
|
tryToClose(rs);
|
||||||
tryToClose(ps);
|
tryToClose(ps);
|
||||||
@@ -637,18 +639,15 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try {
|
try {
|
||||||
String sql = "SELECT COUNT(groupId) FROM subscriptions"
|
String sql = "SELECT NULL FROM subscriptions WHERE groupId = ?";
|
||||||
+ " WHERE groupId = ?";
|
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setBytes(1, g.getBytes());
|
ps.setBytes(1, g.getBytes());
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
if(!rs.next()) throw new DbStateException();
|
boolean found = rs.next();
|
||||||
int count = rs.getInt(1);
|
|
||||||
if(count > 1) throw new DbStateException();
|
|
||||||
if(rs.next()) throw new DbStateException();
|
if(rs.next()) throw new DbStateException();
|
||||||
rs.close();
|
rs.close();
|
||||||
ps.close();
|
ps.close();
|
||||||
return count > 0;
|
return found;
|
||||||
} catch(SQLException e) {
|
} catch(SQLException e) {
|
||||||
tryToClose(rs);
|
tryToClose(rs);
|
||||||
tryToClose(ps);
|
tryToClose(ps);
|
||||||
@@ -731,7 +730,36 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<ContactId> getContacts(Connection txn) throws DbException {
|
public ConnectionWindow getConnectionWindow(Connection txn, ContactId c,
|
||||||
|
int transport) throws DbException {
|
||||||
|
PreparedStatement ps = null;
|
||||||
|
ResultSet rs = null;
|
||||||
|
try {
|
||||||
|
String sql = "SELECT centre, bitmap FROM connectionWindows"
|
||||||
|
+ " WHERE contactId = ? AND transportId = ?";
|
||||||
|
ps = txn.prepareStatement(sql);
|
||||||
|
ps.setInt(1, c.getInt());
|
||||||
|
ps.setInt(2, transport);
|
||||||
|
rs = ps.executeQuery();
|
||||||
|
long centre = 0L;
|
||||||
|
int bitmap = 0;
|
||||||
|
if(rs.next()) {
|
||||||
|
centre = rs.getLong(1);
|
||||||
|
bitmap = rs.getInt(2);
|
||||||
|
if(rs.next()) throw new DbStateException();
|
||||||
|
}
|
||||||
|
rs.close();
|
||||||
|
ps.close();
|
||||||
|
return new ConnectionWindowImpl(centre, bitmap);
|
||||||
|
} catch(SQLException e) {
|
||||||
|
tryToClose(rs);
|
||||||
|
tryToClose(ps);
|
||||||
|
throw new DbException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<ContactId> getContacts(Connection txn)
|
||||||
|
throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try {
|
try {
|
||||||
@@ -1496,6 +1524,48 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setConnectionWindow(Connection txn, ContactId c, int transport,
|
||||||
|
ConnectionWindow w) throws DbException {
|
||||||
|
PreparedStatement ps = null;
|
||||||
|
ResultSet rs = null;
|
||||||
|
try {
|
||||||
|
String sql = "SELECT NULL FROM connectionWindows"
|
||||||
|
+ " WHERE contactId = ? AND transportId = ?";
|
||||||
|
ps = txn.prepareStatement(sql);
|
||||||
|
ps.setInt(1, c.getInt());
|
||||||
|
ps.setInt(2, transport);
|
||||||
|
rs = ps.executeQuery();
|
||||||
|
if(rs.next()) {
|
||||||
|
if(rs.next()) throw new DbStateException();
|
||||||
|
rs.close();
|
||||||
|
ps.close();
|
||||||
|
sql = "UPDATE connectionWindows SET centre = ?, bitmap = ?"
|
||||||
|
+ " WHERE contactId = ? AND transportId = ?";
|
||||||
|
ps = txn.prepareStatement(sql);
|
||||||
|
int affected = ps.executeUpdate();
|
||||||
|
if(affected != 1) throw new DbStateException();
|
||||||
|
} else {
|
||||||
|
rs.close();
|
||||||
|
ps.close();
|
||||||
|
sql = "INSERT INTO connectionWindows"
|
||||||
|
+ " (contactId, transportId, centre, bitmap)"
|
||||||
|
+ " VALUES(?, ?, ?, ?)";
|
||||||
|
ps = txn.prepareStatement(sql);
|
||||||
|
ps.setInt(1, c.getInt());
|
||||||
|
ps.setInt(2, transport);
|
||||||
|
ps.setLong(3, w.getCentre());
|
||||||
|
ps.setInt(4, w.getBitmap());
|
||||||
|
int affected = ps.executeUpdate();
|
||||||
|
if(affected != 1) throw new DbStateException();
|
||||||
|
}
|
||||||
|
ps.close();
|
||||||
|
} catch(SQLException e) {
|
||||||
|
tryToClose(rs);
|
||||||
|
tryToClose(ps);
|
||||||
|
throw new DbException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Rating setRating(Connection txn, AuthorId a, Rating r)
|
public Rating setRating(Connection txn, AuthorId a, Rating r)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
@@ -1608,7 +1678,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try {
|
try {
|
||||||
String sql = "SELECT COUNT(messages.messageId) FROM messages"
|
String sql = "SELECT NULL FROM messages"
|
||||||
+ " JOIN contactSubscriptions"
|
+ " JOIN contactSubscriptions"
|
||||||
+ " ON messages.groupId = contactSubscriptions.groupId"
|
+ " ON messages.groupId = contactSubscriptions.groupId"
|
||||||
+ " JOIN visibilities"
|
+ " JOIN visibilities"
|
||||||
@@ -1621,13 +1691,11 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
ps.setInt(2, c.getInt());
|
ps.setInt(2, c.getInt());
|
||||||
ps.setInt(3, c.getInt());
|
ps.setInt(3, c.getInt());
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
if(!rs.next()) throw new DbStateException();
|
boolean found = rs.next();
|
||||||
int count = rs.getInt(1);
|
|
||||||
if(count > 1) throw new DbStateException();
|
|
||||||
if(rs.next()) throw new DbStateException();
|
if(rs.next()) throw new DbStateException();
|
||||||
rs.close();
|
rs.close();
|
||||||
ps.close();
|
ps.close();
|
||||||
if(count == 0) return false;
|
if(!found) return false;
|
||||||
sql = "UPDATE statuses SET status = ?"
|
sql = "UPDATE statuses SET status = ?"
|
||||||
+ " WHERE messageId = ? AND contactId = ?";
|
+ " WHERE messageId = ? AND contactId = ?";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import net.sf.briar.TestUtils;
|
|||||||
import net.sf.briar.api.ContactId;
|
import net.sf.briar.api.ContactId;
|
||||||
import net.sf.briar.api.Rating;
|
import net.sf.briar.api.Rating;
|
||||||
import net.sf.briar.api.crypto.Password;
|
import net.sf.briar.api.crypto.Password;
|
||||||
|
import net.sf.briar.api.db.ConnectionWindow;
|
||||||
import net.sf.briar.api.db.DbException;
|
import net.sf.briar.api.db.DbException;
|
||||||
import net.sf.briar.api.db.Status;
|
import net.sf.briar.api.db.Status;
|
||||||
import net.sf.briar.api.protocol.AuthorId;
|
import net.sf.briar.api.protocol.AuthorId;
|
||||||
@@ -1204,6 +1205,61 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
// Make the group invisible again
|
// Make the group invisible again
|
||||||
db.setVisibility(txn, groupId, Collections.<ContactId>emptySet());
|
db.setVisibility(txn, groupId, Collections.<ContactId>emptySet());
|
||||||
assertEquals(Collections.emptyList(), db.getVisibility(txn, groupId));
|
assertEquals(Collections.emptyList(), db.getVisibility(txn, groupId));
|
||||||
|
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
db.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGettingUnknownConnectionWindowReturnsDefault()
|
||||||
|
throws DbException {
|
||||||
|
Database<Connection> db = open(false);
|
||||||
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
|
// Add a contact
|
||||||
|
assertEquals(contactId, db.addContact(txn, transports));
|
||||||
|
|
||||||
|
// Get the connection window for a new transport
|
||||||
|
ConnectionWindow w = db.getConnectionWindow(txn, contactId, 123);
|
||||||
|
|
||||||
|
// The connection window should exist and be in the initial state
|
||||||
|
assertNotNull(w);
|
||||||
|
assertEquals(0L, w.getCentre());
|
||||||
|
assertEquals(0, w.getBitmap());
|
||||||
|
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
db.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testConnectionWindow() throws DbException {
|
||||||
|
Database<Connection> db = open(false);
|
||||||
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
|
// Add a contact
|
||||||
|
assertEquals(contactId, db.addContact(txn, transports));
|
||||||
|
|
||||||
|
// Get the connection window for a new transport
|
||||||
|
ConnectionWindow w = db.getConnectionWindow(txn, contactId, 123);
|
||||||
|
|
||||||
|
// The connection window should exist and be in the initial state
|
||||||
|
assertNotNull(w);
|
||||||
|
assertEquals(0L, w.getCentre());
|
||||||
|
assertEquals(0, w.getBitmap());
|
||||||
|
|
||||||
|
// Update the connection window and store it
|
||||||
|
w.setCentre(1);
|
||||||
|
w.setBitmap(0x00008000);
|
||||||
|
db.setConnectionWindow(txn, contactId, 123, w);
|
||||||
|
|
||||||
|
// Check that the connection window was stored
|
||||||
|
w = db.getConnectionWindow(txn, contactId, 123);
|
||||||
|
assertNotNull(w);
|
||||||
|
assertEquals(1L, w.getCentre());
|
||||||
|
assertEquals(0x00008000, w.getBitmap());
|
||||||
|
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
db.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user