diff --git a/briar-api/src/org/briarproject/api/db/DatabaseComponent.java b/briar-api/src/org/briarproject/api/db/DatabaseComponent.java index 80fd14a7e69c84255a396f7e5d75b9d19d5b8f17..5609844f42a6c8337dbdc0b30d07b894c2b93773 100644 --- a/briar-api/src/org/briarproject/api/db/DatabaseComponent.java +++ b/briar-api/src/org/briarproject/api/db/DatabaseComponent.java @@ -69,6 +69,9 @@ public interface DatabaseComponent { */ void deleteMessage(MessageId m) throws DbException; + /** Deletes any metadata associated with the given message. */ + void deleteMessageMetadata(MessageId m) throws DbException; + /** * Returns an acknowledgement for the given contact, or null if there are * no messages to acknowledge. diff --git a/briar-core/src/org/briarproject/db/Database.java b/briar-core/src/org/briarproject/db/Database.java index d21e6c349523b9fed572cc31409fcee03129308b..934156308b6b53ef99322206b16f0f642ce41bad 100644 --- a/briar-core/src/org/briarproject/db/Database.java +++ b/briar-core/src/org/briarproject/db/Database.java @@ -225,6 +225,13 @@ interface Database<T> { */ void deleteMessage(T txn, MessageId m) throws DbException; + /** + * Deletes any metadata associated with the given message. + * <p> + * Locking: write. + */ + void deleteMessageMetadata(T txn, MessageId m) throws DbException; + /** * Returns the contact with the given ID. * <p> diff --git a/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java b/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java index d55501a101d6bfa2417a528775fd96a291af7a49..0a974ed8edb9095e56ea94fabdf635df4258f617 100644 --- a/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java +++ b/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java @@ -310,6 +310,23 @@ class DatabaseComponentImpl<T> implements DatabaseComponent { } } + public void deleteMessageMetadata(MessageId m) throws DbException { + lock.writeLock().lock(); + try { + T txn = db.startTransaction(); + try { + if (!db.containsMessage(txn, m)) + throw new NoSuchMessageException(); + db.deleteMessageMetadata(txn, m); + } catch (DbException e) { + db.abortTransaction(txn); + throw e; + } + } finally { + lock.writeLock().unlock(); + } + } + public Ack generateAck(ContactId c, int maxMessages) throws DbException { Collection<MessageId> ids; lock.writeLock().lock(); diff --git a/briar-core/src/org/briarproject/db/JdbcDatabase.java b/briar-core/src/org/briarproject/db/JdbcDatabase.java index 2f32e8fd8b1e3079394702718986af4a2f480f95..ac583594bd27844440519e3c9256cab770b06409 100644 --- a/briar-core/src/org/briarproject/db/JdbcDatabase.java +++ b/briar-core/src/org/briarproject/db/JdbcDatabase.java @@ -949,6 +949,22 @@ abstract class JdbcDatabase implements Database<Connection> { } } + public void deleteMessageMetadata(Connection txn, MessageId m) + throws DbException { + PreparedStatement ps = null; + try { + String sql = "DELETE FROM messageMetadata WHERE messageId = ?"; + ps = txn.prepareStatement(sql); + ps.setBytes(1, m.getBytes()); + int affected = ps.executeUpdate(); + if (affected < 0) throw new DbStateException(); + ps.close(); + } catch (SQLException e) { + tryToClose(ps); + throw new DbException(e); + } + } + public Contact getContact(Connection txn, ContactId c) throws DbException { PreparedStatement ps = null; ResultSet rs = null; diff --git a/briar-tests/src/org/briarproject/db/DatabaseComponentImplTest.java b/briar-tests/src/org/briarproject/db/DatabaseComponentImplTest.java index b0930805f3613372bff049863e98c2ac5bf43015..70a9113f23c5de966476e7efbb867f0d94236bc7 100644 --- a/briar-tests/src/org/briarproject/db/DatabaseComponentImplTest.java +++ b/briar-tests/src/org/briarproject/db/DatabaseComponentImplTest.java @@ -543,11 +543,11 @@ public class DatabaseComponentImplTest extends BriarTestCase { final EventBus eventBus = context.mock(EventBus.class); context.checking(new Expectations() {{ // Check whether the message is in the DB (which it's not) - exactly(6).of(database).startTransaction(); + exactly(8).of(database).startTransaction(); will(returnValue(txn)); - exactly(6).of(database).containsMessage(txn, messageId); + exactly(8).of(database).containsMessage(txn, messageId); will(returnValue(false)); - exactly(6).of(database).abortTransaction(txn); + exactly(8).of(database).abortTransaction(txn); // This is needed for getMessageStatus() to proceed exactly(1).of(database).containsContact(txn, contactId); will(returnValue(true)); @@ -555,6 +555,20 @@ public class DatabaseComponentImplTest extends BriarTestCase { DatabaseComponent db = createDatabaseComponent(database, eventBus, shutdown); + try { + db.deleteMessage(messageId); + fail(); + } catch (NoSuchMessageException expected) { + // Expected + } + + try { + db.deleteMessageMetadata(messageId); + fail(); + } catch (NoSuchMessageException expected) { + // Expected + } + try { db.getRawMessage(messageId); fail(); diff --git a/briar-tests/src/org/briarproject/db/H2DatabaseTest.java b/briar-tests/src/org/briarproject/db/H2DatabaseTest.java index ec0674e03faf047578599b04395254a9082623cb..1e880356b2adddadf63a084acb8b6a7223f5c4a8 100644 --- a/briar-tests/src/org/briarproject/db/H2DatabaseTest.java +++ b/briar-tests/src/org/briarproject/db/H2DatabaseTest.java @@ -939,6 +939,17 @@ public class H2DatabaseTest extends BriarTestCase { assertTrue(retrieved.containsKey("baz")); assertArrayEquals(metadata.get("baz"), retrieved.get("baz")); + // Delete the metadata + db.deleteMessageMetadata(txn, messageId); + + // Retrieve the metadata again + retrieved = db.getMessageMetadata(txn, messageId); + assertTrue(retrieved.isEmpty()); + + // Retrieve the metadata for the group again + all = db.getMessageMetadata(txn, groupId); + assertTrue(all.isEmpty()); + db.commitTransaction(txn); db.close(); }