Ferricstore.Bitcask.NIF (ferricstore v0.4.3)

Copy Markdown View Source

Rustler NIF bindings for Bitcask record I/O, hint files, and mmap-backed probabilistic data structure file operations.

Summary

Functions

Does the path exist? Follows symlinks (broken symlink → false). Never returns an error for the common kinds (missing, no-permission).

Is the path a directory? Follows symlinks. Returns false for missing paths (matches File.dir?/1).

List the entries in a directory (names only, no path prefix). Yields every 256 entries to keep BEAM reductions accurate on huge directories.

Recursive mkdir -p. Idempotent when the directory already exists. Equivalent to File.mkdir_p/1.

Atomic rename. On POSIX, rename replaces the target atomically. Cross-device renames return {:error, {:other, _}} — caller must handle with copy+remove.

Remove a single file. Use fs_rm_rf_async/3 for directory trees.

Async recursive remove. Runs on the Tokio blocking pool; sends {:tokio_complete, correlation_id, :ok} or {:tokio_complete, correlation_id, :error, {kind, msg}} to the caller on completion. Idempotent: removing a non-existent path sends :ok.

Creates an empty file if it does not exist. Idempotent on an existing file (does not truncate). Equivalent to File.touch!/1 without the timestamp update (matches our callers' usage).

Fsyncs a directory so that recent File.rename/2, File.rm/1, File.touch!/1, or File.create/1 operations on files inside it are durable. Use after any namespace mutation that must survive a kernel panic — rotation, compaction rename, hint-file creation, prob-file create/delete, shard init.

Types

append_op()

@type append_op() ::
  {:put, binary(), binary(), non_neg_integer()} | {:delete, binary()}

append_op_location()

@type append_op_location() ::
  {:put, non_neg_integer(), non_neg_integer()}
  | {:delete, non_neg_integer(), non_neg_integer()}

flow_index_claim_entry()

@type flow_index_claim_entry() ::
  {binary(), binary(), float(), binary(), float(), binary(), float(), binary(),
   float(), binary(), binary(), float()}

flow_index_resource()

@type flow_index_resource() :: reference()

flow_record_claim_history_entry()

@type flow_record_claim_history_entry() ::
  {binary(), binary(), non_neg_integer(), non_neg_integer(), binary(), binary(),
   non_neg_integer() | nil, non_neg_integer() | nil, boolean()}

flow_record_claim_history_plan()

@type flow_record_claim_history_plan() ::
  {binary(), flow_index_claim_entry(), binary(), non_neg_integer() | nil,
   flow_record_claim_history_entry()}

flow_record_claim_plan()

@type flow_record_claim_plan() ::
  {binary(), flow_index_claim_entry(), binary(), non_neg_integer() | nil}

fs_error()

@type fs_error() :: {:error, {atom(), binary()}}

lmdb_op()

@type lmdb_op() ::
  {:put, binary(), binary()}
  | {:put_new, binary(), binary()}
  | {:delete, binary()}

lmdb_original()

@type lmdb_original() :: {binary(), :missing | {:value, binary()}}

pread_batch_result()

@type pread_batch_result() :: [pread_batch_value()]

pread_batch_value()

@type pread_batch_value() :: binary() | nil | {:error, binary()}

Functions

bloom_file_add(path, element)

@spec bloom_file_add(binary(), binary()) :: :ok | {:error, term()}

bloom_file_card(path)

@spec bloom_file_card(binary()) :: {:ok, non_neg_integer()} | {:error, term()}

bloom_file_card_async(caller_pid, correlation_id, path)

@spec bloom_file_card_async(pid(), term(), binary()) :: :ok | {:error, term()}

bloom_file_create(path, num_bits, num_hashes)

@spec bloom_file_create(binary(), non_neg_integer(), non_neg_integer()) ::
  :ok | {:error, term()}

bloom_file_exists(path, element)

@spec bloom_file_exists(binary(), binary()) :: {:ok, boolean()} | {:error, term()}

bloom_file_exists_async(caller_pid, correlation_id, path, element)

@spec bloom_file_exists_async(pid(), term(), binary(), binary()) ::
  :ok | {:error, term()}

bloom_file_info(path)

@spec bloom_file_info(binary()) ::
  {:ok, {non_neg_integer(), non_neg_integer(), non_neg_integer()}}
  | {:error, term()}

bloom_file_info_async(caller_pid, correlation_id, path)

@spec bloom_file_info_async(pid(), term(), binary()) :: :ok | {:error, term()}

bloom_file_madd(path, elements)

@spec bloom_file_madd(binary(), [binary()]) :: :ok | {:error, term()}

bloom_file_mexists(path, elements)

@spec bloom_file_mexists(binary(), [binary()]) ::
  {:ok, [boolean()]} | {:error, term()}

bloom_file_mexists_async(caller_pid, correlation_id, path, elements)

@spec bloom_file_mexists_async(pid(), term(), binary(), [binary()]) ::
  :ok | {:error, term()}

cms_file_create(path, width, depth)

@spec cms_file_create(binary(), non_neg_integer(), non_neg_integer()) ::
  :ok | {:error, term()}

cms_file_incrby(path, items)

@spec cms_file_incrby(binary(), [{binary(), non_neg_integer()}]) ::
  :ok | {:error, term()}

cms_file_info(path)

@spec cms_file_info(binary()) ::
  {:ok, {non_neg_integer(), non_neg_integer(), non_neg_integer()}}
  | {:error, term()}

cms_file_info_async(caller_pid, correlation_id, path)

@spec cms_file_info_async(pid(), term(), binary()) :: :ok | {:error, term()}

cms_file_merge(dst_path, src_paths, weights)

@spec cms_file_merge(binary(), [binary()], [number()]) :: :ok | {:error, term()}

cms_file_query(path, elements)

@spec cms_file_query(binary(), [binary()]) ::
  {:ok, [non_neg_integer()]} | {:error, term()}

cms_file_query_async(caller_pid, correlation_id, path, elements)

@spec cms_file_query_async(pid(), term(), binary(), [binary()]) ::
  :ok | {:error, term()}

cuckoo_file_add(path, element)

@spec cuckoo_file_add(binary(), binary()) :: :ok | {:error, term()}

cuckoo_file_addnx(path, element)

@spec cuckoo_file_addnx(binary(), binary()) :: {:ok, boolean()} | {:error, term()}

cuckoo_file_count(path, element)

@spec cuckoo_file_count(binary(), binary()) ::
  {:ok, non_neg_integer()} | {:error, term()}

cuckoo_file_count_async(caller_pid, correlation_id, path, element)

@spec cuckoo_file_count_async(pid(), term(), binary(), binary()) ::
  :ok | {:error, term()}

cuckoo_file_create(path, capacity, bucket_size)

@spec cuckoo_file_create(binary(), non_neg_integer(), non_neg_integer()) ::
  :ok | {:error, term()}

cuckoo_file_del(path, element)

@spec cuckoo_file_del(binary(), binary()) :: :ok | {:error, term()}

cuckoo_file_exists(path, element)

@spec cuckoo_file_exists(binary(), binary()) :: {:ok, boolean()} | {:error, term()}

cuckoo_file_exists_async(caller_pid, correlation_id, path, element)

@spec cuckoo_file_exists_async(pid(), term(), binary(), binary()) ::
  :ok | {:error, term()}

cuckoo_file_info(path)

@spec cuckoo_file_info(binary()) :: {:ok, tuple()} | {:error, term()}

cuckoo_file_info_async(caller_pid, correlation_id, path)

@spec cuckoo_file_info_async(pid(), term(), binary()) :: :ok | {:error, term()}

cuckoo_file_mexists(path, elements)

@spec cuckoo_file_mexists(binary(), [binary()]) ::
  {:ok, [boolean()]} | {:error, term()}

cuckoo_file_mexists_async(caller_pid, correlation_id, path, elements)

@spec cuckoo_file_mexists_async(pid(), term(), binary(), [binary()]) ::
  :ok | {:error, term()}

flow_history_decode(value)

@spec flow_history_decode(binary()) :: {:ok, list()} | :error

flow_history_encode(event, version, now_ms, id, type, state, priority, attempts, fencing_token, created_at_ms, updated_at_ms, next_run_at_ms, lease_deadline_ms, lease_owner, payload_ref, parent_flow_id, root_flow_id, correlation_id, result_ref, error_ref, rewound_to_event_id, meta_encoded)

@spec flow_history_encode(
  binary(),
  non_neg_integer() | nil,
  non_neg_integer() | nil,
  binary() | nil,
  binary() | nil,
  binary() | nil,
  non_neg_integer() | nil,
  non_neg_integer() | nil,
  non_neg_integer() | nil,
  non_neg_integer() | nil,
  non_neg_integer() | nil,
  non_neg_integer() | nil,
  non_neg_integer() | nil,
  binary() | nil,
  binary() | nil,
  binary() | nil,
  binary() | nil,
  binary() | nil,
  binary() | nil,
  binary() | nil,
  binary() | nil,
  binary()
) :: binary()

flow_index_apply_batch(resource, put_entries, put_new_entries, move_entries, delete_entries, claim_entries)

@spec flow_index_apply_batch(
  flow_index_resource(),
  [{binary(), binary(), float()}],
  [{binary(), binary(), float()}],
  [{binary(), binary(), binary(), float()}],
  [{binary(), [binary()]}],
  [flow_index_claim_entry()]
) :: :ok

flow_index_apply_claim_entries(resource, entries)

@spec flow_index_apply_claim_entries(flow_index_resource(), [flow_index_claim_entry()]) ::
  :ok

flow_index_claim_due_candidates(resource, keys, max_score, limit, max_scan)

@spec flow_index_claim_due_candidates(
  flow_index_resource(),
  [binary()],
  float(),
  non_neg_integer(),
  non_neg_integer()
) :: [{binary(), [{binary(), float()}]}]

flow_index_count_all(resource, key)

@spec flow_index_count_all(flow_index_resource(), binary()) :: non_neg_integer()

flow_index_count_keys(resource)

@spec flow_index_count_keys(flow_index_resource()) :: [binary()]

flow_index_count_many(resource, keys)

@spec flow_index_count_many(flow_index_resource(), [binary()]) :: [non_neg_integer()]

flow_index_delete_count(resource, key)

@spec flow_index_delete_count(flow_index_resource(), binary()) :: :ok

flow_index_delete_entries(resource, entries)

@spec flow_index_delete_entries(flow_index_resource(), [{binary(), binary()}]) :: :ok

flow_index_delete_members(resource, key, members)

@spec flow_index_delete_members(flow_index_resource(), binary(), [binary()]) :: :ok

flow_index_due_count_keys(resource)

@spec flow_index_due_count_keys(flow_index_resource()) :: [binary()]

flow_index_due_keys_present(resource, keys, max_score)

@spec flow_index_due_keys_present(flow_index_resource(), [binary()], float()) :: [
  binary()
]

flow_index_move_entries(resource, entries)

@spec flow_index_move_entries(flow_index_resource(), [
  {binary(), binary(), binary(), float()}
]) :: :ok

flow_index_new()

@spec flow_index_new() :: flow_index_resource()

flow_index_put_entries(resource, entries)

@spec flow_index_put_entries(flow_index_resource(), [{binary(), binary(), float()}]) ::
  :ok

flow_index_put_new_entries(resource, entries)

@spec flow_index_put_new_entries(flow_index_resource(), [
  {binary(), binary(), float()}
]) :: :ok

flow_index_range_slice(resource, key, min_kind, min_score, max_kind, max_score, reverse?, offset, count)

@spec flow_index_range_slice(
  flow_index_resource(),
  binary(),
  non_neg_integer(),
  float(),
  non_neg_integer(),
  float(),
  boolean(),
  non_neg_integer(),
  integer()
) :: [{binary(), float()}]

flow_index_restore_count(resource, key, count)

@spec flow_index_restore_count(flow_index_resource(), binary(), integer()) :: :ok

flow_index_rollback_claim_entries(resource, entries)

@spec flow_index_rollback_claim_entries(flow_index_resource(), [
  flow_index_claim_entry()
]) :: :ok

flow_index_score_of(resource, key, member)

@spec flow_index_score_of(flow_index_resource(), binary(), binary()) ::
  {:ok, float()} | :miss

flow_index_take_due(resource, key, max_score, count)

@spec flow_index_take_due(
  flow_index_resource(),
  binary(),
  float(),
  non_neg_integer()
) :: [{binary(), float()}]

flow_record_decode(value)

@spec flow_record_decode(binary()) :: {:ok, list()} | :error

flow_record_encode(id, type, state, version, attempts, fencing_token, created_at_ms, updated_at_ms, next_run_at_ms, priority, ttl_ms, history_hot_max_events, history_max_events, retention_ttl_ms, terminal_retention_until_ms, partition_key, payload_ref, parent_flow_id, parent_partition_key, root_flow_id, correlation_id, result_ref, error_ref, lease_owner, lease_token, lease_deadline_ms, run_state, rewound_to_event_id, child_groups_encoded)

@spec flow_record_encode(
  binary() | nil,
  binary() | nil,
  binary() | nil,
  non_neg_integer() | nil,
  non_neg_integer() | nil,
  non_neg_integer() | nil,
  non_neg_integer() | nil,
  non_neg_integer() | nil,
  non_neg_integer() | nil,
  non_neg_integer() | nil,
  non_neg_integer() | nil,
  non_neg_integer() | nil,
  non_neg_integer() | nil,
  non_neg_integer() | nil,
  non_neg_integer() | nil,
  binary() | nil,
  binary() | nil,
  binary() | nil,
  binary() | nil,
  binary() | nil,
  binary() | nil,
  binary() | nil,
  binary() | nil,
  binary() | nil,
  binary() | nil,
  non_neg_integer() | nil,
  binary() | nil,
  binary() | nil,
  binary()
) :: binary()

flow_record_plan_claims(candidates, values, type, expected_state, worker, lease_ms, now_ms, remaining, from_due_key, to_due_key, from_state_key, to_state_key, inflight_key, worker_key, state_key_prefix)

@spec flow_record_plan_claims(
  [{binary(), float()}],
  [binary() | nil],
  binary(),
  binary(),
  binary(),
  non_neg_integer(),
  non_neg_integer(),
  non_neg_integer(),
  binary(),
  binary(),
  binary(),
  binary(),
  binary(),
  binary(),
  binary()
) ::
  {:ok, [flow_record_claim_plan()], [binary()], non_neg_integer()} | :fallback

flow_record_plan_claims_with_history(candidates, values, type, expected_state, worker, lease_ms, now_ms, remaining, from_due_key, to_due_key, from_state_key, to_state_key, inflight_key, worker_key, state_key_prefix, history_key_prefix)

@spec flow_record_plan_claims_with_history(
  [{binary(), float()}],
  [binary() | nil],
  binary(),
  binary(),
  binary(),
  non_neg_integer(),
  non_neg_integer(),
  non_neg_integer(),
  binary(),
  binary(),
  binary(),
  binary(),
  binary(),
  binary(),
  binary(),
  binary()
) ::
  {:ok, [flow_record_claim_history_plan()], [binary()], non_neg_integer()}
  | :fallback

flow_records_terminal_after_noop(values)

@spec flow_records_terminal_after_noop([binary()]) :: [boolean()]

fs_exists(path)

@spec fs_exists(binary()) :: boolean()

Does the path exist? Follows symlinks (broken symlink → false). Never returns an error for the common kinds (missing, no-permission).

fs_is_dir(path)

@spec fs_is_dir(binary()) :: boolean()

Is the path a directory? Follows symlinks. Returns false for missing paths (matches File.dir?/1).

fs_ls(path)

@spec fs_ls(binary()) :: {:ok, [binary()]} | fs_error()

List the entries in a directory (names only, no path prefix). Yields every 256 entries to keep BEAM reductions accurate on huge directories.

fs_mkdir_p(path)

@spec fs_mkdir_p(binary()) :: :ok | fs_error()

Recursive mkdir -p. Idempotent when the directory already exists. Equivalent to File.mkdir_p/1.

fs_rename(old_path, new_path)

@spec fs_rename(binary(), binary()) :: :ok | fs_error()

Atomic rename. On POSIX, rename replaces the target atomically. Cross-device renames return {:error, {:other, _}} — caller must handle with copy+remove.

fs_rm(path)

@spec fs_rm(binary()) :: :ok | fs_error()

Remove a single file. Use fs_rm_rf_async/3 for directory trees.

fs_rm_rf_async(caller_pid, correlation_id, path)

@spec fs_rm_rf_async(pid(), term(), binary()) :: :ok | fs_error()

Async recursive remove. Runs on the Tokio blocking pool; sends {:tokio_complete, correlation_id, :ok} or {:tokio_complete, correlation_id, :error, {kind, msg}} to the caller on completion. Idempotent: removing a non-existent path sends :ok.

fs_touch(path)

@spec fs_touch(binary()) :: :ok | fs_error()

Creates an empty file if it does not exist. Idempotent on an existing file (does not truncate). Equivalent to File.touch!/1 without the timestamp update (matches our callers' usage).

io_uring_available()

@spec io_uring_available() :: boolean()

lmdb_clear(path, map_size)

@spec lmdb_clear(binary(), non_neg_integer()) :: :ok | {:error, term()}

lmdb_delete(path, key, map_size)

@spec lmdb_delete(binary(), binary(), non_neg_integer()) :: :ok | {:error, term()}

lmdb_get(path, key, map_size)

@spec lmdb_get(binary(), binary(), non_neg_integer()) ::
  {:ok, binary()} | :not_found | {:error, term()}

lmdb_get_many(path, keys, map_size)

@spec lmdb_get_many(binary(), [binary()], non_neg_integer()) ::
  {:ok, [{:ok, binary()} | :not_found]} | {:error, term()}

lmdb_prefix_count(path, prefix, map_size)

@spec lmdb_prefix_count(binary(), binary(), non_neg_integer()) ::
  {:ok, non_neg_integer()} | {:error, term()}

lmdb_prefix_entries(path, prefix, limit, map_size)

@spec lmdb_prefix_entries(binary(), binary(), non_neg_integer(), non_neg_integer()) ::
  {:ok, [{binary(), binary()}]} | {:error, term()}

lmdb_prefix_entries_after(path, prefix, after_key, limit, map_size)

@spec lmdb_prefix_entries_after(
  binary(),
  binary(),
  binary(),
  non_neg_integer(),
  non_neg_integer()
) :: {:ok, [{binary(), binary()}]} | {:error, term()}

lmdb_prefix_entries_reverse(path, prefix, limit, map_size)

@spec lmdb_prefix_entries_reverse(
  binary(),
  binary(),
  non_neg_integer(),
  non_neg_integer()
) ::
  {:ok, [{binary(), binary()}]} | {:error, term()}

lmdb_prefix_entries_reverse_before(path, prefix, before_key, limit, map_size)

@spec lmdb_prefix_entries_reverse_before(
  binary(),
  binary(),
  binary(),
  non_neg_integer(),
  non_neg_integer()
) :: {:ok, [{binary(), binary()}]} | {:error, term()}

lmdb_put(path, key, value, map_size)

@spec lmdb_put(binary(), binary(), binary(), non_neg_integer()) ::
  :ok | {:error, term()}

lmdb_release_all()

@spec lmdb_release_all() ::
  {:ok, non_neg_integer()} | {:busy, non_neg_integer()} | {:error, term()}

lmdb_write_batch(path, ops, map_size)

@spec lmdb_write_batch(binary(), [lmdb_op()], non_neg_integer()) ::
  :ok | {:error, term()}

lmdb_write_batch_with_originals(path, ops, map_size)

@spec lmdb_write_batch_with_originals(binary(), [lmdb_op()], non_neg_integer()) ::
  {:ok, [lmdb_original()]} | {:error, term()}

rust_allocated_bytes()

@spec rust_allocated_bytes() :: {:ok, non_neg_integer()} | {:error, term()}

topk_file_add_v2(path, elements)

@spec topk_file_add_v2(binary(), [binary()]) ::
  {:ok, [binary() | nil]} | {:error, term()}

topk_file_count_v2(path, elements)

@spec topk_file_count_v2(binary(), [binary()]) ::
  {:ok, [non_neg_integer()]} | {:error, term()}

topk_file_count_v2_async(caller_pid, correlation_id, path, elements)

@spec topk_file_count_v2_async(pid(), term(), binary(), [binary()]) ::
  :ok | {:error, term()}

topk_file_create_v2(path, k, width, depth, decay)

@spec topk_file_create_v2(
  binary(),
  non_neg_integer(),
  non_neg_integer(),
  non_neg_integer(),
  float()
) :: :ok | {:error, term()}

topk_file_incrby_v2(path, pairs)

@spec topk_file_incrby_v2(binary(), [{binary(), non_neg_integer()}]) ::
  {:ok, [binary() | nil]} | {:error, term()}

topk_file_info_v2(path)

@spec topk_file_info_v2(binary()) :: {:ok, tuple()} | {:error, term()}

topk_file_info_v2_async(caller_pid, correlation_id, path)

@spec topk_file_info_v2_async(pid(), term(), binary()) :: :ok | {:error, term()}

topk_file_list_v2(path)

@spec topk_file_list_v2(binary()) ::
  {:ok, [{binary(), non_neg_integer()}]} | {:error, term()}

topk_file_list_v2_async(caller_pid, correlation_id, path)

@spec topk_file_list_v2_async(pid(), term(), binary()) :: :ok | {:error, term()}

topk_file_query_v2(path, elements)

@spec topk_file_query_v2(binary(), [binary()]) ::
  {:ok, [boolean()]} | {:error, term()}

topk_file_query_v2_async(caller_pid, correlation_id, path, elements)

@spec topk_file_query_v2_async(pid(), term(), binary(), [binary()]) ::
  :ok | {:error, term()}

v2_append_batch(path, records)

@spec v2_append_batch(binary(), [{binary(), binary(), non_neg_integer()}]) ::
  {:ok, [{non_neg_integer(), non_neg_integer()}]} | {:error, term()}

v2_append_batch_async(caller_pid, correlation_id, path, records)

@spec v2_append_batch_async(pid(), term(), binary(), [
  {binary(), binary(), non_neg_integer()}
]) ::
  :ok | {:error, term()}

v2_append_batch_nosync(path, records)

@spec v2_append_batch_nosync(binary(), [{binary(), binary(), non_neg_integer()}]) ::
  {:ok, [{non_neg_integer(), non_neg_integer()}]} | {:error, term()}

v2_append_ops_batch_nosync(path, records)

@spec v2_append_ops_batch_nosync(binary(), [append_op()]) ::
  {:ok, [append_op_location()]} | {:error, term()}

v2_append_record(path, key, value, expire_at_ms)

@spec v2_append_record(binary(), binary(), binary(), non_neg_integer()) ::
  {:ok, {non_neg_integer(), non_neg_integer()}} | {:error, term()}

v2_append_tombstone(path, key)

@spec v2_append_tombstone(binary(), binary()) ::
  {:ok, {non_neg_integer(), non_neg_integer()}} | {:error, term()}

v2_available_disk_space(path)

@spec v2_available_disk_space(binary()) :: {:ok, non_neg_integer()} | {:error, term()}

v2_copy_records(source_path, dest_path, offsets)

@spec v2_copy_records(binary(), binary(), [non_neg_integer()]) ::
  {:ok, [{non_neg_integer(), non_neg_integer()}]} | {:error, term()}

v2_copy_records_preserve_tombstones(source_path, dest_path, live_offsets, tombstone_offsets)

@spec v2_copy_records_preserve_tombstones(binary(), binary(), [non_neg_integer()], [
  non_neg_integer()
]) ::
  {:ok, [{non_neg_integer(), non_neg_integer()}]} | {:error, term()}

v2_fsync(path)

@spec v2_fsync(binary()) :: :ok | {:error, term()}

v2_fsync_async(caller_pid, correlation_id, path)

@spec v2_fsync_async(pid(), term(), binary()) :: :ok | {:error, term()}

v2_fsync_dir(path)

@spec v2_fsync_dir(binary()) :: :ok | {:error, term()}

Fsyncs a directory so that recent File.rename/2, File.rm/1, File.touch!/1, or File.create/1 operations on files inside it are durable. Use after any namespace mutation that must survive a kernel panic — rotation, compaction rename, hint-file creation, prob-file create/delete, shard init.

Returns :ok on success or {:error, reason} where reason is a short string suitable for logging.

POSIX: file-data fsync does NOT make the filename durable; only a directory fsync does.

v2_pread_at(path, offset)

@spec v2_pread_at(binary(), non_neg_integer()) :: {:ok, binary()} | {:error, term()}

v2_pread_at_async(caller_pid, correlation_id, path, offset)

@spec v2_pread_at_async(pid(), term(), binary(), non_neg_integer()) ::
  :ok | {:error, term()}

v2_pread_at_key_async(caller_pid, correlation_id, path, offset, expected_key)

@spec v2_pread_at_key_async(pid(), term(), binary(), non_neg_integer(), binary()) ::
  :ok | {:error, term()}

v2_pread_batch(path, locations)

@spec v2_pread_batch(binary(), [non_neg_integer()]) ::
  {:ok, [binary() | nil]} | {:error, term()}

v2_pread_batch_async(caller_pid, correlation_id, locations)

@spec v2_pread_batch_async(pid(), term(), [{binary(), non_neg_integer()}]) ::
  :ok | {:error, term()}

v2_pread_batch_grouped_async(caller_pid, correlation_id, groups)

@spec v2_pread_batch_grouped_async(
  pid(),
  term(),
  [{binary(), [{non_neg_integer(), non_neg_integer()}]}]
) :: :ok | {:error, term()}

v2_pread_batch_grouped_key_async(caller_pid, correlation_id, groups)

@spec v2_pread_batch_grouped_key_async(
  pid(),
  term(),
  [{binary(), [{non_neg_integer(), non_neg_integer(), binary()}]}]
) :: :ok | {:error, term()}

v2_pread_batch_path_async(caller_pid, correlation_id, path, offsets)

@spec v2_pread_batch_path_async(pid(), term(), binary(), [non_neg_integer()]) ::
  :ok | {:error, term()}

v2_pread_batch_path_key_async(caller_pid, correlation_id, path, reads)

@spec v2_pread_batch_path_key_async(
  pid(),
  term(),
  binary(),
  [{non_neg_integer(), binary()}]
) :: :ok | {:error, term()}

v2_read_hint_file(path)

@spec v2_read_hint_file(binary()) ::
  {:ok,
   [
     {binary(), non_neg_integer(), non_neg_integer(), non_neg_integer(),
      non_neg_integer()}
   ]}
  | {:error, term()}

v2_scan_file(path)

@spec v2_scan_file(binary()) ::
  {:ok,
   [
     {binary(), non_neg_integer(), non_neg_integer(), non_neg_integer(),
      boolean()}
   ]}
  | {:error, term()}

v2_scan_file_from_offset(path, start_offset)

@spec v2_scan_file_from_offset(binary(), non_neg_integer()) ::
  {:ok,
   [
     {binary(), non_neg_integer(), non_neg_integer(), non_neg_integer(),
      boolean()}
   ]}
  | {:error, term()}

v2_scan_file_page(path, start_offset, limit)

@spec v2_scan_file_page(binary(), non_neg_integer(), pos_integer()) ::
  {:ok,
   [
     {binary(), non_neg_integer(), non_neg_integer(), non_neg_integer(),
      boolean()}
   ], non_neg_integer(), boolean()}
  | {:error, term()}

v2_scan_key_states(path, keys)

@spec v2_scan_key_states(binary(), [binary()]) ::
  {:ok, [{binary(), non_neg_integer(), boolean()}]} | {:error, term()}

v2_scan_tombstones(path)

@spec v2_scan_tombstones(binary()) ::
  {:ok, [{binary(), non_neg_integer(), non_neg_integer(), non_neg_integer()}]}
  | {:error, term()}

v2_validate_value_ref(path, offset, expected_key, expected_value_size)

@spec v2_validate_value_ref(binary(), non_neg_integer(), binary(), non_neg_integer()) ::
  {:ok, {non_neg_integer(), non_neg_integer()}} | :mismatch | {:error, term()}

v2_write_hint_file(path, entries)

@spec v2_write_hint_file(binary(), [
  {binary(), non_neg_integer(), non_neg_integer(), non_neg_integer(),
   non_neg_integer()}
]) :: :ok | {:error, term()}