use of org.apache.derby.iapi.services.locks.CompatibilitySpace in project derby by apache.
the class DataDictionaryImpl method startReading.
/*
** Methods related to ModuleControl
*/
/**
* @see org.apache.derby.iapi.sql.dictionary.DataDictionary#startReading
*
* @exception StandardException Thrown on error
*/
public int startReading(LanguageConnectionContext lcc) throws StandardException {
int bindCount = lcc.incrementBindCount();
int localCacheMode;
boolean needRetry = false;
do {
if (needRetry) {
try {
lockFactory.zeroDurationlockObject(lcc.getTransactionExecute().getLockSpace(), cacheCoordinator, ShExQual.SH, C_LockFactory.WAIT_FOREVER);
} catch (StandardException e) {
// DEADLOCK, timeout will not happen with WAIT_FOREVER
lcc.decrementBindCount();
throw e;
}
needRetry = false;
}
synchronized (this) {
localCacheMode = getCacheMode();
/*
** Keep track of how deeply nested this bind() operation is.
** It's possible for nested binding to happen if the user
** prepares SQL statements from within a static initializer
** of a class, and calls a method on that class (or uses a
** field in the class).
**
** If nested binding is happening, we only want to lock the
** DataDictionary on the outermost nesting level.
*/
if (bindCount == 1) {
if (localCacheMode == DataDictionary.COMPILE_ONLY_MODE) {
if (SanityManager.DEBUG) {
SanityManager.ASSERT(ddlUsers == 0, "Cache mode is COMPILE_ONLY and there are DDL users.");
}
/*
** If we deadlock while waiting for a lock,
** then be sure to restore things as they
** were.
*/
boolean lockGranted = false;
try {
// When the C_LockFactory.NO_WAIT is used this
// routine will not throw timeout or deadlock
// exceptions. The boolean returned will indicate
// if the lock was granted or not. If it would
// have had to wait, it just returns immediately
// and returns false.
//
// See if we can get this lock granted without
// waiting (while holding the dataDictionary
// synchronization).
CompatibilitySpace space = lcc.getTransactionExecute().getLockSpace();
lockGranted = lockFactory.lockObject(space, space.getOwner(), cacheCoordinator, ShExQual.SH, C_LockFactory.NO_WAIT);
} catch (StandardException e) {
// neither TIMEOUT or DEADLOCK can happen with
// NO_WAIT flag. This must be some other exception.
lcc.decrementBindCount();
throw e;
}
if (!lockGranted)
needRetry = true;
} else {
readersInDDLMode++;
}
}
}
// end of sync block
} while (needRetry);
return localCacheMode;
}
use of org.apache.derby.iapi.services.locks.CompatibilitySpace in project derby by apache.
the class DataDictionaryImpl method doneReading.
/* @see org.apache.derby.iapi.sql.dictionary.DataDictionary#doneReading */
public void doneReading(int mode, LanguageConnectionContext lcc) throws StandardException {
int bindCount = lcc.decrementBindCount();
/* This is an arbitrary choice of object to synchronize these methods */
synchronized (this) {
/*
** Keep track of how deeply nested this bind() operation is.
** It's possible for nested binding to happen if the user
** prepares SQL statements from within a static initializer
** of a class, and calls a method on that class (or uses a
** field in the class).
**
** If nested binding is happening, we only want to unlock the
** DataDictionary on the outermost nesting level.
*/
if (bindCount == 0) {
if (mode == DataDictionary.COMPILE_ONLY_MODE) {
/*
** Release the share lock that was acquired by the reader when
** it called startReading().
** Beetle 4418, during bind, we may even execute something (eg., in a vti
** constructor) and if a severe error occured, the transaction is rolled
** back and lock released already, so don't try to unlock if statement context
** is cleared.
*/
if ((lcc.getStatementContext() != null) && lcc.getStatementContext().inUse()) {
CompatibilitySpace space = lcc.getTransactionExecute().getLockSpace();
int unlockCount = lockFactory.unlock(space, space.getOwner(), cacheCoordinator, ShExQual.SH);
if (SanityManager.DEBUG) {
if (unlockCount != 1) {
SanityManager.THROWASSERT("unlockCount not " + "1 as expected, it is " + unlockCount);
}
}
}
} else {
readersInDDLMode--;
/*
** We can only switch back to cached (COMPILE_ONLY)
** mode if there aren't any readers that started in
** DDL_MODE. Otherwise we could get a reader
** in DDL_MODE that reads a cached object that
** was brought in by a reader in COMPILE_ONLY_MODE.
** If 2nd reader finished and releases it lock
** on the cache there is nothing to pevent another
** writer from coming along an deleting the cached
** object.
*/
if (ddlUsers == 0 && readersInDDLMode == 0) {
// Until we implement ALTER SEQUENCE, there should be no need
// to clear the sequence cache. Always clearing the sequence cache
// here gives rise to heisenbug DERBY-6595.
clearCaches(false);
setCacheMode(DataDictionary.COMPILE_ONLY_MODE);
}
if (SanityManager.DEBUG) {
SanityManager.ASSERT(readersInDDLMode >= 0, "readersInDDLMode is invalid -- should never be < 0");
}
}
}
}
}
use of org.apache.derby.iapi.services.locks.CompatibilitySpace in project derby by apache.
the class ClassLoaderLock method lockClassLoader.
private boolean lockClassLoader(ShExQual qualifier) throws StandardException {
if (lf == null)
return false;
ClassFactoryContext cfc = (ClassFactoryContext) getContextOrNull(ClassFactoryContext.CONTEXT_ID);
// This method can be called from outside of the database
// engine, in which case tc will be null. In that case
// we lock the class loader only for the duration of
// the loadClass().
CompatibilitySpace lockSpace = null;
if (cfc != null) {
lockSpace = cfc.getLockSpace();
}
if (lockSpace == null)
lockSpace = compat;
Object lockGroup = lockSpace.getOwner();
lf.lockObject(lockSpace, lockGroup, classLoaderLock, qualifier, C_LockFactory.TIMED_WAIT);
return (lockGroup == this);
}
use of org.apache.derby.iapi.services.locks.CompatibilitySpace in project derby by apache.
the class BaseContainer method compressContainer.
/*
** Implementation specific methods
*/
/**
* Release free space to the OS.
* <P>
* As is possible release any free space to the operating system. This
* will usually mean releasing any free pages located at the end of the
* file using the java truncate() interface.
*
* @exception StandardException Standard Derby error policy
*/
public void compressContainer(BaseContainerHandle handle) throws StandardException {
RawTransaction ntt = handle.getTransaction().startNestedTopTransaction();
int mode = handle.getMode();
if (SanityManager.DEBUG) {
SanityManager.ASSERT((mode & ContainerHandle.MODE_FORUPDATE) == ContainerHandle.MODE_FORUPDATE, "addPage handle not for update");
}
// crashed.
if ((mode & ContainerHandle.MODE_CREATE_UNLOGGED) == 0 && (mode & ContainerHandle.MODE_UNLOGGED) == ContainerHandle.MODE_UNLOGGED)
mode &= ~ContainerHandle.MODE_UNLOGGED;
// make a handle which is tied to the ntt, not to the user transaction
// this handle is tied to. The container is already locked by the
// user transaction, open it nolock
BaseContainerHandle allocHandle = (BaseContainerHandle) ntt.openContainer(identity, (LockingPolicy) null, mode);
if (allocHandle == null) {
throw StandardException.newException(SQLState.DATA_ALLOC_NTT_CANT_OPEN, getSegmentId(), getContainerId());
}
CompatibilitySpace cs = ntt.getCompatibilitySpace();
// Latch this container, the commit will release the latch
ntt.getLockFactory().lockObject(cs, ntt, this, null, C_LockFactory.WAIT_FOREVER);
try {
incrementReusableRecordIdSequenceNumber();
compressContainer(ntt, allocHandle);
} finally {
ntt.commit();
ntt.close();
}
}
use of org.apache.derby.iapi.services.locks.CompatibilitySpace in project derby by apache.
the class BaseContainer method addPage.
/**
* Add a page to this container.
*
* <BR> MT - thread aware -
*
* The add page operation involves 2 transactions, one is the user
* transaction (the transaction which owns the passed in handle), the
* other one is a NestedTopTransaction created by this BaseContainer.
*
* The nestedTopTransaction is used by the underlying container to change
* high contention structures, such as link list anchor or bit map pages.
* The nestedTopTransaction commits or aborts before this routine returns.
*
* The user transaction is used to latch the newly created page.
*
* @exception StandardException Standard Derby error policy
*/
public Page addPage(BaseContainerHandle handle, boolean isOverflow) throws StandardException {
RawTransaction ntt = handle.getTransaction().startNestedTopTransaction();
int mode = handle.getMode();
if (SanityManager.DEBUG) {
SanityManager.ASSERT((mode & ContainerHandle.MODE_FORUPDATE) == ContainerHandle.MODE_FORUPDATE, "addPage handle not for update");
}
// crashed.
if ((mode & ContainerHandle.MODE_CREATE_UNLOGGED) == 0 && (mode & ContainerHandle.MODE_UNLOGGED) == ContainerHandle.MODE_UNLOGGED)
mode &= ~ContainerHandle.MODE_UNLOGGED;
// make a handle which is tied to the ntt, not to the user transaction this
// handle is tied to. The container is already locked by the user transaction,
// open it nolock
BaseContainerHandle allocHandle = (BaseContainerHandle) ntt.openContainer(identity, (LockingPolicy) null, mode);
if (allocHandle == null) {
throw StandardException.newException(SQLState.DATA_ALLOC_NTT_CANT_OPEN, getSegmentId(), getContainerId());
}
// Latch this container, the commit will release the latch
CompatibilitySpace cs = ntt.getCompatibilitySpace();
ntt.getLockFactory().lockObject(cs, ntt, this, null, C_LockFactory.WAIT_FOREVER);
BasePage newPage = null;
try {
newPage = newPage(handle, ntt, allocHandle, isOverflow);
} finally {
if (newPage != null) {
// it is ok to commit without syncing, as it is ok if this
// transaction never makes it to the db, if no subsequent
// log record makes it to the log. If any subsequent log
// record is sync'd then this transaction will be sync'd
// as well.
ntt.commitNoSync(Transaction.RELEASE_LOCKS);
} else {
ntt.abort();
}
ntt.close();
}
if (SanityManager.DEBUG) {
SanityManager.ASSERT(newPage.isLatched());
}
if (!this.identity.equals(newPage.getPageId().getContainerId())) {
if (SanityManager.DEBUG) {
SanityManager.THROWASSERT("BaseContainer.addPage(), just got a new page from a different container" + "\n this.identity = " + this.identity + "\n newPage.getPageId().getContainerId() = " + newPage.getPageId().getContainerId() + "\n handle is: " + handle + "\n allocHandle is: " + allocHandle + "\n this container is: " + this);
}
throw StandardException.newException(SQLState.DATA_DIFFERENT_CONTAINER, this.identity, newPage.getPageId().getContainerId());
}
return newPage;
}
Aggregations