Package org.tmatesoft.sqljet.core.internal

Examples of org.tmatesoft.sqljet.core.internal.ISqlJetPage


             * copy). This page is never written* into the journal file. Unless
             * i==iSkip or the page was not* present in pTo before the copy
             * operation, journal page i from pTo.
             */
            if (i != iSkip && i <= nToPage) {
                ISqlJetPage pDbPage = null;
                pDbPage = pBtTo.pPager.getPage(i);
                try {
                    pDbPage.write();
                    if (i > nFromPage) {
                        /*
                         * Yeah. It seems wierd to call DontWrite() right after
                         * Write(). But* that is because the names of those
                         * procedures do not exactly* represent what they do.
                         * Write() really means "put this page in the* rollback
                         * journal and mark it as dirty so that it will be
                         * written* to the database file later." DontWrite()
                         * undoes the second part of* that and prevents the page
                         * from being written to the database. The* page is
                         * still on the rollback journal, though. And that is
                         * the* whole point of this block: to put pages on the
                         * rollback journal.
                         */
                        pDbPage.dontWrite();
                    }
                } finally {
                    pDbPage.unref();
                }
            }

            /* Overwrite the data in page i of the target database */
            if (i != iSkip && i <= nNewPage) {

                ISqlJetPage pToPage = null;
                long iOff;

                pToPage = pBtTo.pPager.getPage(i);
                pToPage.write();

                for (iOff = (i - 1) * nToPageSize; iOff < i * nToPageSize; iOff += nFromPageSize) {
                    ISqlJetPage pFromPage = null;
                    int iFrom = (int) (iOff / nFromPageSize) + 1;

                    if (iFrom == pBtFrom.PENDING_BYTE_PAGE()) {
                        continue;
                    }

                    pFromPage = pBtFrom.pPager.getPage(iFrom);

                    ISqlJetMemoryPointer zTo = pToPage.getData();
                    ISqlJetMemoryPointer zFrom = pFromPage.getData();
                    int nCopy;

                    int nFrom = 0;
                    int nTo = 0;

                    if (nFromPageSize >= nToPageSize) {
                        nFrom += ((i - 1) * nToPageSize - ((iFrom - 1) * nFromPageSize));
                        nCopy = nToPageSize;
                    } else {
                        nTo += (((iFrom - 1) * nFromPageSize) - (i - 1) * nToPageSize);
                        nCopy = nFromPageSize;
                    }
                    SqlJetUtility.memcpy(zTo, nTo, zFrom, nFrom, nCopy);

                    pFromPage.unref();
                }

                if (pToPage != null) {
                    SqlJetMemPage p = (SqlJetMemPage) pToPage.getExtra();
                    p.isInit = false;
                    pToPage.unref();
                }
            }
        }

        /*
         * If things have worked so far, the database file may need to be*
         * truncated. The complex part is that it may need to be truncated to* a
         * size that is not an integer multiple of nToPageSize - the current*
         * page size used by the pager associated with B-Tree pTo.** For
         * example, say the page-size of pTo is 2048 bytes and the original*
         * number of pages is 5 (10 KB file). If pFrom has a page size of 1024*
         * bytes and 9 pages, then the file needs to be truncated to 9KB.
         */

        ISqlJetFile pFile = pBtTo.pPager.getFile();
        long iSize = (long) nFromPageSize * (long) nFromPage;
        long iNow = (long) ((nToPage > nNewPage) ? nToPage : nNewPage) * (long) nToPageSize;
        long iPending = ((long) pBtTo.PENDING_BYTE_PAGE() - 1) * (long) nToPageSize;

        assert (iSize <= iNow);

        /*
         * Commit phase one syncs the journal file associated with pTo*
         * containing the original data. It does not sync the database file*
         * itself. After doing this it is safe to use OsTruncate() and other*
         * file APIs on the database file directly.
         */
        pBtTo.db = pTo.db;
        pBtTo.pPager.commitPhaseOne(null, true);
        if (iSize < iNow) {
            pFile.truncate(iSize);
        }

        /*
         * The loop that copied data from database pFrom to pTo did not*
         * populate the locking page of database pTo. If the page-size of* pFrom
         * is smaller than that of pTo, this means some data will* not have been
         * copied.** This block copies the missing data from database pFrom to
         * pTo* using file APIs. This is safe because at this point we know that
         * * all of the original data from pTo has been synced into the* journal
         * file. At this point it would be safe to do anything at* all to the
         * database file except truncate it to zero bytes.
         */
        if (nFromPageSize < nToPageSize && iSize > iPending) {
            long iOff;
            for (iOff = iPending; iOff < (iPending + nToPageSize); iOff += nFromPageSize) {
                ISqlJetPage pFromPage = null;
                int iFrom = (int) (iOff / nFromPageSize) + 1;

                if (iFrom == pBtFrom.PENDING_BYTE_PAGE() || iFrom > nFromPage) {
                    continue;
                }

                pFromPage = pBtFrom.pPager.getPage(iFrom);
                ISqlJetMemoryPointer zFrom = pFromPage.getData();
                pFile.write(zFrom, nFromPageSize, iOff);
                pFromPage.unref();
            }
        }

        /* Sync the database file */
        try {
View Full Code Here


        enter();

        try {

            ISqlJetPage pDbPage = null;
            ISqlJetMemoryPointer pP1;

            pBt.db = this.db;

            /*
             * Reading a meta-data value requires a read-lock on page 1 (and
             * hence the sqlite_master table. We grab this lock regardless of
             * whether or not the SQLITE_ReadUncommitted flag is set (the table
             * rooted at page 1 is treated as a special case by queryTableLock()
             * and lockTable()).
             */
            queryTableLock(1, SqlJetBtreeLockMode.READ);

            assert (idx >= 0 && idx <= 15);
            if (pBt.pPage1 != null) {
                /*
                 * The b-tree is already holding a reference to page 1 of the
                 * database file. In this case the required meta-data value can
                 * be read directly from the page data of this reference. This
                 * is slightly faster than* requesting a new reference from the
                 * pager layer.
                 */
                pP1 = pBt.pPage1.aData;
            } else {
                /*
                 * The b-tree does not have a reference to page 1 of the
                 * database file. Obtain one from the pager layer.
                 */
                pDbPage = pBt.pPager.acquirePage(1, true);
                pP1 = pDbPage.getData();
            }

            int pMeta = SqlJetUtility.get4byte(pP1, 36 + idx * 4);

            /*
             * If the b-tree is not holding a reference to page 1, then one was
             * requested from the pager layer in the above block. Release it
             * now.
             */
            if (pBt.pPage1 == null) {
                pDbPage.unref();
            }

            /* Grab the read-lock on page 1. */
            lockTable(1, SqlJetBtreeLockMode.READ);

View Full Code Here

     * This routine updates the pointer map entry for page number 'key' so that
     * it maps to type 'eType' and parent page number 'pgno'. An error code is
     * returned if something goes wrong, otherwise SQLITE_OK.
     */
    public void ptrmapPut(int key, short eType, int parent) throws SqlJetException {
        ISqlJetPage pDbPage; /* The pointer map page */
        ISqlJetMemoryPointer pPtrmap; /* The pointer map data */
        int iPtrmap; /* The pointer map page number */
        int offset; /* Offset in pointer map page */

        assert (mutex.held());
        /*
         * The master-journal page number must never be used as a pointer map
         * page
         */
        assert (!PTRMAP_ISPAGE(PENDING_BYTE_PAGE()));

        assert (autoVacuum);
        if (key == 0) {
            throw new SqlJetException(SqlJetErrorCode.CORRUPT);
        }
        iPtrmap = PTRMAP_PAGENO(key);
        pDbPage = pPager.getPage(iPtrmap);
        offset = PTRMAP_PTROFFSET(iPtrmap, key);
        pPtrmap = pDbPage.getData();

        if (eType != SqlJetUtility.getUnsignedByte(pPtrmap, offset)
                || SqlJetUtility.get4byte(pPtrmap, offset + 1) != parent) {
            TRACE("PTRMAP_UPDATE: %d->(%d,%d)\n", key, eType, parent);
            pDbPage.write();
            SqlJetUtility.putUnsignedByte(pPtrmap, offset, eType);
            SqlJetUtility.put4byte(pPtrmap, offset + 1, parent);
        }
        pDbPage.unref();
    }
View Full Code Here

     * This routine retrieves the pointer map entry for page 'key', writing the
     * type and parent page number to *pEType and *pPgno respectively. An error
     * code is returned if something goes wrong, otherwise SQLITE_OK.
     */
    public void ptrmapGet(int key, short[] pEType, int[] pPgno) throws SqlJetException {
        ISqlJetPage pDbPage; /* The pointer map page */
        int iPtrmap; /* Pointer map page index */
        ISqlJetMemoryPointer pPtrmap; /* Pointer map page data */
        int offset; /* Offset of entry in pointer map */

        assert (mutex.held());

        iPtrmap = PTRMAP_PAGENO(key);
        pDbPage = pPager.acquirePage(iPtrmap, true);
        pPtrmap = pDbPage.getData();

        offset = PTRMAP_PTROFFSET(iPtrmap, key);
        assert (pEType != null && pEType.length > 0);
        pEType[0] = (short) SqlJetUtility.getUnsignedByte(pPtrmap, offset);
        if (pPgno != null && pPgno.length > 0)
            pPgno[0] = SqlJetUtility.get4byte(pPtrmap, offset + 1);

        pDbPage.unref();

        if (pEType[0] < 1 || pEType[0] > 5)
            throw new SqlJetException(SqlJetErrorCode.CORRUPT);
    }
View Full Code Here

     *            Do not load page content if true
     * @return
     * @throws SqlJetException
     */
    public SqlJetMemPage getPage(int pgno, boolean noContent) throws SqlJetException {
        ISqlJetPage pDbPage;
        assert (mutex.held());
        pDbPage = pPager.acquirePage(pgno, !noContent);
        return pageFromDbPage(pDbPage, pgno);
    }
View Full Code Here

     * @return
     * @throws SqlJetException
     */
    SqlJetMemPage getAndInitPage(int pgno) throws SqlJetException {

        ISqlJetPage pDbPage = null;
        SqlJetMemPage pPage = null;

        assert (mutex.held());
        if (pgno == 0) {
            throw new SqlJetException(SqlJetErrorCode.CORRUPT);
View Full Code Here

     * (non-Javadoc)
     *
     * @see org.tmatesoft.sqljet.core.ISqlJetPageCache#cleanAll()
     */
    public void cleanAll() {
        ISqlJetPage p;
        while ((p = pDirty) != null) {
            makeClean(p);
        }
    }
View Full Code Here

         * already held.
         */
        sharedLock();
        assert (state != SqlJetPagerState.UNLOCK);

        final ISqlJetPage page = pageCache.fetch(pageNumber, true);

        if (null == page) {
            throw new SqlJetException(SqlJetErrorCode.INTERNAL, "Page cache is overflow");
        }

        if (null == page.getPager()) {
            /*
             * The pager cache has created a new page. Its content needs to be
             * initialized.
             */
            page.setPager(this);

            int nMax;
            try {
                nMax = getPageCount();
            } catch (SqlJetException e) {
                page.unref();
                throw e;
            }

            if (nMax < pageNumber || memDb || !read) {

                if (pageNumber > mxPgno) {
                    page.unref();
                    throw new SqlJetException(SqlJetErrorCode.FULL);
                }

                SqlJetUtility.memset(page.getData(), (byte) 0, pageSize);
                if (!read) {
                    if (null == page.getFlags())
                        page.setFlags(SqlJetUtility.noneOf(SqlJetPageFlags.class));
                    page.getFlags().add(SqlJetPageFlags.NEED_READ);
                }
                PAGERTRACE("ZERO %s %d\n", PAGERID(), pageNumber);

            } else {
                try {
                    readDbPage(page, pageNumber);
                } catch (SqlJetIOException e) {
                    if (SqlJetIOErrorCode.IOERR_SHORT_READ != e.getIoErrorCode()) {
                        dropPage(page);
                        throw e;
                    }
                }
            }
            page.setHash(pageHash(page));
        } else {
            /* The requested page is in the page cache. */
            assert (pageCache.getRefCount() > 0 || 1 == pageNumber);
            if (read) {
                try {
                    getContent(page);
                } catch (SqlJetException e) {
                    page.unref();
                    throw e;
                }
            }
        }

View Full Code Here

     *
     */
    private long playbackOnePage(boolean isMainJrnl, long pOffset, boolean isSavepnt, BitSet pDone)
            throws SqlJetException {

        ISqlJetPage pPg; /* An existing page in the cache */
        int pgno; /* The page number of a page in journal */
        long cksum; /* Checksum used for sanity checking */
        ISqlJetMemoryPointer aData; /* Temporary storage for the page */
        ISqlJetFile jfd; /* The file descriptor for the journal file */

        assert (isMainJrnl || pDone != null); /*
                                               * pDone always used on
                                               * sub-journals
                                               */
        assert (isSavepnt || pDone == null); /*
                                              * pDone never used on
                                              * non-savepoint
                                              */

        aData = tmpSpace;
        assert (aData != null); /* Temp storage must have already been allocated */

        jfd = (isMainJrnl ? this.jfd : this.sjfd);

        pgno = read32bits(jfd, pOffset);
        jfd.read(aData, pageSize, pOffset + 4);
        pOffset += pageSize + 4 + (isMainJrnl ? 4 : 0);

        /*
         * Sanity checking on the page. This is more important that I originally
         * thought. If a power failure occurs while the journal is being
         * written, it could cause invalid data to be written into the journal.
         * We need to detect this invalid data (with high probability) and
         * ignore it.
         */
        if (pgno == 0 || pgno == PAGER_MJ_PGNO()) {
            throw new SqlJetException(SqlJetErrorCode.DONE);
        }
        if (pgno > dbSize || SqlJetUtility.bitSetTest(pDone, pgno)) {
            return pOffset;
        }
        if (isMainJrnl) {
            cksum = read32bitsUnsigned(jfd, pOffset - 4);
            if (!isSavepnt && cksum(aData) != cksum) {
                throw new SqlJetException(SqlJetErrorCode.DONE);
            }
        }
        if (pDone != null) {
            pDone.set(pgno);
        }

        assert (state == SqlJetPagerState.RESERVED || state.compareTo(SqlJetPagerState.EXCLUSIVE) >= 0);

        /*
         * If the pager is in RESERVED state, then there must be a copy of this
         * page in the pager cache. In this case just update the pager cache,
         * not the database file. The page is left marked dirty in this case.
         *
         * An exception to the above rule: If the database is in no-sync mode
         * and a page is moved during an incremental vacuum then the page may
         * not be in the pager cache. Later: if a malloc() or IO error occurs
         * during a Movepage() call, then the page may not be in the cache
         * either. So the condition described in the above paragraph is not
         * assert()able.
         *
         * If in EXCLUSIVE state, then we update the pager cache if it exists
         * and the main file. The page is then marked not dirty.
         *
         * Ticket #1171: The statement journal might contain page content that
         * is different from the page content at the start of the transaction.
         * This occurs when a page is changed prior to the start of a statement
         * then changed again within the statement. When rolling back such a
         * statement we must not write to the original database unless we know
         * for certain that original page contents are synced into the main
         * rollback journal. Otherwise, a power loss might leave modified data
         * in the database file without an entry in the rollback journal that
         * can restore the database to its original form. Two conditions must be
         * met before writing to the database files. (1) the database must be
         * locked. (2) we know that the original page content is fully synced in
         * the main journal either because the page is not in cache or else the
         * page is marked as needSync==0.
         *
         * 2008-04-14: When attempting to vacuum a corrupt database file, it is
         * possible to fail a statement on a database that does not yet exist.
         * Do not attempt to write if database file has never been opened.
         */
        pPg = lookup(pgno);
        PAGERTRACE("PLAYBACK %s page %d hash(%08x) %s\n", PAGERID(), pgno, dataHash(pageSize, aData),
                (isMainJrnl ? "main-journal" : "sub-journal"));
        if (state.compareTo(SqlJetPagerState.EXCLUSIVE) >= 0
                && (pPg == null || !pPg.getFlags().contains(SqlJetPageFlags.NEED_SYNC)) && null != fd) {
            long ofst = (pgno - 1) * pageSize;
            fd.write(aData, pageSize, ofst);
            if (pgno > dbFileSize) {
                dbFileSize = pgno;
            }
        } else if (!isMainJrnl && pPg == null) {
            /*
             * If this is a rollback of a savepoint and data was not written to
             * the database and the page is not in-memory, there is a potential
             * problem. When the page is next fetched by the b-tree layer, it
             * will be read from the database file, which may or may not be
             * current.
             *
             * There are a couple of different ways this can happen. All are
             * quite obscure. When running in synchronous mode, this can only
             * happen if the page is on the free-list at the start of the
             * transaction, then populated, then moved using
             * sqlite3PagerMovepage().
             *
             * The solution is to add an in-memory page to the cache containing
             * the data just read from the sub-journal. Mark the page as dirty
             * and if the pager requires a journal-sync, then mark the page as
             * requiring a journal-sync before it is written.
             */
            assert (isSavepnt);
            pPg = acquirePage(pgno, true);
            pPg.getFlags().remove(SqlJetPageFlags.NEED_READ);
            pageCache.makeDirty(pPg);
        }
        if (null != pPg) {
            /*
             * No page should ever be explicitly rolled back that is in use,
             * except for page 1 which is held in use in order to keep the lock
             * on the database active. However such a page may be rolled back as
             * a result of an internal error resulting in an automatic call to
             * sqlite3PagerRollback().
             */
            final ISqlJetMemoryPointer pData = pPg.getData();
            SqlJetUtility.memcpy(pData, aData, pageSize);

            if (null != reiniter) {
                reiniter.pageCallback(pPg);
            }

            if (isMainJrnl && (!isSavepnt || journalOff <= journalHdr)) {
                /*
                 * If the contents of this page were just restored from the main
                 * journal file, then its content must be as they were when the
                 * transaction was first opened. In this case we can mark the
                 * page as clean, since there will be no need to write it out to
                 * the.
                 *
                 * There is one exception to this rule. If the page is being
                 * rolled back as part of a savepoint (or statement) rollback
                 * from an unsynced portion of the main journal file, then it is
                 * not safe to mark the page as clean. This is because marking
                 * the page as clean will clear the PGHDR_NEED_SYNC flag. Since
                 * the page is already in the journal file (recorded in
                 * Pager.pInJournal) and the PGHDR_NEED_SYNC flag is cleared, if
                 * the page is written to again within this transaction, it will
                 * be marked as dirty but the PGHDR_NEED_SYNC flag will not be
                 * set. It could then potentially be written out into the
                 * database file before its journal file segment is synced. If a
                 * crash occurs during or following this, database corruption
                 * may ensue.
                 */
                pageCache.makeClean(pPg);
            }
            pPg.setHash(pageHash(pPg));
            /*
             * If this was page 1, then restore the value of Pager.dbFileVers.
             * Do this before any decoding.
             */
            if (pgno == 1) {
View Full Code Here

                            long iSkip = PAGER_MJ_PGNO();
                            int dbSize = this.dbSize;
                            this.dbSize = this.dbOrigSize;
                            for (i = dbSize + 1; i <= this.dbOrigSize; i++) {
                                if (!SqlJetUtility.bitSetTest(pagesInJournal, i) && i != iSkip) {
                                    final ISqlJetPage pg = getPage(i);
                                    pg.write();
                                    pg.unref();
                                }
                            }
                            this.dbSize = dbSize;
                        }

                        writeMasterJournal(master);
                        syncJournal();
                    }
                }

                /* Write all dirty pages to the database file */
                final ISqlJetPage dirtyList = pageCache.getDirtyList();
                writePageList(dirtyList);
                /*
                 * The error might have left the dirty list all fouled up here,
                 * but that does not matter because if the if the dirty list did
                 * get corrupted, then the transaction will roll back and
View Full Code Here

TOP

Related Classes of org.tmatesoft.sqljet.core.internal.ISqlJetPage

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.