Search in sources :

Example 11 with Page

use of org.apache.derby.iapi.store.raw.Page in project derby by apache.

the class BTreeController method reclaim_deleted_rows.

/*
	** private Methods of BTreeController
	*/
/**
 * Attempt to reclaim committed deleted rows from the page.
 * <p>
 * Get exclusive latch on page, and then loop backward through
 * page searching for deleted rows which are committed.  The routine
 * assumes that it is called from a transaction which cannot have
 * deleted any rows on the page.  For each deleted row on the page
 * it attempts to get an exclusive lock on the deleted row, NOWAIT.
 * If it succeeds, and since this row did not delete the row then the
 * row must have been deleted by a transaction which has committed, so
 * it is safe to purge the row.  It then purges the row from the page.
 * <p>
 * Note that this routine may remove all rows from the page, it will not
 * attempt a merge in this situation.  This is because this routine is
 * called from split which is attempting an insert on the given page, so
 * it would be a waste to merge the page only to split it again to allow
 * the insert of the row causing the split.
 *
 * @return true if at least one row was purged.  If true, then the routine
 *              will leave the page latched, and the caller will release
 *              the latch by committing or aborting the transaction.  The
 *              latch must be held to end transaction to insure space on
 *              the page remains available for a undo of the purge.
 *
 * @param open_btree The already open btree to use to get latch on page.
 * @param pageno     The page number of the leaf to attempt the reclaim on.
 *
 * @exception  StandardException  Standard exception policy.
 */
private boolean reclaim_deleted_rows(OpenBTree open_btree, long pageno) throws StandardException {
    boolean purged_at_least_one_row = false;
    ControlRow controlRow = null;
    try {
        if ((controlRow = ControlRow.get(open_btree, pageno)) == null)
            return (false);
        LeafControlRow leaf = (LeafControlRow) controlRow;
        BTreeLockingPolicy btree_locking_policy = open_btree.getLockingPolicy();
        // The number records that can be reclaimed is:
        // total recs - control row - recs_not_deleted
        int num_possible_commit_delete = leaf.page.recordCount() - 1 - leaf.page.nonDeletedRecordCount();
        if (num_possible_commit_delete > 0) {
            Page page = leaf.page;
            // RowLocation column is in last column of template.
            FetchDescriptor lock_fetch_desc = RowUtil.getFetchDescriptorConstant(scratch_template.length - 1);
            // have already looked at).
            for (int slot_no = page.recordCount() - 1; slot_no > 0; slot_no--) {
                if (page.isDeletedAtSlot(slot_no)) {
                    // safe to purge it.
                    if (btree_locking_policy.lockScanCommittedDeletedRow(open_btree, leaf, scratch_template, lock_fetch_desc, slot_no)) {
                        // the row is a committed deleted row, purge it.
                        page.purgeAtSlot(slot_no, 1, true);
                        purged_at_least_one_row = true;
                    }
                }
            }
        }
    } catch (java.lang.ClassCastException cce) {
    // because we give up the latch on the leaf before entering this
    // routine, the page might change from a leaf to branch.  If that
    // happens this routine will get a ClassCastException, and we
    // just give up trying to reclaim space.
    } finally {
        if (controlRow != null) {
            if (purged_at_least_one_row) {
                // Set a hint in the page that scans positioned on it
                // need to reposition because rows have disappeared from
                // the page.  If at least one row has been purged, then
                // do not release the latch.  Purge requires latch to
                // be held until commit, where it will be released after
                // the commit log record has been logged.
                controlRow.page.setRepositionNeeded();
            } else {
                // Ok to release latch if no purging has happened.
                controlRow.release();
            }
        }
    }
    return (purged_at_least_one_row);
}
Also used : FetchDescriptor(org.apache.derby.iapi.store.raw.FetchDescriptor) Page(org.apache.derby.iapi.store.raw.Page)

Example 12 with Page

use of org.apache.derby.iapi.store.raw.Page in project derby by apache.

