You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by ka...@apache.org on 2007/02/04 17:43:40 UTC
svn commit: r503440 -
/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/BasePage.java
Author: kahatlen
Date: Sun Feb 4 08:43:40 2007
New Revision: 503440
URL: http://svn.apache.org/viewvc?view=rev&rev=503440
Log:
DERBY-2107: Move page latching out of the lock manager
Handle latches locally in BasePage instead of going through the lock
manager.
Modified:
db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/BasePage.java
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/BasePage.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/BasePage.java?view=diff&rev=503440&r1=503439&r2=503440
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/BasePage.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/BasePage.java Sun Feb 4 08:43:40 2007
@@ -25,12 +25,6 @@
import org.apache.derby.iapi.services.io.FormatableBitSet;
import org.apache.derby.iapi.services.io.DynamicByteArrayOutputStream;
-import org.apache.derby.iapi.services.io.DynamicByteArrayOutputStream;
-
-import org.apache.derby.iapi.services.locks.C_LockFactory;
-import org.apache.derby.iapi.services.locks.Lockable;
-import org.apache.derby.iapi.services.locks.Latch;
-import org.apache.derby.iapi.services.locks.VirtualLockTable;
import org.apache.derby.iapi.services.sanity.SanityManager;
@@ -46,20 +40,15 @@
import org.apache.derby.iapi.store.raw.Page;
import org.apache.derby.iapi.store.raw.PageKey;
import org.apache.derby.iapi.store.raw.RecordHandle;
-import org.apache.derby.iapi.store.raw.RawStoreFactory;
import org.apache.derby.iapi.store.raw.xact.RawTransaction;
import org.apache.derby.iapi.store.raw.log.LogInstant;
-import org.apache.derby.iapi.store.access.Qualifier;
import org.apache.derby.iapi.store.access.conglomerate.LogicalUndo;
-import org.apache.derby.iapi.types.DataValueDescriptor;
-
import java.io.IOException;
import java.io.OutputStream;
import java.io.ObjectInput;
-import java.util.Hashtable;
import java.util.Observer;
import java.util.Observable;
@@ -85,7 +74,7 @@
**/
-public abstract class BasePage implements Page, Lockable, Observer, TypedFormat
+abstract class BasePage implements Page, Observer, TypedFormat
{
/**
@@ -128,12 +117,6 @@
*/
private int nestedLatch;
- /**
- LockManager held latch during exclusive access.
- When this is not null, latch.getQualifier() == owner
- */
- private Latch myLatch;
-
protected boolean inClean; // is the page being cleaned
/**
@@ -1306,18 +1289,16 @@
releaseExclusive();
}
- /** @see Page#isLatched */
- public boolean isLatched() {
+ /**
+ * Check whether the page is latched.
+ *
+ * @return <code>true</code> if the page is latched, <code>false</code>
+ * otherwise
+ * @see Page#isLatched
+ */
+ public final synchronized boolean isLatched() {
if (SanityManager.DEBUG) {
-
- synchronized(this)
- {
- SanityManager.ASSERT(identity != null);
- if (owner != null) {
- if (owner != myLatch.getQualifier())
- SanityManager.THROWASSERT("Page incorrectly latched - " + owner + " " + myLatch.getQualifier());
- }
- }
+ SanityManager.ASSERT(identity != null);
}
return owner != null;
@@ -1503,88 +1484,6 @@
}
/*
- ** Methods from Lockable, just require a single exclusive locker
- */
-
- /**
- Latch me.
- <BR>
- MT - single thread required (methods of Lockable)
- @see Lockable#lockEvent
- */
- public void lockEvent(Latch lockInfo) {
- if (SanityManager.DEBUG) {
- SanityManager.ASSERT(owner == null, "Should only be called when not locked");
- }
-
- synchronized (this) {
-
- myLatch = lockInfo;
-
- // Move page state from UNLATCHED to PRELATCH, setExclusiveNo*()
- // routines do the work of completing the latch - using the
- // preLatch status. This is so that
- // we don't have to wait for a clean() initiated I/O here while
- // holding the locking system monitor.
- (owner = (BaseContainerHandle) lockInfo.getQualifier()).addObserver(this);
- preLatch = true;
- }
- }
-
- /**
- Is another request compatible, no never.
- <BR> MT - single thread required (methods of Lockable)
- @see Lockable#requestCompatible
- */
- public boolean requestCompatible(Object requestedQualifier, Object grantedQualifier) {
- if (SanityManager.DEBUG) {
- SanityManager.ASSERT(owner != null, "Should only be called when locked");
- }
-
- return false;
- }
-
- /**
- Is another request compatible, no never.
- <BR> MT - single thread required (methods of Lockable)
- @see Lockable#requestCompatible
- */
- public boolean lockerAlwaysCompatible() {
- if (SanityManager.DEBUG) {
- SanityManager.ASSERT(owner != null, "Should only be called when locked");
- }
-
- return false;
- }
-
- /**
- Unlatch me, only to be called from lock manager.
- <BR> MT - single thread required (methods of Lockable)
-
- @see Lockable#requestCompatible
- */
- public void unlockEvent(Latch lockInfo) {
- if (SanityManager.DEBUG) {
- SanityManager.ASSERT(owner != null, "Should only be called when locked");
- }
-
- synchronized (this) {
-
- if (SanityManager.DEBUG) {
- if (nestedLatch != 0)
- SanityManager.THROWASSERT("nestedLatch is non-zero on unlockEvent - value = " + nestedLatch);
- }
-
- owner.deleteObserver(this);
- owner = null;
- myLatch = null;
- if (inClean)
- notifyAll();
- }
- }
-
-
- /*
** Methods of Observer.
*/
@@ -1632,7 +1531,7 @@
MT - thread safe
@exception StandardException Standard Cloudscape policy.
*/
- public void setExclusive(BaseContainerHandle requester)
+ void setExclusive(BaseContainerHandle requester)
throws StandardException {
RawTransaction t = requester.getTransaction();
@@ -1642,7 +1541,7 @@
// If this is the case then during an abort a latch
// request will be made for a latch that is already held.
// We do not allow the latch to be obtained multiple times
- // because i) lock manager might assume latches are exclusive for
+ // because i) latches are exclusive for simplicity and
// performance, ii) holding a page latched means that the page is
// on the container handle's obervers list, if we latched it twice
// then the paeg would have to be on the list twice, which is not supported
@@ -1661,24 +1560,29 @@
nestedLatch++;
return;
}
+
+ // just deadlock out if a transaction tries to double latch the
+ // page while not in abort
}
- // just deadlock out ...
- }
+ while (owner != null) {
+ try {
+ // Expect notify from releaseExclusive().
+ wait();
+ } catch (InterruptedException ie) {
+ throw StandardException.interrupt(ie);
+ }
+ }
- // Latch the page, owner is set through the Lockable call backs.
- t.getLockFactory().latchObject(
- t, this, requester, C_LockFactory.WAIT_FOREVER);
+ preLatch(requester);
- // latch granted, but cleaner may "own" the page.
+ // latch granted, but cleaner may "own" the page.
- if (SanityManager.DEBUG) {
- SanityManager.ASSERT(isLatched(), "page not latched");
- }
+ if (SanityManager.DEBUG) {
+ SanityManager.ASSERT(isLatched(), "page not latched");
+ }
- synchronized (this)
- {
- // lockEvent() will grant latch, even if cleaner "owns" the page.
+ // Latch will be granted, even if cleaner "owns" the page.
// Wait here unil cleaner is done. This is safe as now we own the
// latch, and have yet to do anything to the in-memory data
// structures.
@@ -1724,17 +1628,16 @@
return true;
}
}
- // just deadlock out ...
- }
- // Latch the page, owner is set through the Lockable call backs.
- boolean gotLatch = t.getLockFactory().latchObject(t, this, requester, C_LockFactory.NO_WAIT);
- if (!gotLatch)
- return false;
+ // Pre-latch the page if no one already has latched it or requested
+ // a latch. Otherwise, give up and return false.
+ if (owner == null) {
+ preLatch(requester);
+ } else {
+ return false;
+ }
- synchronized (this)
- {
- // lockEvent() will grant latch, even if cleaner "owns" the page.
+ // Latch will be granted, even if cleaner "owns" the page.
// Wait here unil cleaner is done. This is safe as now we own the
// latch, and have yet to do anything to the in-memory data
// structures.
@@ -1773,7 +1676,7 @@
<BR>
MT - latched
*/
- protected void releaseExclusive() /* throws StandardException */ {
+ protected synchronized void releaseExclusive() {
if (SanityManager.DEBUG) {
if (!isLatched())
@@ -1788,8 +1691,26 @@
return;
}
- RawTransaction t = owner.getTransaction();
- t.getLockFactory().unlatch(myLatch);
+ owner.deleteObserver(this);
+ owner = null;
+ notifyAll();
+ }
+
+ /**
+ * Move page state from UNLATCHED to PRELATCH. setExclusive*() routines do
+ * the work of completing the latch - using the preLatch status.
+ *
+ * @param requester handle to the container requesting ownership
+ */
+ private void preLatch(BaseContainerHandle requester) {
+ if (SanityManager.DEBUG) {
+ SanityManager.ASSERT(!isLatched(),
+ "Attempted to pre-latch a latched page");
+ }
+ owner = requester;
+ // make sure the latch is released if the container is closed
+ requester.addObserver(this);
+ preLatch = true;
}
/*
@@ -2798,39 +2719,4 @@
}
return str;
}
-
- /**
- This lockable wants to participate in the Virtual Lock table.
- */
- public boolean lockAttributes(int flag, Hashtable attributes)
- {
- if (SanityManager.DEBUG)
- {
- SanityManager.ASSERT(attributes != null,
- "cannot call lockProperties with null attribute list");
- }
-
- if ((flag & VirtualLockTable.LATCH) == 0)
- return false;
-
- // by the time this is called, the page may be unlatched.
- PageKey pageId = identity;
-
- // not latched
- if (pageId == null)
- return false;
-
- attributes.put(VirtualLockTable.CONTAINERID,
- new Long(pageId.getContainerId().getContainerId()));
- attributes.put(VirtualLockTable.LOCKNAME, pageId.toString());
- attributes.put(VirtualLockTable.LOCKTYPE, "LATCH");
-
- // don't new unecesary things for now
- // attributes.put(VirtualLockTable.SEGMENTID, new Long(pageId.getContainerId().getSegmentId()));
- // attributes.put(VirtualLockTable.PAGENUM, new Long(pageId.getPageNumber()));
-
- return true;
- }
-
-
}