⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcache.c

📁 最新的sqlite3.6.2源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    pcacheAddToList(&pCache->pClean, p);    if( p->nRef==0 ){      pcacheAddToLruList(p);      pCache->nPinned--;    }  }  sqlite3PcacheAssertFlags(pCache, 0, PGHDR_DIRTY);  expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) );  pcacheExitMutex();}/*** Change the page number of page p to newPgno. If newPgno is 0, then the** page object is added to the clean-list and the PGHDR_REUSE_UNLIKELY ** flag set.*/void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){  assert( p->nRef>0 );  pcacheEnterMutex();  pcacheRemoveFromHash(p);  p->pgno = newPgno;  if( newPgno==0 ){    p->flags |= PGHDR_REUSE_UNLIKELY;    pcacheFree(p->apSave[0]);    pcacheFree(p->apSave[1]);    p->apSave[0] = 0;    p->apSave[1] = 0;    if( (p->flags & PGHDR_DIRTY) ){      pcacheMakeClean(p);    }  }  pcacheAddToHash(p);  pcacheExitMutex();}/*** Remove all content from a page cache*/void pcacheClear(PCache *pCache){  PgHdr *p, *pNext;  assert( sqlite3_mutex_held(pcache.mutex) );  for(p=pCache->pClean; p; p=pNext){    pNext = p->pNext;    pcacheRemoveFromLruList(p);    pcachePageFree(p);  }  for(p=pCache->pDirty; p; p=pNext){    pNext = p->pNext;    pcachePageFree(p);  }  pCache->pClean = 0;  pCache->pDirty = 0;  pCache->pDirtyTail = 0;  pCache->nPage = 0;  pCache->nPinned = 0;  memset(pCache->apHash, 0, pCache->nHash*sizeof(pCache->apHash[0]));}/*** Drop every cache entry whose page number is greater than "pgno".*/void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){  PgHdr *p, *pNext;  PgHdr *pDirty = pCache->pDirty;  pcacheEnterMutex();  for(p=pCache->pClean; p||pDirty; p=pNext){    if( !p ){      p = pDirty;      pDirty = 0;    }    pNext = p->pNext;    if( p->pgno>pgno ){      if( p->nRef==0 ){        pcacheRemoveFromHash(p);        if( p->flags&PGHDR_DIRTY ){          pcacheRemoveFromList(&pCache->pDirty, p);          pCache->nPinned--;        }else{          pcacheRemoveFromList(&pCache->pClean, p);          pcacheRemoveFromLruList(p);        }        pcachePageFree(p);      }else{        /* If there are references to the page, it cannot be freed. In this        ** case, zero the page content instead.        */        memset(p->pData, 0, pCache->szPage);      }    }  }  pcacheExitMutex();}/*** If there are currently more than pcache.nMaxPage pages allocated, try** to recycle pages to reduce the number allocated to pcache.nMaxPage.*/static void pcacheEnforceMaxPage(){  PgHdr *p;  assert( sqlite3_mutex_held(pcache.mutex) );  while( pcache.nCurrentPage>pcache.nMaxPage && (p = pcacheRecyclePage()) ){    pcachePageFree(p);  }}/*** Close a cache.*/void sqlite3PcacheClose(PCache *pCache){  pcacheEnterMutex();  /* Free all the pages used by this pager and remove them from the LRU list. */  pcacheClear(pCache);  if( pCache->bPurgeable ){    pcache.nMaxPage -= pCache->nMax;    pcache.nMinPage -= pCache->nMin;    pcacheEnforceMaxPage();  }  sqlite3_free(pCache->apHash);  pcacheExitMutex();}/*** Preserve the content of the page.  It is assumed that the content** has not been preserved already.**** If idJournal==0 then this is for the overall transaction.** If idJournal==1 then this is for the statement journal.**** This routine is used for in-memory databases only.**** Return SQLITE_OK or SQLITE_NOMEM if a memory allocation fails.*/int sqlite3PcachePreserve(PgHdr *p, int idJournal){  void *x;  int sz;  assert( p->pCache->bPurgeable==0 );  assert( p->apSave[idJournal]==0 );  sz = p->pCache->szPage;  p->apSave[idJournal] = x = sqlite3PageMalloc( sz );  if( x==0 ) return SQLITE_NOMEM;  memcpy(x, p->pData, sz);  return SQLITE_OK;}/*** Commit a change previously preserved.*/void sqlite3PcacheCommit(PCache *pCache, int idJournal){  PgHdr *p;  pcacheEnterMutex();     /* Mutex is required to call pcacheFree() */  for(p=pCache->pDirty; p; p=p->pNext){    if( p->apSave[idJournal] ){      pcacheFree(p->apSave[idJournal]);      p->apSave[idJournal] = 0;    }  }  pcacheExitMutex();}/*** Rollback a change previously preserved.*/void sqlite3PcacheRollback(PCache *pCache, int idJournal){  PgHdr *p;  int sz;  pcacheEnterMutex();     /* Mutex is required to call pcacheFree() */  sz = pCache->szPage;  for(p=pCache->pDirty; p; p=p->pNext){    if( p->apSave[idJournal] ){      memcpy(p->pData, p->apSave[idJournal], sz);      pcacheFree(p->apSave[idJournal]);      p->apSave[idJournal] = 0;    }  }  pcacheExitMutex();}/* ** Assert flags settings on all pages.  Debugging only.*/void sqlite3PcacheAssertFlags(PCache *pCache, int trueMask, int falseMask){  PgHdr *p;  for(p=pCache->pDirty; p; p=p->pNext){    assert( (p->flags&trueMask)==trueMask );    assert( (p->flags&falseMask)==0 );  }  for(p=pCache->pClean; p; p=p->pNext){    assert( (p->flags&trueMask)==trueMask );    assert( (p->flags&falseMask)==0 );  }}/* ** Discard the contents of the cache.*/int sqlite3PcacheClear(PCache *pCache){  assert(pCache->nRef==0);  pcacheEnterMutex();  pcacheClear(pCache);  pcacheExitMutex();  return SQLITE_OK;}/*** Merge two lists of pages connected by pDirty and in pgno order.** Do not both fixing the pPrevDirty pointers.*/static PgHdr *pcacheMergeDirtyList(PgHdr *pA, PgHdr *pB){  PgHdr result, *pTail;  pTail = &result;  while( pA && pB ){    if( pA->pgno<pB->pgno ){      pTail->pDirty = pA;      pTail = pA;      pA = pA->pDirty;    }else{      pTail->pDirty = pB;      pTail = pB;      pB = pB->pDirty;    }  }  if( pA ){    pTail->pDirty = pA;  }else if( pB ){    pTail->pDirty = pB;  }else{    pTail->pDirty = 0;  }  return result.pDirty;}/*** Sort the list of pages in accending order by pgno.  Pages are** connected by pDirty pointers.  The pPrevDirty pointers are** corrupted by this sort.*/#define N_SORT_BUCKET_ALLOC 25#define N_SORT_BUCKET       25#ifdef SQLITE_TEST  int sqlite3_pager_n_sort_bucket = 0;  #undef N_SORT_BUCKET  #define N_SORT_BUCKET \   (sqlite3_pager_n_sort_bucket?sqlite3_pager_n_sort_bucket:N_SORT_BUCKET_ALLOC)#endifstatic PgHdr *pcacheSortDirtyList(PgHdr *pIn){  PgHdr *a[N_SORT_BUCKET_ALLOC], *p;  int i;  memset(a, 0, sizeof(a));  while( pIn ){    p = pIn;    pIn = p->pDirty;    p->pDirty = 0;    for(i=0; i<N_SORT_BUCKET-1; i++){      if( a[i]==0 ){        a[i] = p;        break;      }else{        p = pcacheMergeDirtyList(a[i], p);        a[i] = 0;      }    }    if( i==N_SORT_BUCKET-1 ){      /* Coverage: To get here, there need to be 2^(N_SORT_BUCKET)       ** elements in the input list. This is possible, but impractical.      ** Testing this line is the point of global variable      ** sqlite3_pager_n_sort_bucket.      */      a[i] = pcacheMergeDirtyList(a[i], p);    }  }  p = a[0];  for(i=1; i<N_SORT_BUCKET; i++){    p = pcacheMergeDirtyList(p, a[i]);  }  return p;}/*** Return a list of all dirty pages in the cache, sorted by page number.*/PgHdr *sqlite3PcacheDirtyList(PCache *pCache){  PgHdr *p;  for(p=pCache->pDirty; p; p=p->pNext){    p->pDirty = p->pNext;  }  return pcacheSortDirtyList(pCache->pDirty);}/* ** Return the total number of outstanding page references.*/int sqlite3PcacheRefCount(PCache *pCache){  return pCache->nRef;}/* ** Return the total number of pages in the cache.*/int sqlite3PcachePagecount(PCache *pCache){  assert( pCache->nPage>=0 );  return pCache->nPage;}#ifdef SQLITE_CHECK_PAGES/*** This function is used by the pager.c module to iterate through all ** pages in the cache. At present, this is only required if the** SQLITE_CHECK_PAGES macro (used for debugging) is specified.*/void sqlite3PcacheIterate(PCache *pCache, void (*xIter)(PgHdr *)){  PgHdr *p;  for(p=pCache->pClean; p; p=p->pNext){    xIter(p);  }  for(p=pCache->pDirty; p; p=p->pNext){    xIter(p);  }}#endif/* ** Set flags on all pages in the page cache */void sqlite3PcacheSetFlags(PCache *pCache, int andMask, int orMask){  PgHdr *p;  assert( (orMask&PGHDR_NEED_SYNC)==0 );  /* Obtain the global mutex before modifying any PgHdr.flags variables   ** or traversing the LRU list.  */   pcacheEnterMutex();  for(p=pCache->pDirty; p; p=p->pNext){    p->flags = (p->flags&andMask)|orMask;  }  for(p=pCache->pClean; p; p=p->pNext){    p->flags = (p->flags&andMask)|orMask;  }  if( 0==(andMask&PGHDR_NEED_SYNC) ){    pCache->pSynced = pCache->pDirtyTail;    assert( !pCache->pSynced || (pCache->pSynced->flags&PGHDR_NEED_SYNC)==0 );  }  pcacheExitMutex();}/*** Set the suggested cache-size value.*/int sqlite3PcacheGetCachesize(PCache *pCache){  return pCache->nMax;}/*** Set the suggested cache-size value.*/void sqlite3PcacheSetCachesize(PCache *pCache, int mxPage){  if( mxPage<10 ){    mxPage = 10;  }  if( pCache->bPurgeable ){    pcacheEnterMutex();    pcache.nMaxPage -= pCache->nMax;    pcache.nMaxPage += mxPage;    pcacheEnforceMaxPage();    pcacheExitMutex();  }  pCache->nMax = mxPage;}#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT/*** This function is called to free superfluous dynamically allocated memory** held by the pager system. Memory in use by any SQLite pager allocated** by the current thread may be sqlite3_free()ed.**** nReq is the number of bytes of memory required. Once this much has** been released, the function returns. The return value is the total number ** of bytes of memory released.*/int sqlite3PcacheReleaseMemory(int nReq){  int nFree = 0;  if( pcache.pStart==0 ){    PgHdr *p;    pcacheEnterMutex();    while( (nReq<0 || nFree<nReq) && (p=pcacheRecyclePage()) ){      nFree += pcachePageSize(p);      pcachePageFree(p);    }    pcacheExitMutex();  }  return nFree;}#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */#ifdef SQLITE_TESTvoid sqlite3PcacheStats(  int *pnCurrent,  int *pnMax,  int *pnMin,  int *pnRecyclable){  PgHdr *p;  int nRecyclable = 0;  for(p=pcache.pLruHead; p; p=p->pNextLru){    nRecyclable++;  }  *pnCurrent = pcache.nCurrentPage;  *pnMax = pcache.nMaxPage;  *pnMin = pcache.nMinPage;  *pnRecyclable = nRecyclable;}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -