Пример #1
0
 // was:sqlite3PagerOpenSavepoint
 public RC OpenSavepoint(int nSavepoint)
 {
     var rc = RC.OK;
     var nCurrent = this.nSavepoint;        // Current number of savepoints
     Debug.Assert(this.eState >= PAGER.WRITER_LOCKED);
     Debug.Assert(assert_pager_state());
     if (nSavepoint > nCurrent && this.useJournal != 0)
     {
         // Grow the Pager.aSavepoint array using realloc(). Return SQLITE_NOMEM if the allocation fails. Otherwise, zero the new portion in case a
         // malloc failure occurs while populating it in the for(...) loop below.
         Array.Resize(ref this.aSavepoint, nSavepoint);
         var aNew = this.aSavepoint; // New Pager.aSavepoint array
         // Populate the PagerSavepoint structures just allocated.
         for (var ii = nCurrent; ii < nSavepoint; ii++)
         {
             aNew[ii] = new PagerSavepoint();
             aNew[ii].nOrig = this.dbSize;
             aNew[ii].iOffset = (this.jfd.IsOpen && this.journalOff > 0 ? this.journalOff : (int)JOURNAL_HDR_SZ(this));
             aNew[ii].iSubRec = this.nSubRec;
             aNew[ii].pInSavepoint = new BitArray(this.dbSize);
             if (pagerUseWal())
                 this.pWal.Savepoint(aNew[ii].aWalData);
             this.nSavepoint = ii + 1;
         }
         Debug.Assert(this.nSavepoint == nSavepoint);
         assertTruncateConstraint();
     }
     return rc;
 }
Пример #2
0
        // was:sqlite3PagerOpenSavepoint
        public RC OpenSavepoint(int nSavepoint)
        {
            var rc       = RC.OK;
            var nCurrent = this.nSavepoint;        // Current number of savepoints

            Debug.Assert(this.eState >= PAGER.WRITER_LOCKED);
            Debug.Assert(assert_pager_state());
            if (nSavepoint > nCurrent && this.useJournal != 0)
            {
                // Grow the Pager.aSavepoint array using realloc(). Return SQLITE_NOMEM if the allocation fails. Otherwise, zero the new portion in case a
                // malloc failure occurs while populating it in the for(...) loop below.
                Array.Resize(ref this.aSavepoint, nSavepoint);
                var aNew = this.aSavepoint; // New Pager.aSavepoint array
                // Populate the PagerSavepoint structures just allocated.
                for (var ii = nCurrent; ii < nSavepoint; ii++)
                {
                    aNew[ii]              = new PagerSavepoint();
                    aNew[ii].nOrig        = this.dbSize;
                    aNew[ii].iOffset      = (this.jfd.IsOpen && this.journalOff > 0 ? this.journalOff : (int)JOURNAL_HDR_SZ(this));
                    aNew[ii].iSubRec      = this.nSubRec;
                    aNew[ii].pInSavepoint = new BitArray(this.dbSize);
                    if (pagerUseWal())
                    {
                        this.pWal.Savepoint(aNew[ii].aWalData);
                    }
                    this.nSavepoint = ii + 1;
                }
                Debug.Assert(this.nSavepoint == nSavepoint);
                assertTruncateConstraint();
            }
            return(rc);
        }
