mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-15 20:29:52 +01:00
Code and API cleanup for the database component.
This commit is contained in:
@@ -256,15 +256,6 @@ interface Database<T> {
|
|||||||
*/
|
*/
|
||||||
Collection<Transport> getLocalTransports(T txn) throws DbException;
|
Collection<Transport> getLocalTransports(T txn) throws DbException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the IDs of any messages sent to the given contact that should
|
|
||||||
* now be considered lost.
|
|
||||||
* <p>
|
|
||||||
* Locking: contact read, message read, messageStatus read.
|
|
||||||
*/
|
|
||||||
Collection<MessageId> getLostMessages(T txn, ContactId c)
|
|
||||||
throws DbException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the message identified by the given ID, in serialised form.
|
* Returns the message identified by the given ID, in serialised form.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -307,14 +298,24 @@ interface Database<T> {
|
|||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the IDs of any messages received from the given contact that
|
* Returns the IDs of some messages received from the given contact that
|
||||||
* need to be acknowledged.
|
* need to be acknowledged, up to the given number of messages.
|
||||||
* <p>
|
* <p>
|
||||||
* Locking: contact read, messageStatus read.
|
* Locking: contact read, messageStatus read.
|
||||||
*/
|
*/
|
||||||
Collection<MessageId> getMessagesToAck(T txn, ContactId c, int maxMessages)
|
Collection<MessageId> getMessagesToAck(T txn, ContactId c, int maxMessages)
|
||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the IDs of some messages that are eligible to be sent to the
|
||||||
|
* given contact, up to the given number of messages.
|
||||||
|
* <p>
|
||||||
|
* Locking: contact read, message read, messageStatus read,
|
||||||
|
* subscription read.
|
||||||
|
*/
|
||||||
|
Collection<MessageId> getMessagesToOffer(T txn, ContactId c,
|
||||||
|
int maxMessages) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of children of the message identified by the given
|
* Returns the number of children of the message identified by the given
|
||||||
* ID that are present in the database and have sendability scores greater
|
* ID that are present in the database and have sendability scores greater
|
||||||
@@ -324,16 +325,6 @@ interface Database<T> {
|
|||||||
*/
|
*/
|
||||||
int getNumberOfSendableChildren(T txn, MessageId m) throws DbException;
|
int getNumberOfSendableChildren(T txn, MessageId m) throws DbException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the IDs of some messages that are eligible to be sent to the
|
|
||||||
* given contact, up to the given number of messages.
|
|
||||||
* <p>
|
|
||||||
* Locking: contact read, message read, messageStatus read,
|
|
||||||
* subscription read.
|
|
||||||
*/
|
|
||||||
Collection<MessageId> getOfferableMessages(T txn, ContactId c,
|
|
||||||
int maxMessages) throws DbException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the IDs of the oldest messages in the database, with a total
|
* Returns the IDs of the oldest messages in the database, with a total
|
||||||
* size less than or equal to the given size.
|
* size less than or equal to the given size.
|
||||||
@@ -354,7 +345,7 @@ interface Database<T> {
|
|||||||
* <p>
|
* <p>
|
||||||
* Locking: message read, messageFlag read.
|
* Locking: message read, messageFlag read.
|
||||||
*/
|
*/
|
||||||
boolean getRead(T txn, MessageId m) throws DbException;
|
boolean getReadFlag(T txn, MessageId m) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all remote properties for the given transport.
|
* Returns all remote properties for the given transport.
|
||||||
@@ -394,7 +385,7 @@ interface Database<T> {
|
|||||||
* <p>
|
* <p>
|
||||||
* Locking: message read, messageFlag read.
|
* Locking: message read, messageFlag read.
|
||||||
*/
|
*/
|
||||||
boolean getStarred(T txn, MessageId m) throws DbException;
|
boolean getStarredFlag(T txn, MessageId m) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the groups to which the user subscribes.
|
* Returns the groups to which the user subscribes.
|
||||||
@@ -500,8 +491,8 @@ interface Database<T> {
|
|||||||
* <p>
|
* <p>
|
||||||
* Locking: contact read, message read, messageStatus write.
|
* Locking: contact read, message read, messageStatus write.
|
||||||
*/
|
*/
|
||||||
void removeAckedMessages(T txn, ContactId c, Collection<MessageId> acked)
|
void removeOutstandingMessages(T txn, ContactId c,
|
||||||
throws DbException;
|
Collection<MessageId> acked) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks the given messages received from the given contact as having been
|
* Marks the given messages received from the given contact as having been
|
||||||
@@ -520,16 +511,6 @@ interface Database<T> {
|
|||||||
*/
|
*/
|
||||||
void removeContact(T txn, ContactId c) throws DbException;
|
void removeContact(T txn, ContactId c) throws DbException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes outstanding messages that have been lost. Any messages that are
|
|
||||||
* still considered outstanding (Status.SENT) with respect to the given
|
|
||||||
* contact are now considered unsent (Status.NEW).
|
|
||||||
* <p>
|
|
||||||
* Locking: contact read, message read, messageStatus write.
|
|
||||||
*/
|
|
||||||
void removeLostMessages(T txn, ContactId c, Collection<MessageId> lost)
|
|
||||||
throws DbException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a message (and all associated state) from the database.
|
* Removes a message (and all associated state) from the database.
|
||||||
* <p>
|
* <p>
|
||||||
|
|||||||
@@ -612,7 +612,7 @@ DatabaseCleaner.Callback {
|
|||||||
try {
|
try {
|
||||||
if(!db.containsContact(txn, c))
|
if(!db.containsContact(txn, c))
|
||||||
throw new NoSuchContactException();
|
throw new NoSuchContactException();
|
||||||
offered = db.getOfferableMessages(txn, c, maxMessages);
|
offered = db.getMessagesToOffer(txn, c, maxMessages);
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
} catch(DbException e) {
|
} catch(DbException e) {
|
||||||
db.abortTransaction(txn);
|
db.abortTransaction(txn);
|
||||||
@@ -1048,12 +1048,7 @@ DatabaseCleaner.Callback {
|
|||||||
try {
|
try {
|
||||||
if(!db.containsContact(txn, c))
|
if(!db.containsContact(txn, c))
|
||||||
throw new NoSuchContactException();
|
throw new NoSuchContactException();
|
||||||
// Mark all acked messages as seen
|
db.removeOutstandingMessages(txn, c, a.getMessageIds());
|
||||||
db.removeAckedMessages(txn, c, a.getMessageIds());
|
|
||||||
// Find any lost messages that need to be retransmitted
|
|
||||||
// FIXME: Merge these methods
|
|
||||||
Collection<MessageId> lost = db.getLostMessages(txn, c);
|
|
||||||
if(!lost.isEmpty()) db.removeLostMessages(txn, c, lost);
|
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
} catch(DbException e) {
|
} catch(DbException e) {
|
||||||
db.abortTransaction(txn);
|
db.abortTransaction(txn);
|
||||||
|
|||||||
@@ -64,9 +64,9 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
private static final String CREATE_MESSAGES =
|
private static final String CREATE_MESSAGES =
|
||||||
"CREATE TABLE messages"
|
"CREATE TABLE messages"
|
||||||
+ " (messageId HASH NOT NULL,"
|
+ " (messageId HASH NOT NULL,"
|
||||||
+ " parentId HASH," // Null for the first message in a thread
|
+ " parentId HASH," // Null for the first msg in a thread
|
||||||
+ " groupId HASH," // Null for private messages
|
+ " groupId HASH," // Null for private messages
|
||||||
+ " authorId HASH," // Null for private or anonymous messages
|
+ " authorId HASH," // Null for private or anonymous msgs
|
||||||
+ " subject VARCHAR NOT NULL,"
|
+ " subject VARCHAR NOT NULL,"
|
||||||
+ " timestamp BIGINT NOT NULL,"
|
+ " timestamp BIGINT NOT NULL,"
|
||||||
+ " length INT NOT NULL,"
|
+ " length INT NOT NULL,"
|
||||||
@@ -76,7 +76,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
+ " sendability INT," // Null for private messages
|
+ " sendability INT," // Null for private messages
|
||||||
+ " contactId INT," // Null for group messages
|
+ " contactId INT," // Null for group messages
|
||||||
+ " PRIMARY KEY (messageId),"
|
+ " PRIMARY KEY (messageId),"
|
||||||
+ " FOREIGN KEY (groupId) REFERENCES subscriptions (groupId)"
|
+ " FOREIGN KEY (groupId)"
|
||||||
|
+ " REFERENCES subscriptions (groupId)"
|
||||||
+ " ON DELETE CASCADE,"
|
+ " ON DELETE CASCADE,"
|
||||||
+ " FOREIGN KEY (contactId) REFERENCES contacts (contactId)"
|
+ " FOREIGN KEY (contactId) REFERENCES contacts (contactId)"
|
||||||
+ " ON DELETE CASCADE)";
|
+ " ON DELETE CASCADE)";
|
||||||
@@ -101,7 +102,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
+ " deleted BIGINT NOT NULL,"
|
+ " deleted BIGINT NOT NULL,"
|
||||||
+ " FOREIGN KEY (contactId) REFERENCES contacts (contactId)"
|
+ " FOREIGN KEY (contactId) REFERENCES contacts (contactId)"
|
||||||
+ " ON DELETE CASCADE,"
|
+ " ON DELETE CASCADE,"
|
||||||
+ " FOREIGN KEY (groupId) REFERENCES subscriptions (groupId)"
|
+ " FOREIGN KEY (groupId)"
|
||||||
|
+ " REFERENCES subscriptions (groupId)"
|
||||||
+ " ON DELETE CASCADE)";
|
+ " ON DELETE CASCADE)";
|
||||||
|
|
||||||
private static final String INDEX_VISIBILITIES_BY_GROUP =
|
private static final String INDEX_VISIBILITIES_BY_GROUP =
|
||||||
@@ -537,16 +539,29 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
public void addMessageToAck(Connection txn, ContactId c, MessageId m)
|
public void addMessageToAck(Connection txn, ContactId c, MessageId m)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
|
ResultSet rs = null;
|
||||||
try {
|
try {
|
||||||
String sql = "INSERT INTO messagesToAck (messageId, contactId)"
|
String sql = "SELECT NULL FROM messagesToAck"
|
||||||
|
+ " WHERE messageId = ? AND contactId = ?";
|
||||||
|
ps = txn.prepareStatement(sql);
|
||||||
|
ps.setBytes(1, m.getBytes());
|
||||||
|
ps.setInt(2, c.getInt());
|
||||||
|
rs = ps.executeQuery();
|
||||||
|
boolean found = rs.next();
|
||||||
|
if(rs.next()) throw new DbStateException();
|
||||||
|
rs.close();
|
||||||
|
ps.close();
|
||||||
|
if(found) return;
|
||||||
|
sql = "INSERT INTO messagesToAck (messageId, contactId)"
|
||||||
+ " VALUES (?, ?)";
|
+ " VALUES (?, ?)";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setBytes(1, m.getBytes());
|
ps.setBytes(1, m.getBytes());
|
||||||
ps.setInt(2, c.getInt());
|
ps.setInt(2, c.getInt());
|
||||||
int affected = ps.executeUpdate();
|
int affected = ps.executeUpdate();
|
||||||
if(affected > 1) throw new DbStateException();
|
if(affected != 1) throw new DbStateException();
|
||||||
ps.close();
|
ps.close();
|
||||||
} catch(SQLException e) {
|
} catch(SQLException e) {
|
||||||
|
tryToClose(rs);
|
||||||
tryToClose(ps);
|
tryToClose(ps);
|
||||||
throw new DbException(e);
|
throw new DbException(e);
|
||||||
}
|
}
|
||||||
@@ -1117,12 +1132,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<MessageId> getLostMessages(Connection txn, ContactId c)
|
|
||||||
throws DbException {
|
|
||||||
// FIXME: Retransmission
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getMessage(Connection txn, MessageId m) throws DbException {
|
public byte[] getMessage(Connection txn, MessageId m) throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
@@ -1319,6 +1328,64 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Collection<MessageId> getMessagesToOffer(Connection txn,
|
||||||
|
ContactId c, int maxMessages) throws DbException {
|
||||||
|
PreparedStatement ps = null;
|
||||||
|
ResultSet rs = null;
|
||||||
|
try {
|
||||||
|
// Do we have any sendable private messages?
|
||||||
|
String sql = "SELECT m.messageId FROM messages AS m"
|
||||||
|
+ " JOIN statuses AS s"
|
||||||
|
+ " ON m.messageId = s.messageId"
|
||||||
|
+ " WHERE m.contactId = ? AND status = ?"
|
||||||
|
+ " ORDER BY timestamp"
|
||||||
|
+ " LIMIT ?";
|
||||||
|
ps = txn.prepareStatement(sql);
|
||||||
|
ps.setInt(1, c.getInt());
|
||||||
|
ps.setShort(2, (short) Status.NEW.ordinal());
|
||||||
|
ps.setInt(3, maxMessages);
|
||||||
|
rs = ps.executeQuery();
|
||||||
|
List<MessageId> ids = new ArrayList<MessageId>();
|
||||||
|
while(rs.next()) ids.add(new MessageId(rs.getBytes(2)));
|
||||||
|
rs.close();
|
||||||
|
ps.close();
|
||||||
|
if(ids.size() == maxMessages)
|
||||||
|
return Collections.unmodifiableList(ids);
|
||||||
|
// Do we have any sendable group messages?
|
||||||
|
sql = "SELECT m.messageId FROM messages AS m"
|
||||||
|
+ " JOIN contactSubscriptions AS cs"
|
||||||
|
+ " ON m.groupId = cs.groupId"
|
||||||
|
+ " JOIN visibilities AS v"
|
||||||
|
+ " ON m.groupId = v.groupId"
|
||||||
|
+ " AND cs.contactId = v.contactId"
|
||||||
|
+ " JOIN statuses AS s"
|
||||||
|
+ " ON m.messageId = s.messageId"
|
||||||
|
+ " AND cs.contactId = s.contactId"
|
||||||
|
+ " JOIN subscriptionTimes AS st"
|
||||||
|
+ " ON cs.contactId = st.contactId"
|
||||||
|
+ " WHERE cs.contactId = ?"
|
||||||
|
+ " AND timestamp >= start"
|
||||||
|
+ " AND timestamp >= expiry"
|
||||||
|
+ " AND status = ?"
|
||||||
|
+ " AND sendability > ZERO()"
|
||||||
|
+ " ORDER BY timestamp"
|
||||||
|
+ " LIMIT ?";
|
||||||
|
ps = txn.prepareStatement(sql);
|
||||||
|
ps.setInt(1, c.getInt());
|
||||||
|
ps.setShort(2, (short) Status.NEW.ordinal());
|
||||||
|
ps.setInt(3, maxMessages - ids.size());
|
||||||
|
rs = ps.executeQuery();
|
||||||
|
while(rs.next()) ids.add(new MessageId(rs.getBytes(2)));
|
||||||
|
rs.close();
|
||||||
|
ps.close();
|
||||||
|
return Collections.unmodifiableList(ids);
|
||||||
|
} catch(SQLException e) {
|
||||||
|
tryToClose(rs);
|
||||||
|
tryToClose(ps);
|
||||||
|
throw new DbException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public int getNumberOfSendableChildren(Connection txn, MessageId m)
|
public int getNumberOfSendableChildren(Connection txn, MessageId m)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
@@ -1403,7 +1470,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getRead(Connection txn, MessageId m) throws DbException {
|
public boolean getReadFlag(Connection txn, MessageId m) throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try {
|
try {
|
||||||
@@ -1519,64 +1586,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<MessageId> getOfferableMessages(Connection txn,
|
|
||||||
ContactId c, int maxMessages) throws DbException {
|
|
||||||
PreparedStatement ps = null;
|
|
||||||
ResultSet rs = null;
|
|
||||||
try {
|
|
||||||
// Do we have any sendable private messages?
|
|
||||||
String sql = "SELECT m.messageId FROM messages AS m"
|
|
||||||
+ " JOIN statuses AS s"
|
|
||||||
+ " ON m.messageId = s.messageId"
|
|
||||||
+ " WHERE m.contactId = ? AND status = ?"
|
|
||||||
+ " ORDER BY timestamp"
|
|
||||||
+ " LIMIT ?";
|
|
||||||
ps = txn.prepareStatement(sql);
|
|
||||||
ps.setInt(1, c.getInt());
|
|
||||||
ps.setShort(2, (short) Status.NEW.ordinal());
|
|
||||||
ps.setInt(3, maxMessages);
|
|
||||||
rs = ps.executeQuery();
|
|
||||||
List<MessageId> ids = new ArrayList<MessageId>();
|
|
||||||
while(rs.next()) ids.add(new MessageId(rs.getBytes(2)));
|
|
||||||
rs.close();
|
|
||||||
ps.close();
|
|
||||||
if(ids.size() == maxMessages)
|
|
||||||
return Collections.unmodifiableList(ids);
|
|
||||||
// Do we have any sendable group messages?
|
|
||||||
sql = "SELECT m.messageId FROM messages AS m"
|
|
||||||
+ " JOIN contactSubscriptions AS cs"
|
|
||||||
+ " ON m.groupId = cs.groupId"
|
|
||||||
+ " JOIN visibilities AS v"
|
|
||||||
+ " ON m.groupId = v.groupId"
|
|
||||||
+ " AND cs.contactId = v.contactId"
|
|
||||||
+ " JOIN statuses AS s"
|
|
||||||
+ " ON m.messageId = s.messageId"
|
|
||||||
+ " AND cs.contactId = s.contactId"
|
|
||||||
+ " JOIN subscriptionTimes AS st"
|
|
||||||
+ " ON cs.contactId = st.contactId"
|
|
||||||
+ " WHERE cs.contactId = ?"
|
|
||||||
+ " AND timestamp >= start"
|
|
||||||
+ " AND timestamp >= expiry"
|
|
||||||
+ " AND status = ?"
|
|
||||||
+ " AND sendability > ZERO()"
|
|
||||||
+ " ORDER BY timestamp"
|
|
||||||
+ " LIMIT ?";
|
|
||||||
ps = txn.prepareStatement(sql);
|
|
||||||
ps.setInt(1, c.getInt());
|
|
||||||
ps.setShort(2, (short) Status.NEW.ordinal());
|
|
||||||
ps.setInt(3, maxMessages - ids.size());
|
|
||||||
rs = ps.executeQuery();
|
|
||||||
while(rs.next()) ids.add(new MessageId(rs.getBytes(2)));
|
|
||||||
rs.close();
|
|
||||||
ps.close();
|
|
||||||
return Collections.unmodifiableList(ids);
|
|
||||||
} catch(SQLException e) {
|
|
||||||
tryToClose(rs);
|
|
||||||
tryToClose(ps);
|
|
||||||
throw new DbException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection<MessageId> getSendableMessages(Connection txn,
|
public Collection<MessageId> getSendableMessages(Connection txn,
|
||||||
ContactId c, int maxLength) throws DbException {
|
ContactId c, int maxLength) throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
@@ -1641,7 +1650,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getStarred(Connection txn, MessageId m) throws DbException {
|
public boolean getStarredFlag(Connection txn, MessageId m) throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try {
|
try {
|
||||||
@@ -1975,28 +1984,24 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeAckedMessages(Connection txn, ContactId c,
|
public void removeOutstandingMessages(Connection txn, ContactId c,
|
||||||
Collection<MessageId> acked) throws DbException {
|
Collection<MessageId> acked) throws DbException {
|
||||||
setStatus(txn, c, acked, Status.SEEN);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setStatus(Connection txn, ContactId c,
|
|
||||||
Collection<MessageId> ids, Status newStatus) throws DbException {
|
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
try {
|
try {
|
||||||
// Set the status of each message if it's currently SENT
|
// Set the status of each message to SEEN if it's currently SENT
|
||||||
String sql = "UPDATE statuses SET status = ?"
|
String sql = "UPDATE statuses SET status = ?"
|
||||||
+ " WHERE messageId = ? AND contactId = ? AND status = ?";
|
+ " WHERE messageId = ? AND contactId = ? AND status = ?";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setShort(1, (short) newStatus.ordinal());
|
ps.setShort(1, (short) Status.SEEN.ordinal());
|
||||||
ps.setInt(3, c.getInt());
|
ps.setInt(3, c.getInt());
|
||||||
ps.setShort(4, (short) Status.SENT.ordinal());
|
ps.setShort(4, (short) Status.SENT.ordinal());
|
||||||
for(MessageId m : ids) {
|
for(MessageId m : acked) {
|
||||||
ps.setBytes(2, m.getBytes());
|
ps.setBytes(2, m.getBytes());
|
||||||
ps.addBatch();
|
ps.addBatch();
|
||||||
}
|
}
|
||||||
int[] batchAffected = ps.executeBatch();
|
int[] batchAffected = ps.executeBatch();
|
||||||
if(batchAffected.length != ids.size()) throw new DbStateException();
|
if(batchAffected.length != acked.size())
|
||||||
|
throw new DbStateException();
|
||||||
for(int i = 0; i < batchAffected.length; i++) {
|
for(int i = 0; i < batchAffected.length; i++) {
|
||||||
if(batchAffected[i] > 1) throw new DbStateException();
|
if(batchAffected[i] > 1) throw new DbStateException();
|
||||||
}
|
}
|
||||||
@@ -2048,11 +2053,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeLostMessages(Connection txn, ContactId c,
|
|
||||||
Collection<MessageId> lost) throws DbException {
|
|
||||||
setStatus(txn, c, lost, Status.NEW);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeMessage(Connection txn, MessageId m) throws DbException {
|
public void removeMessage(Connection txn, MessageId m) throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -755,7 +755,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
|||||||
allowing(database).containsContact(txn, contactId);
|
allowing(database).containsContact(txn, contactId);
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
// Get the sendable message IDs
|
// Get the sendable message IDs
|
||||||
oneOf(database).getOfferableMessages(txn, contactId, 123);
|
oneOf(database).getMessagesToOffer(txn, contactId, 123);
|
||||||
will(returnValue(offerable));
|
will(returnValue(offerable));
|
||||||
// Create the packet
|
// Create the packet
|
||||||
oneOf(packetFactory).createOffer(offerable);
|
oneOf(packetFactory).createOffer(offerable);
|
||||||
@@ -898,11 +898,8 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
|||||||
// Get the acked messages
|
// Get the acked messages
|
||||||
oneOf(ack).getMessageIds();
|
oneOf(ack).getMessageIds();
|
||||||
will(returnValue(Collections.singletonList(messageId)));
|
will(returnValue(Collections.singletonList(messageId)));
|
||||||
oneOf(database).removeAckedMessages(txn, contactId,
|
oneOf(database).removeOutstandingMessages(txn, contactId,
|
||||||
Collections.singletonList(messageId));
|
Collections.singletonList(messageId));
|
||||||
// Find lost messages
|
|
||||||
oneOf(database).getLostMessages(txn, contactId);
|
|
||||||
will(returnValue(Collections.emptyList()));
|
|
||||||
}});
|
}});
|
||||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||||
shutdown, packetFactory);
|
shutdown, packetFactory);
|
||||||
|
|||||||
@@ -556,7 +556,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveAckedMessage() throws Exception {
|
public void testOutstandingMessageAcked() throws Exception {
|
||||||
Database<Connection> db = open(false);
|
Database<Connection> db = open(false);
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
@@ -584,7 +584,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
assertFalse(it.hasNext());
|
assertFalse(it.hasNext());
|
||||||
|
|
||||||
// Pretend that the message was acked
|
// Pretend that the message was acked
|
||||||
db.removeAckedMessages(txn, contactId,
|
db.removeOutstandingMessages(txn, contactId,
|
||||||
Collections.singletonList(messageId));
|
Collections.singletonList(messageId));
|
||||||
|
|
||||||
// The message still should not be sendable
|
// The message still should not be sendable
|
||||||
@@ -595,48 +595,6 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
db.close();
|
db.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testRemoveLostMessage() throws Exception {
|
|
||||||
Database<Connection> db = open(false);
|
|
||||||
Connection txn = db.startTransaction();
|
|
||||||
|
|
||||||
// Add a contact, subscribe to a group and store a message
|
|
||||||
assertEquals(contactId, db.addContact(txn));
|
|
||||||
db.addSubscription(txn, group);
|
|
||||||
db.addVisibility(txn, contactId, groupId);
|
|
||||||
db.addSubscription(txn, contactId, group, 0L);
|
|
||||||
db.addGroupMessage(txn, message);
|
|
||||||
db.setSendability(txn, messageId, 1);
|
|
||||||
db.setStatus(txn, contactId, messageId, Status.NEW);
|
|
||||||
|
|
||||||
// Get the message and mark it as sent
|
|
||||||
Iterator<MessageId> it =
|
|
||||||
db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator();
|
|
||||||
assertTrue(it.hasNext());
|
|
||||||
assertEquals(messageId, it.next());
|
|
||||||
assertFalse(it.hasNext());
|
|
||||||
db.setStatus(txn, contactId, messageId, Status.SENT);
|
|
||||||
db.addOutstandingMessages(txn, contactId,
|
|
||||||
Collections.singletonList(messageId));
|
|
||||||
|
|
||||||
// The message should no longer be sendable
|
|
||||||
it = db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator();
|
|
||||||
assertFalse(it.hasNext());
|
|
||||||
|
|
||||||
// Pretend that the message was lost
|
|
||||||
db.removeLostMessages(txn, contactId,
|
|
||||||
Collections.singletonList(messageId));
|
|
||||||
|
|
||||||
// The message should be sendable again
|
|
||||||
it = db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator();
|
|
||||||
assertTrue(it.hasNext());
|
|
||||||
assertEquals(messageId, it.next());
|
|
||||||
assertFalse(it.hasNext());
|
|
||||||
|
|
||||||
db.commitTransaction(txn);
|
|
||||||
db.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetMessagesByAuthor() throws Exception {
|
public void testGetMessagesByAuthor() throws Exception {
|
||||||
AuthorId authorId1 = new AuthorId(TestUtils.getRandomId());
|
AuthorId authorId1 = new AuthorId(TestUtils.getRandomId());
|
||||||
@@ -1467,12 +1425,12 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
db.addGroupMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
|
|
||||||
// The message should be unread by default
|
// The message should be unread by default
|
||||||
assertFalse(db.getRead(txn, messageId));
|
assertFalse(db.getReadFlag(txn, messageId));
|
||||||
// Marking the message read should return the old value
|
// Marking the message read should return the old value
|
||||||
assertFalse(db.setRead(txn, messageId, true));
|
assertFalse(db.setRead(txn, messageId, true));
|
||||||
assertTrue(db.setRead(txn, messageId, true));
|
assertTrue(db.setRead(txn, messageId, true));
|
||||||
// The message should be read
|
// The message should be read
|
||||||
assertTrue(db.getRead(txn, messageId));
|
assertTrue(db.getReadFlag(txn, messageId));
|
||||||
// Marking the message unread should return the old value
|
// Marking the message unread should return the old value
|
||||||
assertTrue(db.setRead(txn, messageId, false));
|
assertTrue(db.setRead(txn, messageId, false));
|
||||||
assertFalse(db.setRead(txn, messageId, false));
|
assertFalse(db.setRead(txn, messageId, false));
|
||||||
@@ -1493,12 +1451,12 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
db.addGroupMessage(txn, message);
|
db.addGroupMessage(txn, message);
|
||||||
|
|
||||||
// The message should be unstarred by default
|
// The message should be unstarred by default
|
||||||
assertFalse(db.getStarred(txn, messageId));
|
assertFalse(db.getStarredFlag(txn, messageId));
|
||||||
// Starring the message should return the old value
|
// Starring the message should return the old value
|
||||||
assertFalse(db.setStarred(txn, messageId, true));
|
assertFalse(db.setStarred(txn, messageId, true));
|
||||||
assertTrue(db.setStarred(txn, messageId, true));
|
assertTrue(db.setStarred(txn, messageId, true));
|
||||||
// The message should be starred
|
// The message should be starred
|
||||||
assertTrue(db.getStarred(txn, messageId));
|
assertTrue(db.getStarredFlag(txn, messageId));
|
||||||
// Unstarring the message should return the old value
|
// Unstarring the message should return the old value
|
||||||
assertTrue(db.setStarred(txn, messageId, false));
|
assertTrue(db.setStarred(txn, messageId, false));
|
||||||
assertFalse(db.setStarred(txn, messageId, false));
|
assertFalse(db.setStarred(txn, messageId, false));
|
||||||
|
|||||||
Reference in New Issue
Block a user