Builders for batches and bundles.

This commit is contained in:
akwizgran
2011-07-11 12:25:04 +01:00
parent 51e371f7ca
commit 4f5eb21180
13 changed files with 162 additions and 119 deletions

View File

@@ -7,6 +7,7 @@ import net.sf.briar.api.ContactId;
import net.sf.briar.api.Rating; import net.sf.briar.api.Rating;
import net.sf.briar.api.protocol.AuthorId; import net.sf.briar.api.protocol.AuthorId;
import net.sf.briar.api.protocol.Bundle; import net.sf.briar.api.protocol.Bundle;
import net.sf.briar.api.protocol.BundleBuilder;
import net.sf.briar.api.protocol.GroupId; import net.sf.briar.api.protocol.GroupId;
import net.sf.briar.api.protocol.Message; import net.sf.briar.api.protocol.Message;
@@ -48,7 +49,7 @@ public interface DatabaseComponent {
* Generates a bundle of acknowledgements, subscriptions, and batches of * Generates a bundle of acknowledgements, subscriptions, and batches of
* messages for the given contact. * messages for the given contact.
*/ */
void generateBundle(ContactId c, Bundle b) throws DbException; Bundle generateBundle(ContactId c, BundleBuilder bundleBuilder) throws DbException;
/** Returns the IDs of all contacts. */ /** Returns the IDs of all contacts. */
Set<ContactId> getContacts() throws DbException; Set<ContactId> getContacts() throws DbException;

View File

@@ -5,12 +5,7 @@ public interface Batch {
public static final long CAPACITY = 1024L * 1024L; public static final long CAPACITY = 1024L * 1024L;
/** Prepares the batch for transmission and generates its identifier. */ /** Returns the batch's unique identifier. */
public void seal();
/**
* Returns the batch's unique identifier. Cannot be called before seal().
*/
BatchId getId(); BatchId getId();
/** Returns the size of the batch in bytes. */ /** Returns the size of the batch in bytes. */
@@ -18,7 +13,4 @@ public interface Batch {
/** Returns the messages contained in the batch. */ /** Returns the messages contained in the batch. */
Iterable<Message> getMessages(); Iterable<Message> getMessages();
/** Adds a message to the batch. Cannot be called after seal(). */
void addMessage(Message m);
} }

View File

@@ -0,0 +1,10 @@
package net.sf.briar.api.protocol;
public interface BatchBuilder {
/** Adds a message to the batch. */
void addMessage(Message m);
/** Builds and returns the batch. */
Batch build();
}

View File

@@ -5,12 +5,7 @@ import java.util.Map;
/** A bundle of acknowledgements, subscriptions, and batches of messages. */ /** A bundle of acknowledgements, subscriptions, and batches of messages. */
public interface Bundle { public interface Bundle {
/** Prepares the bundle for transmission and generates its identifier. */ /** Returns the bundle's unique identifier. */
public void seal();
/**
* Returns the bundle's unique identifier. Cannot be called before seal().
*/
BundleId getId(); BundleId getId();
/** Returns the bundle's capacity in bytes. */ /** Returns the bundle's capacity in bytes. */
@@ -22,26 +17,12 @@ public interface Bundle {
/** Returns the acknowledgements contained in the bundle. */ /** Returns the acknowledgements contained in the bundle. */
Iterable<BatchId> getAcks(); Iterable<BatchId> getAcks();
/** Adds an acknowledgement to the bundle. Cannot be called after seal(). */
void addAck(BatchId b);
/** Returns the subscriptions contained in the bundle. */ /** Returns the subscriptions contained in the bundle. */
Iterable<GroupId> getSubscriptions(); Iterable<GroupId> getSubscriptions();
/** Adds a subscription to the bundle. Cannot be called after seal(). */
void addSubscription(GroupId g);
/** Returns the transport details contained in the bundle. */ /** Returns the transport details contained in the bundle. */
Map<String, String> getTransports(); Map<String, String> getTransports();
/** Adds a transport detail to the bundle. Cannot be called after seal(). */
void addTransport(String key, String value);
/** Returns the batches of messages contained in the bundle. */ /** Returns the batches of messages contained in the bundle. */
Iterable<Batch> getBatches(); Iterable<Batch> getBatches();
/**
* Adds a batch of messages to the bundle. Cannot be called after seal().
*/
void addBatch(Batch b);
} }

View File

@@ -0,0 +1,22 @@
package net.sf.briar.api.protocol;
public interface BundleBuilder {
/** Returns the bundle's capacity in bytes. */
long getCapacity();
/** Adds an acknowledgement to the bundle. */
void addAck(BatchId b);
/** Adds a subscription to the bundle. */
void addSubscription(GroupId g);
/** Adds a transport detail to the bundle. */
void addTransport(String key, String value);
/** Adds a batch of messages to the bundle. */
void addBatch(Batch b);
/** Builds and returns the bundle. */
Bundle build();
}

View File

@@ -9,7 +9,7 @@ import net.sf.briar.api.db.DatabaseComponent;
import net.sf.briar.api.db.DbException; import net.sf.briar.api.db.DbException;
import net.sf.briar.api.db.Status; import net.sf.briar.api.db.Status;
import net.sf.briar.api.protocol.AuthorId; import net.sf.briar.api.protocol.AuthorId;
import net.sf.briar.api.protocol.Batch; import net.sf.briar.api.protocol.BatchBuilder;
import net.sf.briar.api.protocol.Message; import net.sf.briar.api.protocol.Message;
import net.sf.briar.api.protocol.MessageId; import net.sf.briar.api.protocol.MessageId;
@@ -27,7 +27,7 @@ DatabaseCleaner.Callback {
protected final Database<Txn> db; protected final Database<Txn> db;
protected final DatabaseCleaner cleaner; protected final DatabaseCleaner cleaner;
protected final Provider<Batch> batchProvider; protected final Provider<BatchBuilder> batchBuilderProvider;
private final Object spaceLock = new Object(); private final Object spaceLock = new Object();
private final Object writeLock = new Object(); private final Object writeLock = new Object();
@@ -36,10 +36,10 @@ DatabaseCleaner.Callback {
private volatile boolean writesAllowed = true; private volatile boolean writesAllowed = true;
DatabaseComponentImpl(Database<Txn> db, DatabaseCleaner cleaner, DatabaseComponentImpl(Database<Txn> db, DatabaseCleaner cleaner,
Provider<Batch> batchProvider) { Provider<BatchBuilder> batchBuilderProvider) {
this.db = db; this.db = db;
this.cleaner = cleaner; this.cleaner = cleaner;
this.batchProvider = batchProvider; this.batchBuilderProvider = batchBuilderProvider;
} }
public void open(boolean resume) throws DbException { public void open(boolean resume) throws DbException {

View File

@@ -15,8 +15,10 @@ import net.sf.briar.api.db.DbException;
import net.sf.briar.api.db.NoSuchContactException; import net.sf.briar.api.db.NoSuchContactException;
import net.sf.briar.api.protocol.AuthorId; import net.sf.briar.api.protocol.AuthorId;
import net.sf.briar.api.protocol.Batch; import net.sf.briar.api.protocol.Batch;
import net.sf.briar.api.protocol.BatchBuilder;
import net.sf.briar.api.protocol.BatchId; import net.sf.briar.api.protocol.BatchId;
import net.sf.briar.api.protocol.Bundle; import net.sf.briar.api.protocol.Bundle;
import net.sf.briar.api.protocol.BundleBuilder;
import net.sf.briar.api.protocol.GroupId; import net.sf.briar.api.protocol.GroupId;
import net.sf.briar.api.protocol.Message; import net.sf.briar.api.protocol.Message;
import net.sf.briar.api.protocol.MessageId; import net.sf.briar.api.protocol.MessageId;
@@ -53,8 +55,8 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
@Inject @Inject
ReadWriteLockDatabaseComponent(Database<Txn> db, DatabaseCleaner cleaner, ReadWriteLockDatabaseComponent(Database<Txn> db, DatabaseCleaner cleaner,
Provider<Batch> batchProvider) { Provider<BatchBuilder> batchBuilderProvider) {
super(db, cleaner, batchProvider); super(db, cleaner, batchBuilderProvider);
} }
public void close() throws DbException { public void close() throws DbException {
@@ -184,7 +186,8 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
} }
} }
public void generateBundle(ContactId c, Bundle b) throws DbException { public Bundle generateBundle(ContactId c, BundleBuilder b)
throws DbException {
if(LOG.isLoggable(Level.FINE)) LOG.fine("Generating bundle for " + c); if(LOG.isLoggable(Level.FINE)) LOG.fine("Generating bundle for " + c);
// Ack all batches received from c // Ack all batches received from c
contactLock.readLock().lock(); contactLock.readLock().lock();
@@ -277,10 +280,11 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
// more messages trickling in but we can't wait forever // more messages trickling in but we can't wait forever
if(size * 2 < Batch.CAPACITY) break; if(size * 2 < Batch.CAPACITY) break;
} }
b.seal(); Bundle bundle = b.build();
if(LOG.isLoggable(Level.FINE)) if(LOG.isLoggable(Level.FINE))
LOG.fine("Bundle sent, " + b.getSize() + " bytes"); LOG.fine("Bundle generated, " + bundle.getSize() + " bytes");
System.gc(); System.gc();
return bundle;
} }
private Batch fillBatch(ContactId c, long capacity) throws DbException { private Batch fillBatch(ContactId c, long capacity) throws DbException {
@@ -290,7 +294,8 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
messageLock.readLock().lock(); messageLock.readLock().lock();
try { try {
Set<MessageId> sent; Set<MessageId> sent;
Batch b; BatchBuilder b;
Batch batch;
messageStatusLock.readLock().lock(); messageStatusLock.readLock().lock();
try { try {
Txn txn = db.startTransaction(); Txn txn = db.startTransaction();
@@ -303,13 +308,13 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
return null; // No more messages to send return null; // No more messages to send
} }
sent = new HashSet<MessageId>(); sent = new HashSet<MessageId>();
b = batchProvider.get(); b = batchBuilderProvider.get();
while(it.hasNext()) { while(it.hasNext()) {
MessageId m = it.next(); MessageId m = it.next();
b.addMessage(db.getMessage(txn, m)); b.addMessage(db.getMessage(txn, m));
sent.add(m); sent.add(m);
} }
b.seal(); batch = b.build();
db.commitTransaction(txn); db.commitTransaction(txn);
} catch(DbException e) { } catch(DbException e) {
db.abortTransaction(txn); db.abortTransaction(txn);
@@ -324,9 +329,9 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
Txn txn = db.startTransaction(); Txn txn = db.startTransaction();
try { try {
assert !sent.isEmpty(); assert !sent.isEmpty();
db.addOutstandingBatch(txn, c, b.getId(), sent); db.addOutstandingBatch(txn, c, batch.getId(), sent);
db.commitTransaction(txn); db.commitTransaction(txn);
return b; return batch;
} catch(DbException e) { } catch(DbException e) {
db.abortTransaction(txn); db.abortTransaction(txn);
throw e; throw e;

View File

@@ -3,8 +3,8 @@ package net.sf.briar.db;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@@ -14,8 +14,10 @@ import net.sf.briar.api.db.DbException;
import net.sf.briar.api.db.NoSuchContactException; import net.sf.briar.api.db.NoSuchContactException;
import net.sf.briar.api.protocol.AuthorId; import net.sf.briar.api.protocol.AuthorId;
import net.sf.briar.api.protocol.Batch; import net.sf.briar.api.protocol.Batch;
import net.sf.briar.api.protocol.BatchBuilder;
import net.sf.briar.api.protocol.BatchId; import net.sf.briar.api.protocol.BatchId;
import net.sf.briar.api.protocol.Bundle; import net.sf.briar.api.protocol.Bundle;
import net.sf.briar.api.protocol.BundleBuilder;
import net.sf.briar.api.protocol.GroupId; import net.sf.briar.api.protocol.GroupId;
import net.sf.briar.api.protocol.Message; import net.sf.briar.api.protocol.Message;
import net.sf.briar.api.protocol.MessageId; import net.sf.briar.api.protocol.MessageId;
@@ -46,8 +48,8 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
@Inject @Inject
SynchronizedDatabaseComponent(Database<Txn> db, DatabaseCleaner cleaner, SynchronizedDatabaseComponent(Database<Txn> db, DatabaseCleaner cleaner,
Provider<Batch> batchProvider) { Provider<BatchBuilder> batchBuilderProvider) {
super(db, cleaner, batchProvider); super(db, cleaner, batchBuilderProvider);
} }
public void close() throws DbException { public void close() throws DbException {
@@ -137,7 +139,8 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
} }
} }
public void generateBundle(ContactId c, Bundle b) throws DbException { public Bundle generateBundle(ContactId c, BundleBuilder b)
throws DbException {
if(LOG.isLoggable(Level.FINE)) LOG.fine("Generating bundle for " + c); if(LOG.isLoggable(Level.FINE)) LOG.fine("Generating bundle for " + c);
// Ack all batches received from c // Ack all batches received from c
synchronized(contactLock) { synchronized(contactLock) {
@@ -212,10 +215,11 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
// more messages trickling in but we can't wait forever // more messages trickling in but we can't wait forever
if(size * 2 < Batch.CAPACITY) break; if(size * 2 < Batch.CAPACITY) break;
} }
b.seal(); Bundle bundle = b.build();
if(LOG.isLoggable(Level.FINE)) if(LOG.isLoggable(Level.FINE))
LOG.fine("Bundle sent, " + b.getSize() + " bytes"); LOG.fine("Bundle generated, " + bundle.getSize() + " bytes");
System.gc(); System.gc();
return bundle;
} }
private Batch fillBatch(ContactId c, long capacity) throws DbException { private Batch fillBatch(ContactId c, long capacity) throws DbException {
@@ -232,19 +236,19 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
db.commitTransaction(txn); db.commitTransaction(txn);
return null; // No more messages to send return null; // No more messages to send
} }
Batch b = batchProvider.get(); BatchBuilder b = batchBuilderProvider.get();
Set<MessageId> sent = new HashSet<MessageId>(); Set<MessageId> sent = new HashSet<MessageId>();
while(it.hasNext()) { while(it.hasNext()) {
MessageId m = it.next(); MessageId m = it.next();
b.addMessage(db.getMessage(txn, m)); b.addMessage(db.getMessage(txn, m));
sent.add(m); sent.add(m);
} }
b.seal(); Batch batch = b.build();
// Record the contents of the batch // Record the contents of the batch
assert !sent.isEmpty(); assert !sent.isEmpty();
db.addOutstandingBatch(txn, c, b.getId(), sent); db.addOutstandingBatch(txn, c, batch.getId(), sent);
db.commitTransaction(txn); db.commitTransaction(txn);
return b; return batch;
} catch(DbException e) { } catch(DbException e) {
db.abortTransaction(txn); db.abortTransaction(txn);
throw e; throw e;

View File

@@ -20,6 +20,8 @@
<test name='net.sf.briar.i18n.FontManagerTest'/> <test name='net.sf.briar.i18n.FontManagerTest'/>
<test name='net.sf.briar.i18n.I18nTest'/> <test name='net.sf.briar.i18n.I18nTest'/>
<test name='net.sf.briar.invitation.InvitationWorkerTest'/> <test name='net.sf.briar.invitation.InvitationWorkerTest'/>
<test name='net.sf.briar.serial.ReaderImplTest'/>
<test name='net.sf.briar.serial.WriterImplTest'/>
<test name='net.sf.briar.setup.SetupWorkerTest'/> <test name='net.sf.briar.setup.SetupWorkerTest'/>
<test name='net.sf.briar.util.FileUtilsTest'/> <test name='net.sf.briar.util.FileUtilsTest'/>
<test name='net.sf.briar.util.StringUtilsTest'/> <test name='net.sf.briar.util.StringUtilsTest'/>

View File

@@ -6,7 +6,7 @@ import static net.sf.briar.api.db.DatabaseComponent.MIN_FREE_SPACE;
import java.util.Collections; import java.util.Collections;
import net.sf.briar.api.db.DbException; import net.sf.briar.api.db.DbException;
import net.sf.briar.api.protocol.Batch; import net.sf.briar.api.protocol.BatchBuilder;
import net.sf.briar.api.protocol.MessageId; import net.sf.briar.api.protocol.MessageId;
import net.sf.briar.db.DatabaseCleaner.Callback; import net.sf.briar.db.DatabaseCleaner.Callback;
@@ -24,7 +24,7 @@ public abstract class DatabaseComponentImplTest extends DatabaseComponentTest {
protected abstract <T> DatabaseComponentImpl<T> createDatabaseComponentImpl( protected abstract <T> DatabaseComponentImpl<T> createDatabaseComponentImpl(
Database<T> database, DatabaseCleaner cleaner, Database<T> database, DatabaseCleaner cleaner,
Provider<Batch> batchProvider); Provider<BatchBuilder> batchBuilderProvider);
@Test @Test
public void testNotCleanedIfEnoughFreeSpace() throws DbException { public void testNotCleanedIfEnoughFreeSpace() throws DbException {
@@ -33,13 +33,14 @@ public abstract class DatabaseComponentImplTest extends DatabaseComponentTest {
final Database<Object> database = context.mock(Database.class); final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class); final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Provider<Batch> batchProvider = context.mock(Provider.class); final Provider<BatchBuilder> batchBuilderProvider =
context.mock(Provider.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).getFreeSpace(); oneOf(database).getFreeSpace();
will(returnValue(MIN_FREE_SPACE)); will(returnValue(MIN_FREE_SPACE));
}}); }});
Callback db = createDatabaseComponentImpl(database, cleaner, Callback db = createDatabaseComponentImpl(database, cleaner,
batchProvider); batchBuilderProvider);
db.checkFreeSpaceAndClean(); db.checkFreeSpaceAndClean();
@@ -53,7 +54,8 @@ public abstract class DatabaseComponentImplTest extends DatabaseComponentTest {
final Database<Object> database = context.mock(Database.class); final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class); final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Provider<Batch> batchProvider = context.mock(Provider.class); final Provider<BatchBuilder> batchBuilderProvider =
context.mock(Provider.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).getFreeSpace(); oneOf(database).getFreeSpace();
will(returnValue(MIN_FREE_SPACE - 1)); will(returnValue(MIN_FREE_SPACE - 1));
@@ -67,7 +69,7 @@ public abstract class DatabaseComponentImplTest extends DatabaseComponentTest {
will(returnValue(MIN_FREE_SPACE)); will(returnValue(MIN_FREE_SPACE));
}}); }});
Callback db = createDatabaseComponentImpl(database, cleaner, Callback db = createDatabaseComponentImpl(database, cleaner,
batchProvider); batchBuilderProvider);
db.checkFreeSpaceAndClean(); db.checkFreeSpaceAndClean();
@@ -82,7 +84,8 @@ public abstract class DatabaseComponentImplTest extends DatabaseComponentTest {
final Database<Object> database = context.mock(Database.class); final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class); final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Provider<Batch> batchProvider = context.mock(Provider.class); final Provider<BatchBuilder> batchBuilderProvider =
context.mock(Provider.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).getFreeSpace(); oneOf(database).getFreeSpace();
will(returnValue(MIN_FREE_SPACE - 1)); will(returnValue(MIN_FREE_SPACE - 1));
@@ -98,7 +101,7 @@ public abstract class DatabaseComponentImplTest extends DatabaseComponentTest {
will(returnValue(MIN_FREE_SPACE)); will(returnValue(MIN_FREE_SPACE));
}}); }});
Callback db = createDatabaseComponentImpl(database, cleaner, Callback db = createDatabaseComponentImpl(database, cleaner,
batchProvider); batchBuilderProvider);
db.checkFreeSpaceAndClean(); db.checkFreeSpaceAndClean();
@@ -113,7 +116,8 @@ public abstract class DatabaseComponentImplTest extends DatabaseComponentTest {
final Database<Object> database = context.mock(Database.class); final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class); final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Provider<Batch> batchProvider = context.mock(Provider.class); final Provider<BatchBuilder> batchBuilderProvider =
context.mock(Provider.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(database).getFreeSpace(); oneOf(database).getFreeSpace();
will(returnValue(MIN_FREE_SPACE - 1)); will(returnValue(MIN_FREE_SPACE - 1));
@@ -131,7 +135,7 @@ public abstract class DatabaseComponentImplTest extends DatabaseComponentTest {
will(returnValue(MIN_FREE_SPACE)); will(returnValue(MIN_FREE_SPACE));
}}); }});
Callback db = createDatabaseComponentImpl(database, cleaner, Callback db = createDatabaseComponentImpl(database, cleaner,
batchProvider); batchBuilderProvider);
db.checkFreeSpaceAndClean(); db.checkFreeSpaceAndClean();

