Exemplo n.º 1
0
/*
** 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);
    }
}
Exemplo n.º 2
0
/*
** Obtain space for a page. Try to recycle an old page if the limit on the
** number of pages has been reached. If the limit has not been reached or
** there are no pages eligible for recycling, allocate a new page.
**
** Return a pointer to the new page, or NULL if an OOM condition occurs.
*/
static int pcacheRecycleOrAlloc(PCache *pCache, PgHdr **ppPage) {
    PgHdr *p = 0;

    int szPage = pCache->szPage;
    int szExtra = pCache->szExtra;

    assert( pcache.isInit );
    assert( sqlite3_mutex_held(pcache.mutex) );

    *ppPage = 0;

    /* If we have reached the limit for pinned/dirty pages, and there is at
    ** least one dirty page, invoke the xStress callback to cause a page to
    ** become clean.
    */
    expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) );
    expensive_assert( pcacheCheckSynced(pCache) );
    if( pCache->xStress
            && pCache->pDirty
            && pCache->nPinned>=(pcache.nMaxPage+pCache->nMin-pcache.nMinPage)
      ) {
        PgHdr *pPg;
        assert(pCache->pDirtyTail);

        for(pPg=pCache->pSynced;
                pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC));
                pPg=pPg->pPrev
           );
        if( !pPg ) {
            for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pPrev);
        }
        if( pPg ) {
            int rc;
            pcacheExitMutex();
            rc = pCache->xStress(pCache->pStress, pPg);
            pcacheEnterMutex();
            if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ) {
                return rc;
            }
        }
    }

    /* If the global page limit has been reached, try to recycle a page. */
    if( pCache->bPurgeable && pcache.nCurrentPage>=pcache.nMaxPage ) {
        p = pcacheRecyclePage();
    }

    /* If a page has been recycled but it is the wrong size, free it. */
    if( p && (p->pCache->szPage!=szPage || p->pCache->szPage!=szExtra) ) {
        pcachePageFree(p);
        p = 0;
    }

    if( !p ) {
        p = pcachePageAlloc(pCache);
    }

    *ppPage = p;
    return (p?SQLITE_OK:SQLITE_NOMEM);
}
Exemplo n.º 3
0
/*
** 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_g.pStart==0 ){
    PgHdr *p;
    pcacheEnterMutex();
    while( (nReq<0 || nFree<nReq) && (p=pcacheRecyclePage()) ){
      nFree += pcachePageSize(p);
      pcachePageFree(p);
    }
    pcacheExitMutex();
  }
  return nFree;
}