Author: reschke
Date: Wed Apr 24 14:19:54 2019
New Revision: 1858053

URL: http://svn.apache.org/viewvc?rev=1858053&view=rev
Log:
OAK-8257: RDBDocumentStore: improve trace logging of batch operations

Modified:
    
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java
    
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreJDBC.java
    
jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/MultiDocumentStoreTest.java

Modified: 
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java?rev=1858053&r1=1858052&r2=1858053&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java
 Wed Apr 24 14:19:54 2019
@@ -429,10 +429,10 @@ public class RDBDocumentStore implements
             UpdateOp conflictedOp = operationsToCover.remove(updateOp.getId());
             if (conflictedOp != null) {
                 if (collection == Collection.NODES) {
-                    LOG.debug("update conflict on {}, invalidating cache and 
retrying...", updateOp.getId());
+                    LOG.debug("createOrUpdate: update conflict on {}, 
invalidating cache and retrying...", updateOp.getId());
                     nodesCache.invalidate(updateOp.getId());
                 } else {
-                    LOG.debug("update conflict on {}, retrying...", 
updateOp.getId());
+                    LOG.debug("createOrUpdate: update conflict on {}, 
retrying...", updateOp.getId());
                 }
                 results.put(conflictedOp, createOrUpdate(collection, 
updateOp));
             } else if (duplicates.contains(updateOp)) {
@@ -524,7 +524,16 @@ public class RDBDocumentStore implements
                 missingDocs.add(op.getId());
             }
         }
-        oldDocs.putAll(readDocumentsUncached(collection, missingDocs));
+
+        if (LOG.isTraceEnabled()) {
+            LOG.trace("bulkUpdate: cached docs to be updated: {}", 
dumpKeysAndModcounts(oldDocs));
+        }
+
+        Map<String, T> freshDocs = readDocumentsUncached(collection, 
missingDocs);
+        if (LOG.isTraceEnabled()) {
+            LOG.trace("bulkUpdate: fresh docs to be updated: {}", 
dumpKeysAndModcounts(freshDocs));
+        }
+        oldDocs.putAll(freshDocs);
 
         try (CacheChangesTracker tracker = obtainTracker(collection, 
Sets.union(oldDocs.keySet(), missingDocs) )) {
             List<T> docsToUpdate = new ArrayList<T>(updates.size());
@@ -554,6 +563,10 @@ public class RDBDocumentStore implements
                 Set<String> failedUpdates = Sets.difference(keysToUpdate, 
successfulUpdates);
                 oldDocs.keySet().removeAll(failedUpdates);
 
+                if (LOG.isTraceEnabled()) {
+                    LOG.trace("bulkUpdate: success for {}, failure for {}", 
successfulUpdates, failedUpdates);
+                }
+
                 if (collection == Collection.NODES) {
                     List<NodeDocument> docsToCache = new ArrayList<>();
                     for (T doc : docsToUpdate) {
@@ -2294,6 +2307,23 @@ public class RDBDocumentStore implements
         }
     }
 
+    @NotNull
+    private static <T extends Document> String 
dumpKeysAndModcounts(Map<String, T> docs) {
+        if (docs.isEmpty()) {
+            return "-";
+        } else {
+            StringBuilder sb = new StringBuilder();
+            for (Map.Entry<String, T> e : docs.entrySet()) {
+                Long mc = e.getValue().getModCount();
+                if (sb.length() != 0) {
+                    sb.append(", ");
+                }
+                sb.append(String.format("%s (%s)", e.getKey(), mc == null ? "" 
: mc.toString()));
+            }
+            return sb.toString();
+        }
+    }
+
     // keeping track of CLUSTER_NODES updates
     private Map<String, Long> cnUpdates = new ConcurrentHashMap<String, 
Long>();
 

Modified: 
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreJDBC.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreJDBC.java?rev=1858053&r1=1858052&r2=1858053&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreJDBC.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreJDBC.java
 Wed Apr 24 14:19:54 2019
@@ -333,6 +333,7 @@ public class RDBDocumentStoreJDBC {
 
         Set<String> successfulUpdates = new HashSet<String>();
         List<String> updatedKeys = new ArrayList<String>();
+        List<Long> modCounts = LOG.isTraceEnabled() ? new ArrayList<>() : null;
         int[] batchResults = new int[0];
 
         PreparedStatement stmt = connection.prepareStatement("update " + 
tmd.getName()
@@ -372,6 +373,9 @@ public class RDBDocumentStoreJDBC {
                 stmt.setObject(si++, modcount - 1, Types.BIGINT);
                 stmt.addBatch();
                 updatedKeys.add(document.getId());
+                if (modCounts != null) {
+                    modCounts.add(modcount);
+                }
 
                 batchIsEmpty = false;
             }
@@ -386,6 +390,20 @@ public class RDBDocumentStoreJDBC {
             stmt.close();
         }
 
+        if (!updatedKeys.isEmpty() && LOG.isTraceEnabled()) {
+            StringBuilder br = new StringBuilder(String.format("update: batch 
result on '%s' (sent: %d, received: %d):", tmd.getName(),
+                    updatedKeys.size(), batchResults.length));
+            String delim = " ";
+            for (int i = 0; i < batchResults.length; i++) {
+                br.append(delim).append(batchResults[i]);
+                if (i < updatedKeys.size()) {
+                    br.append(String.format(" (for %s (%d))", 
updatedKeys.get(i), modCounts.get(i) - 1));
+                }
+                delim = ", ";
+            }
+            LOG.trace(br.toString());
+        }
+
         for (int i = 0; i < batchResults.length; i++) {
             int result = batchResults[i];
             if (result == 1 || result == Statement.SUCCESS_NO_INFO) {

Modified: 
jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/MultiDocumentStoreTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/MultiDocumentStoreTest.java?rev=1858053&r1=1858052&r2=1858053&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/MultiDocumentStoreTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/MultiDocumentStoreTest.java
 Wed Apr 24 14:19:54 2019
@@ -17,10 +17,13 @@
 package org.apache.jackrabbit.oak.plugins.document;
 
 import static java.util.Collections.synchronizedList;
+import static org.apache.jackrabbit.oak.plugins.document.Collection.NODES;
+import static 
org.apache.jackrabbit.oak.plugins.document.util.Utils.getIdFromPath;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 import java.util.ArrayList;
@@ -29,8 +32,12 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.CountDownLatch;
 
+import org.apache.jackrabbit.oak.commons.junit.LogCustomizer;
+import org.apache.jackrabbit.oak.plugins.document.rdb.RDBDocumentStore;
+import org.apache.jackrabbit.oak.plugins.document.rdb.RDBDocumentStoreJDBC;
 import org.apache.jackrabbit.oak.plugins.document.util.Utils;
 import org.junit.Test;
+import org.slf4j.event.Level;
 
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
@@ -366,4 +373,59 @@ public class MultiDocumentStoreTest exte
             }
         }
     }
+
+    @Test
+    public void testTraceLoggingForBulkUpdates() {
+        if (ds instanceof RDBDocumentStore) {
+            int count = 10;
+
+            List<UpdateOp> ops = new ArrayList<>();
+            for (int i = 0; i < count; i++) {
+                UpdateOp op = new UpdateOp(getIdFromPath("/bulktracelog-" + 
i), true);
+                ops.add(op);
+                removeMe.add(op.getId());
+            }
+            ds.createOrUpdate(NODES, ops);
+
+            LogCustomizer logCustomizerJDBC = 
LogCustomizer.forLogger(RDBDocumentStoreJDBC.class.getName()).enable(Level.TRACE)
+                    .matchesRegex("update: batch result.*").create();
+            logCustomizerJDBC.starting();
+            LogCustomizer logCustomizer = 
LogCustomizer.forLogger(RDBDocumentStore.class.getName()).enable(Level.TRACE)
+                    .matchesRegex("bulkUpdate: success.*").create();
+            logCustomizer.starting();
+
+            try {
+                ops.clear();
+
+                // modify first entry through secondary store
+                String modifiedRow = getIdFromPath("/bulktracelog-" + 0);
+                UpdateOp op2 = new UpdateOp(modifiedRow, false);
+                op2.set("foo", "bar");
+                ds2.createOrUpdate(NODES, op2);
+
+                // delete second entry through secondary store
+                String deletedRow = getIdFromPath("/bulktracelog-" + 1);
+                ds2.remove(NODES, deletedRow);
+
+                for (int i = 0; i < count; i++) {
+                    UpdateOp op = new UpdateOp(getIdFromPath("/bulktracelog-" 
+ i), false);
+                    op.set("foo", "qux");
+                    ops.add(op);
+                    removeMe.add(op.getId());
+                }
+                ds.createOrUpdate(NODES, ops);
+
+                assertTrue(logCustomizer.getLogs().size() == 1);
+                assertTrue(logCustomizer.getLogs().get(0).contains("failure 
for [" + modifiedRow + ", " + deletedRow + "]"));
+                // System.out.println(logCustomizer.getLogs());
+                assertTrue(logCustomizerJDBC.getLogs().size() == 1);
+                assertTrue(logCustomizerJDBC.getLogs().get(0).contains("0 (for 
" + modifiedRow + " (1)"));
+                assertTrue(logCustomizerJDBC.getLogs().get(0).contains("0 (for 
" + deletedRow + " (1)"));
+                // System.out.println(logCustomizerJDBC.getLogs());
+            } finally {
+                logCustomizer.finished();
+                logCustomizerJDBC.finished();
+            }
+        }
+    }
 }


Reply via email to