There's a fundamental nastiness in making a call to a distributed cache that then accessing the cache in that call.
In Oracle Coherence, if you have something like this:
public class MyEntryProcessor implements Serializable, EntryProcessor {
.
.
public Object process(Entry entry) {
// this doesn't work...
NamedCache myCache = CacheFactory.getCache(CACHE_NAME);
.
.
(where CACHE_NAME is the name of the cache against which you run this entry processor) you'll get:
2014-02-18 17:15:17.909/10.736 Oracle Coherence GE 3.7.1.0 (thread=DistributedCache, member=2): Assertion failed: poll() is a blocking call and cannot be called on the Service thread
(Note: if CACHE_NAME is different to the cache against which we run this entry processor, we still get this problem.).
This is because we "are making a re-entrant call back into a cache service from the service thread or worker thread of a cache service. This is a bad thing to do as you risk deadlocking your cluster by consuming all of the threads in the service." [1]
One way around it is to enforce an access order. "As with traditional locking, using ordered access (for example, service A can call service B, but not vice versa) can help." [2]
public Object process(Entry entry) {
BackingMapManagerContext context = getContext(entry);
Map<Binary, Binary> myCache = getBackingMap(context);
Binary binaryKey = (Binary) context.getKeyToInternalConverter().convert(myKey);
Binary binaryValue = (Binary) context.getValueToInternalConverter().convert(myValue);
boolean wasEmpty = myCache.get(binaryKey) == null;
myCache.put(binaryKey, binaryValue);
return wasEmpty;
}
protected BackingMapManagerContext getContext(Entry entry) {
BinaryEntry binaryEntry = (BinaryEntry) entry;
BackingMapManagerContext context = binaryEntry.getContext();
return context;
}
private Map getBackingMap(BackingMapManagerContext context) {
Map backingMap = context.getBackingMap(CACHE_NAME);
return backingMap;
}
This uses the deprecated BackingMapManagerContext.getBackingMap method but other people seem to have used this approach as well.
[1] Assertion failed: poll() is a blocking call - Oracle Community
[2] Constraints on Re-entrant calls.
In Oracle Coherence, if you have something like this:
public class MyEntryProcessor implements Serializable, EntryProcessor {
.
.
public Object process(Entry entry) {
// this doesn't work...
NamedCache myCache = CacheFactory.getCache(CACHE_NAME);
.
.
(where CACHE_NAME is the name of the cache against which you run this entry processor) you'll get:
2014-02-18 17:15:17.909/10.736 Oracle Coherence GE 3.7.1.0
(Note: if CACHE_NAME is different to the cache against which we run this entry processor, we still get this problem.).
This is because we "are making a re-entrant call back into a cache service from the service thread or worker thread of a cache service. This is a bad thing to do as you risk deadlocking your cluster by consuming all of the threads in the service." [1]
One way around it is to enforce an access order. "As with traditional locking, using ordered access (for example, service A can call service B, but not vice versa) can help." [2]
Another is the slightly hacky:
BackingMapManagerContext context = getContext(entry);
Map<Binary, Binary> myCache = getBackingMap(context);
Binary binaryKey = (Binary) context.getKeyToInternalConverter().convert(myKey);
Binary binaryValue = (Binary) context.getValueToInternalConverter().convert(myValue);
boolean wasEmpty = myCache.get(binaryKey) == null;
myCache.put(binaryKey, binaryValue);
return wasEmpty;
}
protected BackingMapManagerContext getContext(Entry entry) {
BinaryEntry binaryEntry = (BinaryEntry) entry;
BackingMapManagerContext context = binaryEntry.getContext();
return context;
}
private Map
Map
return backingMap;
}
This uses the deprecated BackingMapManagerContext.getBackingMap method but other people seem to have used this approach as well.
[1] Assertion failed: poll() is a blocking call - Oracle Community
[2] Constraints on Re-entrant calls.
No comments:
Post a Comment