

Refactoring of the TreeCache
============================

Revision: $Id: Refactoring.txt,v 1.1.1.1 2005/03/31 10:10:38 belaban Exp $


Available interceptors
----------------------

* CallInterceptor
Performs the actual call on the JBossCache

* LockInterceptor
Performs locking, acquires and release before/after each method if non-transactional, otherwise releases at TX commit

* CreateIfNotExistsInterceptor
Creates a new node if it doesn't exist on put() methods

* CacheStoreInterceptor
Store modifications back to the CacheLoader, on the way out. If non-transactional, does this after each method call,
otherwise at TX commit

* CacheLoaderInterceptor:
Loads element not in the cache from a CacheLoader, on the way in

* UnlockInterceptor:
Releases all locks held by the current thread (n/a if transactions are used)

* ReplicationInterceptor:
Replicates synchronously or asynchronously. When TX: replicate on TX commit (2PC in case of sync repl)











Example scenario
----------------

1. Shared store

       JBossCache (A)                               JBossCache (B)

      CallInterceptor                              CallInterceptor

      LockInterceptor                              LockInterceptor

 CreateIfNotExistsInterceptor                CreateIfNotExistsInterceptor

   [CacheLoaderInterceptor]                     [CacheLoaderInterceptor (loads on the way in)]

      UnlockInterceptor                            UnlockInterceptor
                            (replication)
  [ReplicationInterceptor]  <-----------------  [ReplicationInterceptor]

  [CacheStoreInterceptor]                        [CacheStoreInterceptor (stores on the way out)]

                                                          ^
                                                          |
                                                          | (incoming method call)


JBossCache A and B are 2 nodes in a cluster.
In this case, node B gets an operation, e.g. put(). Its CacheLoaderInterceptor stores the modification in the store,
and its ReplicationInterceptor replicates the call to node A, where the change is applied to the cache (but not
the CacheLoader !). Both ReplicationInterceptors then pass the call on to their respective caches.
The result here is that only the node where the change is made (node B) actually stores to the backend store.


2. Unshared store


      JBossCache (A)                               JBossCache (B)

      CallInterceptor                              CallInterceptor

     LockInterceptor                              LockInterceptor

 CreateIfNotExistsInterceptor                CreateIfNotExistsInterceptor

  [CacheStoreInterceptor]                      [CacheStoreInterceptor (stores on the way out)]

  [CacheLoaderInterceptor]                      [CacheLoaderInterceptor (loads on the way in)]

      UnlockInterceptor                            UnlockInterceptor

                            (replication)
  [ReplicationInterceptor]  <-----------------   [ReplicationInterceptor]

                                                          ^
                                                          |
                                                          | (incoming method call)


In this scenario, both nodes have their own local store. The call is intercepted at node B, which replicates
it across the cluster. Since CacheLoaderInterceptor is now *above* ReplicationInterceptor, rather than *below*,
the modification will be store in *both* local stores (A and B).
We can therefore provide a (1) shared store and (2) unshared store scenario by just configuring the
interceptor chain differently