true /* stricter OK */ );
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 (work.incrAttempts() < 3) // retry this for serveral times
// 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 code gets here, the space will be lost forever, and
// can only be reclaimed by a full offline compress of the
// table/index.
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;
}
}
// At this point, container is opened with IX lock.
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 /* nowait */))
{
// cannot get the row lock, retry
tran.abort();
if (work.incrAttempts() < 3)
{
return Serviceable.REQUEUE;
}
else
{
// If code gets here, the space will be lost forever, and
// can only be reclaimed by a full offline compress of the
// table/index.
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;
}
}
// The exclusive lock on the head row has been gotten.
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)
{
// It is not clear why headRowPage would be null,
// but logging the failure in case it happens.
// If code gets here, the space will be lost forever, and