[[arch_overview]]
= Architectural Overview

This section contains a high level overview of {brandname}'s internal
architecture.  This document is geared towards people with an interest in
extending or enhancing {brandname}, or just curious about {brandname}’s internals.

[[cache_hierarchy]]
== Cache hierarchy

{brandname}'s Cache interface extends the JRE's ConcurrentMap interface
which provides for a familiar and easy-to-use API.

[source,java]
----
include::code_examples/ConcurrentMap.java[]
----

Caches are created by using a CacheContainer instance - either the
EmbeddedCacheManager or a RemoteCacheManager.  In addition to their capabilities
as a factory for Caches, CacheContainers also act as a registry for looking
up Caches.

EmbeddedCacheManagers create either clustered or standalone Caches that reside
in the same JVM.  RemoteCacheManagers, on the other hand, create RemoteCaches
that connect to a remote cache tier via the Hot Rod protocol.

[[arch_commands]]
== Commands

Internally, each and every cache operation is encapsulated by a command.  These
command objects represent the type of operation being performed, and also hold
references to necessary parameters.  The actual logic of a given command, for
example a ReplaceCommand, is encapsulated in the command’s perform() method.
Very object-oriented and easy to test.

All of these commands implement the VisitableCommand interface which allow a
Visitor (described in next section) to process them accordingly.

[source,java]
----
include::code_examples/VisitableCommand.java[]
----

== Visitors

Commands are processed by the various Visitors.  The visitor interface,
displayed below, exposes methods to visit each of the different types of
commands in the system.  This gives us a type-safe mechanism for adding
behaviour to a call. Commands are processed by `Visitor`s.  The visitor
interface, displayed below, exposes methods to visit each of the different
types of commands in the system.  This gives us a type-safe mechanism for
adding behaviour to a call.

[source, java]
----
include::code_examples/Visitor.java[]
----

An `AbstractVisitor` class in the `org.infinispan.commands` package is provided with
no-op implementations of each of these methods.  Real implementations then only
need override the visitor methods for the commands that interest them, allowing
for very concise, readable and testable visitor implementations.

== Interceptors

Interceptors are special types of Visitors, which are capable of visiting
commands, but also acts in a chain.  A chain of interceptors all visit the
command, one in turn, until all registered interceptors visit the command.

The class to note is the
link:{javadocroot}/org/infinispan/interceptors/base/CommandInterceptor.html[CommandInterceptor].
This abstract class implements the interceptor pattern, and also implements
Visitor.  {brandname}'s interceptors extend CommandInterceptor, and these add
specific behaviour to specific commands, such as distribution across a network
or writing through to disk.

There is also an experimental asynchronous interceptor which can be used.
The interface used for asynchronous interceptors is
link:{javadocroot}/org/infinispan/interceptors/AsyncInterceptor.html[AsyncInterceptor]
and a base implementation which should be used when a custom implementation is desired
link:{javadocroot}/org/infinispan/interceptors/BaseCustomAsyncInterceptor.html[BaseCustomAsyncInterceptor].
Note this class also implements the `Visitor` interface.


== Putting it all together

So how does this all come together?  Invocations on the cache cause the cache
to first create an invocation context for the call.  Invocation contexts
contain, among other things, transactional characteristics of the call.  The
cache then creates a command for the call, making use of a command factory which
initialises the command instance with parameters and references to other subsystems.

The cache then passes the invocation context and command to the InterceptorChain,
which calls each and every registered interceptor in turn to visit the command,
adding behaviour to the call.  Finally, the command’s perform() method is invoked
and the return value, if any, is propagated back to the caller.


== Subsystem Managers

The interceptors act as simple interception points and don’t contain a lot of
logic themselves.  Most behavioural logic is encapsulated as managers in various
subsystems, a small subset of which are:

=== DistributionManager

Manager that controls how entries are distributed across the cluster.

=== TransactionManager

Manager than handles transactions, usually supplied by a third party.

=== RpcManager

Manager that handles replicating commands between nodes in the cluster.

=== LockManager

Manager that handles locking keys when operations require them.

=== PersistenceManager

Manager that handles persisting data to any configured cache stores.

=== DataContainer

Container that holds the actual in memory entries.

=== Configuration

A component detailing all of the configuration in this cache.

== ComponentRegistry

A registry where the various managers above and components are created and
stored for use in the cache.  All of the other managers and crucial components
are accessible through the registry.

The registry itself is a lightweight dependency injection framework, allowing
components and managers to reference and initialise one another.  Here is an
example of a component declaring a dependency on a DataContainer and a
Configuration, and a DataContainerFactory declaring its ability to construct
DataContainers on the fly.

[source,java]
----
include::code_examples/InjectDependencies.java[]
----

Components registered with the ComponentRegistry may also have a lifecycle, and
methods annotated with @Start or @Stop will be invoked before and after they
are used by the component registry.

[source,java]
----
include::code_examples/StartStop.java[]
----

In the example above, the optional priority parameter to @Stop is used to
indicate the order in which the component is stopped, in relation to other
components.  This follows a Unix Sys-V style ordering, where smaller priority
methods are called before higher priority ones.  The default priority, if not
specified, is 10.
