Author: adulceanu
Date: Thu Sep 14 15:06:43 2017
New Revision: 1808355

URL: http://svn.apache.org/viewvc?rev=1808355&view=rev
Log:
OAK-6659 - Cold standby should fail loudly when a big blob can't be timely 
transferred
Restructured StandbyDiff to transparently load all blobs before doing any other 
processing
Added failed sync test case in ExternalPrivateStoreIT

Modified:
    
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/standby/client/StandbyDiff.java
    
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/standby/ExternalPrivateStoreIT.java

Modified: 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/standby/client/StandbyDiff.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/standby/client/StandbyDiff.java?rev=1808355&r1=1808354&r2=1808355&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/standby/client/StandbyDiff.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/standby/client/StandbyDiff.java
 Thu Sep 14 15:06:43 2017
@@ -63,7 +63,7 @@ class StandbyDiff implements NodeStateDi
      * missing binaries can be sync'ed if needed
      */
     private final boolean logOnly;
-
+    
     StandbyDiff(NodeBuilder builder, FileStore store, StandbyClient client, 
Supplier<Boolean> running) {
         this(builder, store, client, "/", false, running);
     }
@@ -87,13 +87,11 @@ class StandbyDiff implements NodeStateDi
         if (stop()) {
             return false;
         }
-
-        if (logOnly) {
-            binaryCheck(after);
-        } else {
-            builder.setProperty(binaryCheck(after));
+        
+        if (!logOnly) {
+            builder.setProperty(after);
         }
-
+        
         return true;
     }
 
@@ -102,13 +100,11 @@ class StandbyDiff implements NodeStateDi
         if (stop()) {
             return false;
         }
-
-        if (logOnly) {
-            binaryCheck(after);
-        } else {
-            builder.setProperty(binaryCheck(after));
+        
+        if (!logOnly) {
+            builder.setProperty(after);
         }
-
+        
         return true;
     }
 
@@ -121,10 +117,70 @@ class StandbyDiff implements NodeStateDi
         if (!logOnly) {
             builder.removeProperty(before.getName());
         }
+        
+        return true;
+    }
+
+    @Override
+    public boolean childNodeAdded(String name, NodeState after) {
+        return process(name, "childNodeAdded", EmptyNodeState.EMPTY_NODE, 
after);
+    }
+
+    @Override
+    public boolean childNodeChanged(String name, NodeState before, NodeState 
after) {
+        return process(name, "childNodeChanged", before, after);
+    }
+    
+    @Override
+    public boolean childNodeDeleted(String name, NodeState before) {
+        log.trace("childNodeDeleted {}, RO:{}", path + name, logOnly);
+
+        if (!logOnly) {
+            builder.getChildNode(name).remove();
+        }
 
         return true;
     }
 
+    private boolean process(String name, String op, NodeState before, 
NodeState after) {
+        if (stop()) {
+            return false;
+        }
+
+        if (after instanceof SegmentNodeState) {
+            if (log.isTraceEnabled()) {
+                log.trace("{} {}, readonly binary check {}", op, path + name, 
logOnly);
+            }
+            
+            if (!logOnly) {
+                RecordId id = ((SegmentNodeState) after).getRecordId();
+                builder.setChildNode(name, store.getReader().readNode(id));
+            }
+            
+            if ("checkpoints".equals(name)) {
+                // if we're on the /checkpoints path, there's no need for a 
deep
+                // traversal to verify binaries
+                return true;
+            }
+
+            if (!hasDataStore) {
+                return true;
+            }
+
+            // has external data store, we need a deep
+            // traversal to verify binaries
+
+            for (PropertyState propertyState : after.getProperties()) {
+                binaryCheck(propertyState);
+            }
+
+            return after.compareAgainstBaseState(before,
+                    new StandbyDiff(builder.getChildNode(name), store, client, 
path + name + "/", true, running));
+        }
+
+        return false;
+    }
+    
     private PropertyState binaryCheck(PropertyState property) {
         Type<?> type = property.getType();
 
@@ -162,7 +218,7 @@ class StandbyDiff implements NodeStateDi
             }
         }
     }
-
+    
     private void readBlob(String blobId, String pName) throws 
