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 re...@apache.org on 2014/08/21 14:28:52 UTC

svn commit: r1619377 - in /jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document: NodeDocument.java rdb/RDBDocumentStore.java

Author: reschke
Date: Thu Aug 21 12:28:52 2014
New Revision: 1619377

URL: http://svn.apache.org/r1619377
Log:
OAK-1941 - add collinsionmodcount property to track changes to _collisions map

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/NodeDocument.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/NodeDocument.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/NodeDocument.java?rev=1619377&r1=1619376&r2=1619377&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/NodeDocument.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/NodeDocument.java Thu Aug 21 12:28:52 2014
@@ -118,7 +118,12 @@ public final class NodeDocument extends 
      * overlap with un-merged branch commits.
      * Key: revision, value: always true
      */
-    static final String COLLISIONS = "_collisions";
+    public static final String COLLISIONS = "_collisions";
+
+    /**
+     * Optional counter for changes to {@link #COLLISIONS} map.
+     */
+    public static final String COLLISIONSMODCOUNT = "_collisionsModCount";
 
     /**
      * The modified time in seconds (5 second resolution).
@@ -305,10 +310,10 @@ public final class NodeDocument extends 
 
 
     /**
-     * Properties to ignore when a document is split.
+     * Properties to ignore when a document is split (see OAK-2044).
      */
     static final Set<String> IGNORE_ON_SPLIT = ImmutableSet.of(
-            ID, MOD_COUNT, MODIFIED_IN_SECS, PREVIOUS, LAST_REV, CHILDREN_FLAG,
+            ID, MOD_COUNT, COLLISIONSMODCOUNT, MODIFIED_IN_SECS, PREVIOUS, LAST_REV, CHILDREN_FLAG,
             HAS_BINARY_FLAG, PATH, DELETED_ONCE, COLLISIONS);
 
     public static final long HAS_BINARY_VAL = 1;

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java?rev=1619377&r1=1619376&r2=1619377&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java Thu Aug 21 12:28:52 2014
@@ -16,6 +16,8 @@
  */
 package org.apache.jackrabbit.oak.plugins.document.rdb;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -34,6 +36,7 @@ import java.util.Comparator;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Set;
 import java.util.TreeMap;
 import java.util.concurrent.Callable;
@@ -58,6 +61,8 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.plugins.document.Revision;
 import org.apache.jackrabbit.oak.plugins.document.StableRevisionComparator;
 import org.apache.jackrabbit.oak.plugins.document.UpdateOp;
+import org.apache.jackrabbit.oak.plugins.document.UpdateOp.Key;
+import org.apache.jackrabbit.oak.plugins.document.UpdateOp.Operation;
 import org.apache.jackrabbit.oak.plugins.document.UpdateUtils;
 import org.apache.jackrabbit.oak.plugins.document.cache.CachingDocumentStore;
 import org.apache.jackrabbit.oak.plugins.document.mongo.MongoDocumentStore;
