You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@solr.apache.org by md...@apache.org on 2022/04/18 16:20:54 UTC
[solr] branch branch_9x updated: SOLR-16143 SolrConfig ResourceProvider can miss updates from ZooKeeper (#801)
This is an automated email from the ASF dual-hosted git repository.
mdrob pushed a commit to branch branch_9x
in repository https://gitbox.apache.org/repos/asf/solr.git
The following commit(s) were added to refs/heads/branch_9x by this push:
new c1ddbe632c7 SOLR-16143 SolrConfig ResourceProvider can miss updates from ZooKeeper (#801)
c1ddbe632c7 is described below
commit c1ddbe632c7204698603387cbe2912d801637320
Author: Mike Drob <md...@apache.org>
AuthorDate: Mon Apr 18 11:20:03 2022 -0500
SOLR-16143 SolrConfig ResourceProvider can miss updates from ZooKeeper (#801)
---
solr/CHANGES.txt | 2 +
.../src/java/org/apache/solr/core/SolrConfig.java | 2 +-
.../configsets/_default/conf/managed-schema.xml | 32 ++++++++
.../solr/configsets/_default/conf/solrconfig.xml | 87 +++++++++++++++++++++
.../solr/util/MultipleManagedSchemasTest.java | 90 ++++++++++++++++++++++
5 files changed, 212 insertions(+), 1 deletion(-)
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index e0f544531fe..1789dc1324a 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -745,6 +745,8 @@ Bug Fixes
* SOLR-16022: Enforce special character requirements on passwords with length less than 15 (Timothy Potter)
+* SOLR-16143: SolrConfig ResourceProvider can miss updates from ZooKeeper (Mike Drob)
+
================== 8.11.2 ==================
Bug Fixes
diff --git a/solr/core/src/java/org/apache/solr/core/SolrConfig.java b/solr/core/src/java/org/apache/solr/core/SolrConfig.java
index c3559585e8f..bb0ec7166bb 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrConfig.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrConfig.java
@@ -180,7 +180,7 @@ public class SolrConfig implements MapSerializable {
ZkSolrResourceLoader.ZkByteArrayInputStream zkin =
(ZkSolrResourceLoader.ZkByteArrayInputStream) in;
zkVersion = zkin.getStat().getVersion();
- hash = Objects.hash(zkVersion, overlay.getZnodeVersion());
+ hash = Objects.hash(zkin.getStat().getCtime(), zkVersion, overlay.getZnodeVersion());
this.fileName = zkin.fileName;
}
}
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/managed-schema.xml b/solr/core/src/test-files/solr/configsets/_default/conf/managed-schema.xml
new file mode 100644
index 00000000000..fbf0cbbe6db
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/managed-schema.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<schema name="default-config" version="1.6">
+ <uniqueKey>id</uniqueKey>
+ <field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />
+ <fieldType name="string" class="solr.StrField" sortMissingLast="true" docValues="true" />
+
+ <field name="_version_" type="plong" indexed="false" stored="false"/>
+ <fieldType name="plong" class="solr.LongPointField" docValues="true"/>
+
+ <fieldType name="booleans" class="solr.BoolField" sortMissingLast="true" multiValued="true"/>
+ <dynamicField name="*_bs" type="booleans" indexed="true" stored="true"/>
+
+ <!-- Used by AddSchemaFieldsUpdateProcessorFactory field type mappings -->
+ <fieldType name="text_general" class="solr.TextField" positionIncrementGap="100" multiValued="true" />
+</schema>
diff --git a/solr/core/src/test-files/solr/configsets/_default/conf/solrconfig.xml b/solr/core/src/test-files/solr/configsets/_default/conf/solrconfig.xml
new file mode 100644
index 00000000000..b6191029056
--- /dev/null
+++ b/solr/core/src/test-files/solr/configsets/_default/conf/solrconfig.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<config>
+ <luceneMatchVersion>${tests.luceneMatchVersion:LATEST}</luceneMatchVersion>
+
+ <dataDir>${solr.data.dir:}</dataDir>
+
+ <directoryFactory name="DirectoryFactory"
+ class="${solr.directoryFactory:solr.NRTCachingDirectoryFactory}"/>
+
+ <codecFactory class="solr.SchemaCodecFactory"/>
+
+ <!-- The default high-performance update handler -->
+ <updateHandler class="solr.DirectUpdateHandler2">
+ <updateLog>
+ <str name="dir">${solr.ulog.dir:}</str>
+ <int name="numVersionBuckets">${solr.ulog.numVersionBuckets:65536}</int>
+ </updateLog>
+ </updateHandler>
+
+ <!-- Primary search handler, expected by most clients, examples and UI frameworks -->
+ <requestHandler name="/select" class="solr.SearchHandler">
+ <lst name="defaults">
+ <str name="echoParams">explicit</str>
+ <int name="rows">10</int>
+ </lst>
+ </requestHandler>
+
+ <!-- Add unknown fields to the schema
+
+ Field type guessing update request processors that will
+ attempt to parse string-typed field values as Booleans, Longs,
+ Doubles, or Dates, and then add schema fields with the guessed
+ field types Text content will be indexed as "text_general" as
+ well as a copy to a plain string version in *_str.
+ See the updateRequestProcessorChain defined later for the order they are executed in.
+
+ These require that the schema is both managed and mutable, by
+ declaring schemaFactory as ManagedIndexSchemaFactory, with
+ mutable specified as true.
+
+ See https://solr.apache.org/guide/schemaless-mode.html for further explanation.
+
+ -->
+ <updateProcessor class="solr.UUIDUpdateProcessorFactory" name="uuid"/>
+ <updateProcessor class="solr.AddSchemaFieldsUpdateProcessorFactory" name="add-schema-fields">
+ <lst name="typeMapping">
+ <str name="valueClass">java.lang.String</str>
+ <str name="fieldType">text_general</str>
+ <lst name="copyField">
+ <str name="dest">*_str</str>
+ <int name="maxChars">256</int>
+ </lst>
+ <!-- Use as default mapping instead of defaultFieldType -->
+ <bool name="default">true</bool>
+ </lst>
+ <lst name="typeMapping">
+ <str name="valueClass">java.lang.Boolean</str>
+ <str name="fieldType">booleans</str>
+ </lst>
+ </updateProcessor>
+
+ <!-- The update.autoCreateFields property can be turned to false to disable schemaless mode -->
+ <updateRequestProcessorChain name="add-unknown-fields-to-the-schema" default="${update.autoCreateFields:true}"
+ processor="uuid,add-schema-fields">
+ <processor class="solr.LogUpdateProcessorFactory"/>
+ <processor class="solr.DistributedUpdateProcessorFactory"/>
+ <processor class="solr.RunUpdateProcessorFactory"/>
+ </updateRequestProcessorChain>
+
+</config>
diff --git a/solr/core/src/test/org/apache/solr/util/MultipleManagedSchemasTest.java b/solr/core/src/test/org/apache/solr/util/MultipleManagedSchemasTest.java
new file mode 100644
index 00000000000..88a6630ab8b
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/util/MultipleManagedSchemasTest.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.util;
+
+import java.lang.invoke.MethodHandles;
+import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.request.CollectionAdminRequest;
+import org.apache.solr.client.solrj.request.ConfigSetAdminRequest;
+import org.apache.solr.cloud.SolrCloudTestCase;
+import org.apache.solr.common.cloud.ZkMaintenanceUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MultipleManagedSchemasTest extends SolrCloudTestCase {
+ private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ System.setProperty("managed.schema.mutable", "false");
+ configureCluster(1).configure();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (cluster != null) {
+ cluster.shutdown();
+ }
+ super.tearDown();
+ }
+
+ @Test
+ public void testSameCollectionNameWithMultipleSchemas() throws Exception {
+ CloudSolrClient client = cluster.getSolrClient();
+
+ String name = "COLL1";
+ String zkPath = ZkMaintenanceUtils.CONFIGS_ZKNODE + "/" + name;
+
+ ZkMaintenanceUtils.uploadToZK(cluster.getZkClient(), configset("_default"), zkPath, null);
+ // Passing null for the second argument makes this test succeed
+ CollectionAdminRequest.createCollection(name, name, 1, 1).process(client);
+
+ // Verify that the config set and collection were created
+ ConfigSetAdminRequest.List list = new ConfigSetAdminRequest.List();
+ assertTrue(
+ "Should have COLL1 config set", list.process(client).getConfigSets().contains("COLL1"));
+ assertTrue(
+ "Should have created COLL1",
+ CollectionAdminRequest.listCollections(client).contains("COLL1"));
+
+ // Delete the config set and collection, and verify
+ CollectionAdminRequest.deleteCollection(name).process(client);
+ new ConfigSetAdminRequest.Delete().setConfigSetName(name).process(client);
+
+ assertFalse(
+ "Should not have COLL1 config set", list.process(client).getConfigSets().contains("COLL1"));
+ assertTrue(
+ "Should have deleted all collections",
+ CollectionAdminRequest.listCollections(client).isEmpty());
+
+ // Upload the replacement config set
+ ZkMaintenanceUtils.uploadToZK(cluster.getZkClient(), configset("cloud-managed"), zkPath, null);
+ assertTrue(
+ "Should have COLL1 config set", list.process(client).getConfigSets().contains("COLL1"));
+
+ // This is the call that fails
+ // Passing null for the config name here also lets the test pass!
+ CollectionAdminRequest.createCollection(name, name, 1, 1).process(client);
+ assertTrue(
+ "Should have created COLL1",
+ CollectionAdminRequest.listCollections(client).contains("COLL1"));
+ }
+}