From 8dd7ec93e7bffa08b542c9fbc9805fde3763166d Mon Sep 17 00:00:00 2001 From: akwizgran Date: Wed, 21 Sep 2011 17:51:17 +0100 Subject: [PATCH] DatabaseComponent.generateAck() now returns a boolean. The return value indicates whether any batch IDs were written. AckWriter.finish() and Database.removeBatchesToAck() are only called if at least one batch ID was written. --- .../sf/briar/api/db/DatabaseComponent.java | 7 +++-- components/net/sf/briar/db/Database.java | 2 +- .../sf/briar/db/DatabaseComponentImpl.java | 30 +++++++++++++++---- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/api/net/sf/briar/api/db/DatabaseComponent.java b/api/net/sf/briar/api/db/DatabaseComponent.java index 4228f4106..8f54a123f 100644 --- a/api/net/sf/briar/api/db/DatabaseComponent.java +++ b/api/net/sf/briar/api/db/DatabaseComponent.java @@ -69,8 +69,11 @@ public interface DatabaseComponent { /** Adds a locally generated private message to the database. */ void addLocalPrivateMessage(Message m, ContactId c) throws DbException; - /** Generates an acknowledgement for the given contact. */ - void generateAck(ContactId c, AckWriter a) throws DbException, + /** + * Generates an acknowledgement for the given contact. + * @return True if any batch IDs were added to the acknowledgement. + */ + boolean generateAck(ContactId c, AckWriter a) throws DbException, IOException; /** diff --git a/components/net/sf/briar/db/Database.java b/components/net/sf/briar/db/Database.java index f6e679a0a..99809c23a 100644 --- a/components/net/sf/briar/db/Database.java +++ b/components/net/sf/briar/db/Database.java @@ -161,7 +161,7 @@ interface Database { * Returns the IDs of any batches received from the given contact that need * to be acknowledged. *

- * Locking: contacts read, messageStatuses write. + * Locking: contacts read, messageStatuses read. */ Collection getBatchesToAck(T txn, ContactId c) throws DbException; diff --git a/components/net/sf/briar/db/DatabaseComponentImpl.java b/components/net/sf/briar/db/DatabaseComponentImpl.java index 8b8c7d5c9..a0f7a3b2f 100644 --- a/components/net/sf/briar/db/DatabaseComponentImpl.java +++ b/components/net/sf/briar/db/DatabaseComponentImpl.java @@ -377,20 +377,21 @@ DatabaseCleaner.Callback { } } - public void generateAck(ContactId c, AckWriter a) throws DbException, + public boolean generateAck(ContactId c, AckWriter a) throws DbException, IOException { contactLock.readLock().lock(); try { if(!containsContact(c)) throw new NoSuchContactException(); - messageStatusLock.writeLock().lock(); + Collection sent = new ArrayList(); + messageStatusLock.readLock().lock(); try { T txn = db.startTransaction(); try { Collection acks = db.getBatchesToAck(txn, c); - Collection sent = new ArrayList(); - for(BatchId b : acks) if(a.writeBatchId(b)) sent.add(b); - a.finish(); - db.removeBatchesToAck(txn, c, sent); + for(BatchId b : acks) { + if(!a.writeBatchId(b)) break; + sent.add(b); + } if(LOG.isLoggable(Level.FINE)) LOG.fine("Added " + acks.size() + " acks"); db.commitTransaction(txn); @@ -401,6 +402,23 @@ DatabaseCleaner.Callback { db.abortTransaction(txn); throw e; } + } finally { + messageStatusLock.readLock().unlock(); + } + // Record the contents of the ack, unless it's empty + if(sent.isEmpty()) return false; + a.finish(); + messageStatusLock.writeLock().lock(); + try { + T txn = db.startTransaction(); + try { + db.removeBatchesToAck(txn, c, sent); + db.commitTransaction(txn); + return true; + } catch(DbException e) { + db.abortTransaction(txn); + throw e; + } } finally { messageStatusLock.writeLock().unlock(); }