Bug 2265: Use new NormalizedNode streaming in messages
Utilized the new NormalizedNode streaming classes for the WriteData,
MergeData, ReadDataReply and DataChanged messages.
One solution was to add a bytes field to the protobuff messages and
make the previous fields optional. For backwards compatibility, in
the wrapper message's fromSerializable method, check whether or not
the protobuff message has the bytes field and act accordingly.
While this works, it results in an undesirable inefficiency.
Protobuff translates the bytes field to a ByteString type. So when
streaming, we need to create a ByteArrayOutputStream and pass that to
the NormalizedNode stream writer. Then call
ByteString.copyFrom(bos.toByteArray) to get the resulting ByteString.
However this results in 2 copies of the serialized byte[]. The
byte[] cannot be passed to ByteString as is as it always copies it to
maintain immutability. I looked into subclassing ByteString and
lazily streaming the data on demand but the ByteString ctor is
package scoped so they don’t allow subclassing.
So I went with an approach to make each message Externalizable
instead of using protobuff. The classes writes
the version number to enable us to handle compatibility in the future.
So in this manner, we can get the efficient direct streaming we
want and easily handle backwards and forwards compatibility.
I added a VersionedSerializableMessage interface whose
toSerializable method takes a version number. The version # is passed
from the remote version # obtained from the CreateTransactionReply.
This allows the message classes to handle backwards compatibility. So
if the version is Helium-1 or less, send the protobuff message
otherwise send the Externalizable instance.
In the fromSerializable method, it checks if the passed Object is an
instance of the Externalizable class or the protbuff message type.
Change-Id: I5ebb968e70ac8ff92c29183c52e6c3fe5362ae34
Signed-off-by: tpantelis <[email protected]>