这部分的结构体在sqlite中定义了相似的两组,区别是名字后面加了个数字1,使的阅读起来非常不方便。后面加1的是内部定义;没加1的相当于接口,是给程序使用的。而且结构体中存在相互指向,使用起来也许比较方便,但抽象性不高
/*
** Every page in the cache is controlled by an instance of the following
** structure.
*/
struct PgHdr {
void *pData; /* Content of this page 用于存放数据*/
void *pExtra; /* Extra content */
PgHdr *pDirty; /* Transient list of dirty pages */
Pgno pgno; /* Page number for this page */
Pager *pPager; /* The pager this page is part of */
#ifdef sqlITE_CHECK_PAGES
u32 pageHash; /* Hash of page content */
#endif
u16 flags; /* PGHDR flags defined below */
/**********************************************************************
** Elements above are public. All that follows is private to pcache.c
** and should not be accessed by other modules.
*/
i16 nRef; /* Number of users of this page */
PCache *pCache; /* Cache that owns this page 指向cache列表*/
PgHdr *pDirtyNext; /* Next element in list of dirty pages 和下面的一起指向PCache中*/
PgHdr *pDirtyPrev; /* PrevIoUs element in list of dirty pages */
};
这就是page在内存中的page head
struct PCache {
PgHdr *pDirty,*pDirtyTail; /* List of dirty pages in LRU order 和PgHdr中的pDirtyNext pDirtyPrev一起使用*/
PgHdr *pSynced; /* Last synced page in dirty page list */
int nRef; /* Number of referenced pages */
int nMax; /* Configured cache size */
int szPage; /* Size of every page in this cache */
int szExtra; /* Size of extra space for each page */
int bPurgeable; /* True if pages are on backing store */
int (*xStress)(void*,PgHdr*); /* Call to try make a page clean */
void *pStress; /* Argument to xStress */
sqlite3_pcache *pCache; /* Pluggable cache module 把向PCache1 指向cache的真正实现*/
PgHdr *pPage1; /* Reference to page 1 */
};
cache的定义,在这一层上,是没有内存淘汰算法的,只是记录一些信息
/*
** Global data used by this cache.
*/
static sqlITE_WSD struct PCacheGlobal {
sqlite3_mutex *mutex; /* static mutex MUTEX_STATIC_LRU */
int nMaxPage; /* Sum of nMaxPage for purgeable caches */
int nMinPage; /* Sum of nMinPage for purgeable caches */
int nCurrentPage; /* Number of purgeable pages allocated */
PgHdr1 *pLruHead,*pLruTail; /* LRU list of unpinned pages */
/* Variables related to sqlITE_CONFIG_PAGECACHE settings. */
int szSlot; /* Size of each free slot */
void *pStart,*pEnd; /* Bounds of pagecache malloc range指向预先分配的内存的起始和结束位置*/
PgFreeslot *pFree; /* Free page blocks 使用时转化为, 这没有用union结构体,而是强制转化*/
int isInit; /* True if initialized */
} pcache1_g;
这是cache的全局结构了,内存中只存在一个的全局变量pcache1。
这种分配策略不是每次分配内存时都通过malloc获得,而是把系统启动时分配的一块大内存,分配成PCacheGlobal ->szSlot大小的多个页面,用PCacheGlobal ->pFree链表连起来,每次申请时先从这里面取,释放时归还。当申请的,可通过unpin和pin不把内存归还到链表中,而是放入pLruHead,pLruTail组成的LRU链表中,形成LRU的内存淘汰算法,链表LRU很简单,就是把刚使用的接入链头,每次重用都是从链尾开始。
/* Pointers to structures of this type are cast and returned as
** opaque sqlite3_pcache* handles
*/
struct PCache1 {
/* Cache configuration parameters. Page size (szPage) and the purgeable
** flag (bPurgeable) are set when the cache is created. nMax may be
** modified at any time by a call to the pcache1CacheSize() method.
** The global mutex must be held when accessing nMax.
*/
int szPage; /* Size of allocated pages in bytes */
int bPurgeable; /* True if cache is purgeable */
unsigned int nMin; /* Minimum number of pages reserved */
unsigned int nMax; /* Configured "cache_size" value */
/* Hash table of all pages. The following variables may only be accessed
** when the accessor is holding the global mutex (see pcache1EnterMutex()
** and pcache1LeaveMutex()).
*/
unsigned int nRecyclable; /* Number of pages in the LRU list */
unsigned int nPage; /* Total number of pages in apHash */
unsigned int nHash; /* Number of slots in apHash[] */
PgHdr1 **apHash; /* Hash table for fast lookup by key 根据page number形成的HASH表,HASH值相同的组成单链表*/
unsigned int iMaxKey; /* Largest key seen since xTruncate() */
};
在内部层次的cache结构,对外是不可见的
/*
** Each cache entry is represented by an instance of the following
** structure. A buffer of PgHdr1.pCache->szPage bytes is allocated
** directly before this structure in memory (see the PGHDR1_TO_PAGE()
** macro below).
*/
struct PgHdr1 {
unsigned int iKey; /* Key value (page number) */
PgHdr1 *pNext; /* Next in hash table chain */
PCache1 *pCache; /* Cache that currently owns this page */
PgHdr1 *pLruNext; /* Next in LRU list of unpinned pages 形成PCacheGlobal的LRU链表 */
PgHdr1 *pLruPrev; /* PrevIoUs in LRU list of unpinned pages */
};
在内部层次的page header结构,用在PCache1中的HASH表
/*
** Free slots in the allocator used to divide up the buffer provided using
** the sqlITE_CONFIG_PAGECACHE mechanism.
*/
struct PgFreeslot {
PgFreeslot *pNext; /* Next free slot */
};
分配cache的时候,是从PCache->PCache1->PCacheGlobal 这个过程