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 the oak:counter property
you'll need to set the oak:increment one (PROP_INCREMENT). Please note that the
oak:incremement will never be saved, only the oak: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();
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 to
AtomicCounterEditor(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.
| Modifier and Type | Class and Description |
|---|---|
static class |
AtomicCounterEditor.ConsolidatorTask |
| Modifier and Type | Field and Description |
|---|---|
static java.lang.String |
PREFIX_PROP_COUNTER
prefix used internally for tracking the counting requests
|
static java.lang.String |
PREFIX_PROP_REVISION
prefix used internally for tracking the cluster node related revision numbers
|
static java.lang.String |
PROP_COUNTER
property with the consolidated counter
|
static java.lang.String |
PROP_INCREMENT
property to be set for incrementing/decrementing the counter
|
INSTANCE| Constructor and Description |
|---|
AtomicCounterEditor(NodeBuilder builder,
java.lang.String instanceId,
java.util.concurrent.ScheduledExecutorService executor,
NodeStore store,
Whiteboard board)
Create an instance of the editor for atomic increments.
|
| Modifier and Type | Method and Description |
|---|---|
Editor |
childNodeAdded(java.lang.String name,
NodeState after)
Processes an added child node.
|
Editor |
childNodeChanged(java.lang.String name,
NodeState before,
NodeState after)
Processes a changed child node.
|
static void |
consolidateCount(NodeBuilder builder)
consolidate the
PREFIX_PROP_COUNTER properties and sum them into the
PROP_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.
|
childNodeDeleted, enter, propertyChanged, propertyDeletedpublic static final java.lang.String PROP_INCREMENT
public static final java.lang.String PROP_COUNTER
public static final java.lang.String PREFIX_PROP_COUNTER
public static final java.lang.String PREFIX_PROP_REVISION
public AtomicCounterEditor(NodeBuilder builder, java.lang.String instanceId, java.util.concurrent.ScheduledExecutorService executor, NodeStore store, 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 OR executor OR store OR board are null, the
editor will switch to synchronous behaviour for consolidation. If no CommitHook will
be found in the whiteboard, a EmptyHook will be provided to the NodeStore for
merging.
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 Oak Whiteboard.public static void consolidateCount(NodeBuilder builder)
consolidate the PREFIX_PROP_COUNTER properties and sum them into the
PROP_COUNTER
The passed in NodeBuilder must have
JCR_MIXINTYPES with
MIX_ATOMIC_COUNTER.
If not it will be silently ignored.
builder - the builder to work on. Cannot be null.public void propertyAdded(PropertyState after) throws CommitFailedException
EditorpropertyAdded in interface EditorpropertyAdded in class DefaultEditorafter - the added propertyCommitFailedException - if processing failedpublic Editor childNodeAdded(java.lang.String name, NodeState after) throws CommitFailedException
EditorchildNodeAdded in interface EditorchildNodeAdded in class DefaultEditorname - name of the added nodeafter - the added child nodenull if the subtree does not need processingCommitFailedException - if processing failedpublic Editor childNodeChanged(java.lang.String name, NodeState before, NodeState after) throws CommitFailedException
EditorchildNodeChanged in interface EditorchildNodeChanged in class DefaultEditorname - name of the changed nodebefore - child node before the changeafter - child node after the changenull if the subtree does not need processingCommitFailedException - if processing failedpublic void leave(NodeState before, NodeState after) throws CommitFailedException
Editorleave in interface Editorleave in class DefaultEditorbefore - before state, non-existent if this node was addedafter - after state, non-existent if this node was removedCommitFailedException - if this commit should be rejected"Copyright © 2010 - 2018 Adobe Systems Incorporated. All Rights Reserved"