@@ -401,27 +406,27 @@ public class RDBDocumentStore implements
             if ("PostgreSQL".equals(dbtype)) {
                 stmt.execute("create table "
                         + tableName
-                        + " (ID varchar(1000) not null primary key, MODIFIED bigint, HASBINARY smallint, MODCOUNT bigint, DSIZE bigint, DATA varchar(16384), BDATA bytea)");
+                        + " (ID varchar(1000) not null primary key, MODIFIED bigint, HASBINARY smallint, MODCOUNT bigint, CMODCOUNT bigint, DSIZE bigint, DATA varchar(16384), BDATA bytea)");
             } else if ("DB2".equals(dbtype) || (dbtype != null && dbtype.startsWith("DB2/"))) {
                 stmt.execute("create table "
                         + tableName
-                        + " (ID varchar(1000) not null primary key, MODIFIED bigint, HASBINARY smallint, MODCOUNT bigint, DSIZE bigint, DATA varchar(16384), BDATA blob)");
+                        + " (ID varchar(1000) not null primary key, MODIFIED bigint, HASBINARY smallint, MODCOUNT bigint, CMODCOUNT bigint, DSIZE bigint, DATA varchar(16384), BDATA blob)");
             } else if ("MySQL".equals(dbtype)) {
                 // see
                 // http://dev.mysql.com/doc/refman/5.5/en/innodb-parameters.html#sysvar_innodb_large_prefix
                 stmt.execute("create table "
                         + tableName
-                        + " (ID varchar(767) not null primary key, MODIFIED bigint, HASBINARY smallint, MODCOUNT bigint, DSIZE bigint, DATA varchar(16384), BDATA mediumblob)");
+                        + " (ID varchar(767) not null primary key, MODIFIED bigint, HASBINARY smallint, MODCOUNT bigint, CMODCOUNT bigint, DSIZE bigint, DATA varchar(16384), BDATA mediumblob)");
             } else if ("Oracle".equals(dbtype)) {
                 // see https://issues.apache.org/jira/browse/OAK-1914
                 this.datalimit = 4000 / 6;
                 stmt.execute("create table "
                         + tableName
-                        + " (ID varchar(1000) not null primary key, MODIFIED number, HASBINARY number, MODCOUNT number, DSIZE number, DATA varchar(4000), BDATA blob)");
+                        + " (ID varchar(1000) not null primary key, MODIFIED number, HASBINARY number, MODCOUNT number, CMODCOUNT number, DSIZE number, DATA varchar(4000), BDATA blob)");
             } else {
                 stmt.execute("create table "
                         + tableName
-                        + " (ID varchar(1000) not null primary key, MODIFIED bigint, HASBINARY smallint, MODCOUNT bigint, DSIZE bigint, DATA varchar(16384), BDATA blob)");
+                        + " (ID varchar(1000) not null primary key, MODIFIED bigint, HASBINARY smallint, MODCOUNT bigint, CMODCOUNT bigint, DSIZE bigint, DATA varchar(16384), BDATA blob)");
             }
             stmt.close();
 
