You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by sa...@apache.org on 2016/12/20 17:07:09 UTC

[2/2] lucene-solr:branch_6x: SOLR-9847: Stop blocking further schema updates while waiting for a pending update to propagate to other replicas. This reduces the likelihood of a (time-limited) distributed deadlock during concurrent schema updates.

SOLR-9847: Stop blocking further schema updates while waiting for a pending update to propagate to other replicas.  This reduces the likelihood of a (time-limited) distributed deadlock during concurrent schema updates.


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/cfbfc132
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/cfbfc132
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/cfbfc132

Branch: refs/heads/branch_6x
Commit: cfbfc13209c57e1c76bd478c3b584135b5d109eb
Parents: 791b8bc
Author: Steve Rowe <sa...@apache.org>
Authored: Tue Dec 20 12:05:33 2016 -0500
Committer: Steve Rowe <sa...@apache.org>
Committed: Tue Dec 20 12:05:59 2016 -0500

----------------------------------------------------------------------
 solr/CHANGES.txt                                |  4 +
 .../org/apache/solr/schema/SchemaManager.java   | 99 +++++++++++---------
 2 files changed, 59 insertions(+), 44 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/cfbfc132/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 2fd91f4..8cadb1b 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -199,6 +199,10 @@ Bug Fixes
 * SOLR-1953: It may be possible for temporary files to accumulate until the Solr process is shut down.
   (Karl Wright, Mark Miller)
 
+* SOLR-9847: Stop blocking further schema updates while waiting for a pending update to propagate to other replicas.
+  This reduces the likelihood of a (time-limited) distributed deadlock during concurrent schema updates.
+  (Mark Miller, Steve Rowe)
+
 Other Changes
 ----------------------
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/cfbfc132/solr/core/src/java/org/apache/solr/schema/SchemaManager.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/SchemaManager.java b/solr/core/src/java/org/apache/solr/schema/SchemaManager.java
index 3340631..8c3b5f0 100644
--- a/solr/core/src/java/org/apache/solr/schema/SchemaManager.java
+++ b/solr/core/src/java/org/apache/solr/schema/SchemaManager.java
@@ -88,9 +88,7 @@ public class SchemaManager {
 
     IndexSchema schema = req.getCore().getLatestSchema();
     if (schema instanceof ManagedIndexSchema && schema.isMutable()) {
-      synchronized (schema.getSchemaUpdateLock()) {
-        return doOperations(ops);
-      }
+      return doOperations(ops);
     } else {
       return singletonList(singletonMap(CommandOperation.ERR_MSGS, "schema is not editable"));
     }
@@ -107,52 +105,65 @@ public class SchemaManager {
     TimeOut timeOut = new TimeOut(timeout, TimeUnit.SECONDS);
     SolrCore core = req.getCore();
     String errorMsg = "Unable to persist managed schema. ";
-    while (!timeOut.hasTimedOut()) {
-      managedIndexSchema = getFreshManagedSchema(req.getCore());
-      for (CommandOperation op : operations) {
-        OpType opType = OpType.get(op.name);
-        if (opType != null) {
-          opType.perform(op, this);
-        } else {
-          op.addError("No such operation : " + op.name);
-        }
-      }
-      List errs = CommandOperation.captureErrors(operations);
-      if (!errs.isEmpty()) return errs;
-      SolrResourceLoader loader = req.getCore().getResourceLoader();
-      if (loader instanceof ZkSolrResourceLoader) {
-        ZkSolrResourceLoader zkLoader = (ZkSolrResourceLoader) loader;
-        StringWriter sw = new StringWriter();
-        try {
-          managedIndexSchema.persist(sw);
-        } catch (IOException e) {
-          throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "unable to serialize schema");
-          //unlikely
-        }
+    List errors = Collections.emptyList();
+    int latestVersion = -1;
 
-        try {
-          int latestVersion = ZkController.persistConfigResourceToZooKeeper(zkLoader, managedIndexSchema.getSchemaZkVersion(),
-              managedIndexSchema.getResourceName(), sw.toString().getBytes(StandardCharsets.UTF_8), true);
-          req.getCore().getCoreDescriptor().getCoreContainer().reload(req.getCore().getName());
-          waitForOtherReplicasToUpdate(timeOut, latestVersion);
-          return Collections.emptyList();
-        } catch (ZkController.ResourceModifiedInZkException e) {
-          log.info("Schema was modified by another node. Retrying..");
+    synchronized (req.getSchema().getSchemaUpdateLock()) {
+      while (!timeOut.hasTimedOut()) {
+        managedIndexSchema = getFreshManagedSchema(req.getCore());
+        for (CommandOperation op : operations) {
+          OpType opType = OpType.get(op.name);
+          if (opType != null) {
+            opType.perform(op, this);
+          } else {
+            op.addError("No such operation : " + op.name);
+          }
         }
-      } else {
-        try {
-          //only for non cloud stuff
-          managedIndexSchema.persistManagedSchema(false);
-          core.setLatestSchema(managedIndexSchema);
-          return Collections.emptyList();
-        } catch (SolrException e) {
-          log.warn(errorMsg);
-          return singletonList(errorMsg + e.getMessage());
+        errors = CommandOperation.captureErrors(operations);
+        if (!errors.isEmpty()) break;
+        SolrResourceLoader loader = req.getCore().getResourceLoader();
+        if (loader instanceof ZkSolrResourceLoader) {
+          ZkSolrResourceLoader zkLoader = (ZkSolrResourceLoader) loader;
+          StringWriter sw = new StringWriter();
+          try {
+            managedIndexSchema.persist(sw);
+          } catch (IOException e) {
+            throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "unable to serialize schema");
+            //unlikely
+          }
+
+          try {
+            latestVersion = ZkController.persistConfigResourceToZooKeeper
+                (zkLoader, managedIndexSchema.getSchemaZkVersion(), managedIndexSchema.getResourceName(),
+                 sw.toString().getBytes(StandardCharsets.UTF_8), true);
+            req.getCore().getCoreDescriptor().getCoreContainer().reload(req.getCore().getName());
+            break;
+          } catch (ZkController.ResourceModifiedInZkException e) {
+            log.info("Schema was modified by another node. Retrying..");
+          }
+        } else {
+          try {
+            //only for non cloud stuff
+            managedIndexSchema.persistManagedSchema(false);
+            core.setLatestSchema(managedIndexSchema);
+          } catch (SolrException e) {
+            log.warn(errorMsg);
+            errors = singletonList(errorMsg + e.getMessage());
+          }
+          break;
         }
       }
     }
-    log.warn(errorMsg + "Timed out.");
-    return singletonList(errorMsg + "Timed out.");
+    if (req.getCore().getResourceLoader() instanceof ZkSolrResourceLoader) {
+      // Don't block further schema updates while waiting for a pending update to propagate to other replicas.
+      // This reduces the likelihood of a (time-limited) distributed deadlock during concurrent schema updates.
+      waitForOtherReplicasToUpdate(timeOut, latestVersion);
+    }
+    if (errors.isEmpty() && timeOut.hasTimedOut()) {
+      log.warn(errorMsg + "Timed out.");
+      errors = singletonList(errorMsg + "Timed out.");
+    }
+    return errors;
   }
 
   private void waitForOtherReplicasToUpdate(TimeOut timeOut, int latestVersion) {