mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 19:29:06 +01:00
Use 'retention' rather than 'expiry' to describe DB's retention period.
This will avoid a name clash when retransmission is implemented.
This commit is contained in:
@@ -11,8 +11,8 @@ import net.sf.briar.api.TransportProperties;
|
||||
import net.sf.briar.api.db.event.DatabaseListener;
|
||||
import net.sf.briar.api.protocol.Ack;
|
||||
import net.sf.briar.api.protocol.AuthorId;
|
||||
import net.sf.briar.api.protocol.ExpiryAck;
|
||||
import net.sf.briar.api.protocol.ExpiryUpdate;
|
||||
import net.sf.briar.api.protocol.RetentionAck;
|
||||
import net.sf.briar.api.protocol.RetentionUpdate;
|
||||
import net.sf.briar.api.protocol.Group;
|
||||
import net.sf.briar.api.protocol.GroupId;
|
||||
import net.sf.briar.api.protocol.Message;
|
||||
@@ -98,24 +98,24 @@ public interface DatabaseComponent {
|
||||
Collection<byte[]> generateBatch(ContactId c, int maxLength,
|
||||
Collection<MessageId> requested) throws DbException;
|
||||
|
||||
/**
|
||||
* Generates an expiry ack for the given contact. Returns null if no ack
|
||||
* is due.
|
||||
*/
|
||||
ExpiryAck generateExpiryAck(ContactId c) throws DbException;
|
||||
|
||||
/**
|
||||
* Generates an expiry update for the given contact. Returns null if no
|
||||
* update is due.
|
||||
*/
|
||||
ExpiryUpdate generateExpiryUpdate(ContactId c) throws DbException;
|
||||
|
||||
/**
|
||||
* Generates an offer for the given contact. Returns null if there are no
|
||||
* messages to offer.
|
||||
*/
|
||||
Offer generateOffer(ContactId c, int maxMessages) throws DbException;
|
||||
|
||||
/**
|
||||
* Generates a retention ack for the given contact. Returns null if no ack
|
||||
* is due.
|
||||
*/
|
||||
RetentionAck generateRetentionAck(ContactId c) throws DbException;
|
||||
|
||||
/**
|
||||
* Generates a retention update for the given contact. Returns null if no
|
||||
* update is due.
|
||||
*/
|
||||
RetentionUpdate generateRetentionUpdate(ContactId c) throws DbException;
|
||||
|
||||
/**
|
||||
* Generates a subscription ack for the given contact. Returns null if no
|
||||
* ack is due.
|
||||
@@ -200,12 +200,6 @@ public interface DatabaseComponent {
|
||||
/** Processes an ack from the given contact. */
|
||||
void receiveAck(ContactId c, Ack a) throws DbException;
|
||||
|
||||
/** Processes an expiry ack from the given contact. */
|
||||
void receiveExpiryAck(ContactId c, ExpiryAck a) throws DbException;
|
||||
|
||||
/** Processes an expiry update from the given contact. */
|
||||
void receiveExpiryUpdate(ContactId c, ExpiryUpdate u) throws DbException;
|
||||
|
||||
/** Processes a message from the given contact. */
|
||||
void receiveMessage(ContactId c, Message m) throws DbException;
|
||||
|
||||
@@ -219,6 +213,13 @@ public interface DatabaseComponent {
|
||||
*/
|
||||
Request receiveOffer(ContactId c, Offer o) throws DbException;
|
||||
|
||||
/** Processes a retention ack from the given contact. */
|
||||
void receiveRetentionAck(ContactId c, RetentionAck a) throws DbException;
|
||||
|
||||
/** Processes a retention update from the given contact. */
|
||||
void receiveRetentionUpdate(ContactId c, RetentionUpdate u)
|
||||
throws DbException;
|
||||
|
||||
/** Processes a subscription ack from the given contact. */
|
||||
void receiveSubscriptionAck(ContactId c, SubscriptionAck a)
|
||||
throws DbException;
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
package net.sf.briar.api.protocol;
|
||||
|
||||
/**
|
||||
* A packet updating the recipient's view of the expiry time of the sender's
|
||||
* database.
|
||||
*/
|
||||
public class ExpiryUpdate {
|
||||
|
||||
private final long expiry, version;
|
||||
|
||||
public ExpiryUpdate(long expiry, long version) {
|
||||
this.expiry = expiry;
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public long getExpiryTime() {
|
||||
return expiry;
|
||||
}
|
||||
|
||||
public long getVersionNumber() {
|
||||
return version;
|
||||
}
|
||||
}
|
||||
@@ -9,12 +9,6 @@ public interface ProtocolReader {
|
||||
boolean hasAck() throws IOException;
|
||||
Ack readAck() throws IOException;
|
||||
|
||||
boolean hasExpiryAck() throws IOException;
|
||||
ExpiryAck readExpiryAck() throws IOException;
|
||||
|
||||
boolean hasExpiryUpdate() throws IOException;
|
||||
ExpiryUpdate readExpiryUpdate() throws IOException;
|
||||
|
||||
boolean hasMessage() throws IOException;
|
||||
UnverifiedMessage readMessage() throws IOException;
|
||||
|
||||
@@ -24,6 +18,12 @@ public interface ProtocolReader {
|
||||
boolean hasRequest() throws IOException;
|
||||
Request readRequest() throws IOException;
|
||||
|
||||
boolean hasRetentionAck() throws IOException;
|
||||
RetentionAck readRetentionAck() throws IOException;
|
||||
|
||||
boolean hasRetentionUpdate() throws IOException;
|
||||
RetentionUpdate readRetentionUpdate() throws IOException;
|
||||
|
||||
boolean hasSubscriptionAck() throws IOException;
|
||||
SubscriptionAck readSubscriptionAck() throws IOException;
|
||||
|
||||
|
||||
@@ -10,16 +10,16 @@ public interface ProtocolWriter {
|
||||
|
||||
void writeAck(Ack a) throws IOException;
|
||||
|
||||
void writeExpiryAck(ExpiryAck a) throws IOException;
|
||||
|
||||
void writeExpiryUpdate(ExpiryUpdate e) throws IOException;
|
||||
|
||||
void writeMessage(byte[] raw) throws IOException;
|
||||
|
||||
void writeOffer(Offer o) throws IOException;
|
||||
|
||||
void writeRequest(Request r) throws IOException;
|
||||
|
||||
void writeRetentionAck(RetentionAck a) throws IOException;
|
||||
|
||||
void writeRetentionUpdate(RetentionUpdate u) throws IOException;
|
||||
|
||||
void writeSubscriptionAck(SubscriptionAck a) throws IOException;
|
||||
|
||||
void writeSubscriptionUpdate(SubscriptionUpdate u) throws IOException;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package net.sf.briar.api.protocol;
|
||||
|
||||
/** A packet acknowledging a (@link ExpiryUpdate} */
|
||||
public class ExpiryAck {
|
||||
/** A packet acknowledging a (@link RetentionUpdate} */
|
||||
public class RetentionAck {
|
||||
|
||||
private final long version;
|
||||
|
||||
public ExpiryAck(long version) {
|
||||
public RetentionAck(long version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
23
briar-api/src/net/sf/briar/api/protocol/RetentionUpdate.java
Normal file
23
briar-api/src/net/sf/briar/api/protocol/RetentionUpdate.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package net.sf.briar.api.protocol;
|
||||
|
||||
/**
|
||||
* A packet updating the recipient's view of the retention time of the sender's
|
||||
* database.
|
||||
*/
|
||||
public class RetentionUpdate {
|
||||
|
||||
private final long retention, version;
|
||||
|
||||
public RetentionUpdate(long retention, long version) {
|
||||
this.retention = retention;
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public long getRetentionTime() {
|
||||
return retention;
|
||||
}
|
||||
|
||||
public long getVersionNumber() {
|
||||
return version;
|
||||
}
|
||||
}
|
||||
@@ -6,11 +6,11 @@ public interface Types {
|
||||
int AUTHOR = 0;
|
||||
int GROUP = 1;
|
||||
int ACK = 2;
|
||||
int EXPIRY_ACK = 3;
|
||||
int EXPIRY_UPDATE = 4;
|
||||
int MESSAGE = 5;
|
||||
int OFFER = 6;
|
||||
int REQUEST = 7;
|
||||
int MESSAGE = 3;
|
||||
int OFFER = 4;
|
||||
int REQUEST = 5;
|
||||
int RETENTION_ACK = 6;
|
||||
int RETENTION_UPDATE = 7;
|
||||
int SUBSCRIPTION_ACK = 8;
|
||||
int SUBSCRIPTION_UPDATE = 9;
|
||||
int TRANSPORT_ACK = 10;
|
||||
|
||||
@@ -11,8 +11,8 @@ import net.sf.briar.api.TransportProperties;
|
||||
import net.sf.briar.api.db.DbException;
|
||||
import net.sf.briar.api.db.MessageHeader;
|
||||
import net.sf.briar.api.protocol.AuthorId;
|
||||
import net.sf.briar.api.protocol.ExpiryAck;
|
||||
import net.sf.briar.api.protocol.ExpiryUpdate;
|
||||
import net.sf.briar.api.protocol.RetentionAck;
|
||||
import net.sf.briar.api.protocol.RetentionUpdate;
|
||||
import net.sf.briar.api.protocol.Group;
|
||||
import net.sf.briar.api.protocol.GroupId;
|
||||
import net.sf.briar.api.protocol.Message;
|
||||
@@ -36,9 +36,9 @@ import net.sf.briar.api.transport.TemporarySecret;
|
||||
* deadlock, locks must be acquired in the following (alphabetical) order:
|
||||
* <ul>
|
||||
* <li> contact
|
||||
* <li> expiry
|
||||
* <li> message
|
||||
* <li> rating
|
||||
* <li> retention
|
||||
* <li> subscription
|
||||
* <li> transport
|
||||
* <li> window
|
||||
@@ -208,21 +208,6 @@ interface Database<T> {
|
||||
*/
|
||||
Collection<ContactTransport> getContactTransports(T txn) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns an expiry ack for the given contact, or null if no ack is due.
|
||||
* <p>
|
||||
* Locking: contact read, expiry write.
|
||||
*/
|
||||
ExpiryAck getExpiryAck(T txn, ContactId c) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns an expiry update for the given contact, or null if no update is
|
||||
* due.
|
||||
* <p>
|
||||
* Locking: contact read, expiry write.
|
||||
*/
|
||||
ExpiryUpdate getExpiryUpdate(T txn, ContactId c) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the amount of free storage space available to the database, in
|
||||
* bytes. This is based on the minimum of the space available on the device
|
||||
@@ -346,6 +331,21 @@ interface Database<T> {
|
||||
Map<ContactId, TransportProperties> getRemoteProperties(T txn,
|
||||
TransportId t) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns a retention ack for the given contact, or null if no ack is due.
|
||||
* <p>
|
||||
* Locking: contact read, retention write.
|
||||
*/
|
||||
RetentionAck getRetentionAck(T txn, ContactId c) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns a retention update for the given contact, or null if no update
|
||||
* is due.
|
||||
* <p>
|
||||
* Locking: contact read, retention write.
|
||||
*/
|
||||
RetentionUpdate getRetentionUpdate(T txn, ContactId c) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns all temporary secrets.
|
||||
* <p>
|
||||
@@ -459,12 +459,12 @@ interface Database<T> {
|
||||
long period) throws DbException;
|
||||
|
||||
/**
|
||||
* Increments the expiry versions for all contacts to indicate that the
|
||||
* database's expiry time has changed and expiry updates should be sent.
|
||||
* Increments the retention time versions for all contacts to indicate that
|
||||
* the database's retention time has changed and updates should be sent.
|
||||
* <p>
|
||||
* Locking: contact read, expiry write.
|
||||
* Locking: contact read, retention write.
|
||||
*/
|
||||
void incrementExpiryVersions(T txn) throws DbException;
|
||||
void incrementRetentionVersions(T txn) throws DbException;
|
||||
|
||||
/**
|
||||
* Merges the given configuration with the existing configuration for the
|
||||
@@ -549,16 +549,6 @@ interface Database<T> {
|
||||
void setConnectionWindow(T txn, ContactId c, TransportId t, long period,
|
||||
long centre, byte[] bitmap) throws DbException;
|
||||
|
||||
/**
|
||||
* Sets the expiry time of the given contact's database, unless an update
|
||||
* with an equal or higher version number has already been received from
|
||||
* the contact.
|
||||
* <p>
|
||||
* Locking: contact read, expiry write.
|
||||
*/
|
||||
void setExpiryTime(T txn, ContactId c, long expiry, long version)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Sets the user's rating for the given author.
|
||||
* <p>
|
||||
@@ -585,6 +575,16 @@ interface Database<T> {
|
||||
void setRemoteProperties(T txn, ContactId c, TransportUpdate u)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Sets the retention time of the given contact's database, unless an
|
||||
* update with an equal or higher version number has already been received
|
||||
* from the contact.
|
||||
* <p>
|
||||
* Locking: contact read, retention write.
|
||||
*/
|
||||
void setRetentionTime(T txn, ContactId c, long retention, long version)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Sets the sendability score of the given message.
|
||||
* <p>
|
||||
@@ -630,12 +630,12 @@ interface Database<T> {
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Records an expiry ack from the given contact for the given version
|
||||
* Records a retention ack from the given contact for the given version
|
||||
* unless the contact has already acked an equal or higher version.
|
||||
* <p>
|
||||
* Locking: contact read, expiry write.
|
||||
* Locking: contact read, retention write.
|
||||
*/
|
||||
void setExpiryUpdateAcked(T txn, ContactId c, long version)
|
||||
void setRetentionUpdateAcked(T txn, ContactId c, long version)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
|
||||
@@ -46,8 +46,8 @@ import net.sf.briar.api.db.event.TransportRemovedEvent;
|
||||
import net.sf.briar.api.lifecycle.ShutdownManager;
|
||||
import net.sf.briar.api.protocol.Ack;
|
||||
import net.sf.briar.api.protocol.AuthorId;
|
||||
import net.sf.briar.api.protocol.ExpiryAck;
|
||||
import net.sf.briar.api.protocol.ExpiryUpdate;
|
||||
import net.sf.briar.api.protocol.RetentionAck;
|
||||
import net.sf.briar.api.protocol.RetentionUpdate;
|
||||
import net.sf.briar.api.protocol.Group;
|
||||
import net.sf.briar.api.protocol.GroupId;
|
||||
import net.sf.briar.api.protocol.Message;
|
||||
@@ -83,12 +83,12 @@ DatabaseCleaner.Callback {
|
||||
|
||||
private final ReentrantReadWriteLock contactLock =
|
||||
new ReentrantReadWriteLock(true);
|
||||
private final ReentrantReadWriteLock expiryLock =
|
||||
new ReentrantReadWriteLock(true);
|
||||
private final ReentrantReadWriteLock messageLock =
|
||||
new ReentrantReadWriteLock(true);
|
||||
private final ReentrantReadWriteLock ratingLock =
|
||||
new ReentrantReadWriteLock(true);
|
||||
private final ReentrantReadWriteLock retentionLock =
|
||||
new ReentrantReadWriteLock(true);
|
||||
private final ReentrantReadWriteLock subscriptionLock =
|
||||
new ReentrantReadWriteLock(true);
|
||||
private final ReentrantReadWriteLock transportLock =
|
||||
@@ -594,54 +594,6 @@ DatabaseCleaner.Callback {
|
||||
return Collections.unmodifiableList(messages);
|
||||
}
|
||||
|
||||
public ExpiryAck generateExpiryAck(ContactId c) throws DbException {
|
||||
contactLock.readLock().lock();
|
||||
try {
|
||||
expiryLock.writeLock().lock();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
if(!db.containsContact(txn, c))
|
||||
throw new NoSuchContactException();
|
||||
ExpiryAck a = db.getExpiryAck(txn, c);
|
||||
db.commitTransaction(txn);
|
||||
return a;
|
||||
} catch(DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
expiryLock.writeLock().unlock();
|
||||
}
|
||||
} finally {
|
||||
contactLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public ExpiryUpdate generateExpiryUpdate(ContactId c) throws DbException {
|
||||
contactLock.readLock().lock();
|
||||
try {
|
||||
expiryLock.writeLock().lock();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
if(!db.containsContact(txn, c))
|
||||
throw new NoSuchContactException();
|
||||
ExpiryUpdate e = db.getExpiryUpdate(txn, c);
|
||||
db.commitTransaction(txn);
|
||||
return e;
|
||||
} catch(DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
expiryLock.writeLock().unlock();
|
||||
}
|
||||
} finally {
|
||||
contactLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public Offer generateOffer(ContactId c, int maxMessages)
|
||||
throws DbException {
|
||||
Collection<MessageId> offered;
|
||||
@@ -668,6 +620,55 @@ DatabaseCleaner.Callback {
|
||||
return new Offer(offered);
|
||||
}
|
||||
|
||||
public RetentionAck generateRetentionAck(ContactId c) throws DbException {
|
||||
contactLock.readLock().lock();
|
||||
try {
|
||||
retentionLock.writeLock().lock();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
if(!db.containsContact(txn, c))
|
||||
throw new NoSuchContactException();
|
||||
RetentionAck a = db.getRetentionAck(txn, c);
|
||||
db.commitTransaction(txn);
|
||||
return a;
|
||||
} catch(DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
retentionLock.writeLock().unlock();
|
||||
}
|
||||
} finally {
|
||||
contactLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public RetentionUpdate generateRetentionUpdate(ContactId c)
|
||||
throws DbException {
|
||||
contactLock.readLock().lock();
|
||||
try {
|
||||
retentionLock.writeLock().lock();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
if(!db.containsContact(txn, c))
|
||||
throw new NoSuchContactException();
|
||||
RetentionUpdate u = db.getRetentionUpdate(txn, c);
|
||||
db.commitTransaction(txn);
|
||||
return u;
|
||||
} catch(DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
retentionLock.writeLock().unlock();
|
||||
}
|
||||
} finally {
|
||||
contactLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public SubscriptionAck generateSubscriptionAck(ContactId c)
|
||||
throws DbException {
|
||||
contactLock.readLock().lock();
|
||||
@@ -1090,54 +1091,6 @@ DatabaseCleaner.Callback {
|
||||
}
|
||||
}
|
||||
|
||||
public void receiveExpiryAck(ContactId c, ExpiryAck a) throws DbException {
|
||||
contactLock.readLock().lock();
|
||||
try {
|
||||
expiryLock.writeLock().lock();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
if(!db.containsContact(txn, c))
|
||||
throw new NoSuchContactException();
|
||||
db.setExpiryUpdateAcked(txn, c, a.getVersionNumber());
|
||||
db.commitTransaction(txn);
|
||||
} catch(DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
expiryLock.writeLock().unlock();
|
||||
}
|
||||
} finally {
|
||||
contactLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void receiveExpiryUpdate(ContactId c, ExpiryUpdate u)
|
||||
throws DbException {
|
||||
contactLock.readLock().lock();
|
||||
try {
|
||||
expiryLock.writeLock().lock();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
if(!db.containsContact(txn, c))
|
||||
throw new NoSuchContactException();
|
||||
db.setExpiryTime(txn, c, u.getExpiryTime(),
|
||||
u.getVersionNumber());
|
||||
db.commitTransaction(txn);
|
||||
} catch(DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
expiryLock.writeLock().unlock();
|
||||
}
|
||||
} finally {
|
||||
contactLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void receiveMessage(ContactId c, Message m) throws DbException {
|
||||
boolean added = false;
|
||||
contactLock.readLock().lock();
|
||||
@@ -1226,6 +1179,55 @@ DatabaseCleaner.Callback {
|
||||
return new Request(request, offered.size());
|
||||
}
|
||||
|
||||
public void receiveRetentionAck(ContactId c, RetentionAck a)
|
||||
throws DbException {
|
||||
contactLock.readLock().lock();
|
||||
try {
|
||||
retentionLock.writeLock().lock();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
if(!db.containsContact(txn, c))
|
||||
throw new NoSuchContactException();
|
||||
db.setRetentionUpdateAcked(txn, c, a.getVersionNumber());
|
||||
db.commitTransaction(txn);
|
||||
} catch(DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
retentionLock.writeLock().unlock();
|
||||
}
|
||||
} finally {
|
||||
contactLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void receiveRetentionUpdate(ContactId c, RetentionUpdate u)
|
||||
throws DbException {
|
||||
contactLock.readLock().lock();
|
||||
try {
|
||||
retentionLock.writeLock().lock();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
if(!db.containsContact(txn, c))
|
||||
throw new NoSuchContactException();
|
||||
db.setRetentionTime(txn, c, u.getRetentionTime(),
|
||||
u.getVersionNumber());
|
||||
db.commitTransaction(txn);
|
||||
} catch(DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
retentionLock.writeLock().unlock();
|
||||
}
|
||||
} finally {
|
||||
contactLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void receiveSubscriptionAck(ContactId c, SubscriptionAck a)
|
||||
throws DbException {
|
||||
contactLock.readLock().lock();
|
||||
@@ -1606,9 +1608,9 @@ DatabaseCleaner.Callback {
|
||||
boolean removed = false;
|
||||
contactLock.readLock().lock();
|
||||
try {
|
||||
expiryLock.writeLock().lock();
|
||||
messageLock.writeLock().lock();
|
||||
try {
|
||||
messageLock.writeLock().lock();
|
||||
retentionLock.writeLock().lock();
|
||||
try {
|
||||
T txn = db.startTransaction();
|
||||
try {
|
||||
@@ -1616,7 +1618,7 @@ DatabaseCleaner.Callback {
|
||||
db.getOldMessages(txn, size);
|
||||
if(!old.isEmpty()) {
|
||||
for(MessageId m : old) removeMessage(txn, m);
|
||||
db.incrementExpiryVersions(txn);
|
||||
db.incrementRetentionVersions(txn);
|
||||
removed = true;
|
||||
}
|
||||
db.commitTransaction(txn);
|
||||
@@ -1625,10 +1627,10 @@ DatabaseCleaner.Callback {
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
messageLock.writeLock().unlock();
|
||||
retentionLock.writeLock().unlock();
|
||||
}
|
||||
} finally {
|
||||
expiryLock.writeLock().unlock();
|
||||
messageLock.writeLock().unlock();
|
||||
}
|
||||
} finally {
|
||||
contactLock.readLock().unlock();
|
||||
|
||||
@@ -40,7 +40,7 @@ interface DatabaseConstants {
|
||||
* The timestamp of the oldest message in the database is rounded using
|
||||
* this modulus to avoid revealing the presence of any particular message.
|
||||
*/
|
||||
long EXPIRY_MODULUS = 60L * 60L * 1000L; // 1 hour
|
||||
long RETENTION_MODULUS = 60L * 60L * 1000L; // 1 hour
|
||||
|
||||
/**
|
||||
* The time in milliseconds after which a subscription or transport update
|
||||
|
||||
@@ -3,7 +3,7 @@ package net.sf.briar.db;
|
||||
import static java.sql.Types.BINARY;
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static net.sf.briar.db.DatabaseConstants.EXPIRY_MODULUS;
|
||||
import static net.sf.briar.db.DatabaseConstants.RETENTION_MODULUS;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
@@ -31,8 +31,8 @@ import net.sf.briar.api.db.DbClosedException;
|
||||
import net.sf.briar.api.db.DbException;
|
||||
import net.sf.briar.api.db.MessageHeader;
|
||||
import net.sf.briar.api.protocol.AuthorId;
|
||||
import net.sf.briar.api.protocol.ExpiryAck;
|
||||
import net.sf.briar.api.protocol.ExpiryUpdate;
|
||||
import net.sf.briar.api.protocol.RetentionAck;
|
||||
import net.sf.briar.api.protocol.RetentionUpdate;
|
||||
import net.sf.briar.api.protocol.Group;
|
||||
import net.sf.briar.api.protocol.GroupId;
|
||||
import net.sf.briar.api.protocol.Message;
|
||||
@@ -58,20 +58,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
+ " (contactId COUNTER,"
|
||||
+ " PRIMARY KEY (contactId))";
|
||||
|
||||
// Locking: expiry
|
||||
private static final String CREATE_EXPIRY_VERSIONS =
|
||||
"CREATE TABLE expiryVersions"
|
||||
+ " (contactId INT NOT NULL,"
|
||||
+ " expiry BIGINT NOT NULL,"
|
||||
+ " localVersion BIGINT NOT NULL,"
|
||||
+ " localAcked BIGINT NOT NULL,"
|
||||
+ " remoteVersion BIGINT NOT NULL,"
|
||||
+ " remoteAcked BOOLEAN NOT NULL,"
|
||||
+ " PRIMARY KEY (contactId),"
|
||||
+ " FOREIGN KEY (contactId)"
|
||||
+ " REFERENCES contacts (contactId)"
|
||||
+ " ON DELETE CASCADE)";
|
||||
|
||||
// Locking: message
|
||||
private static final String CREATE_MESSAGES =
|
||||
"CREATE TABLE messages"
|
||||
@@ -155,6 +141,20 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
+ " rating SMALLINT NOT NULL,"
|
||||
+ " PRIMARY KEY (authorId))";
|
||||
|
||||
// Locking: contact read, retention
|
||||
private static final String CREATE_RETENTION_VERSIONS =
|
||||
"CREATE TABLE retentionVersions"
|
||||
+ " (contactId INT NOT NULL,"
|
||||
+ " retention BIGINT NOT NULL,"
|
||||
+ " localVersion BIGINT NOT NULL,"
|
||||
+ " localAcked BIGINT NOT NULL,"
|
||||
+ " remoteVersion BIGINT NOT NULL,"
|
||||
+ " remoteAcked BOOLEAN NOT NULL,"
|
||||
+ " PRIMARY KEY (contactId),"
|
||||
+ " FOREIGN KEY (contactId)"
|
||||
+ " REFERENCES contacts (contactId)"
|
||||
+ " ON DELETE CASCADE)";
|
||||
|
||||
// Locking: subscription
|
||||
private static final String CREATE_GROUPS =
|
||||
"CREATE TABLE groups"
|
||||
@@ -355,7 +355,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
try {
|
||||
s = txn.createStatement();
|
||||
s.executeUpdate(insertTypeNames(CREATE_CONTACTS));
|
||||
s.executeUpdate(insertTypeNames(CREATE_EXPIRY_VERSIONS));
|
||||
s.executeUpdate(insertTypeNames(CREATE_MESSAGES));
|
||||
s.executeUpdate(INDEX_MESSAGES_BY_PARENT);
|
||||
s.executeUpdate(INDEX_MESSAGES_BY_AUTHOR);
|
||||
@@ -367,6 +366,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
s.executeUpdate(INDEX_STATUSES_BY_CONTACT);
|
||||
s.executeUpdate(insertTypeNames(CREATE_FLAGS));
|
||||
s.executeUpdate(insertTypeNames(CREATE_RATINGS));
|
||||
s.executeUpdate(insertTypeNames(CREATE_RETENTION_VERSIONS));
|
||||
s.executeUpdate(insertTypeNames(CREATE_GROUPS));
|
||||
s.executeUpdate(insertTypeNames(CREATE_GROUP_VISIBILITIES));
|
||||
s.executeUpdate(insertTypeNames(CREATE_CONTACT_GROUPS));
|
||||
@@ -513,8 +513,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if(rs.next()) throw new DbStateException();
|
||||
rs.close();
|
||||
ps.close();
|
||||
// Create an expiry version row
|
||||
sql = "INSERT INTO expiryVersions (contactId, expiry,"
|
||||
// Create a retention version row
|
||||
sql = "INSERT INTO retentionVersions (contactId, retention,"
|
||||
+ " localVersion, localAcked, remoteVersion, remoteAcked)"
|
||||
+ " VALUES (?, ZERO(), ?, ZERO(), ZERO(), TRUE)";
|
||||
ps = txn.prepareStatement(sql);
|
||||
@@ -1042,72 +1042,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
} else return f.length();
|
||||
}
|
||||
|
||||
public ExpiryAck getExpiryAck(Connection txn, ContactId c)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = "SELECT remoteVersion FROM expiryVersions"
|
||||
+ " WHERE contactId = ? AND remoteAcked = FALSE";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setInt(1, c.getInt());
|
||||
rs = ps.executeQuery();
|
||||
if(!rs.next()) {
|
||||
rs.close();
|
||||
ps.close();
|
||||
return null;
|
||||
}
|
||||
long version = rs.getLong(1);
|
||||
if(rs.next()) throw new DbStateException();
|
||||
rs.close();
|
||||
ps.close();
|
||||
sql = "UPDATE expiryVersions SET remoteAcked = TRUE"
|
||||
+ " WHERE contactId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setInt(1, c.getInt());
|
||||
int affected = ps.executeUpdate();
|
||||
if(affected != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
return new ExpiryAck(version);
|
||||
} catch(SQLException e) {
|
||||
tryToClose(ps);
|
||||
tryToClose(rs);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public ExpiryUpdate getExpiryUpdate(Connection txn, ContactId c)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = "SELECT timestamp, localVersion"
|
||||
+ " FROM messages JOIN expiryVersions"
|
||||
+ " WHERE contactId = ? AND localVersion > localAcked"
|
||||
+ " ORDER BY timestamp LIMIT ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setInt(1, c.getInt());
|
||||
ps.setInt(2, 1);
|
||||
rs = ps.executeQuery();
|
||||
if(!rs.next()) {
|
||||
rs.close();
|
||||
ps.close();
|
||||
return null;
|
||||
}
|
||||
long expiry = rs.getLong(1);
|
||||
expiry -= expiry % EXPIRY_MODULUS;
|
||||
long version = rs.getLong(2);
|
||||
if(rs.next()) throw new DbStateException();
|
||||
rs.close();
|
||||
ps.close();
|
||||
return new ExpiryUpdate(expiry, version);
|
||||
} catch(SQLException e) {
|
||||
tryToClose(ps);
|
||||
tryToClose(rs);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public MessageId getGroupMessageParent(Connection txn, MessageId m)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
@@ -1277,14 +1211,14 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
+ " JOIN groupVisibilities AS gv"
|
||||
+ " ON m.groupId = gv.groupId"
|
||||
+ " AND cg.contactId = gv.contactId"
|
||||
+ " JOIN expiryVersions AS ev"
|
||||
+ " ON cg.contactId = ev.contactId"
|
||||
+ " JOIN retentionVersions AS rv"
|
||||
+ " ON cg.contactId = rv.contactId"
|
||||
+ " JOIN statuses AS s"
|
||||
+ " ON m.messageId = s.messageId"
|
||||
+ " AND cg.contactId = s.contactId"
|
||||
+ " WHERE m.messageId = ?"
|
||||
+ " AND cg.contactId = ?"
|
||||
+ " AND timestamp >= expiry"
|
||||
+ " AND timestamp >= retention"
|
||||
+ " AND status = ?"
|
||||
+ " AND sendability > ZERO()";
|
||||
ps = txn.prepareStatement(sql);
|
||||
@@ -1382,13 +1316,13 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
+ " JOIN groupVisibilities AS gv"
|
||||
+ " ON m.groupId = gv.groupId"
|
||||
+ " AND cg.contactId = gv.contactId"
|
||||
+ " JOIN expiryVersions AS ev"
|
||||
+ " ON cg.contactId = ev.contactId"
|
||||
+ " JOIN retentionVersions AS rv"
|
||||
+ " ON cg.contactId = rv.contactId"
|
||||
+ " JOIN statuses AS s"
|
||||
+ " ON m.messageId = s.messageId"
|
||||
+ " AND cg.contactId = s.contactId"
|
||||
+ " WHERE cg.contactId = ?"
|
||||
+ " AND timestamp >= expiry"
|
||||
+ " AND timestamp >= retention"
|
||||
+ " AND status = ?"
|
||||
+ " AND sendability > ZERO()"
|
||||
+ " ORDER BY timestamp DESC LIMIT ?";
|
||||
@@ -1548,6 +1482,72 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
}
|
||||
|
||||
public RetentionAck getRetentionAck(Connection txn, ContactId c)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = "SELECT remoteVersion FROM retentionVersions"
|
||||
+ " WHERE contactId = ? AND remoteAcked = FALSE";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setInt(1, c.getInt());
|
||||
rs = ps.executeQuery();
|
||||
if(!rs.next()) {
|
||||
rs.close();
|
||||
ps.close();
|
||||
return null;
|
||||
}
|
||||
long version = rs.getLong(1);
|
||||
if(rs.next()) throw new DbStateException();
|
||||
rs.close();
|
||||
ps.close();
|
||||
sql = "UPDATE retentionVersions SET remoteAcked = TRUE"
|
||||
+ " WHERE contactId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setInt(1, c.getInt());
|
||||
int affected = ps.executeUpdate();
|
||||
if(affected != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
return new RetentionAck(version);
|
||||
} catch(SQLException e) {
|
||||
tryToClose(ps);
|
||||
tryToClose(rs);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public RetentionUpdate getRetentionUpdate(Connection txn, ContactId c)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = "SELECT timestamp, localVersion"
|
||||
+ " FROM messages JOIN retentionVersions"
|
||||
+ " WHERE contactId = ? AND localVersion > localAcked"
|
||||
+ " ORDER BY timestamp LIMIT ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setInt(1, c.getInt());
|
||||
ps.setInt(2, 1);
|
||||
rs = ps.executeQuery();
|
||||
if(!rs.next()) {
|
||||
rs.close();
|
||||
ps.close();
|
||||
return null;
|
||||
}
|
||||
long retention = rs.getLong(1);
|
||||
retention -= retention % RETENTION_MODULUS;
|
||||
long version = rs.getLong(2);
|
||||
if(rs.next()) throw new DbStateException();
|
||||
rs.close();
|
||||
ps.close();
|
||||
return new RetentionUpdate(retention, version);
|
||||
} catch(SQLException e) {
|
||||
tryToClose(ps);
|
||||
tryToClose(rs);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<TemporarySecret> getSecrets(Connection txn)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
@@ -1642,13 +1642,13 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
+ " JOIN groupVisibilities AS gv"
|
||||
+ " ON m.groupId = gv.groupId"
|
||||
+ " AND cg.contactId = gv.contactId"
|
||||
+ " JOIN expiryVersions AS ev"
|
||||
+ " ON cg.contactId = ev.contactId"
|
||||
+ " JOIN retentionVersions AS rv"
|
||||
+ " ON cg.contactId = rv.contactId"
|
||||
+ " JOIN statuses AS s"
|
||||
+ " ON m.messageId = s.messageId"
|
||||
+ " AND cg.contactId = s.contactId"
|
||||
+ " WHERE cg.contactId = ?"
|
||||
+ " AND timestamp >= expiry"
|
||||
+ " AND timestamp >= retention"
|
||||
+ " AND status = ?"
|
||||
+ " AND sendability > ZERO()"
|
||||
+ " ORDER BY timestamp DESC";
|
||||
@@ -1974,13 +1974,13 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
+ " JOIN groupVisibilities AS gv"
|
||||
+ " ON m.groupId = gv.groupId"
|
||||
+ " AND cg.contactId = gv.contactId"
|
||||
+ " JOIN expiryVersions AS ev"
|
||||
+ " ON cg.contactId = ev.contactId"
|
||||
+ " JOIN retentionVersios AS rv"
|
||||
+ " ON cg.contactId = rv.contactId"
|
||||
+ " JOIN statuses AS s"
|
||||
+ " ON m.messageId = s.messageId"
|
||||
+ " AND cg.contactId = s.contactId"
|
||||
+ " WHERE cg.contactId = ?"
|
||||
+ " AND timestamp >= expiry"
|
||||
+ " AND timestamp >= retention"
|
||||
+ " AND status = ?"
|
||||
+ " AND sendability > ZERO()"
|
||||
+ " LIMIT ?";
|
||||
@@ -2042,10 +2042,10 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
}
|
||||
|
||||
public void incrementExpiryVersions(Connection txn) throws DbException {
|
||||
public void incrementRetentionVersions(Connection txn) throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
try {
|
||||
String sql = "UPDATE expiryVersions"
|
||||
String sql = "UPDATE retentionVersions"
|
||||
+ " SET localVersion = localVersion + ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setInt(1, 1);
|
||||
@@ -2323,15 +2323,15 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
}
|
||||
|
||||
public void setExpiryTime(Connection txn, ContactId c, long expiry,
|
||||
public void setRetentionTime(Connection txn, ContactId c, long retention,
|
||||
long version) throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
try {
|
||||
String sql = "UPDATE expiryVersions"
|
||||
+ " SET expiry = ?, remoteVersion = ?, remoteAcked = FALSE"
|
||||
String sql = "UPDATE retentionVersions SET retention = ?,"
|
||||
+ " remoteVersion = ?, remoteAcked = FALSE"
|
||||
+ " WHERE contactId = ? AND remoteVersion < ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setLong(1, expiry);
|
||||
ps.setLong(1, retention);
|
||||
ps.setLong(2, version);
|
||||
ps.setInt(3, c.getInt());
|
||||
ps.setLong(4, version);
|
||||
@@ -2344,11 +2344,11 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
}
|
||||
|
||||
public void setExpiryUpdateAcked(Connection txn, ContactId c, long version)
|
||||
throws DbException {
|
||||
public void setRetentionUpdateAcked(Connection txn, ContactId c,
|
||||
long version) throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
try {
|
||||
String sql = "UPDATE expiryVersions SET localAcked = ?"
|
||||
String sql = "UPDATE retentionVersions SET localAcked = ?"
|
||||
+ " WHERE contactId = ?"
|
||||
+ " AND localAcked < ? AND localVersion >= ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
@@ -2672,11 +2672,11 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
+ " JOIN groupVisibilities AS gv"
|
||||
+ " ON m.groupId = gv.groupId"
|
||||
+ " AND cg.contactId = gv.contactId"
|
||||
+ " JOIN expiryVersions AS ev"
|
||||
+ " ON cg.contactId = ev.contactId"
|
||||
+ " JOIN retentionVersions AS rv"
|
||||
+ " ON cg.contactId = rv.contactId"
|
||||
+ " WHERE messageId = ?"
|
||||
+ " AND cg.contactId = ?"
|
||||
+ " AND timestamp >= expiry";
|
||||
+ " AND timestamp >= retention";
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setBytes(1, m.getBytes());
|
||||
ps.setInt(2, c.getInt());
|
||||
|
||||
@@ -4,8 +4,8 @@ import static net.sf.briar.api.protocol.ProtocolConstants.MAX_PACKET_LENGTH;
|
||||
import static net.sf.briar.api.protocol.ProtocolConstants.MAX_PROPERTIES_PER_TRANSPORT;
|
||||
import static net.sf.briar.api.protocol.ProtocolConstants.MAX_PROPERTY_LENGTH;
|
||||
import static net.sf.briar.api.protocol.Types.ACK;
|
||||
import static net.sf.briar.api.protocol.Types.EXPIRY_ACK;
|
||||
import static net.sf.briar.api.protocol.Types.EXPIRY_UPDATE;
|
||||
import static net.sf.briar.api.protocol.Types.RETENTION_ACK;
|
||||
import static net.sf.briar.api.protocol.Types.RETENTION_UPDATE;
|
||||
import static net.sf.briar.api.protocol.Types.MESSAGE;
|
||||
import static net.sf.briar.api.protocol.Types.OFFER;
|
||||
import static net.sf.briar.api.protocol.Types.REQUEST;
|
||||
@@ -26,8 +26,8 @@ import net.sf.briar.api.Bytes;
|
||||
import net.sf.briar.api.FormatException;
|
||||
import net.sf.briar.api.TransportProperties;
|
||||
import net.sf.briar.api.protocol.Ack;
|
||||
import net.sf.briar.api.protocol.ExpiryAck;
|
||||
import net.sf.briar.api.protocol.ExpiryUpdate;
|
||||
import net.sf.briar.api.protocol.RetentionAck;
|
||||
import net.sf.briar.api.protocol.RetentionUpdate;
|
||||
import net.sf.briar.api.protocol.MessageId;
|
||||
import net.sf.briar.api.protocol.Offer;
|
||||
import net.sf.briar.api.protocol.ProtocolReader;
|
||||
@@ -90,30 +90,6 @@ class ProtocolReaderImpl implements ProtocolReader {
|
||||
return new Ack(Collections.unmodifiableList(acked));
|
||||
}
|
||||
|
||||
public boolean hasExpiryAck() throws IOException {
|
||||
return r.hasStruct(EXPIRY_ACK);
|
||||
}
|
||||
|
||||
public ExpiryAck readExpiryAck() throws IOException {
|
||||
r.readStructId(EXPIRY_ACK);
|
||||
long version = r.readInt64();
|
||||
if(version < 0L) throw new FormatException();
|
||||
return new ExpiryAck(version);
|
||||
}
|
||||
|
||||
public boolean hasExpiryUpdate() throws IOException {
|
||||
return r.hasStruct(EXPIRY_UPDATE);
|
||||
}
|
||||
|
||||
public ExpiryUpdate readExpiryUpdate() throws IOException {
|
||||
r.readStructId(EXPIRY_UPDATE);
|
||||
long expiry = r.readInt64();
|
||||
if(expiry < 0L) throw new FormatException();
|
||||
long version = r.readInt64();
|
||||
if(version < 0L) throw new FormatException();
|
||||
return new ExpiryUpdate(expiry, version);
|
||||
}
|
||||
|
||||
public boolean hasMessage() throws IOException {
|
||||
return r.hasStruct(MESSAGE);
|
||||
}
|
||||
@@ -173,6 +149,30 @@ class ProtocolReaderImpl implements ProtocolReader {
|
||||
return new Request(b, length);
|
||||
}
|
||||
|
||||
public boolean hasRetentionAck() throws IOException {
|
||||
return r.hasStruct(RETENTION_ACK);
|
||||
}
|
||||
|
||||
public RetentionAck readRetentionAck() throws IOException {
|
||||
r.readStructId(RETENTION_ACK);
|
||||
long version = r.readInt64();
|
||||
if(version < 0L) throw new FormatException();
|
||||
return new RetentionAck(version);
|
||||
}
|
||||
|
||||
public boolean hasRetentionUpdate() throws IOException {
|
||||
return r.hasStruct(RETENTION_UPDATE);
|
||||
}
|
||||
|
||||
public RetentionUpdate readRetentionUpdate() throws IOException {
|
||||
r.readStructId(RETENTION_UPDATE);
|
||||
long retention = r.readInt64();
|
||||
if(retention < 0L) throw new FormatException();
|
||||
long version = r.readInt64();
|
||||
if(version < 0L) throw new FormatException();
|
||||
return new RetentionUpdate(retention, version);
|
||||
}
|
||||
|
||||
public boolean hasSubscriptionAck() throws IOException {
|
||||
return r.hasStruct(SUBSCRIPTION_ACK);
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ package net.sf.briar.protocol;
|
||||
|
||||
import static net.sf.briar.api.protocol.ProtocolConstants.MAX_PACKET_LENGTH;
|
||||
import static net.sf.briar.api.protocol.Types.ACK;
|
||||
import static net.sf.briar.api.protocol.Types.EXPIRY_ACK;
|
||||
import static net.sf.briar.api.protocol.Types.EXPIRY_UPDATE;
|
||||
import static net.sf.briar.api.protocol.Types.RETENTION_ACK;
|
||||
import static net.sf.briar.api.protocol.Types.RETENTION_UPDATE;
|
||||
import static net.sf.briar.api.protocol.Types.GROUP;
|
||||
import static net.sf.briar.api.protocol.Types.OFFER;
|
||||
import static net.sf.briar.api.protocol.Types.REQUEST;
|
||||
@@ -17,8 +17,8 @@ import java.io.OutputStream;
|
||||
import java.util.BitSet;
|
||||
|
||||
import net.sf.briar.api.protocol.Ack;
|
||||
import net.sf.briar.api.protocol.ExpiryAck;
|
||||
import net.sf.briar.api.protocol.ExpiryUpdate;
|
||||
import net.sf.briar.api.protocol.RetentionAck;
|
||||
import net.sf.briar.api.protocol.RetentionUpdate;
|
||||
import net.sf.briar.api.protocol.Group;
|
||||
import net.sf.briar.api.protocol.MessageId;
|
||||
import net.sf.briar.api.protocol.Offer;
|
||||
@@ -74,19 +74,6 @@ class ProtocolWriterImpl implements ProtocolWriter {
|
||||
if(flush) out.flush();
|
||||
}
|
||||
|
||||
public void writeExpiryAck(ExpiryAck a) throws IOException {
|
||||
w.writeStructId(EXPIRY_ACK);
|
||||
w.writeInt64(a.getVersionNumber());
|
||||
if(flush) out.flush();
|
||||
}
|
||||
|
||||
public void writeExpiryUpdate(ExpiryUpdate e) throws IOException {
|
||||
w.writeStructId(EXPIRY_UPDATE);
|
||||
w.writeInt64(e.getExpiryTime());
|
||||
w.writeInt64(e.getVersionNumber());
|
||||
if(flush) out.flush();
|
||||
}
|
||||
|
||||
public void writeMessage(byte[] raw) throws IOException {
|
||||
out.write(raw);
|
||||
if(flush) out.flush();
|
||||
@@ -120,6 +107,19 @@ class ProtocolWriterImpl implements ProtocolWriter {
|
||||
if(flush) out.flush();
|
||||
}
|
||||
|
||||
public void writeRetentionAck(RetentionAck a) throws IOException {
|
||||
w.writeStructId(RETENTION_ACK);
|
||||
w.writeInt64(a.getVersionNumber());
|
||||
if(flush) out.flush();
|
||||
}
|
||||
|
||||
public void writeRetentionUpdate(RetentionUpdate u) throws IOException {
|
||||
w.writeStructId(RETENTION_UPDATE);
|
||||
w.writeInt64(u.getRetentionTime());
|
||||
w.writeInt64(u.getVersionNumber());
|
||||
if(flush) out.flush();
|
||||
}
|
||||
|
||||
public void writeSubscriptionAck(SubscriptionAck a) throws IOException {
|
||||
w.writeStructId(SUBSCRIPTION_ACK);
|
||||
w.writeInt64(a.getVersionNumber());
|
||||
|
||||
Reference in New Issue
Block a user