mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-20 14:49:53 +01:00
Transport details for contacts can be stored in the database (these are arbitrary key/value pairs that describe how to reach the contact using a particular transport). Moved the generic ContactId and Rating classes out of the database package of the API.
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
package net.sf.briar.api.db;
|
package net.sf.briar.api;
|
||||||
|
|
||||||
/** Type-safe wrapper for an integer that uniquely identifies a contact. */
|
/** Type-safe wrapper for an integer that uniquely identifies a contact. */
|
||||||
public class ContactId {
|
public class ContactId {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package net.sf.briar.api.db;
|
package net.sf.briar.api;
|
||||||
|
|
||||||
/** The ratings that may be applied to an author in peer moderation. */
|
/** The ratings that may be applied to an author in peer moderation. */
|
||||||
public enum Rating {
|
public enum Rating {
|
||||||
@@ -1,7 +1,10 @@
|
|||||||
package net.sf.briar.api.db;
|
package net.sf.briar.api.db;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import net.sf.briar.api.ContactId;
|
||||||
|
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.GroupId;
|
import net.sf.briar.api.protocol.GroupId;
|
||||||
@@ -32,8 +35,11 @@ public interface DatabaseComponent {
|
|||||||
/** Waits for any open transactions to finish and closes the database. */
|
/** Waits for any open transactions to finish and closes the database. */
|
||||||
void close() throws DbException;
|
void close() throws DbException;
|
||||||
|
|
||||||
/** Adds a new contact to the database and returns an ID for the contact. */
|
/**
|
||||||
ContactId addContact() throws DbException;
|
* Adds a new contact to the database with the given transport details and
|
||||||
|
* returns an ID for the contact.
|
||||||
|
*/
|
||||||
|
ContactId addContact(Map<String, String> transports) throws DbException;
|
||||||
|
|
||||||
/** Adds a locally generated message to the database. */
|
/** Adds a locally generated message to the database. */
|
||||||
void addLocallyGeneratedMessage(Message m) throws DbException;
|
void addLocallyGeneratedMessage(Message m) throws DbException;
|
||||||
@@ -53,6 +59,9 @@ public interface DatabaseComponent {
|
|||||||
/** Returns the set of groups to which the user subscribes. */
|
/** Returns the set of groups to which the user subscribes. */
|
||||||
Set<GroupId> getSubscriptions() throws DbException;
|
Set<GroupId> getSubscriptions() throws DbException;
|
||||||
|
|
||||||
|
/** Returns the transport details for the given contact. */
|
||||||
|
Map<String, String> getTransports(ContactId c) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes a bundle of acknowledgements, subscriptions, and batches of
|
* Processes a bundle of acknowledgements, subscriptions, and batches of
|
||||||
* messages received from the given contact. Some or all of the messages
|
* messages received from the given contact. Some or all of the messages
|
||||||
@@ -66,6 +75,12 @@ public interface DatabaseComponent {
|
|||||||
/** Records the user's rating for the given author. */
|
/** Records the user's rating for the given author. */
|
||||||
void setRating(AuthorId a, Rating r) throws DbException;
|
void setRating(AuthorId a, Rating r) throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Records the transport details for the given contact, replacing any
|
||||||
|
* existing transport details.
|
||||||
|
*/
|
||||||
|
void setTransports(ContactId c, Map<String, String> transports) throws DbException;
|
||||||
|
|
||||||
/** Subscribes to the given group. */
|
/** Subscribes to the given group. */
|
||||||
void subscribe(GroupId g) throws DbException;
|
void subscribe(GroupId g) throws DbException;
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
package net.sf.briar.db;
|
package net.sf.briar.db;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import net.sf.briar.api.ContactId;
|
||||||
|
import net.sf.briar.api.Rating;
|
||||||
import net.sf.briar.api.db.DbException;
|
import net.sf.briar.api.db.DbException;
|
||||||
import net.sf.briar.api.db.ContactId;
|
|
||||||
import net.sf.briar.api.db.Rating;
|
|
||||||
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.BatchId;
|
import net.sf.briar.api.protocol.BatchId;
|
||||||
@@ -28,6 +29,7 @@ import net.sf.briar.api.protocol.MessageId;
|
|||||||
* <li> messageStatuses
|
* <li> messageStatuses
|
||||||
* <li> ratings
|
* <li> ratings
|
||||||
* <li> subscriptions
|
* <li> subscriptions
|
||||||
|
* <li> transports
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
interface Database<T> {
|
interface Database<T> {
|
||||||
@@ -49,7 +51,11 @@ interface Database<T> {
|
|||||||
*/
|
*/
|
||||||
void open(boolean resume) throws DbException;
|
void open(boolean resume) throws DbException;
|
||||||
|
|
||||||
/** Waits for all open transactions to finish and closes the database. */
|
/**
|
||||||
|
* Waits for all open transactions to finish and closes the database.
|
||||||
|
* <p>
|
||||||
|
* Locking: all locks write.
|
||||||
|
*/
|
||||||
void close() throws DbException;
|
void close() throws DbException;
|
||||||
|
|
||||||
/** Starts a new transaction and returns an object representing it. */
|
/** Starts a new transaction and returns an object representing it. */
|
||||||
@@ -75,11 +81,12 @@ interface Database<T> {
|
|||||||
void addBatchToAck(T txn, ContactId c, BatchId b) throws DbException;
|
void addBatchToAck(T txn, ContactId c, BatchId b) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a new contact to the database and returns an ID for the contact.
|
* Adds a new contact to the database with the given transport details and
|
||||||
|
* returns an ID for the contact.
|
||||||
* <p>
|
* <p>
|
||||||
* Locking: contacts write, messageStatuses write.
|
* Locking: contacts write, transports write.
|
||||||
*/
|
*/
|
||||||
ContactId addContact(T txn) throws DbException;
|
ContactId addContact(T txn, Map<String, String> transports) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns false if the given message is already in the database. Otherwise
|
* Returns false if the given message is already in the database. Otherwise
|
||||||
@@ -115,14 +122,14 @@ interface Database<T> {
|
|||||||
/**
|
/**
|
||||||
* Records a contact's subscription to a group.
|
* Records a contact's subscription to a group.
|
||||||
* <p>
|
* <p>
|
||||||
* Locking: contacts read, messageStatuses write.
|
* Locking: contacts read, subscriptions write.
|
||||||
*/
|
*/
|
||||||
void addSubscription(T txn, ContactId c, GroupId g) throws DbException;
|
void addSubscription(T txn, ContactId c, GroupId g) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes all recorded subscriptions for the given contact.
|
* Removes all recorded subscriptions for the given contact.
|
||||||
* <p>
|
* <p>
|
||||||
* Locking: contacts read, messageStatuses write.
|
* Locking: contacts read, subscriptions write.
|
||||||
*/
|
*/
|
||||||
void clearSubscriptions(T txn, ContactId c) throws DbException;
|
void clearSubscriptions(T txn, ContactId c) throws DbException;
|
||||||
|
|
||||||
@@ -150,7 +157,7 @@ interface Database<T> {
|
|||||||
/**
|
/**
|
||||||
* Returns the IDs of all contacts.
|
* Returns the IDs of all contacts.
|
||||||
* <p>
|
* <p>
|
||||||
* Locking: contacts read, messageStatuses read.
|
* Locking: contacts read.
|
||||||
*/
|
*/
|
||||||
Set<ContactId> getContacts(T txn) throws DbException;
|
Set<ContactId> getContacts(T txn) throws DbException;
|
||||||
|
|
||||||
@@ -238,6 +245,13 @@ interface Database<T> {
|
|||||||
*/
|
*/
|
||||||
Set<GroupId> getSubscriptions(T txn) throws DbException;
|
Set<GroupId> getSubscriptions(T txn) throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the transport details for the given contact.
|
||||||
|
* <p>
|
||||||
|
* Locking: contacts read, transports read.
|
||||||
|
*/
|
||||||
|
Map<String, String> getTransports(T txn, ContactId c) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes an outstanding batch that has been acknowledged. Any messages in
|
* Removes an outstanding batch that has been acknowledged. Any messages in
|
||||||
* the batch that are still considered outstanding (Status.SENT) with
|
* the batch that are still considered outstanding (Status.SENT) with
|
||||||
@@ -258,7 +272,8 @@ interface Database<T> {
|
|||||||
/**
|
/**
|
||||||
* Removes a contact (and all associated state) from the database.
|
* Removes a contact (and all associated state) from the database.
|
||||||
* <p>
|
* <p>
|
||||||
* Locking: contacts write, messageStatuses write.
|
* Locking: contacts write, messageStatuses write, subscriptions write,
|
||||||
|
* transports write.
|
||||||
*/
|
*/
|
||||||
void removeContact(T txn, ContactId c) throws DbException;
|
void removeContact(T txn, ContactId c) throws DbException;
|
||||||
|
|
||||||
@@ -282,20 +297,20 @@ interface Database<T> {
|
|||||||
* Unsubscribes from the given group. Any messages belonging to the group
|
* Unsubscribes from the given group. Any messages belonging to the group
|
||||||
* are deleted from the database.
|
* are deleted from the database.
|
||||||
* <p>
|
* <p>
|
||||||
* Locking: contacts read, subscriptions write, messages write,
|
* Locking: contacts read, messages write, messageStatuses write,
|
||||||
* messageStatuses write.
|
* subscriptions write.
|
||||||
*/
|
*/
|
||||||
void removeSubscription(T txn, GroupId g) throws DbException;
|
void removeSubscription(T txn, GroupId g) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Records the user's rating for the given author.
|
* Sets the user's rating for the given author.
|
||||||
* <p>
|
* <p>
|
||||||
* Locking: ratings write.
|
* Locking: ratings write.
|
||||||
*/
|
*/
|
||||||
Rating setRating(T txn, AuthorId a, Rating r) throws DbException;
|
Rating setRating(T txn, AuthorId a, Rating r) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Records the sendability score of the given message.
|
* Sets the sendability score of the given message.
|
||||||
* <p>
|
* <p>
|
||||||
* Locking: messages write.
|
* Locking: messages write.
|
||||||
*/
|
*/
|
||||||
@@ -307,4 +322,12 @@ interface Database<T> {
|
|||||||
* Locking: contacts read, messages read, messageStatuses write.
|
* Locking: contacts read, messages read, messageStatuses write.
|
||||||
*/
|
*/
|
||||||
void setStatus(T txn, ContactId c, MessageId m, Status s) throws DbException;
|
void setStatus(T txn, ContactId c, MessageId m, Status s) throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the transport details for the given contact, replacing any existing
|
||||||
|
* transport details.
|
||||||
|
* <p>
|
||||||
|
* Locking: contacts read, transports write.
|
||||||
|
*/
|
||||||
|
void setTransports(T txn, ContactId c, Map<String, String> transports) throws DbException;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ package net.sf.briar.db;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import net.sf.briar.api.db.ContactId;
|
import net.sf.briar.api.ContactId;
|
||||||
|
import net.sf.briar.api.Rating;
|
||||||
import net.sf.briar.api.db.DatabaseComponent;
|
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.Rating;
|
|
||||||
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;
|
||||||
|
|||||||
@@ -13,13 +13,16 @@ import java.util.Collections;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.TreeMap;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import net.sf.briar.api.db.ContactId;
|
import net.sf.briar.api.ContactId;
|
||||||
|
import net.sf.briar.api.Rating;
|
||||||
import net.sf.briar.api.db.DbException;
|
import net.sf.briar.api.db.DbException;
|
||||||
import net.sf.briar.api.db.Rating;
|
|
||||||
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.BatchId;
|
import net.sf.briar.api.protocol.BatchId;
|
||||||
@@ -147,6 +150,15 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
private static final String INDEX_STATUSES_BY_CONTACT =
|
private static final String INDEX_STATUSES_BY_CONTACT =
|
||||||
"CREATE INDEX statusesByContact ON statuses (contactId)";
|
"CREATE INDEX statusesByContact ON statuses (contactId)";
|
||||||
|
|
||||||
|
private static final String CREATE_TRANSPORTS =
|
||||||
|
"CREATE TABLE transports"
|
||||||
|
+ " (contactId INT NOT NULL,"
|
||||||
|
+ " detailKey VARCHAR NOT NULL,"
|
||||||
|
+ " detailValue VARCHAR NOT NULL,"
|
||||||
|
+ " PRIMARY KEY (contactId, detailKey),"
|
||||||
|
+ " FOREIGN KEY (contactId) REFERENCES contacts (contactId)"
|
||||||
|
+ " ON DELETE CASCADE)";
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(JdbcDatabase.class.getName());
|
Logger.getLogger(JdbcDatabase.class.getName());
|
||||||
|
|
||||||
@@ -236,6 +248,9 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
s.executeUpdate(insertHashType(CREATE_STATUSES));
|
s.executeUpdate(insertHashType(CREATE_STATUSES));
|
||||||
s.executeUpdate(INDEX_STATUSES_BY_MESSAGE);
|
s.executeUpdate(INDEX_STATUSES_BY_MESSAGE);
|
||||||
s.executeUpdate(INDEX_STATUSES_BY_CONTACT);
|
s.executeUpdate(INDEX_STATUSES_BY_CONTACT);
|
||||||
|
if(LOG.isLoggable(Level.FINE))
|
||||||
|
LOG.fine("Creating transports table");
|
||||||
|
s.executeUpdate(insertHashType(CREATE_TRANSPORTS));
|
||||||
s.close();
|
s.close();
|
||||||
} catch(SQLException e) {
|
} catch(SQLException e) {
|
||||||
tryToClose(s);
|
tryToClose(s);
|
||||||
@@ -363,7 +378,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ContactId addContact(Connection txn) throws DbException {
|
public ContactId addContact(Connection txn, Map<String, String> transports)
|
||||||
|
throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try {
|
try {
|
||||||
@@ -400,6 +416,25 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
rowsAffected = ps.executeUpdate();
|
rowsAffected = ps.executeUpdate();
|
||||||
assert rowsAffected == 1;
|
assert rowsAffected == 1;
|
||||||
ps.close();
|
ps.close();
|
||||||
|
// Store the contact's transport details
|
||||||
|
if(transports != null) {
|
||||||
|
sql = "INSERT INTO transports"
|
||||||
|
+ " (contactId, detailKey, detailValue)"
|
||||||
|
+ " VALUES (?, ?, ?)";
|
||||||
|
ps = txn.prepareStatement(sql);
|
||||||
|
ps.setInt(1, c.getInt());
|
||||||
|
for(Entry<String, String> e : transports.entrySet()) {
|
||||||
|
ps.setString(2, e.getKey());
|
||||||
|
ps.setString(3, e.getValue());
|
||||||
|
ps.addBatch();
|
||||||
|
}
|
||||||
|
int[] rowsAffectedArray = ps.executeBatch();
|
||||||
|
assert rowsAffectedArray.length == transports.size();
|
||||||
|
for(int i = 0; i < rowsAffectedArray.length; i++) {
|
||||||
|
assert rowsAffectedArray[i] == 1;
|
||||||
|
}
|
||||||
|
ps.close();
|
||||||
|
}
|
||||||
return c;
|
return c;
|
||||||
} catch(SQLException e) {
|
} catch(SQLException e) {
|
||||||
tryToClose(ps);
|
tryToClose(ps);
|
||||||
@@ -476,10 +511,10 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
ps.setBytes(3, m.getBytes());
|
ps.setBytes(3, m.getBytes());
|
||||||
ps.addBatch();
|
ps.addBatch();
|
||||||
}
|
}
|
||||||
int[] rowsAffected1 = ps.executeBatch();
|
int[] rowsAffectedArray = ps.executeBatch();
|
||||||
assert rowsAffected1.length == sent.size();
|
assert rowsAffectedArray.length == sent.size();
|
||||||
for(int i = 0; i < rowsAffected1.length; i++) {
|
for(int i = 0; i < rowsAffectedArray.length; i++) {
|
||||||
assert rowsAffected1[i] == 1;
|
assert rowsAffectedArray[i] == 1;
|
||||||
}
|
}
|
||||||
ps.close();
|
ps.close();
|
||||||
// Set the status of each message in the batch to SENT
|
// Set the status of each message in the batch to SENT
|
||||||
@@ -493,10 +528,10 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
ps.setBytes(2, m.getBytes());
|
ps.setBytes(2, m.getBytes());
|
||||||
ps.addBatch();
|
ps.addBatch();
|
||||||
}
|
}
|
||||||
rowsAffected1 = ps.executeBatch();
|
rowsAffectedArray = ps.executeBatch();
|
||||||
assert rowsAffected1.length == sent.size();
|
assert rowsAffectedArray.length == sent.size();
|
||||||
for(int i = 0; i < rowsAffected1.length; i++) {
|
for(int i = 0; i < rowsAffectedArray.length; i++) {
|
||||||
assert rowsAffected1[i] <= 1;
|
assert rowsAffectedArray[i] <= 1;
|
||||||
}
|
}
|
||||||
ps.close();
|
ps.close();
|
||||||
} catch(SQLException e) {
|
} catch(SQLException e) {
|
||||||
@@ -1067,6 +1102,29 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getTransports(Connection txn, ContactId c)
|
||||||
|
throws DbException {
|
||||||
|
PreparedStatement ps = null;
|
||||||
|
ResultSet rs = null;
|
||||||
|
try {
|
||||||
|
String sql = "SELECT detailKey, detailValue FROM transports"
|
||||||
|
+ " WHERE contactId = ?";
|
||||||
|
ps = txn.prepareStatement(sql);
|
||||||
|
ps.setInt(1, c.getInt());
|
||||||
|
rs = ps.executeQuery();
|
||||||
|
Map<String, String> transports = new TreeMap<String, String>();
|
||||||
|
while(rs.next()) transports.put(rs.getString(1), rs.getString(2));
|
||||||
|
rs.close();
|
||||||
|
ps.close();
|
||||||
|
return transports;
|
||||||
|
} catch(SQLException e) {
|
||||||
|
tryToClose(rs);
|
||||||
|
tryToClose(ps);
|
||||||
|
tryToClose(txn);
|
||||||
|
throw new DbException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void removeAckedBatch(Connection txn, ContactId c, BatchId b)
|
public void removeAckedBatch(Connection txn, ContactId c, BatchId b)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
removeBatch(txn, c, b, Status.SEEN);
|
removeBatch(txn, c, b, Status.SEEN);
|
||||||
@@ -1097,18 +1155,18 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
rs.close();
|
rs.close();
|
||||||
ps.close();
|
ps.close();
|
||||||
int[] rowsAffected = ps1.executeBatch();
|
int[] rowsAffectedArray = ps1.executeBatch();
|
||||||
assert rowsAffected.length == messages;
|
assert rowsAffectedArray.length == messages;
|
||||||
for(int i = 0; i < rowsAffected.length; i++) {
|
for(int i = 0; i < rowsAffectedArray.length; i++) {
|
||||||
assert rowsAffected[i] <= 1;
|
assert rowsAffectedArray[i] <= 1;
|
||||||
}
|
}
|
||||||
ps1.close();
|
ps1.close();
|
||||||
// Cascade on delete
|
// Cascade on delete
|
||||||
sql = "DELETE FROM outstandingBatches WHERE batchId = ?";
|
sql = "DELETE FROM outstandingBatches WHERE batchId = ?";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setBytes(1, b.getBytes());
|
ps.setBytes(1, b.getBytes());
|
||||||
int rowsAffected1 = ps.executeUpdate();
|
int rowsAffected = ps.executeUpdate();
|
||||||
assert rowsAffected1 <= 1;
|
assert rowsAffected <= 1;
|
||||||
ps.close();
|
ps.close();
|
||||||
} catch(SQLException e) {
|
} catch(SQLException e) {
|
||||||
tryToClose(rs);
|
tryToClose(rs);
|
||||||
@@ -1314,4 +1372,40 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
throw new DbException(e);
|
throw new DbException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setTransports(Connection txn, ContactId c,
|
||||||
|
Map<String, String> transports) throws DbException {
|
||||||
|
PreparedStatement ps = null;
|
||||||
|
try {
|
||||||
|
// Delete any existing transports
|
||||||
|
String sql = "DELETE FROM transports WHERE contactId = ?";
|
||||||
|
ps = txn.prepareStatement(sql);
|
||||||
|
ps.setInt(1, c.getInt());
|
||||||
|
ps.executeUpdate();
|
||||||
|
ps.close();
|
||||||
|
// Store the new transports
|
||||||
|
if(transports != null) {
|
||||||
|
sql = "INSERT INTO transports"
|
||||||
|
+ " (contactId, detailKey, detailValue)"
|
||||||
|
+ " VALUES (?, ?, ?)";
|
||||||
|
ps = txn.prepareStatement(sql);
|
||||||
|
ps.setInt(1, c.getInt());
|
||||||
|
for(Entry<String, String> e : transports.entrySet()) {
|
||||||
|
ps.setString(2, e.getKey());
|
||||||
|
ps.setString(3, e.getValue());
|
||||||
|
ps.addBatch();
|
||||||
|
}
|
||||||
|
int[] rowsAffectedArray = ps.executeBatch();
|
||||||
|
assert rowsAffectedArray.length == transports.size();
|
||||||
|
for(int i = 0; i < rowsAffectedArray.length; i++) {
|
||||||
|
assert rowsAffectedArray[i] == 1;
|
||||||
|
}
|
||||||
|
ps.close();
|
||||||
|
}
|
||||||
|
} catch(SQLException e) {
|
||||||
|
tryToClose(ps);
|
||||||
|
tryToClose(txn);
|
||||||
|
throw new DbException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,15 +2,16 @@ 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.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import net.sf.briar.api.db.ContactId;
|
import net.sf.briar.api.ContactId;
|
||||||
|
import net.sf.briar.api.Rating;
|
||||||
import net.sf.briar.api.db.DbException;
|
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.db.Rating;
|
|
||||||
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.BatchId;
|
import net.sf.briar.api.protocol.BatchId;
|
||||||
@@ -46,6 +47,8 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
new ReentrantReadWriteLock(true);
|
new ReentrantReadWriteLock(true);
|
||||||
private final ReentrantReadWriteLock subscriptionLock =
|
private final ReentrantReadWriteLock subscriptionLock =
|
||||||
new ReentrantReadWriteLock(true);
|
new ReentrantReadWriteLock(true);
|
||||||
|
private final ReentrantReadWriteLock transportLock =
|
||||||
|
new ReentrantReadWriteLock(true);
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
ReadWriteLockDatabaseComponent(Database<Txn> db, DatabaseCleaner cleaner,
|
ReadWriteLockDatabaseComponent(Database<Txn> db, DatabaseCleaner cleaner,
|
||||||
@@ -83,15 +86,16 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ContactId addContact() throws DbException {
|
public ContactId addContact(Map<String, String> transports)
|
||||||
|
throws DbException {
|
||||||
if(LOG.isLoggable(Level.FINE)) LOG.fine("Adding contact");
|
if(LOG.isLoggable(Level.FINE)) LOG.fine("Adding contact");
|
||||||
contactLock.writeLock().lock();
|
contactLock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
messageStatusLock.writeLock().lock();
|
transportLock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
Txn txn = db.startTransaction();
|
Txn txn = db.startTransaction();
|
||||||
try {
|
try {
|
||||||
ContactId c = db.addContact(txn);
|
ContactId c = db.addContact(txn, transports);
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
if(LOG.isLoggable(Level.FINE))
|
if(LOG.isLoggable(Level.FINE))
|
||||||
LOG.fine("Added contact " + c);
|
LOG.fine("Added contact " + c);
|
||||||
@@ -101,7 +105,7 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
messageStatusLock.writeLock().unlock();
|
transportLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
contactLock.writeLock().unlock();
|
contactLock.writeLock().unlock();
|
||||||
@@ -313,19 +317,14 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
public Set<ContactId> getContacts() throws DbException {
|
public Set<ContactId> getContacts() throws DbException {
|
||||||
contactLock.readLock().lock();
|
contactLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
messageStatusLock.readLock().lock();
|
Txn txn = db.startTransaction();
|
||||||
try {
|
try {
|
||||||
Txn txn = db.startTransaction();
|
Set<ContactId> contacts = db.getContacts(txn);
|
||||||
try {
|
db.commitTransaction(txn);
|
||||||
Set<ContactId> contacts = db.getContacts(txn);
|
return contacts;
|
||||||
db.commitTransaction(txn);
|
} catch(DbException e) {
|
||||||
return contacts;
|
db.abortTransaction(txn);
|
||||||
} catch(DbException e) {
|
throw e;
|
||||||
db.abortTransaction(txn);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
messageStatusLock.readLock().unlock();
|
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
contactLock.readLock().unlock();
|
contactLock.readLock().unlock();
|
||||||
@@ -366,6 +365,29 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getTransports(ContactId c) throws DbException {
|
||||||
|
contactLock.readLock().lock();
|
||||||
|
try {
|
||||||
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
|
transportLock.readLock().lock();
|
||||||
|
try {
|
||||||
|
Txn txn = db.startTransaction();
|
||||||
|
try {
|
||||||
|
Map<String, String> transports = db.getTransports(txn, c);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
return transports;
|
||||||
|
} catch(DbException e) {
|
||||||
|
db.abortTransaction(txn);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
transportLock.readLock().unlock();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
contactLock.readLock().unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void receiveBundle(ContactId c, Bundle b) throws DbException {
|
public void receiveBundle(ContactId c, Bundle b) throws DbException {
|
||||||
if(LOG.isLoggable(Level.FINE))
|
if(LOG.isLoggable(Level.FINE))
|
||||||
LOG.fine("Received bundle from " + c + ", "
|
LOG.fine("Received bundle from " + c + ", "
|
||||||
@@ -405,7 +427,7 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
contactLock.readLock().lock();
|
contactLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
if(!containsContact(c)) throw new NoSuchContactException();
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
messageStatusLock.writeLock().lock();
|
subscriptionLock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
Txn txn = db.startTransaction();
|
Txn txn = db.startTransaction();
|
||||||
try {
|
try {
|
||||||
@@ -423,7 +445,7 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
messageStatusLock.writeLock().unlock();
|
subscriptionLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
contactLock.readLock().lock();
|
contactLock.readLock().lock();
|
||||||
@@ -539,13 +561,23 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
try {
|
try {
|
||||||
messageStatusLock.writeLock().lock();
|
messageStatusLock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
Txn txn = db.startTransaction();
|
subscriptionLock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
db.removeContact(txn, c);
|
transportLock.writeLock().lock();
|
||||||
db.commitTransaction(txn);
|
try {
|
||||||
} catch(DbException e) {
|
Txn txn = db.startTransaction();
|
||||||
db.abortTransaction(txn);
|
try {
|
||||||
throw e;
|
db.removeContact(txn, c);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} catch(DbException e) {
|
||||||
|
db.abortTransaction(txn);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
transportLock.writeLock().unlock();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
subscriptionLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
messageStatusLock.writeLock().unlock();
|
messageStatusLock.writeLock().unlock();
|
||||||
@@ -581,6 +613,29 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setTransports(ContactId c, Map<String, String> transports)
|
||||||
|
throws DbException {
|
||||||
|
contactLock.readLock().lock();
|
||||||
|
try {
|
||||||
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
|
transportLock.writeLock().lock();
|
||||||
|
try {
|
||||||
|
Txn txn = db.startTransaction();
|
||||||
|
try {
|
||||||
|
db.setTransports(txn, c, transports);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} catch(DbException e) {
|
||||||
|
db.abortTransaction(txn);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
transportLock.writeLock().unlock();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
contactLock.readLock().unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void subscribe(GroupId g) throws DbException {
|
public void subscribe(GroupId g) throws DbException {
|
||||||
if(LOG.isLoggable(Level.FINE)) LOG.fine("Subscribing to " + g);
|
if(LOG.isLoggable(Level.FINE)) LOG.fine("Subscribing to " + g);
|
||||||
subscriptionLock.writeLock().lock();
|
subscriptionLock.writeLock().lock();
|
||||||
|
|||||||
@@ -2,14 +2,15 @@ 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.Set;
|
import java.util.Set;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import net.sf.briar.api.ContactId;
|
||||||
|
import net.sf.briar.api.Rating;
|
||||||
import net.sf.briar.api.db.DbException;
|
import net.sf.briar.api.db.DbException;
|
||||||
import net.sf.briar.api.db.ContactId;
|
|
||||||
import net.sf.briar.api.db.NoSuchContactException;
|
import net.sf.briar.api.db.NoSuchContactException;
|
||||||
import net.sf.briar.api.db.Rating;
|
|
||||||
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.BatchId;
|
import net.sf.briar.api.protocol.BatchId;
|
||||||
@@ -40,6 +41,7 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
private final Object messageStatusLock = new Object();
|
private final Object messageStatusLock = new Object();
|
||||||
private final Object ratingLock = new Object();
|
private final Object ratingLock = new Object();
|
||||||
private final Object subscriptionLock = new Object();
|
private final Object subscriptionLock = new Object();
|
||||||
|
private final Object transportLock = new Object();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
SynchronizedDatabaseComponent(Database<Txn> db, DatabaseCleaner cleaner,
|
SynchronizedDatabaseComponent(Database<Txn> db, DatabaseCleaner cleaner,
|
||||||
@@ -54,7 +56,9 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
synchronized(messageStatusLock) {
|
synchronized(messageStatusLock) {
|
||||||
synchronized(ratingLock) {
|
synchronized(ratingLock) {
|
||||||
synchronized(subscriptionLock) {
|
synchronized(subscriptionLock) {
|
||||||
db.close();
|
synchronized(transportLock) {
|
||||||
|
db.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -62,13 +66,14 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ContactId addContact() throws DbException {
|
public ContactId addContact(Map<String, String> transports)
|
||||||
|
throws DbException {
|
||||||
if(LOG.isLoggable(Level.FINE)) LOG.fine("Adding contact");
|
if(LOG.isLoggable(Level.FINE)) LOG.fine("Adding contact");
|
||||||
synchronized(contactLock) {
|
synchronized(contactLock) {
|
||||||
synchronized(messageStatusLock) {
|
synchronized(transportLock) {
|
||||||
Txn txn = db.startTransaction();
|
Txn txn = db.startTransaction();
|
||||||
try {
|
try {
|
||||||
ContactId c = db.addContact(txn);
|
ContactId c = db.addContact(txn, transports);
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
if(LOG.isLoggable(Level.FINE))
|
if(LOG.isLoggable(Level.FINE))
|
||||||
LOG.fine("Added contact " + c);
|
LOG.fine("Added contact " + c);
|
||||||
@@ -229,16 +234,14 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
|
|
||||||
public Set<ContactId> getContacts() throws DbException {
|
public Set<ContactId> getContacts() throws DbException {
|
||||||
synchronized(contactLock) {
|
synchronized(contactLock) {
|
||||||
synchronized(messageStatusLock) {
|
Txn txn = db.startTransaction();
|
||||||
Txn txn = db.startTransaction();
|
try {
|
||||||
try {
|
Set<ContactId> contacts = db.getContacts(txn);
|
||||||
Set<ContactId> contacts = db.getContacts(txn);
|
db.commitTransaction(txn);
|
||||||
db.commitTransaction(txn);
|
return contacts;
|
||||||
return contacts;
|
} catch(DbException e) {
|
||||||
} catch(DbException e) {
|
db.abortTransaction(txn);
|
||||||
db.abortTransaction(txn);
|
throw e;
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -271,6 +274,23 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getTransports(ContactId c) throws DbException {
|
||||||
|
synchronized(contactLock) {
|
||||||
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
|
synchronized(transportLock) {
|
||||||
|
Txn txn = db.startTransaction();
|
||||||
|
try {
|
||||||
|
Map<String, String> transports = db.getTransports(txn, c);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
return transports;
|
||||||
|
} catch(DbException e) {
|
||||||
|
db.abortTransaction(txn);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void receiveBundle(ContactId c, Bundle b) throws DbException {
|
public void receiveBundle(ContactId c, Bundle b) throws DbException {
|
||||||
if(LOG.isLoggable(Level.FINE))
|
if(LOG.isLoggable(Level.FINE))
|
||||||
LOG.fine("Received bundle from " + c + ", "
|
LOG.fine("Received bundle from " + c + ", "
|
||||||
@@ -300,7 +320,7 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
// Update the contact's subscriptions
|
// Update the contact's subscriptions
|
||||||
synchronized(contactLock) {
|
synchronized(contactLock) {
|
||||||
if(!containsContact(c)) throw new NoSuchContactException();
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
synchronized(messageStatusLock) {
|
synchronized(subscriptionLock) {
|
||||||
Txn txn = db.startTransaction();
|
Txn txn = db.startTransaction();
|
||||||
try {
|
try {
|
||||||
db.clearSubscriptions(txn, c);
|
db.clearSubscriptions(txn, c);
|
||||||
@@ -397,13 +417,17 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
if(LOG.isLoggable(Level.FINE)) LOG.fine("Removing contact " + c);
|
if(LOG.isLoggable(Level.FINE)) LOG.fine("Removing contact " + c);
|
||||||
synchronized(contactLock) {
|
synchronized(contactLock) {
|
||||||
synchronized(messageStatusLock) {
|
synchronized(messageStatusLock) {
|
||||||
Txn txn = db.startTransaction();
|
synchronized(subscriptionLock) {
|
||||||
try {
|
synchronized(transportLock) {
|
||||||
db.removeContact(txn, c);
|
Txn txn = db.startTransaction();
|
||||||
db.commitTransaction(txn);
|
try {
|
||||||
} catch(DbException e) {
|
db.removeContact(txn, c);
|
||||||
db.abortTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
throw e;
|
} catch(DbException e) {
|
||||||
|
db.abortTransaction(txn);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -429,6 +453,23 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setTransports(ContactId c, Map<String, String> transports)
|
||||||
|
throws DbException {
|
||||||
|
synchronized(contactLock) {
|
||||||
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
|
synchronized(transportLock) {
|
||||||
|
Txn txn = db.startTransaction();
|
||||||
|
try {
|
||||||
|
db.setTransports(txn, c, transports);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} catch(DbException e) {
|
||||||
|
db.abortTransaction(txn);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void subscribe(GroupId g) throws DbException {
|
public void subscribe(GroupId g) throws DbException {
|
||||||
if(LOG.isLoggable(Level.FINE)) LOG.fine("Subscribing to " + g);
|
if(LOG.isLoggable(Level.FINE)) LOG.fine("Subscribing to " + g);
|
||||||
synchronized(subscriptionLock) {
|
synchronized(subscriptionLock) {
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
package net.sf.briar.db;
|
package net.sf.briar.db;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
import net.sf.briar.TestUtils;
|
import net.sf.briar.TestUtils;
|
||||||
import net.sf.briar.api.db.ContactId;
|
import net.sf.briar.api.ContactId;
|
||||||
|
import net.sf.briar.api.Rating;
|
||||||
import net.sf.briar.api.db.DatabaseComponent;
|
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.NoSuchContactException;
|
import net.sf.briar.api.db.NoSuchContactException;
|
||||||
import net.sf.briar.api.db.Rating;
|
|
||||||
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;
|
||||||
@@ -65,6 +66,10 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSimpleCalls() throws DbException {
|
public void testSimpleCalls() throws DbException {
|
||||||
|
final Map<String, String> transports =
|
||||||
|
Collections.singletonMap("foo", "bar");
|
||||||
|
final Map<String, String> transports1 =
|
||||||
|
Collections.singletonMap("foo", "bar baz");
|
||||||
final Set<GroupId> subs = Collections.singleton(groupId);
|
final Set<GroupId> subs = Collections.singleton(groupId);
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@@ -82,12 +87,21 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
// getRating(authorId)
|
// getRating(authorId)
|
||||||
oneOf(database).getRating(txn, authorId);
|
oneOf(database).getRating(txn, authorId);
|
||||||
will(returnValue(Rating.UNRATED));
|
will(returnValue(Rating.UNRATED));
|
||||||
// addContact(contactId)
|
// addContact(transports)
|
||||||
oneOf(database).addContact(txn);
|
oneOf(database).addContact(txn, transports);
|
||||||
will(returnValue(contactId));
|
will(returnValue(contactId));
|
||||||
// getContacts()
|
// getContacts()
|
||||||
oneOf(database).getContacts(txn);
|
oneOf(database).getContacts(txn);
|
||||||
will(returnValue(Collections.singleton(contactId)));
|
will(returnValue(Collections.singleton(contactId)));
|
||||||
|
// getTransports(contactId)
|
||||||
|
oneOf(database).containsContact(txn, contactId);
|
||||||
|
will(returnValue(true));
|
||||||
|
oneOf(database).getTransports(txn, contactId);
|
||||||
|
will(returnValue(transports));
|
||||||
|
// setTransports(contactId, transports1)
|
||||||
|
oneOf(database).containsContact(txn, contactId);
|
||||||
|
will(returnValue(true));
|
||||||
|
oneOf(database).setTransports(txn, contactId, transports1);
|
||||||
// subscribe(groupId)
|
// subscribe(groupId)
|
||||||
oneOf(database).addSubscription(txn, groupId);
|
oneOf(database).addSubscription(txn, groupId);
|
||||||
// getSubscriptions()
|
// getSubscriptions()
|
||||||
@@ -106,8 +120,10 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
|
|
||||||
db.open(false);
|
db.open(false);
|
||||||
assertEquals(Rating.UNRATED, db.getRating(authorId));
|
assertEquals(Rating.UNRATED, db.getRating(authorId));
|
||||||
assertEquals(contactId, db.addContact());
|
assertEquals(contactId, db.addContact(transports));
|
||||||
assertEquals(Collections.singleton(contactId), db.getContacts());
|
assertEquals(Collections.singleton(contactId), db.getContacts());
|
||||||
|
assertEquals(transports, db.getTransports(contactId));
|
||||||
|
db.setTransports(contactId, transports1);
|
||||||
db.subscribe(groupId);
|
db.subscribe(groupId);
|
||||||
assertEquals(Collections.singleton(groupId), db.getSubscriptions());
|
assertEquals(Collections.singleton(groupId), db.getSubscriptions());
|
||||||
db.unsubscribe(groupId);
|
db.unsubscribe(groupId);
|
||||||
|
|||||||
@@ -6,16 +6,18 @@ import java.util.Arrays;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.TreeMap;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
import net.sf.briar.TestUtils;
|
import net.sf.briar.TestUtils;
|
||||||
|
import net.sf.briar.api.ContactId;
|
||||||
|
import net.sf.briar.api.Rating;
|
||||||
import net.sf.briar.api.crypto.Password;
|
import net.sf.briar.api.crypto.Password;
|
||||||
import net.sf.briar.api.db.ContactId;
|
|
||||||
import net.sf.briar.api.db.DbException;
|
import net.sf.briar.api.db.DbException;
|
||||||
import net.sf.briar.api.db.Rating;
|
|
||||||
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.BatchId;
|
import net.sf.briar.api.protocol.BatchId;
|
||||||
@@ -80,7 +82,8 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
// Store some records
|
// Store some records
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
assertFalse(db.containsContact(txn, contactId));
|
assertFalse(db.containsContact(txn, contactId));
|
||||||
assertEquals(contactId, db.addContact(txn));
|
Map<String, String> transports = Collections.singletonMap("foo", "bar");
|
||||||
|
assertEquals(contactId, db.addContact(txn, transports));
|
||||||
assertTrue(db.containsContact(txn, contactId));
|
assertTrue(db.containsContact(txn, contactId));
|
||||||
assertFalse(db.containsSubscription(txn, groupId));
|
assertFalse(db.containsSubscription(txn, groupId));
|
||||||
db.addSubscription(txn, groupId);
|
db.addSubscription(txn, groupId);
|
||||||
@@ -96,6 +99,8 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
// Check that the records are still there
|
// Check that the records are still there
|
||||||
txn = db.startTransaction();
|
txn = db.startTransaction();
|
||||||
assertTrue(db.containsContact(txn, contactId));
|
assertTrue(db.containsContact(txn, contactId));
|
||||||
|
transports = db.getTransports(txn, contactId);
|
||||||
|
assertEquals(Collections.singletonMap("foo", "bar"), transports);
|
||||||
assertTrue(db.containsSubscription(txn, groupId));
|
assertTrue(db.containsSubscription(txn, groupId));
|
||||||
assertTrue(db.containsMessage(txn, messageId));
|
assertTrue(db.containsMessage(txn, messageId));
|
||||||
Message m1 = db.getMessage(txn, messageId);
|
Message m1 = db.getMessage(txn, messageId);
|
||||||
@@ -118,6 +123,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
// Check that the records are gone
|
// Check that the records are gone
|
||||||
txn = db.startTransaction();
|
txn = db.startTransaction();
|
||||||
assertFalse(db.containsContact(txn, contactId));
|
assertFalse(db.containsContact(txn, contactId));
|
||||||
|
assertEquals(Collections.emptyMap(), db.getTransports(txn, contactId));
|
||||||
assertFalse(db.containsSubscription(txn, groupId));
|
assertFalse(db.containsSubscription(txn, groupId));
|
||||||
assertFalse(db.containsMessage(txn, messageId));
|
assertFalse(db.containsMessage(txn, messageId));
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
@@ -130,28 +136,25 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
ContactId contactId2 = new ContactId(3);
|
ContactId contactId2 = new ContactId(3);
|
||||||
ContactId contactId3 = new ContactId(4);
|
ContactId contactId3 = new ContactId(4);
|
||||||
MessageFactory messageFactory = new TestMessageFactory();
|
MessageFactory messageFactory = new TestMessageFactory();
|
||||||
|
|
||||||
// Create a new database
|
|
||||||
Database<Connection> db = open(false, messageFactory);
|
Database<Connection> db = open(false, messageFactory);
|
||||||
|
|
||||||
// Create three contacts
|
// Create three contacts
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
assertFalse(db.containsContact(txn, contactId));
|
assertFalse(db.containsContact(txn, contactId));
|
||||||
assertEquals(contactId, db.addContact(txn));
|
assertEquals(contactId, db.addContact(txn, null));
|
||||||
assertTrue(db.containsContact(txn, contactId));
|
assertTrue(db.containsContact(txn, contactId));
|
||||||
assertFalse(db.containsContact(txn, contactId1));
|
assertFalse(db.containsContact(txn, contactId1));
|
||||||
assertEquals(contactId1, db.addContact(txn));
|
assertEquals(contactId1, db.addContact(txn, null));
|
||||||
assertTrue(db.containsContact(txn, contactId1));
|
assertTrue(db.containsContact(txn, contactId1));
|
||||||
assertFalse(db.containsContact(txn, contactId2));
|
assertFalse(db.containsContact(txn, contactId2));
|
||||||
assertEquals(contactId2, db.addContact(txn));
|
assertEquals(contactId2, db.addContact(txn, null));
|
||||||
assertTrue(db.containsContact(txn, contactId2));
|
assertTrue(db.containsContact(txn, contactId2));
|
||||||
/*
|
|
||||||
// Delete one of the contacts
|
// Delete one of the contacts
|
||||||
db.removeContact(txn, contactId1);
|
db.removeContact(txn, contactId1);
|
||||||
assertFalse(db.containsContact(txn, contactId1));
|
assertFalse(db.containsContact(txn, contactId1));
|
||||||
*/
|
|
||||||
// Add another contact - a new ID should be created
|
// Add another contact - a new ID should be created
|
||||||
assertFalse(db.containsContact(txn, contactId3));
|
assertFalse(db.containsContact(txn, contactId3));
|
||||||
assertEquals(contactId3, db.addContact(txn));
|
assertEquals(contactId3, db.addContact(txn, null));
|
||||||
assertTrue(db.containsContact(txn, contactId3));
|
assertTrue(db.containsContact(txn, contactId3));
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
db.close();
|
db.close();
|
||||||
@@ -180,9 +183,8 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
public void testUnsubscribingRemovesMessage() throws DbException {
|
public void testUnsubscribingRemovesMessage() throws DbException {
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
MessageFactory messageFactory = context.mock(MessageFactory.class);
|
MessageFactory messageFactory = context.mock(MessageFactory.class);
|
||||||
|
|
||||||
// Create a new database
|
|
||||||
Database<Connection> db = open(false, messageFactory);
|
Database<Connection> db = open(false, messageFactory);
|
||||||
|
|
||||||
// Subscribe to a group and store a message
|
// Subscribe to a group and store a message
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
db.addSubscription(txn, groupId);
|
db.addSubscription(txn, groupId);
|
||||||
@@ -204,12 +206,11 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
public void testSendableMessagesMustBeSendable() throws DbException {
|
public void testSendableMessagesMustBeSendable() throws DbException {
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
MessageFactory messageFactory = context.mock(MessageFactory.class);
|
MessageFactory messageFactory = context.mock(MessageFactory.class);
|
||||||
|
|
||||||
// Create a new database
|
|
||||||
Database<Connection> db = open(false, messageFactory);
|
Database<Connection> db = open(false, messageFactory);
|
||||||
|
|
||||||
// Add a contact, subscribe to a group and store a message
|
// Add a contact, subscribe to a group and store a message
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
assertEquals(contactId, db.addContact(txn));
|
assertEquals(contactId, db.addContact(txn, null));
|
||||||
db.addSubscription(txn, groupId);
|
db.addSubscription(txn, groupId);
|
||||||
db.addSubscription(txn, contactId, groupId);
|
db.addSubscription(txn, contactId, groupId);
|
||||||
db.addMessage(txn, message);
|
db.addMessage(txn, message);
|
||||||
@@ -247,12 +248,11 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
public void testSendableMessagesMustBeNew() throws DbException {
|
public void testSendableMessagesMustBeNew() throws DbException {
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
MessageFactory messageFactory = context.mock(MessageFactory.class);
|
MessageFactory messageFactory = context.mock(MessageFactory.class);
|
||||||
|
|
||||||
// Create a new database
|
|
||||||
Database<Connection> db = open(false, messageFactory);
|
Database<Connection> db = open(false, messageFactory);
|
||||||
|
|
||||||
// Add a contact, subscribe to a group and store a message
|
// Add a contact, subscribe to a group and store a message
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
assertEquals(contactId, db.addContact(txn));
|
assertEquals(contactId, db.addContact(txn, null));
|
||||||
db.addSubscription(txn, groupId);
|
db.addSubscription(txn, groupId);
|
||||||
db.addSubscription(txn, contactId, groupId);
|
db.addSubscription(txn, contactId, groupId);
|
||||||
db.addMessage(txn, message);
|
db.addMessage(txn, message);
|
||||||
@@ -296,12 +296,11 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
public void testSendableMessagesMustBeSubscribed() throws DbException {
|
public void testSendableMessagesMustBeSubscribed() throws DbException {
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
MessageFactory messageFactory = context.mock(MessageFactory.class);
|
MessageFactory messageFactory = context.mock(MessageFactory.class);
|
||||||
|
|
||||||
// Create a new database
|
|
||||||
Database<Connection> db = open(false, messageFactory);
|
Database<Connection> db = open(false, messageFactory);
|
||||||
|
|
||||||
// Add a contact, subscribe to a group and store a message
|
// Add a contact, subscribe to a group and store a message
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
assertEquals(contactId, db.addContact(txn));
|
assertEquals(contactId, db.addContact(txn, null));
|
||||||
db.addSubscription(txn, groupId);
|
db.addSubscription(txn, groupId);
|
||||||
db.addMessage(txn, message);
|
db.addMessage(txn, message);
|
||||||
db.setSendability(txn, messageId, 1);
|
db.setSendability(txn, messageId, 1);
|
||||||
@@ -338,12 +337,11 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
public void testSendableMessagesMustFitCapacity() throws DbException {
|
public void testSendableMessagesMustFitCapacity() throws DbException {
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
MessageFactory messageFactory = context.mock(MessageFactory.class);
|
MessageFactory messageFactory = context.mock(MessageFactory.class);
|
||||||
|
|
||||||
// Create a new database
|
|
||||||
Database<Connection> db = open(false, messageFactory);
|
Database<Connection> db = open(false, messageFactory);
|
||||||
|
|
||||||
// Add a contact, subscribe to a group and store a message
|
// Add a contact, subscribe to a group and store a message
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
assertEquals(contactId, db.addContact(txn));
|
assertEquals(contactId, db.addContact(txn, null));
|
||||||
db.addSubscription(txn, groupId);
|
db.addSubscription(txn, groupId);
|
||||||
db.addSubscription(txn, contactId, groupId);
|
db.addSubscription(txn, contactId, groupId);
|
||||||
db.addMessage(txn, message);
|
db.addMessage(txn, message);
|
||||||
@@ -374,12 +372,11 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
BatchId batchId1 = new BatchId(TestUtils.getRandomId());
|
BatchId batchId1 = new BatchId(TestUtils.getRandomId());
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
MessageFactory messageFactory = context.mock(MessageFactory.class);
|
MessageFactory messageFactory = context.mock(MessageFactory.class);
|
||||||
|
|
||||||
// Create a new database
|
|
||||||
Database<Connection> db = open(false, messageFactory);
|
Database<Connection> db = open(false, messageFactory);
|
||||||
|
|
||||||
// Add a contact and some batches to ack
|
// Add a contact and some batches to ack
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
assertEquals(contactId, db.addContact(txn));
|
assertEquals(contactId, db.addContact(txn, null));
|
||||||
db.addBatchToAck(txn, contactId, batchId);
|
db.addBatchToAck(txn, contactId, batchId);
|
||||||
db.addBatchToAck(txn, contactId, batchId1);
|
db.addBatchToAck(txn, contactId, batchId1);
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
@@ -406,12 +403,11 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
public void testRemoveAckedBatch() throws DbException {
|
public void testRemoveAckedBatch() throws DbException {
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
MessageFactory messageFactory = context.mock(MessageFactory.class);
|
MessageFactory messageFactory = context.mock(MessageFactory.class);
|
||||||
|
|
||||||
// Create a new database
|
|
||||||
Database<Connection> db = open(false, messageFactory);
|
Database<Connection> db = open(false, messageFactory);
|
||||||
|
|
||||||
// Add a contact, subscribe to a group and store a message
|
// Add a contact, subscribe to a group and store a message
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
assertEquals(contactId, db.addContact(txn));
|
assertEquals(contactId, db.addContact(txn, null));
|
||||||
db.addSubscription(txn, groupId);
|
db.addSubscription(txn, groupId);
|
||||||
db.addSubscription(txn, contactId, groupId);
|
db.addSubscription(txn, contactId, groupId);
|
||||||
db.addMessage(txn, message);
|
db.addMessage(txn, message);
|
||||||
@@ -450,12 +446,11 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
public void testRemoveLostBatch() throws DbException {
|
public void testRemoveLostBatch() throws DbException {
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
MessageFactory messageFactory = context.mock(MessageFactory.class);
|
MessageFactory messageFactory = context.mock(MessageFactory.class);
|
||||||
|
|
||||||
// Create a new database
|
|
||||||
Database<Connection> db = open(false, messageFactory);
|
Database<Connection> db = open(false, messageFactory);
|
||||||
|
|
||||||
// Add a contact, subscribe to a group and store a message
|
// Add a contact, subscribe to a group and store a message
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
assertEquals(contactId, db.addContact(txn));
|
assertEquals(contactId, db.addContact(txn, null));
|
||||||
db.addSubscription(txn, groupId);
|
db.addSubscription(txn, groupId);
|
||||||
db.addSubscription(txn, contactId, groupId);
|
db.addSubscription(txn, contactId, groupId);
|
||||||
db.addMessage(txn, message);
|
db.addMessage(txn, message);
|
||||||
@@ -504,12 +499,11 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
Set<MessageId> empty = Collections.emptySet();
|
Set<MessageId> empty = Collections.emptySet();
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
MessageFactory messageFactory = context.mock(MessageFactory.class);
|
MessageFactory messageFactory = context.mock(MessageFactory.class);
|
||||||
|
|
||||||
// Create a new database
|
|
||||||
Database<Connection> db = open(false, messageFactory);
|
Database<Connection> db = open(false, messageFactory);
|
||||||
|
|
||||||
// Add a contact
|
// Add a contact
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
assertEquals(contactId, db.addContact(txn));
|
assertEquals(contactId, db.addContact(txn, null));
|
||||||
// Add an oustanding batch (associated with BundleId.NONE)
|
// Add an oustanding batch (associated with BundleId.NONE)
|
||||||
db.addOutstandingBatch(txn, contactId, batchId, empty);
|
db.addOutstandingBatch(txn, contactId, batchId, empty);
|
||||||
// Receive a bundle
|
// Receive a bundle
|
||||||
@@ -535,6 +529,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
lost = db.addReceivedBundle(txn, contactId, bundleId4);
|
lost = db.addReceivedBundle(txn, contactId, bundleId4);
|
||||||
assertTrue(lost.isEmpty());
|
assertTrue(lost.isEmpty());
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
|
|
||||||
db.close();
|
db.close();
|
||||||
context.assertIsSatisfied();
|
context.assertIsSatisfied();
|
||||||
}
|
}
|
||||||
@@ -547,9 +542,8 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
authorId1, timestamp, body);
|
authorId1, timestamp, body);
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
MessageFactory messageFactory = context.mock(MessageFactory.class);
|
MessageFactory messageFactory = context.mock(MessageFactory.class);
|
||||||
|
|
||||||
// Create a new database
|
|
||||||
Database<Connection> db = open(false, messageFactory);
|
Database<Connection> db = open(false, messageFactory);
|
||||||
|
|
||||||
// Subscribe to a group and store two messages
|
// Subscribe to a group and store two messages
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
db.addSubscription(txn, groupId);
|
db.addSubscription(txn, groupId);
|
||||||
@@ -589,9 +583,8 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
authorId, timestamp, body);
|
authorId, timestamp, body);
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
MessageFactory messageFactory = context.mock(MessageFactory.class);
|
MessageFactory messageFactory = context.mock(MessageFactory.class);
|
||||||
|
|
||||||
// Create a new database
|
|
||||||
Database<Connection> db = open(false, messageFactory);
|
Database<Connection> db = open(false, messageFactory);
|
||||||
|
|
||||||
// Subscribe to the groups and store the messages
|
// Subscribe to the groups and store the messages
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
db.addSubscription(txn, groupId);
|
db.addSubscription(txn, groupId);
|
||||||
@@ -626,9 +619,8 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
authorId, timestamp + 1000, body);
|
authorId, timestamp + 1000, body);
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
MessageFactory messageFactory = context.mock(MessageFactory.class);
|
MessageFactory messageFactory = context.mock(MessageFactory.class);
|
||||||
|
|
||||||
// Create a new database
|
|
||||||
Database<Connection> db = open(false, messageFactory);
|
Database<Connection> db = open(false, messageFactory);
|
||||||
|
|
||||||
// Subscribe to a group and store two messages
|
// Subscribe to a group and store two messages
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
db.addSubscription(txn, groupId);
|
db.addSubscription(txn, groupId);
|
||||||
@@ -665,9 +657,8 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
authorId, timestamp, largeBody);
|
authorId, timestamp, largeBody);
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
MessageFactory messageFactory = context.mock(MessageFactory.class);
|
MessageFactory messageFactory = context.mock(MessageFactory.class);
|
||||||
|
|
||||||
// Create a new database
|
|
||||||
Database<Connection> db = open(false, messageFactory);
|
Database<Connection> db = open(false, messageFactory);
|
||||||
|
|
||||||
// Sanity check: there should be enough space on disk for this test
|
// Sanity check: there should be enough space on disk for this test
|
||||||
assertTrue(testDir.getFreeSpace() > MAX_SIZE);
|
assertTrue(testDir.getFreeSpace() > MAX_SIZE);
|
||||||
// The free space should not be more than the allowed maximum size
|
// The free space should not be more than the allowed maximum size
|
||||||
@@ -692,9 +683,8 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
final AtomicBoolean transactionFinished = new AtomicBoolean(false);
|
final AtomicBoolean transactionFinished = new AtomicBoolean(false);
|
||||||
final AtomicBoolean closed = new AtomicBoolean(false);
|
final AtomicBoolean closed = new AtomicBoolean(false);
|
||||||
final AtomicBoolean error = new AtomicBoolean(false);
|
final AtomicBoolean error = new AtomicBoolean(false);
|
||||||
|
|
||||||
// Create a new database
|
|
||||||
final Database<Connection> db = open(false, messageFactory);
|
final Database<Connection> db = open(false, messageFactory);
|
||||||
|
|
||||||
// Start a transaction
|
// Start a transaction
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
// In another thread, close the database
|
// In another thread, close the database
|
||||||
@@ -733,9 +723,8 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
final AtomicBoolean transactionFinished = new AtomicBoolean(false);
|
final AtomicBoolean transactionFinished = new AtomicBoolean(false);
|
||||||
final AtomicBoolean closed = new AtomicBoolean(false);
|
final AtomicBoolean closed = new AtomicBoolean(false);
|
||||||
final AtomicBoolean error = new AtomicBoolean(false);
|
final AtomicBoolean error = new AtomicBoolean(false);
|
||||||
|
|
||||||
// Create a new database
|
|
||||||
final Database<Connection> db = open(false, messageFactory);
|
final Database<Connection> db = open(false, messageFactory);
|
||||||
|
|
||||||
// Start a transaction
|
// Start a transaction
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
// In another thread, close the database
|
// In another thread, close the database
|
||||||
@@ -767,6 +756,32 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
assertFalse(error.get());
|
assertFalse(error.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateTransports() throws DbException {
|
||||||
|
Mockery context = new Mockery();
|
||||||
|
MessageFactory messageFactory = context.mock(MessageFactory.class);
|
||||||
|
Database<Connection> db = open(false, messageFactory);
|
||||||
|
|
||||||
|
// Add a contact with some transport details
|
||||||
|
Connection txn = db.startTransaction();
|
||||||
|
Map<String, String> transports = Collections.singletonMap("foo", "bar");
|
||||||
|
assertEquals(contactId, db.addContact(txn, transports));
|
||||||
|
assertEquals(transports, db.getTransports(txn, contactId));
|
||||||
|
// Replace the transport details
|
||||||
|
transports = new TreeMap<String, String>();
|
||||||
|
transports.put("foo", "bar baz");
|
||||||
|
transports.put("bar", "baz quux");
|
||||||
|
db.setTransports(txn, contactId, transports);
|
||||||
|
assertEquals(transports, db.getTransports(txn, contactId));
|
||||||
|
// Remove the transport details
|
||||||
|
db.setTransports(txn, contactId, null);
|
||||||
|
assertEquals(Collections.emptyMap(), db.getTransports(txn, contactId));
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
|
||||||
|
db.close();
|
||||||
|
context.assertIsSatisfied();
|
||||||
|
}
|
||||||
|
|
||||||
private Database<Connection> open(boolean resume,
|
private Database<Connection> open(boolean resume,
|
||||||
MessageFactory messageFactory) throws DbException {
|
MessageFactory messageFactory) throws DbException {
|
||||||
final char[] passwordArray = passwordString.toCharArray();
|
final char[] passwordArray = passwordString.toCharArray();
|
||||||
|
|||||||
Reference in New Issue
Block a user