mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-15 12:19:54 +01:00
Removed peer moderation (may be restored after beta testing).
This commit is contained in:
@@ -20,7 +20,6 @@ import net.sf.briar.api.messaging.GroupId;
|
||||
import net.sf.briar.api.messaging.GroupStatus;
|
||||
import net.sf.briar.api.messaging.Message;
|
||||
import net.sf.briar.api.messaging.MessageId;
|
||||
import net.sf.briar.api.messaging.Rating;
|
||||
import net.sf.briar.api.messaging.RetentionAck;
|
||||
import net.sf.briar.api.messaging.RetentionUpdate;
|
||||
import net.sf.briar.api.messaging.SubscriptionAck;
|
||||
@@ -45,7 +44,6 @@ import net.sf.briar.api.transport.TemporarySecret;
|
||||
* <li> contact
|
||||
* <li> identity
|
||||
* <li> message
|
||||
* <li> rating
|
||||
* <li> retention
|
||||
* <li> subscription
|
||||
* <li> transport
|
||||
@@ -270,7 +268,7 @@ interface Database<T> {
|
||||
/**
|
||||
* Returns the headers of all messages in the given group.
|
||||
* <p>
|
||||
* Locking: message read, rating read.
|
||||
* Locking: message read.
|
||||
*/
|
||||
Collection<GroupMessageHeader> getGroupMessageHeaders(T txn, GroupId g)
|
||||
throws DbException;
|
||||
@@ -341,7 +339,7 @@ interface Database<T> {
|
||||
* Returns the headers of all private messages to or from the given
|
||||
* contact.
|
||||
* <p>
|
||||
* Locking: contact read, identity read, message read, rating read.
|
||||
* Locking: contact read, identity read, message read.
|
||||
*/
|
||||
Collection<PrivateMessageHeader> getPrivateMessageHeaders(T txn,
|
||||
ContactId c) throws DbException;
|
||||
@@ -364,15 +362,6 @@ interface Database<T> {
|
||||
Collection<MessageId> getMessagesToOffer(T txn, ContactId c,
|
||||
int maxMessages) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the number of children of the message identified by the given
|
||||
* ID that are present in the database and have sendability scores greater
|
||||
* than zero.
|
||||
* <p>
|
||||
* Locking: message read.
|
||||
*/
|
||||
int getNumberOfSendableChildren(T txn, MessageId m) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the message identified by the given ID, in serialised form.
|
||||
* <p>
|
||||
@@ -398,13 +387,6 @@ interface Database<T> {
|
||||
*/
|
||||
Collection<MessageId> getOldMessages(T txn, int size) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the user's rating for the given author.
|
||||
* <p>
|
||||
* Locking: rating read.
|
||||
*/
|
||||
Rating getRating(T txn, AuthorId a) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns true if the given message has been read.
|
||||
* <p>
|
||||
@@ -443,13 +425,6 @@ interface Database<T> {
|
||||
*/
|
||||
Collection<TemporarySecret> getSecrets(T txn) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the sendability score of the given group message.
|
||||
* <p>
|
||||
* Locking: message read.
|
||||
*/
|
||||
int getSendability(T txn, MessageId m) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the IDs of some messages that are eligible to be sent to the
|
||||
* given contact, with a total length less than or equal to the given
|
||||
@@ -669,13 +644,6 @@ interface Database<T> {
|
||||
*/
|
||||
void setLastConnected(T txn, ContactId c, long now) throws DbException;
|
||||
|
||||
/**
|
||||
* Sets the user's rating for the given author.
|
||||
* <p>
|
||||
* Locking: rating write.
|
||||
*/
|
||||
Rating setRating(T txn, AuthorId a, Rating r) throws DbException;
|
||||
|
||||
/**
|
||||
* Marks the given message read or unread and returns true if it was
|
||||
* previously read.
|
||||
@@ -714,13 +682,6 @@ interface Database<T> {
|
||||
boolean setRetentionTime(T txn, ContactId c, long retention, long version)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Sets the sendability score of the given message.
|
||||
* <p>
|
||||
* Locking: message write.
|
||||
*/
|
||||
void setSendability(T txn, MessageId m, int sendability) throws DbException;
|
||||
|
||||
/**
|
||||
* Marks the given message starred or unstarred and returns true if it was
|
||||
* previously starred.
|
||||
|
||||
@@ -2,7 +2,6 @@ package net.sf.briar.db;
|
||||
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static net.sf.briar.api.messaging.Rating.GOOD;
|
||||
import static net.sf.briar.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
|
||||
import static net.sf.briar.db.DatabaseConstants.BYTES_PER_SWEEP;
|
||||
import static net.sf.briar.db.DatabaseConstants.CRITICAL_FREE_SPACE;
|
||||
@@ -52,7 +51,6 @@ import net.sf.briar.api.db.event.LocalTransportsUpdatedEvent;
|
||||
import net.sf.briar.api.db.event.MessageExpiredEvent;
|
||||
import net.sf.briar.api.db.event.MessageReceivedEvent;
|
||||
import net.sf.briar.api.db.event.PrivateMessageAddedEvent;
|
||||
import net.sf.briar.api.db.event.RatingChangedEvent;
|
||||
import net.sf.briar.api.db.event.RemoteRetentionTimeUpdatedEvent;
|
||||
import net.sf.briar.api.db.event.RemoteSubscriptionsUpdatedEvent;
|
||||
import net.sf.briar.api.db.event.RemoteTransportsUpdatedEvent;
|
||||
@@ -68,7 +66,6 @@ import net.sf.briar.api.messaging.GroupStatus;
|
||||
import net.sf.briar.api.messaging.Message;
|
||||
import net.sf.briar.api.messaging.MessageId;
|
||||
import net.sf.briar.api.messaging.Offer;
|
||||
import net.sf.briar.api.messaging.Rating;
|
||||
import net.sf.briar.api.messaging.Request;
|
||||
import net.sf.briar.api.messaging.RetentionAck;
|
||||
import net.sf.briar.api.messaging.RetentionUpdate;
|
||||
@@ -105,8 +102,6 @@ DatabaseCleaner.Callback {
|
||||
new ReentrantReadWriteLock(true);
|
||||
private final ReentrantReadWriteLock messageLock =
|
||||
new ReentrantReadWriteLock(true);
|
||||
private final ReentrantReadWriteLock ratingLock =
|
||||
new ReentrantReadWriteLock(true);
|
||||
private final ReentrantReadWriteLock retentionLock =
|
||||
new ReentrantReadWriteLock(true);
|
||||
private final ReentrantReadWriteLock subscriptionLock =
|
||||
@@ -290,27 +285,22 @@ DatabaseCleaner.Callback {
|
||||
try {
|
||||
messageLock.writeLock().lock();
|
||||
try {
|
||||
ratingLock.readLock().lock();
|
||||
subscriptionLock.readLock().lock();
|
||||
try {
|
||||
subscriptionLock.readLock().lock();
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
// Don't store the message if the user has
|
||||
// unsubscribed from the group
|
||||
GroupId g = m.getGroup().getId();
|
||||
if(db.containsSubscription(txn, g))
|
||||
added = storeGroupMessage(txn, m, null);
|
||||
db.commitTransaction(txn);
|
||||
} catch(DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
subscriptionLock.readLock().unlock();
|
||||
// Don't store the message if the user has
|
||||
// unsubscribed from the group
|
||||
GroupId g = m.getGroup().getId();
|
||||
if(db.containsSubscription(txn, g))
|
||||
added = storeGroupMessage(txn, m, null);
|
||||
db.commitTransaction(txn);
|
||||
} catch(DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
ratingLock.readLock().unlock();
|
||||
subscriptionLock.readLock().unlock();
|
||||
}
|
||||
} finally {
|
||||
messageLock.writeLock().unlock();
|
||||
@@ -324,11 +314,10 @@ DatabaseCleaner.Callback {
|
||||
|
||||
/**
|
||||
* If the given message is already in the database, marks it as seen by the
|
||||
* sender and returns false. Otherwise stores the message, updates the
|
||||
* sendability of its ancestors if necessary, marks the message as seen by
|
||||
* the sender and unseen by all other contacts, and returns true.
|
||||
* sender and returns false. Otherwise stores the message, marks it as seen
|
||||
* by the sender and unseen by all other contacts, and returns true.
|
||||
* <p>
|
||||
* Locking: contact read, message write, rating read.
|
||||
* Locking: contact read, message write.
|
||||
* @param sender is null for a locally generated message.
|
||||
*/
|
||||
private boolean storeGroupMessage(T txn, Message m, ContactId sender)
|
||||
@@ -341,13 +330,8 @@ DatabaseCleaner.Callback {
|
||||
if(sender != null) db.addStatus(txn, sender, id, true);
|
||||
if(stored) {
|
||||
// Mark the message as unseen by other contacts
|
||||
for(ContactId c : db.getContactIds(txn)) {
|
||||
for(ContactId c : db.getContactIds(txn))
|
||||
if(!c.equals(sender)) db.addStatus(txn, c, id, false);
|
||||
}
|
||||
// Calculate and store the message's sendability
|
||||
int sendability = calculateSendability(txn, m);
|
||||
db.setSendability(txn, id, sendability);
|
||||
if(sendability > 0) updateAncestorSendability(txn, id, true);
|
||||
// Count the bytes stored
|
||||
synchronized(spaceLock) {
|
||||
bytesStoredSinceLastCheck += m.getSerialised().length;
|
||||
@@ -359,59 +343,6 @@ DatabaseCleaner.Callback {
|
||||
return stored;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates and returns the sendability score of a message.
|
||||
* <p>
|
||||
* Locking: message read, rating read.
|
||||
*/
|
||||
private int calculateSendability(T txn, Message m) throws DbException {
|
||||
int sendability = 0;
|
||||
// One point for a good rating
|
||||
Author a = m.getAuthor();
|
||||
if(a != null && db.getRating(txn, a.getId()) == GOOD) sendability++;
|
||||
// One point per sendable child (backward inclusion)
|
||||
sendability += db.getNumberOfSendableChildren(txn, m.getId());
|
||||
return sendability;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Iteratively updates the sendability of a message's ancestors to reflect
|
||||
* a change in the message's sendability. Returns the number of ancestors
|
||||
* that have changed from sendable to not sendable, or vice versa.
|
||||
* <p>
|
||||
* Locking: message write.
|
||||
* @param increment true if the message's sendability has changed from 0 to
|
||||
* greater than 0, or false if it has changed from greater than 0 to 0.
|
||||
*/
|
||||
private int updateAncestorSendability(T txn, MessageId m, boolean increment)
|
||||
throws DbException {
|
||||
int affected = 0;
|
||||
boolean changed = true;
|
||||
while(changed) {
|
||||
// Stop if the message has no parent, or the parent isn't in the
|
||||
// database, or the parent belongs to a different group
|
||||
MessageId parent = db.getGroupMessageParent(txn, m);
|
||||
if(parent == null) break;
|
||||
// Increment or decrement the parent's sendability
|
||||
int parentSendability = db.getSendability(txn, parent);
|
||||
if(increment) {
|
||||
parentSendability++;
|
||||
changed = parentSendability == 1;
|
||||
if(changed) affected++;
|
||||
} else {
|
||||
assert parentSendability > 0;
|
||||
parentSendability--;
|
||||
changed = parentSendability == 0;
|
||||
if(changed) affected++;
|
||||
}
|
||||
db.setSendability(txn, parent, parentSendability);
|
||||
// Move on to the parent's parent
|
||||
m = parent;
|
||||
}
|
||||
return affected;
|
||||
}
|
||||
|
||||
public void addLocalPrivateMessage(Message m, ContactId c)
|
||||
throws DbException {
|
||||
boolean added;
|
||||
@@ -967,27 +898,22 @@ DatabaseCleaner.Callback {
|
||||
throws DbException {
|
||||
messageLock.readLock().lock();
|
||||
try {
|
||||
ratingLock.readLock().lock();
|
||||
subscriptionLock.readLock().lock();
|
||||
try {
|
||||
subscriptionLock.readLock().lock();
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
if(!db.containsSubscription(txn, g))
|
||||
throw new NoSuchSubscriptionException();
|
||||
Collection<GroupMessageHeader> headers =
|
||||
db.getGroupMessageHeaders(txn, g);
|
||||
db.commitTransaction(txn);
|
||||
return headers;
|
||||
} catch(DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
subscriptionLock.readLock().unlock();
|
||||
if(!db.containsSubscription(txn, g))
|
||||
throw new NoSuchSubscriptionException();
|
||||
Collection<GroupMessageHeader> headers =
|
||||
db.getGroupMessageHeaders(txn, g);
|
||||
db.commitTransaction(txn);
|
||||
return headers;
|
||||
} catch(DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
ratingLock.readLock().unlock();
|
||||
subscriptionLock.readLock().unlock();
|
||||
}
|
||||
} finally {
|
||||
messageLock.readLock().unlock();
|
||||
@@ -1111,20 +1037,15 @@ DatabaseCleaner.Callback {
|
||||
try {
|
||||
messageLock.readLock().lock();
|
||||
try {
|
||||
ratingLock.readLock().lock();
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
Collection<PrivateMessageHeader> headers =
|
||||
db.getPrivateMessageHeaders(txn, c);
|
||||
db.commitTransaction(txn);
|
||||
return headers;
|
||||
} catch(DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
ratingLock.readLock().unlock();
|
||||
Collection<PrivateMessageHeader> headers =
|
||||
db.getPrivateMessageHeaders(txn, c);
|
||||
db.commitTransaction(txn);
|
||||
return headers;
|
||||
} catch(DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
messageLock.readLock().unlock();
|
||||
@@ -1137,23 +1058,6 @@ DatabaseCleaner.Callback {
|
||||
}
|
||||
}
|
||||
|
||||
public Rating getRating(AuthorId a) throws DbException {
|
||||
ratingLock.readLock().lock();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
Rating r = db.getRating(txn, a);
|
||||
db.commitTransaction(txn);
|
||||
return r;
|
||||
} catch(DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
ratingLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getReadFlag(MessageId m) throws DbException {
|
||||
messageLock.readLock().lock();
|
||||
try {
|
||||
@@ -1463,26 +1367,21 @@ DatabaseCleaner.Callback {
|
||||
try {
|
||||
messageLock.writeLock().lock();
|
||||
try {
|
||||
ratingLock.readLock().lock();
|
||||
subscriptionLock.readLock().lock();
|
||||
try {
|
||||
subscriptionLock.readLock().lock();
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
if(!db.containsContact(txn, c))
|
||||
throw new NoSuchContactException();
|
||||
added = storeMessage(txn, c, m);
|
||||
db.addMessageToAck(txn, c, m.getId());
|
||||
db.commitTransaction(txn);
|
||||
} catch(DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
subscriptionLock.readLock().unlock();
|
||||
if(!db.containsContact(txn, c))
|
||||
throw new NoSuchContactException();
|
||||
added = storeMessage(txn, c, m);
|
||||
db.addMessageToAck(txn, c, m.getId());
|
||||
db.commitTransaction(txn);
|
||||
} catch(DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
ratingLock.readLock().unlock();
|
||||
subscriptionLock.readLock().unlock();
|
||||
}
|
||||
} finally {
|
||||
messageLock.writeLock().unlock();
|
||||
@@ -1502,7 +1401,7 @@ DatabaseCleaner.Callback {
|
||||
* Attempts to store a message received from the given contact, and returns
|
||||
* true if it was stored.
|
||||
* <p>
|
||||
* Locking: contact read, message write, rating read, subscription read.
|
||||
* Locking: contact read, message write, subscription read.
|
||||
*/
|
||||
private boolean storeMessage(T txn, ContactId c, Message m)
|
||||
throws DbException {
|
||||
@@ -1823,35 +1722,6 @@ DatabaseCleaner.Callback {
|
||||
}
|
||||
}
|
||||
|
||||
public void setRating(AuthorId a, Rating r) throws DbException {
|
||||
boolean changed;
|
||||
messageLock.writeLock().lock();
|
||||
try {
|
||||
ratingLock.writeLock().lock();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
Rating old = db.setRating(txn, a, r);
|
||||
changed = (old != r);
|
||||
// Update the sendability of the author's messages
|
||||
if(r == GOOD && old != GOOD)
|
||||
updateAuthorSendability(txn, a, true);
|
||||
else if(r != GOOD && old == GOOD)
|
||||
updateAuthorSendability(txn, a, false);
|
||||
db.commitTransaction(txn);
|
||||
} catch(DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
ratingLock.writeLock().unlock();
|
||||
}
|
||||
} finally {
|
||||
messageLock.writeLock().unlock();
|
||||
}
|
||||
if(changed) callListeners(new RatingChangedEvent(a, r));
|
||||
}
|
||||
|
||||
public boolean setReadFlag(MessageId m, boolean read) throws DbException {
|
||||
messageLock.writeLock().lock();
|
||||
try {
|
||||
@@ -1925,31 +1795,6 @@ DatabaseCleaner.Callback {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the sendability of all group messages posted by the given
|
||||
* author, and the ancestors of those messages if necessary.
|
||||
* <p>
|
||||
* Locking: message write.
|
||||
* @param increment true if the user's rating for the author has changed
|
||||
* from not good to good, or false if it has changed from good to not good.
|
||||
*/
|
||||
private void updateAuthorSendability(T txn, AuthorId a, boolean increment)
|
||||
throws DbException {
|
||||
for(MessageId id : db.getGroupMessages(txn, a)) {
|
||||
int sendability = db.getSendability(txn, id);
|
||||
if(increment) {
|
||||
db.setSendability(txn, id, sendability + 1);
|
||||
if(sendability == 0)
|
||||
updateAncestorSendability(txn, id, true);
|
||||
} else {
|
||||
assert sendability > 0;
|
||||
db.setSendability(txn, id, sendability - 1);
|
||||
if(sendability == 1)
|
||||
updateAncestorSendability(txn, id, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean setStarredFlag(MessageId m, boolean starred)
|
||||
throws DbException {
|
||||
messageLock.writeLock().lock();
|
||||
@@ -2134,7 +1979,7 @@ DatabaseCleaner.Callback {
|
||||
try {
|
||||
expired = db.getOldMessages(txn, size);
|
||||
if(!expired.isEmpty()) {
|
||||
for(MessageId m : expired) removeMessage(txn, m);
|
||||
for(MessageId m : expired) db.removeMessage(txn, m);
|
||||
db.incrementRetentionVersions(txn);
|
||||
if(LOG.isLoggable(INFO))
|
||||
LOG.info("Expired " + expired.size() + " messages");
|
||||
@@ -2155,19 +2000,6 @@ DatabaseCleaner.Callback {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the given message (and all associated state) from the database.
|
||||
* <p>
|
||||
* Locking: message write.
|
||||
*/
|
||||
private void removeMessage(T txn, MessageId m) throws DbException {
|
||||
int sendability = db.getSendability(txn, m);
|
||||
// If the message is sendable, deleting it may affect its ancestors'
|
||||
// sendability (backward inclusion)
|
||||
if(sendability > 0) updateAncestorSendability(txn, m, false);
|
||||
db.removeMessage(txn, m);
|
||||
}
|
||||
|
||||
public boolean shouldCheckFreeSpace() {
|
||||
synchronized(spaceLock) {
|
||||
long now = clock.currentTimeMillis();
|
||||
|
||||
@@ -6,7 +6,6 @@ import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static net.sf.briar.api.messaging.MessagingConstants.MAX_SUBSCRIPTIONS;
|
||||
import static net.sf.briar.api.messaging.MessagingConstants.RETENTION_MODULUS;
|
||||
import static net.sf.briar.api.messaging.Rating.UNRATED;
|
||||
import static net.sf.briar.db.ExponentialBackoff.calculateExpiry;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -45,7 +44,6 @@ import net.sf.briar.api.messaging.GroupId;
|
||||
import net.sf.briar.api.messaging.GroupStatus;
|
||||
import net.sf.briar.api.messaging.Message;
|
||||
import net.sf.briar.api.messaging.MessageId;
|
||||
import net.sf.briar.api.messaging.Rating;
|
||||
import net.sf.briar.api.messaging.RetentionAck;
|
||||
import net.sf.briar.api.messaging.RetentionUpdate;
|
||||
import net.sf.briar.api.messaging.SubscriptionAck;
|
||||
@@ -154,7 +152,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
+ " bodyLength INT NOT NULL,"
|
||||
+ " raw BLOB NOT NULL,"
|
||||
+ " incoming BOOLEAN NOT NULL,"
|
||||
+ " sendability INT UNSIGNED," // Null for private messages
|
||||
+ " contactId INT UNSIGNED," // Null for group messages
|
||||
+ " read BOOLEAN NOT NULL,"
|
||||
+ " starred BOOLEAN NOT NULL,"
|
||||
@@ -166,18 +163,12 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
+ " REFERENCES contacts (contactId)"
|
||||
+ " ON DELETE CASCADE)";
|
||||
|
||||
private static final String INDEX_MESSAGES_BY_PARENT =
|
||||
"CREATE INDEX messagesByParent ON messages (parentId)";
|
||||
|
||||
private static final String INDEX_MESSAGES_BY_AUTHOR =
|
||||
"CREATE INDEX messagesByAuthor ON messages (authorId)";
|
||||
|
||||
private static final String INDEX_MESSAGES_BY_TIMESTAMP =
|
||||
"CREATE INDEX messagesByTimestamp ON messages (timestamp)";
|
||||
|
||||
private static final String INDEX_MESSAGES_BY_SENDABILITY =
|
||||
"CREATE INDEX messagesBySendability ON messages (sendability)";
|
||||
|
||||
// Locking: message
|
||||
private static final String CREATE_MESSAGES_TO_ACK =
|
||||
"CREATE TABLE messagesToAck"
|
||||
@@ -210,13 +201,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
private static final String INDEX_STATUSES_BY_CONTACT =
|
||||
"CREATE INDEX statusesByContact ON statuses (contactId)";
|
||||
|
||||
// Locking: rating
|
||||
private static final String CREATE_RATINGS =
|
||||
"CREATE TABLE ratings"
|
||||
+ " (authorId HASH NOT NULL,"
|
||||
+ " rating SMALLINT NOT NULL,"
|
||||
+ " PRIMARY KEY (authorId))";
|
||||
|
||||
// Locking: retention
|
||||
private static final String CREATE_RETENTION_VERSIONS =
|
||||
"CREATE TABLE retentionVersions"
|
||||
@@ -403,15 +387,12 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
s.executeUpdate(insertTypeNames(CREATE_CONTACT_GROUPS));
|
||||
s.executeUpdate(insertTypeNames(CREATE_GROUP_VERSIONS));
|
||||
s.executeUpdate(insertTypeNames(CREATE_MESSAGES));
|
||||
s.executeUpdate(INDEX_MESSAGES_BY_PARENT);
|
||||
s.executeUpdate(INDEX_MESSAGES_BY_AUTHOR);
|
||||
s.executeUpdate(INDEX_MESSAGES_BY_TIMESTAMP);
|
||||
s.executeUpdate(INDEX_MESSAGES_BY_SENDABILITY);
|
||||
s.executeUpdate(insertTypeNames(CREATE_MESSAGES_TO_ACK));
|
||||
s.executeUpdate(insertTypeNames(CREATE_STATUSES));
|
||||
s.executeUpdate(INDEX_STATUSES_BY_MESSAGE);
|
||||
s.executeUpdate(INDEX_STATUSES_BY_CONTACT);
|
||||
s.executeUpdate(insertTypeNames(CREATE_RATINGS));
|
||||
s.executeUpdate(insertTypeNames(CREATE_RETENTION_VERSIONS));
|
||||
s.executeUpdate(insertTypeNames(CREATE_TRANSPORTS));
|
||||
s.executeUpdate(insertTypeNames(CREATE_TRANSPORT_CONFIGS));
|
||||
@@ -681,8 +662,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
String sql = "INSERT INTO messages (messageId, parentId, groupId,"
|
||||
+ " authorId, authorName, authorKey, contentType, subject,"
|
||||
+ " timestamp, length, bodyStart, bodyLength, raw,"
|
||||
+ " incoming, sendability, read, starred)"
|
||||
+ " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0,"
|
||||
+ " incoming, read, starred)"
|
||||
+ " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,"
|
||||
+ " FALSE, FALSE)";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setBytes(1, m.getId().getBytes());
|
||||
@@ -1307,12 +1288,10 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = "SELECT messageId, parentId, m.authorId, authorName,"
|
||||
+ " authorKey, rating, contentType, subject, timestamp,"
|
||||
+ " read, starred"
|
||||
+ " FROM messages AS m"
|
||||
+ " LEFT OUTER JOIN ratings AS r"
|
||||
+ " ON m.authorId = r.authorId"
|
||||
String sql = "SELECT messageId, parentId, authorId, authorName,"
|
||||
+ " authorKey, contentType, subject, timestamp, read,"
|
||||
+ " starred"
|
||||
+ " FROM messages"
|
||||
+ " WHERE groupId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setBytes(1, g.getBytes());
|
||||
@@ -1324,27 +1303,22 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
byte[] b = rs.getBytes(2);
|
||||
MessageId parent = b == null ? null : new MessageId(b);
|
||||
Author author;
|
||||
Rating rating;
|
||||
b = rs.getBytes(3);
|
||||
if(b == null) {
|
||||
author = null;
|
||||
rating = UNRATED;
|
||||
} else {
|
||||
AuthorId authorId = new AuthorId(b);
|
||||
String authorName = rs.getString(4);
|
||||
byte[] authorKey = rs.getBytes(5);
|
||||
author = new Author(authorId, authorName, authorKey);
|
||||
// NULL == 0 == UNRATED
|
||||
rating = Rating.values()[rs.getByte(6)];
|
||||
}
|
||||
String contentType = rs.getString(7);
|
||||
String subject = rs.getString(8);
|
||||
long timestamp = rs.getLong(9);
|
||||
boolean read = rs.getBoolean(10);
|
||||
boolean starred = rs.getBoolean(11);
|
||||
String contentType = rs.getString(6);
|
||||
String subject = rs.getString(7);
|
||||
long timestamp = rs.getLong(8);
|
||||
boolean read = rs.getBoolean(9);
|
||||
boolean starred = rs.getBoolean(10);
|
||||
headers.add(new GroupMessageHeader(id, parent, author,
|
||||
contentType, subject, timestamp, read, starred, rating,
|
||||
g));
|
||||
contentType, subject, timestamp, read, starred, g));
|
||||
}
|
||||
rs.close();
|
||||
ps.close();
|
||||
@@ -1626,7 +1600,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
+ " WHERE cg.contactId = ?"
|
||||
+ " AND timestamp >= retention"
|
||||
+ " AND seen = FALSE AND s.expiry < ?"
|
||||
+ " AND sendability > 0"
|
||||
+ " ORDER BY timestamp DESC LIMIT ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setInt(1, c.getInt());
|
||||
@@ -1644,41 +1617,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
}
|
||||
|
||||
public int getNumberOfSendableChildren(Connection txn, MessageId m)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
// Children in other groups should not be counted
|
||||
String sql = "SELECT groupId FROM messages WHERE messageId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setBytes(1, m.getBytes());
|
||||
rs = ps.executeQuery();
|
||||
if(!rs.next()) throw new DbStateException();
|
||||
byte[] groupId = rs.getBytes(1);
|
||||
if(rs.next()) throw new DbStateException();
|
||||
rs.close();
|
||||
ps.close();
|
||||
sql = "SELECT COUNT (messageId) FROM messages"
|
||||
+ " WHERE parentId = ? AND groupId = ?"
|
||||
+ " AND sendability > 0";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setBytes(1, m.getBytes());
|
||||
ps.setBytes(2, groupId);
|
||||
rs = ps.executeQuery();
|
||||
if(!rs.next()) throw new DbStateException();
|
||||
int count = rs.getInt(1);
|
||||
if(rs.next()) throw new DbStateException();
|
||||
rs.close();
|
||||
ps.close();
|
||||
return count;
|
||||
} catch(SQLException e) {
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<MessageId> getOldMessages(Connection txn, int capacity)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
@@ -1713,13 +1651,10 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
try {
|
||||
// Get the incoming message headers
|
||||
String sql = "SELECT m.messageId, parentId, contentType, subject,"
|
||||
+ " timestamp, read, starred, c.authorId, name, publicKey,"
|
||||
+ " rating"
|
||||
+ " timestamp, read, starred, c.authorId, name, publicKey"
|
||||
+ " FROM messages AS m"
|
||||
+ " JOIN contacts AS c"
|
||||
+ " ON m.contactId = c.contactId"
|
||||
+ " LEFT OUTER JOIN ratings AS r"
|
||||
+ " ON c.authorId = r.authorId"
|
||||
+ " WHERE m.contactId = ?"
|
||||
+ " AND groupId IS NULL"
|
||||
+ " AND incoming = TRUE";
|
||||
@@ -1741,25 +1676,21 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
String authorName = rs.getString(9);
|
||||
byte[] authorKey = rs.getBytes(10);
|
||||
Author author = new Author(authorId, authorName, authorKey);
|
||||
// NULL == 0 == UNRATED
|
||||
Rating rating = Rating.values()[rs.getByte(11)];
|
||||
headers.add(new PrivateMessageHeader(id, parent, author,
|
||||
contentType, subject, timestamp, read, starred, rating,
|
||||
c, true));
|
||||
contentType, subject, timestamp, read, starred, c,
|
||||
true));
|
||||
}
|
||||
rs.close();
|
||||
ps.close();
|
||||
// Get the outgoing message headers
|
||||
sql = "SELECT m.messageId, parentId, contentType, subject,"
|
||||
+ " timestamp, read, starred, a.authorId, a.name,"
|
||||
+ " a.publicKey, rating"
|
||||
+ " a.publicKey"
|
||||
+ " FROM messages AS m"
|
||||
+ " JOIN contacts AS c"
|
||||
+ " ON m.contactId = c.contactId"
|
||||
+ " JOIN localAuthors AS a"
|
||||
+ " ON c.localAuthorId = a.authorId"
|
||||
+ " LEFT OUTER JOIN ratings AS r"
|
||||
+ " ON c.localAuthorId = r.authorId"
|
||||
+ " WHERE m.contactId = ?"
|
||||
+ " AND groupId IS NULL"
|
||||
+ " AND incoming = FALSE";
|
||||
@@ -1779,11 +1710,9 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
String authorName = rs.getString(9);
|
||||
byte[] authorKey = rs.getBytes(10);
|
||||
Author author = new Author(authorId, authorName, authorKey);
|
||||
// NULL == 0 == UNRATED
|
||||
Rating rating = Rating.values()[rs.getByte(11)];
|
||||
headers.add(new PrivateMessageHeader(id, parent, author,
|
||||
contentType, subject, timestamp, read, starred, rating,
|
||||
c, false));
|
||||
contentType, subject, timestamp, read, starred, c,
|
||||
false));
|
||||
}
|
||||
rs.close();
|
||||
ps.close();
|
||||
@@ -1795,28 +1724,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
}
|
||||
|
||||
public Rating getRating(Connection txn, AuthorId a) throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = "SELECT rating FROM ratings WHERE authorId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setBytes(1, a.getBytes());
|
||||
rs = ps.executeQuery();
|
||||
Rating r;
|
||||
if(rs.next()) r = Rating.values()[rs.getByte(1)];
|
||||
else r = UNRATED;
|
||||
if(rs.next()) throw new DbStateException();
|
||||
rs.close();
|
||||
ps.close();
|
||||
return r;
|
||||
} catch(SQLException e) {
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getRawMessage(Connection txn, MessageId m)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
@@ -1883,8 +1790,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
+ " WHERE m.messageId = ?"
|
||||
+ " AND cg.contactId = ?"
|
||||
+ " AND timestamp >= retention"
|
||||
+ " AND seen = FALSE AND s.expiry < ?"
|
||||
+ " AND sendability > 0";
|
||||
+ " AND seen = FALSE AND s.expiry < ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setBytes(1, m.getBytes());
|
||||
ps.setInt(2, c.getInt());
|
||||
@@ -2080,27 +1986,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
}
|
||||
|
||||
public int getSendability(Connection txn, MessageId m) throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = "SELECT sendability FROM messages WHERE messageId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setBytes(1, m.getBytes());
|
||||
rs = ps.executeQuery();
|
||||
if(!rs.next()) throw new DbStateException();
|
||||
int sendability = rs.getInt(1);
|
||||
if(rs.next()) throw new DbStateException();
|
||||
rs.close();
|
||||
ps.close();
|
||||
return sendability;
|
||||
} catch(SQLException e) {
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<MessageId> getSendableMessages(Connection txn,
|
||||
ContactId c, int maxLength) throws DbException {
|
||||
long now = clock.currentTimeMillis();
|
||||
@@ -2143,7 +2028,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
+ " WHERE cg.contactId = ?"
|
||||
+ " AND timestamp >= retention"
|
||||
+ " AND seen = FALSE AND s.expiry < ?"
|
||||
+ " AND sendability > 0"
|
||||
+ " ORDER BY timestamp DESC";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setInt(1, c.getInt());
|
||||
@@ -2587,7 +2471,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
+ " WHERE cg.contactId = ?"
|
||||
+ " AND timestamp >= retention"
|
||||
+ " AND seen = FALSE AND s.expiry < ?"
|
||||
+ " AND sendability > 0"
|
||||
+ " LIMIT 1";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setInt(1, c.getInt());
|
||||
@@ -2940,53 +2823,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
}
|
||||
|
||||
public Rating setRating(Connection txn, AuthorId a, Rating r)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = "SELECT rating FROM ratings WHERE authorId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setBytes(1, a.getBytes());
|
||||
rs = ps.executeQuery();
|
||||
Rating old = UNRATED;
|
||||
boolean exists = false;
|
||||
if(rs.next()) {
|
||||
old = Rating.values()[rs.getByte(1)];
|
||||
exists = true;
|
||||
}
|
||||
if(rs.next()) throw new DbStateException();
|
||||
rs.close();
|
||||
ps.close();
|
||||
if(old == r) return old;
|
||||
if(exists) {
|
||||
// A rating row exists - update it
|
||||
sql = "UPDATE ratings SET rating = ? WHERE authorId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setByte(1, (byte) r.ordinal());
|
||||
ps.setBytes(2, a.getBytes());
|
||||
int affected = ps.executeUpdate();
|
||||
if(affected != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} else {
|
||||
// No rating row exists - create one
|
||||
sql = "INSERT INTO ratings (authorId, rating)"
|
||||
+ " VALUES (?, ?)";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setBytes(1, a.getBytes());
|
||||
ps.setByte(2, (byte) r.ordinal());
|
||||
int affected = ps.executeUpdate();
|
||||
if(affected != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
}
|
||||
return old;
|
||||
} catch(SQLException e) {
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean setReadFlag(Connection txn, MessageId m, boolean read)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
@@ -3181,24 +3017,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
}
|
||||
|
||||
public void setSendability(Connection txn, MessageId m, int sendability)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
try {
|
||||
String sql = "UPDATE messages SET sendability = ?"
|
||||
+ " WHERE messageId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setInt(1, sendability);
|
||||
ps.setBytes(2, m.getBytes());
|
||||
int affected = ps.executeUpdate();
|
||||
if(affected != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch(SQLException e) {
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean setStarredFlag(Connection txn, MessageId m, boolean starred)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
|
||||
@@ -9,7 +9,6 @@ import static net.sf.briar.api.TransportPropertyConstants.MAX_PROPERTIES_PER_TRA
|
||||
import static net.sf.briar.api.TransportPropertyConstants.MAX_PROPERTY_LENGTH;
|
||||
import static net.sf.briar.api.invitation.InvitationConstants.CONNECTION_TIMEOUT;
|
||||
import static net.sf.briar.api.invitation.InvitationConstants.HASH_LENGTH;
|
||||
import static net.sf.briar.api.messaging.Rating.GOOD;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
@@ -263,8 +262,6 @@ abstract class Connector extends Thread {
|
||||
long epoch, boolean alice) throws DbException {
|
||||
// Add the contact to the database
|
||||
contactId = db.addContact(remoteAuthor, localAuthor.getId());
|
||||
// Add a positive rating for the contact's pseudonym
|
||||
db.setRating(remoteAuthor.getId(), GOOD);
|
||||
// Store the remote transport properties
|
||||
db.setRemoteProperties(contactId, remoteProps);
|
||||
// Create an endpoint for each transport shared with the contact
|
||||
|
||||
@@ -3,7 +3,6 @@ package net.sf.briar.messaging.duplex;
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static net.sf.briar.api.messaging.MessagingConstants.MAX_PACKET_LENGTH;
|
||||
import static net.sf.briar.api.messaging.Rating.GOOD;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -35,7 +34,6 @@ import net.sf.briar.api.db.event.LocalTransportsUpdatedEvent;
|
||||
import net.sf.briar.api.db.event.MessageExpiredEvent;
|
||||
import net.sf.briar.api.db.event.MessageReceivedEvent;
|
||||
import net.sf.briar.api.db.event.PrivateMessageAddedEvent;
|
||||
import net.sf.briar.api.db.event.RatingChangedEvent;
|
||||
import net.sf.briar.api.db.event.RemoteRetentionTimeUpdatedEvent;
|
||||
import net.sf.briar.api.db.event.RemoteSubscriptionsUpdatedEvent;
|
||||
import net.sf.briar.api.db.event.RemoteTransportsUpdatedEvent;
|
||||
@@ -157,10 +155,6 @@ abstract class DuplexConnection implements DatabaseListener {
|
||||
if(canSendOffer.getAndSet(false))
|
||||
dbExecutor.execute(new GenerateOffer());
|
||||
}
|
||||
} else if(e instanceof RatingChangedEvent) {
|
||||
RatingChangedEvent r = (RatingChangedEvent) e;
|
||||
if(r.getRating() == GOOD && canSendOffer.getAndSet(false))
|
||||
dbExecutor.execute(new GenerateOffer());
|
||||
} else if(e instanceof RemoteRetentionTimeUpdatedEvent) {
|
||||
dbExecutor.execute(new GenerateRetentionAck());
|
||||
} else if(e instanceof RemoteSubscriptionsUpdatedEvent) {
|
||||
|
||||
Reference in New Issue
Block a user