Кэширование страниц, определяемое приложением
Кэширование страниц, определяемое приложением.
typedef struct sqlite3_pcache_methods2 sqlite3_pcache_methods2;
struct sqlite3_pcache_methods2 {
int iVersion;
void *pArg;
int (*xInit)(void*);
void (*xShutdown)(void*);
sqlite3_pcache *(*xCreate)(int szPage, int szExtra, int bPurgeable);
void (*xCachesize)(sqlite3_pcache*, int nCachesize);
int (*xPagecount)(sqlite3_pcache*);
sqlite3_pcache_page *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag);
void (*xUnpin)(sqlite3_pcache*, sqlite3_pcache_page*, int discard);
void (*xRekey)(sqlite3_pcache*, sqlite3_pcache_page*,
unsigned oldKey, unsigned newKey);
void (*xTruncate)(sqlite3_pcache*, unsigned iLimit);
void (*xDestroy)(sqlite3_pcache*);
void (*xShrink)(sqlite3_pcache*);
};
Интерфейс sqlite3_config(SQLITE_CONFIG_PCACHE2, ...) может зарегистрировать альтернативную реализацию кэша страниц, передав экземпляр структуры sqlite3_pcache_methods2. Во многих приложениях большая часть памяти кучи, выделенной SQLite, используется для кэширования страниц. Реализовав пользовательский кэш страниц с помощью этого API, приложение может лучше контролировать объём памяти, потребляемой SQLite, способ её выделения и освобождения, а также политики, определяющие, какие части файла базы данных кэшируются и на какой срок.
Механизм альтернативного кэширования страниц — это крайняя мера, необходимая только для самых требовательных приложений. Для большинства случаев рекомендуется встроенный кэш страниц.
SQLite копирует содержимое структуры sqlite3_pcache_methods2 во внутренний буфер внутри вызова sqlite3_config. Следовательно, приложение может удалить параметр после возврата вызова sqlite3_config().
Метод xInit() вызывается один раз для каждого эффективного вызова sqlite3_initialize() (обычно только один раз за время существования процесса). Методу xInit() передаётся копия значения sqlite3_pcache_methods2.pArg. Цель метода xInit() — настроить глобальные структуры данных, необходимые для реализации пользовательского кэша страниц. Если метод xInit() равен NULL, используется встроенный кэш страниц по умолчанию вместо кэша, определяемого приложением.
Метод xShutdown() вызывается методом sqlite3_shutdown(). Он может использоваться для очистки любых открытых ресурсов перед завершением процесса, если это необходимо. Метод xShutdown() может быть равен NULL.
SQLite автоматически сериализует вызовы к методу xInit, поэтому метод xInit не обязательно должен быть потокобезопасным. Метод xShutdown вызывается только из sqlite3_shutdown(), поэтому он также не обязательно должен быть потокобезопасным. Все остальные методы должны быть потокобезопасными в многопоточных приложениях.
SQLite никогда не вызовет xInit() более одного раза без предшествующего вызова xShutdown().
SQLite вызывает метод xCreate() для создания нового экземпляра кэша. SQLite обычно создаёт один экземпляр кэша для каждого открытого файла базы данных, хотя это не гарантируется. Первый параметр, szPage, представляет собой размер страниц в байтах, которые должны быть выделены кэшем. szPage всегда является степенью двойки. Второй параметр szExtra — это количество байтов дополнительного хранилища, связанного с каждым элементом кэша страниц. Параметр szExtra будет числом, меньшим 250. SQLite будет использовать дополнительные szExtra байты на каждой странице для хранения метаданных о базовой странице базы данных на диске. Значение, передаваемое в szExtra, зависит от версии SQLite, целевой платформы и способа компиляции SQLite. Третий аргумент метода xCreate(), bPurgeable, равен true, если создаваемый кэш будет использоваться для кэширования страниц файла базы данных, хранящегося на диске, или false, если он используется для базы данных в памяти. Реализация кэша не должна делать ничего особенного в зависимости от значения bPurgeable; оно является только рекомендательным. В кэше, где bPurgeable равен false, SQLite никогда не вызовет xUnpin(), за исключением преднамеренной удаления страницы. Другими словами, вызовы xUnpin() в кэше с bPurgeable, установленным в false, всегда будут иметь флаг «удаления», установленный в true. Следовательно, кэш, созданный с bPurgeable, равным false, никогда не будет содержать каких-либо не закреплённых страниц.
Метод xCachesize() может быть вызван SQLite в любое время для установки рекомендуемого максимального размера кэша (числа страниц, хранимых в) экземпляре кэша, переданном в качестве первого аргумента. Это значение настраивается с помощью команды SQLite "PRAGMA cache_size". Как и параметр bPurgeable, реализация не обязана выполнять какие-либо действия с этим значением; оно является только рекомендательным.
Метод xPagecount() должен возвращать количество страниц, хранящихся в кэше, как закреплённых, так и не закреплённых.
Метод xFetch() ищет страницу в кэше и возвращает указатель на объект sqlite3_pcache_page, связанный с этой страницей, или нулевой указатель. Элемент pBuf возвращённого объекта sqlite3_pcache_page будет указателем на буфер размером szPage байт, используемый для хранения содержимого одной страницы базы данных. Элемент pExtra объекта sqlite3_pcache_page будет указателем на szExtra байты дополнительного хранилища, запрошенного SQLite для каждого элемента кэша страниц.
Страница, подлежащая извлечению, определяется ключом. Минимальное значение ключа — 1. После извлечения с помощью xFetch страница считается «закреплённой».
Если запрашиваемая страница уже находится в кэше страниц, то реализация кэша страниц должна вернуть указатель на буфер страницы с её содержимым без изменений. Если запрашиваемая страница ещё не находится в кэше, то реализация кэша должна использовать значение параметра createFlag, чтобы определить, какие действия предпринять:
| createFlag | Поведение, когда страница ещё не находится в кэше |
|---|---|
| 0 | Не выделять новую страницу. Вернуть NULL. |
| 1 | Выделить новую страницу, если это легко и удобно. В противном случае вернуть NULL. |
| 2 | Постараться выделить новую страницу. Вернуть NULL только если выделение новой страницы невозможно. |
SQLite обычно вызывает xFetch() с createFlag 0 или 1. SQLite будет использовать createFlag 2 только после предыдущего вызова с createFlag 1, который завершился неудачей. Между вызовами xFetch() SQLite может попытаться открепить одну или несколько страниц кэша, выгрузив содержимое закреплённых страниц на диск и синхронизируя кэш диска операционной системы.
xUnpin() вызывается SQLite с указателем на текущую закреплённую страницу в качестве второго аргумента. Если третий параметр, discard, имеет ненулевое значение, страница должна быть удалена из кэша. Если параметр discard равен нулю, то страница может быть удалена или сохранена по усмотрению реализации кэша страниц. Реализация кэша страниц может выбирать время для удаления не закреплённых страниц.
Кэш не должен выполнять подсчёт ссылок. Один вызов xUnpin() открепляет страницу независимо от числа предыдущих вызовов xFetch().
Метод xRekey() используется для изменения значения ключа, связанного со страницей, переданной в качестве второго аргумента. Если кэш ранее содержал запись, связанную с newKey, он должен быть удалён. Любая предыдущая запись кэша, связанная с newKey, гарантированно не будет закреплена.
Когда SQLite вызывает метод xTruncate(), кэш должен удалить все существующие записи кэша со номерами страниц (ключами), большими или равными значению параметра iLimit, переданного в xTruncate(). Если какие-либо из этих страниц закреплены, они неявно открепляются, что означает, что их можно безопасно удалить.
Метод xDestroy() используется для удаления кэша, выделенного методом xCreate(). Все ресурсы, связанные с указанным кэшем, должны быть освобождены. После вызова метода xDestroy() SQLite считает обработку sqlite3_pcache* недействительной и не будет использовать её с другими функциями sqlite3_pcache_methods2.
SQLite вызывает метод xShrink(), когда он хочет, чтобы кэш страниц освободил как можно больше памяти кучи. Реализация кэша страниц не обязана освобождать какую-либо память, но хорошо написанные реализации должны сделать всё возможное.
См. также списки Объектов, Констант и Функций.
SQLite is in the Public Domain.
https://sqlite.org/c3ref/pcache_methods2.html