这部分的结构体在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 这个过程 (编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|