Author: mreutegg
Date: Tue May 19 14:21:11 2015
New Revision: 1680301

URL: http://svn.apache.org/r1680301
Log:
OAK-2888: ArrayIndexOutOfBoundsException in UnsavedModifications.put()

Modified:
    
jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UnsavedModifications.java
    
jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/UnsavedModificationsTest.java

Modified: 
jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UnsavedModifications.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UnsavedModifications.java?rev=1680301&r1=1680300&r2=1680301&view=diff
==============================================================================
--- 
jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UnsavedModifications.java
 (original)
+++ 
jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UnsavedModifications.java
 Tue May 19 14:21:11 2015
@@ -70,6 +70,11 @@ class UnsavedModifications implements Cl
     private final ConcurrentMap<String, Revision> map = mapFactory.create();
 
     /**
+     * Monitor object to synchronize updates on the {@link #map}. See OAK-2888.
+     */
+    private final Object update = new Object();
+
+    /**
      * Puts a revision for the given path. The revision for the given path is
      * only put if there is no modification present for the revision or if the
      * current modification revision is older than the passed revision.
@@ -83,20 +88,22 @@ class UnsavedModifications implements Cl
     public Revision put(@Nonnull String path, @Nonnull Revision revision) {
         checkNotNull(path);
         checkNotNull(revision);
-        for (;;) {
-            Revision previous = map.get(path);
-            if (previous == null) {
-                if (map.putIfAbsent(path, revision) == null) {
-                    return null;
-                }
-            } else {
-                if (previous.compareRevisionTime(revision) < 0) {
-                    if (map.replace(path, previous, revision)) {
-                        return previous;
+        synchronized (update) {
+            for (;;) {
+                Revision previous = map.get(path);
+                if (previous == null) {
+                    if (map.putIfAbsent(path, revision) == null) {
+                        return null;
                     }
                 } else {
-                    // revision is earlier, do not update
-                    return null;
+                    if (previous.compareRevisionTime(revision) < 0) {
+                        if (map.replace(path, previous, revision)) {
+                            return previous;
+                        }
+                    } else {
+                        // revision is earlier, do not update
+                        return null;
+                    }
                 }
             }
         }
@@ -212,8 +219,10 @@ class UnsavedModifications implements Cl
                     }
                     store.getDocumentStore().update(NODES, ids, updateOp);
                     LOG.debug("Updated _lastRev to {} on {}", lastRev, ids);
-                    for (String path : pathList) {
-                        map.remove(path, lastRev);
+                    synchronized (update) {
+                        for (String path : pathList) {
+                            map.remove(path, lastRev);
+                        }
                     }
                     pathList.clear();
                     updateOp = null;

Modified: 
jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/UnsavedModificationsTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/UnsavedModificationsTest.java?rev=1680301&r1=1680300&r2=1680301&view=diff
==============================================================================
--- 
jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/UnsavedModificationsTest.java
 (original)
+++ 
jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/UnsavedModificationsTest.java
 Tue May 19 14:21:11 2015
@@ -31,7 +31,6 @@ import org.junit.Test;
  */
 public class UnsavedModificationsTest {
 
-    @Ignore
     @Test
     public void concurrent() throws Exception {
         final List<Exception> exceptions = Collections.synchronizedList(
@@ -96,15 +95,20 @@ public class UnsavedModificationsTest {
         });
         t2.start();
 
-        while (exceptions.isEmpty()) {
+        long end = System.currentTimeMillis() + 5000;
+        while (exceptions.isEmpty() && System.currentTimeMillis() < end) {
             Thread.sleep(1000);
-            System.out.println("size: " + mod.getPaths().size());
         }
 
         try {
             for (Exception e : exceptions) {
                 throw e;
             }
+
+            exceptions.add(new Exception("stop"));
+            t1.join();
+            t2.join();
+
         } finally {
             ns.dispose();
             mod.close();


Reply via email to