*/
public void lockPage(int pageId) throws CouldNotLockPageException
{
final Thread thread = Thread.currentThread();
final PageLock lock = new PageLock(pageId, thread);
final Time start = Time.now();
boolean locked = false;
final boolean isDebugEnabled = logger.isDebugEnabled();
while (!locked && start.elapsedSince().lessThan(timeout))
{
if (isDebugEnabled)
{
logger.debug("'{}' attempting to acquire lock to page with id '{}'",
thread.getName(), pageId);
}
PageLock previous = locks.get().putIfAbsent(pageId, lock);
if (previous == null || previous.getThread() == thread)
{
// first thread to acquire lock or lock is already owned by this thread
locked = true;
}
else
{
// wait for a lock to become available
long remaining = remaining(start, timeout);
if (remaining > 0)
{
synchronized (previous)
{
if (isDebugEnabled)
{
logger.debug("{} waiting for lock to page {} for {}", new Object[] {
thread.getName(), pageId, Duration.milliseconds(remaining) });
}
try
{
previous.wait(remaining);
}
catch (InterruptedException e)
{
// TODO better exception
throw new RuntimeException(e);
}
}
}
}
}
if (locked)
{
if (isDebugEnabled)
{
logger.debug("{} acquired lock to page {}", thread.getName(), pageId);
}
}
else
{
if (logger.isWarnEnabled())
{
logger.warn(
"{} failed to acquire lock to page {}, attempted for {} out of allowed {}",
new Object[] { thread.getName(), pageId, start.elapsedSince(), timeout });
}
throw new CouldNotLockPageException(pageId, thread.getName(), timeout);
}
}