protected Object updateCacheEntry(
ProviderResult result, InternalCacheEntry entry) {
final Object value = result.getValue();
PostSynchronizationAction postSynchronizationAction = null;
synchronized (entry) {
try {
EntryState state = entry.getState();
if (state != EntryState.PENDING) {
throw new IllegalStateException("Expected to be in " +
EntryState.PENDING + " but is in " + state);
}
// If the entry is still in the cache then make sure that
// it is in the correct group.
if (entry.inCache()) {
InternalGroup newGroup = (InternalGroup) result.getGroup();
postSynchronizationAction = updateGroup(entry, newGroup);
}
if (result.isCacheable()) {
// Mark the entry as ready so that other thread will pick
// the value up.
entry.setValue(value);
entry.setState(EntryState.READY);
entry.setExtensionObject(result.getExtensionObject());
entry.setAsyncResult(new AsyncReady(entry));
} else {
// The result is uncacheable so clear the value
// in the entry and mark it as uncacheable.
// This is so that in future concurrent
// requests for this entry will not conflict
// but will instead make simultaneous
// requests to the provider.
entry.setValue(null);
entry.setState(EntryState.UNCACHEABLE);
entry.setExtensionObject(null);
entry.setAsyncResult(new AsyncUncacheable(entry));
}
entry.setThrowable(result.getThrowable());
} finally {
// Make sure that whatever happens that every thread
// waiting on the entry wakes up.
entry.notifyAll();
}
}
// At this point any threads waiting on the entry being updated will
// have been woken up and so the following code could potentially be
// executed by multiple threads at once.
// Perform any post query action. This must be done after the entry
// has been updated to ensure that it is in a consistent state.
if (postSynchronizationAction != null) {
postSynchronizationAction.takeAction();
}
return value;
}