public RC Fetch(Pid id, bool createFlag, out PgHdr pageOut) { Debug.Assert(id > 0); // If the pluggable cache (sqlite3_pcache*) has not been allocated, allocate it now. if (Cache == null && createFlag) { var p = _pcache.Create(SizePage, SizeExtra + 0, Purgeable); p.Cachesize(get_CacheSize()); Cache = p; } ICachePage page = null; var create = (createFlag ? 1 : 0) * (1 + ((!Purgeable || Dirty == null) ? 1 : 0)); if (Cache != null) { page = Cache.Fetch(id, create > 0); } if (page == null && create == 1) { // 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 EXPENSIVE_ASSERT CheckSynced(this); #endif PgHdr pg; for (pg = Synced; pg != null && (pg.Refs != 0 || (pg.Flags & PgHdr.PGHDR.NEED_SYNC) != 0); pg = pg.DirtyPrev) { ; } Synced = pg; if (pg == null) { for (pg = DirtyTail; pg != null && pg.Refs != 0; pg = pg.DirtyPrev) { ; } } if (pg != null) { #if LOG_CACHE_SPILL SysEx.Log(RC.FULL, "spill page %d making room for %d - cache used: %d/%d", pg.ID, id, _pcache->Pagecount(Cache), NumberOfCachePages(this)); #endif var rc = Stress(StressArg, pg); if (rc != RC.OK && rc != RC.BUSY) { pageOut = null; return(rc); } } page = Cache.Fetch(id, true); } PgHdr pgHdr = null; if (page != null) { //pgHdr = page.Extra; if (page.Data == null) { //page.Page = page; page.Data = C._alloc(SizePage); //page.Extra = this; page.Cache = this; page.ID = id; } Debug.Assert(page.Cache == Cache); Debug.Assert(page.ID == id); //Debug.Assert(page.Data == page.Buffer); //Debug.Assert(page.Extra == this); if (page.Refs == 0) { Refs++; } page.Refs++; if (id == 1) { Page1 = pgHdr; } } pageOut = pgHdr; return(pgHdr == null && create != 0 ? RC.NOMEM : RC.OK); }