saker.build Documentation TaskDoc JavaDoc
public interface CacheKey<Data, Resource>
Unique identifier for a cache entry.

Implementations of this interface uniquely identify a cached data entry. That means that if two cache keys equal then they compute the same data.

Cache entries are separated into two objects. A Resource, and a Data object. The difference between them that any unmanaged resources (e.g. files, network streams) reside in the Resource, and the Data object is pure data computed based on the Resource. The lifetime of the two objects are managed differently. The Data can be garbage collected at any time, while Resource will be closed when the Data is no longer accessible.

The Data and the Resource objects must never identity equal, and an InvalidCacheKeyImplementationException will be thrown if they do. The Resource must not hold a strong reference to the Data. If it does, the Data will not be garbage collectable.

As a general rule of thumb, the Data and Resource objects should be immutable and hold no state as they can be accessed from multiple agents at the same time. With careful design of the objects, this restriction is not necessary, but recommended.

Implementations can also validate a cache entry, to ensure that always the most up-to-date data is present and recompute it if it's necessary.

When a retrieval is requested from the cache, the cache implementation will check if a cache entry for this key already exists. If it does, validate(Data, Resource) will be called. If it returns false, then the currently allocated resources will be closed, and reallocated using this cache key. If it returns true then the current data will be returned. If the data has been already garbage collected, it will be regenerated using the validated resource.

If no cache entry exists for the retrieval, the allocation and generation will proceed without any validation.

If the cache key implementation throws an error during allocation or generation, the cache entry will be removed completly from the cache, and any open resources will be closed.

The cache implementation uses soft and {linkplain WeakReference weak} references to keep track of the generated Datas. When it detects that they have been garbage collected, then the allocated Resource will be closed sometime in the future via close(Data, Resource), and the cache entry will be completly removed.

It is possible that the Data is garbage collected, and Resource still resides in the cache. When a new cache entry retrieval is done, it can reuse the still available Resource if possible.

Each cache key can specify an expiry timeout for the generated data. The cache implementation will refer to the generated Data using a SoftReference until the timeout expires, then it will be changed to a WeakReference. The granularity of the expiry timeout checking is implementation dependent.

When a cache entry retrieval is requested, the reference to the returned Data will be refreshed to SoftReference, and the expiry timeout is restarted.

When the cache implementation is closed, all cache entries are closed appropriately.

DataThe type of the computed data.
ResourceThe type of the computed resource.
Methods
public Resource
Allocates the Resource for this cache key.
public void
close(Data data, Resource resource)
Closes the objects related to this cache key.
public boolean
Checks if this cache key identifies the same cache entry and computes the same data as the parameter given the same circumstances.
public Data
generate(Resource resource)
Generates the Data for this cache key based on a previously allocated Resource.
public long
Gets the expiry milliseconds of the generated cache Data.
public int
Returns a hash code value for the object.
public boolean
validate(Data data, Resource resource)
Validates the cached data if it's still useable.
public abstract Resource allocate() throws Exception
Allocates the Resource for this cache key.

The result of the allocation must never be null.

The allocated Resource can contain unmanaged data which requires explicit closing of the object. (E.g. file handles, network connections, etc...) Implementations will have an opportunity to close these resources in close(Data, Resource).

If this method throws an exception, the cache entry will be removed for this cache key. Unclosed resources will be closed nonetheless.

The allocated Resource. Non-null.
ExceptionIf allocation of the resource failed. This exception is relayed to the caller.
public abstract void close(Data data, Resource resource) throws Exception
Closes the objects related to this cache key.

Implementations should close unmanaged objects in the allocated Resource.

The Data parameter should not play a role in the closing of the resources, but it is passed to this method nonetheless. If the Data is no longer accessible, null is used.

dataThe generated Data or null if it's no longer available.
resourceThe allocated Resource to close. Never null.
ExceptionIn case of closing errors. Exceptions thrown from this method is usually not relayed to anyone, but printed to an error stream.
public abstract boolean equals(Object obj)
Checks if this cache key identifies the same cache entry and computes the same data as the parameter given the same circumstances.

Indicates whether some other object is "equal to" this one.

The equals method implements an equivalence relation on non-null object references:

  • It is reflexive: for any non-null reference value x, x.equals(x) should return true.
  • It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
  • It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
  • It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
  • For any non-null reference value x, x.equals(null) should return false.

The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).

Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.

true if this object is the same as the obj argument; false otherwise.
public abstract Data generate(Resource resource) throws Exception
Generates the Data for this cache key based on a previously allocated Resource.

The result of the generation must never be null. The previously generated Resource must not hold a strong reference to the returned Data.

The returned Data should not contain any unmanaged data which requires explicit closing of the object. The returned Data might be garbage collected any time in the future when all references are released to it.

If this method throws an exception, the cache entry will be removed for this cache key. Unclosed resources will be closed nonetheless.

resourceThe Resource from a previous allocate() call.
The generated Data.
ExceptionIf allocation of the resource failed. This exception is relayed to the caller.
public abstract long getExpiry()
Gets the expiry milliseconds of the generated cache Data.

After the expiry milliseconds elapse, the cache implementation will convert the soft reference pointing to the generated Data to weak reference. It will result in that the Data will be more easily garbage collected.

If this method returns negative, it will be normalized to 0 (zero).

The milliseconds of expiry.
public abstract int hashCode()
Overridden from: Object
Returns a hash code value for the object. This method is supported for the benefit of hash tables such as those provided by HashMap.

The general contract of hashCode is:

  • Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
  • If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
  • It is not required that if two objects are unequal according to the Object.equals(Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.

As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the Java™ programming language.)

a hash code value for this object.
public abstract boolean validate(Data data, Resource resource)
Validates the cached data if it's still useable.

The Data parameter might be null, if only the Resource is available for validation. Implementations should handle that gracefully.

dataThe generated Data, or null if it is no longer available.
resourceThe allocated Resource. Never null.
true if the passed arguments are in a valid state for usage.