mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 10:49:06 +01:00
Added new database events and simplified database locking.
This commit is contained in:
@@ -9,20 +9,20 @@ import net.sf.briar.api.ContactId;
|
||||
* An event that is broadcast when the set of subscriptions visible to one or
|
||||
* more contacts is updated.
|
||||
*/
|
||||
public class SubscriptionsUpdatedEvent extends DatabaseEvent {
|
||||
public class LocalSubscriptionsUpdatedEvent extends DatabaseEvent {
|
||||
|
||||
private final Collection<ContactId> affectedContacts;
|
||||
private final Collection<ContactId> affected;
|
||||
|
||||
public SubscriptionsUpdatedEvent() {
|
||||
affectedContacts = Collections.emptyList();
|
||||
public LocalSubscriptionsUpdatedEvent() {
|
||||
affected = Collections.emptyList();
|
||||
}
|
||||
|
||||
public SubscriptionsUpdatedEvent(Collection<ContactId> affectedContacts) {
|
||||
this.affectedContacts = affectedContacts;
|
||||
public LocalSubscriptionsUpdatedEvent(Collection<ContactId> affected) {
|
||||
this.affected = affected;
|
||||
}
|
||||
|
||||
/** Returns the contacts affected by the update. */
|
||||
public Collection<ContactId> getAffectedContacts() {
|
||||
return affectedContacts;
|
||||
return affected;
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,6 @@ package net.sf.briar.api.db.event;
|
||||
* An event that is broadcast when the local transport properties are
|
||||
* updated.
|
||||
*/
|
||||
public class TransportsUpdatedEvent extends DatabaseEvent {
|
||||
public class LocalTransportsUpdatedEvent extends DatabaseEvent {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package net.sf.briar.api.db.event;
|
||||
|
||||
import net.sf.briar.api.ContactId;
|
||||
|
||||
/** An event that is broadcast when a contact's subscriptions are updated. */
|
||||
public class RemoteSubscriptionsUpdatedEvent extends DatabaseEvent {
|
||||
|
||||
private final ContactId contactId;
|
||||
|
||||
public RemoteSubscriptionsUpdatedEvent(ContactId contactId) {
|
||||
this.contactId = contactId;
|
||||
}
|
||||
|
||||
public ContactId getContactId() {
|
||||
return contactId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package net.sf.briar.api.db.event;
|
||||
|
||||
import net.sf.briar.api.ContactId;
|
||||
import net.sf.briar.api.protocol.TransportId;
|
||||
|
||||
/**
|
||||
* An event that is broadcast when a contact's remote transport properties
|
||||
* are updated.
|
||||
*/
|
||||
public class RemoteTransportsUpdatedEvent extends DatabaseEvent {
|
||||
|
||||
private final ContactId contactId;
|
||||
private final TransportId transportId;
|
||||
|
||||
public RemoteTransportsUpdatedEvent(ContactId contactId,
|
||||
TransportId transportId) {
|
||||
this.contactId = contactId;
|
||||
this.transportId = transportId;
|
||||
}
|
||||
|
||||
public ContactId getContactId() {
|
||||
return contactId;
|
||||
}
|
||||
|
||||
public TransportId getTransportId() {
|
||||
return transportId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package net.sf.briar.api.db.event;
|
||||
|
||||
import net.sf.briar.api.protocol.TransportId;
|
||||
|
||||
/** An event that is broadcast when a transport is added. */
|
||||
public class TransportAddedEvent extends DatabaseEvent {
|
||||
|
||||
private final TransportId transportId;
|
||||
|
||||
public TransportAddedEvent(TransportId transportId) {
|
||||
this.transportId = transportId;
|
||||
}
|
||||
|
||||
public TransportId getTransportId() {
|
||||
return transportId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package net.sf.briar.api.db.event;
|
||||
|
||||
import net.sf.briar.api.protocol.TransportId;
|
||||
|
||||
/** An event that is broadcast when a transport is removed. */
|
||||
public class TransportRemovedEvent extends DatabaseEvent {
|
||||
|
||||
private final TransportId transportId;
|
||||
|
||||
public TransportRemovedEvent(TransportId transportId) {
|
||||
this.transportId = transportId;
|
||||
}
|
||||
|
||||
public TransportId getTransportId() {
|
||||
return transportId;
|
||||
}
|
||||
}
|
||||
@@ -31,12 +31,10 @@ import net.sf.briar.api.transport.TemporarySecret;
|
||||
* {@link #commitTransaction(T)}, even if an exception is thrown.
|
||||
* <p>
|
||||
* Locking is provided by the DatabaseComponent implementation. To prevent
|
||||
* deadlock, locks must be acquired in the following order:
|
||||
* deadlock, locks must be acquired in the following (alphabetical) order:
|
||||
* <ul>
|
||||
* <li> contact
|
||||
* <li> message
|
||||
* <li> messageFlag
|
||||
* <li> messageStatus
|
||||
* <li> rating
|
||||
* <li> subscription
|
||||
* <li> transport
|
||||
@@ -83,7 +81,7 @@ interface Database<T> {
|
||||
/**
|
||||
* Adds a contact transport to the database.
|
||||
* <p>
|
||||
* Locking: contact read, window write.
|
||||
* Locking: contact read, transport read, window write.
|
||||
*/
|
||||
void addContactTransport(T txn, ContactTransport ct) throws DbException;
|
||||
|
||||
@@ -98,14 +96,14 @@ interface Database<T> {
|
||||
/**
|
||||
* Records a received message as needing to be acknowledged.
|
||||
* <p>
|
||||
* Locking: contact read, messageStatus write.
|
||||
* Locking: contact read, message write.
|
||||
*/
|
||||
void addMessageToAck(T txn, ContactId c, MessageId m) throws DbException;
|
||||
|
||||
/**
|
||||
* Records a collection of sent messages as needing to be acknowledged.
|
||||
* <p>
|
||||
* Locking: contact read, message read, messageStatus write.
|
||||
* Locking: contact read, message write.
|
||||
*/
|
||||
void addOutstandingMessages(T txn, ContactId c, Collection<MessageId> sent)
|
||||
throws DbException;
|
||||
@@ -122,7 +120,7 @@ interface Database<T> {
|
||||
* Stores the given temporary secrets and deletes any secrets that have
|
||||
* been made obsolete.
|
||||
* <p>
|
||||
* Locking: contact read, window write.
|
||||
* Locking: contact read, transport read, window write.
|
||||
*/
|
||||
void addSecrets(T txn, Collection<TemporarySecret> secrets)
|
||||
throws DbException;
|
||||
@@ -158,7 +156,7 @@ interface Database<T> {
|
||||
/**
|
||||
* Returns true if the database contains the given contact transport.
|
||||
* <p>
|
||||
* Locking: contact read, window read.
|
||||
* Locking: contact read, transport read, window read.
|
||||
*/
|
||||
boolean containsContactTransport(T txn, ContactId c, TransportId t)
|
||||
throws DbException;
|
||||
@@ -203,7 +201,7 @@ interface Database<T> {
|
||||
/**
|
||||
* Returns all contact transports.
|
||||
* <p>
|
||||
* Locking: contact read, window read.
|
||||
* Locking: contact read, transport read, window read.
|
||||
*/
|
||||
Collection<ContactTransport> getContactTransports(T txn) throws DbException;
|
||||
|
||||
@@ -257,7 +255,7 @@ interface Database<T> {
|
||||
/**
|
||||
* Returns the headers of all messages in the given group.
|
||||
* <p>
|
||||
* Locking: message read, messageFlag read.
|
||||
* Locking: message read.
|
||||
*/
|
||||
Collection<MessageHeader> getMessageHeaders(T txn, GroupId g)
|
||||
throws DbException;
|
||||
@@ -267,8 +265,7 @@ interface Database<T> {
|
||||
* if the message is not present in the database or is not sendable to the
|
||||
* given contact.
|
||||
* <p>
|
||||
* Locking: contact read, message read, messageStatus read,
|
||||
* subscription read.
|
||||
* Locking: contact read, message read, subscription read.
|
||||
*/
|
||||
byte[] getMessageIfSendable(T txn, ContactId c, MessageId m)
|
||||
throws DbException;
|
||||
@@ -285,7 +282,7 @@ interface Database<T> {
|
||||
* Returns the IDs of some messages received from the given contact that
|
||||
* need to be acknowledged, up to the given number of messages.
|
||||
* <p>
|
||||
* Locking: contact read, messageStatus read.
|
||||
* Locking: contact read, message read.
|
||||
*/
|
||||
Collection<MessageId> getMessagesToAck(T txn, ContactId c, int maxMessages)
|
||||
throws DbException;
|
||||
@@ -294,8 +291,7 @@ interface Database<T> {
|
||||
* Returns the IDs of some messages that are eligible to be sent to the
|
||||
* given contact, up to the given number of messages.
|
||||
* <p>
|
||||
* Locking: contact read, message read, messageStatus read,
|
||||
* subscription read.
|
||||
* Locking: contact read, message read, subscription read.
|
||||
*/
|
||||
Collection<MessageId> getMessagesToOffer(T txn, ContactId c,
|
||||
int maxMessages) throws DbException;
|
||||
@@ -327,7 +323,7 @@ interface Database<T> {
|
||||
/**
|
||||
* Returns true if the given message has been read.
|
||||
* <p>
|
||||
* Locking: message read, messageFlag read.
|
||||
* Locking: message read.
|
||||
*/
|
||||
boolean getReadFlag(T txn, MessageId m) throws DbException;
|
||||
|
||||
@@ -342,7 +338,7 @@ interface Database<T> {
|
||||
/**
|
||||
* Returns all temporary secrets.
|
||||
* <p>
|
||||
* Locking: contact read, window read.
|
||||
* Locking: contact read, transport read, window read.
|
||||
*/
|
||||
Collection<TemporarySecret> getSecrets(T txn) throws DbException;
|
||||
|
||||
@@ -358,8 +354,7 @@ interface Database<T> {
|
||||
* given contact, with a total length less than or equal to the given
|
||||
* length.
|
||||
* <p>
|
||||
* Locking: contact read, message read, messageStatus read,
|
||||
* subscription read.
|
||||
* Locking: contact read, message read, subscription read.
|
||||
*/
|
||||
Collection<MessageId> getSendableMessages(T txn, ContactId c, int maxLength)
|
||||
throws DbException;
|
||||
@@ -367,7 +362,7 @@ interface Database<T> {
|
||||
/**
|
||||
* Returns true if the given message has been starred.
|
||||
* <p>
|
||||
* Locking: message read, messageFlag read.
|
||||
* Locking: message read.
|
||||
*/
|
||||
boolean getStarredFlag(T txn, MessageId m) throws DbException;
|
||||
|
||||
@@ -425,7 +420,7 @@ interface Database<T> {
|
||||
/**
|
||||
* Returns the number of unread messages in each subscribed group.
|
||||
* <p>
|
||||
* Locking: message read, messageFlag read, subscription read.
|
||||
* Locking: message read, subscription read.
|
||||
*/
|
||||
Map<GroupId, Integer> getUnreadMessageCounts(T txn) throws DbException;
|
||||
|
||||
@@ -439,7 +434,7 @@ interface Database<T> {
|
||||
/**
|
||||
* Returns true if any messages are sendable to the given contact.
|
||||
* <p>
|
||||
* Locking: contact read, message read, messageStatus read.
|
||||
* Locking: contact read, message read.
|
||||
*/
|
||||
boolean hasSendableMessages(T txn, ContactId c) throws DbException;
|
||||
|
||||
@@ -447,7 +442,7 @@ interface Database<T> {
|
||||
* Increments the outgoing connection counter for the given contact
|
||||
* transport in the given rotation period and returns the old value;
|
||||
* <p>
|
||||
* Locking: contact read, window write.
|
||||
* Locking: contact read, transport read, window write.
|
||||
*/
|
||||
long incrementConnectionCounter(T txn, ContactId c, TransportId t,
|
||||
long period) throws DbException;
|
||||
@@ -470,54 +465,52 @@ interface Database<T> {
|
||||
void mergeLocalProperties(T txn, TransportId t, TransportProperties p)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Removes outstanding messages that have been acknowledged. Any of the
|
||||
* messages that are still considered outstanding (Status.SENT) with
|
||||
* respect to the given contact are now considered seen (Status.SEEN).
|
||||
* <p>
|
||||
* Locking: contact read, message read, messageStatus write.
|
||||
*/
|
||||
void removeOutstandingMessages(T txn, ContactId c,
|
||||
Collection<MessageId> acked) throws DbException;
|
||||
|
||||
/**
|
||||
* Marks the given messages received from the given contact as having been
|
||||
* acknowledged.
|
||||
* <p>
|
||||
* Locking: contact read, messageStatus write.
|
||||
*/
|
||||
void removeMessagesToAck(T txn, ContactId c, Collection<MessageId> acked)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Removes a contact (and all associated state) from the database.
|
||||
* <p>
|
||||
* Locking: contact write, message write, messageFlag write,
|
||||
* messageStatus write, subscription write, transport write, window write.
|
||||
* Locking: contact write, message write, subscription write,
|
||||
* transport write, window write.
|
||||
*/
|
||||
void removeContact(T txn, ContactId c) throws DbException;
|
||||
|
||||
/**
|
||||
* Removes a message (and all associated state) from the database.
|
||||
* <p>
|
||||
* Locking: contact read, message write, messageFlag write,
|
||||
* messageStatus write.
|
||||
* Locking: contact read, message write.
|
||||
*/
|
||||
void removeMessage(T txn, MessageId m) throws DbException;
|
||||
|
||||
/**
|
||||
* Marks the given messages received from the given contact as having been
|
||||
* acknowledged.
|
||||
* <p>
|
||||
* Locking: contact read, message write.
|
||||
*/
|
||||
void removeMessagesToAck(T txn, ContactId c, Collection<MessageId> acked)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Removes outstanding messages that have been acknowledged. Any of the
|
||||
* messages that are still considered outstanding (Status.SENT) with
|
||||
* respect to the given contact are now considered seen (Status.SEEN).
|
||||
* <p>
|
||||
* Locking: contact read, message write.
|
||||
*/
|
||||
void removeOutstandingMessages(T txn, ContactId c,
|
||||
Collection<MessageId> acked) throws DbException;
|
||||
|
||||
/**
|
||||
* Unsubscribes from the given group. Any messages belonging to the group
|
||||
* are deleted from the database.
|
||||
* <p>
|
||||
* Locking: contact write, message write, messageFlag write,
|
||||
* messageStatus write, subscription write.
|
||||
* Locking: contact write, message write, subscription write.
|
||||
*/
|
||||
void removeSubscription(T txn, GroupId g) throws DbException;
|
||||
|
||||
/**
|
||||
* Removes a transport (and all associated state) from the database.
|
||||
* <p>
|
||||
* Locking: contact read, transport write.
|
||||
* Locking: transport write.
|
||||
*/
|
||||
void removeTransport(T txn, TransportId t) throws DbException;
|
||||
|
||||
@@ -532,7 +525,7 @@ interface Database<T> {
|
||||
* Sets the connection reordering window for the given contact transport in
|
||||
* the given rotation period.
|
||||
* <p>
|
||||
* Locking: contact read, window write.
|
||||
* Locking: contact read, transport read, window write.
|
||||
*/
|
||||
void setConnectionWindow(T txn, ContactId c, TransportId t, long period,
|
||||
long centre, byte[] bitmap) throws DbException;
|
||||
@@ -555,7 +548,7 @@ interface Database<T> {
|
||||
* Marks the given message read or unread and returns true if it was
|
||||
* previously read.
|
||||
* <p>
|
||||
* Locking: message read, messageFlag write.
|
||||
* Locking: message write.
|
||||
*/
|
||||
boolean setRead(T txn, MessageId m, boolean read) throws DbException;
|
||||
|
||||
@@ -581,14 +574,14 @@ interface Database<T> {
|
||||
* Marks the given message starred or unstarred and returns true if it was
|
||||
* previously starred.
|
||||
* <p>
|
||||
* Locking: message read, messageFlag write.
|
||||
* Locking: message write.
|
||||
*/
|
||||
boolean setStarred(T txn, MessageId m, boolean starred) throws DbException;
|
||||
|
||||
/**
|
||||
* Sets the status of the given message with respect to the given contact.
|
||||
* <p>
|
||||
* Locking: contact read, message read, messageStatus write.
|
||||
* Locking: contact read, message write.
|
||||
*/
|
||||
void setStatus(T txn, ContactId c, MessageId m, Status s)
|
||||
throws DbException;
|
||||
@@ -599,8 +592,7 @@ interface Database<T> {
|
||||
* with respect to the contact to Status.SEEN and returns true; otherwise
|
||||
* returns false.
|
||||
* <p>
|
||||
* Locking: contact read, message read, messageStatus write,
|
||||
* subscription read.
|
||||
* Locking: contact read, message write, subscription read.
|
||||
*/
|
||||
boolean setStatusSeenIfVisible(T txn, ContactId c, MessageId m)
|
||||
throws DbException;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -92,7 +92,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
private static final String INDEX_MESSAGES_BY_SENDABILITY =
|
||||
"CREATE INDEX messagesBySendability ON messages (sendability)";
|
||||
|
||||
// Locking: contact read, messageStatus
|
||||
// Locking: contact read, message
|
||||
private static final String CREATE_MESSAGES_TO_ACK =
|
||||
"CREATE TABLE messagesToAck"
|
||||
+ " (messageId HASH NOT NULL,"
|
||||
@@ -102,7 +102,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
+ " REFERENCES contacts (contactId)"
|
||||
+ " ON DELETE CASCADE)";
|
||||
|
||||
// Locking: contact read, message read, messageStatus
|
||||
// Locking: contact read, message
|
||||
private static final String CREATE_STATUSES =
|
||||
"CREATE TABLE statuses"
|
||||
+ " (messageId HASH NOT NULL,"
|
||||
@@ -122,7 +122,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
private static final String INDEX_STATUSES_BY_CONTACT =
|
||||
"CREATE INDEX statusesByContact ON statuses (contactId)";
|
||||
|
||||
// Locking: message read, messageFlag
|
||||
// Locking: message
|
||||
private static final String CREATE_FLAGS =
|
||||
"CREATE TABLE flags"
|
||||
+ " (messageId HASH NOT NULL,"
|
||||
@@ -252,7 +252,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
+ " REFERENCES contacts (contactId)"
|
||||
+ " ON DELETE CASCADE)";
|
||||
|
||||
// Locking: contact read, window
|
||||
// Locking: contact read, transport read, window
|
||||
private static final String CREATE_CONTACT_TRANSPORTS =
|
||||
"CREATE TABLE contactTransports"
|
||||
+ " (contactId INT NOT NULL,"
|
||||
@@ -269,7 +269,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
+ " REFERENCES transports (transportId)"
|
||||
+ " ON DELETE CASCADE)";
|
||||
|
||||
// Locking: contact read, window
|
||||
// Locking: contact read, transport read, window
|
||||
private static final String CREATE_SECRETS =
|
||||
"CREATE TABLE secrets"
|
||||
+ " (contactId INT NOT NULL,"
|
||||
|
||||
@@ -29,8 +29,8 @@ import net.sf.briar.api.db.event.DatabaseEvent;
|
||||
import net.sf.briar.api.db.event.DatabaseListener;
|
||||
import net.sf.briar.api.db.event.MessageAddedEvent;
|
||||
import net.sf.briar.api.db.event.MessageReceivedEvent;
|
||||
import net.sf.briar.api.db.event.SubscriptionsUpdatedEvent;
|
||||
import net.sf.briar.api.db.event.TransportsUpdatedEvent;
|
||||
import net.sf.briar.api.db.event.LocalSubscriptionsUpdatedEvent;
|
||||
import net.sf.briar.api.db.event.LocalTransportsUpdatedEvent;
|
||||
import net.sf.briar.api.plugins.duplex.DuplexTransportConnection;
|
||||
import net.sf.briar.api.protocol.Ack;
|
||||
import net.sf.briar.api.protocol.Message;
|
||||
@@ -127,13 +127,13 @@ abstract class DuplexConnection implements DatabaseListener {
|
||||
} else if(e instanceof MessageAddedEvent) {
|
||||
if(canSendOffer.getAndSet(false))
|
||||
dbExecutor.execute(new GenerateOffer());
|
||||
} else if(e instanceof SubscriptionsUpdatedEvent) {
|
||||
} else if(e instanceof LocalSubscriptionsUpdatedEvent) {
|
||||
Collection<ContactId> affected =
|
||||
((SubscriptionsUpdatedEvent) e).getAffectedContacts();
|
||||
((LocalSubscriptionsUpdatedEvent) e).getAffectedContacts();
|
||||
if(affected.contains(contactId)) {
|
||||
dbExecutor.execute(new GenerateSubscriptionUpdate());
|
||||
}
|
||||
} else if(e instanceof TransportsUpdatedEvent) {
|
||||
} else if(e instanceof LocalTransportsUpdatedEvent) {
|
||||
dbExecutor.execute(new GenerateTransportUpdate());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import net.sf.briar.api.db.event.ContactRemovedEvent;
|
||||
import net.sf.briar.api.db.event.DatabaseListener;
|
||||
import net.sf.briar.api.db.event.MessageAddedEvent;
|
||||
import net.sf.briar.api.db.event.RatingChangedEvent;
|
||||
import net.sf.briar.api.db.event.SubscriptionsUpdatedEvent;
|
||||
import net.sf.briar.api.db.event.LocalSubscriptionsUpdatedEvent;
|
||||
import net.sf.briar.api.lifecycle.ShutdownManager;
|
||||
import net.sf.briar.api.protocol.Ack;
|
||||
import net.sf.briar.api.protocol.AuthorId;
|
||||
@@ -1377,7 +1377,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||
oneOf(database).removeVisibility(txn, contactId1, groupId);
|
||||
oneOf(database).commitTransaction(txn);
|
||||
oneOf(listener).eventOccurred(with(any(
|
||||
SubscriptionsUpdatedEvent.class)));
|
||||
LocalSubscriptionsUpdatedEvent.class)));
|
||||
}});
|
||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||
shutdown);
|
||||
|
||||
Reference in New Issue
Block a user