You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by ch...@apache.org on 2014/04/02 08:14:03 UTC

svn commit: r1583892 - in /jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document: ClusterNodeInfo.java ClusterNodeInfoDocument.java

Author: chetanm
Date: Wed Apr  2 06:14:02 2014
New Revision: 1583892

URL: http://svn.apache.org/r1583892
Log:
OAK-1295 - Recovery for missing _lastRev updates (WIP)

Refactor
-- to use enum for string constant
-- clock handling moved to single method
-- Strongly type getters for property

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfo.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfoDocument.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfo.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfo.java?rev=1583892&r1=1583891&r2=1583892&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfo.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfo.java Wed Apr  2 06:14:02 2014
@@ -61,25 +61,48 @@ public class ClusterNodeInfo {
     protected static final String LEASE_END_KEY = "leaseEnd";
 
     /**
-     * The state of the cluster.
-     * On proper shutdown the state should be cleared.
-     */
-    protected static final String STATE = "state";
+     * The state of the cluster. On proper shutdown the state should be cleared.
+     *
+     * @see org.apache.jackrabbit.oak.plugins.document.ClusterNodeInfo.ClusterNodeState
+     */
+    public static final String STATE = "state";
+
+    public static enum ClusterNodeState {
+        NONE,
+        /**
+         * Indicates that cluster node is currently active
+         */
+        ACTIVE;
+
+        static ClusterNodeState fromString(String state){
+            if(state == null){
+                return NONE;
+            }
+            return valueOf(state);
+        }
+    }
 
     /**
      * Flag to indicate whether the _lastRev recovery is in progress.
+     *
+     * @see RecoverLockState
      */
-    protected static final String REV_RECOVERY_LOCK = "revLock";
+    public static final String REV_RECOVERY_LOCK = "recoveryLock";
 
-    /**
-     * Active State.
-     */
-    private static final String ACTIVE_STATE = "active";
-
-    /**
-     * _lastRev recovery in progress
-     */
-    protected static final String REV_RECOVERY_ON = "true";
+    public static enum RecoverLockState {
+        NONE,
+        /**
+         * _lastRev recovery in progress
+         */
+        ACQUIRED;
+
+        static RecoverLockState fromString(String state){
+            if(state == null){
+                return NONE;
+            }
+            return valueOf(state);
+        }
+    }
 
     /**
      * Additional info, such as the process id, for support.
@@ -87,7 +110,8 @@ public class ClusterNodeInfo {
     private static final String INFO_KEY = "info";
 
     /**
-     * The read/write mode key.
+     * The read/write mode key. Specifies the read/write preference to be used with
+     * DocumentStore
      */
     private static final String READ_WRITE_MODE_KEY = "readWriteMode";
 
@@ -109,7 +133,7 @@ public class ClusterNodeInfo {
     /**
      * <b>Only Used For Testing</b>
      */
-    private static Clock clock;
+    private static Clock clock = Clock.SIMPLE;
 
     /**
      * The number of milliseconds for a lease (1 minute by default, and
@@ -160,26 +184,17 @@ public class ClusterNodeInfo {
     /**
      * The state of the cluter node.
      */
-    private String state;
+    private ClusterNodeState state;
 
     /**
      * The revLock value of the cluster;
      */
-    private String revRecoveryLock;
-
-    ClusterNodeInfo(int id, DocumentStore store, String machineId, String instanceId) {
-        this.id = id;
-        this.startTime = (clock == null ? System.currentTimeMillis() : clock.getTime());
-        this.leaseEndTime = startTime;
-        this.store = store;
-        this.machineId = machineId;
-        this.instanceId = instanceId;
-    }
+    private RecoverLockState revRecoveryLock;
 
-    ClusterNodeInfo(int id, DocumentStore store, String machineId, String instanceId, String state,
-            String revRecoveryLock) {
+    ClusterNodeInfo(int id, DocumentStore store, String machineId, String instanceId, ClusterNodeState state,
+                    RecoverLockState revRecoveryLock) {
         this.id = id;
-        this.startTime = (clock == null ? System.currentTimeMillis() : clock.getTime());
+        this.startTime = getCurrentTime();
         this.leaseEndTime = startTime;
         this.store = store;
         this.machineId = machineId;
@@ -193,13 +208,6 @@ public class ClusterNodeInfo {
     }
 
     /**
-     * <b>Only Used For Testing</b>
-     */
-    static void setClock(Clock c) {
-        clock = c;
-    }
-
-    /**
      * Create a cluster node info instance for the store, with the
      * 
      * @param store the document store (for the lease)
@@ -231,12 +239,10 @@ public class ClusterNodeInfo {
             update.set(ID, String.valueOf(clusterNode.id));
             update.set(MACHINE_ID_KEY, clusterNode.machineId);
             update.set(INSTANCE_ID_KEY, clusterNode.instanceId);
-            update.set(LEASE_END_KEY,
-                    (clock == null ? System.currentTimeMillis() : clock.getTime())
-                            + clusterNode.leaseTime);
+            update.set(LEASE_END_KEY, getCurrentTime() + clusterNode.leaseTime);
             update.set(INFO_KEY, clusterNode.toString());
-            update.set(STATE, clusterNode.state);
-            update.set(REV_RECOVERY_LOCK, clusterNode.revRecoveryLock);
+            update.set(STATE, clusterNode.state.name());
+            update.set(REV_RECOVERY_LOCK, clusterNode.revRecoveryLock.name());
             boolean success =
                     store.create(Collection.CLUSTER_NODES, Collections.singletonList(update));
             if (success) {
@@ -248,13 +254,14 @@ public class ClusterNodeInfo {
 
     private static ClusterNodeInfo createInstance(DocumentStore store, String machineId,
             String instanceId) {
-        long now = (clock == null ? System.currentTimeMillis() : clock.getTime());
+        long now = getCurrentTime();
         // keys between "0" and "a" includes all possible numbers
         List<ClusterNodeInfoDocument> list = store.query(Collection.CLUSTER_NODES,
-                "0", "a", Integer.MAX_VALUE);
+                ClusterNodeInfoDocument.MIN_ID_VALUE, ClusterNodeInfoDocument.MAX_ID_VALUE,
+                Integer.MAX_VALUE);
         int clusterNodeId = 0;
         int maxId = 0;
-        String state = null;
+        ClusterNodeState state = ClusterNodeState.NONE;
         for (Document doc : list) {
             String key = doc.getId();
             int id;
@@ -286,13 +293,13 @@ public class ClusterNodeInfo {
             if (clusterNodeId == 0 || id < clusterNodeId) {
                 // if there are multiple, use the smallest value
                 clusterNodeId = id;
-                state = (String) doc.get(STATE);
+                state = ClusterNodeState.fromString((String) doc.get(STATE));
             }
         }
         if (clusterNodeId == 0) {
             clusterNodeId = maxId + 1;
         }
-        return new ClusterNodeInfo(clusterNodeId, store, machineId, instanceId, state, null);
+        return new ClusterNodeInfo(clusterNodeId, store, machineId, instanceId, state, RecoverLockState.NONE);
     }
 
     /**
@@ -302,14 +309,14 @@ public class ClusterNodeInfo {
      * @param nextCheckMillis the millisecond offset
      */
     public void renewLease(long nextCheckMillis) {
-        long now = (clock == null ? System.currentTimeMillis() : clock.getTime());
+        long now = getCurrentTime();
         if (now + nextCheckMillis + nextCheckMillis < leaseEndTime) {
             return;
         }
         UpdateOp update = new UpdateOp("" + id, true);
         leaseEndTime = now + leaseTime;
         update.set(LEASE_END_KEY, leaseEndTime);
-        update.set(STATE, ACTIVE_STATE);
+        update.set(STATE, ClusterNodeState.ACTIVE.name());
         ClusterNodeInfoDocument doc = store.createOrUpdate(Collection.CLUSTER_NODES, update);
         String mode = (String) doc.get(READ_WRITE_MODE_KEY);
         if (mode != null && !mode.equals(readWriteMode)) {
@@ -347,6 +354,19 @@ public class ClusterNodeInfo {
                 "revLock: " + revRecoveryLock;
     }
 
+    /**
+     * Specify a custom clock to be used for determining current time.
+     * If passed clock is null then clock would be set to the default clock
+     *
+     * <b>Only Used For Testing</b>
+     */
+    static void setClock(Clock c) {
+        if(c == null){
+            c = Clock.SIMPLE;
+        }
+        clock = c;
+    }
+
     private static long getProcessId() {
         try {
             String name = ManagementFactory.getRuntimeMXBean().getName();
@@ -388,4 +408,8 @@ public class ClusterNodeInfo {
         return RANDOM_PREFIX + UUID.randomUUID().toString();
     }
 
+    private static long getCurrentTime() {
+        return clock.getTime();
+    }
+
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfoDocument.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfoDocument.java?rev=1583892&r1=1583891&r2=1583892&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfoDocument.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/ClusterNodeInfoDocument.java Wed Apr  2 06:14:02 2014
@@ -16,11 +16,44 @@
  */
 package org.apache.jackrabbit.oak.plugins.document;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.apache.jackrabbit.oak.plugins.document.ClusterNodeInfo.ClusterNodeState;
+import static org.apache.jackrabbit.oak.plugins.document.ClusterNodeInfo.RecoverLockState;
+
 /**
  * A document storing cluster node info. See also {@link ClusterNodeInfo}.
  */
 public class ClusterNodeInfoDocument extends Document {
 
-    // marker interface
+    /**
+     * All ClusterNodeInfoDocument ID value would be greater than this value
+     * It can be used as startKey in DocumentStore#query methods
+     */
+    public static final String MIN_ID_VALUE = "0";
+
+    /**
+     * All ClusterNodeInfoDocument ID value would be less than this value
+     * It can be used as endKey in DocumentStore#query methods
+     */
+    public static final String MAX_ID_VALUE = "a";
+
+    public long getLeaseEndTime(){
+        return checkNotNull((Long) get(ClusterNodeInfo.LEASE_END_KEY), "Lease End Time not set");
+    }
+
+    public boolean isActive(){
+        return getState() == ClusterNodeState.ACTIVE;
+    }
+
+    public boolean isBeingRecovered(){
+        return getRecoveryState() == RecoverLockState.ACQUIRED;
+    }
+
+    private ClusterNodeState getState(){
+        return ClusterNodeState.fromString((String) get(ClusterNodeInfo.STATE));
+    }
 
+    private RecoverLockState getRecoveryState(){
+        return RecoverLockState.fromString((String) get(ClusterNodeInfo.REV_RECOVERY_LOCK));
+    }
 }