diff --git a/components/net/sf/briar/db/Database.java b/components/net/sf/briar/db/Database.java index a08da0163a8c139d324cf776d26ed10e8f39ca90..cc6be9b2fbd03aa4d78f4ae4b556251a3f44278f 100644 --- a/components/net/sf/briar/db/Database.java +++ b/components/net/sf/briar/db/Database.java @@ -125,6 +125,15 @@ interface Database<T> { */ void addSubscription(T txn, Group g) throws DbException; + /** + * Records the given contact's subscription to the given group starting at + * the given time. + * <p> + * Locking: contact read, subscription write. + */ + void addSubscription(T txn, ContactId c, Group g, long start) + throws DbException; + /** * Allocates and returns a local index for the given transport. Returns * null if all indices have been allocated. @@ -526,6 +535,16 @@ interface Database<T> { */ void removeSubscription(T txn, GroupId g) throws DbException; + /** + * Removes any subscriptions for the given contact with IDs between the + * given IDs. If both of the given IDs are null, all subscriptions are + * removed. If only the first is null, all subscriptions with IDs less than + * the second ID are removed. If onlt the second is null, all subscriptions + * with IDs greater than the first are removed. + */ + void removeSubscriptions(T txn, ContactId c, GroupId start, GroupId end) + throws DbException; + /** * Makes the given group invisible to the given contact. * <p> @@ -551,6 +570,13 @@ interface Database<T> { void setConnectionWindow(T txn, ContactId c, TransportIndex i, ConnectionWindow w) throws DbException; + /** + * Sets the given contact's database expiry time. + * <p> + * Locking: contact read, subscription write. + */ + void setExpiryTime(T txn, ContactId c, long expiry) throws DbException; + /** * Sets the local transport properties for the given transport, replacing * any existing properties for that transport. @@ -611,21 +637,21 @@ interface Database<T> { throws DbException; /** - * Sets the subscriptions for the given contact, replacing any existing - * subscriptions unless the existing subscriptions have a newer timestamp. + * Records the time of the latest subscription update acknowledged by the + * given contact. * <p> * Locking: contact read, subscription write. */ - void setSubscriptions(T txn, ContactId c, Map<Group, Long> subs, - long timestamp) throws DbException; + void setSubscriptionsAcked(T txn, ContactId c, long timestamp) + throws DbException; /** - * Records the time of the latest subscription modification acknowledged by - * the given contact. + * Records the time of the latest subscription update received from the + * given contact. * <p> * Locking: contact read, subscription write. */ - void setSubscriptionsAcked(T txn, ContactId c, long timestamp) + void setSubscriptionsReceived(T txn, ContactId c, long timestamp) throws DbException; /** diff --git a/components/net/sf/briar/db/DatabaseComponentImpl.java b/components/net/sf/briar/db/DatabaseComponentImpl.java index 96f33d4a110a717a3ef9703c064a5010eec159cc..c9603296100e7f57e65aeaaf945c0c533580bd64 100644 --- a/components/net/sf/briar/db/DatabaseComponentImpl.java +++ b/components/net/sf/briar/db/DatabaseComponentImpl.java @@ -15,6 +15,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.logging.Level; @@ -1175,8 +1176,17 @@ DatabaseCleaner.Callback { try { T txn = db.startTransaction(); try { + Map<GroupId, GroupId> holes = s.getHoles(); + for(Entry<GroupId, GroupId> e : holes.entrySet()) { + GroupId start = e.getKey(), end = e.getValue(); + db.removeSubscriptions(txn, c, start, end); + } Map<Group, Long> subs = s.getSubscriptions(); - db.setSubscriptions(txn, c, subs, s.getTimestamp()); + for(Entry<Group, Long> e : subs.entrySet()) { + db.addSubscription(txn, c, e.getKey(), e.getValue()); + } + db.setExpiryTime(txn, c, s.getExpiryTime()); + db.setSubscriptionsReceived(txn, c, s.getTimestamp()); db.commitTransaction(txn); } catch(DbException e) { db.abortTransaction(txn); diff --git a/components/net/sf/briar/db/JdbcDatabase.java b/components/net/sf/briar/db/JdbcDatabase.java index faecea8611fb799f44d4bba9df2d18d51b8d66c4..7e4daaec8f6e9e88db7eab57a5fdbf553d331997 100644 --- a/components/net/sf/briar/db/JdbcDatabase.java +++ b/components/net/sf/briar/db/JdbcDatabase.java @@ -735,10 +735,8 @@ abstract class JdbcDatabase implements Database<Connection> { public void addSubscription(Connection txn, Group g) throws DbException { PreparedStatement ps = null; try { - // Add the group to the subscriptions table String sql = "INSERT INTO subscriptions" - + " (groupId, groupName, groupKey, start)" - + " VALUES (?, ?, ?, ?)"; + + " (groupId, groupName, groupKey, start) VALUES (?, ?, ?, ?)"; ps = txn.prepareStatement(sql); ps.setBytes(1, g.getId().getBytes()); ps.setString(2, g.getName()); @@ -754,6 +752,43 @@ abstract class JdbcDatabase implements Database<Connection> { } } + public void addSubscription(Connection txn, ContactId c, Group g, + long start) throws DbException { + PreparedStatement ps = null; + ResultSet rs = null; + try { + // Check whether the subscription already exists + String sql = "SELECT NULL FROM contactSubscriptions" + + " WHERE contactId = ? AND groupId = ?"; + ps = txn.prepareStatement(sql); + ps.setInt(1, c.getInt()); + ps.setBytes(2, g.getId().getBytes()); + rs = ps.executeQuery(); + boolean found = rs.next(); + if(rs.next()) throw new DbStateException(); + rs.close(); + ps.close(); + if(found) return; + // Add the subscription + sql = "INSERT INTO contactSubscriptions" + + " (contactId, groupId, groupName, groupKey, start)" + + " VALUES (?, ?, ?, ?, ?)"; + ps = txn.prepareStatement(sql); + ps.setInt(1, c.getInt()); + ps.setBytes(2, g.getId().getBytes()); + ps.setString(3, g.getName()); + ps.setBytes(4, g.getPublicKey()); + ps.setLong(5, start); + int affected = ps.executeUpdate(); + if(affected != 1) throw new DbStateException(); + ps.close(); + } catch(SQLException e) { + tryToClose(rs); + tryToClose(ps); + throw new DbException(e); + } + } + public TransportIndex addTransport(Connection txn, TransportId t) throws DbException { PreparedStatement ps = null; @@ -2234,6 +2269,49 @@ abstract class JdbcDatabase implements Database<Connection> { } } + public void removeSubscriptions(Connection txn, ContactId c, GroupId start, + GroupId end) throws DbException { + PreparedStatement ps = null; + try { + if(start == null && end == null) { + // Delete everything + String sql = "DELETE FROM contactSubscriptions" + + " WHERE contactId = ?"; + ps = txn.prepareStatement(sql); + ps.setInt(1, c.getInt()); + } else if(start == null) { + // Delete everything before end + String sql = "DELETE FROM contactSubscriptions" + + " WHERE contactId = ? AND groupId < ?"; + ps = txn.prepareStatement(sql); + ps.setInt(1, c.getInt()); + ps.setBytes(2, end.getBytes()); + } else if(end == null) { + // Delete everything after start + String sql = "DELETE FROM contactSubscriptions" + + " WHERE contactId = ? AND groupId > ?"; + ps = txn.prepareStatement(sql); + ps.setInt(1, c.getInt()); + ps.setBytes(2, start.getBytes()); + } else { + // Delete everything between start and end + String sql = "DELETE FROM contactSubscriptions" + + " WHERE contactId = ?" + + " AND groupId > ? AND groupId < ?"; + ps = txn.prepareStatement(sql); + ps.setInt(1, c.getInt()); + ps.setBytes(2, start.getBytes()); + ps.setBytes(3, end.getBytes()); + } + ps.executeUpdate(); + ps.close(); + } catch(SQLException e) { + e.printStackTrace(); + tryToClose(ps); + throw new DbException(e); + } + } + public void removeVisibility(Connection txn, ContactId c, GroupId g) throws DbException { PreparedStatement ps = null; @@ -2348,6 +2426,24 @@ abstract class JdbcDatabase implements Database<Connection> { } } + public void setExpiryTime(Connection txn, ContactId c, long expiry) + throws DbException { + PreparedStatement ps = null; + try { + String sql = "UPDATE subscriptionTimes SET expiry = ?" + + " WHERE contactId = ?"; + ps = txn.prepareStatement(sql); + ps.setLong(1, expiry); + ps.setInt(2, c.getInt()); + int affected = ps.executeUpdate(); + if(affected > 1) throw new DbStateException(); + ps.close(); + } catch(SQLException e) { + tryToClose(ps); + throw new DbException(e); + } + } + public void setLocalProperties(Connection txn, TransportId t, TransportProperties p) throws DbException { PreparedStatement ps = null; @@ -2641,76 +2737,33 @@ abstract class JdbcDatabase implements Database<Connection> { } } - public void setSubscriptions(Connection txn, ContactId c, - Map<Group, Long> subs, long timestamp) throws DbException { + public void setSubscriptionsAcked(Connection txn, ContactId c, + long timestamp) throws DbException { PreparedStatement ps = null; - ResultSet rs = null; try { - // Return if the timestamp isn't fresh - String sql = "SELECT received FROM subscriptionTimes" - + " WHERE contactId = ?"; - ps = txn.prepareStatement(sql); - ps.setInt(1, c.getInt()); - rs = ps.executeQuery(); - if(!rs.next()) throw new DbStateException(); - long lastTimestamp = rs.getLong(1); - if(rs.next()) throw new DbStateException(); - rs.close(); - ps.close(); - if(lastTimestamp >= timestamp) return; - // Delete any existing subscriptions - sql = "DELETE FROM contactSubscriptions WHERE contactId = ?"; - ps = txn.prepareStatement(sql); - ps.setInt(1, c.getInt()); - ps.executeUpdate(); - ps.close(); - // Store the new subscriptions - sql = "INSERT INTO contactSubscriptions" - + " (contactId, groupId, groupName, groupKey, start)" - + " VALUES (?, ?, ?, ?, ?)"; - ps = txn.prepareStatement(sql); - ps.setInt(1, c.getInt()); - for(Entry<Group, Long> e : subs.entrySet()) { - Group g = e.getKey(); - ps.setBytes(2, g.getId().getBytes()); - ps.setString(3, g.getName()); - ps.setBytes(4, g.getPublicKey()); - ps.setLong(5, e.getValue()); - ps.addBatch(); - } - int[] batchAffected = ps.executeBatch(); - if(batchAffected.length != subs.size()) - throw new DbStateException(); - for(int i = 0; i < batchAffected.length; i++) { - if(batchAffected[i] != 1) throw new DbStateException(); - } - ps.close(); - // Update the timestamp - sql = "UPDATE subscriptionTimes SET received = ?" + String sql = "UPDATE subscriptionTimes SET acked = ?" + " WHERE contactId = ?"; ps = txn.prepareStatement(sql); ps.setLong(1, timestamp); ps.setInt(2, c.getInt()); int affected = ps.executeUpdate(); - if(affected != 1) throw new DbStateException(); + if(affected > 1) throw new DbStateException(); ps.close(); } catch(SQLException e) { - tryToClose(rs); tryToClose(ps); throw new DbException(e); } } - public void setSubscriptionsAcked(Connection txn, ContactId c, + public void setSubscriptionsReceived(Connection txn, ContactId c, long timestamp) throws DbException { PreparedStatement ps = null; try { - String sql = "UPDATE subscriptionTimes SET acked = ?" + String sql = "UPDATE subscriptionTimes SET received = ?" + " WHERE contactId = ?"; ps = txn.prepareStatement(sql); ps.setLong(1, timestamp); ps.setInt(2, c.getInt()); - ps.setLong(3, timestamp); int affected = ps.executeUpdate(); if(affected > 1) throw new DbStateException(); ps.close(); diff --git a/test/net/sf/briar/db/DatabaseComponentTest.java b/test/net/sf/briar/db/DatabaseComponentTest.java index 3f25f3f5aa24b312e1b4a403113b0a9f0159758e..013fcf2c080a966ab0092b88718c89bb371d189f 100644 --- a/test/net/sf/briar/db/DatabaseComponentTest.java +++ b/test/net/sf/briar/db/DatabaseComponentTest.java @@ -1231,7 +1231,9 @@ public abstract class DatabaseComponentTest extends BriarTestCase { @Test public void testReceiveSubscriptionUpdate() throws Exception { - final long timestamp = 1234L; + final GroupId start = new GroupId(TestUtils.getRandomId()); + final GroupId end = new GroupId(TestUtils.getRandomId()); + final long expiry = 1234L, timestamp = 5678L; Mockery context = new Mockery(); @SuppressWarnings("unchecked") final Database<Object> database = context.mock(Database.class); @@ -1247,12 +1249,19 @@ public abstract class DatabaseComponentTest extends BriarTestCase { allowing(database).containsContact(txn, contactId); will(returnValue(true)); // Get the contents of the update + oneOf(subscriptionUpdate).getHoles(); + will(returnValue(Collections.singletonMap(start, end))); oneOf(subscriptionUpdate).getSubscriptions(); will(returnValue(Collections.singletonMap(group, 0L))); + oneOf(subscriptionUpdate).getExpiryTime(); + will(returnValue(expiry)); oneOf(subscriptionUpdate).getTimestamp(); will(returnValue(timestamp)); - oneOf(database).setSubscriptions(txn, contactId, - Collections.singletonMap(group, 0L), timestamp); + // Store the contents of the update + oneOf(database).removeSubscriptions(txn, contactId, start, end); + oneOf(database).addSubscription(txn, contactId, group, 0L); + oneOf(database).setExpiryTime(txn, contactId, expiry); + oneOf(database).setSubscriptionsReceived(txn, contactId, timestamp); }}); DatabaseComponent db = createDatabaseComponent(database, cleaner, shutdown, packetFactory); diff --git a/test/net/sf/briar/db/H2DatabaseTest.java b/test/net/sf/briar/db/H2DatabaseTest.java index 4a00ad10a9c5244f9a537e734fcdb27ff78a6210..671cc5905bdfb905fd4b10d458b1a915765ce71c 100644 --- a/test/net/sf/briar/db/H2DatabaseTest.java +++ b/test/net/sf/briar/db/H2DatabaseTest.java @@ -88,7 +88,6 @@ public class H2DatabaseTest extends BriarTestCase { private final TransportProperties properties; private final Map<ContactId, TransportProperties> remoteProperties; private final Collection<Transport> remoteTransports; - private final Map<Group, Long> subscriptions; private final byte[] inSecret, outSecret; private final Collection<byte[]> erase; @@ -128,7 +127,6 @@ public class H2DatabaseTest extends BriarTestCase { Transport remoteTransport = new Transport(transportId, remoteIndex, properties); remoteTransports = Collections.singletonList(remoteTransport); - subscriptions = Collections.singletonMap(group, 0L); Random r = new Random(); inSecret = new byte[32]; r.nextBytes(inSecret); @@ -356,7 +354,7 @@ public class H2DatabaseTest extends BriarTestCase { assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase)); db.addSubscription(txn, group); db.addVisibility(txn, contactId, groupId); - db.setSubscriptions(txn, contactId, subscriptions, 1); + db.addSubscription(txn, contactId, group, 0L); db.addGroupMessage(txn, message); db.setStatus(txn, contactId, messageId, Status.NEW); @@ -394,7 +392,7 @@ public class H2DatabaseTest extends BriarTestCase { assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase)); db.addSubscription(txn, group); db.addVisibility(txn, contactId, groupId); - db.setSubscriptions(txn, contactId, subscriptions, 1); + db.addSubscription(txn, contactId, group, 0L); db.addGroupMessage(txn, message); db.setSendability(txn, messageId, 1); @@ -447,7 +445,7 @@ public class H2DatabaseTest extends BriarTestCase { assertFalse(it.hasNext()); // The contact subscribing should make the message sendable - db.setSubscriptions(txn, contactId, subscriptions, 1); + db.addSubscription(txn, contactId, group, 0L); assertTrue(db.hasSendableMessages(txn, contactId)); it = db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator(); assertTrue(it.hasNext()); @@ -455,8 +453,7 @@ public class H2DatabaseTest extends BriarTestCase { assertFalse(it.hasNext()); // The contact unsubscribing should make the message unsendable - db.setSubscriptions(txn, contactId, - Collections.<Group, Long>emptyMap(), 2); + db.removeSubscriptions(txn, contactId, null, null); assertFalse(db.hasSendableMessages(txn, contactId)); it = db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator(); assertFalse(it.hasNext()); @@ -481,16 +478,15 @@ public class H2DatabaseTest extends BriarTestCase { // The message is older than the contact's subscription, so it should // not be sendable - db.setSubscriptions(txn, contactId, - Collections.singletonMap(group, timestamp + 1), 1); + db.addSubscription(txn, contactId, group, timestamp + 1); assertFalse(db.hasSendableMessages(txn, contactId)); Iterator<MessageId> it = db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator(); assertFalse(it.hasNext()); // Changing the contact's subscription should make the message sendable - db.setSubscriptions(txn, contactId, - Collections.singletonMap(group, timestamp), 2); + db.removeSubscriptions(txn, contactId, null, null); + db.addSubscription(txn, contactId, group, timestamp); assertTrue(db.hasSendableMessages(txn, contactId)); it = db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator(); assertTrue(it.hasNext()); @@ -510,7 +506,7 @@ public class H2DatabaseTest extends BriarTestCase { assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase)); db.addSubscription(txn, group); db.addVisibility(txn, contactId, groupId); - db.setSubscriptions(txn, contactId, subscriptions, 1); + db.addSubscription(txn, contactId, group, 0L); db.addGroupMessage(txn, message); db.setSendability(txn, messageId, 1); db.setStatus(txn, contactId, messageId, Status.NEW); @@ -540,7 +536,7 @@ public class H2DatabaseTest extends BriarTestCase { // Add a contact, subscribe to a group and store a message assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase)); db.addSubscription(txn, group); - db.setSubscriptions(txn, contactId, subscriptions, 1); + db.addSubscription(txn, contactId, group, 0L); db.addGroupMessage(txn, message); db.setSendability(txn, messageId, 1); db.setStatus(txn, contactId, messageId, Status.NEW); @@ -675,7 +671,7 @@ public class H2DatabaseTest extends BriarTestCase { assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase)); db.addSubscription(txn, group); db.addVisibility(txn, contactId, groupId); - db.setSubscriptions(txn, contactId, subscriptions, 1); + db.addSubscription(txn, contactId, group, 0L); db.addGroupMessage(txn, message); db.setSendability(txn, messageId, 1); db.setStatus(txn, contactId, messageId, Status.NEW); @@ -714,7 +710,7 @@ public class H2DatabaseTest extends BriarTestCase { assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase)); db.addSubscription(txn, group); db.addVisibility(txn, contactId, groupId); - db.setSubscriptions(txn, contactId, subscriptions, 1); + db.addSubscription(txn, contactId, group, 0L); db.addGroupMessage(txn, message); db.setSendability(txn, messageId, 1); db.setStatus(txn, contactId, messageId, Status.NEW); @@ -1150,57 +1146,6 @@ public class H2DatabaseTest extends BriarTestCase { db.close(); } - @Test - public void testUpdateSubscriptions() throws Exception { - GroupId groupId1 = new GroupId(TestUtils.getRandomId()); - Group group1 = groupFactory.createGroup(groupId1, "Another group name", - null); - Database<Connection> db = open(false); - Connection txn = db.startTransaction(); - - // Add a contact with some subscriptions - assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase)); - db.setSubscriptions(txn, contactId, subscriptions, 1); - assertEquals(Collections.singletonList(group), - db.getSubscriptions(txn, contactId)); - - // Update the subscriptions - Map<Group, Long> subscriptions1 = Collections.singletonMap(group1, 0L); - db.setSubscriptions(txn, contactId, subscriptions1, 2); - assertEquals(Collections.singletonList(group1), - db.getSubscriptions(txn, contactId)); - - db.commitTransaction(txn); - db.close(); - } - - @Test - public void testSubscriptionsNotUpdatedIfTimestampIsOld() - throws Exception { - GroupId groupId1 = new GroupId(TestUtils.getRandomId()); - Group group1 = groupFactory.createGroup(groupId1, "Another group name", - null); - Database<Connection> db = open(false); - Connection txn = db.startTransaction(); - - // Add a contact with some subscriptions - assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase)); - db.setSubscriptions(txn, contactId, subscriptions, 2); - assertEquals(Collections.singletonList(group), - db.getSubscriptions(txn, contactId)); - - // Try to update the subscriptions using a timestamp of 1 - Map<Group, Long> subscriptions1 = Collections.singletonMap(group1, 0L); - db.setSubscriptions(txn, contactId, subscriptions1, 1); - - // The old subscriptions should still be there - assertEquals(Collections.singletonList(group), - db.getSubscriptions(txn, contactId)); - - db.commitTransaction(txn); - db.close(); - } - @Test public void testGetMessageIfSendableReturnsNullIfNotInDatabase() throws Exception { @@ -1210,7 +1155,7 @@ public class H2DatabaseTest extends BriarTestCase { // Add a contact and subscribe to a group assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase)); db.addSubscription(txn, group); - db.setSubscriptions(txn, contactId, subscriptions, 1); + db.addSubscription(txn, contactId, group, 0L); // The message is not in the database assertNull(db.getMessageIfSendable(txn, contactId, messageId)); @@ -1228,7 +1173,7 @@ public class H2DatabaseTest extends BriarTestCase { // Add a contact, subscribe to a group and store a message assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase)); db.addSubscription(txn, group); - db.setSubscriptions(txn, contactId, subscriptions, 1); + db.addSubscription(txn, contactId, group, 0L); db.addGroupMessage(txn, message); // Set the sendability to > 0 and the status to SEEN @@ -1251,7 +1196,7 @@ public class H2DatabaseTest extends BriarTestCase { // Add a contact, subscribe to a group and store a message assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase)); db.addSubscription(txn, group); - db.setSubscriptions(txn, contactId, subscriptions, 1); + db.addSubscription(txn, contactId, group, 0L); db.addGroupMessage(txn, message); // Set the sendability to 0 and the status to NEW @@ -1275,8 +1220,7 @@ public class H2DatabaseTest extends BriarTestCase { assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase)); db.addSubscription(txn, group); db.addVisibility(txn, contactId, groupId); - Map<Group, Long> subs = Collections.singletonMap(group, timestamp + 1); - db.setSubscriptions(txn, contactId, subs, 1); + db.addSubscription(txn, contactId, group, timestamp + 1); db.addGroupMessage(txn, message); // Set the sendability to > 0 and the status to NEW @@ -1299,7 +1243,7 @@ public class H2DatabaseTest extends BriarTestCase { assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase)); db.addSubscription(txn, group); db.addVisibility(txn, contactId, groupId); - db.setSubscriptions(txn, contactId, subscriptions, 1); + db.addSubscription(txn, contactId, group, 0L); db.addGroupMessage(txn, message); // Set the sendability to > 0 and the status to NEW @@ -1324,7 +1268,7 @@ public class H2DatabaseTest extends BriarTestCase { assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase)); db.addSubscription(txn, group); db.addVisibility(txn, contactId, groupId); - db.setSubscriptions(txn, contactId, subscriptions, 1); + db.addSubscription(txn, contactId, group, 0L); // The message is not in the database assertFalse(db.setStatusSeenIfVisible(txn, contactId, messageId)); @@ -1341,7 +1285,7 @@ public class H2DatabaseTest extends BriarTestCase { // Add a contact with a subscription assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase)); - db.setSubscriptions(txn, contactId, subscriptions, 1); + db.addSubscription(txn, contactId, group, 0L); // There's no local subscription for the group assertFalse(db.setStatusSeenIfVisible(txn, contactId, messageId)); @@ -1379,7 +1323,7 @@ public class H2DatabaseTest extends BriarTestCase { assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase)); db.addSubscription(txn, group); db.addGroupMessage(txn, message); - db.setSubscriptions(txn, contactId, subscriptions, 1); + db.addSubscription(txn, contactId, group, 0L); db.setStatus(txn, contactId, messageId, Status.NEW); // The subscription is not visible @@ -1399,7 +1343,7 @@ public class H2DatabaseTest extends BriarTestCase { assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase)); db.addSubscription(txn, group); db.addVisibility(txn, contactId, groupId); - db.setSubscriptions(txn, contactId, subscriptions, 1); + db.addSubscription(txn, contactId, group, 0L); db.addGroupMessage(txn, message); // The message has already been seen by the contact @@ -1421,7 +1365,7 @@ public class H2DatabaseTest extends BriarTestCase { assertEquals(contactId, db.addContact(txn, inSecret, outSecret, erase)); db.addSubscription(txn, group); db.addVisibility(txn, contactId, groupId); - db.setSubscriptions(txn, contactId, subscriptions, 1); + db.addSubscription(txn, contactId, group, 0L); db.addGroupMessage(txn, message); // The message has not been seen by the contact