SQLite C 接口
应用程序定义的页面缓存。
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 消耗的内存量、分配和释放内存的方式,以及用于确定数据库文件的哪些部分被缓存和缓存的策略。多长时间。
替代页面缓存机制是一种极端措施,只有最苛刻的应用程序才需要。对于大多数用途,建议使用内置页面缓存。
sqlite3_pcache_methods2 结构的内容在对sqlite3_config的调用中被 SQLite 复制到内部缓冲区。因此,应用程序可能会在调用sqlite3_config()返回后丢弃该参数 。
每次有效调用sqlite3_initialize()都会 调用一次 xInit() 方法 (通常在进程的生命周期内只调用一次)。xInit() 方法传递了 sqlite3_pcache_methods2.pArg 值的副本。xInit() 方法的目的是设置自定义页面缓存实现所需的全局数据结构。如果 xInit() 方法为 NULL,则使用内置的默认页面缓存而不是应用程序定义的页面缓存。
xShutdown() 方法由sqlite3_shutdown()调用。如果需要,它可用于在进程关闭之前清理任何未完成的资源。xShutdown() 方法可能为 NULL。
SQLite 自动序列化对 xInit 方法的调用,因此 xInit 方法不需要是线程安全的。xShutdown 方法仅从sqlite3_shutdown()调用,因此它也不需要是线程安全的。在多线程应用程序中,所有其他方法都必须是线程安全的。
如果没有对 xShutdown() 的干预调用,SQLite 将永远不会多次调用 xInit()。
SQLite 调用 xCreate() 方法来构造一个新的缓存实例。SQLite 通常会为每个打开的数据库文件创建一个缓存实例,但不能保证这一点。第一个参数 szPage 是缓存必须分配的页面大小(以字节为单位)。szPage 永远是二的幂。第二个参数 szExtra 是与每个页面缓存条目关联的额外存储字节数。szExtra 参数将小于 250。SQLite 将在每个页面上使用额外的 szExtra 字节来存储磁盘上有关底层数据库页面的元数据。传递给 szExtra 的值取决于 SQLite 版本、目标平台以及 SQLite 的编译方式。如果正在创建的缓存将用于缓存存储在磁盘上的文件的数据库页面,则 xCreate() 的第三个参数 bPurgeable 为真,如果用于内存数据库,则为 false。缓存实现不必根据 bPurgeable 的值做任何特殊的事情;它纯粹是建议性的。在 bPurgeable 为 false 的缓存中,SQLite 将永远不会调用 xUnpin() 除非故意删除页面。换句话说,在 bPurgeable 设置为 false 的缓存上调用 xUnpin() 将始终将“discard”标志设置为 true。因此,使用 bPurgeable false 创建的缓存永远不会包含任何未固定的页面。在 bPurgeable 设置为 false 的缓存上调用 xUnpin() 将始终将“discard”标志设置为 true。因此,使用 bPurgeable false 创建的缓存永远不会包含任何未固定的页面。在 bPurgeable 设置为 false 的缓存上调用 xUnpin() 将始终将“discard”标志设置为 true。因此,使用 bPurgeable false 创建的缓存永远不会包含任何未固定的页面。
SQLite 可以随时调用 xCachesize() 方法来设置作为第一个参数传递的缓存实例的建议最大缓存大小(存储的页面数)。这是使用 SQLite“ PRAGMA cache_size ”命令配置的值。与 bPurgeable 参数一样,实现不需要对该值做任何事情;它仅供参考。
xPagecount() 方法必须返回当前存储在缓存中的页面数,包括固定和未固定的。
xFetch() 方法在缓存中定位一个页面并返回一个指向与该页面关联的 sqlite3_pcache_page 对象的指针,或一个 NULL 指针。返回的 sqlite3_pcache_page 对象的 pBuf 元素将是指向用于存储单个数据库页面内容的 szPage 字节缓冲区的指针。sqlite3_pcache_page 的 pExtra 元素将是一个指针,指向 SQLite 为页面缓存中的每个条目请求的额外存储的 szExtra 字节。
要获取的页面由键确定。最小键值为 1。使用 xFetch 检索后,页面被视为“已固定”。
如果请求的页面已经在页面缓存中,那么页面缓存实现必须返回一个指向页面缓冲区的指针,其内容完好无损。如果请求的页面不在缓存中,那么缓存实现应该使用 createFlag 参数的值来帮助它确定要采取的操作:
创建标志 | 页面不在缓存中时的行为 |
---|---|
0 | 不要分配新页面。返回 NULL。 |
1 | 如果分配一个新页面简单方便的话。否则返回 NULL。 |
2 | 尽一切努力分配一个新页面。只有在实际上不可能分配新页面时才返回 NULL。 |
SQLite 通常会调用带有 0 或 1 的 createFlag 的 xFetch()。SQLite 只会在先前使用 1 的 createFlag 调用失败后使用 2 的 createFlag。在 xFetch() 调用之间,SQLite 可能会尝试通过将固定页面的内容溢出到磁盘并同步操作系统磁盘缓存来取消固定一个或多个缓存页面。
xUnpin() 由 SQLite 调用,将指向当前固定页面的指针作为其第二个参数。如果第三个参数 discard 不为零,则页面必须从缓存中逐出。如果丢弃参数为零,则页面可以根据页面缓存实现的判断被丢弃或保留。页面缓存实现可以随时选择驱逐未固定的页面。
缓存不得执行任何引用计数。无论之前调用 xFetch() 的次数如何,对 xUnpin() 的一次调用都会取消固定页面。
xRekey() 方法用于更改与作为第二个参数传递的页面关联的键值。如果缓存以前包含与 newKey 关联的条目,则必须将其丢弃。保证不会固定与 newKey 关联的任何先前缓存条目。
当 SQLite 调用 xTruncate() 方法时,缓存必须丢弃所有页码(键)大于或等于传递给 xTruncate() 的 iLimit 参数值的现有缓存条目。如果这些页面中的任何一个被固定,它们将被隐式取消固定,这意味着它们可以被安全地丢弃。
xDestroy() 方法用于删除由 xCreate() 分配的缓存。应释放与指定缓存关联的所有资源。调用 xDestroy() 方法后,SQLite 认为sqlite3_pcache* 句柄无效,不会将其与任何其他 sqlite3_pcache_methods2 函数一起使用。
当 SQLite 希望页面缓存释放尽可能多的堆内存时,它会调用 xShrink() 方法。页面缓存实现没有义务释放任何内存,但行为良好的实现应该尽力而为。