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

📄 pcache1.c

📁 sqlite最新源码
💻 C
📖 第 1 页 / 共 2 页
字号:
}/******************************************************************************//******** sqlite3_pcache Methods **********************************************//*** Implementation of the sqlite3_pcache.xInit method.*/static int pcache1Init(void *NotUsed){  UNUSED_PARAMETER(NotUsed);  memset(&pcache1, 0, sizeof(pcache1));  if( sqlite3GlobalConfig.bCoreMutex ){    pcache1.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU);  }  return SQLITE_OK;}/*** Implementation of the sqlite3_pcache.xShutdown method.*/static void pcache1Shutdown(void *NotUsed){  UNUSED_PARAMETER(NotUsed);  /* no-op */}/*** Implementation of the sqlite3_pcache.xCreate method.**** Allocate a new cache.*/static sqlite3_pcache *pcache1Create(int szPage, int bPurgeable){  PCache1 *pCache;  pCache = (PCache1 *)sqlite3_malloc(sizeof(PCache1));  if( pCache ){    memset(pCache, 0, sizeof(PCache1));    pCache->szPage = szPage;    pCache->bPurgeable = (bPurgeable ? 1 : 0);    if( bPurgeable ){      pCache->nMin = 10;      pcache1EnterMutex();      pcache1.nMinPage += pCache->nMin;      pcache1LeaveMutex();    }  }  return (sqlite3_pcache *)pCache;}/*** Implementation of the sqlite3_pcache.xCachesize method. **** Configure the cache_size limit for a cache.*/static void pcache1Cachesize(sqlite3_pcache *p, int nMax){  PCache1 *pCache = (PCache1 *)p;  if( pCache->bPurgeable ){    pcache1EnterMutex();    pcache1.nMaxPage += (nMax - pCache->nMax);    pCache->nMax = nMax;    pcache1EnforceMaxPage();    pcache1LeaveMutex();  }}/*** Implementation of the sqlite3_pcache.xPagecount method. */static int pcache1Pagecount(sqlite3_pcache *p){  int n;  pcache1EnterMutex();  n = ((PCache1 *)p)->nPage;  pcache1LeaveMutex();  return n;}/*** Implementation of the sqlite3_pcache.xFetch method. **** Fetch a page by key value.**** Whether or not a new page may be allocated by this function depends on** the value of the createFlag argument.**** There are three different approaches to obtaining space for a page,** depending on the value of parameter createFlag (which may be 0, 1 or 2).****   1. Regardless of the value of createFlag, the cache is searched for a **      copy of the requested page. If one is found, it is returned.****   2. If createFlag==0 and the page is not already in the cache, NULL is**      returned.****   3. If createFlag is 1, the cache is marked as purgeable and the page is **      not already in the cache, and if either of the following are true, **      return NULL:****       (a) the number of pages pinned by the cache is greater than**           PCache1.nMax, or**       (b) the number of pages pinned by the cache is greater than**           the sum of nMax for all purgeable caches, less the sum of **           nMin for all other purgeable caches. ****   4. If none of the first three conditions apply and the cache is marked**      as purgeable, and if one of the following is true:****       (a) The number of pages allocated for the cache is already **           PCache1.nMax, or****       (b) The number of pages allocated for all purgeable caches is**           already equal to or greater than the sum of nMax for all**           purgeable caches,****      then attempt to recycle a page from the LRU list. If it is the right**      size, return the recycled buffer. Otherwise, free the buffer and**      proceed to step 5. ****   5. Otherwise, allocate and return a new page buffer.*/static void *pcache1Fetch(sqlite3_pcache *p, unsigned int iKey, int createFlag){  unsigned int nPinned;  PCache1 *pCache = (PCache1 *)p;  PgHdr1 *pPage = 0;  pcache1EnterMutex();  if( createFlag==1 ) sqlite3BeginBenignMalloc();  /* Search the hash table for an existing entry. */  if( pCache->nHash>0 ){    unsigned int h = iKey % pCache->nHash;    for(pPage=pCache->apHash[h]; pPage&&pPage->iKey!=iKey; pPage=pPage->pNext);  }  if( pPage || createFlag==0 ){    pcache1PinPage(pPage);    goto fetch_out;  }  /* Step 3 of header comment. */  nPinned = pCache->nPage - pCache->nRecyclable;  if( createFlag==1 && pCache->bPurgeable && (        nPinned>=(pcache1.nMaxPage+pCache->nMin-pcache1.nMinPage)     || nPinned>=(pCache->nMax)  )){    goto fetch_out;  }  if( pCache->nPage>=pCache->nHash && pcache1ResizeHash(pCache) ){    goto fetch_out;  }  /* Step 4. Try to recycle a page buffer if appropriate. */  if( pCache->bPurgeable && pcache1.pLruTail && (      pCache->nPage>=pCache->nMax-1 || pcache1.nCurrentPage>=pcache1.nMaxPage  )){    pPage = pcache1.pLruTail;    pcache1RemoveFromHash(pPage);    pcache1PinPage(pPage);    if( pPage->pCache->szPage!=pCache->szPage ){      pcache1FreePage(pPage);      pPage = 0;    }else{      pcache1.nCurrentPage -= (pPage->pCache->bPurgeable - pCache->bPurgeable);    }  }  /* Step 5. If a usable page buffer has still not been found,   ** attempt to allocate a new one.   */  if( !pPage ){    pPage = pcache1AllocPage(pCache);  }  if( pPage ){    unsigned int h = iKey % pCache->nHash;    *(void **)(PGHDR1_TO_PAGE(pPage)) = 0;    pCache->nPage++;    pPage->iKey = iKey;    pPage->pNext = pCache->apHash[h];    pPage->pCache = pCache;    pPage->pLruPrev = 0;    pPage->pLruNext = 0;    pCache->apHash[h] = pPage;  }fetch_out:  if( pPage && iKey>pCache->iMaxKey ){    pCache->iMaxKey = iKey;  }  if( createFlag==1 ) sqlite3EndBenignMalloc();  pcache1LeaveMutex();  return (pPage ? PGHDR1_TO_PAGE(pPage) : 0);}/*** Implementation of the sqlite3_pcache.xUnpin method.**** Mark a page as unpinned (eligible for asynchronous recycling).*/static void pcache1Unpin(sqlite3_pcache *p, void *pPg, int reuseUnlikely){  PCache1 *pCache = (PCache1 *)p;  PgHdr1 *pPage = PAGE_TO_PGHDR1(pPg);  pcache1EnterMutex();  /* It is an error to call this function if the page is already   ** part of the global LRU list.  */  assert( pPage->pLruPrev==0 && pPage->pLruNext==0 );  assert( pcache1.pLruHead!=pPage && pcache1.pLruTail!=pPage );  if( reuseUnlikely || pcache1.nCurrentPage>pcache1.nMaxPage ){    pcache1RemoveFromHash(pPage);    pcache1FreePage(pPage);  }else{    /* Add the page to the global LRU list. Normally, the page is added to    ** the head of the list (last page to be recycled). However, if the     ** reuseUnlikely flag passed to this function is true, the page is added    ** to the tail of the list (first page to be recycled).    */    if( pcache1.pLruHead ){      pcache1.pLruHead->pLruPrev = pPage;      pPage->pLruNext = pcache1.pLruHead;      pcache1.pLruHead = pPage;    }else{      pcache1.pLruTail = pPage;      pcache1.pLruHead = pPage;    }    pCache->nRecyclable++;  }  pcache1LeaveMutex();}/*** Implementation of the sqlite3_pcache.xRekey method. */static void pcache1Rekey(  sqlite3_pcache *p,  void *pPg,  unsigned int iOld,  unsigned int iNew){  PCache1 *pCache = (PCache1 *)p;  PgHdr1 *pPage = PAGE_TO_PGHDR1(pPg);  PgHdr1 **pp;  unsigned int h;   assert( pPage->iKey==iOld );  pcache1EnterMutex();  h = iOld%pCache->nHash;  pp = &pCache->apHash[h];  while( (*pp)!=pPage ){    pp = &(*pp)->pNext;  }  *pp = pPage->pNext;  h = iNew%pCache->nHash;  pPage->iKey = iNew;  pPage->pNext = pCache->apHash[h];  pCache->apHash[h] = pPage;  if( iNew>pCache->iMaxKey ){    pCache->iMaxKey = iNew;  }  pcache1LeaveMutex();}/*** Implementation of the sqlite3_pcache.xTruncate method. **** Discard all unpinned pages in the cache with a page number equal to** or greater than parameter iLimit. Any pinned pages with a page number** equal to or greater than iLimit are implicitly unpinned.*/static void pcache1Truncate(sqlite3_pcache *p, unsigned int iLimit){  PCache1 *pCache = (PCache1 *)p;  pcache1EnterMutex();  if( iLimit<=pCache->iMaxKey ){    pcache1TruncateUnsafe(pCache, iLimit);    pCache->iMaxKey = iLimit-1;  }  pcache1LeaveMutex();}/*** Implementation of the sqlite3_pcache.xDestroy method. **** Destroy a cache allocated using pcache1Create().*/static void pcache1Destroy(sqlite3_pcache *p){  PCache1 *pCache = (PCache1 *)p;  pcache1EnterMutex();  pcache1TruncateUnsafe(pCache, 0);  pcache1.nMaxPage -= pCache->nMax;  pcache1.nMinPage -= pCache->nMin;  pcache1EnforceMaxPage();  pcache1LeaveMutex();  sqlite3_free(pCache->apHash);  sqlite3_free(pCache);}/*** This function is called during initialization (sqlite3_initialize()) to** install the default pluggable cache module, assuming the user has not** already provided an alternative.*/void sqlite3PCacheSetDefault(void){  static sqlite3_pcache_methods defaultMethods = {    0,                       /* pArg */    pcache1Init,             /* xInit */    pcache1Shutdown,         /* xShutdown */    pcache1Create,           /* xCreate */    pcache1Cachesize,        /* xCachesize */    pcache1Pagecount,        /* xPagecount */    pcache1Fetch,            /* xFetch */    pcache1Unpin,            /* xUnpin */    pcache1Rekey,            /* xRekey */    pcache1Truncate,         /* xTruncate */    pcache1Destroy           /* xDestroy */  };  sqlite3_config(SQLITE_CONFIG_PCACHE, &defaultMethods);}#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( pcache1.pStart==0 ){    PgHdr1 *p;    pcache1EnterMutex();    while( (nReq<0 || nFree<nReq) && (p=pcache1.pLruTail) ){      nFree += sqlite3MallocSize(p);      pcache1PinPage(p);      pcache1RemoveFromHash(p);      pcache1FreePage(p);    }    pcache1LeaveMutex();  }  return nFree;}#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */#ifdef SQLITE_TEST/*** This function is used by test procedures to inspect the internal state** of the global cache.*/void sqlite3PcacheStats(  int *pnCurrent,      /* OUT: Total number of pages cached */  int *pnMax,          /* OUT: Global maximum cache size */  int *pnMin,          /* OUT: Sum of PCache1.nMin for purgeable caches */  int *pnRecyclable    /* OUT: Total number of pages available for recycling */){  PgHdr1 *p;  int nRecyclable = 0;  for(p=pcache1.pLruHead; p; p=p->pLruNext){    nRecyclable++;  }  *pnCurrent = pcache1.nCurrentPage;  *pnMax = pcache1.nMaxPage;  *pnMin = pcache1.nMinPage;  *pnRecyclable = nRecyclable;}#endif

⌨️ 快捷键说明

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