Wednesday, April 08, 2009

Disabling Coherence Cache

Another simple problem: How do I control if certain or all Cache operations should be disabled? By default it is not possible and need some custom coding... How? As usual lets create a cache config..

<cache-config>
<caching-scheme-mapping>
<cache-mapping>
<cache-name>ControllerCache</cache-name>
<scheme-name>some-dist</scheme-name>
</cache-mapping>
<cache-mapping>
<cache-name>ControlledCache</cache-name>
<scheme-name>with-rw-bm</scheme-name>
</cache-mapping>
</caching-scheme-mapping>
<caching-schemes>
<distributed-scheme>
<scheme-name>with-rw-bm</scheme-name>
<service-name>unlimited-partitioned</service-name>
<backing-map-scheme>
<read-write-backing-map-scheme>
<scheme-ref>base-rw-bm</scheme-ref>
</read-write-backing-map-scheme>
</backing-map-scheme>
<autostart>true</autostart>
</distributed-scheme>
<read-write-backing-map-scheme>
<scheme-name>base-rw-bm</scheme-name>
<class-name>ControllerBackingMap</class-name>
<internal-cache-scheme>
<local-scheme/>
</internal-cache-scheme>
</read-write-backing-map-scheme>
</caching-schemes>
</cache-config>
Now lets create the ControllerBackingMap...
public class ControllerBackingMap extends ReadWriteBackingMap 
implements XmlConfigurable, MapListenerSupport.SynchronousListener {
private XmlElement m_config;
private volatile boolean isOkay = true;

public ControllerBackingMap (.,.,.,...) {
super (.,.,.,...);
}
...
public void setConfig (XmlElement xmlElement) {
...
// -- Or pass the cache name as a parameter
NamedCache nCache = CacheFactory.getCache ("ControllerCache");
nCache.addMapListener (this);
}

public void entryInserted (MapEvent evt) {
if (evt.getNewValue() == ....) {
isOkay = false;
}
}

public Object put(final Object oKey, final Object oValue) {
???????
}
....
}
Now what? Lets say we want to disable any Cache puts if something has been inserted in the ControllerCache.. Of course expand it to any specifics keeping the controller cache model. The put () method will look like:
   public Object put(final Object oKey, final Object oValue) {
if (!isOkay) {
throw new RuntimeException("Operation currently blocked");
}
return super.put(oKey, oValue);
}
So here you go, Enjoy!

3 comments:

Robert Varga said...

Hi Ashish,

not bad, one thing though: You should register a synchronous listener because this way there can be a delay in reacting to the replicated cache change. With this delay, the method writing into the replicated cache would return sooner than the writing is actually disabled/enabled everywhere.

Best regards,

Robert

Robert Varga said...

There is another problem:

this way the putAll operation can be broken into half even within a single partition: part of it can succeed then when the listener kicks in, the other part is disabled. Definitely not what you would expect or want.

Robert Varga said...

Oh, and by the way: the isOkay boolean must be volatile.