transferHandleLockToHandleSet((Long) entry.getKey(),
(Set) entry.getValue());
}
}
LogManager logManager = envImpl.getLogManager();
/*
* Release all read locks, clear lock collection. Optimize for
* the case where there are no read locks.
*/
int numReadLocks = clearReadLocks();
/*
* Log the commit if we ever held any write locks. Note that
* with dbhandle write locks, we may have held the write lock
* but then had it transferred away.
*/
int numWriteLocks = 0;
if (writeInfo != null) {
numWriteLocks = writeInfo.size();
TxnCommit commitRecord =
new TxnCommit(id, lastLoggedLsn);
if (flushSyncBehavior == TXN_SYNC) {
/* Flush and sync required. */
commitLsn = logManager.
logForceFlush(commitRecord, true);
} else if (flushSyncBehavior == TXN_WRITE_NOSYNC) {
/* Flush but no sync required. */
commitLsn = logManager.
logForceFlush(commitRecord, false);
} else {
/* No flush, no sync required. */
commitLsn = logManager.log(commitRecord);
}
/*
* Used to prevent double counting abortLNS if there is
* more then one node with the same abortLSN in this txn.
* Two nodes with the same abortLSN occur when a deleted
* slot is reused in the same txn.
*/
Set alreadyCountedLsnSet = new HashSet();
/* Release all write locks, clear lock collection. */
Iterator iter = writeInfo.values().iterator();
while (iter.hasNext()) {
WriteLockInfo info = (WriteLockInfo) iter.next();
lockManager.release(info.lock, this);
/*
* Count the abortLSN as obsolete. Do not count if a
* slot with a deleted LN was reused
* (abortKnownDeleted), to avoid double counting.
*/
if (info.abortLsn != DbLsn.NULL_LSN &&
!info.abortKnownDeleted) {
Long longLsn = new Long(info.abortLsn);
if (!alreadyCountedLsnSet.contains(longLsn)) {
logManager.countObsoleteNode
(info.abortLsn, null);
alreadyCountedLsnSet.add(longLsn);
}
}
}