View File

@@ -14,8 +14,10 @@ import net.sf.briar.api.db.NoSuchContactException;
import net.sf.briar.api.db.Status; import net.sf.briar.api.db.Status;
import net.sf.briar.api.protocol.AuthorId; import net.sf.briar.api.protocol.AuthorId;
import net.sf.briar.api.protocol.Batch; import net.sf.briar.api.protocol.Batch;
import net.sf.briar.api.protocol.BatchBuilder;
import net.sf.briar.api.protocol.BatchId; import net.sf.briar.api.protocol.BatchId;
import net.sf.briar.api.protocol.Bundle; import net.sf.briar.api.protocol.Bundle;
import net.sf.briar.api.protocol.BundleBuilder;
import net.sf.briar.api.protocol.BundleId; import net.sf.briar.api.protocol.BundleId;
import net.sf.briar.api.protocol.GroupId; import net.sf.briar.api.protocol.GroupId;
import net.sf.briar.api.protocol.Message; import net.sf.briar.api.protocol.Message;
@@ -62,7 +64,7 @@ public abstract class DatabaseComponentTest extends TestCase {
protected abstract <T> DatabaseComponent createDatabaseComponent( protected abstract <T> DatabaseComponent createDatabaseComponent(
Database<T> database, DatabaseCleaner cleaner, Database<T> database, DatabaseCleaner cleaner,
Provider<Batch> batchProvider); Provider<BatchBuilder> batchBuilderProvider);
@Test @Test
public void testSimpleCalls() throws DbException { public void testSimpleCalls() throws DbException {
@@ -76,7 +78,8 @@ public abstract class DatabaseComponentTest extends TestCase {
final Database<Object> database = context.mock(Database.class); final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class); final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Provider<Batch> batchProvider = context.mock(Provider.class); final Provider<BatchBuilder> batchBuilderProvider =
context.mock(Provider.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
allowing(database).startTransaction(); allowing(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -116,7 +119,7 @@ public abstract class DatabaseComponentTest extends TestCase {
oneOf(database).close(); oneOf(database).close();
}}); }});
DatabaseComponent db = createDatabaseComponent(database, cleaner, DatabaseComponent db = createDatabaseComponent(database, cleaner,
batchProvider); batchBuilderProvider);
db.open(false); db.open(false);
assertEquals(Rating.UNRATED, db.getRating(authorId)); assertEquals(Rating.UNRATED, db.getRating(authorId));
@@ -141,7 +144,8 @@ public abstract class DatabaseComponentTest extends TestCase {
final Database<Object> database = context.mock(Database.class); final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class); final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Provider<Batch> batchProvider = context.mock(Provider.class); final Provider<BatchBuilder> batchBuilderProvider =
context.mock(Provider.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// setRating(Rating.GOOD) // setRating(Rating.GOOD)
allowing(database).startTransaction(); allowing(database).startTransaction();
@@ -159,7 +163,7 @@ public abstract class DatabaseComponentTest extends TestCase {
oneOf(database).commitTransaction(txn); oneOf(database).commitTransaction(txn);
}}); }});
DatabaseComponent db = createDatabaseComponent(database, cleaner, DatabaseComponent db = createDatabaseComponent(database, cleaner,
batchProvider); batchBuilderProvider);
db.setRating(authorId, Rating.GOOD); db.setRating(authorId, Rating.GOOD);
@@ -174,7 +178,8 @@ public abstract class DatabaseComponentTest extends TestCase {
final Database<Object> database = context.mock(Database.class); final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class); final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Provider<Batch> batchProvider = context.mock(Provider.class); final Provider<BatchBuilder> batchBuilderProvider =
context.mock(Provider.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// setRating(Rating.GOOD) // setRating(Rating.GOOD)
oneOf(database).startTransaction(); oneOf(database).startTransaction();
@@ -195,7 +200,7 @@ public abstract class DatabaseComponentTest extends TestCase {
oneOf(database).commitTransaction(txn); oneOf(database).commitTransaction(txn);
}}); }});
DatabaseComponent db = createDatabaseComponent(database, cleaner, DatabaseComponent db = createDatabaseComponent(database, cleaner,
batchProvider); batchBuilderProvider);
db.setRating(authorId, Rating.GOOD); db.setRating(authorId, Rating.GOOD);
@@ -211,7 +216,8 @@ public abstract class DatabaseComponentTest extends TestCase {
final Database<Object> database = context.mock(Database.class); final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class); final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Provider<Batch> batchProvider = context.mock(Provider.class); final Provider<BatchBuilder> batchBuilderProvider =
context.mock(Provider.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// setRating(Rating.GOOD) // setRating(Rating.GOOD)
oneOf(database).startTransaction(); oneOf(database).startTransaction();
@@ -236,7 +242,7 @@ public abstract class DatabaseComponentTest extends TestCase {
oneOf(database).commitTransaction(txn); oneOf(database).commitTransaction(txn);
}}); }});
DatabaseComponent db = createDatabaseComponent(database, cleaner, DatabaseComponent db = createDatabaseComponent(database, cleaner,
batchProvider); batchBuilderProvider);
db.setRating(authorId, Rating.GOOD); db.setRating(authorId, Rating.GOOD);
@@ -252,7 +258,8 @@ public abstract class DatabaseComponentTest extends TestCase {
final Database<Object> database = context.mock(Database.class); final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class); final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Provider<Batch> batchProvider = context.mock(Provider.class); final Provider<BatchBuilder> batchBuilderProvider =
context.mock(Provider.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// setRating(Rating.GOOD) // setRating(Rating.GOOD)
oneOf(database).startTransaction(); oneOf(database).startTransaction();
@@ -280,7 +287,7 @@ public abstract class DatabaseComponentTest extends TestCase {
oneOf(database).commitTransaction(txn); oneOf(database).commitTransaction(txn);
}}); }});
DatabaseComponent db = createDatabaseComponent(database, cleaner, DatabaseComponent db = createDatabaseComponent(database, cleaner,
batchProvider); batchBuilderProvider);
db.setRating(authorId, Rating.GOOD); db.setRating(authorId, Rating.GOOD);
@@ -296,7 +303,8 @@ public abstract class DatabaseComponentTest extends TestCase {
final Database<Object> database = context.mock(Database.class); final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class); final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Provider<Batch> batchProvider = context.mock(Provider.class); final Provider<BatchBuilder> batchBuilderProvider =
context.mock(Provider.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// setRating(Rating.GOOD) // setRating(Rating.GOOD)
oneOf(database).startTransaction(); oneOf(database).startTransaction();
@@ -326,7 +334,7 @@ public abstract class DatabaseComponentTest extends TestCase {
oneOf(database).commitTransaction(txn); oneOf(database).commitTransaction(txn);
}}); }});
DatabaseComponent db = createDatabaseComponent(database, cleaner, DatabaseComponent db = createDatabaseComponent(database, cleaner,
batchProvider); batchBuilderProvider);
db.setRating(authorId, Rating.GOOD); db.setRating(authorId, Rating.GOOD);
@@ -341,7 +349,8 @@ public abstract class DatabaseComponentTest extends TestCase {
final Database<Object> database = context.mock(Database.class); final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class); final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Provider<Batch> batchProvider = context.mock(Provider.class); final Provider<BatchBuilder> batchBuilderProvider =
context.mock(Provider.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// addLocallyGeneratedMessage(message) // addLocallyGeneratedMessage(message)
oneOf(database).startTransaction(); oneOf(database).startTransaction();
@@ -351,7 +360,7 @@ public abstract class DatabaseComponentTest extends TestCase {
oneOf(database).commitTransaction(txn); oneOf(database).commitTransaction(txn);
}}); }});
DatabaseComponent db = createDatabaseComponent(database, cleaner, DatabaseComponent db = createDatabaseComponent(database, cleaner,
batchProvider); batchBuilderProvider);
db.addLocallyGeneratedMessage(message); db.addLocallyGeneratedMessage(message);
@@ -365,7 +374,8 @@ public abstract class DatabaseComponentTest extends TestCase {
final Database<Object> database = context.mock(Database.class); final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class); final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Provider<Batch> batchProvider = context.mock(Provider.class); final Provider<BatchBuilder> batchBuilderProvider =
context.mock(Provider.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// addLocallyGeneratedMessage(message) // addLocallyGeneratedMessage(message)
oneOf(database).startTransaction(); oneOf(database).startTransaction();
@@ -377,7 +387,7 @@ public abstract class DatabaseComponentTest extends TestCase {
oneOf(database).commitTransaction(txn); oneOf(database).commitTransaction(txn);
}}); }});
DatabaseComponent db = createDatabaseComponent(database, cleaner, DatabaseComponent db = createDatabaseComponent(database, cleaner,
batchProvider); batchBuilderProvider);
db.addLocallyGeneratedMessage(message); db.addLocallyGeneratedMessage(message);
@@ -391,7 +401,8 @@ public abstract class DatabaseComponentTest extends TestCase {
final Database<Object> database = context.mock(Database.class); final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class); final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Provider<Batch> batchProvider = context.mock(Provider.class); final Provider<BatchBuilder> batchBuilderProvider =
context.mock(Provider.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// addLocallyGeneratedMessage(message) // addLocallyGeneratedMessage(message)
oneOf(database).startTransaction(); oneOf(database).startTransaction();
@@ -412,7 +423,7 @@ public abstract class DatabaseComponentTest extends TestCase {
oneOf(database).commitTransaction(txn); oneOf(database).commitTransaction(txn);
}}); }});
DatabaseComponent db = createDatabaseComponent(database, cleaner, DatabaseComponent db = createDatabaseComponent(database, cleaner,
batchProvider); batchBuilderProvider);
db.addLocallyGeneratedMessage(message); db.addLocallyGeneratedMessage(message);
@@ -427,7 +438,8 @@ public abstract class DatabaseComponentTest extends TestCase {
final Database<Object> database = context.mock(Database.class); final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class); final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Provider<Batch> batchProvider = context.mock(Provider.class); final Provider<BatchBuilder> batchBuilderProvider =
context.mock(Provider.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// addLocallyGeneratedMessage(message) // addLocallyGeneratedMessage(message)
oneOf(database).startTransaction(); oneOf(database).startTransaction();
@@ -451,7 +463,7 @@ public abstract class DatabaseComponentTest extends TestCase {
oneOf(database).commitTransaction(txn); oneOf(database).commitTransaction(txn);
}}); }});
DatabaseComponent db = createDatabaseComponent(database, cleaner, DatabaseComponent db = createDatabaseComponent(database, cleaner,
batchProvider); batchBuilderProvider);
db.addLocallyGeneratedMessage(message); db.addLocallyGeneratedMessage(message);
@@ -466,8 +478,9 @@ public abstract class DatabaseComponentTest extends TestCase {
final Database<Object> database = context.mock(Database.class); final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class); final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Provider<Batch> batchProvider = context.mock(Provider.class); final Provider<BatchBuilder> batchBuilderProvider =
final Bundle bundle = context.mock(Bundle.class); context.mock(Provider.class);
final BundleBuilder bundleBuilder = context.mock(BundleBuilder.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Check that the contact is still in the DB // Check that the contact is still in the DB
oneOf(database).startTransaction(); oneOf(database).startTransaction();
@@ -477,10 +490,10 @@ public abstract class DatabaseComponentTest extends TestCase {
oneOf(database).commitTransaction(txn); oneOf(database).commitTransaction(txn);
}}); }});
DatabaseComponent db = createDatabaseComponent(database, cleaner, DatabaseComponent db = createDatabaseComponent(database, cleaner,
batchProvider); batchBuilderProvider);
try { try {
db.generateBundle(contactId, bundle); db.generateBundle(contactId, bundleBuilder);
assertTrue(false); assertTrue(false);
} catch(NoSuchContactException expected) {} } catch(NoSuchContactException expected) {}
@@ -494,9 +507,12 @@ public abstract class DatabaseComponentTest extends TestCase {
final Database<Object> database = context.mock(Database.class); final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class); final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Provider<Batch> batchProvider = context.mock(Provider.class); final Provider<BatchBuilder> batchBuilderProvider =
final Bundle bundle = context.mock(Bundle.class); context.mock(Provider.class);
final BundleBuilder bundleBuilder = context.mock(BundleBuilder.class);
final BatchBuilder batchBuilder = context.mock(BatchBuilder.class);
final Batch batch = context.mock(Batch.class); final Batch batch = context.mock(Batch.class);
final Bundle bundle = context.mock(Bundle.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
allowing(database).startTransaction(); allowing(database).startTransaction();
will(returnValue(txn)); will(returnValue(txn));
@@ -506,44 +522,46 @@ public abstract class DatabaseComponentTest extends TestCase {
// Add acks to the bundle // Add acks to the bundle
oneOf(database).removeBatchesToAck(txn, contactId); oneOf(database).removeBatchesToAck(txn, contactId);
will(returnValue(Collections.singleton(batchId))); will(returnValue(Collections.singleton(batchId)));
oneOf(bundle).addAck(batchId); oneOf(bundleBuilder).addAck(batchId);
// Add subscriptions to the bundle // Add subscriptions to the bundle
oneOf(database).getSubscriptions(txn); oneOf(database).getSubscriptions(txn);
will(returnValue(Collections.singleton(groupId))); will(returnValue(Collections.singleton(groupId)));
oneOf(bundle).addSubscription(groupId); oneOf(bundleBuilder).addSubscription(groupId);
// Add transports to the bundle // Add transports to the bundle
oneOf(database).getTransports(txn); oneOf(database).getTransports(txn);
will(returnValue(Collections.singletonMap("foo", "bar"))); will(returnValue(Collections.singletonMap("foo", "bar")));
oneOf(bundle).addTransport("foo", "bar"); oneOf(bundleBuilder).addTransport("foo", "bar");
// Prepare to add batches to the bundle // Prepare to add batches to the bundle
oneOf(bundle).getCapacity(); oneOf(bundleBuilder).getCapacity();
will(returnValue((long) ONE_MEGABYTE)); will(returnValue((long) ONE_MEGABYTE));
// Add messages to the batch // Add messages to the batch
oneOf(database).getSendableMessages(txn, contactId, ONE_MEGABYTE); oneOf(database).getSendableMessages(txn, contactId, Batch.CAPACITY);
will(returnValue(Collections.singleton(messageId))); will(returnValue(Collections.singleton(messageId)));
oneOf(batchProvider).get(); oneOf(batchBuilderProvider).get();
will(returnValue(batch)); will(returnValue(batchBuilder));
oneOf(database).getMessage(txn, messageId); oneOf(database).getMessage(txn, messageId);
will(returnValue(message)); will(returnValue(message));
oneOf(batch).addMessage(message); oneOf(batchBuilder).addMessage(message);
oneOf(batch).seal(); oneOf(batchBuilder).build();
will(returnValue(batch));
// Record the batch as outstanding // Record the batch as outstanding
oneOf(batch).getId(); oneOf(batch).getId();
will(returnValue(batchId)); will(returnValue(batchId));
oneOf(database).addOutstandingBatch(txn, contactId, batchId, oneOf(database).addOutstandingBatch(txn, contactId, batchId,
Collections.singleton(messageId)); Collections.singleton(messageId));
// Add the batch to the bundle // Add the batch to the bundle
oneOf(bundle).addBatch(batch); oneOf(bundleBuilder).addBatch(batch);
// Check whether to add another batch // Check whether to add another batch
oneOf(batch).getSize(); oneOf(batch).getSize();
will(returnValue((long) message.getSize())); will(returnValue((long) message.getSize()));
// Nope // No, just send the bundle
oneOf(bundle).seal(); oneOf(bundleBuilder).build();
will(returnValue(bundle));
}}); }});
DatabaseComponent db = createDatabaseComponent(database, cleaner, DatabaseComponent db = createDatabaseComponent(database, cleaner,
batchProvider); batchBuilderProvider);
db.generateBundle(contactId, bundle); db.generateBundle(contactId, bundleBuilder);
context.assertIsSatisfied(); context.assertIsSatisfied();
} }
@@ -556,7 +574,8 @@ public abstract class DatabaseComponentTest extends TestCase {
final Database<Object> database = context.mock(Database.class); final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class); final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Provider<Batch> batchProvider = context.mock(Provider.class); final Provider<BatchBuilder> batchBuilderProvider =
context.mock(Provider.class);
final Bundle bundle = context.mock(Bundle.class); final Bundle bundle = context.mock(Bundle.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Check that the contact is still in the DB // Check that the contact is still in the DB
@@ -567,7 +586,7 @@ public abstract class DatabaseComponentTest extends TestCase {
oneOf(database).commitTransaction(txn); oneOf(database).commitTransaction(txn);
}}); }});
DatabaseComponent db = createDatabaseComponent(database, cleaner, DatabaseComponent db = createDatabaseComponent(database, cleaner,
batchProvider); batchBuilderProvider);
try { try {
db.receiveBundle(contactId, bundle); db.receiveBundle(contactId, bundle);
@@ -586,7 +605,8 @@ public abstract class DatabaseComponentTest extends TestCase {
final Database<Object> database = context.mock(Database.class); final Database<Object> database = context.mock(Database.class);
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class); final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final Provider<Batch> batchProvider = context.mock(Provider.class); final Provider<BatchBuilder> batchBuilderProvider =
context.mock(Provider.class);
final Bundle bundle = context.mock(Bundle.class); final Bundle bundle = context.mock(Bundle.class);
final Batch batch = context.mock(Batch.class); final Batch batch = context.mock(Batch.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -630,7 +650,7 @@ public abstract class DatabaseComponentTest extends TestCase {
oneOf(database).removeLostBatch(txn, contactId, batchId); oneOf(database).removeLostBatch(txn, contactId, batchId);
}}); }});
DatabaseComponent db = createDatabaseComponent(database, cleaner, DatabaseComponent db = createDatabaseComponent(database, cleaner,
batchProvider); batchBuilderProvider);
db.receiveBundle(contactId, bundle); db.receiveBundle(contactId, bundle);

