JBCACHE-538 deals with the fact that in the BR context, transferred state has to be integrated ina different place than indicated by the Fqns included with the transferred state, e.g.
if DataOwner 192.168.1.2:5555 transferred state for a node with Fqn /a, the recipient should integrate it into node /_BUDDY_BACKUP_/192.168.1.2:5555/a
I've realized that my implementation of this for 1.4.0.Alpha was incomplete; the in-memory state was handled correctly, but the persistent state was not handled, and would have been stored in the persistent store under /a.
This is not trivial to fix, because storage of persistent state transfers is done via a call to CacheLoader.storeEntireState(byte), where the byte is the state transferred from the other node. The CacheLoader API does not include a method that says "store this byte, but make sure the data ends up under this Fqn".
ExtendedCacheLoader does expose a more useful method:
void storeState(byte state, Fqn subtree) throws Exception;
the subtree parameter is there so the ExtendedCacheLoader can pass it to any marshalling RegionManager to find a classloader to use to unmarshal the state.
The described behavior of the method could be changed so that if the transferred state does not already sit under the given Fqn, the ExtendedCacheLoader should integrate it under that Fqn.
Unfortunately, doing that means changing the prescribed behavior of an
already existing interface, e.g. from:
/** * Store the given portion of the cache tree's state in secondary storage. * Overwrite whatever is currently in secondary storage. * * @param state the state to store * @param subtree Fqn naming the root (i.e. highest level parent) node of * the subtree included in <code>state</code>. */ void storeState(byte state, Fqn subtree) throws Exception;
/** * Store the given portion of the cache tree's state in secondary storage. * Overwrite whatever is currently in secondary storage. Ensure that * the state is integrated under the given <code>subtree</code>. * * @param state the state to store * @param subtree Fqn naming the root (i.e. highest level parent) node of * the subtree included in <code>state</code>. If the Fqns * of the data included in <code>state</code> are not * already children of <code>subtree</code>, then their * Fqns should be altered to make them children of * <code>subtree</code> before they are persisted. */ void storeState(byte state, Fqn subtree) throws Exception;
Going with this solution has major downsides
1) If BR is used, the configured cache loader must implement ExtendedCacheLoader. Otherwise, we throw an ISE during startService.
2) We're changing behavior of an existing interface.
An alternative is to create yet another interface "BuddyReplicationCacheLoader extends ExtendedCacheLoader", with the only difference being the new Javadoc requirement. This way at least, users with existing custom ExtendedCacheLoader impls will know they need to change behavior to use their cache loader with BR.
Also, the existing DelegatingCacheLoaders don't implement ExtendedCacheLoader. Actually, looking at them they don't properly support the state transfer methods from CacheLoader either.
Thoughts? I should be able to implement either of the above tomorrow (except for dealing with DelegatingCacheLoader) if we decide to go that route.