В предыдущем посте я сосредоточился в основном на чтении кода для записи SST на диск. Но я должен признать, что на самом деле я не следую тому, как вы читаете их так, чтобы их было легко читать.
Чтобы понять это, я думаю, что правильное место в коде будет TableCache. API для этого довольно прост, вот только заголовок (комментарии были удалены).
class TableCache { public: TableCache(const std::string& dbname, const Options* options, int entries); ~TableCache(); Iterator* NewIterator(const ReadOptions& options, uint64_t file_number, uint64_t file_size, Table** tableptr = NULL); Status Get(const ReadOptions& options, uint64_t file_number, uint64_t file_size, const Slice& k, void* arg, void (*handle_result)(void*, const Slice&, const Slice&)); void Evict(uint64_t file_number); private: Status FindTable(uint64_t file_number, uint64_t file_size, Cache::Handle**); };
Здесь есть пара интересных вещей, которые появляются сразу. Как же вы знаете , что такое количество записей. Я думаю, что это хранится внешне, но я не уверен, где. Я собираюсь выяснить этот вопрос первым.
И ответ странный:
Это не количество записей в таблице , это количество файлов? На самом деле это говорит о чем-то очень важном, поскольку это означает, что кеш таблицы читает несколько файлов SST, а не только один на кеш. Глядя на остальную часть API, это имеет еще больше смысла. Нам нужно передать номер файла, который мы собираемся прочитать. Это будет получено из версии, которую мы используем.
Примечание: я потратил около часа на настройку проекта для leveldb, чтобы я мог выполнить код и посмотреть, что он делает. Это заставило меня изучить cmake (я использую KDevelop для чтения кода), и я, наконец, получил его. До сих пор не понял , как войти в код leveldb . Но это хороший шаг.
Кроме того, опыт отладки составляет около 2/10 по сравнению с VS.
И блин, я так не разработчик C ++ больше. С другой стороны, никогда не был настоящим разработчиком Linux.
Первое, что делает TableCache, это устанавливает кеш. Это интересно, и я следовал коду, он создает 16 внутренних кэшей и имеет между ними. Я думаю, что это сделано для обеспечения параллелизма, потому что все методы внутреннего кэша выглядят так:
Обратите внимание на блокировку мьютекса. Это в значительной степени то, как это работает для всей работы кэша. Углубившись в код, я вижу еще одну причину, по которой я должен быть благодарен за то, что остался в стороне от C ++. leveldb поставляется с собственной функциональностью хэш-таблицы. В любом случае, кеш использует LRU для удаления элементов и получает количество записей из значения, которое было передано в ctor. Это заставляет меня думать, что он содержит открытые файлы.
Говоря о кеше, вот пример кода, использующего его:
Кеш также используется для кеширования блоков, поэтому он принимает в качестве аргумента срез. Я собираюсь обсудить это позже, потому что это выглядит довольно интересно. Остальная часть этого метода выглядит так:
Таким образом, единственный очень интересный бит это Table :: Open. Остальное — просто открыть файл mmap и сохранить его в кеше. Обратите внимание, что фактический размер файла передается извне. Я еще не совсем уверен, что это значит. Я рассмотрю код таблицы позже, сейчас я хочу сосредоточиться на кэше таблицы.
Просматривая интерфейс TableCache, мы видим, что мы всегда получаем размер файла извне. Это сделало меня достаточно любопытным, чтобы понять, почему. И ответ таков: у нас всегда есть это в FileMetaData, который мы ранее исследовали. Я не уверен, почему это так важно, но я пока проигнорирую это.
Остальная часть TableCache довольно проста, хотя это заставило меня улыбнуться:
Более конкретно, посмотрите на RegisterCleanup, это в основном регистрация для события удаления, чтобы они могли восстановить кэш. Довольно мило, все вокруг.
Остальная часть кода просто перенаправляет вызовы в Таблицу, поэтому я буду читать дальше