/*
* This file is part of the HyperGraphDB source distribution. This is copyrighted
* software. For permitted uses, licensing options and redistribution, please see
* the LicensingInformation file at the root level of the distribution.
*
* Copyright (c) 2005-2010 Kobrix Software, Inc. All rights reserved.
*/
package org.hypergraphdb;
import org.hypergraphdb.cache.HGCache;
import org.hypergraphdb.handle.HGLiveHandle;
/**
* <p>The <code>HGAtomCache</code> interface abstracts the HyperGraph
* caching activities in order for different caching policies and implementations
* to be configured and plugged. A successful caching policy will largely depend
* on a particular application. For instance, some applications may maintain most HyperGraph
* atoms within their own data structures whilst others would entirely rely on HyperGraph
* and continuously query for atoms on a need by need basis.
* </p>
*
* <p>
* The cache is reminiscent to a memory manager. Both HyperGraph and its
* HGTypeSystem rely on the cache to manage live vs. persistent information.
* </p>
*
* <p>
* This interface is made public in order to allow for custom plugging of atom caching
* policies. It is <strong>never</strong> to be used directly be applications.
* </p>
*
* <p>
* The <code>HGAtomCache</code> is responsible for the following:
*
* <ul>
* <li>Manage run-time instances of atoms.</li>
* <li>Create live handle for newly loaded atoms.</li>
* <li>Generate an <code>HGAtomEvictedEvent</code> for every atom that is removed
* from the cache.</li>
* <li>Cache and manages incidence sets on a per-atom basis.</li>
* <li>Provide mappings between atoms' live handles and their persistence handles.</li>
* </ul>
* </p>
*/
public interface HGAtomCache
{
/**
* <p>
* Set the <code>HyperGraph</code> within which this cache is operating. A given
* cache implementation may or may not need a reference to the <code>HyperGraph</code>
* instance, depending on the level of sophistication of the cache. For example,
* some cache policies may want to persist certain usage statistics in the
* <code>HGStore</code>, others may want to attach particular importance to certain
* atom types etc.
* </p>
*
* @param hg The <code>HyperGraph</code> instance.
*/
void setHyperGraph(final HyperGraph hg);
/**
* <p>
* Inform the cache that a new atom has just been added to the database.
* The cache is free to decide whether that atom should be actually cached or not,
* but in any case it must construct and return <code>HGLiveHandle</code> for
* the atom.
* </p>
*
* @param pHandle The persistent handle of the atom.
* @param atom The run-time instance of the atom.
* @param attrib Atom management related attributes that must be stored as part of its live handle.
* @return A valid <code>HGLiveHandle</code> to the atom.
*/
HGLiveHandle atomAdded(final HGPersistentHandle pHandle, final Object atom, final HGAtomAttrib attrib);
/**
* <p>
* Inform the cache that an atom has just been read from persistent storage.
* The cache is free to decide whether that atom should be actually cached or not,
* but in any case it must construct and return <code>HGLiveHandle</code> for
* the atom.
* </p>
*
* <p>
* If the atom corresponding to specified persistent handle is already in the cache,
* it should be replaced with the new passed in value.
* </p>
*
* @param pHandle The persistent handle of the atom.
* @param atom The run-time instance of the atom.
* @param attrib Atom management related attributes that must be stored as part of its live handle.
* @return A valid <code>HGLiveHandle</code> to the atom.
*/
HGLiveHandle atomRead(final HGPersistentHandle pHandle, final Object atom, final HGAtomAttrib attrib);
/**
* <p>
* Inform the cache that an atom with system-level attributes has been loaded.
* This has the same function as the simpler version of <code>atomRead</code>, but
* the cache must construct an instance of <code>HGExtLiveHandle</code> for purposes
* of <em>non-default</em> atom management.
* </p>
*
* @param pHandle The persistent handle of the atom.
* @param atom The run-time instance of the atom.
* @param flags The system flags for this atom.
* @param retrievalCount The recorded overall retrieval count for this atom.
* @param lastAccessTime A timestamps (in milliseconds) representing the last
* time this atom was accessed.
* @return A <code>HGManagedLiveHandle</code> encapsulating the atom instance,
* persistence handle and system-level attributes.
*/
// HGManagedLiveHandle atomRead(final HGPersistentHandle pHandle,
// final Object atom,
// final byte flags,
// final long retrievalCount,
// final long lastAccessTime);
/**
* <p>Replace the runtime instance of an atom with a new value. This method is invoked when <code>HyperGraph</code>
* needs to inform the cache about a change of the value of an atom. The cache must
* assign the new reference to the cached live handle and, as the case may be, reinsert the atom
* into its caching structures.
* </p>
*
* <p>
* Note that there are two important cases of "refreshing" an atom in the cache - the atom
* being reloaded from permanent storage or when there is an actual value change. In the
* former case, a transaction abort does not need to roll back changes in the caching
* structures while in the latter it does! The two cases are distinguished by the third
* parameter of this method. ??? Note that the cache should perform a replace if <code>handle.getRef() != null
* && handle.getRef() != atom</code> because this signals that a new value must be stored.
* If the atom's value hasn't changed (i.e. if <code>handle.getRef() == atom</code>) then
* nothing is done.
* </p>
*
* @param handle The <code>HGLiveHandle</code> handle of the atom to be refreshed.
* @param atom The atom value. <code>HyperGraph</code> will obtain this value
* either from the cache, in case the atom has already been re-fetched from storage
* after the eviction event, or it will retrieve and create a new run-time instance.
* @param replace <code>true</code> if this is a new atom value (old must be restored
* if the transaction aborts) and <code>false</code> if this is simply a reload from
* permanent storage where the effects of that reload may (or may not, depending on the
* implementation) be reversed in case of a transaction abort.
* @return Possibly a new live handle instance or the <code>handle</code> parameter depending
* on the implementation. If a new instance is return, the reference of the old instance
* is cleared.
*/
HGLiveHandle atomRefresh(HGLiveHandle handle, Object atom, boolean replace);
/**
* <p>
* Retrieve an atom from the cache by its persistent handle.
* </p>
*
* @param pHandle The <code>HGPersistentHandle</code> of the desired atom.
* @return The <code>HGLiveHandle</code> of the atom or <code>null</code> if
* the atom is not in the cache.
*/
HGLiveHandle get(final HGPersistentHandle pHandle);
/**
* <p>
* Retrieve the <code>HGLiveHandle</code> of a run-time atom instance.
* </p>
*
* @param atom The atom object.
* @return The <code>HGLiveHandle</code> of that atom or <code>null</code> if
* the atom is not in the cache.
*/
HGLiveHandle get(final Object atom);
/**
* <p>Force a removal a given atom from the cache. This method is generally invoked when
* the atom is actually deleted from the graph.</p>
*
* <p>
* If the incidence set of this atom was loaded in the cache, it should be removed as well.
* </p>
*
* @param handle The <code>HGLiveHandle</code> of the atom to be removed. If the atom is
* currently not in the cache, nothing should be done.
*/
void remove(final HGHandle handle);
/**
* <p>Freezing an atom in the cache would prevent it from ever being removed.</p>
*
* @param handle The <code>HGLiveHandle</code> of the atom to be frozen. The atom
* must already be in the cache.
*/
void freeze(HGLiveHandle handle);
/**
* <p>Unfreezing a previously frozen atom makes it available for eviction. It is ok
* to unfreeze an atom that has never been frozen.
* </p>
*
* @param handle The <code>HGLiveHandle</code> of the atom to be unfrozen. The atom
* must be in the cache.
*/
void unfreeze(HGLiveHandle handle);
/**
* <p>Find out whether a given atom is frozen in the cache.</p>
*
* @param handle The live handle of the atom.
* @return <code>true</code> if the atom is frozen (i.e. would never be evicted from the cache)
* and <code>false</code> otherwise.
*/
boolean isFrozen(HGLiveHandle handle);
/**
* <p>Close the cache. This will clear the cache, completely and perform any
* cleaning operations such as unloading of atoms and the like.</p>
*
* <p>
* Once the cache is closed, it cannot be used again.
* </p>
*
* <p>
* This method is normally invoked by HyperGraph only. The method is not guaranteed
* to be thread-safe. It can rely on the fact that no other threads are accessing
* the cache while it is executing.
* </p>
*/
void close();
/**
* <p>Return the incidence set cache. The incidence set cache is maintained separately
* from the main atom cache. Incidence sets don't hold actual atoms, but only their
* handles. Also, they are ordered and can be queried for membership efficiently.
*/
HGCache<HGPersistentHandle, IncidenceSet> getIncidenceCache();
/**
* <p>
* Set the implementation of the incidence sets cache to use.
* </p>
* @param cache
*/
void setIncidenceCache(HGCache<HGPersistentHandle, IncidenceSet> cache);
}