Ankusa.Storage.Index (ankusa v0.7.0)

Copy Markdown View Source

The index object beside a segment: %{event_id => {offset, length, seq}}.

Format 1

"ANKIDX" <> <<version::8, count::32>>   (11 bytes)
:erlang.term_to_binary(index)
sha256(everything above)                (32 bytes)

The term is decoded with binary_to_term(bin, [:safe]), so an object that names an atom this node has never seen, or carries a fun or a pid, is refused rather than executed or interned, and the decoded shape is checked (binary ids to three non-negative integers, as many as count says) before anything else sees it.

Format 0

The bare term_to_binary map the compactor wrote before the header existed. It is read the same way ([:safe] and the shape check), so legacy segments stay readable and a hostile or damaged one is {:error, :bad_index}.

Summary

Functions

Decode an index object of either format: {:ok, index}, or {:error, :bad_index | :unsupported_format | :sha_mismatch}.

Encode index (%{id => {offset, length, seq}}) as a format 1 object.

Where an index ends: the end of the last frame, the position the trailer starts at.

The lowest and highest event id of an index: {min_id, max_id}.

Types

t()

@type t() :: %{
  optional(String.t()) => {non_neg_integer(), pos_integer(), pos_integer()}
}

Functions

decode(object)

@spec decode(binary()) :: {:ok, t()} | {:error, atom()}

Decode an index object of either format: {:ok, index}, or {:error, :bad_index | :unsupported_format | :sha_mismatch}.

encode(index)

@spec encode(t()) :: binary()

Encode index (%{id => {offset, length, seq}}) as a format 1 object.

frames_end(index)

@spec frames_end(t()) :: non_neg_integer()

Where an index ends: the end of the last frame, the position the trailer starts at.

id_range(index)

@spec id_range(t()) :: {String.t(), String.t()}

The lowest and highest event id of an index: {min_id, max_id}.