Exemplo n.º 1
0
        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);
        }