mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 19:29:06 +01:00
DatabaseComponent throws an exception instead of returning silently if a contact is removed during an operation involving that contact. More unit tests.
This commit is contained in:
@@ -32,6 +32,16 @@ import net.sf.briar.api.protocol.MessageId;
|
||||
*/
|
||||
interface Database<T> {
|
||||
|
||||
/**
|
||||
* A batch sent to a contact is considered lost when this many bundles have
|
||||
* been received from the contact since the batch was sent.
|
||||
* <p>
|
||||
* FIXME: Come up with a better retransmission scheme. This scheme doesn't
|
||||
* cope well with transports that have high latency but send bundles
|
||||
* frequently.
|
||||
*/
|
||||
static final int RETRANSMIT_THRESHOLD = 3;
|
||||
|
||||
/**
|
||||
* Opens the database.
|
||||
* @param resume True to reopen an existing database, false to create a
|
||||
|
||||
@@ -18,7 +18,6 @@ import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import net.sf.briar.api.db.ContactId;
|
||||
import net.sf.briar.api.db.DatabaseComponent;
|
||||
import net.sf.briar.api.db.DbException;
|
||||
import net.sf.briar.api.db.Rating;
|
||||
import net.sf.briar.api.db.Status;
|
||||
@@ -527,7 +526,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
rs.close();
|
||||
ps.close();
|
||||
Set<BatchId> lost;
|
||||
if(received == DatabaseComponent.RETRANSMIT_THRESHOLD) {
|
||||
if(received == RETRANSMIT_THRESHOLD) {
|
||||
// Expire batches related to the oldest received bundle
|
||||
assert oldestBundle != null;
|
||||
lost = findLostBatches(txn, c, oldestBundle);
|
||||
|
||||
@@ -7,8 +7,9 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import net.sf.briar.api.db.DbException;
|
||||
import net.sf.briar.api.db.ContactId;
|
||||
import net.sf.briar.api.db.DbException;
|
||||
import net.sf.briar.api.db.NoSuchContactException;
|
||||
import net.sf.briar.api.db.Rating;
|
||||
import net.sf.briar.api.protocol.AuthorId;
|
||||
import net.sf.briar.api.protocol.Batch;
|
||||
@@ -120,7 +121,10 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
||||
// unsubscribed from the group
|
||||
if(db.containsSubscription(txn, m.getGroup())) {
|
||||
boolean added = storeMessage(txn, m, null);
|
||||
assert added;
|
||||
if(!added) {
|
||||
if(LOG.isLoggable(Level.FINE))
|
||||
LOG.fine("Duplicate local message");
|
||||
}
|
||||
} else {
|
||||
if(LOG.isLoggable(Level.FINE))
|
||||
LOG.fine("Not subscribed");
|
||||
@@ -177,7 +181,7 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
||||
// Ack all batches received from c
|
||||
contactLock.readLock().lock();
|
||||
try {
|
||||
if(!containsContact(c)) return;
|
||||
if(!containsContact(c)) throw new NoSuchContactException();
|
||||
messageStatusLock.writeLock().lock();
|
||||
try {
|
||||
Txn txn = db.startTransaction();
|
||||
@@ -203,7 +207,7 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
||||
// Add a list of subscriptions
|
||||
contactLock.readLock().lock();
|
||||
try {
|
||||
if(!containsContact(c)) return;
|
||||
if(!containsContact(c)) throw new NoSuchContactException();
|
||||
subscriptionLock.readLock().lock();
|
||||
try {
|
||||
Txn txn = db.startTransaction();
|
||||
@@ -246,7 +250,7 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
||||
private Batch fillBatch(ContactId c, long capacity) throws DbException {
|
||||
contactLock.readLock().lock();
|
||||
try {
|
||||
if(!containsContact(c)) return null;
|
||||
if(!containsContact(c)) throw new NoSuchContactException();
|
||||
messageLock.readLock().lock();
|
||||
try {
|
||||
Set<MessageId> sent;
|
||||
@@ -344,7 +348,7 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
||||
// Mark all messages in acked batches as seen
|
||||
contactLock.readLock().lock();
|
||||
try {
|
||||
if(!containsContact(c)) return;
|
||||
if(!containsContact(c)) throw new NoSuchContactException();
|
||||
messageLock.readLock().lock();
|
||||
try {
|
||||
messageStatusLock.writeLock().lock();
|
||||
@@ -375,7 +379,7 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
||||
// Update the contact's subscriptions
|
||||
contactLock.readLock().lock();
|
||||
try {
|
||||
if(!containsContact(c)) return;
|
||||
if(!containsContact(c)) throw new NoSuchContactException();
|
||||
messageStatusLock.writeLock().lock();
|
||||
try {
|
||||
Txn txn = db.startTransaction();
|
||||
@@ -406,7 +410,7 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
||||
waitForPermissionToWrite();
|
||||
contactLock.readLock().lock();
|
||||
try {
|
||||
if(!containsContact(c)) return;
|
||||
if(!containsContact(c)) throw new NoSuchContactException();
|
||||
messageLock.writeLock().lock();
|
||||
try {
|
||||
messageStatusLock.writeLock().lock();
|
||||
@@ -451,7 +455,7 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
||||
Set<BatchId> lost;
|
||||
contactLock.readLock().lock();
|
||||
try {
|
||||
if(!containsContact(c)) return;
|
||||
if(!containsContact(c)) throw new NoSuchContactException();
|
||||
messageLock.readLock().lock();
|
||||
try {
|
||||
messageStatusLock.writeLock().lock();
|
||||
@@ -476,7 +480,7 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
||||
for(BatchId batch : lost) {
|
||||
contactLock.readLock().lock();
|
||||
try {
|
||||
if(!containsContact(c)) return;
|
||||
if(!containsContact(c)) throw new NoSuchContactException();
|
||||
messageLock.readLock().lock();
|
||||
try {
|
||||
messageStatusLock.writeLock().lock();
|
||||
|
||||
@@ -8,6 +8,7 @@ import java.util.logging.Logger;
|
||||
|
||||
import net.sf.briar.api.db.DbException;
|
||||
import net.sf.briar.api.db.ContactId;
|
||||
import net.sf.briar.api.db.NoSuchContactException;
|
||||
import net.sf.briar.api.db.Rating;
|
||||
import net.sf.briar.api.protocol.AuthorId;
|
||||
import net.sf.briar.api.protocol.Batch;
|
||||
@@ -89,7 +90,10 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
||||
// unsubscribed from the group
|
||||
if(db.containsSubscription(txn, m.getGroup())) {
|
||||
boolean added = storeMessage(txn, m, null);
|
||||
assert added;
|
||||
if(!added) {
|
||||
if(LOG.isLoggable(Level.FINE))
|
||||
LOG.fine("Duplicate local message");
|
||||
}
|
||||
} else {
|
||||
if(LOG.isLoggable(Level.FINE))
|
||||
LOG.fine("Not subscribed");
|
||||
@@ -128,7 +132,7 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
||||
if(LOG.isLoggable(Level.FINE)) LOG.fine("Generating bundle for " + c);
|
||||
// Ack all batches received from c
|
||||
synchronized(contactLock) {
|
||||
if(!containsContact(c)) return;
|
||||
if(!containsContact(c)) throw new NoSuchContactException();
|
||||
synchronized(messageStatusLock) {
|
||||
Txn txn = db.startTransaction();
|
||||
try {
|
||||
@@ -148,7 +152,7 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
||||
}
|
||||
// Add a list of subscriptions
|
||||
synchronized(contactLock) {
|
||||
if(!containsContact(c)) return;
|
||||
if(!containsContact(c)) throw new NoSuchContactException();
|
||||
synchronized(subscriptionLock) {
|
||||
Txn txn = db.startTransaction();
|
||||
try {
|
||||
@@ -185,7 +189,7 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
||||
|
||||
private Batch fillBatch(ContactId c, long capacity) throws DbException {
|
||||
synchronized(contactLock) {
|
||||
if(!containsContact(c)) return null;
|
||||
if(!containsContact(c)) throw new NoSuchContactException();
|
||||
synchronized(messageLock) {
|
||||
synchronized(messageStatusLock) {
|
||||
Txn txn = db.startTransaction();
|
||||
@@ -254,7 +258,7 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
||||
+ b.getSize() + " bytes");
|
||||
// Mark all messages in acked batches as seen
|
||||
synchronized(contactLock) {
|
||||
if(!containsContact(c)) return;
|
||||
if(!containsContact(c)) throw new NoSuchContactException();
|
||||
synchronized(messageLock) {
|
||||
synchronized(messageStatusLock) {
|
||||
int acks = 0;
|
||||
@@ -276,7 +280,7 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
||||
}
|
||||
// Update the contact's subscriptions
|
||||
synchronized(contactLock) {
|
||||
if(!containsContact(c)) return;
|
||||
if(!containsContact(c)) throw new NoSuchContactException();
|
||||
synchronized(messageStatusLock) {
|
||||
Txn txn = db.startTransaction();
|
||||
try {
|
||||
@@ -301,7 +305,7 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
||||
batches++;
|
||||
waitForPermissionToWrite();
|
||||
synchronized(contactLock) {
|
||||
if(!containsContact(c)) return;
|
||||
if(!containsContact(c)) throw new NoSuchContactException();
|
||||
synchronized(messageLock) {
|
||||
synchronized(messageStatusLock) {
|
||||
synchronized(subscriptionLock) {
|
||||
@@ -334,7 +338,7 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
||||
// Find any lost batches that need to be retransmitted
|
||||
Set<BatchId> lost;
|
||||
synchronized(contactLock) {
|
||||
if(!containsContact(c)) return;
|
||||
if(!containsContact(c)) throw new NoSuchContactException();
|
||||
synchronized(messageLock) {
|
||||
synchronized(messageStatusLock) {
|
||||
Txn txn = db.startTransaction();
|
||||
@@ -350,7 +354,7 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
||||
}
|
||||
for(BatchId batch : lost) {
|
||||
synchronized(contactLock) {
|
||||
if(!containsContact(c)) return;
|
||||
if(!containsContact(c)) throw new NoSuchContactException();
|
||||
synchronized(messageLock) {
|
||||
synchronized(messageStatusLock) {
|
||||
Txn txn = db.startTransaction();
|
||||
|
||||
Reference in New Issue
Block a user