mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-16 04:39:54 +01:00
Attached data to DB events to avoid DB lookups; refactored UI code.
Fields in Android UI objects that are accessed from background threads must be declared volatile. UI objects use data attached to DB events to avoid DB lookups, which complicates the UI code but should improve performance.
This commit is contained in:
@@ -202,6 +202,13 @@ interface Database<T> {
|
||||
*/
|
||||
TransportConfig getConfig(T txn, TransportId t) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the contact with the given ID.
|
||||
* <p>
|
||||
* Locking: contact read, window read.
|
||||
*/
|
||||
Contact getContact(T txn, ContactId c) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the IDs of all contacts.
|
||||
* <p>
|
||||
@@ -230,6 +237,11 @@ interface Database<T> {
|
||||
*/
|
||||
long getFreeSpace() throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the group with the given ID, if the user subscribes to it.
|
||||
*/
|
||||
Group getGroup(T txn, GroupId g) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the parent of the given group message, or null if either the
|
||||
* message has no parent, or the parent is absent from the database, or the
|
||||
|
||||
@@ -41,11 +41,12 @@ import net.sf.briar.api.db.event.ContactAddedEvent;
|
||||
import net.sf.briar.api.db.event.ContactRemovedEvent;
|
||||
import net.sf.briar.api.db.event.DatabaseEvent;
|
||||
import net.sf.briar.api.db.event.DatabaseListener;
|
||||
import net.sf.briar.api.db.event.GroupMessageAddedEvent;
|
||||
import net.sf.briar.api.db.event.LocalSubscriptionsUpdatedEvent;
|
||||
import net.sf.briar.api.db.event.LocalTransportsUpdatedEvent;
|
||||
import net.sf.briar.api.db.event.MessageAddedEvent;
|
||||
import net.sf.briar.api.db.event.MessageExpiredEvent;
|
||||
import net.sf.briar.api.db.event.MessageReceivedEvent;
|
||||
import net.sf.briar.api.db.event.PrivateMessageAddedEvent;
|
||||
import net.sf.briar.api.db.event.RatingChangedEvent;
|
||||
import net.sf.briar.api.db.event.RemoteRetentionTimeUpdatedEvent;
|
||||
import net.sf.briar.api.db.event.RemoteSubscriptionsUpdatedEvent;
|
||||
@@ -286,7 +287,7 @@ DatabaseCleaner.Callback {
|
||||
} finally {
|
||||
contactLock.readLock().unlock();
|
||||
}
|
||||
if(added) callListeners(new MessageAddedEvent());
|
||||
if(added) callListeners(new GroupMessageAddedEvent(m, false));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -399,7 +400,7 @@ DatabaseCleaner.Callback {
|
||||
} finally {
|
||||
contactLock.readLock().unlock();
|
||||
}
|
||||
if(added) callListeners(new MessageAddedEvent());
|
||||
if(added) callListeners(new PrivateMessageAddedEvent(m, c, false));
|
||||
}
|
||||
|
||||
public void addSecrets(Collection<TemporarySecret> secrets)
|
||||
@@ -844,6 +845,30 @@ DatabaseCleaner.Callback {
|
||||
}
|
||||
}
|
||||
|
||||
public Contact getContact(ContactId c) throws DbException {
|
||||
contactLock.readLock().lock();
|
||||
try {
|
||||
windowLock.readLock().lock();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
if(!db.containsContact(txn, c))
|
||||
throw new NoSuchContactException();
|
||||
Contact contact = db.getContact(txn, c);
|
||||
db.commitTransaction(txn);
|
||||
return contact;
|
||||
} catch(DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
windowLock.readLock().unlock();
|
||||
}
|
||||
} finally {
|
||||
contactLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<Contact> getContacts() throws DbException {
|
||||
contactLock.readLock().lock();
|
||||
try {
|
||||
@@ -866,6 +891,25 @@ DatabaseCleaner.Callback {
|
||||
}
|
||||
}
|
||||
|
||||
public Group getGroup(GroupId g) throws DbException {
|
||||
subscriptionLock.readLock().lock();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
if(!db.containsSubscription(txn, g))
|
||||
throw new NoSuchSubscriptionException();
|
||||
Group group = db.getGroup(txn, g);
|
||||
db.commitTransaction(txn);
|
||||
return group;
|
||||
} catch(DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
subscriptionLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public TransportProperties getLocalProperties(TransportId t)
|
||||
throws DbException {
|
||||
transportLock.readLock().lock();
|
||||
@@ -1301,8 +1345,12 @@ DatabaseCleaner.Callback {
|
||||
} finally {
|
||||
contactLock.readLock().unlock();
|
||||
}
|
||||
callListeners(new MessageReceivedEvent());
|
||||
if(added) callListeners(new MessageAddedEvent());
|
||||
callListeners(new MessageReceivedEvent(c));
|
||||
if(added) {
|
||||
if(m.getGroup() == null)
|
||||
callListeners(new PrivateMessageAddedEvent(m, c, true));
|
||||
else callListeners(new GroupMessageAddedEvent(m, true));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1795,7 +1843,7 @@ DatabaseCleaner.Callback {
|
||||
} finally {
|
||||
subscriptionLock.writeLock().unlock();
|
||||
}
|
||||
if(added) callListeners(new SubscriptionAddedEvent(g.getId()));
|
||||
if(added) callListeners(new SubscriptionAddedEvent(g));
|
||||
return added;
|
||||
}
|
||||
|
||||
|
||||
@@ -1047,6 +1047,31 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
}
|
||||
|
||||
public Contact getContact(Connection txn, ContactId c) throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = "SELECT name, lastConnected"
|
||||
+ " FROM contacts AS c"
|
||||
+ " JOIN connectionTimes AS ct"
|
||||
+ " ON c.contactId = ct.contactId"
|
||||
+ " WHERE c.contactId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setInt(1, c.getInt());
|
||||
rs = ps.executeQuery();
|
||||
if(!rs.next()) throw new DbStateException();
|
||||
String name = rs.getString(1);
|
||||
long lastConnected = rs.getLong(2);
|
||||
rs.close();
|
||||
ps.close();
|
||||
return new Contact(c, name, lastConnected);
|
||||
} catch(SQLException e) {
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<ContactId> getContactIds(Connection txn)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
@@ -1124,6 +1149,27 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
}
|
||||
|
||||
public Group getGroup(Connection txn, GroupId g) throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = "SELECT name, key FROM groups WHERE groupId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setBytes(1, g.getBytes());
|
||||
rs = ps.executeQuery();
|
||||
if(!rs.next()) throw new DbStateException();
|
||||
String name = rs.getString(1);
|
||||
byte[] publicKey = rs.getBytes(2);
|
||||
rs.close();
|
||||
ps.close();
|
||||
return new Group(g, name, publicKey);
|
||||
} catch(SQLException e) {
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public MessageId getGroupMessageParent(Connection txn, MessageId m)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
@@ -1228,10 +1274,12 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = "SELECT messageId, parentId, authorId, authorName,"
|
||||
String sql = "SELECT messageId, parentId, m.authorId, authorName,"
|
||||
+ " authorKey, contentType, subject, timestamp, read,"
|
||||
+ " starred"
|
||||
+ " FROM messages"
|
||||
+ " starred, rating"
|
||||
+ " FROM messages AS m"
|
||||
+ " LEFT OUTER JOIN ratings AS r"
|
||||
+ " ON m.authorId = r.authorId"
|
||||
+ " WHERE groupId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setBytes(1, g.getBytes());
|
||||
@@ -1242,13 +1290,18 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
MessageId id = new MessageId(rs.getBytes(1));
|
||||
byte[] b = rs.getBytes(2);
|
||||
MessageId parent = b == null ? null : new MessageId(b);
|
||||
Author author = null;
|
||||
Author author;
|
||||
Rating rating;
|
||||
b = rs.getBytes(3);
|
||||
if(b != null) {
|
||||
if(b == null) {
|
||||
author = null;
|
||||
rating = UNRATED;
|
||||
} else {
|
||||
AuthorId authorId = new AuthorId(b);
|
||||
String authorName = rs.getString(4);
|
||||
byte[] authorKey = rs.getBytes(5);
|
||||
author = new Author(authorId, authorName, authorKey);
|
||||
rating = Rating.values()[rs.getByte(11)];
|
||||
}
|
||||
String contentType = rs.getString(6);
|
||||
String subject = rs.getString(7);
|
||||
@@ -1256,7 +1309,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
boolean read = rs.getBoolean(9);
|
||||
boolean starred = rs.getBoolean(10);
|
||||
headers.add(new GroupMessageHeader(id, parent, contentType,
|
||||
subject, timestamp, read, starred, g, author));
|
||||
subject, timestamp, read, starred, g, author, rating));
|
||||
}
|
||||
rs.close();
|
||||
ps.close();
|
||||
|
||||
@@ -30,11 +30,12 @@ import net.sf.briar.api.db.DbException;
|
||||
import net.sf.briar.api.db.event.ContactRemovedEvent;
|
||||
import net.sf.briar.api.db.event.DatabaseEvent;
|
||||
import net.sf.briar.api.db.event.DatabaseListener;
|
||||
import net.sf.briar.api.db.event.GroupMessageAddedEvent;
|
||||
import net.sf.briar.api.db.event.LocalSubscriptionsUpdatedEvent;
|
||||
import net.sf.briar.api.db.event.LocalTransportsUpdatedEvent;
|
||||
import net.sf.briar.api.db.event.MessageAddedEvent;
|
||||
import net.sf.briar.api.db.event.MessageExpiredEvent;
|
||||
import net.sf.briar.api.db.event.MessageReceivedEvent;
|
||||
import net.sf.briar.api.db.event.PrivateMessageAddedEvent;
|
||||
import net.sf.briar.api.db.event.RatingChangedEvent;
|
||||
import net.sf.briar.api.db.event.RemoteRetentionTimeUpdatedEvent;
|
||||
import net.sf.briar.api.db.event.RemoteSubscriptionsUpdatedEvent;
|
||||
@@ -134,6 +135,9 @@ abstract class DuplexConnection implements DatabaseListener {
|
||||
if(e instanceof ContactRemovedEvent) {
|
||||
ContactRemovedEvent c = (ContactRemovedEvent) e;
|
||||
if(contactId.equals(c.getContactId())) dispose(false, true);
|
||||
} else if(e instanceof GroupMessageAddedEvent) {
|
||||
if(canSendOffer.getAndSet(false))
|
||||
dbExecutor.execute(new GenerateOffer());
|
||||
} else if(e instanceof MessageExpiredEvent) {
|
||||
dbExecutor.execute(new GenerateRetentionUpdate());
|
||||
} else if(e instanceof LocalSubscriptionsUpdatedEvent) {
|
||||
@@ -143,11 +147,15 @@ abstract class DuplexConnection implements DatabaseListener {
|
||||
dbExecutor.execute(new GenerateSubscriptionUpdate());
|
||||
} else if(e instanceof LocalTransportsUpdatedEvent) {
|
||||
dbExecutor.execute(new GenerateTransportUpdates());
|
||||
} else if(e instanceof MessageAddedEvent) {
|
||||
if(canSendOffer.getAndSet(false))
|
||||
dbExecutor.execute(new GenerateOffer());
|
||||
} else if(e instanceof MessageReceivedEvent) {
|
||||
dbExecutor.execute(new GenerateAcks());
|
||||
if(((MessageReceivedEvent) e).getContactId().equals(contactId))
|
||||
dbExecutor.execute(new GenerateAcks());
|
||||
} else if(e instanceof PrivateMessageAddedEvent) {
|
||||
PrivateMessageAddedEvent p = (PrivateMessageAddedEvent) e;
|
||||
if(!p.isIncoming() && p.getContactId().equals(contactId)) {
|
||||
if(canSendOffer.getAndSet(false))
|
||||
dbExecutor.execute(new GenerateOffer());
|
||||
}
|
||||
} else if(e instanceof RatingChangedEvent) {
|
||||
RatingChangedEvent r = (RatingChangedEvent) e;
|
||||
if(r.getRating() == GOOD && canSendOffer.getAndSet(false))
|
||||
|
||||
Reference in New Issue
Block a user