the class DeleteOperation method restoreLoggedRow.

/*
	 * LogicalUndoable methods
	 */
/**
 *		Restore the row stored in the optional data of the log record.
 *
 *		@exception IOException error reading from log stream
 *		@exception StandardException Standard Derby error policy
 */
public void restoreLoggedRow(Object[] row, LimitObjectInput in) throws StandardException, IOException {
    Page p = null;
    try {
        // the optional data is written by the page in the same format it
        // stores record on the page,
        // only a page knows how to restore a logged row back to a storable row
        // first get the page where the insert went even though the row may no
        // longer be there
        p = getContainer().getPage(getPageId().getPageNumber());
        ((BasePage) p).restoreRecordFromStream(in, row);
    } finally {
        if (p != null) {
            p.unlatch();
            p = null;
        }
    }
}
Also used : Page(org.apache.derby.iapi.store.raw.Page) BasePage(org.apache.derby.impl.store.raw.data.BasePage) BasePage(org.apache.derby.impl.store.raw.data.BasePage)

Example 13 with Page

use of org.apache.derby.iapi.store.raw.Page in project derby by apache.

the class D_DiagnosticUtil method diag_dump_page.

/**
 * Dump raw contents of a page.
 * <p>
 * A utility routine that can be called from an ij session that will
 * dump the raw contents of a page, in the raw store dump format.
 *
 * @param db_name       name of the database
 * @param segmentid     segmentid of the table (usually 0)
 * @param containerid   containerid of the table (not conglomid)
 * @param pagenumber    pagenumber of page to dump.
 */
public static void diag_dump_page(String db_name, long segmentid, long containerid, long pagenumber) {
    Transaction xact = null;
    try {
        Object module = getModuleFromDbName(db_name);
        RawStoreFactory store_module = (RawStoreFactory) findServiceModule(module, RawStoreFactory.MODULE);
        xact = store_module.startInternalTransaction(FileContainer.getContextService().getCurrentContextManager());
        ContainerKey id = new ContainerKey(segmentid, containerid);
        ContainerHandle container = xact.openContainer(id, ContainerHandle.MODE_READONLY);
        Page page = container.getPage(pagenumber);
        if (page != null) {
            System.out.println(page.toString());
            page.unlatch();
        } else {
            System.out.println("page " + pagenumber + " not found");
        }
        xact.abort();
        xact.close();
        xact = null;
    } catch (StandardException se) {
        se.printStackTrace();
    } finally {
        if (xact != null) {
            try {
                xact.abort();
                xact.close();
            } catch (StandardException se) {
            }
        }
    }
}
Also used : StandardException(org.apache.derby.shared.common.error.StandardException) Transaction(org.apache.derby.iapi.store.raw.Transaction) Page(org.apache.derby.iapi.store.raw.Page) ContainerKey(org.apache.derby.iapi.store.raw.ContainerKey) RawStoreFactory(org.apache.derby.iapi.store.raw.RawStoreFactory) ContainerHandle(org.apache.derby.iapi.store.raw.ContainerHandle)

Example 14 with Page

use of org.apache.derby.iapi.store.raw.Page in project derby by apache.

the class ReclaimSpaceHelper method reclaimSpace.

/**
 *		Reclaim space based on work.
 */
