lucene-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From er...@apache.org
Subject svn commit: r1433787 - in /lucene/dev/branches/lucene_solr_4_1: ./ dev-tools/ lucene/ lucene/analysis/ lucene/analysis/icu/src/java/org/apache/lucene/collation/ lucene/backwards/ lucene/benchmark/ lucene/codecs/ lucene/core/ lucene/core/src/test/org/ap...
Date Wed, 16 Jan 2013 01:16:51 GMT
Author: erick
Date: Wed Jan 16 01:16:50 2013
New Revision: 1433787

URL: http://svn.apache.org/viewvc?rev=1433787&view=rev
Log:
Fix for SOLR-4300, race condition when more than one thread loaded a lazy core

Modified:
    lucene/dev/branches/lucene_solr_4_1/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/dev-tools/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/BUILD.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/CHANGES.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/JRE_VERSION_MIGRATION.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/LICENSE.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/MIGRATE.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/NOTICE.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/README.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/SYSTEM_REQUIREMENTS.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/analysis/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/analysis/icu/src/java/org/apache/lucene/collation/ICUCollationKeyFilterFactory.java
  (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/backwards/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/benchmark/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/build.xml   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/codecs/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/common-build.xml   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/core/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/core/src/test/org/apache/lucene/index/TestBackwardsCompatibility.java
  (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/core/src/test/org/apache/lucene/index/index.40.cfs.zip
  (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/core/src/test/org/apache/lucene/index/index.40.nocfs.zip
  (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/core/src/test/org/apache/lucene/index/index.40.optimized.cfs.zip
  (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/core/src/test/org/apache/lucene/index/index.40.optimized.nocfs.zip
  (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/demo/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/facet/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/grouping/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/highlighter/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/ivy-settings.xml   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/join/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/licenses/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/memory/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/misc/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/module-build.xml   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/queries/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/queryparser/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/sandbox/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/site/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/spatial/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/suggest/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/test-framework/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/lucene/tools/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/solr/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/solr/CHANGES.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_1/solr/LICENSE.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_1/solr/NOTICE.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_1/solr/README.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_1/solr/SYSTEM_REQUIREMENTS.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_1/solr/build.xml   (props changed)
    lucene/dev/branches/lucene_solr_4_1/solr/cloud-dev/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/solr/common-build.xml   (props changed)
    lucene/dev/branches/lucene_solr_4_1/solr/contrib/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/solr/core/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/solr/core/src/java/org/apache/solr/core/CoreContainer.java
    lucene/dev/branches/lucene_solr_4_1/solr/core/src/test/org/apache/solr/core/TestLazyCores.java
    lucene/dev/branches/lucene_solr_4_1/solr/example/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/solr/licenses/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/solr/licenses/httpclient-LICENSE-ASL.txt   (props
changed)
    lucene/dev/branches/lucene_solr_4_1/solr/licenses/httpclient-NOTICE.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_1/solr/licenses/httpcore-LICENSE-ASL.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_1/solr/licenses/httpcore-NOTICE.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_1/solr/licenses/httpmime-LICENSE-ASL.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_1/solr/licenses/httpmime-NOTICE.txt   (props changed)
    lucene/dev/branches/lucene_solr_4_1/solr/scripts/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/solr/site/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/solr/solrj/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/solr/test-framework/   (props changed)
    lucene/dev/branches/lucene_solr_4_1/solr/testlogging.properties   (props changed)
    lucene/dev/branches/lucene_solr_4_1/solr/webapp/   (props changed)

Modified: lucene/dev/branches/lucene_solr_4_1/solr/core/src/java/org/apache/solr/core/CoreContainer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene_solr_4_1/solr/core/src/java/org/apache/solr/core/CoreContainer.java?rev=1433787&r1=1433786&r2=1433787&view=diff
==============================================================================
--- lucene/dev/branches/lucene_solr_4_1/solr/core/src/java/org/apache/solr/core/CoreContainer.java
(original)
+++ lucene/dev/branches/lucene_solr_4_1/solr/core/src/java/org/apache/solr/core/CoreContainer.java
Wed Jan 16 01:16:50 2013
@@ -128,6 +128,8 @@ public class CoreContainer 
 
   protected final Map<String, CoreDescriptor> dynamicDescriptors = new LinkedHashMap<String,
CoreDescriptor>();
 
+  protected final Set<String> pendingDynamicCoreLoads = new HashSet<String>();
+
   protected final Map<String,Exception> coreInitFailures = 
     Collections.synchronizedMap(new LinkedHashMap<String,Exception>());
   
@@ -1245,17 +1247,8 @@ public class CoreContainer 
       }
     }
   }
-  
-  /** Gets a core by name and increase its refcount.
-   * @see SolrCore#close() 
-   * @param name the core name
-   * @return the core if found
-   */
-  public SolrCore getCore(String name) {
-    name = checkDefault(name);
-    // Do this in two phases since we don't want to lock access to the cores over a load.
+  private SolrCore getCoreFromAnyList(String name) {
     SolrCore core;
-
     synchronized (cores) {
       core = cores.get(name);
       if (core != null) {
@@ -1274,20 +1267,64 @@ public class CoreContainer 
         return core;
       }
     }
+    return null;
+  }
+  /** Gets a core by name and increase its refcount.
+   * @see SolrCore#close() 
+   * @param name the core name
+   * @return the core if found
+   */
+  public SolrCore getCore(String name) {
+    name = checkDefault(name);
+    // Do this in two phases since we don't want to lock access to the cores over a load.
+    SolrCore core = getCoreFromAnyList(name);
+
+    if (core != null) return core;
+
+    // OK, it's not presently in any list, is it in the list of dynamic cores but not loaded
yet? If so, load it.
     CoreDescriptor desc =  dynamicDescriptors.get(name);
     if (desc == null) { //Nope, no transient core with this name
       return null;
     }
+
+    // Keep multiple threads from loading the same core at the same time.
     try {
-      core = create(desc); // This should throw an error if it fails.
-      core.open();
-      if (desc.isTransient()) {
-        registerLazyCore(name, core, false);    // This is a transient core
-      } else {
-        register(name, core, false); // This is a "permanent", although deferred-load core
+      boolean isPending;
+      synchronized (pendingDynamicCoreLoads) {
+        isPending = pendingDynamicCoreLoads.contains(name);
+        if (! isPending) {
+          pendingDynamicCoreLoads.add(name);
+        }
       }
-    } catch (Exception ex) {
-      throw recordAndThrow(name, "Unable to create core" + name, ex);
+
+      while (isPending) {
+        try {
+          Thread.sleep(100);
+        } catch (InterruptedException e) {
+          return null; // Seems best not to do anything at all if the thread is interrupted
+        }
+
+        synchronized (pendingDynamicCoreLoads) {
+          if (!pendingDynamicCoreLoads.contains(name)) {
+            // NOTE: If, for some reason, the load failed, we'll return null here and presumably
the log will show
+            // why. We'll fail all over again next time if the problem isn't corrected.
+            return getCoreFromAnyList(name);
+          }
+        }
+      }
+      try {
+        core = create(desc); // This should throw an error if it fails.
+        core.open();
+        if (desc.isTransient()) {
+          registerLazyCore(name, core, false);    // This is a transient core
+        } else {
+          register(name, core, false); // This is a "permanent", although deferred-load core
+        }
+      } catch (Exception ex) {
+        throw recordAndThrow(name, "Unable to create core" + name, ex);
+      }
+    } finally {
+      pendingDynamicCoreLoads.remove(name);
     }
     return core;
   }

Modified: lucene/dev/branches/lucene_solr_4_1/solr/core/src/test/org/apache/solr/core/TestLazyCores.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene_solr_4_1/solr/core/src/test/org/apache/solr/core/TestLazyCores.java?rev=1433787&r1=1433786&r2=1433787&view=diff
==============================================================================
--- lucene/dev/branches/lucene_solr_4_1/solr/core/src/test/org/apache/solr/core/TestLazyCores.java
(original)
+++ lucene/dev/branches/lucene_solr_4_1/solr/core/src/test/org/apache/solr/core/TestLazyCores.java
Wed Jan 16 01:16:50 2013
@@ -34,8 +34,10 @@ import org.junit.Test;
 
 import java.io.File;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.List;
 
 public class TestLazyCores extends SolrTestCaseJ4 {
 
@@ -246,6 +248,44 @@ public class TestLazyCores extends SolrT
     }
   }
 
+  static List<SolrCore> _theCores = new ArrayList<SolrCore>();
+  // Test case for SOLR-4300
+  @Test
+  public void testRace() throws Exception {
+    final CoreContainer cc = init();
+    try {
+
+      Thread[] threads = new Thread[15];
+      for (int idx = 0; idx < threads.length; idx++) {
+        threads[idx] = new Thread() {
+          @Override
+          public void run() {
+            SolrCore core = cc.getCore("collectionLazy3");
+            synchronized (_theCores) {
+              _theCores.add(core);
+            }
+          }
+        };
+        threads[idx].start();
+      }
+
+      for (Thread thread : threads) {
+        thread.join();
+      }
+
+      for (int idx = 0; idx < _theCores.size() - 1; ++idx) {
+        assertEquals("Cores should be the same!", _theCores.get(idx), _theCores.get(idx +
1));
+      }
+
+      for (SolrCore core : _theCores) {
+        core.close();
+      }
+
+    } finally {
+      cc.shutdown();
+    }
+  }
+
   private void checkNotInCores(CoreContainer cc, String... nameCheck) {
     Collection<String> names = cc.getCoreNames();
     for (String name : nameCheck) {



Mime
View raw message