Trying to standardise binary manipulation of value

Looking into theory that use of term_to_binary is imperfect.  Also may
be better to compress values only when they are compacted?
This commit is contained in:
martinsumner 2017-03-20 15:43:54 +00:00
parent 0cdc0eb558
commit f3ffa920af
4 changed files with 230 additions and 112 deletions

View file

@ -52,7 +52,8 @@
compact_inkerkvc/2,
split_inkvalue/1,
check_forinkertype/2,
create_value_for_journal/1,
maybe_compress/1,
create_value_for_journal/2,
build_metadata_object/2,
generate_ledgerkv/5,
get_size/2,
@ -185,20 +186,92 @@ to_inkerkv(LedgerKey, SQN, to_fetch, null) ->
{{SQN, ?INKT_STND, LedgerKey}, null, true};
to_inkerkv(LedgerKey, SQN, Object, KeyChanges) ->
InkerType = check_forinkertype(LedgerKey, Object),
Value = create_value_for_journal({Object, KeyChanges}),
Value = create_value_for_journal({Object, KeyChanges}, false),
{{SQN, InkerType, LedgerKey}, Value}.
%% Used when fetching objects, so only handles standard, hashable entries
from_inkerkv(Object) ->
case Object of
{{SQN, ?INKT_STND, PK}, Bin} when is_binary(Bin) ->
{{SQN, PK}, binary_to_term(Bin)};
{{SQN, PK}, revert_value_from_journal(Bin)};
{{SQN, ?INKT_STND, PK}, Term} ->
{{SQN, PK}, Term};
_ ->
Object
end.
create_value_for_journal({Object, KeyChanges}, Compress) ->
KeyChangeBin = term_to_binary(KeyChanges, [compressed]),
KeyChangeBinLen = byte_size(KeyChangeBin),
ObjectBin = serialise_object(Object, Compress),
TypeCode = encode_valuetype(is_binary(Object), Compress),
<<ObjectBin/binary,
KeyChangeBin/binary,
KeyChangeBinLen:32/integer,
TypeCode:8/integer>>.
maybe_compress({null, KeyChanges}) ->
create_value_for_journal({null, KeyChanges}, false);
maybe_compress(JournalBin) ->
Length0 = byte_size(JournalBin) - 1,
<<JBin0:Length0/binary, Type:8/integer>> = JournalBin,
{IsBinary, IsCompressed} = decode_valuetype(Type),
case IsCompressed of
true ->
JournalBin;
false ->
V0 = revert_value_from_journal(JBin0, Length0, IsBinary, false),
create_value_for_journal(V0, true)
end.
serialise_object(Object, false) when is_binary(Object) ->
Object;
serialise_object(Object, true) when is_binary(Object) ->
zlib:compress(Object);
serialise_object(Object, false) ->
term_to_binary(Object);
serialise_object(Object, true) ->
term_to_binary(Object, [compressed]).
revert_value_from_journal(JournalBin) ->
Length0 = byte_size(JournalBin) - 1,
<<JBin0:Length0/binary, Type:8/integer>> = JournalBin,
{IsBinary, IsCompressed} = decode_valuetype(Type),
revert_value_from_journal(JBin0, Length0, IsBinary, IsCompressed).
revert_value_from_journal(ValueBin, ValueLen, IsBinary, IsCompressed) ->
Length1 = ValueLen - 4,
<<JBin1:Length1/binary, KeyChangeLength:32/integer>> = ValueBin,
Length2 = Length1 - KeyChangeLength,
<<OBin2:Length2/binary, KCBin2:KeyChangeLength/binary>> = JBin1,
{deserialise_object(OBin2, IsBinary, IsCompressed),
binary_to_term(KCBin2)}.
deserialise_object(Binary, true, true) ->
zlib:uncompress(Binary);
deserialise_object(Binary, true, false) ->
Binary;
deserialise_object(Binary, false, _) ->
binary_to_term(Binary).
encode_valuetype(IsBinary, IsCompressed) ->
Bit2 =
case IsBinary of
true -> 2;
false -> 0
end,
Bit1 =
case IsCompressed of
true -> 1;
false -> 0
end,
Bit1 + Bit2.
decode_valuetype(TypeInt) ->
IsCompressed = TypeInt band 1 == 1,
IsBinary = TypeInt band 2 == 2,
{IsBinary, IsCompressed}.
from_journalkey({SQN, _Type, LedgerKey}) ->
{SQN, LedgerKey}.
@ -220,7 +293,7 @@ compact_inkerkvc({{SQN, ?INKT_STND, LK}, V, CrcCheck}, Strategy) ->
skip ->
skip;
retain ->
{_V, KeyDeltas} = split_inkvalue(V),
{_V, KeyDeltas} = revert_value_from_journal(V),
{retain, {{SQN, ?INKT_KEYD, LK}, {null, KeyDeltas}, CrcCheck}};
TagStrat ->
{TagStrat, null}
@ -245,7 +318,7 @@ get_tagstrategy(LK, Strategy) ->
split_inkvalue(VBin) ->
case is_binary(VBin) of
true ->
binary_to_term(VBin);
revert_value_from_journal(VBin);
false ->
VBin
end.
@ -255,14 +328,6 @@ check_forinkertype(_LedgerKey, delete) ->
check_forinkertype(_LedgerKey, _Object) ->
?INKT_STND.
create_value_for_journal(Value) ->
case Value of
{Object, KeyChanges} ->
term_to_binary({Object, KeyChanges}, [compressed]);
Value when is_binary(Value) ->
Value
end.
hash(Obj) ->
erlang:phash2(term_to_binary(Obj)).