typedef struct sqlite3_pcache_methods2 sqlite3_pcache_methods2; struct sqlite3_pcache_methods2 { int iVersion; 无效* pArg; int(* xInit)(无效*); 无效(* xShutdown)(无效*); 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 *,无符号密钥,int createFlag); void(* xUnpin)(sqlite3_pcache *,sqlite3_pcache_page *,int丢弃); 无效(* xRekey)(sqlite3_pcache *,sqlite3_pcache_page *, unsigned oldKey,unsigned newKey); void(* xTruncate)(sqlite3_pcache *,未签名的iLimit); void(* xDestroy)(sqlite3_pcache *); void(* xShrink)(sqlite3_pcache *); };
该sqlite3_config(SQLITE_CONFIG_PCACHE2,...)接口可以通过传递sqlite3_pcache_methods2结构的一个实例注册一个替代页面缓存实现。在许多应用程序中,SQLite分配的大部分堆内存都用于页面缓存。通过使用此API实现自定义页面缓存,应用程序可以更好地控制SQLite占用的内存量,分配和释放内存的方式,以及用于确切确定要缓存数据库文件的哪些部分的策略以及多长时间。
备用页面缓存机制是一种极端的措施,只有最苛刻的应用程序才需要。建议将内置页面缓存用于大多数用途。
在调用sqlite3_config时,SQLite将sqlite3_pcache_methods2结构的内容复制到内部缓冲区。因此,在调用sqlite3_config()返回之后,应用程序可能会丢弃该参数 。
每次对sqlite3_initialize()的有效调用都会调用一次xInit()方法 (通常在该过程的生命周期内仅调用一次)。向xInit()方法传递了sqlite3_pcache_methods2.pArg值的副本。xInit()方法的目的是建立自定义页面缓存实现所需的全局数据结构。如果xInit()方法为NULL,则使用内置的默认页面缓存,而不是应用程序定义的页面缓存。
xShutdown()方法由sqlite3_shutdown()调用。如果需要,它可以用来在进程关闭之前清除所有未使用的资源。xShutdown()方法可以为NULL。
SQLite自动将对xInit方法的调用序列化,因此xInit方法不必是线程安全的。仅从sqlite3_shutdown()调用xShutdown方法,因此也不必是线程安全的。在多线程应用程序中,所有其他方法都必须是线程安全的。
如果没有对xShutdown()的中间调用,SQLite将永远不会多次调用xInit()。
SQLite调用xCreate()方法来构造一个新的缓存实例。尽管不能保证,但SQLite通常会为每个打开的数据库文件创建一个缓存实例。第一个参数szPage是必须由缓存分配的页面大小(以字节为单位)。szPage将始终是2的幂。第二个参数szExtra是与每个页面缓存条目关联的额外存储空间的字节数。szExtra参数的数字小于250。SQLite将在每个页面上使用额外的szExtra字节在磁盘上存储有关基础数据库页面的元数据。传递给szExtra的值取决于SQLite版本,目标平台以及SQLite的编译方式。如果正在创建的缓存将用于缓存磁盘上存储的文件的数据库页面,则xCreate()的第三个参数bPurgeable为true,如果用于内存数据库,则返回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参数的值来帮助它确定要采取的操作:
createFlag | 页面尚未在缓存中时的行为 |
---|---|
0 | 不要分配新页面。返回NULL。 |
1个 | 如果方便且方便地分配新页面。否则返回NULL。 |
2个 | 尽一切努力分配一个新页面。仅在实际上不可能分配新页面的情况下才返回NULL。 |
通常,SQLite将使用createFlag为0或1调用xFetch()。SQLite将仅在createFlag为1的先前调用失败后才使用createFlag为2。在两次xFetch()调用之间,SQLite可能会通过将固定页面的内容溢出到磁盘上并同步操作系统磁盘缓存来尝试取消固定一个或多个缓存页面。
xUnpin()由SQLite调用,并以指向当前固定页面的指针作为第二个参数。如果第三个参数“ discard”不为零,则必须从高速缓存中逐出该页面。如果丢弃参数为零,则页面缓存实现可以自行决定丢弃还是保留该页面。页面缓存实现可以选择随时撤出未固定的页面。
缓存不得执行任何引用计数。一次调用xUnpin()会取消固定页面,而不管先前调用xFetch()的次数如何。
xRekey()方法用于更改与作为第二个参数传递的页面关联的键值。如果缓存先前包含与newKey关联的条目,则必须将其丢弃。与newKey关联的任何先前的高速缓存条目都保证不会被固定。
当SQLite调用xTruncate()方法时,缓存必须丢弃页号(键)大于或等于传递给xTruncate()的iLimit参数值的所有现有缓存条目。如果将这些页面中的任何一个固定,则将其隐式取消固定,这意味着可以安全地将其丢弃。
xDestroy()方法用于删除xCreate()分配的缓存。与指定的缓存关联的所有资源都应释放。调用xDestroy()方法后,SQLite认为sqlite3_pcache * 处理无效,并且不会与任何其他sqlite3_pcache_methods2函数一起使用。
当SQLite希望页面缓存释放尽可能多的堆内存时,它会调用xShrink()方法。页面缓存实现没有义务释放任何内存,但是行为规范的实现应尽力而为。