net.java.ao.cache
Interface CacheLayer


public interface CacheLayer

Superinterface for classes which manage the cache semantics for specific entity values. Implementations of this interface are what actually handle the meat of the cache operation, using resources allocated within the corresponding Cache implementation.

The basic cache model is that of the Map interface (which is logical as ActiveObjects was originally cached with a conventional HashMap). Values are stored in the cache based on String keys. These values must be typed within the cache and returned in their proper type, up-cast to Object. This is extremely important since AO will assume that values can be cast to their appropriate types within code which uses the cache. Thus, any cache implementation must also store value types in its implementation. It is also critical that any cache implementation be able to store null values. Technically, null values may be dropped for non-dirty fields, but this will lead to decreased performance in the entity accessor algorithm. Null keys need not be accepted.

Cache bindings themselves need not be persistent. For example, it is strongly encouraged to implement value expiry on implementations with a distributed backend. Likewise, local caches may take into account finite resources (such as memory). There is nothing in the ActiveObjects core implementation which assumes that bindings will be persistent for any length of time. In fact, it is technically permissible to implement a cache layer which does not cache at all, but simply responds appropriately when invoked. Note that while this is certainly possible, it would be quite detrimental to performance. Implementations should make the utmost effort to ensure that key,value bindings persist for as long as possible. The values themselves will never become stale (out of sync with the DB) unless the cache is being accessed by multiple instnaces of AO.

It is important to note that all of the methods in the interface must be implemented for ActiveObjects to function properly. A few of the methods may be omitted without affecting critical functionality, but this should not be assumed. This fact is especially important to keep in mind when working with limitted cache backends (such as memcached). By whatever means necessary, the contract must be fullfilled.

Concurrency must be considered for all implementations, but especially those with a distributed backend. ActiveObjects does not synchronize calls to the cache, that task is left up to the cache implementation itself. Due to the fact that entire code blocks are not locked against the cache, ActiveObjects is inherantly prone to race conditions and stale data in distributed caches. This is a design decision which may change in future, but for now it remains due to performance and stability concerns. For this reason, caches with distributed backends (such as memcached) are encouraged to set a sufficiently short default timeout to allow invalid data to simply expire naturally.

Except in odd cases, CacheLayer implementations should not manage volatile resources themselves. All of this work should be handled within the corresponding ValueCache implementation. The general rule of thumb is that the value cache handles the "what" while the cache layer manages the "how".

Author:
Daniel Spiewak
See Also:
Cache

Method Summary
 void clear()
          Removes all bindings, effectively flushing the cache.
 void clearDirty()
          Removes all fields from the dirty set, implicitly marking all fields as "in sync" with the database.
 void clearFlush()
           
 boolean contains(String field)
          Determines if a binding is present which corresponds to the given key.
 boolean dirtyContains(String field)
          Determines if a given field is in the set of dirty fields (has been locally modified).
 Object get(String field)
          Retrieves a typed value from the cache based on the given String key.
 String[] getDirtyFields()
          Retrieves the set of all dirty fields in no particular order.
 Class<? extends RawEntity<?>>[] getToFlush()
           
 void markDirty(String field)
          Adds a given field to the set of dirty fields (fields which have been modified without being persisted back to the DB).
 void markToFlush(Class<? extends RawEntity<?>> type)
           
 void put(String field, Object value)
          Stores a typed value in the cache, indexed by the given String key.
 void remove(String field)
          Removes the binding for a specified key, deleting the association from the cache.
 

Method Detail

put

void put(String field,
         Object value)
Stores a typed value in the cache, indexed by the given String key. If the key is already assigned, its value should be overwritten.

Parameters:
field - The key which should be assigned to the given value.
value - The value to be stored (may be null).

get

Object get(String field)
Retrieves a typed value from the cache based on the given String key. Even with a non-native cache backend, all values returned from the get(String) method must be of the same type with which they were stored. If this contract is not observed, a ClassCastException will be thrown on some entity operations.

Parameters:
field - The key for which the corresponding value should be retrieved.
Returns:
The value which corresponds to the given key, or null if no binding is found (or if the value itself is null).

remove

void remove(String field)
Removes the binding for a specified key, deleting the association from the cache. From an implementation standpoint, the cache itself need not discard the value when its binding is removed, it must simply return null for any future calls to get(String) on that key, as well as false for any calls to contains(String).

Parameters:
field - The key which indexes the binding to be removed.

contains

boolean contains(String field)
Determines if a binding is present which corresponds to the given key. Note that this method cannot simply check for a null value as ActiveObjects may store nulls within the cache. If this method is inconsistent in its implementation, very strange things will happen on all entity calls.

Parameters:
field - The key for which a binding may be found.
Returns:
true if the cache contains a binding for the given key, false otherwise.

clear

void clear()
Removes all bindings, effectively flushing the cache. As with remove(String), values need not actually be deleted, but the bindings must become void.


markDirty

void markDirty(String field)
Adds a given field to the set of dirty fields (fields which have been modified without being persisted back to the DB). At the very least, this method must append the field to the set of dirty fields (as returned from getDirtyFields()). However, secondary actions are also permitted (such as flagging the field for a preemptive, local cache).

Parameters:
field - The field which has been locally modified.

getDirtyFields

String[] getDirtyFields()
Retrieves the set of all dirty fields in no particular order.

Returns:
The set of all fields which have been locally modified.
See Also:
markDirty(String)

dirtyContains

boolean dirtyContains(String field)
Determines if a given field is in the set of dirty fields (has been locally modified). Correct implementation of this method is critical to the functionality of the RawEntity.save() method.

Parameters:
field - The field which may be dirty.
Returns:
true if the field is dirty, false otherwise.

clearDirty

void clearDirty()
Removes all fields from the dirty set, implicitly marking all fields as "in sync" with the database. As with the markDirty(String) method, the implementation must at the minimum clear the set of all dirty fields. However, other side effects (like resyncing with a distributed cache) may also be implemented.


markToFlush

void markToFlush(Class<? extends RawEntity<?>> type)

getToFlush

Class<? extends RawEntity<?>>[] getToFlush()

clearFlush

void clearFlush()


Copyright © 2007-2013. All Rights Reserved.