Пример #3
0
        private RC pagerPlaybackSavepoint(PagerSavepoint pSavepoint)
        {
            Debug.Assert(this.eState != PAGER.ERROR);
            Debug.Assert(this.eState >= PAGER.WRITER_LOCKED);
            // Allocate a bitvec to use to store the set of pages rolled back
            BitArray pDone = null;     // Bitvec to ensure pages played back only once

            if (pSavepoint != null)
            {
                pDone = new BitArray(pSavepoint.nOrig);
            }
            // Set the database size back to the value it was before the savepoint being reverted was opened.
            this.dbSize          = pSavepoint != null ? pSavepoint.nOrig : this.dbOrigSize;
            this.changeCountDone = this.tempFile;
            if (!pSavepoint && this.pagerUseWal())
            {
                return(this.pagerRollbackWal());
            }
            // Use pPager.journalOff as the effective size of the main rollback journal.  The actual file might be larger than this in
            // PAGER_JOURNALMODE_TRUNCATE or PAGER_JOURNALMODE_PERSIST.  But anything past pPager.journalOff is off-limits to us.
            var szJ = this.journalOff; // Effective size of the main journal

            Debug.Assert(!this.pagerUseWal() || szJ == 0);
            // Begin by rolling back records from the main journal starting at PagerSavepoint.iOffset and continuing to the next journal header.
            // There might be records in the main journal that have a page number greater than the current database size (pPager.dbSize) but those
            // will be skipped automatically.  Pages are added to pDone as they are played back.
            long iHdrOff;        // End of first segment of main-journal records
            var  rc = RC.OK;     // Return code

            if (pSavepoint != null && !this.pagerUseWal())
            {
                iHdrOff         = (pSavepoint.iHdrOffset != 0 ? pSavepoint.iHdrOffset : szJ);
                this.journalOff = pSavepoint.iOffset;
                while (rc == RC.OK && this.journalOff < iHdrOff)
                {
                    rc = pager_playback_one_page(ref this.journalOff, pDone, 1, 1);
                }
                Debug.Assert(rc != RC.DONE);
            }
            else
            {
                this.journalOff = 0;
            }
            // Continue rolling back records out of the main journal starting at the first journal header seen and continuing until the effective end
            // of the main journal file.  Continue to skip out-of-range pages and continue adding pages rolled back to pDone.
            while (rc == RC.OK && this.journalOff < szJ)
            {
                uint nJRec;         // Number of Journal Records
                uint dummy;
                rc = readJournalHdr(0, szJ, out nJRec, out dummy);
                Debug.Assert(rc != RC.DONE);
                // The "pPager.journalHdr+JOURNAL_HDR_SZ(pPager)==pPager.journalOff" test is related to ticket #2565.  See the discussion in the
                // pager_playback() function for additional information.
                if (nJRec == 0 && this.journalHdr + JOURNAL_HDR_SZ(this) >= this.journalOff)
                {
                    nJRec = (uint)((szJ - this.journalOff) / JOURNAL_PG_SZ(this));
                }
                for (uint ii = 0; rc == RC.OK && ii < nJRec && this.journalOff < szJ; ii++)
                {
                    rc = pager_playback_one_page(ref this.journalOff, pDone, 1, 1);
                }
                Debug.Assert(rc != RC.DONE);
            }
            Debug.Assert(rc != RC.OK || this.journalOff >= szJ);
            // Finally,  rollback pages from the sub-journal.  Page that were previously rolled back out of the main journal (and are hence in pDone)
            // will be skipped.  Out-of-range pages are also skipped.
            if (pSavepoint != null)
            {
                long offset = pSavepoint.iSubRec * (4 + this.pageSize);
                if (this.pagerUseWal())
                {
                    rc = this.pWal.SavepointUndo(pSavepoint.aWalData);
                }
                for (var ii = pSavepoint.iSubRec; rc == RC.OK && ii < this.nSubRec; ii++)
                {
                    Debug.Assert(offset == ii * (4 + this.pageSize));
                    rc = pager_playback_one_page(ref offset, pDone, 0, 1);
                }
                Debug.Assert(rc != RC.DONE);
            }
            BitArray.Destroy(ref pDone);
            if (rc == RC.OK)
            {
                this.journalOff = (int)szJ;
            }
            return(rc);
        }