public static int reclaimSpace(BaseDataFileFactory dataFactory, RawTransaction tran, ReclaimSpace work) throws StandardException {
    if (work.reclaimWhat() == ReclaimSpace.CONTAINER)
        return reclaimContainer(dataFactory, tran, work);
    // Else, not reclaiming container. Get a no-wait shared lock on the
    // container regardless of how the user transaction had the
    // container opened.
    LockingPolicy container_rlock = tran.newLockingPolicy(LockingPolicy.MODE_RECORD, TransactionController.ISOLATION_SERIALIZABLE, true);
    if (SanityManager.DEBUG)
        SanityManager.ASSERT(container_rlock != null);
    ContainerHandle containerHdl = openContainerNW(tran, container_rlock, work.getContainerId());
    if (containerHdl == null) {
        tran.abort();
        if (SanityManager.DEBUG) {
            if (SanityManager.DEBUG_ON(DaemonService.DaemonTrace)) {
                SanityManager.DEBUG(DaemonService.DaemonTrace, " aborted " + work + " because container is locked or dropped");
            }
        }
        if (// retry this for serveral times
        work.incrAttempts() < 3) // it is however, unlikely that three tries will be
        // enough because there is no delay between retries.
        // See DERBY-4059 and DERBY-4055 for details.
        {
            return Serviceable.REQUEUE;
        } else {
            if (SanityManager.DEBUG) {
                if (SanityManager.DEBUG_ON(DaemonService.DaemonTrace)) {
                    SanityManager.DEBUG(DaemonService.DaemonTrace, "  gave up after 3 tries to get container lock " + work);
                }
            }
            return Serviceable.DONE;
        }
    }
    if (work.reclaimWhat() == ReclaimSpace.PAGE) {
        // Reclaiming a page - called by undo of insert which purged the
        // last row off an overflow page. It is safe to reclaim the page
        // without first locking the head row because unlike post commit
        // work, this is post abort work.  Abort is guarenteed to happen
        // and to happen only once, if at all.
        Page p = containerHdl.getPageNoWait(work.getPageId().getPageNumber());
        if (p != null)
            containerHdl.removePage(p);
        tran.commit();
        return Serviceable.DONE;
    }
    // We are reclaiming row space or long column.
    // First get an xlock on the head row piece.
    RecordHandle headRecord = work.getHeadRowHandle();
    if (!container_rlock.lockRecordForWrite(tran, headRecord, false, /* not insert */
    false)) {
        // cannot get the row lock, retry
        tran.abort();
        if (work.incrAttempts() < 3) {
            return Serviceable.REQUEUE;
        } else {
            if (SanityManager.DEBUG) {
                if (SanityManager.DEBUG_ON(DaemonService.DaemonTrace)) {
                    SanityManager.DEBUG(DaemonService.DaemonTrace, "  gave up after 3 tries to get row lock " + work);
                }
            }
            return Serviceable.DONE;
        }
    }
    if (work.reclaimWhat() == ReclaimSpace.ROW_RESERVE) {
        // This row may benefit from compaction.
        containerHdl.compactRecord(headRecord);
        // This work is being done - post commit, there is no user
        // transaction that depends on the commit being sync'd.  It is safe
        // to commitNoSync() This do as one of 2 things will happen:
        // 
        // 1) if any data page associated with this transaction is
        // moved from cache to disk, then the transaction log
        // must be sync'd to the log record for that change and
        // all log records including the commit of this xact must
        // be sync'd before returning.
        // 
        // 2) if the data page is never written then the log record
        // for the commit may never be written, and the xact will
        // never make to disk.  This is ok as no subsequent action
        // depends on this operation being committed.
        // 
        tran.commitNoSync(Transaction.RELEASE_LOCKS);
        return Serviceable.DONE;
    } else {
        if (SanityManager.DEBUG)
            SanityManager.ASSERT(work.reclaimWhat() == ReclaimSpace.COLUMN_CHAIN);
        // Reclaiming a long column chain due to update.  The long column
        // chain being reclaimed is the before image of the update
        // operation.
        // 
        long headPageId = ((PageKey) headRecord.getPageId()).getPageNumber();
        // DERBY-4050 - we wait for the page so we don't have to retry.
        // prior to the 4050 fix, we called getPageNoWait and just
        // retried 3 times.  This left unreclaimed space if we were
        // not successful after three tries.
        StoredPage headRowPage = (StoredPage) containerHdl.getPage(headPageId);
        if (headRowPage == null) {
            if (SanityManager.DEBUG) {
                if (SanityManager.DEBUG_ON(DaemonService.DaemonTrace)) {
                    SanityManager.DEBUG(DaemonService.DaemonTrace, "gave up because hadRowPage was null" + work);
                }
            }
            tran.abort();
            return Serviceable.DONE;
        }
        try {
            headRowPage.removeOrphanedColumnChain(work, containerHdl);
        } finally {
            headRowPage.unlatch();
        }
        // This work is being done - post commit, there is no user
        // transaction that depends on the commit being sync'd.  It is safe
        // to commitNoSync() This do as one of 2 things will happen:
        // 
        // 1) if any data page associated with this transaction is
        // moved from cache to disk, then the transaction log
        // must be sync'd to the log record for that change and
        // all log records including the commit of this xact must
        // be sync'd before returning.
        // 
        // 2) if the data page is never written then the log record
        // for the commit may never be written, and the xact will
        // never make to disk.  This is ok as no subsequent action
        // depends on this operation being committed.
        // 
        tran.commitNoSync(Transaction.RELEASE_LOCKS);
        return Serviceable.DONE;
    }
}
Also used : PageKey(org.apache.derby.iapi.store.raw.PageKey) RecordHandle(org.apache.derby.iapi.store.raw.RecordHandle) Page(org.apache.derby.iapi.store.raw.Page) BasePage(org.apache.derby.impl.store.raw.data.BasePage) LockingPolicy(org.apache.derby.iapi.store.raw.LockingPolicy) RawContainerHandle(org.apache.derby.iapi.store.raw.data.RawContainerHandle) ContainerHandle(org.apache.derby.iapi.store.raw.ContainerHandle)

