diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java index 9ec8b5c7b..f88b613cb 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java @@ -208,6 +208,24 @@ public interface DatabaseComponent { Collection generateRequestedBatch(Transaction txn, ContactId c, int maxLength, int maxLatency) throws DbException; + /** + * Returns the number of blocks in the given message. + *

+ * Read-only. + */ + int getBlockCount(Transaction txn, MessageId m) throws DbException; + + /** + * Returns the given block of the given message. + *

+ * Read-only. + * + * @throws NoSuchBlockException if 'blockNumber' is greater than or equal + * to the number of blocks in the message + */ + byte[] getBlock(Transaction txn, MessageId m, int blockNumber) + throws DbException; + /** * Returns the contact with the given ID. *

diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/db/NoSuchBlockException.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/NoSuchBlockException.java new file mode 100644 index 000000000..3fa6688ea --- /dev/null +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/NoSuchBlockException.java @@ -0,0 +1,9 @@ +package org.briarproject.bramble.api.db; + +/** + * Thrown when a database operation is attempted for a block that is not in + * the database. This exception may occur due to concurrent updates and does + * not indicate a database error. + */ +public class NoSuchBlockException extends DbException { +} diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/BlockSourceImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/db/BlockSourceImpl.java new file mode 100644 index 000000000..da65809f2 --- /dev/null +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/BlockSourceImpl.java @@ -0,0 +1,29 @@ +package org.briarproject.bramble.db; + +import org.briarproject.bramble.api.db.DatabaseComponent; +import org.briarproject.bramble.api.db.DbException; +import org.briarproject.bramble.api.io.BlockSource; +import org.briarproject.bramble.api.sync.MessageId; + +import javax.inject.Inject; + +class BlockSourceImpl implements BlockSource { + + private final DatabaseComponent db; + + @Inject + BlockSourceImpl(DatabaseComponent db) { + this.db = db; + } + + @Override + public int getBlockCount(MessageId m) throws DbException { + return db.transactionWithResult(true, txn -> db.getBlockCount(txn, m)); + } + + @Override + public byte[] getBlock(MessageId m, int blockNumber) throws DbException { + return db.transactionWithResult(true, txn -> + db.getBlock(txn, m, blockNumber)); + } +} diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java index 97e7670c9..5f51d8910 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java @@ -14,6 +14,7 @@ import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbRunnable; import org.briarproject.bramble.api.db.Metadata; import org.briarproject.bramble.api.db.MigrationListener; +import org.briarproject.bramble.api.db.NoSuchBlockException; import org.briarproject.bramble.api.db.NoSuchContactException; import org.briarproject.bramble.api.db.NoSuchGroupException; import org.briarproject.bramble.api.db.NoSuchLocalAuthorException; @@ -420,6 +421,26 @@ class DatabaseComponentImpl implements DatabaseComponent { return messages; } + @Override + public int getBlockCount(Transaction transaction, MessageId m) + throws DbException { + T txn = unbox(transaction); + if (!db.containsMessage(txn, m)) + throw new NoSuchMessageException(); + return 1; + } + + @Override + public byte[] getBlock(Transaction transaction, MessageId m, + int blockNumber) throws DbException { + T txn = unbox(transaction); + if (!db.containsMessage(txn, m)) + throw new NoSuchMessageException(); + if (blockNumber != 0) + throw new NoSuchBlockException(); + return db.getMessage(txn, m).getBody(); + } + @Override public Contact getContact(Transaction transaction, ContactId c) throws DbException { diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseModule.java b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseModule.java index 398236583..26baa97c7 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseModule.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseModule.java @@ -3,6 +3,7 @@ package org.briarproject.bramble.db; import org.briarproject.bramble.api.db.DatabaseComponent; import org.briarproject.bramble.api.db.DatabaseConfig; import org.briarproject.bramble.api.event.EventBus; +import org.briarproject.bramble.api.io.BlockSource; import org.briarproject.bramble.api.lifecycle.ShutdownManager; import org.briarproject.bramble.api.sync.MessageFactory; import org.briarproject.bramble.api.system.Clock; @@ -31,4 +32,9 @@ public class DatabaseModule { return new DatabaseComponentImpl<>(db, Connection.class, eventBus, shutdown); } + + @Provides + BlockSource provideBlockSource(BlockSourceImpl blockSource) { + return blockSource; + } }