Limit the number of offered messages per contact.

Also fixed a bug in addGroup(): SELECT COUNT (NULL) doesn't work.
This commit is contained in:
akwizgran
2014-01-04 21:57:13 +00:00
parent fc827c191e
commit 3779f6ea8b
6 changed files with 101 additions and 36 deletions

View File

@@ -220,6 +220,13 @@ interface Database<T> {
boolean containsVisibleMessage(T txn, ContactId c, MessageId m)
throws DbException;
/**
* Returns the number of messages offered by the given contact.
* <p>
* Locking: message read.
*/
int countOfferedMessages(T txn, ContactId c) throws DbException;
/**
* Returns the status of all groups to which the user subscribes or can
* subscribe, excluding inbox groups.
@@ -634,8 +641,8 @@ interface Database<T> {
void removeMessage(T txn, MessageId m) throws DbException;
/**
* Removes an offered message ID that was offered by the given contact, or
* returns false if there is no such message ID.
* Removes an offered message that was offered by the given contact, or
* returns false if there is no such message.
* <p>
* Locking: message write.
*/
@@ -643,7 +650,7 @@ interface Database<T> {
throws DbException;
/**
* Removes the given offered message IDs that were offered by the given
* Removes the given offered messages that were offered by the given
* contact.
* <p>
* Locking: message write.

View File

@@ -6,6 +6,7 @@ import static net.sf.briar.db.DatabaseConstants.BYTES_PER_SWEEP;
import static net.sf.briar.db.DatabaseConstants.CRITICAL_FREE_SPACE;
import static net.sf.briar.db.DatabaseConstants.MAX_BYTES_BETWEEN_SPACE_CHECKS;
import static net.sf.briar.db.DatabaseConstants.MAX_MS_BETWEEN_SPACE_CHECKS;
import static net.sf.briar.db.DatabaseConstants.MAX_OFFERED_MESSAGES;
import static net.sf.briar.db.DatabaseConstants.MIN_FREE_SPACE;
import java.io.IOException;
@@ -1363,14 +1364,16 @@ DatabaseCleaner.Callback {
try {
if(!db.containsContact(txn, c))
throw new NoSuchContactException();
int count = db.countOfferedMessages(txn, c);
for(MessageId m : o.getMessageIds()) {
if(db.containsVisibleMessage(txn, c, m)) {
db.raiseSeenFlag(txn, c, m);
db.raiseAckFlag(txn, c, m);
ack = true;
} else {
} else if(count < MAX_OFFERED_MESSAGES) {
db.addOfferedMessage(txn, c, m);
request = true;
count++;
}
}
db.commitTransaction(txn);

View File

@@ -2,6 +2,13 @@ package net.sf.briar.db;
interface DatabaseConstants {
/**
* The maximum number of offered messages from each contact that will be
* stored. If offers arrive more quickly than requests can be sent and this
* limit is reached, additional offers will not be stored.
*/
int MAX_OFFERED_MESSAGES = 1000;
// FIXME: These should be configurable
/**

View File

@@ -668,10 +668,20 @@ abstract class JdbcDatabase implements Database<Connection> {
}
public boolean addGroup(Connection txn, Group g) throws DbException {
if(maximumSubscriptionsReached(txn)) return false;
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = "INSERT INTO groups"
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, salt, visibleToAll)"
+ " VALUES (?, ?, ?, FALSE)";
ps = txn.prepareStatement(sql);
@@ -682,27 +692,6 @@ abstract class JdbcDatabase implements Database<Connection> {
if(affected != 1) throw new DbStateException();
ps.close();
return true;
} catch(SQLException e) {
tryToClose(ps);
throw new DbException(e);
}
}
private boolean maximumSubscriptionsReached(Connection txn)
throws DbException {
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = "SELECT COUNT (NULL) 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();
return count == MAX_SUBSCRIPTIONS;
} catch(SQLException e) {
tryToClose(rs);
tryToClose(ps);
@@ -772,7 +761,6 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
// FIXME: Limit the number of offers per contact
public void addOfferedMessage(Connection txn, ContactId c, MessageId m)
throws DbException {
PreparedStatement ps = null;
@@ -1130,6 +1118,29 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
public int countOfferedMessages(Connection txn, ContactId c)
throws DbException {
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = "SELECT COUNT (messageId) FROM offers "
+ " WHERE contactId = ?";
ps = txn.prepareStatement(sql);
ps.setInt(1, c.getInt());
rs = ps.executeQuery();
if(!rs.next()) throw new DbException();
int count = rs.getInt(1);
if(rs.next()) throw new DbException();
rs.close();
ps.close();
return count;
} catch(SQLException e) {
tryToClose(rs);
tryToClose(ps);
throw new DbException(e);
}
}
public Collection<GroupStatus> getAvailableGroups(Connection txn)
throws DbException {
PreparedStatement ps = null;