Example 15 with Page

use of org.apache.derby.iapi.store.raw.Page in project derby by apache.

the class BaseDataFileFactory method addContainer.

/**
 * Add a container with a specified page size to a segment.
 *		@exception StandardException Standard Derby error policy
 */
public long addContainer(RawTransaction t, long segmentId, long input_containerid, int mode, Properties tableProperties, int temporaryFlag) throws StandardException {
    if (SanityManager.DEBUG) {
        if ((mode & ContainerHandle.MODE_CREATE_UNLOGGED) != 0)
            SanityManager.ASSERT((mode & ContainerHandle.MODE_UNLOGGED) != 0, "cannot have CREATE_UNLOGGED set but UNLOGGED not set");
    }
    // If client has provided a containerid then use it, else use the
    // internally generated one from getNextId().
    long containerId = ((input_containerid != ContainerHandle.DEFAULT_ASSIGN_ID) ? input_containerid : getNextId());
    ContainerKey identity = new ContainerKey(segmentId, containerId);
    boolean tmpContainer = (segmentId == ContainerHandle.TEMPORARY_SEGMENT);
    ContainerHandle ch = null;
    LockingPolicy cl = null;
    if (!tmpContainer) {
        if (isReadOnly()) {
            throw StandardException.newException(SQLState.DATA_CONTAINER_READ_ONLY);
        }
        cl = t.newLockingPolicy(LockingPolicy.MODE_CONTAINER, TransactionController.ISOLATION_SERIALIZABLE, true);
        if (SanityManager.DEBUG)
            SanityManager.ASSERT(cl != null);
        ch = t.openContainer(identity, cl, (ContainerHandle.MODE_FORUPDATE | ContainerHandle.MODE_OPEN_FOR_LOCK_ONLY));
    }
    FileContainer container = (FileContainer) containerCache.create(identity, tableProperties);
    // create the first alloc page and the first user page,
    // if this fails for any reason the transaction
    // will roll back and the container will be dropped (removed)
    ContainerHandle containerHdl = null;
    Page firstPage = null;
    try {
        // make sure to open it with IS_KEPT too.
        if (tmpContainer && ((temporaryFlag & TransactionController.IS_KEPT) == TransactionController.IS_KEPT)) {
            mode |= ContainerHandle.MODE_TEMP_IS_KEPT;
        }
        // open no-locking as we already have the container locked
        containerHdl = t.openContainer(identity, null, (ContainerHandle.MODE_FORUPDATE | mode));
        // we just added it, containerHdl should not be null
        if (SanityManager.DEBUG)
            SanityManager.ASSERT(containerHdl != null);
        if (!tmpContainer) {
            // make it persistent (in concept if not in reality)
            RawContainerHandle rch = (RawContainerHandle) containerHdl;
            ContainerOperation lop = new ContainerOperation(rch, ContainerOperation.CREATE);
            // mark the container as pre-dirtied so that if a checkpoint
            // happens after the log record is sent to the log stream, the
            // cache cleaning will wait for this change.
            rch.preDirty(true);
            try {
                t.logAndDo(lop);
                // flush the log to reduce the window between where
                // the container is created & synced and the log record
                // for it makes it to disk. If we fail in this
                // window we will leave a stranded container file.
                flush(t.getLastLogInstant());
            } finally {
                // in case logAndDo fail, make sure the container is not
                // stuck in preDirty state.
                rch.preDirty(false);
            }
        }
        firstPage = containerHdl.addPage();
    } finally {
        if (firstPage != null) {
            firstPage.unlatch();
            firstPage = null;
        }
        containerCache.release(container);
        if (containerHdl != null) {
            containerHdl.close();
            containerHdl = null;
        }
        if (!tmpContainer) {
            // this should do nothing, since we requested isolation 3
            // but we can't assume that, so call the policy correctly.
            cl.unlockContainer(t, ch);
        }
    }
    return containerId;
}
Also used : Page(org.apache.derby.iapi.store.raw.Page) RawContainerHandle(org.apache.derby.iapi.store.raw.data.RawContainerHandle) ContainerKey(org.apache.derby.iapi.store.raw.ContainerKey) LockingPolicy(org.apache.derby.iapi.store.raw.LockingPolicy) RawContainerHandle(org.apache.derby.iapi.store.raw.data.RawContainerHandle) ContainerHandle(org.apache.derby.iapi.store.raw.ContainerHandle) StreamContainerHandle(org.apache.derby.iapi.store.raw.StreamContainerHandle)

