mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 10:49:06 +01:00
Reset message status when contact unsubscribes from group. Dev task #68.
This commit is contained in:
@@ -703,7 +703,7 @@ interface Database<T> {
|
||||
* true, unless an update with an equal or higher version number has
|
||||
* already been received from the contact.
|
||||
* <p>
|
||||
* Locking: subscription write.
|
||||
* Locking: message write, subscription write.
|
||||
*/
|
||||
boolean setGroups(T txn, ContactId c, Collection<Group> groups,
|
||||
long version) throws DbException;
|
||||
|
||||
@@ -1500,22 +1500,27 @@ DatabaseCleaner.Callback {
|
||||
boolean updated;
|
||||
contactLock.readLock().lock();
|
||||
try {
|
||||
subscriptionLock.writeLock().lock();
|
||||
messageLock.writeLock().lock();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
subscriptionLock.writeLock().lock();
|
||||
try {
|
||||
if(!db.containsContact(txn, c))
|
||||
throw new NoSuchContactException();
|
||||
Collection<Group> groups = u.getGroups();
|
||||
long version = u.getVersion();
|
||||
updated = db.setGroups(txn, c, groups, version);
|
||||
db.commitTransaction(txn);
|
||||
} catch(DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
throw e;
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
if(!db.containsContact(txn, c))
|
||||
throw new NoSuchContactException();
|
||||
Collection<Group> groups = u.getGroups();
|
||||
long version = u.getVersion();
|
||||
updated = db.setGroups(txn, c, groups, version);
|
||||
db.commitTransaction(txn);
|
||||
} catch(DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
subscriptionLock.writeLock().unlock();
|
||||
}
|
||||
} finally {
|
||||
subscriptionLock.writeLock().unlock();
|
||||
messageLock.writeLock().unlock();
|
||||
}
|
||||
} finally {
|
||||
contactLock.readLock().unlock();
|
||||
|
||||
@@ -21,10 +21,12 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -2896,8 +2898,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
try {
|
||||
String sql = "UPDATE statuses"
|
||||
+ " SET expiry = 0, txCount = 0"
|
||||
String sql = "UPDATE statuses SET expiry = 0, txCount = 0"
|
||||
+ " WHERE messageId = ? AND contactId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setBytes(1, m.getBytes());
|
||||
@@ -2949,6 +2950,43 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
// Return false if the update is obsolete
|
||||
if(affected == 0) return false;
|
||||
// Find any messages in groups that are being removed
|
||||
Set<GroupId> newIds = new HashSet<GroupId>();
|
||||
for(Group g : groups) newIds.add(g.getId());
|
||||
sql = "SELECT messageId, m.groupId"
|
||||
+ " FROM messages AS m"
|
||||
+ " JOIN contactGroups AS cg"
|
||||
+ " ON m.groupId = cg.groupId"
|
||||
+ " WHERE contactId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setInt(1, c.getInt());
|
||||
rs = ps.executeQuery();
|
||||
List<MessageId> removed = new ArrayList<MessageId>();
|
||||
while(rs.next()) {
|
||||
if(!newIds.contains(new GroupId(rs.getBytes(2))))
|
||||
removed.add(new MessageId(rs.getBytes(1)));
|
||||
}
|
||||
rs.close();
|
||||
ps.close();
|
||||
// Reset any statuses for messages in groups that are being removed
|
||||
if(!removed.isEmpty()) {
|
||||
sql = "UPDATE statuses SET ack = FALSE, seen = FALSE,"
|
||||
+ " requested = FALSE, expiry = 0, txCount = 0"
|
||||
+ " WHERE contactId = ? AND messageId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setInt(1, c.getInt());
|
||||
for(MessageId m : removed) {
|
||||
ps.setBytes(2, m.getBytes());
|
||||
ps.addBatch();
|
||||
}
|
||||
int[] batchAffected = ps.executeBatch();
|
||||
if(batchAffected.length != removed.size())
|
||||
throw new DbStateException();
|
||||
for(int i = 0; i < batchAffected.length; i++) {
|
||||
if(batchAffected[i] < 0) throw new DbStateException();
|
||||
}
|
||||
ps.close();
|
||||
}
|
||||
// Delete the existing subscriptions, if any
|
||||
sql = "DELETE FROM contactGroups WHERE contactId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
|
||||
@@ -1577,6 +1577,46 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
db.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContactUnsubscribingResetsMessageStatus() throws Exception {
|
||||
Database<Connection> db = open(false);
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Add a contact who subscribes to a group
|
||||
db.addLocalAuthor(txn, localAuthor);
|
||||
assertEquals(contactId, db.addContact(txn, author, localAuthorId));
|
||||
db.setGroups(txn, contactId, Arrays.asList(group), 1);
|
||||
|
||||
// Subscribe to the group and make it visible to the contact
|
||||
db.addGroup(txn, group);
|
||||
db.addVisibility(txn, contactId, groupId);
|
||||
|
||||
// Add a message - it should be sendable to the contact
|
||||
db.addMessage(txn, message, true);
|
||||
db.addStatus(txn, contactId, messageId, false, false);
|
||||
Collection<MessageId> sendable = db.getMessagesToSend(txn, contactId,
|
||||
ONE_MEGABYTE);
|
||||
assertEquals(Arrays.asList(messageId), sendable);
|
||||
|
||||
// Mark the message as seen - it should no longer be sendable
|
||||
db.raiseSeenFlag(txn, contactId, messageId);
|
||||
sendable = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE);
|
||||
assertEquals(Collections.emptyList(), sendable);
|
||||
|
||||
// The contact unsubscribes - the message should not be sendable
|
||||
db.setGroups(txn, contactId, Collections.<Group>emptyList(), 2);
|
||||
sendable = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE);
|
||||
assertEquals(Collections.emptyList(), sendable);
|
||||
|
||||
// The contact resubscribes - the message should be sendable again
|
||||
db.setGroups(txn, contactId, Arrays.asList(group), 3);
|
||||
sendable = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE);
|
||||
assertEquals(Arrays.asList(messageId), sendable);
|
||||
|
||||
db.commitTransaction(txn);
|
||||
db.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExceptionHandling() throws Exception {
|
||||
Database<Connection> db = open(false);
|
||||
|
||||
Reference in New Issue
Block a user