Limit the number of subscriptions per user.

This limit is necessary to limit the size of subscription update
packets; it can be lifted when incremental subscription updates are
implemented.
This commit is contained in:
akwizgran
2013-02-07 18:13:58 +00:00
parent f4675c3edd
commit 78d6100262
8 changed files with 134 additions and 34 deletions

View File

@@ -132,11 +132,12 @@ interface Database<T> {
throws DbException;
/**
* Subscribes to the given group.
* Subscribes to the given group, or returns false if the user already has
* the maximum number of subscriptions.
* <p>
* Locking: subscription write.
*/
void addSubscription(T txn, Group g) throws DbException;
boolean addSubscription(T txn, Group g) throws DbException;
/**
* Adds a new transport to the database.

View File

@@ -1715,14 +1715,16 @@ DatabaseCleaner.Callback {
callListeners(new LocalSubscriptionsUpdatedEvent(affected));
}
public void subscribe(Group g) throws DbException {
public boolean subscribe(Group g) throws DbException {
subscriptionLock.writeLock().lock();
try {
T txn = db.startTransaction();
try {
boolean added = false;
if(!db.containsSubscription(txn, g.getId()))
db.addSubscription(txn, g);
added = db.addSubscription(txn, g);
db.commitTransaction(txn);
return added;
} catch(DbException e) {
db.abortTransaction(txn);
throw e;

View File

@@ -4,6 +4,7 @@ import static java.sql.Types.BINARY;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static net.sf.briar.api.Rating.UNRATED;
import static net.sf.briar.api.messaging.MessagingConstants.MAX_SUBSCRIPTIONS;
import static net.sf.briar.db.DatabaseConstants.RETENTION_MODULUS;
import static net.sf.briar.db.ExponentialBackoff.calculateExpiry;
@@ -709,11 +710,21 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
public void addSubscription(Connection txn, Group g) throws DbException {
public boolean addSubscription(Connection txn, Group g) throws DbException {
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = "INSERT INTO groups"
+ " (groupId, name, key) VALUES (?, ?, ?)";
String sql = "SELECT COUNT (groupId) from GROUPS";
ps = txn.prepareStatement(sql);
rs = ps.executeQuery();
if(!rs.next()) throw new DbStateException();
int count = rs.getInt(1);
if(rs.next()) throw new DbStateException();
rs.close();
ps.close();
if(count > MAX_SUBSCRIPTIONS) throw new DbStateException();
if(count == MAX_SUBSCRIPTIONS) return false;
sql = "INSERT INTO groups (groupId, name, key) VALUES (?, ?, ?)";
ps = txn.prepareStatement(sql);
ps.setBytes(1, g.getId().getBytes());
ps.setString(2, g.getName());
@@ -721,6 +732,7 @@ abstract class JdbcDatabase implements Database<Connection> {
int affected = ps.executeUpdate();
if(affected != 1) throw new DbStateException();
ps.close();
return true;
} catch(SQLException e) {
tryToClose(ps);
throw new DbException(e);

View File

@@ -221,8 +221,7 @@ class PacketReaderImpl implements PacketReader {
r.setMaxStringLength(MAX_PROPERTY_LENGTH);
Map<String, String> m = r.readMap(String.class, String.class);
r.resetMaxStringLength();
if(m.size() > MAX_PROPERTIES_PER_TRANSPORT)
throw new FormatException();
if(m.size() > MAX_PROPERTIES_PER_TRANSPORT) throw new FormatException();
// Read the version number
long version = r.readInt64();
if(version < 0) throw new FormatException();

View File

@@ -1,6 +1,7 @@
package net.sf.briar.messaging;
import static net.sf.briar.api.messaging.MessagingConstants.MAX_PACKET_LENGTH;
import static net.sf.briar.api.messaging.MessagingConstants.MAX_SUBSCRIPTIONS;
import static net.sf.briar.api.messaging.Types.SUBSCRIPTION_UPDATE;
import java.io.IOException;
@@ -31,7 +32,8 @@ class SubscriptionUpdateReader implements StructReader<SubscriptionUpdate> {
// Read the subscriptions
List<Group> subs = new ArrayList<Group>();
r.readListStart();
while(!r.hasListEnd()) subs.add(groupReader.readStruct(r));
for(int i = 0; i < MAX_SUBSCRIPTIONS && !r.hasListEnd(); i++)
subs.add(groupReader.readStruct(r));
r.readListEnd();
// Read the version number
long version = r.readInt64();