mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 18:59:06 +01:00
Removed contact subscriptions from database.
This commit is contained in:
@@ -45,9 +45,6 @@ public interface DatabaseComponent {
|
||||
*/
|
||||
ContactId addContact(Author remote, AuthorId local) throws DbException;
|
||||
|
||||
/** Adds a group to the given contact's subscriptions. */
|
||||
void addContactGroup(ContactId c, Group g) throws DbException;
|
||||
|
||||
/**
|
||||
* Subscribes to a group, or returns false if the user already has the
|
||||
* maximum number of subscriptions.
|
||||
@@ -111,12 +108,6 @@ public interface DatabaseComponent {
|
||||
Collection<byte[]> generateRequestedBatch(ContactId c, int maxLength,
|
||||
int maxLatency) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns all groups belonging to the given client to which the user could
|
||||
* subscribe.
|
||||
*/
|
||||
Collection<Group> getAvailableGroups(ClientId c) throws DbException;
|
||||
|
||||
/** Returns the contact with the given ID. */
|
||||
Contact getContact(ContactId c) throws DbException;
|
||||
|
||||
@@ -180,9 +171,6 @@ public interface DatabaseComponent {
|
||||
/** Returns all settings in the given namespace. */
|
||||
Settings getSettings(String namespace) throws DbException;
|
||||
|
||||
/** Returns all contacts who subscribe to the given group. */
|
||||
Collection<Contact> getSubscribers(GroupId g) throws DbException;
|
||||
|
||||
/** Returns all transport keys for the given transport. */
|
||||
Map<ContactId, TransportKeys> getTransportKeys(TransportId t)
|
||||
throws DbException;
|
||||
|
||||
@@ -83,13 +83,6 @@ interface Database<T> {
|
||||
ContactId addContact(T txn, Author remote, AuthorId local)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Adds a group to the given contact's subscriptions.
|
||||
* <p>
|
||||
* Locking: write.
|
||||
*/
|
||||
void addContactGroup(T txn, ContactId c, Group g) throws DbException;
|
||||
|
||||
/**
|
||||
* Subscribes to a group, or returns false if the user already has the
|
||||
* maximum number of subscriptions.
|
||||
@@ -223,14 +216,6 @@ interface Database<T> {
|
||||
*/
|
||||
int countOfferedMessages(T txn, ContactId c) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns all groups belonging to the given client to which the user could
|
||||
* subscribe.
|
||||
* <p>
|
||||
* Locking: read.
|
||||
*/
|
||||
Collection<Group> getAvailableGroups(T txn, ClientId c) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the contact with the given ID.
|
||||
* <p>
|
||||
@@ -411,13 +396,6 @@ interface Database<T> {
|
||||
*/
|
||||
Settings getSettings(T txn, String namespace) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns all contacts who subscribe to the given group.
|
||||
* <p>
|
||||
* Locking: read.
|
||||
*/
|
||||
Collection<Contact> getSubscribers(T txn, GroupId g) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns all transport keys for the given transport.
|
||||
* <p>
|
||||
@@ -624,25 +602,6 @@ interface Database<T> {
|
||||
void setReorderingWindow(T txn, ContactId c, TransportId t,
|
||||
long rotationPeriod, long base, byte[] bitmap) throws DbException;
|
||||
|
||||
/**
|
||||
* Updates the given contact's subscriptions and returns true, unless an
|
||||
* update with an equal or higher version number has already been received
|
||||
* from the contact.
|
||||
* <p>
|
||||
* Locking: write.
|
||||
*/
|
||||
boolean setGroups(T txn, ContactId c, Collection<Group> groups,
|
||||
long version) throws DbException;
|
||||
|
||||
/**
|
||||
* Records a subscription ack from the given contact for the given version,
|
||||
* unless the contact has already acked an equal or higher version.
|
||||
* <p>
|
||||
* Locking: write.
|
||||
*/
|
||||
void setSubscriptionUpdateAcked(T txn, ContactId c, long version)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Makes a group visible or invisible to future contacts by default.
|
||||
* <p>
|
||||
|
||||
@@ -161,22 +161,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
||||
}
|
||||
}
|
||||
|
||||
public void addContactGroup(ContactId c, Group g) throws DbException {
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
db.addContactGroup(txn, c, g);
|
||||
db.commitTransaction(txn);
|
||||
} catch (DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean addGroup(Group g) throws DbException {
|
||||
boolean added = false;
|
||||
lock.writeLock().lock();
|
||||
@@ -431,23 +415,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
||||
return Collections.unmodifiableList(messages);
|
||||
}
|
||||
|
||||
public Collection<Group> getAvailableGroups(ClientId c) throws DbException {
|
||||
lock.readLock().lock();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
Collection<Group> groups = db.getAvailableGroups(txn, c);
|
||||
db.commitTransaction(txn);
|
||||
return groups;
|
||||
} catch (DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public Contact getContact(ContactId c) throws DbException {
|
||||
lock.readLock().lock();
|
||||
try {
|
||||
@@ -750,23 +717,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<Contact> getSubscribers(GroupId g) throws DbException {
|
||||
lock.readLock().lock();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
Collection<Contact> contacts = db.getSubscribers(txn, g);
|
||||
db.commitTransaction(txn);
|
||||
return contacts;
|
||||
} catch (DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public Map<ContactId, TransportKeys> getTransportKeys(TransportId t)
|
||||
throws DbException {
|
||||
lock.readLock().lock();
|
||||
|
||||
@@ -37,12 +37,10 @@ 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.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
@@ -132,31 +130,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
+ " REFERENCES groups (groupId)"
|
||||
+ " ON DELETE CASCADE)";
|
||||
|
||||
private static final String CREATE_CONTACT_GROUPS =
|
||||
"CREATE TABLE contactGroups"
|
||||
+ " (contactId INT NOT NULL,"
|
||||
+ " groupId HASH NOT NULL," // Not a foreign key
|
||||
+ " clientId HASH NOT NULL,"
|
||||
+ " descriptor BINARY NOT NULL,"
|
||||
+ " PRIMARY KEY (contactId, groupId),"
|
||||
+ " FOREIGN KEY (contactId)"
|
||||
+ " REFERENCES contacts (contactId)"
|
||||
+ " ON DELETE CASCADE)";
|
||||
|
||||
private static final String CREATE_GROUP_VERSIONS =
|
||||
"CREATE TABLE groupVersions"
|
||||
+ " (contactId INT NOT NULL,"
|
||||
+ " localVersion BIGINT NOT NULL,"
|
||||
+ " localAcked BIGINT NOT NULL,"
|
||||
+ " remoteVersion BIGINT NOT NULL,"
|
||||
+ " remoteAcked BOOLEAN NOT NULL,"
|
||||
+ " expiry BIGINT NOT NULL,"
|
||||
+ " txCount INT NOT NULL,"
|
||||
+ " PRIMARY KEY (contactId),"
|
||||
+ " FOREIGN KEY (contactid)"
|
||||
+ " REFERENCES contacts (contactId)"
|
||||
+ " ON DELETE CASCADE)";
|
||||
|
||||
private static final String CREATE_MESSAGES =
|
||||
"CREATE TABLE messages"
|
||||
+ " (messageId HASH NOT NULL,"
|
||||
@@ -351,8 +324,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
s.executeUpdate(insertTypeNames(CREATE_GROUPS));
|
||||
s.executeUpdate(insertTypeNames(CREATE_GROUP_METADATA));
|
||||
s.executeUpdate(insertTypeNames(CREATE_GROUP_VISIBILITIES));
|
||||
s.executeUpdate(insertTypeNames(CREATE_CONTACT_GROUPS));
|
||||
s.executeUpdate(insertTypeNames(CREATE_GROUP_VERSIONS));
|
||||
s.executeUpdate(insertTypeNames(CREATE_MESSAGES));
|
||||
s.executeUpdate(insertTypeNames(CREATE_MESSAGE_METADATA));
|
||||
s.executeUpdate(insertTypeNames(CREATE_OFFERS));
|
||||
@@ -565,16 +536,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (rows != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
}
|
||||
// Create a group version row
|
||||
sql = "INSERT INTO groupVersions (contactId, localVersion,"
|
||||
+ " localAcked, remoteVersion, remoteAcked, expiry,"
|
||||
+ " txCount)"
|
||||
+ " VALUES (?, 1, 0, 0, TRUE, 0, 0)";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setInt(1, c.getInt());
|
||||
affected = ps.executeUpdate();
|
||||
if (affected != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
return c;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs);
|
||||
@@ -583,40 +544,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
}
|
||||
|
||||
public void addContactGroup(Connection txn, ContactId c, Group g)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = "SELECT NULL FROM contactGroups"
|
||||
+ " 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;
|
||||
sql = "INSERT INTO contactGroups"
|
||||
+ " (contactId, groupId, clientId, descriptor)"
|
||||
+ " VALUES (?, ?, ?, ?)";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setInt(1, c.getInt());
|
||||
ps.setBytes(2, g.getId().getBytes());
|
||||
ps.setBytes(3, g.getClientId().getBytes());
|
||||
ps.setBytes(4, g.getDescriptor());
|
||||
int affected = ps.executeUpdate();
|
||||
if (affected != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean addGroup(Connection txn, Group g) throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
@@ -853,16 +780,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
int affected = ps.executeUpdate();
|
||||
if (affected != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
// Bump the subscription version
|
||||
sql = "UPDATE groupVersions"
|
||||
+ " SET localVersion = localVersion + 1,"
|
||||
+ " expiry = 0, txCount = 0"
|
||||
+ " WHERE contactId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setInt(1, c.getInt());
|
||||
affected = ps.executeUpdate();
|
||||
if (affected != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
@@ -1070,39 +987,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<Group> getAvailableGroups(Connection txn, ClientId c)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = "SELECT DISTINCT cg.groupId, cg.descriptor"
|
||||
+ " FROM contactGroups AS cg"
|
||||
+ " LEFT OUTER JOIN groups AS g"
|
||||
+ " ON cg.groupId = g.groupId"
|
||||
+ " WHERE cg.clientId = ?"
|
||||
+ " AND g.groupId IS NULL"
|
||||
+ " GROUP BY cg.groupId";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setBytes(1, c.getBytes());
|
||||
rs = ps.executeQuery();
|
||||
List<Group> groups = new ArrayList<Group>();
|
||||
Set<GroupId> ids = new HashSet<GroupId>();
|
||||
while (rs.next()) {
|
||||
GroupId id = new GroupId(rs.getBytes(1));
|
||||
if (!ids.add(id)) throw new DbStateException();
|
||||
byte[] descriptor = rs.getBytes(2);
|
||||
groups.add(new Group(id, c, descriptor));
|
||||
}
|
||||
rs.close();
|
||||
ps.close();
|
||||
return Collections.unmodifiableList(groups);
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Contact getContact(Connection txn, ContactId c) throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
@@ -1472,15 +1356,12 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = "SELECT m.messageId FROM messages AS m"
|
||||
+ " JOIN contactGroups AS cg"
|
||||
+ " ON m.groupId = cg.groupId"
|
||||
+ " JOIN groupVisibilities AS gv"
|
||||
+ " ON m.groupId = gv.groupId"
|
||||
+ " AND cg.contactId = gv.contactId"
|
||||
+ " JOIN statuses AS s"
|
||||
+ " ON m.messageId = s.messageId"
|
||||
+ " AND cg.contactId = s.contactId"
|
||||
+ " WHERE cg.contactId = ?"
|
||||
+ " AND gv.contactId = s.contactId"
|
||||
+ " WHERE gv.contactId = ?"
|
||||
+ " AND valid = ? AND shared = TRUE"
|
||||
+ " AND seen = FALSE AND requested = FALSE"
|
||||
+ " AND s.expiry < ?"
|
||||
@@ -1534,15 +1415,12 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = "SELECT length, m.messageId FROM messages AS m"
|
||||
+ " JOIN contactGroups AS cg"
|
||||
+ " ON m.groupId = cg.groupId"
|
||||
+ " JOIN groupVisibilities AS gv"
|
||||
+ " ON m.groupId = gv.groupId"
|
||||
+ " AND cg.contactId = gv.contactId"
|
||||
+ " JOIN statuses AS s"
|
||||
+ " ON m.messageId = s.messageId"
|
||||
+ " AND cg.contactId = s.contactId"
|
||||
+ " WHERE cg.contactId = ?"
|
||||
+ " AND gv.contactId = s.contactId"
|
||||
+ " WHERE gv.contactId = ?"
|
||||
+ " AND valid = ? AND shared = TRUE"
|
||||
+ " AND seen = FALSE"
|
||||
+ " AND s.expiry < ?"
|
||||
@@ -1623,15 +1501,12 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = "SELECT length, m.messageId FROM messages AS m"
|
||||
+ " JOIN contactGroups AS cg"
|
||||
+ " ON m.groupId = cg.groupId"
|
||||
+ " JOIN groupVisibilities AS gv"
|
||||
+ " ON m.groupId = gv.groupId"
|
||||
+ " AND cg.contactId = gv.contactId"
|
||||
+ " JOIN statuses AS s"
|
||||
+ " ON m.messageId = s.messageId"
|
||||
+ " AND cg.contactId = s.contactId"
|
||||
+ " WHERE cg.contactId = ?"
|
||||
+ " AND gv.contactId = s.contactId"
|
||||
+ " WHERE gv.contactId = ?"
|
||||
+ " AND valid = ? AND shared = TRUE"
|
||||
+ " AND seen = FALSE AND requested = TRUE"
|
||||
+ " AND s.expiry < ?"
|
||||
@@ -1680,42 +1555,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<Contact> getSubscribers(Connection txn, GroupId g)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = "SELECT c.contactId, authorId, c.name, publicKey,"
|
||||
+ " localAuthorId, status"
|
||||
+ " FROM contacts AS c"
|
||||
+ " JOIN contactGroups AS cg"
|
||||
+ " ON c.contactId = cg.contactId"
|
||||
+ " WHERE groupId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setBytes(1, g.getBytes());
|
||||
rs = ps.executeQuery();
|
||||
List<Contact> contacts = new ArrayList<Contact>();
|
||||
while (rs.next()) {
|
||||
ContactId contactId = new ContactId(rs.getInt(1));
|
||||
AuthorId authorId = new AuthorId(rs.getBytes(2));
|
||||
String name = rs.getString(3);
|
||||
byte[] publicKey = rs.getBytes(4);
|
||||
Author author = new Author(authorId, name, publicKey);
|
||||
AuthorId localAuthorId = new AuthorId(rs.getBytes(5));
|
||||
StorageStatus status = StorageStatus.fromValue(rs.getInt(6));
|
||||
contacts.add(new Contact(contactId, author, localAuthorId,
|
||||
status));
|
||||
}
|
||||
rs.close();
|
||||
ps.close();
|
||||
return Collections.unmodifiableList(contacts);
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<ContactId, TransportKeys> getTransportKeys(Connection txn,
|
||||
TransportId t) throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
@@ -2097,44 +1936,15 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
|
||||
public void removeGroup(Connection txn, GroupId g) throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
// Find out which contacts are affected
|
||||
String sql = "SELECT contactId FROM groupVisibilities"
|
||||
+ " WHERE groupId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setBytes(1, g.getBytes());
|
||||
rs = ps.executeQuery();
|
||||
Collection<Integer> visible = new ArrayList<Integer>();
|
||||
while (rs.next()) visible.add(rs.getInt(1));
|
||||
rs.close();
|
||||
ps.close();
|
||||
// Delete the group
|
||||
sql = "DELETE FROM groups WHERE groupId = ?";
|
||||
String sql = "DELETE FROM groups WHERE groupId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setBytes(1, g.getBytes());
|
||||
int affected = ps.executeUpdate();
|
||||
if (affected != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
if (visible.isEmpty()) return;
|
||||
// Bump the subscription versions for the affected contacts
|
||||
sql = "UPDATE groupVersions"
|
||||
+ " SET localVersion = localVersion + 1, expiry = 0"
|
||||
+ " WHERE contactId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
for (Integer c : visible) {
|
||||
ps.setInt(1, c);
|
||||
ps.addBatch();
|
||||
}
|
||||
int[] batchAffected = ps.executeBatch();
|
||||
if (batchAffected.length != visible.size())
|
||||
throw new DbStateException();
|
||||
for (int rows : batchAffected)
|
||||
if (rows != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps);
|
||||
tryToClose(rs);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2241,15 +2051,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
int affected = ps.executeUpdate();
|
||||
if (affected != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
// Bump the subscription version
|
||||
sql = "UPDATE groupVersions"
|
||||
+ " SET localVersion = localVersion + 1, expiry = 0"
|
||||
+ " WHERE contactId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setInt(1, c.getInt());
|
||||
affected = ps.executeUpdate();
|
||||
if (affected != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
@@ -2364,113 +2165,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean setGroups(Connection txn, ContactId c,
|
||||
Collection<Group> groups, long version) throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
// Mark the update as needing to be acked
|
||||
String sql = "UPDATE groupVersions"
|
||||
+ " SET remoteVersion = ?, remoteAcked = FALSE"
|
||||
+ " WHERE contactId = ? AND remoteVersion < ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setLong(1, version);
|
||||
ps.setInt(2, c.getInt());
|
||||
ps.setLong(3, version);
|
||||
int affected = ps.executeUpdate();
|
||||
if (affected < 0 || affected > 1) throw new DbStateException();
|
||||
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 rows : batchAffected)
|
||||
if (rows < 0) throw new DbStateException();
|
||||
ps.close();
|
||||
}
|
||||
// Delete the existing subscriptions, if any
|
||||
sql = "DELETE FROM contactGroups WHERE contactId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setInt(1, c.getInt());
|
||||
ps.executeUpdate();
|
||||
// Store the new subscriptions, if any
|
||||
if (groups.isEmpty()) return true;
|
||||
sql = "INSERT INTO contactGroups"
|
||||
+ " (contactId, groupId, clientId, descriptor)"
|
||||
+ " VALUES (?, ?, ?, ?)";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setInt(1, c.getInt());
|
||||
for (Group g : groups) {
|
||||
ps.setBytes(2, g.getId().getBytes());
|
||||
ps.setBytes(3, g.getClientId().getBytes());
|
||||
ps.setBytes(4, g.getDescriptor());
|
||||
ps.addBatch();
|
||||
}
|
||||
int[] batchAffected = ps.executeBatch();
|
||||
if (batchAffected.length != groups.size())
|
||||
throw new DbStateException();
|
||||
for (int rows : batchAffected)
|
||||
if (rows != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
return true;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps);
|
||||
tryToClose(rs);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setSubscriptionUpdateAcked(Connection txn, ContactId c,
|
||||
long version) throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
try {
|
||||
String sql = "UPDATE groupVersions SET localAcked = ?"
|
||||
+ " WHERE contactId = ?"
|
||||
+ " AND localAcked < ? AND localVersion >= ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setLong(1, version);
|
||||
ps.setInt(2, c.getInt());
|
||||
ps.setLong(3, version);
|
||||
ps.setLong(4, version);
|
||||
int affected = ps.executeUpdate();
|
||||
if (affected < 0 || affected > 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setVisibleToAll(Connection txn, GroupId g, boolean all)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
|
||||
@@ -143,16 +143,8 @@ class ForumManagerImpl implements ForumManager {
|
||||
|
||||
@Override
|
||||
public Collection<Forum> getAvailableForums() throws DbException {
|
||||
Collection<Group> groups = db.getAvailableGroups(CLIENT_ID);
|
||||
List<Forum> forums = new ArrayList<Forum>(groups.size());
|
||||
for (Group g : groups) {
|
||||
try {
|
||||
forums.add(parseForum(g));
|
||||
} catch (FormatException e) {
|
||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableList(forums);
|
||||
// TODO
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private Forum parseForum(Group g) throws FormatException {
|
||||
@@ -272,7 +264,8 @@ class ForumManagerImpl implements ForumManager {
|
||||
|
||||
@Override
|
||||
public Collection<Contact> getSubscribers(GroupId g) throws DbException {
|
||||
return db.getSubscribers(g);
|
||||
// TODO
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -75,7 +75,6 @@ class MessagingManagerImpl implements MessagingManager, AddContactHook,
|
||||
Group g = getConversationGroup(db.getContact(c));
|
||||
// Subscribe to the group and share it with the contact
|
||||
db.addGroup(g);
|
||||
db.addContactGroup(c, g);
|
||||
db.setVisibility(g.getId(), Collections.singletonList(c));
|
||||
// Attach the contact ID to the group
|
||||
BdfDictionary d = new BdfDictionary();
|
||||
|
||||
@@ -98,7 +98,6 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
||||
Group g = getContactGroup(db.getContact(c));
|
||||
// Subscribe to the group and share it with the contact
|
||||
db.addGroup(g);
|
||||
db.addContactGroup(c, g);
|
||||
db.setVisibility(g.getId(), Collections.singletonList(c));
|
||||
// Copy the latest local properties into the group
|
||||
DeviceId dev = db.getDeviceId();
|
||||
|
||||
@@ -62,7 +62,6 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
|
||||
private final File testDir = TestUtils.getTestDirectory();
|
||||
private final Random random = new Random();
|
||||
private final ClientId clientId;
|
||||
private final GroupId groupId;
|
||||
private final Group group;
|
||||
private final Author author;
|
||||
@@ -77,8 +76,8 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
private final ContactId contactId;
|
||||
|
||||
public H2DatabaseTest() throws Exception {
|
||||
clientId = new ClientId(TestUtils.getRandomId());
|
||||
groupId = new GroupId(TestUtils.getRandomId());
|
||||
ClientId clientId = new ClientId(TestUtils.getRandomId());
|
||||
byte[] descriptor = new byte[MAX_GROUP_DESCRIPTOR_LENGTH];
|
||||
group = new Group(groupId, clientId, descriptor);
|
||||
AuthorId authorId = new AuthorId(TestUtils.getRandomId());
|
||||
@@ -174,7 +173,6 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
assertEquals(contactId, db.addContact(txn, author, localAuthorId));
|
||||
db.addGroup(txn, group);
|
||||
db.addVisibility(txn, contactId, groupId);
|
||||
db.setGroups(txn, contactId, Collections.singletonList(group), 1);
|
||||
db.addMessage(txn, message, VALID, true);
|
||||
|
||||
// The message has no status yet, so it should not be sendable
|
||||
@@ -212,7 +210,6 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
assertEquals(contactId, db.addContact(txn, author, localAuthorId));
|
||||
db.addGroup(txn, group);
|
||||
db.addVisibility(txn, contactId, groupId);
|
||||
db.setGroups(txn, contactId, Collections.singletonList(group), 1);
|
||||
db.addMessage(txn, message, UNKNOWN, true);
|
||||
db.addStatus(txn, contactId, messageId, false, false);
|
||||
|
||||
@@ -251,7 +248,6 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
assertEquals(contactId, db.addContact(txn, author, localAuthorId));
|
||||
db.addGroup(txn, group);
|
||||
db.addVisibility(txn, contactId, groupId);
|
||||
db.setGroups(txn, contactId, Collections.singletonList(group), 1);
|
||||
db.addMessage(txn, message, VALID, false);
|
||||
db.addStatus(txn, contactId, messageId, false, false);
|
||||
|
||||
@@ -280,44 +276,6 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
db.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendableMessagesMustBeSubscribed() throws Exception {
|
||||
Database<Connection> db = open(false);
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Add a contact, subscribe to a group and store a message
|
||||
db.addLocalAuthor(txn, localAuthor);
|
||||
assertEquals(contactId, db.addContact(txn, author, localAuthorId));
|
||||
db.addGroup(txn, group);
|
||||
db.addVisibility(txn, contactId, groupId);
|
||||
db.addMessage(txn, message, VALID, true);
|
||||
db.addStatus(txn, contactId, messageId, false, false);
|
||||
|
||||
// The contact is not subscribed, so the message should not be sendable
|
||||
Collection<MessageId> ids = db.getMessagesToSend(txn, contactId,
|
||||
ONE_MEGABYTE);
|
||||
assertTrue(ids.isEmpty());
|
||||
ids = db.getMessagesToOffer(txn, contactId, 100);
|
||||
assertTrue(ids.isEmpty());
|
||||
|
||||
// The contact subscribing should make the message sendable
|
||||
db.setGroups(txn, contactId, Collections.singletonList(group), 1);
|
||||
ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE);
|
||||
assertEquals(Collections.singletonList(messageId), ids);
|
||||
ids = db.getMessagesToOffer(txn, contactId, 100);
|
||||
assertEquals(Collections.singletonList(messageId), ids);
|
||||
|
||||
// The contact unsubscribing should make the message unsendable
|
||||
db.setGroups(txn, contactId, Collections.<Group>emptyList(), 2);
|
||||
ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE);
|
||||
assertTrue(ids.isEmpty());
|
||||
ids = db.getMessagesToOffer(txn, contactId, 100);
|
||||
assertTrue(ids.isEmpty());
|
||||
|
||||
db.commitTransaction(txn);
|
||||
db.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendableMessagesMustFitCapacity() throws Exception {
|
||||
Database<Connection> db = open(false);
|
||||
@@ -328,7 +286,6 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
assertEquals(contactId, db.addContact(txn, author, localAuthorId));
|
||||
db.addGroup(txn, group);
|
||||
db.addVisibility(txn, contactId, groupId);
|
||||
db.setGroups(txn, contactId, Collections.singletonList(group), 1);
|
||||
db.addMessage(txn, message, VALID, true);
|
||||
db.addStatus(txn, contactId, messageId, false, false);
|
||||
|
||||
@@ -354,7 +311,6 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
db.addLocalAuthor(txn, localAuthor);
|
||||
assertEquals(contactId, db.addContact(txn, author, localAuthorId));
|
||||
db.addGroup(txn, group);
|
||||
db.setGroups(txn, contactId, Collections.singletonList(group), 1);
|
||||
db.addMessage(txn, message, VALID, true);
|
||||
db.addStatus(txn, contactId, messageId, false, false);
|
||||
|
||||
@@ -393,7 +349,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
db.addLocalAuthor(txn, localAuthor);
|
||||
assertEquals(contactId, db.addContact(txn, author, localAuthorId));
|
||||
db.addGroup(txn, group);
|
||||
db.setGroups(txn, contactId, Collections.singletonList(group), 1);
|
||||
db.addVisibility(txn, contactId, groupId);
|
||||
|
||||
// Add some messages to ack
|
||||
MessageId messageId1 = new MessageId(TestUtils.getRandomId());
|
||||
@@ -430,7 +386,6 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
assertEquals(contactId, db.addContact(txn, author, localAuthorId));
|
||||
db.addGroup(txn, group);
|
||||
db.addVisibility(txn, contactId, groupId);
|
||||
db.setGroups(txn, contactId, Collections.singletonList(group), 1);
|
||||
db.addMessage(txn, message, VALID, true);
|
||||
db.addStatus(txn, contactId, messageId, false, false);
|
||||
|
||||
@@ -595,7 +550,6 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
assertEquals(contactId, db.addContact(txn, author, localAuthorId));
|
||||
db.addGroup(txn, group);
|
||||
db.addVisibility(txn, contactId, groupId);
|
||||
db.setGroups(txn, contactId, Collections.singletonList(group), 1);
|
||||
|
||||
// The message is not in the database
|
||||
assertFalse(db.containsVisibleMessage(txn, contactId, messageId));
|
||||
@@ -610,10 +564,9 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
Database<Connection> db = open(false);
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Add a contact with a subscription
|
||||
// Add a contact
|
||||
db.addLocalAuthor(txn, localAuthor);
|
||||
assertEquals(contactId, db.addContact(txn, author, localAuthorId));
|
||||
db.setGroups(txn, contactId, Collections.singletonList(group), 1);
|
||||
|
||||
// There's no local subscription for the group
|
||||
assertFalse(db.containsVisibleMessage(txn, contactId, messageId));
|
||||
@@ -632,7 +585,6 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
db.addLocalAuthor(txn, localAuthor);
|
||||
assertEquals(contactId, db.addContact(txn, author, localAuthorId));
|
||||
db.addGroup(txn, group);
|
||||
db.setGroups(txn, contactId, Collections.singletonList(group), 1);
|
||||
db.addMessage(txn, message, VALID, true);
|
||||
db.addStatus(txn, contactId, messageId, false, false);
|
||||
|
||||
@@ -838,57 +790,6 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
db.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAvailableGroups() throws Exception {
|
||||
ContactId contactId1 = new ContactId(2);
|
||||
AuthorId authorId1 = new AuthorId(TestUtils.getRandomId());
|
||||
Author author1 = new Author(authorId1, "Carol",
|
||||
new byte[MAX_PUBLIC_KEY_LENGTH]);
|
||||
|
||||
Database<Connection> db = open(false);
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Add two contacts who subscribe to a group
|
||||
db.addLocalAuthor(txn, localAuthor);
|
||||
assertEquals(contactId, db.addContact(txn, author, localAuthorId));
|
||||
assertEquals(contactId1, db.addContact(txn, author1, localAuthorId));
|
||||
db.setGroups(txn, contactId, Collections.singletonList(group), 1);
|
||||
db.setGroups(txn, contactId1, Collections.singletonList(group), 1);
|
||||
|
||||
// The group should be available
|
||||
assertEquals(Collections.emptyList(), db.getGroups(txn, clientId));
|
||||
assertEquals(Collections.singletonList(group),
|
||||
db.getAvailableGroups(txn, clientId));
|
||||
|
||||
// Subscribe to the group - it should no longer be available
|
||||
db.addGroup(txn, group);
|
||||
assertEquals(Collections.singletonList(group),
|
||||
db.getGroups(txn, clientId));
|
||||
assertEquals(Collections.emptyList(),
|
||||
db.getAvailableGroups(txn, clientId));
|
||||
|
||||
// Unsubscribe from the group - it should be available again
|
||||
db.removeGroup(txn, groupId);
|
||||
assertEquals(Collections.emptyList(), db.getGroups(txn, clientId));
|
||||
assertEquals(Collections.singletonList(group),
|
||||
db.getAvailableGroups(txn, clientId));
|
||||
|
||||
// The first contact unsubscribes - it should still be available
|
||||
db.setGroups(txn, contactId, Collections.<Group>emptyList(), 2);
|
||||
assertEquals(Collections.emptyList(), db.getGroups(txn, clientId));
|
||||
assertEquals(Collections.singletonList(group),
|
||||
db.getAvailableGroups(txn, clientId));
|
||||
|
||||
// The second contact unsubscribes - it should no longer be available
|
||||
db.setGroups(txn, contactId1, Collections.<Group>emptyList(), 2);
|
||||
assertEquals(Collections.emptyList(), db.getGroups(txn, clientId));
|
||||
assertEquals(Collections.emptyList(),
|
||||
db.getAvailableGroups(txn, clientId));
|
||||
|
||||
db.commitTransaction(txn);
|
||||
db.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetContactsByLocalAuthorId() throws Exception {
|
||||
Database<Connection> db = open(false);
|
||||
@@ -943,46 +844,6 @@ 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, Collections.singletonList(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, VALID, true);
|
||||
db.addStatus(txn, contactId, messageId, false, false);
|
||||
Collection<MessageId> sendable = db.getMessagesToSend(txn, contactId,
|
||||
ONE_MEGABYTE);
|
||||
assertEquals(Collections.singletonList(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, Collections.singletonList(group), 3);
|
||||
sendable = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE);
|
||||
assertEquals(Collections.singletonList(messageId), sendable);
|
||||
|
||||
db.commitTransaction(txn);
|
||||
db.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGroupMetadata() throws Exception {
|
||||
Database<Connection> db = open(false);
|
||||
@@ -1086,12 +947,11 @@ public class H2DatabaseTest extends BriarTestCase {
|
||||
Database<Connection> db = open(false);
|
||||
Connection txn = db.startTransaction();
|
||||
|
||||
// Add a contact who subscribes to a group
|
||||
// Add a contact
|
||||
db.addLocalAuthor(txn, localAuthor);
|
||||
assertEquals(contactId, db.addContact(txn, author, localAuthorId));
|
||||
db.setGroups(txn, contactId, Collections.singletonList(group), 1);
|
||||
|
||||
// Subscribe to the group and make it visible to the contact
|
||||
// Subscribe to a group and make it visible to the contact
|
||||
db.addGroup(txn, group);
|
||||
db.addVisibility(txn, contactId, groupId);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user