You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by yo...@apache.org on 2020/02/28 02:11:47 UTC
[lucene-solr] branch jira/SOLR-13101 updated: SOLR-14213:
Configuring Solr Cloud to use Shared Storage (#1223)
This is an automated email from the ASF dual-hosted git repository.
yonik pushed a commit to branch jira/SOLR-13101
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git
The following commit(s) were added to refs/heads/jira/SOLR-13101 by this push:
new d46803f SOLR-14213: Configuring Solr Cloud to use Shared Storage (#1223)
d46803f is described below
commit d46803f4fe9844f5e09f7b7d4548457e446933f0
Author: Andy Vuong <an...@users.noreply.github.com>
AuthorDate: Thu Feb 27 18:11:35 2020 -0800
SOLR-14213: Configuring Solr Cloud to use Shared Storage (#1223)
* Add SharedStoreConfig for initiating shared store support and refactor tests setup
* Add missing condition
* Fix test failure
* Initialize fields in constructor and fix tests
* load shared store manager vs corecontainer
* Undo change
---
.../cloud/api/collections/CreateCollectionCmd.java | 7 ++
.../java/org/apache/solr/core/CoreContainer.java | 25 +++++-
.../src/java/org/apache/solr/core/NodeConfig.java | 18 +++-
.../org/apache/solr/core/SharedStoreConfig.java | 44 ++++++++++
.../java/org/apache/solr/core/SolrXmlConfig.java | 21 +++--
.../store/blob/metadata/ServerSideMetadata.java | 8 +-
.../solr/store/blob/process/BlobProcessUtil.java | 18 ++--
.../solr/store/blob/process/CorePullTask.java | 39 +++++----
.../solr/store/blob/process/CorePullerFeeder.java | 22 ++---
.../solr/store/blob/process/CoreSyncFeeder.java | 10 +--
.../shared/SharedCoreConcurrencyController.java | 7 +-
.../solr/store/shared/SharedStoreManager.java | 95 +++++++++++-----------
solr/core/src/test-files/solr/solr-sharedstore.xml | 58 +++++++++++++
.../SharedStorageShardMetadataTest.java | 16 +---
.../SimpleSharedStorageCollectionTest.java | 50 ++++++------
.../solr/store/blob/SharedStorageSplitTest.java | 14 +---
.../store/shared/SharedCoreConcurrencyTest.java | 23 ++----
.../store/shared/SharedStoreMissingCoreTest.java | 35 ++------
.../shared/SimpleSharedStoreEndToEndPullTest.java | 18 ----
.../shared/SimpleSharedStoreEndToEndPushTest.java | 19 +----
.../store/shared/SolrCloudSharedStoreTestCase.java | 39 ++++++++-
.../SharedShardMetadataControllerTest.java | 8 +-
.../DistributedZkUpdateProcessorTest.java | 22 -----
23 files changed, 342 insertions(+), 274 deletions(-)
diff --git a/solr/core/src/java/org/apache/solr/cloud/api/collections/CreateCollectionCmd.java b/solr/core/src/java/org/apache/solr/cloud/api/collections/CreateCollectionCmd.java
index 872068d..9197932 100644
--- a/solr/core/src/java/org/apache/solr/cloud/api/collections/CreateCollectionCmd.java
+++ b/solr/core/src/java/org/apache/solr/cloud/api/collections/CreateCollectionCmd.java
@@ -109,11 +109,18 @@ public class CreateCollectionCmd implements OverseerCollectionMessageHandler.Cmd
if (ocmh.zkStateReader.aliasesManager != null) { // not a mock ZkStateReader
ocmh.zkStateReader.aliasesManager.update();
}
+ final boolean sharedIndex = message.getBool(SHARED_INDEX, false);
final Aliases aliases = ocmh.zkStateReader.getAliases();
final String collectionName = message.getStr(NAME);
final boolean waitForFinalState = message.getBool(WAIT_FOR_FINAL_STATE, false);
final String alias = message.getStr(ALIAS, collectionName);
log.info("Create collection {}", collectionName);
+
+ if (sharedIndex && !ocmh.overseer.getCoreContainer().isSharedStoreEnabled()) {
+ throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
+ "Collection " + collectionName + " cannot be created because shared storage is not enabled on this cluster."
+ + " Check solr.xml for the correct configurations");
+ }
if (clusterState.hasCollection(collectionName)) {
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "collection already exists: " + collectionName);
}
diff --git a/solr/core/src/java/org/apache/solr/core/CoreContainer.java b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
index 0bc662d..7e911be 100644
--- a/solr/core/src/java/org/apache/solr/core/CoreContainer.java
+++ b/solr/core/src/java/org/apache/solr/core/CoreContainer.java
@@ -229,6 +229,8 @@ public class CoreContainer {
protected volatile AutoscalingHistoryHandler autoscalingHistoryHandler;
protected SharedStoreManager sharedStoreManager;
+
+ private volatile boolean discoveredSharedCollection = false;
// Bits for the state variable.
@@ -736,7 +738,12 @@ public class CoreContainer {
if (isZooKeeperAware()) {
metricManager.loadClusterReporters(metricReporters, this);
- sharedStoreManager = new SharedStoreManager(getZkController());
+
+ if (cfg.getSharedStoreConfig() != null) {
+ log.info("Shared storage is enabled in Solr Cloud. Initiating SharedStoreManager.");
+ sharedStoreManager = new SharedStoreManager(this);
+ sharedStoreManager.load();
+ }
}
// setup executor to load cores in parallel
@@ -756,6 +763,12 @@ public class CoreContainer {
// is set to true for them
// TODO: should this go behind some config?
List<CoreDescriptor> additionalCoreDescriptors = discoverAdditionalCoreDescriptorsForSharedReplicas(cds);
+ if (!isSharedStoreEnabled() && discoveredSharedCollection) {
+ throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
+ "Core discovery found cores belonging to shared collections but shared storage is not enabled on "
+ + "this cluster! Solr is aborting startup. Check solr.xml for the correct configurations.");
+ }
+
if (!additionalCoreDescriptors.isEmpty()) {
// enhance the list of discovered cores with the additional ones we just discovered/created
cds = new ArrayList<>(cds);
@@ -864,6 +877,7 @@ public class CoreContainer {
// skip non-shared collections
continue;
}
+ discoveredSharedCollection = true;
// TODO: if shard activation(including post split) can guarantee core existence locally we can skip inactive shards
// go over collection's replicas belonging to this node
@@ -1075,8 +1089,7 @@ public class CoreContainer {
}
if (sharedStoreManager != null) {
- sharedStoreManager.getBlobProcessManager().shutdown();
- sharedStoreManager.getBlobDeleteManager().shutdown();
+ sharedStoreManager.shutdown();
}
}
@@ -2101,7 +2114,7 @@ public class CoreContainer {
* the SharedCoreConcurrencyController cache; see SOLR-14134
*/
public void evictSharedCoreMetadata(CoreDescriptor cd) {
- if (!isZooKeeperAware()) {
+ if (!isZooKeeperAware() || !isSharedStoreEnabled()) {
return;
}
@@ -2116,6 +2129,10 @@ public class CoreContainer {
" and shard " + shardId + " from shared core concurrency cache");
}
}
+
+ public boolean isSharedStoreEnabled() {
+ return getSharedStoreManager() != null;
+ }
static {
ExecutorUtil.addThreadLocalProvider(SolrRequestInfo.getInheritableThreadLocalProvider());
diff --git a/solr/core/src/java/org/apache/solr/core/NodeConfig.java b/solr/core/src/java/org/apache/solr/core/NodeConfig.java
index 62c2a98..c273f1a 100644
--- a/solr/core/src/java/org/apache/solr/core/NodeConfig.java
+++ b/solr/core/src/java/org/apache/solr/core/NodeConfig.java
@@ -78,6 +78,8 @@ public class NodeConfig {
private final PluginInfo transientCacheConfig;
private final PluginInfo tracerConfig;
+
+ private final SharedStoreConfig sharedStoreConfig;
private NodeConfig(String nodeName, Path coreRootDirectory, Path solrDataHome, Integer booleanQueryMaxClauseCount,
Path configSetBaseDirectory, String sharedLibDirectory,
@@ -87,7 +89,8 @@ public class NodeConfig {
LogWatcherConfig logWatcherConfig, CloudConfig cloudConfig, Integer coreLoadThreads, int replayUpdatesThreads,
int transientCacheSize, boolean useSchemaCache, String managementPath, SolrResourceLoader loader,
Properties solrProperties, PluginInfo[] backupRepositoryPlugins,
- MetricsConfig metricsConfig, PluginInfo transientCacheConfig, PluginInfo tracerConfig) {
+ MetricsConfig metricsConfig, PluginInfo transientCacheConfig, PluginInfo tracerConfig,
+ SharedStoreConfig sharedStoreConfig) {
this.nodeName = nodeName;
this.coreRootDirectory = coreRootDirectory;
this.solrDataHome = solrDataHome;
@@ -114,6 +117,7 @@ public class NodeConfig {
this.metricsConfig = metricsConfig;
this.transientCacheConfig = transientCacheConfig;
this.tracerConfig = tracerConfig;
+ this.sharedStoreConfig = sharedStoreConfig;
if (this.cloudConfig != null && this.getCoreLoadThreadCount(false) < 2) {
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
@@ -232,6 +236,10 @@ public class NodeConfig {
public PluginInfo getTracerConfiguratorPluginInfo() {
return tracerConfig;
}
+
+ public SharedStoreConfig getSharedStoreConfig() {
+ return sharedStoreConfig;
+ }
public static class NodeConfigBuilder {
@@ -261,6 +269,7 @@ public class NodeConfig {
private MetricsConfig metricsConfig;
private PluginInfo transientCacheConfig;
private PluginInfo tracerConfig;
+ private SharedStoreConfig sharedStoreConfig;
private final SolrResourceLoader loader;
private final String nodeName;
@@ -422,13 +431,18 @@ public class NodeConfig {
this.tracerConfig = tracerConfig;
return this;
}
+
+ public NodeConfigBuilder setSharedStoreConfig(SharedStoreConfig sharedStoreConfig) {
+ this.sharedStoreConfig = sharedStoreConfig;
+ return this;
+ }
public NodeConfig build() {
return new NodeConfig(nodeName, coreRootDirectory, solrDataHome, booleanQueryMaxClauseCount,
configSetBaseDirectory, sharedLibDirectory, shardHandlerFactoryConfig,
updateShardHandlerConfig, coreAdminHandlerClass, collectionsAdminHandlerClass, healthCheckHandlerClass, infoHandlerClass, configSetsHandlerClass,
logWatcherConfig, cloudConfig, coreLoadThreads, replayUpdatesThreads, transientCacheSize, useSchemaCache, managementPath, loader, solrProperties,
- backupRepositoryPlugins, metricsConfig, transientCacheConfig, tracerConfig);
+ backupRepositoryPlugins, metricsConfig, transientCacheConfig, tracerConfig, sharedStoreConfig);
}
}
}
diff --git a/solr/core/src/java/org/apache/solr/core/SharedStoreConfig.java b/solr/core/src/java/org/apache/solr/core/SharedStoreConfig.java
new file mode 100644
index 0000000..05c698d
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/core/SharedStoreConfig.java
@@ -0,0 +1,44 @@
+/*
+ * 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.core;
+
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.core.SolrXmlConfig;
+
+/**
+ * Configuration class representing the configuration of Solr Cloud using shared storage
+ * to persist index files. The configuration properties come from solr.xml and are loaded
+ * via {@link SolrXmlConfig} at Solr startup. The presence of sharedStore section in the solr.xml
+ * file of a Solr Cloud mode cluster indicates the user's intention to enable shared storage
+ * capabilities in the cluster and starts the necessary components required to create/support
+ * shared-type Solr collections.
+ *
+ * TODO: This class is bare bones until we convert the many hard coded configuration values
+ * into configurable fields that can be specified under this section. The current responsibility
+ * of this class is to ensure shared storage is enabled on the cluster and initiate the necessary
+ * processes associated with it.
+ */
+public class SharedStoreConfig {
+
+ public static SharedStoreConfig loadSharedStoreConfig(NamedList<Object> nl) {
+ if (nl == null) {
+ // shared store is not configured
+ return null;
+ }
+ return new SharedStoreConfig();
+ }
+}
diff --git a/solr/core/src/java/org/apache/solr/core/SolrXmlConfig.java b/solr/core/src/java/org/apache/solr/core/SolrXmlConfig.java
index 3be075f..54358a7 100644
--- a/solr/core/src/java/org/apache/solr/core/SolrXmlConfig.java
+++ b/solr/core/src/java/org/apache/solr/core/SolrXmlConfig.java
@@ -16,10 +16,8 @@
*/
package org.apache.solr.core;
-import javax.management.MBeanServer;
-import javax.xml.xpath.XPath;
-import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathExpressionException;
+import static org.apache.solr.common.params.CommonParams.NAME;
+
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.lang.invoke.MethodHandles;
@@ -34,7 +32,11 @@ import java.util.Map;
import java.util.Properties;
import java.util.Set;
-import com.google.common.base.Strings;
+import javax.management.MBeanServer;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+
import org.apache.commons.io.IOUtils;
import org.apache.solr.client.solrj.impl.HttpClientUtil;
import org.apache.solr.common.SolrException;
@@ -51,7 +53,7 @@ import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
-import static org.apache.solr.common.params.CommonParams.NAME;
+import com.google.common.base.Strings;
/**
@@ -95,6 +97,12 @@ public class SolrXmlConfig {
}
updateConfig = deprecatedUpdateConfig;
}
+
+ SharedStoreConfig sharedStoreConfig = null;
+ if (config.getNodeList("solr/sharedStore", false).getLength() > 0) {
+ sharedStoreConfig = SharedStoreConfig.loadSharedStoreConfig(
+ readNodeListAsNamedList(config, "solr/sharedStore/*[@name]", "<sharedStore>"));
+ }
NodeConfig.NodeConfigBuilder configBuilder = new NodeConfig.NodeConfigBuilder(nodeName, config.getResourceLoader());
configBuilder.setUpdateShardHandlerConfig(updateConfig);
@@ -107,6 +115,7 @@ public class SolrXmlConfig {
configBuilder.setCloudConfig(cloudConfig);
configBuilder.setBackupRepositoryPlugins(getBackupRepositoryPluginInfos(config));
configBuilder.setMetricsConfig(getMetricsConfig(config));
+ configBuilder.setSharedStoreConfig(sharedStoreConfig);
return fillSolrSection(configBuilder, entries);
}
diff --git a/solr/core/src/java/org/apache/solr/store/blob/metadata/ServerSideMetadata.java b/solr/core/src/java/org/apache/solr/store/blob/metadata/ServerSideMetadata.java
index d65139a..f18d97f 100644
--- a/solr/core/src/java/org/apache/solr/store/blob/metadata/ServerSideMetadata.java
+++ b/solr/core/src/java/org/apache/solr/store/blob/metadata/ServerSideMetadata.java
@@ -107,10 +107,10 @@ public class ServerSideMetadata {
*
* @throws Exception if core corresponding to <code>coreName</code> can't be found.
*/
- public ServerSideMetadata(String coreName, CoreContainer container, boolean reserveCommit) throws Exception {
+ public ServerSideMetadata(String coreName, CoreContainer coreContainer, boolean reserveCommit) throws Exception {
this.coreName = coreName;
- this.container = container;
- this.core = container.getCore(coreName);
+ this.container = coreContainer;
+ this.core = coreContainer.getCore(coreName);
if (core == null) {
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Can't find core " + coreName);
@@ -193,7 +193,7 @@ public class ServerSideMetadata {
}
public CoreContainer getCoreContainer() {
- return this.container;
+ return container;
}
public long getGeneration() {
diff --git a/solr/core/src/java/org/apache/solr/store/blob/process/BlobProcessUtil.java b/solr/core/src/java/org/apache/solr/store/blob/process/BlobProcessUtil.java
index 7df8aa4..9cf5d02 100644
--- a/solr/core/src/java/org/apache/solr/store/blob/process/BlobProcessUtil.java
+++ b/solr/core/src/java/org/apache/solr/store/blob/process/BlobProcessUtil.java
@@ -18,10 +18,13 @@ package org.apache.solr.store.blob.process;
import java.lang.invoke.MethodHandles;
-import org.apache.solr.core.CoreContainer;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.store.shared.SharedStoreManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.annotations.VisibleForTesting;
+
/**
* Utils related to blob background process e.g. init/shutdown of blob's background processes
*/
@@ -33,18 +36,19 @@ public class BlobProcessUtil {
/*
* Start the Blob store async core pull machinery
*/
- public BlobProcessUtil(CoreContainer coreContainer) {
- this(coreContainer, new CorePullerFeeder(coreContainer));
+ public void load(SharedStoreManager storeManager) {
+ load(new CorePullerFeeder(storeManager));
}
- /*
- * Start the Blob store async core pull machinery
- */
- public BlobProcessUtil(CoreContainer coreContainer, CorePullerFeeder cpf) {
+ @VisibleForTesting
+ public void load(CorePullerFeeder cpf) {
runningFeeder = initializeCorePullerFeeder(cpf);
}
public CorePullerFeeder getCorePullerFeeder() {
+ if (runningFeeder == null) {
+ throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "BlobProcessUtil has not been initialized yet!");
+ }
return runningFeeder;
}
diff --git a/solr/core/src/java/org/apache/solr/store/blob/process/CorePullTask.java b/solr/core/src/java/org/apache/solr/store/blob/process/CorePullTask.java
index 956741d..6c65e65 100644
--- a/solr/core/src/java/org/apache/solr/store/blob/process/CorePullTask.java
+++ b/solr/core/src/java/org/apache/solr/store/blob/process/CorePullTask.java
@@ -23,8 +23,6 @@ import java.util.Locale;
import java.util.Map;
import java.util.Set;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Throwables;
import org.apache.solr.cloud.ZkController;
import org.apache.solr.common.cloud.DocCollection;
import org.apache.solr.common.cloud.Replica;
@@ -44,11 +42,15 @@ import org.apache.solr.store.blob.util.DeduplicatingList;
import org.apache.solr.store.shared.SharedCoreConcurrencyController;
import org.apache.solr.store.shared.SharedCoreConcurrencyController.SharedCoreStage;
import org.apache.solr.store.shared.SharedCoreConcurrencyController.SharedCoreVersionMetadata;
+import org.apache.solr.store.shared.SharedStoreManager;
import org.apache.solr.store.shared.metadata.SharedShardMetadataController;
import org.apache.solr.store.shared.metadata.SharedShardMetadataController.SharedShardVersionMetadata;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Throwables;
+
/**
* Code for pulling updates on a specific core to the Blob store.
*/
@@ -63,7 +65,7 @@ public class CorePullTask implements DeduplicatingList.Deduplicatable<String> {
*/
private static final long MIN_RETRY_DELAY_MS = 20000;
- private final CoreContainer coreContainer;
+ private final SharedStoreManager storeManager;
private final PullCoreInfo pullCoreInfo;
/**
@@ -78,14 +80,14 @@ public class CorePullTask implements DeduplicatingList.Deduplicatable<String> {
private long lastAttemptTimestamp;
private final PullCoreCallback callback;
- CorePullTask(CoreContainer coreContainer, PullCoreInfo pullCoreInfo, PullCoreCallback callback, Set<String> coresCreatedNotPulledYet) {
- this(coreContainer, pullCoreInfo, BlobStoreUtils.getCurrentTimeMs(), 0, 0L, callback, coresCreatedNotPulledYet);
+ CorePullTask(SharedStoreManager storeManager, PullCoreInfo pullCoreInfo, PullCoreCallback callback, Set<String> coresCreatedNotPulledYet) {
+ this(storeManager, pullCoreInfo, BlobStoreUtils.getCurrentTimeMs(), 0, 0L, callback, coresCreatedNotPulledYet);
}
@VisibleForTesting
- CorePullTask(CoreContainer coreContainer, PullCoreInfo pullCoreInfo, long queuedTimeMs, int attempts,
+ CorePullTask(SharedStoreManager storeManager, PullCoreInfo pullCoreInfo, long queuedTimeMs, int attempts,
long lastAttemptTimestamp, PullCoreCallback callback, Set<String> coresCreatedNotPulledYet) {
- this.coreContainer = coreContainer;
+ this.storeManager = storeManager;
this.pullCoreInfo = pullCoreInfo;
this.queuedTimeMs = queuedTimeMs;
this.attempts = attempts;
@@ -117,7 +119,7 @@ public class CorePullTask implements DeduplicatingList.Deduplicatable<String> {
@Override
public CorePullTask merge(CorePullTask task1, CorePullTask task2) {
// The asserts below are not guaranteed by construction but we know that's the case
- assert task1.coreContainer == task2.coreContainer;
+ assert task1.storeManager == task2.storeManager;
assert task1.callback == task2.callback;
int mergedAttempts;
@@ -149,7 +151,7 @@ public class CorePullTask implements DeduplicatingList.Deduplicatable<String> {
}
// We merge the tasks.
- return new CorePullTask(task1.coreContainer, mergedPullCoreInfo,
+ return new CorePullTask(task1.storeManager, mergedPullCoreInfo,
Math.min(task1.queuedTimeMs, task2.queuedTimeMs), mergedAttempts, mergedLatAttemptsTimestamp,
task1.callback, task1.coresCreatedNotPulledYet);
}
@@ -184,7 +186,7 @@ public class CorePullTask implements DeduplicatingList.Deduplicatable<String> {
}
public CoreContainer getCoreContainer() {
- return coreContainer;
+ return storeManager.getCoreContainer();
}
/**
@@ -194,7 +196,7 @@ public class CorePullTask implements DeduplicatingList.Deduplicatable<String> {
*/
void pullCoreFromBlob(boolean isLeaderPulling) throws InterruptedException {
BlobCoreMetadata blobMetadata = null;
- if (coreContainer.isShutDown()) {
+ if (storeManager.getCoreContainer().isShutDown()) {
this.callback.finishedPull(this, blobMetadata, CoreSyncStatus.SHUTTING_DOWN, null);
// TODO could throw InterruptedException here or interrupt ourselves if we wanted to signal to
// CorePullerThread to stop everything.
@@ -213,20 +215,20 @@ public class CorePullTask implements DeduplicatingList.Deduplicatable<String> {
}
}
- SharedCoreConcurrencyController concurrencyController = coreContainer.getSharedStoreManager().getSharedCoreConcurrencyController();
+ SharedCoreConcurrencyController concurrencyController = storeManager.getSharedCoreConcurrencyController();
CoreSyncStatus syncStatus = CoreSyncStatus.FAILURE;
// Auxiliary information related to pull outcome. It can be metadata resolver message which can be null or exception detail in case of failure
String message = null;
try {
// Do the sequence of actions required to pull a core from the Blob store.
- BlobStorageProvider blobProvider = coreContainer.getSharedStoreManager().getBlobStorageProvider();
+ BlobStorageProvider blobProvider = storeManager.getBlobStorageProvider();
CoreStorageClient blobClient = blobProvider.getClient();
SharedCoreVersionMetadata coreVersionMetadata = concurrencyController.getCoreVersionMetadata(pullCoreInfo.getCollectionName(),
pullCoreInfo.getShardName(),
pullCoreInfo.getCoreName());
- SharedShardMetadataController metadataController = coreContainer.getSharedStoreManager().getSharedShardMetadataController();
+ SharedShardMetadataController metadataController = storeManager.getSharedShardMetadataController();
SharedShardVersionMetadata shardVersionMetadata = metadataController.readMetadataValue(pullCoreInfo.getCollectionName(), pullCoreInfo.getShardName());
if(concurrencyController.areVersionsEqual(coreVersionMetadata, shardVersionMetadata)) {
@@ -284,7 +286,7 @@ public class CorePullTask implements DeduplicatingList.Deduplicatable<String> {
}
// Get local metadata + resolve with blob metadata. Given we're doing a pull, don't need to reserve commit point
- ServerSideMetadata serverMetadata = new ServerSideMetadata(pullCoreInfo.getCoreName(), coreContainer, false);
+ ServerSideMetadata serverMetadata = new ServerSideMetadata(pullCoreInfo.getCoreName(), storeManager.getCoreContainer(), false);
SharedMetadataResolutionResult resolutionResult = SharedStoreResolutionUtil.resolveMetadata(
serverMetadata, blobMetadata);
@@ -292,7 +294,7 @@ public class CorePullTask implements DeduplicatingList.Deduplicatable<String> {
// If we call pullUpdateFromBlob with an empty list of files to pull, we'll see an NPE down the line.
// TODO: might be better to handle this error in CorePushPull.pullUpdateFromBlob
if (resolutionResult.getFilesToPull().size() > 0) {
- BlobDeleteManager deleteManager = coreContainer.getSharedStoreManager().getBlobDeleteManager();
+ BlobDeleteManager deleteManager = storeManager.getBlobDeleteManager();
CorePushPull cp = new CorePushPull(blobClient, deleteManager, pullCoreInfo, resolutionResult, serverMetadata, blobMetadata);
// TODO: we are computing/tracking attempts but we are not passing it along
cp.pullUpdateFromBlob(/* waitForSearcher */ true);
@@ -365,9 +367,9 @@ public class CorePullTask implements DeduplicatingList.Deduplicatable<String> {
private boolean coreExists(String coreName) {
SolrCore core = null;
- File coreIndexDir = new File(coreContainer.getCoreRootDirectory() + "/" + coreName);
+ File coreIndexDir = new File(storeManager.getCoreContainer().getCoreRootDirectory() + "/" + coreName);
if (coreIndexDir.exists()) {
- core = coreContainer.getCore(coreName);
+ core = storeManager.getCoreContainer().getCore(coreName);
}
log.info("Core " + coreName + " expected in dir " + coreIndexDir.getAbsolutePath() + " exists=" + coreIndexDir.exists()
@@ -389,6 +391,7 @@ public class CorePullTask implements DeduplicatingList.Deduplicatable<String> {
log.info("About to create local core " + pci.getCoreName());
+ CoreContainer coreContainer = storeManager.getCoreContainer();
ZkController controller = coreContainer.getZkController();
DocCollection collection = controller.getZkStateReader().
getClusterState().getCollection(pci.getCollectionName());
diff --git a/solr/core/src/java/org/apache/solr/store/blob/process/CorePullerFeeder.java b/solr/core/src/java/org/apache/solr/store/blob/process/CorePullerFeeder.java
index 93c07ce..f4b66ee 100644
--- a/solr/core/src/java/org/apache/solr/store/blob/process/CorePullerFeeder.java
+++ b/solr/core/src/java/org/apache/solr/store/blob/process/CorePullerFeeder.java
@@ -20,16 +20,18 @@ import java.lang.invoke.MethodHandles;
import java.util.Locale;
import java.util.Set;
-import com.google.common.collect.Sets;
import org.apache.solr.core.CoreContainer;
import org.apache.solr.store.blob.client.BlobCoreMetadata;
import org.apache.solr.store.blob.metadata.BlobCoreSyncer;
import org.apache.solr.store.blob.metadata.PushPullData;
import org.apache.solr.store.blob.util.BlobStoreUtils;
import org.apache.solr.store.blob.util.DeduplicatingList;
+import org.apache.solr.store.shared.SharedStoreManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.collect.Sets;
+
/**
* A pull version of {@link CoreSyncFeeder} then will continually ({@link #feedTheMonsters()}) to load up a work queue (
* {@link #pullTaskQueue}) with such tasks {@link CorePullTask} to keep the created threads busy :) The tasks will be
@@ -57,8 +59,8 @@ public class CorePullerFeeder extends CoreSyncFeeder {
*/
private final Set<String> coresCreatedNotPulledYet = Sets.newHashSet();
- protected CorePullerFeeder(CoreContainer cores) {
- super(cores, numPullerThreads);
+ protected CorePullerFeeder(SharedStoreManager storeManager) {
+ super(storeManager, numPullerThreads);
this.pullTaskQueue = new DeduplicatingList<>(ALMOST_MAX_WORKER_QUEUE_SIZE, new CorePullTask.PullTaskMerger());
this.callback = new CorePullResult();
}
@@ -95,15 +97,7 @@ public class CorePullerFeeder extends CoreSyncFeeder {
@Override
void feedTheMonsters() throws InterruptedException {
- while (cores.getSharedStoreManager() == null) {
- // todo: Fix cyclic initialization sequence
- // if thread starts early it will be killed since the initialization of sharedStoreManager has triggered the
- // creation of this thread and following line will throw NPE.
- if (Thread.interrupted()) {
- throw new InterruptedException();
- }
- }
- CorePullTracker tracker = cores.getSharedStoreManager().getCorePullTracker();
+ CorePullTracker tracker = storeManager.getCorePullTracker();
final long minMsBetweenLogs = 15000;
long lastLoggedTimestamp = 0L;
long syncsEnqueuedSinceLastLog = 0; // This is the non-deduped count
@@ -112,7 +106,7 @@ public class CorePullerFeeder extends CoreSyncFeeder {
PullCoreInfo pci = tracker.getCoreToPull();
// Add the core to the list consumed by the thread doing the actual work
- CorePullTask pt = new CorePullTask(cores, pci, getCorePullTaskCallback(), coresCreatedNotPulledYet);
+ CorePullTask pt = new CorePullTask(storeManager, pci, getCorePullTaskCallback(), coresCreatedNotPulledYet);
pullTaskQueue.addDeduplicated(pt, /* isReenqueue */ false);
syncsEnqueuedSinceLastLog++;
@@ -227,7 +221,7 @@ public class CorePullerFeeder extends CoreSyncFeeder {
log.warn(String.format(Locale.ROOT, "Pulling core %s failed. Giving up. Last status=%s attempts=%s . %s",
pullCoreInfo.getSharedStoreName(), status, pullTask.getAttempts(), message == null ? "" : message));
}
- BlobCoreSyncer syncer = cores.getSharedStoreManager().getBlobCoreSyncer();
+ BlobCoreSyncer syncer = storeManager.getBlobCoreSyncer();
syncer.finishedPull(pullCoreInfo.getSharedStoreName(), status, blobMetadata, message);
} catch (InterruptedException ie) {
close();
diff --git a/solr/core/src/java/org/apache/solr/store/blob/process/CoreSyncFeeder.java b/solr/core/src/java/org/apache/solr/store/blob/process/CoreSyncFeeder.java
index 29fd22f..985fb07 100644
--- a/solr/core/src/java/org/apache/solr/store/blob/process/CoreSyncFeeder.java
+++ b/solr/core/src/java/org/apache/solr/store/blob/process/CoreSyncFeeder.java
@@ -25,7 +25,7 @@ import java.util.Set;
import org.apache.commons.lang3.exception.ExceptionUtils;
//import com.force.commons.util.concurrent.NamedThreadFactory; difference?
import org.apache.lucene.util.NamedThreadFactory;
-import org.apache.solr.core.CoreContainer;
+import org.apache.solr.store.shared.SharedStoreManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -37,7 +37,7 @@ public abstract class CoreSyncFeeder implements Runnable, Closeable {
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
- protected final CoreContainer cores;
+ protected final SharedStoreManager storeManager;
/**
* Maximum number of elements in the queue, NOT counting re-inserts after failures. Total queue size might therefore
@@ -64,9 +64,9 @@ public abstract class CoreSyncFeeder implements Runnable, Closeable {
private volatile Thread executionThread;
private volatile boolean closed = false;
- protected CoreSyncFeeder(CoreContainer cores, int numSyncThreads) {
+ protected CoreSyncFeeder(SharedStoreManager storeManager, int numSyncThreads) {
this.numSyncThreads = numSyncThreads;
- this.cores = cores;
+ this.storeManager = storeManager;
}
@Override
@@ -115,7 +115,7 @@ public abstract class CoreSyncFeeder implements Runnable, Closeable {
}
boolean shouldContinueRunning() {
- return !this.cores.isShutDown();
+ return !this.storeManager.getCoreContainer().isShutDown();
}
@Override
diff --git a/solr/core/src/java/org/apache/solr/store/shared/SharedCoreConcurrencyController.java b/solr/core/src/java/org/apache/solr/store/shared/SharedCoreConcurrencyController.java
index 77c0034..b542260 100644
--- a/solr/core/src/java/org/apache/solr/store/shared/SharedCoreConcurrencyController.java
+++ b/solr/core/src/java/org/apache/solr/store/shared/SharedCoreConcurrencyController.java
@@ -132,15 +132,15 @@ public class SharedCoreConcurrencyController {
*/
public static int MAX_ATTEMPTS_INDEXING_PULL_WRITE_LOCK = 10;
- private final CoreContainer cores;
+ private final SharedShardMetadataController metadataController;
/**
* This cache maintains the shared store version the each core is at or ahead of(core has to sometimes be ahead of
* shared store given indexing first happens locally before being propagated to shared store).
*/
private final ConcurrentHashMap<String, SharedCoreVersionMetadata> coresVersionMetadata;
- public SharedCoreConcurrencyController(CoreContainer cores) {
- this.cores = cores;
+ public SharedCoreConcurrencyController(SharedShardMetadataController metadataController) {
+ this.metadataController = metadataController;
coresVersionMetadata = buildMetadataCache();
}
@@ -301,7 +301,6 @@ public class SharedCoreConcurrencyController {
@VisibleForTesting
protected void ensureShardVersionMetadataNodeExists(String collectionName, String shardName) {
- SharedShardMetadataController metadataController = cores.getSharedStoreManager().getSharedShardMetadataController();
try {
// creates the metadata node if it doesn't exist
metadataController.ensureMetadataNodeExists(collectionName, shardName);
diff --git a/solr/core/src/java/org/apache/solr/store/shared/SharedStoreManager.java b/solr/core/src/java/org/apache/solr/store/shared/SharedStoreManager.java
index 9fec3f4..1295dd2 100644
--- a/solr/core/src/java/org/apache/solr/store/shared/SharedStoreManager.java
+++ b/solr/core/src/java/org/apache/solr/store/shared/SharedStoreManager.java
@@ -16,8 +16,8 @@
*/
package org.apache.solr.store.shared;
-import com.google.common.annotations.VisibleForTesting;
import org.apache.solr.cloud.ZkController;
+import org.apache.solr.core.CoreContainer;
import org.apache.solr.store.blob.metadata.BlobCoreSyncer;
import org.apache.solr.store.blob.process.BlobDeleteManager;
import org.apache.solr.store.blob.process.BlobProcessUtil;
@@ -25,6 +25,8 @@ import org.apache.solr.store.blob.process.CorePullTracker;
import org.apache.solr.store.blob.provider.BlobStorageProvider;
import org.apache.solr.store.shared.metadata.SharedShardMetadataController;
+import com.google.common.annotations.VisibleForTesting;
+
/**
* Provides access to Shared Store processes. Note that this class is meant to be
* more generic in the future and provide a cleaner API but for now we'll expose
@@ -32,7 +34,7 @@ import org.apache.solr.store.shared.metadata.SharedShardMetadataController;
*/
public class SharedStoreManager {
- private ZkController zkController;
+ private CoreContainer coreContainer;
private SharedShardMetadataController sharedShardMetadataController;
private BlobStorageProvider blobStorageProvider;
private BlobDeleteManager blobDeleteManager;
@@ -41,71 +43,44 @@ public class SharedStoreManager {
private BlobCoreSyncer blobCoreSyncer;
private SharedCoreConcurrencyController sharedCoreConcurrencyController;
- public SharedStoreManager(ZkController controller) {
- zkController = controller;
- // initialize BlobProcessUtil with the SharedStoreManager for background processes to be ready
- blobProcessUtil = new BlobProcessUtil(zkController.getCoreContainer());
+ public SharedStoreManager(CoreContainer coreContainer) {
+ this.coreContainer = coreContainer;
+ ZkController zkController = coreContainer.getZkController();
+
+ blobStorageProvider = new BlobStorageProvider();
+ blobDeleteManager = new BlobDeleteManager(getBlobStorageProvider().getClient());
+ corePullTracker = new CorePullTracker();
+ sharedShardMetadataController = new SharedShardMetadataController(zkController.getSolrCloudManager());
+ sharedCoreConcurrencyController = new SharedCoreConcurrencyController(sharedShardMetadataController);
blobCoreSyncer = new BlobCoreSyncer();
- sharedCoreConcurrencyController = new SharedCoreConcurrencyController(zkController.getCoreContainer());
+ blobProcessUtil = new BlobProcessUtil();
}
- @VisibleForTesting
- public void initBlobStorageProvider(BlobStorageProvider blobStorageProvider) {
- this.blobStorageProvider = blobStorageProvider;
- }
-
- @VisibleForTesting
- public void initBlobProcessUtil(BlobProcessUtil processUtil) {
- if (blobProcessUtil != null) {
- blobProcessUtil.shutdown();
- }
- blobProcessUtil = processUtil;
- }
-
- /*
- * Initiates a SharedShardMetadataController if it doesn't exist and returns one
+ /**
+ * Start blob processes that depend on an initiated {@link SharedStoreManager} in {@link CoreContainer}
*/
+ public void load() {
+ blobProcessUtil.load(this);
+ }
+
public SharedShardMetadataController getSharedShardMetadataController() {
- if (sharedShardMetadataController != null) {
- return sharedShardMetadataController;
- }
- sharedShardMetadataController = new SharedShardMetadataController(zkController.getSolrCloudManager());
return sharedShardMetadataController;
}
- /*
- * Initiates a BlobStorageProvider if it doesn't exist and returns one
- */
public BlobStorageProvider getBlobStorageProvider() {
- if (blobStorageProvider != null) {
- return blobStorageProvider;
- }
- blobStorageProvider = new BlobStorageProvider();
return blobStorageProvider;
}
public BlobDeleteManager getBlobDeleteManager() {
- if (blobDeleteManager != null) {
- return blobDeleteManager;
- }
- blobDeleteManager = new BlobDeleteManager(getBlobStorageProvider().getClient());
return blobDeleteManager;
}
public BlobProcessUtil getBlobProcessManager() {
- if (blobProcessUtil != null) {
- return blobProcessUtil;
- }
- blobProcessUtil = new BlobProcessUtil(zkController.getCoreContainer());
return blobProcessUtil;
}
public CorePullTracker getCorePullTracker() {
- if (corePullTracker != null) {
- return corePullTracker ;
- }
- corePullTracker = new CorePullTracker();
- return corePullTracker ;
+ return corePullTracker;
}
public BlobCoreSyncer getBlobCoreSyncer() {
@@ -115,6 +90,19 @@ public class SharedStoreManager {
public SharedCoreConcurrencyController getSharedCoreConcurrencyController() {
return sharedCoreConcurrencyController;
}
+
+ public CoreContainer getCoreContainer() {
+ return coreContainer;
+ }
+
+ public void shutdown() {
+ if (blobProcessUtil != null) {
+ blobProcessUtil.shutdown();
+ }
+ if (blobDeleteManager != null) {
+ blobDeleteManager.shutdown();
+ }
+ }
@VisibleForTesting
public void initConcurrencyController(SharedCoreConcurrencyController concurrencyController) {
@@ -122,9 +110,22 @@ public class SharedStoreManager {
}
@VisibleForTesting
+ public void initBlobStorageProvider(BlobStorageProvider blobStorageProvider) {
+ this.blobStorageProvider = blobStorageProvider;
+ }
+
+ @VisibleForTesting
+ public void initBlobProcessUtil(BlobProcessUtil processUtil) {
+ if (blobProcessUtil != null) {
+ blobProcessUtil.shutdown();
+ }
+ blobProcessUtil = processUtil;
+ }
+
+ @VisibleForTesting
public void initBlobDeleteManager(BlobDeleteManager blobDeleteManager) {
if (this.blobDeleteManager != null) {
- blobDeleteManager.shutdown();
+ this.blobDeleteManager.shutdown();
}
this.blobDeleteManager = blobDeleteManager;
}
diff --git a/solr/core/src/test-files/solr/solr-sharedstore.xml b/solr/core/src/test-files/solr/solr-sharedstore.xml
new file mode 100644
index 0000000..746d0c7
--- /dev/null
+++ b/solr/core/src/test-files/solr/solr-sharedstore.xml
@@ -0,0 +1,58 @@
+<?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.
+-->
+
+<!--
+ All (relative) paths are relative to the installation path
+-->
+<solr>
+ <str name="shareSchema">${shareSchema:false}</str>
+ <str name="configSetBaseDir">${configSetBaseDir:configsets}</str>
+ <str name="coreRootDirectory">${coreRootDirectory:.}</str>
+ <str name="collectionsHandler">${collectionsHandler:solr.CollectionsHandler}</str>
+
+ <shardHandlerFactory name="shardHandlerFactory" class="HttpShardHandlerFactory">
+ <str name="urlScheme">${urlScheme:}</str>
+ <int name="socketTimeout">${socketTimeout:90000}</int>
+ <int name="connTimeout">${connTimeout:15000}</int>
+ <str name="shardsWhitelist">${SOLR_TESTS_SHARDS_WHITELIST:}</str>
+ </shardHandlerFactory>
+
+ <solrcloud>
+ <str name="host">127.0.0.1</str>
+ <int name="hostPort">${hostPort:8983}</int>
+ <str name="hostContext">${hostContext:solr}</str>
+ <int name="zkClientTimeout">${solr.zkclienttimeout:30000}</int>
+ <bool name="genericCoreNodeNames">${genericCoreNodeNames:true}</bool>
+ <int name="leaderVoteWait">${leaderVoteWait:10000}</int>
+ <int name="distribUpdateConnTimeout">${distribUpdateConnTimeout:45000}</int>
+ <int name="distribUpdateSoTimeout">${distribUpdateSoTimeout:340000}</int>
+ <str name="zkCredentialsProvider">${zkCredentialsProvider:org.apache.solr.common.cloud.DefaultZkCredentialsProvider}</str>
+ <str name="zkACLProvider">${zkACLProvider:org.apache.solr.common.cloud.DefaultZkACLProvider}</str>
+ </solrcloud>
+
+ <sharedStore>
+ <!-- The presence of this config section enables shared storage capabilities for the entire cluster if it
+ is in Solr Cloud mode -->
+ </sharedStore>
+
+ <metrics>
+ <reporter name="default" class="org.apache.solr.metrics.reporters.SolrJmxReporter">
+ <str name="rootName">solr_${hostPort:8983}</str>
+ </reporter>
+ </metrics>
+</solr>
diff --git a/solr/core/src/test/org/apache/solr/cloud/api/collections/SharedStorageShardMetadataTest.java b/solr/core/src/test/org/apache/solr/cloud/api/collections/SharedStorageShardMetadataTest.java
index 595ed86..182db52 100644
--- a/solr/core/src/test/org/apache/solr/cloud/api/collections/SharedStorageShardMetadataTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/api/collections/SharedStorageShardMetadataTest.java
@@ -16,17 +16,14 @@
*/
package org.apache.solr.cloud.api.collections;
-import java.nio.file.Path;
import java.util.Map;
-import org.apache.solr.client.solrj.embedded.JettySolrRunner;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.common.cloud.DocCollection;
import org.apache.solr.common.cloud.Replica.Type;
import org.apache.solr.common.cloud.Slice;
import org.apache.solr.common.cloud.ZkStateReader;
-import org.apache.solr.store.blob.client.CoreStorageClient;
import org.apache.solr.store.shared.SolrCloudSharedStoreTestCase;
import org.junit.AfterClass;
import org.junit.BeforeClass;
@@ -41,20 +38,9 @@ public class SharedStorageShardMetadataTest extends SolrCloudSharedStoreTestCase
@BeforeClass
public static void setupCluster() throws Exception {
- configureCluster(3)
- .addConfig("conf", configset("cloud-minimal"))
- .configure();
-
- // we don't use this in testing
- Path sharedStoreRootPath = createTempDir("tempDir");
- CoreStorageClient storageClient = setupLocalBlobStoreClient(sharedStoreRootPath, DEFAULT_BLOB_DIR_NAME);
- // configure same client for each runner, this isn't a concurrency test so this is fine
- for (JettySolrRunner runner : cluster.getJettySolrRunners()) {
- setupTestSharedClientForNode(getBlobStorageProviderTestInstance(storageClient), runner);
- }
+ setupCluster(3);
}
-
@AfterClass
public static void teardownTest() throws Exception {
shutdownCluster();
diff --git a/solr/core/src/test/org/apache/solr/cloud/api/collections/SimpleSharedStorageCollectionTest.java b/solr/core/src/test/org/apache/solr/cloud/api/collections/SimpleSharedStorageCollectionTest.java
index 5d000fc..fad695d 100644
--- a/solr/core/src/test/org/apache/solr/cloud/api/collections/SimpleSharedStorageCollectionTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/api/collections/SimpleSharedStorageCollectionTest.java
@@ -16,47 +16,34 @@
*/
package org.apache.solr.cloud.api.collections;
-import java.nio.file.Path;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
-import org.apache.commons.io.FileUtils;
import org.apache.solr.client.solrj.embedded.JettySolrRunner;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.client.solrj.request.UpdateRequest;
+import org.apache.solr.common.SolrException;
import org.apache.solr.common.cloud.DocCollection;
import org.apache.solr.common.cloud.Replica;
import org.apache.solr.common.cloud.Replica.Type;
import org.apache.solr.common.cloud.ZkStateReader;
-import org.apache.solr.store.blob.client.CoreStorageClient;
import org.apache.solr.store.shared.SharedCoreConcurrencyController;
import org.apache.solr.store.shared.SharedCoreConcurrencyController.SharedCoreVersionMetadata;
import org.apache.solr.store.shared.SolrCloudSharedStoreTestCase;
import org.junit.After;
-import org.junit.BeforeClass;
import org.junit.Test;
/**
* Tests related to shared storage based collections, i.e. collections having only replicas of type {@link Type#SHARED}.
*/
public class SimpleSharedStorageCollectionTest extends SolrCloudSharedStoreTestCase {
-
- private static Path sharedStoreRootPath;
-
- @BeforeClass
- public static void setupClass() throws Exception {
- sharedStoreRootPath = createTempDir("tempDir");
- }
@After
public void teardownTest() throws Exception {
if (cluster != null) {
cluster.shutdown();
}
- // clean up the shared store after each test. The temp dir should clean up itself after the
- // test class finishes
- FileUtils.cleanDirectory(sharedStoreRootPath.toFile());
}
/**
@@ -66,7 +53,6 @@ public class SimpleSharedStorageCollectionTest extends SolrCloudSharedStoreTestC
@Test
public void testCreateCollection() throws Exception {
setupCluster(3);
- setupSolrNodes();
String collectionName = "BlobBasedCollectionName1";
CloudSolrClient cloudClient = cluster.getSolrClient();
@@ -76,6 +62,28 @@ public class SimpleSharedStorageCollectionTest extends SolrCloudSharedStoreTestC
waitForState("Timed-out wait for collection to be created", collectionName, clusterShape(1, 1));
assertTrue(cloudClient.getZkStateReader().getZkClient().exists(ZkStateReader.COLLECTIONS_ZKNODE + "/" + collectionName, false));
}
+
+ /**
+ * Test that verifies that a collection creation command for a "shared" type collection fails
+ * if the cluster was not enabled with shared storage
+ */
+ @Test
+ public void testCreateCollectionSharedDisabled() throws Exception {
+ setupClusterSharedDisable(1);
+ String collectionName = "BlobBasedCollectionName1";
+ CloudSolrClient cloudClient = cluster.getSolrClient();
+
+ CollectionAdminRequest.Create create = CollectionAdminRequest.createCollection(collectionName, 1, 0).setSharedIndex(true).setSharedReplicas(1);
+ try {
+ create.process(cloudClient);
+ fail("Request should have failed");
+ } catch (SolrException ex) {
+ assertEquals(SolrException.ErrorCode.BAD_REQUEST.code, ex.code());
+ assertTrue(ex.getMessage().contains("shared storage is not enabled"));
+ } catch (Exception ex) {
+ fail("Unexpected exception thrown " + ex.getMessage());
+ }
+ }
/**
* Test that verifies that adding a NRT replica to a shared collection fails but adding a SHARED replica
@@ -84,7 +92,6 @@ public class SimpleSharedStorageCollectionTest extends SolrCloudSharedStoreTestC
@Test
public void testAddReplica() throws Exception {
setupCluster(3);
- setupSolrNodes();
String collectionName = "BlobBasedCollectionName2";
CloudSolrClient cloudClient = cluster.getSolrClient();
@@ -123,7 +130,6 @@ public class SimpleSharedStorageCollectionTest extends SolrCloudSharedStoreTestC
String shardNames = "shard1";
// setup testing components
- setupSolrNodes();
AtomicInteger evictionCount = new AtomicInteger(0);
SharedCoreConcurrencyController concurrencyController =
configureTestSharedConcurrencyControllerForNode(cluster.getJettySolrRunner(0), evictionCount);
@@ -161,18 +167,12 @@ public class SimpleSharedStorageCollectionTest extends SolrCloudSharedStoreTestC
assertEquals(null, scvm.getMetadataSuffix());
assertEquals(null, scvm.getBlobCoreMetadata());
}
-
- private void setupSolrNodes() throws Exception {
- for (JettySolrRunner process : cluster.getJettySolrRunners()) {
- CoreStorageClient storageClient = setupLocalBlobStoreClient(sharedStoreRootPath, DEFAULT_BLOB_DIR_NAME);
- setupTestSharedClientForNode(getBlobStorageProviderTestInstance(storageClient), process);
- }
- }
private SharedCoreConcurrencyController configureTestSharedConcurrencyControllerForNode(JettySolrRunner runner,
AtomicInteger evictionCount) {
SharedCoreConcurrencyController concurrencyController =
- new SharedCoreConcurrencyController(runner.getCoreContainer()) {
+ new SharedCoreConcurrencyController(runner.getCoreContainer().getSharedStoreManager()
+ .getSharedShardMetadataController()) {
@Override
public boolean removeCoreVersionMetadataIfPresent(String coreName) {
diff --git a/solr/core/src/test/org/apache/solr/store/blob/SharedStorageSplitTest.java b/solr/core/src/test/org/apache/solr/store/blob/SharedStorageSplitTest.java
index fe51cac..43aa8a7 100644
--- a/solr/core/src/test/org/apache/solr/store/blob/SharedStorageSplitTest.java
+++ b/solr/core/src/test/org/apache/solr/store/blob/SharedStorageSplitTest.java
@@ -17,7 +17,6 @@
package org.apache.solr.store.blob;
import java.lang.invoke.MethodHandles;
-import java.nio.file.Path;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
@@ -43,7 +42,6 @@ import org.apache.solr.common.cloud.DocCollection;
import org.apache.solr.common.cloud.Replica;
import org.apache.solr.common.cloud.Slice;
import org.apache.solr.common.cloud.ZkStateReader;
-import org.apache.solr.store.blob.client.CoreStorageClient;
import org.apache.solr.store.shared.SolrCloudSharedStoreTestCase;
import org.junit.AfterClass;
import org.junit.BeforeClass;
@@ -60,22 +58,14 @@ public class SharedStorageSplitTest extends SolrCloudSharedStoreTestCase {
static Map<String, Map<String, CountDownLatch>> solrProcessesTaskTracker = new HashMap<>();
@BeforeClass
- public static void setupCluster() throws Exception {
- configureCluster(2)
- .addConfig("conf", configset("cloud-minimal"))
- .configure();
+ public static void setupCluster() throws Exception {
+ setupCluster(2);
- // we don't use this in testing
- Path sharedStoreRootPath = createTempDir("tempDir");
- CoreStorageClient storageClient = setupLocalBlobStoreClient(sharedStoreRootPath, DEFAULT_BLOB_DIR_NAME);
- // configure same client for each runner, this isn't a concurrency test so this is fine
for (JettySolrRunner runner : cluster.getJettySolrRunners()) {
- setupTestSharedClientForNode(getBlobStorageProviderTestInstance(storageClient), runner);
solrProcessesTaskTracker.put(runner.getNodeName(), configureTestBlobProcessForNode(runner));
}
}
-
@AfterClass
public static void teardownTest() throws Exception {
shutdownCluster();
diff --git a/solr/core/src/test/org/apache/solr/store/shared/SharedCoreConcurrencyTest.java b/solr/core/src/test/org/apache/solr/store/shared/SharedCoreConcurrencyTest.java
index 7753d9f..6d0c725 100644
--- a/solr/core/src/test/org/apache/solr/store/shared/SharedCoreConcurrencyTest.java
+++ b/solr/core/src/test/org/apache/solr/store/shared/SharedCoreConcurrencyTest.java
@@ -18,7 +18,6 @@ package org.apache.solr.store.shared;
import java.io.File;
import java.lang.invoke.MethodHandles;
-import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -33,8 +32,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
-import com.google.common.base.Throwables;
-import com.google.common.collect.Lists;
import org.apache.commons.io.FileUtils;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.embedded.JettySolrRunner;
@@ -46,15 +43,16 @@ import org.apache.solr.common.cloud.DocCollection;
import org.apache.solr.common.cloud.Replica;
import org.apache.solr.common.cloud.Slice;
import org.apache.solr.common.params.ModifiableSolrParams;
-import org.apache.solr.store.blob.client.CoreStorageClient;
import org.apache.solr.store.shared.SharedCoreConcurrencyController.SharedCoreStage;
import org.junit.After;
import org.junit.Before;
-import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.base.Throwables;
+import com.google.common.collect.Lists;
+
/**
* Tests around synchronization of concurrent indexing, pushes and pulls
* happening on a core of a shared collection {@link DocCollection#getSharedIndex()}
@@ -95,21 +93,12 @@ public class SharedCoreConcurrencyTest extends SolrCloudSharedStoreTestCase {
* Minimum time between each failover.
*/
private static int DELAY_MS_BETWEEN_EACH_FAILOVER_ITERATION = 500;
- /**
- * Path for local shared store
- */
- private static Path sharedStoreRootPath;
/**
* Manages test state from start to end.
*/
private TestState testState;
- @BeforeClass
- public static void setupClass() throws Exception {
- sharedStoreRootPath = createTempDir("tempDir");
- }
-
@Before
public void setupTest() throws Exception {
int numNodes = 4;
@@ -132,7 +121,6 @@ public class SharedCoreConcurrencyTest extends SolrCloudSharedStoreTestCase {
if (cluster != null) {
cluster.shutdown();
}
- FileUtils.cleanDirectory(sharedStoreRootPath.toFile());
}
/**
@@ -583,8 +571,6 @@ public class SharedCoreConcurrencyTest extends SolrCloudSharedStoreTestCase {
* Setup solr process for test(process is one life of a node, restarts starts a new life).
*/
private void setupSolrProcess(JettySolrRunner solrProcess) throws Exception {
- CoreStorageClient storageClient = setupLocalBlobStoreClient(sharedStoreRootPath, DEFAULT_BLOB_DIR_NAME);
- setupTestSharedClientForNode(getBlobStorageProviderTestInstance(storageClient), solrProcess);
Map<String, CountDownLatch> corePullTracker = configureTestBlobProcessForNode(solrProcess);
ConcurrentHashMap<String, ConcurrentLinkedQueue<String>> coreConcurrencyStagesTracker = new ConcurrentHashMap<>();
configureTestSharedConcurrencyControllerForProcess(solrProcess, coreConcurrencyStagesTracker);
@@ -604,7 +590,8 @@ public class SharedCoreConcurrencyTest extends SolrCloudSharedStoreTestCase {
*/
private void configureTestSharedConcurrencyControllerForProcess(
JettySolrRunner solrProcess, ConcurrentHashMap<String, ConcurrentLinkedQueue<String>> coreConcurrencyStagesMap) {
- SharedCoreConcurrencyController concurrencyController = new SharedCoreConcurrencyController(solrProcess.getCoreContainer()) {
+ SharedCoreConcurrencyController concurrencyController = new SharedCoreConcurrencyController
+ (solrProcess.getCoreContainer().getSharedStoreManager().getSharedShardMetadataController()) {
@Override
public void recordState(String collectionName, String shardName, String coreName, SharedCoreStage stage) {
super.recordState(collectionName, shardName, coreName, stage);
diff --git a/solr/core/src/test/org/apache/solr/store/shared/SharedStoreMissingCoreTest.java b/solr/core/src/test/org/apache/solr/store/shared/SharedStoreMissingCoreTest.java
index d28411e..ef94806 100644
--- a/solr/core/src/test/org/apache/solr/store/shared/SharedStoreMissingCoreTest.java
+++ b/solr/core/src/test/org/apache/solr/store/shared/SharedStoreMissingCoreTest.java
@@ -18,7 +18,6 @@ package org.apache.solr.store.shared;
import java.io.File;
import java.io.IOException;
-import java.nio.file.Path;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -26,7 +25,6 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
-import com.google.common.collect.Lists;
import org.apache.commons.io.FileUtils;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.embedded.JettySolrRunner;
@@ -39,11 +37,11 @@ import org.apache.solr.common.cloud.Replica.State;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.core.CoreContainer;
import org.apache.solr.core.SolrCore;
-import org.apache.solr.store.blob.client.CoreStorageClient;
import org.junit.After;
-import org.junit.BeforeClass;
import org.junit.Test;
+import com.google.common.collect.Lists;
+
/**
* Tests for missing shared core. Missing core refers to a case in which shard index exists on the source-of-truth for
* shared collections, the shared store, but is missing locally on the solr node. The metadata for the index shard and
@@ -51,19 +49,9 @@ import org.junit.Test;
*/
public class SharedStoreMissingCoreTest extends SolrCloudSharedStoreTestCase {
- private static Path sharedStoreRootPath;
-
- @BeforeClass
- public static void setupClass() throws Exception {
- sharedStoreRootPath = createTempDir("tempDir");
- }
-
@After
public void teardownTest() throws Exception {
shutdownCluster();
- // clean up the shared store after each test. The temp dir should clean up itself after the
- // test class finishes
- FileUtils.cleanDirectory(sharedStoreRootPath.toFile());
}
/**
@@ -75,10 +63,6 @@ public class SharedStoreMissingCoreTest extends SolrCloudSharedStoreTestCase {
setupCluster(1);
CloudSolrClient cloudClient = cluster.getSolrClient();
- // setup the test harness
- CoreStorageClient storageClient = setupLocalBlobStoreClient(sharedStoreRootPath, DEFAULT_BLOB_DIR_NAME);
- setupTestSharedClientForNode(getBlobStorageProviderTestInstance(storageClient), cluster.getJettySolrRunner(0));
-
String collectionName = "sharedCollection";
int maxShardsPerNode = 1;
int numReplicas = 1;
@@ -92,7 +76,7 @@ public class SharedStoreMissingCoreTest extends SolrCloudSharedStoreTestCase {
updateReq.add("id", "1");
updateReq.commit(cloudClient, collectionName);
- Map<String, CountDownLatch> asyncPullLatches = stopSolrRemoveCoreRestartSolr(cloudClient, storageClient, collectionName);
+ Map<String, CountDownLatch> asyncPullLatches = stopSolrRemoveCoreRestartSolr(cloudClient, collectionName);
queryAndWaitForPullToFinish(cloudClient, collectionName, asyncPullLatches);
// verify the documents are present
assertQueryReturnsAllDocs(cloudClient, collectionName, Lists.newArrayList("1"));
@@ -106,7 +90,7 @@ public class SharedStoreMissingCoreTest extends SolrCloudSharedStoreTestCase {
assertQueryReturnsAllDocs(cloudClient, collectionName, Lists.newArrayList("1", "2"));
// verify that they made it to shared store by a clean pull
- asyncPullLatches = stopSolrRemoveCoreRestartSolr(cloudClient, storageClient, collectionName);
+ asyncPullLatches = stopSolrRemoveCoreRestartSolr(cloudClient, collectionName);
queryAndWaitForPullToFinish(cloudClient, collectionName, asyncPullLatches);
assertQueryReturnsAllDocs(cloudClient, collectionName, Lists.newArrayList("1", "2"));
}
@@ -121,10 +105,6 @@ public class SharedStoreMissingCoreTest extends SolrCloudSharedStoreTestCase {
setupCluster(1);
CloudSolrClient cloudClient = cluster.getSolrClient();
- // setup the test harness
- CoreStorageClient storageClient = setupLocalBlobStoreClient(sharedStoreRootPath, DEFAULT_BLOB_DIR_NAME);
- setupTestSharedClientForNode(getBlobStorageProviderTestInstance(storageClient), cluster.getJettySolrRunner(0));
-
String collectionName = "sharedCollection";
int maxShardsPerNode = 1;
int numReplicas = 1;
@@ -138,7 +118,7 @@ public class SharedStoreMissingCoreTest extends SolrCloudSharedStoreTestCase {
updateReq.add("id", "1");
updateReq.commit(cloudClient, collectionName);
- stopSolrRemoveCoreRestartSolr(cloudClient, storageClient, collectionName);
+ stopSolrRemoveCoreRestartSolr(cloudClient, collectionName);
// send another update to the collection
updateReq = new UpdateRequest();
@@ -149,7 +129,7 @@ public class SharedStoreMissingCoreTest extends SolrCloudSharedStoreTestCase {
assertQueryReturnsAllDocs(cloudClient, collectionName, Lists.newArrayList("1", "2"));
// verify that new state made it to shared store by doing a clean pull
- Map<String, CountDownLatch> asyncPullLatches = stopSolrRemoveCoreRestartSolr(cloudClient, storageClient, collectionName);
+ Map<String, CountDownLatch> asyncPullLatches = stopSolrRemoveCoreRestartSolr(cloudClient, collectionName);
queryAndWaitForPullToFinish(cloudClient, collectionName, asyncPullLatches);
assertQueryReturnsAllDocs(cloudClient, collectionName, Lists.newArrayList("1", "2"));
}
@@ -166,7 +146,7 @@ public class SharedStoreMissingCoreTest extends SolrCloudSharedStoreTestCase {
assertTrue("Timed-out waiting for pull to finish", latch.await(120, TimeUnit.SECONDS));
}
- private Map<String, CountDownLatch> stopSolrRemoveCoreRestartSolr(CloudSolrClient cloudClient, CoreStorageClient storageClient, String collectionName) throws Exception {
+ private Map<String, CountDownLatch> stopSolrRemoveCoreRestartSolr(CloudSolrClient cloudClient, String collectionName) throws Exception {
// get the replica
DocCollection collection = cloudClient.getZkStateReader().getClusterState().getCollection(collectionName);
Replica shardLeaderReplica = collection.getLeader("shard1");
@@ -194,7 +174,6 @@ public class SharedStoreMissingCoreTest extends SolrCloudSharedStoreTestCase {
// start up the node again
runner = cluster.startJettySolrRunner(runner, true);
cluster.waitForNode(runner, /* seconds */ 30);
- setupTestSharedClientForNode(getBlobStorageProviderTestInstance(storageClient), cluster.getJettySolrRunner(0));
Map<String, CountDownLatch> asyncPullLatches = configureTestBlobProcessForNode(cluster.getJettySolrRunner(0));
collection = cloudClient.getZkStateReader().getClusterState().getCollection(collectionName);
diff --git a/solr/core/src/test/org/apache/solr/store/shared/SimpleSharedStoreEndToEndPullTest.java b/solr/core/src/test/org/apache/solr/store/shared/SimpleSharedStoreEndToEndPullTest.java
index eb018ca..425ee8b 100644
--- a/solr/core/src/test/org/apache/solr/store/shared/SimpleSharedStoreEndToEndPullTest.java
+++ b/solr/core/src/test/org/apache/solr/store/shared/SimpleSharedStoreEndToEndPullTest.java
@@ -16,13 +16,11 @@
*/
package org.apache.solr.store.shared;
-import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-import org.apache.commons.io.FileUtils;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.embedded.JettySolrRunner;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
@@ -33,9 +31,7 @@ import org.apache.solr.common.cloud.Replica;
import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.core.CoreContainer;
import org.apache.solr.core.SolrCore;
-import org.apache.solr.store.blob.client.CoreStorageClient;
import org.junit.After;
-import org.junit.BeforeClass;
import org.junit.Test;
/**
@@ -43,21 +39,11 @@ import org.junit.Test;
*/
public class SimpleSharedStoreEndToEndPullTest extends SolrCloudSharedStoreTestCase {
- private static Path sharedStoreRootPath;
-
- @BeforeClass
- public static void setupClass() throws Exception {
- sharedStoreRootPath = createTempDir("tempDir");
- }
-
@After
public void teardownTest() throws Exception {
if (cluster != null) {
cluster.shutdown();
}
- // clean up the shared store after each test. The temp dir should clean up itself after the
- // test class finishes
- FileUtils.cleanDirectory(sharedStoreRootPath.toFile());
}
/**
@@ -73,13 +59,9 @@ public class SimpleSharedStoreEndToEndPullTest extends SolrCloudSharedStoreTestC
Map<String, Map<String, CountDownLatch>> solrProcessesTaskTracker = new HashMap<>();
JettySolrRunner solrProcess1 = cluster.getJettySolrRunner(0);
- CoreStorageClient storageClient1 = setupLocalBlobStoreClient(sharedStoreRootPath, DEFAULT_BLOB_DIR_NAME);
- setupTestSharedClientForNode(getBlobStorageProviderTestInstance(storageClient1), solrProcess1);
Map<String, CountDownLatch> asyncPullLatches1 = configureTestBlobProcessForNode(solrProcess1);
JettySolrRunner solrProcess2 = cluster.getJettySolrRunner(1);
- CoreStorageClient storageClient2 = setupLocalBlobStoreClient(sharedStoreRootPath, DEFAULT_BLOB_DIR_NAME);
- setupTestSharedClientForNode(getBlobStorageProviderTestInstance(storageClient2), solrProcess2);
Map<String, CountDownLatch> asyncPullLatches2 = configureTestBlobProcessForNode(solrProcess2);
solrProcessesTaskTracker.put(solrProcess1.getNodeName(), asyncPullLatches1);
diff --git a/solr/core/src/test/org/apache/solr/store/shared/SimpleSharedStoreEndToEndPushTest.java b/solr/core/src/test/org/apache/solr/store/shared/SimpleSharedStoreEndToEndPushTest.java
index 039e5ad..2d6bb5c 100644
--- a/solr/core/src/test/org/apache/solr/store/shared/SimpleSharedStoreEndToEndPushTest.java
+++ b/solr/core/src/test/org/apache/solr/store/shared/SimpleSharedStoreEndToEndPushTest.java
@@ -16,10 +16,8 @@
*/
package org.apache.solr.store.shared;
-import java.nio.file.Path;
import java.util.Map;
-import org.apache.commons.io.FileUtils;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
import org.apache.solr.client.solrj.request.QueryRequest;
@@ -36,7 +34,6 @@ import org.apache.solr.store.blob.util.BlobStoreUtils;
import org.apache.solr.store.shared.metadata.SharedShardMetadataController;
import org.apache.solr.store.shared.metadata.SharedShardMetadataController.SharedShardVersionMetadata;
import org.junit.After;
-import org.junit.BeforeClass;
import org.junit.Test;
/**
@@ -44,21 +41,11 @@ import org.junit.Test;
*/
public class SimpleSharedStoreEndToEndPushTest extends SolrCloudSharedStoreTestCase {
- private static Path sharedStoreRootPath;
-
- @BeforeClass
- public static void setupClass() throws Exception {
- sharedStoreRootPath = createTempDir("tempDir");
- }
-
@After
public void teardownTest() throws Exception {
if (cluster != null) {
cluster.shutdown();
}
- // clean up the shared store after each test. The temp dir should clean up itself after the
- // test class finishes
- FileUtils.cleanDirectory(sharedStoreRootPath.toFile());
}
/**
@@ -79,14 +66,9 @@ public class SimpleSharedStoreEndToEndPushTest extends SolrCloudSharedStoreTestC
}
public void testUpdatePushesToBlob(boolean withCommit) throws Exception {
-
setupCluster(1);
CloudSolrClient cloudClient = cluster.getSolrClient();
- // setup the test harness
- CoreStorageClient storageClient = setupLocalBlobStoreClient(sharedStoreRootPath, DEFAULT_BLOB_DIR_NAME);
- setupTestSharedClientForNode(getBlobStorageProviderTestInstance(storageClient), cluster.getJettySolrRunner(0));
-
String collectionName = "sharedCollection";
int maxShardsPerNode = 1;
int numReplicas = 1;
@@ -122,6 +104,7 @@ public class SimpleSharedStoreEndToEndPushTest extends SolrCloudSharedStoreTestC
String sharedShardName = (String) props.get(ZkStateReader.SHARED_SHARD_NAME);
String blobCoreMetadataName = BlobStoreUtils.buildBlobStoreMetadataName(shardMetadata.getMetadataSuffix());
+ CoreStorageClient storageClient = leaderCC.getSharedStoreManager().getBlobStorageProvider().getClient();
// verify that we pushed the core to blob
assertTrue(storageClient.coreMetadataExists(sharedShardName, blobCoreMetadataName));
diff --git a/solr/core/src/test/org/apache/solr/store/shared/SolrCloudSharedStoreTestCase.java b/solr/core/src/test/org/apache/solr/store/shared/SolrCloudSharedStoreTestCase.java
index 909443c..9324cbc 100644
--- a/solr/core/src/test/org/apache/solr/store/shared/SolrCloudSharedStoreTestCase.java
+++ b/solr/core/src/test/org/apache/solr/store/shared/SolrCloudSharedStoreTestCase.java
@@ -21,6 +21,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
+import org.apache.commons.io.FileUtils;
import org.apache.solr.client.solrj.embedded.JettySolrRunner;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.cloud.MiniSolrCloudCluster;
@@ -35,6 +36,8 @@ import org.apache.solr.store.blob.process.CorePullTask.PullCoreCallback;
import org.apache.solr.store.blob.process.CorePullerFeeder;
import org.apache.solr.store.blob.process.CoreSyncStatus;
import org.apache.solr.store.blob.provider.BlobStorageProvider;
+import org.junit.After;
+import org.junit.BeforeClass;
/**
* Base class for SolrCloud tests with a few additional utilities for testing with a shared store
@@ -58,6 +61,20 @@ public class SolrCloudSharedStoreTestCase extends SolrCloudTestCase {
public static String DEFAULT_BLOB_DIR_NAME = "LocalBlobStore/";
+ public static Path blobDir;
+
+ @BeforeClass
+ public static void setupBlobDirectory() throws Exception {
+ blobDir = createTempDir("tempDir");
+ }
+
+ @After
+ public void cleanupBlobDirectory() throws Exception {
+ if (blobDir != null) {
+ FileUtils.cleanDirectory(blobDir.toFile());
+ }
+ }
+
protected static void setupSharedCollectionWithShardNames(String collectionName,
int maxShardsPerNode, int numReplicas, String shardNames) throws Exception {
CollectionAdminRequest.Create create = CollectionAdminRequest
@@ -72,7 +89,24 @@ public class SolrCloudSharedStoreTestCase extends SolrCloudTestCase {
waitForState("Timed-out wait for collection to be created", collectionName, clusterShape(numShards, numShards*numReplicas));
}
+ /**
+ * Spin up a {@link MiniSolrCloudCluster} with shared storage enabled and
+ * the local FS as the shared storage provider
+ */
protected static void setupCluster(int nodes) throws Exception {
+ System.setProperty(LocalStorageClient.BLOB_STORE_LOCAL_FS_ROOT_DIR_PROPERTY,
+ blobDir.resolve(DEFAULT_BLOB_DIR_NAME).toString());
+
+ configureCluster(nodes)
+ .withSolrXml(TEST_PATH().resolve("solr-sharedstore.xml"))
+ .addConfig("conf", configset("cloud-minimal"))
+ .configure();
+ }
+
+ /**
+ * Spin up a {@link MiniSolrCloudCluster} with shared storage disabled
+ */
+ protected static void setupClusterSharedDisable(int nodes) throws Exception {
configureCluster(nodes)
.addConfig("conf", configset("cloud-minimal"))
.configure();
@@ -147,14 +181,15 @@ public class SolrCloudSharedStoreTestCase extends SolrCloudTestCase {
}
};
- CorePullerFeeder cpf = new CorePullerFeeder(runner.getCoreContainer()) {
+ CorePullerFeeder cpf = new CorePullerFeeder(runner.getCoreContainer().getSharedStoreManager()) {
@Override
protected CorePullTask.PullCoreCallback getCorePullTaskCallback() {
return callback;
}
};
- BlobProcessUtil testUtil = new BlobProcessUtil(runner.getCoreContainer(), cpf);
+ BlobProcessUtil testUtil = new BlobProcessUtil();
+ testUtil.load(cpf);
setupTestBlobProcessUtilForNode(testUtil, runner);
return asyncPullTracker;
}
diff --git a/solr/core/src/test/org/apache/solr/store/shared/metadata/SharedShardMetadataControllerTest.java b/solr/core/src/test/org/apache/solr/store/shared/metadata/SharedShardMetadataControllerTest.java
index 6e67b5c..2c65ad9 100644
--- a/solr/core/src/test/org/apache/solr/store/shared/metadata/SharedShardMetadataControllerTest.java
+++ b/solr/core/src/test/org/apache/solr/store/shared/metadata/SharedShardMetadataControllerTest.java
@@ -22,9 +22,9 @@ import java.util.NoSuchElementException;
import org.apache.solr.client.solrj.cloud.SolrCloudManager;
import org.apache.solr.client.solrj.cloud.autoscaling.BadVersionException;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
-import org.apache.solr.cloud.SolrCloudTestCase;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.util.Utils;
+import org.apache.solr.store.shared.SolrCloudSharedStoreTestCase;
import org.apache.solr.store.shared.metadata.SharedShardMetadataController.SharedShardVersionMetadata;
import org.apache.zookeeper.data.Stat;
import org.junit.After;
@@ -34,7 +34,7 @@ import org.junit.Test;
/**
* Tests for {@link SharedShardMetadataController}
*/
-public class SharedShardMetadataControllerTest extends SolrCloudTestCase {
+public class SharedShardMetadataControllerTest extends SolrCloudSharedStoreTestCase {
static final String TEST_COLLECTION_NAME = "testCollectionName1";
static final String TEST_SHARD_NAME = "testShardName";
@@ -47,9 +47,7 @@ public class SharedShardMetadataControllerTest extends SolrCloudTestCase {
@BeforeClass
public static void setupCluster() throws Exception {
assumeWorkingMockito();
- configureCluster(1)
- .addConfig("conf", configset("cloud-minimal"))
- .configure();
+ setupCluster(1);
cloudManager = cluster.getJettySolrRunner(0).getCoreContainer().
getZkController().getSolrCloudManager();
diff --git a/solr/core/src/test/org/apache/solr/update/processor/DistributedZkUpdateProcessorTest.java b/solr/core/src/test/org/apache/solr/update/processor/DistributedZkUpdateProcessorTest.java
index 20fda76..b6f088f 100644
--- a/solr/core/src/test/org/apache/solr/update/processor/DistributedZkUpdateProcessorTest.java
+++ b/solr/core/src/test/org/apache/solr/update/processor/DistributedZkUpdateProcessorTest.java
@@ -20,11 +20,6 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
-import java.io.File;
-import java.nio.file.Path;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.solr.client.solrj.embedded.JettySolrRunner;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.client.solrj.request.UpdateRequest;
@@ -41,7 +36,6 @@ import org.apache.solr.core.SolrCore;
import org.apache.solr.request.LocalSolrQueryRequest;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.SolrQueryResponse;
-import org.apache.solr.store.blob.client.CoreStorageClient;
import org.apache.solr.store.blob.process.CoreUpdateTracker;
import org.apache.solr.store.shared.SolrCloudSharedStoreTestCase;
import org.apache.solr.update.AddUpdateCommand;
@@ -55,25 +49,16 @@ import org.mockito.Mockito;
* Test for the {@link DistributedZkUpdateProcessor}.
*/
public class DistributedZkUpdateProcessorTest extends SolrCloudSharedStoreTestCase {
-
- private static Path sharedStoreRootPath;
- private static CoreStorageClient storageClient;
@BeforeClass
public static void setupTestClass() throws Exception {
assumeWorkingMockito();
- sharedStoreRootPath = createTempDir("tempDir");
- storageClient = setupLocalBlobStoreClient(sharedStoreRootPath, DEFAULT_BLOB_DIR_NAME);
-
- assumeWorkingMockito();
}
@After
public void teardownTest() throws Exception {
cluster.deleteAllCollections();
shutdownCluster();
- File blobPath = sharedStoreRootPath.toFile();
- FileUtils.cleanDirectory(blobPath);
}
/**
@@ -84,7 +69,6 @@ public class DistributedZkUpdateProcessorTest extends SolrCloudSharedStoreTestCa
@Test
public void testNonLeaderSharedReplicaFailsOnForwardedCommit() throws Exception {
setupCluster(1);
- setupTestSharedClientForNode(getBlobStorageProviderTestInstance(storageClient), cluster.getJettySolrRunner(0));
String collectionName = "sharedCollection";
CloudSolrClient cloudClient = cluster.getSolrClient();
@@ -175,7 +159,6 @@ public class DistributedZkUpdateProcessorTest extends SolrCloudSharedStoreTestCa
*/
private void testReplicaUpdatesZk(Replica.Type replicaType, boolean isUpdateAnIsolatedCommit, boolean isWriteToSharedStoreExpected) throws Exception {
setupCluster(1);
- setupTestSharedClientForNode(getBlobStorageProviderTestInstance(storageClient), cluster.getJettySolrRunner(0));
// Set collection name and create client
String collectionName = "testCollection";
@@ -258,11 +241,6 @@ public class DistributedZkUpdateProcessorTest extends SolrCloudSharedStoreTestCa
public void testSharedReplicaSimpleUpdateOnLeaderSuccess() throws Exception {
setupCluster(3);
- // configure same client for each runner, this isn't a concurrency test so this is fine
- for (JettySolrRunner runner : cluster.getJettySolrRunners()) {
- setupTestSharedClientForNode(getBlobStorageProviderTestInstance(storageClient), runner);
- }
-
String collectionName = "sharedCollection";
CloudSolrClient cloudClient = cluster.getSolrClient();