
$Id: EvictionPolicy.txt 900 2005-12-05 03:17:14Z dhuang $

Defs:
 - Region. A group of nodes where they posses the same eviction policy, e.g., same
   expiratory time. In TreeCache, region is denoted by a fqn, e.g., /company/personnel
   and it is recursive. In speicfying the region, order is important. For example,
   if "/org/jboss/test" specified before "/org/jboss/test/data", then any node under
   "/org/jboss/test/data" belongs to to the first region rather than the second.

   In addition, there is a "_default_" global region that fits everything else. And since
   node creation with an example of "/org/jboss/test/data" will create "/org", "/org/jboss",
   etc., you will have "/org", "/org/jboss", "/org/jboss/test" in the default region instead,
   while "/org/jboss/test/data" in your specified region.

Configuration:
 - EvictionPloicyClass. The policy provider. If empty, means there is no eviction.
 - Policy provider-specific configuration XML element. Algorithm such as LRU has
   different parameters. It will be provided throu the XML Element.

Eviction in TreeCache
=========================

The design in the TreeCache of eviction policy is based on the loosely coupled
observable pattern (albeit still synchronous) where the eviction policy provider
will implement one or two
listener interfaces. It's the policy provider responsibility to decide when to call
back the cache "evict" operation. In addition, the notion of "region" will also be
passed on to the provider during the listening events???

Create linstener events for policy provider to subscribe. When it is time to evict,
the policy provider will call "evict(fqn)" method to remove a resource. The evict
mehtod will also be overridden by TreeCacheAop to specify the aop eviction behavior,
e.g., to invoke removeObject instead.

Here are the new interfaces:

1. Add an evict(fqn) method to the current TreeCache api. This will be called by the
eviction policy provider to remove the entry from the TreeCache. Note that this api
is similar to remove. However, we need to differentiate that since remove is part of
regular api that can determine the age of a node while evict doesn't.

2. In TreeCacheListener, add one more interface: nodeTouched to signal a get
node operation has been performed. Note that we won't support the notion of 'peek'.

Then we will have 3 callbacks: nodeAdded, nodeRemoved, and nodeVisisted. Policy
provider will implement TreeCacheListener to perform whatever necessary of an
eviction algorithm. The provider may eventually called "evict" to kick out old items.

3. There will be a new TreeCacheServiceListener that signal the cache life cycle.
Policy provider will need to know when the cache starts and stops, for instance.

Note that:
1. eviction policy is only applied locally. I.e., if the mode is REPL, only
the local node is evicted and it won't propogate the eviction to other participating
caches. This is necessary because different caches may have different get operations
that will touch the timestamp in the eviction policy algorithm. However, get
operation is not replicated. Therefore, node in cache2 may get evicted even when it is
accessed often in cache1! There is always the question state syncrhonization. This is ok since
if user in cache1 finds out a node does not exist, it should get it from the underlying
database and then put it into the cache. This operation will replicate across the group
and the data will then be syncrhonized.

2. When a node is evicted, it will check if it has children nodes. If it has, it will only
remove the data value in the hashmap (without removing the whole node). If not, the whole
node is removed.

Eviction in TreeCacheAop
==============================

Eviction in TreeCacheAop is quite different in that in aop world, first of all the concept
of a unit is object (which can have multiple nodes and children nodes). Second of all, once
a user obtain a POJO reference, everything is supposed to be transparent, e.g., cache retrieve
and update operations. But if an object is evicted, that means there is no CacheInterceptor
for the POJO, and the contents is not intercepted by the cache. Instead, everything will
be channeled through the in-memory reference. Then a user has no way of knowing this fact!
We could have thrown a runtime exception when a user is accessing a "evicted" node. But this
is intrusive and not ideal.

What we should do then is to evict an object (by removing all the nodes and children nodes).
But we leave the CacheInterceptor for that POJO (and any sub-POJOs). This way, when a user
is using the POJO methods, it will get intercepted by the CacheInterceptor. And if it finds
that the node is empty, then it will also check to see if the eventual invocation from the
in-memory reference is null or not. If not null, we know this is an evicted node and we will
need to populate this object in TreeCacheAop based on the in-memory value.

Or it can also check targetObject to see if it is NULL. If not, we know we have evicted this
node before. We should then populate this object first.

And if it is null, we know the object has been garbage collected by VM. We can safely remove
the CacheInterceptor as well.

Q: What happens if the user never reference it again? The CacheInterceptor can potentially
   sit there forever. We will need another mechanism to garbage collect the idle
   CacheInterceptor!


This way, eviction is done transparently from the end user!

Use cases:

Let's use Person and Address POJO again.

I. No object graph (single object reference)
  - Evict a Person will also evict the associating Address
  - Update a Person will also update the associating Address
  - Update an Address, and it still can be evicted since the parent Person can age out
  - When a user issue a POJO method, if the POJO has been evicted
    * When Person is referenced again, e.g., p.getName(), the value is not in in the cache,
      we then check if targetObject is null. If not, we re-construct it.

II. Object graph (a) -- multiple object references
  - Evict Person A will evict the reference node Address A. But the node in JBossInternal will
    still be around since it has the orther reference. Note that JBossInternal is never part of
    eviction scheme.
    Note that we will need to skip JBossInternal node when doing update/remove events!

  - Update Person A field will also update any children nodes, as usual

III. Object graph (b) -- circular object references
  - Should be the same as II.



10-05 Refactoring eviction policy

1.3 Items:

- Each EvictionAlgorithm will have an associated comparator to sort the
eviction items.

- EvictionPolicy will pretty much have 1-1 relationship with EvictionAlgorithm.

- EvictionTimer thread will walk through each region instead of a fixed
EvictionPolicy. And each region will have an associated  EvictionPolicy.

- Implemention additional eviction policy, like, MRU, LFU

- Think about easy user extension

- externalize bounded buffer size as well

- Can we have a getEvictionRegionManager api inside TreeCache?

- Make configuration part of EvictionAlgorithm rather than part of the Region. Otherwise Region will bloat.

2.0 items:

- Make Region as a first class citizen such that it is visible from TreeCache.
  Each Region will have its associated eviction, marshalling, cacheloader, etc.

- Can we do eviction policy configuration at runtime.
  + add/remove/modify a region at runtime?

- How about an eviction timer thread per region in the future? Make it configuraable

- EvictionPolicy will implement TreeCacheListener instead. Or we can
use an EvictionInterceptor to generate the eviction node event?

