/
smychkov
/
SStorage
Обзор
Документация
Войти
/
smychkov
/
SStorage
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/sstable/sstable_reader.hpp
128 строк
5 KB
Андрей Смычков
security: комплексные фиксы по результатам аудита
25 апр 2026, 10:00
25 апр 2026, 10:00
5f1be8e
Код
Авторство
О чём код?
#ifndef SSTORAGE_SSTABLE_SSTABLE_READER_HPP #define SSTORAGE_SSTABLE_SSTABLE_READER_HPP //============================================================================ // SSTableReader — чтение SSTable-файла //============================================================================ // При open(): // - читаем последние 64 байта → Footer (валидируем magic + CRC) // - читаем index block → в память // - читаем Bloom filter → в память // - data blocks читаются по требованию в find()/scan() // // find(key): // 1. Проверка диапазона [minKey, maxKey] // 2. Bloom filter (99% отсечение несуществующих ключей) // 3. Бинпоиск в index → нужный блок // 4. Чтение блока (возможно из BlockCache) // 5. Бинпоиск внутри блока (или линейный, блок маленький) // // scan(from, to): // 1. lower_bound в index → первый блок // 2. Последовательное чтение блоков пока lastKey <= to // 3. Фильтрация записей по диапазону //============================================================================ #include "bloom.hpp" #include "footer.hpp" #include "../core/record.hpp" #include <cstdint> #include <memory> #include <optional> #include <string> #include <vector> namespace sstorage { class SSTableReader { public: explicit SSTableReader(std::string path); ~SSTableReader(); // Открыть файл и прочитать footer/index/bloom в память. // @return true при успехе (valid footer, прошедший CRC) bool open(); // Найти запись по ключу. Возвращает запись (включая tombstone) или nullopt. std::optional<Record> find(const std::string& key) const; // Диапазонный запрос: все записи с fromKey <= key <= toKey. // Результат отсортирован по key ASC. std::vector<Record> scan(const std::string& fromKey, const std::string& toKey, size_t limit = 0) const; // Прочитать все записи из файла (для compaction). // ВНИМАНИЕ: загружает весь SSTable в память. Для больших файлов // используйте BlockIterator (streaming). std::vector<Record> readAll() const; //------------------------------------------------------------------ // Количество data-блоков в файле (для streaming iterator) //------------------------------------------------------------------ size_t blockCount() const; //------------------------------------------------------------------ // Загрузить data-блок по индексу (public-версия для итератора). // Используется MergingIterator во время compaction чтобы читать // блоки по требованию вместо загрузки всех записей в память. //------------------------------------------------------------------ bool loadBlockAt(size_t idx, std::vector<Record>& out) const; //------------------------------------------------------------------ // Метаданные //------------------------------------------------------------------ const std::string& path() const { return path_; } const std::string& minKey() const { return minKey_; } const std::string& maxKey() const { return maxKey_; } uint64_t numRecords() const { return footer_.numRecords; } // Пересекается ли диапазон этого SSTable с [from, to] bool overlaps(const std::string& from, const std::string& to) const; // Может ли содержать этот ключ (быстрая проверка: range + bloom) bool mayContain(const std::string& key) const; private: //------------------------------------------------------------------ // Index entry: (lastKeyOfBlock, blockOffset, blockSize) //------------------------------------------------------------------ struct IndexEntry { std::string lastKey; uint64_t blockOffset; uint64_t blockSize; }; // Прочитать footer (последние 64 байта файла). bool readFooter(); // Прочитать и распарсить index block. bool readIndex(); // Прочитать и распарсить bloom filter. bool readBloom(); // Загрузить data block по индексу (возвращает распарсенные записи). // @param idx — индекс в indexEntries_ bool loadBlock(size_t idx, std::vector<Record>& out) const; // Найти индекс первого блока, где lastKey >= key. // @return индекс или indexEntries_.size() если не найдено size_t findBlockIndex(const std::string& key) const; std::string path_; int fd_ = -1; uint64_t fileSize_ = 0; Footer footer_; BloomFilter bloom_; std::vector<IndexEntry> indexEntries_; std::string minKey_; std::string maxKey_; bool opened_ = false; }; } #endif