View File

@@ -1,7 +1,7 @@
package net.sf.briar.db; package net.sf.briar.db;
import net.sf.briar.api.db.DatabaseComponent; import net.sf.briar.api.db.DatabaseComponent;
import net.sf.briar.api.protocol.Batch; import net.sf.briar.api.protocol.BatchBuilder;
import com.google.inject.Provider; import com.google.inject.Provider;
@@ -11,15 +11,16 @@ extends DatabaseComponentImplTest {
@Override @Override
protected <T> DatabaseComponent createDatabaseComponent( protected <T> DatabaseComponent createDatabaseComponent(
Database<T> database, DatabaseCleaner cleaner, Database<T> database, DatabaseCleaner cleaner,
Provider<Batch> batchProvider) { Provider<BatchBuilder> batchBuilderProvider) {
return createDatabaseComponentImpl(database, cleaner, batchProvider); return createDatabaseComponentImpl(database, cleaner,
batchBuilderProvider);
} }
@Override @Override
protected <T> DatabaseComponentImpl<T> createDatabaseComponentImpl( protected <T> DatabaseComponentImpl<T> createDatabaseComponentImpl(
Database<T> database, DatabaseCleaner cleaner, Database<T> database, DatabaseCleaner cleaner,
Provider<Batch> batchProvider) { Provider<BatchBuilder> batchBuilderProvider) {
return new ReadWriteLockDatabaseComponent<T>(database, cleaner, return new ReadWriteLockDatabaseComponent<T>(database, cleaner,
batchProvider); batchBuilderProvider);
} }
} }

