mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-20 06:39:54 +01:00
Removed peer moderation (may be restored after beta testing).
This commit is contained in:
@@ -13,7 +13,6 @@ import static java.util.logging.Level.INFO;
|
|||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static net.sf.briar.android.util.CommonLayoutParams.MATCH_MATCH;
|
import static net.sf.briar.android.util.CommonLayoutParams.MATCH_MATCH;
|
||||||
import static net.sf.briar.android.util.CommonLayoutParams.WRAP_WRAP;
|
import static net.sf.briar.android.util.CommonLayoutParams.WRAP_WRAP;
|
||||||
import static net.sf.briar.api.messaging.Rating.GOOD;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -168,7 +167,6 @@ public class HomeScreenActivity extends RoboActivity {
|
|||||||
lifecycleManager.waitForDatabase();
|
lifecycleManager.waitForDatabase();
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
db.addLocalAuthor(a);
|
db.addLocalAuthor(a);
|
||||||
db.setRating(a.getId(), GOOD);
|
|
||||||
long duration = System.currentTimeMillis() - now;
|
long duration = System.currentTimeMillis() - now;
|
||||||
if(LOG.isLoggable(INFO))
|
if(LOG.isLoggable(INFO))
|
||||||
LOG.info("Storing author took " + duration + " ms");
|
LOG.info("Storing author took " + duration + " ms");
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import static java.util.logging.Level.INFO;
|
|||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static net.sf.briar.android.util.CommonLayoutParams.MATCH_MATCH;
|
import static net.sf.briar.android.util.CommonLayoutParams.MATCH_MATCH;
|
||||||
import static net.sf.briar.android.util.CommonLayoutParams.WRAP_WRAP;
|
import static net.sf.briar.android.util.CommonLayoutParams.WRAP_WRAP;
|
||||||
import static net.sf.briar.api.messaging.Rating.GOOD;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
@@ -143,7 +142,6 @@ implements OnEditorActionListener, OnClickListener {
|
|||||||
lifecycleManager.waitForDatabase();
|
lifecycleManager.waitForDatabase();
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
db.addLocalAuthor(a);
|
db.addLocalAuthor(a);
|
||||||
db.setRating(a.getId(), GOOD);
|
|
||||||
long duration = System.currentTimeMillis() - now;
|
long duration = System.currentTimeMillis() - now;
|
||||||
if(LOG.isLoggable(INFO))
|
if(LOG.isLoggable(INFO))
|
||||||
LOG.info("Storing author took " + duration + " ms");
|
LOG.info("Storing author took " + duration + " ms");
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import net.sf.briar.api.messaging.GroupStatus;
|
|||||||
import net.sf.briar.api.messaging.Message;
|
import net.sf.briar.api.messaging.Message;
|
||||||
import net.sf.briar.api.messaging.MessageId;
|
import net.sf.briar.api.messaging.MessageId;
|
||||||
import net.sf.briar.api.messaging.Offer;
|
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.Request;
|
||||||
import net.sf.briar.api.messaging.RetentionAck;
|
import net.sf.briar.api.messaging.RetentionAck;
|
||||||
import net.sf.briar.api.messaging.RetentionUpdate;
|
import net.sf.briar.api.messaging.RetentionUpdate;
|
||||||
@@ -204,9 +203,6 @@ public interface DatabaseComponent {
|
|||||||
Collection<PrivateMessageHeader> getPrivateMessageHeaders(ContactId c)
|
Collection<PrivateMessageHeader> getPrivateMessageHeaders(ContactId c)
|
||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
/** Returns the user's rating for the given author. */
|
|
||||||
Rating getRating(AuthorId a) throws DbException;
|
|
||||||
|
|
||||||
/** Returns true if the given message has been read. */
|
/** Returns true if the given message has been read. */
|
||||||
boolean getReadFlag(MessageId m) throws DbException;
|
boolean getReadFlag(MessageId m) throws DbException;
|
||||||
|
|
||||||
@@ -313,9 +309,6 @@ public interface DatabaseComponent {
|
|||||||
void setConnectionWindow(ContactId c, TransportId t, long period,
|
void setConnectionWindow(ContactId c, TransportId t, long period,
|
||||||
long centre, byte[] bitmap) throws DbException;
|
long centre, byte[] bitmap) throws DbException;
|
||||||
|
|
||||||
/** Records the user's rating for the given author. */
|
|
||||||
void setRating(AuthorId a, Rating r) throws DbException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks the given message read or unread and returns true if it was
|
* Marks the given message read or unread and returns true if it was
|
||||||
* previously read.
|
* previously read.
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package net.sf.briar.api.db;
|
|||||||
import net.sf.briar.api.Author;
|
import net.sf.briar.api.Author;
|
||||||
import net.sf.briar.api.messaging.GroupId;
|
import net.sf.briar.api.messaging.GroupId;
|
||||||
import net.sf.briar.api.messaging.MessageId;
|
import net.sf.briar.api.messaging.MessageId;
|
||||||
import net.sf.briar.api.messaging.Rating;
|
|
||||||
|
|
||||||
public class GroupMessageHeader extends MessageHeader {
|
public class GroupMessageHeader extends MessageHeader {
|
||||||
|
|
||||||
@@ -11,9 +10,9 @@ public class GroupMessageHeader extends MessageHeader {
|
|||||||
|
|
||||||
public GroupMessageHeader(MessageId id, MessageId parent, Author author,
|
public GroupMessageHeader(MessageId id, MessageId parent, Author author,
|
||||||
String contentType, String subject, long timestamp, boolean read,
|
String contentType, String subject, long timestamp, boolean read,
|
||||||
boolean starred, Rating rating, GroupId groupId) {
|
boolean starred, GroupId groupId) {
|
||||||
super(id, parent, author, contentType, subject, timestamp, read,
|
super(id, parent, author, contentType, subject, timestamp, read,
|
||||||
starred, rating);
|
starred);
|
||||||
this.groupId = groupId;
|
this.groupId = groupId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package net.sf.briar.api.db;
|
|||||||
|
|
||||||
import net.sf.briar.api.Author;
|
import net.sf.briar.api.Author;
|
||||||
import net.sf.briar.api.messaging.MessageId;
|
import net.sf.briar.api.messaging.MessageId;
|
||||||
import net.sf.briar.api.messaging.Rating;
|
|
||||||
|
|
||||||
public abstract class MessageHeader {
|
public abstract class MessageHeader {
|
||||||
|
|
||||||
@@ -11,11 +10,10 @@ public abstract class MessageHeader {
|
|||||||
private final String contentType, subject;
|
private final String contentType, subject;
|
||||||
private final long timestamp;
|
private final long timestamp;
|
||||||
private final boolean read, starred;
|
private final boolean read, starred;
|
||||||
private final Rating rating;
|
|
||||||
|
|
||||||
protected MessageHeader(MessageId id, MessageId parent, Author author,
|
protected MessageHeader(MessageId id, MessageId parent, Author author,
|
||||||
String contentType, String subject, long timestamp, boolean read,
|
String contentType, String subject, long timestamp, boolean read,
|
||||||
boolean starred, Rating rating) {
|
boolean starred) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.author = author;
|
this.author = author;
|
||||||
@@ -24,7 +22,6 @@ public abstract class MessageHeader {
|
|||||||
this.timestamp = timestamp;
|
this.timestamp = timestamp;
|
||||||
this.read = read;
|
this.read = read;
|
||||||
this.starred = starred;
|
this.starred = starred;
|
||||||
this.rating = rating;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the message's unique identifier. */
|
/** Returns the message's unique identifier. */
|
||||||
@@ -71,12 +68,4 @@ public abstract class MessageHeader {
|
|||||||
public boolean isStarred() {
|
public boolean isStarred() {
|
||||||
return starred;
|
return starred;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the rating for the message's author, or Rating.UNRATED if this
|
|
||||||
* is an anonymous message.
|
|
||||||
*/
|
|
||||||
public Rating getRating() {
|
|
||||||
return rating;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package net.sf.briar.api.db;
|
|||||||
import net.sf.briar.api.Author;
|
import net.sf.briar.api.Author;
|
||||||
import net.sf.briar.api.ContactId;
|
import net.sf.briar.api.ContactId;
|
||||||
import net.sf.briar.api.messaging.MessageId;
|
import net.sf.briar.api.messaging.MessageId;
|
||||||
import net.sf.briar.api.messaging.Rating;
|
|
||||||
|
|
||||||
public class PrivateMessageHeader extends MessageHeader {
|
public class PrivateMessageHeader extends MessageHeader {
|
||||||
|
|
||||||
@@ -12,10 +11,9 @@ public class PrivateMessageHeader extends MessageHeader {
|
|||||||
|
|
||||||
public PrivateMessageHeader(MessageId id, MessageId parent, Author author,
|
public PrivateMessageHeader(MessageId id, MessageId parent, Author author,
|
||||||
String contentType, String subject, long timestamp, boolean read,
|
String contentType, String subject, long timestamp, boolean read,
|
||||||
boolean starred, Rating rating, ContactId contactId,
|
boolean starred, ContactId contactId, boolean incoming) {
|
||||||
boolean incoming) {
|
|
||||||
super(id, parent, author, contentType, subject, timestamp, read,
|
super(id, parent, author, contentType, subject, timestamp, read,
|
||||||
starred, rating);
|
starred);
|
||||||
this.contactId = contactId;
|
this.contactId = contactId;
|
||||||
this.incoming = incoming;
|
this.incoming = incoming;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
package net.sf.briar.api.db.event;
|
|
||||||
|
|
||||||
import net.sf.briar.api.AuthorId;
|
|
||||||
import net.sf.briar.api.messaging.Rating;
|
|
||||||
|
|
||||||
public class RatingChangedEvent extends DatabaseEvent {
|
|
||||||
|
|
||||||
private final AuthorId author;
|
|
||||||
private final Rating rating;
|
|
||||||
|
|
||||||
public RatingChangedEvent(AuthorId author, Rating rating) {
|
|
||||||
this.author = author;
|
|
||||||
this.rating = rating;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AuthorId getAuthorId() {
|
|
||||||
return author;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Rating getRating() {
|
|
||||||
return rating;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
package net.sf.briar.api.messaging;
|
|
||||||
|
|
||||||
/** The ratings that may be applied to an author in peer moderation. */
|
|
||||||
public enum Rating {
|
|
||||||
UNRATED, BAD, GOOD
|
|
||||||
}
|
|
||||||
@@ -20,7 +20,6 @@ import net.sf.briar.api.messaging.GroupId;
|
|||||||
import net.sf.briar.api.messaging.GroupStatus;
|
import net.sf.briar.api.messaging.GroupStatus;
|
||||||
import net.sf.briar.api.messaging.Message;
|
import net.sf.briar.api.messaging.Message;
|
||||||
import net.sf.briar.api.messaging.MessageId;
|
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.RetentionAck;
|
||||||
import net.sf.briar.api.messaging.RetentionUpdate;
|
import net.sf.briar.api.messaging.RetentionUpdate;
|
||||||
import net.sf.briar.api.messaging.SubscriptionAck;
|
import net.sf.briar.api.messaging.SubscriptionAck;
|
||||||
@@ -45,7 +44,6 @@ import net.sf.briar.api.transport.TemporarySecret;
|
|||||||
* <li> contact
|
* <li> contact
|
||||||
* <li> identity
|
* <li> identity
|
||||||
* <li> message
|
* <li> message
|
||||||
* <li> rating
|
|
||||||
* <li> retention
|
* <li> retention
|
||||||
* <li> subscription
|
* <li> subscription
|
||||||
* <li> transport
|
* <li> transport
|
||||||
@@ -270,7 +268,7 @@ interface Database<T> {
|
|||||||
/**
|
/**
|
||||||
* Returns the headers of all messages in the given group.
|
* Returns the headers of all messages in the given group.
|
||||||
* <p>
|
* <p>
|
||||||
* Locking: message read, rating read.
|
* Locking: message read.
|
||||||
*/
|
*/
|
||||||
Collection<GroupMessageHeader> getGroupMessageHeaders(T txn, GroupId g)
|
Collection<GroupMessageHeader> getGroupMessageHeaders(T txn, GroupId g)
|
||||||
throws DbException;
|
throws DbException;
|
||||||
@@ -341,7 +339,7 @@ interface Database<T> {
|
|||||||
* Returns the headers of all private messages to or from the given
|
* Returns the headers of all private messages to or from the given
|
||||||
* contact.
|
* contact.
|
||||||
* <p>
|
* <p>
|
||||||
* Locking: contact read, identity read, message read, rating read.
|
* Locking: contact read, identity read, message read.
|
||||||
*/
|
*/
|
||||||
Collection<PrivateMessageHeader> getPrivateMessageHeaders(T txn,
|
Collection<PrivateMessageHeader> getPrivateMessageHeaders(T txn,
|
||||||
ContactId c) throws DbException;
|
ContactId c) throws DbException;
|
||||||
@@ -364,15 +362,6 @@ interface Database<T> {
|
|||||||
Collection<MessageId> getMessagesToOffer(T txn, ContactId c,
|
Collection<MessageId> getMessagesToOffer(T txn, ContactId c,
|
||||||
int maxMessages) throws DbException;
|
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.
|
* Returns the message identified by the given ID, in serialised form.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -398,13 +387,6 @@ interface Database<T> {
|
|||||||
*/
|
*/
|
||||||
Collection<MessageId> getOldMessages(T txn, int size) throws DbException;
|
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.
|
* Returns true if the given message has been read.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -443,13 +425,6 @@ interface Database<T> {
|
|||||||
*/
|
*/
|
||||||
Collection<TemporarySecret> getSecrets(T txn) throws DbException;
|
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
|
* 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
|
* 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;
|
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
|
* Marks the given message read or unread and returns true if it was
|
||||||
* previously read.
|
* previously read.
|
||||||
@@ -714,13 +682,6 @@ interface Database<T> {
|
|||||||
boolean setRetentionTime(T txn, ContactId c, long retention, long version)
|
boolean setRetentionTime(T txn, ContactId c, long retention, long version)
|
||||||
throws DbException;
|
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
|
* Marks the given message starred or unstarred and returns true if it was
|
||||||
* previously starred.
|
* previously starred.
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package net.sf.briar.db;
|
|||||||
|
|
||||||
import static java.util.logging.Level.INFO;
|
import static java.util.logging.Level.INFO;
|
||||||
import static java.util.logging.Level.WARNING;
|
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.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
|
||||||
import static net.sf.briar.db.DatabaseConstants.BYTES_PER_SWEEP;
|
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.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.MessageExpiredEvent;
|
||||||
import net.sf.briar.api.db.event.MessageReceivedEvent;
|
import net.sf.briar.api.db.event.MessageReceivedEvent;
|
||||||
import net.sf.briar.api.db.event.PrivateMessageAddedEvent;
|
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.RemoteRetentionTimeUpdatedEvent;
|
||||||
import net.sf.briar.api.db.event.RemoteSubscriptionsUpdatedEvent;
|
import net.sf.briar.api.db.event.RemoteSubscriptionsUpdatedEvent;
|
||||||
import net.sf.briar.api.db.event.RemoteTransportsUpdatedEvent;
|
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.Message;
|
||||||
import net.sf.briar.api.messaging.MessageId;
|
import net.sf.briar.api.messaging.MessageId;
|
||||||
import net.sf.briar.api.messaging.Offer;
|
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.Request;
|
||||||
import net.sf.briar.api.messaging.RetentionAck;
|
import net.sf.briar.api.messaging.RetentionAck;
|
||||||
import net.sf.briar.api.messaging.RetentionUpdate;
|
import net.sf.briar.api.messaging.RetentionUpdate;
|
||||||
@@ -105,8 +102,6 @@ DatabaseCleaner.Callback {
|
|||||||
new ReentrantReadWriteLock(true);
|
new ReentrantReadWriteLock(true);
|
||||||
private final ReentrantReadWriteLock messageLock =
|
private final ReentrantReadWriteLock messageLock =
|
||||||
new ReentrantReadWriteLock(true);
|
new ReentrantReadWriteLock(true);
|
||||||
private final ReentrantReadWriteLock ratingLock =
|
|
||||||
new ReentrantReadWriteLock(true);
|
|
||||||
private final ReentrantReadWriteLock retentionLock =
|
private final ReentrantReadWriteLock retentionLock =
|
||||||
new ReentrantReadWriteLock(true);
|
new ReentrantReadWriteLock(true);
|
||||||
private final ReentrantReadWriteLock subscriptionLock =
|
private final ReentrantReadWriteLock subscriptionLock =
|
||||||
@@ -290,27 +285,22 @@ DatabaseCleaner.Callback {
|
|||||||
try {
|
try {
|
||||||
messageLock.writeLock().lock();
|
messageLock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
ratingLock.readLock().lock();
|
subscriptionLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
subscriptionLock.readLock().lock();
|
T txn = db.startTransaction();
|
||||||
try {
|
try {
|
||||||
T txn = db.startTransaction();
|
// Don't store the message if the user has
|
||||||
try {
|
// unsubscribed from the group
|
||||||
// Don't store the message if the user has
|
GroupId g = m.getGroup().getId();
|
||||||
// unsubscribed from the group
|
if(db.containsSubscription(txn, g))
|
||||||
GroupId g = m.getGroup().getId();
|
added = storeGroupMessage(txn, m, null);
|
||||||
if(db.containsSubscription(txn, g))
|
db.commitTransaction(txn);
|
||||||
added = storeGroupMessage(txn, m, null);
|
} catch(DbException e) {
|
||||||
db.commitTransaction(txn);
|
db.abortTransaction(txn);
|
||||||
} catch(DbException e) {
|
throw e;
|
||||||
db.abortTransaction(txn);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
subscriptionLock.readLock().unlock();
|
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
ratingLock.readLock().unlock();
|
subscriptionLock.readLock().unlock();
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
messageLock.writeLock().unlock();
|
messageLock.writeLock().unlock();
|
||||||
@@ -324,11 +314,10 @@ DatabaseCleaner.Callback {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* If the given message is already in the database, marks it as seen by the
|
* 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
|
* sender and returns false. Otherwise stores the message, marks it as seen
|
||||||
* sendability of its ancestors if necessary, marks the message as seen by
|
* by the sender and unseen by all other contacts, and returns true.
|
||||||
* the sender and unseen by all other contacts, and returns true.
|
|
||||||
* <p>
|
* <p>
|
||||||
* Locking: contact read, message write, rating read.
|
* Locking: contact read, message write.
|
||||||
* @param sender is null for a locally generated message.
|
* @param sender is null for a locally generated message.
|
||||||
*/
|
*/
|
||||||
private boolean storeGroupMessage(T txn, Message m, ContactId sender)
|
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(sender != null) db.addStatus(txn, sender, id, true);
|
||||||
if(stored) {
|
if(stored) {
|
||||||
// Mark the message as unseen by other contacts
|
// 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);
|
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
|
// Count the bytes stored
|
||||||
synchronized(spaceLock) {
|
synchronized(spaceLock) {
|
||||||
bytesStoredSinceLastCheck += m.getSerialised().length;
|
bytesStoredSinceLastCheck += m.getSerialised().length;
|
||||||
@@ -359,59 +343,6 @@ DatabaseCleaner.Callback {
|
|||||||
return stored;
|
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)
|
public void addLocalPrivateMessage(Message m, ContactId c)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
boolean added;
|
boolean added;
|
||||||
@@ -967,27 +898,22 @@ DatabaseCleaner.Callback {
|
|||||||
throws DbException {
|
throws DbException {
|
||||||
messageLock.readLock().lock();
|
messageLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
ratingLock.readLock().lock();
|
subscriptionLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
subscriptionLock.readLock().lock();
|
T txn = db.startTransaction();
|
||||||
try {
|
try {
|
||||||
T txn = db.startTransaction();
|
if(!db.containsSubscription(txn, g))
|
||||||
try {
|
throw new NoSuchSubscriptionException();
|
||||||
if(!db.containsSubscription(txn, g))
|
Collection<GroupMessageHeader> headers =
|
||||||
throw new NoSuchSubscriptionException();
|
db.getGroupMessageHeaders(txn, g);
|
||||||
Collection<GroupMessageHeader> headers =
|
db.commitTransaction(txn);
|
||||||
db.getGroupMessageHeaders(txn, g);
|
return headers;
|
||||||
db.commitTransaction(txn);
|
} catch(DbException e) {
|
||||||
return headers;
|
db.abortTransaction(txn);
|
||||||
} catch(DbException e) {
|
throw e;
|
||||||
db.abortTransaction(txn);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
subscriptionLock.readLock().unlock();
|
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
ratingLock.readLock().unlock();
|
subscriptionLock.readLock().unlock();
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
messageLock.readLock().unlock();
|
messageLock.readLock().unlock();
|
||||||
@@ -1111,20 +1037,15 @@ DatabaseCleaner.Callback {
|
|||||||
try {
|
try {
|
||||||
messageLock.readLock().lock();
|
messageLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
ratingLock.readLock().lock();
|
T txn = db.startTransaction();
|
||||||
try {
|
try {
|
||||||
T txn = db.startTransaction();
|
Collection<PrivateMessageHeader> headers =
|
||||||
try {
|
db.getPrivateMessageHeaders(txn, c);
|
||||||
Collection<PrivateMessageHeader> headers =
|
db.commitTransaction(txn);
|
||||||
db.getPrivateMessageHeaders(txn, c);
|
return headers;
|
||||||
db.commitTransaction(txn);
|
} catch(DbException e) {
|
||||||
return headers;
|
db.abortTransaction(txn);
|
||||||
} catch(DbException e) {
|
throw e;
|
||||||
db.abortTransaction(txn);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
ratingLock.readLock().unlock();
|
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
messageLock.readLock().unlock();
|
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 {
|
public boolean getReadFlag(MessageId m) throws DbException {
|
||||||
messageLock.readLock().lock();
|
messageLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
@@ -1463,26 +1367,21 @@ DatabaseCleaner.Callback {
|
|||||||
try {
|
try {
|
||||||
messageLock.writeLock().lock();
|
messageLock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
ratingLock.readLock().lock();
|
subscriptionLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
subscriptionLock.readLock().lock();
|
T txn = db.startTransaction();
|
||||||
try {
|
try {
|
||||||
T txn = db.startTransaction();
|
if(!db.containsContact(txn, c))
|
||||||
try {
|
throw new NoSuchContactException();
|
||||||
if(!db.containsContact(txn, c))
|
added = storeMessage(txn, c, m);
|
||||||
throw new NoSuchContactException();
|
db.addMessageToAck(txn, c, m.getId());
|
||||||
added = storeMessage(txn, c, m);
|
db.commitTransaction(txn);
|
||||||
db.addMessageToAck(txn, c, m.getId());
|
} catch(DbException e) {
|
||||||
db.commitTransaction(txn);
|
db.abortTransaction(txn);
|
||||||
} catch(DbException e) {
|
throw e;
|
||||||
db.abortTransaction(txn);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
subscriptionLock.readLock().unlock();
|
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
ratingLock.readLock().unlock();
|
subscriptionLock.readLock().unlock();
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
messageLock.writeLock().unlock();
|
messageLock.writeLock().unlock();
|
||||||
@@ -1502,7 +1401,7 @@ DatabaseCleaner.Callback {
|
|||||||
* Attempts to store a message received from the given contact, and returns
|
* Attempts to store a message received from the given contact, and returns
|
||||||
* true if it was stored.
|
* true if it was stored.
|
||||||
* <p>
|
* <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)
|
private boolean storeMessage(T txn, ContactId c, Message m)
|
||||||
throws DbException {
|
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 {
|
public boolean setReadFlag(MessageId m, boolean read) throws DbException {
|
||||||
messageLock.writeLock().lock();
|
messageLock.writeLock().lock();
|
||||||
try {
|
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)
|
public boolean setStarredFlag(MessageId m, boolean starred)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
messageLock.writeLock().lock();
|
messageLock.writeLock().lock();
|
||||||
@@ -2134,7 +1979,7 @@ DatabaseCleaner.Callback {
|
|||||||
try {
|
try {
|
||||||
expired = db.getOldMessages(txn, size);
|
expired = db.getOldMessages(txn, size);
|
||||||
if(!expired.isEmpty()) {
|
if(!expired.isEmpty()) {
|
||||||
for(MessageId m : expired) removeMessage(txn, m);
|
for(MessageId m : expired) db.removeMessage(txn, m);
|
||||||
db.incrementRetentionVersions(txn);
|
db.incrementRetentionVersions(txn);
|
||||||
if(LOG.isLoggable(INFO))
|
if(LOG.isLoggable(INFO))
|
||||||
LOG.info("Expired " + expired.size() + " messages");
|
LOG.info("Expired " + expired.size() + " messages");
|
||||||
@@ -2155,19 +2000,6 @@ DatabaseCleaner.Callback {
|
|||||||
return true;
|
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() {
|
public boolean shouldCheckFreeSpace() {
|
||||||
synchronized(spaceLock) {
|
synchronized(spaceLock) {
|
||||||
long now = clock.currentTimeMillis();
|
long now = clock.currentTimeMillis();
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import static java.util.logging.Level.INFO;
|
|||||||
import static java.util.logging.Level.WARNING;
|
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.MAX_SUBSCRIPTIONS;
|
||||||
import static net.sf.briar.api.messaging.MessagingConstants.RETENTION_MODULUS;
|
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 static net.sf.briar.db.ExponentialBackoff.calculateExpiry;
|
||||||
|
|
||||||
import java.io.IOException;
|
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.GroupStatus;
|
||||||
import net.sf.briar.api.messaging.Message;
|
import net.sf.briar.api.messaging.Message;
|
||||||
import net.sf.briar.api.messaging.MessageId;
|
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.RetentionAck;
|
||||||
import net.sf.briar.api.messaging.RetentionUpdate;
|
import net.sf.briar.api.messaging.RetentionUpdate;
|
||||||
import net.sf.briar.api.messaging.SubscriptionAck;
|
import net.sf.briar.api.messaging.SubscriptionAck;
|
||||||
@@ -154,7 +152,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
+ " bodyLength INT NOT NULL,"
|
+ " bodyLength INT NOT NULL,"
|
||||||
+ " raw BLOB NOT NULL,"
|
+ " raw BLOB NOT NULL,"
|
||||||
+ " incoming BOOLEAN NOT NULL,"
|
+ " incoming BOOLEAN NOT NULL,"
|
||||||
+ " sendability INT UNSIGNED," // Null for private messages
|
|
||||||
+ " contactId INT UNSIGNED," // Null for group messages
|
+ " contactId INT UNSIGNED," // Null for group messages
|
||||||
+ " read BOOLEAN NOT NULL,"
|
+ " read BOOLEAN NOT NULL,"
|
||||||
+ " starred BOOLEAN NOT NULL,"
|
+ " starred BOOLEAN NOT NULL,"
|
||||||
@@ -166,18 +163,12 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
+ " REFERENCES contacts (contactId)"
|
+ " REFERENCES contacts (contactId)"
|
||||||
+ " ON DELETE CASCADE)";
|
+ " 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 =
|
private static final String INDEX_MESSAGES_BY_AUTHOR =
|
||||||
"CREATE INDEX messagesByAuthor ON messages (authorId)";
|
"CREATE INDEX messagesByAuthor ON messages (authorId)";
|
||||||
|
|
||||||
private static final String INDEX_MESSAGES_BY_TIMESTAMP =
|
private static final String INDEX_MESSAGES_BY_TIMESTAMP =
|
||||||
"CREATE INDEX messagesByTimestamp ON messages (timestamp)";
|
"CREATE INDEX messagesByTimestamp ON messages (timestamp)";
|
||||||
|
|
||||||
private static final String INDEX_MESSAGES_BY_SENDABILITY =
|
|
||||||
"CREATE INDEX messagesBySendability ON messages (sendability)";
|
|
||||||
|
|
||||||
// Locking: message
|
// Locking: message
|
||||||
private static final String CREATE_MESSAGES_TO_ACK =
|
private static final String CREATE_MESSAGES_TO_ACK =
|
||||||
"CREATE TABLE messagesToAck"
|
"CREATE TABLE messagesToAck"
|
||||||
@@ -210,13 +201,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
private static final String INDEX_STATUSES_BY_CONTACT =
|
private static final String INDEX_STATUSES_BY_CONTACT =
|
||||||
"CREATE INDEX statusesByContact ON statuses (contactId)";
|
"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
|
// Locking: retention
|
||||||
private static final String CREATE_RETENTION_VERSIONS =
|
private static final String CREATE_RETENTION_VERSIONS =
|
||||||
"CREATE TABLE retentionVersions"
|
"CREATE TABLE retentionVersions"
|
||||||
@@ -403,15 +387,12 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
s.executeUpdate(insertTypeNames(CREATE_CONTACT_GROUPS));
|
s.executeUpdate(insertTypeNames(CREATE_CONTACT_GROUPS));
|
||||||
s.executeUpdate(insertTypeNames(CREATE_GROUP_VERSIONS));
|
s.executeUpdate(insertTypeNames(CREATE_GROUP_VERSIONS));
|
||||||
s.executeUpdate(insertTypeNames(CREATE_MESSAGES));
|
s.executeUpdate(insertTypeNames(CREATE_MESSAGES));
|
||||||
s.executeUpdate(INDEX_MESSAGES_BY_PARENT);
|
|
||||||
s.executeUpdate(INDEX_MESSAGES_BY_AUTHOR);
|
s.executeUpdate(INDEX_MESSAGES_BY_AUTHOR);
|
||||||
s.executeUpdate(INDEX_MESSAGES_BY_TIMESTAMP);
|
s.executeUpdate(INDEX_MESSAGES_BY_TIMESTAMP);
|
||||||
s.executeUpdate(INDEX_MESSAGES_BY_SENDABILITY);
|
|
||||||
s.executeUpdate(insertTypeNames(CREATE_MESSAGES_TO_ACK));
|
s.executeUpdate(insertTypeNames(CREATE_MESSAGES_TO_ACK));
|
||||||
s.executeUpdate(insertTypeNames(CREATE_STATUSES));
|
s.executeUpdate(insertTypeNames(CREATE_STATUSES));
|
||||||
s.executeUpdate(INDEX_STATUSES_BY_MESSAGE);
|
s.executeUpdate(INDEX_STATUSES_BY_MESSAGE);
|
||||||
s.executeUpdate(INDEX_STATUSES_BY_CONTACT);
|
s.executeUpdate(INDEX_STATUSES_BY_CONTACT);
|
||||||
s.executeUpdate(insertTypeNames(CREATE_RATINGS));
|
|
||||||
s.executeUpdate(insertTypeNames(CREATE_RETENTION_VERSIONS));
|
s.executeUpdate(insertTypeNames(CREATE_RETENTION_VERSIONS));
|
||||||
s.executeUpdate(insertTypeNames(CREATE_TRANSPORTS));
|
s.executeUpdate(insertTypeNames(CREATE_TRANSPORTS));
|
||||||
s.executeUpdate(insertTypeNames(CREATE_TRANSPORT_CONFIGS));
|
s.executeUpdate(insertTypeNames(CREATE_TRANSPORT_CONFIGS));
|
||||||
@@ -681,8 +662,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
String sql = "INSERT INTO messages (messageId, parentId, groupId,"
|
String sql = "INSERT INTO messages (messageId, parentId, groupId,"
|
||||||
+ " authorId, authorName, authorKey, contentType, subject,"
|
+ " authorId, authorName, authorKey, contentType, subject,"
|
||||||
+ " timestamp, length, bodyStart, bodyLength, raw,"
|
+ " timestamp, length, bodyStart, bodyLength, raw,"
|
||||||
+ " incoming, sendability, read, starred)"
|
+ " incoming, read, starred)"
|
||||||
+ " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0,"
|
+ " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,"
|
||||||
+ " FALSE, FALSE)";
|
+ " FALSE, FALSE)";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setBytes(1, m.getId().getBytes());
|
ps.setBytes(1, m.getId().getBytes());
|
||||||
@@ -1307,12 +1288,10 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try {
|
try {
|
||||||
String sql = "SELECT messageId, parentId, m.authorId, authorName,"
|
String sql = "SELECT messageId, parentId, authorId, authorName,"
|
||||||
+ " authorKey, rating, contentType, subject, timestamp,"
|
+ " authorKey, contentType, subject, timestamp, read,"
|
||||||
+ " read, starred"
|
+ " starred"
|
||||||
+ " FROM messages AS m"
|
+ " FROM messages"
|
||||||
+ " LEFT OUTER JOIN ratings AS r"
|
|
||||||
+ " ON m.authorId = r.authorId"
|
|
||||||
+ " WHERE groupId = ?";
|
+ " WHERE groupId = ?";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setBytes(1, g.getBytes());
|
ps.setBytes(1, g.getBytes());
|
||||||
@@ -1324,27 +1303,22 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
byte[] b = rs.getBytes(2);
|
byte[] b = rs.getBytes(2);
|
||||||
MessageId parent = b == null ? null : new MessageId(b);
|
MessageId parent = b == null ? null : new MessageId(b);
|
||||||
Author author;
|
Author author;
|
||||||
Rating rating;
|
|
||||||
b = rs.getBytes(3);
|
b = rs.getBytes(3);
|
||||||
if(b == null) {
|
if(b == null) {
|
||||||
author = null;
|
author = null;
|
||||||
rating = UNRATED;
|
|
||||||
} else {
|
} else {
|
||||||
AuthorId authorId = new AuthorId(b);
|
AuthorId authorId = new AuthorId(b);
|
||||||
String authorName = rs.getString(4);
|
String authorName = rs.getString(4);
|
||||||
byte[] authorKey = rs.getBytes(5);
|
byte[] authorKey = rs.getBytes(5);
|
||||||
author = new Author(authorId, authorName, authorKey);
|
author = new Author(authorId, authorName, authorKey);
|
||||||
// NULL == 0 == UNRATED
|
|
||||||
rating = Rating.values()[rs.getByte(6)];
|
|
||||||
}
|
}
|
||||||
String contentType = rs.getString(7);
|
String contentType = rs.getString(6);
|
||||||
String subject = rs.getString(8);
|
String subject = rs.getString(7);
|
||||||
long timestamp = rs.getLong(9);
|
long timestamp = rs.getLong(8);
|
||||||
boolean read = rs.getBoolean(10);
|
boolean read = rs.getBoolean(9);
|
||||||
boolean starred = rs.getBoolean(11);
|
boolean starred = rs.getBoolean(10);
|
||||||
headers.add(new GroupMessageHeader(id, parent, author,
|
headers.add(new GroupMessageHeader(id, parent, author,
|
||||||
contentType, subject, timestamp, read, starred, rating,
|
contentType, subject, timestamp, read, starred, g));
|
||||||
g));
|
|
||||||
}
|
}
|
||||||
rs.close();
|
rs.close();
|
||||||
ps.close();
|
ps.close();
|
||||||
@@ -1626,7 +1600,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
+ " WHERE cg.contactId = ?"
|
+ " WHERE cg.contactId = ?"
|
||||||
+ " AND timestamp >= retention"
|
+ " AND timestamp >= retention"
|
||||||
+ " AND seen = FALSE AND s.expiry < ?"
|
+ " AND seen = FALSE AND s.expiry < ?"
|
||||||
+ " AND sendability > 0"
|
|
||||||
+ " ORDER BY timestamp DESC LIMIT ?";
|
+ " ORDER BY timestamp DESC LIMIT ?";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setInt(1, c.getInt());
|
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)
|
public Collection<MessageId> getOldMessages(Connection txn, int capacity)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
@@ -1713,13 +1651,10 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
try {
|
try {
|
||||||
// Get the incoming message headers
|
// Get the incoming message headers
|
||||||
String sql = "SELECT m.messageId, parentId, contentType, subject,"
|
String sql = "SELECT m.messageId, parentId, contentType, subject,"
|
||||||
+ " timestamp, read, starred, c.authorId, name, publicKey,"
|
+ " timestamp, read, starred, c.authorId, name, publicKey"
|
||||||
+ " rating"
|
|
||||||
+ " FROM messages AS m"
|
+ " FROM messages AS m"
|
||||||
+ " JOIN contacts AS c"
|
+ " JOIN contacts AS c"
|
||||||
+ " ON m.contactId = c.contactId"
|
+ " ON m.contactId = c.contactId"
|
||||||
+ " LEFT OUTER JOIN ratings AS r"
|
|
||||||
+ " ON c.authorId = r.authorId"
|
|
||||||
+ " WHERE m.contactId = ?"
|
+ " WHERE m.contactId = ?"
|
||||||
+ " AND groupId IS NULL"
|
+ " AND groupId IS NULL"
|
||||||
+ " AND incoming = TRUE";
|
+ " AND incoming = TRUE";
|
||||||
@@ -1741,25 +1676,21 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
String authorName = rs.getString(9);
|
String authorName = rs.getString(9);
|
||||||
byte[] authorKey = rs.getBytes(10);
|
byte[] authorKey = rs.getBytes(10);
|
||||||
Author author = new Author(authorId, authorName, authorKey);
|
Author author = new Author(authorId, authorName, authorKey);
|
||||||
// NULL == 0 == UNRATED
|
|
||||||
Rating rating = Rating.values()[rs.getByte(11)];
|
|
||||||
headers.add(new PrivateMessageHeader(id, parent, author,
|
headers.add(new PrivateMessageHeader(id, parent, author,
|
||||||
contentType, subject, timestamp, read, starred, rating,
|
contentType, subject, timestamp, read, starred, c,
|
||||||
c, true));
|
true));
|
||||||
}
|
}
|
||||||
rs.close();
|
rs.close();
|
||||||
ps.close();
|
ps.close();
|
||||||
// Get the outgoing message headers
|
// Get the outgoing message headers
|
||||||
sql = "SELECT m.messageId, parentId, contentType, subject,"
|
sql = "SELECT m.messageId, parentId, contentType, subject,"
|
||||||
+ " timestamp, read, starred, a.authorId, a.name,"
|
+ " timestamp, read, starred, a.authorId, a.name,"
|
||||||
+ " a.publicKey, rating"
|
+ " a.publicKey"
|
||||||
+ " FROM messages AS m"
|
+ " FROM messages AS m"
|
||||||
+ " JOIN contacts AS c"
|
+ " JOIN contacts AS c"
|
||||||
+ " ON m.contactId = c.contactId"
|
+ " ON m.contactId = c.contactId"
|
||||||
+ " JOIN localAuthors AS a"
|
+ " JOIN localAuthors AS a"
|
||||||
+ " ON c.localAuthorId = a.authorId"
|
+ " ON c.localAuthorId = a.authorId"
|
||||||
+ " LEFT OUTER JOIN ratings AS r"
|
|
||||||
+ " ON c.localAuthorId = r.authorId"
|
|
||||||
+ " WHERE m.contactId = ?"
|
+ " WHERE m.contactId = ?"
|
||||||
+ " AND groupId IS NULL"
|
+ " AND groupId IS NULL"
|
||||||
+ " AND incoming = FALSE";
|
+ " AND incoming = FALSE";
|
||||||
@@ -1779,11 +1710,9 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
String authorName = rs.getString(9);
|
String authorName = rs.getString(9);
|
||||||
byte[] authorKey = rs.getBytes(10);
|
byte[] authorKey = rs.getBytes(10);
|
||||||
Author author = new Author(authorId, authorName, authorKey);
|
Author author = new Author(authorId, authorName, authorKey);
|
||||||
// NULL == 0 == UNRATED
|
|
||||||
Rating rating = Rating.values()[rs.getByte(11)];
|
|
||||||
headers.add(new PrivateMessageHeader(id, parent, author,
|
headers.add(new PrivateMessageHeader(id, parent, author,
|
||||||
contentType, subject, timestamp, read, starred, rating,
|
contentType, subject, timestamp, read, starred, c,
|
||||||
c, false));
|
false));
|
||||||
}
|
}
|
||||||
rs.close();
|
rs.close();
|
||||||
ps.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)
|
public byte[] getRawMessage(Connection txn, MessageId m)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
@@ -1883,8 +1790,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
+ " WHERE m.messageId = ?"
|
+ " WHERE m.messageId = ?"
|
||||||
+ " AND cg.contactId = ?"
|
+ " AND cg.contactId = ?"
|
||||||
+ " AND timestamp >= retention"
|
+ " AND timestamp >= retention"
|
||||||
+ " AND seen = FALSE AND s.expiry < ?"
|
+ " AND seen = FALSE AND s.expiry < ?";
|
||||||
+ " AND sendability > 0";
|
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setBytes(1, m.getBytes());
|
ps.setBytes(1, m.getBytes());
|
||||||
ps.setInt(2, c.getInt());
|
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,
|
public Collection<MessageId> getSendableMessages(Connection txn,
|
||||||
ContactId c, int maxLength) throws DbException {
|
ContactId c, int maxLength) throws DbException {
|
||||||
long now = clock.currentTimeMillis();
|
long now = clock.currentTimeMillis();
|
||||||
@@ -2143,7 +2028,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
+ " WHERE cg.contactId = ?"
|
+ " WHERE cg.contactId = ?"
|
||||||
+ " AND timestamp >= retention"
|
+ " AND timestamp >= retention"
|
||||||
+ " AND seen = FALSE AND s.expiry < ?"
|
+ " AND seen = FALSE AND s.expiry < ?"
|
||||||
+ " AND sendability > 0"
|
|
||||||
+ " ORDER BY timestamp DESC";
|
+ " ORDER BY timestamp DESC";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setInt(1, c.getInt());
|
ps.setInt(1, c.getInt());
|
||||||
@@ -2587,7 +2471,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
+ " WHERE cg.contactId = ?"
|
+ " WHERE cg.contactId = ?"
|
||||||
+ " AND timestamp >= retention"
|
+ " AND timestamp >= retention"
|
||||||
+ " AND seen = FALSE AND s.expiry < ?"
|
+ " AND seen = FALSE AND s.expiry < ?"
|
||||||
+ " AND sendability > 0"
|
|
||||||
+ " LIMIT 1";
|
+ " LIMIT 1";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setInt(1, c.getInt());
|
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)
|
public boolean setReadFlag(Connection txn, MessageId m, boolean read)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
PreparedStatement ps = null;
|
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)
|
public boolean setStarredFlag(Connection txn, MessageId m, boolean starred)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
PreparedStatement ps = null;
|
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.TransportPropertyConstants.MAX_PROPERTY_LENGTH;
|
||||||
import static net.sf.briar.api.invitation.InvitationConstants.CONNECTION_TIMEOUT;
|
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.invitation.InvitationConstants.HASH_LENGTH;
|
||||||
import static net.sf.briar.api.messaging.Rating.GOOD;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
@@ -263,8 +262,6 @@ abstract class Connector extends Thread {
|
|||||||
long epoch, boolean alice) throws DbException {
|
long epoch, boolean alice) throws DbException {
|
||||||
// Add the contact to the database
|
// Add the contact to the database
|
||||||
contactId = db.addContact(remoteAuthor, localAuthor.getId());
|
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
|
// Store the remote transport properties
|
||||||
db.setRemoteProperties(contactId, remoteProps);
|
db.setRemoteProperties(contactId, remoteProps);
|
||||||
// Create an endpoint for each transport shared with the contact
|
// 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.INFO;
|
||||||
import static java.util.logging.Level.WARNING;
|
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.MessagingConstants.MAX_PACKET_LENGTH;
|
||||||
import static net.sf.briar.api.messaging.Rating.GOOD;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
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.MessageExpiredEvent;
|
||||||
import net.sf.briar.api.db.event.MessageReceivedEvent;
|
import net.sf.briar.api.db.event.MessageReceivedEvent;
|
||||||
import net.sf.briar.api.db.event.PrivateMessageAddedEvent;
|
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.RemoteRetentionTimeUpdatedEvent;
|
||||||
import net.sf.briar.api.db.event.RemoteSubscriptionsUpdatedEvent;
|
import net.sf.briar.api.db.event.RemoteSubscriptionsUpdatedEvent;
|
||||||
import net.sf.briar.api.db.event.RemoteTransportsUpdatedEvent;
|
import net.sf.briar.api.db.event.RemoteTransportsUpdatedEvent;
|
||||||
@@ -157,10 +155,6 @@ abstract class DuplexConnection implements DatabaseListener {
|
|||||||
if(canSendOffer.getAndSet(false))
|
if(canSendOffer.getAndSet(false))
|
||||||
dbExecutor.execute(new GenerateOffer());
|
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) {
|
} else if(e instanceof RemoteRetentionTimeUpdatedEvent) {
|
||||||
dbExecutor.execute(new GenerateRetentionAck());
|
dbExecutor.execute(new GenerateRetentionAck());
|
||||||
} else if(e instanceof RemoteSubscriptionsUpdatedEvent) {
|
} else if(e instanceof RemoteSubscriptionsUpdatedEvent) {
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package net.sf.briar.db;
|
|||||||
import static net.sf.briar.db.DatabaseConstants.BYTES_PER_SWEEP;
|
import static net.sf.briar.db.DatabaseConstants.BYTES_PER_SWEEP;
|
||||||
import static net.sf.briar.db.DatabaseConstants.MIN_FREE_SPACE;
|
import static net.sf.briar.db.DatabaseConstants.MIN_FREE_SPACE;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
import net.sf.briar.api.clock.SystemClock;
|
import net.sf.briar.api.clock.SystemClock;
|
||||||
@@ -66,68 +65,6 @@ public class DatabaseComponentImplTest extends DatabaseComponentTest {
|
|||||||
context.assertIsSatisfied();
|
context.assertIsSatisfied();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testExpiringUnsendableMessageDoesNotTriggerBackwardInclusion()
|
|
||||||
throws DbException {
|
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
context.checking(new Expectations() {{
|
|
||||||
oneOf(database).getFreeSpace();
|
|
||||||
will(returnValue(MIN_FREE_SPACE - 1));
|
|
||||||
oneOf(database).startTransaction();
|
|
||||||
will(returnValue(txn));
|
|
||||||
oneOf(database).getOldMessages(txn, BYTES_PER_SWEEP);
|
|
||||||
will(returnValue(Arrays.asList(messageId)));
|
|
||||||
oneOf(database).getSendability(txn, messageId);
|
|
||||||
will(returnValue(0));
|
|
||||||
oneOf(database).removeMessage(txn, messageId);
|
|
||||||
oneOf(database).incrementRetentionVersions(txn);
|
|
||||||
oneOf(database).commitTransaction(txn);
|
|
||||||
oneOf(database).getFreeSpace();
|
|
||||||
will(returnValue(MIN_FREE_SPACE));
|
|
||||||
}});
|
|
||||||
Callback db = createDatabaseComponentImpl(database, cleaner, shutdown);
|
|
||||||
|
|
||||||
db.checkFreeSpaceAndClean();
|
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testExpiringSendableMessageTriggersBackwardInclusion()
|
|
||||||
throws DbException {
|
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
context.checking(new Expectations() {{
|
|
||||||
oneOf(database).getFreeSpace();
|
|
||||||
will(returnValue(MIN_FREE_SPACE - 1));
|
|
||||||
oneOf(database).startTransaction();
|
|
||||||
will(returnValue(txn));
|
|
||||||
oneOf(database).getOldMessages(txn, BYTES_PER_SWEEP);
|
|
||||||
will(returnValue(Arrays.asList(messageId)));
|
|
||||||
oneOf(database).getSendability(txn, messageId);
|
|
||||||
will(returnValue(1));
|
|
||||||
oneOf(database).getGroupMessageParent(txn, messageId);
|
|
||||||
will(returnValue(null));
|
|
||||||
oneOf(database).removeMessage(txn, messageId);
|
|
||||||
oneOf(database).incrementRetentionVersions(txn);
|
|
||||||
oneOf(database).commitTransaction(txn);
|
|
||||||
oneOf(database).getFreeSpace();
|
|
||||||
will(returnValue(MIN_FREE_SPACE));
|
|
||||||
}});
|
|
||||||
Callback db = createDatabaseComponentImpl(database, cleaner, shutdown);
|
|
||||||
|
|
||||||
db.checkFreeSpaceAndClean();
|
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected <T> DatabaseComponent createDatabaseComponent(
|
protected <T> DatabaseComponent createDatabaseComponent(
|
||||||
Database<T> database, DatabaseCleaner cleaner,
|
Database<T> database, DatabaseCleaner cleaner,
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ package net.sf.briar.db;
|
|||||||
|
|
||||||
import static net.sf.briar.api.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
|
import static net.sf.briar.api.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
|
||||||
import static net.sf.briar.api.messaging.MessagingConstants.GROUP_SALT_LENGTH;
|
import static net.sf.briar.api.messaging.MessagingConstants.GROUP_SALT_LENGTH;
|
||||||
import static net.sf.briar.api.messaging.Rating.GOOD;
|
|
||||||
import static net.sf.briar.api.messaging.Rating.UNRATED;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -34,7 +32,6 @@ import net.sf.briar.api.db.event.DatabaseListener;
|
|||||||
import net.sf.briar.api.db.event.GroupMessageAddedEvent;
|
import net.sf.briar.api.db.event.GroupMessageAddedEvent;
|
||||||
import net.sf.briar.api.db.event.LocalSubscriptionsUpdatedEvent;
|
import net.sf.briar.api.db.event.LocalSubscriptionsUpdatedEvent;
|
||||||
import net.sf.briar.api.db.event.PrivateMessageAddedEvent;
|
import net.sf.briar.api.db.event.PrivateMessageAddedEvent;
|
||||||
import net.sf.briar.api.db.event.RatingChangedEvent;
|
|
||||||
import net.sf.briar.api.db.event.SubscriptionAddedEvent;
|
import net.sf.briar.api.db.event.SubscriptionAddedEvent;
|
||||||
import net.sf.briar.api.db.event.SubscriptionRemovedEvent;
|
import net.sf.briar.api.db.event.SubscriptionRemovedEvent;
|
||||||
import net.sf.briar.api.lifecycle.ShutdownManager;
|
import net.sf.briar.api.lifecycle.ShutdownManager;
|
||||||
@@ -124,9 +121,9 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
|||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
||||||
final DatabaseListener listener = context.mock(DatabaseListener.class);
|
final DatabaseListener listener = context.mock(DatabaseListener.class);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
exactly(13).of(database).startTransaction();
|
exactly(10).of(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
exactly(13).of(database).commitTransaction(txn);
|
exactly(10).of(database).commitTransaction(txn);
|
||||||
// open()
|
// open()
|
||||||
oneOf(database).open();
|
oneOf(database).open();
|
||||||
will(returnValue(false));
|
will(returnValue(false));
|
||||||
@@ -135,18 +132,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
|||||||
with(any(long.class)));
|
with(any(long.class)));
|
||||||
oneOf(shutdown).addShutdownHook(with(any(Runnable.class)));
|
oneOf(shutdown).addShutdownHook(with(any(Runnable.class)));
|
||||||
will(returnValue(shutdownHandle));
|
will(returnValue(shutdownHandle));
|
||||||
// getRating(authorId)
|
|
||||||
oneOf(database).getRating(txn, authorId);
|
|
||||||
will(returnValue(UNRATED));
|
|
||||||
// setRating(authorId, GOOD)
|
|
||||||
oneOf(database).setRating(txn, authorId, GOOD);
|
|
||||||
will(returnValue(UNRATED));
|
|
||||||
oneOf(database).getGroupMessages(txn, authorId);
|
|
||||||
will(returnValue(Collections.emptyList()));
|
|
||||||
oneOf(listener).eventOccurred(with(any(RatingChangedEvent.class)));
|
|
||||||
// setRating(authorId, GOOD) again
|
|
||||||
oneOf(database).setRating(txn, authorId, GOOD);
|
|
||||||
will(returnValue(GOOD));
|
|
||||||
// addLocalAuthor(localAuthor)
|
// addLocalAuthor(localAuthor)
|
||||||
oneOf(database).addLocalAuthor(txn, localAuthor);
|
oneOf(database).addLocalAuthor(txn, localAuthor);
|
||||||
// addContact(author, localAuthorId)
|
// addContact(author, localAuthorId)
|
||||||
@@ -204,9 +189,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
|||||||
|
|
||||||
assertFalse(db.open());
|
assertFalse(db.open());
|
||||||
db.addListener(listener);
|
db.addListener(listener);
|
||||||
assertEquals(UNRATED, db.getRating(authorId));
|
|
||||||
db.setRating(authorId, GOOD); // First time - listeners called
|
|
||||||
db.setRating(authorId, GOOD); // Second time - not called
|
|
||||||
db.addLocalAuthor(localAuthor);
|
db.addLocalAuthor(localAuthor);
|
||||||
assertEquals(contactId, db.addContact(author, localAuthorId));
|
assertEquals(contactId, db.addContact(author, localAuthorId));
|
||||||
assertEquals(Arrays.asList(contact), db.getContacts());
|
assertEquals(Arrays.asList(contact), db.getContacts());
|
||||||
@@ -225,114 +207,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
|||||||
context.assertIsSatisfied();
|
context.assertIsSatisfied();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testNullParentStopsBackwardInclusion() throws Exception {
|
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
context.checking(new Expectations() {{
|
|
||||||
// setRating(authorId, GOOD)
|
|
||||||
oneOf(database).startTransaction();
|
|
||||||
will(returnValue(txn));
|
|
||||||
oneOf(database).setRating(txn, authorId, GOOD);
|
|
||||||
will(returnValue(UNRATED));
|
|
||||||
// The sendability of the author's messages should be incremented
|
|
||||||
oneOf(database).getGroupMessages(txn, authorId);
|
|
||||||
will(returnValue(Arrays.asList(messageId)));
|
|
||||||
oneOf(database).getSendability(txn, messageId);
|
|
||||||
will(returnValue(0));
|
|
||||||
oneOf(database).setSendability(txn, messageId, 1);
|
|
||||||
// Backward inclusion stops when the message has no parent
|
|
||||||
oneOf(database).getGroupMessageParent(txn, messageId);
|
|
||||||
will(returnValue(null));
|
|
||||||
oneOf(database).commitTransaction(txn);
|
|
||||||
}});
|
|
||||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
|
||||||
shutdown);
|
|
||||||
|
|
||||||
db.setRating(authorId, GOOD);
|
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testUnaffectedParentStopsBackwardInclusion() throws Exception {
|
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
context.checking(new Expectations() {{
|
|
||||||
// setRating(authorId, GOOD)
|
|
||||||
oneOf(database).startTransaction();
|
|
||||||
will(returnValue(txn));
|
|
||||||
oneOf(database).setRating(txn, authorId, GOOD);
|
|
||||||
will(returnValue(UNRATED));
|
|
||||||
// The sendability of the author's messages should be incremented
|
|
||||||
oneOf(database).getGroupMessages(txn, authorId);
|
|
||||||
will(returnValue(Arrays.asList(messageId)));
|
|
||||||
oneOf(database).getSendability(txn, messageId);
|
|
||||||
will(returnValue(0));
|
|
||||||
oneOf(database).setSendability(txn, messageId, 1);
|
|
||||||
// The parent exists, is in the DB, and is in the same group
|
|
||||||
oneOf(database).getGroupMessageParent(txn, messageId);
|
|
||||||
will(returnValue(messageId1));
|
|
||||||
// The parent is already sendable
|
|
||||||
oneOf(database).getSendability(txn, messageId1);
|
|
||||||
will(returnValue(1));
|
|
||||||
oneOf(database).setSendability(txn, messageId1, 2);
|
|
||||||
oneOf(database).commitTransaction(txn);
|
|
||||||
}});
|
|
||||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
|
||||||
shutdown);
|
|
||||||
|
|
||||||
db.setRating(authorId, GOOD);
|
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testAffectedParentContinuesBackwardInclusion()
|
|
||||||
throws Exception {
|
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
context.checking(new Expectations() {{
|
|
||||||
// setRating(authorId, GOOD)
|
|
||||||
oneOf(database).startTransaction();
|
|
||||||
will(returnValue(txn));
|
|
||||||
oneOf(database).setRating(txn, authorId, GOOD);
|
|
||||||
will(returnValue(UNRATED));
|
|
||||||
// The sendability of the author's messages should be incremented
|
|
||||||
oneOf(database).getGroupMessages(txn, authorId);
|
|
||||||
will(returnValue(Arrays.asList(messageId)));
|
|
||||||
oneOf(database).getSendability(txn, messageId);
|
|
||||||
will(returnValue(0));
|
|
||||||
oneOf(database).setSendability(txn, messageId, 1);
|
|
||||||
// The parent exists, is in the DB, and is in the same group
|
|
||||||
oneOf(database).getGroupMessageParent(txn, messageId);
|
|
||||||
will(returnValue(messageId1));
|
|
||||||
// The parent is not already sendable
|
|
||||||
oneOf(database).getSendability(txn, messageId1);
|
|
||||||
will(returnValue(0));
|
|
||||||
oneOf(database).setSendability(txn, messageId1, 1);
|
|
||||||
// The parent has no parent
|
|
||||||
oneOf(database).getGroupMessageParent(txn, messageId1);
|
|
||||||
will(returnValue(null));
|
|
||||||
oneOf(database).commitTransaction(txn);
|
|
||||||
}});
|
|
||||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
|
||||||
shutdown);
|
|
||||||
|
|
||||||
db.setRating(authorId, GOOD);
|
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGroupMessagesAreNotStoredUnlessSubscribed()
|
public void testGroupMessagesAreNotStoredUnlessSubscribed()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
@@ -401,51 +275,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
|||||||
oneOf(database).getContactIds(txn);
|
oneOf(database).getContactIds(txn);
|
||||||
will(returnValue(Arrays.asList(contactId)));
|
will(returnValue(Arrays.asList(contactId)));
|
||||||
oneOf(database).addStatus(txn, contactId, messageId, false);
|
oneOf(database).addStatus(txn, contactId, messageId, false);
|
||||||
// The author is unrated and there are no sendable children
|
|
||||||
oneOf(database).getRating(txn, authorId);
|
|
||||||
will(returnValue(UNRATED));
|
|
||||||
oneOf(database).getNumberOfSendableChildren(txn, messageId);
|
|
||||||
will(returnValue(0));
|
|
||||||
oneOf(database).setSendability(txn, messageId, 0);
|
|
||||||
oneOf(database).commitTransaction(txn);
|
|
||||||
}});
|
|
||||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
|
||||||
shutdown);
|
|
||||||
|
|
||||||
db.addLocalGroupMessage(message);
|
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testAddingSendableMessageTriggersBackwardInclusion()
|
|
||||||
throws Exception {
|
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
context.checking(new Expectations() {{
|
|
||||||
// addLocalGroupMessage(message)
|
|
||||||
oneOf(database).startTransaction();
|
|
||||||
will(returnValue(txn));
|
|
||||||
oneOf(database).containsSubscription(txn, groupId);
|
|
||||||
will(returnValue(true));
|
|
||||||
oneOf(database).addGroupMessage(txn, message, false);
|
|
||||||
will(returnValue(true));
|
|
||||||
oneOf(database).setReadFlag(txn, messageId, true);
|
|
||||||
oneOf(database).getContactIds(txn);
|
|
||||||
will(returnValue(Arrays.asList(contactId)));
|
|
||||||
oneOf(database).addStatus(txn, contactId, messageId, false);
|
|
||||||
// The author is rated GOOD and there are two sendable children
|
|
||||||
oneOf(database).getRating(txn, authorId);
|
|
||||||
will(returnValue(GOOD));
|
|
||||||
oneOf(database).getNumberOfSendableChildren(txn, messageId);
|
|
||||||
will(returnValue(2));
|
|
||||||
oneOf(database).setSendability(txn, messageId, 3);
|
|
||||||
// The sendability of the message's ancestors should be updated
|
|
||||||
oneOf(database).getGroupMessageParent(txn, messageId);
|
|
||||||
will(returnValue(null));
|
|
||||||
oneOf(database).commitTransaction(txn);
|
oneOf(database).commitTransaction(txn);
|
||||||
}});
|
}});
|
||||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||||
@@ -1226,124 +1055,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
|||||||
context.assertIsSatisfied();
|
context.assertIsSatisfied();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testReceiveMessageDoesNotCalculateSendabilityForDuplicates()
|
|
||||||
throws Exception {
|
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
context.checking(new Expectations() {{
|
|
||||||
oneOf(database).startTransaction();
|
|
||||||
will(returnValue(txn));
|
|
||||||
oneOf(database).commitTransaction(txn);
|
|
||||||
oneOf(database).containsContact(txn, contactId);
|
|
||||||
will(returnValue(true));
|
|
||||||
// Only store messages belonging to visible, subscribed groups
|
|
||||||
oneOf(database).containsVisibleSubscription(txn, contactId,
|
|
||||||
groupId);
|
|
||||||
will(returnValue(true));
|
|
||||||
// The message is not stored, it's a duplicate
|
|
||||||
oneOf(database).addGroupMessage(txn, message, true);
|
|
||||||
will(returnValue(false));
|
|
||||||
oneOf(database).addStatus(txn, contactId, messageId, true);
|
|
||||||
// The message must be acked
|
|
||||||
oneOf(database).addMessageToAck(txn, contactId, messageId);
|
|
||||||
}});
|
|
||||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
|
||||||
shutdown);
|
|
||||||
|
|
||||||
db.receiveMessage(contactId, message);
|
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testReceiveMessageCalculatesSendability() throws Exception {
|
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
context.checking(new Expectations() {{
|
|
||||||
oneOf(database).startTransaction();
|
|
||||||
will(returnValue(txn));
|
|
||||||
oneOf(database).commitTransaction(txn);
|
|
||||||
oneOf(database).containsContact(txn, contactId);
|
|
||||||
will(returnValue(true));
|
|
||||||
// Only store messages belonging to visible, subscribed groups
|
|
||||||
oneOf(database).containsVisibleSubscription(txn, contactId,
|
|
||||||
groupId);
|
|
||||||
will(returnValue(true));
|
|
||||||
// The message is stored, and it's not a duplicate
|
|
||||||
oneOf(database).addGroupMessage(txn, message, true);
|
|
||||||
will(returnValue(true));
|
|
||||||
oneOf(database).addStatus(txn, contactId, messageId, true);
|
|
||||||
// Set the status to seen = true for all other contacts (none)
|
|
||||||
oneOf(database).getContactIds(txn);
|
|
||||||
will(returnValue(Arrays.asList(contactId)));
|
|
||||||
// Calculate the sendability - zero, so ancestors aren't updated
|
|
||||||
oneOf(database).getRating(txn, authorId);
|
|
||||||
will(returnValue(UNRATED));
|
|
||||||
oneOf(database).getNumberOfSendableChildren(txn, messageId);
|
|
||||||
will(returnValue(0));
|
|
||||||
oneOf(database).setSendability(txn, messageId, 0);
|
|
||||||
// The message must be acked
|
|
||||||
oneOf(database).addMessageToAck(txn, contactId, messageId);
|
|
||||||
}});
|
|
||||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
|
||||||
shutdown);
|
|
||||||
|
|
||||||
db.receiveMessage(contactId, message);
|
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testReceiveMessageUpdatesAncestorSendability()
|
|
||||||
throws Exception {
|
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
context.checking(new Expectations() {{
|
|
||||||
oneOf(database).startTransaction();
|
|
||||||
will(returnValue(txn));
|
|
||||||
oneOf(database).commitTransaction(txn);
|
|
||||||
oneOf(database).containsContact(txn, contactId);
|
|
||||||
will(returnValue(true));
|
|
||||||
// Only store messages belonging to visible, subscribed groups
|
|
||||||
oneOf(database).containsVisibleSubscription(txn, contactId,
|
|
||||||
groupId);
|
|
||||||
will(returnValue(true));
|
|
||||||
// The message is stored, and it's not a duplicate
|
|
||||||
oneOf(database).addGroupMessage(txn, message, true);
|
|
||||||
will(returnValue(true));
|
|
||||||
oneOf(database).addStatus(txn, contactId, messageId, true);
|
|
||||||
// Set the status to seen = true for all other contacts (none)
|
|
||||||
oneOf(database).getContactIds(txn);
|
|
||||||
will(returnValue(Arrays.asList(contactId)));
|
|
||||||
// Calculate the sendability - ancestors are updated
|
|
||||||
oneOf(database).getRating(txn, authorId);
|
|
||||||
will(returnValue(GOOD));
|
|
||||||
oneOf(database).getNumberOfSendableChildren(txn, messageId);
|
|
||||||
will(returnValue(1));
|
|
||||||
oneOf(database).setSendability(txn, messageId, 2);
|
|
||||||
oneOf(database).getGroupMessageParent(txn, messageId);
|
|
||||||
will(returnValue(null));
|
|
||||||
// The message must be acked
|
|
||||||
oneOf(database).addMessageToAck(txn, contactId, messageId);
|
|
||||||
}});
|
|
||||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
|
||||||
shutdown);
|
|
||||||
|
|
||||||
db.receiveMessage(contactId, message);
|
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReceiveOffer() throws Exception {
|
public void testReceiveOffer() throws Exception {
|
||||||
final MessageId messageId1 = new MessageId(TestUtils.getRandomId());
|
final MessageId messageId1 = new MessageId(TestUtils.getRandomId());
|
||||||
@@ -1527,11 +1238,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
|||||||
oneOf(database).getContactIds(txn);
|
oneOf(database).getContactIds(txn);
|
||||||
will(returnValue(Arrays.asList(contactId)));
|
will(returnValue(Arrays.asList(contactId)));
|
||||||
oneOf(database).addStatus(txn, contactId, messageId, false);
|
oneOf(database).addStatus(txn, contactId, messageId, false);
|
||||||
oneOf(database).getRating(txn, authorId);
|
|
||||||
will(returnValue(UNRATED));
|
|
||||||
oneOf(database).getNumberOfSendableChildren(txn, messageId);
|
|
||||||
will(returnValue(0));
|
|
||||||
oneOf(database).setSendability(txn, messageId, 0);
|
|
||||||
oneOf(database).commitTransaction(txn);
|
oneOf(database).commitTransaction(txn);
|
||||||
// The message was added, so the listener should be called
|
// The message was added, so the listener should be called
|
||||||
oneOf(listener).eventOccurred(with(any(
|
oneOf(listener).eventOccurred(with(any(
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ package net.sf.briar.db;
|
|||||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||||
import static net.sf.briar.api.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
|
import static net.sf.briar.api.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
|
||||||
import static net.sf.briar.api.messaging.MessagingConstants.GROUP_SALT_LENGTH;
|
import static net.sf.briar.api.messaging.MessagingConstants.GROUP_SALT_LENGTH;
|
||||||
import static net.sf.briar.api.messaging.Rating.GOOD;
|
|
||||||
import static net.sf.briar.api.messaging.Rating.UNRATED;
|
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -153,22 +151,6 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
db.close();
|
db.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testRatings() throws Exception {
|
|
||||||
Database<Connection> db = open(false);
|
|
||||||
Connection txn = db.startTransaction();
|
|
||||||
|
|
||||||
// Unknown authors should be unrated
|
|
||||||
assertEquals(UNRATED, db.getRating(txn, authorId));
|
|
||||||
// Store a rating
|
|
||||||
db.setRating(txn, authorId, GOOD);
|
|
||||||
// Check that the rating was stored
|
|
||||||
assertEquals(GOOD, db.getRating(txn, authorId));
|
|
||||||
|
|
||||||
db.commitTransaction(txn);
|
|
||||||
db.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUnsubscribingRemovesGroupMessage() throws Exception {
|
public void testUnsubscribingRemovesGroupMessage() throws Exception {
|
||||||
Database<Connection> db = open(false);
|
Database<Connection> db = open(false);
|
||||||
@@ -264,45 +246,6 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
db.close();
|
db.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSendableGroupMessagesMustHavePositiveSendability()
|
|
||||||
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.addSubscription(txn, group);
|
|
||||||
db.addVisibility(txn, contactId, groupId);
|
|
||||||
db.setSubscriptions(txn, contactId, Arrays.asList(group), 1);
|
|
||||||
db.addGroupMessage(txn, message, false);
|
|
||||||
db.addStatus(txn, contactId, messageId, false);
|
|
||||||
|
|
||||||
// The message should not be sendable
|
|
||||||
assertFalse(db.hasSendableMessages(txn, contactId));
|
|
||||||
Iterator<MessageId> it =
|
|
||||||
db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator();
|
|
||||||
assertFalse(it.hasNext());
|
|
||||||
|
|
||||||
// Changing the sendability to > 0 should make the message sendable
|
|
||||||
db.setSendability(txn, messageId, 1);
|
|
||||||
assertTrue(db.hasSendableMessages(txn, contactId));
|
|
||||||
it = db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator();
|
|
||||||
assertTrue(it.hasNext());
|
|
||||||
assertEquals(messageId, it.next());
|
|
||||||
assertFalse(it.hasNext());
|
|
||||||
|
|
||||||
// Changing the sendability to 0 should make the message unsendable
|
|
||||||
db.setSendability(txn, messageId, 0);
|
|
||||||
assertFalse(db.hasSendableMessages(txn, contactId));
|
|
||||||
it = db.getSendableMessages(txn, contactId, ONE_MEGABYTE).iterator();
|
|
||||||
assertFalse(it.hasNext());
|
|
||||||
|
|
||||||
db.commitTransaction(txn);
|
|
||||||
db.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSendableGroupMessagesMustHaveSeenFlagFalse()
|
public void testSendableGroupMessagesMustHaveSeenFlagFalse()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
@@ -316,7 +259,6 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
db.addVisibility(txn, contactId, groupId);
|
db.addVisibility(txn, contactId, groupId);
|
||||||
db.setSubscriptions(txn, contactId, Arrays.asList(group), 1);
|
db.setSubscriptions(txn, contactId, Arrays.asList(group), 1);
|
||||||
db.addGroupMessage(txn, message, false);
|
db.addGroupMessage(txn, message, false);
|
||||||
db.setSendability(txn, messageId, 1);
|
|
||||||
|
|
||||||
// The message has no status yet, so it should not be sendable
|
// The message has no status yet, so it should not be sendable
|
||||||
assertFalse(db.hasSendableMessages(txn, contactId));
|
assertFalse(db.hasSendableMessages(txn, contactId));
|
||||||
@@ -353,7 +295,6 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.addVisibility(txn, contactId, groupId);
|
db.addVisibility(txn, contactId, groupId);
|
||||||
db.addGroupMessage(txn, message, false);
|
db.addGroupMessage(txn, message, false);
|
||||||
db.setSendability(txn, messageId, 1);
|
|
||||||
db.addStatus(txn, contactId, messageId, false);
|
db.addStatus(txn, contactId, messageId, false);
|
||||||
|
|
||||||
// The contact is not subscribed, so the message should not be sendable
|
// The contact is not subscribed, so the message should not be sendable
|
||||||
@@ -392,7 +333,6 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
db.addVisibility(txn, contactId, groupId);
|
db.addVisibility(txn, contactId, groupId);
|
||||||
db.setSubscriptions(txn, contactId, Arrays.asList(group), 1);
|
db.setSubscriptions(txn, contactId, Arrays.asList(group), 1);
|
||||||
db.addGroupMessage(txn, message, false);
|
db.addGroupMessage(txn, message, false);
|
||||||
db.setSendability(txn, messageId, 1);
|
|
||||||
db.addStatus(txn, contactId, messageId, false);
|
db.addStatus(txn, contactId, messageId, false);
|
||||||
|
|
||||||
// The message is sendable, but too large to send
|
// The message is sendable, but too large to send
|
||||||
@@ -423,7 +363,6 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.setSubscriptions(txn, contactId, Arrays.asList(group), 1);
|
db.setSubscriptions(txn, contactId, Arrays.asList(group), 1);
|
||||||
db.addGroupMessage(txn, message, false);
|
db.addGroupMessage(txn, message, false);
|
||||||
db.setSendability(txn, messageId, 1);
|
|
||||||
db.addStatus(txn, contactId, messageId, false);
|
db.addStatus(txn, contactId, messageId, false);
|
||||||
|
|
||||||
// The subscription is not visible to the contact, so the message
|
// The subscription is not visible to the contact, so the message
|
||||||
@@ -509,7 +448,6 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
db.addVisibility(txn, contactId, groupId);
|
db.addVisibility(txn, contactId, groupId);
|
||||||
db.setSubscriptions(txn, contactId, Arrays.asList(group), 1);
|
db.setSubscriptions(txn, contactId, Arrays.asList(group), 1);
|
||||||
db.addGroupMessage(txn, message, false);
|
db.addGroupMessage(txn, message, false);
|
||||||
db.setSendability(txn, messageId, 1);
|
|
||||||
db.addStatus(txn, contactId, messageId, false);
|
db.addStatus(txn, contactId, messageId, false);
|
||||||
|
|
||||||
// Retrieve the message from the database and mark it as sent
|
// Retrieve the message from the database and mark it as sent
|
||||||
@@ -568,47 +506,6 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
db.close();
|
db.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetNumberOfSendableChildren() throws Exception {
|
|
||||||
MessageId childId1 = new MessageId(TestUtils.getRandomId());
|
|
||||||
MessageId childId2 = new MessageId(TestUtils.getRandomId());
|
|
||||||
MessageId childId3 = new MessageId(TestUtils.getRandomId());
|
|
||||||
GroupId groupId1 = new GroupId(TestUtils.getRandomId());
|
|
||||||
Group group1 = new Group(groupId1, "Another group",
|
|
||||||
new byte[GROUP_SALT_LENGTH]);
|
|
||||||
Message child1 = new TestMessage(childId1, messageId, group, author,
|
|
||||||
contentType, subject, timestamp, raw);
|
|
||||||
Message child2 = new TestMessage(childId2, messageId, group, author,
|
|
||||||
contentType, subject, timestamp, raw);
|
|
||||||
// The third child is in a different group
|
|
||||||
Message child3 = new TestMessage(childId3, messageId, group1, author,
|
|
||||||
contentType, subject, timestamp, raw);
|
|
||||||
Database<Connection> db = open(false);
|
|
||||||
Connection txn = db.startTransaction();
|
|
||||||
|
|
||||||
// Subscribe to the groups and store the messages
|
|
||||||
db.addSubscription(txn, group);
|
|
||||||
db.addSubscription(txn, group1);
|
|
||||||
db.addGroupMessage(txn, message, false);
|
|
||||||
db.addGroupMessage(txn, child1, false);
|
|
||||||
db.addGroupMessage(txn, child2, false);
|
|
||||||
db.addGroupMessage(txn, child3, false);
|
|
||||||
// Make all the children sendable
|
|
||||||
db.setSendability(txn, childId1, 1);
|
|
||||||
db.setSendability(txn, childId2, 5);
|
|
||||||
db.setSendability(txn, childId3, 3);
|
|
||||||
|
|
||||||
// There should be two sendable children
|
|
||||||
assertEquals(2, db.getNumberOfSendableChildren(txn, messageId));
|
|
||||||
// Make one of the children unsendable
|
|
||||||
db.setSendability(txn, childId1, 0);
|
|
||||||
// Now there should be one sendable child
|
|
||||||
assertEquals(1, db.getNumberOfSendableChildren(txn, messageId));
|
|
||||||
|
|
||||||
db.commitTransaction(txn);
|
|
||||||
db.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetOldMessages() throws Exception {
|
public void testGetOldMessages() throws Exception {
|
||||||
MessageId messageId1 = new MessageId(TestUtils.getRandomId());
|
MessageId messageId1 = new MessageId(TestUtils.getRandomId());
|
||||||
@@ -902,8 +799,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
db.setSubscriptions(txn, contactId, Arrays.asList(group), 1);
|
db.setSubscriptions(txn, contactId, Arrays.asList(group), 1);
|
||||||
db.addGroupMessage(txn, message, false);
|
db.addGroupMessage(txn, message, false);
|
||||||
|
|
||||||
// Set the sendability to > 0 and the status to seen = true
|
// Set the status to seen = true
|
||||||
db.setSendability(txn, messageId, 1);
|
|
||||||
db.addStatus(txn, contactId, messageId, true);
|
db.addStatus(txn, contactId, messageId, true);
|
||||||
|
|
||||||
// The message is not sendable because its status is seen = true
|
// The message is not sendable because its status is seen = true
|
||||||
@@ -913,31 +809,6 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
db.close();
|
db.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetMessageIfSendableReturnsNullIfNotSendable()
|
|
||||||
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.addSubscription(txn, group);
|
|
||||||
db.addVisibility(txn, contactId, groupId);
|
|
||||||
db.setSubscriptions(txn, contactId, Arrays.asList(group), 1);
|
|
||||||
db.addGroupMessage(txn, message, false);
|
|
||||||
|
|
||||||
// Set the sendability to 0 and the status to seen = false
|
|
||||||
db.setSendability(txn, messageId, 0);
|
|
||||||
db.addStatus(txn, contactId, messageId, false);
|
|
||||||
|
|
||||||
// The message is not sendable because its sendability is 0
|
|
||||||
assertNull(db.getRawMessageIfSendable(txn, contactId, messageId));
|
|
||||||
|
|
||||||
db.commitTransaction(txn);
|
|
||||||
db.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetMessageIfSendableReturnsNullIfOld() throws Exception {
|
public void testGetMessageIfSendableReturnsNullIfOld() throws Exception {
|
||||||
Database<Connection> db = open(false);
|
Database<Connection> db = open(false);
|
||||||
@@ -953,8 +824,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
db.setRetentionTime(txn, contactId, timestamp + 1, 1);
|
db.setRetentionTime(txn, contactId, timestamp + 1, 1);
|
||||||
db.addGroupMessage(txn, message, false);
|
db.addGroupMessage(txn, message, false);
|
||||||
|
|
||||||
// Set the sendability to > 0 and the status to seen = false
|
// Set the status to seen = false
|
||||||
db.setSendability(txn, messageId, 1);
|
|
||||||
db.addStatus(txn, contactId, messageId, false);
|
db.addStatus(txn, contactId, messageId, false);
|
||||||
|
|
||||||
// The message is not sendable because it's too old
|
// The message is not sendable because it's too old
|
||||||
@@ -977,8 +847,7 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
db.setSubscriptions(txn, contactId, Arrays.asList(group), 1);
|
db.setSubscriptions(txn, contactId, Arrays.asList(group), 1);
|
||||||
db.addGroupMessage(txn, message, false);
|
db.addGroupMessage(txn, message, false);
|
||||||
|
|
||||||
// Set the sendability to > 0 and the status to seen = false
|
// Set the status to seen = false
|
||||||
db.setSendability(txn, messageId, 1);
|
|
||||||
db.addStatus(txn, contactId, messageId, false);
|
db.addStatus(txn, contactId, messageId, false);
|
||||||
|
|
||||||
// The message is sendable so it should be returned
|
// The message is sendable so it should be returned
|
||||||
|
|||||||
Reference in New Issue
Block a user