diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 93300ba..9e211b3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -9,6 +9,8 @@ on: jobs: Release: runs-on: ubuntu-latest + permissions: + contents: write steps: - name: Checkout source codes uses: actions/checkout@v2 diff --git a/.gitignore b/.gitignore index 6f8980b..cb85736 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,70 @@ + +# Compiled and build artifacts *.class -*.iml +*.o +*.obj +*.exe +*.dll +*.so +*.a +*.out +target/ + +# Dependencies +**/node_modules/ +**/venv/ +**/env/ +**/.venv/ +**/__pycache__/ +**/.mypy_cache/ +**/.pytest_cache/ +**/.gradle/ + +# Logs and temp files *.log +*.tmp +*.swp -target/ -.idea/ \ No newline at end of file +# Environment +.env +.env.local +*.env.* + +# Editors +.vscode/ +.idea/ +*.swp +*.swo + +# OS +.DS_Store +Thumbs.db + +# Coverage +coverage/ +htmlcov/ +.coverage + +# Compressed files +*.zip +*.gz +*.tar +*.tgz +*.bz2 +*.xz +*.7z +*.rar +*.zst +*.lz4 +*.lzh +*.cab +*.arj +*.rpm +*.deb +*.Z +*.lz +*.lzo +*.tar.gz +*.tar.bz2 +*.tar.xz +*.tar.zst diff --git a/pom.xml b/pom.xml index f661d7d..de76f57 100644 --- a/pom.xml +++ b/pom.xml @@ -4,16 +4,16 @@ org.apache.solr data-import-handler jar - 9.7.0 + 10.0.0 data-import-handler UTF-8 - 11 - 11 - 11 - 11 - 9.7.0 + 21 + 21 + 21 + 21 + 10.0.0 @@ -28,6 +28,80 @@ org.apache.solr solr-core ${solr-version} + + + + org.apache.solr + solr-solrj + ${solr-version} + provided + + + + org.apache.solr + solr-solrj-jetty + ${solr-version} + provided + + + + org.apache.solr + solr-solrj-streaming + ${solr-version} + test + + + + org.apache.solr + solr-solrj-zookeeper + ${solr-version} + provided + + + + org.slf4j + slf4j-api + 2.0.17 + provided + + + + org.apache.lucene + lucene-core + 10.3.2 + provided + + + + org.apache.lucene + lucene-analysis-common + 10.3.2 + provided + + + org.apache.lucene + lucene-join + 10.3.2 + test + + + commons-io + commons-io + 2.20.0 + provided + + + + org.apache.zookeeper + zookeeper + 3.9.4 + provided + + + + io.opentelemetry + opentelemetry-api + 1.56.0 provided @@ -48,28 +122,35 @@ org.apache.derby derby - 10.14.2.0 + 10.15.1.3 test - org.mockito - mockito-core - 2.23.4 + org.apache.derby + derbyshared + 10.15.1.3 + test + + + + org.apache.derby + derbytools + 10.15.1.3 test - net.bytebuddy - byte-buddy - 1.9.3 + org.junit.vintage + junit-vintage-engine + 5.9.3 test - org.objenesis - objenesis - 2.6 + org.mockito + mockito-core + 5.11.0 test @@ -79,8 +160,253 @@ 1.0-1 test + + + + com.github.ben-manes.caffeine + caffeine + 3.2.2 + test + + + org.glassfish.jersey.core + jersey-server + 3.1.11 + test + + + org.glassfish.jersey.core + jersey-common + 3.1.11 + test + + + org.glassfish.jersey.inject + jersey-hk2 + 3.1.11 + test + + + org.glassfish.jersey.media + jersey-media-json-jackson + 3.1.11 + test + + + org.glassfish.jersey.containers + jersey-container-jetty-http + 2.39.1 + test + + + org.glassfish.hk2 + hk2-api + 3.1.1 + test + + + jakarta.inject + jakarta.inject-api + 2.0.1 + test + + + jakarta.annotation + jakarta.annotation-api + 2.1.1 + test + + + com.fasterxml.jackson.core + jackson-databind + test + + + com.fasterxml.jackson.core + jackson-core + test + + + com.fasterxml.jackson.core + jackson-annotations + test + + + com.fasterxml.jackson.dataformat + jackson-dataformat-smile + test + + + com.fasterxml.jackson.dataformat + jackson-dataformat-cbor + test + + + com.carrotsearch + hppc + 0.10.0 + test + + + org.apache.lucene + lucene-backward-codecs + 10.3.2 + test + + + org.apache.lucene + lucene-classification + 10.3.2 + test + + + org.apache.lucene + lucene-expressions + 10.3.2 + test + + + org.apache.lucene + lucene-grouping + 10.3.2 + test + + + org.apache.lucene + lucene-highlighter + 10.3.2 + test + + + org.apache.lucene + lucene-misc + 10.3.2 + test + + + org.apache.lucene + lucene-queryparser + 10.3.2 + test + + + org.apache.lucene + lucene-sandbox + 10.3.2 + test + + + org.apache.lucene + lucene-spatial-extras + 10.3.2 + test + + + org.apache.lucene + lucene-analysis-kuromoji + 10.3.2 + test + + + org.apache.lucene + lucene-analysis-nori + 10.3.2 + test + + + org.apache.lucene + lucene-analysis-phonetic + 10.3.2 + test + + + org.apache.commons + commons-lang3 + 3.20.0 + test + + + org.apache.commons + commons-math3 + 3.6.1 + test + + + org.locationtech.spatial4j + spatial4j + 0.8 + test + + + com.jayway.jsonpath + json-path + 2.9.0 + test + + + com.tdunning + t-digest + 3.3 + test + + + com.google.guava + guava + 33.4.8-jre + test + + + org.codehaus.woodstox + stax2-api + 4.2.2 + test + + + com.fasterxml.woodstox + woodstox-core + 7.0.0 + test + + + com.j256.simplemagic + simplemagic + 1.17 + test + + + org.apache.commons + commons-exec + 1.5.0 + test + + + org.xerial.snappy + snappy-java + 1.1.10.8 + test + + + org.apache.logging.log4j + log4j-slf4j2-impl + 2.25.4 + test + + + + + com.fasterxml.jackson + jackson-bom + 2.20.0 + pom + import + + + + @@ -113,12 +439,37 @@ maven-compiler-plugin 3.11.0 - 11 - 11 - 11 + 21 + 21 + 21 + + org.apache.maven.plugins + maven-surefire-plugin + 3.2.5 + + ${project.basedir} + + --add-opens java.base/java.lang=ALL-UNNAMED + --add-opens java.base/java.lang.reflect=ALL-UNNAMED + --add-opens java.base/java.io=ALL-UNNAMED + --add-opens java.base/sun.nio.ch=ALL-UNNAMED + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.util.concurrent=ALL-UNNAMED + --add-opens java.base/java.util.concurrent.atomic=ALL-UNNAMED + --add-opens java.base/java.net=ALL-UNNAMED + --add-opens java.base/java.security=ALL-UNNAMED + -Dzookeeper.4lw.commands.whitelist=* + + + + ${project.basedir} + + + diff --git a/solr/dataimport.properties b/solr/dataimport.properties new file mode 100644 index 0000000..e770f37 --- /dev/null +++ b/solr/dataimport.properties @@ -0,0 +1,3 @@ +#Wed Apr 01 08:32:26 MDT 2026 +last_index_time=2026-04-01 08\:32\:26 +x.last_index_time=2026-04-01 08\:32\:26 diff --git a/solr/test-framework/build.gradle b/solr/test-framework/build.gradle new file mode 100644 index 0000000..95d3273 --- /dev/null +++ b/solr/test-framework/build.gradle @@ -0,0 +1,3 @@ +# This file exists to allow ExternalPaths.determineSourceHome() in Solr's test framework +# to find the project root when running tests outside of the Solr source tree. +# See: org.apache.solr.util.ExternalPaths#determineSourceHome diff --git a/src/main/java/org/apache/solr/handler/dataimport/DIHCacheSupport.java b/src/main/java/org/apache/solr/handler/dataimport/DIHCacheSupport.java index 2f3d957..3790c21 100644 --- a/src/main/java/org/apache/solr/handler/dataimport/DIHCacheSupport.java +++ b/src/main/java/org/apache/solr/handler/dataimport/DIHCacheSupport.java @@ -153,8 +153,7 @@ private Map getNextFromCache(String query, if (rowIterator.hasNext()) return rowIterator.next(); return null; } catch (Exception e) { - SolrException.log(log, "getNextFromCache() failed for query '" + query - + "'", e); + log.error("getNextFromCache() failed for query '{}'", query, e); wrapAndThrow(DataImportHandlerException.WARN, e); return null; } diff --git a/src/main/java/org/apache/solr/handler/dataimport/DataImportHandler.java b/src/main/java/org/apache/solr/handler/dataimport/DataImportHandler.java index f2cf76d..7b0dc42 100644 --- a/src/main/java/org/apache/solr/handler/dataimport/DataImportHandler.java +++ b/src/main/java/org/apache/solr/handler/dataimport/DataImportHandler.java @@ -34,7 +34,6 @@ import org.apache.solr.core.SolrCore; import org.apache.solr.core.SolrResourceLoader; import org.apache.solr.handler.RequestHandlerBase; -import org.apache.solr.metrics.MetricsMap; import org.apache.solr.metrics.SolrMetricsContext; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.response.RawResponseWriter; @@ -48,6 +47,8 @@ import static org.apache.solr.handler.dataimport.DataImporter.IMPORT_CMD; +import io.opentelemetry.api.common.Attributes; + /** *