View File

@@ -1,7 +1,7 @@
package net.sf.briar.db; package net.sf.briar.db;
import net.sf.briar.api.db.DatabaseComponent; import net.sf.briar.api.db.DatabaseComponent;
import net.sf.briar.api.protocol.Batch; import net.sf.briar.api.protocol.BatchBuilder;
import com.google.inject.Provider; import com.google.inject.Provider;
@@ -11,15 +11,16 @@ extends DatabaseComponentImplTest {
@Override @Override
protected <T> DatabaseComponent createDatabaseComponent( protected <T> DatabaseComponent createDatabaseComponent(
Database<T> database, DatabaseCleaner cleaner, Database<T> database, DatabaseCleaner cleaner,
Provider<Batch> batchProvider) { Provider<BatchBuilder> batchBuilderProvider) {
return createDatabaseComponentImpl(database, cleaner, batchProvider); return createDatabaseComponentImpl(database, cleaner,
batchBuilderProvider);
} }
@Override @Override
protected <T> DatabaseComponentImpl<T> createDatabaseComponentImpl( protected <T> DatabaseComponentImpl<T> createDatabaseComponentImpl(
Database<T> database, DatabaseCleaner cleaner, Database<T> database, DatabaseCleaner cleaner,
Provider<Batch> batchProvider) { Provider<BatchBuilder> batchBuilderProvider) {
return new SynchronizedDatabaseComponent<T>(database, cleaner, return new SynchronizedDatabaseComponent<T>(database, cleaner,
batchProvider); batchBuilderProvider);
} }
} }