Aggregations

Page (org.apache.derby.iapi.store.raw.Page)28 DataValueDescriptor (org.apache.derby.iapi.types.DataValueDescriptor)11 ContainerHandle (org.apache.derby.iapi.store.raw.ContainerHandle)10 RecordHandle (org.apache.derby.iapi.store.raw.RecordHandle)9 FetchDescriptor (org.apache.derby.iapi.store.raw.FetchDescriptor)5 LockingPolicy (org.apache.derby.iapi.store.raw.LockingPolicy)4 ContainerKey (org.apache.derby.iapi.store.raw.ContainerKey)3 Transaction (org.apache.derby.iapi.store.raw.Transaction)2 RawContainerHandle (org.apache.derby.iapi.store.raw.data.RawContainerHandle)2 OpenConglomerate (org.apache.derby.impl.store.access.conglomerate.OpenConglomerate)2 BasePage (org.apache.derby.impl.store.raw.data.BasePage)2 Properties (java.util.Properties)1 FormatableBitSet (org.apache.derby.iapi.services.io.FormatableBitSet)1 DynamicCompiledOpenConglomInfo (org.apache.derby.iapi.store.access.DynamicCompiledOpenConglomInfo)1 TransactionManager (org.apache.derby.iapi.store.access.conglomerate.TransactionManager)1 PageKey (org.apache.derby.iapi.store.raw.PageKey)1 PageTimeStamp (org.apache.derby.iapi.store.raw.PageTimeStamp)1 RawStoreFactory (org.apache.derby.iapi.store.raw.RawStoreFactory)1 StreamContainerHandle (org.apache.derby.iapi.store.raw.StreamContainerHandle)1 RawTransaction (org.apache.derby.iapi.store.raw.xact.RawTransaction)1