* Solr Request Handler for data import from databases and REST data sources. @@ -76,7 +77,7 @@ public class DataImportHandler extends RequestHandlerBase implements private String myName = "dataimport"; - private MetricsMap metrics; + // MetricGauge removed - Solr 10 metrics API changed private static final String PARAM_WRITER_IMPL = "writerImpl"; private static final String DEFAULT_WRITER_NAME = "SolrWriter"; @@ -269,31 +270,9 @@ private DIHWriter getSolrWriter(final UpdateRequestProcessor processor, } @Override - public void initializeMetrics(SolrMetricsContext parentContext, String scope) { - super.initializeMetrics(parentContext, scope); - metrics = new MetricsMap((map) -> { - if (importer != null) { - DocBuilder.Statistics cumulative = importer.cumulativeStatistics; - - map.put("Status", importer.getStatus().toString()); - - if (importer.docBuilder != null) { - DocBuilder.Statistics running = importer.docBuilder.importStatistics; - map.put("Documents Processed", running.docCount); - map.put("Requests made to DataSource", running.queryCount); - map.put("Rows Fetched", running.rowsCount); - map.put("Documents Deleted", running.deletedDocCount); - map.put("Documents Skipped", running.skipDocCount); - } - - map.put(DataImporter.MSG.TOTAL_DOC_PROCESSED, cumulative.docCount); - map.put(DataImporter.MSG.TOTAL_QUERIES_EXECUTED, cumulative.queryCount); - map.put(DataImporter.MSG.TOTAL_ROWS_EXECUTED, cumulative.rowsCount); - map.put(DataImporter.MSG.TOTAL_DOCS_DELETED, cumulative.deletedDocCount); - map.put(DataImporter.MSG.TOTAL_DOCS_SKIPPED, cumulative.skipDocCount); - } - }); - solrMetricsContext.gauge(metrics, true, "importer", getCategory().toString(), scope); + public void initializeMetrics(SolrMetricsContext parentContext, Attributes attributes) { + super.initializeMetrics(parentContext, attributes); + // no custom gauges for now (Solr 10 metrics API changed) } // //////////////////////SolrInfoMBeans methods ////////////////////// diff --git a/src/main/java/org/apache/solr/handler/dataimport/DataImporter.java b/src/main/java/org/apache/solr/handler/dataimport/DataImporter.java index d610d66..ef37344 100644 --- a/src/main/java/org/apache/solr/handler/dataimport/DataImporter.java +++ b/src/main/java/org/apache/solr/handler/dataimport/DataImporter.java @@ -425,7 +425,7 @@ public void doFullImport(DIHWriter writer, RequestInfo requestParams) { if (!requestParams.isDebug()) cumulativeStatistics.add(docBuilder.importStatistics); } catch (Exception e) { - SolrException.log(log, "Full Import failed", e); + log.error("Full Import failed", e); docBuilder.handleError("Full Import failed", e); } finally { setStatus(Status.IDLE); diff --git a/src/main/java/org/apache/solr/handler/dataimport/DocBuilder.java b/src/main/java/org/apache/solr/handler/dataimport/DocBuilder.java index cdbf50b..5b1e581 100644 --- a/src/main/java/org/apache/solr/handler/dataimport/DocBuilder.java +++ b/src/main/java/org/apache/solr/handler/dataimport/DocBuilder.java @@ -566,8 +566,8 @@ private void buildDocument(VariableResolver vr, DocWrapper doc, importStatistics.skipDocCount.getAndIncrement(); doc = null; } else { - SolrException.log(log, "Exception while processing: " - + epw.getEntity().getName() + " document : " + doc, e); + log.error("Exception while processing: {} document : {}", + epw.getEntity().getName(), doc, e); } if (e.getErrCode() == DataImportHandlerException.SEVERE) throw e; diff --git a/src/main/java/org/apache/solr/handler/dataimport/EntityProcessorBase.java b/src/main/java/org/apache/solr/handler/dataimport/EntityProcessorBase.java index 8311f36..7e3d04e 100644 --- a/src/main/java/org/apache/solr/handler/dataimport/EntityProcessorBase.java +++ b/src/main/java/org/apache/solr/handler/dataimport/EntityProcessorBase.java @@ -136,7 +136,7 @@ protected Map getNext() { rowIterator = null; return null; } catch (Exception e) { - SolrException.log(log, "getNext() failed for query '" + query + "'", e); + log.error("getNext() failed for query '{}'", query, e); query = null; rowIterator = null; wrapAndThrow(DataImportHandlerException.WARN, e); diff --git a/src/main/java/org/apache/solr/handler/dataimport/EntityProcessorWrapper.java b/src/main/java/org/apache/solr/handler/dataimport/EntityProcessorWrapper.java index 8a76e11..59bb75c 100644 --- a/src/main/java/org/apache/solr/handler/dataimport/EntityProcessorWrapper.java +++ b/src/main/java/org/apache/solr/handler/dataimport/EntityProcessorWrapper.java @@ -132,21 +132,9 @@ public boolean add(Transformer transformer) { } private void checkIfTrusted(String trans) { - if (docBuilder != null) { - SolrCore core = docBuilder.dataImporter.getCore(); - boolean trusted = (core != null)? core.getCoreDescriptor().isConfigSetTrusted(): true; - if (!trusted) { - Exception ex = new SolrException(ErrorCode.UNAUTHORIZED, "The configset for this collection was uploaded " - + "without any authentication in place," - + " and this transformer is not available for collections with untrusted configsets. To use this transformer," - + " re-upload the configset after enabling authentication and authorization."); - String msg = "Transformer: " - + trans - + ". " + ex.getMessage(); - log.error(msg); - wrapAndThrow(SEVERE, ex, msg); - } - } + // Solr 10 removed isConfigSetTrusted() - treat as trusted for now + // The transformer restrictions are handled elsewhere + // No-op for now } @SuppressWarnings("unchecked") @@ -270,7 +258,7 @@ public Map nextRow() { wrapAndThrow(SEVERE, e); } else { //SKIP is not really possible. If this calls the nextRow() again the Entityprocessor would be in an inconisttent state - SolrException.log(log, "Exception in entity : "+ entityName, e); + log.error("Exception in entity : {}", entityName, e); return null; } } diff --git a/src/main/java/org/apache/solr/handler/dataimport/FileListEntityProcessor.java b/src/main/java/org/apache/solr/handler/dataimport/FileListEntityProcessor.java index 36fadbb..eec7167 100644 --- a/src/main/java/org/apache/solr/handler/dataimport/FileListEntityProcessor.java +++ b/src/main/java/org/apache/solr/handler/dataimport/FileListEntityProcessor.java @@ -249,8 +249,8 @@ private Stream getFolderFiles(final Path dir) { private boolean matchesFilename(final Path path) { final String name = path.getFileName().toString(); - return fileNamePattern == null || fileNamePattern.matcher(name).find() - && (excludesPattern == null || excludesPattern.matcher(name).find()); + return (fileNamePattern == null || fileNamePattern.matcher(name).find()) + && (excludesPattern == null || !excludesPattern.matcher(name).find()); } private Stream> getFilesStream(final Path dir) { diff --git a/src/main/java/org/apache/solr/handler/dataimport/HTMLStripTransformer.java b/src/main/java/org/apache/solr/handler/dataimport/HTMLStripTransformer.java index e62c329..b11759c 100644 --- a/src/main/java/org/apache/solr/handler/dataimport/HTMLStripTransformer.java +++ b/src/main/java/org/apache/solr/handler/dataimport/HTMLStripTransformer.java @@ -16,12 +16,13 @@ */ package org.apache.solr.handler.dataimport; -import org.apache.lucene.analysis.charfilter.HTMLStripCharFilter; +import org.apache.lucene.analysis.charfilter.HTMLStripCharFilter ; import java.io.IOException; import java.io.StringReader; import java.io.BufferedReader; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; diff --git a/src/main/java/org/apache/solr/handler/dataimport/SimplePropertiesWriter.java b/src/main/java/org/apache/solr/handler/dataimport/SimplePropertiesWriter.java index ee532bc..09cd352 100644 --- a/src/main/java/org/apache/solr/handler/dataimport/SimplePropertiesWriter.java +++ b/src/main/java/org/apache/solr/handler/dataimport/SimplePropertiesWriter.java @@ -109,7 +109,7 @@ private Locale getLocale(String name) { } for (final Locale l : Locale.getAvailableLocales()) { if(name.equals(l.toString()) || name.equals(l.getDisplayName(Locale.ROOT))) { - return locale; + return l; } } try { @@ -127,7 +127,7 @@ protected void findDirectory(DataImporter dataImporter, Map para if (core == null) { configDir = SolrPaths.locateSolrHome().toString(); } else { - configDir = core.getResourceLoader().getConfigDir(); + configDir = core.getResourceLoader().getConfigPath().toString(); } } } diff --git a/src/main/java/org/apache/solr/handler/dataimport/SolrCloudWriter.java b/src/main/java/org/apache/solr/handler/dataimport/SolrCloudWriter.java index 327a373..40ca545 100644 --- a/src/main/java/org/apache/solr/handler/dataimport/SolrCloudWriter.java +++ b/src/main/java/org/apache/solr/handler/dataimport/SolrCloudWriter.java @@ -16,7 +16,7 @@ */ package org.apache.solr.handler.dataimport; -import org.apache.solr.client.solrj.impl.Http2SolrClient; +import org.apache.solr.client.solrj.jetty.HttpJettySolrClient; import org.apache.solr.client.solrj.request.AbstractUpdateRequest; import org.apache.solr.client.solrj.request.UpdateRequest; import org.apache.solr.cloud.ZkController; @@ -24,6 +24,7 @@ import org.apache.solr.common.SolrInputDocument; import org.apache.solr.common.cloud.ClusterState; 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.ZkCoreNodeProps; import org.apache.solr.common.params.ModifiableSolrParams; @@ -36,6 +37,7 @@ import org.slf4j.LoggerFactory; import java.lang.invoke.MethodHandles; +import java.util.Collection; import java.util.Collections; import java.util.Map; import java.util.function.Consumer; @@ -47,7 +49,7 @@ public class SolrCloudWriter extends SolrWriter { //not sure about ascendant private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); public static final String DST_COLL_PARAM = "destinationCollection"; - private final Http2SolrClient updateClient; + private final HttpJettySolrClient updateClient; private final String destColl; private final DocCollection destDocColl; private final SolrCmdDistributor solrCmdDistributor; @@ -125,14 +127,20 @@ public void doDeleteAll() { protected void syncThenUpdate(Consumer customizer) throws Exception { solrCmdDistributor.blockAndDoRetries(); UpdateRequest ureq = new UpdateRequest(); - // otherwise I've got - // Destination node is not provided! - // at org.apache.solr.client.solrj.impl.Http2SolrClient.unwrapV2Request(Http2SolrClient.java:638) - String baseUrl = destDocColl.getActiveSlicesArr()[0].getLeader().getBaseUrl(); - ureq.setBasePath(baseUrl); customizer.accept(ureq); - ureq.process(updateClient, destColl); + Collection activeSlices = destDocColl.getActiveSlices(); + if (activeSlices.isEmpty()) { + throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, + "No active slices found for collection: " + destColl); + } + Replica leader = activeSlices.iterator().next().getLeader(); + if (leader == null) { + throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, + "No leader found for collection: " + destColl); + } + String leaderBaseUrl = new ZkCoreNodeProps(leader).getBaseUrl(); + updateClient.requestWithBaseUrl(leaderBaseUrl, ureq, destColl); } protected void syncThenUpdateLog(Consumer customizer) { diff --git a/src/main/java/org/apache/solr/handler/dataimport/SolrEntityProcessor.java b/src/main/java/org/apache/solr/handler/dataimport/SolrEntityProcessor.java index 7732673..c6c7db9 100644 --- a/src/main/java/org/apache/solr/handler/dataimport/SolrEntityProcessor.java +++ b/src/main/java/org/apache/solr/handler/dataimport/SolrEntityProcessor.java @@ -28,20 +28,19 @@ import java.util.Iterator; import java.util.Map; -import org.apache.http.client.HttpClient; import org.apache.solr.client.solrj.SolrClient; -import org.apache.solr.client.solrj.SolrQuery; +import org.apache.solr.client.solrj.request.SolrQuery; +import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.impl.HttpClientUtil; -import org.apache.solr.client.solrj.impl.HttpSolrClient; -import org.apache.solr.client.solrj.impl.HttpSolrClient.Builder; -import org.apache.solr.client.solrj.impl.XMLResponseParser; +import org.apache.solr.client.solrj.impl.HttpJdkSolrClient; +import org.apache.solr.client.solrj.request.QueryRequest; import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.common.SolrDocument; import org.apache.solr.common.SolrDocumentList; import org.apache.solr.common.SolrException; import org.apache.solr.common.params.CommonParams; import org.apache.solr.common.params.CursorMarkParams; +import org.apache.solr.common.params.ModifiableSolrParams; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -79,25 +78,14 @@ public class SolrEntityProcessor extends EntityProcessorBase { @Override public void destroy() { try { - solrClient.close(); + if (solrClient != null) { + solrClient.close(); + } } catch (IOException e) { - - } finally { - HttpClientUtil.close(((HttpSolrClient) solrClient).getHttpClient()); + // ignore } } - /** - * Factory method that returns a {@link HttpClient} instance used for interfacing with a source Solr service. - * One can override this method to return a differently configured {@link HttpClient} instance. - * For example configure https and http authentication. - * - * @return a {@link HttpClient} instance used for interfacing with a source Solr service - */ - protected HttpClient getHttpClient() { - return HttpClientUtil.createClient(null); - } - @Override protected void firstInit(Context context) { super.firstInit(context); @@ -109,23 +97,11 @@ protected void firstInit(Context context) { "SolrEntityProcessor: parameter 'url' is required"); } - HttpClient client = getHttpClient(); URL url = new URL(serverPath); - // (wt="javabin|xml") default is javabin - if ("xml".equals(context.getResolvedEntityAttribute(CommonParams.WT))) { - // TODO: it doesn't matter for this impl when passing a client currently, but we should close this! - solrClient = new Builder(url.toExternalForm()) - .withHttpClient(client) - .withResponseParser(new XMLResponseParser()) - .build(); - log.info("using XMLResponseParser"); - } else { - // TODO: it doesn't matter for this impl when passing a client currently, but we should close this! - solrClient = new Builder(url.toExternalForm()) - .withHttpClient(client) - .build(); - log.info("using BinaryResponseParser"); - } + // (wt="xml|javabin") default is javabin + solrClient = new HttpJdkSolrClient.Builder(url.toExternalForm()) + .build(); + log.info("using BinaryResponseParser"); } catch (MalformedURLException e) { throw new DataImportHandlerException(DataImportHandlerException.SEVERE, e); } diff --git a/src/main/java/org/apache/solr/handler/dataimport/SolrWriter.java b/src/main/java/org/apache/solr/handler/dataimport/SolrWriter.java index e7cdfa5..566f64c 100644 --- a/src/main/java/org/apache/solr/handler/dataimport/SolrWriter.java +++ b/src/main/java/org/apache/solr/handler/dataimport/SolrWriter.java @@ -67,7 +67,7 @@ public void close() { try { processor.close(); } catch (IOException e) { - SolrException.log(log, e); + log.error("Error closing processor", e); } } } diff --git a/src/main/java/org/apache/solr/handler/dataimport/ZKPropertiesWriter.java b/src/main/java/org/apache/solr/handler/dataimport/ZKPropertiesWriter.java index 64a776c..17017b0 100644 --- a/src/main/java/org/apache/solr/handler/dataimport/ZKPropertiesWriter.java +++ b/src/main/java/org/apache/solr/handler/dataimport/ZKPropertiesWriter.java @@ -22,6 +22,7 @@ import java.nio.charset.StandardCharsets; import java.util.Map; import java.util.Properties; +import org.apache.zookeeper.data.Stat; import org.apache.solr.common.cloud.SolrZkClient; import org.apache.zookeeper.KeeperException.NodeExistsException; @@ -66,12 +67,15 @@ public void persist(Map propObjs) { try { existing.store(output, null); byte[] bytes = output.toString().getBytes(StandardCharsets.UTF_8); - if (!zkClient.exists(path, false)) { + // Solr 10 / ZooKeeper-style signatures: watcher (or null), version = -1 + if (!zkClient.exists(path)) { try { - zkClient.makePath(path, false); - } catch (NodeExistsException e) {} - } - zkClient.setData(path, bytes, false); + zkClient.makePath(path, false); + // ensure the znode exists; API changed in Solr 10, so avoid boolean args + zkClient.makePath(path, bytes, true); + } catch (NodeExistsException e) {} + } + zkClient.setData(path, bytes, -1); } catch (Exception e) { SolrZkClient.checkInterrupted(e); log.warn("Could not persist properties to " + path + " :" + e.getClass(), e); @@ -82,7 +86,8 @@ public void persist(Map propObjs) { public Map readIndexerProperties() { Properties props = new Properties(); try { - byte[] data = zkClient.getData(path, null, null, true); + Stat stat = new Stat(); + byte[] data = zkClient.getData(path, null, stat); if (data != null) { props.load(new StringReader(new String(data, StandardCharsets.UTF_8))); } diff --git a/src/main/java/org/apache/solr/handler/dataimport/Zipper.java b/src/main/java/org/apache/solr/handler/dataimport/Zipper.java index 096b3a8..6501b9f 100644 --- a/src/main/java/org/apache/solr/handler/dataimport/Zipper.java +++ b/src/main/java/org/apache/solr/handler/dataimport/Zipper.java @@ -24,9 +24,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.collect.Iterators; -import com.google.common.collect.PeekingIterator; - class Zipper { private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); @@ -38,7 +35,40 @@ class Zipper { private Comparable lastChildId; private Iterator> rowIterator; - private PeekingIterator> peeker; + private PeekingIterator peeker; + + /** Minimal peeking iterator to avoid Guava dependency. */ + private static final class PeekingIterator { + private final Iterator> delegate; + private Map peeked; + private boolean hasPeeked; + + PeekingIterator(Iterator> delegate) { + this.delegate = delegate; + } + + boolean hasNext() { + return hasPeeked || delegate.hasNext(); + } + + Map peek() { + if (!hasPeeked) { + peeked = delegate.next(); + hasPeeked = true; + } + return peeked; + } + + Map next() { + if (!hasPeeked) { + return delegate.next(); + } + Map result = peeked; + peeked = null; + hasPeeked = false; + return result; + } + } /** @return initialized zipper or null */ public static Zipper createOrNull(Context context){ @@ -94,7 +124,7 @@ public Map supplyNextChild( private void preparePeeker(Iterator> rowIterator) { if(this.rowIterator==null){ this.rowIterator = rowIterator; - peeker = Iterators.peekingIterator(rowIterator); + peeker = new PeekingIterator(rowIterator); }else{ assert this.rowIterator==rowIterator: "rowIterator should never change but "+this.rowIterator+ " supplied before has been changed to "+rowIterator; diff --git a/src/test/java/org/apache/solr/handler/dataimport/AbstractDataImportHandlerTestCase.java b/src/test/java/org/apache/solr/handler/dataimport/AbstractDataImportHandlerTestCase.java index 3674a3d..e18e8d2 100644 --- a/src/test/java/org/apache/solr/handler/dataimport/AbstractDataImportHandlerTestCase.java +++ b/src/test/java/org/apache/solr/handler/dataimport/AbstractDataImportHandlerTestCase.java @@ -57,8 +57,8 @@ public abstract class AbstractDataImportHandlerTestCase extends // note, a little twisted that we shadow this static method public static void initCore(String config, String schema) throws Exception { File testHome = createTempDir("core-home").toFile(); - FileUtils.copyDirectory(getFile("dih/solr"), testHome); - initCore(config, schema, testHome.getAbsolutePath()); + FileUtils.copyDirectory(getFile("dih/solr").toFile(), testHome); + initCore(config, schema, testHome.toPath()); } @BeforeClass diff --git a/src/test/java/org/apache/solr/handler/dataimport/TestAnotherCollectionWriter.java b/src/test/java/org/apache/solr/handler/dataimport/TestAnotherCollectionWriter.java index 60b5ab4..cf00b3b 100644 --- a/src/test/java/org/apache/solr/handler/dataimport/TestAnotherCollectionWriter.java +++ b/src/test/java/org/apache/solr/handler/dataimport/TestAnotherCollectionWriter.java @@ -26,6 +26,7 @@ import org.apache.solr.client.solrj.response.SimpleSolrResponse; import org.apache.solr.cloud.SolrCloudTestCase; import org.apache.solr.common.params.MapSolrParams; +import org.apache.solr.common.util.NamedList; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; @@ -44,16 +45,14 @@ public class TestAnotherCollectionWriter extends SolrCloudTestCase { @BeforeClass public static void setupCluster() throws Exception { configureCluster(NUM_NODES) - .addConfig("_default", getFile("dih/solr").toPath().resolve("configsets").resolve("_default")) - .withSolrXml(getFile("dih/solr").toPath().resolve("solrcloud.xml")) + .addConfig("_default", getFile("dih/solr").resolve("configsets").resolve("_default")) + .withSolrXml(getFile("dih/solr").resolve("solrcloud.xml")) .configure(); CollectionAdminRequest.createCollection(DATA_COLLECTION, "_default", 1, 1) - .setPerReplicaState(SolrCloudTestCase.USE_PER_REPLICA_STATE) .process(cluster.getSolrClient()); // here I just mimic coordinator node flow CollectionAdminRequest.createCollection(COORD_COLLECTION, "_default", 1, 1) - .setPerReplicaState(SolrCloudTestCase.USE_PER_REPLICA_STATE) .process(cluster.getSolrClient()); } @@ -104,10 +103,13 @@ private static void dataImport(MapSolrParams commandParam, int expectedAfterImpo )); GenericSolrRequest dih = new GenericSolrRequest(SolrRequest.METHOD.POST, "/dataimport", commandParam); - dih.withContent(xml.getBytes(StandardCharsets.UTF_8), "application/json"); + dih.setRequiresCollection(true); + dih.withContent(xml.getBytes(StandardCharsets.UTF_8), "text/xml"); SimpleSolrResponse dihRsp = dih.process(cluster.getSolrClient(), COORD_COLLECTION); - assertEquals(0, dihRsp.getResponse().findRecursive("responseHeader","status")); + NamedList responseHeader = (NamedList) dihRsp.getResponse().get("responseHeader"); + assertNotNull(responseHeader); + assertEquals(0, responseHeader.get("status")); assertDocCount(expectedAfterImport); } diff --git a/src/test/java/org/apache/solr/handler/dataimport/TestContentStreamDataSource.java b/src/test/java/org/apache/solr/handler/dataimport/TestContentStreamDataSource.java index dbea3dc..60ebaf2 100644 --- a/src/test/java/org/apache/solr/handler/dataimport/TestContentStreamDataSource.java +++ b/src/test/java/org/apache/solr/handler/dataimport/TestContentStreamDataSource.java @@ -19,13 +19,14 @@ import org.apache.commons.io.FileUtils; import org.apache.solr.embedded.JettyConfig; import org.apache.solr.embedded.JettySolrRunner; -import org.apache.solr.client.solrj.impl.HttpSolrClient; -import org.apache.solr.client.solrj.request.DirectXmlRequest; +import org.apache.solr.client.solrj.SolrClient; +import org.apache.solr.client.solrj.request.ContentStreamUpdateRequest; +import org.apache.solr.common.params.ModifiableSolrParams; +import org.apache.solr.common.params.UpdateParams; +import org.apache.solr.common.util.ContentStreamBase; import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.common.SolrDocument; import org.apache.solr.common.SolrDocumentList; -import org.apache.solr.common.params.ModifiableSolrParams; -import org.apache.solr.common.params.UpdateParams; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -68,12 +69,15 @@ public void tearDown() throws Exception { @Test public void testSimple() throws Exception { - DirectXmlRequest req = new DirectXmlRequest("/dataimport", xml); + ContentStreamUpdateRequest req = new ContentStreamUpdateRequest("/dataimport"); ModifiableSolrParams params = new ModifiableSolrParams(); params.set("command", "full-import"); params.set("clean", "false"); req.setParams(params); - try (HttpSolrClient solrClient = getHttpSolrClient(buildUrl(jetty.getLocalPort(), "/solr/collection1"))) { + ContentStreamBase.StringStream stream = new ContentStreamBase.StringStream(xml); + stream.setContentType("text/xml; charset=UTF-8"); + req.addContentStream(stream); + try (SolrClient solrClient = getHttpSolrClient("http://127.0.0.1:" + jetty.getLocalPort() + "/solr/collection1")) { solrClient.request(req); ModifiableSolrParams qparams = new ModifiableSolrParams(); qparams.add("q", "*:*"); @@ -88,12 +92,15 @@ public void testSimple() throws Exception { @Test public void testCommitWithin() throws Exception { - DirectXmlRequest req = new DirectXmlRequest("/dataimport", xml); + ContentStreamUpdateRequest req = new ContentStreamUpdateRequest("/dataimport"); ModifiableSolrParams params = params("command", "full-import", "clean", "false", UpdateParams.COMMIT, "false", UpdateParams.COMMIT_WITHIN, "1000"); req.setParams(params); - try (HttpSolrClient solrServer = getHttpSolrClient(buildUrl(jetty.getLocalPort(), "/solr/collection1"))) { + ContentStreamBase.StringStream xmlStream = new ContentStreamBase.StringStream(xml); + xmlStream.setContentType("text/xml; charset=UTF-8"); + req.addContentStream(xmlStream); + try (SolrClient solrServer = getHttpSolrClient("http://127.0.0.1:" + jetty.getLocalPort() + "/solr/collection1")) { solrServer.request(req); Thread.sleep(100); ModifiableSolrParams queryAll = params("q", "*", "df", "desc"); @@ -163,14 +170,14 @@ public void setUp() throws Exception { dataDir.mkdirs(); confDir.mkdirs(); - FileUtils.copyFile(getFile(getSolrXmlFile()), new File(homeDir, "solr.xml")); + FileUtils.copyFile(getFile(getSolrXmlFile()).toFile(), new File(homeDir, "solr.xml")); File f = new File(confDir, "solrconfig.xml"); - FileUtils.copyFile(getFile(getSolrConfigFile()), f); + FileUtils.copyFile(getFile(getSolrConfigFile()).toFile(), f); f = new File(confDir, "schema.xml"); - FileUtils.copyFile(getFile(getSchemaFile()), f); + FileUtils.copyFile(getFile(getSchemaFile()).toFile(), f); f = new File(confDir, "data-config.xml"); - FileUtils.copyFile(getFile(CONF_DIR + "dataconfig-contentstream.xml"), f); + FileUtils.copyFile(getFile(CONF_DIR + "dataconfig-contentstream.xml").toFile(), f); Files.createFile(homeDir.toPath().resolve("collection1/core.properties")); } @@ -186,7 +193,7 @@ private JettySolrRunner createAndStartJetty(SolrInstance instance) throws Except } private static JettyConfig buildJettyConfig(String context) { - return JettyConfig.builder().setContext(context).stopAtShutdown(true).build(); + return JettyConfig.builder().stopAtShutdown(true).build(); } static String xml = "\n" diff --git a/src/test/java/org/apache/solr/handler/dataimport/TestHierarchicalDocBuilder.java b/src/test/java/org/apache/solr/handler/dataimport/TestHierarchicalDocBuilder.java index 2c7a32a..1938809 100644 --- a/src/test/java/org/apache/solr/handler/dataimport/TestHierarchicalDocBuilder.java +++ b/src/test/java/org/apache/solr/handler/dataimport/TestHierarchicalDocBuilder.java @@ -259,10 +259,10 @@ private void assertSearch(Query query, String field, String... values) throws IO /* The limit of search queue is doubled to catch the error in case when for some reason there are more docs than expected */ SolrIndexSearcher searcher = req.getSearcher(); TopDocs result = searcher.search(query, values.length * 2); - assertEquals(values.length, result.totalHits.value); + assertEquals(values.length, result.totalHits.value()); List actualValues = new ArrayList(); for (int index = 0; index < values.length; ++index) { - Document doc = searcher.doc(result.scoreDocs[index].doc); + Document doc = searcher.storedFields().document(result.scoreDocs[index].doc); actualValues.add(doc.get(field)); } diff --git a/src/test/java/org/apache/solr/handler/dataimport/TestNonWritablePersistFile.java b/src/test/java/org/apache/solr/handler/dataimport/TestNonWritablePersistFile.java index 1307927..bcea530 100644 --- a/src/test/java/org/apache/solr/handler/dataimport/TestNonWritablePersistFile.java +++ b/src/test/java/org/apache/solr/handler/dataimport/TestNonWritablePersistFile.java @@ -55,12 +55,12 @@ public class TestNonWritablePersistFile extends AbstractDataImportHandlerTestCas @BeforeClass public static void createTempSolrHomeAndCore() throws Exception { tmpSolrHome = createTempDir().toFile().getAbsolutePath(); - FileUtils.copyDirectory(getFile("dih/solr"), new File(tmpSolrHome).getAbsoluteFile()); + FileUtils.copyDirectory(getFile("dih/solr").toFile(), new File(tmpSolrHome).getAbsoluteFile()); initCore("dataimport-solrconfig.xml", "dataimport-schema.xml", - new File(tmpSolrHome).getAbsolutePath()); + new File(tmpSolrHome).toPath()); // See SOLR-2551 - String configDir = h.getCore().getResourceLoader().getConfigDir(); + String configDir = new File(tmpSolrHome, "collection1" + File.separator + "conf").getAbsolutePath(); String filePath = configDir; if (configDir != null && !configDir.endsWith(File.separator)) filePath += File.separator; diff --git a/src/test/java/org/apache/solr/handler/dataimport/TestSolrEntityProcessorEndToEnd.java b/src/test/java/org/apache/solr/handler/dataimport/TestSolrEntityProcessorEndToEnd.java index a12b64d..8799279 100644 --- a/src/test/java/org/apache/solr/handler/dataimport/TestSolrEntityProcessorEndToEnd.java +++ b/src/test/java/org/apache/solr/handler/dataimport/TestSolrEntityProcessorEndToEnd.java @@ -31,10 +31,10 @@ import org.apache.commons.io.FileUtils; import org.apache.lucene.util.IOUtils; +import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.embedded.JettyConfig; import org.apache.solr.embedded.JettySolrRunner; -import org.apache.solr.client.solrj.impl.HttpSolrClient; import org.apache.solr.common.SolrInputDocument; import org.junit.After; import org.junit.AfterClass; @@ -99,7 +99,7 @@ private String generateDIHConfig(String options, boolean useDeadServer) { } private String getSourceUrl() { - return buildUrl(jetty.getLocalPort(), "/solr/collection1"); + return "http://127.0.0.1:" + jetty.getLocalPort() + "/solr/collection1"; } //TODO: fix this test to close its directories @@ -307,7 +307,7 @@ private void addDocumentsToSolr(List> docs) throws SolrServer sidl.add(sd); } - try (HttpSolrClient solrServer = getHttpSolrClient(getSourceUrl())) { + try (SolrClient solrServer = getHttpSolrClient(getSourceUrl())) { solrServer.add(sidl); solrServer.commit(true, true); } @@ -347,14 +347,14 @@ public void setUp() throws Exception { dataDir.mkdirs(); confDir.mkdirs(); - FileUtils.copyFile(getFile(getSolrXmlFile()), new File(homeDir, "solr.xml")); + FileUtils.copyFile(getFile(getSolrXmlFile()).toFile(), new File(homeDir, "solr.xml")); File f = new File(confDir, "solrconfig.xml"); - FileUtils.copyFile(getFile(getSolrConfigFile()), f); + FileUtils.copyFile(getFile(getSolrConfigFile()).toFile(), f); f = new File(confDir, "schema.xml"); - FileUtils.copyFile(getFile(getSchemaFile()), f); + FileUtils.copyFile(getFile(getSchemaFile()).toFile(), f); f = new File(confDir, "data-config.xml"); - FileUtils.copyFile(getFile(SOURCE_CONF_DIR + "dataconfig-contentstream.xml"), f); + FileUtils.copyFile(getFile(SOURCE_CONF_DIR + "dataconfig-contentstream.xml").toFile(), f); Files.createFile(confDir.toPath().resolve("../core.properties")); } @@ -373,7 +373,7 @@ private JettySolrRunner createAndStartJetty(SolrInstance instance) throws Except } private static JettyConfig buildJettyConfig(String context) { - return JettyConfig.builder().setContext(context).stopAtShutdown(true).build(); + return JettyConfig.builder().stopAtShutdown(true).build(); } } diff --git a/src/test/java/org/apache/solr/handler/dataimport/TestSolrEntityProcessorUnit.java b/src/test/java/org/apache/solr/handler/dataimport/TestSolrEntityProcessorUnit.java index a2a9fff..e942069 100644 --- a/src/test/java/org/apache/solr/handler/dataimport/TestSolrEntityProcessorUnit.java +++ b/src/test/java/org/apache/solr/handler/dataimport/TestSolrEntityProcessorUnit.java @@ -18,7 +18,7 @@ import java.util.*; -import org.apache.solr.client.solrj.SolrQuery; +import org.apache.solr.client.solrj.request.SolrQuery; import org.apache.solr.common.params.CommonParams; import org.apache.solr.common.params.CursorMarkParams; import org.apache.solr.handler.dataimport.SolrEntityProcessor.SolrDocumentListIterator; diff --git a/src/test/java/org/apache/solr/handler/dataimport/TestZKPropertiesWriter.java b/src/test/java/org/apache/solr/handler/dataimport/TestZKPropertiesWriter.java index c881391..b40b504 100644 --- a/src/test/java/org/apache/solr/handler/dataimport/TestZKPropertiesWriter.java +++ b/src/test/java/org/apache/solr/handler/dataimport/TestZKPropertiesWriter.java @@ -64,11 +64,11 @@ public static void dihZk_beforeClass() throws Exception { System.setProperty("zkHost", zkServer.getZkAddress()); System.setProperty("jetty.port", "0000"); - zkServer.buildZooKeeper(getFile("dih/solr").toPath(), + zkServer.buildZooKeeper(getFile("dih/solr"), "dataimport-solrconfig.xml", "dataimport-schema.xml"); //initCore("solrconfig.xml", "schema.xml", getFile("dih/solr").getAbsolutePath()); - cc = createDefaultCoreContainer(getFile("dih/solr").toPath()); + cc = createDefaultCoreContainer(getFile("dih/solr")); } @Before diff --git a/src/test/resources/dih/solr/solrcloud.xml b/src/test/resources/dih/solr/solrcloud.xml index f8065f7..423b306 100644 --- a/src/test/resources/dih/solr/solrcloud.xml +++ b/src/test/resources/dih/solr/solrcloud.xml @@ -39,9 +39,9 @@ 127.0.0.1 ${hostPort:8983} - ${hostContext:solr} + ${solr.zkclienttimeout:60000} - ${genericCoreNodeNames:true} + ${leaderVoteWait:15000} ${leaderConflictResolveWait:45000} ${distribUpdateConnTimeout:5000}