From 6338e5959a41df5f8072e96ee54cfb697261d49b Mon Sep 17 00:00:00 2001
From: akwizgran <akwizgran@users.sourceforge.net>
Date: Sat, 28 Dec 2013 13:55:19 +0000
Subject: [PATCH] Replaced the messagesToAck table with a flag in the statuses
 table.

---
 .../src/net/sf/briar/db/JdbcDatabase.java     | 38 +++++--------------
 .../src/net/sf/briar/db/H2DatabaseTest.java   | 22 +++++++++--
 2 files changed, 28 insertions(+), 32 deletions(-)

diff --git a/briar-core/src/net/sf/briar/db/JdbcDatabase.java b/briar-core/src/net/sf/briar/db/JdbcDatabase.java
index 8fb1a905bf..6ce8e79a87 100644
--- a/briar-core/src/net/sf/briar/db/JdbcDatabase.java
+++ b/briar-core/src/net/sf/briar/db/JdbcDatabase.java
@@ -97,6 +97,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 					+ " (contactId INT NOT NULL,"
 					+ " groupId HASH NOT NULL,"
 					+ " inbox BOOLEAN NOT NULL,"
+					+ " PRIMARY KEY (contactId, groupId),"
 					+ " FOREIGN KEY (contactId)"
 					+ " REFERENCES contacts (contactId)"
 					+ " ON DELETE CASCADE,"