InterruptedException {
         InputStream in = client.getBlob(blobId);
 
@@ -180,67 +236,4 @@ class StandbyDiff implements NodeStateDi
         }
     }
 
-    @Override
-    public boolean childNodeAdded(String name, NodeState after) {
-        return process(name, "childNodeAdded", EmptyNodeState.EMPTY_NODE, 
after);
-    }
-
-    @Override
-    public boolean childNodeChanged(String name, NodeState before, NodeState 
after) {
-        try {
-            return process(name, "childNodeChanged", before, after);
-        } catch (RuntimeException e) {
-            log.trace("Check binaries for node {} and retry to process 
childNodeChanged", name);
-            // Attempt to load the binaries and retry, see OAK-4969
-            for (PropertyState propertyState : after.getProperties()) {
-                binaryCheck(propertyState);
-            }
-            return process(name, "childNodeChanged", before, after);
-        }
-    }
-
-    private boolean process(String name, String op, NodeState before, 
NodeState after) {
-        if (stop()) {
-            return false;
-        }
-
-        if (after instanceof SegmentNodeState) {
-            if (log.isTraceEnabled()) {
-                log.trace("{} {}, readonly binary check {}", op, path + name, 
logOnly);
-            }
-
-            if (!logOnly) {
-                RecordId id = ((SegmentNodeState) after).getRecordId();
-                builder.setChildNode(name, store.getReader().readNode(id));
-            }
-
-            if ("checkpoints".equals(name)) {
-                // if we're on the /checkpoints path, there's no need for a 
deep
-                // traversal to verify binaries
-                return true;
-            }
-
-            if (!hasDataStore) {
-                return true;
-
-            }
-            // has external datastore, we need a deep
-            // traversal to verify binaries
-            return after.compareAgainstBaseState(before, new 
StandbyDiff(builder.getChildNode(name), store, client, path + name + "/", true, 
running));
-        }
-
-        return false;
-    }
-
-    @Override
-    public boolean childNodeDeleted(String name, NodeState before) {
-        log.trace("childNodeDeleted {}, RO:{}", path + name, logOnly);
-
-        if (!logOnly) {
-            builder.getChildNode(name).remove();
-        }
-
-        return true;
-    }
-
 }

Modified: 
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/standby/ExternalPrivateStoreIT.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/standby/ExternalPrivateStoreIT.java?rev=1808355&r1=1808354&r2=1808355&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/standby/ExternalPrivateStoreIT.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/standby/ExternalPrivateStoreIT.java
 Thu Sep 14 15:06:43 2017
@@ -18,12 +18,20 @@
  */
 package org.apache.jackrabbit.oak.segment.standby;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
 import java.io.File;
 
+import org.apache.jackrabbit.oak.segment.SegmentNodeStoreBuilders;
 import org.apache.jackrabbit.oak.segment.file.FileStore;
+import org.apache.jackrabbit.oak.segment.standby.client.StandbyClientSync;
+import org.apache.jackrabbit.oak.segment.standby.server.StandbyServerSync;
 import org.apache.jackrabbit.oak.segment.test.TemporaryBlobStore;
 import org.apache.jackrabbit.oak.segment.test.TemporaryFileStore;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
 import org.junit.Rule;
+import org.junit.Test;
 import org.junit.rules.RuleChain;
 import org.junit.rules.TemporaryFolder;
 
@@ -61,4 +69,23 @@ public class ExternalPrivateStoreIT exte
         return false;
     }
 
+    @Test
+    public void testSyncFailingDueToTooShortTimeout() throws Exception {
+        final int blobSize = 5 * MB;
+        FileStore primary = getPrimary();
+        FileStore secondary = getSecondary();
+
+        NodeStore store = SegmentNodeStoreBuilders.builder(primary).build();
+        addTestContent(store, "server", blobSize);
+        try (
+                StandbyServerSync serverSync = new 
StandbyServerSync(serverPort.getPort(), primary, 1 * MB);
+                StandbyClientSync cl = newStandbyClientSync(secondary, 
serverPort.getPort(), false, 60)
+        ) {
+            serverSync.start();
+            primary.flush();
+            cl.run();
+            assertNotEquals(primary.getHead(), secondary.getHead());
+            assertEquals(1, cl.getFailedRequests());
+        }
+    }
 }


Reply via email to