#ifndef UDS_VOLUME_INDEX_H
#define UDS_VOLUME_INDEX_H
#include <linux/limits.h>
#include "thread-utils.h"
#include "config.h"
#include "delta-index.h"
#include "indexer.h"
#define NO_CHAPTER U64_MAX
struct volume_index_stats {
ktime_t rebalance_time;
u32 rebalance_count;
u64 record_count;
u64 collision_count;
u64 discard_count;
u64 overflow_count;
u32 delta_lists;
u64 early_flushes;
};
struct volume_sub_index_zone {
u64 virtual_chapter_low;
u64 virtual_chapter_high;
u64 early_flushes;
} __aligned(L1_CACHE_BYTES);
struct volume_sub_index {
struct delta_index delta_index;
u64 *flush_chapters;
struct volume_sub_index_zone *zones;
u64 volume_nonce;
u64 chapter_zone_bits;
u64 max_zone_bits;
u8 address_bits;
u32 address_mask;
u8 chapter_bits;
u32 chapter_mask;
u32 chapter_count;
u32 list_count;
unsigned int zone_count;
u64 memory_size;
};
struct volume_index_zone {
struct mutex hook_mutex;
} __aligned(L1_CACHE_BYTES);
struct volume_index {
u32 sparse_sample_rate;
unsigned int zone_count;
u64 memory_size;
struct volume_sub_index vi_non_hook;
struct volume_sub_index vi_hook;
struct volume_index_zone *zones;
};
struct volume_index_record {
u64 virtual_chapter;
bool is_collision;
bool is_found;
unsigned int zone_number;
struct volume_sub_index *sub_index;
struct mutex *mutex;
const struct uds_record_name *name;
struct delta_index_entry delta_entry;
};
int __must_check uds_make_volume_index(const struct uds_configuration *config,
u64 volume_nonce,
struct volume_index **volume_index);
void uds_free_volume_index(struct volume_index *volume_index);
int __must_check uds_compute_volume_index_save_blocks(const struct uds_configuration *config,
size_t block_size,
u64 *block_count);
unsigned int __must_check uds_get_volume_index_zone(const struct volume_index *volume_index,
const struct uds_record_name *name);
bool __must_check uds_is_volume_index_sample(const struct volume_index *volume_index,
const struct uds_record_name *name);
u64 __must_check uds_lookup_volume_index_name(const struct volume_index *volume_index,
const struct uds_record_name *name);
int __must_check uds_get_volume_index_record(struct volume_index *volume_index,
const struct uds_record_name *name,
struct volume_index_record *record);
int __must_check uds_put_volume_index_record(struct volume_index_record *record,
u64 virtual_chapter);
int __must_check uds_remove_volume_index_record(struct volume_index_record *record);
int __must_check uds_set_volume_index_record_chapter(struct volume_index_record *record,
u64 virtual_chapter);
void uds_set_volume_index_open_chapter(struct volume_index *volume_index,
u64 virtual_chapter);
void uds_set_volume_index_zone_open_chapter(struct volume_index *volume_index,
unsigned int zone_number,
u64 virtual_chapter);
int __must_check uds_load_volume_index(struct volume_index *volume_index,
struct buffered_reader **readers,
unsigned int reader_count);
int __must_check uds_save_volume_index(struct volume_index *volume_index,
struct buffered_writer **writers,
unsigned int writer_count);
void uds_get_volume_index_stats(const struct volume_index *volume_index,
struct volume_index_stats *stats);
#endif