mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 03:09:04 +01:00
Decouple the database from IO.
This will enable asynchronous access to the database for IO threads.
This commit is contained in:
143
components/net/sf/briar/protocol/ProtocolWriterImpl.java
Normal file
143
components/net/sf/briar/protocol/ProtocolWriterImpl.java
Normal file
@@ -0,0 +1,143 @@
|
||||
package net.sf.briar.protocol;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.BitSet;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import net.sf.briar.api.protocol.Ack;
|
||||
import net.sf.briar.api.protocol.BatchId;
|
||||
import net.sf.briar.api.protocol.Group;
|
||||
import net.sf.briar.api.protocol.MessageId;
|
||||
import net.sf.briar.api.protocol.Offer;
|
||||
import static net.sf.briar.api.protocol.ProtocolConstants.MAX_PACKET_LENGTH;
|
||||
import net.sf.briar.api.protocol.ProtocolWriter;
|
||||
import net.sf.briar.api.protocol.RawBatch;
|
||||
import net.sf.briar.api.protocol.Request;
|
||||
import net.sf.briar.api.protocol.SubscriptionUpdate;
|
||||
import net.sf.briar.api.protocol.Transport;
|
||||
import net.sf.briar.api.protocol.TransportUpdate;
|
||||
import net.sf.briar.api.protocol.Types;
|
||||
import net.sf.briar.api.serial.SerialComponent;
|
||||
import net.sf.briar.api.serial.Writer;
|
||||
import net.sf.briar.api.serial.WriterFactory;
|
||||
|
||||
// This class is not thread-safe
|
||||
class ProtocolWriterImpl implements ProtocolWriter {
|
||||
|
||||
private final SerialComponent serial;
|
||||
private final OutputStream out;
|
||||
private final Writer w;
|
||||
|
||||
ProtocolWriterImpl(SerialComponent serial, WriterFactory writerFactory,
|
||||
OutputStream out) {
|
||||
this.serial = serial;
|
||||
this.out = out;
|
||||
w = writerFactory.createWriter(out);
|
||||
}
|
||||
|
||||
public int getMaxBatchesForAck(long capacity) {
|
||||
int packet = (int) Math.min(capacity, MAX_PACKET_LENGTH);
|
||||
int overhead = serial.getSerialisedStructIdLength(Types.ACK)
|
||||
+ serial.getSerialisedListStartLength()
|
||||
+ serial.getSerialisedListEndLength();
|
||||
int idLength = serial.getSerialisedUniqueIdLength(Types.BATCH_ID);
|
||||
return (packet - overhead) / idLength;
|
||||
}
|
||||
|
||||
public int getMaxMessagesForOffer(long capacity) {
|
||||
int packet = (int) Math.min(capacity, MAX_PACKET_LENGTH);
|
||||
int overhead = serial.getSerialisedStructIdLength(Types.OFFER)
|
||||
+ serial.getSerialisedListStartLength()
|
||||
+ serial.getSerialisedListEndLength();
|
||||
int idLength = serial.getSerialisedUniqueIdLength(Types.MESSAGE_ID);
|
||||
return (packet - overhead) / idLength;
|
||||
}
|
||||
|
||||
public int getMessageCapacityForBatch(long capacity) {
|
||||
int packet = (int) Math.min(capacity, MAX_PACKET_LENGTH);
|
||||
int overhead = serial.getSerialisedStructIdLength(Types.BATCH)
|
||||
+ serial.getSerialisedListStartLength()
|
||||
+ serial.getSerialisedListEndLength();
|
||||
return packet - overhead;
|
||||
}
|
||||
|
||||
public void writeAck(Ack a) throws IOException {
|
||||
w.writeStructId(Types.ACK);
|
||||
w.writeListStart();
|
||||
for(BatchId b : a.getBatchIds()) {
|
||||
w.writeStructId(Types.BATCH_ID);
|
||||
w.writeBytes(b.getBytes());
|
||||
}
|
||||
w.writeListEnd();
|
||||
}
|
||||
|
||||
public void writeBatch(RawBatch b) throws IOException {
|
||||
w.writeStructId(Types.BATCH);
|
||||
w.writeListStart();
|
||||
for(byte[] raw : b.getMessages()) out.write(raw);
|
||||
w.writeListEnd();
|
||||
}
|
||||
|
||||
public void writeOffer(Offer o) throws IOException {
|
||||
w.writeStructId(Types.OFFER);
|
||||
w.writeListStart();
|
||||
for(MessageId m : o.getMessageIds()) {
|
||||
w.writeStructId(Types.MESSAGE_ID);
|
||||
w.writeBytes(m.getBytes());
|
||||
}
|
||||
w.writeListEnd();
|
||||
}
|
||||
|
||||
public void writeRequest(Request r) throws IOException {
|
||||
BitSet b = r.getBitmap();
|
||||
int length = r.getLength();
|
||||
// If the number of bits isn't a multiple of 8, round up to a byte
|
||||
int bytes = length % 8 == 0 ? length / 8 : length / 8 + 1;
|
||||
byte[] bitmap = new byte[bytes];
|
||||
// I'm kind of surprised BitSet doesn't have a method for this
|
||||
for(int i = 0; i < length; i++) {
|
||||
if(b.get(i)) {
|
||||
int offset = i / 8;
|
||||
byte bit = (byte) (128 >> i % 8);
|
||||
bitmap[offset] |= bit;
|
||||
}
|
||||
}
|
||||
w.writeStructId(Types.REQUEST);
|
||||
w.writeUint7((byte) (bytes * 8 - length));
|
||||
w.writeBytes(bitmap);
|
||||
}
|
||||
|
||||
public void writeSubscriptionUpdate(SubscriptionUpdate s)
|
||||
throws IOException {
|
||||
w.writeStructId(Types.SUBSCRIPTION_UPDATE);
|
||||
w.writeMapStart();
|
||||
for(Entry<Group, Long> e : s.getSubscriptions().entrySet()) {
|
||||
writeGroup(w, e.getKey());
|
||||
w.writeInt64(e.getValue());
|
||||
}
|
||||
w.writeMapEnd();
|
||||
w.writeInt64(s.getTimestamp());
|
||||
}
|
||||
|
||||
private void writeGroup(Writer w, Group g) throws IOException {
|
||||
w.writeStructId(Types.GROUP);
|
||||
w.writeString(g.getName());
|
||||
byte[] publicKey = g.getPublicKey();
|
||||
if(publicKey == null) w.writeNull();
|
||||
else w.writeBytes(publicKey);
|
||||
}
|
||||
|
||||
public void writeTransportUpdate(TransportUpdate t) throws IOException {
|
||||
w.writeStructId(Types.TRANSPORT_UPDATE);
|
||||
w.writeListStart();
|
||||
for(Transport p : t.getTransports()) {
|
||||
w.writeStructId(Types.TRANSPORT);
|
||||
w.writeBytes(p.getId().getBytes());
|
||||
w.writeInt32(p.getIndex().getInt());
|
||||
w.writeMap(p);
|
||||
}
|
||||
w.writeListEnd();
|
||||
w.writeInt64(t.getTimestamp());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user