From 8dd7ec93e7bffa08b542c9fbc9805fde3763166d Mon Sep 17 00:00:00 2001 From: akwizgran <akwizgran@users.sourceforge.net> 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 4228f41062..8f54a123fe 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 f6e679a0ac..99809c23a9 100644 --- a/components/net/sf/briar/db/Database.java +++ b/components/net/sf/briar/db/Database.java @@ -161,7 +161,7 @@ interface Database<T> { * Returns the IDs of any batches received from the given contact that need * to be acknowledged. * <p> - * Locking: contacts read, messageStatuses write. + * Locking: contacts read, messageStatuses read. */ Collection<BatchId> 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 8b8c7d5c98..a0f7a3b2fc 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<BatchId> sent = new ArrayList<BatchId>(); + messageStatusLock.readLock().lock(); try { T txn = db.startTransaction(); try { Collection<BatchId> acks = db.getBatchesToAck(txn, c); - Collection<BatchId> sent = new ArrayList<BatchId>(); - 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(); } -- GitLab