Skip to content
Commit b16227d5 authored by Daniel Vrátil's avatar Daniel Vrátil 🤖
Browse files

Merge dev/binary-protocol

This replaces the text-based IMAP-like protocol used by clients to communicate
with the Akonadi Server by a binary protocol.

Compared to text-based protocols de/serializing data from/into a binary stream
is much faster and more memory effective. This is mostly because we only malloc
the storage and then memcpy the data from the stream to the storage without
having to spend CPU cycles on intepreting and parsing the data.

Binary protocol requires that both sender and receiver send the data in the
exactly same format and order, unlike IMAP where order of arguments did not
matter most of the time. To enfore this the Akonadi server provides new
Akonadi::Protocol namespace with classes representing each Command/Response
specified in the protocol and the (de)serialization is implemented inside
these classes. This means that the actual binary-level representation of each
command is completely hidden from clients and the server, allowing for changes
in the protocol without having to worry about all places where the modified
command is parsed or generated by client or server.

Although we could technically support multiple versions of the protocol, allowing
for mixing versions of server and client libraries the added complexity is not
worth it and for that reason both server and client now enforce that they both
speak exactly the same version of the protocol. Every change to the (de)serializer
code REQUIRES that the protocol version is bumped. Unlike with text-based protocol
where unknown keyword can be ignored or missing keyword replaced by default value,
with binary protocol inconsistency between serializer and deserializer will lead
to data corruption.

Finally, each Command in the Protocol has debugString() method that returns
a human-readable string representation of the command allowing for easier
debugging.

The Protocol implementation internally uses custom DataStream class instead of
QDataStream, because QDataStream does not handle reading past the end of buffered
data. The custom DataStream serializers for common Qt types and containers are
based on the original Qt serializers for QDataStream, but simplified (no backwards
compatibility with older versions of Qt, no byte-swapping for endianity), but
unlike QDataStream the deserializers always call QIODevice::bytesAvailable() to
ensure enough data are buffered to succesfully deserialize the data. It will
call QIODevice::waitForReadyRead() if not enough data is buffered. This means
that deserialization of Protocol Commands is potentially blocking.

Some additional changes to the protocol are in order, most notably removing
stateful SELECT (permanent collection session context), but those can happen
later.

We don't have any real benchmarks to objectively measure the performance changes,
but subjectively it is faster, best observed on large FETCHes or ItemSyncs.
parents 118d6d3c b415b881
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment