diff --git a/api/net/sf/briar/api/db/DatabaseComponent.java b/api/net/sf/briar/api/db/DatabaseComponent.java index 5a1352e7384a0556c7b20b927d6fe14229f4f563..4a5da87dd835582373662ced2a8a69f5d6eaeb6f 100644 --- a/api/net/sf/briar/api/db/DatabaseComponent.java +++ b/api/net/sf/briar/api/db/DatabaseComponent.java @@ -79,8 +79,9 @@ public interface DatabaseComponent { /** * Generates a batch of messages for the given contact from the given - * collection of requested messages, and returns the IDs of the messages - * added to the bacth. + * collection of requested messages, and returns the IDs of any messages + * that were either added to the batch, or were considered for inclusion + * but are no longer sendable to the contact. */ Collection<MessageId> generateBatch(ContactId c, BatchWriter b, Collection<MessageId> requested) throws DbException, IOException; diff --git a/components/net/sf/briar/db/ReadWriteLockDatabaseComponent.java b/components/net/sf/briar/db/ReadWriteLockDatabaseComponent.java index a4cd24cac44ab5624494b66ff486cda273835261..996d24e9aa9526f16ba914ff74b734a887a16e1b 100644 --- a/components/net/sf/briar/db/ReadWriteLockDatabaseComponent.java +++ b/components/net/sf/briar/db/ReadWriteLockDatabaseComponent.java @@ -300,13 +300,11 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> { try { Txn txn = db.startTransaction(); try { + sent = new ArrayList<MessageId>(); int capacity = b.getCapacity(); Collection<MessageId> sendable = db.getSendableMessages(txn, c, capacity); - Iterator<MessageId> it = sendable.iterator(); - sent = new ArrayList<MessageId>(); - while(it.hasNext()) { - MessageId m = it.next(); + for(MessageId m : sendable) { byte[] raw = db.getMessage(txn, m); if(!b.writeMessage(raw)) break; bytesSent += raw.length; @@ -326,9 +324,9 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> { } finally { messageStatusLock.readLock().unlock(); } - BatchId id = b.finish(); // Record the contents of the batch, unless it's empty if(sent.isEmpty()) return; + BatchId id = b.finish(); messageStatusLock.writeLock().lock(); try { Txn txn = db.startTransaction(); @@ -357,7 +355,7 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> { if(!containsContact(c)) throw new NoSuchContactException(); messageLock.readLock().lock(); try { - Collection<MessageId> sent; + Collection<MessageId> sent, considered; messageStatusLock.readLock().lock(); try{ subscriptionLock.readLock().lock(); @@ -365,13 +363,20 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> { Txn txn = db.startTransaction(); try { sent = new ArrayList<MessageId>(); + considered = new ArrayList<MessageId>(); int bytesSent = 0; for(MessageId m : requested) { byte[] raw = db.getMessageIfSendable(txn, c, m); - if(raw == null) continue; - if(!b.writeMessage(raw)) break; - bytesSent += raw.length; - sent.add(m); + // If the message is still sendable, try to add + // it to the batch. If the batch is full, don't + // treat the message as considered, and don't + // try to add any further messages. + if(raw != null) { + if(!b.writeMessage(raw)) break; + bytesSent += raw.length; + sent.add(m); + } + considered.add(m); } db.commitTransaction(txn); } catch(DbException e) { @@ -387,16 +392,16 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> { } finally { messageStatusLock.readLock().unlock(); } - BatchId id = b.finish(); // Record the contents of the batch, unless it's empty - if(sent.isEmpty()) return sent; + if(sent.isEmpty()) return considered; + BatchId id = b.finish(); messageStatusLock.writeLock().lock(); try { Txn txn = db.startTransaction(); try { db.addOutstandingBatch(txn, c, id, sent); db.commitTransaction(txn); - return sent; + return considered; } catch(DbException e) { db.abortTransaction(txn); throw e; diff --git a/components/net/sf/briar/db/SynchronizedDatabaseComponent.java b/components/net/sf/briar/db/SynchronizedDatabaseComponent.java index af8f67cd02e72093691124e1ca6d5720b157879d..3c1aecd158f49f79486aa2b7c12166b9be8f978e 100644 --- a/components/net/sf/briar/db/SynchronizedDatabaseComponent.java +++ b/components/net/sf/briar/db/SynchronizedDatabaseComponent.java @@ -223,23 +223,24 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> { synchronized(subscriptionLock) { Txn txn = db.startTransaction(); try { - int capacity = b.getCapacity(); - Collection<MessageId> sendable = - db.getSendableMessages(txn, c, capacity); - Iterator<MessageId> it = sendable.iterator(); Collection<MessageId> sent = new ArrayList<MessageId>(); int bytesSent = 0; - while(it.hasNext()) { - MessageId m = it.next(); + int capacity = b.getCapacity(); + Collection<MessageId> sendable = + db.getSendableMessages(txn, c, capacity); + for(MessageId m : sendable) { byte[] raw = db.getMessage(txn, m); if(!b.writeMessage(raw)) break; bytesSent += raw.length; sent.add(m); } - BatchId id = b.finish(); - if(!sent.isEmpty()) + // If the batch is not empty, calculate its ID and + // record it as outstanding + if(!sent.isEmpty()) { + BatchId id = b.finish(); db.addOutstandingBatch(txn, c, id, sent); + } db.commitTransaction(txn); } catch(DbException e) { db.abortTransaction(txn); @@ -265,19 +266,30 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> { try { Collection<MessageId> sent = new ArrayList<MessageId>(); + Collection<MessageId> considered = + new ArrayList<MessageId>(); int bytesSent = 0; for(MessageId m : requested) { byte[] raw = db.getMessageIfSendable(txn, c, m); - if(raw == null) continue; - if(!b.writeMessage(raw)) break; - bytesSent += raw.length; - sent.add(m); + // If the message is still sendable, try to add + // it to the batch. If the batch is full, don't + // treat the message as considered, and don't + // try to add any further messages. + if(raw != null) { + if(!b.writeMessage(raw)) break; + bytesSent += raw.length; + sent.add(m); + } + considered.add(m); } - BatchId id = b.finish(); - if(!sent.isEmpty()) + // If the batch is not empty, calculate its ID and + // record it as outstanding + if(!sent.isEmpty()) { + BatchId id = b.finish(); db.addOutstandingBatch(txn, c, id, sent); + } db.commitTransaction(txn); - return sent; + return considered; } catch(DbException e) { db.abortTransaction(txn); throw e;