@@ -156,21 +157,12 @@ abstract class JdbcDatabase implements Database<Connection> {
 	private static final String INDEX_MESSAGES_BY_TIMESTAMP =
 			"CREATE INDEX messagesByTimestamp ON messages (timestamp)";
 
-	// Locking: message
-	private static final String CREATE_MESSAGES_TO_ACK =
-			"CREATE TABLE messagesToAck"
-					+ " (messageId HASH NOT NULL," // Not a foreign key
-					+ " contactId INT NOT NULL,"
-					+ " PRIMARY KEY (messageId, contactId),"
-					+ " FOREIGN KEY (contactId)"
-					+ " REFERENCES contacts (contactId)"
-					+ " ON DELETE CASCADE)";
-
 	// Locking: message
 	private static final String CREATE_STATUSES =
 			"CREATE TABLE statuses"
 					+ " (messageId HASH NOT NULL,"
 					+ " contactId INT NOT NULL,"
+					+ " ack BOOLEAN NOT NULL,"
 					+ " seen BOOLEAN NOT NULL,"
 					+ " expiry BIGINT NOT NULL,"
 					+ " txCount INT NOT NULL,"
@@ -374,7 +366,6 @@ abstract class JdbcDatabase implements Database<Connection> {
 			s.executeUpdate(insertTypeNames(CREATE_GROUP_VERSIONS));
 			s.executeUpdate(insertTypeNames(CREATE_MESSAGES));
 			s.executeUpdate(INDEX_MESSAGES_BY_TIMESTAMP);
-			s.executeUpdate(insertTypeNames(CREATE_MESSAGES_TO_ACK));
 			s.executeUpdate(insertTypeNames(CREATE_STATUSES));
 			s.executeUpdate(INDEX_STATUSES_BY_MESSAGE);
 			s.executeUpdate(INDEX_STATUSES_BY_CONTACT);
@@ -749,24 +740,13 @@ abstract class JdbcDatabase implements Database<Connection> {
 		PreparedStatement ps = null;
 		ResultSet rs = null;
 		try {
-			String sql = "SELECT NULL FROM messagesToAck"
+			String sql = "UPDATE statuses SET ack = TRUE"
 					+ " WHERE messageId = ? AND contactId = ?";
 			ps = txn.prepareStatement(sql);
 			ps.setBytes(1, m.getBytes());
 			ps.setInt(2, c.getInt());
-			rs = ps.executeQuery();
-			boolean found = rs.next();
-			if(rs.next()) throw new DbStateException();
-			rs.close();
-			ps.close();
-			if(found) return;
-			sql = "INSERT INTO messagesToAck (messageId, contactId)"
-					+ " VALUES (?, ?)";
-			ps = txn.prepareStatement(sql);
-			ps.setBytes(1, m.getBytes());
-			ps.setInt(2, c.getInt());
 			int affected = ps.executeUpdate();
-			if(affected != 1) throw new DbStateException();
+			if(affected > 1) throw new DbStateException();
 			ps.close();
 		} catch(SQLException e) {
 			tryToClose(rs);
@@ -826,8 +806,8 @@ abstract class JdbcDatabase implements Database<Connection> {
 		PreparedStatement ps = null;
 		try {
 			String sql = "INSERT INTO statuses"
-					+ " (messageId, contactId, seen, expiry, txCount)"
-					+ " VALUES (?, ?, ?, 0, 0)";
+					+ " (messageId, contactId, ack, seen, expiry, txCount)"
+					+ " VALUES (?, ?, FALSE, ?, 0, 0)";
 			ps = txn.prepareStatement(sql);
 			ps.setBytes(1, m.getBytes());
 			ps.setInt(2, c.getInt());
@@ -1644,8 +1624,8 @@ abstract class JdbcDatabase implements Database<Connection> {
 		PreparedStatement ps = null;
 		ResultSet rs = null;
 		try {
-			String sql = "SELECT messageId FROM messagesToAck"
-					+ " WHERE contactId = ?"
+			String sql = "SELECT messageId FROM statuses"
+					+ " WHERE contactId = ? AND ack = TRUE"
 					+ " LIMIT ?";
 			ps = txn.prepareStatement(sql);
 			ps.setInt(1, c.getInt());
@@ -2548,7 +2528,7 @@ abstract class JdbcDatabase implements Database<Connection> {
 			Collection<MessageId> acked) throws DbException {
 		PreparedStatement ps = null;
 		try {
-			String sql = "DELETE FROM messagesToAck"
+			String sql = "UPDATE statuses SET ack = FALSE"
 					+ " WHERE contactId = ? AND messageId = ?";
 			ps = txn.prepareStatement(sql);
 			ps.setInt(1, c.getInt());
diff --git a/briar-tests/src/net/sf/briar/db/H2DatabaseTest.java b/briar-tests/src/net/sf/briar/db/H2DatabaseTest.java
index 0fc598ffd0..99c74b2ade 100644
--- a/briar-tests/src/net/sf/briar/db/H2DatabaseTest.java
+++ b/briar-tests/src/net/sf/briar/db/H2DatabaseTest.java
@@ -299,11 +299,21 @@ public class H2DatabaseTest extends BriarTestCase {
 		Database<Connection> db = open(false);
 		Connection txn = db.startTransaction();
 
-		// Add a contact and some messages to ack
-		MessageId messageId1 = new MessageId(TestUtils.getRandomId());
+		// Add a contact and subscribe to a group
 		db.addLocalAuthor(txn, localAuthor);
 		assertEquals(contactId, db.addContact(txn, author, localAuthorId));
+		db.addGroup(txn, group);
+		db.setGroups(txn, contactId, Arrays.asList(group), 1);
+
+		// Add some messages to ack
+		MessageId messageId1 = new MessageId(TestUtils.getRandomId());
+		Message message1 = new TestMessage(messageId1, null, group, author,
+				contentType, subject, timestamp, raw);
+		db.addMessage(txn, message, false);
+		db.addStatus(txn, contactId, messageId, true);
 		db.addMessageToAck(txn, contactId, messageId);
+		db.addMessage(txn, message1, false);
+		db.addStatus(txn, contactId, messageId1, true);
 		db.addMessageToAck(txn, contactId, messageId1);
 
 		// Both message IDs should be returned
@@ -326,9 +336,15 @@ public class H2DatabaseTest extends BriarTestCase {
 		Database<Connection> db = open(false);
 		Connection txn = db.startTransaction();
 
-		// Add a contact and receive the same message twice
+		// Add a contact and subscribe to a group
 		db.addLocalAuthor(txn, localAuthor);
 		assertEquals(contactId, db.addContact(txn, author, localAuthorId));
+		db.addGroup(txn, group);
+		db.setGroups(txn, contactId, Arrays.asList(group), 1);
+
+		// Receive the same message twice
+		db.addMessage(txn, message, false);
+		db.addStatus(txn, contactId, messageId, true);
 		db.addMessageToAck(txn, contactId, messageId);
 		db.addMessageToAck(txn, contactId, messageId);
 
-- 
GitLab