Allow Validator to access metadata for pending messages

Database queries for metadata only returned it for messages that were delivered already.
However, there are cases (e.g. a pending message needs to be delivered) where
the validator needs to retrieve the metadata from the database.

For these cases, a special database query has been introduced.
This commit is contained in:
Torsten Grote
2016-07-29 15:17:18 -03:00
parent e1bdede4f5
commit bdb876552d
7 changed files with 61 additions and 5 deletions

View File

@@ -262,7 +262,7 @@ public interface DatabaseComponent {
byte[] getRawMessage(Transaction txn, MessageId m) throws DbException;
/**
* Returns the metadata for all messages in the given group.
* Returns the metadata for all delivered messages in the given group.
* <p/>
* Read-only.
*/
@@ -280,13 +280,22 @@ public interface DatabaseComponent {
Metadata query) throws DbException;
/**
* Returns the metadata for the given message.
* Returns the metadata for the given delivered message.
* <p/>
* Read-only.
*/
Metadata getMessageMetadata(Transaction txn, MessageId m)
throws DbException;
/**
* Returns the metadata for the given delivered and pending message.
* This is meant to be only used by the ValidationManager
* <p/>
* Read-only.
*/
Metadata getMessageMetadataForValidator(Transaction txn, MessageId m)
throws DbException;
/**
* Returns the status of all messages in the given group with respect to
* the given contact.

View File

@@ -12,7 +12,6 @@ import org.briarproject.api.db.Metadata;
import org.briarproject.api.db.Transaction;
import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.ValidationManager.IncomingMessageHook;
import org.briarproject.api.system.Clock;
import static org.briarproject.api.clients.QueueMessage.QUEUE_MESSAGE_HEADER_LENGTH;
import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;

View File

@@ -310,7 +310,7 @@ interface Database<T> {
throws DbException;
/**
* Returns the metadata for all messages in the given group.
* Returns the metadata for all delivered messages in the given group.
* <p/>
* Read-only.
*/
@@ -327,6 +327,14 @@ interface Database<T> {
Map<MessageId, Metadata> getMessageMetadata(T txn, GroupId g,
Metadata query) throws DbException;
/**
* Returns the metadata for the given delivered message.
* <p/>
* Read-only.
*/
Metadata getMessageMetadataForValidator(T txn, MessageId m)
throws DbException;
/**
* Returns the metadata for the given message.
* <p/>

View File

@@ -456,6 +456,15 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
return db.getMessageMetadata(txn, m);
}
public Metadata getMessageMetadataForValidator(Transaction transaction,
MessageId m)
throws DbException {
T txn = unbox(transaction);
if (!db.containsMessage(txn, m))
throw new NoSuchMessageException();
return db.getMessageMetadataForValidator(txn, m);
}
public Collection<MessageStatus> getMessageStatus(Transaction transaction,
ContactId c, GroupId g) throws DbException {
T txn = unbox(transaction);

View File

@@ -1324,6 +1324,33 @@ abstract class JdbcDatabase implements Database<Connection> {
}
}
public Metadata getMessageMetadataForValidator(Connection txn, MessageId m)
throws DbException {
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = "SELECT key, value FROM messageMetadata AS md"
+ " JOIN messages AS m"
+ " ON m.messageId = md.messageId"
+ " WHERE (m.state = ? OR m.state = ?)"
+ " AND md.messageId = ?";
ps = txn.prepareStatement(sql);
ps.setInt(1, DELIVERED.getValue());
ps.setInt(2, PENDING.getValue());
ps.setBytes(3, m.getBytes());
rs = ps.executeQuery();
Metadata metadata = new Metadata();
while (rs.next()) metadata.put(rs.getString(1), rs.getBytes(2));
rs.close();
ps.close();
return metadata;
} catch (SQLException e) {
tryToClose(rs);
tryToClose(ps);
throw new DbException(e);
}
}
public Collection<MessageStatus> getMessageStatus(Connection txn,
ContactId c, GroupId g) throws DbException {
PreparedStatement ps = null;

View File

@@ -188,7 +188,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
byte[] raw = db.getRawMessage(txn, id);
m = parseMessage(id, raw);
g = db.getGroup(txn, m.getGroupId());
meta = db.getMessageMetadata(txn, id);
meta = db.getMessageMetadataForValidator(txn, id);
txn.setComplete();
} finally {
db.endTransaction(txn);

View File

@@ -1006,6 +1006,10 @@ public class H2DatabaseTest extends BriarTestCase {
map = db.getMessageMetadata(txn, groupId);
assertTrue(map.isEmpty());
// validator gets also metadata for pending messages
retrieved = db.getMessageMetadataForValidator(txn, messageId);
assertFalse(retrieved.isEmpty());
db.commitTransaction(txn);
db.close();
}