/* ** Try to obtain a page from the cache. */ static int sqlite3PcacheFetch( PCache pCache, /* Obtain the page from this cache */ u32 pgno, /* Page number to obtain */ int createFlag, /* If true, create page if it does not exist already */ ref PgHdr ppPage /* Write the page here */ ) { PgHdr pPage = null; int eCreate; Debug.Assert( pCache != null ); Debug.Assert( createFlag == 1 || createFlag == 0 ); Debug.Assert( pgno > 0 ); /* If the pluggable cache (sqlite3_pcache*) has not been allocated, ** allocate it now. */ if ( null == pCache.pCache && createFlag != 0 ) { sqlite3_pcache p; int nByte; nByte = pCache.szPage + pCache.szExtra + 0;// sizeof( PgHdr ); p = sqlite3GlobalConfig.pcache.xCreate( nByte, pCache.bPurgeable ); //if ( null == p ) //{ // return SQLITE_NOMEM; //} sqlite3GlobalConfig.pcache.xCachesize( p, pCache.nMax ); pCache.pCache = p; } eCreate = createFlag * ( 1 + ( ( !pCache.bPurgeable || null == pCache.pDirty ) ? 1 : 0 ) ); if ( pCache.pCache != null ) { pPage = sqlite3GlobalConfig.pcache.xFetch( pCache.pCache, pgno, eCreate ); } if ( null == pPage && eCreate == 1 ) { PgHdr pPg; /* Find a dirty page to write-out and recycle. First try to find a ** page that does not require a journal-sync (one with PGHDR_NEED_SYNC ** cleared), but if that is not possible settle for any other ** unreferenced dirty page. */ #if SQLITE_ENABLE_EXPENSIVE_ASSERT expensive_assert( pcacheCheckSynced(pCache) ); #endif for ( pPg = pCache.pSynced; pPg != null && ( pPg.nRef != 0 || ( pPg.flags & PGHDR_NEED_SYNC ) != 0 ); pPg = pPg.pDirtyPrev ) ; pCache.pSynced = pPg; if ( null == pPg ) { for ( pPg = pCache.pDirtyTail; pPg != null && pPg.nRef != 0; pPg = pPg.pDirtyPrev ) ; } if ( pPg != null ) { int rc; #if SQLITE_LOG_CACHE_SPILL sqlite3_log(SQLITE_FULL, "spill page %d making room for %d - cache used: %d/%d", pPg->pgno, pgno, sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache), pCache->nMax); #endif rc = pCache.xStress( pCache.pStress, pPg ); if ( rc != SQLITE_OK && rc != SQLITE_BUSY ) { return rc; } } pPage = sqlite3GlobalConfig.pcache.xFetch( pCache.pCache, pgno, 2 ); } if ( pPage != null ) { if ( null == pPage.pData ) { // memset(pPage, 0, sizeof(PgHdr)); pPage.pData = sqlite3Malloc( pCache.szPage );// pPage->pData = (void*)&pPage[1]; //pPage->pExtra = (void*)&((char*)pPage->pData)[pCache->szPage]; //memset(pPage->pExtra, 0, pCache->szExtra); pPage.pCache = pCache; pPage.pgno = pgno; } Debug.Assert( pPage.pCache == pCache ); Debug.Assert( pPage.pgno == pgno ); //assert(pPage->pData == (void*)&pPage[1]); //assert(pPage->pExtra == (void*)&((char*)&pPage[1])[pCache->szPage]); if ( 0 == pPage.nRef ) { pCache.nRef++; } pPage.nRef++; if ( pgno == 1 ) { pCache.pPage1 = pPage; } } ppPage = pPage; return ( pPage == null && eCreate != 0 ) ? SQLITE_NOMEM : SQLITE_OK; }
/* ** Try to obtain a page from the cache. */ static int sqlite3PcacheFetch( PCache pCache, /* Obtain the page from this cache */ u32 pgno, /* Page number to obtain */ int createFlag, /* If true, create page if it does not exist already */ ref PgHdr ppPage /* Write the page here */ ) { PgHdr pPage = null; int eCreate; Debug.Assert(pCache != null); Debug.Assert(createFlag == 1 || createFlag == 0); Debug.Assert(pgno > 0); /* If the pluggable cache (sqlite3_pcache*) has not been allocated, ** allocate it now. */ if (null == pCache.pCache && createFlag != 0) { sqlite3_pcache p; int nByte; nByte = pCache.szPage + pCache.szExtra + 0;// sizeof( PgHdr ); p = sqlite3GlobalConfig.pcache.xCreate(nByte, pCache.bPurgeable); if (null == p) { return(SQLITE_NOMEM); } sqlite3GlobalConfig.pcache.xCachesize(p, pCache.nMax); pCache.pCache = p; } eCreate = createFlag * (1 + ((!pCache.bPurgeable || null == pCache.pDirty) ? 1 : 0)); if (pCache.pCache != null) { pPage = sqlite3GlobalConfig.pcache.xFetch(pCache.pCache, pgno, eCreate); } if (null == pPage && eCreate == 1) { PgHdr pPg; /* Find a dirty page to write-out and recycle. First try to find a ** page that does not require a journal-sync (one with PGHDR_NEED_SYNC ** cleared), but if that is not possible settle for any other ** unreferenced dirty page. */ #if SQLITE_ENABLE_EXPENSIVE_ASSERT expensive_assert(pcacheCheckSynced(pCache)); #endif for (pPg = pCache.pSynced; pPg != null && (pPg.nRef != 0 || (pPg.flags & PGHDR_NEED_SYNC) != 0); pPg = pPg.pDirtyPrev ) { ; } pCache.pSynced = pPg; if (null == pPg) { for (pPg = pCache.pDirtyTail; pPg != null && pPg.nRef != 0; pPg = pPg.pDirtyPrev) { ; } } if (pPg != null) { int rc; rc = pCache.xStress(pCache.pStress, pPg); if (rc != SQLITE_OK && rc != SQLITE_BUSY) { return(rc); } } pPage = sqlite3GlobalConfig.pcache.xFetch(pCache.pCache, pgno, 2); } if (pPage != null) { if (null == pPage.pData) { // memset(pPage, 0, sizeof(PgHdr)); pPage.pData = sqlite3Malloc(pCache.szPage);// pPage->pData = (void*)&pPage[1]; //pPage->pExtra = (void*)&((char*)pPage->pData)[pCache->szPage]; //memset(pPage->pExtra, 0, pCache->szExtra); pPage.pCache = pCache; pPage.pgno = pgno; } Debug.Assert(pPage.pCache == pCache); Debug.Assert(pPage.pgno == pgno); //assert(pPage->pData == (void*)&pPage[1]); //assert(pPage->pExtra == (void*)&((char*)&pPage[1])[pCache->szPage]); if (0 == pPage.nRef) { pCache.nRef++; } pPage.nRef++; if (pgno == 1) { pCache.pPage1 = pPage; } } ppPage = pPage; return((pPage == null && eCreate != 0) ? SQLITE_NOMEM : SQLITE_OK); }