* Locking: contact write, message write, retention write,
* subscription write, transport write, window write.
@@ -96,13 +95,12 @@ interface Database
- * Locking: message write.
+ * Locking: message write, subscription write.
*/
- boolean addGroupMessage(T txn, Message m, boolean incoming)
- throws DbException;
+ boolean addGroup(T txn, Group g) throws DbException;
/**
* Stores a local pseudonym.
@@ -112,6 +110,13 @@ interface Database
+ * Locking: message write.
+ */
+ void addMessage(T txn, Message m, boolean incoming) throws DbException;
+
/**
* Records a received message as needing to be acknowledged.
*
@@ -119,15 +124,6 @@ interface Database
- * Locking: message write.
- */
- boolean addPrivateMessage(T txn, Message m, ContactId c, boolean incoming)
- throws DbException;
-
/**
* Stores the given temporary secrets and deletes any secrets that have
* been made obsolete.
@@ -146,14 +142,6 @@ interface Database
- * Locking: subscription write.
- */
- boolean addSubscription(T txn, Group g) throws DbException;
-
/**
* Stores a transport and returns true if the transport was not previously
* in the database.
@@ -184,6 +172,13 @@ interface Database
+ * Locking: subscription read.
+ */
+ boolean containsGroup(T txn, GroupId g) throws DbException;
+
/**
* Returns true if the database contains the given local pseudonym.
*
@@ -199,11 +194,11 @@ interface Database
- * Locking: subscription read.
+ * Locking: message read, subscription read.
*/
- boolean containsSubscription(T txn, GroupId g) throws DbException;
+ boolean containsSendableMessages(T txn, ContactId c) throws DbException;
/**
* Returns true if the database contains the given transport.
@@ -213,12 +208,12 @@ interface Database
* Locking: subscription read.
*/
- boolean containsVisibleSubscription(T txn, ContactId c, GroupId g)
+ boolean containsVisibleGroup(T txn, ContactId c, GroupId g)
throws DbException;
/**
@@ -279,25 +274,34 @@ interface Database
+ * Locking: subscription read.
*/
Group getGroup(T txn, GroupId g) throws DbException;
/**
- * Returns the headers of all messages in the given group.
+ * Returns all groups to which the user subscribes.
*
- * Locking: message read.
+ * Locking: subscription read.
*/
- Collection
- * Locking: message read.
+ * Locking: contact read, subscription read.
*/
- MessageId getGroupMessageParent(T txn, MessageId m) throws DbException;
+ GroupId getInboxGroup(T txn, ContactId c) throws DbException;
+
+ /**
+ * Returns the headers of all messages in the inbox group for the given
+ * contact, or null if no inbox group has been set.
+ *
+ * Locking: contact read, identity read, message read, subscription read.
+ */
+ Collection
- * Locking: contact read, identity read, message read.
+ * Locking: message read.
*/
- Collection
* Locking: message read.
*/
@@ -371,6 +374,23 @@ interface Database
+ * Locking: message read.
+ */
+ Collection
+ * Locking: message read.
+ */
+ MessageId getParent(T txn, MessageId m) throws DbException;
+
/**
* Returns the message identified by the given ID, in serialised form.
*
@@ -388,14 +408,6 @@ interface Database
- * Locking: message read.
- */
- Collection
@@ -444,20 +456,6 @@ interface Database
- * Locking: subscription read.
- */
- Collection
- * Locking: subscription read.
- */
- Collection
* Locking: subscription read.
*/
Collection
* Locking: subscription read.
*/
- Collection
- * Locking: message read, subscription read.
- */
- boolean hasSendableMessages(T txn, ContactId c) throws DbException;
-
/**
* Increments the outgoing connection counter for the given endpoint
* in the given rotation period and returns the old value, or -1 if the
@@ -576,7 +568,7 @@ interface Database
* Locking: contact write, message write, retention write,
* subscription write, transport write, window write.
@@ -584,8 +576,16 @@ interface Database
+ * Locking: message write, subscription write.
+ */
+ void removeGroup(T txn, GroupId g) throws DbException;
+
+ /**
+ * Removes a local pseudonym (and all associated contacts) from the
+ * database.
*
* Locking: contact write, identity write, message write, retention write,
* subscription write, transport write, window write.
@@ -608,23 +608,6 @@ interface Database
- * Locking: message write.
- */
- void removeOutstandingMessages(T txn, ContactId c,
- Collection
- * Locking: message write, subscription write.
- */
- void removeSubscription(T txn, GroupId g) throws DbException;
-
/**
* Removes a transport (and all associated state) from the database.
*
@@ -648,6 +631,24 @@ interface Database
+ * Locking: subscription write.
+ */
+ boolean setGroups(T txn, ContactId c, Collection
+ * Locking: contact read, message write, subscription write.
+ */
+ public void setInboxGroup(T txn, ContactId c, Group g) throws DbException;
+
/**
* Sets the time at which a connection to the given contact was last made.
*
@@ -656,8 +657,8 @@ interface Database
* Locking: message write.
*/
@@ -703,16 +704,6 @@ interface Database
- * Locking: subscription write.
- */
- boolean setSubscriptions(T txn, ContactId c, Collection
- * Locking: contact read, message write.
- * @param sender is null for a locally generated message.
+ * Locking: contact read, message write, subscription read.
+ * @param sender null for a locally generated message.
*/
- private boolean storeGroupMessage(T txn, Message m, ContactId sender)
+ private void addMessage(T txn, Message m, ContactId sender)
throws DbException {
- if(m.getGroup() == null) throw new IllegalArgumentException();
- boolean stored = db.addGroupMessage(txn, m, sender != null);
- if(stored && sender == null) db.setReadFlag(txn, m.getId(), true);
- // Mark the message as seen by the sender
+ db.addMessage(txn, m, sender != null);
MessageId id = m.getId();
- if(sender != null) db.addStatus(txn, sender, id, true);
- if(stored) {
- // Mark the message as unseen by other contacts
- for(ContactId c : db.getContactIds(txn))
- if(!c.equals(sender)) db.addStatus(txn, c, id, false);
- // Count the bytes stored
- synchronized(spaceLock) {
- bytesStoredSinceLastCheck += m.getSerialised().length;
- }
- } else {
- if(LOG.isLoggable(INFO))
- LOG.info("Duplicate group message not stored");
- }
- return stored;
- }
-
- public void addLocalPrivateMessage(Message m, ContactId c)
- throws DbException {
- boolean added;
- contactLock.readLock().lock();
- try {
- messageLock.writeLock().lock();
- try {
- T txn = db.startTransaction();
- try {
- if(!db.containsContact(txn, c))
- throw new NoSuchContactException();
- added = storePrivateMessage(txn, m, c, false);
- db.commitTransaction(txn);
- } catch(DbException e) {
- db.abortTransaction(txn);
- throw e;
- }
- } finally {
- messageLock.writeLock().unlock();
- }
- } finally {
- contactLock.readLock().unlock();
- }
- if(added) callListeners(new PrivateMessageAddedEvent(c, false));
- }
-
- /**
- * If the given message is already in the database, returns false.
- * Otherwise stores the message and marks it as seen or unseen with respect
- * to the given contact, depending on whether the message is incoming or
- * outgoing, respectively.
- *
- * Locking: message write.
- */
- private boolean storePrivateMessage(T txn, Message m, ContactId c,
- boolean incoming) throws DbException {
- if(m.getGroup() != null) throw new IllegalArgumentException();
- if(m.getAuthor() != null) throw new IllegalArgumentException();
- if(!db.addPrivateMessage(txn, m, c, incoming)) {
- if(LOG.isLoggable(INFO))
- LOG.info("Duplicate private message not stored");
- return false;
- }
- if(!incoming) db.setReadFlag(txn, m.getId(), true);
- db.addStatus(txn, c, m.getId(), incoming);
+ if(sender == null) db.setReadFlag(txn, id, true);
+ else db.addStatus(txn, sender, id, true);
+ for(ContactId c : db.getContactIds(txn))
+ if(!c.equals(sender)) db.addStatus(txn, c, id, false);
// Count the bytes stored
synchronized(spaceLock) {
bytesStoredSinceLastCheck += m.getSerialised().length;
}
- return true;
}
public void addSecrets(Collection
- * Locking: contact read, message write, subscription read.
- */
- private boolean storeMessage(T txn, ContactId c, Message m)
- throws DbException {
- long now = clock.currentTimeMillis();
- if(m.getTimestamp() > now + MAX_CLOCK_DIFFERENCE) {
- if(LOG.isLoggable(INFO))
- LOG.info("Discarding message with future timestamp");
- return false;
- }
- Group g = m.getGroup();
- if(g == null) return storePrivateMessage(txn, m, c, true);
- if(!db.containsVisibleSubscription(txn, c, g.getId())) {
- if(LOG.isLoggable(INFO))
- LOG.info("Discarding message without visible subscription");
- return false;
- }
- return storeGroupMessage(txn, m, c);
+ if(visible) callListeners(new MessageReceivedEvent(c));
+ if(!duplicate) callListeners(new MessageAddedEvent(m.getGroup(), c));
}
public AckAndRequest receiveOffer(ContactId c, Offer o) throws DbException {
@@ -1573,7 +1516,7 @@ DatabaseCleaner.Callback {
throw new NoSuchContactException();
Collection