Пример #4
0
 private RC pagerPlaybackSavepoint(PagerSavepoint pSavepoint)
 {
     Debug.Assert(this.eState != PAGER.ERROR);
     Debug.Assert(this.eState >= PAGER.WRITER_LOCKED);
     // Allocate a bitvec to use to store the set of pages rolled back
     BitArray pDone = null;     // Bitvec to ensure pages played back only once
     if (pSavepoint != null)
         pDone = new BitArray(pSavepoint.nOrig);
     // Set the database size back to the value it was before the savepoint being reverted was opened.
     this.dbSize = pSavepoint != null ? pSavepoint.nOrig : this.dbOrigSize;
     this.changeCountDone = this.tempFile;
     if (!pSavepoint && this.pagerUseWal())
         return this.pagerRollbackWal();
     // Use pPager.journalOff as the effective size of the main rollback journal.  The actual file might be larger than this in
     // PAGER_JOURNALMODE_TRUNCATE or PAGER_JOURNALMODE_PERSIST.  But anything past pPager.journalOff is off-limits to us.
     var szJ = this.journalOff; // Effective size of the main journal
     Debug.Assert(!this.pagerUseWal() || szJ == 0);
     // Begin by rolling back records from the main journal starting at PagerSavepoint.iOffset and continuing to the next journal header.
     // There might be records in the main journal that have a page number greater than the current database size (pPager.dbSize) but those
     // will be skipped automatically.  Pages are added to pDone as they are played back.
     long iHdrOff;             // End of first segment of main-journal records
     var rc = RC.OK;      // Return code
     if (pSavepoint != null && !this.pagerUseWal())
     {
         iHdrOff = (pSavepoint.iHdrOffset != 0 ? pSavepoint.iHdrOffset : szJ);
         this.journalOff = pSavepoint.iOffset;
         while (rc == RC.OK && this.journalOff < iHdrOff)
             rc = pager_playback_one_page(ref this.journalOff, pDone, 1, 1);
         Debug.Assert(rc != RC.DONE);
     }
     else
         this.journalOff = 0;
     // Continue rolling back records out of the main journal starting at the first journal header seen and continuing until the effective end
     // of the main journal file.  Continue to skip out-of-range pages and continue adding pages rolled back to pDone.
     while (rc == RC.OK && this.journalOff < szJ)
     {
         uint nJRec;         // Number of Journal Records
         uint dummy;
         rc = readJournalHdr(0, szJ, out nJRec, out dummy);
         Debug.Assert(rc != RC.DONE);
         // The "pPager.journalHdr+JOURNAL_HDR_SZ(pPager)==pPager.journalOff" test is related to ticket #2565.  See the discussion in the
         // pager_playback() function for additional information.
         if (nJRec == 0 && this.journalHdr + JOURNAL_HDR_SZ(this) >= this.journalOff)
             nJRec = (uint)((szJ - this.journalOff) / JOURNAL_PG_SZ(this));
         for (uint ii = 0; rc == RC.OK && ii < nJRec && this.journalOff < szJ; ii++)
             rc = pager_playback_one_page(ref this.journalOff, pDone, 1, 1);
         Debug.Assert(rc != RC.DONE);
     }
     Debug.Assert(rc != RC.OK || this.journalOff >= szJ);
     // Finally,  rollback pages from the sub-journal.  Page that were previously rolled back out of the main journal (and are hence in pDone)
     // will be skipped.  Out-of-range pages are also skipped.
     if (pSavepoint != null)
     {
         long offset = pSavepoint.iSubRec * (4 + this.pageSize);
         if (this.pagerUseWal())
             rc = this.pWal.SavepointUndo(pSavepoint.aWalData);
         for (var ii = pSavepoint.iSubRec; rc == RC.OK && ii < this.nSubRec; ii++)
         {
             Debug.Assert(offset == ii * (4 + this.pageSize));
             rc = pager_playback_one_page(ref offset, pDone, 0, 1);
         }
         Debug.Assert(rc != RC.DONE);
     }
     BitArray.Destroy(ref pDone);
     if (rc == RC.OK)
         this.journalOff = (int)szJ;
     return rc;
 }