diff options
author | danielk1977 <danielk1977@noemail.net> | 2007-08-28 08:00:17 +0000 |
---|---|---|
committer | danielk1977 <danielk1977@noemail.net> | 2007-08-28 08:00:17 +0000 |
commit | 84f786fcdd092e22aa1e0acecbe5ae459a5bd35e (patch) | |
tree | fb89977edde87c6c827391af66af8778565e2386 /src | |
parent | 900b31ef49b4faed9c3f991ac1062f662f56a76d (diff) | |
download | sqlite-84f786fcdd092e22aa1e0acecbe5ae459a5bd35e.tar.gz sqlite-84f786fcdd092e22aa1e0acecbe5ae459a5bd35e.zip |
Add some comments and test-cases for the global lru page list (used by sqlite3_release_memory()). (CVS 4308)
FossilOrigin-Name: 0b80168895993af5774369f839f284712d006f0a
Diffstat (limited to 'src')
-rw-r--r-- | src/pager.c | 78 |
1 files changed, 67 insertions, 11 deletions
diff --git a/src/pager.c b/src/pager.c index e6539e61a..a2595243b 100644 --- a/src/pager.c +++ b/src/pager.c @@ -18,7 +18,7 @@ ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.377 2007/08/27 17:27:49 danielk1977 Exp $ +** @(#) $Id: pager.c,v 1.378 2007/08/28 08:00:18 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" @@ -132,6 +132,33 @@ #define FORCE_ALIGNMENT(X) (((X)+7)&~7) typedef struct PgHdr PgHdr; + +/* +** Each pager stores all currently unreferenced pages in a list sorted +** in least-recently-used (LRU) order (i.e. the first item on the list has +** not been referenced in a long time, the last item has been recently +** used). An instance of this structure is included as part of each +** pager structure for this purpose (variable Pager.lru). +** +** Additionally, if memory-management is enabled, all unreferenced pages +** are stored in a global LRU list (global variable sqlite3LruPageList). +** +** In both cases, the PagerLruList.pFirstSynced variable points to +** the first page in the corresponding list that does not require an +** fsync() operation before it's memory can be reclaimed. If no such +** page exists, PagerLruList.pFirstSynced is set to NULL. +*/ +typedef struct PagerLruList PagerLruList; +struct PagerLruList { + PgHdr *pFirst; /* First page in LRU list */ + PgHdr *pLast; /* Last page in LRU list (the most recently used) */ + PgHdr *pFirstSynced; /* First page in list with PgHdr.needSync==0 */ +}; + +/* +** The following structure contains the next and previous pointers used +** to link a PgHdr structure into a PagerLruList linked list. +*/ typedef struct PagerLruLink PagerLruLink; struct PagerLruLink { PgHdr *pNext; @@ -292,13 +319,6 @@ struct PgHistory { #define PGHDR_TO_HIST(P,PGR) \ ((PgHistory*)&((char*)(&(P)[1]))[(PGR)->pageSize+(PGR)->nExtra]) -typedef struct PagerLruList PagerLruList; -struct PagerLruList { - PgHdr *pFirst; - PgHdr *pLast; - PgHdr *pFirstSynced; /* First page in list with PgHdr.needSync==0 */ -}; - /* ** A open page cache is an instance of the following structure. ** @@ -531,10 +551,22 @@ static const unsigned char aJournalMagic[] = { # define REFINFO(X) #endif +/* +** Add page pPg to the end of the linked list managed by structure +** pList (pPg becomes the last entry in the list - the most recently +** used). Argument pLink should point to either pPg->free or pPg->gfree, +** depending on whether pPg is being added to the pager-specific or +** global LRU list. +*/ static void listAdd(PagerLruList *pList, PagerLruLink *pLink, PgHdr *pPg){ pLink->pNext = 0; pLink->pPrev = pList->pLast; +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + assert(pLink==&pPg->free || pLink==&pPg->gfree); + assert(pLink==&pPg->gfree || pList!=&sqlite3LruPageList); +#endif + if( pList->pLast ){ int iOff = (char *)pLink - (char *)pPg; PagerLruLink *pLastLink = (PagerLruLink *)(&((u8 *)pList->pLast)[iOff]); @@ -550,9 +582,20 @@ static void listAdd(PagerLruList *pList, PagerLruLink *pLink, PgHdr *pPg){ } } +/* +** Remove pPg from the list managed by the structure pointed to by pList. +** +** Argument pLink should point to either pPg->free or pPg->gfree, depending +** on whether pPg is being added to the pager-specific or global LRU list. +*/ static void listRemove(PagerLruList *pList, PagerLruLink *pLink, PgHdr *pPg){ int iOff = (char *)pLink - (char *)pPg; +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + assert(pLink==&pPg->free || pLink==&pPg->gfree); + assert(pLink==&pPg->gfree || pList!=&sqlite3LruPageList); +#endif + if( pPg==pList->pFirst ){ pList->pFirst = pLink->pNext; } @@ -580,7 +623,9 @@ static void listRemove(PagerLruList *pList, PagerLruLink *pLink, PgHdr *pPg){ } /* -** Add page to the free-list +** Add page pPg to the list of free pages for the pager. If +** memory-management is enabled, also add the page to the global +** list of free pages. */ static void lruListAdd(PgHdr *pPg){ listAdd(&pPg->pPager->lru, &pPg->free, pPg); @@ -594,7 +639,9 @@ static void lruListAdd(PgHdr *pPg){ } /* -** Remove page from free-list +** Remove page pPg from the list of free pages for the associated pager. +** If memory-management is enabled, also remove pPg from the global list +** of free pages. */ static void lruListRemove(PgHdr *pPg){ listRemove(&pPg->pPager->lru, &pPg->free, pPg); @@ -608,7 +655,11 @@ static void lruListRemove(PgHdr *pPg){ } /* -** Set the Pager.pFirstSynced variable +** This function is called just after the needSync flag has been cleared +** from all pages managed by pPager (usually because the journal file +** has just been synced). It updates the pPager->lru.pFirstSynced variable +** and, if memory-management is enabled, the sqlite3LruPageList.pFirstSynced +** variable also. */ static void lruListSetFirstSynced(Pager *pPager){ pPager->lru.pFirstSynced = pPager->lru.pFirst; @@ -3056,6 +3107,10 @@ int sqlite3PagerReleaseMemory(int nReq){ } sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU)); + /* If pPg==0, then the block above has failed to find a page to + ** recycle. In this case return early - no further memory will + ** be released. + */ if( !pPg ) break; pPager = pPg->pPager; @@ -3089,6 +3144,7 @@ int sqlite3PagerReleaseMemory(int nReq){ IOTRACE(("PGFREE %p %d *\n", pPager, pPg->pgno)); PAGER_INCR(sqlite3_pager_pgfree_count); sqlite3_free(pPg); + pPager->nPage--; }else{ /* An error occured whilst writing to the database file or ** journal in pager_recycle(). The error is not returned to the |