@@ -500,6 +505,9 @@ public class RDBDocumentStore implements
                 for (UpdateOp update : chunks) {
                     T doc = collection.newDocument(this);
                     update.increment(MODCOUNT, 1);
+                    if (hasChangesToCollisions(update)) {
+                        update.increment(NodeDocument.COLLISIONSMODCOUNT, 1);
+                    }
                     UpdateUtils.applyChanges(doc, update, comparator);
                     if (!update.getId().equals(doc.getId())) {
                         throw new DocumentStoreException("ID mismatch - UpdateOp: " + update.getId() + ", ID property: "
@@ -534,6 +542,9 @@ public class RDBDocumentStore implements
                 return null;
             }
             update.increment(MODCOUNT, 1);
+            if (hasChangesToCollisions(update)) {
+                update.increment(NodeDocument.COLLISIONSMODCOUNT, 1);
+            }
             UpdateUtils.applyChanges(doc, update, comparator);
             try {
                 insertDocuments(collection, Collections.singletonList(doc));
@@ -623,6 +634,9 @@ public class RDBDocumentStore implements
         if (checkConditions && !UpdateUtils.checkConditions(doc, update)) {
             return null;
         }
+        if (hasChangesToCollisions(update)) {
+            update.increment(NodeDocument.COLLISIONSMODCOUNT, 1);
+        }
         update.increment(MODCOUNT, 1);
         UpdateUtils.applyChanges(doc, update, comparator);
         doc.seal();
@@ -774,7 +788,8 @@ public class RDBDocumentStore implements
             Number flag = (Number) document.get(NodeDocument.HAS_BINARY_FLAG);
             Boolean hasBinary = flag == null ? false : flag.intValue() == NodeDocument.HAS_BINARY_VAL;
             Long modcount = (Long) document.get(MODCOUNT);
-            boolean success = dbUpdate(connection, tableName, document.getId(), modified, hasBinary, modcount, oldmodcount, data);
+            Long cmodcount = (Long) document.get(NodeDocument.COLLISIONSMODCOUNT);
+            boolean success = dbUpdate(connection, tableName, document.getId(), modified, hasBinary, modcount, cmodcount, oldmodcount, data);
             connection.commit();
             return success;
         } catch (SQLException ex) {
@@ -803,7 +818,8 @@ public class RDBDocumentStore implements
                 Number flag = (Number) document.get(NodeDocument.HAS_BINARY_FLAG);
                 Boolean hasBinary = flag == null ? false : flag.intValue() == NodeDocument.HAS_BINARY_VAL;
                 Long modcount = (Long) document.get(MODCOUNT);
-                dbInsert(connection, tableName, document.getId(), modified, hasBinary, modcount, data);
+                Long cmodcount = (Long) document.get(NodeDocument.COLLISIONSMODCOUNT);
+                dbInsert(connection, tableName, document.getId(), modified, hasBinary, modcount, cmodcount, data);
             }
             connection.commit();
         } catch (SQLException ex) {
@@ -949,9 +965,9 @@ public class RDBDocumentStore implements
         return result;
     }
 
-    private boolean dbUpdate(Connection connection, String tableName, String id, Long modified, Boolean hasBinary, Long modcount, Long oldmodcount,
+    private boolean dbUpdate(Connection connection, String tableName, String id, Long modified, Boolean hasBinary, Long modcount, Long cmodcount, Long oldmodcount,
             String data) throws SQLException {
-        String t = "update " + tableName + " set MODIFIED = ?, HASBINARY = ?, MODCOUNT = ?, DSIZE = ?, DATA = ?, BDATA = ? where ID = ?";
+        String t = "update " + tableName + " set MODIFIED = ?, HASBINARY = ?, MODCOUNT = ?, CMODCOUNT = ?, DSIZE = ?, DATA = ?, BDATA = ? where ID = ?";
         if (oldmodcount != null) {
             t += " and MODCOUNT = ?";
         }
@@ -961,6 +977,7 @@ public class RDBDocumentStore implements
             stmt.setObject(si++, modified, Types.BIGINT);
             stmt.setObject(si++, hasBinary ? 1 : 0, Types.SMALLINT);
             stmt.setObject(si++, modcount, Types.BIGINT);
+            stmt.setObject(si++, cmodcount == null ? 0 : cmodcount, Types.BIGINT);
             stmt.setObject(si++, data.length(), Types.BIGINT);
 
             if (data.length() < datalimit) {
@@ -987,15 +1004,16 @@ public class RDBDocumentStore implements
     }
 
     private boolean dbInsert(Connection connection, String tableName, String id, Long modified, Boolean hasBinary, Long modcount,
-            String data) throws SQLException {
+            Long cmodcount, String data) throws SQLException {
         PreparedStatement stmt = connection.prepareStatement("insert into " + tableName
-                + "(ID, MODIFIED, HASBINARY, MODCOUNT, DSIZE, DATA, BDATA) values (?, ?, ?, ?, ?, ?, ?)");
+                + "(ID, MODIFIED, HASBINARY, MODCOUNT, CMODCOUNT, DSIZE, DATA, BDATA) values (?, ?, ?, ?, ?, ?, ?, ?)");
         try {
             int si = 1;
             stmt.setString(si++, id);
             stmt.setObject(si++, modified, Types.BIGINT);
             stmt.setObject(si++, hasBinary ? 1 : 0, Types.SMALLINT);
             stmt.setObject(si++, modcount, Types.BIGINT);
+            stmt.setObject(si++, cmodcount == null ? 0 : cmodcount, Types.BIGINT);
             stmt.setObject(si++, data.length(), Types.BIGINT);
             if (data.length() < datalimit) {
                 stmt.setString(si++, data);
@@ -1157,17 +1175,6 @@ public class RDBDocumentStore implements
         }
     }
 
-    private <T extends Document> void applyToCache(Collection<T> collection, T oldDoc, T newDoc) {
-        if (collection == Collection.NODES) {
-            Lock lock = getAndLock(newDoc.getId());
-            try {
-                applyToCache((NodeDocument) oldDoc, (NodeDocument) newDoc);
-            } finally {
-                lock.unlock();
-            }
-        }
-    }
-
     private <T extends Document> void addToCacheIfNotNewer(Collection<T> collection, T doc) {
         if (collection == Collection.NODES) {
             String id = doc.getId();
@@ -1211,4 +1218,17 @@ public class RDBDocumentStore implements
             }
         }
     }
+
+    private boolean hasChangesToCollisions(UpdateOp update) {
+        for (Entry<Key, Operation> e : checkNotNull(update).getChanges().entrySet()) {
+            Key k = e.getKey();
+            Operation op = e.getValue();
+            if (op.type == Operation.Type.SET_MAP_ENTRY) {
+                if (NodeDocument.COLLISIONS.equals(k.getName())) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
 }