Class AtomicCounterEditor
- java.lang.Object
-
- org.apache.jackrabbit.oak.spi.commit.DefaultEditor
-
- org.apache.jackrabbit.oak.plugins.atomic.AtomicCounterEditor
-
- All Implemented Interfaces:
Editor
public class AtomicCounterEditor extends DefaultEditor
Manages a node as Atomic Counter: a node which will handle at low level a protected property (
PROP_COUNTER
) in an atomic way. This will represent an increment or decrement of a counter in the case, for example, of Likes or Voting.Whenever you add a
NodeTypeConstants.MIX_ATOMIC_COUNTER
mixin to a node it will turn it into an atomic counter. Then in order to increment or decrement theoak:counter
property you'll need to set theoak:increment
one (PROP_INCREMENT
). Please note that theoak:incremement
will never be saved, only theoak:counter
will be amended accordingly.So in order to deal with the counter from a JCR point of view you'll do something as follows
Session session = ... // creating a counter node Node counter = session.getRootNode().addNode("mycounter"); counter.addMixin("mix:atomicCounter"); // or use the NodeTypeConstants session.save(); // Will output 0. the default value System.out.println("counter now: " + counter.getProperty("oak:counter").getLong()); // incrementing by 5 the counter counter.setProperty("oak:increment", 5); session.save(); // Will output 5 System.out.println("counter now: " + counter.getProperty("oak:counter").getLong()); // decreasing by 1 counter.setProperty("oak:increment", -1); session.save(); // Will output 4 System.out.println("counter now: " + counter.getProperty("oak:counter").getLong()); session.logout();
Internal behavioural details
The related jira ticket is OAK-2472. In a nutshell when you save an
oak:increment
behind the scene it takes its value and increment an internal counter. There will be an individual counter for each cluster node.Then it will consolidate all the internal counters into a single one:
oak:counter
. The consolidation process can happen either synchronously or asynchronously. Refer toAtomicCounterEditor(NodeBuilder, String, ScheduledExecutorService, NodeStore, Whiteboard)
for details on when it consolidate one way or the other.synchronous. It means the consolidation, sum of all the internal counters, will happen in the same thread. During the lifecycle of the same commit.
asynchronous. It means the internal counters will be set during the same commit; but it will eventually schedule a separate thread in which will retry some times to consolidate them.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static class
AtomicCounterEditor.ConsolidatorTask
-
Field Summary
Fields Modifier and Type Field Description static String
PREFIX_PROP_COUNTER
prefix used internally for tracking the counting requestsstatic String
PREFIX_PROP_REVISION
prefix used internally for tracking the cluster node related revision numbersstatic String
PROP_COUNTER
property with the consolidated counterstatic String
PROP_INCREMENT
property to be set for incrementing/decrementing the counter-
Fields inherited from class org.apache.jackrabbit.oak.spi.commit.DefaultEditor
INSTANCE
-
-
Constructor Summary
Constructors Constructor Description AtomicCounterEditor(@NotNull NodeBuilder builder, @Nullable String instanceId, @Nullable ScheduledExecutorService executor, @Nullable NodeStore store, @Nullable Whiteboard board)
Create an instance of the editor for atomic increments.
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description Editor
childNodeAdded(String name, NodeState after)
Processes an added child node.Editor
childNodeChanged(String name, NodeState before, NodeState after)
Processes a changed child node.static void
consolidateCount(@NotNull NodeBuilder builder)
consolidate thePREFIX_PROP_COUNTER
properties and sum them into thePROP_COUNTER
void
leave(NodeState before, NodeState after)
Called after the given before and after states are compared.void
propertyAdded(PropertyState after)
Processes an added property.-
Methods inherited from class org.apache.jackrabbit.oak.spi.commit.DefaultEditor
childNodeDeleted, enter, propertyChanged, propertyDeleted
-
-
-
-
Field Detail
-
PROP_INCREMENT
public static final String PROP_INCREMENT
property to be set for incrementing/decrementing the counter- See Also:
- Constant Field Values
-
PROP_COUNTER
public static final String PROP_COUNTER
property with the consolidated counter- See Also:
- Constant Field Values
-
PREFIX_PROP_COUNTER
public static final String PREFIX_PROP_COUNTER
prefix used internally for tracking the counting requests- See Also:
- Constant Field Values
-
PREFIX_PROP_REVISION
public static final String PREFIX_PROP_REVISION
prefix used internally for tracking the cluster node related revision numbers- See Also:
- Constant Field Values
-
-
Constructor Detail
-
AtomicCounterEditor
public AtomicCounterEditor(@NotNull @NotNull NodeBuilder builder, @Nullable @Nullable String instanceId, @Nullable @Nullable ScheduledExecutorService executor, @Nullable @Nullable NodeStore store, @Nullable @Nullable Whiteboard board)
Create an instance of the editor for atomic increments. It can works synchronously as well as asynchronously. See class javadoc for details around it.
If
instanceId
ORexecutor
ORstore
ORboard
are null, the editor will switch to synchronous behaviour for consolidation. If noCommitHook
will be found in the whiteboard, aEmptyHook
will be provided to theNodeStore
for merging.- Parameters:
builder
- the build on which to work. Cannot be null.instanceId
- the current Oak instance Id. If null editor will be synchronous.executor
- the current Oak executor service. If null editor will be synchronous.store
- the current Oak node store. If null the editor will be synchronous.board
- the current OakWhiteboard
.
-
-
Method Detail
-
consolidateCount
public static void consolidateCount(@NotNull @NotNull NodeBuilder builder)
consolidate the
PREFIX_PROP_COUNTER
properties and sum them into thePROP_COUNTER
The passed in
NodeBuilder
must haveJCR_MIXINTYPES
withMIX_ATOMIC_COUNTER
. If not it will be silently ignored.- Parameters:
builder
- the builder to work on. Cannot be null.
-
propertyAdded
public void propertyAdded(PropertyState after) throws CommitFailedException
Description copied from interface:Editor
Processes an added property.- Specified by:
propertyAdded
in interfaceEditor
- Overrides:
propertyAdded
in classDefaultEditor
- Parameters:
after
- the added property- Throws:
CommitFailedException
- if processing failed
-
childNodeAdded
public Editor childNodeAdded(String name, NodeState after) throws CommitFailedException
Description copied from interface:Editor
Processes an added child node.- Specified by:
childNodeAdded
in interfaceEditor
- Overrides:
childNodeAdded
in classDefaultEditor
- Parameters:
name
- name of the added nodeafter
- the added child node- Returns:
- an editor for processing the subtree below the added node,
or
null
if the subtree does not need processing - Throws:
CommitFailedException
- if processing failed
-
childNodeChanged
public Editor childNodeChanged(String name, NodeState before, NodeState after) throws CommitFailedException
Description copied from interface:Editor
Processes a changed child node. This method gets called for all child nodes that may contain changes between the before and after states.- Specified by:
childNodeChanged
in interfaceEditor
- Overrides:
childNodeChanged
in classDefaultEditor
- Parameters:
name
- name of the changed nodebefore
- child node before the changeafter
- child node after the change- Returns:
- an editor for processing the subtree below the added node,
or
null
if the subtree does not need processing - Throws:
CommitFailedException
- if processing failed
-
leave
public void leave(NodeState before, NodeState after) throws CommitFailedException
Description copied from interface:Editor
Called after the given before and after states are compared. The implementation can use this method to post-process information collected during the content diff. For example an implementation that during the diff just recorded the fact that this node was modified in some way could then use this method to trigger an index update based on that modification flag.- Specified by:
leave
in interfaceEditor
- Overrides:
leave
in classDefaultEditor
- Parameters:
before
- before state, non-existent if this node was addedafter
- after state, non-existent if this node was removed- Throws:
CommitFailedException
- if this commit should be rejected
-
-