LOG.debug("replace: cache [{}] key [{}] was not in, nothing replaced", cacheName, key);
return null;
} else {
Object value = oldElement.getObjectValue();
if (value instanceof SoftLock) {
SoftLock softLock = (SoftLock) value;
if (cleanupExpiredSoftLock(oldElement, softLock)) {
LOG.debug("replace: cache [{}] key [{}] guarded by expired soft lock, cleaned up {}",
new Object[] {cacheName, key, softLock});
continue;
}
if (softLock.getTransactionID().equals(getCurrentTransactionContext().getTransactionId())) {
Element currentElement = softLock.getElement(getCurrentTransactionContext().getTransactionId());
if (currentElement != null) {
Element replaced = softLock.updateElement(element);
underlyingStore.put(oldElement);
getCurrentTransactionContext().updateSoftLock(cacheName, softLock);
// replaced old element with new one under soft lock, job done.
LOG.debug("replace: cache [{}] key [{}] soft locked in current transaction, replaced old element with" +
" new one under soft lock", cacheName, key);
return copyElementForRead(replaced);
} else {
// old element is not equals to element to remove, job done.
LOG.debug("replace: cache [{}] key [{}] soft locked in current transaction, old element was null," +
" not replaced", cacheName, key);
return null;
}
} else {
try {
LOG.debug("replace: cache [{}] key [{}] soft locked in foreign transaction, waiting {}ms for soft lock" +
" to die...", new Object[] {cacheName, key, timeBeforeTimeout()});
boolean locked = softLock.tryLock(timeBeforeTimeout());
if (!locked) {
LOG.debug("replace: cache [{}] key [{}] soft locked in foreign transaction and not released before" +
" current transaction timeout", cacheName, key);
throw new DeadLockException("deadlock detected in cache [" + cacheName + "] on key [" + key + "]" +
" between current transaction [" + getCurrentTransactionContext().getTransactionId() + "]" +
" and foreign transaction [" + softLock.getTransactionID() + "]");
}
softLock.clearTryLock();
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
}
// once the soft lock got unlocked we don't know what's in the store anymore, restart.
LOG.debug("replace: cache [{}] key [{}] soft locked in foreign transaction, soft lock died, retrying...",
cacheName, key);
continue;
}
} else {
SoftLock softLock = softLockFactory.createSoftLock(getCurrentTransactionContext().getTransactionId(), key,
element, oldElement);
softLock.lock();
Element newElement = createElement(key, softLock);
Element replaced = underlyingStore.replace(newElement);
if (replaced != null) {
// CAS succeeded, value replaced with soft lock, job done.
getCurrentTransactionContext().registerSoftLock(cacheName, this, softLock);
LOG.debug("replace: cache [{}] key [{}] was in, replaced with soft lock", cacheName, key);
return copyElementForRead(replaced);
} else {
// CAS failed, something else with that key is now in store or the key disappeared, job done.
softLock.unlock();
LOG.debug("replace: cache [{}] key [{}] was in, replacement by soft lock failed", cacheName, key);
return null;
}
}
}