}
@Override
public Object perform(InvocationContext ctx) throws Throwable {
Object o;
MVCCEntry e = (MVCCEntry) ctx.lookupEntry(key);
if (e == null && hasFlag(Flag.PUT_FOR_EXTERNAL_READ)) {
successful = false;
return null;
}
//possible as in certain situations (e.g. when locking delegation is used) we don't wrap
if (e == null) return null;
Object entryValue = e.getValue();
if (entryValue != null && putIfAbsent && !e.isRemoved()) {
// Revert assumption that new value is to be committed
e.setChanged(false);
successful = false;
return entryValue;
} else {
notifier.notifyCacheEntryModified(
key, entryValue, entryValue == null, true, ctx, this);
if (value instanceof Delta) {
// magic
Delta dv = (Delta) value;
DeltaAware toMergeWith = null;
if (entryValue instanceof DeltaAware) toMergeWith = (DeltaAware) entryValue;
e.setValue(dv.merge(toMergeWith));
o = entryValue;
e.setLifespan(lifespanMillis);
e.setMaxIdle(maxIdleTimeMillis);
} else {
o = e.setValue(value);
if (e.isRemoved()) {
e.setRemoved(false);
e.setValid(true);
o = null;
}
e.setLifespan(lifespanMillis);
e.setMaxIdle(maxIdleTimeMillis);
}
}
return o;
}